Rollup merge of #147125 - connortsui20:poison-once-remove, r=tgross35 move `once` module out of `poison` From https://github.com/rust-lang/rust/issues/134645#issuecomment-3324577500, since `Once` will not have a non-poisoning variant, we remove it from the `poison` module. Additionally: 1. Renames `once::ExclusiveState` to `OnceExclusiveState` since it was a bit confusing reading just `ExclusiveState` where it is used. 2. Reorders a few module definitions and re-exports in `library/std/src/sync/mod.rs` for clarity. Also, once this is merged, I think that we can begin the process of stabilizing [`sync_poison_mod`](https://github.com/rust-lang/rust/issues/134646)
diff --git a/Cargo.lock b/Cargo.lock index e661d81..bcb7dd1 100644 --- a/Cargo.lock +++ b/Cargo.lock
@@ -5263,9 +5263,9 @@ [[package]] name = "stringdex" -version = "0.0.1-alpha10" +version = "0.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa846a7d509d1828a4f90962dc09810e161abcada7fc6a921e92c168d0811d7" +checksum = "18b3bd4f10d15ef859c40291769f0d85209de6b0f1c30713ff9cdf45ac43ea36" dependencies = [ "stacker", ]
diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index d11b7f7..e4b23cb 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs
@@ -426,7 +426,7 @@ fn lower_item_kind( |this| { this.lower_param_bounds( bounds, - RelaxedBoundPolicy::Allowed, + RelaxedBoundPolicy::Forbidden(RelaxedBoundForbiddenReason::TraitAlias), ImplTraitContext::Disallowed(ImplTraitPosition::Bound), ) },
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 282a62c..d959657 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -297,6 +297,7 @@ enum RelaxedBoundPolicy<'a> { enum RelaxedBoundForbiddenReason { TraitObjectTy, SuperTrait, + TraitAlias, AssocTyBounds, LateBoundVarsInScope, } @@ -2086,12 +2087,14 @@ fn validate_relaxed_bound( span: Span, rbp: RelaxedBoundPolicy<'_>, ) { - // Even though feature `more_maybe_bounds` bypasses the given policy and (currently) enables - // relaxed bounds in every conceivable position[^1], we don't want to advertise it to the user - // (via a feature gate) since it's super internal. Besides this, it'd be quite distracting. + // Even though feature `more_maybe_bounds` enables the user to relax all default bounds + // other than `Sized` in a lot more positions (thereby bypassing the given policy), we don't + // want to advertise it to the user (via a feature gate error) since it's super internal. // - // [^1]: Strictly speaking, this is incorrect (at the very least for `Sized`) because it's - // no longer fully consistent with default trait elaboration in HIR ty lowering. + // FIXME(more_maybe_bounds): Moreover, if we actually were to add proper default traits + // (like a hypothetical `Move` or `Leak`) we would want to validate the location according + // to default trait elaboration in HIR ty lowering (which depends on the specific trait in + // question: E.g., `?Sized` & `?Move` most likely won't be allowed in all the same places). match rbp { RelaxedBoundPolicy::Allowed => return, @@ -2104,33 +2107,41 @@ fn validate_relaxed_bound( } } RelaxedBoundPolicy::Forbidden(reason) => { + let gate = |context, subject| { + let extended = self.tcx.features().more_maybe_bounds(); + let is_sized = trait_ref + .trait_def_id() + .is_some_and(|def_id| self.tcx.is_lang_item(def_id, hir::LangItem::Sized)); + + if extended && !is_sized { + return; + } + + let prefix = if extended { "`Sized` " } else { "" }; + let mut diag = self.dcx().struct_span_err( + span, + format!("relaxed {prefix}bounds are not permitted in {context}"), + ); + if is_sized { + diag.note(format!( + "{subject} are not implicitly bounded by `Sized`, \ + so there is nothing to relax" + )); + } + diag.emit(); + }; + match reason { RelaxedBoundForbiddenReason::TraitObjectTy => { - if self.tcx.features().more_maybe_bounds() { - return; - } - - self.dcx().span_err( - span, - "relaxed bounds are not permitted in trait object types", - ); + gate("trait object types", "trait object types"); return; } RelaxedBoundForbiddenReason::SuperTrait => { - if self.tcx.features().more_maybe_bounds() { - return; - } - - let mut diag = self.dcx().struct_span_err( - span, - "relaxed bounds are not permitted in supertrait bounds", - ); - if let Some(def_id) = trait_ref.trait_def_id() - && self.tcx.is_lang_item(def_id, hir::LangItem::Sized) - { - diag.note("traits are `?Sized` by default"); - } - diag.emit(); + gate("supertrait bounds", "traits"); + return; + } + RelaxedBoundForbiddenReason::TraitAlias => { + gate("trait alias bounds", "trait aliases"); return; } RelaxedBoundForbiddenReason::AssocTyBounds @@ -2143,7 +2154,7 @@ fn validate_relaxed_bound( .struct_span_err(span, "this relaxed bound is not permitted here") .with_note( "in this context, relaxed bounds are only allowed on \ - type parameters defined by the closest item", + type parameters defined on the closest item", ) .emit(); }
diff --git a/compiler/rustc_attr_parsing/messages.ftl b/compiler/rustc_attr_parsing/messages.ftl index 8b6b762..a2a5f8a 100644 --- a/compiler/rustc_attr_parsing/messages.ftl +++ b/compiler/rustc_attr_parsing/messages.ftl
@@ -4,6 +4,8 @@ attr_parsing_bundle_needs_static = linking modifier `bundle` is only compatible with `static` linking kind +attr_parsing_cfg_attr_bad_delim = wrong `cfg_attr` delimiters + attr_parsing_cfg_predicate_identifier = `cfg` predicate key must be an identifier
diff --git a/compiler/rustc_attr_parsing/src/attributes/cfg.rs b/compiler/rustc_attr_parsing/src/attributes/cfg.rs index 7085561..af94e8a 100644 --- a/compiler/rustc_attr_parsing/src/attributes/cfg.rs +++ b/compiler/rustc_attr_parsing/src/attributes/cfg.rs
@@ -1,19 +1,28 @@ -use rustc_ast::{LitKind, NodeId}; +use rustc_ast::token::Delimiter; +use rustc_ast::tokenstream::DelimSpan; +use rustc_ast::{AttrItem, Attribute, CRATE_NODE_ID, LitKind, NodeId, ast, token}; +use rustc_errors::{Applicability, PResult}; use rustc_feature::{AttributeTemplate, Features, template}; -use rustc_hir::RustcVersion; use rustc_hir::attrs::CfgEntry; +use rustc_hir::{AttrPath, RustcVersion}; +use rustc_parse::parser::{ForceCollect, Parser}; +use rustc_parse::{exp, parse_in}; use rustc_session::Session; use rustc_session::config::ExpectedValues; use rustc_session::lint::BuiltinLintDiag; use rustc_session::lint::builtin::UNEXPECTED_CFGS; -use rustc_session::parse::feature_err; +use rustc_session::parse::{ParseSess, feature_err}; use rustc_span::{Span, Symbol, sym}; use thin_vec::ThinVec; use crate::context::{AcceptContext, ShouldEmit, Stage}; use crate::parser::{ArgParser, MetaItemListParser, MetaItemOrLitParser, NameValueParser}; +use crate::session_diagnostics::{ + AttributeParseError, AttributeParseErrorReason, CfgAttrBadDelim, MetaBadDelimSugg, +}; use crate::{ - CfgMatchesLintEmitter, fluent_generated, parse_version, session_diagnostics, try_gate_cfg, + AttributeParser, CfgMatchesLintEmitter, fluent_generated, parse_version, session_diagnostics, + try_gate_cfg, }; pub const CFG_TEMPLATE: AttributeTemplate = template!( @@ -21,7 +30,12 @@ "https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg-attribute" ); -pub fn parse_cfg_attr<'c, S: Stage>( +const CFG_ATTR_TEMPLATE: AttributeTemplate = template!( + List: &["predicate, attr1, attr2, ..."], + "https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg_attr-attribute" +); + +pub fn parse_cfg<'c, S: Stage>( cx: &'c mut AcceptContext<'_, '_, S>, args: &'c ArgParser<'_>, ) -> Option<CfgEntry> { @@ -70,9 +84,7 @@ pub(crate) fn parse_cfg_entry<S: Stage>( }, a @ (ArgParser::NoArgs | ArgParser::NameValue(_)) => { let Some(name) = meta.path().word_sym() else { - cx.emit_err(session_diagnostics::CfgPredicateIdentifier { - span: meta.path().span(), - }); + cx.expected_identifier(meta.path().span()); return None; }; parse_name_value(name, meta.path().span(), a.name_value(), meta.span(), cx)? @@ -81,7 +93,7 @@ pub(crate) fn parse_cfg_entry<S: Stage>( MetaItemOrLitParser::Lit(lit) => match lit.kind { LitKind::Bool(b) => CfgEntry::Bool(b, lit.span), _ => { - cx.emit_err(session_diagnostics::CfgPredicateIdentifier { span: lit.span }); + cx.expected_identifier(lit.span); return None; } }, @@ -149,9 +161,7 @@ fn parse_cfg_entry_target<S: Stage>( // Then, parse it as a name-value item let Some(name) = sub_item.path().word_sym() else { - cx.emit_err(session_diagnostics::CfgPredicateIdentifier { - span: sub_item.path().span(), - }); + cx.expected_identifier(sub_item.path().span()); return None; }; let name = Symbol::intern(&format!("target_{name}")); @@ -300,3 +310,120 @@ pub fn as_bool(&self) -> bool { } } } + +pub fn parse_cfg_attr( + cfg_attr: &Attribute, + sess: &Session, + features: Option<&Features>, +) -> Option<(CfgEntry, Vec<(AttrItem, Span)>)> { + match cfg_attr.get_normal_item().args { + ast::AttrArgs::Delimited(ast::DelimArgs { dspan, delim, ref tokens }) + if !tokens.is_empty() => + { + check_cfg_attr_bad_delim(&sess.psess, dspan, delim); + match parse_in(&sess.psess, tokens.clone(), "`cfg_attr` input", |p| { + parse_cfg_attr_internal(p, sess, features, cfg_attr) + }) { + Ok(r) => return Some(r), + Err(e) => { + let suggestions = CFG_ATTR_TEMPLATE.suggestions(cfg_attr.style, sym::cfg_attr); + e.with_span_suggestions( + cfg_attr.span, + "must be of the form", + suggestions, + Applicability::HasPlaceholders, + ) + .with_note(format!( + "for more information, visit <{}>", + CFG_ATTR_TEMPLATE.docs.expect("cfg_attr has docs") + )) + .emit(); + } + } + } + _ => { + let (span, reason) = if let ast::AttrArgs::Delimited(ast::DelimArgs { dspan, .. }) = + cfg_attr.get_normal_item().args + { + (dspan.entire(), AttributeParseErrorReason::ExpectedAtLeastOneArgument) + } else { + (cfg_attr.span, AttributeParseErrorReason::ExpectedList) + }; + + sess.dcx().emit_err(AttributeParseError { + span, + attr_span: cfg_attr.span, + template: CFG_ATTR_TEMPLATE, + attribute: AttrPath::from_ast(&cfg_attr.get_normal_item().path), + reason, + attr_style: cfg_attr.style, + }); + } + } + None +} + +fn check_cfg_attr_bad_delim(psess: &ParseSess, span: DelimSpan, delim: Delimiter) { + if let Delimiter::Parenthesis = delim { + return; + } + psess.dcx().emit_err(CfgAttrBadDelim { + span: span.entire(), + sugg: MetaBadDelimSugg { open: span.open, close: span.close }, + }); +} + +/// Parses `cfg_attr(pred, attr_item_list)` where `attr_item_list` is comma-delimited. +fn parse_cfg_attr_internal<'a>( + parser: &mut Parser<'a>, + sess: &'a Session, + features: Option<&Features>, + attribute: &Attribute, +) -> PResult<'a, (CfgEntry, Vec<(ast::AttrItem, Span)>)> { + // Parse cfg predicate + let pred_start = parser.token.span; + let meta = MetaItemOrLitParser::parse_single(parser, ShouldEmit::ErrorsAndLints)?; + let pred_span = pred_start.with_hi(parser.token.span.hi()); + + let cfg_predicate = AttributeParser::parse_single_args( + sess, + attribute.span, + attribute.style, + AttrPath { + segments: attribute + .ident_path() + .expect("cfg_attr is not a doc comment") + .into_boxed_slice(), + span: attribute.span, + }, + pred_span, + CRATE_NODE_ID, + features, + ShouldEmit::ErrorsAndLints, + &meta, + parse_cfg_entry, + &CFG_ATTR_TEMPLATE, + ) + .ok_or_else(|| { + let mut diag = sess.dcx().struct_err( + "cfg_entry parsing failing with `ShouldEmit::ErrorsAndLints` should emit a error.", + ); + diag.downgrade_to_delayed_bug(); + diag + })?; + + parser.expect(exp!(Comma))?; + + // Presumably, the majority of the time there will only be one attr. + let mut expanded_attrs = Vec::with_capacity(1); + while parser.token != token::Eof { + let lo = parser.token.span; + let item = parser.parse_attr_item(ForceCollect::Yes)?; + expanded_attrs.push((item, lo.to(parser.prev_token.span))); + if !parser.eat(exp!(Comma)) { + break; + } + } + + Ok((cfg_predicate, expanded_attrs)) +}
diff --git a/compiler/rustc_attr_parsing/src/interface.rs b/compiler/rustc_attr_parsing/src/interface.rs index 8f2de4a..b8ef11c 100644 --- a/compiler/rustc_attr_parsing/src/interface.rs +++ b/compiler/rustc_attr_parsing/src/interface.rs
@@ -1,7 +1,7 @@ use std::borrow::Cow; use rustc_ast as ast; -use rustc_ast::NodeId; +use rustc_ast::{AttrStyle, NodeId}; use rustc_errors::DiagCtxtHandle; use rustc_feature::{AttributeTemplate, Features}; use rustc_hir::attrs::AttributeKind; @@ -62,7 +62,8 @@ pub fn parse_limited( ) } - /// Usually you want `parse_limited`, which defaults to no errors. + /// This does the same as `parse_limited`, except it has a `should_emit` parameter which allows it to emit errors. + /// Usually you want `parse_limited`, which emits no errors. pub fn parse_limited_should_emit( sess: &'sess Session, attrs: &[ast::Attribute], @@ -86,6 +87,13 @@ pub fn parse_limited_should_emit( parsed.pop() } + /// This method allows you to parse a list of attributes *before* `rustc_ast_lowering`. + /// This can be used for attributes that would be removed before `rustc_ast_lowering`, such as attributes on macro calls. + /// + /// Try to use this as little as possible. Attributes *should* be lowered during + /// `rustc_ast_lowering`. Some attributes require access to features to parse, which would + /// crash if you tried to do so through [`parse_limited_all`](Self::parse_limited_all). + /// Therefore, if `parse_only` is None, then features *must* be provided. pub fn parse_limited_all( sess: &'sess Session, attrs: &[ast::Attribute], @@ -111,6 +119,8 @@ pub fn parse_limited_all( ) } + /// This method parses a single attribute, using `parse_fn`. + /// This is useful if you already know what exact attribute this is, and want to parse it. pub fn parse_single<T>( sess: &'sess Session, attr: &ast::Attribute, @@ -121,13 +131,6 @@ pub fn parse_single<T>( parse_fn: fn(cx: &mut AcceptContext<'_, '_, Early>, item: &ArgParser<'_>) -> Option<T>, template: &AttributeTemplate, ) -> Option<T> { - let mut parser = Self { - features, - tools: Vec::new(), - parse_only: None, - sess, - stage: Early { emit_errors }, - }; let ast::AttrKind::Normal(normal_attr) = &attr.kind else { panic!("parse_single called on a doc attr") }; @@ -136,6 +139,43 @@ pub fn parse_single<T>( let meta_parser = MetaItemParser::from_attr(normal_attr, &parts, &sess.psess, emit_errors)?; let path = meta_parser.path(); let args = meta_parser.args(); + Self::parse_single_args( + sess, + attr.span, + attr.style, + path.get_attribute_path(), + target_span, + target_node_id, + features, + emit_errors, + args, + parse_fn, + template, + ) + } + + /// This method is equivalent to `parse_single`, but parses arguments using `parse_fn` using manually created `args`. + /// This is useful when you want to parse other things than attributes using attribute parsers. + pub fn parse_single_args<T, I>( + sess: &'sess Session, + attr_span: Span, + attr_style: AttrStyle, + attr_path: AttrPath, + target_span: Span, + target_node_id: NodeId, + features: Option<&'sess Features>, + emit_errors: ShouldEmit, + args: &I, + parse_fn: fn(cx: &mut AcceptContext<'_, '_, Early>, item: &I) -> Option<T>, + template: &AttributeTemplate, + ) -> Option<T> { + let mut parser = Self { + features, + tools: Vec::new(), + parse_only: None, + sess, + stage: Early { emit_errors }, + }; let mut cx: AcceptContext<'_, 'sess, Early> = AcceptContext { shared: SharedContext { cx: &mut parser, @@ -145,10 +185,10 @@ pub fn parse_single<T>( crate::lints::emit_attribute_lint(&lint, sess); }, }, - attr_span: attr.span, - attr_style: attr.style, + attr_span, + attr_style, template, - attr_path: path.get_attribute_path(), + attr_path, }; parse_fn(&mut cx, args) }
diff --git a/compiler/rustc_attr_parsing/src/lib.rs b/compiler/rustc_attr_parsing/src/lib.rs index f51cc8c..bcd0d67 100644 --- a/compiler/rustc_attr_parsing/src/lib.rs +++ b/compiler/rustc_attr_parsing/src/lib.rs
@@ -105,7 +105,9 @@ mod target_checking; pub mod validate_attr; -pub use attributes::cfg::{CFG_TEMPLATE, EvalConfigResult, eval_config_entry, parse_cfg_attr}; +pub use attributes::cfg::{ + CFG_TEMPLATE, EvalConfigResult, eval_config_entry, parse_cfg, parse_cfg_attr, +}; pub use attributes::cfg_old::*; pub use attributes::util::{is_builtin_attr, is_doc_alias_attrs_contain_symbol, parse_version}; pub use context::{Early, Late, OmitDoc, ShouldEmit};
diff --git a/compiler/rustc_attr_parsing/src/parser.rs b/compiler/rustc_attr_parsing/src/parser.rs index 3f4f567..7474471 100644 --- a/compiler/rustc_attr_parsing/src/parser.rs +++ b/compiler/rustc_attr_parsing/src/parser.rs
@@ -8,7 +8,7 @@ use rustc_ast::token::{self, Delimiter, MetaVarKind}; use rustc_ast::tokenstream::TokenStream; -use rustc_ast::{AttrArgs, DelimArgs, Expr, ExprKind, LitKind, MetaItemLit, NormalAttr, Path}; +use rustc_ast::{AttrArgs, Expr, ExprKind, LitKind, MetaItemLit, NormalAttr, Path}; use rustc_ast_pretty::pprust; use rustc_errors::{Diag, PResult}; use rustc_hir::{self as hir, AttrPath}; @@ -124,7 +124,11 @@ pub fn from_attr_args<'sess>( return None; } - Self::List(MetaItemListParser::new(args, psess, should_emit)?) + Self::List( + MetaItemListParser::new(&args.tokens, args.dspan.entire(), psess, should_emit) + .map_err(|e| should_emit.emit_err(e)) + .ok()?, + ) } AttrArgs::Eq { eq_span, expr } => Self::NameValue(NameValueParser { eq_span: *eq_span, @@ -186,7 +190,15 @@ pub enum MetaItemOrLitParser<'a> { Err(Span, ErrorGuaranteed), } -impl<'a> MetaItemOrLitParser<'a> { +impl<'sess> MetaItemOrLitParser<'sess> { + pub fn parse_single( + parser: &mut Parser<'sess>, + should_emit: ShouldEmit, + ) -> PResult<'sess, MetaItemOrLitParser<'static>> { + let mut this = MetaItemListParserContext { parser, should_emit }; + this.parse_meta_item_inner() + } + pub fn span(&self) -> Span { match self { MetaItemOrLitParser::MetaItemParser(generic_meta_item_parser) => { @@ -204,7 +216,7 @@ pub fn lit(&self) -> Option<&MetaItemLit> { } } - pub fn meta_item(&self) -> Option<&MetaItemParser<'a>> { + pub fn meta_item(&self) -> Option<&MetaItemParser<'sess>> { match self { MetaItemOrLitParser::MetaItemParser(parser) => Some(parser), _ => None, @@ -542,23 +554,13 @@ pub struct MetaItemListParser<'a> { } impl<'a> MetaItemListParser<'a> { - fn new<'sess>( - delim: &'a DelimArgs, + pub(crate) fn new<'sess>( + tokens: &'a TokenStream, + span: Span, psess: &'sess ParseSess, should_emit: ShouldEmit, - ) -> Option<Self> { - match MetaItemListParserContext::parse( - delim.tokens.clone(), - psess, - delim.dspan.entire(), - should_emit, - ) { - Ok(s) => Some(s), - Err(e) => { - should_emit.emit_err(e); - None - } - } + ) -> Result<Self, Diag<'sess>> { + MetaItemListParserContext::parse(tokens.clone(), psess, span, should_emit) } /// Lets you pick and choose as what you want to parse each element in the list
diff --git a/compiler/rustc_attr_parsing/src/session_diagnostics.rs b/compiler/rustc_attr_parsing/src/session_diagnostics.rs index 1194ac5..7b82f3b 100644 --- a/compiler/rustc_attr_parsing/src/session_diagnostics.rs +++ b/compiler/rustc_attr_parsing/src/session_diagnostics.rs
@@ -971,3 +971,12 @@ pub(crate) struct LimitInvalid<'a> { pub value_span: Span, pub error_str: &'a str, } + +#[derive(Diagnostic)] +#[diag(attr_parsing_cfg_attr_bad_delim)] +pub(crate) struct CfgAttrBadDelim { + #[primary_span] + pub span: Span, + #[subdiagnostic] + pub sugg: MetaBadDelimSugg, +}
diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index 6b5af15..b4990ff 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
@@ -708,8 +708,7 @@ fn is_error_in_trait(&self, local: Local) -> (bool, bool, Option<Span>) { return (false, false, None); } let my_def = self.body.source.def_id(); - let Some(td) = - tcx.trait_impl_of_assoc(my_def).and_then(|id| self.infcx.tcx.trait_id_of_impl(id)) + let Some(td) = tcx.trait_impl_of_assoc(my_def).map(|id| self.infcx.tcx.impl_trait_id(id)) else { return (false, false, None); };
diff --git a/compiler/rustc_borrowck/src/renumber.rs b/compiler/rustc_borrowck/src/renumber.rs index fa3064a..d6dbc7d 100644 --- a/compiler/rustc_borrowck/src/renumber.rs +++ b/compiler/rustc_borrowck/src/renumber.rs
@@ -21,10 +21,10 @@ pub(crate) fn renumber_mir<'tcx>( let mut renumberer = RegionRenumberer { infcx }; for body in promoted.iter_mut() { - renumberer.visit_body(body); + renumberer.visit_body_preserves_cfg(body); } - renumberer.visit_body(body); + renumberer.visit_body_preserves_cfg(body); } // The fields are used only for debugging output in `sccs_info`.
diff --git a/compiler/rustc_codegen_cranelift/src/abi/mod.rs b/compiler/rustc_codegen_cranelift/src/abi/mod.rs index 29ee461..9a9a1f4 100644 --- a/compiler/rustc_codegen_cranelift/src/abi/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/abi/mod.rs
@@ -467,7 +467,7 @@ pub(crate) fn codegen_terminator_call<'tcx>( true } else { instance.is_some_and(|inst| { - fx.tcx.codegen_fn_attrs(inst.def_id()).flags.contains(CodegenFnAttrFlags::COLD) + fx.tcx.codegen_instance_attrs(inst.def).flags.contains(CodegenFnAttrFlags::COLD) }) }; if is_cold {
diff --git a/compiler/rustc_codegen_llvm/src/builder/gpu_offload.rs b/compiler/rustc_codegen_llvm/src/builder/gpu_offload.rs index 0737a18..3d55064 100644 --- a/compiler/rustc_codegen_llvm/src/builder/gpu_offload.rs +++ b/compiler/rustc_codegen_llvm/src/builder/gpu_offload.rs
@@ -16,25 +16,42 @@ pub(crate) fn handle_gpu_code<'ll>( cx: &'ll SimpleCx<'_>, ) { // The offload memory transfer type for each kernel - let mut o_types = vec![]; - let mut kernels = vec![]; - let offload_entry_ty = add_tgt_offload_entry(&cx); + let mut memtransfer_types = vec![]; + let mut region_ids = vec![]; + let offload_entry_ty = TgtOffloadEntry::new_decl(&cx); for num in 0..9 { let kernel = cx.get_function(&format!("kernel_{num}")); if let Some(kernel) = kernel { - o_types.push(gen_define_handling(&cx, kernel, offload_entry_ty, num)); - kernels.push(kernel); + let (o, k) = gen_define_handling(&cx, kernel, offload_entry_ty, num); + memtransfer_types.push(o); + region_ids.push(k); } } - gen_call_handling(&cx, &kernels, &o_types); + gen_call_handling(&cx, &memtransfer_types, ®ion_ids); +} + +// ; Function Attrs: nounwind +// declare i32 @__tgt_target_kernel(ptr, i64, i32, i32, ptr, ptr) #2 +fn generate_launcher<'ll>(cx: &'ll SimpleCx<'_>) -> (&'ll llvm::Value, &'ll llvm::Type) { + let tptr = cx.type_ptr(); + let ti64 = cx.type_i64(); + let ti32 = cx.type_i32(); + let args = vec![tptr, ti64, ti32, ti32, tptr, tptr]; + let tgt_fn_ty = cx.type_func(&args, ti32); + let name = "__tgt_target_kernel"; + let tgt_decl = declare_offload_fn(&cx, name, tgt_fn_ty); + let nounwind = llvm::AttributeKind::NoUnwind.create_attr(cx.llcx); + attributes::apply_to_llfn(tgt_decl, Function, &[nounwind]); + (tgt_decl, tgt_fn_ty) } // What is our @1 here? A magic global, used in our data_{begin/update/end}_mapper: // @0 = private unnamed_addr constant [23 x i8] c";unknown;unknown;0;0;;\00", align 1 // @1 = private unnamed_addr constant %struct.ident_t { i32 0, i32 2, i32 0, i32 22, ptr @0 }, align 8 +// FIXME(offload): @0 should include the file name (e.g. lib.rs) in which the function to be +// offloaded was defined. fn generate_at_one<'ll>(cx: &'ll SimpleCx<'_>) -> &'ll llvm::Value { - // @0 = private unnamed_addr constant [23 x i8] c";unknown;unknown;0;0;;\00", align 1 let unknown_txt = ";unknown;unknown;0;0;;"; let c_entry_name = CString::new(unknown_txt).unwrap(); let c_val = c_entry_name.as_bytes_with_nul(); @@ -59,15 +76,7 @@ fn generate_at_one<'ll>(cx: &'ll SimpleCx<'_>) -> &'ll llvm::Value { at_one } -pub(crate) fn add_tgt_offload_entry<'ll>(cx: &'ll SimpleCx<'_>) -> &'ll llvm::Type { - let offload_entry_ty = cx.type_named_struct("struct.__tgt_offload_entry"); - let tptr = cx.type_ptr(); - let ti64 = cx.type_i64(); - let ti32 = cx.type_i32(); - let ti16 = cx.type_i16(); - // For each kernel to run on the gpu, we will later generate one entry of this type. - // copied from LLVM - // typedef struct { +struct TgtOffloadEntry { // uint64_t Reserved; // uint16_t Version; // uint16_t Kind; @@ -77,21 +86,40 @@ pub(crate) fn add_tgt_offload_entry<'ll>(cx: &'ll SimpleCx<'_>) -> &'ll llvm::Ty // uint64_t Size; Size of the entry info (0 if it is a function) // uint64_t Data; // void *AuxAddr; - // } __tgt_offload_entry; - let entry_elements = vec![ti64, ti16, ti16, ti32, tptr, tptr, ti64, ti64, tptr]; - cx.set_struct_body(offload_entry_ty, &entry_elements, false); - offload_entry_ty } -fn gen_tgt_kernel_global<'ll>(cx: &'ll SimpleCx<'_>) { - let kernel_arguments_ty = cx.type_named_struct("struct.__tgt_kernel_arguments"); - let tptr = cx.type_ptr(); - let ti64 = cx.type_i64(); - let ti32 = cx.type_i32(); - let tarr = cx.type_array(ti32, 3); +impl TgtOffloadEntry { + pub(crate) fn new_decl<'ll>(cx: &'ll SimpleCx<'_>) -> &'ll llvm::Type { + let offload_entry_ty = cx.type_named_struct("struct.__tgt_offload_entry"); + let tptr = cx.type_ptr(); + let ti64 = cx.type_i64(); + let ti32 = cx.type_i32(); + let ti16 = cx.type_i16(); + // For each kernel to run on the gpu, we will later generate one entry of this type. + // copied from LLVM + let entry_elements = vec![ti64, ti16, ti16, ti32, tptr, tptr, ti64, ti64, tptr]; + cx.set_struct_body(offload_entry_ty, &entry_elements, false); + offload_entry_ty + } - // Taken from the LLVM APITypes.h declaration: - //struct KernelArgsTy { + fn new<'ll>( + cx: &'ll SimpleCx<'_>, + region_id: &'ll Value, + llglobal: &'ll Value, + ) -> [&'ll Value; 9] { + let reserved = cx.get_const_i64(0); + let version = cx.get_const_i16(1); + let kind = cx.get_const_i16(1); + let flags = cx.get_const_i32(0); + let size = cx.get_const_i64(0); + let data = cx.get_const_i64(0); + let aux_addr = cx.const_null(cx.type_ptr()); + [reserved, version, kind, flags, region_id, llglobal, size, data, aux_addr] + } +} + +// Taken from the LLVM APITypes.h declaration: +struct KernelArgsTy { // uint32_t Version = 0; // Version of this struct for ABI compatibility. // uint32_t NumArgs = 0; // Number of arguments in each input pointer. // void **ArgBasePtrs = @@ -102,25 +130,65 @@ fn gen_tgt_kernel_global<'ll>(cx: &'ll SimpleCx<'_>) { // void **ArgNames = nullptr; // Name of the data for debugging, possibly null. // void **ArgMappers = nullptr; // User-defined mappers, possibly null. // uint64_t Tripcount = - // 0; // Tripcount for the teams / distribute loop, 0 otherwise. - // struct { + // 0; // Tripcount for the teams / distribute loop, 0 otherwise. + // struct { // uint64_t NoWait : 1; // Was this kernel spawned with a `nowait` clause. // uint64_t IsCUDA : 1; // Was this kernel spawned via CUDA. // uint64_t Unused : 62; - // } Flags = {0, 0, 0}; + // } Flags = {0, 0, 0}; // totals to 64 Bit, 8 Byte // // The number of teams (for x,y,z dimension). // uint32_t NumTeams[3] = {0, 0, 0}; // // The number of threads (for x,y,z dimension). // uint32_t ThreadLimit[3] = {0, 0, 0}; // uint32_t DynCGroupMem = 0; // Amount of dynamic cgroup memory requested. - //}; - let kernel_elements = - vec![ti32, ti32, tptr, tptr, tptr, tptr, tptr, tptr, ti64, ti64, tarr, tarr, ti32]; +} - cx.set_struct_body(kernel_arguments_ty, &kernel_elements, false); - // For now we don't handle kernels, so for now we just add a global dummy - // to make sure that the __tgt_offload_entry is defined and handled correctly. - cx.declare_global("my_struct_global2", kernel_arguments_ty); +impl KernelArgsTy { + const OFFLOAD_VERSION: u64 = 3; + const FLAGS: u64 = 0; + const TRIPCOUNT: u64 = 0; + fn new_decl<'ll>(cx: &'ll SimpleCx<'_>) -> &'ll Type { + let kernel_arguments_ty = cx.type_named_struct("struct.__tgt_kernel_arguments"); + let tptr = cx.type_ptr(); + let ti64 = cx.type_i64(); + let ti32 = cx.type_i32(); + let tarr = cx.type_array(ti32, 3); + + let kernel_elements = + vec![ti32, ti32, tptr, tptr, tptr, tptr, tptr, tptr, ti64, ti64, tarr, tarr, ti32]; + + cx.set_struct_body(kernel_arguments_ty, &kernel_elements, false); + kernel_arguments_ty + } + + fn new<'ll>( + cx: &'ll SimpleCx<'_>, + num_args: u64, + memtransfer_types: &[&'ll Value], + geps: [&'ll Value; 3], + ) -> [(Align, &'ll Value); 13] { + let four = Align::from_bytes(4).expect("4 Byte alignment should work"); + let eight = Align::EIGHT; + + let ti32 = cx.type_i32(); + let ci32_0 = cx.get_const_i32(0); + [ + (four, cx.get_const_i32(KernelArgsTy::OFFLOAD_VERSION)), + (four, cx.get_const_i32(num_args)), + (eight, geps[0]), + (eight, geps[1]), + (eight, geps[2]), + (eight, memtransfer_types[0]), + // The next two are debug infos. FIXME(offload): set them + (eight, cx.const_null(cx.type_ptr())), // dbg + (eight, cx.const_null(cx.type_ptr())), // dbg + (eight, cx.get_const_i64(KernelArgsTy::TRIPCOUNT)), + (eight, cx.get_const_i64(KernelArgsTy::FLAGS)), + (four, cx.const_array(ti32, &[cx.get_const_i32(2097152), ci32_0, ci32_0])), + (four, cx.const_array(ti32, &[cx.get_const_i32(256), ci32_0, ci32_0])), + (four, cx.get_const_i32(0)), + ] + } } fn gen_tgt_data_mappers<'ll>( @@ -182,12 +250,15 @@ pub(crate) fn add_global<'ll>( llglobal } +// This function returns a memtransfer value which encodes how arguments to this kernel shall be +// mapped to/from the gpu. It also returns a region_id with the name of this kernel, to be +// concatenated into the list of region_ids. fn gen_define_handling<'ll>( cx: &'ll SimpleCx<'_>, kernel: &'ll llvm::Value, offload_entry_ty: &'ll llvm::Type, num: i64, -) -> &'ll llvm::Value { +) -> (&'ll llvm::Value, &'ll llvm::Value) { let types = cx.func_params_types(cx.get_type_of_global(kernel)); // It seems like non-pointer values are automatically mapped. So here, we focus on pointer (or // reference) types. @@ -205,10 +276,14 @@ fn gen_define_handling<'ll>( // or both to and from the gpu (=3). Other values shouldn't affect us for now. // A non-mutable reference or pointer will be 1, an array that's not read, but fully overwritten // will be 2. For now, everything is 3, until we have our frontend set up. - let o_types = - add_priv_unnamed_arr(&cx, &format!(".offload_maptypes.{num}"), &vec![3; num_ptr_types]); + // 1+2+32: 1 (MapTo), 2 (MapFrom), 32 (Add one extra input ptr per function, to be used later). + let memtransfer_types = add_priv_unnamed_arr( + &cx, + &format!(".offload_maptypes.{num}"), + &vec![1 + 2 + 32; num_ptr_types], + ); // Next: For each function, generate these three entries. A weak constant, - // the llvm.rodata entry name, and the omp_offloading_entries value + // the llvm.rodata entry name, and the llvm_offload_entries value let name = format!(".kernel_{num}.region_id"); let initializer = cx.get_const_i8(0); @@ -222,19 +297,10 @@ fn gen_define_handling<'ll>( let llglobal = add_unnamed_global(&cx, &offload_entry_name, initializer, InternalLinkage); llvm::set_alignment(llglobal, Align::ONE); llvm::set_section(llglobal, c".llvm.rodata.offloading"); - - // Not actively used yet, for calling real kernels let name = format!(".offloading.entry.kernel_{num}"); // See the __tgt_offload_entry documentation above. - let reserved = cx.get_const_i64(0); - let version = cx.get_const_i16(1); - let kind = cx.get_const_i16(1); - let flags = cx.get_const_i32(0); - let size = cx.get_const_i64(0); - let data = cx.get_const_i64(0); - let aux_addr = cx.const_null(cx.type_ptr()); - let elems = vec![reserved, version, kind, flags, region_id, llglobal, size, data, aux_addr]; + let elems = TgtOffloadEntry::new(&cx, region_id, llglobal); let initializer = crate::common::named_struct(offload_entry_ty, &elems); let c_name = CString::new(name).unwrap(); @@ -242,13 +308,13 @@ fn gen_define_handling<'ll>( llvm::set_global_constant(llglobal, true); llvm::set_linkage(llglobal, WeakAnyLinkage); llvm::set_initializer(llglobal, initializer); - llvm::set_alignment(llglobal, Align::ONE); - let c_section_name = CString::new(".omp_offloading_entries").unwrap(); + llvm::set_alignment(llglobal, Align::EIGHT); + let c_section_name = CString::new("llvm_offload_entries").unwrap(); llvm::set_section(llglobal, &c_section_name); - o_types + (memtransfer_types, region_id) } -fn declare_offload_fn<'ll>( +pub(crate) fn declare_offload_fn<'ll>( cx: &'ll SimpleCx<'_>, name: &str, ty: &'ll llvm::Type, @@ -285,9 +351,10 @@ fn declare_offload_fn<'ll>( // 6. generate __tgt_target_data_end calls to move data from the GPU fn gen_call_handling<'ll>( cx: &'ll SimpleCx<'_>, - _kernels: &[&'ll llvm::Value], - o_types: &[&'ll llvm::Value], + memtransfer_types: &[&'ll llvm::Value], + region_ids: &[&'ll llvm::Value], ) { + let (tgt_decl, tgt_target_kernel_ty) = generate_launcher(&cx); // %struct.__tgt_bin_desc = type { i32, ptr, ptr, ptr } let tptr = cx.type_ptr(); let ti32 = cx.type_i32(); @@ -295,7 +362,7 @@ fn gen_call_handling<'ll>( let tgt_bin_desc = cx.type_named_struct("struct.__tgt_bin_desc"); cx.set_struct_body(tgt_bin_desc, &tgt_bin_desc_ty, false); - gen_tgt_kernel_global(&cx); + let tgt_kernel_decl = KernelArgsTy::new_decl(&cx); let (begin_mapper_decl, _, end_mapper_decl, fn_ty) = gen_tgt_data_mappers(&cx); let main_fn = cx.get_function("main"); @@ -329,35 +396,32 @@ fn gen_call_handling<'ll>( // These represent the sizes in bytes, e.g. the entry for `&[f64; 16]` will be 8*16. let ty2 = cx.type_array(cx.type_i64(), num_args); let a4 = builder.direct_alloca(ty2, Align::EIGHT, ".offload_sizes"); - // Now we allocate once per function param, a copy to be passed to one of our maps. - let mut vals = vec![]; - let mut geps = vec![]; - let i32_0 = cx.get_const_i32(0); - for (index, in_ty) in types.iter().enumerate() { - // get function arg, store it into the alloca, and read it. - let p = llvm::get_param(called, index as u32); - let name = llvm::get_value_name(p); - let name = str::from_utf8(&name).unwrap(); - let arg_name = format!("{name}.addr"); - let alloca = builder.direct_alloca(in_ty, Align::EIGHT, &arg_name); - builder.store(p, alloca, Align::EIGHT); - let val = builder.load(in_ty, alloca, Align::EIGHT); - let gep = builder.inbounds_gep(cx.type_f32(), val, &[i32_0]); - vals.push(val); - geps.push(gep); - } + //%kernel_args = alloca %struct.__tgt_kernel_arguments, align 8 + let a5 = builder.direct_alloca(tgt_kernel_decl, Align::EIGHT, "kernel_args"); // Step 1) unsafe { llvm::LLVMRustPositionBefore(builder.llbuilder, kernel_call) }; builder.memset(tgt_bin_desc_alloca, cx.get_const_i8(0), cx.get_const_i64(32), Align::EIGHT); + // Now we allocate once per function param, a copy to be passed to one of our maps. + let mut vals = vec![]; + let mut geps = vec![]; + let i32_0 = cx.get_const_i32(0); + for index in 0..types.len() { + let v = unsafe { llvm::LLVMGetOperand(kernel_call, index as u32).unwrap() }; + let gep = builder.inbounds_gep(cx.type_f32(), v, &[i32_0]); + vals.push(v); + geps.push(gep); + } + let mapper_fn_ty = cx.type_func(&[cx.type_ptr()], cx.type_void()); let register_lib_decl = declare_offload_fn(&cx, "__tgt_register_lib", mapper_fn_ty); let unregister_lib_decl = declare_offload_fn(&cx, "__tgt_unregister_lib", mapper_fn_ty); let init_ty = cx.type_func(&[], cx.type_void()); let init_rtls_decl = declare_offload_fn(cx, "__tgt_init_all_rtls", init_ty); + // FIXME(offload): Later we want to add them to the wrapper code, rather than our main function. // call void @__tgt_register_lib(ptr noundef %6) builder.call(mapper_fn_ty, register_lib_decl, &[tgt_bin_desc_alloca], None); // call void @__tgt_init_all_rtls() @@ -386,19 +450,19 @@ fn get_geps<'a, 'll>( a1: &'ll Value, a2: &'ll Value, a4: &'ll Value, - ) -> (&'ll Value, &'ll Value, &'ll Value) { + ) -> [&'ll Value; 3] { let i32_0 = cx.get_const_i32(0); let gep1 = builder.inbounds_gep(ty, a1, &[i32_0, i32_0]); let gep2 = builder.inbounds_gep(ty, a2, &[i32_0, i32_0]); let gep3 = builder.inbounds_gep(ty2, a4, &[i32_0, i32_0]); - (gep1, gep2, gep3) + [gep1, gep2, gep3] } fn generate_mapper_call<'a, 'll>( builder: &mut SBuilder<'a, 'll>, cx: &'ll SimpleCx<'ll>, - geps: (&'ll Value, &'ll Value, &'ll Value), + geps: [&'ll Value; 3], o_type: &'ll Value, fn_to_call: &'ll Value, fn_ty: &'ll Type, @@ -409,31 +473,51 @@ fn generate_mapper_call<'a, 'll>( let i64_max = cx.get_const_i64(u64::MAX); let num_args = cx.get_const_i32(num_args); let args = - vec![s_ident_t, i64_max, num_args, geps.0, geps.1, geps.2, o_type, nullptr, nullptr]; + vec![s_ident_t, i64_max, num_args, geps[0], geps[1], geps[2], o_type, nullptr, nullptr]; builder.call(fn_ty, fn_to_call, &args, None); } // Step 2) let s_ident_t = generate_at_one(&cx); - let o = o_types[0]; + let o = memtransfer_types[0]; let geps = get_geps(&mut builder, &cx, ty, ty2, a1, a2, a4); generate_mapper_call(&mut builder, &cx, geps, o, begin_mapper_decl, fn_ty, num_args, s_ident_t); + let values = KernelArgsTy::new(&cx, num_args, memtransfer_types, geps); // Step 3) - // Here we will add code for the actual kernel launches in a follow-up PR. - // FIXME(offload): launch kernels + // Here we fill the KernelArgsTy, see the documentation above + for (i, value) in values.iter().enumerate() { + let ptr = builder.inbounds_gep(tgt_kernel_decl, a5, &[i32_0, cx.get_const_i32(i as u64)]); + builder.store(value.1, ptr, value.0); + } + + let args = vec![ + s_ident_t, + // FIXME(offload) give users a way to select which GPU to use. + cx.get_const_i64(u64::MAX), // MAX == -1. + // FIXME(offload): Don't hardcode the numbers of threads in the future. + cx.get_const_i32(2097152), + cx.get_const_i32(256), + region_ids[0], + a5, + ]; + let offload_success = builder.call(tgt_target_kernel_ty, tgt_decl, &args, None); + // %41 = call i32 @__tgt_target_kernel(ptr @1, i64 -1, i32 2097152, i32 256, ptr @.kernel_1.region_id, ptr %kernel_args) + unsafe { + let next = llvm::LLVMGetNextInstruction(offload_success).unwrap(); + llvm::LLVMRustPositionAfter(builder.llbuilder, next); + llvm::LLVMInstructionEraseFromParent(next); + } // Step 4) - unsafe { llvm::LLVMRustPositionAfter(builder.llbuilder, kernel_call) }; - let geps = get_geps(&mut builder, &cx, ty, ty2, a1, a2, a4); generate_mapper_call(&mut builder, &cx, geps, o, end_mapper_decl, fn_ty, num_args, s_ident_t); builder.call(mapper_fn_ty, unregister_lib_decl, &[tgt_bin_desc_alloca], None); - // With this we generated the following begin and end mappers. We could easily generate the - // update mapper in an update. - // call void @__tgt_target_data_begin_mapper(ptr @1, i64 -1, i32 3, ptr %27, ptr %28, ptr %29, ptr @.offload_maptypes, ptr null, ptr null) - // call void @__tgt_target_data_update_mapper(ptr @1, i64 -1, i32 2, ptr %46, ptr %47, ptr %48, ptr @.offload_maptypes.1, ptr null, ptr null) - // call void @__tgt_target_data_end_mapper(ptr @1, i64 -1, i32 3, ptr %49, ptr %50, ptr %51, ptr @.offload_maptypes, ptr null, ptr null) + drop(builder); + // FIXME(offload) The issue is that we right now add a call to the gpu version of the function, + // and then delete the call to the CPU version. In the future, we should use an intrinsic which + // directly resolves to a call to the GPU version. + unsafe { llvm::LLVMDeleteFunction(called) }; }
diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index abda91b..284e2ec 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
@@ -1117,6 +1117,7 @@ pub(crate) fn LLVMCreateStringAttribute( // Operations on functions pub(crate) fn LLVMSetFunctionCallConv(Fn: &Value, CC: c_uint); + pub(crate) fn LLVMDeleteFunction(Fn: &Value); // Operations about llvm intrinsics pub(crate) fn LLVMLookupIntrinsicID(Name: *const c_char, NameLen: size_t) -> c_uint; @@ -1146,6 +1147,8 @@ pub(crate) fn LLVMAppendBasicBlockInContext<'a>( pub(crate) fn LLVMIsAInstruction(Val: &Value) -> Option<&Value>; pub(crate) fn LLVMGetFirstBasicBlock(Fn: &Value) -> &BasicBlock; pub(crate) fn LLVMGetOperand(Val: &Value, Index: c_uint) -> Option<&Value>; + pub(crate) fn LLVMGetNextInstruction(Val: &Value) -> Option<&Value>; + pub(crate) fn LLVMInstructionEraseFromParent(Val: &Value); // Operations on call sites pub(crate) fn LLVMSetInstructionCallConv(Instr: &Value, CC: c_uint);
diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index e371f1a..e2241a7 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs
@@ -200,10 +200,11 @@ fn do_call<Bx: BuilderMethods<'a, 'tcx>>( let fn_ty = bx.fn_decl_backend_type(fn_abi); let fn_attrs = if bx.tcx().def_kind(fx.instance.def_id()).has_codegen_attrs() { - Some(bx.tcx().codegen_fn_attrs(fx.instance.def_id())) + Some(bx.tcx().codegen_instance_attrs(fx.instance.def)) } else { None }; + let fn_attrs = fn_attrs.as_deref(); if !fn_abi.can_unwind { unwind = mir::UnwindAction::Unreachable;
diff --git a/compiler/rustc_codegen_ssa/src/mir/locals.rs b/compiler/rustc_codegen_ssa/src/mir/locals.rs index 93f0ab3..5d586d9 100644 --- a/compiler/rustc_codegen_ssa/src/mir/locals.rs +++ b/compiler/rustc_codegen_ssa/src/mir/locals.rs
@@ -40,12 +40,12 @@ pub(super) fn indices(&self) -> impl DoubleEndedIterator<Item = mir::Local> + Cl impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { pub(super) fn initialize_locals(&mut self, values: Vec<LocalRef<'tcx, Bx::Value>>) { assert!(self.locals.values.is_empty()); + self.locals.values = IndexVec::from_raw(values); // FIXME(#115215): After #115025 get's merged this might not be necessary - for (local, value) in values.into_iter().enumerate() { + for (local, value) in self.locals.values.iter_enumerated() { match value { LocalRef::Place(_) | LocalRef::UnsizedPlace(_) | LocalRef::PendingOperand => (), LocalRef::Operand(op) => { - let local = mir::Local::from_usize(local); let expected_ty = self.monomorphize(self.mir.local_decls[local].ty); if expected_ty != op.layout.ty { warn!( @@ -56,7 +56,6 @@ pub(super) fn initialize_locals(&mut self, values: Vec<LocalRef<'tcx, Bx::Value> } } } - self.locals.values.push(value); } }
diff --git a/compiler/rustc_codegen_ssa/src/mir/mod.rs b/compiler/rustc_codegen_ssa/src/mir/mod.rs index 6b109e8..1670e2d 100644 --- a/compiler/rustc_codegen_ssa/src/mir/mod.rs +++ b/compiler/rustc_codegen_ssa/src/mir/mod.rs
@@ -180,6 +180,9 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( let llfn = cx.get_fn(instance); let mut mir = tcx.instance_mir(instance.def); + // Note that the ABI logic has deduced facts about the functions' parameters based on the MIR we + // got here (`deduce_param_attrs`). That means we can *not* apply arbitrary further MIR + // transforms as that may invalidate those deduced facts! let fn_abi = cx.fn_abi_of_instance(instance, ty::List::empty()); debug!("fn_abi: {:?}", fn_abi); @@ -317,6 +320,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( } } +/// Replace `clone` calls that come from `use` statements with direct copies if possible. // FIXME: Move this function to mir::transform when post-mono MIR passes land. fn optimize_use_clone<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( cx: &'a Bx::CodegenCx,
diff --git a/compiler/rustc_const_eval/src/check_consts/qualifs.rs b/compiler/rustc_const_eval/src/check_consts/qualifs.rs index b63e929..5b65f17 100644 --- a/compiler/rustc_const_eval/src/check_consts/qualifs.rs +++ b/compiler/rustc_const_eval/src/check_consts/qualifs.rs
@@ -234,7 +234,7 @@ pub fn in_rvalue<'tcx, Q, F>( Rvalue::Discriminant(place) => in_place::<Q, _>(cx, in_local, place.as_ref()), - Rvalue::CopyForDeref(_) => bug!("`CopyForDeref` in runtime MIR"), + Rvalue::CopyForDeref(place) => in_place::<Q, _>(cx, in_local, place.as_ref()), Rvalue::Use(operand) | Rvalue::Repeat(operand, _)
diff --git a/compiler/rustc_const_eval/src/const_eval/fn_queries.rs b/compiler/rustc_const_eval/src/const_eval/fn_queries.rs index 35c3e3e..530d8d4 100644 --- a/compiler/rustc_const_eval/src/const_eval/fn_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/fn_queries.rs
@@ -7,7 +7,7 @@ fn parent_impl_or_trait_constness(tcx: TyCtxt<'_>, def_id: LocalDefId) -> hir::Constness { let parent_id = tcx.local_parent(def_id); match tcx.def_kind(parent_id) { - DefKind::Impl { of_trait: true } => tcx.impl_trait_header(parent_id).unwrap().constness, + DefKind::Impl { of_trait: true } => tcx.impl_trait_header(parent_id).constness, DefKind::Trait => { if tcx.is_const_trait(parent_id.into()) { hir::Constness::Const
diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index 0d10f29..afdb582 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs
@@ -2154,11 +2154,11 @@ fn emit_suggestion_default( assert!(!file_lines.lines.is_empty() || parts[0].span.is_dummy()); - let line_start = sm.lookup_char_pos(parts[0].span.lo()).line; + let line_start = sm.lookup_char_pos(parts[0].original_span.lo()).line; let mut lines = complete.lines(); if lines.clone().next().is_none() { // Account for a suggestion to completely remove a line(s) with whitespace (#94192). - let line_end = sm.lookup_char_pos(parts[0].span.hi()).line; + let line_end = sm.lookup_char_pos(parts[0].original_span.hi()).line; for line in line_start..=line_end { self.draw_line_num( &mut buffer,
diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 8869799..6bec65f 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs
@@ -224,6 +224,13 @@ pub struct SubstitutionPart { pub snippet: String, } +#[derive(Clone, Debug, PartialEq, Hash, Encodable, Decodable)] +pub struct TrimmedSubstitutionPart { + pub original_span: Span, + pub span: Span, + pub snippet: String, +} + /// Used to translate between `Span`s and byte positions within a single output line in highlighted /// code of structured suggestions. #[derive(Debug, Clone, Copy)] @@ -233,6 +240,35 @@ pub(crate) struct SubstitutionHighlight { } impl SubstitutionPart { + /// Try to turn a replacement into an addition when the span that is being + /// overwritten matches either the prefix or suffix of the replacement. + fn trim_trivial_replacements(self, sm: &SourceMap) -> TrimmedSubstitutionPart { + let mut trimmed_part = TrimmedSubstitutionPart { + original_span: self.span, + span: self.span, + snippet: self.snippet, + }; + if trimmed_part.snippet.is_empty() { + return trimmed_part; + } + let Ok(snippet) = sm.span_to_snippet(trimmed_part.span) else { + return trimmed_part; + }; + + if let Some((prefix, substr, suffix)) = as_substr(&snippet, &trimmed_part.snippet) { + trimmed_part.span = Span::new( + trimmed_part.span.lo() + BytePos(prefix as u32), + trimmed_part.span.hi() - BytePos(suffix as u32), + trimmed_part.span.ctxt(), + trimmed_part.span.parent(), + ); + trimmed_part.snippet = substr.to_string(); + } + trimmed_part + } +} + +impl TrimmedSubstitutionPart { pub fn is_addition(&self, sm: &SourceMap) -> bool { !self.snippet.is_empty() && !self.replaces_meaningful_content(sm) } @@ -260,27 +296,6 @@ fn replaces_meaningful_content(&self, sm: &SourceMap) -> bool { sm.span_to_snippet(self.span) .map_or(!self.span.is_empty(), |snippet| !snippet.trim().is_empty()) } - - /// Try to turn a replacement into an addition when the span that is being - /// overwritten matches either the prefix or suffix of the replacement. - fn trim_trivial_replacements(&mut self, sm: &SourceMap) { - if self.snippet.is_empty() { - return; - } - let Ok(snippet) = sm.span_to_snippet(self.span) else { - return; - }; - - if let Some((prefix, substr, suffix)) = as_substr(&snippet, &self.snippet) { - self.span = Span::new( - self.span.lo() + BytePos(prefix as u32), - self.span.hi() - BytePos(suffix as u32), - self.span.ctxt(), - self.span.parent(), - ); - self.snippet = substr.to_string(); - } - } } /// Given an original string like `AACC`, and a suggestion like `AABBCC`, try to detect @@ -310,7 +325,8 @@ impl CodeSuggestion { pub(crate) fn splice_lines( &self, sm: &SourceMap, - ) -> Vec<(String, Vec<SubstitutionPart>, Vec<Vec<SubstitutionHighlight>>, ConfusionType)> { + ) -> Vec<(String, Vec<TrimmedSubstitutionPart>, Vec<Vec<SubstitutionHighlight>>, ConfusionType)> + { // For the `Vec<Vec<SubstitutionHighlight>>` value, the first level of the vector // corresponds to the output snippet's lines, while the second level corresponds to the // substrings within that line that should be highlighted. @@ -428,12 +444,17 @@ fn push_trailing( // or deleted code in order to point at the correct column *after* substitution. let mut acc = 0; let mut confusion_type = ConfusionType::None; - for part in &mut substitution.parts { + + let trimmed_parts = substitution + .parts + .into_iter() // If this is a replacement of, e.g. `"a"` into `"ab"`, adjust the // suggestion and snippet to look as if we just suggested to add // `"b"`, which is typically much easier for the user to understand. - part.trim_trivial_replacements(sm); + .map(|part| part.trim_trivial_replacements(sm)) + .collect::<Vec<_>>(); + for part in &trimmed_parts { let part_confusion = detect_confusion_type(sm, &part.snippet, part.span); confusion_type = confusion_type.combine(part_confusion); let cur_lo = sm.lookup_char_pos(part.span.lo()); @@ -521,7 +542,7 @@ fn push_trailing( if highlights.iter().all(|parts| parts.is_empty()) { None } else { - Some((buf, substitution.parts, highlights, confusion_type)) + Some((buf, trimmed_parts, highlights, confusion_type)) } }) .collect()
diff --git a/compiler/rustc_expand/messages.ftl b/compiler/rustc_expand/messages.ftl index e3aae97..6c23320a 100644 --- a/compiler/rustc_expand/messages.ftl +++ b/compiler/rustc_expand/messages.ftl
@@ -49,6 +49,9 @@ .note = removed in {$removed_rustc_version}{$pull_note} .reason = {$reason} +expand_file_modules_in_proc_macro_input_are_unstable = + file modules in proc macro input are unstable + expand_glob_delegation_outside_impls = glob delegation is only supported in impls @@ -158,9 +161,6 @@ expand_mve_unrecognized_var = variable `{$key}` is not recognized in meta-variable expression -expand_non_inline_modules_in_proc_macro_input_are_unstable = - non-inline modules in proc macro input are unstable - expand_or_patterns_back_compat = the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro .suggestion = use pat_param to preserve semantics
diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs index 2925e33..8278c29 100644 --- a/compiler/rustc_expand/src/config.rs +++ b/compiler/rustc_expand/src/config.rs
@@ -13,7 +13,7 @@ use rustc_attr_parsing as attr; use rustc_attr_parsing::validate_attr::deny_builtin_meta_unsafety; use rustc_attr_parsing::{ - AttributeParser, CFG_TEMPLATE, EvalConfigResult, ShouldEmit, eval_config_entry, parse_cfg_attr, + AttributeParser, CFG_TEMPLATE, EvalConfigResult, ShouldEmit, eval_config_entry, parse_cfg, validate_attr, }; use rustc_data_structures::flat_map_in_place::FlatMapInPlace; @@ -303,7 +303,7 @@ pub(crate) fn expand_cfg_attr(&self, cfg_attr: &Attribute, recursive: bool) -> V let trace_attr = attr_into_trace(cfg_attr.clone(), sym::cfg_attr_trace); let Some((cfg_predicate, expanded_attrs)) = - rustc_parse::parse_cfg_attr(cfg_attr, &self.sess.psess) + rustc_attr_parsing::parse_cfg_attr(cfg_attr, &self.sess, self.features) else { return vec![trace_attr]; }; @@ -318,7 +318,15 @@ pub(crate) fn expand_cfg_attr(&self, cfg_attr: &Attribute, recursive: bool) -> V ); } - if !attr::cfg_matches(&cfg_predicate, &self.sess, self.lint_node_id, self.features) { + if !attr::eval_config_entry( + self.sess, + &cfg_predicate, + ast::CRATE_NODE_ID, + self.features, + ShouldEmit::ErrorsAndLints, + ) + .as_bool() + { return vec![trace_attr]; } @@ -428,7 +436,7 @@ pub(crate) fn cfg_true( node, self.features, emit_errors, - parse_cfg_attr, + parse_cfg, &CFG_TEMPLATE, ) else { // Cfg attribute was not parsable, give up @@ -488,7 +496,7 @@ pub fn configure_expr(&self, expr: &mut ast::Expr, method_receiver: bool) { } /// FIXME: Still used by Rustdoc, should be removed after -pub fn parse_cfg<'a>(meta_item: &'a MetaItem, sess: &Session) -> Option<&'a MetaItemInner> { +pub fn parse_cfg_old<'a>(meta_item: &'a MetaItem, sess: &Session) -> Option<&'a MetaItemInner> { let span = meta_item.span; match meta_item.meta_item_list() { None => {
diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index 8031e11..276490b 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs
@@ -1050,7 +1050,7 @@ fn visit_item(&mut self, item: &'ast ast::Item) { self.sess, sym::proc_macro_hygiene, item.span, - fluent_generated::expand_non_inline_modules_in_proc_macro_input_are_unstable, + fluent_generated::expand_file_modules_in_proc_macro_input_are_unstable, ) .emit(); }
diff --git a/compiler/rustc_hir_analysis/src/check/always_applicable.rs b/compiler/rustc_hir_analysis/src/check/always_applicable.rs index 0ff0147..f39d1b7 100644 --- a/compiler/rustc_hir_analysis/src/check/always_applicable.rs +++ b/compiler/rustc_hir_analysis/src/check/always_applicable.rs
@@ -148,8 +148,7 @@ fn ensure_impl_params_and_item_params_correspond<'tcx>( ty::ImplPolarity::Positive | ty::ImplPolarity::Reservation => "", ty::ImplPolarity::Negative => "!", }; - let trait_name = tcx - .item_name(tcx.trait_id_of_impl(impl_def_id.to_def_id()).expect("expected impl of trait")); + let trait_name = tcx.item_name(tcx.impl_trait_id(impl_def_id.to_def_id())); let mut err = struct_span_code_err!( tcx.dcx(), impl_span, @@ -187,8 +186,7 @@ fn ensure_impl_predicates_are_implied_by_item_defn<'tcx>( let ocx = ObligationCtxt::new_with_diagnostics(&infcx); let impl_span = tcx.def_span(impl_def_id.to_def_id()); - let trait_name = tcx - .item_name(tcx.trait_id_of_impl(impl_def_id.to_def_id()).expect("expected impl of trait")); + let trait_name = tcx.item_name(tcx.impl_trait_id(impl_def_id.to_def_id())); let polarity = match tcx.impl_polarity(impl_def_id) { ty::ImplPolarity::Positive | ty::ImplPolarity::Reservation => "", ty::ImplPolarity::Negative => "!", @@ -212,8 +210,7 @@ fn ensure_impl_predicates_are_implied_by_item_defn<'tcx>( ty::EarlyBinder::bind(tcx.param_env(adt_def_id)).instantiate(tcx, adt_to_impl_args); let fresh_impl_args = infcx.fresh_args_for_item(impl_span, impl_def_id.to_def_id()); - let fresh_adt_ty = - tcx.impl_trait_ref(impl_def_id).unwrap().instantiate(tcx, fresh_impl_args).self_ty(); + let fresh_adt_ty = tcx.impl_trait_ref(impl_def_id).instantiate(tcx, fresh_impl_args).self_ty(); ocx.eq(&ObligationCause::dummy_with_span(impl_span), adt_env, fresh_adt_ty, impl_adt_ty) .expect("equating fully generic trait ref should never fail");
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 4c910d2..95b47c8 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -806,10 +806,10 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), DefKind::Impl { of_trait } => { tcx.ensure_ok().generics_of(def_id); tcx.ensure_ok().type_of(def_id); - tcx.ensure_ok().impl_trait_header(def_id); tcx.ensure_ok().predicates_of(def_id); tcx.ensure_ok().associated_items(def_id); - if of_trait && let Some(impl_trait_header) = tcx.impl_trait_header(def_id) { + if of_trait { + let impl_trait_header = tcx.impl_trait_header(def_id); res = res.and( tcx.ensure_ok() .coherent_trait(impl_trait_header.trait_ref.instantiate_identity().def_id), @@ -1191,9 +1191,7 @@ fn check_impl_items_against_trait<'tcx>( tcx, ty_impl_item, ty_trait_item, - tcx.impl_trait_ref(ty_impl_item.container_id(tcx)) - .unwrap() - .instantiate_identity(), + tcx.impl_trait_ref(ty_impl_item.container_id(tcx)).instantiate_identity(), ); } ty::AssocKind::Const { .. } => {}
diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index 5b504cc..936b02c 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
@@ -38,8 +38,7 @@ pub(super) fn compare_impl_item( ) -> Result<(), ErrorGuaranteed> { let impl_item = tcx.associated_item(impl_item_def_id); let trait_item = tcx.associated_item(impl_item.expect_trait_impl()?); - let impl_trait_ref = - tcx.impl_trait_ref(impl_item.container_id(tcx)).unwrap().instantiate_identity(); + let impl_trait_ref = tcx.impl_trait_ref(impl_item.container_id(tcx)).instantiate_identity(); debug!(?impl_trait_ref); match impl_item.kind { @@ -443,7 +442,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>( let impl_m = tcx.associated_item(impl_m_def_id.to_def_id()); let trait_m = tcx.associated_item(impl_m.expect_trait_impl()?); let impl_trait_ref = - tcx.impl_trait_ref(tcx.parent(impl_m_def_id.to_def_id())).unwrap().instantiate_identity(); + tcx.impl_trait_ref(tcx.parent(impl_m_def_id.to_def_id())).instantiate_identity(); // First, check a few of the same things as `compare_impl_method`, // just so we don't ICE during instantiation later. check_method_is_structurally_compatible(tcx, impl_m, trait_m, impl_trait_ref, true)?;
diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs index 0166c3b..f1c84a1 100644 --- a/compiler/rustc_hir_analysis/src/check/mod.rs +++ b/compiler/rustc_hir_analysis/src/check/mod.rs
@@ -244,7 +244,7 @@ fn missing_items_err( let snippet = with_types_for_signature!(suggestion_signature( tcx, trait_item, - tcx.impl_trait_ref(impl_def_id).unwrap().instantiate_identity(), + tcx.impl_trait_ref(impl_def_id).instantiate_identity(), )); let code = format!("{padding}{snippet}\n{padding}"); if let Some(span) = tcx.hir_span_if_local(trait_item.def_id) {
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 6e537c6..f3d6398 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -245,10 +245,10 @@ pub(super) fn check_item<'tcx>( // won't be allowed unless there's an *explicit* implementation of `Send` // for `T` hir::ItemKind::Impl(ref impl_) => { - crate::impl_wf_check::check_impl_wf(tcx, def_id)?; + crate::impl_wf_check::check_impl_wf(tcx, def_id, impl_.of_trait.is_some())?; let mut res = Ok(()); if let Some(of_trait) = impl_.of_trait { - let header = tcx.impl_trait_header(def_id).unwrap(); + let header = tcx.impl_trait_header(def_id); let is_auto = tcx.trait_is_auto(header.trait_ref.skip_binder().def_id); if let (hir::Defaultness::Default { .. }, true) = (of_trait.defaultness, is_auto) { let sp = of_trait.trait_ref.path.span; @@ -1258,7 +1258,7 @@ fn check_impl<'tcx>( // `#[rustc_reservation_impl]` impls are not real impls and // therefore don't need to be WF (the trait's `Self: Trait` predicate // won't hold). - let trait_ref = tcx.impl_trait_ref(item.owner_id).unwrap().instantiate_identity(); + let trait_ref = tcx.impl_trait_ref(item.owner_id).instantiate_identity(); // Avoid bogus "type annotations needed `Foo: Bar`" errors on `impl Bar for Foo` in case // other `Foo` impls are incoherent. tcx.ensure_ok().coherent_trait(trait_ref.def_id)?;
diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs index b7a74ac..6dee167 100644 --- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs +++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs
@@ -377,7 +377,7 @@ pub(crate) fn coerce_unsized_info<'tcx>( let unsize_trait = tcx.require_lang_item(LangItem::Unsize, span); let source = tcx.type_of(impl_did).instantiate_identity(); - let trait_ref = tcx.impl_trait_ref(impl_did).unwrap().instantiate_identity(); + let trait_ref = tcx.impl_trait_ref(impl_did).instantiate_identity(); assert_eq!(trait_ref.def_id, coerce_unsized_trait); let target = trait_ref.args.type_at(1); @@ -707,7 +707,7 @@ fn visit_implementation_of_coerce_pointee_validity( checker: &Checker<'_>, ) -> Result<(), ErrorGuaranteed> { let tcx = checker.tcx; - let self_ty = tcx.impl_trait_ref(checker.impl_def_id).unwrap().instantiate_identity().self_ty(); + let self_ty = tcx.impl_trait_ref(checker.impl_def_id).instantiate_identity().self_ty(); let span = tcx.def_span(checker.impl_def_id); if !tcx.is_builtin_derived(checker.impl_def_id.into()) { return Err(tcx.dcx().emit_err(errors::CoercePointeeNoUserValidityAssertion { span }));
diff --git a/compiler/rustc_hir_analysis/src/coherence/mod.rs b/compiler/rustc_hir_analysis/src/coherence/mod.rs index fbb4424..bc3231c 100644 --- a/compiler/rustc_hir_analysis/src/coherence/mod.rs +++ b/compiler/rustc_hir_analysis/src/coherence/mod.rs
@@ -163,7 +163,7 @@ fn coherent_trait(tcx: TyCtxt<'_>, def_id: DefId) -> Result<(), ErrorGuaranteed> let mut res = tcx.ensure_ok().specialization_graph_of(def_id); for &impl_def_id in impls { - let impl_header = tcx.impl_trait_header(impl_def_id).unwrap(); + let impl_header = tcx.impl_trait_header(impl_def_id); let trait_ref = impl_header.trait_ref.instantiate_identity(); let trait_def = tcx.trait_def(trait_ref.def_id);
diff --git a/compiler/rustc_hir_analysis/src/coherence/orphan.rs b/compiler/rustc_hir_analysis/src/coherence/orphan.rs index c4aeb4c..27682d0 100644 --- a/compiler/rustc_hir_analysis/src/coherence/orphan.rs +++ b/compiler/rustc_hir_analysis/src/coherence/orphan.rs
@@ -22,7 +22,7 @@ pub(crate) fn orphan_check_impl( tcx: TyCtxt<'_>, impl_def_id: LocalDefId, ) -> Result<(), ErrorGuaranteed> { - let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap().instantiate_identity(); + let trait_ref = tcx.impl_trait_ref(impl_def_id).instantiate_identity(); trait_ref.error_reported()?; match orphan_check(tcx, impl_def_id, OrphanCheckMode::Proper) { @@ -294,7 +294,7 @@ fn orphan_check<'tcx>( ) -> Result<(), OrphanCheckErr<TyCtxt<'tcx>, FxIndexSet<DefId>>> { // We only accept this routine to be invoked on implementations // of a trait, not inherent implementations. - let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap(); + let trait_ref = tcx.impl_trait_ref(impl_def_id); debug!(trait_ref = ?trait_ref.skip_binder()); // If the *trait* is local to the crate, ok.
diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index b6a662f..89ab710 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs
@@ -1291,28 +1291,26 @@ pub fn suggest_impl_trait<'tcx>( None } -fn impl_trait_header(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<ty::ImplTraitHeader<'_>> { +fn impl_trait_header(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::ImplTraitHeader<'_> { let icx = ItemCtxt::new(tcx, def_id); let item = tcx.hir_expect_item(def_id); let impl_ = item.expect_impl(); + let of_trait = impl_ + .of_trait + .unwrap_or_else(|| panic!("expected impl trait, found inherent impl on {def_id:?}")); + let selfty = tcx.type_of(def_id).instantiate_identity(); let is_rustc_reservation = tcx.has_attr(def_id, sym::rustc_reservation_impl); - if is_rustc_reservation && impl_.of_trait.is_none() { - tcx.dcx().span_err(item.span, "reservation impls can't be inherent"); + + check_impl_constness(tcx, of_trait.constness, &of_trait.trait_ref); + + let trait_ref = icx.lowerer().lower_impl_trait_ref(&of_trait.trait_ref, selfty); + + ty::ImplTraitHeader { + trait_ref: ty::EarlyBinder::bind(trait_ref), + safety: of_trait.safety, + polarity: polarity_of_impl(tcx, of_trait, is_rustc_reservation), + constness: of_trait.constness, } - impl_.of_trait.map(|of_trait| { - let selfty = tcx.type_of(def_id).instantiate_identity(); - - check_impl_constness(tcx, of_trait.constness, &of_trait.trait_ref); - - let trait_ref = icx.lowerer().lower_impl_trait_ref(&of_trait.trait_ref, selfty); - - ty::ImplTraitHeader { - trait_ref: ty::EarlyBinder::bind(trait_ref), - safety: of_trait.safety, - polarity: polarity_of_impl(tcx, of_trait, is_rustc_reservation), - constness: of_trait.constness, - } - }) } fn check_impl_constness(
diff --git a/compiler/rustc_hir_analysis/src/collect/dump.rs b/compiler/rustc_hir_analysis/src/collect/dump.rs index 44cc2de..b167f31 100644 --- a/compiler/rustc_hir_analysis/src/collect/dump.rs +++ b/compiler/rustc_hir_analysis/src/collect/dump.rs
@@ -108,7 +108,7 @@ pub(crate) fn vtables<'tcx>(tcx: TyCtxt<'tcx>) { let vtable_entries = match tcx.hir_item(id).kind { hir::ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }) => { - let trait_ref = tcx.impl_trait_ref(def_id).unwrap().instantiate_identity(); + let trait_ref = tcx.impl_trait_ref(def_id).instantiate_identity(); if trait_ref.has_non_region_param() { tcx.dcx().span_err( attr.span(),
diff --git a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs index 129b26d..67284e1 100644 --- a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs +++ b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
@@ -514,17 +514,15 @@ pub(super) fn impl_super_outlives( tcx: TyCtxt<'_>, def_id: DefId, ) -> ty::EarlyBinder<'_, ty::Clauses<'_>> { - tcx.impl_trait_header(def_id).expect("expected an impl of trait").trait_ref.map_bound( - |trait_ref| { - let clause: ty::Clause<'_> = trait_ref.upcast(tcx); - tcx.mk_clauses_from_iter(util::elaborate(tcx, [clause]).filter(|clause| { - matches!( - clause.kind().skip_binder(), - ty::ClauseKind::TypeOutlives(_) | ty::ClauseKind::RegionOutlives(_) - ) - })) - }, - ) + tcx.impl_trait_header(def_id).trait_ref.map_bound(|trait_ref| { + let clause: ty::Clause<'_> = trait_ref.upcast(tcx); + tcx.mk_clauses_from_iter(util::elaborate(tcx, [clause]).filter(|clause| { + matches!( + clause.kind().skip_binder(), + ty::ClauseKind::TypeOutlives(_) | ty::ClauseKind::RegionOutlives(_) + ) + })) + }) } struct AssocTyToOpaque<'tcx> {
diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index ffdf2a2..e66accc 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
@@ -118,8 +118,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen let impl_assoc_identity_args = ty::GenericArgs::identity_for_item(tcx, def_id); let impl_def_id = tcx.parent(fn_def_id); - let impl_trait_ref_args = - tcx.impl_trait_ref(impl_def_id).unwrap().instantiate_identity().args; + let impl_trait_ref_args = tcx.impl_trait_ref(impl_def_id).instantiate_identity().args; let impl_assoc_args = impl_assoc_identity_args.rebase_onto(tcx, impl_def_id, impl_trait_ref_args); @@ -162,9 +161,8 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen if let Some(of_trait) = impl_.of_trait && of_trait.defaultness.is_default() { - is_default_impl_trait = tcx - .impl_trait_ref(def_id) - .map(|t| ty::Binder::dummy(t.instantiate_identity())); + is_default_impl_trait = + Some(ty::Binder::dummy(tcx.impl_trait_ref(def_id).instantiate_identity())); } } ItemKind::Trait(_, _, _, _, _, self_bounds, ..) @@ -350,9 +348,10 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen // before uses of `U`. This avoids false ambiguity errors // in trait checking. See `setup_constraining_predicates` // for details. - if let Node::Item(&Item { kind: ItemKind::Impl { .. }, .. }) = node { + if let Node::Item(&Item { kind: ItemKind::Impl(impl_), .. }) = node { let self_ty = tcx.type_of(def_id).instantiate_identity(); - let trait_ref = tcx.impl_trait_ref(def_id).map(ty::EarlyBinder::instantiate_identity); + let trait_ref = + impl_.of_trait.is_some().then(|| tcx.impl_trait_ref(def_id).instantiate_identity()); cgp::setup_constraining_predicates( tcx, &mut predicates, @@ -460,11 +459,12 @@ fn visit_const(&mut self, c: ty::Const<'tcx>) { } if let hir::Node::Item(item) = node - && let hir::ItemKind::Impl(_) = item.kind + && let hir::ItemKind::Impl(impl_) = item.kind { - if let Some(of_trait) = tcx.impl_trait_ref(def_id) { + if impl_.of_trait.is_some() { debug!("visit impl trait_ref"); - of_trait.instantiate_identity().visit_with(&mut collector); + let trait_ref = tcx.impl_trait_ref(def_id); + trait_ref.instantiate_identity().visit_with(&mut collector); } debug!("visit self_ty");
diff --git a/compiler/rustc_hir_analysis/src/delegation.rs b/compiler/rustc_hir_analysis/src/delegation.rs index f5821ae..125fc21 100644 --- a/compiler/rustc_hir_analysis/src/delegation.rs +++ b/compiler/rustc_hir_analysis/src/delegation.rs
@@ -272,8 +272,7 @@ fn create_generic_args<'tcx>( (FnKind::AssocTraitImpl, FnKind::AssocTrait) => { let callee_generics = tcx.generics_of(sig_id); let parent = tcx.parent(def_id.into()); - let parent_args = - tcx.impl_trait_header(parent).unwrap().trait_ref.instantiate_identity().args; + let parent_args = tcx.impl_trait_header(parent).trait_ref.instantiate_identity().args; let trait_args = ty::GenericArgs::identity_for_item(tcx, sig_id); let method_args = tcx.mk_args(&trait_args[callee_generics.parent_count..]);
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs index 7accab8..a3cb49e 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs
@@ -202,11 +202,9 @@ pub(crate) fn add_sizedness_bounds( // where we are guaranteed to catch *all* bounds like in // `Self::lower_poly_trait_ref`. List of concrete issues: // FIXME(more_maybe_bounds): We don't call this for trait object tys, supertrait - // bounds or associated type bounds (ATB)! - // FIXME(trait_alias, #143122): We don't call it for the RHS. Arguably however, - // AST lowering should reject them outright. + // bounds, trait alias bounds, assoc type bounds (ATB)! let bounds = collect_relaxed_bounds(hir_bounds, self_ty_where_predicates); - self.check_and_report_invalid_relaxed_bounds(bounds); + self.reject_duplicate_relaxed_bounds(bounds); } let collected = collect_sizedness_bounds(tcx, hir_bounds, self_ty_where_predicates, span); @@ -310,6 +308,53 @@ fn should_add_default_traits<'a>( !self.tcx().has_attr(CRATE_DEF_ID, sym::rustc_no_implicit_bounds) && !collected.any() } + fn reject_duplicate_relaxed_bounds(&self, relaxed_bounds: SmallVec<[&PolyTraitRef<'_>; 1]>) { + let tcx = self.tcx(); + + let mut grouped_bounds = FxIndexMap::<_, Vec<_>>::default(); + + for bound in &relaxed_bounds { + if let Res::Def(DefKind::Trait, trait_def_id) = bound.trait_ref.path.res { + grouped_bounds.entry(trait_def_id).or_default().push(bound.span); + } + } + + for (trait_def_id, spans) in grouped_bounds { + if spans.len() > 1 { + let name = tcx.item_name(trait_def_id); + self.dcx() + .struct_span_err(spans, format!("duplicate relaxed `{name}` bounds")) + .with_code(E0203) + .emit(); + } + } + } + + pub(crate) fn require_bound_to_relax_default_trait( + &self, + trait_ref: hir::TraitRef<'_>, + span: Span, + ) { + let tcx = self.tcx(); + + if let Res::Def(DefKind::Trait, def_id) = trait_ref.path.res + && (tcx.is_lang_item(def_id, hir::LangItem::Sized) || tcx.is_default_trait(def_id)) + { + return; + } + + self.dcx().span_err( + span, + if tcx.sess.opts.unstable_opts.experimental_default_bounds + || tcx.features().more_maybe_bounds() + { + "bound modifier `?` can only be applied to default traits" + } else { + "bound modifier `?` can only be applied to `Sized`" + }, + ); + } + /// Lower HIR bounds into `bounds` given the self type `param_ty` and the overarching late-bound vars if any. /// /// ### Examples
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs index 1650517..600684d 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs
@@ -8,7 +8,7 @@ }; use rustc_hir::def::{CtorOf, DefKind, Res}; use rustc_hir::def_id::DefId; -use rustc_hir::{self as hir, HirId, PolyTraitRef}; +use rustc_hir::{self as hir, HirId}; use rustc_middle::bug; use rustc_middle::ty::fast_reject::{TreatParams, simplify_type}; use rustc_middle::ty::print::{PrintPolyTraitRefExt as _, PrintTraitRefExt as _}; @@ -35,52 +35,6 @@ use crate::hir_ty_lowering::{AssocItemQSelf, HirTyLowerer}; impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { - /// Check for duplicate relaxed bounds and relaxed bounds of non-default traits. - pub(crate) fn check_and_report_invalid_relaxed_bounds( - &self, - relaxed_bounds: SmallVec<[&PolyTraitRef<'_>; 1]>, - ) { - let tcx = self.tcx(); - - let mut grouped_bounds = FxIndexMap::<_, Vec<_>>::default(); - - for bound in &relaxed_bounds { - if let Res::Def(DefKind::Trait, trait_def_id) = bound.trait_ref.path.res { - grouped_bounds.entry(trait_def_id).or_default().push(bound.span); - } - } - - for (trait_def_id, spans) in grouped_bounds { - if spans.len() > 1 { - let name = tcx.item_name(trait_def_id); - self.dcx() - .struct_span_err(spans, format!("duplicate relaxed `{name}` bounds")) - .with_code(E0203) - .emit(); - } - } - - let sized_def_id = tcx.require_lang_item(hir::LangItem::Sized, DUMMY_SP); - - for bound in relaxed_bounds { - if let Res::Def(DefKind::Trait, def_id) = bound.trait_ref.path.res - && (def_id == sized_def_id || tcx.is_default_trait(def_id)) - { - continue; - } - self.dcx().span_err( - bound.span, - if tcx.sess.opts.unstable_opts.experimental_default_bounds - || tcx.features().more_maybe_bounds() - { - "bound modifier `?` can only be applied to default traits like `Sized`" - } else { - "bound modifier `?` can only be applied to `Sized`" - }, - ); - } - } - /// On missing type parameters, emit an E0393 error and provide a structured suggestion using /// the type parameter's name as a placeholder. pub(crate) fn report_missing_type_params( @@ -473,7 +427,7 @@ pub(crate) fn report_missing_self_ty_for_resolved_path( } else { // Find all the types that have an `impl` for the trait. tcx.all_impls(trait_def_id) - .filter_map(|impl_def_id| tcx.impl_trait_header(impl_def_id)) + .map(|impl_def_id| tcx.impl_trait_header(impl_def_id)) .filter(|header| { // Consider only accessible traits tcx.visibility(trait_def_id).is_accessible_from(self.item_def_id(), tcx)
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index eb66080..58bd8e3 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
@@ -717,16 +717,15 @@ pub fn lower_impl_trait_ref( trait_ref: &hir::TraitRef<'tcx>, self_ty: Ty<'tcx>, ) -> ty::TraitRef<'tcx> { - let _ = self.prohibit_generic_args( - trait_ref.path.segments.split_last().unwrap().1.iter(), - GenericsArgsErrExtend::None, - ); + let [leading_segments @ .., segment] = trait_ref.path.segments else { bug!() }; + + let _ = self.prohibit_generic_args(leading_segments.iter(), GenericsArgsErrExtend::None); self.lower_mono_trait_ref( trait_ref.path.span, trait_ref.trait_def_id().unwrap_or_else(|| FatalError.raise()), self_ty, - trait_ref.path.segments.last().unwrap(), + segment, true, ) } @@ -757,7 +756,12 @@ pub fn lower_impl_trait_ref( #[instrument(level = "debug", skip(self, bounds))] pub(crate) fn lower_poly_trait_ref( &self, - poly_trait_ref: &hir::PolyTraitRef<'tcx>, + &hir::PolyTraitRef { + bound_generic_params, + modifiers: hir::TraitBoundModifiers { constness, polarity }, + trait_ref, + span, + }: &hir::PolyTraitRef<'tcx>, self_ty: Ty<'tcx>, bounds: &mut Vec<(ty::Clause<'tcx>, Span)>, predicate_filter: PredicateFilter, @@ -767,50 +771,67 @@ pub(crate) fn lower_poly_trait_ref( // We use the *resolved* bound vars later instead of the HIR ones since the former // also include the bound vars of the overarching predicate if applicable. - let hir::PolyTraitRef { bound_generic_params: _, modifiers, ref trait_ref, span } = - *poly_trait_ref; - let hir::TraitBoundModifiers { constness, polarity } = modifiers; + let _ = bound_generic_params; let trait_def_id = trait_ref.trait_def_id().unwrap_or_else(|| FatalError.raise()); - // Relaxed bounds `?Trait` and `PointeeSized` bounds aren't represented in the `middle::ty` IR + // Relaxed bounds `?Trait` and `PointeeSized` bounds aren't represented in the middle::ty IR // as they denote the *absence* of a default bound. However, we can't bail out early here since // we still need to perform several validation steps (see below). Instead, simply "pour" all // resulting bounds "down the drain", i.e., into a new `Vec` that just gets dropped at the end. - let (polarity, bounds) = match polarity { - rustc_ast::BoundPolarity::Positive - if tcx.is_lang_item(trait_def_id, hir::LangItem::PointeeSized) => - { + let transient = match polarity { + hir::BoundPolarity::Positive => { // To elaborate on the comment directly above, regarding `PointeeSized` specifically, // we don't "reify" such bounds to avoid trait system limitations -- namely, // non-global where-clauses being preferred over item bounds (where `PointeeSized` // bounds would be proven) -- which can result in errors when a `PointeeSized` // supertrait / bound / predicate is added to some items. - (ty::PredicatePolarity::Positive, &mut Vec::new()) + tcx.is_lang_item(trait_def_id, hir::LangItem::PointeeSized) } - rustc_ast::BoundPolarity::Positive => (ty::PredicatePolarity::Positive, bounds), - rustc_ast::BoundPolarity::Negative(_) => (ty::PredicatePolarity::Negative, bounds), - rustc_ast::BoundPolarity::Maybe(_) => { - (ty::PredicatePolarity::Positive, &mut Vec::new()) + hir::BoundPolarity::Negative(_) => false, + hir::BoundPolarity::Maybe(_) => { + self.require_bound_to_relax_default_trait(trait_ref, span); + true } }; + let bounds = if transient { &mut Vec::new() } else { bounds }; - let trait_segment = trait_ref.path.segments.last().unwrap(); + let polarity = match polarity { + hir::BoundPolarity::Positive | hir::BoundPolarity::Maybe(_) => { + ty::PredicatePolarity::Positive + } + hir::BoundPolarity::Negative(_) => ty::PredicatePolarity::Negative, + }; - let _ = self.prohibit_generic_args( - trait_ref.path.segments.split_last().unwrap().1.iter(), - GenericsArgsErrExtend::None, - ); - self.report_internal_fn_trait(span, trait_def_id, trait_segment, false); + let [leading_segments @ .., segment] = trait_ref.path.segments else { bug!() }; + + let _ = self.prohibit_generic_args(leading_segments.iter(), GenericsArgsErrExtend::None); + self.report_internal_fn_trait(span, trait_def_id, segment, false); let (generic_args, arg_count) = self.lower_generic_args_of_path( trait_ref.path.span, trait_def_id, &[], - trait_segment, + segment, Some(self_ty), ); + let constraints = segment.args().constraints; + + if transient && (!generic_args[1..].is_empty() || !constraints.is_empty()) { + // Since the bound won't be present in the middle::ty IR as established above, any + // arguments or constraints won't be checked for well-formedness in later passes. + // + // This is only an issue if the trait ref is otherwise valid which can only happen if + // the corresponding default trait has generic parameters or associated items. Such a + // trait would be degenerate. We delay a bug to detect and guard us against these. + // + // E.g: Given `/*default*/ trait Bound<'a: 'static, T, const N: usize> {}`, + // `?Bound<Vec<str>, { panic!() }>` won't be wfchecked. + self.dcx() + .span_delayed_bug(span, "transient bound should not have args or constraints"); + } + let bound_vars = tcx.late_bound_vars(trait_ref.hir_ref_id); debug!(?bound_vars); @@ -922,7 +943,7 @@ pub(crate) fn lower_poly_trait_ref( == OverlappingAsssocItemConstraints::Forbidden) .then_some(FxIndexMap::default()); - for constraint in trait_segment.args().constraints { + for constraint in constraints { // Don't register any associated item constraints for negative bounds, // since we should have emitted an error for them earlier, and they // would not be well-formed! @@ -1387,10 +1408,7 @@ fn resolve_type_relative_path( (_, Res::SelfTyAlias { alias_to: impl_def_id, is_trait_impl: true, .. }) => { // `Self` in an impl of a trait -- we have a concrete self type and a // trait reference. - let Some(trait_ref) = tcx.impl_trait_ref(impl_def_id) else { - // A cycle error occurred, most likely. - self.dcx().span_bug(span, "expected cycle error"); - }; + let trait_ref = tcx.impl_trait_ref(impl_def_id); self.probe_single_bound_for_assoc_item( || { @@ -1618,7 +1636,7 @@ fn probe_traits_that_match_assoc_ty( .is_accessible_from(self.item_def_id(), tcx) && tcx.all_impls(*trait_def_id) .any(|impl_def_id| { - let header = tcx.impl_trait_header(impl_def_id).unwrap(); + let header = tcx.impl_trait_header(impl_def_id); let trait_ref = header.trait_ref.instantiate( tcx, infcx.fresh_args_for_item(DUMMY_SP, impl_def_id), @@ -1914,10 +1932,12 @@ pub fn lower_resolved_ty_path( Res::Def(DefKind::OpaqueTy, did) => { // Check for desugared `impl Trait`. assert_matches!(tcx.opaque_ty_origin(did), hir::OpaqueTyOrigin::TyAlias { .. }); - let item_segment = path.segments.split_last().unwrap(); - let _ = self - .prohibit_generic_args(item_segment.1.iter(), GenericsArgsErrExtend::OpaqueTy); - let args = self.lower_generic_args_of_path_segment(span, did, item_segment.0); + let [leading_segments @ .., segment] = path.segments else { bug!() }; + let _ = self.prohibit_generic_args( + leading_segments.iter(), + GenericsArgsErrExtend::OpaqueTy, + ); + let args = self.lower_generic_args_of_path_segment(span, did, segment); Ty::new_opaque(tcx, did, args) } Res::Def( @@ -1929,11 +1949,10 @@ pub fn lower_resolved_ty_path( did, ) => { assert_eq!(opt_self_ty, None); - let _ = self.prohibit_generic_args( - path.segments.split_last().unwrap().1.iter(), - GenericsArgsErrExtend::None, - ); - self.lower_path_segment(span, did, path.segments.last().unwrap()) + let [leading_segments @ .., segment] = path.segments else { bug!() }; + let _ = self + .prohibit_generic_args(leading_segments.iter(), GenericsArgsErrExtend::None); + self.lower_path_segment(span, did, segment) } Res::Def(kind @ DefKind::Variant, def_id) if let PermitVariants::Yes = permit_variants => @@ -1953,8 +1972,8 @@ pub fn lower_resolved_ty_path( GenericsArgsErrExtend::DefVariant(&path.segments), ); - let GenericPathSegment(def_id, index) = generic_segments.last().unwrap(); - self.lower_path_segment(span, *def_id, &path.segments[*index]) + let &GenericPathSegment(def_id, index) = generic_segments.last().unwrap(); + self.lower_path_segment(span, def_id, &path.segments[index]) } Res::Def(DefKind::TyParam, def_id) => { assert_eq!(opt_self_ty, None); @@ -2240,15 +2259,10 @@ fn lower_resolved_const_path( } Res::Def(DefKind::Const | DefKind::Ctor(_, CtorKind::Const), did) => { assert_eq!(opt_self_ty, None); - let _ = self.prohibit_generic_args( - path.segments.split_last().unwrap().1.iter(), - GenericsArgsErrExtend::None, - ); - let args = self.lower_generic_args_of_path_segment( - span, - did, - path.segments.last().unwrap(), - ); + let [leading_segments @ .., segment] = path.segments else { bug!() }; + let _ = self + .prohibit_generic_args(leading_segments.iter(), GenericsArgsErrExtend::None); + let args = self.lower_generic_args_of_path_segment(span, did, segment); ty::Const::new_unevaluated(tcx, ty::UnevaluatedConst::new(did, args)) } Res::Def(DefKind::AssocConst, did) => {
diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check.rs b/compiler/rustc_hir_analysis/src/impl_wf_check.rs index 19ba166..3dede69 100644 --- a/compiler/rustc_hir_analysis/src/impl_wf_check.rs +++ b/compiler/rustc_hir_analysis/src/impl_wf_check.rs
@@ -56,6 +56,7 @@ pub(crate) fn check_impl_wf( tcx: TyCtxt<'_>, impl_def_id: LocalDefId, + of_trait: bool, ) -> Result<(), ErrorGuaranteed> { debug_assert_matches!(tcx.def_kind(impl_def_id), DefKind::Impl { .. }); @@ -63,9 +64,9 @@ pub(crate) fn check_impl_wf( // since unconstrained type/const params cause ICEs in projection, so we want to // detect those specifically and project those to `TyKind::Error`. let mut res = tcx.ensure_ok().enforce_impl_non_lifetime_params_are_constrained(impl_def_id); - res = res.and(enforce_impl_lifetime_params_are_constrained(tcx, impl_def_id)); + res = res.and(enforce_impl_lifetime_params_are_constrained(tcx, impl_def_id, of_trait)); - if tcx.features().min_specialization() { + if of_trait && tcx.features().min_specialization() { res = res.and(check_min_specialization(tcx, impl_def_id)); } res @@ -74,6 +75,7 @@ pub(crate) fn check_impl_wf( pub(crate) fn enforce_impl_lifetime_params_are_constrained( tcx: TyCtxt<'_>, impl_def_id: LocalDefId, + of_trait: bool, ) -> Result<(), ErrorGuaranteed> { let impl_self_ty = tcx.type_of(impl_def_id).instantiate_identity(); @@ -83,7 +85,7 @@ pub(crate) fn enforce_impl_lifetime_params_are_constrained( let impl_generics = tcx.generics_of(impl_def_id); let impl_predicates = tcx.predicates_of(impl_def_id); - let impl_trait_ref = tcx.impl_trait_ref(impl_def_id).map(ty::EarlyBinder::instantiate_identity); + let impl_trait_ref = of_trait.then(|| tcx.impl_trait_ref(impl_def_id).instantiate_identity()); impl_trait_ref.error_reported()?; @@ -171,7 +173,8 @@ pub(crate) fn enforce_impl_non_lifetime_params_are_constrained( let impl_generics = tcx.generics_of(impl_def_id); let impl_predicates = tcx.predicates_of(impl_def_id); - let impl_trait_ref = tcx.impl_trait_ref(impl_def_id).map(ty::EarlyBinder::instantiate_identity); + let impl_trait_ref = + tcx.impl_opt_trait_ref(impl_def_id).map(ty::EarlyBinder::instantiate_identity); impl_trait_ref.error_reported()?;
diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs index 64a36e2..41af593 100644 --- a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs +++ b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs
@@ -93,7 +93,7 @@ pub(super) fn check_min_specialization( } fn parent_specialization_node(tcx: TyCtxt<'_>, impl1_def_id: LocalDefId) -> Option<Node> { - let trait_ref = tcx.impl_trait_ref(impl1_def_id)?; + let trait_ref = tcx.impl_trait_ref(impl1_def_id); let trait_def = tcx.trait_def(trait_ref.skip_binder().def_id); let impl2_node = trait_def.ancestors(tcx, impl1_def_id.to_def_id()).ok()?.nth(1)?; @@ -215,7 +215,7 @@ fn unconstrained_parent_impl_args<'tcx>( let impl_generic_predicates = tcx.predicates_of(impl_def_id); let mut unconstrained_parameters = FxHashSet::default(); let mut constrained_params = FxHashSet::default(); - let impl_trait_ref = tcx.impl_trait_ref(impl_def_id).map(ty::EarlyBinder::instantiate_identity); + let impl_trait_ref = tcx.impl_trait_ref(impl_def_id).instantiate_identity(); // Unfortunately the functions in `constrained_generic_parameters` don't do // what we want here. We want only a list of constrained parameters while @@ -224,7 +224,7 @@ fn unconstrained_parent_impl_args<'tcx>( for (clause, _) in impl_generic_predicates.predicates.iter() { if let ty::ClauseKind::Projection(proj) = clause.kind().skip_binder() { let unbound_trait_ref = proj.projection_term.trait_ref(tcx); - if Some(unbound_trait_ref) == impl_trait_ref { + if unbound_trait_ref == impl_trait_ref { continue; } @@ -373,7 +373,7 @@ fn check_predicates<'tcx>( .map(|(c, _span)| c.as_predicate()); // Include the well-formed predicates of the type parameters of the impl. - for arg in tcx.impl_trait_ref(impl1_def_id).unwrap().instantiate_identity().args { + for arg in tcx.impl_trait_ref(impl1_def_id).instantiate_identity().args { let Some(term) = arg.as_term() else { continue; };
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index c1dbf90..2605aa1 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -3629,7 +3629,7 @@ fn find_and_report_unsatisfied_index_impl( let ocx = ObligationCtxt::new_with_diagnostics(self); let impl_args = self.fresh_args_for_item(base_expr.span, impl_def_id); let impl_trait_ref = - self.tcx.impl_trait_ref(impl_def_id).unwrap().instantiate(self.tcx, impl_args); + self.tcx.impl_trait_ref(impl_def_id).instantiate(self.tcx, impl_args); let cause = self.misc(base_expr.span); // Match the impl self type against the base ty. If this fails,
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs index ed88e32..f478cab 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs
@@ -711,7 +711,7 @@ fn blame_specific_expr_if_possible_for_derived_predicate_obligation( ) } else { self.tcx - .impl_trait_ref(obligation.impl_or_alias_def_id) + .impl_opt_trait_ref(obligation.impl_or_alias_def_id) .map(|impl_def| impl_def.skip_binder()) // It is possible that this is absent. In this case, we make no progress. .ok_or(expr)?
diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index a615ac9..99a9566 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs
@@ -285,7 +285,7 @@ fn infer_type_if_missing<'tcx>(fcx: &FnCtxt<'_, 'tcx>, node: Node<'tcx>) -> Opti && let ty::AssocContainer::TraitImpl(Ok(trait_item_def_id)) = item.container { let impl_def_id = item.container_id(tcx); - let impl_trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap().instantiate_identity(); + let impl_trait_ref = tcx.impl_trait_ref(impl_def_id).instantiate_identity(); let args = ty::GenericArgs::identity_for_item(tcx, def_id).rebase_onto( tcx, impl_def_id,
diff --git a/compiler/rustc_hir_typeck/src/method/confirm.rs b/compiler/rustc_hir_typeck/src/method/confirm.rs index b23e7ae..f7a0a55 100644 --- a/compiler/rustc_hir_typeck/src/method/confirm.rs +++ b/compiler/rustc_hir_typeck/src/method/confirm.rs
@@ -18,8 +18,8 @@ Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability, PointerCoercion, }; use rustc_middle::ty::{ - self, GenericArgs, GenericArgsRef, GenericParamDefKind, Ty, TyCtxt, TypeFoldable, - TypeVisitableExt, UserArgs, + self, AssocContainer, GenericArgs, GenericArgsRef, GenericParamDefKind, Ty, TyCtxt, + TypeFoldable, TypeVisitableExt, UserArgs, }; use rustc_middle::{bug, span_bug}; use rustc_span::{DUMMY_SP, Span}; @@ -272,7 +272,7 @@ fn fresh_receiver_args( probe::InherentImplPick => { let impl_def_id = pick.item.container_id(self.tcx); assert!( - self.tcx.impl_trait_ref(impl_def_id).is_none(), + matches!(pick.item.container, AssocContainer::InherentImpl), "impl {impl_def_id:?} is not an inherent impl" ); self.fresh_args_for_item(self.span, impl_def_id)
diff --git a/compiler/rustc_hir_typeck/src/method/mod.rs b/compiler/rustc_hir_typeck/src/method/mod.rs index 04f112e..35be28f 100644 --- a/compiler/rustc_hir_typeck/src/method/mod.rs +++ b/compiler/rustc_hir_typeck/src/method/mod.rs
@@ -242,7 +242,7 @@ pub(crate) fn lookup_method( match *source { // Note: this cannot come from an inherent impl, // because the first probing succeeded. - CandidateSource::Impl(def) => self.tcx.trait_id_of_impl(def), + CandidateSource::Impl(def) => Some(self.tcx.impl_trait_id(def)), CandidateSource::Trait(_) => None, } })
diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index 8a9d394..14043be 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs
@@ -1176,9 +1176,6 @@ fn pick(mut self) -> PickResult<'tcx> { // things failed, so lets look at all traits, for diagnostic purposes now: self.reset(); - let span = self.span; - let tcx = self.tcx; - self.assemble_extension_candidates_for_all_traits(); let out_of_scope_traits = match self.pick_core(&mut Vec::new()) { @@ -1187,10 +1184,7 @@ fn pick(mut self) -> PickResult<'tcx> { .into_iter() .map(|source| match source { CandidateSource::Trait(id) => id, - CandidateSource::Impl(impl_id) => match tcx.trait_id_of_impl(impl_id) { - Some(id) => id, - None => span_bug!(span, "found inherent method when looking at traits"), - }, + CandidateSource::Impl(impl_id) => self.tcx.impl_trait_id(impl_id), }) .collect(), Some(Err(MethodError::NoMatch(NoMatchData {
diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 44602e6..7a211db 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -1962,8 +1962,8 @@ fn note_candidates_on_method_error( // Provide the best span we can. Use the item, if local to crate, else // the impl, if local to crate (item may be defaulted), else nothing. let Some(item) = self.associated_value(impl_did, item_name).or_else(|| { - let impl_trait_ref = self.tcx.impl_trait_ref(impl_did)?; - self.associated_value(impl_trait_ref.skip_binder().def_id, item_name) + let impl_trait_id = self.tcx.impl_opt_trait_id(impl_did)?; + self.associated_value(impl_trait_id, item_name) }) else { continue; }; @@ -1978,7 +1978,7 @@ fn note_candidates_on_method_error( let impl_ty = self.tcx.at(span).type_of(impl_did).instantiate_identity(); - let insertion = match self.tcx.impl_trait_ref(impl_did) { + let insertion = match self.tcx.impl_opt_trait_ref(impl_did) { None => String::new(), Some(trait_ref) => { format!( @@ -2013,7 +2013,7 @@ fn note_candidates_on_method_error( err.note(note_str); } if let Some(sugg_span) = sugg_span - && let Some(trait_ref) = self.tcx.impl_trait_ref(impl_did) + && let Some(trait_ref) = self.tcx.impl_opt_trait_ref(impl_did) && let Some(sugg) = print_disambiguation_help( self.tcx, err, @@ -2547,6 +2547,8 @@ fn report_failed_method_call_on_numerical_infer_var( "you must specify a type for this binding, like `{concrete_type}`", ); + // FIXME: Maybe FileName::Anon should also be handled, + // otherwise there would be no suggestion if the source is STDIN for example. match (filename, parent_node) { ( FileName::Real(_), @@ -2568,6 +2570,44 @@ fn report_failed_method_call_on_numerical_infer_var( Applicability::MaybeIncorrect, ); } + // For closure parameters with reference patterns (e.g., |&v|), suggest the type annotation + // on the pattern itself, e.g., |&v: &i32| + (FileName::Real(_), Node::Pat(pat)) + if let Node::Pat(binding_pat) = self.tcx.hir_node(hir_id) + && let hir::PatKind::Binding(..) = binding_pat.kind + && let Node::Pat(parent_pat) = parent_node + && matches!(parent_pat.kind, hir::PatKind::Ref(..)) => + { + err.span_label(span, "you must specify a type for this binding"); + + let mut ref_muts = Vec::new(); + let mut current_node = parent_node; + + while let Node::Pat(parent_pat) = current_node { + if let hir::PatKind::Ref(_, mutability) = parent_pat.kind { + ref_muts.push(mutability); + current_node = self.tcx.parent_hir_node(parent_pat.hir_id); + } else { + break; + } + } + + let mut type_annotation = String::new(); + for mutability in ref_muts.iter().rev() { + match mutability { + hir::Mutability::Mut => type_annotation.push_str("&mut "), + hir::Mutability::Not => type_annotation.push('&'), + } + } + type_annotation.push_str(&concrete_type); + + err.span_suggestion_verbose( + pat.span.shrink_to_hi(), + "specify the type in the closure argument list", + format!(": {type_annotation}"), + Applicability::MaybeIncorrect, + ); + } _ => { err.span_label(span, msg); } @@ -3720,7 +3760,7 @@ fn suggest_traits_to_import( static_candidates.iter().all(|sc| match *sc { CandidateSource::Trait(def_id) => def_id != info.def_id, CandidateSource::Impl(def_id) => { - self.tcx.trait_id_of_impl(def_id) != Some(info.def_id) + self.tcx.impl_opt_trait_id(def_id) != Some(info.def_id) } }) }) @@ -3980,11 +4020,7 @@ enum Introducer { if self .tcx .all_impls(candidate.def_id) - .map(|imp_did| { - self.tcx.impl_trait_header(imp_did).expect( - "inherent impls can't be candidates, only trait impls can be", - ) - }) + .map(|imp_did| self.tcx.impl_trait_header(imp_did)) .filter(|header| header.polarity != ty::ImplPolarity::Positive) .any(|header| { let imp = header.trait_ref.instantiate_identity();
diff --git a/compiler/rustc_incremental/src/persist/fs.rs b/compiler/rustc_incremental/src/persist/fs.rs index f0d24d2..975bf1d 100644 --- a/compiler/rustc_incremental/src/persist/fs.rs +++ b/compiler/rustc_incremental/src/persist/fs.rs
@@ -721,11 +721,37 @@ pub(crate) fn garbage_collect_session_directories(sess: &Session) -> io::Result< } } + let current_session_directory_name = + session_directory.file_name().expect("session directory is not `..`"); + // Now garbage collect the valid session directories. let deletion_candidates = lock_file_to_session_dir.items().filter_map(|(lock_file_name, directory_name)| { debug!("garbage_collect_session_directories() - inspecting: {}", directory_name); + if directory_name.as_str() == current_session_directory_name { + // Skipping our own directory is, unfortunately, important for correctness. + // + // To summarize #147821: we will try to lock directories before deciding they can be + // garbage collected, but the ability of `flock::Lock` to detect a lock held *by the + // same process* varies across file locking APIs. Then, if our own session directory + // has become old enough to be eligible for GC, we are beholden to platform-specific + // details about detecting the our own lock on the session directory. + // + // POSIX `fcntl(F_SETLK)`-style file locks are maintained across a process. On + // systems where this is the mechanism for `flock::Lock`, there is no way to + // discover if an `flock::Lock` has been created in the same process on the same + // file. Attempting to set a lock on the lockfile again will succeed, even if the + // lock was set by another thread, on another file descriptor. Then we would + // garbage collect our own live directory, unable to tell it was locked perhaps by + // this same thread. + // + // It's not clear that `flock::Lock` can be fixed for this in general, and our own + // incremental session directory is the only one which this process may own, so skip + // it here and avoid the problem. We know it's not garbage anyway: we're using it. + return None; + } + let Ok(timestamp) = extract_timestamp_from_session_dir(directory_name) else { debug!( "found session-dir with malformed timestamp: {}",
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 6167b0d..d9bcd5e 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs
@@ -152,7 +152,10 @@ fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &ast::Expr) { impl<'tcx> LateLintPass<'tcx> for NonShorthandFieldPatterns { fn check_pat(&mut self, cx: &LateContext<'_>, pat: &hir::Pat<'_>) { - if let PatKind::Struct(ref qpath, field_pats, _) = pat.kind { + // The result shouldn't be tainted, otherwise it will cause ICE. + if let PatKind::Struct(ref qpath, field_pats, _) = pat.kind + && cx.typeck_results().tainted_by_errors.is_none() + { let variant = cx .typeck_results() .pat_ty(pat)
diff --git a/compiler/rustc_lint/src/default_could_be_derived.rs b/compiler/rustc_lint/src/default_could_be_derived.rs index 1d92cfb..8f028b1 100644 --- a/compiler/rustc_lint/src/default_could_be_derived.rs +++ b/compiler/rustc_lint/src/default_could_be_derived.rs
@@ -1,14 +1,12 @@ use rustc_data_structures::fx::FxHashMap; use rustc_errors::{Applicability, Diag}; use rustc_hir as hir; -use rustc_hir::attrs::AttributeKind; -use rustc_hir::find_attr; use rustc_middle::ty; use rustc_middle::ty::TyCtxt; -use rustc_session::{declare_lint, impl_lint_pass}; -use rustc_span::Symbol; +use rustc_session::{declare_lint, declare_lint_pass}; use rustc_span::def_id::DefId; use rustc_span::symbol::sym; +use rustc_span::{Span, Symbol}; use crate::{LateContext, LateLintPass}; @@ -52,27 +50,24 @@ @feature_gate = default_field_values; } -#[derive(Default)] -pub(crate) struct DefaultCouldBeDerived; - -impl_lint_pass!(DefaultCouldBeDerived => [DEFAULT_OVERRIDES_DEFAULT_FIELDS]); +declare_lint_pass!(DefaultCouldBeDerived => [DEFAULT_OVERRIDES_DEFAULT_FIELDS]); impl<'tcx> LateLintPass<'tcx> for DefaultCouldBeDerived { fn check_impl_item(&mut self, cx: &LateContext<'_>, impl_item: &hir::ImplItem<'_>) { // Look for manual implementations of `Default`. - let Some(default_def_id) = cx.tcx.get_diagnostic_item(sym::Default) else { return }; + let hir::ImplItemImplKind::Trait { trait_item_def_id, .. } = impl_item.impl_kind else { + return; + }; + if !trait_item_def_id.is_ok_and(|id| cx.tcx.is_diagnostic_item(sym::default_fn, id)) { + return; + } let hir::ImplItemKind::Fn(_sig, body_id) = impl_item.kind else { return }; - let parent = cx.tcx.parent(impl_item.owner_id.to_def_id()); - if find_attr!(cx.tcx.get_all_attrs(parent), AttributeKind::AutomaticallyDerived(..)) { + let impl_id = cx.tcx.local_parent(impl_item.owner_id.def_id); + if cx.tcx.is_automatically_derived(impl_id.to_def_id()) { // We don't care about what `#[derive(Default)]` produces in this lint. return; } - let Some(trait_ref) = cx.tcx.impl_trait_ref(parent) else { return }; - let trait_ref = trait_ref.instantiate_identity(); - if trait_ref.def_id != default_def_id { - return; - } - let ty = trait_ref.self_ty(); + let ty = cx.tcx.type_of(impl_id).instantiate_identity(); let ty::Adt(def, _) = ty.kind() else { return }; // We now know we have a manually written definition of a `<Type as Default>::default()`. @@ -150,11 +145,10 @@ fn check_impl_item(&mut self, cx: &LateContext<'_>, impl_item: &hir::ImplItem<'_ return; } - let Some(local) = parent.as_local() else { return }; - let hir_id = cx.tcx.local_def_id_to_hir_id(local); - let hir::Node::Item(item) = cx.tcx.hir_node(hir_id) else { return }; - cx.tcx.node_span_lint(DEFAULT_OVERRIDES_DEFAULT_FIELDS, hir_id, item.span, |diag| { - mk_lint(cx.tcx, diag, type_def_id, parent, orig_fields, fields); + let hir_id = cx.tcx.local_def_id_to_hir_id(impl_id); + let span = cx.tcx.hir_span_with_body(hir_id); + cx.tcx.node_span_lint(DEFAULT_OVERRIDES_DEFAULT_FIELDS, hir_id, span, |diag| { + mk_lint(cx.tcx, diag, type_def_id, orig_fields, fields, span); }); } } @@ -163,9 +157,9 @@ fn mk_lint( tcx: TyCtxt<'_>, diag: &mut Diag<'_, ()>, type_def_id: DefId, - impl_def_id: DefId, orig_fields: FxHashMap<Symbol, &hir::FieldDef<'_>>, fields: &[hir::ExprField<'_>], + impl_span: Span, ) { diag.primary_message("`Default` impl doesn't use the declared default field values"); @@ -186,18 +180,14 @@ fn mk_lint( if removed_all_fields { let msg = "to avoid divergence in behavior between `Struct { .. }` and \ `<Struct as Default>::default()`, derive the `Default`"; - if let Some(hir::Node::Item(impl_)) = tcx.hir_get_if_local(impl_def_id) { - diag.multipart_suggestion_verbose( - msg, - vec![ - (tcx.def_span(type_def_id).shrink_to_lo(), "#[derive(Default)] ".to_string()), - (impl_.span, String::new()), - ], - Applicability::MachineApplicable, - ); - } else { - diag.help(msg); - } + diag.multipart_suggestion_verbose( + msg, + vec![ + (tcx.def_span(type_def_id).shrink_to_lo(), "#[derive(Default)] ".to_string()), + (impl_span, String::new()), + ], + Applicability::MachineApplicable, + ); } else { let msg = "use the default values in the `impl` with `Struct { mandatory_field, .. }` to \ avoid them diverging over time";
diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index b2abd0e..b4c1848 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs
@@ -191,7 +191,7 @@ fn lint_mod(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) { BuiltinCombinedModuleLateLintPass, [ ForLoopsOverFallibles: ForLoopsOverFallibles, - DefaultCouldBeDerived: DefaultCouldBeDerived::default(), + DefaultCouldBeDerived: DefaultCouldBeDerived, DerefIntoDynSupertrait: DerefIntoDynSupertrait, DropForgetUseless: DropForgetUseless, ImproperCTypesLint: ImproperCTypesLint,
diff --git a/compiler/rustc_lint/src/lifetime_syntax.rs b/compiler/rustc_lint/src/lifetime_syntax.rs index 413525e..0cac91c 100644 --- a/compiler/rustc_lint/src/lifetime_syntax.rs +++ b/compiler/rustc_lint/src/lifetime_syntax.rs
@@ -3,6 +3,7 @@ use rustc_hir::{self as hir, LifetimeSource}; use rustc_session::{declare_lint, declare_lint_pass}; use rustc_span::Span; +use rustc_span::def_id::LocalDefId; use tracing::instrument; use crate::{LateContext, LateLintPass, LintContext, lints}; @@ -78,11 +79,11 @@ impl<'tcx> LateLintPass<'tcx> for LifetimeSyntax { fn check_fn( &mut self, cx: &LateContext<'tcx>, - _: hir::intravisit::FnKind<'tcx>, + _: intravisit::FnKind<'tcx>, fd: &'tcx hir::FnDecl<'tcx>, _: &'tcx hir::Body<'tcx>, - _: rustc_span::Span, - _: rustc_span::def_id::LocalDefId, + _: Span, + _: LocalDefId, ) { check_fn_like(cx, fd); } @@ -97,11 +98,7 @@ fn check_trait_item(&mut self, cx: &LateContext<'tcx>, ti: &'tcx hir::TraitItem< } #[instrument(skip_all)] - fn check_foreign_item( - &mut self, - cx: &LateContext<'tcx>, - fi: &'tcx rustc_hir::ForeignItem<'tcx>, - ) { + fn check_foreign_item(&mut self, cx: &LateContext<'tcx>, fi: &'tcx hir::ForeignItem<'tcx>) { match fi.kind { hir::ForeignItemKind::Fn(fn_sig, _idents, _generics) => check_fn_like(cx, fn_sig.decl), hir::ForeignItemKind::Static(..) => {} @@ -111,35 +108,47 @@ fn check_foreign_item( } fn check_fn_like<'tcx>(cx: &LateContext<'tcx>, fd: &'tcx hir::FnDecl<'tcx>) { - let mut input_map = Default::default(); - let mut output_map = Default::default(); + if fd.inputs.is_empty() { + return; + } + let hir::FnRetTy::Return(output) = fd.output else { + return; + }; + + let mut map: FxIndexMap<hir::LifetimeKind, LifetimeGroup<'_>> = FxIndexMap::default(); + + LifetimeInfoCollector::collect(output, |info| { + let group = map.entry(info.lifetime.kind).or_default(); + group.outputs.push(info); + }); + if map.is_empty() { + return; + } for input in fd.inputs { - LifetimeInfoCollector::collect(input, &mut input_map); - } - - if let hir::FnRetTy::Return(output) = fd.output { - LifetimeInfoCollector::collect(output, &mut output_map); - } - - report_mismatches(cx, &input_map, &output_map); -} - -#[instrument(skip_all)] -fn report_mismatches<'tcx>( - cx: &LateContext<'tcx>, - inputs: &LifetimeInfoMap<'tcx>, - outputs: &LifetimeInfoMap<'tcx>, -) { - for (resolved_lifetime, output_info) in outputs { - if let Some(input_info) = inputs.get(resolved_lifetime) { - if !lifetimes_use_matched_syntax(input_info, output_info) { - emit_mismatch_diagnostic(cx, input_info, output_info); + LifetimeInfoCollector::collect(input, |info| { + if let Some(group) = map.get_mut(&info.lifetime.kind) { + group.inputs.push(info); } + }); + } + + for LifetimeGroup { ref inputs, ref outputs } in map.into_values() { + if inputs.is_empty() { + continue; + } + if !lifetimes_use_matched_syntax(inputs, outputs) { + emit_mismatch_diagnostic(cx, inputs, outputs); } } } +#[derive(Default)] +struct LifetimeGroup<'tcx> { + inputs: Vec<Info<'tcx>>, + outputs: Vec<Info<'tcx>>, +} + #[derive(Debug, Copy, Clone, PartialEq)] enum LifetimeSyntaxCategory { Hidden, @@ -148,11 +157,11 @@ enum LifetimeSyntaxCategory { } impl LifetimeSyntaxCategory { - fn new(syntax_source: (hir::LifetimeSyntax, LifetimeSource)) -> Option<Self> { + fn new(lifetime: &hir::Lifetime) -> Option<Self> { use LifetimeSource::*; use hir::LifetimeSyntax::*; - match syntax_source { + match (lifetime.syntax, lifetime.source) { // E.g. `&T`. (Implicit, Reference) | // E.g. `&'_ T`. @@ -216,7 +225,7 @@ pub fn len(&self) -> LifetimeSyntaxCategories<usize> { pub fn iter_unnamed(&self) -> impl Iterator<Item = &T> { let Self { hidden, elided, named: _ } = self; - [hidden.iter(), elided.iter()].into_iter().flatten() + std::iter::chain(hidden, elided) } } @@ -233,22 +242,8 @@ fn add(self, rhs: Self) -> Self::Output { } fn lifetimes_use_matched_syntax(input_info: &[Info<'_>], output_info: &[Info<'_>]) -> bool { - let mut syntax_counts = LifetimeSyntaxCategories::<usize>::default(); - - for info in input_info.iter().chain(output_info) { - if let Some(category) = info.lifetime_syntax_category() { - *syntax_counts.select(category) += 1; - } - } - - tracing::debug!(?syntax_counts); - - matches!( - syntax_counts, - LifetimeSyntaxCategories { hidden: _, elided: 0, named: 0 } - | LifetimeSyntaxCategories { hidden: 0, elided: _, named: 0 } - | LifetimeSyntaxCategories { hidden: 0, elided: 0, named: _ } - ) + let (first, inputs) = input_info.split_first().unwrap(); + std::iter::chain(inputs, output_info).all(|info| info.syntax_category == first.syntax_category) } fn emit_mismatch_diagnostic<'tcx>( @@ -310,18 +305,13 @@ fn emit_mismatch_diagnostic<'tcx>( use LifetimeSource::*; use hir::LifetimeSyntax::*; - let syntax_source = info.syntax_source(); + let lifetime = info.lifetime; - if let (_, Other) = syntax_source { - // Ignore any other kind of lifetime. - continue; - } - - if let (ExplicitBound, _) = syntax_source { + if lifetime.syntax == ExplicitBound { bound_lifetime = Some(info); } - match syntax_source { + match (lifetime.syntax, lifetime.source) { // E.g. `&T`. (Implicit, Reference) => { suggest_change_to_explicit_anonymous.push(info); @@ -341,8 +331,8 @@ fn emit_mismatch_diagnostic<'tcx>( suggest_change_to_explicit_bound.push(info); } - // E.g. `ContainsLifetime<'_>`. - (ExplicitAnonymous, Path { .. }) => { + // E.g. `ContainsLifetime<'_>`, `+ '_`, `+ use<'_>`. + (ExplicitAnonymous, Path { .. } | OutlivesBound | PreciseCapturing) => { suggest_change_to_explicit_bound.push(info); } @@ -353,8 +343,8 @@ fn emit_mismatch_diagnostic<'tcx>( suggest_change_to_explicit_anonymous.push(info); } - // E.g. `ContainsLifetime<'a>`. - (ExplicitBound, Path { .. }) => { + // E.g. `ContainsLifetime<'a>`, `+ 'a`, `+ use<'a>`. + (ExplicitBound, Path { .. } | OutlivesBound | PreciseCapturing) => { suggest_change_to_mixed_explicit_anonymous.push(info); suggest_change_to_explicit_anonymous.push(info); } @@ -363,29 +353,18 @@ fn emit_mismatch_diagnostic<'tcx>( panic!("This syntax / source combination is not possible"); } - // E.g. `+ '_`, `+ use<'_>`. - (ExplicitAnonymous, OutlivesBound | PreciseCapturing) => { - suggest_change_to_explicit_bound.push(info); - } - - // E.g. `+ 'a`, `+ use<'a>`. - (ExplicitBound, OutlivesBound | PreciseCapturing) => { - suggest_change_to_mixed_explicit_anonymous.push(info); - suggest_change_to_explicit_anonymous.push(info); - } - (_, Other) => { panic!("This syntax / source combination has already been skipped"); } } - if matches!(syntax_source, (_, Path { .. } | OutlivesBound | PreciseCapturing)) { + if matches!(lifetime.source, Path { .. } | OutlivesBound | PreciseCapturing) { allow_suggesting_implicit = false; } - match syntax_source { - (_, Reference) => saw_a_reference = true, - (_, Path { .. }) => saw_a_path = true, + match lifetime.source { + Reference => saw_a_reference = true, + Path { .. } => saw_a_path = true, _ => {} } } @@ -393,9 +372,7 @@ fn emit_mismatch_diagnostic<'tcx>( let categorize = |infos: &[Info<'_>]| { let mut categories = LifetimeSyntaxCategories::<Vec<_>>::default(); for info in infos { - if let Some(category) = info.lifetime_syntax_category() { - categories.select(category).push(info.reporting_span()); - } + categories.select(info.syntax_category).push(info.reporting_span()); } categories }; @@ -407,10 +384,10 @@ fn emit_mismatch_diagnostic<'tcx>( |infos: &[&Info<'_>]| infos.iter().map(|i| i.removing_span()).collect::<Vec<_>>(); let explicit_bound_suggestion = bound_lifetime.map(|info| { - build_mismatch_suggestion(info.lifetime_name(), &suggest_change_to_explicit_bound) + build_mismatch_suggestion(info.lifetime.ident.as_str(), &suggest_change_to_explicit_bound) }); - let is_bound_static = bound_lifetime.is_some_and(|info| info.is_static()); + let is_bound_static = bound_lifetime.is_some_and(|info| info.lifetime.is_static()); tracing::debug!(?bound_lifetime, ?explicit_bound_suggestion, ?is_bound_static); @@ -517,33 +494,17 @@ fn build_mismatch_suggestion( #[derive(Debug)] struct Info<'tcx> { - type_span: Span, - referenced_type_span: Option<Span>, lifetime: &'tcx hir::Lifetime, + syntax_category: LifetimeSyntaxCategory, + ty: &'tcx hir::Ty<'tcx>, } impl<'tcx> Info<'tcx> { - fn syntax_source(&self) -> (hir::LifetimeSyntax, LifetimeSource) { - (self.lifetime.syntax, self.lifetime.source) - } - - fn lifetime_syntax_category(&self) -> Option<LifetimeSyntaxCategory> { - LifetimeSyntaxCategory::new(self.syntax_source()) - } - - fn lifetime_name(&self) -> &str { - self.lifetime.ident.as_str() - } - - fn is_static(&self) -> bool { - self.lifetime.is_static() - } - /// When reporting a lifetime that is implicit, we expand the span /// to include the type. Otherwise we end up pointing at nothing, /// which is a bit confusing. fn reporting_span(&self) -> Span { - if self.lifetime.is_implicit() { self.type_span } else { self.lifetime.ident.span } + if self.lifetime.is_implicit() { self.ty.span } else { self.lifetime.ident.span } } /// When removing an explicit lifetime from a reference, @@ -560,12 +521,10 @@ fn reporting_span(&self) -> Span { /// ``` // FIXME: Ideally, we'd also remove the lifetime declaration. fn removing_span(&self) -> Span { - let mut span = self.suggestion("'dummy").0; - - if let Some(referenced_type_span) = self.referenced_type_span { - span = span.until(referenced_type_span); + let mut span = self.lifetime.ident.span; + if let hir::TyKind::Ref(_, mut_ty) = self.ty.kind { + span = span.until(mut_ty.ty.span); } - span } @@ -574,46 +533,38 @@ fn suggestion(&self, lifetime_name: &str) -> (Span, String) { } } -type LifetimeInfoMap<'tcx> = FxIndexMap<&'tcx hir::LifetimeKind, Vec<Info<'tcx>>>; - -struct LifetimeInfoCollector<'a, 'tcx> { - type_span: Span, - referenced_type_span: Option<Span>, - map: &'a mut LifetimeInfoMap<'tcx>, +struct LifetimeInfoCollector<'tcx, F> { + info_func: F, + ty: &'tcx hir::Ty<'tcx>, } -impl<'a, 'tcx> LifetimeInfoCollector<'a, 'tcx> { - fn collect(ty: &'tcx hir::Ty<'tcx>, map: &'a mut LifetimeInfoMap<'tcx>) { - let mut this = Self { type_span: ty.span, referenced_type_span: None, map }; +impl<'tcx, F> LifetimeInfoCollector<'tcx, F> +where + F: FnMut(Info<'tcx>), +{ + fn collect(ty: &'tcx hir::Ty<'tcx>, info_func: F) { + let mut this = Self { info_func, ty }; intravisit::walk_unambig_ty(&mut this, ty); } } -impl<'a, 'tcx> Visitor<'tcx> for LifetimeInfoCollector<'a, 'tcx> { +impl<'tcx, F> Visitor<'tcx> for LifetimeInfoCollector<'tcx, F> +where + F: FnMut(Info<'tcx>), +{ #[instrument(skip(self))] fn visit_lifetime(&mut self, lifetime: &'tcx hir::Lifetime) { - let type_span = self.type_span; - let referenced_type_span = self.referenced_type_span; - - let info = Info { type_span, referenced_type_span, lifetime }; - - self.map.entry(&lifetime.kind).or_default().push(info); + if let Some(syntax_category) = LifetimeSyntaxCategory::new(lifetime) { + let info = Info { lifetime, syntax_category, ty: self.ty }; + (self.info_func)(info); + } } #[instrument(skip(self))] fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx, hir::AmbigArg>) -> Self::Result { - let old_type_span = self.type_span; - let old_referenced_type_span = self.referenced_type_span; - - self.type_span = ty.span; - if let hir::TyKind::Ref(_, ty) = ty.kind { - self.referenced_type_span = Some(ty.ty.span); - } - + let old_ty = std::mem::replace(&mut self.ty, ty.as_unambig_ty()); intravisit::walk_ty(self, ty); - - self.type_span = old_type_span; - self.referenced_type_span = old_referenced_type_span; + self.ty = old_ty; } }
diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index eaec0c9..7c66559 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs
@@ -814,7 +814,7 @@ fn get_nullable_type<'tcx>( /// A type is niche-optimization candidate iff: /// - Is a zero-sized type with alignment 1 (a “1-ZST”). -/// - Has no fields. +/// - Is either a struct/tuple with no fields, or an enum with no variants. /// - Does not have the `#[non_exhaustive]` attribute. fn is_niche_optimization_candidate<'tcx>( tcx: TyCtxt<'tcx>, @@ -828,7 +828,7 @@ fn is_niche_optimization_candidate<'tcx>( match ty.kind() { ty::Adt(ty_def, _) => { let non_exhaustive = ty_def.is_variant_list_non_exhaustive(); - let empty = (ty_def.is_struct() && ty_def.all_fields().next().is_none()) + let empty = (ty_def.is_struct() && ty_def.non_enum_variant().fields.is_empty()) || (ty_def.is_enum() && ty_def.variants().is_empty()); !non_exhaustive && empty
diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index 1594a03..533ab67 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs
@@ -273,13 +273,13 @@ fn is_ty_must_use<'tcx>( expr: &hir::Expr<'_>, span: Span, ) -> Option<MustUsePath> { - if ty.is_unit() - || !ty.is_inhabited_from( - cx.tcx, - cx.tcx.parent_module(expr.hir_id).to_def_id(), - cx.typing_env(), - ) - { + if ty.is_unit() { + return Some(MustUsePath::Suppressed); + } + let parent_mod_did = cx.tcx.parent_module(expr.hir_id).to_def_id(); + let is_uninhabited = + |t: Ty<'tcx>| !t.is_inhabited_from(cx.tcx, parent_mod_did, cx.typing_env()); + if is_uninhabited(ty) { return Some(MustUsePath::Suppressed); } @@ -293,6 +293,22 @@ fn is_ty_must_use<'tcx>( is_ty_must_use(cx, pinned_ty, expr, span) .map(|inner| MustUsePath::Pinned(Box::new(inner))) } + // Suppress warnings on `Result<(), Uninhabited>` (e.g. `Result<(), !>`). + ty::Adt(def, args) + if cx.tcx.is_diagnostic_item(sym::Result, def.did()) + && args.type_at(0).is_unit() + && is_uninhabited(args.type_at(1)) => + { + Some(MustUsePath::Suppressed) + } + // Suppress warnings on `ControlFlow<Uninhabited, ()>` (e.g. `ControlFlow<!, ()>`). + ty::Adt(def, args) + if cx.tcx.is_diagnostic_item(sym::ControlFlow, def.did()) + && args.type_at(1).is_unit() + && is_uninhabited(args.type_at(0)) => + { + Some(MustUsePath::Suppressed) + } ty::Adt(def, _) => is_def_must_use(cx, def.did(), span), ty::Alias(ty::Opaque | ty::Projection, ty::AliasTy { def_id: def, .. }) => { elaborate(cx.tcx, cx.tcx.explicit_item_self_bounds(def).iter_identity_copied())
diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 8b7b13a..1e96508 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs
@@ -4065,7 +4065,6 @@ /// ### Example /// /// ```rust,compile_fail - /// #![deny(never_type_fallback_flowing_into_unsafe)] /// fn main() { /// if true { /// // return has type `!` which, is some cases, causes never type fallback @@ -4100,7 +4099,7 @@ /// [`!`]: https://doc.rust-lang.org/core/primitive.never.html /// [`()`]: https://doc.rust-lang.org/core/primitive.unit.html pub NEVER_TYPE_FALLBACK_FLOWING_INTO_UNSAFE, - Warn, + Deny, "never type fallback affecting unsafe function calls", @future_incompatible = FutureIncompatibleInfo { reason: FutureIncompatibilityReason::EditionAndFutureReleaseSemanticsChange(Edition::Edition2024), @@ -4122,7 +4121,7 @@ /// ### Example /// /// ```rust,compile_fail,edition2021 - /// #![deny(dependency_on_unit_never_type_fallback)] + /// # #![deny(dependency_on_unit_never_type_fallback)] /// fn main() { /// if true { /// // return has type `!` which, is some cases, causes never type fallback @@ -4155,7 +4154,7 @@ /// /// See [Tracking Issue for making `!` fall back to `!`](https://github.com/rust-lang/rust/issues/123748). pub DEPENDENCY_ON_UNIT_NEVER_TYPE_FALLBACK, - Warn, + Deny, "never type fallback affecting unsafe function calls", @future_incompatible = FutureIncompatibleInfo { reason: FutureIncompatibilityReason::EditionAndFutureReleaseError(Edition::Edition2024),
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index db66938..e13ef7e 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -2115,7 +2115,8 @@ fn encode_impls(&mut self) -> LazyArray<TraitImpls> { }; let def_id = id.owner_id.to_def_id(); - if of_trait && let Some(header) = tcx.impl_trait_header(def_id) { + if of_trait { + let header = tcx.impl_trait_header(def_id); record!(self.tables.impl_trait_header[def_id] <- header); self.tables.defaultness.set_some(def_id.index, tcx.defaultness(def_id));
diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index 720970b..9fbfa0a 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs
@@ -24,12 +24,13 @@ use rustc_middle::metadata::ModChild; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs; use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile; +use rustc_middle::middle::deduced_param_attrs::DeducedParamAttrs; use rustc_middle::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo}; use rustc_middle::middle::lib_features::FeatureStability; use rustc_middle::middle::resolve_bound_vars::ObjectLifetimeDefault; use rustc_middle::mir; use rustc_middle::ty::fast_reject::SimplifiedType; -use rustc_middle::ty::{self, DeducedParamAttrs, Ty, TyCtxt, UnusedGenericParams}; +use rustc_middle::ty::{self, Ty, TyCtxt, UnusedGenericParams}; use rustc_middle::util::Providers; use rustc_serialize::opaque::FileEncoder; use rustc_session::config::{SymbolManglingVersion, TargetModifier};
diff --git a/compiler/rustc_metadata/src/rmeta/parameterized.rs b/compiler/rustc_metadata/src/rmeta/parameterized.rs index 4b2dc2c..733e33f 100644 --- a/compiler/rustc_metadata/src/rmeta/parameterized.rs +++ b/compiler/rustc_metadata/src/rmeta/parameterized.rs
@@ -97,6 +97,7 @@ impl ParameterizedOverTcx for $ty { rustc_middle::metadata::ModChild, rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs, rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile, + rustc_middle::middle::deduced_param_attrs::DeducedParamAttrs, rustc_middle::middle::exported_symbols::SymbolExportInfo, rustc_middle::middle::lib_features::FeatureStability, rustc_middle::middle::resolve_bound_vars::ObjectLifetimeDefault, @@ -105,7 +106,6 @@ impl ParameterizedOverTcx for $ty { rustc_middle::ty::AssocContainer, rustc_middle::ty::AsyncDestructor, rustc_middle::ty::Asyncness, - rustc_middle::ty::DeducedParamAttrs, rustc_middle::ty::Destructor, rustc_middle::ty::Generics, rustc_middle::ty::ImplTraitInTraitData,
diff --git a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs index f0d96c6..d47d811 100644 --- a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs +++ b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs
@@ -13,6 +13,8 @@ pub fn codegen_instance_attrs( self, instance_kind: InstanceKind<'_>, ) -> Cow<'tcx, CodegenFnAttrs> { + // NOTE: we try to not clone the `CodegenFnAttrs` when that is not needed. + // The `to_mut` method used below clones the inner value. let mut attrs = Cow::Borrowed(self.codegen_fn_attrs(instance_kind.def_id())); // Drop the `#[naked]` attribute on non-item `InstanceKind`s, like the shims that @@ -23,6 +25,28 @@ pub fn codegen_instance_attrs( } } + // A shim created by `#[track_caller]` should not inherit any attributes + // that modify the symbol name. Failing to remove these attributes from + // the shim leads to errors like `symbol `foo` is already defined`. + // + // A `ClosureOnceShim` with the track_caller attribute does not have a symbol, + // and therefore can be skipped here. + if let InstanceKind::ReifyShim(_, _) = instance_kind + && attrs.flags.contains(CodegenFnAttrFlags::TRACK_CALLER) + { + if attrs.flags.contains(CodegenFnAttrFlags::NO_MANGLE) { + attrs.to_mut().flags.remove(CodegenFnAttrFlags::NO_MANGLE); + } + + if attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL) { + attrs.to_mut().flags.remove(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL); + } + + if attrs.symbol_name.is_some() { + attrs.to_mut().symbol_name = None; + } + } + attrs } }
diff --git a/compiler/rustc_middle/src/middle/deduced_param_attrs.rs b/compiler/rustc_middle/src/middle/deduced_param_attrs.rs new file mode 100644 index 0000000..68d1c85 --- /dev/null +++ b/compiler/rustc_middle/src/middle/deduced_param_attrs.rs
@@ -0,0 +1,68 @@ +use rustc_macros::{Decodable, Encodable, HashStable}; + +use crate::ty::{Ty, TyCtxt, TypingEnv}; + +/// Flags that dictate how a parameter is mutated. If the flags are empty, the param is +/// read-only. If non-empty, it is read-only if *all* flags' conditions are met. +#[derive(Clone, Copy, PartialEq, Debug, Decodable, Encodable, HashStable)] +pub struct DeducedReadOnlyParam(u8); + +bitflags::bitflags! { + impl DeducedReadOnlyParam: u8 { + /// This parameter is dropped. It is read-only if `!needs_drop`. + const IF_NO_DROP = 1 << 0; + /// This parameter is borrowed. It is read-only if `Freeze`. + const IF_FREEZE = 1 << 1; + /// This parameter is mutated. It is never read-only. + const MUTATED = 1 << 2; + } +} + +/// Parameter attributes that can only be determined by examining the body of a function instead +/// of just its signature. +/// +/// These can be useful for optimization purposes when a function is directly called. We compute +/// them and store them into the crate metadata so that downstream crates can make use of them. +/// +/// Right now, we only have `read_only`, but `no_capture` and `no_alias` might be useful in the +/// future. +#[derive(Clone, Copy, PartialEq, Debug, Decodable, Encodable, HashStable)] +pub struct DeducedParamAttrs { + /// The parameter is marked immutable in the function. + pub read_only: DeducedReadOnlyParam, +} + +// By default, consider the parameters to be mutated. +impl Default for DeducedParamAttrs { + #[inline] + fn default() -> DeducedParamAttrs { + DeducedParamAttrs { read_only: DeducedReadOnlyParam::MUTATED } + } +} + +impl DeducedParamAttrs { + #[inline] + pub fn is_default(self) -> bool { + self.read_only.contains(DeducedReadOnlyParam::MUTATED) + } + + pub fn read_only<'tcx>( + &self, + tcx: TyCtxt<'tcx>, + typing_env: TypingEnv<'tcx>, + ty: Ty<'tcx>, + ) -> bool { + let read_only = self.read_only; + // We have to check *all* set bits; only if all checks pass is this truly read-only. + if read_only.contains(DeducedReadOnlyParam::MUTATED) { + return false; + } + if read_only.contains(DeducedReadOnlyParam::IF_NO_DROP) && ty.needs_drop(tcx, typing_env) { + return false; + } + if read_only.contains(DeducedReadOnlyParam::IF_FREEZE) && !ty.is_freeze(tcx, typing_env) { + return false; + } + true + } +}
diff --git a/compiler/rustc_middle/src/middle/mod.rs b/compiler/rustc_middle/src/middle/mod.rs index 6ca1e62..9091d49 100644 --- a/compiler/rustc_middle/src/middle/mod.rs +++ b/compiler/rustc_middle/src/middle/mod.rs
@@ -1,5 +1,6 @@ pub mod codegen_fn_attrs; pub mod debugger_visualizer; +pub mod deduced_param_attrs; pub mod dependency_format; pub mod exported_symbols; pub mod lang_items;
diff --git a/compiler/rustc_middle/src/mir/basic_blocks.rs b/compiler/rustc_middle/src/mir/basic_blocks.rs index 0d2e236..aae815c 100644 --- a/compiler/rustc_middle/src/mir/basic_blocks.rs +++ b/compiler/rustc_middle/src/mir/basic_blocks.rs
@@ -1,4 +1,4 @@ -use std::sync::OnceLock; +use std::sync::{Arc, OnceLock}; use rustc_data_structures::graph; use rustc_data_structures::graph::dominators::{Dominators, dominators}; @@ -14,7 +14,8 @@ #[derive(Clone, TyEncodable, TyDecodable, Debug, HashStable, TypeFoldable, TypeVisitable)] pub struct BasicBlocks<'tcx> { basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>, - cache: Cache, + /// Use an `Arc` so we can share the cache when we clone the MIR body, as borrowck does. + cache: Arc<Cache>, } // Typically 95%+ of basic blocks have 4 or fewer predecessors. @@ -38,9 +39,10 @@ struct Cache { impl<'tcx> BasicBlocks<'tcx> { #[inline] pub fn new(basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>) -> Self { - BasicBlocks { basic_blocks, cache: Cache::default() } + BasicBlocks { basic_blocks, cache: Arc::new(Cache::default()) } } + #[inline] pub fn dominators(&self) -> &Dominators<BasicBlock> { self.cache.dominators.get_or_init(|| dominators(self)) } @@ -104,7 +106,14 @@ pub fn as_mut_preserves_cfg(&mut self) -> &mut IndexVec<BasicBlock, BasicBlockDa /// All other methods that allow you to mutate the basic blocks also call this method /// themselves, thereby avoiding any risk of accidentally cache invalidation. pub fn invalidate_cfg_cache(&mut self) { - self.cache = Cache::default(); + if let Some(cache) = Arc::get_mut(&mut self.cache) { + // If we only have a single reference to this cache, clear it. + *cache = Cache::default(); + } else { + // If we have several references to this cache, overwrite the pointer itself so other + // users can continue to use their (valid) cache. + self.cache = Arc::new(Cache::default()); + } } }
diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index 6f616b5..38f03cf 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs
@@ -137,6 +137,7 @@ pub enum RuntimePhase { /// And the following variants are allowed: /// * [`StatementKind::Retag`] /// * [`StatementKind::SetDiscriminant`] + /// * [`PlaceElem::ConstantIndex`] / [`PlaceElem::Subslice`] after [`PlaceElem::Subslice`] /// /// Furthermore, `Copy` operands are allowed for non-`Copy` types. Initial = 0, @@ -1246,6 +1247,9 @@ pub enum ProjectionElem<V, T> { /// /// If `from_end` is true `slice[from..slice.len() - to]`. /// Otherwise `array[from..to]`. + /// + /// This projection cannot have `ConstantIndex` or additional `Subslice` projections after it + /// before runtime MIR. Subslice { from: u64, to: u64,
diff --git a/compiler/rustc_middle/src/mir/terminator.rs b/compiler/rustc_middle/src/mir/terminator.rs index 4249914..62711ad 100644 --- a/compiler/rustc_middle/src/mir/terminator.rs +++ b/compiler/rustc_middle/src/mir/terminator.rs
@@ -696,6 +696,28 @@ pub fn as_goto(&self) -> Option<BasicBlock> { _ => None, } } + + /// Returns true if the terminator can write to memory. + pub fn can_write_to_memory(&self) -> bool { + match self { + TerminatorKind::Goto { .. } + | TerminatorKind::SwitchInt { .. } + | TerminatorKind::UnwindResume + | TerminatorKind::UnwindTerminate(_) + | TerminatorKind::Return + | TerminatorKind::Assert { .. } + | TerminatorKind::CoroutineDrop + | TerminatorKind::FalseEdge { .. } + | TerminatorKind::FalseUnwind { .. } + | TerminatorKind::Unreachable => false, + TerminatorKind::Call { .. } + | TerminatorKind::Drop { .. } + | TerminatorKind::TailCall { .. } + // Yield writes to the resume_arg place. + | TerminatorKind::Yield { .. } + | TerminatorKind::InlineAsm { .. } => true, + } + } } #[derive(Copy, Clone, Debug)]
diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs index cad10fc..ad82e83 100644 --- a/compiler/rustc_middle/src/query/erase.rs +++ b/compiler/rustc_middle/src/query/erase.rs
@@ -200,8 +200,8 @@ impl EraseType for Option<mir::DestructuredConstant<'_>> { type Result = [u8; size_of::<Option<mir::DestructuredConstant<'static>>>()]; } -impl EraseType for Option<ty::ImplTraitHeader<'_>> { - type Result = [u8; size_of::<Option<ty::ImplTraitHeader<'static>>>()]; +impl EraseType for ty::ImplTraitHeader<'_> { + type Result = [u8; size_of::<ty::ImplTraitHeader<'static>>()]; } impl EraseType for Option<ty::EarlyBinder<'_, Ty<'_>>> { @@ -313,6 +313,7 @@ impl EraseType for $ty { rustc_hir::Stability, rustc_hir::Upvar, rustc_index::bit_set::FiniteBitSet<u32>, + rustc_middle::middle::deduced_param_attrs::DeducedParamAttrs, rustc_middle::middle::dependency_format::Linkage, rustc_middle::middle::exported_symbols::SymbolExportInfo, rustc_middle::middle::resolve_bound_vars::ObjectLifetimeDefault, @@ -336,7 +337,6 @@ impl EraseType for $ty { rustc_middle::ty::AsyncDestructor, rustc_middle::ty::BoundVariableKind, rustc_middle::ty::AnonConstKind, - rustc_middle::ty::DeducedParamAttrs, rustc_middle::ty::Destructor, rustc_middle::ty::fast_reject::SimplifiedType, rustc_middle::ty::ImplPolarity,
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 448c26e..588ff68 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs
@@ -107,6 +107,7 @@ use crate::metadata::ModChild; use crate::middle::codegen_fn_attrs::CodegenFnAttrs; use crate::middle::debugger_visualizer::DebuggerVisualizerFile; +use crate::middle::deduced_param_attrs::DeducedParamAttrs; use crate::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo}; use crate::middle::lib_features::LibFeatures; use crate::middle::privacy::EffectiveVisibilities; @@ -1104,8 +1105,7 @@ } /// Given an `impl_id`, return the trait it implements along with some header information. - /// Return `None` if this is an inherent impl. - query impl_trait_header(impl_id: DefId) -> Option<ty::ImplTraitHeader<'tcx>> { + query impl_trait_header(impl_id: DefId) -> ty::ImplTraitHeader<'tcx> { desc { |tcx| "computing trait implemented by `{}`", tcx.def_path_str(impl_id) } cache_on_disk_if { impl_id.is_local() } separate_provide_extern @@ -1202,10 +1202,10 @@ /// Return the live symbols in the crate for dead code check. /// /// The second return value maps from ADTs to ignored derived traits (e.g. Debug and Clone). - query live_symbols_and_ignored_derived_traits(_: ()) -> &'tcx ( + query live_symbols_and_ignored_derived_traits(_: ()) -> &'tcx Result<( LocalDefIdSet, LocalDefIdMap<FxIndexSet<DefId>>, - ) { + ), ErrorGuaranteed> { arena_cache desc { "finding live symbols in crate" } } @@ -2657,7 +2657,7 @@ return_result_from_ensure_ok } - query deduced_param_attrs(def_id: DefId) -> &'tcx [ty::DeducedParamAttrs] { + query deduced_param_attrs(def_id: DefId) -> &'tcx [DeducedParamAttrs] { desc { |tcx| "deducing parameter attributes for {}", tcx.def_path_str(def_id) } separate_provide_extern }
diff --git a/compiler/rustc_middle/src/query/on_disk_cache.rs b/compiler/rustc_middle/src/query/on_disk_cache.rs index 5467911..e8952d0 100644 --- a/compiler/rustc_middle/src/query/on_disk_cache.rs +++ b/compiler/rustc_middle/src/query/on_disk_cache.rs
@@ -799,7 +799,7 @@ fn decode(d: &mut CacheDecoder<'a, $tcx>) -> Self { rustc_span::def_id::DefId, rustc_span::def_id::LocalDefId, (rustc_middle::middle::exported_symbols::ExportedSymbol<'tcx>, rustc_middle::middle::exported_symbols::SymbolExportInfo), - ty::DeducedParamAttrs, + rustc_middle::middle::deduced_param_attrs::DeducedParamAttrs, } //- ENCODING -------------------------------------------------------------------
diff --git a/compiler/rustc_middle/src/ty/codec.rs b/compiler/rustc_middle/src/ty/codec.rs index 3f37595..3d6320b 100644 --- a/compiler/rustc_middle/src/ty/codec.rs +++ b/compiler/rustc_middle/src/ty/codec.rs
@@ -577,7 +577,7 @@ fn decode(decoder: &mut D) -> &'tcx Self { rustc_span::def_id::DefId, rustc_span::def_id::LocalDefId, (rustc_middle::middle::exported_symbols::ExportedSymbol<'tcx>, rustc_middle::middle::exported_symbols::SymbolExportInfo), - ty::DeducedParamAttrs, + rustc_middle::middle::deduced_param_attrs::DeducedParamAttrs, } #[macro_export]
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index de2b2e6..7d55ce2 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs
@@ -41,7 +41,6 @@ use rustc_hir::limit::Limit; use rustc_hir::{self as hir, Attribute, HirId, Node, TraitCandidate, find_attr}; use rustc_index::IndexVec; -use rustc_macros::{HashStable, TyDecodable, TyEncodable}; use rustc_query_system::cache::WithDepNode; use rustc_query_system::dep_graph::DepNodeIndex; use rustc_query_system::ich::StableHashingContext; @@ -679,7 +678,7 @@ fn impl_is_default(self, impl_def_id: DefId) -> bool { } fn impl_trait_ref(self, impl_def_id: DefId) -> ty::EarlyBinder<'tcx, ty::TraitRef<'tcx>> { - self.impl_trait_ref(impl_def_id).unwrap() + self.impl_trait_ref(impl_def_id) } fn impl_polarity(self, impl_def_id: DefId) -> ty::ImplPolarity { @@ -1786,9 +1785,7 @@ pub fn default_traits(self) -> &'static [rustc_hir::LangItem] { } pub fn is_default_trait(self, def_id: DefId) -> bool { - self.default_traits() - .iter() - .any(|&default_trait| self.lang_items().get(default_trait) == Some(def_id)) + self.default_traits().iter().any(|&default_trait| self.is_lang_item(def_id, default_trait)) } pub fn is_sizedness_trait(self, def_id: DefId) -> bool { @@ -3472,7 +3469,7 @@ pub fn is_stable_const_fn(self, def_id: DefId) -> bool { /// Whether the trait impl is marked const. This does not consider stability or feature gates. pub fn is_const_trait_impl(self, def_id: DefId) -> bool { self.def_kind(def_id) == DefKind::Impl { of_trait: true } - && self.impl_trait_header(def_id).unwrap().constness == hir::Constness::Const + && self.impl_trait_header(def_id).constness == hir::Constness::Const } pub fn is_sdylib_interface_build(self) -> bool { @@ -3530,19 +3527,6 @@ pub fn metadata_dep_node(self) -> crate::dep_graph::DepNode { crate::dep_graph::make_metadata(self) } - /// Given an `impl_id`, return the trait it implements. - /// Return `None` if this is an inherent impl. - pub fn impl_trait_ref( - self, - def_id: impl IntoQueryParam<DefId>, - ) -> Option<ty::EarlyBinder<'tcx, ty::TraitRef<'tcx>>> { - Some(self.impl_trait_header(def_id)?.trait_ref) - } - - pub fn impl_polarity(self, def_id: impl IntoQueryParam<DefId>) -> ty::ImplPolarity { - self.impl_trait_header(def_id).map_or(ty::ImplPolarity::Positive, |h| h.polarity) - } - pub fn needs_coroutine_by_move_body_def_id(self, def_id: DefId) -> bool { if let Some(hir::CoroutineKind::Desugared(_, hir::CoroutineSource::Closure)) = self.coroutine_kind(def_id) @@ -3575,21 +3559,6 @@ pub fn is_entrypoint(self, def_id: DefId) -> bool { } } -/// Parameter attributes that can only be determined by examining the body of a function instead -/// of just its signature. -/// -/// These can be useful for optimization purposes when a function is directly called. We compute -/// them and store them into the crate metadata so that downstream crates can make use of them. -/// -/// Right now, we only have `read_only`, but `no_capture` and `no_alias` might be useful in the -/// future. -#[derive(Clone, Copy, PartialEq, Debug, Default, TyDecodable, TyEncodable, HashStable)] -pub struct DeducedParamAttrs { - /// The parameter is marked immutable in the function and contains no `UnsafeCell` (i.e. its - /// type is freeze). - pub read_only: bool, -} - pub fn provide(providers: &mut Providers) { providers.is_panic_runtime = |tcx, LocalCrate| contains_name(tcx.hir_krate_attrs(), sym::panic_runtime);
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index b6adc60..c3e1def 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -78,8 +78,7 @@ ExprKind, ScalarInt, UnevaluatedConst, ValTree, ValTreeKind, Value, }; pub use self::context::{ - CtxtInterners, CurrentGcx, DeducedParamAttrs, Feed, FreeRegionInfo, GlobalCtxt, Lift, TyCtxt, - TyCtxtFeed, tls, + CtxtInterners, CurrentGcx, Feed, FreeRegionInfo, GlobalCtxt, Lift, TyCtxt, TyCtxtFeed, tls, }; pub use self::fold::*; pub use self::instance::{Instance, InstanceKind, ReifyReason, UnusedGenericParams}; @@ -1614,8 +1613,8 @@ pub fn impls_are_allowed_to_overlap( def_id1: DefId, def_id2: DefId, ) -> Option<ImplOverlapKind> { - let impl1 = self.impl_trait_header(def_id1).unwrap(); - let impl2 = self.impl_trait_header(def_id2).unwrap(); + let impl1 = self.impl_trait_header(def_id1); + let impl2 = self.impl_trait_header(def_id2); let trait_ref1 = impl1.trait_ref.skip_binder(); let trait_ref2 = impl2.trait_ref.skip_binder(); @@ -1913,12 +1912,6 @@ pub fn coroutine_layout( } } - /// Given the `DefId` of an impl, returns the `DefId` of the trait it implements. - /// If it implements no trait, returns `None`. - pub fn trait_id_of_impl(self, def_id: DefId) -> Option<DefId> { - self.impl_trait_ref(def_id).map(|tr| tr.skip_binder().def_id) - } - /// If the given `DefId` is an associated item, returns the `DefId` and `DefKind` of the parent trait or impl. pub fn assoc_parent(self, def_id: DefId) -> Option<(DefId, DefKind)> { if !self.def_kind(def_id).is_assoc() { @@ -1943,6 +1936,14 @@ pub fn trait_of_assoc(self, def_id: DefId) -> Option<DefId> { } } + pub fn impl_is_of_trait(self, def_id: impl IntoQueryParam<DefId>) -> bool { + let def_id = def_id.into_query_param(); + let DefKind::Impl { of_trait } = self.def_kind(def_id) else { + panic!("expected Impl for {def_id:?}"); + }; + of_trait + } + /// If the given `DefId` is an associated item of an impl, /// returns the `DefId` of the impl; otherwise returns `None`. pub fn impl_of_assoc(self, def_id: DefId) -> Option<DefId> { @@ -1970,6 +1971,40 @@ pub fn trait_impl_of_assoc(self, def_id: DefId) -> Option<DefId> { } } + pub fn impl_polarity(self, def_id: impl IntoQueryParam<DefId>) -> ty::ImplPolarity { + self.impl_trait_header(def_id).polarity + } + + /// Given an `impl_id`, return the trait it implements. + pub fn impl_trait_ref( + self, + def_id: impl IntoQueryParam<DefId>, + ) -> ty::EarlyBinder<'tcx, ty::TraitRef<'tcx>> { + self.impl_trait_header(def_id).trait_ref + } + + /// Given an `impl_id`, return the trait it implements. + /// Returns `None` if it is an inherent impl. + pub fn impl_opt_trait_ref( + self, + def_id: impl IntoQueryParam<DefId>, + ) -> Option<ty::EarlyBinder<'tcx, ty::TraitRef<'tcx>>> { + let def_id = def_id.into_query_param(); + self.impl_is_of_trait(def_id).then(|| self.impl_trait_ref(def_id)) + } + + /// Given the `DefId` of an impl, returns the `DefId` of the trait it implements. + pub fn impl_trait_id(self, def_id: impl IntoQueryParam<DefId>) -> DefId { + self.impl_trait_ref(def_id).skip_binder().def_id + } + + /// Given the `DefId` of an impl, returns the `DefId` of the trait it implements. + /// Returns `None` if it is an inherent impl. + pub fn impl_opt_trait_id(self, def_id: impl IntoQueryParam<DefId>) -> Option<DefId> { + let def_id = def_id.into_query_param(); + self.impl_is_of_trait(def_id).then(|| self.impl_trait_id(def_id)) + } + pub fn is_exportable(self, def_id: DefId) -> bool { self.exportable_items(def_id.krate).contains(&def_id) } @@ -2062,7 +2097,7 @@ pub fn is_conditionally_const(self, def_id: impl Into<DefId>) -> bool { let def_id: DefId = def_id.into(); match self.def_kind(def_id) { DefKind::Impl { of_trait: true } => { - let header = self.impl_trait_header(def_id).unwrap(); + let header = self.impl_trait_header(def_id); header.constness == hir::Constness::Const && self.is_const_trait(header.trait_ref.skip_binder().def_id) }
diff --git a/compiler/rustc_middle/src/ty/print/mod.rs b/compiler/rustc_middle/src/ty/print/mod.rs index d636e8e..0fd68e7 100644 --- a/compiler/rustc_middle/src/ty/print/mod.rs +++ b/compiler/rustc_middle/src/ty/print/mod.rs
@@ -45,7 +45,7 @@ fn print_impl_path( ) -> Result<(), PrintError> { let tcx = self.tcx(); let self_ty = tcx.type_of(impl_def_id); - let impl_trait_ref = tcx.impl_trait_ref(impl_def_id); + let impl_trait_ref = tcx.impl_opt_trait_ref(impl_def_id); let (self_ty, impl_trait_ref) = if tcx.generics_of(impl_def_id).count() <= args.len() { ( self_ty.instantiate(tcx, args),
diff --git a/compiler/rustc_middle/src/ty/trait_def.rs b/compiler/rustc_middle/src/ty/trait_def.rs index 4e38d96..691cb43 100644 --- a/compiler/rustc_middle/src/ty/trait_def.rs +++ b/compiler/rustc_middle/src/ty/trait_def.rs
@@ -271,9 +271,7 @@ pub(super) fn traits_provider(tcx: TyCtxt<'_>, _: LocalCrate) -> &[DefId] { pub(super) fn trait_impls_in_crate_provider(tcx: TyCtxt<'_>, _: LocalCrate) -> &[DefId] { let mut trait_impls = Vec::new(); for id in tcx.hir_free_items() { - if matches!(tcx.def_kind(id.owner_id), DefKind::Impl { .. }) - && tcx.impl_trait_ref(id.owner_id).is_some() - { + if tcx.def_kind(id.owner_id) == (DefKind::Impl { of_trait: true }) { trait_impls.push(id.owner_id.to_def_id()) } }
diff --git a/compiler/rustc_mir_build/src/builder/matches/match_pair.rs b/compiler/rustc_mir_build/src/builder/matches/match_pair.rs index 82c769e..c3028b9 100644 --- a/compiler/rustc_mir_build/src/builder/matches/match_pair.rs +++ b/compiler/rustc_mir_build/src/builder/matches/match_pair.rs
@@ -43,13 +43,23 @@ fn prefix_slice_suffix( ) { let tcx = self.tcx; let (min_length, exact_size) = if let Some(place_resolved) = place.try_to_place(self) { - match place_resolved.ty(&self.local_decls, tcx).ty.kind() { - ty::Array(_, length) => ( - length - .try_to_target_usize(tcx) - .expect("expected len of array pat to be definite"), - true, - ), + let place_ty = place_resolved.ty(&self.local_decls, tcx).ty; + match place_ty.kind() { + ty::Array(_, length) => { + if let Some(length) = length.try_to_target_usize(tcx) { + (length, true) + } else { + // This can happen when the array length is a generic const + // expression that couldn't be evaluated (e.g., due to an error). + // Since there's already a compilation error, we use a fallback + // to avoid an ICE. + tcx.dcx().span_delayed_bug( + tcx.def_span(self.def_id), + "array length in pattern couldn't be evaluated", + ); + ((prefix.len() + suffix.len()).try_into().unwrap(), false) + } + } _ => ((prefix.len() + suffix.len()).try_into().unwrap(), false), } } else {
diff --git a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs index c60713c..b45f8a7 100644 --- a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs +++ b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs
@@ -9,7 +9,7 @@ use super::{ Init, InitIndex, InitKind, InitLocation, LocationMap, LookupResult, MoveData, MoveOut, - MoveOutIndex, MovePath, MovePathIndex, MovePathLookup, + MoveOutIndex, MovePath, MovePathIndex, MovePathLookup, MoveSubPath, MoveSubPathResult, }; struct MoveDataBuilder<'a, 'tcx, F> { @@ -94,26 +94,25 @@ fn new_move_path<'tcx>( move_path } -enum MovePathResult { - Path(MovePathIndex), - Union(MovePathIndex), - Error, -} - impl<'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> MoveDataBuilder<'a, 'tcx, F> { - /// This creates a MovePath for a given place, returning an `MovePathError` - /// if that place can't be moved from. + /// This creates a MovePath for a given place, calling `on_move` + /// if it can be moved from. If theres a union in the path, its + /// move place will be given to `on_move`. If there's a subslice + /// projection, `on_move` will be called for each element. /// /// NOTE: places behind references *do not* get a move path, which is /// problematic for borrowck. /// /// Maybe we should have separate "borrowck" and "moveck" modes. - fn move_path_for(&mut self, place: Place<'tcx>) -> MovePathResult { + fn move_path_for<G>(&mut self, place: Place<'tcx>, mut on_move: G) + where + G: FnMut(&mut Self, MovePathIndex), + { let data = &mut self.data; debug!("lookup({:?})", place); let Some(mut base) = data.rev_lookup.find_local(place.local) else { - return MovePathResult::Error; + return; }; // The move path index of the first union that we find. Once this is @@ -123,144 +122,186 @@ fn move_path_for(&mut self, place: Place<'tcx>) -> MovePathResult { // from `*(u.f: &_)` isn't allowed. let mut union_path = None; - for (place_ref, elem) in data.rev_lookup.un_derefer.iter_projections(place.as_ref()) { + let mut iter = data.rev_lookup.un_derefer.iter_projections(place.as_ref()); + while let Some((place_ref, elem)) = iter.next() { let body = self.body; let tcx = self.tcx; let place_ty = place_ref.ty(body, tcx).ty; if place_ty.references_error() { - return MovePathResult::Error; + return; } - match elem { - ProjectionElem::Deref => match place_ty.kind() { - ty::Ref(..) | ty::RawPtr(..) => { - return MovePathResult::Error; - } - ty::Adt(adt, _) => { - if !adt.is_box() { - bug!("Adt should be a box type when Place is deref"); - } - } - ty::Bool - | ty::Char - | ty::Int(_) - | ty::Uint(_) - | ty::Float(_) - | ty::Foreign(_) - | ty::Str - | ty::Array(_, _) - | ty::Pat(_, _) - | ty::Slice(_) - | ty::FnDef(_, _) - | ty::FnPtr(..) - | ty::Dynamic(_, _) - | ty::Closure(..) - | ty::CoroutineClosure(..) - | ty::Coroutine(_, _) - | ty::CoroutineWitness(..) - | ty::Never - | ty::Tuple(_) - | ty::UnsafeBinder(_) - | ty::Alias(_, _) - | ty::Param(_) - | ty::Bound(_, _) - | ty::Infer(_) - | ty::Error(_) - | ty::Placeholder(_) => { - bug!("When Place is Deref it's type shouldn't be {place_ty:#?}") - } - }, - ProjectionElem::Field(_, _) => match place_ty.kind() { - ty::Adt(adt, _) => { - if adt.has_dtor(tcx) { - return MovePathResult::Error; - } - if adt.is_union() { - union_path.get_or_insert(base); - } - } - ty::Closure(..) - | ty::CoroutineClosure(..) - | ty::Coroutine(_, _) - | ty::Tuple(_) => (), - ty::Bool - | ty::Char - | ty::Int(_) - | ty::Uint(_) - | ty::Float(_) - | ty::Foreign(_) - | ty::Str - | ty::Array(_, _) - | ty::Pat(_, _) - | ty::Slice(_) - | ty::RawPtr(_, _) - | ty::Ref(_, _, _) - | ty::FnDef(_, _) - | ty::FnPtr(..) - | ty::Dynamic(_, _) - | ty::CoroutineWitness(..) - | ty::Never - | ty::UnsafeBinder(_) - | ty::Alias(_, _) - | ty::Param(_) - | ty::Bound(_, _) - | ty::Infer(_) - | ty::Error(_) - | ty::Placeholder(_) => bug!( - "When Place contains ProjectionElem::Field its type shouldn't be {place_ty:#?}" - ), - }, - ProjectionElem::ConstantIndex { .. } | ProjectionElem::Subslice { .. } => { - match place_ty.kind() { - ty::Slice(_) => { - return MovePathResult::Error; - } - ty::Array(_, _) => (), - _ => bug!("Unexpected type {:#?}", place_ty.is_array()), - } + + let res = MoveSubPath::of(elem.kind()); + + let move_elem = match res { + MoveSubPathResult::One(move_elem) => { + match move_elem { + MoveSubPath::Deref => match place_ty.kind() { + ty::Ref(..) | ty::RawPtr(..) => { + return; + } + ty::Adt(adt, _) => { + if !adt.is_box() { + bug!("Adt should be a box type when Place is deref"); + } + } + ty::Bool + | ty::Char + | ty::Int(_) + | ty::Uint(_) + | ty::Float(_) + | ty::Foreign(_) + | ty::Str + | ty::Array(_, _) + | ty::Pat(_, _) + | ty::Slice(_) + | ty::FnDef(_, _) + | ty::FnPtr(..) + | ty::Dynamic(_, _) + | ty::Closure(..) + | ty::CoroutineClosure(..) + | ty::Coroutine(_, _) + | ty::CoroutineWitness(..) + | ty::Never + | ty::Tuple(_) + | ty::UnsafeBinder(_) + | ty::Alias(_, _) + | ty::Param(_) + | ty::Bound(_, _) + | ty::Infer(_) + | ty::Error(_) + | ty::Placeholder(_) => { + bug!("When Place is Deref it's type shouldn't be {place_ty:#?}") + } + }, + MoveSubPath::Field(_) => match place_ty.kind() { + ty::Adt(adt, _) => { + if adt.has_dtor(tcx) { + return; + } + if adt.is_union() { + union_path.get_or_insert(base); + } + } + ty::Closure(..) + | ty::CoroutineClosure(..) + | ty::Coroutine(_, _) + | ty::Tuple(_) => (), + ty::Bool + | ty::Char + | ty::Int(_) + | ty::Uint(_) + | ty::Float(_) + | ty::Foreign(_) + | ty::Str + | ty::Array(_, _) + | ty::Pat(_, _) + | ty::Slice(_) + | ty::RawPtr(_, _) + | ty::Ref(_, _, _) + | ty::FnDef(_, _) + | ty::FnPtr(..) + | ty::Dynamic(_, _) + | ty::CoroutineWitness(..) + | ty::Never + | ty::UnsafeBinder(_) + | ty::Alias(_, _) + | ty::Param(_) + | ty::Bound(_, _) + | ty::Infer(_) + | ty::Error(_) + | ty::Placeholder(_) => bug!( + "When Place contains ProjectionElem::Field its type shouldn't be {place_ty:#?}" + ), + }, + MoveSubPath::ConstantIndex(_) => match place_ty.kind() { + ty::Slice(_) => { + return; + } + ty::Array(_, _) => (), + _ => bug!("Unexpected type {:#?}", place_ty.is_array()), + }, + MoveSubPath::Downcast(_) => (), + MoveSubPath::UnwrapUnsafeBinder => (), + }; + + move_elem } - ProjectionElem::Index(_) => match place_ty.kind() { - ty::Array(..) | ty::Slice(_) => { - return MovePathResult::Error; + + // Split `Subslice` patterns into the corresponding list of + // `ConstIndex` patterns. This is done to ensure that all move paths + // are disjoint, which is expected by drop elaboration. + MoveSubPathResult::Subslice { from, to } => { + assert!( + iter.all( + |(_, elem)| MoveSubPath::of(elem.kind()) == MoveSubPathResult::Skip + ) + ); + drop(iter); // drop for borrowck + + let (&elem_ty, len) = match place_ty.kind() { + ty::Array(ty, size) => ( + ty, + size.try_to_target_usize(self.tcx) + .expect("expected subslice projection on fixed-size array"), + ), + _ => bug!("from_end: false slice pattern of non-array type"), + }; + + if !(self.filter)(elem_ty) { + return; } - _ => bug!("Unexpected type {place_ty:#?}"), - }, - ProjectionElem::UnwrapUnsafeBinder(_) => {} - // `OpaqueCast`:Only transmutes the type, so no moves there. - // `Downcast` :Only changes information about a `Place` without moving. - // So it's safe to skip these. - ProjectionElem::OpaqueCast(_) | ProjectionElem::Downcast(_, _) => (), - } + + for offset in from..to { + let place_elem = + PlaceElem::ConstantIndex { offset, min_length: len, from_end: false }; + let subpath_elem = MoveSubPath::ConstantIndex(offset); + + let mpi = self.add_move_path(base, subpath_elem, |tcx| { + place_ref.project_deeper(&[place_elem], tcx) + }); + on_move(self, mpi); + } + + return; + } + + MoveSubPathResult::Skip => continue, + MoveSubPathResult::Stop => return, + }; + let elem_ty = PlaceTy::from_ty(place_ty).projection_ty(tcx, elem).ty; if !(self.filter)(elem_ty) { - return MovePathResult::Error; + return; } if union_path.is_none() { // inlined from add_move_path because of a borrowck conflict with the iterator - base = - *data.rev_lookup.projections.entry((base, elem.kind())).or_insert_with(|| { - new_move_path( - &mut data.move_paths, - &mut data.path_map, - &mut data.init_path_map, - Some(base), - place_ref.project_deeper(&[elem], tcx), - ) - }) + base = *data.rev_lookup.projections.entry((base, move_elem)).or_insert_with(|| { + new_move_path( + &mut data.move_paths, + &mut data.path_map, + &mut data.init_path_map, + Some(base), + place_ref.project_deeper(&[elem], tcx), + ) + }) } } + drop(iter); // drop for borrowck + if let Some(base) = union_path { // Move out of union - always move the entire union. - MovePathResult::Union(base) + on_move(self, base); } else { - MovePathResult::Path(base) + on_move(self, base); } } fn add_move_path( &mut self, base: MovePathIndex, - elem: PlaceElem<'tcx>, + elem: MoveSubPath, mk_place: impl FnOnce(TyCtxt<'tcx>) -> Place<'tcx>, ) -> MovePathIndex { let MoveDataBuilder { @@ -268,7 +309,7 @@ fn add_move_path( tcx, .. } = self; - *rev_lookup.projections.entry((base, elem.kind())).or_insert_with(move || { + *rev_lookup.projections.entry((base, elem)).or_insert_with(move || { new_move_path(move_paths, path_map, init_path_map, Some(base), mk_place(*tcx)) }) } @@ -276,7 +317,7 @@ fn add_move_path( fn create_move_path(&mut self, place: Place<'tcx>) { // This is an non-moving access (such as an overwrite or // drop), so this not being a valid move path is OK. - let _ = self.move_path_for(place); + self.move_path_for(place, |_, _| ()); } fn finalize(self) -> MoveData<'tcx> { @@ -525,46 +566,7 @@ fn gather_operand(&mut self, operand: &Operand<'tcx>) { fn gather_move(&mut self, place: Place<'tcx>) { debug!("gather_move({:?}, {:?})", self.loc, place); - if let [ref base @ .., ProjectionElem::Subslice { from, to, from_end: false }] = - **place.projection - { - // Split `Subslice` patterns into the corresponding list of - // `ConstIndex` patterns. This is done to ensure that all move paths - // are disjoint, which is expected by drop elaboration. - let base_place = - Place { local: place.local, projection: self.tcx.mk_place_elems(base) }; - let base_path = match self.move_path_for(base_place) { - MovePathResult::Path(path) => path, - MovePathResult::Union(path) => { - self.record_move(place, path); - return; - } - MovePathResult::Error => { - return; - } - }; - let base_ty = base_place.ty(self.body, self.tcx).ty; - let len: u64 = match base_ty.kind() { - ty::Array(_, size) => size - .try_to_target_usize(self.tcx) - .expect("expected subslice projection on fixed-size array"), - _ => bug!("from_end: false slice pattern of non-array type"), - }; - for offset in from..to { - let elem = - ProjectionElem::ConstantIndex { offset, min_length: len, from_end: false }; - let path = - self.add_move_path(base_path, elem, |tcx| tcx.mk_place_elem(base_place, elem)); - self.record_move(place, path); - } - } else { - match self.move_path_for(place) { - MovePathResult::Path(path) | MovePathResult::Union(path) => { - self.record_move(place, path) - } - MovePathResult::Error => {} - }; - } + self.move_path_for(place, |this, mpi| this.record_move(place, mpi)); } fn record_move(&mut self, place: Place<'tcx>, path: MovePathIndex) {
diff --git a/compiler/rustc_mir_dataflow/src/move_paths/mod.rs b/compiler/rustc_mir_dataflow/src/move_paths/mod.rs index 466416d..6faef3e 100644 --- a/compiler/rustc_mir_dataflow/src/move_paths/mod.rs +++ b/compiler/rustc_mir_dataflow/src/move_paths/mod.rs
@@ -1,18 +1,9 @@ -//! The move-analysis portion of borrowck needs to work in an abstract domain of lifted `Place`s. -//! Most of the `Place` variants fall into a one-to-one mapping between the concrete and abstract -//! (e.g., a field projection on a local variable, `x.field`, has the same meaning in both -//! domains). In other words, all field projections for the same field on the same local do not -//! have meaningfully different types if ever. Indexed projections are the exception: `a[x]` needs -//! to be treated as mapping to the same move path as `a[y]` as well as `a[13]`, etc. So we map -//! these `x`/`y` values to `()`. -//! -//! (In theory, the analysis could be extended to work with sets of paths, so that `a[0]` and -//! `a[13]` could be kept distinct, while `a[x]` would still overlap them both. But that is not -//! what this representation does today.) +//! [`MovePath`]s track the initialization state of places and their sub-paths. use std::fmt; use std::ops::{Index, IndexMut}; +use rustc_abi::{FieldIdx, VariantIdx}; use rustc_data_structures::fx::FxHashMap; use rustc_index::{IndexSlice, IndexVec}; use rustc_middle::mir::*; @@ -309,7 +300,7 @@ pub struct MovePathLookup<'tcx> { /// subsequent search so that it is solely relative to that /// base-place). For the remaining lookup, we map the projection /// elem to the associated MovePathIndex. - projections: FxHashMap<(MovePathIndex, ProjectionKind), MovePathIndex>, + projections: FxHashMap<(MovePathIndex, MoveSubPath), MovePathIndex>, un_derefer: UnDerefer<'tcx>, } @@ -333,7 +324,14 @@ pub fn find(&self, place: PlaceRef<'tcx>) -> LookupResult { }; for (_, elem) in self.un_derefer.iter_projections(place) { - if let Some(&subpath) = self.projections.get(&(result, elem.kind())) { + let subpath = match MoveSubPath::of(elem.kind()) { + MoveSubPathResult::One(kind) => self.projections.get(&(result, kind)), + MoveSubPathResult::Subslice { .. } => None, // just use the parent MovePath + MoveSubPathResult::Skip => continue, + MoveSubPathResult::Stop => None, + }; + + if let Some(&subpath) = subpath { result = subpath; } else { return LookupResult::Parent(Some(result)); @@ -390,3 +388,58 @@ pub fn find_in_move_path_or_its_descendants( self.move_paths[root].find_descendant(&self.move_paths, pred) } } + +/// A projection into a move path producing a child path +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] +pub enum MoveSubPath { + Deref, + Field(FieldIdx), + ConstantIndex(u64), + Downcast(VariantIdx), + UnwrapUnsafeBinder, +} + +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub enum MoveSubPathResult { + One(MoveSubPath), + Subslice { from: u64, to: u64 }, + Skip, + Stop, +} + +impl MoveSubPath { + pub fn of(elem: ProjectionKind) -> MoveSubPathResult { + let subpath = match elem { + // correspond to a MoveSubPath + ProjectionKind::Deref => MoveSubPath::Deref, + ProjectionKind::Field(idx, _) => MoveSubPath::Field(idx), + ProjectionKind::ConstantIndex { offset, min_length: _, from_end: false } => { + MoveSubPath::ConstantIndex(offset) + } + ProjectionKind::Downcast(_, idx) => MoveSubPath::Downcast(idx), + ProjectionKind::UnwrapUnsafeBinder(_) => MoveSubPath::UnwrapUnsafeBinder, + + // this should be the same move path as its parent + // its fine to skip because it cannot have sibling move paths + // and it is not a user visible path + ProjectionKind::OpaqueCast(_) => { + return MoveSubPathResult::Skip; + } + + // these cannot be moved through + ProjectionKind::Index(_) + | ProjectionKind::ConstantIndex { offset: _, min_length: _, from_end: true } + | ProjectionKind::Subslice { from: _, to: _, from_end: true } => { + return MoveSubPathResult::Stop; + } + + // subslice is special. + // it needs to be split into individual move paths + ProjectionKind::Subslice { from, to, from_end: false } => { + return MoveSubPathResult::Subslice { from, to }; + } + }; + + MoveSubPathResult::One(subpath) + } +}
diff --git a/compiler/rustc_mir_transform/src/check_call_recursion.rs b/compiler/rustc_mir_transform/src/check_call_recursion.rs index a9acb1d..cac6308 100644 --- a/compiler/rustc_mir_transform/src/check_call_recursion.rs +++ b/compiler/rustc_mir_transform/src/check_call_recursion.rs
@@ -44,7 +44,7 @@ fn run_lint(&self, tcx: TyCtxt<'tcx>, body: &Body<'tcx>) { // First check if `body` is an `fn drop()` of `Drop` if let DefKind::AssocFn = tcx.def_kind(def_id) && let Some(impl_id) = tcx.trait_impl_of_assoc(def_id.to_def_id()) - && let trait_ref = tcx.impl_trait_ref(impl_id).unwrap() + && let trait_ref = tcx.impl_trait_ref(impl_id) && tcx.is_lang_item(trait_ref.instantiate_identity().def_id, LangItem::Drop) // avoid erroneous `Drop` impls from causing ICEs below && let sig = tcx.fn_sig(def_id).instantiate_identity()
diff --git a/compiler/rustc_mir_transform/src/deduce_param_attrs.rs b/compiler/rustc_mir_transform/src/deduce_param_attrs.rs index a0db8bd..e421e47 100644 --- a/compiler/rustc_mir_transform/src/deduce_param_attrs.rs +++ b/compiler/rustc_mir_transform/src/deduce_param_attrs.rs
@@ -4,57 +4,72 @@ //! body of the function instead of just the signature. These can be useful for optimization //! purposes on a best-effort basis. We compute them here and store them into the crate metadata so //! dependent crates can use them. +//! +//! Note that this *crucially* relies on codegen *not* doing any more MIR-level transformations +//! after `optimized_mir`! We check for things that are *not* guaranteed to be preserved by MIR +//! transforms, such as which local variables happen to be mutated. use rustc_hir::def_id::LocalDefId; -use rustc_index::bit_set::DenseBitSet; -use rustc_middle::mir::visit::{NonMutatingUseContext, PlaceContext, Visitor}; -use rustc_middle::mir::{Body, Location, Operand, Place, RETURN_PLACE, Terminator, TerminatorKind}; -use rustc_middle::ty::{self, DeducedParamAttrs, Ty, TyCtxt}; +use rustc_index::IndexVec; +use rustc_middle::middle::deduced_param_attrs::{DeducedParamAttrs, DeducedReadOnlyParam}; +use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor}; +use rustc_middle::mir::*; +use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_session::config::OptLevel; /// A visitor that determines which arguments have been mutated. We can't use the mutability field /// on LocalDecl for this because it has no meaning post-optimization. struct DeduceReadOnly { /// Each bit is indexed by argument number, starting at zero (so 0 corresponds to local decl - /// 1). The bit is true if the argument may have been mutated or false if we know it hasn't + /// 1). The bit is false if the argument may have been mutated or true if we know it hasn't /// been up to the point we're at. - mutable_args: DenseBitSet<usize>, + read_only: IndexVec<usize, DeducedReadOnlyParam>, } impl DeduceReadOnly { /// Returns a new DeduceReadOnly instance. fn new(arg_count: usize) -> Self { - Self { mutable_args: DenseBitSet::new_empty(arg_count) } + Self { read_only: IndexVec::from_elem_n(DeducedReadOnlyParam::empty(), arg_count) } + } + + /// Returns whether the given local is a parameter and its index. + fn as_param(&self, local: Local) -> Option<usize> { + // Locals and parameters are shifted by `RETURN_PLACE`. + let param_index = local.as_usize().checked_sub(1)?; + if param_index < self.read_only.len() { Some(param_index) } else { None } } } impl<'tcx> Visitor<'tcx> for DeduceReadOnly { fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, _location: Location) { // We're only interested in arguments. - if place.local == RETURN_PLACE || place.local.index() > self.mutable_args.domain_size() { - return; - } + let Some(param_index) = self.as_param(place.local) else { return }; - let mark_as_mutable = match context { - PlaceContext::MutatingUse(..) => { - // This is a mutation, so mark it as such. - true + match context { + // Not mutating, so it's fine. + PlaceContext::NonUse(..) => {} + // Dereference is not a mutation. + _ if place.is_indirect_first_projection() => {} + // This is a `Drop`. It could disappear at monomorphization, so mark it specially. + PlaceContext::MutatingUse(MutatingUseContext::Drop) + // Projection changes the place's type, so `needs_drop(local.ty)` is not + // `needs_drop(place.ty)`. + if place.projection.is_empty() => { + self.read_only[param_index] |= DeducedReadOnlyParam::IF_NO_DROP; } - PlaceContext::NonMutatingUse(NonMutatingUseContext::RawBorrow) => { - // Whether mutating though a `&raw const` is allowed is still undecided, so we - // disable any sketchy `readonly` optimizations for now. But we only need to do - // this if the pointer would point into the argument. IOW: for indirect places, - // like `&raw (*local).field`, this surely cannot mutate `local`. - !place.is_indirect() + // This is a mutation, so mark it as such. + PlaceContext::MutatingUse(..) + // Whether mutating though a `&raw const` is allowed is still undecided, so we + // disable any sketchy `readonly` optimizations for now. + | PlaceContext::NonMutatingUse(NonMutatingUseContext::RawBorrow) => { + self.read_only[param_index] |= DeducedReadOnlyParam::MUTATED; } - PlaceContext::NonMutatingUse(..) | PlaceContext::NonUse(..) => { - // Not mutating, so it's fine. - false + // Not mutating if the parameter is `Freeze`. + PlaceContext::NonMutatingUse(NonMutatingUseContext::SharedBorrow) => { + self.read_only[param_index] |= DeducedReadOnlyParam::IF_FREEZE; } - }; - - if mark_as_mutable { - self.mutable_args.insert(place.local.index() - 1); + // Not mutating, so it's fine. + PlaceContext::NonMutatingUse(..) => {} } } @@ -82,16 +97,12 @@ fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location // from. if let TerminatorKind::Call { ref args, .. } = terminator.kind { for arg in args { - if let Operand::Move(place) = arg.node { - let local = place.local; - if place.is_indirect() - || local == RETURN_PLACE - || local.index() > self.mutable_args.domain_size() - { - continue; - } - - self.mutable_args.insert(local.index() - 1); + if let Operand::Move(place) = arg.node + // We're only interested in arguments. + && let Some(param_index) = self.as_param(place.local) + && !place.is_indirect_first_projection() + { + self.read_only[param_index] |= DeducedReadOnlyParam::MUTATED; } } }; @@ -121,6 +132,7 @@ fn type_will_always_be_passed_directly(ty: Ty<'_>) -> bool { /// body of the function instead of just the signature. These can be useful for optimization /// purposes on a best-effort basis. We compute them here and store them into the crate metadata so /// dependent crates can use them. +#[tracing::instrument(level = "trace", skip(tcx), ret)] pub(super) fn deduced_param_attrs<'tcx>( tcx: TyCtxt<'tcx>, def_id: LocalDefId, @@ -160,36 +172,19 @@ pub(super) fn deduced_param_attrs<'tcx>( let body: &Body<'tcx> = tcx.optimized_mir(def_id); let mut deduce_read_only = DeduceReadOnly::new(body.arg_count); deduce_read_only.visit_body(body); + tracing::trace!(?deduce_read_only.read_only); - // Set the `readonly` attribute for every argument that we concluded is immutable and that - // contains no UnsafeCells. - // - // FIXME: This is overly conservative around generic parameters: `is_freeze()` will always - // return false for them. For a description of alternatives that could do a better job here, - // see [1]. - // - // [1]: https://github.com/rust-lang/rust/pull/103172#discussion_r999139997 - let typing_env = body.typing_env(tcx); - let mut deduced_param_attrs = tcx.arena.alloc_from_iter( - body.local_decls.iter().skip(1).take(body.arg_count).enumerate().map( - |(arg_index, local_decl)| DeducedParamAttrs { - read_only: !deduce_read_only.mutable_args.contains(arg_index) - // We must normalize here to reveal opaques and normalize - // their generic parameters, otherwise we'll see exponential - // blow-up in compile times: #113372 - && tcx - .normalize_erasing_regions(typing_env, local_decl.ty) - .is_freeze(tcx, typing_env), - }, - ), + let mut deduced_param_attrs: &[_] = tcx.arena.alloc_from_iter( + deduce_read_only.read_only.into_iter().map(|read_only| DeducedParamAttrs { read_only }), ); // Trailing parameters past the size of the `deduced_param_attrs` array are assumed to have the // default set of attributes, so we don't have to store them explicitly. Pop them off to save a // few bytes in metadata. - while deduced_param_attrs.last() == Some(&DeducedParamAttrs::default()) { - let last_index = deduced_param_attrs.len() - 1; - deduced_param_attrs = &mut deduced_param_attrs[0..last_index]; + while let Some((last, rest)) = deduced_param_attrs.split_last() + && last.is_default() + { + deduced_param_attrs = rest; } deduced_param_attrs
diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index 0d97571..bdf53f4 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs
@@ -1926,13 +1926,8 @@ fn visit_terminator(&mut self, terminator: &mut Terminator<'tcx>, location: Loca self.assign(local, opaque); } } - // Function calls and ASM may invalidate (nested) derefs. We must handle them carefully. - // Currently, only preserving derefs for trivial terminators like SwitchInt and Goto. - let safe_to_preserve_derefs = matches!( - terminator.kind, - TerminatorKind::SwitchInt { .. } | TerminatorKind::Goto { .. } - ); - if !safe_to_preserve_derefs { + // Terminators that can write to memory may invalidate (nested) derefs. + if terminator.kind.can_write_to_memory() { self.invalidate_derefs(); } self.super_terminator(terminator, location);
diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index 38c7d83..dc60888 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs
@@ -245,7 +245,7 @@ fn on_inline_success( fn on_inline_failure(&self, callsite: &CallSite<'tcx>, reason: &'static str) { let tcx = self.tcx(); let InlineAttr::Force { attr_span, reason: justification } = - tcx.codegen_fn_attrs(callsite.callee.def_id()).inline + tcx.codegen_instance_attrs(callsite.callee.def).inline else { bug!("called on item without required inlining"); }; @@ -603,7 +603,8 @@ fn try_inlining<'tcx, I: Inliner<'tcx>>( let tcx = inliner.tcx(); check_mir_is_available(inliner, caller_body, callsite.callee)?; - let callee_attrs = tcx.codegen_fn_attrs(callsite.callee.def_id()); + let callee_attrs = tcx.codegen_instance_attrs(callsite.callee.def); + let callee_attrs = callee_attrs.as_ref(); check_inline::is_inline_valid_on_fn(tcx, callsite.callee.def_id())?; check_codegen_attributes(inliner, callsite, callee_attrs)?; inliner.check_codegen_attributes_extra(callee_attrs)?;
diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index 3ffd263..4625b20 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs
@@ -189,6 +189,7 @@ pub mod simplify : Final }; mod simplify_branches : SimplifyConstCondition { + AfterInstSimplify, AfterConstProp, Final }; @@ -708,6 +709,15 @@ fn o1<T>(x: T) -> WithMinOptLevel<T> { // optimizations. This invalidates CFG caches, so avoid putting between // `ReferencePropagation` and `GVN` which both use the dominator tree. &instsimplify::InstSimplify::AfterSimplifyCfg, + // After `InstSimplify-after-simplifycfg` with `-Zub_checks=false`, simplify + // ``` + // _13 = const false; + // assume(copy _13); + // Call(precondition_check); + // ``` + // to unreachable to eliminate the call to help later passes. + // This invalidates CFG caches also. + &o1(simplify_branches::SimplifyConstCondition::AfterInstSimplify), &ref_prop::ReferencePropagation, &sroa::ScalarReplacementOfAggregates, &simplify::SimplifyLocals::BeforeConstProp,
diff --git a/compiler/rustc_mir_transform/src/patch.rs b/compiler/rustc_mir_transform/src/patch.rs index 2c535d0..015bae5 100644 --- a/compiler/rustc_mir_transform/src/patch.rs +++ b/compiler/rustc_mir_transform/src/patch.rs
@@ -24,6 +24,8 @@ pub(crate) struct MirPatch<'tcx> { // Cached block for UnwindTerminate (with reason) terminate_block: Option<(BasicBlock, UnwindTerminateReason)>, body_span: Span, + /// The number of locals at the start of the transformation. New locals + /// get appended at the end. next_local: usize, /// The number of blocks at the start of the transformation. New blocks /// get appended at the end. @@ -176,8 +178,7 @@ pub(crate) fn new_local_with_info( span: Span, local_info: LocalInfo<'tcx>, ) -> Local { - let index = self.next_local; - self.next_local += 1; + let index = self.next_local + self.new_locals.len(); let mut new_decl = LocalDecl::new(ty, span); **new_decl.local_info.as_mut().unwrap_crate_local() = local_info; self.new_locals.push(new_decl); @@ -186,8 +187,7 @@ pub(crate) fn new_local_with_info( /// Queues the addition of a new temporary. pub(crate) fn new_temp(&mut self, ty: Ty<'tcx>, span: Span) -> Local { - let index = self.next_local; - self.next_local += 1; + let index = self.next_local + self.new_locals.len(); self.new_locals.push(LocalDecl::new(ty, span)); Local::new(index) } @@ -195,8 +195,8 @@ pub(crate) fn new_temp(&mut self, ty: Ty<'tcx>, span: Span) -> Local { /// Returns the type of a local that's newly-added in the patch. pub(crate) fn local_ty(&self, local: Local) -> Ty<'tcx> { let local = local.as_usize(); - assert!(local < self.next_local); - let new_local_idx = self.new_locals.len() - (self.next_local - local); + assert!(local < self.next_local + self.new_locals.len()); + let new_local_idx = local - self.next_local; self.new_locals[new_local_idx].ty }
diff --git a/compiler/rustc_mir_transform/src/simplify_branches.rs b/compiler/rustc_mir_transform/src/simplify_branches.rs index ed94a05..ba2286f 100644 --- a/compiler/rustc_mir_transform/src/simplify_branches.rs +++ b/compiler/rustc_mir_transform/src/simplify_branches.rs
@@ -5,6 +5,7 @@ use crate::patch::MirPatch; pub(super) enum SimplifyConstCondition { + AfterInstSimplify, AfterConstProp, Final, } @@ -13,6 +14,9 @@ pub(super) enum SimplifyConstCondition { impl<'tcx> crate::MirPass<'tcx> for SimplifyConstCondition { fn name(&self) -> &'static str { match self { + SimplifyConstCondition::AfterInstSimplify => { + "SimplifyConstCondition-after-inst-simplify" + } SimplifyConstCondition::AfterConstProp => "SimplifyConstCondition-after-const-prop", SimplifyConstCondition::Final => "SimplifyConstCondition-final", } @@ -23,12 +27,33 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let typing_env = body.typing_env(tcx); let mut patch = MirPatch::new(body); + fn try_get_const<'tcx, 'a>( + operand: &'a Operand<'tcx>, + has_place_const: Option<(Place<'tcx>, &'a ConstOperand<'tcx>)>, + ) -> Option<&'a ConstOperand<'tcx>> { + match operand { + Operand::Constant(const_operand) => Some(const_operand), + // `has_place_const` must be the LHS of the previous statement. + // Soundness: There is nothing can modify the place, as there are no statements between the two statements. + Operand::Copy(place) | Operand::Move(place) + if let Some((place_const, const_operand)) = has_place_const + && place_const == *place => + { + Some(const_operand) + } + Operand::Copy(_) | Operand::Move(_) => None, + } + } + 'blocks: for (bb, block) in body.basic_blocks.iter_enumerated() { + let mut pre_place_const: Option<(Place<'tcx>, &ConstOperand<'tcx>)> = None; + for (statement_index, stmt) in block.statements.iter().enumerate() { + let has_place_const = pre_place_const.take(); // Simplify `assume` of a known value: either a NOP or unreachable. if let StatementKind::Intrinsic(box ref intrinsic) = stmt.kind && let NonDivergingIntrinsic::Assume(discr) = intrinsic - && let Operand::Constant(c) = discr + && let Some(c) = try_get_const(discr, has_place_const) && let Some(constant) = c.const_.try_eval_bool(tcx, typing_env) { if constant { @@ -37,28 +62,29 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { patch.patch_terminator(bb, TerminatorKind::Unreachable); continue 'blocks; } + } else if let StatementKind::Assign(box (lhs, ref rvalue)) = stmt.kind + && let Rvalue::Use(Operand::Constant(c)) = rvalue + { + pre_place_const = Some((lhs, c)); } } let terminator = block.terminator(); let terminator = match terminator.kind { - TerminatorKind::SwitchInt { - discr: Operand::Constant(ref c), ref targets, .. - } => { - let constant = c.const_.try_eval_bits(tcx, typing_env); - if let Some(constant) = constant { - let target = targets.target_for_value(constant); - TerminatorKind::Goto { target } - } else { - continue; - } + TerminatorKind::SwitchInt { ref discr, ref targets, .. } + if let Some(c) = try_get_const(discr, pre_place_const.take()) + && let Some(constant) = c.const_.try_eval_bits(tcx, typing_env) => + { + let target = targets.target_for_value(constant); + TerminatorKind::Goto { target } } - TerminatorKind::Assert { - target, cond: Operand::Constant(ref c), expected, .. - } => match c.const_.try_eval_bool(tcx, typing_env) { - Some(v) if v == expected => TerminatorKind::Goto { target }, - _ => continue, - }, + TerminatorKind::Assert { target, ref cond, expected, .. } + if let Some(c) = try_get_const(&cond, pre_place_const.take()) + && let Some(constant) = c.const_.try_eval_bool(tcx, typing_env) + && constant == expected => + { + TerminatorKind::Goto { target } + } _ => continue, }; patch.patch_terminator(bb, terminator);
diff --git a/compiler/rustc_mir_transform/src/validate.rs b/compiler/rustc_mir_transform/src/validate.rs index 2945298..634c01e 100644 --- a/compiler/rustc_mir_transform/src/validate.rs +++ b/compiler/rustc_mir_transform/src/validate.rs
@@ -655,20 +655,6 @@ fn visit_projection_elem( location: Location, ) { match elem { - ProjectionElem::OpaqueCast(ty) - if self.body.phase >= MirPhase::Runtime(RuntimePhase::Initial) => - { - self.fail( - location, - format!("explicit opaque type cast to `{ty}` after `PostAnalysisNormalize`"), - ) - } - ProjectionElem::Index(index) => { - let index_ty = self.body.local_decls[index].ty; - if index_ty != self.tcx.types.usize { - self.fail(location, format!("bad index ({index_ty} != usize)")) - } - } ProjectionElem::Deref if self.body.phase >= MirPhase::Runtime(RuntimePhase::PostCleanup) => { @@ -815,6 +801,78 @@ fn visit_projection_elem( } } } + ProjectionElem::Index(index) => { + let indexed_ty = place_ref.ty(&self.body.local_decls, self.tcx).ty; + match indexed_ty.kind() { + ty::Array(_, _) | ty::Slice(_) => {} + _ => self.fail(location, format!("{indexed_ty:?} cannot be indexed")), + } + + let index_ty = self.body.local_decls[index].ty; + if index_ty != self.tcx.types.usize { + self.fail(location, format!("bad index ({index_ty} != usize)")) + } + } + ProjectionElem::ConstantIndex { offset, min_length, from_end } => { + let indexed_ty = place_ref.ty(&self.body.local_decls, self.tcx).ty; + match indexed_ty.kind() { + ty::Array(_, _) => { + if from_end { + self.fail(location, "arrays should not be indexed from end"); + } + } + ty::Slice(_) => {} + _ => self.fail(location, format!("{indexed_ty:?} cannot be indexed")), + } + + if from_end { + if offset > min_length { + self.fail( + location, + format!( + "constant index with offset -{offset} out of bounds of min length {min_length}" + ), + ); + } + } else { + if offset >= min_length { + self.fail( + location, + format!( + "constant index with offset {offset} out of bounds of min length {min_length}" + ), + ); + } + } + } + ProjectionElem::Subslice { from, to, from_end } => { + let indexed_ty = place_ref.ty(&self.body.local_decls, self.tcx).ty; + match indexed_ty.kind() { + ty::Array(_, _) => { + if from_end { + self.fail(location, "arrays should not be subsliced from end"); + } + } + ty::Slice(_) => { + if !from_end { + self.fail(location, "slices should be subsliced from end"); + } + } + _ => self.fail(location, format!("{indexed_ty:?} cannot be indexed")), + } + + if !from_end && from > to { + self.fail(location, "backwards subslice {from}..{to}"); + } + } + ProjectionElem::OpaqueCast(ty) + if self.body.phase >= MirPhase::Runtime(RuntimePhase::Initial) => + { + self.fail( + location, + format!("explicit opaque type cast to `{ty}` after `PostAnalysisNormalize`"), + ) + } ProjectionElem::UnwrapUnsafeBinder(unwrapped_ty) => { let binder_ty = place_ref.ty(&self.body.local_decls, self.tcx); let ty::UnsafeBinder(binder_ty) = *binder_ty.ty.kind() else { @@ -921,6 +979,25 @@ fn visit_place(&mut self, place: &Place<'tcx>, cntxt: PlaceContext, location: Lo } } + if self.body.phase < MirPhase::Runtime(RuntimePhase::Initial) + && let Some(i) = place + .projection + .iter() + .position(|elem| matches!(elem, ProjectionElem::Subslice { .. })) + && let Some(tail) = place.projection.get(i + 1..) + && tail.iter().any(|elem| { + matches!( + elem, + ProjectionElem::ConstantIndex { .. } | ProjectionElem::Subslice { .. } + ) + }) + { + self.fail( + location, + format!("place {place:?} has `ConstantIndex` or `Subslice` after `Subslice`"), + ); + } + self.super_place(place, cntxt, location); }
diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 2169ed3..93f647c 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs
@@ -1568,7 +1568,7 @@ fn process_item(&mut self, id: hir::ItemId) { } } } - DefKind::Impl { .. } => { + DefKind::Impl { of_trait: true } => { if self.strategy == MonoItemCollectionStrategy::Eager { create_mono_items_for_default_impls(self.tcx, id, self.output); } @@ -1715,9 +1715,7 @@ fn create_mono_items_for_default_impls<'tcx>( item: hir::ItemId, output: &mut MonoItems<'tcx>, ) { - let Some(impl_) = tcx.impl_trait_header(item.owner_id) else { - return; - }; + let impl_ = tcx.impl_trait_header(item.owner_id); if matches!(impl_.polarity, ty::ImplPolarity::Negative) { return;
diff --git a/compiler/rustc_monomorphize/src/partitioning.rs b/compiler/rustc_monomorphize/src/partitioning.rs index d784d35..b87ab84 100644 --- a/compiler/rustc_monomorphize/src/partitioning.rs +++ b/compiler/rustc_monomorphize/src/partitioning.rs
@@ -649,7 +649,7 @@ fn characteristic_def_id_of_mono_item<'tcx>( if let Some((impl_def_id, DefKind::Impl { of_trait })) = assoc_parent { if of_trait && tcx.sess.opts.incremental.is_some() - && tcx.is_lang_item(tcx.trait_id_of_impl(impl_def_id).unwrap(), LangItem::Drop) + && tcx.is_lang_item(tcx.impl_trait_id(impl_def_id), LangItem::Drop) { // Put `Drop::drop` into the same cgu as `drop_in_place` // since `drop_in_place` is the only thing that can
diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl index b1894ab..52a35c9 100644 --- a/compiler/rustc_parse/messages.ftl +++ b/compiler/rustc_parse/messages.ftl
@@ -122,7 +122,6 @@ parse_catch_after_try = keyword `catch` cannot follow a `try` block .help = try using `match` on the result of the `try` block instead -parse_cfg_attr_bad_delim = wrong `cfg_attr` delimiters parse_colon_as_semi = statements are terminated with a semicolon .suggestion = use a semicolon instead @@ -573,10 +572,6 @@ parse_macro_rules_visibility = can't qualify macro_rules invocation with `{$vis}` .suggestion = try exporting the macro -parse_malformed_cfg_attr = malformed `cfg_attr` attribute input - .suggestion = missing condition and attribute - .note = for more information, visit <https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg_attr-attribute> - parse_malformed_loop_label = malformed loop label .suggestion = use the correct loop label format @@ -610,8 +605,6 @@ ambiguous `+` in a type .suggestion = use parentheses to disambiguate -parse_meta_bad_delim_suggestion = the delimiters should be `(` and `)` - parse_mismatched_closing_delimiter = mismatched closing delimiter: `{$delimiter}` .label_unmatched = mismatched closing delimiter .label_opening_candidate = closing delimiter possibly meant for this
diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index 1abeee6..6d536aa 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs
@@ -3352,34 +3352,6 @@ pub(crate) struct KwBadCase<'a> { } #[derive(Diagnostic)] -#[diag(parse_cfg_attr_bad_delim)] -pub(crate) struct CfgAttrBadDelim { - #[primary_span] - pub span: Span, - #[subdiagnostic] - pub sugg: MetaBadDelimSugg, -} - -#[derive(Subdiagnostic)] -#[multipart_suggestion(parse_meta_bad_delim_suggestion, applicability = "machine-applicable")] -pub(crate) struct MetaBadDelimSugg { - #[suggestion_part(code = "(")] - pub open: Span, - #[suggestion_part(code = ")")] - pub close: Span, -} - -#[derive(Diagnostic)] -#[diag(parse_malformed_cfg_attr)] -#[note] -pub(crate) struct MalformedCfgAttr { - #[primary_span] - #[suggestion(style = "verbose", code = "{sugg}")] - pub span: Span, - pub sugg: &'static str, -} - -#[derive(Diagnostic)] #[diag(parse_unknown_builtin_construct)] pub(crate) struct UnknownBuiltinConstruct { #[primary_span]
diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs index c26c7b9..edec44c 100644 --- a/compiler/rustc_parse/src/lib.rs +++ b/compiler/rustc_parse/src/lib.rs
@@ -18,8 +18,8 @@ use std::sync::Arc; use rustc_ast as ast; -use rustc_ast::tokenstream::{DelimSpan, TokenStream}; -use rustc_ast::{AttrItem, Attribute, MetaItemInner, token}; +use rustc_ast::token; +use rustc_ast::tokenstream::TokenStream; use rustc_ast_pretty::pprust; use rustc_errors::{Diag, EmissionGuarantee, FatalError, PResult, pluralize}; use rustc_session::parse::ParseSess; @@ -32,7 +32,6 @@ #[macro_use] pub mod parser; use parser::Parser; -use rustc_ast::token::Delimiter; use crate::lexer::StripTokens; @@ -230,45 +229,3 @@ pub fn fake_token_stream_for_crate(psess: &ParseSess, krate: &ast::Crate) -> Tok Some(krate.spans.inner_span), )) } - -pub fn parse_cfg_attr( - cfg_attr: &Attribute, - psess: &ParseSess, -) -> Option<(MetaItemInner, Vec<(AttrItem, Span)>)> { - const CFG_ATTR_GRAMMAR_HELP: &str = "#[cfg_attr(condition, attribute, other_attribute, ...)]"; - const CFG_ATTR_NOTE_REF: &str = "for more information, visit \ - <https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg_attr-attribute>"; - - match cfg_attr.get_normal_item().args { - ast::AttrArgs::Delimited(ast::DelimArgs { dspan, delim, ref tokens }) - if !tokens.is_empty() => - { - check_cfg_attr_bad_delim(psess, dspan, delim); - match parse_in(psess, tokens.clone(), "`cfg_attr` input", |p| p.parse_cfg_attr()) { - Ok(r) => return Some(r), - Err(e) => { - e.with_help(format!("the valid syntax is `{CFG_ATTR_GRAMMAR_HELP}`")) - .with_note(CFG_ATTR_NOTE_REF) - .emit(); - } - } - } - _ => { - psess.dcx().emit_err(errors::MalformedCfgAttr { - span: cfg_attr.span, - sugg: CFG_ATTR_GRAMMAR_HELP, - }); - } - } - None -} - -fn check_cfg_attr_bad_delim(psess: &ParseSess, span: DelimSpan, delim: Delimiter) { - if let Delimiter::Parenthesis = delim { - return; - } - psess.dcx().emit_err(errors::CfgAttrBadDelim { - span: span.entire(), - sugg: errors::MetaBadDelimSugg { open: span.open, close: span.close }, - }); -}
diff --git a/compiler/rustc_parse/src/parser/attr.rs b/compiler/rustc_parse/src/parser/attr.rs index acd3381..5725f4c 100644 --- a/compiler/rustc_parse/src/parser/attr.rs +++ b/compiler/rustc_parse/src/parser/attr.rs
@@ -377,27 +377,6 @@ pub(crate) fn parse_unsuffixed_meta_item_lit(&mut self) -> PResult<'a, ast::Meta Ok(lit) } - /// Parses `cfg_attr(pred, attr_item_list)` where `attr_item_list` is comma-delimited. - pub fn parse_cfg_attr( - &mut self, - ) -> PResult<'a, (ast::MetaItemInner, Vec<(ast::AttrItem, Span)>)> { - let cfg_predicate = self.parse_meta_item_inner()?; - self.expect(exp!(Comma))?; - - // Presumably, the majority of the time there will only be one attr. - let mut expanded_attrs = Vec::with_capacity(1); - while self.token != token::Eof { - let lo = self.token.span; - let item = self.parse_attr_item(ForceCollect::Yes)?; - expanded_attrs.push((item, lo.to(self.prev_token.span))); - if !self.eat(exp!(Comma)) { - break; - } - } - - Ok((cfg_predicate, expanded_attrs)) - } - /// Matches `COMMASEP(meta_item_inner)`. pub fn parse_meta_seq_top(&mut self) -> PResult<'a, ThinVec<ast::MetaItemInner>> { // Presumably, the majority of the time there will only be one attr.
diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index aa03d59..6f0e3b8 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs
@@ -2664,7 +2664,10 @@ pub(super) fn check_fn_front_matter(&mut self, check_pub: bool, case: Case) -> b // Rule out `unsafe extern {`. && !self.is_unsafe_foreign_mod() // Rule out `async gen {` and `async gen move {` - && !self.is_async_gen_block()) + && !self.is_async_gen_block() + // Rule out `const unsafe auto` and `const unsafe trait`. + && !self.is_keyword_ahead(2, &[kw::Auto, kw::Trait]) + ) }) // `extern ABI fn` || self.check_keyword_case(exp!(Extern), case)
diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index 3c2c968..877b5ad 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs
@@ -4,11 +4,12 @@ // is dead. use std::mem; +use std::ops::ControlFlow; use hir::def_id::{LocalDefIdMap, LocalDefIdSet}; use rustc_abi::FieldIdx; use rustc_data_structures::fx::FxIndexSet; -use rustc_errors::MultiSpan; +use rustc_errors::{ErrorGuaranteed, MultiSpan}; use rustc_hir::def::{CtorOf, DefKind, Res}; use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId}; use rustc_hir::intravisit::{self, Visitor}; @@ -178,12 +179,12 @@ fn handle_assign(&mut self, expr: &'tcx hir::Expr<'tcx>) { .iter() .any(|adj| matches!(adj.kind, ty::adjustment::Adjust::Deref(_))) { - self.visit_expr(expr); + let _ = self.visit_expr(expr); } else if let hir::ExprKind::Field(base, ..) = expr.kind { // Ignore write to field self.handle_assign(base); } else { - self.visit_expr(expr); + let _ = self.visit_expr(expr); } } @@ -318,7 +319,7 @@ fn handle_offset_of(&mut self, expr: &'tcx hir::Expr<'tcx>) { } } - fn mark_live_symbols(&mut self) { + fn mark_live_symbols(&mut self) -> <MarkSymbolVisitor<'tcx> as Visitor<'tcx>>::Result { while let Some(work) = self.worklist.pop() { let (mut id, comes_from_allow_expect) = work; @@ -366,8 +367,10 @@ fn mark_live_symbols(&mut self) { continue; } - self.visit_node(self.tcx.hir_node_by_def_id(id)); + self.visit_node(self.tcx.hir_node_by_def_id(id))?; } + + ControlFlow::Continue(()) } /// Automatically generated items marked with `rustc_trivial_field_reads` @@ -377,7 +380,7 @@ fn should_ignore_impl_item(&mut self, impl_item: &hir::ImplItem<'_>) -> bool { if let hir::ImplItemImplKind::Trait { .. } = impl_item.impl_kind && let impl_of = self.tcx.parent(impl_item.owner_id.to_def_id()) && self.tcx.is_automatically_derived(impl_of) - && let trait_ref = self.tcx.impl_trait_ref(impl_of).unwrap().instantiate_identity() + && let trait_ref = self.tcx.impl_trait_ref(impl_of).instantiate_identity() && self.tcx.has_attr(trait_ref.def_id, sym::rustc_trivial_field_reads) { if let ty::Adt(adt_def, _) = trait_ref.self_ty().kind() @@ -391,11 +394,14 @@ fn should_ignore_impl_item(&mut self, impl_item: &hir::ImplItem<'_>) -> bool { false } - fn visit_node(&mut self, node: Node<'tcx>) { + fn visit_node( + &mut self, + node: Node<'tcx>, + ) -> <MarkSymbolVisitor<'tcx> as Visitor<'tcx>>::Result { if let Node::ImplItem(impl_item) = node && self.should_ignore_impl_item(impl_item) { - return; + return ControlFlow::Continue(()); } let unconditionally_treated_fields_as_live = @@ -403,7 +409,7 @@ fn visit_node(&mut self, node: Node<'tcx>) { let had_repr_simd = self.repr_has_repr_simd; self.repr_unconditionally_treats_fields_as_live = false; self.repr_has_repr_simd = false; - match node { + let walk_result = match node { Node::Item(item) => match item.kind { hir::ItemKind::Struct(..) | hir::ItemKind::Union(..) => { let def = self.tcx.adt_def(item.owner_id); @@ -413,7 +419,7 @@ fn visit_node(&mut self, node: Node<'tcx>) { intravisit::walk_item(self, item) } - hir::ItemKind::ForeignMod { .. } => {} + hir::ItemKind::ForeignMod { .. } => ControlFlow::Continue(()), hir::ItemKind::Trait(.., trait_item_refs) => { // mark assoc ty live if the trait is live for trait_item in trait_item_refs { @@ -431,7 +437,7 @@ fn visit_node(&mut self, node: Node<'tcx>) { if let Some(trait_id) = self.tcx.trait_of_assoc(trait_item_id) { self.check_def_id(trait_id); } - intravisit::walk_trait_item(self, trait_item); + intravisit::walk_trait_item(self, trait_item) } Node::ImplItem(impl_item) => { let item = self.tcx.local_parent(impl_item.owner_id.def_id); @@ -452,16 +458,16 @@ fn visit_node(&mut self, node: Node<'tcx>) { _ => {} } } - intravisit::walk_impl_item(self, impl_item); + intravisit::walk_impl_item(self, impl_item) } - Node::ForeignItem(foreign_item) => { - intravisit::walk_foreign_item(self, foreign_item); - } + Node::ForeignItem(foreign_item) => intravisit::walk_foreign_item(self, foreign_item), Node::OpaqueTy(opaq) => intravisit::walk_opaque_ty(self, opaq), - _ => {} - } + _ => ControlFlow::Continue(()), + }; self.repr_has_repr_simd = had_repr_simd; self.repr_unconditionally_treats_fields_as_live = unconditionally_treated_fields_as_live; + + walk_result } fn mark_as_used_if_union(&mut self, adt: ty::AdtDef<'tcx>, fields: &[hir::ExprField<'_>]) { @@ -486,12 +492,9 @@ fn check_impl_or_impl_item_live(&mut self, local_def_id: LocalDefId) -> bool { (self.tcx.local_parent(local_def_id), trait_item_id) } // impl items are live if the corresponding traits are live - DefKind::Impl { of_trait: true } => ( - local_def_id, - self.tcx - .impl_trait_ref(local_def_id) - .and_then(|trait_ref| trait_ref.skip_binder().def_id.as_local()), - ), + DefKind::Impl { of_trait: true } => { + (local_def_id, self.tcx.impl_trait_id(local_def_id).as_local()) + } _ => bug!(), }; @@ -514,15 +517,25 @@ fn check_impl_or_impl_item_live(&mut self, local_def_id: LocalDefId) -> bool { } impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> { - fn visit_nested_body(&mut self, body: hir::BodyId) { - let old_maybe_typeck_results = - self.maybe_typeck_results.replace(self.tcx.typeck_body(body)); + type Result = ControlFlow<ErrorGuaranteed>; + + fn visit_nested_body(&mut self, body: hir::BodyId) -> Self::Result { + let typeck_results = self.tcx.typeck_body(body); + + // The result shouldn't be tainted, otherwise it will cause ICE. + if let Some(guar) = typeck_results.tainted_by_errors { + return ControlFlow::Break(guar); + } + + let old_maybe_typeck_results = self.maybe_typeck_results.replace(typeck_results); let body = self.tcx.hir_body(body); - self.visit_body(body); + let result = self.visit_body(body); self.maybe_typeck_results = old_maybe_typeck_results; + + result } - fn visit_variant_data(&mut self, def: &'tcx hir::VariantData<'tcx>) { + fn visit_variant_data(&mut self, def: &'tcx hir::VariantData<'tcx>) -> Self::Result { let tcx = self.tcx; let unconditionally_treat_fields_as_live = self.repr_unconditionally_treats_fields_as_live; let has_repr_simd = self.repr_has_repr_simd; @@ -539,10 +552,10 @@ fn visit_variant_data(&mut self, def: &'tcx hir::VariantData<'tcx>) { }); self.live_symbols.extend(live_fields); - intravisit::walk_struct_def(self, def); + intravisit::walk_struct_def(self, def) } - fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) { + fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) -> Self::Result { match expr.kind { hir::ExprKind::Path(ref qpath @ QPath::TypeRelative(..)) => { let res = self.typeck_results().qpath_res(qpath, expr.hir_id); @@ -578,20 +591,22 @@ fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) { _ => (), } - intravisit::walk_expr(self, expr); + intravisit::walk_expr(self, expr) } - fn visit_arm(&mut self, arm: &'tcx hir::Arm<'tcx>) { + fn visit_arm(&mut self, arm: &'tcx hir::Arm<'tcx>) -> Self::Result { // Inside the body, ignore constructions of variants // necessary for the pattern to match. Those construction sites // can't be reached unless the variant is constructed elsewhere. let len = self.ignore_variant_stack.len(); self.ignore_variant_stack.extend(arm.pat.necessary_variants()); - intravisit::walk_arm(self, arm); + let result = intravisit::walk_arm(self, arm); self.ignore_variant_stack.truncate(len); + + result } - fn visit_pat(&mut self, pat: &'tcx hir::Pat<'tcx>) { + fn visit_pat(&mut self, pat: &'tcx hir::Pat<'tcx>) -> Self::Result { self.in_pat = true; match pat.kind { PatKind::Struct(ref path, fields, _) => { @@ -605,11 +620,13 @@ fn visit_pat(&mut self, pat: &'tcx hir::Pat<'tcx>) { _ => (), } - intravisit::walk_pat(self, pat); + let result = intravisit::walk_pat(self, pat); self.in_pat = false; + + result } - fn visit_pat_expr(&mut self, expr: &'tcx rustc_hir::PatExpr<'tcx>) { + fn visit_pat_expr(&mut self, expr: &'tcx rustc_hir::PatExpr<'tcx>) -> Self::Result { match &expr.kind { rustc_hir::PatExprKind::Path(qpath) => { // mark the type of variant live when meeting E::V in expr @@ -622,37 +639,41 @@ fn visit_pat_expr(&mut self, expr: &'tcx rustc_hir::PatExpr<'tcx>) { } _ => {} } - intravisit::walk_pat_expr(self, expr); + intravisit::walk_pat_expr(self, expr) } - fn visit_path(&mut self, path: &hir::Path<'tcx>, _: hir::HirId) { + fn visit_path(&mut self, path: &hir::Path<'tcx>, _: hir::HirId) -> Self::Result { self.handle_res(path.res); - intravisit::walk_path(self, path); + intravisit::walk_path(self, path) } - fn visit_anon_const(&mut self, c: &'tcx hir::AnonConst) { + fn visit_anon_const(&mut self, c: &'tcx hir::AnonConst) -> Self::Result { // When inline const blocks are used in pattern position, paths // referenced by it should be considered as used. let in_pat = mem::replace(&mut self.in_pat, false); self.live_symbols.insert(c.def_id); - intravisit::walk_anon_const(self, c); + let result = intravisit::walk_anon_const(self, c); self.in_pat = in_pat; + + result } - fn visit_inline_const(&mut self, c: &'tcx hir::ConstBlock) { + fn visit_inline_const(&mut self, c: &'tcx hir::ConstBlock) -> Self::Result { // When inline const blocks are used in pattern position, paths // referenced by it should be considered as used. let in_pat = mem::replace(&mut self.in_pat, false); self.live_symbols.insert(c.def_id); - intravisit::walk_inline_const(self, c); + let result = intravisit::walk_inline_const(self, c); self.in_pat = in_pat; + + result } - fn visit_trait_ref(&mut self, t: &'tcx hir::TraitRef<'tcx>) { + fn visit_trait_ref(&mut self, t: &'tcx hir::TraitRef<'tcx>) -> Self::Result { if let Some(trait_def_id) = t.path.res.opt_def_id() && let Some(segment) = t.path.segments.last() && let Some(args) = segment.args @@ -674,7 +695,7 @@ fn visit_trait_ref(&mut self, t: &'tcx hir::TraitRef<'tcx>) { } } - intravisit::walk_trait_ref(self, t); + intravisit::walk_trait_ref(self, t) } } @@ -821,7 +842,7 @@ fn create_and_seed_worklist( fn live_symbols_and_ignored_derived_traits( tcx: TyCtxt<'_>, (): (), -) -> (LocalDefIdSet, LocalDefIdMap<FxIndexSet<DefId>>) { +) -> Result<(LocalDefIdSet, LocalDefIdMap<FxIndexSet<DefId>>), ErrorGuaranteed> { let (worklist, mut unsolved_items) = create_and_seed_worklist(tcx); let mut symbol_visitor = MarkSymbolVisitor { worklist, @@ -835,7 +856,9 @@ fn live_symbols_and_ignored_derived_traits( ignore_variant_stack: vec![], ignored_derived_traits: Default::default(), }; - symbol_visitor.mark_live_symbols(); + if let ControlFlow::Break(guar) = symbol_visitor.mark_live_symbols() { + return Err(guar); + } // We have marked the primary seeds as live. We now need to process unsolved items from traits // and trait impls: add them to the work list if the trait or the implemented type is live. @@ -849,14 +872,16 @@ fn live_symbols_and_ignored_derived_traits( symbol_visitor .worklist .extend(items_to_check.drain(..).map(|id| (id, ComesFromAllowExpect::No))); - symbol_visitor.mark_live_symbols(); + if let ControlFlow::Break(guar) = symbol_visitor.mark_live_symbols() { + return Err(guar); + } items_to_check.extend(unsolved_items.extract_if(.., |&mut local_def_id| { symbol_visitor.check_impl_or_impl_item_live(local_def_id) })); } - (symbol_visitor.live_symbols, symbol_visitor.ignored_derived_traits) + Ok((symbol_visitor.live_symbols, symbol_visitor.ignored_derived_traits)) } struct DeadItem { @@ -1136,7 +1161,12 @@ fn is_live_code(&self, def_id: LocalDefId) -> bool { } fn check_mod_deathness(tcx: TyCtxt<'_>, module: LocalModDefId) { - let (live_symbols, ignored_derived_traits) = tcx.live_symbols_and_ignored_derived_traits(()); + let Ok((live_symbols, ignored_derived_traits)) = + tcx.live_symbols_and_ignored_derived_traits(()).as_ref() + else { + return; + }; + let mut visitor = DeadVisitor { tcx, live_symbols, ignored_derived_traits }; let module_items = tcx.hir_module_items(module);
diff --git a/compiler/rustc_passes/src/reachable.rs b/compiler/rustc_passes/src/reachable.rs index d1a703f..74f6892 100644 --- a/compiler/rustc_passes/src/reachable.rs +++ b/compiler/rustc_passes/src/reachable.rs
@@ -404,9 +404,7 @@ fn check_item<'tcx>( let items = tcx.associated_item_def_ids(id.owner_id); worklist.extend(items.iter().map(|ii_ref| ii_ref.expect_local())); - let Some(trait_def_id) = tcx.trait_id_of_impl(id.owner_id.to_def_id()) else { - unreachable!(); - }; + let trait_def_id = tcx.impl_trait_id(id.owner_id.to_def_id()); if !trait_def_id.is_local() { return;
diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index c9dbb20..85646b5 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs
@@ -344,13 +344,14 @@ fn new_min<const SHALLOW: bool>( // associated types for which we can't determine visibility precisely. fn of_impl<const SHALLOW: bool>( def_id: LocalDefId, + of_trait: bool, tcx: TyCtxt<'_>, effective_visibilities: &EffectiveVisibilities, ) -> Self { let mut find = FindMin::<_, SHALLOW> { tcx, effective_visibilities, min: Self::MAX }; find.visit(tcx.type_of(def_id).instantiate_identity()); - if let Some(trait_ref) = tcx.impl_trait_ref(def_id) { - find.visit_trait(trait_ref.instantiate_identity()); + if of_trait { + find.visit_trait(tcx.impl_trait_ref(def_id).instantiate_identity()); } find.min } @@ -699,13 +700,20 @@ fn check_def_id(&mut self, owner_id: OwnerId) { // its trait if it exists (which require reaching the `DefId`s in them). let item_ev = EffectiveVisibility::of_impl::<true>( owner_id.def_id, + of_trait, self.tcx, &self.effective_visibilities, ); self.update_eff_vis(owner_id.def_id, item_ev, None, Level::Direct); - self.reach(owner_id.def_id, item_ev).generics().predicates().ty().trait_ref(); + { + let mut reach = self.reach(owner_id.def_id, item_ev); + reach.generics().predicates().ty(); + if of_trait { + reach.trait_ref(); + } + } for assoc_item in self.tcx.associated_items(owner_id).in_definition_order() { if assoc_item.is_impl_trait_in_trait() { @@ -820,9 +828,7 @@ fn ty(&mut self) -> &mut Self { } fn trait_ref(&mut self) -> &mut Self { - if let Some(trait_ref) = self.ev.tcx.impl_trait_ref(self.item_def_id) { - self.visit_trait(trait_ref.instantiate_identity()); - } + self.visit_trait(self.ev.tcx.impl_trait_ref(self.item_def_id).instantiate_identity()); self } } @@ -1395,9 +1401,7 @@ fn ty(&mut self) -> &mut Self { fn trait_ref(&mut self) -> &mut Self { self.in_primary_interface = true; - if let Some(trait_ref) = self.tcx.impl_trait_ref(self.item_def_id) { - let _ = self.visit_trait(trait_ref.instantiate_identity()); - } + let _ = self.visit_trait(self.tcx.impl_trait_ref(self.item_def_id).instantiate_identity()); self } @@ -1666,7 +1670,8 @@ fn check_item(&self, id: ItemId) { // A trait impl is public when both its type and its trait are public // Subitems of trait impls have inherited publicity. DefKind::Impl { of_trait } => { - let impl_vis = ty::Visibility::of_impl::<false>(def_id, tcx, &Default::default()); + let impl_vis = + ty::Visibility::of_impl::<false>(def_id, of_trait, tcx, &Default::default()); // We are using the non-shallow version here, unlike when building the // effective visisibilities table to avoid large number of false positives. @@ -1679,8 +1684,12 @@ fn check_item(&self, id: ItemId) { // lints shouldn't be emitted even if `from` effective visibility // is larger than `Priv` nominal visibility and if `Priv` can leak // in some scenarios due to type inference. - let impl_ev = - EffectiveVisibility::of_impl::<false>(def_id, tcx, self.effective_visibilities); + let impl_ev = EffectiveVisibility::of_impl::<false>( + def_id, + of_trait, + tcx, + self.effective_visibilities, + ); let mut check = self.check(def_id, impl_vis, Some(impl_ev)); @@ -1694,7 +1703,10 @@ fn check_item(&self, id: ItemId) { // normalization they produce very ridiculous false positives. // FIXME: Remove this when full normalization is implemented. check.skip_assoc_tys = true; - check.ty().trait_ref(); + check.ty(); + if of_trait { + check.trait_ref(); + } for assoc_item in tcx.associated_items(id.owner_id).in_definition_order() { if assoc_item.is_impl_trait_in_trait() { @@ -1763,7 +1775,7 @@ fn check_mod_privacy(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) { } if let DefKind::Impl { of_trait: true } = tcx.def_kind(def_id) { - let trait_ref = tcx.impl_trait_ref(def_id).unwrap(); + let trait_ref = tcx.impl_trait_ref(def_id); let trait_ref = trait_ref.instantiate_identity(); visitor.span = tcx.hir_expect_item(def_id).expect_impl().of_trait.unwrap().trait_ref.path.span;
diff --git a/compiler/rustc_public_bridge/src/context/impls.rs b/compiler/rustc_public_bridge/src/context/impls.rs index 9b3948d..d9fa654 100644 --- a/compiler/rustc_public_bridge/src/context/impls.rs +++ b/compiler/rustc_public_bridge/src/context/impls.rs
@@ -189,7 +189,7 @@ pub fn trait_impls(&self, crate_num: CrateNum) -> Vec<DefId> { } pub fn trait_impl(&self, impl_def: DefId) -> EarlyBinder<'tcx, TraitRef<'tcx>> { - self.tcx.impl_trait_ref(impl_def).unwrap() + self.tcx.impl_trait_ref(impl_def) } pub fn generics_of(&self, def_id: DefId) -> &'tcx ty::Generics {
diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index a0cb6c4..88fbc6d 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs
@@ -77,6 +77,7 @@ fn define_extern( parent: Module<'ra>, ident: Ident, ns: Namespace, + child_index: usize, res: Res, vis: Visibility<DefId>, span: Span, @@ -86,10 +87,8 @@ fn define_extern( // Even if underscore names cannot be looked up, we still need to add them to modules, // because they can be fetched by glob imports from those modules, and bring traits // into scope both directly and through glob imports. - let key = BindingKey::new_disambiguated(ident, ns, || { - parent.underscore_disambiguator.update_unchecked(|d| d + 1); - parent.underscore_disambiguator.get() - }); + let key = + BindingKey::new_disambiguated(ident, ns, || (child_index + 1).try_into().unwrap()); // 0 indicates no underscore if self .resolution_or_default(parent, key) .borrow_mut_unchecked() @@ -233,9 +232,9 @@ pub(crate) fn build_reduced_graph( } pub(crate) fn build_reduced_graph_external(&self, module: Module<'ra>) { - for child in self.tcx.module_children(module.def_id()) { + for (i, child) in self.tcx.module_children(module.def_id()).into_iter().enumerate() { let parent_scope = ParentScope::module(module, self.arenas); - self.build_reduced_graph_for_external_crate_res(child, parent_scope) + self.build_reduced_graph_for_external_crate_res(child, parent_scope, i) } } @@ -244,6 +243,7 @@ fn build_reduced_graph_for_external_crate_res( &self, child: &ModChild, parent_scope: ParentScope<'ra>, + child_index: usize, ) { let parent = parent_scope.module; let ModChild { ident, res, vis, ref reexport_chain } = *child; @@ -272,7 +272,9 @@ fn build_reduced_graph_for_external_crate_res( _, ) | Res::PrimTy(..) - | Res::ToolMod => self.define_extern(parent, ident, TypeNS, res, vis, span, expansion), + | Res::ToolMod => { + self.define_extern(parent, ident, TypeNS, child_index, res, vis, span, expansion) + } Res::Def( DefKind::Fn | DefKind::AssocFn @@ -281,9 +283,9 @@ fn build_reduced_graph_for_external_crate_res( | DefKind::AssocConst | DefKind::Ctor(..), _, - ) => self.define_extern(parent, ident, ValueNS, res, vis, span, expansion), + ) => self.define_extern(parent, ident, ValueNS, child_index, res, vis, span, expansion), Res::Def(DefKind::Macro(..), _) | Res::NonMacroAttr(..) => { - self.define_extern(parent, ident, MacroNS, res, vis, span, expansion) + self.define_extern(parent, ident, MacroNS, child_index, res, vis, span, expansion) } Res::Def( DefKind::TyParam
diff --git a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs index 82a2a64..021b206 100644 --- a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs +++ b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs
@@ -10,8 +10,9 @@ use rustc_hir::LangItem; use rustc_middle::bug; use rustc_middle::ty::{ - self, ExistentialPredicateStableCmpExt as _, Instance, InstanceKind, IntTy, List, TraitRef, Ty, - TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt, UintTy, + self, AssocContainer, ExistentialPredicateStableCmpExt as _, Instance, InstanceKind, IntTy, + List, TraitRef, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt, + UintTy, }; use rustc_span::def_id::DefId; use rustc_span::{DUMMY_SP, sym}; @@ -466,20 +467,20 @@ fn implemented_method<'tcx>( let method_id; let trait_id; let trait_method; - let ancestor = if let Some(impl_id) = tcx.impl_of_assoc(instance.def_id()) { - // Implementation in an `impl` block - trait_ref = tcx.impl_trait_ref(impl_id)?; - method_id = tcx.trait_item_of(instance.def_id())?; + let assoc = tcx.opt_associated_item(instance.def_id())?; + let ancestor = if let AssocContainer::TraitImpl(Ok(trait_method_id)) = assoc.container { + let impl_id = tcx.parent(instance.def_id()); + trait_ref = tcx.impl_trait_ref(impl_id); + method_id = trait_method_id; trait_method = tcx.associated_item(method_id); trait_id = trait_ref.skip_binder().def_id; impl_id - } else if let InstanceKind::Item(def_id) = instance.def - && let Some(trait_method_bound) = tcx.opt_associated_item(def_id) + } else if let AssocContainer::Trait = assoc.container + && let InstanceKind::Item(def_id) = instance.def { - // Provided method in a `trait` block - trait_method = trait_method_bound; - method_id = instance.def_id(); - trait_id = tcx.trait_of_assoc(method_id)?; + trait_method = assoc; + method_id = def_id; + trait_id = tcx.parent(method_id); trait_ref = ty::EarlyBinder::bind(TraitRef::from_assoc(tcx, trait_id, instance.args)); trait_id } else {
diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 172672a..085983c 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs
@@ -603,7 +603,8 @@ pub fn lto(&self) -> config::Lto { // Autodiff currently requires fat-lto to have access to the llvm-ir of all (indirectly) used functions and types. // fat-lto is the easiest solution to this requirement, but quite expensive. // FIXME(autodiff): Make autodiff also work with embed-bc instead of fat-lto. - if self.opts.autodiff_enabled() { + // Don't apply fat-lto to proc-macro crates as they cannot use fat-lto without -Zdylib-lto + if self.opts.autodiff_enabled() && !self.opts.crate_types.contains(&CrateType::ProcMacro) { return config::Lto::Fat; }
diff --git a/compiler/rustc_symbol_mangling/src/legacy.rs b/compiler/rustc_symbol_mangling/src/legacy.rs index 95a7ec6..ee2621a 100644 --- a/compiler/rustc_symbol_mangling/src/legacy.rs +++ b/compiler/rustc_symbol_mangling/src/legacy.rs
@@ -403,7 +403,7 @@ fn print_impl_path( args: &'tcx [GenericArg<'tcx>], ) -> Result<(), PrintError> { let self_ty = self.tcx.type_of(impl_def_id); - let impl_trait_ref = self.tcx.impl_trait_ref(impl_def_id); + let impl_trait_ref = self.tcx.impl_opt_trait_ref(impl_def_id); let generics = self.tcx.generics_of(impl_def_id); // We have two cases to worry about here: // 1. We're printing a nested item inside of an impl item, like an inner
diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index aeac40a..d5bc831 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs
@@ -311,7 +311,7 @@ fn print_impl_path( let parent_def_id = DefId { index: key.parent.unwrap(), ..impl_def_id }; let self_ty = self.tcx.type_of(impl_def_id); - let impl_trait_ref = self.tcx.impl_trait_ref(impl_def_id); + let impl_trait_ref = self.tcx.impl_opt_trait_ref(impl_def_id); let generics = self.tcx.generics_of(impl_def_id); // We have two cases to worry about here: // 1. We're printing a nested item inside of an impl item, like an inner
diff --git a/compiler/rustc_target/src/spec/base/nto_qnx.rs b/compiler/rustc_target/src/spec/base/nto_qnx.rs index 3f35b8b..6498742 100644 --- a/compiler/rustc_target/src/spec/base/nto_qnx.rs +++ b/compiler/rustc_target/src/spec/base/nto_qnx.rs
@@ -12,6 +12,9 @@ pub(crate) fn opts() -> TargetOptions { has_thread_local: false, linker: Some("qcc".into()), os: "nto".into(), + // We want backtraces to work by default and they rely on unwind tables + // (regardless of `-C panic` strategy). + default_uwtable: true, position_independent_executables: true, static_position_independent_executables: true, relro_level: RelroLevel::Full,
diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs index 9a8ccea..0765434 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs
@@ -574,7 +574,7 @@ pub fn suggest_copy_trait_method_bounds( let Some(impl_def_id) = self.tcx.trait_impl_of_assoc(impl_item_def_id.to_def_id()) else { return; }; - let trait_ref = self.tcx.impl_trait_ref(impl_def_id).unwrap(); + let trait_ref = self.tcx.impl_trait_ref(impl_def_id); let trait_args = trait_ref .instantiate_identity() // Replace the explicit self type with `Self` for better suggestion rendering
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs index edb002c..eb72f71 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs
@@ -47,8 +47,7 @@ pub fn compute_applicable_impls_for_diagnostics<'tcx>( ); let impl_args = infcx.fresh_args_for_item(DUMMY_SP, impl_def_id); - let impl_trait_ref = - tcx.impl_trait_ref(impl_def_id).unwrap().instantiate(tcx, impl_args); + let impl_trait_ref = tcx.impl_trait_ref(impl_def_id).instantiate(tcx, impl_args); let impl_trait_ref = ocx.normalize(&ObligationCause::dummy(), param_env, impl_trait_ref); @@ -58,7 +57,7 @@ pub fn compute_applicable_impls_for_diagnostics<'tcx>( return false; } - let impl_trait_header = tcx.impl_trait_header(impl_def_id).unwrap(); + let impl_trait_header = tcx.impl_trait_header(impl_def_id); let impl_polarity = impl_trait_header.polarity; match (impl_polarity, predicate_polarity) {
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/call_kind.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/call_kind.rs index f54ebd7..2c18ffc 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/call_kind.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/call_kind.rs
@@ -77,7 +77,7 @@ pub fn call_kind<'tcx>( let container_id = assoc.container_id(tcx); match assoc.container { AssocContainer::InherentImpl => None, - AssocContainer::TraitImpl(_) => tcx.trait_id_of_impl(container_id), + AssocContainer::TraitImpl(_) => Some(tcx.impl_trait_id(container_id)), AssocContainer::Trait => Some(container_id), } });
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index 4305d41..373819d 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
@@ -1867,7 +1867,7 @@ pub(super) fn find_similar_impl_candidates( .tcx .all_impls(trait_pred.def_id()) .filter_map(|def_id| { - let imp = self.tcx.impl_trait_header(def_id).unwrap(); + let imp = self.tcx.impl_trait_header(def_id); if imp.polarity != ty::ImplPolarity::Positive || !self.tcx.is_user_visible_dep(def_id.krate) { @@ -1906,7 +1906,7 @@ pub(super) fn report_similar_impl_candidates( // ignore `do_not_recommend` items .filter(|def_id| !self.tcx.do_not_recommend_impl(*def_id)) // Ignore automatically derived impls and `!Trait` impls. - .filter_map(|def_id| self.tcx.impl_trait_header(def_id)) + .map(|def_id| self.tcx.impl_trait_header(def_id)) .filter_map(|header| { (header.polarity != ty::ImplPolarity::Negative || self.tcx.is_automatically_derived(def_id))
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs index 9052031..ded5969 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs
@@ -354,7 +354,7 @@ fn report_fulfillment_error(&self, error: &FulfillmentError<'tcx>) -> ErrorGuara pub(crate) fn to_pretty_impl_header(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Option<String> { use std::fmt::Write; - let trait_ref = tcx.impl_trait_ref(impl_def_id)?.instantiate_identity(); + let trait_ref = tcx.impl_opt_trait_ref(impl_def_id)?.instantiate_identity(); let mut w = "impl".to_owned(); #[derive(Debug, Default)]
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs index b7d470d..a5cb374 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs
@@ -44,8 +44,7 @@ fn impl_similar_to( self.tcx.for_each_relevant_impl(trait_pred.def_id(), trait_self_ty, |def_id| { let impl_args = self.fresh_args_for_item(obligation.cause.span, def_id); - let impl_trait_ref = - tcx.impl_trait_ref(def_id).unwrap().instantiate(tcx, impl_args); + let impl_trait_ref = tcx.impl_trait_ref(def_id).instantiate(tcx, impl_args); let impl_self_ty = impl_trait_ref.self_ty();
diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index 22ef214..e488fb6 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs
@@ -137,8 +137,8 @@ pub fn overlapping_trait_impls( // Before doing expensive operations like entering an inference context, do // a quick check via fast_reject to tell if the impl headers could possibly // unify. - let impl1_args = tcx.impl_trait_ref(impl1_def_id).unwrap().skip_binder().args; - let impl2_args = tcx.impl_trait_ref(impl2_def_id).unwrap().skip_binder().args; + let impl1_args = tcx.impl_trait_ref(impl1_def_id).skip_binder().args; + let impl2_args = tcx.impl_trait_ref(impl2_def_id).skip_binder().args; let may_overlap = DeepRejectCtxt::relate_infer_infer(tcx).args_may_unify(impl1_args, impl2_args); @@ -209,8 +209,7 @@ fn fresh_impl_header<'tcx>( impl_def_id, impl_args, self_ty: tcx.type_of(impl_def_id).instantiate(tcx, impl_args), - trait_ref: is_of_trait - .then(|| tcx.impl_trait_ref(impl_def_id).unwrap().instantiate(tcx, impl_args)), + trait_ref: is_of_trait.then(|| tcx.impl_trait_ref(impl_def_id).instantiate(tcx, impl_args)), predicates: tcx .predicates_of(impl_def_id) .instantiate(tcx, impl_args)
diff --git a/compiler/rustc_trait_selection/src/traits/effects.rs b/compiler/rustc_trait_selection/src/traits/effects.rs index d694a09..7f2a999 100644 --- a/compiler/rustc_trait_selection/src/traits/effects.rs +++ b/compiler/rustc_trait_selection/src/traits/effects.rs
@@ -458,9 +458,7 @@ fn evaluate_host_effect_from_selection_candidate<'tcx>( Err(_) => Err(EvaluationFailure::NoSolution), Ok(Some(source)) => match source { ImplSource::UserDefined(impl_) => { - if tcx.impl_trait_header(impl_.impl_def_id).unwrap().constness - != hir::Constness::Const - { + if tcx.impl_trait_header(impl_.impl_def_id).constness != hir::Constness::Const { return Err(EvaluationFailure::NoSolution); }
diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index 3d27756..0f3b38e 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs
@@ -835,10 +835,7 @@ fn visit_const(&mut self, ct: ty::Const<'tcx>) -> Self::Result { let param_env = ty::ParamEnv::empty(); let fresh_args = infcx.fresh_args_for_item(tcx.def_span(impl_def_id), impl_def_id); - let impl_trait_ref = tcx - .impl_trait_ref(impl_def_id) - .expect("expected impl to correspond to trait") - .instantiate(tcx, fresh_args); + let impl_trait_ref = tcx.impl_trait_ref(impl_def_id).instantiate(tcx, fresh_args); let mut visitor = ReferencesOnlyParentGenerics { tcx, generics, trait_item_def_id }; let predicates_for_trait = predicates.predicates.iter().filter_map(|(pred, span)| {
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index fab5102..fea4b7c 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -1979,7 +1979,7 @@ fn confirm_impl_candidate<'cx, 'tcx>( let ImplSourceUserDefinedData { impl_def_id, args, mut nested } = impl_impl_source; let assoc_item_id = obligation.predicate.def_id; - let trait_def_id = tcx.trait_id_of_impl(impl_def_id).unwrap(); + let trait_def_id = tcx.impl_trait_id(impl_def_id); let param_env = obligation.param_env; let assoc_term = match specialization_graph::assoc_def(tcx, impl_def_id, assoc_item_id) {
diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index cb980d5..cecb43e 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
@@ -604,7 +604,7 @@ fn assemble_candidates_from_impls( // Before we create the generic parameters and everything, first // consider a "quick reject". This avoids creating more types // and so forth that we need to. - let impl_trait_header = self.tcx().impl_trait_header(impl_def_id).unwrap(); + let impl_trait_header = self.tcx().impl_trait_header(impl_def_id); if !drcx .args_may_unify(obligation_args, impl_trait_header.trait_ref.skip_binder().args) {
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 9be5d06..614c09d 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -2487,7 +2487,7 @@ fn rematch_impl( impl_def_id: DefId, obligation: &PolyTraitObligation<'tcx>, ) -> Normalized<'tcx, GenericArgsRef<'tcx>> { - let impl_trait_header = self.tcx().impl_trait_header(impl_def_id).unwrap(); + let impl_trait_header = self.tcx().impl_trait_header(impl_def_id); match self.match_impl(impl_def_id, impl_trait_header, obligation) { Ok(args) => args, Err(()) => {
diff --git a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs index ab01d07..ca6fd78 100644 --- a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
@@ -117,7 +117,7 @@ pub fn translate_args_with_cause<'tcx>( param_env, source_impl, source_args, target_node ); let source_trait_ref = - infcx.tcx.impl_trait_ref(source_impl).unwrap().instantiate(infcx.tcx, source_args); + infcx.tcx.impl_trait_ref(source_impl).instantiate(infcx.tcx, source_args); // translate the Self and Param parts of the generic parameters, since those // vary across impls @@ -176,11 +176,7 @@ fn fulfill_implication<'tcx>( let target_trait_ref = ocx.normalize( cause, param_env, - infcx - .tcx - .impl_trait_ref(target_impl) - .expect("expected source impl to be a trait impl") - .instantiate(infcx.tcx, target_args), + infcx.tcx.impl_trait_ref(target_impl).instantiate(infcx.tcx, target_args), ); // do the impls unify? If not, no specialization. @@ -256,7 +252,7 @@ pub(super) fn specializes( } } - let specializing_impl_trait_header = tcx.impl_trait_header(specializing_impl_def_id).unwrap(); + let specializing_impl_trait_header = tcx.impl_trait_header(specializing_impl_def_id); // We determine whether there's a subset relationship by: // @@ -307,11 +303,7 @@ pub(super) fn specializes( let parent_impl_trait_ref = ocx.normalize( cause, param_env, - infcx - .tcx - .impl_trait_ref(parent_impl_def_id) - .expect("expected source impl to be a trait impl") - .instantiate(infcx.tcx, parent_args), + infcx.tcx.impl_trait_ref(parent_impl_def_id).instantiate(infcx.tcx, parent_args), ); // do the impls unify? If not, no specialization.
diff --git a/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs b/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs index 12ba12b..02db81d 100644 --- a/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs +++ b/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs
@@ -38,7 +38,7 @@ enum Inserted<'tcx> { impl<'tcx> Children { /// Insert an impl into this set of children without comparing to any existing impls. fn insert_blindly(&mut self, tcx: TyCtxt<'tcx>, impl_def_id: DefId) { - let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap().skip_binder(); + let trait_ref = tcx.impl_trait_ref(impl_def_id).skip_binder(); if let Some(st) = fast_reject::simplify_type(tcx, trait_ref.self_ty(), TreatParams::InstantiateWithInfer) { @@ -54,7 +54,7 @@ fn insert_blindly(&mut self, tcx: TyCtxt<'tcx>, impl_def_id: DefId) { /// an impl with a parent. The impl must be present in the list of /// children already. fn remove_existing(&mut self, tcx: TyCtxt<'tcx>, impl_def_id: DefId) { - let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap().skip_binder(); + let trait_ref = tcx.impl_trait_ref(impl_def_id).skip_binder(); let vec: &mut Vec<DefId>; if let Some(st) = fast_reject::simplify_type(tcx, trait_ref.self_ty(), TreatParams::InstantiateWithInfer) @@ -164,7 +164,7 @@ fn insert( if le && !ge { debug!( "descending as child of TraitRef {:?}", - tcx.impl_trait_ref(possible_sibling).unwrap().instantiate_identity() + tcx.impl_trait_ref(possible_sibling).instantiate_identity() ); // The impl specializes `possible_sibling`. @@ -172,7 +172,7 @@ fn insert( } else if ge && !le { debug!( "placing as parent of TraitRef {:?}", - tcx.impl_trait_ref(possible_sibling).unwrap().instantiate_identity() + tcx.impl_trait_ref(possible_sibling).instantiate_identity() ); replace_children.push(possible_sibling); @@ -242,7 +242,7 @@ fn insert( assert!(impl_def_id.is_local()); // FIXME: use `EarlyBinder` in `self.children` - let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap().skip_binder(); + let trait_ref = tcx.impl_trait_ref(impl_def_id).skip_binder(); let trait_def_id = trait_ref.def_id; debug!( @@ -354,7 +354,7 @@ pub(crate) fn assoc_def( impl_def_id: DefId, assoc_def_id: DefId, ) -> Result<LeafDef, ErrorGuaranteed> { - let trait_def_id = tcx.trait_id_of_impl(impl_def_id).unwrap(); + let trait_def_id = tcx.impl_trait_id(impl_def_id); let trait_def = tcx.trait_def(trait_def_id); // This function may be called while we are still building the
diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs index e4ed084..ed5289c 100644 --- a/compiler/rustc_ty_utils/src/abi.rs +++ b/compiler/rustc_ty_utils/src/abi.rs
@@ -640,10 +640,10 @@ fn unadjust<'tcx>(arg: &mut ArgAbi<'tcx, Ty<'tcx>>) { // we can't deduce any parameters for, so make sure the argument index is in // bounds. if let Some(deduced_param_attrs) = deduced_param_attrs.get(arg_idx) - && deduced_param_attrs.read_only + && deduced_param_attrs.read_only(tcx, cx.typing_env, arg.layout.ty) { - attrs.regular.insert(ArgAttribute::ReadOnly); debug!("added deduced read-only attribute"); + attrs.regular.insert(ArgAttribute::ReadOnly); } } }
diff --git a/compiler/rustc_ty_utils/src/implied_bounds.rs b/compiler/rustc_ty_utils/src/implied_bounds.rs index 543f6a3..990120d 100644 --- a/compiler/rustc_ty_utils/src/implied_bounds.rs +++ b/compiler/rustc_ty_utils/src/implied_bounds.rs
@@ -42,12 +42,14 @@ fn assumed_wf_types<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx [(Ty<' )); tcx.arena.alloc_slice(&assumed_wf_types) } - DefKind::Impl { .. } => { + DefKind::Impl { of_trait } => { // Trait arguments and the self type for trait impls or only the self type for // inherent impls. - let tys = match tcx.impl_trait_ref(def_id) { - Some(trait_ref) => trait_ref.skip_binder().args.types().collect(), - None => vec![tcx.type_of(def_id).instantiate_identity()], + let tys = if of_trait { + let trait_ref = tcx.impl_trait_ref(def_id); + trait_ref.skip_binder().args.types().collect() + } else { + vec![tcx.type_of(def_id).instantiate_identity()] }; let mut impl_spans = impl_spans(tcx, def_id); @@ -111,7 +113,7 @@ fn assumed_wf_types<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx [(Ty<' let args = ty::GenericArgs::identity_for_item(tcx, def_id).rebase_onto( tcx, impl_def_id.to_def_id(), - tcx.impl_trait_ref(impl_def_id).unwrap().instantiate_identity().args, + tcx.impl_trait_ref(impl_def_id).instantiate_identity().args, ); tcx.arena.alloc_from_iter( ty::EarlyBinder::bind(tcx.assumed_wf_types_for_rpitit(rpitit_def_id))
diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs index e28ebaa..23bbd9c 100644 --- a/compiler/rustc_ty_utils/src/instance.rs +++ b/compiler/rustc_ty_utils/src/instance.rs
@@ -131,7 +131,7 @@ fn resolve_associated_item<'tcx>( assert!(!rcvr_args.has_infer()); assert!(!trait_ref.has_infer()); - let trait_def_id = tcx.trait_id_of_impl(impl_data.impl_def_id).unwrap(); + let trait_def_id = tcx.impl_trait_id(impl_data.impl_def_id); let trait_def = tcx.trait_def(trait_def_id); let leaf_def = trait_def .ancestors(tcx, impl_data.impl_def_id)?
diff --git a/compiler/rustc_ty_utils/src/opaque_types.rs b/compiler/rustc_ty_utils/src/opaque_types.rs index eb3236d..4dd45a0 100644 --- a/compiler/rustc_ty_utils/src/opaque_types.rs +++ b/compiler/rustc_ty_utils/src/opaque_types.rs
@@ -62,24 +62,6 @@ fn visit_spanned(&mut self, span: Span, value: impl TypeVisitable<TyCtxt<'tcx>>) self.span = old; } - fn parent_impl_trait_ref(&self) -> Option<ty::TraitRef<'tcx>> { - let parent = self.parent()?; - if matches!(self.tcx.def_kind(parent), DefKind::Impl { .. }) { - Some(self.tcx.impl_trait_ref(parent)?.instantiate_identity()) - } else { - None - } - } - - fn parent(&self) -> Option<LocalDefId> { - match self.tcx.def_kind(self.item) { - DefKind::AssocFn | DefKind::AssocTy | DefKind::AssocConst => { - Some(self.tcx.local_parent(self.item)) - } - _ => None, - } - } - #[instrument(level = "trace", skip(self))] fn collect_taits_declared_in_body(&mut self) { let body = self.tcx.hir_body_owned_by(self.item).value; @@ -236,13 +218,12 @@ fn visit_ty(&mut self, t: Ty<'tcx>) { // This avoids having to do normalization of `Self::AssocTy` by only // supporting the case of a method defining opaque types from assoc types // in the same impl block. - if let Some(impl_trait_ref) = self.parent_impl_trait_ref() { + if let Some(parent) = self.tcx.trait_impl_of_assoc(self.item.to_def_id()) { + let impl_trait_ref = self.tcx.impl_trait_ref(parent).instantiate_identity(); // If the trait ref of the associated item and the impl differs, // then we can't use the impl's identity args below, so // just skip. if alias_ty.trait_ref(self.tcx) == impl_trait_ref { - let parent = self.parent().expect("we should have a parent here"); - for &assoc in self.tcx.associated_items(parent).in_definition_order() { trace!(?assoc); if assoc.expect_trait_impl() != Ok(alias_ty.def_id) {
diff --git a/compiler/rustc_ty_utils/src/sig_types.rs b/compiler/rustc_ty_utils/src/sig_types.rs index d956608..07f379d 100644 --- a/compiler/rustc_ty_utils/src/sig_types.rs +++ b/compiler/rustc_ty_utils/src/sig_types.rs
@@ -88,7 +88,7 @@ pub fn walk_types<'tcx, V: SpannedTypeVisitor<'tcx>>( DefKind::Impl { of_trait } => { if of_trait { let span = tcx.hir_node_by_def_id(item).expect_item().expect_impl().of_trait.unwrap().trait_ref.path.span; - let args = &tcx.impl_trait_ref(item).unwrap().instantiate_identity().args[1..]; + let args = &tcx.impl_trait_ref(item).instantiate_identity().args[1..]; try_visit!(visitor.visit(span, args)); } let span = match tcx.hir_node_by_def_id(item).ty() {
diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index 49ff768..ae43fbf 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs
@@ -237,6 +237,7 @@ pub struct Box< /// the newly allocated memory. This is an intrinsic to avoid unnecessary copies. /// /// This is the surface syntax for `box <expr>` expressions. +#[doc(hidden)] #[rustc_intrinsic] #[unstable(feature = "liballoc_internals", issue = "none")] pub fn box_new<T>(x: T) -> Box<T>;
diff --git a/library/alloc/src/collections/btree/node.rs b/library/alloc/src/collections/btree/node.rs index a87259e..84dd4b7 100644 --- a/library/alloc/src/collections/btree/node.rs +++ b/library/alloc/src/collections/btree/node.rs
@@ -33,6 +33,7 @@ use core::marker::PhantomData; use core::mem::{self, MaybeUninit}; +use core::num::NonZero; use core::ptr::{self, NonNull}; use core::slice::SliceIndex; @@ -143,7 +144,7 @@ unsafe fn new<A: Allocator + Clone>(alloc: A) -> Box<Self, A> { /// /// A reference to a node. /// -/// This type has a number of parameters that controls how it acts: +/// This type has a number of parameters that control how it acts: /// - `BorrowType`: A dummy type that describes the kind of borrow and carries a lifetime. /// - When this is `Immut<'a>`, the `NodeRef` acts roughly like `&'a Node`. /// - When this is `ValMut<'a>`, the `NodeRef` acts roughly like `&'a Node` @@ -226,33 +227,27 @@ pub(super) fn new_leaf<A: Allocator + Clone>(alloc: A) -> Self { fn from_new_leaf<A: Allocator + Clone>(leaf: Box<LeafNode<K, V>, A>) -> Self { // The allocator must be dropped, not leaked. See also `BTreeMap::alloc`. - let (leaf, _alloc) = Box::into_raw_with_allocator(leaf); - // SAFETY: the node was just allocated. - let node = unsafe { NonNull::new_unchecked(leaf) }; + let (node, _alloc) = Box::into_non_null_with_allocator(leaf); NodeRef { height: 0, node, _marker: PhantomData } } } impl<K, V> NodeRef<marker::Owned, K, V, marker::Internal> { + /// Creates a new internal (height > 0) `NodeRef` fn new_internal<A: Allocator + Clone>(child: Root<K, V>, alloc: A) -> Self { let mut new_node = unsafe { InternalNode::new(alloc) }; new_node.edges[0].write(child.node); - unsafe { NodeRef::from_new_internal(new_node, child.height + 1) } + NodeRef::from_new_internal(new_node, NonZero::new(child.height + 1).unwrap()) } - /// # Safety - /// `height` must not be zero. - unsafe fn from_new_internal<A: Allocator + Clone>( + /// Creates a new internal (height > 0) `NodeRef` from an existing internal node + fn from_new_internal<A: Allocator + Clone>( internal: Box<InternalNode<K, V>, A>, - height: usize, + height: NonZero<usize>, ) -> Self { - debug_assert!(height > 0); // The allocator must be dropped, not leaked. See also `BTreeMap::alloc`. - let (internal, _alloc) = Box::into_raw_with_allocator(internal); - // SAFETY: the node was just allocated. - let internal = unsafe { NonNull::new_unchecked(internal) }; - let node = internal.cast(); - let mut this = NodeRef { height, node, _marker: PhantomData }; + let (node, _alloc) = Box::into_non_null_with_allocator(internal); + let mut this = NodeRef { height: height.into(), node: node.cast(), _marker: PhantomData }; this.borrow_mut().correct_all_childrens_parent_links(); this } @@ -625,9 +620,8 @@ pub(super) fn pop_internal_level<A: Allocator + Clone>(&mut self, alloc: A) { let top = self.node; // SAFETY: we asserted to be internal. - let internal_self = unsafe { self.borrow_mut().cast_to_internal_unchecked() }; - // SAFETY: we borrowed `self` exclusively and its borrow type is exclusive. - let internal_node = unsafe { &mut *NodeRef::as_internal_ptr(&internal_self) }; + let mut internal_self = unsafe { self.borrow_mut().cast_to_internal_unchecked() }; + let internal_node = internal_self.as_internal_mut(); // SAFETY: the first edge is always initialized. self.node = unsafe { internal_node.edges[0].assume_init_read() }; self.height -= 1; @@ -1305,7 +1299,8 @@ pub(super) fn split<A: Allocator + Clone>( &mut new_node.edges[..new_len + 1], ); - let height = self.node.height; + // SAFETY: self is `marker::Internal`, so `self.node.height` is positive + let height = NonZero::new_unchecked(self.node.height); let right = NodeRef::from_new_internal(new_node, height); SplitResult { left: self.node, kv, right }
diff --git a/library/alloc/src/wtf8/tests.rs b/library/alloc/src/wtf8/tests.rs index 291f63f..a72ad08 100644 --- a/library/alloc/src/wtf8/tests.rs +++ b/library/alloc/src/wtf8/tests.rs
@@ -580,6 +580,17 @@ fn wtf8_encode_wide_size_hint() { } #[test] +fn wtf8_encode_wide_debug() { + let mut string = Wtf8Buf::from_str("aé "); + string.push(CodePoint::from_u32(0xD83D).unwrap()); + string.push_char('💩'); + assert_eq!( + format!("{:?}", string.encode_wide()), + r#"EncodeWide(['a', 'é', ' ', 0xD83D, 0xD83D, 0xDCA9])"# + ); +} + +#[test] fn wtf8_clone_into() { let mut string = Wtf8Buf::new(); clone_into(Wtf8::from_str("green"), &mut string);
diff --git a/library/core/src/iter/sources/repeat.rs b/library/core/src/iter/sources/repeat.rs index 7fcd6f8..f578ae8 100644 --- a/library/core/src/iter/sources/repeat.rs +++ b/library/core/src/iter/sources/repeat.rs
@@ -101,8 +101,9 @@ fn nth(&mut self, n: usize) -> Option<A> { Some(self.element.clone()) } + #[track_caller] fn last(self) -> Option<A> { - Some(self.element) + panic!("iterator is infinite"); } #[track_caller]
diff --git a/library/core/src/option.rs b/library/core/src/option.rs index 430ee34..e3c4758 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs
@@ -118,9 +118,14 @@ //! //! # Representation //! -//! Rust guarantees to optimize the following types `T` such that -//! [`Option<T>`] has the same size, alignment, and [function call ABI] as `T`. In some -//! of these cases, Rust further guarantees the following: +//! Rust guarantees to optimize the following types `T` such that [`Option<T>`] +//! has the same size, alignment, and [function call ABI] as `T`. It is +//! therefore sound, when `T` is one of these types, to transmute a value `t` of +//! type `T` to type `Option<T>` (producing the value `Some(t)`) and to +//! transmute a value `Some(t)` of type `Option<T>` to type `T` (producing the +//! value `t`). +//! +//! In some of these cases, Rust further guarantees the following: //! - `transmute::<_, Option<T>>([0u8; size_of::<T>()])` is sound and produces //! `Option::<T>::None` //! - `transmute::<_, [u8; size_of::<T>()]>(Option::<T>::None)` is sound and produces
diff --git a/library/core/src/result.rs b/library/core/src/result.rs index c69762a..6fee7fe 100644 --- a/library/core/src/result.rs +++ b/library/core/src/result.rs
@@ -230,24 +230,31 @@ //! //! # Representation //! -//! In some cases, [`Result<T, E>`] will gain the same size, alignment, and ABI -//! guarantees as [`Option<U>`] has. One of either the `T` or `E` type must be a -//! type that qualifies for the `Option` [representation guarantees][opt-rep], -//! and the *other* type must meet all of the following conditions: -//! * Is a zero-sized type with alignment 1 (a "1-ZST"). -//! * Has no fields. -//! * Does not have the `#[non_exhaustive]` attribute. +//! In some cases, [`Result<T, E>`] comes with size, alignment, and ABI +//! guarantees. Specifically, one of either the `T` or `E` type must be a type +//! that qualifies for the `Option` [representation guarantees][opt-rep] (let's +//! call that type `I`), and the *other* type is a zero-sized type with +//! alignment 1 (a "1-ZST"). +//! +//! If that is the case, then `Result<T, E>` has the same size, alignment, and +//! [function call ABI] as `I` (and therefore, as `Option<I>`). If `I` is `T`, +//! it is therefore sound to transmute a value `t` of type `I` to type +//! `Result<T, E>` (producing the value `Ok(t)`) and to transmute a value +//! `Ok(t)` of type `Result<T, E>` to type `I` (producing the value `t`). If `I` +//! is `E`, the same applies with `Ok` replaced by `Err`. //! //! For example, `NonZeroI32` qualifies for the `Option` representation -//! guarantees, and `()` is a zero-sized type with alignment 1, no fields, and -//! it isn't `non_exhaustive`. This means that both `Result<NonZeroI32, ()>` and -//! `Result<(), NonZeroI32>` have the same size, alignment, and ABI guarantees -//! as `Option<NonZeroI32>`. The only difference is the implied semantics: +//! guarantees and `()` is a zero-sized type with alignment 1. This means that +//! both `Result<NonZeroI32, ()>` and `Result<(), NonZeroI32>` have the same +//! size, alignment, and ABI as `NonZeroI32` (and `Option<NonZeroI32>`). The +//! only difference between these is in the implied semantics: +//! //! * `Option<NonZeroI32>` is "a non-zero i32 might be present" //! * `Result<NonZeroI32, ()>` is "a non-zero i32 success result, if any" //! * `Result<(), NonZeroI32>` is "a non-zero i32 error result, if any" //! //! [opt-rep]: ../option/index.html#representation "Option Representation" +//! [function call ABI]: ../primitive.fn.html#abi-compatibility //! //! # Method overview //!
diff --git a/library/core/src/wtf8.rs b/library/core/src/wtf8.rs index de0dfa5..0c03496 100644 --- a/library/core/src/wtf8.rs +++ b/library/core/src/wtf8.rs
@@ -562,15 +562,36 @@ fn size_hint(&self) -> (usize, Option<usize>) { } } -impl fmt::Debug for EncodeWide<'_> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("EncodeWide").finish_non_exhaustive() - } -} - #[stable(feature = "encode_wide_fused_iterator", since = "1.62.0")] impl FusedIterator for EncodeWide<'_> {} +#[stable(feature = "encode_wide_debug", since = "CURRENT_RUSTC_VERSION")] +impl fmt::Debug for EncodeWide<'_> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + struct CodeUnit(u16); + impl fmt::Debug for CodeUnit { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + // This output attempts to balance readability with precision. + // Render characters which take only one WTF-16 code unit using + // `char` syntax and everything else as code units with hex + // integer syntax (including paired and unpaired surrogate + // halves). Since Rust has no `char`-like type for WTF-16, this + // isn't perfect, so if this output isn't suitable, it is open + // to being changed (see #140153). + match char::from_u32(self.0 as u32) { + Some(c) => write!(f, "{c:?}"), + None => write!(f, "0x{:04X}", self.0), + } + } + } + + write!(f, "EncodeWide(")?; + f.debug_list().entries(self.clone().map(CodeUnit)).finish()?; + write!(f, ")")?; + Ok(()) + } +} + impl Hash for CodePoint { #[inline] fn hash<H: Hasher>(&self, state: &mut H) {
diff --git a/library/coretests/tests/iter/sources.rs b/library/coretests/tests/iter/sources.rs index 5a391cb..420f308 100644 --- a/library/coretests/tests/iter/sources.rs +++ b/library/coretests/tests/iter/sources.rs
@@ -37,6 +37,7 @@ fn test_repeat_count() { } #[test] +#[should_panic = "iterator is infinite"] fn test_repeat_last() { assert_eq!(repeat(42).last(), Some(42)); }
diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index 28b2c71..b548eb4 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs
@@ -387,6 +387,87 @@ fn inner(path: &Path, contents: &[u8]) -> io::Result<()> { inner(path.as_ref(), contents.as_ref()) } +/// Changes the timestamps of the file or directory at the specified path. +/// +/// This function will attempt to set the access and modification times +/// to the times specified. If the path refers to a symbolic link, this function +/// will follow the link and change the timestamps of the target file. +/// +/// # Platform-specific behavior +/// +/// This function currently corresponds to the `utimensat` function on Unix platforms, the +/// `setattrlist` function on Apple platforms, and the `SetFileTime` function on Windows. +/// +/// # Errors +/// +/// This function will return an error if the user lacks permission to change timestamps on the +/// target file or symlink. It may also return an error if the OS does not support it. +/// +/// # Examples +/// +/// ```no_run +/// #![feature(fs_set_times)] +/// use std::fs::{self, FileTimes}; +/// use std::time::SystemTime; +/// +/// fn main() -> std::io::Result<()> { +/// let now = SystemTime::now(); +/// let times = FileTimes::new() +/// .set_accessed(now) +/// .set_modified(now); +/// fs::set_times("foo.txt", times)?; +/// Ok(()) +/// } +/// ``` +#[unstable(feature = "fs_set_times", issue = "147455")] +#[doc(alias = "utimens")] +#[doc(alias = "utimes")] +#[doc(alias = "utime")] +pub fn set_times<P: AsRef<Path>>(path: P, times: FileTimes) -> io::Result<()> { + fs_imp::set_times(path.as_ref(), times.0) +} + +/// Changes the timestamps of the file or symlink at the specified path. +/// +/// This function will attempt to set the access and modification times +/// to the times specified. Differ from `set_times`, if the path refers to a symbolic link, +/// this function will change the timestamps of the symlink itself, not the target file. +/// +/// # Platform-specific behavior +/// +/// This function currently corresponds to the `utimensat` function with `AT_SYMLINK_NOFOLLOW` on +/// Unix platforms, the `setattrlist` function with `FSOPT_NOFOLLOW` on Apple platforms, and the +/// `SetFileTime` function on Windows. +/// +/// # Errors +/// +/// This function will return an error if the user lacks permission to change timestamps on the +/// target file or symlink. It may also return an error if the OS does not support it. +/// +/// # Examples +/// +/// ```no_run +/// #![feature(fs_set_times)] +/// use std::fs::{self, FileTimes}; +/// use std::time::SystemTime; +/// +/// fn main() -> std::io::Result<()> { +/// let now = SystemTime::now(); +/// let times = FileTimes::new() +/// .set_accessed(now) +/// .set_modified(now); +/// fs::set_times_nofollow("symlink.txt", times)?; +/// Ok(()) +/// } +/// ``` +#[unstable(feature = "fs_set_times", issue = "147455")] +#[doc(alias = "utimensat")] +#[doc(alias = "lutimens")] +#[doc(alias = "lutimes")] +pub fn set_times_nofollow<P: AsRef<Path>>(path: P, times: FileTimes) -> io::Result<()> { + fs_imp::set_times_nofollow(path.as_ref(), times.0) +} + #[stable(feature = "file_lock", since = "1.89.0")] impl error::Error for TryLockError {}
diff --git a/library/std/src/fs/tests.rs b/library/std/src/fs/tests.rs index f8dfb0d..4d67ba9 100644 --- a/library/std/src/fs/tests.rs +++ b/library/std/src/fs/tests.rs
@@ -2226,3 +2226,222 @@ fn test_open_options_invalid_combinations() { assert_eq!(err.kind(), ErrorKind::InvalidInput); assert_eq!(err.to_string(), "must specify at least one of read, write, or append access"); } + +#[test] +fn test_fs_set_times() { + #[cfg(target_vendor = "apple")] + use crate::os::darwin::fs::FileTimesExt; + #[cfg(windows)] + use crate::os::windows::fs::FileTimesExt; + + let tmp = tmpdir(); + let path = tmp.join("foo"); + File::create(&path).unwrap(); + + let mut times = FileTimes::new(); + let accessed = SystemTime::UNIX_EPOCH + Duration::from_secs(12345); + let modified = SystemTime::UNIX_EPOCH + Duration::from_secs(54321); + times = times.set_accessed(accessed).set_modified(modified); + + #[cfg(any(windows, target_vendor = "apple"))] + let created = SystemTime::UNIX_EPOCH + Duration::from_secs(32123); + #[cfg(any(windows, target_vendor = "apple"))] + { + times = times.set_created(created); + } + + match fs::set_times(&path, times) { + // Allow unsupported errors on platforms which don't support setting times. + #[cfg(not(any( + windows, + all( + unix, + not(any( + target_os = "android", + target_os = "redox", + target_os = "espidf", + target_os = "horizon" + )) + ) + )))] + Err(e) if e.kind() == ErrorKind::Unsupported => return, + Err(e) => panic!("error setting file times: {e:?}"), + Ok(_) => {} + } + + let metadata = fs::metadata(&path).unwrap(); + assert_eq!(metadata.accessed().unwrap(), accessed); + assert_eq!(metadata.modified().unwrap(), modified); + #[cfg(any(windows, target_vendor = "apple"))] + { + assert_eq!(metadata.created().unwrap(), created); + } +} + +#[test] +fn test_fs_set_times_follows_symlink() { + #[cfg(target_vendor = "apple")] + use crate::os::darwin::fs::FileTimesExt; + #[cfg(windows)] + use crate::os::windows::fs::FileTimesExt; + + let tmp = tmpdir(); + + // Create a target file + let target = tmp.join("target"); + File::create(&target).unwrap(); + + // Create a symlink to the target + #[cfg(unix)] + let link = tmp.join("link"); + #[cfg(unix)] + crate::os::unix::fs::symlink(&target, &link).unwrap(); + + #[cfg(windows)] + let link = tmp.join("link.txt"); + #[cfg(windows)] + crate::os::windows::fs::symlink_file(&target, &link).unwrap(); + + // Get the symlink's own modified time BEFORE calling set_times (to compare later) + // We don't check accessed time because reading metadata may update atime on some platforms. + let link_metadata_before = fs::symlink_metadata(&link).unwrap(); + let link_modified_before = link_metadata_before.modified().unwrap(); + + let mut times = FileTimes::new(); + let accessed = SystemTime::UNIX_EPOCH + Duration::from_secs(12345); + let modified = SystemTime::UNIX_EPOCH + Duration::from_secs(54321); + times = times.set_accessed(accessed).set_modified(modified); + + #[cfg(any(windows, target_vendor = "apple"))] + let created = SystemTime::UNIX_EPOCH + Duration::from_secs(32123); + #[cfg(any(windows, target_vendor = "apple"))] + { + times = times.set_created(created); + } + + // Call fs::set_times on the symlink - it should follow the link and modify the target + match fs::set_times(&link, times) { + // Allow unsupported errors on platforms which don't support setting times. + #[cfg(not(any( + windows, + all( + unix, + not(any( + target_os = "android", + target_os = "redox", + target_os = "espidf", + target_os = "horizon" + )) + ) + )))] + Err(e) if e.kind() == ErrorKind::Unsupported => return, + Err(e) => panic!("error setting file times through symlink: {e:?}"), + Ok(_) => {} + } + + // Verify that the TARGET file's times were changed (following the symlink) + let target_metadata = fs::metadata(&target).unwrap(); + assert_eq!( + target_metadata.accessed().unwrap(), + accessed, + "target file accessed time should match" + ); + assert_eq!( + target_metadata.modified().unwrap(), + modified, + "target file modified time should match" + ); + #[cfg(any(windows, target_vendor = "apple"))] + { + assert_eq!( + target_metadata.created().unwrap(), + created, + "target file created time should match" + ); + } + + // Also verify through the symlink (fs::metadata follows symlinks) + let link_followed_metadata = fs::metadata(&link).unwrap(); + assert_eq!(link_followed_metadata.accessed().unwrap(), accessed); + assert_eq!(link_followed_metadata.modified().unwrap(), modified); + + // Verify that the SYMLINK ITSELF was NOT modified + // Note: We only check modified time, not accessed time, because reading the symlink + // metadata may update its atime on some platforms (e.g., Linux). + let link_metadata_after = fs::symlink_metadata(&link).unwrap(); + assert_eq!( + link_metadata_after.modified().unwrap(), + link_modified_before, + "symlink's own modified time should not change" + ); +} + +#[test] +fn test_fs_set_times_nofollow() { + #[cfg(target_vendor = "apple")] + use crate::os::darwin::fs::FileTimesExt; + #[cfg(windows)] + use crate::os::windows::fs::FileTimesExt; + + let tmp = tmpdir(); + + // Create a target file and a symlink to it + let target = tmp.join("target"); + File::create(&target).unwrap(); + + #[cfg(unix)] + let link = tmp.join("link"); + #[cfg(unix)] + crate::os::unix::fs::symlink(&target, &link).unwrap(); + + #[cfg(windows)] + let link = tmp.join("link.txt"); + #[cfg(windows)] + crate::os::windows::fs::symlink_file(&target, &link).unwrap(); + + let mut times = FileTimes::new(); + let accessed = SystemTime::UNIX_EPOCH + Duration::from_secs(11111); + let modified = SystemTime::UNIX_EPOCH + Duration::from_secs(22222); + times = times.set_accessed(accessed).set_modified(modified); + + #[cfg(any(windows, target_vendor = "apple"))] + let created = SystemTime::UNIX_EPOCH + Duration::from_secs(33333); + #[cfg(any(windows, target_vendor = "apple"))] + { + times = times.set_created(created); + } + + // Set times on the symlink itself (not following it) + match fs::set_times_nofollow(&link, times) { + // Allow unsupported errors on platforms which don't support setting times. + #[cfg(not(any( + windows, + all( + unix, + not(any( + target_os = "android", + target_os = "redox", + target_os = "espidf", + target_os = "horizon" + )) + ) + )))] + Err(e) if e.kind() == ErrorKind::Unsupported => return, + Err(e) => panic!("error setting symlink times: {e:?}"), + Ok(_) => {} + } + + // Read symlink metadata (without following) + let metadata = fs::symlink_metadata(&link).unwrap(); + assert_eq!(metadata.accessed().unwrap(), accessed); + assert_eq!(metadata.modified().unwrap(), modified); + #[cfg(any(windows, target_vendor = "apple"))] + { + assert_eq!(metadata.created().unwrap(), created); + } + + // Verify that the target file's times were NOT changed + let target_metadata = fs::metadata(&target).unwrap(); + assert_ne!(target_metadata.accessed().unwrap(), accessed); + assert_ne!(target_metadata.modified().unwrap(), modified); +}
diff --git a/library/std/src/sys/fs/hermit.rs b/library/std/src/sys/fs/hermit.rs index 175d919..21235bc 100644 --- a/library/std/src/sys/fs/hermit.rs +++ b/library/std/src/sys/fs/hermit.rs
@@ -566,6 +566,14 @@ pub fn set_perm(_p: &Path, _perm: FilePermissions) -> io::Result<()> { Err(Error::from_raw_os_error(22)) } +pub fn set_times(_p: &Path, _times: FileTimes) -> io::Result<()> { + Err(Error::from_raw_os_error(22)) +} + +pub fn set_times_nofollow(_p: &Path, _times: FileTimes) -> io::Result<()> { + Err(Error::from_raw_os_error(22)) +} + pub fn rmdir(path: &Path) -> io::Result<()> { run_path_with_cstr(path, &|path| cvt(unsafe { hermit_abi::rmdir(path.as_ptr()) }).map(|_| ())) }
diff --git a/library/std/src/sys/fs/mod.rs b/library/std/src/sys/fs/mod.rs index 403bfb2..7435422 100644 --- a/library/std/src/sys/fs/mod.rs +++ b/library/std/src/sys/fs/mod.rs
@@ -165,3 +165,11 @@ pub fn exists(path: &Path) -> io::Result<bool> { #[cfg(windows)] with_native_path(path, &imp::exists) } + +pub fn set_times(path: &Path, times: FileTimes) -> io::Result<()> { + with_native_path(path, &|path| imp::set_times(path, times.clone())) +} + +pub fn set_times_nofollow(path: &Path, times: FileTimes) -> io::Result<()> { + with_native_path(path, &|path| imp::set_times_nofollow(path, times.clone())) +}
diff --git a/library/std/src/sys/fs/solid.rs b/library/std/src/sys/fs/solid.rs index 808a958..f6d5d3b 100644 --- a/library/std/src/sys/fs/solid.rs +++ b/library/std/src/sys/fs/solid.rs
@@ -538,6 +538,14 @@ pub fn set_perm(p: &Path, perm: FilePermissions) -> io::Result<()> { Ok(()) } +pub fn set_times(_p: &Path, _times: FileTimes) -> io::Result<()> { + unsupported() +} + +pub fn set_times_nofollow(_p: &Path, _times: FileTimes) -> io::Result<()> { + unsupported() +} + pub fn rmdir(p: &Path) -> io::Result<()> { if stat(p)?.file_type().is_dir() { error::SolidError::err_if_negative(unsafe { abi::SOLID_FS_Unlink(cstr(p)?.as_ptr()) })
diff --git a/library/std/src/sys/fs/uefi.rs b/library/std/src/sys/fs/uefi.rs index 5763d78..e4e7274 100644 --- a/library/std/src/sys/fs/uefi.rs +++ b/library/std/src/sys/fs/uefi.rs
@@ -333,6 +333,14 @@ pub fn set_perm(_p: &Path, _perm: FilePermissions) -> io::Result<()> { unsupported() } +pub fn set_times(_p: &Path, _times: FileTimes) -> io::Result<()> { + unsupported() +} + +pub fn set_times_nofollow(_p: &Path, _times: FileTimes) -> io::Result<()> { + unsupported() +} + pub fn rmdir(_p: &Path) -> io::Result<()> { unsupported() }
diff --git a/library/std/src/sys/fs/unix.rs b/library/std/src/sys/fs/unix.rs index 33a1e7f..d9a7fcb 100644 --- a/library/std/src/sys/fs/unix.rs +++ b/library/std/src/sys/fs/unix.rs
@@ -1604,24 +1604,6 @@ pub fn set_permissions(&self, perm: FilePermissions) -> io::Result<()> { } pub fn set_times(&self, times: FileTimes) -> io::Result<()> { - #[cfg(not(any( - target_os = "redox", - target_os = "espidf", - target_os = "horizon", - target_os = "nuttx", - )))] - let to_timespec = |time: Option<SystemTime>| match time { - Some(time) if let Some(ts) = time.t.to_timespec() => Ok(ts), - Some(time) if time > crate::sys::time::UNIX_EPOCH => Err(io::const_error!( - io::ErrorKind::InvalidInput, - "timestamp is too large to set as a file time", - )), - Some(_) => Err(io::const_error!( - io::ErrorKind::InvalidInput, - "timestamp is too small to set as a file time", - )), - None => Ok(libc::timespec { tv_sec: 0, tv_nsec: libc::UTIME_OMIT as _ }), - }; cfg_select! { any(target_os = "redox", target_os = "espidf", target_os = "horizon", target_os = "nuttx") => { // Redox doesn't appear to support `UTIME_OMIT`. @@ -1634,36 +1616,18 @@ pub fn set_times(&self, times: FileTimes) -> io::Result<()> { )) } target_vendor = "apple" => { - let mut buf = [mem::MaybeUninit::<libc::timespec>::uninit(); 3]; - let mut num_times = 0; - let mut attrlist: libc::attrlist = unsafe { mem::zeroed() }; - attrlist.bitmapcount = libc::ATTR_BIT_MAP_COUNT; - if times.created.is_some() { - buf[num_times].write(to_timespec(times.created)?); - num_times += 1; - attrlist.commonattr |= libc::ATTR_CMN_CRTIME; - } - if times.modified.is_some() { - buf[num_times].write(to_timespec(times.modified)?); - num_times += 1; - attrlist.commonattr |= libc::ATTR_CMN_MODTIME; - } - if times.accessed.is_some() { - buf[num_times].write(to_timespec(times.accessed)?); - num_times += 1; - attrlist.commonattr |= libc::ATTR_CMN_ACCTIME; - } + let ta = TimesAttrlist::from_times(×)?; cvt(unsafe { libc::fsetattrlist( self.as_raw_fd(), - (&raw const attrlist).cast::<libc::c_void>().cast_mut(), - buf.as_ptr().cast::<libc::c_void>().cast_mut(), - num_times * size_of::<libc::timespec>(), + ta.attrlist(), + ta.times_buf(), + ta.times_buf_size(), 0 ) })?; Ok(()) } target_os = "android" => { - let times = [to_timespec(times.accessed)?, to_timespec(times.modified)?]; + let times = [file_time_to_timespec(times.accessed)?, file_time_to_timespec(times.modified)?]; // futimens requires Android API level 19 cvt(unsafe { weak!( @@ -1697,7 +1661,7 @@ pub fn set_times(&self, times: FileTimes) -> io::Result<()> { return Ok(()); } } - let times = [to_timespec(times.accessed)?, to_timespec(times.modified)?]; + let times = [file_time_to_timespec(times.accessed)?, file_time_to_timespec(times.modified)?]; cvt(unsafe { libc::futimens(self.as_raw_fd(), times.as_ptr()) })?; Ok(()) } @@ -1705,6 +1669,74 @@ pub fn set_times(&self, times: FileTimes) -> io::Result<()> { } } +#[cfg(not(any( + target_os = "redox", + target_os = "espidf", + target_os = "horizon", + target_os = "nuttx", +)))] +fn file_time_to_timespec(time: Option<SystemTime>) -> io::Result<libc::timespec> { + match time { + Some(time) if let Some(ts) = time.t.to_timespec() => Ok(ts), + Some(time) if time > crate::sys::time::UNIX_EPOCH => Err(io::const_error!( + io::ErrorKind::InvalidInput, + "timestamp is too large to set as a file time", + )), + Some(_) => Err(io::const_error!( + io::ErrorKind::InvalidInput, + "timestamp is too small to set as a file time", + )), + None => Ok(libc::timespec { tv_sec: 0, tv_nsec: libc::UTIME_OMIT as _ }), + } +} + +#[cfg(target_vendor = "apple")] +struct TimesAttrlist { + buf: [mem::MaybeUninit<libc::timespec>; 3], + attrlist: libc::attrlist, + num_times: usize, +} + +#[cfg(target_vendor = "apple")] +impl TimesAttrlist { + fn from_times(times: &FileTimes) -> io::Result<Self> { + let mut this = Self { + buf: [mem::MaybeUninit::<libc::timespec>::uninit(); 3], + attrlist: unsafe { mem::zeroed() }, + num_times: 0, + }; + this.attrlist.bitmapcount = libc::ATTR_BIT_MAP_COUNT; + if times.created.is_some() { + this.buf[this.num_times].write(file_time_to_timespec(times.created)?); + this.num_times += 1; + this.attrlist.commonattr |= libc::ATTR_CMN_CRTIME; + } + if times.modified.is_some() { + this.buf[this.num_times].write(file_time_to_timespec(times.modified)?); + this.num_times += 1; + this.attrlist.commonattr |= libc::ATTR_CMN_MODTIME; + } + if times.accessed.is_some() { + this.buf[this.num_times].write(file_time_to_timespec(times.accessed)?); + this.num_times += 1; + this.attrlist.commonattr |= libc::ATTR_CMN_ACCTIME; + } + Ok(this) + } + + fn attrlist(&self) -> *mut libc::c_void { + (&raw const self.attrlist).cast::<libc::c_void>().cast_mut() + } + + fn times_buf(&self) -> *mut libc::c_void { + self.buf.as_ptr().cast::<libc::c_void>().cast_mut() + } + + fn times_buf_size(&self) -> usize { + self.num_times * size_of::<libc::timespec>() + } +} + impl DirBuilder { pub fn new() -> DirBuilder { DirBuilder { mode: 0o777 } @@ -2081,6 +2113,87 @@ fn open_from(from: &Path) -> io::Result<(crate::fs::File, crate::fs::Metadata)> Ok((reader, metadata)) } +fn set_times_impl(p: &CStr, times: FileTimes, follow_symlinks: bool) -> io::Result<()> { + cfg_select! { + any(target_os = "redox", target_os = "espidf", target_os = "horizon", target_os = "nuttx") => { + let _ = (p, times, follow_symlinks); + Err(io::const_error!( + io::ErrorKind::Unsupported, + "setting file times not supported", + )) + } + target_vendor = "apple" => { + // Apple platforms use setattrlist which supports setting times on symlinks + let ta = TimesAttrlist::from_times(×)?; + let options = if follow_symlinks { + 0 + } else { + libc::FSOPT_NOFOLLOW + }; + + cvt(unsafe { libc::setattrlist( + p.as_ptr(), + ta.attrlist(), + ta.times_buf(), + ta.times_buf_size(), + options as u32 + ) })?; + Ok(()) + } + target_os = "android" => { + let times = [file_time_to_timespec(times.accessed)?, file_time_to_timespec(times.modified)?]; + let flags = if follow_symlinks { 0 } else { libc::AT_SYMLINK_NOFOLLOW }; + // utimensat requires Android API level 19 + cvt(unsafe { + weak!( + fn utimensat(dirfd: c_int, path: *const libc::c_char, times: *const libc::timespec, flags: c_int) -> c_int; + ); + match utimensat.get() { + Some(utimensat) => utimensat(libc::AT_FDCWD, p.as_ptr(), times.as_ptr(), flags), + None => return Err(io::const_error!( + io::ErrorKind::Unsupported, + "setting file times requires Android API level >= 19", + )), + } + })?; + Ok(()) + } + _ => { + let flags = if follow_symlinks { 0 } else { libc::AT_SYMLINK_NOFOLLOW }; + #[cfg(all(target_os = "linux", target_env = "gnu", target_pointer_width = "32", not(target_arch = "riscv32")))] + { + use crate::sys::{time::__timespec64, weak::weak}; + + // Added in glibc 2.34 + weak!( + fn __utimensat64(dirfd: c_int, path: *const c_char, times: *const __timespec64, flags: c_int) -> c_int; + ); + + if let Some(utimensat64) = __utimensat64.get() { + let to_timespec = |time: Option<SystemTime>| time.map(|time| time.t.to_timespec64()) + .unwrap_or(__timespec64::new(0, libc::UTIME_OMIT as _)); + let times = [to_timespec(times.accessed), to_timespec(times.modified)]; + cvt(unsafe { utimensat64(libc::AT_FDCWD, p.as_ptr(), times.as_ptr(), flags) })?; + return Ok(()); + } + } + let times = [file_time_to_timespec(times.accessed)?, file_time_to_timespec(times.modified)?]; + cvt(unsafe { libc::utimensat(libc::AT_FDCWD, p.as_ptr(), times.as_ptr(), flags) })?; + Ok(()) + } + } +} + +#[inline(always)] +pub fn set_times(p: &CStr, times: FileTimes) -> io::Result<()> { + set_times_impl(p, times, true) +} + +#[inline(always)] +pub fn set_times_nofollow(p: &CStr, times: FileTimes) -> io::Result<()> { + set_times_impl(p, times, false) +} + #[cfg(target_os = "espidf")] fn open_to_and_set_permissions( to: &Path,
diff --git a/library/std/src/sys/fs/unsupported.rs b/library/std/src/sys/fs/unsupported.rs index efaddb5..f222151 100644 --- a/library/std/src/sys/fs/unsupported.rs +++ b/library/std/src/sys/fs/unsupported.rs
@@ -312,6 +312,14 @@ pub fn set_perm(_p: &Path, perm: FilePermissions) -> io::Result<()> { match perm.0 {} } +pub fn set_times(_p: &Path, _times: FileTimes) -> io::Result<()> { + unsupported() +} + +pub fn set_times_nofollow(_p: &Path, _times: FileTimes) -> io::Result<()> { + unsupported() +} + pub fn rmdir(_p: &Path) -> io::Result<()> { unsupported() }
diff --git a/library/std/src/sys/fs/vexos.rs b/library/std/src/sys/fs/vexos.rs index f642e7c..99b156d 100644 --- a/library/std/src/sys/fs/vexos.rs +++ b/library/std/src/sys/fs/vexos.rs
@@ -492,6 +492,14 @@ pub fn set_perm(_p: &Path, _perm: FilePermissions) -> io::Result<()> { unsupported() } +pub fn set_times(_p: &Path, _times: FileTimes) -> io::Result<()> { + unsupported() +} + +pub fn set_times_nofollow(_p: &Path, _times: FileTimes) -> io::Result<()> { + unsupported() +} + pub fn exists(path: &Path) -> io::Result<bool> { run_path_with_cstr(path, &|path| Ok(unsafe { vex_sdk::vexFileStatus(path.as_ptr()) } != 0)) }
diff --git a/library/std/src/sys/fs/wasi.rs b/library/std/src/sys/fs/wasi.rs index 0b65b9c..92eb353 100644 --- a/library/std/src/sys/fs/wasi.rs +++ b/library/std/src/sys/fs/wasi.rs
@@ -536,17 +536,9 @@ pub fn set_permissions(&self, _perm: FilePermissions) -> io::Result<()> { } pub fn set_times(&self, times: FileTimes) -> io::Result<()> { - let to_timestamp = |time: Option<SystemTime>| match time { - Some(time) if let Some(ts) = time.to_wasi_timestamp() => Ok(ts), - Some(_) => Err(io::const_error!( - io::ErrorKind::InvalidInput, - "timestamp is too large to set as a file time", - )), - None => Ok(0), - }; self.fd.filestat_set_times( - to_timestamp(times.accessed)?, - to_timestamp(times.modified)?, + to_wasi_timestamp_or_now(times.accessed)?, + to_wasi_timestamp_or_now(times.modified)?, times.accessed.map_or(0, |_| wasi::FSTFLAGS_ATIM) | times.modified.map_or(0, |_| wasi::FSTFLAGS_MTIM), ) @@ -643,6 +635,45 @@ pub fn set_perm(_p: &Path, _perm: FilePermissions) -> io::Result<()> { unsupported() } +#[inline(always)] +pub fn set_times(p: &Path, times: FileTimes) -> io::Result<()> { + let (dir, file) = open_parent(p)?; + set_times_impl(&dir, &file, times, wasi::LOOKUPFLAGS_SYMLINK_FOLLOW) +} + +#[inline(always)] +pub fn set_times_nofollow(p: &Path, times: FileTimes) -> io::Result<()> { + let (dir, file) = open_parent(p)?; + set_times_impl(&dir, &file, times, 0) +} + +fn to_wasi_timestamp_or_now(time: Option<SystemTime>) -> io::Result<wasi::Timestamp> { + match time { + Some(time) if let Some(ts) = time.to_wasi_timestamp() => Ok(ts), + Some(_) => Err(io::const_error!( + io::ErrorKind::InvalidInput, + "timestamp is too large to set as a file time", + )), + None => Ok(0), + } +} + +fn set_times_impl( + fd: &WasiFd, + path: &Path, + times: FileTimes, + flags: wasi::Lookupflags, +) -> io::Result<()> { + fd.path_filestat_set_times( + flags, + osstr2str(path.as_ref())?, + to_wasi_timestamp_or_now(times.accessed)?, + to_wasi_timestamp_or_now(times.modified)?, + times.accessed.map_or(0, |_| wasi::FSTFLAGS_ATIM) + | times.modified.map_or(0, |_| wasi::FSTFLAGS_MTIM), + ) +} + pub fn rmdir(p: &Path) -> io::Result<()> { let (dir, file) = open_parent(p)?; dir.remove_directory(osstr2str(file.as_ref())?)
diff --git a/library/std/src/sys/fs/windows.rs b/library/std/src/sys/fs/windows.rs index ccfe410..f2d325d 100644 --- a/library/std/src/sys/fs/windows.rs +++ b/library/std/src/sys/fs/windows.rs
@@ -1514,6 +1514,23 @@ pub fn set_perm(p: &WCStr, perm: FilePermissions) -> io::Result<()> { } } +pub fn set_times(p: &WCStr, times: FileTimes) -> io::Result<()> { + let mut opts = OpenOptions::new(); + opts.write(true); + opts.custom_flags(c::FILE_FLAG_BACKUP_SEMANTICS); + let file = File::open_native(p, &opts)?; + file.set_times(times) +} + +pub fn set_times_nofollow(p: &WCStr, times: FileTimes) -> io::Result<()> { + let mut opts = OpenOptions::new(); + opts.write(true); + // `FILE_FLAG_OPEN_REPARSE_POINT` for no_follow behavior + opts.custom_flags(c::FILE_FLAG_BACKUP_SEMANTICS | c::FILE_FLAG_OPEN_REPARSE_POINT); + let file = File::open_native(p, &opts)?; + file.set_times(times) +} + fn get_path(f: &File) -> io::Result<PathBuf> { fill_utf16_buf( |buf, sz| unsafe {
diff --git a/library/std/src/sys/thread/unix.rs b/library/std/src/sys/thread/unix.rs index 2d2c4f9..2a3e3a9 100644 --- a/library/std/src/sys/thread/unix.rs +++ b/library/std/src/sys/thread/unix.rs
@@ -314,13 +314,10 @@ pub fn available_parallelism() -> io::Result<NonZero<usize>> { target_os = "vxworks" => { // Note: there is also `vxCpuConfiguredGet`, closer to _SC_NPROCESSORS_CONF // expectations than the actual cores availability. - unsafe extern "C" { - fn vxCpuEnabledGet() -> libc::cpuset_t; - } // SAFETY: `vxCpuEnabledGet` always fetches a mask with at least one bit set unsafe{ - let set = vxCpuEnabledGet(); + let set = libc::vxCpuEnabledGet(); Ok(NonZero::new_unchecked(set.count_ones() as usize)) } }
diff --git a/library/std/src/sys_common/mod.rs b/library/std/src/sys_common/mod.rs index ec45c72..c6cb1b0 100644 --- a/library/std/src/sys_common/mod.rs +++ b/library/std/src/sys_common/mod.rs
@@ -15,7 +15,6 @@ //! Progress on this is tracked in #84187. #![allow(missing_docs)] -#![allow(missing_debug_implementations)] #[cfg(test)] mod tests;
diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs index fd7cce3..16313da 100644 --- a/library/std/src/thread/mod.rs +++ b/library/std/src/thread/mod.rs
@@ -620,9 +620,8 @@ fn drop(&mut self) { /// (It is the responsibility of the program to either eventually join threads it /// creates or detach them; otherwise, a resource leak will result.) /// -/// This call will create a thread using default parameters of [`Builder`], if you -/// want to specify the stack size or the name of the thread, use this API -/// instead. +/// This function creates a thread with the default parameters of [`Builder`]. +/// To specify the new thread's stack size or the name, use [`Builder::spawn`]. /// /// As you can see in the signature of `spawn` there are two constraints on /// both the closure given to `spawn` and its return value, let's explain them:
diff --git a/library/std/src/thread/scoped.rs b/library/std/src/thread/scoped.rs index a4c0ca5..75a5303 100644 --- a/library/std/src/thread/scoped.rs +++ b/library/std/src/thread/scoped.rs
@@ -181,9 +181,8 @@ impl<'scope, 'env> Scope<'scope, 'env> { /// end of the scope. In that case, if the spawned thread panics, [`scope`] will /// panic after all threads are joined. /// - /// This call will create a thread using default parameters of [`Builder`]. - /// If you want to specify the stack size or the name of the thread, use - /// [`Builder::spawn_scoped`] instead. + /// This function creates a thread with the default parameters of [`Builder`]. + /// To specify the new thread's stack size or the name, use [`Builder::spawn_scoped`]. /// /// # Panics ///
diff --git a/library/std/tests/sync/condvar.rs b/library/std/tests/sync/condvar.rs index 2a525f9..42b880e 100644 --- a/library/std/tests/sync/condvar.rs +++ b/library/std/tests/sync/condvar.rs
@@ -285,17 +285,31 @@ thread::scope(|s| { s.spawn(|| { + // Sleep so that the other thread has a chance to encounter the + // timeout. thread::sleep(Duration::from_secs(2)); maybe_unwrap(sent.set(true)); cond.notify_all(); }); - let guard = maybe_unwrap(sent.lock()); - // If there is internal overflow, this call will return almost - // immediately, before the other thread has reached the `notify_all` - let (guard, res) = maybe_unwrap(cond.wait_timeout(guard, Duration::from_secs(u64::MAX.div_ceil(1_000_000_000)))); - assert!(!res.timed_out()); - assert!(*guard); + let mut guard = maybe_unwrap(sent.lock()); + // Loop until `sent` is set by the thread to guard against spurious + // wakeups. If the `wait_timeout` happens just before the signal by + // the other thread, such a spurious wakeup might prevent the + // miscalculated timeout from occurring, but this is basically just + // a smoke test anyway. + loop { + if *guard { + break; + } + + // If there is internal overflow, this call will return almost + // immediately, before the other thread has reached the `notify_all`, + // and indicate a timeout. + let (g, res) = maybe_unwrap(cond.wait_timeout(guard, Duration::from_secs(u64::MAX.div_ceil(1_000_000_000)))); + assert!(!res.timed_out()); + guard = g; + } }) } );
diff --git a/src/bootstrap/Cargo.lock b/src/bootstrap/Cargo.lock index fe83265..5a2adb2 100644 --- a/src/bootstrap/Cargo.lock +++ b/src/bootstrap/Cargo.lock
@@ -491,9 +491,9 @@ [[package]] name = "object" -version = "0.36.5" +version = "0.37.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aedf0a2d09c573ed1d8d85b30c119153926a2b36dce0ab28322c09a117a4683e" +checksum = "ff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fe" dependencies = [ "memchr", ]
diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml index 9a76a7d..e1725db 100644 --- a/src/bootstrap/Cargo.toml +++ b/src/bootstrap/Cargo.toml
@@ -41,7 +41,7 @@ home = "0.5" ignore = "0.4" libc = "0.2" -object = { version = "0.36.3", default-features = false, features = ["archive", "coff", "read_core", "std", "unaligned"] } +object = { version = "0.37", default-features = false, features = ["archive", "coff", "read_core", "std", "unaligned"] } opener = "0.8" semver = "1.0" serde = "1.0"
diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index 85388d3..121ef69 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs
@@ -1016,6 +1016,15 @@ pub(crate) fn parse_inner( continue; } + // The rust.lld option is global, and not target specific, so if we enable it, it will + // be applied to all targets being built. + // So we only apply an override if we're building a compiler/host code for the given + // override target. + // Note: we could also make the LLD config per-target, but that would complicate things + if !hosts.contains(&TargetSelection::from_user(&target)) { + continue; + } + let default_linux_linker_override = match linker_override { DefaultLinuxLinkerOverride::Off => continue, DefaultLinuxLinkerOverride::SelfContainedLldCc => {
diff --git a/src/bootstrap/src/core/config/toml/llvm.rs b/src/bootstrap/src/core/config/toml/llvm.rs index 9751837..9523f80 100644 --- a/src/bootstrap/src/core/config/toml/llvm.rs +++ b/src/bootstrap/src/core/config/toml/llvm.rs
@@ -117,7 +117,7 @@ macro_rules! warn { enable_warnings, download_ci_llvm: _, build_config, - enzyme, + enzyme: _, } = ci_llvm_config; err!(current_llvm_config.optimize, optimize); @@ -139,7 +139,6 @@ macro_rules! warn { err!(current_llvm_config.clang, clang); err!(current_llvm_config.build_config, build_config); err!(current_llvm_config.plugins, plugins); - err!(current_llvm_config.enzyme, enzyme); warn!(current_llvm_config.enable_warnings, enable_warnings);
diff --git a/src/bootstrap/src/core/config/toml/rust.rs b/src/bootstrap/src/core/config/toml/rust.rs index 5a2c6e1..cb48c7d 100644 --- a/src/bootstrap/src/core/config/toml/rust.rs +++ b/src/bootstrap/src/core/config/toml/rust.rs
@@ -321,7 +321,6 @@ macro_rules! warn { debuginfo_level_rustc, llvm_tools, llvm_bitcode_linker, - lto, stack_protector, strip, jemalloc, @@ -354,6 +353,7 @@ macro_rules! warn { save_toolstates: _, codegen_backends: _, lld: _, + lto: _, deny_warnings: _, backtrace_on_ice: _, verify_llvm_ir: _, @@ -393,7 +393,6 @@ macro_rules! warn { err!(current_rust_config.jemalloc, jemalloc, "rust"); err!(current_rust_config.default_linker, default_linker, "rust"); err!(current_rust_config.stack_protector, stack_protector, "rust"); - err!(current_rust_config.lto, lto, "rust"); err!(current_rust_config.std_features, std_features, "rust"); warn!(current_rust_config.channel, channel, "rust");
diff --git a/src/bootstrap/src/utils/change_tracker.rs b/src/bootstrap/src/utils/change_tracker.rs index ea5fc77..921f57e 100644 --- a/src/bootstrap/src/utils/change_tracker.rs +++ b/src/bootstrap/src/utils/change_tracker.rs
@@ -571,4 +571,9 @@ pub fn human_readable_changes(changes: &[ChangeInfo]) -> String { severity: ChangeSeverity::Warning, summary: "`rust.lld = true` no longer automatically causes the `x86_64-unknown-linux-gnu` target to default into using the self-contained LLD linker. This target now uses the LLD linker by default. To opt out, set `target.x86_64-unknown-linux-gnu.default-linker-linux-override = 'off'`.", }, + ChangeInfo { + change_id: 147888, + severity: ChangeSeverity::Info, + summary: "`llvm.enzyme` now works with `download-ci-llvm=true`.", + }, ];
diff --git a/src/doc/rustc-dev-guide/src/autodiff/debugging.md b/src/doc/rustc-dev-guide/src/autodiff/debugging.md index 9789353..7c7af85 100644 --- a/src/doc/rustc-dev-guide/src/autodiff/debugging.md +++ b/src/doc/rustc-dev-guide/src/autodiff/debugging.md
@@ -25,7 +25,7 @@ ## 2) Check your llvm-ir reproducer -To confirm that your previous step worked, we will use llvm's `opt` tool. find your path to the opt binary, with a path similar to `<some_dir>/rust/build/<x86/arm/...-target-triple>/build/bin/opt`. also find `llvmenzyme-19.<so/dll/dylib>` path, similar to `/rust/build/target-triple/enzyme/build/enzyme/llvmenzyme-19`. Please keep in mind that llvm frequently updates it's llvm backend, so the version number might be higher (20, 21, ...). Once you have both, run the following command: +To confirm that your previous step worked, we will use llvm's `opt` tool. Find your path to the opt binary, with a path similar to `<some_dir>/rust/build/<x86/arm/...-target-triple>/ci-llvm/bin/opt`. If you build LLVM from source, you'll likely need to replace `ci-llvm` with `build`. Also find `llvmenzyme-21.<so/dll/dylib>` path, similar to `/rust/build/target-triple/enzyme/build/enzyme/llvmenzyme-21`. Please keep in mind that llvm frequently updates it's llvm backend, so the version number might be higher (20, 21, ...). Once you have both, run the following command: ```sh <path/to/opt> out.ll -load-pass-plugin=/path/to/build/<target-triple>/stage1/lib/libEnzyme-21.so -passes="enzyme" -enzyme-strict-aliasing=0 -s
diff --git a/src/doc/rustc-dev-guide/src/autodiff/installation.md b/src/doc/rustc-dev-guide/src/autodiff/installation.md index ddbb3a0..c9b6c85 100644 --- a/src/doc/rustc-dev-guide/src/autodiff/installation.md +++ b/src/doc/rustc-dev-guide/src/autodiff/installation.md
@@ -8,7 +8,7 @@ ```bash git clone git@github.com:rust-lang/rust cd rust -./configure --enable-llvm-link-shared --enable-llvm-plugins --enable-llvm-enzyme --release-channel=nightly --enable-llvm-assertions --enable-clang --enable-lld --enable-option-checking --enable-ninja --disable-docs +./configure --release-channel=nightly --enable-llvm-enzyme --enable-llvm-assertions --enable-option-checking --disable-docs --set llvm.download-ci-llvm=true ``` Afterwards you can build rustc using: @@ -47,7 +47,7 @@ ```bash git clone https://github.com/rust-lang/rust cd rust -./configure --enable-llvm-link-shared --enable-llvm-plugins --enable-llvm-enzyme --release-channel=nightly --enable-llvm-assertions --enable-clang --enable-lld --enable-option-checking --enable-ninja --disable-docs +./configure --release-channel=nightly --enable-llvm-enzyme --enable-llvm-assertions --enable-option-checking --disable-docs --set llvm.download-ci-llvm=true ./x dist ``` We then copy the tarball to our host. The dockerid is the newest entry under `docker ps -a`. @@ -84,5 +84,5 @@ cmake .. -G Ninja -DLLVM_DIR=<YourLocalPath>/llvm-project/build/lib/cmake/llvm/ -DLLVM_EXTERNAL_LIT=<YourLocalPath>/llvm-project/llvm/utils/lit/lit.py -DCMAKE_BUILD_TYPE=Release -DCMAKE_EXPORT_COMPILE_COMMANDS=YES -DBUILD_SHARED_LIBS=ON ninja ``` -This will build Enzyme, and you can find it in `Enzyme/enzyme/build/lib/<LLD/Clang/LLVM>Enzyme.so`. (Endings might differ based on your OS). +This will build Enzyme, and you can find it in `Enzyme/enzyme/build/lib/<LLD/Clang/LLVM/lib>Enzyme.so`. (Endings might differ based on your OS).
diff --git a/src/doc/rustc-dev-guide/src/borrow_check/moves_and_initialization/move_paths.md b/src/doc/rustc-dev-guide/src/borrow_check/moves_and_initialization/move_paths.md index 95518fb..9ed4e67 100644 --- a/src/doc/rustc-dev-guide/src/borrow_check/moves_and_initialization/move_paths.md +++ b/src/doc/rustc-dev-guide/src/borrow_check/moves_and_initialization/move_paths.md
@@ -67,8 +67,6 @@ used. In particular, if it is illegal to move from a [`Place`], then there is no need for a [`MovePathIndex`]. Some examples: -- You cannot move from a static variable, so we do not create a [`MovePathIndex`] - for static variables. - You cannot move an individual element of an array, so if we have e.g. `foo: [String; 3]`, there would be no move-path for `foo[1]`. - You cannot move from inside of a borrowed reference, so if we have e.g. `foo: &String`, @@ -82,6 +80,18 @@ [`move_path_for`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_dataflow/move_paths/builder/struct.MoveDataBuilder.html#method.move_path_for +## Projections + +Instead of using [`PlaceElem`], projections in move paths are stored as [`MoveSubPath`]s. +Projections that can't be moved out of and projections that can be skipped are not represented. + +Subslice projections of arrays (produced by slice patterns) are special; they're turned into +multiple [`ConstantIndex`] subpaths, one for each element in the subslice. + +[`PlaceElem`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/type.PlaceElem.html +[`MoveSubPath`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_dataflow/move_paths/enum.MoveSubPath.html +[`ConstantIndex`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir_dataflow/move_paths/enum.MoveSubPath.html#variant.ConstantIndex + ## Looking up a move-path If you have a [`Place`] and you would like to convert it to a [`MovePathIndex`], you
diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index 87fc404..4eb0dab 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md
@@ -432,7 +432,7 @@ `x86_64-unknown-l4re-uclibc` | ? | | [`x86_64-unknown-linux-none`](platform-support/x86_64-unknown-linux-none.md) | * | | 64-bit Linux with no libc [`x86_64-unknown-managarm-mlibc`](platform-support/managarm.md) | ? | | x86_64 Managarm -[`x86_64-unknown-motor`](platform-support/motor.md) | ? | | x86_64 Motor OS +[`x86_64-unknown-motor`](platform-support/motor.md) | ✓ | | x86_64 Motor OS [`x86_64-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | 64-bit OpenBSD [`x86_64-unknown-trusty`](platform-support/trusty.md) | ✓ | | `x86_64-uwp-windows-gnu` | ✓ | |
diff --git a/src/doc/rustc/src/platform-support/motor.md b/src/doc/rustc/src/platform-support/motor.md index e7aa7b2..6d44d17 100644 --- a/src/doc/rustc/src/platform-support/motor.md +++ b/src/doc/rustc/src/platform-support/motor.md
@@ -15,27 +15,35 @@ Motor OS uses the ELF file format. -## Building the target +## Building the target toolchain -The target can be built by enabling it for a `rustc` build, for example: +Motor OS target toolchain can be +[built using `x.py`](https://rustc-dev-guide.rust-lang.org/building/how-to-build-and-run.html): + +The bootstrap file: ```toml [build] -build-stage = 2 -target = ["x86_64-unknown-motor"] +host = ["x86_64-unknown-linux-gnu"] +target = ["x86_64-unknown-linux-gnu", "x86_64-unknown-motor"] +``` + +The build command: + +```sh +./x.py build --stage 2 clippy library ``` ## Building Rust programs -Rust standard library is fully supported/implemented, but is not yet part of -the official Rust repo, so an out-of-tree building process should be -followed, as described in the -[build doc](https://github.com/moturus/motor-os/blob/main/docs/build.md). +See the [Hello Motor OS](https://github.com/moturus/motor-os/blob/main/docs/recipes/hello-motor-os.md) +example. ## Testing Cross-compiled Rust binaries and test artifacts can be executed in Motor OS VMs, -as described in e.g. +as described in the [build doc](https://github.com/moturus/motor-os/blob/main/docs/build.md) +and the [Hello Motor OS](https://github.com/moturus/motor-os/blob/main/docs/recipes/hello-motor-os.md) example.
diff --git a/src/librustdoc/Cargo.toml b/src/librustdoc/Cargo.toml index f9c2465..63412e2 100644 --- a/src/librustdoc/Cargo.toml +++ b/src/librustdoc/Cargo.toml
@@ -21,7 +21,7 @@ serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" smallvec = "1.8.1" -stringdex = { version = "0.0.1-alpha10" } +stringdex = "=0.0.2" tempfile = "3" threadpool = "1.8.1" tracing = "0.1"
diff --git a/src/librustdoc/clean/blanket_impl.rs b/src/librustdoc/clean/blanket_impl.rs index 100e07f..ddfce7a 100644 --- a/src/librustdoc/clean/blanket_impl.rs +++ b/src/librustdoc/clean/blanket_impl.rs
@@ -34,7 +34,7 @@ pub(crate) fn synthesize_blanket_impls( 'blanket_impls: for &impl_def_id in trait_impls.blanket_impls() { trace!("considering impl `{impl_def_id:?}` for trait `{trait_def_id:?}`"); - let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap(); + let trait_ref = tcx.impl_trait_ref(impl_def_id); if !matches!(trait_ref.skip_binder().self_ty().kind(), ty::Param(_)) { continue; }
diff --git a/src/librustdoc/clean/cfg.rs b/src/librustdoc/clean/cfg.rs index 881a81b..6c77e41 100644 --- a/src/librustdoc/clean/cfg.rs +++ b/src/librustdoc/clean/cfg.rs
@@ -751,7 +751,7 @@ fn check_changed_auto_active_status( } for attr in doc_cfg { if let Some(cfg_mi) = - attr.meta_item().and_then(|attr| rustc_expand::config::parse_cfg(attr, sess)) + attr.meta_item().and_then(|attr| rustc_expand::config::parse_cfg_old(attr, sess)) { match Cfg::parse(cfg_mi) { Ok(new_cfg) => cfg_info.current_cfg &= new_cfg,
diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 971c7f6..b470af5 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs
@@ -448,7 +448,7 @@ pub(crate) fn build_impl( let tcx = cx.tcx; let _prof_timer = tcx.sess.prof.generic_activity("build_impl"); - let associated_trait = tcx.impl_trait_ref(did).map(ty::EarlyBinder::skip_binder); + let associated_trait = tcx.impl_opt_trait_ref(did).map(ty::EarlyBinder::skip_binder); // Do not inline compiler-internal items unless we're a compiler-internal crate. let is_compiler_internal = |did| { @@ -566,7 +566,11 @@ pub(crate) fn build_impl( clean::enter_impl_trait(cx, |cx| clean_ty_generics(cx, did)), ), }; - let polarity = tcx.impl_polarity(did); + let polarity = if associated_trait.is_some() { + tcx.impl_polarity(did) + } else { + ty::ImplPolarity::Positive + }; let trait_ = associated_trait .map(|t| clean_trait_ref_with_constraints(cx, ty::Binder::dummy(t), ThinVec::new())); if trait_.as_ref().map(|t| t.def_id()) == tcx.lang_items().deref_trait() {
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 481395f..4a95f21 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs
@@ -2934,7 +2934,11 @@ fn clean_impl<'tcx>( trait_, for_, items, - polarity: tcx.impl_polarity(def_id), + polarity: if impl_.of_trait.is_some() { + tcx.impl_polarity(def_id) + } else { + ty::ImplPolarity::Positive + }, kind: if utils::has_doc_flag(tcx, def_id.to_def_id(), sym::fake_variadic) { ImplKind::FakeVariadic } else {
diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index c3b1e3e..13178ee 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs
@@ -2403,7 +2403,7 @@ fn get_id_for_impl(tcx: TyCtxt<'_>, impl_id: ItemId) -> String { (ty, Some(ty::TraitRef::new(tcx, trait_, [ty]))) } ItemId::Blanket { impl_id, .. } | ItemId::DefId(impl_id) => { - if let Some(trait_ref) = tcx.impl_trait_ref(impl_id) { + if let Some(trait_ref) = tcx.impl_opt_trait_ref(impl_id) { let trait_ref = trait_ref.skip_binder(); (trait_ref.self_ty(), Some(trait_ref)) } else {
diff --git a/src/librustdoc/html/static/js/stringdex.js b/src/librustdoc/html/static/js/stringdex.js index 6299576..d8b8c5b 100644 --- a/src/librustdoc/html/static/js/stringdex.js +++ b/src/librustdoc/html/static/js/stringdex.js
@@ -1447,7 +1447,7 @@ makeSearchTreeBranchesAlphaBitmapClass(LONG_ALPHABITMAP_CHARS, 4); /** - * @typedef {PrefixSearchTree|SuffixSearchTree} SearchTree + * @typedef {PrefixSearchTree|SuffixSearchTree|InlineNeighborsTree} SearchTree * @typedef {PrefixTrie|SuffixTrie} Trie */ @@ -1675,9 +1675,12 @@ yield leaves; } } - /** @type {HashTable<[number, SearchTree][]>} */ + /** @type {HashTable<[number, PrefixSearchTree|SuffixSearchTree][]>} */ const subnodes = new HashTable(); - for await (const node of current_layer) { + for await (const nodeEncoded of current_layer) { + const node = nodeEncoded instanceof InlineNeighborsTree ? + nodeEncoded.decode() : + nodeEncoded; const branches = node.branches; const l = branches.subtrees.length; for (let i = 0; i < l; ++i) { @@ -1741,7 +1744,10 @@ // we then yield the smallest ones (can't yield bigger ones // if we want to do them in order) for (const {node, len} of current_layer) { - const tree = await node; + const treeEncoded = await node; + const tree = treeEncoded instanceof InlineNeighborsTree ? + treeEncoded.decode() : + treeEncoded; if (!(tree instanceof PrefixSearchTree)) { continue; } @@ -1804,7 +1810,10 @@ /** @type {HashTable<{byte: number, tree: PrefixSearchTree, len: number}[]>} */ const subnodes = new HashTable(); for await (const {node, len} of current_layer) { - const tree = await node; + const treeEncoded = await node; + const tree = treeEncoded instanceof InlineNeighborsTree ? + treeEncoded.decode() : + treeEncoded; if (!(tree instanceof PrefixSearchTree)) { continue; } @@ -2166,9 +2175,12 @@ yield leaves; } } - /** @type {HashTable<[number, SearchTree][]>} */ + /** @type {HashTable<[number, PrefixSearchTree|SuffixSearchTree][]>} */ const subnodes = new HashTable(); - for await (const node of current_layer) { + for await (const nodeEncoded of current_layer) { + const node = nodeEncoded instanceof InlineNeighborsTree ? + nodeEncoded.decode() : + nodeEncoded; const branches = node.branches; const l = branches.subtrees.length; for (let i = 0; i < l; ++i) { @@ -2264,6 +2276,174 @@ } } + /** + * Represents a subtree where all transitive leaves + * have a shared 16bit prefix and there are no sub-branches. + */ + class InlineNeighborsTree { + /** + * @param {Uint8Array} encoded + * @param {number} start + */ + constructor( + encoded, + start, + ) { + this.encoded = encoded; + this.start = start; + } + /** + * @return {PrefixSearchTree|SuffixSearchTree} + */ + decode() { + let i = this.start; + const encoded = this.encoded; + const has_branches = (encoded[i] & 0x04) !== 0; + /** @type {boolean} */ + const is_suffixes_only = (encoded[i] & 0x01) !== 0; + let leaves_count = ((encoded[i] >> 4) & 0x0f) + 1; + i += 1; + let branch_count = 0; + if (has_branches) { + branch_count = encoded[i] + 1; + i += 1; + } + const dlen = encoded[i] & 0x3f; + if ((encoded[i] & 0x80) !== 0) { + leaves_count = 0; + } + i += 1; + let data = EMPTY_UINT8; + if (!is_suffixes_only && dlen !== 0) { + data = encoded.subarray(i, i + dlen); + i += dlen; + } + const leaf_value_upper = encoded[i] | (encoded[i + 1] << 8); + i += 2; + /** @type {Promise<SearchTree>[]} */ + const branch_nodes = []; + for (let j = 0; j < branch_count; j += 1) { + const branch_dlen = encoded[i] & 0x0f; + const branch_leaves_count = ((encoded[i] >> 4) & 0x0f) + 1; + i += 1; + let branch_data = EMPTY_UINT8; + if (!is_suffixes_only && branch_dlen !== 0) { + branch_data = encoded.subarray(i, i + branch_dlen); + i += branch_dlen; + } + const branch_leaves = new RoaringBitmap(null); + branch_leaves.keysAndCardinalities = Uint8Array.of( + leaf_value_upper & 0xff, + (leaf_value_upper >> 8) & 0xff, + (branch_leaves_count - 1) & 0xff, + ((branch_leaves_count - 1) >> 8) & 0xff, + ); + branch_leaves.containers = [ + new RoaringBitmapArray( + branch_leaves_count, + encoded.subarray(i, i + (branch_leaves_count * 2)), + ), + ]; + i += branch_leaves_count * 2; + branch_nodes.push(Promise.resolve( + is_suffixes_only ? + new SuffixSearchTree( + EMPTY_SEARCH_TREE_BRANCHES, + branch_dlen, + branch_leaves, + ) : + new PrefixSearchTree( + EMPTY_SEARCH_TREE_BRANCHES, + EMPTY_SEARCH_TREE_BRANCHES, + branch_data, + branch_leaves, + EMPTY_BITMAP, + ), + )); + } + /** @type {SearchTreeBranchesArray<SearchTree>} */ + const branches = branch_count === 0 ? + EMPTY_SEARCH_TREE_BRANCHES : + new SearchTreeBranchesArray( + encoded.subarray(i, i + branch_count), + EMPTY_UINT8, + ); + i += branch_count; + branches.subtrees = branch_nodes; + let leaves = EMPTY_BITMAP; + if (leaves_count !== 0) { + leaves = new RoaringBitmap(null); + leaves.keysAndCardinalities = Uint8Array.of( + leaf_value_upper & 0xff, + (leaf_value_upper >> 8) & 0xff, + (leaves_count - 1) & 0xff, + ((leaves_count - 1) >> 8) & 0xff, + ); + leaves.containers = [ + new RoaringBitmapArray( + leaves_count, + encoded.subarray(i, i + (leaves_count * 2)), + ), + ]; + i += leaves_count * 2; + } + return is_suffixes_only ? + new SuffixSearchTree( + branches, + dlen, + leaves, + ) : + new PrefixSearchTree( + branches, + branches, + data, + leaves, + EMPTY_BITMAP, + ); + } + + /** + * Returns the Trie for the root node. + * + * A Trie pointer refers to a single node in a logical decompressed search tree + * (the real search tree is compressed). + * + * @param {DataColumn} dataColumn + * @param {Uint8ArraySearchPattern} searchPattern + * @return {Trie} + */ + trie(dataColumn, searchPattern) { + const tree = this.decode(); + return tree instanceof SuffixSearchTree ? + new SuffixTrie(tree, 0, dataColumn, searchPattern) : + new PrefixTrie(tree, 0, dataColumn, searchPattern); + } + + /** + * Return the trie representing `name` + * @param {Uint8Array|string} name + * @param {DataColumn} dataColumn + * @returns {Promise<Trie?>} + */ + search(name, dataColumn) { + return this.decode().search(name, dataColumn); + } + + /** + * @param {Uint8Array|string} name + * @param {DataColumn} dataColumn + * @returns {AsyncGenerator<Trie>} + */ + searchLev(name, dataColumn) { + return this.decode().searchLev(name, dataColumn); + } + + /** @returns {RoaringBitmap} */ + getCurrentLeaves() { + return this.decode().getCurrentLeaves(); + } + } + class DataColumn { /** * Construct the wrapper object for a data column. @@ -2765,21 +2945,37 @@ // because that's the canonical, hashed version of the data let compression_tag = input[i]; const is_pure_suffixes_only_node = (compression_tag & 0x01) !== 0; + const is_long_compressed = (compression_tag & 0x04) !== 0; + const is_data_compressed = (compression_tag & 0x08) !== 0; + i += 1; + if (is_long_compressed) { + compression_tag |= input[i] << 8; + i += 1; + } + /** @type {number} */ + let dlen; + /** @type {number} */ let no_leaves_flag; - if (compression_tag > 1) { - // compressed node - const is_long_compressed = (compression_tag & 0x04) !== 0; - const is_data_compressed = (compression_tag & 0x08) !== 0; - i += 1; - if (is_long_compressed) { - compression_tag |= input[i] << 8; - i += 1; - compression_tag |= input[i] << 16; - i += 1; - } - let dlen = input[i] & 0x7F; + /** @type {number} */ + let inline_neighbors_flag; + if (is_data_compressed && is_pure_suffixes_only_node) { + dlen = 0; + no_leaves_flag = 0x80; + inline_neighbors_flag = 0; + } else { + dlen = input[i] & 0x3F; no_leaves_flag = input[i] & 0x80; + inline_neighbors_flag = input[i] & 0x40; i += 1; + } + if (inline_neighbors_flag !== 0) { + // node with packed leaves and common 16bit prefix + const leaves_count = no_leaves_flag !== 0 ? + 0 : + ((compression_tag >> 4) & 0x0f) + 1; + const branch_count = is_long_compressed ? + ((compression_tag >> 8) & 0xff) + 1 : + 0; if (is_data_compressed) { data = data_history[data_history.length - dlen - 1]; dlen = data.length; @@ -2791,6 +2987,72 @@ new Uint8Array(input.buffer, i + input.byteOffset, dlen); i += dlen; } + const branches_start = i; + // leaf_value_upper + i += 2; + // branch_nodes + for (let j = 0; j < branch_count; j += 1) { + const branch_dlen = input[i] & 0x0f; + const branch_leaves_count = ((input[i] >> 4) & 0x0f) + 1; + i += 1; + if (!is_pure_suffixes_only_node) { + i += branch_dlen; + } + i += branch_leaves_count * 2; + } + // branch keys + i += branch_count; + // leaves + i += leaves_count * 2; + if (is_data_compressed) { + const clen = ( + 1 + // first compression header byte + (is_long_compressed ? 1 : 0) + // branch count + 1 + // data length and other flags + dlen + // data + (i - branches_start) // branches and leaves + ); + const canonical = new Uint8Array(clen); + let ci = 0; + canonical[ci] = input[start] ^ 0x08; + ci += 1; + if (is_long_compressed) { + canonical[ci] = input[start + ci]; + ci += 1; + } + canonical[ci] = dlen | no_leaves_flag | 0x40; + ci += 1; + for (let j = 0; j < dlen; j += 1) { + canonical[ci] = data[j]; + ci += 1; + } + for (let j = branches_start; j < i; j += 1) { + canonical[ci] = input[j]; + ci += 1; + } + tree = new InlineNeighborsTree(canonical, 0); + siphashOfBytes(canonical, 0, 0, 0, 0, hash); + } else { + tree = new InlineNeighborsTree(input, start); + siphashOfBytes(new Uint8Array( + input.buffer, + start + input.byteOffset, + i - start, + ), 0, 0, 0, 0, hash); + } + } else if (compression_tag > 1) { + // compressed node + if (is_pure_suffixes_only_node) { + data = EMPTY_UINT8; + } else if (is_data_compressed) { + data = data_history[data_history.length - dlen - 1]; + dlen = data.length; + } else { + data = dlen === 0 ? + EMPTY_UINT8 : + new Uint8Array(input.buffer, i + input.byteOffset, dlen); + i += dlen; + } const coffset = i; const { cpbranches, @@ -2820,19 +3082,27 @@ suffix, ); const clen = ( - 3 + // lengths of children and data + // lengths of children and data + (is_data_compressed ? 2 : 3) + + // branches csnodes.length + csbranches.length + + // leaves suffix.consumed_len_bytes ); if (canonical.length < clen) { canonical = new Uint8Array(clen); } let ci = 0; - canonical[ci] = 1; - ci += 1; - canonical[ci] = dlen | no_leaves_flag; - ci += 1; + if (is_data_compressed) { + canonical[ci] = 0x09; + ci += 1; + } else { + canonical[ci] = 1; + ci += 1; + canonical[ci] = dlen | no_leaves_flag; + ci += 1; + } canonical[ci] = input[coffset]; // suffix child count ci += 1; canonical.set(csnodes, ci); @@ -2901,13 +3171,8 @@ } siphashOfBytes(canonical.subarray(0, clen), 0, 0, 0, 0, hash); } - hash[2] &= 0x7f; } else { - i += 1; // uncompressed node - const dlen = input[i] & 0x7F; - no_leaves_flag = input[i] & 0x80; - i += 1; if (dlen === 0 || is_pure_suffixes_only_node) { data = EMPTY_UINT8; } else { @@ -2946,7 +3211,6 @@ start + input.byteOffset, i - start, ), 0, 0, 0, 0, hash); - hash[2] &= 0x7f; tree = is_pure_suffixes_only_node ? new SuffixSearchTree( branches, @@ -2961,30 +3225,33 @@ suffix, ); } + hash[2] &= 0x7f; hash_history.push({hash: truncatedHash.slice(), used: false}); if (data.length !== 0) { data_history.push(data); } - const tree_branch_nodeids = tree.branches.nodeids; - const tree_branch_subtrees = tree.branches.subtrees; - let j = 0; - let lb = tree.branches.subtrees.length; - while (j < lb) { - // node id with a 1 in its most significant bit is inlined, and, so - // it won't be in the stash - if ((tree_branch_nodeids[j * 6] & 0x80) === 0) { - const subtree = stash.getWithOffsetKey(tree_branch_nodeids, j * 6); - if (subtree !== undefined) { - tree_branch_subtrees[j] = Promise.resolve(subtree); + if (!(tree instanceof InlineNeighborsTree)) { + const tree_branch_nodeids = tree.branches.nodeids; + const tree_branch_subtrees = tree.branches.subtrees; + let j = 0; + const lb = tree.branches.subtrees.length; + while (j < lb) { + // node id with a 1 in its most significant bit is inlined, and, so + // it won't be in the stash + if ((tree_branch_nodeids[j * 6] & 0x80) === 0) { + const subtree = stash.getWithOffsetKey(tree_branch_nodeids, j * 6); + if (subtree !== undefined) { + tree_branch_subtrees[j] = Promise.resolve(subtree); + } } + j += 1; } - j += 1; } if (tree instanceof PrefixSearchTree) { const tree_mhp_branch_nodeids = tree.might_have_prefix_branches.nodeids; const tree_mhp_branch_subtrees = tree.might_have_prefix_branches.subtrees; - j = 0; - lb = tree.might_have_prefix_branches.subtrees.length; + let j = 0; + const lb = tree.might_have_prefix_branches.subtrees.length; while (j < lb) { // node id with a 1 in its most significant bit is inlined, and, so // it won't be in the stash
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 155abef..d09949e 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs
@@ -847,7 +847,7 @@ fn trait_impls_for<'a>( for &trait_ in tcx.doc_link_traits_in_scope(module) { tcx.for_each_relevant_impl(trait_, ty, |impl_| { - let trait_ref = tcx.impl_trait_ref(impl_).expect("this is not an inherent impl"); + let trait_ref = tcx.impl_trait_ref(impl_); // Check if these are the same type. let impl_type = trait_ref.skip_binder().self_ty(); trace!(
diff --git a/src/librustdoc/passes/mod.rs b/src/librustdoc/passes/mod.rs index f45df8d..856581e 100644 --- a/src/librustdoc/passes/mod.rs +++ b/src/librustdoc/passes/mod.rs
@@ -94,11 +94,11 @@ pub(crate) enum Condition { ConditionalPass::always(COLLECT_TRAIT_IMPLS), ConditionalPass::always(CHECK_DOC_TEST_VISIBILITY), ConditionalPass::always(CHECK_DOC_CFG), - ConditionalPass::always(COLLECT_INTRA_DOC_LINKS), ConditionalPass::always(STRIP_ALIASED_NON_LOCAL), ConditionalPass::new(STRIP_HIDDEN, WhenNotDocumentHidden), ConditionalPass::new(STRIP_PRIVATE, WhenNotDocumentPrivate), ConditionalPass::new(STRIP_PRIV_IMPORTS, WhenDocumentPrivate), + ConditionalPass::always(COLLECT_INTRA_DOC_LINKS), ConditionalPass::always(PROPAGATE_DOC_CFG), ConditionalPass::always(PROPAGATE_STABILITY), ConditionalPass::always(RUN_LINTS),
diff --git a/src/tools/clippy/clippy_lints/src/derive/derive_ord_xor_partial_ord.rs b/src/tools/clippy/clippy_lints/src/derive/derive_ord_xor_partial_ord.rs index 274c699..2bd5e2c 100644 --- a/src/tools/clippy/clippy_lints/src/derive/derive_ord_xor_partial_ord.rs +++ b/src/tools/clippy/clippy_lints/src/derive/derive_ord_xor_partial_ord.rs
@@ -28,7 +28,7 @@ pub(super) fn check<'tcx>( return; } - let trait_ref = cx.tcx.impl_trait_ref(impl_id).expect("must be a trait implementation"); + let trait_ref = cx.tcx.impl_trait_ref(impl_id); // Only care about `impl PartialOrd<Foo> for Foo` // For `impl PartialOrd<B> for A, input_types is [A, B]
diff --git a/src/tools/clippy/clippy_lints/src/derive/derived_hash_with_manual_eq.rs b/src/tools/clippy/clippy_lints/src/derive/derived_hash_with_manual_eq.rs index afc02ce..dc3fbe5 100644 --- a/src/tools/clippy/clippy_lints/src/derive/derived_hash_with_manual_eq.rs +++ b/src/tools/clippy/clippy_lints/src/derive/derived_hash_with_manual_eq.rs
@@ -27,7 +27,7 @@ pub(super) fn check<'tcx>( return; } - let trait_ref = cx.tcx.impl_trait_ref(impl_id).expect("must be a trait implementation"); + let trait_ref = cx.tcx.impl_trait_ref(impl_id); // Only care about `impl PartialEq<Foo> for Foo` // For `impl PartialEq<B> for A, input_types is [A, B]
diff --git a/src/tools/clippy/clippy_lints/src/fallible_impl_from.rs b/src/tools/clippy/clippy_lints/src/fallible_impl_from.rs index 4446b91..c42998f 100644 --- a/src/tools/clippy/clippy_lints/src/fallible_impl_from.rs +++ b/src/tools/clippy/clippy_lints/src/fallible_impl_from.rs
@@ -52,11 +52,9 @@ impl<'tcx> LateLintPass<'tcx> for FallibleImplFrom { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) { // check for `impl From<???> for ..` - if let hir::ItemKind::Impl(_) = &item.kind - && let Some(impl_trait_ref) = cx.tcx.impl_trait_ref(item.owner_id) - && cx - .tcx - .is_diagnostic_item(sym::From, impl_trait_ref.skip_binder().def_id) + if let hir::ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }) = &item.kind + && let impl_trait_id = cx.tcx.impl_trait_id(item.owner_id) + && cx.tcx.is_diagnostic_item(sym::From, impl_trait_id) { lint_impl_body(cx, item.owner_id, item.span); }
diff --git a/src/tools/clippy/clippy_lints/src/from_over_into.rs b/src/tools/clippy/clippy_lints/src/from_over_into.rs index fd80729..ed55f90 100644 --- a/src/tools/clippy/clippy_lints/src/from_over_into.rs +++ b/src/tools/clippy/clippy_lints/src/from_over_into.rs
@@ -76,8 +76,7 @@ fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) { // `impl Into<target_ty> for self_ty` && let Some(GenericArgs { args: [GenericArg::Type(target_ty)], .. }) = into_trait_seg.args && span_is_local(item.span) - && let Some(middle_trait_ref) = cx.tcx.impl_trait_ref(item.owner_id) - .map(ty::EarlyBinder::instantiate_identity) + && let middle_trait_ref = cx.tcx.impl_trait_ref(item.owner_id).instantiate_identity() && cx.tcx.is_diagnostic_item(sym::Into, middle_trait_ref.def_id) && !matches!(middle_trait_ref.args.type_at(1).kind(), ty::Alias(ty::Opaque, _)) && self.msrv.meets(cx, msrvs::RE_REBALANCING_COHERENCE)
diff --git a/src/tools/clippy/clippy_lints/src/implicit_saturating_sub.rs b/src/tools/clippy/clippy_lints/src/implicit_saturating_sub.rs index 678a299..7b6f872 100644 --- a/src/tools/clippy/clippy_lints/src/implicit_saturating_sub.rs +++ b/src/tools/clippy/clippy_lints/src/implicit_saturating_sub.rs
@@ -339,8 +339,7 @@ fn check_with_condition<'tcx>( ExprKind::Path(QPath::TypeRelative(_, name)) => { if name.ident.name == sym::MIN && let Some(const_id) = cx.typeck_results().type_dependent_def_id(cond_num_val.hir_id) - && let Some(impl_id) = cx.tcx.impl_of_assoc(const_id) - && let None = cx.tcx.impl_trait_ref(impl_id) // An inherent impl + && let Some(impl_id) = cx.tcx.inherent_impl_of_assoc(const_id) && cx.tcx.type_of(impl_id).instantiate_identity().is_integral() { print_lint_and_sugg(cx, var_name, expr); @@ -350,8 +349,7 @@ fn check_with_condition<'tcx>( if let ExprKind::Path(QPath::TypeRelative(_, name)) = func.kind && name.ident.name == sym::min_value && let Some(func_id) = cx.typeck_results().type_dependent_def_id(func.hir_id) - && let Some(impl_id) = cx.tcx.impl_of_assoc(func_id) - && let None = cx.tcx.impl_trait_ref(impl_id) // An inherent impl + && let Some(impl_id) = cx.tcx.inherent_impl_of_assoc(func_id) && cx.tcx.type_of(impl_id).instantiate_identity().is_integral() { print_lint_and_sugg(cx, var_name, expr);
diff --git a/src/tools/clippy/clippy_lints/src/methods/suspicious_splitn.rs b/src/tools/clippy/clippy_lints/src/methods/suspicious_splitn.rs index 9876681..be1481e 100644 --- a/src/tools/clippy/clippy_lints/src/methods/suspicious_splitn.rs +++ b/src/tools/clippy/clippy_lints/src/methods/suspicious_splitn.rs
@@ -10,8 +10,7 @@ pub(super) fn check(cx: &LateContext<'_>, method_name: Symbol, expr: &Expr<'_>, self_arg: &Expr<'_>, count: u128) { if count <= 1 && let Some(call_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id) - && let Some(impl_id) = cx.tcx.impl_of_assoc(call_id) - && cx.tcx.impl_trait_ref(impl_id).is_none() + && let Some(impl_id) = cx.tcx.inherent_impl_of_assoc(call_id) && let self_ty = cx.tcx.type_of(impl_id).instantiate_identity() && (self_ty.is_slice() || self_ty.is_str()) {
diff --git a/src/tools/clippy/clippy_lints/src/missing_inline.rs b/src/tools/clippy/clippy_lints/src/missing_inline.rs index 6323e72..bccc72c 100644 --- a/src/tools/clippy/clippy_lints/src/missing_inline.rs +++ b/src/tools/clippy/clippy_lints/src/missing_inline.rs
@@ -167,7 +167,7 @@ fn check_impl_item(&mut self, cx: &LateContext<'tcx>, impl_item: &'tcx hir::Impl let container_id = assoc_item.container_id(cx.tcx); let trait_def_id = match assoc_item.container { AssocContainer::Trait => Some(container_id), - AssocContainer::TraitImpl(_) => cx.tcx.impl_trait_ref(container_id).map(|t| t.skip_binder().def_id), + AssocContainer::TraitImpl(_) => Some(cx.tcx.impl_trait_id(container_id)), AssocContainer::InherentImpl => None, };
diff --git a/src/tools/clippy/clippy_lints/src/non_canonical_impls.rs b/src/tools/clippy/clippy_lints/src/non_canonical_impls.rs index 3285023..e11f775 100644 --- a/src/tools/clippy/clippy_lints/src/non_canonical_impls.rs +++ b/src/tools/clippy/clippy_lints/src/non_canonical_impls.rs
@@ -6,7 +6,7 @@ use rustc_hir::def_id::DefId; use rustc_hir::{Block, Body, Expr, ExprKind, ImplItem, ImplItemKind, Item, ItemKind, LangItem, UnOp}; use rustc_lint::{LateContext, LateLintPass, LintContext}; -use rustc_middle::ty::{EarlyBinder, TyCtxt, TypeckResults}; +use rustc_middle::ty::{TyCtxt, TypeckResults}; use rustc_session::impl_lint_pass; use rustc_span::sym; use rustc_span::symbol::kw; @@ -173,10 +173,11 @@ fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) { } }); + let trait_impl = cx.tcx.impl_trait_ref(item.owner_id).skip_binder(); + match trait_ { Trait::Clone => { if let Some(copy_trait) = self.copy_trait - && let Some(trait_impl) = cx.tcx.impl_trait_ref(item.owner_id).map(EarlyBinder::skip_binder) && implements_trait(cx, trait_impl.self_ty(), copy_trait, &[]) { for (assoc, _, block) in assoc_fns { @@ -185,10 +186,9 @@ fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) { } }, Trait::PartialOrd => { - if let Some(trait_impl) = cx.tcx.impl_trait_ref(item.owner_id).map(EarlyBinder::skip_binder) - // If `Self` and `Rhs` are not the same type, then a corresponding `Ord` impl is not possible, - // since it doesn't have an `Rhs` - && let [lhs, rhs] = trait_impl.args.as_slice() + // If `Self` and `Rhs` are not the same type, then a corresponding `Ord` impl is not possible, + // since it doesn't have an `Rhs` + if let [lhs, rhs] = trait_impl.args.as_slice() && lhs == rhs && let Some(ord_trait) = self.ord_trait && implements_trait(cx, trait_impl.self_ty(), ord_trait, &[])
diff --git a/src/tools/clippy/clippy_lints/src/non_send_fields_in_send_ty.rs b/src/tools/clippy/clippy_lints/src/non_send_fields_in_send_ty.rs index b810bc0..fd5562f 100644 --- a/src/tools/clippy/clippy_lints/src/non_send_fields_in_send_ty.rs +++ b/src/tools/clippy/clippy_lints/src/non_send_fields_in_send_ty.rs
@@ -87,7 +87,7 @@ fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) { && let Some(trait_id) = of_trait.trait_ref.trait_def_id() && send_trait == trait_id && of_trait.polarity == ImplPolarity::Positive - && let Some(ty_trait_ref) = cx.tcx.impl_trait_ref(item.owner_id) + && let ty_trait_ref = cx.tcx.impl_trait_ref(item.owner_id) && let self_ty = ty_trait_ref.instantiate_identity().self_ty() && let ty::Adt(adt_def, impl_trait_args) = self_ty.kind() {
diff --git a/src/tools/clippy/clippy_lints/src/only_used_in_recursion.rs b/src/tools/clippy/clippy_lints/src/only_used_in_recursion.rs index 784ea34..51644f7 100644 --- a/src/tools/clippy/clippy_lints/src/only_used_in_recursion.rs +++ b/src/tools/clippy/clippy_lints/src/only_used_in_recursion.rs
@@ -6,9 +6,9 @@ use rustc_errors::Applicability; use rustc_hir::def_id::DefId; use rustc_hir::hir_id::HirIdMap; -use rustc_hir::{Body, Expr, ExprKind, HirId, ImplItem, ImplItemKind, Node, PatKind, TraitItem, TraitItemKind}; +use rustc_hir::{Body, Expr, ExprKind, HirId, ImplItem, ImplItemImplKind, ImplItemKind, Node, PatKind, TraitItem, TraitItemKind}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_middle::ty::{self, ConstKind, EarlyBinder, GenericArgKind, GenericArgsRef}; +use rustc_middle::ty::{self, ConstKind, GenericArgKind, GenericArgsRef}; use rustc_session::impl_lint_pass; use rustc_span::Span; use rustc_span::symbol::{Ident, kw}; @@ -320,15 +320,14 @@ fn check_body(&mut self, cx: &LateContext<'tcx>, body: &Body<'tcx>) { Node::ImplItem(&ImplItem { kind: ImplItemKind::Fn(ref sig, _), owner_id, + impl_kind, .. }) => { - if let Node::Item(item) = cx.tcx.parent_hir_node(owner_id.into()) - && let Some(trait_ref) = cx - .tcx - .impl_trait_ref(item.owner_id) - .map(EarlyBinder::instantiate_identity) - && let Some(trait_item_id) = cx.tcx.trait_item_of(owner_id) + if let ImplItemImplKind::Trait { trait_item_def_id, .. } = impl_kind + && let Ok(trait_item_id) = trait_item_def_id { + let impl_id = cx.tcx.parent(owner_id.into()); + let trait_ref = cx.tcx.impl_trait_ref(impl_id).instantiate_identity(); ( trait_item_id, FnKind::ImplTraitFn(
diff --git a/src/tools/clippy/clippy_lints/src/return_self_not_must_use.rs b/src/tools/clippy/clippy_lints/src/return_self_not_must_use.rs index b057396..83a226b 100644 --- a/src/tools/clippy/clippy_lints/src/return_self_not_must_use.rs +++ b/src/tools/clippy/clippy_lints/src/return_self_not_must_use.rs
@@ -113,10 +113,9 @@ fn check_fn( ) { if matches!(kind, FnKind::Method(_, _)) // We are only interested in methods, not in functions or associated functions. - && let Some(impl_def) = cx.tcx.impl_of_assoc(fn_def.to_def_id()) // We don't want this method to be te implementation of a trait because the // `#[must_use]` should be put on the trait definition directly. - && cx.tcx.trait_id_of_impl(impl_def).is_none() + && cx.tcx.inherent_impl_of_assoc(fn_def.to_def_id()).is_some() { let hir_id = cx.tcx.local_def_id_to_hir_id(fn_def); check_method(cx, decl, fn_def, span, hir_id.expect_owner());
diff --git a/src/tools/clippy/clippy_lints/src/unused_io_amount.rs b/src/tools/clippy/clippy_lints/src/unused_io_amount.rs index cff798f..2884bbd 100644 --- a/src/tools/clippy/clippy_lints/src/unused_io_amount.rs +++ b/src/tools/clippy/clippy_lints/src/unused_io_amount.rs
@@ -85,9 +85,8 @@ impl<'tcx> LateLintPass<'tcx> for UnusedIoAmount { /// get desugared to match. fn check_block(&mut self, cx: &LateContext<'tcx>, block: &'tcx hir::Block<'tcx>) { let fn_def_id = block.hir_id.owner.to_def_id(); - if let Some(impl_id) = cx.tcx.impl_of_assoc(fn_def_id) - && let Some(trait_id) = cx.tcx.trait_id_of_impl(impl_id) - { + if let Some(impl_id) = cx.tcx.trait_impl_of_assoc(fn_def_id) { + let trait_id = cx.tcx.impl_trait_id(impl_id); // We don't want to lint inside io::Read or io::Write implementations, as the author has more // information about their trait implementation than our lint, see https://github.com/rust-lang/rust-clippy/issues/4836 if let Some(trait_name) = cx.tcx.get_diagnostic_name(trait_id)
diff --git a/src/tools/clippy/clippy_lints/src/use_self.rs b/src/tools/clippy/clippy_lints/src/use_self.rs index f46dedf..eba6050 100644 --- a/src/tools/clippy/clippy_lints/src/use_self.rs +++ b/src/tools/clippy/clippy_lints/src/use_self.rs
@@ -10,7 +10,7 @@ use rustc_hir::intravisit::{InferKind, Visitor, VisitorExt, walk_ty}; use rustc_hir::{ self as hir, AmbigArg, Expr, ExprKind, FnRetTy, FnSig, GenericArgsParentheses, GenericParamKind, HirId, Impl, - ImplItemKind, Item, ItemKind, Pat, PatExpr, PatExprKind, PatKind, Path, QPath, Ty, TyKind, + ImplItemImplKind, ImplItemKind, Item, ItemKind, Pat, PatExpr, PatExprKind, PatKind, Path, QPath, Ty, TyKind, }; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::Ty as MiddleTy; @@ -142,13 +142,14 @@ fn check_impl_item(&mut self, cx: &LateContext<'_>, impl_item: &hir::ImplItem<'_ // We want to skip types in trait `impl`s that aren't declared as `Self` in the trait // declaration. The collection of those types is all this method implementation does. if let ImplItemKind::Fn(FnSig { decl, .. }, ..) = impl_item.kind + && let ImplItemImplKind::Trait { .. } = impl_item.impl_kind && let Some(&mut StackItem::Check { impl_id, ref mut types_to_skip, .. }) = self.stack.last_mut() - && let Some(impl_trait_ref) = cx.tcx.impl_trait_ref(impl_id) { + let impl_trait_ref = cx.tcx.impl_trait_ref(impl_id); // `self_ty` is the semantic self type of `impl <trait> for <type>`. This cannot be // `Self`. let self_ty = impl_trait_ref.instantiate_identity().self_ty();
diff --git a/src/tools/clippy/clippy_lints_internal/src/msrv_attr_impl.rs b/src/tools/clippy/clippy_lints_internal/src/msrv_attr_impl.rs index 66aeb91..e529bc2 100644 --- a/src/tools/clippy/clippy_lints_internal/src/msrv_attr_impl.rs +++ b/src/tools/clippy/clippy_lints_internal/src/msrv_attr_impl.rs
@@ -26,10 +26,7 @@ fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) { items, .. }) = &item.kind - && let Some(trait_ref) = cx - .tcx - .impl_trait_ref(item.owner_id) - .map(EarlyBinder::instantiate_identity) + && let trait_ref = cx.tcx.impl_trait_ref(item.owner_id).instantiate_identity() && internal_paths::EARLY_LINT_PASS.matches(cx, trait_ref.def_id) && let ty::Adt(self_ty_def, _) = trait_ref.self_ty().kind() && self_ty_def.is_struct()
diff --git a/src/tools/compiletest/src/directives.rs b/src/tools/compiletest/src/directives.rs index c96a1be..3bb5933 100644 --- a/src/tools/compiletest/src/directives.rs +++ b/src/tools/compiletest/src/directives.rs
@@ -8,7 +8,8 @@ use crate::common::{CodegenBackend, Config, Debugger, FailMode, PassMode, RunFailMode, TestMode}; use crate::debuggers::{extract_cdb_version, extract_gdb_version}; -use crate::directives::auxiliary::{AuxProps, parse_and_update_aux}; +pub(crate) use crate::directives::auxiliary::AuxProps; +use crate::directives::auxiliary::parse_and_update_aux; use crate::directives::directive_names::{ KNOWN_DIRECTIVE_NAMES, KNOWN_HTMLDOCCK_DIRECTIVE_NAMES, KNOWN_JSONDOCCK_DIRECTIVE_NAMES, }; @@ -21,7 +22,7 @@ use crate::util::static_regex; use crate::{fatal, help}; -pub(crate) mod auxiliary; +mod auxiliary; mod cfg; mod directive_names; mod file; @@ -44,10 +45,6 @@ pub fn load(config: &Config) -> Self { /// the test. #[derive(Default)] pub(crate) struct EarlyProps { - /// Auxiliary crates that should be built and made available to this test. - /// Included in [`EarlyProps`] so that the indicated files can participate - /// in up-to-date checking. Building happens via [`TestProps::aux`] instead. - pub(crate) aux: AuxProps, pub(crate) revisions: Vec<String>, } @@ -66,8 +63,7 @@ pub(crate) fn from_file_directives( file_directives, // (dummy comment to force args into vertical layout) &mut |ln: &DirectiveLine<'_>| { - parse_and_update_aux(config, ln, testfile, &mut props.aux); - config.parse_and_update_revisions(testfile, ln, &mut props.revisions); + config.parse_and_update_revisions(ln, &mut props.revisions); }, ); @@ -81,11 +77,15 @@ pub(crate) fn from_file_directives( } #[derive(Clone, Debug)] -pub struct TestProps { +pub(crate) struct TestProps { // Lines that should be expected, in order, on standard out pub error_patterns: Vec<String>, // Regexes that should be expected, in order, on standard out pub regex_error_patterns: Vec<String>, + /// Edition selected by an `//@ edition` directive, if any. + /// + /// Automatically added to `compile_flags` during directive processing. + pub edition: Option<Edition>, // Extra flags to pass to the compiler pub compile_flags: Vec<String>, // Extra flags to pass when the compiled code is run (such as --bench) @@ -267,6 +267,7 @@ pub fn new() -> Self { TestProps { error_patterns: vec![], regex_error_patterns: vec![], + edition: None, compile_flags: vec![], run_flags: vec![], doc_flags: vec![], @@ -355,7 +356,6 @@ pub fn from_file(testfile: &Utf8Path, revision: Option<&str>, config: &Config) - /// `//@[foo]`), then the property is ignored unless `test_revision` is /// `Some("foo")`. fn load_from(&mut self, testfile: &Utf8Path, test_revision: Option<&str>, config: &Config) { - let mut has_edition = false; if !testfile.is_dir() { let file_contents = fs::read_to_string(testfile).unwrap(); let file_directives = FileDirectives::from_file_contents(testfile, &file_contents); @@ -376,25 +376,17 @@ fn load_from(&mut self, testfile: &Utf8Path, test_revision: Option<&str>, config config.push_name_value_directive( ln, ERROR_PATTERN, - testfile, &mut self.error_patterns, |r| r, ); config.push_name_value_directive( ln, REGEX_ERROR_PATTERN, - testfile, &mut self.regex_error_patterns, |r| r, ); - config.push_name_value_directive( - ln, - DOC_FLAGS, - testfile, - &mut self.doc_flags, - |r| r, - ); + config.push_name_value_directive(ln, DOC_FLAGS, &mut self.doc_flags, |r| r); fn split_flags(flags: &str) -> Vec<String> { // Individual flags can be single-quoted to preserve spaces; see @@ -409,9 +401,7 @@ fn split_flags(flags: &str) -> Vec<String> { .collect::<Vec<_>>() } - if let Some(flags) = - config.parse_name_value_directive(ln, COMPILE_FLAGS, testfile) - { + if let Some(flags) = config.parse_name_value_directive(ln, COMPILE_FLAGS) { let flags = split_flags(&flags); for (i, flag) in flags.iter().enumerate() { if flag == "--edition" || flag.starts_with("--edition=") { @@ -428,32 +418,22 @@ fn split_flags(flags: &str) -> Vec<String> { } self.compile_flags.extend(flags); } - if config - .parse_name_value_directive(ln, INCORRECT_COMPILER_FLAGS, testfile) - .is_some() - { + if config.parse_name_value_directive(ln, INCORRECT_COMPILER_FLAGS).is_some() { panic!("`compiler-flags` directive should be spelled `compile-flags`"); } - if let Some(range) = parse_edition_range(config, ln, testfile) { - // The edition is added at the start, since flags from //@compile-flags must - // be passed to rustc last. - self.compile_flags.insert( - 0, - format!("--edition={}", range.edition_to_test(config.edition)), - ); - has_edition = true; + if let Some(range) = parse_edition_range(config, ln) { + self.edition = Some(range.edition_to_test(config.edition)); } - config.parse_and_update_revisions(testfile, ln, &mut self.revisions); + config.parse_and_update_revisions(ln, &mut self.revisions); - if let Some(flags) = config.parse_name_value_directive(ln, RUN_FLAGS, testfile) - { + if let Some(flags) = config.parse_name_value_directive(ln, RUN_FLAGS) { self.run_flags.extend(split_flags(&flags)); } if self.pp_exact.is_none() { - self.pp_exact = config.parse_pp_exact(ln, testfile); + self.pp_exact = config.parse_pp_exact(ln); } config.set_name_directive(ln, SHOULD_ICE, &mut self.should_ice); @@ -475,7 +455,7 @@ fn split_flags(flags: &str) -> Vec<String> { ); config.set_name_directive(ln, NO_PREFER_DYNAMIC, &mut self.no_prefer_dynamic); - if let Some(m) = config.parse_name_value_directive(ln, PRETTY_MODE, testfile) { + if let Some(m) = config.parse_name_value_directive(ln, PRETTY_MODE) { self.pretty_mode = m; } @@ -486,40 +466,35 @@ fn split_flags(flags: &str) -> Vec<String> { ); // Call a helper method to deal with aux-related directives. - parse_and_update_aux(config, ln, testfile, &mut self.aux); + parse_and_update_aux(config, ln, &mut self.aux); config.push_name_value_directive( ln, EXEC_ENV, - testfile, &mut self.exec_env, Config::parse_env, ); config.push_name_value_directive( ln, UNSET_EXEC_ENV, - testfile, &mut self.unset_exec_env, |r| r.trim().to_owned(), ); config.push_name_value_directive( ln, RUSTC_ENV, - testfile, &mut self.rustc_env, Config::parse_env, ); config.push_name_value_directive( ln, UNSET_RUSTC_ENV, - testfile, &mut self.unset_rustc_env, |r| r.trim().to_owned(), ); config.push_name_value_directive( ln, FORBID_OUTPUT, - testfile, &mut self.forbid_output, |r| r, ); @@ -555,7 +530,7 @@ fn split_flags(flags: &str) -> Vec<String> { } if let Some(code) = config - .parse_name_value_directive(ln, FAILURE_STATUS, testfile) + .parse_name_value_directive(ln, FAILURE_STATUS) .and_then(|code| code.trim().parse::<i32>().ok()) { self.failure_status = Some(code); @@ -576,7 +551,6 @@ fn split_flags(flags: &str) -> Vec<String> { config.set_name_value_directive( ln, ASSEMBLY_OUTPUT, - testfile, &mut self.assembly_output, |r| r.trim().to_string(), ); @@ -589,9 +563,7 @@ fn split_flags(flags: &str) -> Vec<String> { // Unlike the other `name_value_directive`s this needs to be handled manually, // because it sets a `bool` flag. - if let Some(known_bug) = - config.parse_name_value_directive(ln, KNOWN_BUG, testfile) - { + if let Some(known_bug) = config.parse_name_value_directive(ln, KNOWN_BUG) { let known_bug = known_bug.trim(); if known_bug == "unknown" || known_bug.split(',').all(|issue_ref| { @@ -619,21 +591,16 @@ fn split_flags(flags: &str) -> Vec<String> { config.set_name_value_directive( ln, TEST_MIR_PASS, - testfile, &mut self.mir_unit_test, |s| s.trim().to_string(), ); config.set_name_directive(ln, REMAP_SRC_BASE, &mut self.remap_src_base); - if let Some(flags) = - config.parse_name_value_directive(ln, LLVM_COV_FLAGS, testfile) - { + if let Some(flags) = config.parse_name_value_directive(ln, LLVM_COV_FLAGS) { self.llvm_cov_flags.extend(split_flags(&flags)); } - if let Some(flags) = - config.parse_name_value_directive(ln, FILECHECK_FLAGS, testfile) - { + if let Some(flags) = config.parse_name_value_directive(ln, FILECHECK_FLAGS) { self.filecheck_flags.extend(split_flags(&flags)); } @@ -642,7 +609,7 @@ fn split_flags(flags: &str) -> Vec<String> { self.update_add_core_stubs(ln, config); if let Some(flags) = - config.parse_name_value_directive(ln, CORE_STUBS_COMPILE_FLAGS, testfile) + config.parse_name_value_directive(ln, CORE_STUBS_COMPILE_FLAGS) { let flags = split_flags(&flags); for flag in &flags { @@ -654,7 +621,7 @@ fn split_flags(flags: &str) -> Vec<String> { } if let Some(err_kind) = - config.parse_name_value_directive(ln, DONT_REQUIRE_ANNOTATIONS, testfile) + config.parse_name_value_directive(ln, DONT_REQUIRE_ANNOTATIONS) { self.dont_require_annotations .insert(ErrorKind::expect_from_user_str(err_kind.trim())); @@ -705,10 +672,10 @@ fn split_flags(flags: &str) -> Vec<String> { } } - if let (Some(edition), false) = (&config.edition, has_edition) { + if let Some(edition) = self.edition.or(config.edition) { // The edition is added at the start, since flags from //@compile-flags must be passed // to rustc last. - self.compile_flags.insert(0, format!("--edition={}", edition)); + self.compile_flags.insert(0, format!("--edition={edition}")); } } @@ -870,7 +837,7 @@ fn iter_directives( ]; // Process the extra implied directives, with a dummy line number of 0. for directive_str in extra_directives { - let directive_line = line_directive(0, directive_str) + let directive_line = line_directive(testfile, 0, directive_str) .unwrap_or_else(|| panic!("bad extra-directive line: {directive_str:?}")); it(&directive_line); } @@ -911,12 +878,7 @@ fn iter_directives( } impl Config { - fn parse_and_update_revisions( - &self, - testfile: &Utf8Path, - line: &DirectiveLine<'_>, - existing: &mut Vec<String>, - ) { + fn parse_and_update_revisions(&self, line: &DirectiveLine<'_>, existing: &mut Vec<String>) { const FORBIDDEN_REVISION_NAMES: [&str; 2] = [ // `//@ revisions: true false` Implying `--cfg=true` and `--cfg=false` makes it very // weird for the test, since if the test writer wants a cfg of the same revision name @@ -927,7 +889,9 @@ fn parse_and_update_revisions( const FILECHECK_FORBIDDEN_REVISION_NAMES: [&str; 9] = ["CHECK", "COM", "NEXT", "SAME", "EMPTY", "NOT", "COUNT", "DAG", "LABEL"]; - if let Some(raw) = self.parse_name_value_directive(line, "revisions", testfile) { + if let Some(raw) = self.parse_name_value_directive(line, "revisions") { + let &DirectiveLine { file_path: testfile, .. } = line; + if self.mode == TestMode::RunMake { panic!("`run-make` mode tests do not support revisions: {}", testfile); } @@ -972,11 +936,11 @@ fn parse_env(nv: String) -> (String, String) { (name.to_owned(), value.to_owned()) } - fn parse_pp_exact(&self, line: &DirectiveLine<'_>, testfile: &Utf8Path) -> Option<Utf8PathBuf> { - if let Some(s) = self.parse_name_value_directive(line, "pp-exact", testfile) { + fn parse_pp_exact(&self, line: &DirectiveLine<'_>) -> Option<Utf8PathBuf> { + if let Some(s) = self.parse_name_value_directive(line, "pp-exact") { Some(Utf8PathBuf::from(&s)) } else if self.parse_name_directive(line, "pp-exact") { - testfile.file_name().map(Utf8PathBuf::from) + line.file_path.file_name().map(Utf8PathBuf::from) } else { None } @@ -1013,9 +977,8 @@ fn parse_name_value_directive( &self, line: &DirectiveLine<'_>, directive: &str, - testfile: &Utf8Path, ) -> Option<String> { - let &DirectiveLine { line_number, .. } = line; + let &DirectiveLine { file_path, line_number, .. } = line; if line.name != directive { return None; @@ -1029,7 +992,7 @@ fn parse_name_value_directive( let value = expand_variables(value.to_owned(), self); if value.is_empty() { - error!("{testfile}:{line_number}: empty value for directive `{directive}`"); + error!("{file_path}:{line_number}: empty value for directive `{directive}`"); help!("expected syntax is: `{directive}: value`"); panic!("empty directive value detected"); } @@ -1046,12 +1009,11 @@ fn set_name_value_directive<T>( &self, line: &DirectiveLine<'_>, directive: &str, - testfile: &Utf8Path, value: &mut Option<T>, parse: impl FnOnce(String) -> T, ) { if value.is_none() { - *value = self.parse_name_value_directive(line, directive, testfile).map(parse); + *value = self.parse_name_value_directive(line, directive).map(parse); } } @@ -1059,11 +1021,10 @@ fn push_name_value_directive<T>( &self, line: &DirectiveLine<'_>, directive: &str, - testfile: &Utf8Path, values: &mut Vec<T>, parse: impl FnOnce(String) -> T, ) { - if let Some(value) = self.parse_name_value_directive(line, directive, testfile).map(parse) { + if let Some(value) = self.parse_name_value_directive(line, directive).map(parse) { values.push(value); } } @@ -1343,6 +1304,7 @@ pub(crate) fn make_test_description( file_directives: &FileDirectives<'_>, test_revision: Option<&str>, poisoned: &mut bool, + aux_props: &mut AuxProps, ) -> CollectedTestDesc { let mut ignore = false; let mut ignore_message = None; @@ -1360,6 +1322,9 @@ pub(crate) fn make_test_description( return; } + // Parse `aux-*` directives, for use by up-to-date checks. + parse_and_update_aux(config, ln, aux_props); + macro_rules! decision { ($e:expr) => { match $e { @@ -1380,9 +1345,9 @@ macro_rules! decision { decision!(cfg::handle_ignore(config, ln)); decision!(cfg::handle_only(config, ln)); decision!(needs::handle_needs(&cache.needs, config, ln)); - decision!(ignore_llvm(config, path, ln)); - decision!(ignore_backends(config, path, ln)); - decision!(needs_backends(config, path, ln)); + decision!(ignore_llvm(config, ln)); + decision!(ignore_backends(config, ln)); + decision!(needs_backends(config, ln)); decision!(ignore_cdb(config, ln)); decision!(ignore_gdb(config, ln)); decision!(ignore_lldb(config, ln)); @@ -1523,10 +1488,9 @@ fn ignore_lldb(config: &Config, line: &DirectiveLine<'_>) -> IgnoreDecision { IgnoreDecision::Continue } -fn ignore_backends(config: &Config, path: &Utf8Path, line: &DirectiveLine<'_>) -> IgnoreDecision { - if let Some(backends_to_ignore) = - config.parse_name_value_directive(line, "ignore-backends", path) - { +fn ignore_backends(config: &Config, line: &DirectiveLine<'_>) -> IgnoreDecision { + let path = line.file_path; + if let Some(backends_to_ignore) = config.parse_name_value_directive(line, "ignore-backends") { for backend in backends_to_ignore.split_whitespace().map(|backend| { match CodegenBackend::try_from(backend) { Ok(backend) => backend, @@ -1545,8 +1509,9 @@ fn ignore_backends(config: &Config, path: &Utf8Path, line: &DirectiveLine<'_>) - IgnoreDecision::Continue } -fn needs_backends(config: &Config, path: &Utf8Path, line: &DirectiveLine<'_>) -> IgnoreDecision { - if let Some(needed_backends) = config.parse_name_value_directive(line, "needs-backends", path) { +fn needs_backends(config: &Config, line: &DirectiveLine<'_>) -> IgnoreDecision { + let path = line.file_path; + if let Some(needed_backends) = config.parse_name_value_directive(line, "needs-backends") { if !needed_backends .split_whitespace() .map(|backend| match CodegenBackend::try_from(backend) { @@ -1568,9 +1533,10 @@ fn needs_backends(config: &Config, path: &Utf8Path, line: &DirectiveLine<'_>) -> IgnoreDecision::Continue } -fn ignore_llvm(config: &Config, path: &Utf8Path, line: &DirectiveLine<'_>) -> IgnoreDecision { +fn ignore_llvm(config: &Config, line: &DirectiveLine<'_>) -> IgnoreDecision { + let path = line.file_path; if let Some(needed_components) = - config.parse_name_value_directive(line, "needs-llvm-components", path) + config.parse_name_value_directive(line, "needs-llvm-components") { let components: HashSet<_> = config.llvm_components.split_whitespace().collect(); if let Some(missing_component) = needed_components @@ -1579,8 +1545,8 @@ fn ignore_llvm(config: &Config, path: &Utf8Path, line: &DirectiveLine<'_>) -> Ig { if env::var_os("COMPILETEST_REQUIRE_ALL_LLVM_COMPONENTS").is_some() { panic!( - "missing LLVM component {}, and COMPILETEST_REQUIRE_ALL_LLVM_COMPONENTS is set: {}", - missing_component, path + "missing LLVM component {missing_component}, \ + and COMPILETEST_REQUIRE_ALL_LLVM_COMPONENTS is set: {path}", ); } return IgnoreDecision::Ignore { @@ -1591,9 +1557,7 @@ fn ignore_llvm(config: &Config, path: &Utf8Path, line: &DirectiveLine<'_>) -> Ig if let Some(actual_version) = &config.llvm_version { // Note that these `min` versions will check for not just major versions. - if let Some(version_string) = - config.parse_name_value_directive(line, "min-llvm-version", path) - { + if let Some(version_string) = config.parse_name_value_directive(line, "min-llvm-version") { let min_version = extract_llvm_version(&version_string); // Ignore if actual version is smaller than the minimum required version. if *actual_version < min_version { @@ -1604,7 +1568,7 @@ fn ignore_llvm(config: &Config, path: &Utf8Path, line: &DirectiveLine<'_>) -> Ig }; } } else if let Some(version_string) = - config.parse_name_value_directive(line, "max-llvm-major-version", path) + config.parse_name_value_directive(line, "max-llvm-major-version") { let max_version = extract_llvm_version(&version_string); // Ignore if actual major version is larger than the maximum required major version. @@ -1618,7 +1582,7 @@ fn ignore_llvm(config: &Config, path: &Utf8Path, line: &DirectiveLine<'_>) -> Ig }; } } else if let Some(version_string) = - config.parse_name_value_directive(line, "min-system-llvm-version", path) + config.parse_name_value_directive(line, "min-system-llvm-version") { let min_version = extract_llvm_version(&version_string); // Ignore if using system LLVM and actual version @@ -1631,7 +1595,7 @@ fn ignore_llvm(config: &Config, path: &Utf8Path, line: &DirectiveLine<'_>) -> Ig }; } } else if let Some(version_range) = - config.parse_name_value_directive(line, "ignore-llvm-version", path) + config.parse_name_value_directive(line, "ignore-llvm-version") { // Syntax is: "ignore-llvm-version: <version1> [- <version2>]" let (v_min, v_max) = @@ -1657,7 +1621,7 @@ fn ignore_llvm(config: &Config, path: &Utf8Path, line: &DirectiveLine<'_>) -> Ig } } } else if let Some(version_string) = - config.parse_name_value_directive(line, "exact-llvm-major-version", path) + config.parse_name_value_directive(line, "exact-llvm-major-version") { // Syntax is "exact-llvm-major-version: <version>" let version = extract_llvm_version(&version_string); @@ -1680,13 +1644,9 @@ enum IgnoreDecision { Error { message: String }, } -fn parse_edition_range( - config: &Config, - line: &DirectiveLine<'_>, - testfile: &Utf8Path, -) -> Option<EditionRange> { - let raw = config.parse_name_value_directive(line, "edition", testfile)?; - let line_number = line.line_number; +fn parse_edition_range(config: &Config, line: &DirectiveLine<'_>) -> Option<EditionRange> { + let raw = config.parse_name_value_directive(line, "edition")?; + let &DirectiveLine { file_path: testfile, line_number, .. } = line; // Edition range is half-open: `[lower_bound, upper_bound)` if let Some((lower_bound, upper_bound)) = raw.split_once("..") {
diff --git a/src/tools/compiletest/src/directives/auxiliary.rs b/src/tools/compiletest/src/directives/auxiliary.rs index 7cf9817..40e2e70 100644 --- a/src/tools/compiletest/src/directives/auxiliary.rs +++ b/src/tools/compiletest/src/directives/auxiliary.rs
@@ -3,8 +3,6 @@ use std::iter; -use camino::Utf8Path; - use super::directives::{AUX_BIN, AUX_BUILD, AUX_CODEGEN_BACKEND, AUX_CRATE, PROC_MACRO}; use crate::common::Config; use crate::directives::DirectiveLine; @@ -47,7 +45,6 @@ pub(crate) fn all_aux_path_strings(&self) -> impl Iterator<Item = &str> { pub(super) fn parse_and_update_aux( config: &Config, directive_line: &DirectiveLine<'_>, - testfile: &Utf8Path, aux: &mut AuxProps, ) { if !(directive_line.name.starts_with("aux-") || directive_line.name == "proc-macro") { @@ -56,16 +53,12 @@ pub(super) fn parse_and_update_aux( let ln = directive_line; - config.push_name_value_directive(ln, AUX_BUILD, testfile, &mut aux.builds, |r| { - r.trim().to_string() - }); + config.push_name_value_directive(ln, AUX_BUILD, &mut aux.builds, |r| r.trim().to_string()); + config.push_name_value_directive(ln, AUX_BIN, &mut aux.bins, |r| r.trim().to_string()); + config.push_name_value_directive(ln, AUX_CRATE, &mut aux.crates, parse_aux_crate); config - .push_name_value_directive(ln, AUX_BIN, testfile, &mut aux.bins, |r| r.trim().to_string()); - config.push_name_value_directive(ln, AUX_CRATE, testfile, &mut aux.crates, parse_aux_crate); - config.push_name_value_directive(ln, PROC_MACRO, testfile, &mut aux.proc_macros, |r| { - r.trim().to_string() - }); - if let Some(r) = config.parse_name_value_directive(ln, AUX_CODEGEN_BACKEND, testfile) { + .push_name_value_directive(ln, PROC_MACRO, &mut aux.proc_macros, |r| r.trim().to_string()); + if let Some(r) = config.parse_name_value_directive(ln, AUX_CODEGEN_BACKEND) { aux.codegen_backend = Some(r.trim().to_owned()); } }
diff --git a/src/tools/compiletest/src/directives/file.rs b/src/tools/compiletest/src/directives/file.rs index afb9bb1..82819ac 100644 --- a/src/tools/compiletest/src/directives/file.rs +++ b/src/tools/compiletest/src/directives/file.rs
@@ -14,7 +14,7 @@ pub(crate) fn from_file_contents(path: &'a Utf8Path, file_contents: &'a str) -> for (line_number, ln) in (1..).zip(file_contents.lines()) { let ln = ln.trim(); - if let Some(directive_line) = line_directive(line_number, ln) { + if let Some(directive_line) = line_directive(path, line_number, ln) { lines.push(directive_line); } }
diff --git a/src/tools/compiletest/src/directives/line.rs b/src/tools/compiletest/src/directives/line.rs index 4990720..16dd9a8 100644 --- a/src/tools/compiletest/src/directives/line.rs +++ b/src/tools/compiletest/src/directives/line.rs
@@ -1,13 +1,16 @@ use std::fmt; +use camino::Utf8Path; + const COMPILETEST_DIRECTIVE_PREFIX: &str = "//@"; /// If the given line begins with the appropriate comment prefix for a directive, /// returns a struct containing various parts of the directive. -pub(crate) fn line_directive<'line>( +pub(crate) fn line_directive<'a>( + file_path: &'a Utf8Path, line_number: usize, - original_line: &'line str, -) -> Option<DirectiveLine<'line>> { + original_line: &'a str, +) -> Option<DirectiveLine<'a>> { // Ignore lines that don't start with the comment prefix. let after_comment = original_line.trim_start().strip_prefix(COMPILETEST_DIRECTIVE_PREFIX)?.trim_start(); @@ -33,7 +36,7 @@ pub(crate) fn line_directive<'line>( // The directive name ends at the first occurrence of colon, space, or end-of-string. let name = raw_directive.split([':', ' ']).next().expect("split is never empty"); - Some(DirectiveLine { line_number, revision, raw_directive, name }) + Some(DirectiveLine { file_path, line_number, revision, raw_directive, name }) } /// The (partly) broken-down contents of a line containing a test directive, @@ -51,25 +54,30 @@ pub(crate) fn line_directive<'line>( /// ^^^^^^^^^^^^^^^^^ raw_directive /// ^^^^^^^^^^^^^ name /// ``` -pub(crate) struct DirectiveLine<'ln> { +pub(crate) struct DirectiveLine<'a> { + /// Path of the file containing this line. + /// + /// Mostly used for diagnostics, but some directives (e.g. `//@ pp-exact`) + /// also use it to compute a value based on the filename. + pub(crate) file_path: &'a Utf8Path, pub(crate) line_number: usize, /// Some test directives start with a revision name in square brackets /// (e.g. `[foo]`), and only apply to that revision of the test. /// If present, this field contains the revision name (e.g. `foo`). - pub(crate) revision: Option<&'ln str>, + pub(crate) revision: Option<&'a str>, /// The main part of the directive, after removing the comment prefix /// and the optional revision specifier. /// /// This is "raw" because the directive's name and colon-separated value /// (if present) have not yet been extracted or checked. - raw_directive: &'ln str, + raw_directive: &'a str, /// Name of the directive. /// /// Invariant: `self.raw_directive.starts_with(self.name)` - pub(crate) name: &'ln str, + pub(crate) name: &'a str, } impl<'ln> DirectiveLine<'ln> {
diff --git a/src/tools/compiletest/src/directives/tests.rs b/src/tools/compiletest/src/directives/tests.rs index 4e7ae6d..ddc14b9 100644 --- a/src/tools/compiletest/src/directives/tests.rs +++ b/src/tools/compiletest/src/directives/tests.rs
@@ -3,8 +3,9 @@ use crate::common::{Config, Debugger, TestMode}; use crate::directives::{ - DirectivesCache, EarlyProps, Edition, EditionRange, FileDirectives, extract_llvm_version, - extract_version_range, iter_directives, line_directive, parse_edition, parse_normalize_rule, + AuxProps, DirectivesCache, EarlyProps, Edition, EditionRange, FileDirectives, + extract_llvm_version, extract_version_range, iter_directives, line_directive, parse_edition, + parse_normalize_rule, }; use crate::executor::{CollectedTestDesc, ShouldPanic}; @@ -20,6 +21,7 @@ fn make_test_description( let mut poisoned = false; let file_directives = FileDirectives::from_file_contents(path, file_contents); + let mut aux_props = AuxProps::default(); let test = crate::directives::make_test_description( config, &cache, @@ -29,6 +31,7 @@ fn make_test_description( &file_directives, revision, &mut poisoned, + &mut aux_props, ); if poisoned { panic!("poisoned!"); @@ -225,7 +228,7 @@ fn cfg() -> ConfigBuilder { ConfigBuilder::default() } -fn parse_rs(config: &Config, contents: &str) -> EarlyProps { +fn parse_early_props(config: &Config, contents: &str) -> EarlyProps { let file_directives = FileDirectives::from_file_contents(Utf8Path::new("a.rs"), contents); EarlyProps::from_file_directives(config, &file_directives) } @@ -253,25 +256,7 @@ fn should_fail() { fn revisions() { let config: Config = cfg().build(); - assert_eq!(parse_rs(&config, "//@ revisions: a b c").revisions, vec!["a", "b", "c"],); -} - -#[test] -fn aux_build() { - let config: Config = cfg().build(); - - assert_eq!( - parse_rs( - &config, - r" - //@ aux-build: a.rs - //@ aux-build: b.rs - " - ) - .aux - .builds, - vec!["a.rs", "b.rs"], - ); + assert_eq!(parse_early_props(&config, "//@ revisions: a b c").revisions, vec!["a", "b", "c"],); } #[test] @@ -550,7 +535,7 @@ fn test_extract_version_range() { #[should_panic(expected = "duplicate revision: `rpass1` in line ` rpass1 rpass1`")] fn test_duplicate_revisions() { let config: Config = cfg().build(); - parse_rs(&config, "//@ revisions: rpass1 rpass1"); + parse_early_props(&config, "//@ revisions: rpass1 rpass1"); } #[test] @@ -559,14 +544,14 @@ fn test_duplicate_revisions() { )] fn test_assembly_mode_forbidden_revisions() { let config = cfg().mode("assembly").build(); - parse_rs(&config, "//@ revisions: CHECK"); + parse_early_props(&config, "//@ revisions: CHECK"); } #[test] #[should_panic(expected = "revision name `true` is not permitted")] fn test_forbidden_revisions() { let config = cfg().mode("ui").build(); - parse_rs(&config, "//@ revisions: true"); + parse_early_props(&config, "//@ revisions: true"); } #[test] @@ -575,7 +560,7 @@ fn test_forbidden_revisions() { )] fn test_codegen_mode_forbidden_revisions() { let config = cfg().mode("codegen").build(); - parse_rs(&config, "//@ revisions: CHECK"); + parse_early_props(&config, "//@ revisions: CHECK"); } #[test] @@ -584,7 +569,7 @@ fn test_codegen_mode_forbidden_revisions() { )] fn test_miropt_mode_forbidden_revisions() { let config = cfg().mode("mir-opt").build(); - parse_rs(&config, "//@ revisions: CHECK"); + parse_early_props(&config, "//@ revisions: CHECK"); } #[test] @@ -608,7 +593,7 @@ fn test_forbidden_revisions_allowed_in_non_filecheck_dir() { let content = format!("//@ revisions: {rev}"); for mode in modes { let config = cfg().mode(mode).build(); - parse_rs(&config, &content); + parse_early_props(&config, &content); } } } @@ -956,9 +941,21 @@ fn parse_edition_range(line: &str) -> Option<EditionRange> { let config = cfg().build(); let line_with_comment = format!("//@ {line}"); - let line = line_directive(0, &line_with_comment).unwrap(); + let line = line_directive(Utf8Path::new("tmp.rs"), 0, &line_with_comment).unwrap(); - super::parse_edition_range(&config, &line, "tmp.rs".into()) + super::parse_edition_range(&config, &line) +} + +#[test] +fn edition_order() { + let editions = &[ + Edition::Year(2015), + Edition::Year(2018), + Edition::Year(2021), + Edition::Year(2024), + Edition::Future, + ]; + assert!(editions.is_sorted(), "{editions:#?}"); } #[test]
diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs index 4cfb1e2..798008a 100644 --- a/src/tools/compiletest/src/lib.rs +++ b/src/tools/compiletest/src/lib.rs
@@ -41,7 +41,7 @@ CodegenBackend, CompareMode, Config, Debugger, PassMode, TestMode, TestPaths, UI_EXTENSIONS, expected_output_path, output_base_dir, output_relative_path, }; -use crate::directives::{DirectivesCache, FileDirectives}; +use crate::directives::{AuxProps, DirectivesCache, FileDirectives}; use crate::edition::parse_edition; use crate::executor::{CollectedTest, ColorConfig}; @@ -891,6 +891,11 @@ fn make_test(cx: &TestCollectorCx, collector: &mut TestCollector, testpaths: &Te // Create a test name and description to hand over to the executor. let (test_name, filterable_path) = make_test_name_and_filterable_path(&cx.config, testpaths, revision); + + // While scanning for ignore/only/needs directives, also collect aux + // paths for up-to-date checking. + let mut aux_props = AuxProps::default(); + // Create a description struct for the test/revision. // This is where `ignore-*`/`only-*`/`needs-*` directives are handled, // because they historically needed to set the libtest ignored flag. @@ -903,11 +908,15 @@ fn make_test(cx: &TestCollectorCx, collector: &mut TestCollector, testpaths: &Te &file_directives, revision, &mut collector.poisoned, + &mut aux_props, ); // If a test's inputs haven't changed since the last time it ran, // mark it as ignored so that the executor will skip it. - if !cx.config.force_rerun && is_up_to_date(cx, testpaths, &early_props, revision) { + if !desc.ignore + && !cx.config.force_rerun + && is_up_to_date(cx, testpaths, &aux_props, revision) + { desc.ignore = true; // Keep this in sync with the "up-to-date" message detected by bootstrap. // FIXME(Zalathar): Now that we are no longer tied to libtest, we could @@ -936,7 +945,7 @@ fn stamp_file_path(config: &Config, testpaths: &TestPaths, revision: Option<&str fn files_related_to_test( config: &Config, testpaths: &TestPaths, - props: &EarlyProps, + aux_props: &AuxProps, revision: Option<&str>, ) -> Vec<Utf8PathBuf> { let mut related = vec![]; @@ -953,8 +962,11 @@ fn files_related_to_test( related.push(testpaths.file.clone()); } - for aux in props.aux.all_aux_path_strings() { + for aux in aux_props.all_aux_path_strings() { // FIXME(Zalathar): Perform all `auxiliary` path resolution in one place. + // FIXME(Zalathar): This only finds auxiliary files used _directly_ by + // the test file; if a transitive auxiliary is modified, the test might + // be treated as "up-to-date" even though it should run. let path = testpaths.file.parent().unwrap().join("auxiliary").join(aux); related.push(path); } @@ -979,7 +991,7 @@ fn files_related_to_test( fn is_up_to_date( cx: &TestCollectorCx, testpaths: &TestPaths, - props: &EarlyProps, + aux_props: &AuxProps, revision: Option<&str>, ) -> bool { let stamp_file_path = stamp_file_path(&cx.config, testpaths, revision); @@ -1000,7 +1012,7 @@ fn is_up_to_date( // Check the timestamp of the stamp file against the last modified time // of all files known to be relevant to the test. let mut inputs_stamp = cx.common_inputs_stamp.clone(); - for path in files_related_to_test(&cx.config, testpaths, props, revision) { + for path in files_related_to_test(&cx.config, testpaths, aux_props, revision) { inputs_stamp.add_path(&path); }
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index e9dea95..ff275df 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs
@@ -1838,8 +1838,9 @@ fn make_compile_args( // Add `-A unused` before `config` flags and in-test (`props`) flags, so that they can // overwrite this. + // Don't allow `unused_attributes` since these are usually actual mistakes, rather than just unused code. if let AllowUnused::Yes = allow_unused { - rustc.args(&["-A", "unused"]); + rustc.args(&["-A", "unused", "-W", "unused_attributes"]); } // Allow tests to use internal features.
diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index 3164dcc..60ad88e 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs
@@ -19,32 +19,52 @@ #[rustfmt::skip] const LICENSES: &[&str] = &[ // tidy-alphabetical-start - "(MIT OR Apache-2.0) AND Unicode-3.0", // unicode_ident (1.0.14) - "(MIT OR Apache-2.0) AND Unicode-DFS-2016", // unicode_ident (1.0.12) "0BSD OR MIT OR Apache-2.0", // adler2 license - "0BSD", "Apache-2.0 / MIT", "Apache-2.0 OR ISC OR MIT", "Apache-2.0 OR MIT", "Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT", // wasi license - "Apache-2.0", "Apache-2.0/MIT", "BSD-2-Clause OR Apache-2.0 OR MIT", // zerocopy + "BSD-2-Clause OR MIT OR Apache-2.0", + "BSD-3-Clause/MIT", + "CC0-1.0 OR MIT-0 OR Apache-2.0", "ISC", "MIT / Apache-2.0", "MIT AND (MIT OR Apache-2.0)", "MIT AND Apache-2.0 WITH LLVM-exception AND (MIT OR Apache-2.0)", // compiler-builtins - "MIT OR Apache-2.0 OR LGPL-2.1-or-later", // r-efi, r-efi-alloc + "MIT OR Apache-2.0 OR BSD-1-Clause", + "MIT OR Apache-2.0 OR LGPL-2.1-or-later", // r-efi, r-efi-alloc; LGPL is not acceptable, but we use it under MIT OR Apache-2.0 "MIT OR Apache-2.0 OR Zlib", // tinyvec_macros "MIT OR Apache-2.0", "MIT OR Zlib OR Apache-2.0", // miniz_oxide "MIT", "MIT/Apache-2.0", - "Unicode-3.0", // icu4x - "Unicode-DFS-2016", // tinystr "Unlicense OR MIT", "Unlicense/MIT", + // tidy-alphabetical-end +]; + +/// These are licenses that are allowed for rustc, tools, etc. But not for the runtime! +#[rustfmt::skip] +const LICENSES_TOOLS: &[&str] = &[ + // tidy-alphabetical-start + "(Apache-2.0 OR MIT) AND BSD-3-Clause", + "(MIT OR Apache-2.0) AND Unicode-3.0", // unicode_ident (1.0.14) + "(MIT OR Apache-2.0) AND Unicode-DFS-2016", // unicode_ident (1.0.12) + "0BSD", + "Apache-2.0 AND ISC", + "Apache-2.0 OR BSL-1.0", // BSL is not acceptable, but we use it under Apache-2.0 + "Apache-2.0 WITH LLVM-exception", + "Apache-2.0", + "BSD-2-Clause", + "BSD-3-Clause", + "CC0-1.0 OR Apache-2.0 OR Apache-2.0 WITH LLVM-exception", + "CC0-1.0", + "Unicode-3.0", // icu4x + "Unicode-DFS-2016", // tinystr "Zlib OR Apache-2.0 OR MIT", // tinyvec + "Zlib", // tidy-alphabetical-end ]; @@ -89,17 +109,15 @@ pub(crate) struct WorkspaceInfo<'a> { )), submodules: &[], }, - { - WorkspaceInfo { - path: "compiler/rustc_codegen_cranelift", - exceptions: EXCEPTIONS_CRANELIFT, - crates_and_deps: Some(( - &["rustc_codegen_cranelift"], - PERMITTED_CRANELIFT_DEPENDENCIES, - PERMITTED_CRANELIFT_DEPS_LOCATION, - )), - submodules: &[], - } + WorkspaceInfo { + path: "compiler/rustc_codegen_cranelift", + exceptions: EXCEPTIONS_CRANELIFT, + crates_and_deps: Some(( + &["rustc_codegen_cranelift"], + PERMITTED_CRANELIFT_DEPENDENCIES, + PERMITTED_CRANELIFT_DEPS_LOCATION, + )), + submodules: &[], }, WorkspaceInfo { path: "compiler/rustc_codegen_gcc", @@ -169,19 +187,8 @@ pub(crate) struct WorkspaceInfo<'a> { #[rustfmt::skip] const EXCEPTIONS: ExceptionList = &[ // tidy-alphabetical-start - ("ar_archive_writer", "Apache-2.0 WITH LLVM-exception"), // rustc - ("arrayref", "BSD-2-Clause"), // rustc - ("blake3", "CC0-1.0 OR Apache-2.0 OR Apache-2.0 WITH LLVM-exception"), // rustc ("colored", "MPL-2.0"), // rustfmt - ("constant_time_eq", "CC0-1.0 OR MIT-0 OR Apache-2.0"), // rustc - ("dissimilar", "Apache-2.0"), // rustdoc, rustc_lexer (few tests) via expect-test, (dev deps) - ("fluent-langneg", "Apache-2.0"), // rustc (fluent translations) - ("foldhash", "Zlib"), // rustc ("option-ext", "MPL-2.0"), // cargo-miri (via `directories`) - ("rustc_apfloat", "Apache-2.0 WITH LLVM-exception"), // rustc (license is the same as LLVM uses) - ("ryu", "Apache-2.0 OR BSL-1.0"), // BSL is not acceptble, but we use it under Apache-2.0 // cargo/... (because of serde) - ("self_cell", "Apache-2.0"), // rustc (fluent translations) - ("wasi-preview1-component-adapter-provider", "Apache-2.0 WITH LLVM-exception"), // rustc // tidy-alphabetical-end ]; @@ -198,57 +205,22 @@ pub(crate) struct WorkspaceInfo<'a> { const EXCEPTIONS_CARGO: ExceptionList = &[ // tidy-alphabetical-start - ("arrayref", "BSD-2-Clause"), ("bitmaps", "MPL-2.0+"), - ("blake3", "CC0-1.0 OR Apache-2.0 OR Apache-2.0 WITH LLVM-exception"), - ("ciborium", "Apache-2.0"), - ("ciborium-io", "Apache-2.0"), - ("ciborium-ll", "Apache-2.0"), - ("constant_time_eq", "CC0-1.0 OR MIT-0 OR Apache-2.0"), - ("dunce", "CC0-1.0 OR MIT-0 OR Apache-2.0"), - ("encoding_rs", "(Apache-2.0 OR MIT) AND BSD-3-Clause"), - ("fiat-crypto", "MIT OR Apache-2.0 OR BSD-1-Clause"), - ("foldhash", "Zlib"), ("im-rc", "MPL-2.0+"), - ("libz-rs-sys", "Zlib"), - ("normalize-line-endings", "Apache-2.0"), - ("openssl", "Apache-2.0"), - ("ring", "Apache-2.0 AND ISC"), - ("ryu", "Apache-2.0 OR BSL-1.0"), // BSL is not acceptble, but we use it under Apache-2.0 - ("similar", "Apache-2.0"), ("sized-chunks", "MPL-2.0+"), - ("subtle", "BSD-3-Clause"), - ("supports-hyperlinks", "Apache-2.0"), - ("unicode-bom", "Apache-2.0"), - ("zlib-rs", "Zlib"), // tidy-alphabetical-end ]; const EXCEPTIONS_RUST_ANALYZER: ExceptionList = &[ // tidy-alphabetical-start - ("dissimilar", "Apache-2.0"), - ("foldhash", "Zlib"), - ("notify", "CC0-1.0"), ("option-ext", "MPL-2.0"), - ("pulldown-cmark-to-cmark", "Apache-2.0"), - ("rustc_apfloat", "Apache-2.0 WITH LLVM-exception"), - ("ryu", "Apache-2.0 OR BSL-1.0"), // BSL is not acceptble, but we use it under Apache-2.0 - ("scip", "Apache-2.0"), // tidy-alphabetical-end ]; const EXCEPTIONS_RUSTC_PERF: ExceptionList = &[ // tidy-alphabetical-start - ("alloc-no-stdlib", "BSD-3-Clause"), - ("alloc-stdlib", "BSD-3-Clause"), - ("brotli", "BSD-3-Clause/MIT"), - ("brotli-decompressor", "BSD-3-Clause/MIT"), - ("encoding_rs", "(Apache-2.0 OR MIT) AND BSD-3-Clause"), ("inferno", "CDDL-1.0"), ("option-ext", "MPL-2.0"), - ("ryu", "Apache-2.0 OR BSL-1.0"), - ("snap", "BSD-3-Clause"), - ("subtle", "BSD-3-Clause"), // tidy-alphabetical-end ]; @@ -258,36 +230,10 @@ pub(crate) struct WorkspaceInfo<'a> { ("cssparser-macros", "MPL-2.0"), ("dtoa-short", "MPL-2.0"), ("mdbook", "MPL-2.0"), - ("ryu", "Apache-2.0 OR BSL-1.0"), // tidy-alphabetical-end ]; -const EXCEPTIONS_CRANELIFT: ExceptionList = &[ - // tidy-alphabetical-start - ("cranelift-assembler-x64", "Apache-2.0 WITH LLVM-exception"), - ("cranelift-assembler-x64-meta", "Apache-2.0 WITH LLVM-exception"), - ("cranelift-bforest", "Apache-2.0 WITH LLVM-exception"), - ("cranelift-bitset", "Apache-2.0 WITH LLVM-exception"), - ("cranelift-codegen", "Apache-2.0 WITH LLVM-exception"), - ("cranelift-codegen-meta", "Apache-2.0 WITH LLVM-exception"), - ("cranelift-codegen-shared", "Apache-2.0 WITH LLVM-exception"), - ("cranelift-control", "Apache-2.0 WITH LLVM-exception"), - ("cranelift-entity", "Apache-2.0 WITH LLVM-exception"), - ("cranelift-frontend", "Apache-2.0 WITH LLVM-exception"), - ("cranelift-isle", "Apache-2.0 WITH LLVM-exception"), - ("cranelift-jit", "Apache-2.0 WITH LLVM-exception"), - ("cranelift-module", "Apache-2.0 WITH LLVM-exception"), - ("cranelift-native", "Apache-2.0 WITH LLVM-exception"), - ("cranelift-object", "Apache-2.0 WITH LLVM-exception"), - ("cranelift-srcgen", "Apache-2.0 WITH LLVM-exception"), - ("foldhash", "Zlib"), - ("mach2", "BSD-2-Clause OR MIT OR Apache-2.0"), - ("regalloc2", "Apache-2.0 WITH LLVM-exception"), - ("target-lexicon", "Apache-2.0 WITH LLVM-exception"), - ("wasmtime-jit-icache-coherence", "Apache-2.0 WITH LLVM-exception"), - ("wasmtime-math", "Apache-2.0 WITH LLVM-exception"), - // tidy-alphabetical-end -]; +const EXCEPTIONS_CRANELIFT: ExceptionList = &[]; const EXCEPTIONS_GCC: ExceptionList = &[ // tidy-alphabetical-start @@ -296,13 +242,9 @@ pub(crate) struct WorkspaceInfo<'a> { // tidy-alphabetical-end ]; -const EXCEPTIONS_BOOTSTRAP: ExceptionList = &[ - ("ryu", "Apache-2.0 OR BSL-1.0"), // through serde. BSL is not acceptble, but we use it under Apache-2.0 -]; +const EXCEPTIONS_BOOTSTRAP: ExceptionList = &[]; -const EXCEPTIONS_UEFI_QEMU_TEST: ExceptionList = &[ - ("r-efi", "MIT OR Apache-2.0 OR LGPL-2.1-or-later"), // LGPL is not acceptable, but we use it under MIT OR Apache-2.0 -]; +const EXCEPTIONS_UEFI_QEMU_TEST: ExceptionList = &[]; #[derive(Clone, Copy)] struct ListLocation { @@ -867,6 +809,11 @@ fn check_license_exceptions( } } } + if LICENSES.contains(license) || LICENSES_TOOLS.contains(license) { + check.error(format!( + "dependency exception `{name}` is not necessary. `{license}` is an allowed license" + )); + } } let exception_names: Vec<_> = exceptions.iter().map(|(name, _license)| *name).collect(); @@ -890,7 +837,7 @@ fn check_license_exceptions( continue; } }; - if !LICENSES.contains(&license.as_str()) { + if !LICENSES.contains(&license.as_str()) && !LICENSES_TOOLS.contains(&license.as_str()) { check.error(format!( "invalid license `{}` for package `{}` in workspace `{workspace}`", license, pkg.id
diff --git a/tests/codegen-llvm/deduced-param-attrs.rs b/tests/codegen-llvm/deduced-param-attrs.rs index 34504c8..f99615c 100644 --- a/tests/codegen-llvm/deduced-param-attrs.rs +++ b/tests/codegen-llvm/deduced-param-attrs.rs
@@ -1,4 +1,4 @@ -//@ compile-flags: -Copt-level=3 +//@ compile-flags: -Copt-level=3 -Cno-prepopulate-passes #![crate_type = "lib"] #![allow(internal_features)] @@ -28,7 +28,9 @@ pub fn use_big_struct_immutably(big_struct: BigStruct) { // The by-value parameter for this big struct can't be marked readonly, because we mutate it. // -// CHECK-NOT: @use_big_struct_mutably({{.*}} readonly {{.*}} %big_struct) +// CHECK: @use_big_struct_mutably( +// CHECK-NOT: readonly +// CHECK-SAME: %big_struct) #[no_mangle] pub fn use_big_struct_mutably(mut big_struct: BigStruct) { big_struct.blah[987] = 654; @@ -38,7 +40,9 @@ pub fn use_big_struct_mutably(mut big_struct: BigStruct) { // The by-value parameter for this big struct can't be marked readonly, because it contains // UnsafeCell. // -// CHECK-NOT: @use_big_cell_container({{.*}} readonly {{.*}} %big_cell_container) +// CHECK: @use_big_cell_container( +// CHECK-NOT: readonly +// CHECK-SAME: %big_cell_container) #[no_mangle] pub fn use_big_cell_container(big_cell_container: BigCellContainer) { hint::black_box(&big_cell_container); @@ -47,14 +51,31 @@ pub fn use_big_cell_container(big_cell_container: BigCellContainer) { // Make sure that we don't mistakenly mark a big struct as `readonly` when passed through a generic // type parameter if it contains UnsafeCell. // -// CHECK-NOT: @use_something({{.*}} readonly {{.*}} %something) +// CHECK: @use_something( +// CHECK-NOT: readonly +// CHECK-SAME: %something) #[no_mangle] #[inline(never)] pub fn use_something<T>(something: T) { hint::black_box(&something); } +// Make sure that we still mark a big `Freeze` struct as `readonly` when passed through a generic +// type parameter. +// +// CHECK: @use_something_freeze( +// CHECK-SAME: readonly +// CHECK-SAME: %x) +#[no_mangle] +#[inline(never)] +pub fn use_something_freeze<T>(x: T) {} + #[no_mangle] pub fn forward_big_cell_container(big_cell_container: BigCellContainer) { use_something(big_cell_container) } + +#[no_mangle] +pub fn forward_big_container(big_struct: BigStruct) { + use_something_freeze(big_struct) +}
diff --git a/tests/codegen-llvm/gpu_offload/gpu_host.rs b/tests/codegen-llvm/gpu_offload/gpu_host.rs index 513e274..fac4054 100644 --- a/tests/codegen-llvm/gpu_offload/gpu_host.rs +++ b/tests/codegen-llvm/gpu_offload/gpu_host.rs
@@ -21,16 +21,15 @@ fn main() { } // CHECK: %struct.__tgt_offload_entry = type { i64, i16, i16, i32, ptr, ptr, i64, i64, ptr } -// CHECK: %struct.__tgt_kernel_arguments = type { i32, i32, ptr, ptr, ptr, ptr, ptr, ptr, i64, i64, [3 x i32], [3 x i32], i32 } // CHECK: %struct.ident_t = type { i32, i32, i32, i32, ptr } // CHECK: %struct.__tgt_bin_desc = type { i32, ptr, ptr, ptr } +// CHECK: %struct.__tgt_kernel_arguments = type { i32, i32, ptr, ptr, ptr, ptr, ptr, ptr, i64, i64, [3 x i32], [3 x i32], i32 } // CHECK: @.offload_sizes.1 = private unnamed_addr constant [1 x i64] [i64 1024] -// CHECK: @.offload_maptypes.1 = private unnamed_addr constant [1 x i64] [i64 3] +// CHECK: @.offload_maptypes.1 = private unnamed_addr constant [1 x i64] [i64 35] // CHECK: @.kernel_1.region_id = weak unnamed_addr constant i8 0 // CHECK: @.offloading.entry_name.1 = internal unnamed_addr constant [9 x i8] c"kernel_1\00", section ".llvm.rodata.offloading", align 1 -// CHECK: @.offloading.entry.kernel_1 = weak constant %struct.__tgt_offload_entry { i64 0, i16 1, i16 1, i32 0, ptr @.kernel_1.region_id, ptr @.offloading.entry_name.1, i64 0, i64 0, ptr null }, section ".omp_offloading_entries", align 1 -// CHECK: @my_struct_global2 = external global %struct.__tgt_kernel_arguments +// CHECK: @.offloading.entry.kernel_1 = weak constant %struct.__tgt_offload_entry { i64 0, i16 1, i16 1, i32 0, ptr @.kernel_1.region_id, ptr @.offloading.entry_name.1, i64 0, i64 0, ptr null }, section "llvm_offload_entries", align 8 // CHECK: @0 = private unnamed_addr constant [23 x i8] c";unknown;unknown;0;0;;\00", align 1 // CHECK: @1 = private unnamed_addr constant %struct.ident_t { i32 0, i32 2, i32 0, i32 22, ptr @0 }, align 8 @@ -43,34 +42,61 @@ fn main() { // CHECK-NEXT: %.offload_baseptrs = alloca [1 x ptr], align 8 // CHECK-NEXT: %.offload_ptrs = alloca [1 x ptr], align 8 // CHECK-NEXT: %.offload_sizes = alloca [1 x i64], align 8 -// CHECK-NEXT: %x.addr = alloca ptr, align 8 -// CHECK-NEXT: store ptr %x, ptr %x.addr, align 8 -// CHECK-NEXT: %1 = load ptr, ptr %x.addr, align 8 -// CHECK-NEXT: %2 = getelementptr inbounds float, ptr %1, i32 0 +// CHECK-NEXT: %kernel_args = alloca %struct.__tgt_kernel_arguments, align 8 // CHECK: call void @llvm.memset.p0.i64(ptr align 8 %EmptyDesc, i8 0, i64 32, i1 false) +// CHECK-NEXT: %1 = getelementptr inbounds float, ptr %x, i32 0 // CHECK-NEXT: call void @__tgt_register_lib(ptr %EmptyDesc) // CHECK-NEXT: call void @__tgt_init_all_rtls() -// CHECK-NEXT: %3 = getelementptr inbounds [1 x ptr], ptr %.offload_baseptrs, i32 0, i32 0 +// CHECK-NEXT: %2 = getelementptr inbounds [1 x ptr], ptr %.offload_baseptrs, i32 0, i32 0 +// CHECK-NEXT: store ptr %x, ptr %2, align 8 +// CHECK-NEXT: %3 = getelementptr inbounds [1 x ptr], ptr %.offload_ptrs, i32 0, i32 0 // CHECK-NEXT: store ptr %1, ptr %3, align 8 -// CHECK-NEXT: %4 = getelementptr inbounds [1 x ptr], ptr %.offload_ptrs, i32 0, i32 0 -// CHECK-NEXT: store ptr %2, ptr %4, align 8 -// CHECK-NEXT: %5 = getelementptr inbounds [1 x i64], ptr %.offload_sizes, i32 0, i32 0 -// CHECK-NEXT: store i64 1024, ptr %5, align 8 -// CHECK-NEXT: %6 = getelementptr inbounds [1 x ptr], ptr %.offload_baseptrs, i32 0, i32 0 -// CHECK-NEXT: %7 = getelementptr inbounds [1 x ptr], ptr %.offload_ptrs, i32 0, i32 0 -// CHECK-NEXT: %8 = getelementptr inbounds [1 x i64], ptr %.offload_sizes, i32 0, i32 0 -// CHECK-NEXT: call void @__tgt_target_data_begin_mapper(ptr @1, i64 -1, i32 1, ptr %6, ptr %7, ptr %8, ptr @.offload_maptypes.1, ptr null, ptr null) -// CHECK-NEXT: call void @kernel_1(ptr noalias noundef nonnull align 4 dereferenceable(1024) %x) -// CHECK-NEXT: %9 = getelementptr inbounds [1 x ptr], ptr %.offload_baseptrs, i32 0, i32 0 -// CHECK-NEXT: %10 = getelementptr inbounds [1 x ptr], ptr %.offload_ptrs, i32 0, i32 0 -// CHECK-NEXT: %11 = getelementptr inbounds [1 x i64], ptr %.offload_sizes, i32 0, i32 0 -// CHECK-NEXT: call void @__tgt_target_data_end_mapper(ptr @1, i64 -1, i32 1, ptr %9, ptr %10, ptr %11, ptr @.offload_maptypes.1, ptr null, ptr null) +// CHECK-NEXT: %4 = getelementptr inbounds [1 x i64], ptr %.offload_sizes, i32 0, i32 0 +// CHECK-NEXT: store i64 1024, ptr %4, align 8 +// CHECK-NEXT: %5 = getelementptr inbounds [1 x ptr], ptr %.offload_baseptrs, i32 0, i32 0 +// CHECK-NEXT: %6 = getelementptr inbounds [1 x ptr], ptr %.offload_ptrs, i32 0, i32 0 +// CHECK-NEXT: %7 = getelementptr inbounds [1 x i64], ptr %.offload_sizes, i32 0, i32 0 +// CHECK-NEXT: call void @__tgt_target_data_begin_mapper(ptr @1, i64 -1, i32 1, ptr %5, ptr %6, ptr %7, ptr @.offload_maptypes.1, ptr null, ptr null) +// CHECK-NEXT: %8 = getelementptr inbounds %struct.__tgt_kernel_arguments, ptr %kernel_args, i32 0, i32 0 +// CHECK-NEXT: store i32 3, ptr %8, align 4 +// CHECK-NEXT: %9 = getelementptr inbounds %struct.__tgt_kernel_arguments, ptr %kernel_args, i32 0, i32 1 +// CHECK-NEXT: store i32 1, ptr %9, align 4 +// CHECK-NEXT: %10 = getelementptr inbounds %struct.__tgt_kernel_arguments, ptr %kernel_args, i32 0, i32 2 +// CHECK-NEXT: store ptr %5, ptr %10, align 8 +// CHECK-NEXT: %11 = getelementptr inbounds %struct.__tgt_kernel_arguments, ptr %kernel_args, i32 0, i32 3 +// CHECK-NEXT: store ptr %6, ptr %11, align 8 +// CHECK-NEXT: %12 = getelementptr inbounds %struct.__tgt_kernel_arguments, ptr %kernel_args, i32 0, i32 4 +// CHECK-NEXT: store ptr %7, ptr %12, align 8 +// CHECK-NEXT: %13 = getelementptr inbounds %struct.__tgt_kernel_arguments, ptr %kernel_args, i32 0, i32 5 +// CHECK-NEXT: store ptr @.offload_maptypes.1, ptr %13, align 8 +// CHECK-NEXT: %14 = getelementptr inbounds %struct.__tgt_kernel_arguments, ptr %kernel_args, i32 0, i32 6 +// CHECK-NEXT: store ptr null, ptr %14, align 8 +// CHECK-NEXT: %15 = getelementptr inbounds %struct.__tgt_kernel_arguments, ptr %kernel_args, i32 0, i32 7 +// CHECK-NEXT: store ptr null, ptr %15, align 8 +// CHECK-NEXT: %16 = getelementptr inbounds %struct.__tgt_kernel_arguments, ptr %kernel_args, i32 0, i32 8 +// CHECK-NEXT: store i64 0, ptr %16, align 8 +// CHECK-NEXT: %17 = getelementptr inbounds %struct.__tgt_kernel_arguments, ptr %kernel_args, i32 0, i32 9 +// CHECK-NEXT: store i64 0, ptr %17, align 8 +// CHECK-NEXT: %18 = getelementptr inbounds %struct.__tgt_kernel_arguments, ptr %kernel_args, i32 0, i32 10 +// CHECK-NEXT: store [3 x i32] [i32 2097152, i32 0, i32 0], ptr %18, align 4 +// CHECK-NEXT: %19 = getelementptr inbounds %struct.__tgt_kernel_arguments, ptr %kernel_args, i32 0, i32 11 +// CHECK-NEXT: store [3 x i32] [i32 256, i32 0, i32 0], ptr %19, align 4 +// CHECK-NEXT: %20 = getelementptr inbounds %struct.__tgt_kernel_arguments, ptr %kernel_args, i32 0, i32 12 +// CHECK-NEXT: store i32 0, ptr %20, align 4 +// CHECK-NEXT: %21 = call i32 @__tgt_target_kernel(ptr @1, i64 -1, i32 2097152, i32 256, ptr @.kernel_1.region_id, ptr %kernel_args) +// CHECK-NEXT: %22 = getelementptr inbounds [1 x ptr], ptr %.offload_baseptrs, i32 0, i32 0 +// CHECK-NEXT: %23 = getelementptr inbounds [1 x ptr], ptr %.offload_ptrs, i32 0, i32 0 +// CHECK-NEXT: %24 = getelementptr inbounds [1 x i64], ptr %.offload_sizes, i32 0, i32 0 +// CHECK-NEXT: call void @__tgt_target_data_end_mapper(ptr @1, i64 -1, i32 1, ptr %22, ptr %23, ptr %24, ptr @.offload_maptypes.1, ptr null, ptr null) // CHECK-NEXT: call void @__tgt_unregister_lib(ptr %EmptyDesc) // CHECK: store ptr %x, ptr %0, align 8 // CHECK-NEXT: call void asm sideeffect "", "r,~{memory}"(ptr nonnull %0) // CHECK: ret void // CHECK-NEXT: } +// CHECK: Function Attrs: nounwind +// CHECK: declare i32 @__tgt_target_kernel(ptr, i64, i32, i32, ptr, ptr) + #[unsafe(no_mangle)] #[inline(never)] pub fn kernel_1(x: &mut [f32; 256]) {
diff --git a/tests/crashes/125323.rs b/tests/crashes/125323.rs deleted file mode 100644 index 180b7bb..0000000 --- a/tests/crashes/125323.rs +++ /dev/null
@@ -1,6 +0,0 @@ -//@ known-bug: rust-lang/rust#125323 -fn main() { - for _ in 0..0 { - [(); loop {}]; - } -}
diff --git a/tests/mir-opt/const_prop/control_flow_simplification.hello.GVN.panic-abort.diff b/tests/mir-opt/const_prop/control_flow_simplification.hello.GVN.panic-abort.diff index 24b1021..5df2232 100644 --- a/tests/mir-opt/const_prop/control_flow_simplification.hello.GVN.panic-abort.diff +++ b/tests/mir-opt/const_prop/control_flow_simplification.hello.GVN.panic-abort.diff
@@ -3,23 +3,17 @@ fn hello() -> () { let mut _0: (); - let mut _1: bool; - let mut _2: !; + let mut _1: !; bb0: { - StorageLive(_1); -- _1 = const <bool as NeedsDrop>::NEEDS; -- switchInt(move _1) -> [0: bb2, otherwise: bb1]; -+ _1 = const false; -+ switchInt(const false) -> [0: bb2, otherwise: bb1]; + goto -> bb2; } bb1: { - _2 = begin_panic::<&str>(const "explicit panic") -> unwind unreachable; + _1 = begin_panic::<&str>(const "explicit panic") -> unwind unreachable; } bb2: { - StorageDead(_1); return; } }
diff --git a/tests/mir-opt/const_prop/control_flow_simplification.hello.GVN.panic-unwind.diff b/tests/mir-opt/const_prop/control_flow_simplification.hello.GVN.panic-unwind.diff index a73485e..788a442 100644 --- a/tests/mir-opt/const_prop/control_flow_simplification.hello.GVN.panic-unwind.diff +++ b/tests/mir-opt/const_prop/control_flow_simplification.hello.GVN.panic-unwind.diff
@@ -3,23 +3,17 @@ fn hello() -> () { let mut _0: (); - let mut _1: bool; - let mut _2: !; + let mut _1: !; bb0: { - StorageLive(_1); -- _1 = const <bool as NeedsDrop>::NEEDS; -- switchInt(move _1) -> [0: bb2, otherwise: bb1]; -+ _1 = const false; -+ switchInt(const false) -> [0: bb2, otherwise: bb1]; + goto -> bb2; } bb1: { - _2 = begin_panic::<&str>(const "explicit panic") -> unwind continue; + _1 = begin_panic::<&str>(const "explicit panic") -> unwind continue; } bb2: { - StorageDead(_1); return; } }
diff --git a/tests/mir-opt/const_prop/control_flow_simplification.rs b/tests/mir-opt/const_prop/control_flow_simplification.rs index 64605ca..8ec630d 100644 --- a/tests/mir-opt/const_prop/control_flow_simplification.rs +++ b/tests/mir-opt/const_prop/control_flow_simplification.rs
@@ -1,4 +1,3 @@ -// skip-filecheck // EMIT_MIR_FOR_EACH_PANIC_STRATEGY //@ test-mir-pass: GVN //@ compile-flags: -Zmir-opt-level=1 @@ -12,6 +11,9 @@ impl<This> NeedsDrop for This {} // EMIT_MIR control_flow_simplification.hello.GVN.diff // EMIT_MIR control_flow_simplification.hello.PreCodegen.before.mir fn hello<T>() { + // CHECK-LABEL: fn hello( + // CHECK: bb0: + // CHECK-NEXT: return; if <bool>::NEEDS { panic!() }
diff --git a/tests/mir-opt/const_prop/trivial_const.rs b/tests/mir-opt/const_prop/trivial_const.rs new file mode 100644 index 0000000..e9134c1 --- /dev/null +++ b/tests/mir-opt/const_prop/trivial_const.rs
@@ -0,0 +1,15 @@ +//@ test-mir-pass: SimplifyConstCondition-after-inst-simplify +//@ compile-flags: -Zmir-enable-passes=+InstSimplify-after-simplifycfg -Zub_checks=false -Zinline-mir + +#![crate_type = "lib"] + +// EMIT_MIR trivial_const.unwrap_unchecked.SimplifyConstCondition-after-inst-simplify.diff +pub fn unwrap_unchecked(v: &Option<i32>) -> i32 { + // CHECK-LABEL: fn unwrap_unchecked( + // CHECK: bb0: { + // CHECK: switchInt({{.*}}) -> [0: [[AssumeFalseBB:bb.*]], 1: + // CHECK: [[AssumeFalseBB]]: { + // CHECK-NEXT: unreachable; + let v = unsafe { v.unwrap_unchecked() }; + v +}
diff --git a/tests/mir-opt/const_prop/trivial_const.unwrap_unchecked.SimplifyConstCondition-after-inst-simplify.diff b/tests/mir-opt/const_prop/trivial_const.unwrap_unchecked.SimplifyConstCondition-after-inst-simplify.diff new file mode 100644 index 0000000..d14c42a --- /dev/null +++ b/tests/mir-opt/const_prop/trivial_const.unwrap_unchecked.SimplifyConstCondition-after-inst-simplify.diff
@@ -0,0 +1,58 @@ +- // MIR for `unwrap_unchecked` before SimplifyConstCondition-after-inst-simplify ++ // MIR for `unwrap_unchecked` after SimplifyConstCondition-after-inst-simplify + + fn unwrap_unchecked(_1: &Option<i32>) -> i32 { + debug v => _1; + let mut _0: i32; + let _2: i32; + let mut _3: std::option::Option<i32>; + scope 1 { + debug v => _2; + } + scope 2 (inlined #[track_caller] Option::<i32>::unwrap_unchecked) { + let mut _4: isize; + scope 3 { + } + scope 4 (inlined #[track_caller] unreachable_unchecked) { + let _5: (); + scope 5 (inlined core::ub_checks::check_language_ub) { + let mut _6: bool; + scope 6 (inlined core::ub_checks::check_language_ub::runtime) { + } + } + } + } + + bb0: { + StorageLive(_2); + StorageLive(_3); + _3 = copy (*_1); + StorageLive(_4); + StorageLive(_5); + _4 = discriminant(_3); + switchInt(move _4) -> [0: bb2, 1: bb3, otherwise: bb1]; + } + + bb1: { + unreachable; + } + + bb2: { +- StorageLive(_6); +- _6 = const false; +- assume(copy _6); +- _5 = unreachable_unchecked::precondition_check() -> [return: bb1, unwind unreachable]; ++ unreachable; + } + + bb3: { + _2 = move ((_3 as Some).0: i32); + StorageDead(_5); + StorageDead(_4); + StorageDead(_3); + _0 = copy _2; + StorageDead(_2); + return; + } + } +
diff --git a/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.rs b/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.rs index 4368933..5534a45 100644 --- a/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.rs +++ b/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.rs
@@ -1,10 +1,14 @@ -// skip-filecheck -//@ compile-flags: -Zmir-enable-passes=+Inline,+GVN --crate-type lib +//@ test-mir-pass: GVN +//@ compile-flags: -Zinline-mir --crate-type lib // EMIT_MIR_FOR_EACH_BIT_WIDTH // EMIT_MIR_FOR_EACH_PANIC_STRATEGY // EMIT_MIR dont_reset_cast_kind_without_updating_operand.test.GVN.diff fn test() { + // CHECK-LABEL: fn test( + // CHECK: debug slf => [[SLF:_.*]]; + // CHECK: debug _x => [[X:_.*]]; + // CHECK: [[X]] = copy [[SLF]] as *mut () (PtrToPtr); let vp_ctx: &Box<()> = &Box::new(()); let slf: *const () = &raw const **vp_ctx; let bytes = std::ptr::slice_from_raw_parts(slf, 1);
diff --git a/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.32bit.panic-abort.diff b/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.32bit.panic-abort.diff index bb10fc8..5d7343a 100644 --- a/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.32bit.panic-abort.diff +++ b/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.32bit.panic-abort.diff
@@ -6,24 +6,26 @@ let _1: &std::boxed::Box<()>; let _2: &std::boxed::Box<()>; let _3: std::boxed::Box<()>; - let mut _6: *const (); - let mut _8: *const [()]; - let mut _9: *const (); - let mut _22: usize; - let mut _23: std::ptr::NonNull<()>; + let mut _4: (); + let mut _7: *const (); + let mut _9: *const [()]; + let mut _10: std::boxed::Box<()>; + let mut _11: *const (); + let mut _25: usize; scope 1 { debug vp_ctx => _1; - let _4: *const (); + let _5: *const (); scope 2 { - debug slf => _9; - let _5: *const [()]; + debug slf => _5; + let _6: *const [()]; scope 3 { - debug bytes => _5; - let _7: *mut (); + debug bytes => _6; + let _8: *mut (); scope 4 { - debug _x => _7; + debug _x => _8; } scope 18 (inlined foo) { + let mut _26: *const [()]; } } scope 16 (inlined slice_from_raw_parts::<()>) { @@ -33,21 +35,22 @@ } } scope 5 (inlined Box::<()>::new) { - let mut _10: usize; - let mut _11: usize; - let mut _12: *mut u8; + let mut _12: usize; + let mut _13: usize; + let mut _14: *mut u8; + let mut _15: *const (); scope 6 (inlined alloc::alloc::exchange_malloc) { - let _13: std::alloc::Layout; - let mut _14: std::result::Result<std::ptr::NonNull<[u8]>, std::alloc::AllocError>; - let mut _15: isize; - let mut _17: !; + let _16: std::alloc::Layout; + let mut _17: std::result::Result<std::ptr::NonNull<[u8]>, std::alloc::AllocError>; + let mut _18: isize; + let mut _20: !; scope 7 { - let _16: std::ptr::NonNull<[u8]>; + let _19: std::ptr::NonNull<[u8]>; scope 8 { scope 11 (inlined NonNull::<[u8]>::as_mut_ptr) { scope 12 (inlined NonNull::<[u8]>::as_non_null_ptr) { scope 13 (inlined NonNull::<[u8]>::cast::<u8>) { - let mut _21: *mut [u8]; + let mut _24: *mut [u8]; scope 14 (inlined NonNull::<[u8]>::as_ptr) { } } @@ -60,31 +63,37 @@ } } scope 9 (inlined #[track_caller] Layout::from_size_align_unchecked) { - let mut _18: bool; - let _19: (); - let mut _20: std::ptr::Alignment; + let mut _21: bool; + let _22: (); + let mut _23: std::ptr::Alignment; } } } bb0: { StorageLive(_1); - StorageLive(_2); +- StorageLive(_2); ++ nop; StorageLive(_3); - StorageLive(_10); - StorageLive(_11); + StorageLive(_4); +- _4 = (); ++ _4 = const (); StorageLive(_12); -- _10 = SizeOf(()); -- _11 = AlignOf(()); -+ _10 = const 0_usize; -+ _11 = const 1_usize; StorageLive(_13); + StorageLive(_14); StorageLive(_15); +- _12 = SizeOf(()); +- _13 = AlignOf(()); ++ _12 = const 0_usize; ++ _13 = const 1_usize; StorageLive(_16); StorageLive(_18); - _18 = const false; -- switchInt(move _18) -> [0: bb6, otherwise: bb5]; -+ switchInt(const false) -> [0: bb6, otherwise: bb5]; + StorageLive(_19); + StorageLive(_20); + StorageLive(_22); + StorageLive(_21); + _21 = UbChecks(); + switchInt(move _21) -> [0: bb6, otherwise: bb5]; } bb1: { @@ -98,76 +107,91 @@ } bb3: { -- _17 = handle_alloc_error(move _13) -> unwind unreachable; -+ _17 = handle_alloc_error(const Layout {{ size: 0_usize, align: std::ptr::Alignment(std::ptr::alignment::AlignmentEnum::_Align1Shl0) }}) -> unwind unreachable; +- _20 = handle_alloc_error(move _16) -> unwind unreachable; ++ _20 = handle_alloc_error(const Layout {{ size: 0_usize, align: std::ptr::Alignment(std::ptr::alignment::AlignmentEnum::_Align1Shl0) }}) -> unwind unreachable; } bb4: { - _16 = copy ((_14 as Ok).0: std::ptr::NonNull<[u8]>); - StorageLive(_21); - _21 = copy _16 as *mut [u8] (Transmute); - _12 = copy _21 as *mut u8 (PtrToPtr); - StorageDead(_21); - StorageDead(_14); - StorageDead(_16); - StorageDead(_15); - StorageDead(_13); - _3 = ShallowInitBox(copy _12, ()); - StorageDead(_12); - StorageDead(_11); - StorageDead(_10); - _2 = &_3; - _1 = copy _2; - StorageDead(_2); - StorageLive(_4); - _23 = copy ((_3.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>); - _9 = copy _23 as *const () (Transmute); - _4 = copy _9; -- StorageLive(_5); -+ nop; - StorageLive(_6); -- _6 = copy _4; -+ _6 = copy _9; - StorageLive(_22); - _22 = const 1_usize; -- _5 = *const [()] from (copy _6, copy _22); -+ _5 = *const [()] from (copy _9, const 1_usize); + _19 = copy ((_17 as Ok).0: std::ptr::NonNull<[u8]>); + StorageLive(_24); + _24 = copy _19 as *mut [u8] (Transmute); + _14 = copy _24 as *mut u8 (PtrToPtr); + StorageDead(_24); + StorageDead(_17); StorageDead(_22); - StorageDead(_6); + StorageDead(_20); + StorageDead(_19); + StorageDead(_18); + StorageDead(_16); + _3 = ShallowInitBox(copy _14, ()); + _15 = copy ((_3.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>) as *const () (Transmute); +- (*_15) = move _4; ++ (*_15) = const (); + StorageDead(_15); + StorageDead(_14); + StorageDead(_13); + StorageDead(_12); + StorageDead(_4); + _2 = &_3; + _1 = &(*_2); +- StorageDead(_2); +- StorageLive(_5); +- _10 = copy (*_1); ++ nop; ++ nop; ++ _10 = copy (*_2); + _11 = copy ((_10.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>) as *const () (Transmute); + _5 = &raw const (*_11); +- StorageLive(_6); ++ nop; StorageLive(_7); - StorageLive(_8); - _8 = copy _5; -- _7 = copy _8 as *mut () (PtrToPtr); -+ _7 = copy _23 as *mut () (Transmute); - StorageDead(_8); + _7 = copy _5; + StorageLive(_25); + _25 = const 1_usize; +- _6 = *const [()] from (copy _7, copy _25); ++ _6 = *const [()] from (copy _5, const 1_usize); + StorageDead(_25); StorageDead(_7); + StorageLive(_8); + StorageLive(_9); + _9 = copy _6; + StorageLive(_26); +- _26 = copy _9; +- _8 = copy _9 as *mut () (PtrToPtr); ++ _26 = copy _6; ++ _8 = copy _5 as *mut () (PtrToPtr); + StorageDead(_26); + StorageDead(_9); + _0 = const (); + StorageDead(_8); +- StorageDead(_6); - StorageDead(_5); + nop; - StorageDead(_4); ++ nop; drop(_3) -> [return: bb1, unwind unreachable]; } bb5: { -- _19 = Layout::from_size_align_unchecked::precondition_check(copy _10, copy _11) -> [return: bb6, unwind unreachable]; -+ _19 = Layout::from_size_align_unchecked::precondition_check(const 0_usize, const 1_usize) -> [return: bb6, unwind unreachable]; +- _22 = Layout::from_size_align_unchecked::precondition_check(copy _12, copy _13) -> [return: bb6, unwind unreachable]; ++ _22 = Layout::from_size_align_unchecked::precondition_check(const 0_usize, const 1_usize) -> [return: bb6, unwind unreachable]; } bb6: { - StorageDead(_18); - StorageLive(_20); -- _20 = copy _11 as std::ptr::Alignment (Transmute); -- _13 = Layout { size: copy _10, align: move _20 }; -+ _20 = const std::ptr::Alignment(std::ptr::alignment::AlignmentEnum::_Align1Shl0); -+ _13 = const Layout {{ size: 0_usize, align: std::ptr::Alignment(std::ptr::alignment::AlignmentEnum::_Align1Shl0) }}; - StorageDead(_20); - StorageLive(_14); -- _14 = std::alloc::Global::alloc_impl(const alloc::alloc::exchange_malloc::promoted[0], copy _13, const false) -> [return: bb7, unwind unreachable]; -+ _14 = std::alloc::Global::alloc_impl(const alloc::alloc::exchange_malloc::promoted[0], const Layout {{ size: 0_usize, align: std::ptr::Alignment(std::ptr::alignment::AlignmentEnum::_Align1Shl0) }}, const false) -> [return: bb7, unwind unreachable]; + StorageDead(_21); + StorageLive(_23); +- _23 = copy _13 as std::ptr::Alignment (Transmute); +- _16 = Layout { size: copy _12, align: move _23 }; ++ _23 = const std::ptr::Alignment(std::ptr::alignment::AlignmentEnum::_Align1Shl0); ++ _16 = const Layout {{ size: 0_usize, align: std::ptr::Alignment(std::ptr::alignment::AlignmentEnum::_Align1Shl0) }}; + StorageDead(_23); + StorageLive(_17); +- _17 = std::alloc::Global::alloc_impl(const alloc::alloc::exchange_malloc::promoted[0], copy _16, const false) -> [return: bb7, unwind unreachable]; ++ _17 = std::alloc::Global::alloc_impl(const alloc::alloc::exchange_malloc::promoted[0], const Layout {{ size: 0_usize, align: std::ptr::Alignment(std::ptr::alignment::AlignmentEnum::_Align1Shl0) }}, const false) -> [return: bb7, unwind unreachable]; } bb7: { - _15 = discriminant(_14); - switchInt(move _15) -> [0: bb4, 1: bb3, otherwise: bb2]; + _18 = discriminant(_17); + switchInt(move _18) -> [0: bb4, 1: bb3, otherwise: bb2]; } + } +
diff --git a/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.32bit.panic-unwind.diff b/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.32bit.panic-unwind.diff index 88754cb..82a14a8 100644 --- a/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.32bit.panic-unwind.diff +++ b/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.32bit.panic-unwind.diff
@@ -6,24 +6,26 @@ let _1: &std::boxed::Box<()>; let _2: &std::boxed::Box<()>; let _3: std::boxed::Box<()>; - let mut _6: *const (); - let mut _8: *const [()]; - let mut _9: *const (); - let mut _10: usize; - let mut _11: std::ptr::NonNull<()>; + let mut _4: (); + let mut _7: *const (); + let mut _9: *const [()]; + let mut _10: std::boxed::Box<()>; + let mut _11: *const (); + let mut _12: usize; scope 1 { debug vp_ctx => _1; - let _4: *const (); + let _5: *const (); scope 2 { - debug slf => _9; - let _5: *const [()]; + debug slf => _5; + let _6: *const [()]; scope 3 { - debug bytes => _5; - let _7: *mut (); + debug bytes => _6; + let _8: *mut (); scope 4 { - debug _x => _7; + debug _x => _8; } scope 7 (inlined foo) { + let mut _13: *const [()]; } } scope 5 (inlined slice_from_raw_parts::<()>) { @@ -35,40 +37,54 @@ bb0: { StorageLive(_1); - StorageLive(_2); +- StorageLive(_2); ++ nop; StorageLive(_3); - _3 = Box::<()>::new(const ()) -> [return: bb1, unwind continue]; + StorageLive(_4); +- _4 = (); +- _3 = Box::<()>::new(move _4) -> [return: bb1, unwind continue]; ++ _4 = const (); ++ _3 = Box::<()>::new(const ()) -> [return: bb1, unwind continue]; } bb1: { + StorageDead(_4); _2 = &_3; - _1 = copy _2; - StorageDead(_2); - StorageLive(_4); - _11 = copy ((_3.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>); - _9 = copy _11 as *const () (Transmute); - _4 = copy _9; + _1 = &(*_2); +- StorageDead(_2); - StorageLive(_5); +- _10 = copy (*_1); + nop; - StorageLive(_6); -- _6 = copy _4; -+ _6 = copy _9; - StorageLive(_10); - _10 = const 1_usize; -- _5 = *const [()] from (copy _6, copy _10); -+ _5 = *const [()] from (copy _9, const 1_usize); - StorageDead(_10); - StorageDead(_6); ++ nop; ++ _10 = copy (*_2); + _11 = copy ((_10.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>) as *const () (Transmute); + _5 = &raw const (*_11); +- StorageLive(_6); ++ nop; StorageLive(_7); - StorageLive(_8); - _8 = copy _5; -- _7 = copy _8 as *mut () (PtrToPtr); -+ _7 = copy _11 as *mut () (Transmute); - StorageDead(_8); + _7 = copy _5; + StorageLive(_12); + _12 = const 1_usize; +- _6 = *const [()] from (copy _7, copy _12); ++ _6 = *const [()] from (copy _5, const 1_usize); + StorageDead(_12); StorageDead(_7); + StorageLive(_8); + StorageLive(_9); + _9 = copy _6; + StorageLive(_13); +- _13 = copy _9; +- _8 = copy _9 as *mut () (PtrToPtr); ++ _13 = copy _6; ++ _8 = copy _5 as *mut () (PtrToPtr); + StorageDead(_13); + StorageDead(_9); + _0 = const (); + StorageDead(_8); +- StorageDead(_6); - StorageDead(_5); + nop; - StorageDead(_4); ++ nop; drop(_3) -> [return: bb2, unwind: bb3]; }
diff --git a/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.64bit.panic-abort.diff b/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.64bit.panic-abort.diff index 97b7c9a..ba5fe28 100644 --- a/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.64bit.panic-abort.diff +++ b/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.64bit.panic-abort.diff
@@ -6,24 +6,26 @@ let _1: &std::boxed::Box<()>; let _2: &std::boxed::Box<()>; let _3: std::boxed::Box<()>; - let mut _6: *const (); - let mut _8: *const [()]; - let mut _9: *const (); - let mut _22: usize; - let mut _23: std::ptr::NonNull<()>; + let mut _4: (); + let mut _7: *const (); + let mut _9: *const [()]; + let mut _10: std::boxed::Box<()>; + let mut _11: *const (); + let mut _25: usize; scope 1 { debug vp_ctx => _1; - let _4: *const (); + let _5: *const (); scope 2 { - debug slf => _9; - let _5: *const [()]; + debug slf => _5; + let _6: *const [()]; scope 3 { - debug bytes => _5; - let _7: *mut (); + debug bytes => _6; + let _8: *mut (); scope 4 { - debug _x => _7; + debug _x => _8; } scope 18 (inlined foo) { + let mut _26: *const [()]; } } scope 16 (inlined slice_from_raw_parts::<()>) { @@ -33,21 +35,22 @@ } } scope 5 (inlined Box::<()>::new) { - let mut _10: usize; - let mut _11: usize; - let mut _12: *mut u8; + let mut _12: usize; + let mut _13: usize; + let mut _14: *mut u8; + let mut _15: *const (); scope 6 (inlined alloc::alloc::exchange_malloc) { - let _13: std::alloc::Layout; - let mut _14: std::result::Result<std::ptr::NonNull<[u8]>, std::alloc::AllocError>; - let mut _15: isize; - let mut _17: !; + let _16: std::alloc::Layout; + let mut _17: std::result::Result<std::ptr::NonNull<[u8]>, std::alloc::AllocError>; + let mut _18: isize; + let mut _20: !; scope 7 { - let _16: std::ptr::NonNull<[u8]>; + let _19: std::ptr::NonNull<[u8]>; scope 8 { scope 11 (inlined NonNull::<[u8]>::as_mut_ptr) { scope 12 (inlined NonNull::<[u8]>::as_non_null_ptr) { scope 13 (inlined NonNull::<[u8]>::cast::<u8>) { - let mut _21: *mut [u8]; + let mut _24: *mut [u8]; scope 14 (inlined NonNull::<[u8]>::as_ptr) { } } @@ -60,31 +63,37 @@ } } scope 9 (inlined #[track_caller] Layout::from_size_align_unchecked) { - let mut _18: bool; - let _19: (); - let mut _20: std::ptr::Alignment; + let mut _21: bool; + let _22: (); + let mut _23: std::ptr::Alignment; } } } bb0: { StorageLive(_1); - StorageLive(_2); +- StorageLive(_2); ++ nop; StorageLive(_3); - StorageLive(_10); - StorageLive(_11); + StorageLive(_4); +- _4 = (); ++ _4 = const (); StorageLive(_12); -- _10 = SizeOf(()); -- _11 = AlignOf(()); -+ _10 = const 0_usize; -+ _11 = const 1_usize; StorageLive(_13); + StorageLive(_14); StorageLive(_15); +- _12 = SizeOf(()); +- _13 = AlignOf(()); ++ _12 = const 0_usize; ++ _13 = const 1_usize; StorageLive(_16); StorageLive(_18); - _18 = const false; -- switchInt(move _18) -> [0: bb6, otherwise: bb5]; -+ switchInt(const false) -> [0: bb6, otherwise: bb5]; + StorageLive(_19); + StorageLive(_20); + StorageLive(_22); + StorageLive(_21); + _21 = UbChecks(); + switchInt(move _21) -> [0: bb6, otherwise: bb5]; } bb1: { @@ -98,76 +107,91 @@ } bb3: { -- _17 = handle_alloc_error(move _13) -> unwind unreachable; -+ _17 = handle_alloc_error(const Layout {{ size: 0_usize, align: std::ptr::Alignment(std::ptr::alignment::AlignmentEnum::_Align1Shl0) }}) -> unwind unreachable; +- _20 = handle_alloc_error(move _16) -> unwind unreachable; ++ _20 = handle_alloc_error(const Layout {{ size: 0_usize, align: std::ptr::Alignment(std::ptr::alignment::AlignmentEnum::_Align1Shl0) }}) -> unwind unreachable; } bb4: { - _16 = copy ((_14 as Ok).0: std::ptr::NonNull<[u8]>); - StorageLive(_21); - _21 = copy _16 as *mut [u8] (Transmute); - _12 = copy _21 as *mut u8 (PtrToPtr); - StorageDead(_21); - StorageDead(_14); - StorageDead(_16); - StorageDead(_15); - StorageDead(_13); - _3 = ShallowInitBox(copy _12, ()); - StorageDead(_12); - StorageDead(_11); - StorageDead(_10); - _2 = &_3; - _1 = copy _2; - StorageDead(_2); - StorageLive(_4); - _23 = copy ((_3.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>); - _9 = copy _23 as *const () (Transmute); - _4 = copy _9; -- StorageLive(_5); -+ nop; - StorageLive(_6); -- _6 = copy _4; -+ _6 = copy _9; - StorageLive(_22); - _22 = const 1_usize; -- _5 = *const [()] from (copy _6, copy _22); -+ _5 = *const [()] from (copy _9, const 1_usize); + _19 = copy ((_17 as Ok).0: std::ptr::NonNull<[u8]>); + StorageLive(_24); + _24 = copy _19 as *mut [u8] (Transmute); + _14 = copy _24 as *mut u8 (PtrToPtr); + StorageDead(_24); + StorageDead(_17); StorageDead(_22); - StorageDead(_6); + StorageDead(_20); + StorageDead(_19); + StorageDead(_18); + StorageDead(_16); + _3 = ShallowInitBox(copy _14, ()); + _15 = copy ((_3.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>) as *const () (Transmute); +- (*_15) = move _4; ++ (*_15) = const (); + StorageDead(_15); + StorageDead(_14); + StorageDead(_13); + StorageDead(_12); + StorageDead(_4); + _2 = &_3; + _1 = &(*_2); +- StorageDead(_2); +- StorageLive(_5); +- _10 = copy (*_1); ++ nop; ++ nop; ++ _10 = copy (*_2); + _11 = copy ((_10.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>) as *const () (Transmute); + _5 = &raw const (*_11); +- StorageLive(_6); ++ nop; StorageLive(_7); - StorageLive(_8); - _8 = copy _5; -- _7 = copy _8 as *mut () (PtrToPtr); -+ _7 = copy _23 as *mut () (Transmute); - StorageDead(_8); + _7 = copy _5; + StorageLive(_25); + _25 = const 1_usize; +- _6 = *const [()] from (copy _7, copy _25); ++ _6 = *const [()] from (copy _5, const 1_usize); + StorageDead(_25); StorageDead(_7); + StorageLive(_8); + StorageLive(_9); + _9 = copy _6; + StorageLive(_26); +- _26 = copy _9; +- _8 = copy _9 as *mut () (PtrToPtr); ++ _26 = copy _6; ++ _8 = copy _5 as *mut () (PtrToPtr); + StorageDead(_26); + StorageDead(_9); + _0 = const (); + StorageDead(_8); +- StorageDead(_6); - StorageDead(_5); + nop; - StorageDead(_4); ++ nop; drop(_3) -> [return: bb1, unwind unreachable]; } bb5: { -- _19 = Layout::from_size_align_unchecked::precondition_check(copy _10, copy _11) -> [return: bb6, unwind unreachable]; -+ _19 = Layout::from_size_align_unchecked::precondition_check(const 0_usize, const 1_usize) -> [return: bb6, unwind unreachable]; +- _22 = Layout::from_size_align_unchecked::precondition_check(copy _12, copy _13) -> [return: bb6, unwind unreachable]; ++ _22 = Layout::from_size_align_unchecked::precondition_check(const 0_usize, const 1_usize) -> [return: bb6, unwind unreachable]; } bb6: { - StorageDead(_18); - StorageLive(_20); -- _20 = copy _11 as std::ptr::Alignment (Transmute); -- _13 = Layout { size: copy _10, align: move _20 }; -+ _20 = const std::ptr::Alignment(std::ptr::alignment::AlignmentEnum::_Align1Shl0); -+ _13 = const Layout {{ size: 0_usize, align: std::ptr::Alignment(std::ptr::alignment::AlignmentEnum::_Align1Shl0) }}; - StorageDead(_20); - StorageLive(_14); -- _14 = std::alloc::Global::alloc_impl(const alloc::alloc::exchange_malloc::promoted[0], copy _13, const false) -> [return: bb7, unwind unreachable]; -+ _14 = std::alloc::Global::alloc_impl(const alloc::alloc::exchange_malloc::promoted[0], const Layout {{ size: 0_usize, align: std::ptr::Alignment(std::ptr::alignment::AlignmentEnum::_Align1Shl0) }}, const false) -> [return: bb7, unwind unreachable]; + StorageDead(_21); + StorageLive(_23); +- _23 = copy _13 as std::ptr::Alignment (Transmute); +- _16 = Layout { size: copy _12, align: move _23 }; ++ _23 = const std::ptr::Alignment(std::ptr::alignment::AlignmentEnum::_Align1Shl0); ++ _16 = const Layout {{ size: 0_usize, align: std::ptr::Alignment(std::ptr::alignment::AlignmentEnum::_Align1Shl0) }}; + StorageDead(_23); + StorageLive(_17); +- _17 = std::alloc::Global::alloc_impl(const alloc::alloc::exchange_malloc::promoted[0], copy _16, const false) -> [return: bb7, unwind unreachable]; ++ _17 = std::alloc::Global::alloc_impl(const alloc::alloc::exchange_malloc::promoted[0], const Layout {{ size: 0_usize, align: std::ptr::Alignment(std::ptr::alignment::AlignmentEnum::_Align1Shl0) }}, const false) -> [return: bb7, unwind unreachable]; } bb7: { - _15 = discriminant(_14); - switchInt(move _15) -> [0: bb4, 1: bb3, otherwise: bb2]; + _18 = discriminant(_17); + switchInt(move _18) -> [0: bb4, 1: bb3, otherwise: bb2]; } + } +
diff --git a/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.64bit.panic-unwind.diff b/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.64bit.panic-unwind.diff index 88754cb..82a14a8 100644 --- a/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.64bit.panic-unwind.diff +++ b/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.64bit.panic-unwind.diff
@@ -6,24 +6,26 @@ let _1: &std::boxed::Box<()>; let _2: &std::boxed::Box<()>; let _3: std::boxed::Box<()>; - let mut _6: *const (); - let mut _8: *const [()]; - let mut _9: *const (); - let mut _10: usize; - let mut _11: std::ptr::NonNull<()>; + let mut _4: (); + let mut _7: *const (); + let mut _9: *const [()]; + let mut _10: std::boxed::Box<()>; + let mut _11: *const (); + let mut _12: usize; scope 1 { debug vp_ctx => _1; - let _4: *const (); + let _5: *const (); scope 2 { - debug slf => _9; - let _5: *const [()]; + debug slf => _5; + let _6: *const [()]; scope 3 { - debug bytes => _5; - let _7: *mut (); + debug bytes => _6; + let _8: *mut (); scope 4 { - debug _x => _7; + debug _x => _8; } scope 7 (inlined foo) { + let mut _13: *const [()]; } } scope 5 (inlined slice_from_raw_parts::<()>) { @@ -35,40 +37,54 @@ bb0: { StorageLive(_1); - StorageLive(_2); +- StorageLive(_2); ++ nop; StorageLive(_3); - _3 = Box::<()>::new(const ()) -> [return: bb1, unwind continue]; + StorageLive(_4); +- _4 = (); +- _3 = Box::<()>::new(move _4) -> [return: bb1, unwind continue]; ++ _4 = const (); ++ _3 = Box::<()>::new(const ()) -> [return: bb1, unwind continue]; } bb1: { + StorageDead(_4); _2 = &_3; - _1 = copy _2; - StorageDead(_2); - StorageLive(_4); - _11 = copy ((_3.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>); - _9 = copy _11 as *const () (Transmute); - _4 = copy _9; + _1 = &(*_2); +- StorageDead(_2); - StorageLive(_5); +- _10 = copy (*_1); + nop; - StorageLive(_6); -- _6 = copy _4; -+ _6 = copy _9; - StorageLive(_10); - _10 = const 1_usize; -- _5 = *const [()] from (copy _6, copy _10); -+ _5 = *const [()] from (copy _9, const 1_usize); - StorageDead(_10); - StorageDead(_6); ++ nop; ++ _10 = copy (*_2); + _11 = copy ((_10.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>) as *const () (Transmute); + _5 = &raw const (*_11); +- StorageLive(_6); ++ nop; StorageLive(_7); - StorageLive(_8); - _8 = copy _5; -- _7 = copy _8 as *mut () (PtrToPtr); -+ _7 = copy _11 as *mut () (Transmute); - StorageDead(_8); + _7 = copy _5; + StorageLive(_12); + _12 = const 1_usize; +- _6 = *const [()] from (copy _7, copy _12); ++ _6 = *const [()] from (copy _5, const 1_usize); + StorageDead(_12); StorageDead(_7); + StorageLive(_8); + StorageLive(_9); + _9 = copy _6; + StorageLive(_13); +- _13 = copy _9; +- _8 = copy _9 as *mut () (PtrToPtr); ++ _13 = copy _6; ++ _8 = copy _5 as *mut () (PtrToPtr); + StorageDead(_13); + StorageDead(_9); + _0 = const (); + StorageDead(_8); +- StorageDead(_6); - StorageDead(_5); + nop; - StorageDead(_4); ++ nop; drop(_3) -> [return: bb2, unwind: bb3]; }
diff --git a/tests/mir-opt/pre-codegen/two_unwrap_unchecked.rs b/tests/mir-opt/pre-codegen/two_unwrap_unchecked.rs new file mode 100644 index 0000000..7b742b9 --- /dev/null +++ b/tests/mir-opt/pre-codegen/two_unwrap_unchecked.rs
@@ -0,0 +1,15 @@ +//@ compile-flags: -O + +#![crate_type = "lib"] + +// EMIT_MIR two_unwrap_unchecked.two_unwrap_unchecked.GVN.diff +// EMIT_MIR two_unwrap_unchecked.two_unwrap_unchecked.PreCodegen.after.mir +pub fn two_unwrap_unchecked(v: &Option<i32>) -> i32 { + // CHECK-LABEL: fn two_unwrap_unchecked( + // CHECK: [[DEREF_V:_.*]] = copy (*_1); + // CHECK: [[V1V2:_.*]] = copy (([[DEREF_V]] as Some).0: i32); + // CHECK: _0 = Add(copy [[V1V2]], copy [[V1V2]]); + let v1 = unsafe { v.unwrap_unchecked() }; + let v2 = unsafe { v.unwrap_unchecked() }; + v1 + v2 +}
diff --git a/tests/mir-opt/pre-codegen/two_unwrap_unchecked.two_unwrap_unchecked.GVN.diff b/tests/mir-opt/pre-codegen/two_unwrap_unchecked.two_unwrap_unchecked.GVN.diff new file mode 100644 index 0000000..5b063e6 --- /dev/null +++ b/tests/mir-opt/pre-codegen/two_unwrap_unchecked.two_unwrap_unchecked.GVN.diff
@@ -0,0 +1,105 @@ +- // MIR for `two_unwrap_unchecked` before GVN ++ // MIR for `two_unwrap_unchecked` after GVN + + fn two_unwrap_unchecked(_1: &Option<i32>) -> i32 { + debug v => _1; + let mut _0: i32; + let _2: i32; + let mut _3: std::option::Option<i32>; + let mut _5: std::option::Option<i32>; + let mut _6: i32; + let mut _7: i32; + scope 1 { + debug v1 => _2; + let _4: i32; + scope 2 { + debug v2 => _4; + } + scope 8 (inlined #[track_caller] Option::<i32>::unwrap_unchecked) { + let mut _9: isize; + scope 9 { + } + scope 10 (inlined #[track_caller] unreachable_unchecked) { + scope 11 (inlined core::ub_checks::check_language_ub) { + scope 12 (inlined core::ub_checks::check_language_ub::runtime) { + } + } + } + } + } + scope 3 (inlined #[track_caller] Option::<i32>::unwrap_unchecked) { + let mut _8: isize; + scope 4 { + } + scope 5 (inlined #[track_caller] unreachable_unchecked) { + scope 6 (inlined core::ub_checks::check_language_ub) { + scope 7 (inlined core::ub_checks::check_language_ub::runtime) { + } + } + } + } + + bb0: { +- StorageLive(_2); +- StorageLive(_3); ++ nop; ++ nop; + _3 = copy (*_1); +- StorageLive(_8); ++ nop; + _8 = discriminant(_3); +- switchInt(move _8) -> [0: bb2, 1: bb3, otherwise: bb1]; ++ switchInt(copy _8) -> [0: bb2, 1: bb3, otherwise: bb1]; + } + + bb1: { + unreachable; + } + + bb2: { + unreachable; + } + + bb3: { +- _2 = move ((_3 as Some).0: i32); +- StorageDead(_8); +- StorageDead(_3); ++ _2 = copy ((_3 as Some).0: i32); ++ nop; ++ nop; + StorageLive(_4); + StorageLive(_5); +- _5 = copy (*_1); ++ _5 = copy _3; + StorageLive(_9); +- _9 = discriminant(_5); +- switchInt(move _9) -> [0: bb4, 1: bb5, otherwise: bb1]; ++ _9 = copy _8; ++ switchInt(copy _8) -> [0: bb4, 1: bb5, otherwise: bb1]; + } + + bb4: { + unreachable; + } + + bb5: { +- _4 = move ((_5 as Some).0: i32); ++ _4 = copy _2; + StorageDead(_9); + StorageDead(_5); + StorageLive(_6); + _6 = copy _2; + StorageLive(_7); +- _7 = copy _4; +- _0 = Add(move _6, move _7); ++ _7 = copy _2; ++ _0 = Add(copy _2, copy _2); + StorageDead(_7); + StorageDead(_6); + StorageDead(_4); +- StorageDead(_2); ++ nop; + return; + } + } +
diff --git a/tests/mir-opt/pre-codegen/two_unwrap_unchecked.two_unwrap_unchecked.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/two_unwrap_unchecked.two_unwrap_unchecked.PreCodegen.after.mir new file mode 100644 index 0000000..b2b7f88 --- /dev/null +++ b/tests/mir-opt/pre-codegen/two_unwrap_unchecked.two_unwrap_unchecked.PreCodegen.after.mir
@@ -0,0 +1,51 @@ +// MIR for `two_unwrap_unchecked` after PreCodegen + +fn two_unwrap_unchecked(_1: &Option<i32>) -> i32 { + debug v => _1; + let mut _0: i32; + let mut _2: std::option::Option<i32>; + let _4: i32; + scope 1 { + debug v1 => _4; + scope 2 { + debug v2 => _4; + } + scope 8 (inlined #[track_caller] Option::<i32>::unwrap_unchecked) { + scope 9 { + } + scope 10 (inlined #[track_caller] unreachable_unchecked) { + scope 11 (inlined core::ub_checks::check_language_ub) { + scope 12 (inlined core::ub_checks::check_language_ub::runtime) { + } + } + } + } + } + scope 3 (inlined #[track_caller] Option::<i32>::unwrap_unchecked) { + let mut _3: isize; + scope 4 { + } + scope 5 (inlined #[track_caller] unreachable_unchecked) { + scope 6 (inlined core::ub_checks::check_language_ub) { + scope 7 (inlined core::ub_checks::check_language_ub::runtime) { + } + } + } + } + + bb0: { + _2 = copy (*_1); + _3 = discriminant(_2); + switchInt(copy _3) -> [0: bb2, 1: bb1, otherwise: bb2]; + } + + bb1: { + _4 = copy ((_2 as Some).0: i32); + _0 = Add(copy _4, copy _4); + return; + } + + bb2: { + unreachable; + } +}
diff --git a/tests/mir-opt/simplify_if.main.SimplifyConstCondition-after-const-prop.panic-abort.diff b/tests/mir-opt/simplify_if.main.SimplifyConstCondition-after-const-prop.panic-abort.diff deleted file mode 100644 index c3076fb..0000000 --- a/tests/mir-opt/simplify_if.main.SimplifyConstCondition-after-const-prop.panic-abort.diff +++ /dev/null
@@ -1,21 +0,0 @@ -- // MIR for `main` before SimplifyConstCondition-after-const-prop -+ // MIR for `main` after SimplifyConstCondition-after-const-prop - - fn main() -> () { - let mut _0: (); - let _1: (); - - bb0: { -- switchInt(const false) -> [0: bb2, otherwise: bb1]; -+ goto -> bb2; - } - - bb1: { - _1 = noop() -> [return: bb2, unwind unreachable]; - } - - bb2: { - return; - } - } -
diff --git a/tests/mir-opt/simplify_if.main.SimplifyConstCondition-after-const-prop.panic-unwind.diff b/tests/mir-opt/simplify_if.main.SimplifyConstCondition-after-const-prop.panic-unwind.diff deleted file mode 100644 index 6c346e2..0000000 --- a/tests/mir-opt/simplify_if.main.SimplifyConstCondition-after-const-prop.panic-unwind.diff +++ /dev/null
@@ -1,21 +0,0 @@ -- // MIR for `main` before SimplifyConstCondition-after-const-prop -+ // MIR for `main` after SimplifyConstCondition-after-const-prop - - fn main() -> () { - let mut _0: (); - let _1: (); - - bb0: { -- switchInt(const false) -> [0: bb2, otherwise: bb1]; -+ goto -> bb2; - } - - bb1: { - _1 = noop() -> [return: bb2, unwind continue]; - } - - bb2: { - return; - } - } -
diff --git a/tests/mir-opt/simplify_if.main.SimplifyConstCondition-after-inst-simplify.panic-abort.diff b/tests/mir-opt/simplify_if.main.SimplifyConstCondition-after-inst-simplify.panic-abort.diff new file mode 100644 index 0000000..c67fd69 --- /dev/null +++ b/tests/mir-opt/simplify_if.main.SimplifyConstCondition-after-inst-simplify.panic-abort.diff
@@ -0,0 +1,25 @@ +- // MIR for `main` before SimplifyConstCondition-after-inst-simplify ++ // MIR for `main` after SimplifyConstCondition-after-inst-simplify + + fn main() -> () { + let mut _0: (); + let mut _1: bool; + let _2: (); + + bb0: { + StorageLive(_1); + _1 = const false; +- switchInt(move _1) -> [0: bb2, otherwise: bb1]; ++ goto -> bb2; + } + + bb1: { + _2 = noop() -> [return: bb2, unwind unreachable]; + } + + bb2: { + StorageDead(_1); + return; + } + } +
diff --git a/tests/mir-opt/simplify_if.main.SimplifyConstCondition-after-inst-simplify.panic-unwind.diff b/tests/mir-opt/simplify_if.main.SimplifyConstCondition-after-inst-simplify.panic-unwind.diff new file mode 100644 index 0000000..07f179d --- /dev/null +++ b/tests/mir-opt/simplify_if.main.SimplifyConstCondition-after-inst-simplify.panic-unwind.diff
@@ -0,0 +1,25 @@ +- // MIR for `main` before SimplifyConstCondition-after-inst-simplify ++ // MIR for `main` after SimplifyConstCondition-after-inst-simplify + + fn main() -> () { + let mut _0: (); + let mut _1: bool; + let _2: (); + + bb0: { + StorageLive(_1); + _1 = const false; +- switchInt(move _1) -> [0: bb2, otherwise: bb1]; ++ goto -> bb2; + } + + bb1: { + _2 = noop() -> [return: bb2, unwind continue]; + } + + bb2: { + StorageDead(_1); + return; + } + } +
diff --git a/tests/mir-opt/simplify_if.rs b/tests/mir-opt/simplify_if.rs index f600c05..6aca233 100644 --- a/tests/mir-opt/simplify_if.rs +++ b/tests/mir-opt/simplify_if.rs
@@ -2,7 +2,7 @@ #[inline(never)] fn noop() {} -// EMIT_MIR simplify_if.main.SimplifyConstCondition-after-const-prop.diff +// EMIT_MIR simplify_if.main.SimplifyConstCondition-after-inst-simplify.diff fn main() { // CHECK-LABEL: fn main(
diff --git a/tests/rustdoc-ui/doc-alias-assoc-const.rs b/tests/rustdoc-ui/doc-alias-assoc-const.rs index d953247..cbbc3fe 100644 --- a/tests/rustdoc-ui/doc-alias-assoc-const.rs +++ b/tests/rustdoc-ui/doc-alias-assoc-const.rs
@@ -1,5 +1,3 @@ -#![feature(trait_alias)] - pub struct Foo; pub trait Bar {
diff --git a/tests/rustdoc-ui/doc-alias-assoc-const.stderr b/tests/rustdoc-ui/doc-alias-assoc-const.stderr index cd3ad4a..cc628c3 100644 --- a/tests/rustdoc-ui/doc-alias-assoc-const.stderr +++ b/tests/rustdoc-ui/doc-alias-assoc-const.stderr
@@ -1,5 +1,5 @@ error: `#[doc(alias = "...")]` isn't allowed on associated constant in trait implementation block - --> $DIR/doc-alias-assoc-const.rs:10:11 + --> $DIR/doc-alias-assoc-const.rs:8:11 | LL | #[doc(alias = "CONST_BAZ")] | ^^^^^^^^^^^^^^^^^^^
diff --git a/tests/rustdoc-ui/intra-doc/hidden-check.rs b/tests/rustdoc-ui/intra-doc/hidden-check.rs new file mode 100644 index 0000000..db2a6dd --- /dev/null +++ b/tests/rustdoc-ui/intra-doc/hidden-check.rs
@@ -0,0 +1,14 @@ +// This test ensures that `doc(hidden)` items intra-doc links are checked whereas private +// items are ignored. + +//@ compile-flags: -Zunstable-options --document-hidden-items + +#![deny(rustdoc::broken_intra_doc_links)] + +/// [not::exist] +//~^ ERROR unresolved link to `not::exist` +#[doc(hidden)] +pub struct X; + +/// [not::exist] +struct Y;
diff --git a/tests/rustdoc-ui/intra-doc/hidden-check.stderr b/tests/rustdoc-ui/intra-doc/hidden-check.stderr new file mode 100644 index 0000000..4fffb80 --- /dev/null +++ b/tests/rustdoc-ui/intra-doc/hidden-check.stderr
@@ -0,0 +1,14 @@ +error: unresolved link to `not::exist` + --> $DIR/hidden-check.rs:8:6 + | +LL | /// [not::exist] + | ^^^^^^^^^^ no item named `not` in scope + | +note: the lint level is defined here + --> $DIR/hidden-check.rs:6:9 + | +LL | #![deny(rustdoc::broken_intra_doc_links)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error +
diff --git a/tests/rustdoc-ui/intra-doc/private-check.rs b/tests/rustdoc-ui/intra-doc/private-check.rs new file mode 100644 index 0000000..2f987d1a --- /dev/null +++ b/tests/rustdoc-ui/intra-doc/private-check.rs
@@ -0,0 +1,14 @@ +// This test ensures that private items intra-doc links are checked whereas `doc(hidden)` +// items are ignored. + +//@ compile-flags: -Zunstable-options --document-private-items + +#![deny(rustdoc::broken_intra_doc_links)] + +/// [not::exist] +#[doc(hidden)] +pub struct X; + +/// [not::exist] +//~^ ERROR unresolved link to `not::exist` +struct Y;
diff --git a/tests/rustdoc-ui/intra-doc/private-check.stderr b/tests/rustdoc-ui/intra-doc/private-check.stderr new file mode 100644 index 0000000..2ec1628 --- /dev/null +++ b/tests/rustdoc-ui/intra-doc/private-check.stderr
@@ -0,0 +1,14 @@ +error: unresolved link to `not::exist` + --> $DIR/private-check.rs:12:6 + | +LL | /// [not::exist] + | ^^^^^^^^^^ no item named `not` in scope + | +note: the lint level is defined here + --> $DIR/private-check.rs:6:9 + | +LL | #![deny(rustdoc::broken_intra_doc_links)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error +
diff --git a/tests/rustdoc-ui/issues/issue-91713.stdout b/tests/rustdoc-ui/issues/issue-91713.stdout index d34714b..7254708 100644 --- a/tests/rustdoc-ui/issues/issue-91713.stdout +++ b/tests/rustdoc-ui/issues/issue-91713.stdout
@@ -16,11 +16,11 @@ collect-trait-impls check_doc_test_visibility check-doc-cfg -collect-intra-doc-links strip-aliased-non-local strip-hidden (when not --document-hidden-items) strip-private (when not --document-private-items) strip-priv-imports (when --document-private-items) +collect-intra-doc-links propagate-doc-cfg propagate-stability run-lints
diff --git a/tests/ui/associated-consts/ambiguous-associated-type-error-78622.rs b/tests/ui/associated-types/ambiguous-associated-type-error-78622.rs similarity index 100% rename from tests/ui/associated-consts/ambiguous-associated-type-error-78622.rs rename to tests/ui/associated-types/ambiguous-associated-type-error-78622.rs
diff --git a/tests/ui/associated-consts/ambiguous-associated-type-error-78622.stderr b/tests/ui/associated-types/ambiguous-associated-type-error-78622.stderr similarity index 100% rename from tests/ui/associated-consts/ambiguous-associated-type-error-78622.stderr rename to tests/ui/associated-types/ambiguous-associated-type-error-78622.stderr
diff --git a/tests/ui/mismatched_types/mismatched-types-in-trait-implementation-87490.rs b/tests/ui/associated-types/mismatched-types-in-associated-type-87490.rs similarity index 100% rename from tests/ui/mismatched_types/mismatched-types-in-trait-implementation-87490.rs rename to tests/ui/associated-types/mismatched-types-in-associated-type-87490.rs
diff --git a/tests/ui/mismatched_types/mismatched-types-in-trait-implementation-87490.stderr b/tests/ui/associated-types/mismatched-types-in-associated-type-87490.stderr similarity index 87% rename from tests/ui/mismatched_types/mismatched-types-in-trait-implementation-87490.stderr rename to tests/ui/associated-types/mismatched-types-in-associated-type-87490.stderr index bbd7334..0a2dbcd 100644 --- a/tests/ui/mismatched_types/mismatched-types-in-trait-implementation-87490.stderr +++ b/tests/ui/associated-types/mismatched-types-in-associated-type-87490.stderr
@@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/mismatched-types-in-trait-implementation-87490.rs:10:5 + --> $DIR/mismatched-types-in-associated-type-87490.rs:10:5 | LL | fn follow(_: &str) -> <&str as StreamOnce>::Position { | ------------------------------ expected `usize` because of return type
diff --git a/tests/ui/issues/issue-72076.rs b/tests/ui/associated-types/missing-default-associated-type-72076.rs similarity index 63% rename from tests/ui/issues/issue-72076.rs rename to tests/ui/associated-types/missing-default-associated-type-72076.rs index 1659044..c25bdff 100644 --- a/tests/ui/issues/issue-72076.rs +++ b/tests/ui/associated-types/missing-default-associated-type-72076.rs
@@ -1,3 +1,4 @@ +// https://github.com/rust-lang/rust/issues/72076 trait X { type S; fn f() -> Self::S {} //~ ERROR mismatched types
diff --git a/tests/ui/issues/issue-72076.stderr b/tests/ui/associated-types/missing-default-associated-type-72076.stderr similarity index 90% rename from tests/ui/issues/issue-72076.stderr rename to tests/ui/associated-types/missing-default-associated-type-72076.stderr index a08704c..c91dbb6 100644 --- a/tests/ui/issues/issue-72076.stderr +++ b/tests/ui/associated-types/missing-default-associated-type-72076.stderr
@@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/issue-72076.rs:3:23 + --> $DIR/missing-default-associated-type-72076.rs:4:23 | LL | fn f() -> Self::S {} | ^^ expected associated type, found `()`
diff --git a/tests/ui/attributes/attr-mix-new.rs b/tests/ui/attributes/attr-mix-new.rs index bd249a0..c4f080e 100644 --- a/tests/ui/attributes/attr-mix-new.rs +++ b/tests/ui/attributes/attr-mix-new.rs
@@ -5,6 +5,7 @@ #[rustc_dummy(bar)] mod foo { #![feature(globs)] + //~^ WARN crate-level attribute should be in the root module } fn main() {}
diff --git a/tests/ui/attributes/attr-mix-new.stderr b/tests/ui/attributes/attr-mix-new.stderr new file mode 100644 index 0000000..c1bb8a5 --- /dev/null +++ b/tests/ui/attributes/attr-mix-new.stderr
@@ -0,0 +1,10 @@ +warning: crate-level attribute should be in the root module + --> $DIR/attr-mix-new.rs:7:3 + | +LL | #![feature(globs)] + | ^^^^^^^^^^^^^^^^^^ + | + = note: requested on the command line with `-W unused-attributes` + +warning: 1 warning emitted +
diff --git a/tests/ui/attributes/crate-type-macro-empty.rs b/tests/ui/attributes/crate-type-macro-empty.rs index 217ff59..cfc71e6 100644 --- a/tests/ui/attributes/crate-type-macro-empty.rs +++ b/tests/ui/attributes/crate-type-macro-empty.rs
@@ -1,6 +1,7 @@ // Tests for the issue in #137589 #[crate_type = foo!()] //~^ ERROR cannot find macro `foo` in this scope +//~| WARN crate-level attribute should be an inner attribute macro_rules! foo {} //~ ERROR macros must contain at least one rule
diff --git a/tests/ui/attributes/crate-type-macro-empty.stderr b/tests/ui/attributes/crate-type-macro-empty.stderr index 130fa45..0c2c4cf 100644 --- a/tests/ui/attributes/crate-type-macro-empty.stderr +++ b/tests/ui/attributes/crate-type-macro-empty.stderr
@@ -1,5 +1,5 @@ error: macros must contain at least one rule - --> $DIR/crate-type-macro-empty.rs:5:1 + --> $DIR/crate-type-macro-empty.rs:6:1 | LL | macro_rules! foo {} | ^^^^^^^^^^^^^^^^^^^ @@ -11,10 +11,22 @@ | ^^^ consider moving the definition of `foo` before this call | note: a macro with the same name exists, but it appears later - --> $DIR/crate-type-macro-empty.rs:5:14 + --> $DIR/crate-type-macro-empty.rs:6:14 | LL | macro_rules! foo {} | ^^^ -error: aborting due to 2 previous errors +warning: crate-level attribute should be an inner attribute + --> $DIR/crate-type-macro-empty.rs:2:1 + | +LL | #[crate_type = foo!()] + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = note: requested on the command line with `-W unused-attributes` +help: add a `!` + | +LL | #![crate_type = foo!()] + | + + +error: aborting due to 2 previous errors; 1 warning emitted
diff --git a/tests/ui/attributes/crate-type-macro-not-found.rs b/tests/ui/attributes/crate-type-macro-not-found.rs index 824468c..b9f05fa 100644 --- a/tests/ui/attributes/crate-type-macro-not-found.rs +++ b/tests/ui/attributes/crate-type-macro-not-found.rs
@@ -1,5 +1,6 @@ // Tests for the issue in #137589 #[crate_type = foo!()] //~ ERROR cannot find macro `foo` in this scope +//~| WARN crate-level attribute should be an inner attribute macro_rules! foo { ($x:expr) => {"rlib"}
diff --git a/tests/ui/attributes/crate-type-macro-not-found.stderr b/tests/ui/attributes/crate-type-macro-not-found.stderr index a4967e4..7b8c6a8 100644 --- a/tests/ui/attributes/crate-type-macro-not-found.stderr +++ b/tests/ui/attributes/crate-type-macro-not-found.stderr
@@ -5,10 +5,22 @@ | ^^^ consider moving the definition of `foo` before this call | note: a macro with the same name exists, but it appears later - --> $DIR/crate-type-macro-not-found.rs:4:14 + --> $DIR/crate-type-macro-not-found.rs:5:14 | LL | macro_rules! foo { | ^^^ -error: aborting due to 1 previous error +warning: crate-level attribute should be an inner attribute + --> $DIR/crate-type-macro-not-found.rs:2:1 + | +LL | #[crate_type = foo!()] + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = note: requested on the command line with `-W unused-attributes` +help: add a `!` + | +LL | #![crate_type = foo!()] + | + + +error: aborting due to 1 previous error; 1 warning emitted
diff --git a/tests/ui/attributes/inline/attr-usage-inline.rs b/tests/ui/attributes/inline/attr-usage-inline.rs index 8217b98..54f2f80 100644 --- a/tests/ui/attributes/inline/attr-usage-inline.rs +++ b/tests/ui/attributes/inline/attr-usage-inline.rs
@@ -9,16 +9,22 @@ fn f() {} struct I { #[inline] + //~^ WARN attribute cannot be used on + //~| WARN previously accepted i: u8, } #[macro_export] #[inline] +//~^ WARN attribute cannot be used on +//~| WARN previously accepted macro_rules! m_e { () => {}; } #[inline] //~ ERROR: attribute should be applied to function or closure +//~^ WARN attribute cannot be used on +//~| WARN previously accepted macro_rules! m { () => {}; }
diff --git a/tests/ui/attributes/inline/attr-usage-inline.stderr b/tests/ui/attributes/inline/attr-usage-inline.stderr index 9fca17d..0a0af1a 100644 --- a/tests/ui/attributes/inline/attr-usage-inline.stderr +++ b/tests/ui/attributes/inline/attr-usage-inline.stderr
@@ -7,11 +7,39 @@ = help: `#[inline]` can only be applied to functions error[E0518]: attribute should be applied to function or closure - --> $DIR/attr-usage-inline.rs:21:1 + --> $DIR/attr-usage-inline.rs:25:1 | LL | #[inline] | ^^^^^^^^^ not a function or closure -error: aborting due to 2 previous errors +warning: `#[inline]` attribute cannot be used on struct fields + --> $DIR/attr-usage-inline.rs:11:5 + | +LL | #[inline] + | ^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[inline]` can only be applied to functions + = note: requested on the command line with `-W unused-attributes` + +warning: `#[inline]` attribute cannot be used on macro defs + --> $DIR/attr-usage-inline.rs:18:1 + | +LL | #[inline] + | ^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[inline]` can only be applied to functions + +warning: `#[inline]` attribute cannot be used on macro defs + --> $DIR/attr-usage-inline.rs:25:1 + | +LL | #[inline] + | ^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[inline]` can only be applied to functions + +error: aborting due to 2 previous errors; 3 warnings emitted For more information about this error, try `rustc --explain E0518`.
diff --git a/tests/ui/attributes/link-dl.rs b/tests/ui/attributes/link-dl.rs index 0785c83..b3b22c6 100644 --- a/tests/ui/attributes/link-dl.rs +++ b/tests/ui/attributes/link-dl.rs
@@ -9,7 +9,7 @@ //@ revisions: default_fcw allowed //@[allowed] check-pass -#[cfg_attr(allowed, allow(ill_formed_attribute_input))] +#![cfg_attr(allowed, allow(ill_formed_attribute_input))] #[link="dl"] //[default_fcw]~^ ERROR valid forms for the attribute are
diff --git a/tests/ui/attributes/malformed-attrs.rs b/tests/ui/attributes/malformed-attrs.rs index 820484a..26ee89d 100644 --- a/tests/ui/attributes/malformed-attrs.rs +++ b/tests/ui/attributes/malformed-attrs.rs
@@ -73,6 +73,7 @@ //~| ERROR attribute cannot be used on #[crate_name] //~^ ERROR malformed +//~| WARN crate-level attribute should be an inner attribute #[doc] //~^ ERROR valid forms for the attribute are //~| WARN this was previously accepted by the compiler @@ -82,8 +83,12 @@ //~^ ERROR malformed #[link] //~^ ERROR malformed +//~| WARN attribute should be applied to an `extern` block with non-Rust ABI +//~| WARN previously accepted #[link_name] //~^ ERROR malformed +//~| WARN cannot be used on functions +//~| WARN previously accepted #[link_section] //~^ ERROR malformed #[coverage] @@ -95,6 +100,8 @@ //~| WARN this was previously accepted by the compiler #[no_implicit_prelude = 23] //~^ ERROR malformed +//~| WARN cannot be used on functions +//~| WARN previously accepted #[proc_macro = 18] //~^ ERROR malformed //~| ERROR the `#[proc_macro]` attribute is only usable with crates of the `proc-macro` crate type @@ -188,6 +195,8 @@ trait EmptyTrait { //~^ ERROR malformed `debugger_visualizer` attribute input #[automatically_derived = 18] //~^ ERROR malformed +//~| WARN cannot be used on modules +//~| WARN previously accepted mod yooo { }
diff --git a/tests/ui/attributes/malformed-attrs.stderr b/tests/ui/attributes/malformed-attrs.stderr index 70ab3fb..c29bd02 100644 --- a/tests/ui/attributes/malformed-attrs.stderr +++ b/tests/ui/attributes/malformed-attrs.stderr
@@ -1,5 +1,5 @@ error[E0539]: malformed `cfg` attribute input - --> $DIR/malformed-attrs.rs:101:1 + --> $DIR/malformed-attrs.rs:108:1 | LL | #[cfg] | ^^^^^^ @@ -9,20 +9,19 @@ | = note: for more information, visit <https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg-attribute> -error: malformed `cfg_attr` attribute input - --> $DIR/malformed-attrs.rs:103:1 +error[E0539]: malformed `cfg_attr` attribute input + --> $DIR/malformed-attrs.rs:110:1 | LL | #[cfg_attr] | ^^^^^^^^^^^ + | | + | expected this to be a list + | help: must be of the form: `#[cfg_attr(predicate, attr1, attr2, ...)]` | = note: for more information, visit <https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg_attr-attribute> -help: missing condition and attribute - | -LL | #[cfg_attr(condition, attribute, other_attribute, ...)] - | ++++++++++++++++++++++++++++++++++++++++++++ error[E0463]: can't find crate for `wloop` - --> $DIR/malformed-attrs.rs:209:1 + --> $DIR/malformed-attrs.rs:218:1 | LL | extern crate wloop; | ^^^^^^^^^^^^^^^^^^^ can't find crate @@ -42,7 +41,7 @@ | +++++++++++ error: malformed `instruction_set` attribute input - --> $DIR/malformed-attrs.rs:105:1 + --> $DIR/malformed-attrs.rs:112:1 | LL | #[instruction_set] | ^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[instruction_set(set)]` @@ -50,13 +49,13 @@ = note: for more information, visit <https://doc.rust-lang.org/reference/attributes/codegen.html#the-instruction_set-attribute> error: malformed `patchable_function_entry` attribute input - --> $DIR/malformed-attrs.rs:107:1 + --> $DIR/malformed-attrs.rs:114:1 | LL | #[patchable_function_entry] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[patchable_function_entry(prefix_nops = m, entry_nops = n)]` error: malformed `must_not_suspend` attribute input - --> $DIR/malformed-attrs.rs:131:1 + --> $DIR/malformed-attrs.rs:138:1 | LL | #[must_not_suspend()] | ^^^^^^^^^^^^^^^^^^^^^ @@ -71,13 +70,13 @@ | error: malformed `cfi_encoding` attribute input - --> $DIR/malformed-attrs.rs:133:1 + --> $DIR/malformed-attrs.rs:140:1 | LL | #[cfi_encoding] | ^^^^^^^^^^^^^^^ help: must be of the form: `#[cfi_encoding = "encoding"]` error: malformed `allow` attribute input - --> $DIR/malformed-attrs.rs:177:1 + --> $DIR/malformed-attrs.rs:184:1 | LL | #[allow] | ^^^^^^^^ @@ -93,7 +92,7 @@ | +++++++++++++++++++++++++++++++++++++ error: malformed `expect` attribute input - --> $DIR/malformed-attrs.rs:179:1 + --> $DIR/malformed-attrs.rs:186:1 | LL | #[expect] | ^^^^^^^^^ @@ -109,7 +108,7 @@ | +++++++++++++++++++++++++++++++++++++ error: malformed `warn` attribute input - --> $DIR/malformed-attrs.rs:181:1 + --> $DIR/malformed-attrs.rs:188:1 | LL | #[warn] | ^^^^^^^ @@ -125,7 +124,7 @@ | +++++++++++++++++++++++++++++++++++++ error: malformed `deny` attribute input - --> $DIR/malformed-attrs.rs:183:1 + --> $DIR/malformed-attrs.rs:190:1 | LL | #[deny] | ^^^^^^^ @@ -141,7 +140,7 @@ | +++++++++++++++++++++++++++++++++++++ error: malformed `forbid` attribute input - --> $DIR/malformed-attrs.rs:185:1 + --> $DIR/malformed-attrs.rs:192:1 | LL | #[forbid] | ^^^^^^^^^ @@ -157,13 +156,13 @@ | +++++++++++++++++++++++++++++++++++++ error: malformed `thread_local` attribute input - --> $DIR/malformed-attrs.rs:201:1 + --> $DIR/malformed-attrs.rs:210:1 | LL | #[thread_local()] | ^^^^^^^^^^^^^^^^^ help: must be of the form: `#[thread_local]` error: malformed `no_link` attribute input - --> $DIR/malformed-attrs.rs:205:1 + --> $DIR/malformed-attrs.rs:214:1 | LL | #[no_link()] | ^^^^^^^^^^^^ help: must be of the form: `#[no_link]` @@ -171,25 +170,25 @@ = note: for more information, visit <https://doc.rust-lang.org/reference/items/extern-crates.html#the-no_link-attribute> error: the `#[proc_macro]` attribute is only usable with crates of the `proc-macro` crate type - --> $DIR/malformed-attrs.rs:98:1 + --> $DIR/malformed-attrs.rs:105:1 | LL | #[proc_macro = 18] | ^^^^^^^^^^^^^^^^^^ error: the `#[proc_macro_attribute]` attribute is only usable with crates of the `proc-macro` crate type - --> $DIR/malformed-attrs.rs:115:1 + --> $DIR/malformed-attrs.rs:122:1 | LL | #[proc_macro_attribute = 19] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: the `#[proc_macro_derive]` attribute is only usable with crates of the `proc-macro` crate type - --> $DIR/malformed-attrs.rs:122:1 + --> $DIR/malformed-attrs.rs:129:1 | LL | #[proc_macro_derive] | ^^^^^^^^^^^^^^^^^^^^ error[E0658]: allow_internal_unsafe side-steps the unsafe_code lint - --> $DIR/malformed-attrs.rs:214:1 + --> $DIR/malformed-attrs.rs:223:1 | LL | #[allow_internal_unsafe = 1] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -209,7 +208,7 @@ = note: `#[deny(ill_formed_attribute_input)]` (part of `#[deny(future_incompatible)]`) on by default error: valid forms for the attribute are `#[doc(hidden)]`, `#[doc(inline)]`, and `#[doc = "string"]` - --> $DIR/malformed-attrs.rs:76:1 + --> $DIR/malformed-attrs.rs:77:1 | LL | #[doc] | ^^^^^^ @@ -433,7 +432,7 @@ | ^^^^^^^^^^^^^ help: must be of the form: `#[crate_name = "name"]` error[E0539]: malformed `target_feature` attribute input - --> $DIR/malformed-attrs.rs:79:1 + --> $DIR/malformed-attrs.rs:80:1 | LL | #[target_feature] | ^^^^^^^^^^^^^^^^^ @@ -442,7 +441,7 @@ | help: must be of the form: `#[target_feature(enable = "feat1, feat2")]` error[E0565]: malformed `export_stable` attribute input - --> $DIR/malformed-attrs.rs:81:1 + --> $DIR/malformed-attrs.rs:82:1 | LL | #[export_stable = 1] | ^^^^^^^^^^^^^^^^---^ @@ -451,7 +450,7 @@ | help: must be of the form: `#[export_stable]` error[E0539]: malformed `link` attribute input - --> $DIR/malformed-attrs.rs:83:1 + --> $DIR/malformed-attrs.rs:84:1 | LL | #[link] | ^^^^^^^ expected this to be a list @@ -470,7 +469,7 @@ = and 1 other candidate error[E0539]: malformed `link_name` attribute input - --> $DIR/malformed-attrs.rs:85:1 + --> $DIR/malformed-attrs.rs:88:1 | LL | #[link_name] | ^^^^^^^^^^^^ help: must be of the form: `#[link_name = "name"]` @@ -478,7 +477,7 @@ = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link_name-attribute> error[E0539]: malformed `link_section` attribute input - --> $DIR/malformed-attrs.rs:87:1 + --> $DIR/malformed-attrs.rs:92:1 | LL | #[link_section] | ^^^^^^^^^^^^^^^ help: must be of the form: `#[link_section = "name"]` @@ -486,7 +485,7 @@ = note: for more information, visit <https://doc.rust-lang.org/reference/abi.html#the-link_section-attribute> error[E0539]: malformed `coverage` attribute input - --> $DIR/malformed-attrs.rs:89:1 + --> $DIR/malformed-attrs.rs:94:1 | LL | #[coverage] | ^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument @@ -499,7 +498,7 @@ | ++++ error[E0539]: malformed `sanitize` attribute input - --> $DIR/malformed-attrs.rs:91:1 + --> $DIR/malformed-attrs.rs:96:1 | LL | #[sanitize] | ^^^^^^^^^^^ expected this to be a list @@ -517,7 +516,7 @@ = and 5 other candidates error[E0565]: malformed `no_implicit_prelude` attribute input - --> $DIR/malformed-attrs.rs:96:1 + --> $DIR/malformed-attrs.rs:101:1 | LL | #[no_implicit_prelude = 23] | ^^^^^^^^^^^^^^^^^^^^^^----^ @@ -526,7 +525,7 @@ | help: must be of the form: `#[no_implicit_prelude]` error[E0565]: malformed `proc_macro` attribute input - --> $DIR/malformed-attrs.rs:98:1 + --> $DIR/malformed-attrs.rs:105:1 | LL | #[proc_macro = 18] | ^^^^^^^^^^^^^----^ @@ -535,7 +534,7 @@ | help: must be of the form: `#[proc_macro]` error[E0565]: malformed `coroutine` attribute input - --> $DIR/malformed-attrs.rs:110:5 + --> $DIR/malformed-attrs.rs:117:5 | LL | #[coroutine = 63] || {} | ^^^^^^^^^^^^----^ @@ -544,7 +543,7 @@ | help: must be of the form: `#[coroutine]` error[E0565]: malformed `proc_macro_attribute` attribute input - --> $DIR/malformed-attrs.rs:115:1 + --> $DIR/malformed-attrs.rs:122:1 | LL | #[proc_macro_attribute = 19] | ^^^^^^^^^^^^^^^^^^^^^^^----^ @@ -553,7 +552,7 @@ | help: must be of the form: `#[proc_macro_attribute]` error[E0539]: malformed `must_use` attribute input - --> $DIR/malformed-attrs.rs:118:1 + --> $DIR/malformed-attrs.rs:125:1 | LL | #[must_use = 1] | ^^^^^^^^^^^^^-^ @@ -571,7 +570,7 @@ | error[E0539]: malformed `proc_macro_derive` attribute input - --> $DIR/malformed-attrs.rs:122:1 + --> $DIR/malformed-attrs.rs:129:1 | LL | #[proc_macro_derive] | ^^^^^^^^^^^^^^^^^^^^ expected this to be a list @@ -585,7 +584,7 @@ | ++++++++++++++++++++++++++++++++++++++++++ error[E0539]: malformed `rustc_layout_scalar_valid_range_start` attribute input - --> $DIR/malformed-attrs.rs:127:1 + --> $DIR/malformed-attrs.rs:134:1 | LL | #[rustc_layout_scalar_valid_range_start] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -594,7 +593,7 @@ | help: must be of the form: `#[rustc_layout_scalar_valid_range_start(start)]` error[E0539]: malformed `rustc_layout_scalar_valid_range_end` attribute input - --> $DIR/malformed-attrs.rs:129:1 + --> $DIR/malformed-attrs.rs:136:1 | LL | #[rustc_layout_scalar_valid_range_end] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -603,7 +602,7 @@ | help: must be of the form: `#[rustc_layout_scalar_valid_range_end(end)]` error[E0565]: malformed `marker` attribute input - --> $DIR/malformed-attrs.rs:154:1 + --> $DIR/malformed-attrs.rs:161:1 | LL | #[marker = 3] | ^^^^^^^^^---^ @@ -612,7 +611,7 @@ | help: must be of the form: `#[marker]` error[E0565]: malformed `fundamental` attribute input - --> $DIR/malformed-attrs.rs:156:1 + --> $DIR/malformed-attrs.rs:163:1 | LL | #[fundamental()] | ^^^^^^^^^^^^^--^ @@ -621,7 +620,7 @@ | help: must be of the form: `#[fundamental]` error[E0565]: malformed `ffi_pure` attribute input - --> $DIR/malformed-attrs.rs:164:5 + --> $DIR/malformed-attrs.rs:171:5 | LL | #[unsafe(ffi_pure = 1)] | ^^^^^^^^^^^^^^^^^^---^^ @@ -630,7 +629,7 @@ | help: must be of the form: `#[ffi_pure]` error[E0539]: malformed `link_ordinal` attribute input - --> $DIR/malformed-attrs.rs:166:5 + --> $DIR/malformed-attrs.rs:173:5 | LL | #[link_ordinal] | ^^^^^^^^^^^^^^^ @@ -641,7 +640,7 @@ = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link_ordinal-attribute> error[E0565]: malformed `ffi_const` attribute input - --> $DIR/malformed-attrs.rs:170:5 + --> $DIR/malformed-attrs.rs:177:5 | LL | #[unsafe(ffi_const = 1)] | ^^^^^^^^^^^^^^^^^^^---^^ @@ -650,7 +649,7 @@ | help: must be of the form: `#[ffi_const]` error[E0539]: malformed `linkage` attribute input - --> $DIR/malformed-attrs.rs:172:5 + --> $DIR/malformed-attrs.rs:179:5 | LL | #[linkage] | ^^^^^^^^^^ expected this to be of the form `linkage = "..."` @@ -668,7 +667,7 @@ = and 5 other candidates error[E0539]: malformed `debugger_visualizer` attribute input - --> $DIR/malformed-attrs.rs:187:1 + --> $DIR/malformed-attrs.rs:194:1 | LL | #[debugger_visualizer] | ^^^^^^^^^^^^^^^^^^^^^^ @@ -679,7 +678,7 @@ = note: for more information, visit <https://doc.rust-lang.org/reference/attributes/debugger.html#the-debugger_visualizer-attribute> error[E0565]: malformed `automatically_derived` attribute input - --> $DIR/malformed-attrs.rs:189:1 + --> $DIR/malformed-attrs.rs:196:1 | LL | #[automatically_derived = 18] | ^^^^^^^^^^^^^^^^^^^^^^^^----^ @@ -688,7 +687,7 @@ | help: must be of the form: `#[automatically_derived]` error[E0565]: malformed `non_exhaustive` attribute input - --> $DIR/malformed-attrs.rs:195:1 + --> $DIR/malformed-attrs.rs:204:1 | LL | #[non_exhaustive = 1] | ^^^^^^^^^^^^^^^^^---^ @@ -697,19 +696,19 @@ | help: must be of the form: `#[non_exhaustive]` error: valid forms for the attribute are `#[macro_use(name1, name2, ...)]` and `#[macro_use]` - --> $DIR/malformed-attrs.rs:207:1 + --> $DIR/malformed-attrs.rs:216:1 | LL | #[macro_use = 1] | ^^^^^^^^^^^^^^^^ error: valid forms for the attribute are `#![macro_export(local_inner_macros)]` and `#![macro_export]` - --> $DIR/malformed-attrs.rs:212:1 + --> $DIR/malformed-attrs.rs:221:1 | LL | #[macro_export = 18] | ^^^^^^^^^^^^^^^^^^^^ error[E0565]: malformed `allow_internal_unsafe` attribute input - --> $DIR/malformed-attrs.rs:214:1 + --> $DIR/malformed-attrs.rs:223:1 | LL | #[allow_internal_unsafe = 1] | ^^^^^^^^^^^^^^^^^^^^^^^^---^ @@ -718,7 +717,7 @@ | help: must be of the form: `#[allow_internal_unsafe]` error[E0565]: malformed `type_const` attribute input - --> $DIR/malformed-attrs.rs:142:5 + --> $DIR/malformed-attrs.rs:149:5 | LL | #[type_const = 1] | ^^^^^^^^^^^^^---^ @@ -738,6 +737,21 @@ LL | | } | |_- not a `const fn` +warning: attribute should be applied to an `extern` block with non-Rust ABI + --> $DIR/malformed-attrs.rs:84:1 + | +LL | #[link] + | ^^^^^^^ +... +LL | / fn test() { +LL | | #[coroutine = 63] || {} +... | +LL | | } + | |_- not an `extern` block + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: requested on the command line with `-W unused-attributes` + error: `#[repr(align(...))]` is not supported on functions --> $DIR/malformed-attrs.rs:47:1 | @@ -751,7 +765,7 @@ | ^^^^^^^ warning: `#[diagnostic::do_not_recommend]` does not expect any arguments - --> $DIR/malformed-attrs.rs:148:1 + --> $DIR/malformed-attrs.rs:155:1 | LL | #[diagnostic::do_not_recommend()] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -759,7 +773,7 @@ = note: `#[warn(malformed_diagnostic_attributes)]` (part of `#[warn(unknown_or_malformed_diagnostic_attributes)]`) on by default warning: missing options for `on_unimplemented` attribute - --> $DIR/malformed-attrs.rs:137:1 + --> $DIR/malformed-attrs.rs:144:1 | LL | #[diagnostic::on_unimplemented] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -767,7 +781,7 @@ = help: at least one of the `message`, `note` and `label` options are expected warning: malformed `on_unimplemented` attribute - --> $DIR/malformed-attrs.rs:139:1 + --> $DIR/malformed-attrs.rs:146:1 | LL | #[diagnostic::on_unimplemented = 1] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid option found here @@ -783,8 +797,32 @@ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571> +warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![crate_name]` + --> $DIR/malformed-attrs.rs:74:1 + | +LL | #[crate_name] + | ^^^^^^^^^^^^^ + | +note: This attribute does not have an `!`, which means it is applied to this function + --> $DIR/malformed-attrs.rs:116:1 + | +LL | / fn test() { +LL | | #[coroutine = 63] || {} +... | +LL | | } + | |_^ + +warning: `#[link_name]` attribute cannot be used on functions + --> $DIR/malformed-attrs.rs:88:1 + | +LL | #[link_name] + | ^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[link_name]` can be applied to foreign functions and foreign statics + error: valid forms for the attribute are `#[ignore = "reason"]` and `#[ignore]` - --> $DIR/malformed-attrs.rs:93:1 + --> $DIR/malformed-attrs.rs:98:1 | LL | #[ignore()] | ^^^^^^^^^^^ @@ -792,8 +830,26 @@ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571> +warning: `#[no_implicit_prelude]` attribute cannot be used on functions + --> $DIR/malformed-attrs.rs:101:1 + | +LL | #[no_implicit_prelude = 23] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[no_implicit_prelude]` can be applied to crates and modules + +warning: `#[automatically_derived]` attribute cannot be used on modules + --> $DIR/malformed-attrs.rs:196:1 + | +LL | #[automatically_derived = 18] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[automatically_derived]` can only be applied to trait impl blocks + error: valid forms for the attribute are `#[ignore = "reason"]` and `#[ignore]` - --> $DIR/malformed-attrs.rs:221:1 + --> $DIR/malformed-attrs.rs:230:1 | LL | #[ignore = 1] | ^^^^^^^^^^^^^ @@ -802,7 +858,7 @@ = note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571> error[E0308]: mismatched types - --> $DIR/malformed-attrs.rs:110:23 + --> $DIR/malformed-attrs.rs:117:23 | LL | fn test() { | - help: a return type might be missing here: `-> _` @@ -810,9 +866,9 @@ | ^^^^^ expected `()`, found coroutine | = note: expected unit type `()` - found coroutine `{coroutine@$DIR/malformed-attrs.rs:110:23: 110:25}` + found coroutine `{coroutine@$DIR/malformed-attrs.rs:117:23: 117:25}` -error: aborting due to 76 previous errors; 3 warnings emitted +error: aborting due to 76 previous errors; 8 warnings emitted Some errors have detailed explanations: E0308, E0463, E0539, E0565, E0658, E0805. For more information about an error, try `rustc --explain E0308`. @@ -830,7 +886,7 @@ Future breakage diagnostic: error: valid forms for the attribute are `#[doc(hidden)]`, `#[doc(inline)]`, and `#[doc = "string"]` - --> $DIR/malformed-attrs.rs:76:1 + --> $DIR/malformed-attrs.rs:77:1 | LL | #[doc] | ^^^^^^ @@ -853,7 +909,7 @@ Future breakage diagnostic: error: valid forms for the attribute are `#[ignore = "reason"]` and `#[ignore]` - --> $DIR/malformed-attrs.rs:93:1 + --> $DIR/malformed-attrs.rs:98:1 | LL | #[ignore()] | ^^^^^^^^^^^ @@ -864,7 +920,7 @@ Future breakage diagnostic: error: valid forms for the attribute are `#[ignore = "reason"]` and `#[ignore]` - --> $DIR/malformed-attrs.rs:221:1 + --> $DIR/malformed-attrs.rs:230:1 | LL | #[ignore = 1] | ^^^^^^^^^^^^^
diff --git a/tests/ui/attributes/malformed-no-std.rs b/tests/ui/attributes/malformed-no-std.rs index 528ecb5..2e618a1 100644 --- a/tests/ui/attributes/malformed-no-std.rs +++ b/tests/ui/attributes/malformed-no-std.rs
@@ -4,14 +4,18 @@ //~^ ERROR malformed `no_std` attribute input #![no_std("bar")] //~^ ERROR malformed `no_std` attribute input +//~| WARN unused attribute #![no_std(foo = "bar")] //~^ ERROR malformed `no_std` attribute input +//~| WARN unused attribute #![no_core = "foo"] //~^ ERROR malformed `no_core` attribute input #![no_core("bar")] //~^ ERROR malformed `no_core` attribute input +//~| WARN unused attribute #![no_core(foo = "bar")] //~^ ERROR malformed `no_core` attribute input +//~| WARN unused attribute #[deny(unused_attributes)] #[no_std]
diff --git a/tests/ui/attributes/malformed-no-std.stderr b/tests/ui/attributes/malformed-no-std.stderr index 322d5f0..89d7ee4 100644 --- a/tests/ui/attributes/malformed-no-std.stderr +++ b/tests/ui/attributes/malformed-no-std.stderr
@@ -17,7 +17,7 @@ | help: must be of the form: `#![no_std]` error[E0565]: malformed `no_std` attribute input - --> $DIR/malformed-no-std.rs:7:1 + --> $DIR/malformed-no-std.rs:8:1 | LL | #![no_std(foo = "bar")] | ^^^^^^^^^-------------^ @@ -26,7 +26,7 @@ | help: must be of the form: `#![no_std]` error[E0565]: malformed `no_core` attribute input - --> $DIR/malformed-no-std.rs:9:1 + --> $DIR/malformed-no-std.rs:11:1 | LL | #![no_core = "foo"] | ^^^^^^^^^^^-------^ @@ -35,7 +35,7 @@ | help: must be of the form: `#![no_core]` error[E0565]: malformed `no_core` attribute input - --> $DIR/malformed-no-std.rs:11:1 + --> $DIR/malformed-no-std.rs:13:1 | LL | #![no_core("bar")] | ^^^^^^^^^^-------^ @@ -44,7 +44,7 @@ | help: must be of the form: `#![no_core]` error[E0565]: malformed `no_core` attribute input - --> $DIR/malformed-no-std.rs:13:1 + --> $DIR/malformed-no-std.rs:16:1 | LL | #![no_core(foo = "bar")] | ^^^^^^^^^^-------------^ @@ -53,34 +53,83 @@ | help: must be of the form: `#![no_core]` error: crate-level attribute should be an inner attribute: add an exclamation mark: `#![no_std]` - --> $DIR/malformed-no-std.rs:17:1 + --> $DIR/malformed-no-std.rs:21:1 | LL | #[no_std] | ^^^^^^^^^ | note: This attribute does not have an `!`, which means it is applied to this extern crate - --> $DIR/malformed-no-std.rs:22:1 + --> $DIR/malformed-no-std.rs:26:1 | LL | extern crate core; | ^^^^^^^^^^^^^^^^^^ note: the lint level is defined here - --> $DIR/malformed-no-std.rs:16:8 + --> $DIR/malformed-no-std.rs:20:8 | LL | #[deny(unused_attributes)] | ^^^^^^^^^^^^^^^^^ error: crate-level attribute should be an inner attribute: add an exclamation mark: `#![no_core]` - --> $DIR/malformed-no-std.rs:19:1 + --> $DIR/malformed-no-std.rs:23:1 | LL | #[no_core] | ^^^^^^^^^^ | note: This attribute does not have an `!`, which means it is applied to this extern crate - --> $DIR/malformed-no-std.rs:22:1 + --> $DIR/malformed-no-std.rs:26:1 | LL | extern crate core; | ^^^^^^^^^^^^^^^^^^ -error: aborting due to 8 previous errors +warning: unused attribute + --> $DIR/malformed-no-std.rs:5:1 + | +LL | #![no_std("bar")] + | ^^^^^^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/malformed-no-std.rs:3:1 + | +LL | #![no_std = "foo"] + | ^^^^^^^^^^^^^^^^^^ + = note: requested on the command line with `-W unused-attributes` + +warning: unused attribute + --> $DIR/malformed-no-std.rs:8:1 + | +LL | #![no_std(foo = "bar")] + | ^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/malformed-no-std.rs:5:1 + | +LL | #![no_std("bar")] + | ^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/malformed-no-std.rs:13:1 + | +LL | #![no_core("bar")] + | ^^^^^^^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/malformed-no-std.rs:11:1 + | +LL | #![no_core = "foo"] + | ^^^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/malformed-no-std.rs:16:1 + | +LL | #![no_core(foo = "bar")] + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/malformed-no-std.rs:13:1 + | +LL | #![no_core("bar")] + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to 8 previous errors; 4 warnings emitted For more information about this error, try `rustc --explain E0565`.
diff --git a/tests/ui/binding/invalid-assignment-in-while-loop-77218.fixed b/tests/ui/binding/invalid-assignment-in-while-77218.fixed similarity index 100% rename from tests/ui/binding/invalid-assignment-in-while-loop-77218.fixed rename to tests/ui/binding/invalid-assignment-in-while-77218.fixed
diff --git a/tests/ui/binding/invalid-assignment-in-while-loop-77218.rs b/tests/ui/binding/invalid-assignment-in-while-77218.rs similarity index 100% rename from tests/ui/binding/invalid-assignment-in-while-loop-77218.rs rename to tests/ui/binding/invalid-assignment-in-while-77218.rs
diff --git a/tests/ui/binding/invalid-assignment-in-while-loop-77218.stderr b/tests/ui/binding/invalid-assignment-in-while-77218.stderr similarity index 88% rename from tests/ui/binding/invalid-assignment-in-while-loop-77218.stderr rename to tests/ui/binding/invalid-assignment-in-while-77218.stderr index e6baf34..0545a01 100644 --- a/tests/ui/binding/invalid-assignment-in-while-loop-77218.stderr +++ b/tests/ui/binding/invalid-assignment-in-while-77218.stderr
@@ -1,5 +1,5 @@ error[E0070]: invalid left-hand side of assignment - --> $DIR/invalid-assignment-in-while-loop-77218.rs:5:19 + --> $DIR/invalid-assignment-in-while-77218.rs:5:19 | LL | while Some(0) = value.get(0) {} | - ^
diff --git a/tests/ui/issues/issue-70724-add_type_neq_err_label-unwrap.rs b/tests/ui/binop/binary-operation-error-on-function-70724.rs similarity index 77% rename from tests/ui/issues/issue-70724-add_type_neq_err_label-unwrap.rs rename to tests/ui/binop/binary-operation-error-on-function-70724.rs index c268315..0bbf137 100644 --- a/tests/ui/issues/issue-70724-add_type_neq_err_label-unwrap.rs +++ b/tests/ui/binop/binary-operation-error-on-function-70724.rs
@@ -1,3 +1,4 @@ +// https://github.com/rust-lang/rust/issues/70724 fn a() -> i32 { 3 }
diff --git a/tests/ui/issues/issue-70724-add_type_neq_err_label-unwrap.stderr b/tests/ui/binop/binary-operation-error-on-function-70724.stderr similarity index 86% rename from tests/ui/issues/issue-70724-add_type_neq_err_label-unwrap.stderr rename to tests/ui/binop/binary-operation-error-on-function-70724.stderr index 736002c..11b0e4b 100644 --- a/tests/ui/issues/issue-70724-add_type_neq_err_label-unwrap.stderr +++ b/tests/ui/binop/binary-operation-error-on-function-70724.stderr
@@ -1,5 +1,5 @@ error[E0369]: binary operation `==` cannot be applied to type `fn() -> i32 {a}` - --> $DIR/issue-70724-add_type_neq_err_label-unwrap.rs:6:5 + --> $DIR/binary-operation-error-on-function-70724.rs:7:5 | LL | assert_eq!(a, 0); | ^^^^^^^^^^^^^^^^ @@ -10,7 +10,7 @@ = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0308]: mismatched types - --> $DIR/issue-70724-add_type_neq_err_label-unwrap.rs:6:5 + --> $DIR/binary-operation-error-on-function-70724.rs:7:5 | LL | assert_eq!(a, 0); | ^^^^^^^^^^^^^^^^ expected fn item, found integer @@ -20,7 +20,7 @@ = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: `fn() -> i32 {a}` doesn't implement `Debug` - --> $DIR/issue-70724-add_type_neq_err_label-unwrap.rs:6:5 + --> $DIR/binary-operation-error-on-function-70724.rs:7:5 | LL | fn a() -> i32 { | - consider calling this function
diff --git a/tests/ui/borrowck/incorrect-use-after-storage-end-78192.rs b/tests/ui/borrowck/pointer-reassignment-after-deref-78192.rs similarity index 100% rename from tests/ui/borrowck/incorrect-use-after-storage-end-78192.rs rename to tests/ui/borrowck/pointer-reassignment-after-deref-78192.rs
diff --git a/tests/ui/cfg/cfg-path-error.rs b/tests/ui/cfg/cfg-path-error.rs index 9db1f19..f22e6be 100644 --- a/tests/ui/cfg/cfg-path-error.rs +++ b/tests/ui/cfg/cfg-path-error.rs
@@ -3,19 +3,27 @@ #![allow(unexpected_cfgs)] // invalid cfgs #[cfg(any(foo, foo::bar))] -//~^ERROR `cfg` predicate key must be an identifier +//~^ ERROR malformed `cfg` attribute input +//~| NOTE expected a valid identifier here +//~| NOTE for more information, visit fn foo1() {} #[cfg(any(foo::bar, foo))] -//~^ERROR `cfg` predicate key must be an identifier +//~^ ERROR malformed `cfg` attribute input +//~| NOTE expected a valid identifier here +//~| NOTE for more information, visit fn foo2() {} #[cfg(all(foo, foo::bar))] -//~^ERROR `cfg` predicate key must be an identifier +//~^ ERROR malformed `cfg` attribute input +//~| NOTE expected a valid identifier here +//~| NOTE for more information, visit fn foo3() {} #[cfg(all(foo::bar, foo))] -//~^ERROR `cfg` predicate key must be an identifier +//~^ ERROR malformed `cfg` attribute input +//~| NOTE expected a valid identifier here +//~| NOTE for more information, visit fn foo4() {} fn main() {}
diff --git a/tests/ui/cfg/cfg-path-error.stderr b/tests/ui/cfg/cfg-path-error.stderr index 4f68fa3..bb9b703 100644 --- a/tests/ui/cfg/cfg-path-error.stderr +++ b/tests/ui/cfg/cfg-path-error.stderr
@@ -1,26 +1,47 @@ -error: `cfg` predicate key must be an identifier - --> $DIR/cfg-path-error.rs:5:16 +error[E0539]: malformed `cfg` attribute input + --> $DIR/cfg-path-error.rs:5:1 | LL | #[cfg(any(foo, foo::bar))] - | ^^^^^^^^ + | ^^^^^^^^^^^^^^^--------^^^ + | | | + | | expected a valid identifier here + | help: must be of the form: `#[cfg(predicate)]` + | + = note: for more information, visit <https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg-attribute> -error: `cfg` predicate key must be an identifier - --> $DIR/cfg-path-error.rs:9:11 +error[E0539]: malformed `cfg` attribute input + --> $DIR/cfg-path-error.rs:11:1 | LL | #[cfg(any(foo::bar, foo))] - | ^^^^^^^^ + | ^^^^^^^^^^--------^^^^^^^^ + | | | + | | expected a valid identifier here + | help: must be of the form: `#[cfg(predicate)]` + | + = note: for more information, visit <https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg-attribute> -error: `cfg` predicate key must be an identifier - --> $DIR/cfg-path-error.rs:13:16 +error[E0539]: malformed `cfg` attribute input + --> $DIR/cfg-path-error.rs:17:1 | LL | #[cfg(all(foo, foo::bar))] - | ^^^^^^^^ + | ^^^^^^^^^^^^^^^--------^^^ + | | | + | | expected a valid identifier here + | help: must be of the form: `#[cfg(predicate)]` + | + = note: for more information, visit <https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg-attribute> -error: `cfg` predicate key must be an identifier - --> $DIR/cfg-path-error.rs:17:11 +error[E0539]: malformed `cfg` attribute input + --> $DIR/cfg-path-error.rs:23:1 | LL | #[cfg(all(foo::bar, foo))] - | ^^^^^^^^ + | ^^^^^^^^^^--------^^^^^^^^ + | | | + | | expected a valid identifier here + | help: must be of the form: `#[cfg(predicate)]` + | + = note: for more information, visit <https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg-attribute> error: aborting due to 4 previous errors +For more information about this error, try `rustc --explain E0539`.
diff --git a/tests/ui/cfg/cfg-target-compact-errors.rs b/tests/ui/cfg/cfg-target-compact-errors.rs index cfb19c5..1ce6833 100644 --- a/tests/ui/cfg/cfg-target-compact-errors.rs +++ b/tests/ui/cfg/cfg-target-compact-errors.rs
@@ -19,7 +19,7 @@ fn three() {} fn four() {} #[cfg(target(clippy::os = "linux"))] -//~^ ERROR `cfg` predicate key must be an identifier +//~^ ERROR malformed `cfg` attribute input fn five() {} fn main() {}
diff --git a/tests/ui/cfg/cfg-target-compact-errors.stderr b/tests/ui/cfg/cfg-target-compact-errors.stderr index cf61f94..3ca1b73 100644 --- a/tests/ui/cfg/cfg-target-compact-errors.stderr +++ b/tests/ui/cfg/cfg-target-compact-errors.stderr
@@ -42,11 +42,16 @@ | = note: for more information, visit <https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg-attribute> -error: `cfg` predicate key must be an identifier - --> $DIR/cfg-target-compact-errors.rs:21:14 +error[E0539]: malformed `cfg` attribute input + --> $DIR/cfg-target-compact-errors.rs:21:1 | LL | #[cfg(target(clippy::os = "linux"))] - | ^^^^^^^^^^ + | ^^^^^^^^^^^^^----------^^^^^^^^^^^^^ + | | | + | | expected a valid identifier here + | help: must be of the form: `#[cfg(predicate)]` + | + = note: for more information, visit <https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg-attribute> error: aborting due to 5 previous errors
diff --git a/tests/ui/issues/issue-72002.rs b/tests/ui/coercion/index-coercion-over-indexmut-72002.rs similarity index 90% rename from tests/ui/issues/issue-72002.rs rename to tests/ui/coercion/index-coercion-over-indexmut-72002.rs index ce34630..826cc99 100644 --- a/tests/ui/issues/issue-72002.rs +++ b/tests/ui/coercion/index-coercion-over-indexmut-72002.rs
@@ -1,3 +1,4 @@ +// https://github.com/rust-lang/rust/issues/72002 //@ check-pass struct Indexable;
diff --git a/tests/ui/conditional-compilation/cfg-attr-parse.rs b/tests/ui/conditional-compilation/cfg-attr-parse.rs index 8ca31c1..b8aaad2 100644 --- a/tests/ui/conditional-compilation/cfg-attr-parse.rs +++ b/tests/ui/conditional-compilation/cfg-attr-parse.rs
@@ -9,7 +9,8 @@ struct A0C0; // Zero attributes, one trailing comma -#[cfg_attr(all(),)] // Ok +#[cfg_attr(all(),)] +//~^ WARN `#[cfg_attr]` does not expand to any attributes struct A0C1; // Zero attributes, two trailing commas
diff --git a/tests/ui/conditional-compilation/cfg-attr-parse.stderr b/tests/ui/conditional-compilation/cfg-attr-parse.stderr index 76f199c..4d4769b 100644 --- a/tests/ui/conditional-compilation/cfg-attr-parse.stderr +++ b/tests/ui/conditional-compilation/cfg-attr-parse.stderr
@@ -1,53 +1,60 @@ -error: malformed `cfg_attr` attribute input +error[E0539]: malformed `cfg_attr` attribute input --> $DIR/cfg-attr-parse.rs:4:1 | LL | #[cfg_attr()] - | ^^^^^^^^^^^^^ + | ^^^^^^^^^^--^ + | | | + | | expected at least 1 argument here + | help: must be of the form: `#[cfg_attr(predicate, attr1, attr2, ...)]` | = note: for more information, visit <https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg_attr-attribute> -help: missing condition and attribute - | -LL | #[cfg_attr(condition, attribute, other_attribute, ...)] - | ++++++++++++++++++++++++++++++++++++++++++ error: expected `,`, found end of `cfg_attr` input --> $DIR/cfg-attr-parse.rs:8:17 | LL | #[cfg_attr(all())] - | ^ expected `,` + | ----------------^- + | | | + | | expected `,` + | help: must be of the form: `#[cfg_attr(predicate, attr1, attr2, ...)]` | - = help: the valid syntax is `#[cfg_attr(condition, attribute, other_attribute, ...)]` = note: for more information, visit <https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg_attr-attribute> error: expected identifier, found `,` - --> $DIR/cfg-attr-parse.rs:16:18 + --> $DIR/cfg-attr-parse.rs:17:18 | LL | #[cfg_attr(all(),,)] - | ^ expected identifier + | -----------------^-- + | | | + | | expected identifier + | help: must be of the form: `#[cfg_attr(predicate, attr1, attr2, ...)]` | - = help: the valid syntax is `#[cfg_attr(condition, attribute, other_attribute, ...)]` = note: for more information, visit <https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg_attr-attribute> error: expected identifier, found `,` - --> $DIR/cfg-attr-parse.rs:28:28 + --> $DIR/cfg-attr-parse.rs:29:28 | LL | #[cfg_attr(all(), must_use,,)] - | ^ expected identifier + | ---------------------------^-- + | | | + | | expected identifier + | help: must be of the form: `#[cfg_attr(predicate, attr1, attr2, ...)]` | - = help: the valid syntax is `#[cfg_attr(condition, attribute, other_attribute, ...)]` = note: for more information, visit <https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg_attr-attribute> error: expected identifier, found `,` - --> $DIR/cfg-attr-parse.rs:40:40 + --> $DIR/cfg-attr-parse.rs:41:40 | LL | #[cfg_attr(all(), must_use, deprecated,,)] - | ^ expected identifier + | ---------------------------------------^-- + | | | + | | expected identifier + | help: must be of the form: `#[cfg_attr(predicate, attr1, attr2, ...)]` | - = help: the valid syntax is `#[cfg_attr(condition, attribute, other_attribute, ...)]` = note: for more information, visit <https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg_attr-attribute> error: wrong `cfg_attr` delimiters - --> $DIR/cfg-attr-parse.rs:44:11 + --> $DIR/cfg-attr-parse.rs:45:11 | LL | #[cfg_attr[all(),,]] | ^^^^^^^^^ @@ -59,16 +66,18 @@ | error: expected identifier, found `,` - --> $DIR/cfg-attr-parse.rs:44:18 + --> $DIR/cfg-attr-parse.rs:45:18 | LL | #[cfg_attr[all(),,]] - | ^ expected identifier + | -----------------^-- + | | | + | | expected identifier + | help: must be of the form: `#[cfg_attr(predicate, attr1, attr2, ...)]` | - = help: the valid syntax is `#[cfg_attr(condition, attribute, other_attribute, ...)]` = note: for more information, visit <https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg_attr-attribute> error: wrong `cfg_attr` delimiters - --> $DIR/cfg-attr-parse.rs:50:11 + --> $DIR/cfg-attr-parse.rs:51:11 | LL | #[cfg_attr{all(),,}] | ^^^^^^^^^ @@ -80,13 +89,24 @@ | error: expected identifier, found `,` - --> $DIR/cfg-attr-parse.rs:50:18 + --> $DIR/cfg-attr-parse.rs:51:18 | LL | #[cfg_attr{all(),,}] - | ^ expected identifier + | -----------------^-- + | | | + | | expected identifier + | help: must be of the form: `#[cfg_attr(predicate, attr1, attr2, ...)]` | - = help: the valid syntax is `#[cfg_attr(condition, attribute, other_attribute, ...)]` = note: for more information, visit <https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg_attr-attribute> -error: aborting due to 9 previous errors +warning: `#[cfg_attr]` does not expand to any attributes + --> $DIR/cfg-attr-parse.rs:12:1 + | +LL | #[cfg_attr(all(),)] + | ^^^^^^^^^^^^^^^^^^^ + | + = note: requested on the command line with `-W unused-attributes` +error: aborting due to 9 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0539`.
diff --git a/tests/ui/conditional-compilation/cfg-attr-syntax-validation.rs b/tests/ui/conditional-compilation/cfg-attr-syntax-validation.rs index 2c84a96..7d4fd20 100644 --- a/tests/ui/conditional-compilation/cfg-attr-syntax-validation.rs +++ b/tests/ui/conditional-compilation/cfg-attr-syntax-validation.rs
@@ -22,10 +22,16 @@ //~| NOTE for more information, visit struct S4; -#[cfg("str")] //~ ERROR `cfg` predicate key must be an identifier +#[cfg("str")] +//~^ ERROR malformed `cfg` attribute input +//~| NOTE expected a valid identifier here +//~| NOTE for more information, visit struct S5; -#[cfg(a::b)] //~ ERROR `cfg` predicate key must be an identifier +#[cfg(a::b)] +//~^ ERROR malformed `cfg` attribute input +//~| NOTE expected a valid identifier here +//~| NOTE for more information, visit struct S6; #[cfg(a())] //~ ERROR invalid predicate `a`
diff --git a/tests/ui/conditional-compilation/cfg-attr-syntax-validation.stderr b/tests/ui/conditional-compilation/cfg-attr-syntax-validation.stderr index 59ff611..e73b20f 100644 --- a/tests/ui/conditional-compilation/cfg-attr-syntax-validation.stderr +++ b/tests/ui/conditional-compilation/cfg-attr-syntax-validation.stderr
@@ -42,26 +42,36 @@ | = note: for more information, visit <https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg-attribute> -error: `cfg` predicate key must be an identifier - --> $DIR/cfg-attr-syntax-validation.rs:25:7 +error[E0539]: malformed `cfg` attribute input + --> $DIR/cfg-attr-syntax-validation.rs:25:1 | LL | #[cfg("str")] - | ^^^^^ + | ^^^^^^-----^^ + | | | + | | expected a valid identifier here + | help: must be of the form: `#[cfg(predicate)]` + | + = note: for more information, visit <https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg-attribute> -error: `cfg` predicate key must be an identifier - --> $DIR/cfg-attr-syntax-validation.rs:28:7 +error[E0539]: malformed `cfg` attribute input + --> $DIR/cfg-attr-syntax-validation.rs:31:1 | LL | #[cfg(a::b)] - | ^^^^ + | ^^^^^^----^^ + | | | + | | expected a valid identifier here + | help: must be of the form: `#[cfg(predicate)]` + | + = note: for more information, visit <https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg-attribute> error[E0537]: invalid predicate `a` - --> $DIR/cfg-attr-syntax-validation.rs:31:7 + --> $DIR/cfg-attr-syntax-validation.rs:37:7 | LL | #[cfg(a())] | ^^^ error[E0539]: malformed `cfg` attribute input - --> $DIR/cfg-attr-syntax-validation.rs:34:1 + --> $DIR/cfg-attr-syntax-validation.rs:40:1 | LL | #[cfg(a = 10)] | ^^^^^^^^^^--^^ @@ -72,7 +82,7 @@ = note: for more information, visit <https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg-attribute> error[E0539]: malformed `cfg` attribute input - --> $DIR/cfg-attr-syntax-validation.rs:39:1 + --> $DIR/cfg-attr-syntax-validation.rs:45:1 | LL | #[cfg(a = b"hi")] | ^^^^^^^^^^-^^^^^^ @@ -82,7 +92,7 @@ = note: expected a normal string literal, not a byte string literal error: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found `expr` metavariable - --> $DIR/cfg-attr-syntax-validation.rs:45:25 + --> $DIR/cfg-attr-syntax-validation.rs:51:25 | LL | #[cfg(feature = $expr)] | ^^^^^
diff --git a/tests/ui/conditional-compilation/cfg_attr-attr-syntax-validation.rs b/tests/ui/conditional-compilation/cfg_attr-attr-syntax-validation.rs new file mode 100644 index 0000000..a0f86e3 --- /dev/null +++ b/tests/ui/conditional-compilation/cfg_attr-attr-syntax-validation.rs
@@ -0,0 +1,52 @@ +#[cfg_attr] +//~^ ERROR malformed `cfg_attr` attribute +struct S1; + +#[cfg_attr = 10] +//~^ ERROR malformed `cfg_attr` attribute +struct S2; + +#[cfg_attr()] +//~^ ERROR malformed `cfg_attr` attribute +struct S3; + +#[cfg_attr("str")] //~ ERROR malformed `cfg_attr` attribute input +struct S5; + +#[cfg_attr(a::b)] //~ ERROR malformed `cfg_attr` attribute input +struct S6; + +#[cfg_attr(a())] //~ ERROR invalid predicate `a` +struct S7; + +#[cfg_attr(a = 10)] //~ ERROR malformed `cfg_attr` attribute input +struct S8; + +#[cfg_attr(a = b"hi")] //~ ERROR malformed `cfg_attr` attribute input +struct S9; + +macro_rules! generate_s10 { + ($expr: expr) => { + #[cfg_attr(feature = $expr)] + //~^ ERROR expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found `expr` metavariable + struct S10; + } +} + +generate_s10!(concat!("nonexistent")); + +#[cfg_attr(true)] //~ ERROR expected `,`, found end of `cfg_attr` input +struct S11; + +#[cfg_attr(true, unknown_attribute)] //~ ERROR cannot find attribute `unknown_attribute` in this scope +struct S12; + +#[cfg_attr(true, link_section)] //~ ERROR malformed `link_section` attribute input +//~^ WARN attribute cannot be used on +//~| WARN previously accepted +struct S13; + +#[cfg_attr(true, inline())] //~ ERROR malformed `inline` attribute input +fn f1() {} + +fn main() {}
diff --git a/tests/ui/conditional-compilation/cfg_attr-attr-syntax-validation.stderr b/tests/ui/conditional-compilation/cfg_attr-attr-syntax-validation.stderr new file mode 100644 index 0000000..2b7a7da --- /dev/null +++ b/tests/ui/conditional-compilation/cfg_attr-attr-syntax-validation.stderr
@@ -0,0 +1,154 @@ +error[E0539]: malformed `cfg_attr` attribute input + --> $DIR/cfg_attr-attr-syntax-validation.rs:1:1 + | +LL | #[cfg_attr] + | ^^^^^^^^^^^ + | | + | expected this to be a list + | help: must be of the form: `#[cfg_attr(predicate, attr1, attr2, ...)]` + | + = note: for more information, visit <https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg_attr-attribute> + +error[E0539]: malformed `cfg_attr` attribute input + --> $DIR/cfg_attr-attr-syntax-validation.rs:5:1 + | +LL | #[cfg_attr = 10] + | ^^^^^^^^^^^^^^^^ + | | + | expected this to be a list + | help: must be of the form: `#[cfg_attr(predicate, attr1, attr2, ...)]` + | + = note: for more information, visit <https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg_attr-attribute> + +error[E0539]: malformed `cfg_attr` attribute input + --> $DIR/cfg_attr-attr-syntax-validation.rs:9:1 + | +LL | #[cfg_attr()] + | ^^^^^^^^^^--^ + | | | + | | expected at least 1 argument here + | help: must be of the form: `#[cfg_attr(predicate, attr1, attr2, ...)]` + | + = note: for more information, visit <https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg_attr-attribute> + +error[E0539]: malformed `cfg_attr` attribute input + --> $DIR/cfg_attr-attr-syntax-validation.rs:13:1 + | +LL | #[cfg_attr("str")] + | ^^^^^^^^^^^-----^^ + | | | + | | expected a valid identifier here + | help: must be of the form: `#[cfg_attr(predicate, attr1, attr2, ...)]` + | + = note: for more information, visit <https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg_attr-attribute> + +error[E0539]: malformed `cfg_attr` attribute input + --> $DIR/cfg_attr-attr-syntax-validation.rs:16:1 + | +LL | #[cfg_attr(a::b)] + | ^^^^^^^^^^^----^^ + | | | + | | expected a valid identifier here + | help: must be of the form: `#[cfg_attr(predicate, attr1, attr2, ...)]` + | + = note: for more information, visit <https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg_attr-attribute> + +error[E0537]: invalid predicate `a` + --> $DIR/cfg_attr-attr-syntax-validation.rs:19:12 + | +LL | #[cfg_attr(a())] + | ^^^ + +error[E0539]: malformed `cfg_attr` attribute input + --> $DIR/cfg_attr-attr-syntax-validation.rs:22:1 + | +LL | #[cfg_attr(a = 10)] + | ^^^^^^^^^^^^^^^--^^ + | | | + | | expected a string literal here + | help: must be of the form: `#[cfg_attr(predicate, attr1, attr2, ...)]` + | + = note: for more information, visit <https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg_attr-attribute> + +error[E0539]: malformed `cfg_attr` attribute input + --> $DIR/cfg_attr-attr-syntax-validation.rs:25:1 + | +LL | #[cfg_attr(a = b"hi")] + | ^^^^^^^^^^^^^^^-^^^^^^ + | | + | help: consider removing the prefix + | + = note: expected a normal string literal, not a byte string literal + +error: expected `,`, found end of `cfg_attr` input + --> $DIR/cfg_attr-attr-syntax-validation.rs:38:16 + | +LL | #[cfg_attr(true)] + | ---------------^- + | | | + | | expected `,` + | help: must be of the form: `#[cfg_attr(predicate, attr1, attr2, ...)]` + | + = note: for more information, visit <https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg_attr-attribute> + +error: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found `expr` metavariable + --> $DIR/cfg_attr-attr-syntax-validation.rs:30:30 + | +LL | #[cfg_attr(feature = $expr)] + | ---------------------^^^^^-- help: must be of the form: `#[cfg_attr(predicate, attr1, attr2, ...)]` +... +LL | generate_s10!(concat!("nonexistent")); + | ------------------------------------- in this macro invocation + | + = note: for more information, visit <https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg_attr-attribute> + = note: this error originates in the macro `generate_s10` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: cannot find attribute `unknown_attribute` in this scope + --> $DIR/cfg_attr-attr-syntax-validation.rs:41:18 + | +LL | #[cfg_attr(true, unknown_attribute)] + | ^^^^^^^^^^^^^^^^^ + +error[E0539]: malformed `link_section` attribute input + --> $DIR/cfg_attr-attr-syntax-validation.rs:44:18 + | +LL | #[cfg_attr(true, link_section)] + | ^^^^^^^^^^^^ help: must be of the form: `#[link_section = "name"]` + | + = note: for more information, visit <https://doc.rust-lang.org/reference/abi.html#the-link_section-attribute> + +error[E0805]: malformed `inline` attribute input + --> $DIR/cfg_attr-attr-syntax-validation.rs:49:18 + | +LL | #[cfg_attr(true, inline())] + | ^^^^^^-- + | | + | expected a single argument here + | + = note: for more information, visit <https://doc.rust-lang.org/reference/attributes/codegen.html#the-inline-attribute> +help: try changing it to one of the following valid forms of the attribute + | +LL - #[cfg_attr(true, inline())] +LL + #[cfg_attr(true, #[inline(always)])] + | +LL - #[cfg_attr(true, inline())] +LL + #[cfg_attr(true, #[inline(never)])] + | +LL - #[cfg_attr(true, inline())] +LL + #[cfg_attr(true, #[inline])] + | + +warning: `#[link_section]` attribute cannot be used on structs + --> $DIR/cfg_attr-attr-syntax-validation.rs:44:18 + | +LL | #[cfg_attr(true, link_section)] + | ^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[link_section]` can be applied to functions and statics + = note: requested on the command line with `-W unused-attributes` + +error: aborting due to 13 previous errors; 1 warning emitted + +Some errors have detailed explanations: E0537, E0539, E0805. +For more information about an error, try `rustc --explain E0537`.
diff --git a/tests/crashes/139815.rs b/tests/ui/const-generics/generic-const-array-pattern-ice-139815.rs similarity index 60% rename from tests/crashes/139815.rs rename to tests/ui/const-generics/generic-const-array-pattern-ice-139815.rs index 9094acdc..52f4b24 100644 --- a/tests/crashes/139815.rs +++ b/tests/ui/const-generics/generic-const-array-pattern-ice-139815.rs
@@ -1,8 +1,10 @@ -//@ known-bug: #139815 - +//@ compile-flags: --crate-type=lib +#![allow(incomplete_features)] #![feature(generic_const_exprs)] + fn is_123<const N: usize>( x: [u32; { + //~^ ERROR overly complex generic constant N + 1; 5 }],
diff --git a/tests/ui/const-generics/generic-const-array-pattern-ice-139815.stderr b/tests/ui/const-generics/generic-const-array-pattern-ice-139815.stderr new file mode 100644 index 0000000..9da973e --- /dev/null +++ b/tests/ui/const-generics/generic-const-array-pattern-ice-139815.stderr
@@ -0,0 +1,16 @@ +error: overly complex generic constant + --> $DIR/generic-const-array-pattern-ice-139815.rs:6:14 + | +LL | x: [u32; { + | ______________^ +LL | | +LL | | N + 1; +LL | | 5 +LL | | }], + | |_____^ blocks are not supported in generic constants + | + = help: consider moving this anonymous constant into a `const` function + = note: this operation may be supported in the future + +error: aborting due to 1 previous error +
diff --git a/tests/ui/attributes/invalid-attributes-on-const-params-78957.rs b/tests/ui/const-generics/invalid-attributes-on-const-params-78957.rs similarity index 100% rename from tests/ui/attributes/invalid-attributes-on-const-params-78957.rs rename to tests/ui/const-generics/invalid-attributes-on-const-params-78957.rs
diff --git a/tests/ui/attributes/invalid-attributes-on-const-params-78957.stderr b/tests/ui/const-generics/invalid-attributes-on-const-params-78957.stderr similarity index 100% rename from tests/ui/attributes/invalid-attributes-on-const-params-78957.stderr rename to tests/ui/const-generics/invalid-attributes-on-const-params-78957.stderr
diff --git a/tests/ui/consts/do-not-ice-long-constant-evaluation-in-for-loop.rs b/tests/ui/consts/do-not-ice-long-constant-evaluation-in-for-loop.rs new file mode 100644 index 0000000..465b54e --- /dev/null +++ b/tests/ui/consts/do-not-ice-long-constant-evaluation-in-for-loop.rs
@@ -0,0 +1,14 @@ +// The test confirms ICE-125323 is fixed. +// +// This warning tests there is no warning about dead code +// when there is a constant evaluation error. +#![warn(unused)] +fn should_not_be_dead() {} + +fn main() { + for _ in 0..0 { + [(); loop {}]; //~ ERROR constant evaluation is taking a long time + } + + should_not_be_dead(); +}
diff --git a/tests/ui/consts/do-not-ice-long-constant-evaluation-in-for-loop.stderr b/tests/ui/consts/do-not-ice-long-constant-evaluation-in-for-loop.stderr new file mode 100644 index 0000000..32a1846 --- /dev/null +++ b/tests/ui/consts/do-not-ice-long-constant-evaluation-in-for-loop.stderr
@@ -0,0 +1,17 @@ +error: constant evaluation is taking a long time + --> $DIR/do-not-ice-long-constant-evaluation-in-for-loop.rs:10:14 + | +LL | [(); loop {}]; + | ^^^^^^^ + | + = note: this lint makes sure the compiler doesn't get stuck due to infinite loops in const eval. + If your compilation actually takes a long time, you can safely allow the lint. +help: the constant being evaluated + --> $DIR/do-not-ice-long-constant-evaluation-in-for-loop.rs:10:14 + | +LL | [(); loop {}]; + | ^^^^^^^ + = note: `#[deny(long_running_const_eval)]` on by default + +error: aborting due to 1 previous error +
diff --git a/tests/ui/consts/precise-drop-nested-deref-ice.rs b/tests/ui/consts/precise-drop-nested-deref-ice.rs new file mode 100644 index 0000000..3ac5bea --- /dev/null +++ b/tests/ui/consts/precise-drop-nested-deref-ice.rs
@@ -0,0 +1,15 @@ +//! Tests that multiple derefs in a projection does not cause an ICE +//! when checking const precise drops. +//! +//! Regression test for <https://github.com/rust-lang/rust/issues/147733> + +#![feature(const_precise_live_drops)] +struct Foo(u32); +impl Foo { + const fn get(self: Box<&Self>, f: &u32) -> u32 { + //~^ ERROR destructor of `Box<&Foo>` cannot be evaluated at compile-time + self.0 + } +} + +fn main() {}
diff --git a/tests/ui/consts/precise-drop-nested-deref-ice.stderr b/tests/ui/consts/precise-drop-nested-deref-ice.stderr new file mode 100644 index 0000000..4e5af10 --- /dev/null +++ b/tests/ui/consts/precise-drop-nested-deref-ice.stderr
@@ -0,0 +1,12 @@ +error[E0493]: destructor of `Box<&Foo>` cannot be evaluated at compile-time + --> $DIR/precise-drop-nested-deref-ice.rs:9:18 + | +LL | const fn get(self: Box<&Self>, f: &u32) -> u32 { + | ^^^^ the destructor for this type cannot be evaluated in constant functions +... +LL | } + | - value is dropped here + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0493`.
diff --git a/tests/ui/consts/required-consts/collect-in-promoted-const.noopt.stderr b/tests/ui/consts/required-consts/collect-in-promoted-const.noopt.stderr index c1ae42b..9f65e4f 100644 --- a/tests/ui/consts/required-consts/collect-in-promoted-const.noopt.stderr +++ b/tests/ui/consts/required-consts/collect-in-promoted-const.noopt.stderr
@@ -1,17 +1,17 @@ error[E0080]: evaluation panicked: explicit panic - --> $DIR/collect-in-promoted-const.rs:11:19 + --> $DIR/collect-in-promoted-const.rs:9:19 | LL | const C: () = panic!(); | ^^^^^^^^ evaluation of `Fail::<i32>::C` failed here note: erroneous constant encountered - --> $DIR/collect-in-promoted-const.rs:22:21 + --> $DIR/collect-in-promoted-const.rs:17:21 | LL | let _val = &Fail::<T>::C; | ^^^^^^^^^^^^ note: the above error was encountered while instantiating `fn f::<i32>` - --> $DIR/collect-in-promoted-const.rs:27:5 + --> $DIR/collect-in-promoted-const.rs:22:5 | LL | f::<i32>(); | ^^^^^^^^^^
diff --git a/tests/ui/consts/required-consts/collect-in-promoted-const.opt.stderr b/tests/ui/consts/required-consts/collect-in-promoted-const.opt.stderr index 0d7ac48..9f65e4f 100644 --- a/tests/ui/consts/required-consts/collect-in-promoted-const.opt.stderr +++ b/tests/ui/consts/required-consts/collect-in-promoted-const.opt.stderr
@@ -1,35 +1,21 @@ error[E0080]: evaluation panicked: explicit panic - --> $DIR/collect-in-promoted-const.rs:11:19 - | -LL | const C: () = panic!(); - | ^^^^^^^^ evaluation of `Fail::<T>::C` failed here - -note: erroneous constant encountered - --> $DIR/collect-in-promoted-const.rs:22:21 - | -LL | let _val = &Fail::<T>::C; - | ^^^^^^^^^^^^ - -error[E0080]: evaluation panicked: explicit panic - --> $DIR/collect-in-promoted-const.rs:11:19 + --> $DIR/collect-in-promoted-const.rs:9:19 | LL | const C: () = panic!(); | ^^^^^^^^ evaluation of `Fail::<i32>::C` failed here note: erroneous constant encountered - --> $DIR/collect-in-promoted-const.rs:22:21 + --> $DIR/collect-in-promoted-const.rs:17:21 | LL | let _val = &Fail::<T>::C; | ^^^^^^^^^^^^ - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` note: the above error was encountered while instantiating `fn f::<i32>` - --> $DIR/collect-in-promoted-const.rs:27:5 + --> $DIR/collect-in-promoted-const.rs:22:5 | LL | f::<i32>(); | ^^^^^^^^^^ -error: aborting due to 2 previous errors +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0080`.
diff --git a/tests/ui/consts/required-consts/collect-in-promoted-const.rs b/tests/ui/consts/required-consts/collect-in-promoted-const.rs index 498328a..c475720 100644 --- a/tests/ui/consts/required-consts/collect-in-promoted-const.rs +++ b/tests/ui/consts/required-consts/collect-in-promoted-const.rs
@@ -1,17 +1,12 @@ //@revisions: noopt opt //@ build-fail //@[noopt] compile-flags: -Copt-level=0 -// FIXME(#61117): Respect debuginfo-level-tests, do not force debuginfo=0 -//@[opt] compile-flags: -C debuginfo=0 //@[opt] compile-flags: -O //! Make sure we error on erroneous consts even if they get promoted. struct Fail<T>(T); impl<T> Fail<T> { const C: () = panic!(); //~ERROR evaluation panicked: explicit panic - //[opt]~^ ERROR evaluation panicked: explicit panic - // (Not sure why optimizations lead to this being emitted twice, but as long as compilation - // fails either way it's fine.) } #[inline(never)]
diff --git a/tests/ui/cross/cross-file-errors/main.stderr b/tests/ui/cross/cross-file-errors/main.stderr index c7dea80..db7b3a8 100644 --- a/tests/ui/cross/cross-file-errors/main.stderr +++ b/tests/ui/cross/cross-file-errors/main.stderr
@@ -1,5 +1,5 @@ error: in expressions, `_` can only be used on the left-hand side of an assignment - --> $DIR/underscore.rs:6:9 + --> $DIR/underscore.rs:5:9 | LL | _ | ^ `_` not allowed here
diff --git a/tests/ui/cross/cross-file-errors/underscore.rs b/tests/ui/cross/cross-file-errors/underscore.rs index 73eb36c..9bad226 100644 --- a/tests/ui/cross/cross-file-errors/underscore.rs +++ b/tests/ui/cross/cross-file-errors/underscore.rs
@@ -1,5 +1,4 @@ //@ ignore-auxiliary (used by `./main.rs`) -#![crate_type = "lib"] macro_rules! underscore { () => (
diff --git a/tests/ui/deprecation/deprecated-expr-precedence.rs b/tests/ui/deprecation/deprecated-expr-precedence.rs index 9636b46..08a741e1 100644 --- a/tests/ui/deprecation/deprecated-expr-precedence.rs +++ b/tests/ui/deprecation/deprecated-expr-precedence.rs
@@ -5,4 +5,6 @@ pub fn public() { #[deprecated] 0 //~^ ERROR mismatched types + //~| WARN attribute cannot be used on expressions + //~| WARN previously accepted }
diff --git a/tests/ui/deprecation/deprecated-expr-precedence.stderr b/tests/ui/deprecation/deprecated-expr-precedence.stderr index 3275f2e..c3124cf 100644 --- a/tests/ui/deprecation/deprecated-expr-precedence.stderr +++ b/tests/ui/deprecation/deprecated-expr-precedence.stderr
@@ -1,3 +1,13 @@ +warning: `#[deprecated]` attribute cannot be used on expressions + --> $DIR/deprecated-expr-precedence.rs:6:5 + | +LL | #[deprecated] 0 + | ^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[deprecated]` can be applied to associated consts, associated types, constants, crates, data types, enum variants, foreign statics, functions, inherent impl blocks, macro defs, modules, statics, struct fields, traits, type aliases, unions, and use statements + = note: requested on the command line with `-W unused-attributes` + error[E0308]: mismatched types --> $DIR/deprecated-expr-precedence.rs:6:19 | @@ -6,6 +16,6 @@ LL | #[deprecated] 0 | ^ expected `()`, found integer -error: aborting due to 1 previous error +error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/editions/never-type-fallback-breaking.e2021.fixed b/tests/ui/editions/never-type-fallback-breaking.e2021.fixed index 8c11ab0..c8f3e87 100644 --- a/tests/ui/editions/never-type-fallback-breaking.e2021.fixed +++ b/tests/ui/editions/never-type-fallback-breaking.e2021.fixed
@@ -3,9 +3,7 @@ //@[e2021] edition: 2021 //@[e2024] edition: 2024 // -//@[e2021] run-pass //@[e2021] run-rustfix -//@[e2024] check-fail fn main() { m(); @@ -16,8 +14,8 @@ } fn m() { - //[e2021]~^ WARN this function depends on never type fallback being `()` - //[e2021]~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! + //[e2021]~^ error: this function depends on never type fallback being `()` + //[e2021]~| warn: this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! let x: () = match true { true => Default::default(), //[e2024]~^ error: the trait bound `!: Default` is not satisfied @@ -28,8 +26,8 @@ } fn q() -> Option<()> { - //[e2021]~^ WARN this function depends on never type fallback being `()` - //[e2021]~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! + //[e2021]~^ error: this function depends on never type fallback being `()` + //[e2021]~| warn: this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! fn deserialize<T: Default>() -> Option<T> { Some(T::default()) } @@ -45,8 +43,8 @@ Err(()) } fn meow() -> Result<(), ()> { - //[e2021]~^ WARN this function depends on never type fallback being `()` - //[e2021]~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! + //[e2021]~^ error: this function depends on never type fallback being `()` + //[e2021]~| warn: this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! help::<(), _>(1)?; //[e2024]~^ error: the trait bound `(): From<!>` is not satisfied Ok(()) @@ -57,8 +55,8 @@ } pub fn fallback_return() -> Result<(), ()> { - //[e2021]~^ WARN this function depends on never type fallback being `()` - //[e2021]~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! + //[e2021]~^ error: this function depends on never type fallback being `()` + //[e2021]~| warn: this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! takes_apit::<()>(|| Default::default())?; //[e2024]~^ error: the trait bound `!: Default` is not satisfied Ok(()) @@ -71,8 +69,8 @@ fn takes_apit2(_x: impl Default) {} fn fully_apit() -> Result<(), ()> { - //[e2021]~^ WARN this function depends on never type fallback being `()` - //[e2021]~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! + //[e2021]~^ error: this function depends on never type fallback being `()` + //[e2021]~| warn: this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! takes_apit2(mk::<()>()?); //[e2024]~^ error: the trait bound `!: Default` is not satisfied Ok(())
diff --git a/tests/ui/editions/never-type-fallback-breaking.e2021.stderr b/tests/ui/editions/never-type-fallback-breaking.e2021.stderr index 3d4a10a..ded694f 100644 --- a/tests/ui/editions/never-type-fallback-breaking.e2021.stderr +++ b/tests/ui/editions/never-type-fallback-breaking.e2021.stderr
@@ -1,5 +1,5 @@ -warning: this function depends on never type fallback being `()` - --> $DIR/never-type-fallback-breaking.rs:18:1 +error: this function depends on never type fallback being `()` + --> $DIR/never-type-fallback-breaking.rs:16:1 | LL | fn m() { | ^^^^^^ @@ -8,18 +8,18 @@ = note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/never-type-fallback.html> = help: specify the types explicitly note: in edition 2024, the requirement `!: Default` will fail - --> $DIR/never-type-fallback-breaking.rs:22:17 + --> $DIR/never-type-fallback-breaking.rs:20:17 | LL | true => Default::default(), | ^^^^^^^^^^^^^^^^^^ - = note: `#[warn(dependency_on_unit_never_type_fallback)]` (part of `#[warn(rust_2024_compatibility)]`) on by default + = note: `#[deny(dependency_on_unit_never_type_fallback)]` (part of `#[deny(rust_2024_compatibility)]`) on by default help: use `()` annotations to avoid fallback changes | LL | let x: () = match true { | ++++ -warning: this function depends on never type fallback being `()` - --> $DIR/never-type-fallback-breaking.rs:30:1 +error: this function depends on never type fallback being `()` + --> $DIR/never-type-fallback-breaking.rs:28:1 | LL | fn q() -> Option<()> { | ^^^^^^^^^^^^^^^^^^^^ @@ -28,7 +28,7 @@ = note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/never-type-fallback.html> = help: specify the types explicitly note: in edition 2024, the requirement `!: Default` will fail - --> $DIR/never-type-fallback-breaking.rs:37:5 + --> $DIR/never-type-fallback-breaking.rs:35:5 | LL | deserialize()?; | ^^^^^^^^^^^^^ @@ -37,8 +37,8 @@ LL | deserialize::<()>()?; | ++++++ -warning: this function depends on never type fallback being `()` - --> $DIR/never-type-fallback-breaking.rs:47:1 +error: this function depends on never type fallback being `()` + --> $DIR/never-type-fallback-breaking.rs:45:1 | LL | fn meow() -> Result<(), ()> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -47,7 +47,7 @@ = note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/never-type-fallback.html> = help: specify the types explicitly note: in edition 2024, the requirement `(): From<!>` will fail - --> $DIR/never-type-fallback-breaking.rs:50:5 + --> $DIR/never-type-fallback-breaking.rs:48:5 | LL | help(1)?; | ^^^^^^^ @@ -56,8 +56,8 @@ LL | help::<(), _>(1)?; | +++++++++ -warning: this function depends on never type fallback being `()` - --> $DIR/never-type-fallback-breaking.rs:59:1 +error: this function depends on never type fallback being `()` + --> $DIR/never-type-fallback-breaking.rs:57:1 | LL | pub fn fallback_return() -> Result<(), ()> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -66,7 +66,7 @@ = note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/never-type-fallback.html> = help: specify the types explicitly note: in edition 2024, the requirement `!: Default` will fail - --> $DIR/never-type-fallback-breaking.rs:62:19 + --> $DIR/never-type-fallback-breaking.rs:60:19 | LL | takes_apit(|| Default::default())?; | ^^^^^^^^^^^^^^^^^^ @@ -75,8 +75,8 @@ LL | takes_apit::<()>(|| Default::default())?; | ++++++ -warning: this function depends on never type fallback being `()` - --> $DIR/never-type-fallback-breaking.rs:73:1 +error: this function depends on never type fallback being `()` + --> $DIR/never-type-fallback-breaking.rs:71:1 | LL | fn fully_apit() -> Result<(), ()> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -85,7 +85,7 @@ = note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/never-type-fallback.html> = help: specify the types explicitly note: in edition 2024, the requirement `!: Default` will fail - --> $DIR/never-type-fallback-breaking.rs:76:17 + --> $DIR/never-type-fallback-breaking.rs:74:17 | LL | takes_apit2(mk()?); | ^^^^^ @@ -94,11 +94,11 @@ LL | takes_apit2(mk::<()>()?); | ++++++ -warning: 5 warnings emitted +error: aborting due to 5 previous errors Future incompatibility report: Future breakage diagnostic: -warning: this function depends on never type fallback being `()` - --> $DIR/never-type-fallback-breaking.rs:18:1 +error: this function depends on never type fallback being `()` + --> $DIR/never-type-fallback-breaking.rs:16:1 | LL | fn m() { | ^^^^^^ @@ -107,19 +107,19 @@ = note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/never-type-fallback.html> = help: specify the types explicitly note: in edition 2024, the requirement `!: Default` will fail - --> $DIR/never-type-fallback-breaking.rs:22:17 + --> $DIR/never-type-fallback-breaking.rs:20:17 | LL | true => Default::default(), | ^^^^^^^^^^^^^^^^^^ - = note: `#[warn(dependency_on_unit_never_type_fallback)]` (part of `#[warn(rust_2024_compatibility)]`) on by default + = note: `#[deny(dependency_on_unit_never_type_fallback)]` (part of `#[deny(rust_2024_compatibility)]`) on by default help: use `()` annotations to avoid fallback changes | LL | let x: () = match true { | ++++ Future breakage diagnostic: -warning: this function depends on never type fallback being `()` - --> $DIR/never-type-fallback-breaking.rs:30:1 +error: this function depends on never type fallback being `()` + --> $DIR/never-type-fallback-breaking.rs:28:1 | LL | fn q() -> Option<()> { | ^^^^^^^^^^^^^^^^^^^^ @@ -128,19 +128,19 @@ = note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/never-type-fallback.html> = help: specify the types explicitly note: in edition 2024, the requirement `!: Default` will fail - --> $DIR/never-type-fallback-breaking.rs:37:5 + --> $DIR/never-type-fallback-breaking.rs:35:5 | LL | deserialize()?; | ^^^^^^^^^^^^^ - = note: `#[warn(dependency_on_unit_never_type_fallback)]` (part of `#[warn(rust_2024_compatibility)]`) on by default + = note: `#[deny(dependency_on_unit_never_type_fallback)]` (part of `#[deny(rust_2024_compatibility)]`) on by default help: use `()` annotations to avoid fallback changes | LL | deserialize::<()>()?; | ++++++ Future breakage diagnostic: -warning: this function depends on never type fallback being `()` - --> $DIR/never-type-fallback-breaking.rs:47:1 +error: this function depends on never type fallback being `()` + --> $DIR/never-type-fallback-breaking.rs:45:1 | LL | fn meow() -> Result<(), ()> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -149,19 +149,19 @@ = note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/never-type-fallback.html> = help: specify the types explicitly note: in edition 2024, the requirement `(): From<!>` will fail - --> $DIR/never-type-fallback-breaking.rs:50:5 + --> $DIR/never-type-fallback-breaking.rs:48:5 | LL | help(1)?; | ^^^^^^^ - = note: `#[warn(dependency_on_unit_never_type_fallback)]` (part of `#[warn(rust_2024_compatibility)]`) on by default + = note: `#[deny(dependency_on_unit_never_type_fallback)]` (part of `#[deny(rust_2024_compatibility)]`) on by default help: use `()` annotations to avoid fallback changes | LL | help::<(), _>(1)?; | +++++++++ Future breakage diagnostic: -warning: this function depends on never type fallback being `()` - --> $DIR/never-type-fallback-breaking.rs:59:1 +error: this function depends on never type fallback being `()` + --> $DIR/never-type-fallback-breaking.rs:57:1 | LL | pub fn fallback_return() -> Result<(), ()> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -170,19 +170,19 @@ = note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/never-type-fallback.html> = help: specify the types explicitly note: in edition 2024, the requirement `!: Default` will fail - --> $DIR/never-type-fallback-breaking.rs:62:19 + --> $DIR/never-type-fallback-breaking.rs:60:19 | LL | takes_apit(|| Default::default())?; | ^^^^^^^^^^^^^^^^^^ - = note: `#[warn(dependency_on_unit_never_type_fallback)]` (part of `#[warn(rust_2024_compatibility)]`) on by default + = note: `#[deny(dependency_on_unit_never_type_fallback)]` (part of `#[deny(rust_2024_compatibility)]`) on by default help: use `()` annotations to avoid fallback changes | LL | takes_apit::<()>(|| Default::default())?; | ++++++ Future breakage diagnostic: -warning: this function depends on never type fallback being `()` - --> $DIR/never-type-fallback-breaking.rs:73:1 +error: this function depends on never type fallback being `()` + --> $DIR/never-type-fallback-breaking.rs:71:1 | LL | fn fully_apit() -> Result<(), ()> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -191,11 +191,11 @@ = note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/never-type-fallback.html> = help: specify the types explicitly note: in edition 2024, the requirement `!: Default` will fail - --> $DIR/never-type-fallback-breaking.rs:76:17 + --> $DIR/never-type-fallback-breaking.rs:74:17 | LL | takes_apit2(mk()?); | ^^^^^ - = note: `#[warn(dependency_on_unit_never_type_fallback)]` (part of `#[warn(rust_2024_compatibility)]`) on by default + = note: `#[deny(dependency_on_unit_never_type_fallback)]` (part of `#[deny(rust_2024_compatibility)]`) on by default help: use `()` annotations to avoid fallback changes | LL | takes_apit2(mk::<()>()?);
diff --git a/tests/ui/editions/never-type-fallback-breaking.e2024.stderr b/tests/ui/editions/never-type-fallback-breaking.e2024.stderr index f0d4de3..45e02ea 100644 --- a/tests/ui/editions/never-type-fallback-breaking.e2024.stderr +++ b/tests/ui/editions/never-type-fallback-breaking.e2024.stderr
@@ -1,5 +1,5 @@ error[E0277]: the trait bound `!: Default` is not satisfied - --> $DIR/never-type-fallback-breaking.rs:22:17 + --> $DIR/never-type-fallback-breaking.rs:20:17 | LL | true => Default::default(), | ^^^^^^^^^^^^^^^^^^ the trait `Default` is not implemented for `!` @@ -8,7 +8,7 @@ = help: you might have intended to use the type `()` here instead error[E0277]: the trait bound `!: Default` is not satisfied - --> $DIR/never-type-fallback-breaking.rs:37:5 + --> $DIR/never-type-fallback-breaking.rs:35:5 | LL | deserialize()?; | ^^^^^^^^^^^^^ the trait `Default` is not implemented for `!` @@ -16,13 +16,13 @@ = note: this error might have been caused by changes to Rust's type-inference algorithm (see issue #48950 <https://github.com/rust-lang/rust/issues/48950> for more information) = help: you might have intended to use the type `()` here instead note: required by a bound in `deserialize` - --> $DIR/never-type-fallback-breaking.rs:33:23 + --> $DIR/never-type-fallback-breaking.rs:31:23 | LL | fn deserialize<T: Default>() -> Option<T> { | ^^^^^^^ required by this bound in `deserialize` error[E0277]: the trait bound `(): From<!>` is not satisfied - --> $DIR/never-type-fallback-breaking.rs:50:5 + --> $DIR/never-type-fallback-breaking.rs:48:5 | LL | help(1)?; | ^^^^^^^ the trait `From<!>` is not implemented for `()` @@ -39,13 +39,13 @@ and 4 others = note: required for `!` to implement `Into<()>` note: required by a bound in `help` - --> $DIR/never-type-fallback-breaking.rs:44:20 + --> $DIR/never-type-fallback-breaking.rs:42:20 | LL | fn help<'a: 'a, T: Into<()>, U>(_: U) -> Result<T, ()> { | ^^^^^^^^ required by this bound in `help` error[E0277]: the trait bound `!: Default` is not satisfied - --> $DIR/never-type-fallback-breaking.rs:62:19 + --> $DIR/never-type-fallback-breaking.rs:60:19 | LL | takes_apit(|| Default::default())?; | ^^^^^^^^^^^^^^^^^^ the trait `Default` is not implemented for `!` @@ -54,7 +54,7 @@ = help: you might have intended to use the type `()` here instead error[E0277]: the trait bound `!: Default` is not satisfied - --> $DIR/never-type-fallback-breaking.rs:76:17 + --> $DIR/never-type-fallback-breaking.rs:74:17 | LL | takes_apit2(mk()?); | ----------- ^^^^^ the trait `Default` is not implemented for `!` @@ -64,7 +64,7 @@ = note: this error might have been caused by changes to Rust's type-inference algorithm (see issue #48950 <https://github.com/rust-lang/rust/issues/48950> for more information) = help: you might have intended to use the type `()` here instead note: required by a bound in `takes_apit2` - --> $DIR/never-type-fallback-breaking.rs:71:25 + --> $DIR/never-type-fallback-breaking.rs:69:25 | LL | fn takes_apit2(_x: impl Default) {} | ^^^^^^^ required by this bound in `takes_apit2`
diff --git a/tests/ui/editions/never-type-fallback-breaking.rs b/tests/ui/editions/never-type-fallback-breaking.rs index 80974f8..96e4694 100644 --- a/tests/ui/editions/never-type-fallback-breaking.rs +++ b/tests/ui/editions/never-type-fallback-breaking.rs
@@ -3,9 +3,7 @@ //@[e2021] edition: 2021 //@[e2024] edition: 2024 // -//@[e2021] run-pass //@[e2021] run-rustfix -//@[e2024] check-fail fn main() { m(); @@ -16,8 +14,8 @@ fn main() { } fn m() { - //[e2021]~^ WARN this function depends on never type fallback being `()` - //[e2021]~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! + //[e2021]~^ error: this function depends on never type fallback being `()` + //[e2021]~| warn: this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! let x = match true { true => Default::default(), //[e2024]~^ error: the trait bound `!: Default` is not satisfied @@ -28,8 +26,8 @@ fn m() { } fn q() -> Option<()> { - //[e2021]~^ WARN this function depends on never type fallback being `()` - //[e2021]~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! + //[e2021]~^ error: this function depends on never type fallback being `()` + //[e2021]~| warn: this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! fn deserialize<T: Default>() -> Option<T> { Some(T::default()) } @@ -45,8 +43,8 @@ fn help<'a: 'a, T: Into<()>, U>(_: U) -> Result<T, ()> { Err(()) } fn meow() -> Result<(), ()> { - //[e2021]~^ WARN this function depends on never type fallback being `()` - //[e2021]~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! + //[e2021]~^ error: this function depends on never type fallback being `()` + //[e2021]~| warn: this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! help(1)?; //[e2024]~^ error: the trait bound `(): From<!>` is not satisfied Ok(()) @@ -57,8 +55,8 @@ pub fn takes_apit<T>(_y: impl Fn() -> T) -> Result<T, ()> { } pub fn fallback_return() -> Result<(), ()> { - //[e2021]~^ WARN this function depends on never type fallback being `()` - //[e2021]~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! + //[e2021]~^ error: this function depends on never type fallback being `()` + //[e2021]~| warn: this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! takes_apit(|| Default::default())?; //[e2024]~^ error: the trait bound `!: Default` is not satisfied Ok(()) @@ -71,8 +69,8 @@ fn mk<T>() -> Result<T, ()> { fn takes_apit2(_x: impl Default) {} fn fully_apit() -> Result<(), ()> { - //[e2021]~^ WARN this function depends on never type fallback being `()` - //[e2021]~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! + //[e2021]~^ error: this function depends on never type fallback being `()` + //[e2021]~| warn: this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! takes_apit2(mk()?); //[e2024]~^ error: the trait bound `!: Default` is not satisfied Ok(())
diff --git a/tests/ui/empty/empty-macro-use.rs b/tests/ui/empty/empty-macro-use.rs index 8f5ea7d..fadc653 100644 --- a/tests/ui/empty/empty-macro-use.rs +++ b/tests/ui/empty/empty-macro-use.rs
@@ -1,6 +1,7 @@ //@ aux-build:two_macros.rs #[macro_use()] +//~^ WARN unused attribute extern crate two_macros; pub fn main() {
diff --git a/tests/ui/empty/empty-macro-use.stderr b/tests/ui/empty/empty-macro-use.stderr index cdf3ff8..0b23dd4 100644 --- a/tests/ui/empty/empty-macro-use.stderr +++ b/tests/ui/empty/empty-macro-use.stderr
@@ -1,5 +1,5 @@ error: cannot find macro `macro_two` in this scope - --> $DIR/empty-macro-use.rs:7:5 + --> $DIR/empty-macro-use.rs:8:5 | LL | macro_two!(); | ^^^^^^^^^ @@ -9,5 +9,14 @@ LL + use two_macros::macro_two; | -error: aborting due to 1 previous error +warning: unused attribute + --> $DIR/empty-macro-use.rs:3:12 + | +LL | #[macro_use()] + | ^^ help: remove these parentheses + | + = note: using `macro_use` with an empty list is equivalent to not using a list at all + = note: requested on the command line with `-W unused-attributes` + +error: aborting due to 1 previous error; 1 warning emitted
diff --git a/tests/ui/error-emitter/trimmed_multiline_suggestion.rs b/tests/ui/error-emitter/trimmed_multiline_suggestion.rs new file mode 100644 index 0000000..c0ae9af --- /dev/null +++ b/tests/ui/error-emitter/trimmed_multiline_suggestion.rs
@@ -0,0 +1,14 @@ +//@ compile-flags: -Z ui-testing=no +fn function_with_lots_of_arguments(a: i32, b: char, c: i32, d: i32, e: i32, f: i32) {} + +fn main() { + let variable_name = 42; + function_with_lots_of_arguments( + variable_name, + variable_name, + variable_name, + variable_name, + variable_name, + ); + //~^^^^^^^ ERROR this function takes 6 arguments but 5 arguments were supplied [E0061] +}
diff --git a/tests/ui/error-emitter/trimmed_multiline_suggestion.stderr b/tests/ui/error-emitter/trimmed_multiline_suggestion.stderr new file mode 100644 index 0000000..6e1ffb1 --- /dev/null +++ b/tests/ui/error-emitter/trimmed_multiline_suggestion.stderr
@@ -0,0 +1,25 @@ +error[E0061]: this function takes 6 arguments but 5 arguments were supplied + --> $DIR/trimmed_multiline_suggestion.rs:6:5 + | +6 | function_with_lots_of_arguments( + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +7 | variable_name, +8 | variable_name, + | ------------- argument #2 of type `char` is missing + | +note: function defined here + --> $DIR/trimmed_multiline_suggestion.rs:2:4 + | +2 | fn function_with_lots_of_arguments(a: i32, b: char, c: i32, d: i32, e: i32, f: i32) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ------- +help: provide the argument + | +6 | function_with_lots_of_arguments( +7 | variable_name, +8 ~ /* char */, +9 ~ variable_name, + | + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0061`.
diff --git a/tests/ui/feature-gates/feature-gate-more-maybe-bounds.rs b/tests/ui/feature-gates/feature-gate-more-maybe-bounds.rs index 9c727ae..191fef3 100644 --- a/tests/ui/feature-gates/feature-gate-more-maybe-bounds.rs +++ b/tests/ui/feature-gates/feature-gate-more-maybe-bounds.rs
@@ -1,12 +1,17 @@ -#![feature(auto_traits)] +#![feature(auto_traits, lang_items)] -trait Trait1 {} -auto trait Trait2 {} -trait Trait3: ?Trait1 {} //~ ERROR relaxed bounds are not permitted in supertrait bounds -trait Trait4 where Self: ?Trait1 {} //~ ERROR this relaxed bound is not permitted here +#[lang = "default_trait1"] trait Trait1 {} +#[lang = "default_trait2"] auto trait Trait2 {} + +trait Trait3: ?Trait1 {} +//~^ ERROR relaxed bounds are not permitted in supertrait bounds +//~| ERROR bound modifier `?` can only be applied to `Sized` +//~| ERROR bound modifier `?` can only be applied to `Sized` +//~| ERROR bound modifier `?` can only be applied to `Sized` fn foo(_: Box<dyn Trait1 + ?Trait2>) {} //~^ ERROR relaxed bounds are not permitted in trait object types +//~| ERROR bound modifier `?` can only be applied to `Sized` fn bar<T: ?Trait1 + ?Trait2>(_: T) {} //~^ ERROR bound modifier `?` can only be applied to `Sized` //~| ERROR bound modifier `?` can only be applied to `Sized`
diff --git a/tests/ui/feature-gates/feature-gate-more-maybe-bounds.stderr b/tests/ui/feature-gates/feature-gate-more-maybe-bounds.stderr index da6ad5f..6503af2 100644 --- a/tests/ui/feature-gates/feature-gate-more-maybe-bounds.stderr +++ b/tests/ui/feature-gates/feature-gate-more-maybe-bounds.stderr
@@ -1,34 +1,54 @@ error: relaxed bounds are not permitted in supertrait bounds - --> $DIR/feature-gate-more-maybe-bounds.rs:5:15 + --> $DIR/feature-gate-more-maybe-bounds.rs:6:15 | LL | trait Trait3: ?Trait1 {} | ^^^^^^^ -error: this relaxed bound is not permitted here - --> $DIR/feature-gate-more-maybe-bounds.rs:6:26 - | -LL | trait Trait4 where Self: ?Trait1 {} - | ^^^^^^^ - | - = note: in this context, relaxed bounds are only allowed on type parameters defined by the closest item - error: relaxed bounds are not permitted in trait object types - --> $DIR/feature-gate-more-maybe-bounds.rs:8:28 + --> $DIR/feature-gate-more-maybe-bounds.rs:12:28 | LL | fn foo(_: Box<dyn Trait1 + ?Trait2>) {} | ^^^^^^^ error: bound modifier `?` can only be applied to `Sized` - --> $DIR/feature-gate-more-maybe-bounds.rs:10:11 + --> $DIR/feature-gate-more-maybe-bounds.rs:6:15 + | +LL | trait Trait3: ?Trait1 {} + | ^^^^^^^ + +error: bound modifier `?` can only be applied to `Sized` + --> $DIR/feature-gate-more-maybe-bounds.rs:6:15 + | +LL | trait Trait3: ?Trait1 {} + | ^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: bound modifier `?` can only be applied to `Sized` + --> $DIR/feature-gate-more-maybe-bounds.rs:6:15 + | +LL | trait Trait3: ?Trait1 {} + | ^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: bound modifier `?` can only be applied to `Sized` + --> $DIR/feature-gate-more-maybe-bounds.rs:12:28 + | +LL | fn foo(_: Box<dyn Trait1 + ?Trait2>) {} + | ^^^^^^^ + +error: bound modifier `?` can only be applied to `Sized` + --> $DIR/feature-gate-more-maybe-bounds.rs:15:11 | LL | fn bar<T: ?Trait1 + ?Trait2>(_: T) {} | ^^^^^^^ error: bound modifier `?` can only be applied to `Sized` - --> $DIR/feature-gate-more-maybe-bounds.rs:10:21 + --> $DIR/feature-gate-more-maybe-bounds.rs:15:21 | LL | fn bar<T: ?Trait1 + ?Trait2>(_: T) {} | ^^^^^^^ -error: aborting due to 5 previous errors +error: aborting due to 8 previous errors
diff --git a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.rs b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.rs index 4bea448..0b0dd80 100644 --- a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.rs +++ b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.rs
@@ -16,15 +16,23 @@ //~| NOTE: the `#[rustc_main]` attribute is used internally to specify test entry point function #![repr()] //~^ ERROR: `repr` attribute cannot be used at crate level +//~| WARN unused attribute +//~| NOTE empty list has no effect #![path = "3800"] //~^ ERROR: attribute cannot be used on #![automatically_derived] //~^ ERROR: attribute cannot be used on #![no_mangle] +//~^ WARN may not be used in combination with `#[export_name]` +//~| NOTE is ignored +//~| NOTE requested on the command line +//~| WARN cannot be used on crates +//~| WARN previously accepted #![no_link] //~^ ERROR: attribute should be applied to an `extern crate` item #![export_name = "2200"] //~^ ERROR: attribute cannot be used on +//~| NOTE takes precedence #![inline] //~^ ERROR: attribute cannot be used on #[inline]
diff --git a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr index 8091b0b..013e529 100644 --- a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr +++ b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr
@@ -25,7 +25,7 @@ = help: `#[rustc_main]` can only be applied to functions error: `#[path]` attribute cannot be used on crates - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:19:1 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:21:1 | LL | #![path = "3800"] | ^^^^^^^^^^^^^^^^^ @@ -33,7 +33,7 @@ = help: `#[path]` can only be applied to modules error: `#[automatically_derived]` attribute cannot be used on crates - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:21:1 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:23:1 | LL | #![automatically_derived] | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -41,7 +41,7 @@ = help: `#[automatically_derived]` can only be applied to trait impl blocks error: `#[export_name]` attribute cannot be used on crates - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:26:1 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:33:1 | LL | #![export_name = "2200"] | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -49,7 +49,7 @@ = help: `#[export_name]` can be applied to functions and statics error: `#[inline]` attribute cannot be used on crates - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:28:1 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:36:1 | LL | #![inline] | ^^^^^^^^^^ @@ -57,7 +57,7 @@ = help: `#[inline]` can only be applied to functions error: `#[inline]` attribute cannot be used on modules - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:30:1 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:38:1 | LL | #[inline] | ^^^^^^^^^ @@ -65,7 +65,7 @@ = help: `#[inline]` can only be applied to functions error: `#[inline]` attribute cannot be used on modules - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:35:17 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:43:17 | LL | mod inner { #![inline] } | ^^^^^^^^^^ @@ -73,7 +73,7 @@ = help: `#[inline]` can only be applied to functions error: `#[inline]` attribute cannot be used on structs - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:44:5 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:52:5 | LL | #[inline] struct S; | ^^^^^^^^^ @@ -81,7 +81,7 @@ = help: `#[inline]` can only be applied to functions error: `#[inline]` attribute cannot be used on type aliases - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:47:5 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:55:5 | LL | #[inline] type T = S; | ^^^^^^^^^ @@ -89,7 +89,7 @@ = help: `#[inline]` can only be applied to functions error: `#[inline]` attribute cannot be used on inherent impl blocks - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:50:5 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:58:5 | LL | #[inline] impl S { } | ^^^^^^^^^ @@ -97,7 +97,7 @@ = help: `#[inline]` can only be applied to functions error: `#[export_name]` attribute cannot be used on modules - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:80:1 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:88:1 | LL | #[export_name = "2200"] | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -105,7 +105,7 @@ = help: `#[export_name]` can be applied to functions and statics error: `#[export_name]` attribute cannot be used on modules - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:83:17 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:91:17 | LL | mod inner { #![export_name="2200"] } | ^^^^^^^^^^^^^^^^^^^^^^ @@ -113,7 +113,7 @@ = help: `#[export_name]` can be applied to functions and statics error: `#[export_name]` attribute cannot be used on structs - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:88:5 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:96:5 | LL | #[export_name = "2200"] struct S; | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -121,7 +121,7 @@ = help: `#[export_name]` can be applied to functions and statics error: `#[export_name]` attribute cannot be used on type aliases - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:91:5 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:99:5 | LL | #[export_name = "2200"] type T = S; | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -129,7 +129,7 @@ = help: `#[export_name]` can be applied to functions and statics error: `#[export_name]` attribute cannot be used on inherent impl blocks - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:94:5 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:102:5 | LL | #[export_name = "2200"] impl S { } | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -137,7 +137,7 @@ = help: `#[export_name]` can be applied to functions and statics error: `#[export_name]` attribute cannot be used on required trait methods - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:98:9 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:106:9 | LL | #[export_name = "2200"] fn foo(); | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -145,7 +145,7 @@ = help: `#[export_name]` can be applied to functions, inherent methods, provided trait methods, statics, and trait methods in impl blocks error: attribute should be applied to an `extern crate` item - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:54:1 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:62:1 | LL | #[no_link] | ^^^^^^^^^^ @@ -159,7 +159,7 @@ | |_- not an `extern crate` item error[E0517]: attribute should be applied to a struct, enum, or union - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:105:8 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:113:8 | LL | #[repr(C)] | ^ @@ -172,7 +172,7 @@ | |_- not a struct, enum, or union error[E0517]: attribute should be applied to a struct, enum, or union - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:129:8 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:137:8 | LL | #[repr(Rust)] | ^^^^ @@ -185,11 +185,28 @@ | |_- not a struct, enum, or union error: attribute should be applied to an `extern crate` item - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:24:1 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:31:1 | LL | #![no_link] | ^^^^^^^^^^^ not an `extern crate` item +warning: `#[no_mangle]` attribute may not be used in combination with `#[export_name]` + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:25:1 + | +LL | #![no_mangle] + | ^^^^^^^^^^^^^ `#[no_mangle]` is ignored + | +note: `#[export_name]` takes precedence + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:33:1 + | +LL | #![export_name = "2200"] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + = note: requested on the command line with `-W unused-attributes` +help: remove the `#[no_mangle]` attribute + | +LL - #![no_mangle] + | + error: `repr` attribute cannot be used at crate level --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:17:1 | @@ -206,85 +223,85 @@ | error: attribute should be applied to an `extern crate` item - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:59:17 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:67:17 | LL | mod inner { #![no_link] } | ------------^^^^^^^^^^^-- not an `extern crate` item error: attribute should be applied to an `extern crate` item - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:63:5 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:71:5 | LL | #[no_link] fn f() { } | ^^^^^^^^^^ ---------- not an `extern crate` item error: attribute should be applied to an `extern crate` item - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:67:5 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:75:5 | LL | #[no_link] struct S; | ^^^^^^^^^^ --------- not an `extern crate` item error: attribute should be applied to an `extern crate` item - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:71:5 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:79:5 | LL | #[no_link]type T = S; | ^^^^^^^^^^----------- not an `extern crate` item error: attribute should be applied to an `extern crate` item - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:75:5 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:83:5 | LL | #[no_link] impl S { } | ^^^^^^^^^^ ---------- not an `extern crate` item error[E0517]: attribute should be applied to a struct, enum, or union - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:109:25 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:117:25 | LL | mod inner { #![repr(C)] } | --------------------^---- not a struct, enum, or union error[E0517]: attribute should be applied to a struct, enum, or union - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:113:12 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:121:12 | LL | #[repr(C)] fn f() { } | ^ ---------- not a struct, enum, or union error[E0517]: attribute should be applied to a struct, enum, or union - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:119:12 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:127:12 | LL | #[repr(C)] type T = S; | ^ ----------- not a struct, enum, or union error[E0517]: attribute should be applied to a struct, enum, or union - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:123:12 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:131:12 | LL | #[repr(C)] impl S { } | ^ ---------- not a struct, enum, or union error[E0517]: attribute should be applied to a struct, enum, or union - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:133:25 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:141:25 | LL | mod inner { #![repr(Rust)] } | --------------------^^^^---- not a struct, enum, or union error[E0517]: attribute should be applied to a struct, enum, or union - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:137:12 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:145:12 | LL | #[repr(Rust)] fn f() { } | ^^^^ ---------- not a struct, enum, or union error[E0517]: attribute should be applied to a struct, enum, or union - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:143:12 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:151:12 | LL | #[repr(Rust)] type T = S; | ^^^^ ----------- not a struct, enum, or union error[E0517]: attribute should be applied to a struct, enum, or union - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:147:12 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:155:12 | LL | #[repr(Rust)] impl S { } | ^^^^ ---------- not a struct, enum, or union error: valid forms for the attribute are `#[inline(always)]`, `#[inline(never)]`, and `#[inline]` - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:38:5 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:46:5 | LL | #[inline = "2100"] fn f() { } | ^^^^^^^^^^^^^^^^^^ @@ -293,13 +310,30 @@ = note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571> = note: `#[deny(ill_formed_attribute_input)]` (part of `#[deny(future_incompatible)]`) on by default -error: aborting due to 37 previous errors +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:17:1 + | +LL | #![repr()] + | ^^^^^^^^^^ help: remove this attribute + | + = note: using `repr` with an empty list has no effect + +warning: `#[no_mangle]` attribute cannot be used on crates + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:25:1 + | +LL | #![no_mangle] + | ^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[no_mangle]` can be applied to functions and statics + +error: aborting due to 37 previous errors; 3 warnings emitted Some errors have detailed explanations: E0517, E0658. For more information about an error, try `rustc --explain E0517`. Future incompatibility report: Future breakage diagnostic: error: valid forms for the attribute are `#[inline(always)]`, `#[inline(never)]`, and `#[inline]` - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:38:5 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:46:5 | LL | #[inline = "2100"] fn f() { } | ^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/feature-gates/issue-43106-gating-of-macro_use.rs b/tests/ui/feature-gates/issue-43106-gating-of-macro_use.rs index 0438152..67959a3 100644 --- a/tests/ui/feature-gates/issue-43106-gating-of-macro_use.rs +++ b/tests/ui/feature-gates/issue-43106-gating-of-macro_use.rs
@@ -14,12 +14,20 @@ mod inner { #![macro_use(my_macro)] } #[macro_use = "2700"] struct S; //~^ ERROR valid forms for the attribute are `#[macro_use(name1, name2, ...)]` and `#[macro_use]` + //~| WARN cannot be used on + //~| WARN previously accepted #[macro_use] fn f() { } + //~^ WARN cannot be used on + //~| WARN previously accepted #[macro_use] type T = S; + //~^ WARN cannot be used on + //~| WARN previously accepted #[macro_use] impl S { } + //~^ WARN cannot be used on + //~| WARN previously accepted } fn main() { }
diff --git a/tests/ui/feature-gates/issue-43106-gating-of-macro_use.stderr b/tests/ui/feature-gates/issue-43106-gating-of-macro_use.stderr index 4da7176..5be17e9 100644 --- a/tests/ui/feature-gates/issue-43106-gating-of-macro_use.stderr +++ b/tests/ui/feature-gates/issue-43106-gating-of-macro_use.stderr
@@ -22,5 +22,42 @@ LL | #[macro_use = "2700"] struct S; | ^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 4 previous errors +warning: `#[macro_use]` attribute cannot be used on structs + --> $DIR/issue-43106-gating-of-macro_use.rs:15:5 + | +LL | #[macro_use = "2700"] struct S; + | ^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[macro_use]` can be applied to crates, extern crates, and modules + = note: requested on the command line with `-W unused-attributes` + +warning: `#[macro_use]` attribute cannot be used on functions + --> $DIR/issue-43106-gating-of-macro_use.rs:20:5 + | +LL | #[macro_use] fn f() { } + | ^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[macro_use]` can be applied to crates, extern crates, and modules + +warning: `#[macro_use]` attribute cannot be used on type aliases + --> $DIR/issue-43106-gating-of-macro_use.rs:24:5 + | +LL | #[macro_use] type T = S; + | ^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[macro_use]` can be applied to crates, extern crates, and modules + +warning: `#[macro_use]` attribute cannot be used on inherent impl blocks + --> $DIR/issue-43106-gating-of-macro_use.rs:28:5 + | +LL | #[macro_use] impl S { } + | ^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[macro_use]` can be applied to crates, extern crates, and modules + +error: aborting due to 4 previous errors; 4 warnings emitted
diff --git a/tests/ui/ffi/extern-static-mut-slice-54410.rs b/tests/ui/ffi/extern-static-mut-slice-54410.rs new file mode 100644 index 0000000..0c96722 --- /dev/null +++ b/tests/ui/ffi/extern-static-mut-slice-54410.rs
@@ -0,0 +1,9 @@ +// https://github.com/rust-lang/rust/issues/54410 +extern "C" { + pub static mut symbol: [i8]; + //~^ ERROR the size for values of type `[i8]` cannot be known at compilation time +} + +fn main() { + println!("{:p}", unsafe { &symbol }); +}
diff --git a/tests/ui/ffi/extern-static-mut-slice-54410.stderr b/tests/ui/ffi/extern-static-mut-slice-54410.stderr new file mode 100644 index 0000000..7336836 --- /dev/null +++ b/tests/ui/ffi/extern-static-mut-slice-54410.stderr
@@ -0,0 +1,12 @@ +error[E0277]: the size for values of type `[i8]` cannot be known at compilation time + --> $DIR/extern-static-mut-slice-54410.rs:3:5 + | +LL | pub static mut symbol: [i8]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[i8]` + = note: statics and constants must have a statically known size + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/issues/issue-70381.rs b/tests/ui/fmt/unicode-format-string-missing-parameter-70381.rs similarity index 76% rename from tests/ui/issues/issue-70381.rs rename to tests/ui/fmt/unicode-format-string-missing-parameter-70381.rs index 3df8277..fad2fd8 100644 --- a/tests/ui/issues/issue-70381.rs +++ b/tests/ui/fmt/unicode-format-string-missing-parameter-70381.rs
@@ -1,3 +1,4 @@ +// https://github.com/rust-lang/rust/issues/70381 // Test that multi-byte unicode characters with missing parameters do not ICE. fn main() {
diff --git a/tests/ui/issues/issue-70381.stderr b/tests/ui/fmt/unicode-format-string-missing-parameter-70381.stderr similarity index 72% rename from tests/ui/issues/issue-70381.stderr rename to tests/ui/fmt/unicode-format-string-missing-parameter-70381.stderr index 298a1cf..cfcff0e 100644 --- a/tests/ui/issues/issue-70381.stderr +++ b/tests/ui/fmt/unicode-format-string-missing-parameter-70381.stderr
@@ -1,5 +1,5 @@ error: 1 positional argument in format string, but no arguments were given - --> $DIR/issue-70381.rs:4:16 + --> $DIR/unicode-format-string-missing-parameter-70381.rs:5:16 | LL | println!("\r¡{}") | ^^
diff --git a/tests/ui/higher-ranked-trait-bounds/higher-trait-bounds-ice-60218.rs b/tests/ui/higher-ranked-trait-bounds/higher-trait-bounds-ice-60218.rs new file mode 100644 index 0000000..d1a4e09 --- /dev/null +++ b/tests/ui/higher-ranked-trait-bounds/higher-trait-bounds-ice-60218.rs
@@ -0,0 +1,20 @@ +// https://github.com/rust-lang/rust/issues/60218 +// Regression test for #60218 +// +// This was reported to cause ICEs. + +use std::iter::Map; + +pub trait Foo {} + +pub fn trigger_error<I, F>(iterable: I, functor: F) +where + for<'t> &'t I: IntoIterator, +for<'t> Map<<&'t I as IntoIterator>::IntoIter, F>: Iterator, +for<'t> <Map<<&'t I as IntoIterator>::IntoIter, F> as Iterator>::Item: Foo, +{ +} + +fn main() { + trigger_error(vec![], |x: &u32| x) //~ ERROR E0277 +}
diff --git a/tests/ui/higher-ranked-trait-bounds/higher-trait-bounds-ice-60218.stderr b/tests/ui/higher-ranked-trait-bounds/higher-trait-bounds-ice-60218.stderr new file mode 100644 index 0000000..4c403bcb --- /dev/null +++ b/tests/ui/higher-ranked-trait-bounds/higher-trait-bounds-ice-60218.stderr
@@ -0,0 +1,25 @@ +error[E0277]: the trait bound `&u32: Foo` is not satisfied + --> $DIR/higher-trait-bounds-ice-60218.rs:19:19 + | +LL | trigger_error(vec![], |x: &u32| x) + | ------------- ^^^^^^ the trait `Foo` is not implemented for `&u32` + | | + | required by a bound introduced by this call + | +help: this trait has no implementations, consider adding one + --> $DIR/higher-trait-bounds-ice-60218.rs:8:1 + | +LL | pub trait Foo {} + | ^^^^^^^^^^^^^ +note: required by a bound in `trigger_error` + --> $DIR/higher-trait-bounds-ice-60218.rs:14:72 + | +LL | pub fn trigger_error<I, F>(iterable: I, functor: F) + | ------------- required by a bound in this function +... +LL | for<'t> <Map<<&'t I as IntoIterator>::IntoIter, F> as Iterator>::Item: Foo, + | ^^^ required by this bound in `trigger_error` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/inference/ambiguous-numeric-in-closure-ref.fixed b/tests/ui/inference/ambiguous-numeric-in-closure-ref.fixed new file mode 100644 index 0000000..683d581 --- /dev/null +++ b/tests/ui/inference/ambiguous-numeric-in-closure-ref.fixed
@@ -0,0 +1,14 @@ +// Test for better error message when numeric type is ambiguous in closure parameter with reference + +//@ run-rustfix + +fn main() { + let _ = (0..10).filter(|&v: &i32| v.pow(2) > 0); + //~^ ERROR can't call method `pow` on ambiguous numeric type `{integer}` + //~| SUGGESTION &i32 + + let v = vec![0, 1, 2]; + let _ = v.iter().filter(|&&v: &&i32| v.pow(2) > 0); + //~^ ERROR can't call method `pow` on ambiguous numeric type `{integer}` + //~| SUGGESTION &&i32 +}
diff --git a/tests/ui/inference/ambiguous-numeric-in-closure-ref.rs b/tests/ui/inference/ambiguous-numeric-in-closure-ref.rs new file mode 100644 index 0000000..eab309c --- /dev/null +++ b/tests/ui/inference/ambiguous-numeric-in-closure-ref.rs
@@ -0,0 +1,14 @@ +// Test for better error message when numeric type is ambiguous in closure parameter with reference + +//@ run-rustfix + +fn main() { + let _ = (0..10).filter(|&v| v.pow(2) > 0); + //~^ ERROR can't call method `pow` on ambiguous numeric type `{integer}` + //~| SUGGESTION &i32 + + let v = vec![0, 1, 2]; + let _ = v.iter().filter(|&&v| v.pow(2) > 0); + //~^ ERROR can't call method `pow` on ambiguous numeric type `{integer}` + //~| SUGGESTION &&i32 +}
diff --git a/tests/ui/inference/ambiguous-numeric-in-closure-ref.stderr b/tests/ui/inference/ambiguous-numeric-in-closure-ref.stderr new file mode 100644 index 0000000..0789581 --- /dev/null +++ b/tests/ui/inference/ambiguous-numeric-in-closure-ref.stderr
@@ -0,0 +1,29 @@ +error[E0689]: can't call method `pow` on ambiguous numeric type `{integer}` + --> $DIR/ambiguous-numeric-in-closure-ref.rs:6:35 + | +LL | let _ = (0..10).filter(|&v| v.pow(2) > 0); + | - ^^^ + | | + | you must specify a type for this binding + | +help: specify the type in the closure argument list + | +LL | let _ = (0..10).filter(|&v: &i32| v.pow(2) > 0); + | ++++++ + +error[E0689]: can't call method `pow` on ambiguous numeric type `{integer}` + --> $DIR/ambiguous-numeric-in-closure-ref.rs:11:37 + | +LL | let _ = v.iter().filter(|&&v| v.pow(2) > 0); + | - ^^^ + | | + | you must specify a type for this binding + | +help: specify the type in the closure argument list + | +LL | let _ = v.iter().filter(|&&v: &&i32| v.pow(2) > 0); + | +++++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0689`.
diff --git a/tests/ui/instrument-coverage/link-regex-crate-with-instrument-coverage-85461.rs b/tests/ui/instrument-coverage/msvc-link-dead-code-inline-always-85461.rs similarity index 100% rename from tests/ui/instrument-coverage/link-regex-crate-with-instrument-coverage-85461.rs rename to tests/ui/instrument-coverage/msvc-link-dead-code-inline-always-85461.rs
diff --git a/tests/ui/internal/internal-unstable.rs b/tests/ui/internal/internal-unstable.rs index 381c133..5564852e 100644 --- a/tests/ui/internal/internal-unstable.rs +++ b/tests/ui/internal/internal-unstable.rs
@@ -8,6 +8,8 @@ struct Baz { #[allow_internal_unstable] //~ ERROR `allow_internal_unstable` expects a list of feature names + //~^ WARN cannot be used on + //~| WARN previously accepted baz: u8, } @@ -57,6 +59,8 @@ fn main() { match true { #[allow_internal_unstable] //~ ERROR `allow_internal_unstable` expects a list of feature names + //~^ WARN cannot be used on + //~| WARN previously accepted _ => {} }
diff --git a/tests/ui/internal/internal-unstable.stderr b/tests/ui/internal/internal-unstable.stderr index bbf589d..192ecdf 100644 --- a/tests/ui/internal/internal-unstable.stderr +++ b/tests/ui/internal/internal-unstable.stderr
@@ -5,13 +5,13 @@ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: `allow_internal_unstable` expects a list of feature names - --> $DIR/internal-unstable.rs:59:9 + --> $DIR/internal-unstable.rs:61:9 | LL | #[allow_internal_unstable] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0658]: use of unstable library feature `function` - --> $DIR/internal-unstable.rs:48:25 + --> $DIR/internal-unstable.rs:50:25 | LL | pass_through_allow!(internal_unstable::unstable()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -20,7 +20,7 @@ = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: use of unstable library feature `function` - --> $DIR/internal-unstable.rs:50:27 + --> $DIR/internal-unstable.rs:52:27 | LL | pass_through_noallow!(internal_unstable::unstable()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -29,7 +29,7 @@ = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: use of unstable library feature `function` - --> $DIR/internal-unstable.rs:54:22 + --> $DIR/internal-unstable.rs:56:22 | LL | println!("{:?}", internal_unstable::unstable()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -38,7 +38,7 @@ = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: use of unstable library feature `function` - --> $DIR/internal-unstable.rs:56:10 + --> $DIR/internal-unstable.rs:58:10 | LL | bar!(internal_unstable::unstable()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -47,7 +47,7 @@ = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: use of unstable library feature `function` - --> $DIR/internal-unstable.rs:18:9 + --> $DIR/internal-unstable.rs:20:9 | LL | internal_unstable::unstable(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -59,6 +59,25 @@ = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date = note: this error originates in the macro `foo` which comes from the expansion of the macro `bar` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 7 previous errors +warning: `#[allow_internal_unstable]` attribute cannot be used on struct fields + --> $DIR/internal-unstable.rs:10:5 + | +LL | #[allow_internal_unstable] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[allow_internal_unstable]` can be applied to functions and macro defs + = note: requested on the command line with `-W unused-attributes` + +warning: `#[allow_internal_unstable]` attribute cannot be used on match arms + --> $DIR/internal-unstable.rs:61:9 + | +LL | #[allow_internal_unstable] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[allow_internal_unstable]` can be applied to functions and macro defs + +error: aborting due to 7 previous errors; 2 warnings emitted For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/issues/issue-73112.rs b/tests/ui/issues/issue-73112.rs deleted file mode 100644 index 89075b7..0000000 --- a/tests/ui/issues/issue-73112.rs +++ /dev/null
@@ -1,13 +0,0 @@ -//@ aux-build:issue-73112.rs - -extern crate issue_73112; - -fn main() { - use issue_73112::PageTable; - - #[repr(C, packed)] - struct SomeStruct { - //~^ ERROR packed type cannot transitively contain a `#[repr(align)]` type [E0588] - page_table: PageTable, - } -}
diff --git a/tests/ui/issues/issue-72278.rs b/tests/ui/lifetimes/late-bound-lifetime-arguments-warning-72278.rs similarity index 72% rename from tests/ui/issues/issue-72278.rs rename to tests/ui/lifetimes/late-bound-lifetime-arguments-warning-72278.rs index 2a9cd94..81e4d3e 100644 --- a/tests/ui/issues/issue-72278.rs +++ b/tests/ui/lifetimes/late-bound-lifetime-arguments-warning-72278.rs
@@ -1,3 +1,5 @@ +// https://github.com/rust-lang/rust/issues/72278 +// and https://github.com/rust-lang/rust/issues/42868 //@ run-pass #![allow(unused)]
diff --git a/tests/ui/issues/issue-72278.stderr b/tests/ui/lifetimes/late-bound-lifetime-arguments-warning-72278.stderr similarity index 90% rename from tests/ui/issues/issue-72278.stderr rename to tests/ui/lifetimes/late-bound-lifetime-arguments-warning-72278.stderr index 91efada..cffdf0d 100644 --- a/tests/ui/issues/issue-72278.stderr +++ b/tests/ui/lifetimes/late-bound-lifetime-arguments-warning-72278.stderr
@@ -1,5 +1,5 @@ warning: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present - --> $DIR/issue-72278.rs:14:14 + --> $DIR/late-bound-lifetime-arguments-warning-72278.rs:16:14 | LL | fn func<'a, U>(&'a self) -> U { | -- the late bound lifetime parameter is introduced here
diff --git a/tests/ui/link-native-libs/issue-43925.rs b/tests/ui/link-native-libs/issue-43925.rs index e3ce713..09248db 100644 --- a/tests/ui/link-native-libs/issue-43925.rs +++ b/tests/ui/link-native-libs/issue-43925.rs
@@ -1,6 +1,6 @@ #[link(name = "foo", cfg("rlib"))] //~^ ERROR link cfg is unstable -//~| ERROR `cfg` predicate key must be an identifier +//~| ERROR malformed `link` attribute input extern "C" {} fn main() {}
diff --git a/tests/ui/link-native-libs/issue-43925.stderr b/tests/ui/link-native-libs/issue-43925.stderr index 82d2042..68a0205 100644 --- a/tests/ui/link-native-libs/issue-43925.stderr +++ b/tests/ui/link-native-libs/issue-43925.stderr
@@ -7,12 +7,32 @@ = help: add `#![feature(link_cfg)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: `cfg` predicate key must be an identifier - --> $DIR/issue-43925.rs:1:26 +error[E0539]: malformed `link` attribute input + --> $DIR/issue-43925.rs:1:1 | LL | #[link(name = "foo", cfg("rlib"))] - | ^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^------^^^ + | | + | expected a valid identifier here + | + = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute> +help: try changing it to one of the following valid forms of the attribute + | +LL - #[link(name = "foo", cfg("rlib"))] +LL + #[link(name = "...")] + | +LL - #[link(name = "foo", cfg("rlib"))] +LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")] + | +LL - #[link(name = "foo", cfg("rlib"))] +LL + #[link(name = "...", kind = "dylib|static|...")] + | +LL - #[link(name = "foo", cfg("rlib"))] +LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")] + | + = and 1 other candidate error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0658`. +Some errors have detailed explanations: E0539, E0658. +For more information about an error, try `rustc --explain E0539`.
diff --git a/tests/ui/link-native-libs/link-attr-validation-late.rs b/tests/ui/link-native-libs/link-attr-validation-late.rs index d2947b5..c24acca 100644 --- a/tests/ui/link-native-libs/link-attr-validation-late.rs +++ b/tests/ui/link-native-libs/link-attr-validation-late.rs
@@ -22,7 +22,7 @@ #[link(name = "...", modifiers())] //~ ERROR malformed `link` attribute input #[link(name = "...", cfg)] //~ ERROR malformed `link` attribute input #[link(name = "...", cfg = "literal")] //~ ERROR malformed `link` attribute input -#[link(name = "...", cfg("literal"))] //~ ERROR `cfg` predicate key must be an identifier +#[link(name = "...", cfg("literal"))] //~ ERROR malformed `link` attribute input #[link(name = "...", wasm_import_module)] //~ ERROR malformed `link` attribute input #[link(name = "...", wasm_import_module())] //~ ERROR malformed `link` attribute input extern "C" {}
diff --git a/tests/ui/link-native-libs/link-attr-validation-late.stderr b/tests/ui/link-native-libs/link-attr-validation-late.stderr index 834dca0..106b7ce 100644 --- a/tests/ui/link-native-libs/link-attr-validation-late.stderr +++ b/tests/ui/link-native-libs/link-attr-validation-late.stderr
@@ -367,11 +367,30 @@ | = and 1 other candidate -error: `cfg` predicate key must be an identifier - --> $DIR/link-attr-validation-late.rs:25:26 +error[E0539]: malformed `link` attribute input + --> $DIR/link-attr-validation-late.rs:25:1 | LL | #[link(name = "...", cfg("literal"))] - | ^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^---------^^^ + | | + | expected a valid identifier here + | + = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute> +help: try changing it to one of the following valid forms of the attribute + | +LL - #[link(name = "...", cfg("literal"))] +LL + #[link(name = "...")] + | +LL - #[link(name = "...", cfg("literal"))] +LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")] + | +LL - #[link(name = "...", cfg("literal"))] +LL + #[link(name = "...", kind = "dylib|static|...")] + | +LL - #[link(name = "...", cfg("literal"))] +LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")] + | + = and 1 other candidate error[E0539]: malformed `link` attribute input --> $DIR/link-attr-validation-late.rs:26:1
diff --git a/tests/ui/lint/empty-lint-attributes.rs b/tests/ui/lint/empty-lint-attributes.rs index 0193345e..4f550ea 100644 --- a/tests/ui/lint/empty-lint-attributes.rs +++ b/tests/ui/lint/empty-lint-attributes.rs
@@ -3,13 +3,13 @@ // Empty (and reason-only) lint attributes are legal—although we may want to // lint them in the future (Issue #55112). -#![allow()] -#![warn(reason = "observationalism")] +#![allow()] //~ WARN unused attribute +#![warn(reason = "observationalism")] //~ WARN unused attribute -#[forbid()] +#[forbid()] //~ WARN unused attribute fn devoir() {} -#[deny(reason = "ultion")] +#[deny(reason = "ultion")] //~ WARN unused attribute fn waldgrave() {} fn main() {}
diff --git a/tests/ui/lint/empty-lint-attributes.stderr b/tests/ui/lint/empty-lint-attributes.stderr new file mode 100644 index 0000000..5bf8ae1 --- /dev/null +++ b/tests/ui/lint/empty-lint-attributes.stderr
@@ -0,0 +1,35 @@ +warning: unused attribute + --> $DIR/empty-lint-attributes.rs:9:1 + | +LL | #[forbid()] + | ^^^^^^^^^^^ help: remove this attribute + | + = note: attribute `forbid` with an empty list has no effect + = note: requested on the command line with `-W unused-attributes` + +warning: unused attribute + --> $DIR/empty-lint-attributes.rs:12:1 + | +LL | #[deny(reason = "ultion")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | + = note: attribute `deny` without any lints has no effect + +warning: unused attribute + --> $DIR/empty-lint-attributes.rs:6:1 + | +LL | #![allow()] + | ^^^^^^^^^^^ help: remove this attribute + | + = note: attribute `allow` with an empty list has no effect + +warning: unused attribute + --> $DIR/empty-lint-attributes.rs:7:1 + | +LL | #![warn(reason = "observationalism")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | + = note: attribute `warn` without any lints has no effect + +warning: 4 warnings emitted +
diff --git a/tests/ui/lint/fn_must_use.rs b/tests/ui/lint/fn_must_use.rs index be18ffe..b0f7a12 100644 --- a/tests/ui/lint/fn_must_use.rs +++ b/tests/ui/lint/fn_must_use.rs
@@ -39,6 +39,8 @@ impl Replaceable for MyStruct { // method won't work; the attribute should be on the method signature in // the trait's definition. #[must_use] + //~^ WARN attribute cannot be used on trait methods in impl blocks + //~| WARN previously accepted fn replace(&mut self, substitute: usize) -> usize { let previously = self.n; self.n = substitute;
diff --git a/tests/ui/lint/fn_must_use.stderr b/tests/ui/lint/fn_must_use.stderr index e88c1a9..0e8da87 100644 --- a/tests/ui/lint/fn_must_use.stderr +++ b/tests/ui/lint/fn_must_use.stderr
@@ -1,5 +1,15 @@ +warning: `#[must_use]` attribute cannot be used on trait methods in impl blocks + --> $DIR/fn_must_use.rs:41:5 + | +LL | #[must_use] + | ^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[must_use]` can be applied to data types, foreign functions, functions, inherent methods, provided trait methods, required trait methods, traits, and unions + = note: requested on the command line with `-W unused-attributes` + warning: unused return value of `need_to_use_this_value` that must be used - --> $DIR/fn_must_use.rs:55:5 + --> $DIR/fn_must_use.rs:57:5 | LL | need_to_use_this_value(); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -16,7 +26,7 @@ | +++++++ warning: unused return value of `MyStruct::need_to_use_this_method_value` that must be used - --> $DIR/fn_must_use.rs:60:5 + --> $DIR/fn_must_use.rs:62:5 | LL | m.need_to_use_this_method_value(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -27,7 +37,7 @@ | +++++++ warning: unused return value of `EvenNature::is_even` that must be used - --> $DIR/fn_must_use.rs:61:5 + --> $DIR/fn_must_use.rs:63:5 | LL | m.is_even(); // trait method! | ^^^^^^^^^^^ @@ -39,7 +49,7 @@ | +++++++ warning: unused return value of `MyStruct::need_to_use_this_associated_function_value` that must be used - --> $DIR/fn_must_use.rs:64:5 + --> $DIR/fn_must_use.rs:66:5 | LL | MyStruct::need_to_use_this_associated_function_value(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -50,7 +60,7 @@ | +++++++ warning: unused return value of `std::cmp::PartialEq::eq` that must be used - --> $DIR/fn_must_use.rs:70:5 + --> $DIR/fn_must_use.rs:72:5 | LL | 2.eq(&3); | ^^^^^^^^ @@ -61,7 +71,7 @@ | +++++++ warning: unused return value of `std::cmp::PartialEq::eq` that must be used - --> $DIR/fn_must_use.rs:71:5 + --> $DIR/fn_must_use.rs:73:5 | LL | m.eq(&n); | ^^^^^^^^ @@ -72,7 +82,7 @@ | +++++++ warning: unused comparison that must be used - --> $DIR/fn_must_use.rs:74:5 + --> $DIR/fn_must_use.rs:76:5 | LL | 2 == 3; | ^^^^^^ the comparison produces a value @@ -83,7 +93,7 @@ | +++++++ warning: unused comparison that must be used - --> $DIR/fn_must_use.rs:75:5 + --> $DIR/fn_must_use.rs:77:5 | LL | m == n; | ^^^^^^ the comparison produces a value @@ -93,5 +103,5 @@ LL | let _ = m == n; | +++++++ -warning: 8 warnings emitted +warning: 9 warnings emitted
diff --git a/tests/ui/lint/forbid-error-capped.rs b/tests/ui/lint/forbid-error-capped.rs index f505979..e458ddf 100644 --- a/tests/ui/lint/forbid-error-capped.rs +++ b/tests/ui/lint/forbid-error-capped.rs
@@ -6,6 +6,8 @@ #![forbid(warnings)] #![allow(unused)] +//~^ WARN allow(unused) incompatible with previous forbid +//~| WARN previously accepted #[allow(unused)] mod bar {
diff --git a/tests/ui/lint/forbid-error-capped.stderr b/tests/ui/lint/forbid-error-capped.stderr new file mode 100644 index 0000000..479e7b9 --- /dev/null +++ b/tests/ui/lint/forbid-error-capped.stderr
@@ -0,0 +1,27 @@ +warning: allow(unused) incompatible with previous forbid + --> $DIR/forbid-error-capped.rs:8:10 + | +LL | #![forbid(warnings)] + | -------- `forbid` level set here +LL | #![allow(unused)] + | ^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670> + = note: `#[warn(forbidden_lint_groups)]` (part of `#[warn(future_incompatible)]`) on by default + +warning: 1 warning emitted + +Future incompatibility report: Future breakage diagnostic: +warning: allow(unused) incompatible with previous forbid + --> $DIR/forbid-error-capped.rs:8:10 + | +LL | #![forbid(warnings)] + | -------- `forbid` level set here +LL | #![allow(unused)] + | ^^^^^^ overruled by previous forbid + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670> + = note: `#[warn(forbidden_lint_groups)]` (part of `#[warn(future_incompatible)]`) on by default +
diff --git a/tests/ui/lint/rfc-2383-lint-reason/expect_lint_from_macro.rs b/tests/ui/lint/rfc-2383-lint-reason/expect_lint_from_macro.rs index 549f031..c93c94a 100644 --- a/tests/ui/lint/rfc-2383-lint-reason/expect_lint_from_macro.rs +++ b/tests/ui/lint/rfc-2383-lint-reason/expect_lint_from_macro.rs
@@ -23,7 +23,7 @@ pub fn check_expect_on_item() { pub fn check_expect_on_macro() { // This should be fulfilled by the macro - #[expect(unused_variables)] + #[expect(unused_variables)] //~ WARN unused attribute trigger_unused_variables_macro!(); // FIXME: Lint attributes currently don't work directly on macros, and
diff --git a/tests/ui/lint/rfc-2383-lint-reason/expect_lint_from_macro.stderr b/tests/ui/lint/rfc-2383-lint-reason/expect_lint_from_macro.stderr index b09270d..f0ee27a 100644 --- a/tests/ui/lint/rfc-2383-lint-reason/expect_lint_from_macro.stderr +++ b/tests/ui/lint/rfc-2383-lint-reason/expect_lint_from_macro.stderr
@@ -1,3 +1,16 @@ +warning: unused attribute `expect` + --> $DIR/expect_lint_from_macro.rs:26:5 + | +LL | #[expect(unused_variables)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the built-in attribute `expect` will be ignored, since it's applied to the macro invocation `trigger_unused_variables_macro` + --> $DIR/expect_lint_from_macro.rs:27:5 + | +LL | trigger_unused_variables_macro!(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: requested on the command line with `-W unused-attributes` + warning: unused variable: `x` --> $DIR/expect_lint_from_macro.rs:7:13 | @@ -41,5 +54,5 @@ | --------------------------------- in this macro invocation = note: this warning originates in the macro `trigger_unused_variables_macro` (in Nightly builds, run with -Z macro-backtrace for more info) -warning: 2 warnings emitted +warning: 3 warnings emitted
diff --git a/tests/ui/lint/semicolon-in-expressions-from-macros/semicolon-in-expressions-from-macros.rs b/tests/ui/lint/semicolon-in-expressions-from-macros/semicolon-in-expressions-from-macros.rs index 33efdb3..28c2a2c 100644 --- a/tests/ui/lint/semicolon-in-expressions-from-macros/semicolon-in-expressions-from-macros.rs +++ b/tests/ui/lint/semicolon-in-expressions-from-macros/semicolon-in-expressions-from-macros.rs
@@ -48,4 +48,5 @@ fn inner() { // This `#[allow]` does not work, since the attribute gets dropped // when we expand the macro let _ = #[allow(semicolon_in_expressions_from_macros)] foo!(allow_does_not_work); + //~^ WARN unused attribute }
diff --git a/tests/ui/lint/semicolon-in-expressions-from-macros/semicolon-in-expressions-from-macros.stderr b/tests/ui/lint/semicolon-in-expressions-from-macros/semicolon-in-expressions-from-macros.stderr index ea72ef8..0f3a5d7 100644 --- a/tests/ui/lint/semicolon-in-expressions-from-macros/semicolon-in-expressions-from-macros.stderr +++ b/tests/ui/lint/semicolon-in-expressions-from-macros/semicolon-in-expressions-from-macros.stderr
@@ -31,6 +31,19 @@ = note: for more information, see issue #79813 <https://github.com/rust-lang/rust/issues/79813> = note: this warning originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) +warning: unused attribute `allow` + --> $DIR/semicolon-in-expressions-from-macros.rs:50:13 + | +LL | let _ = #[allow(semicolon_in_expressions_from_macros)] foo!(allow_does_not_work); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the built-in attribute `allow` will be ignored, since it's applied to the macro invocation `foo` + --> $DIR/semicolon-in-expressions-from-macros.rs:50:60 + | +LL | let _ = #[allow(semicolon_in_expressions_from_macros)] foo!(allow_does_not_work); + | ^^^ + = note: requested on the command line with `-W unused-attributes` + warning: trailing semicolon in macro used in expression position --> $DIR/semicolon-in-expressions-from-macros.rs:9:13 | @@ -44,7 +57,7 @@ = note: for more information, see issue #79813 <https://github.com/rust-lang/rust/issues/79813> = note: this warning originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) -warning: 3 warnings emitted +warning: 4 warnings emitted Future incompatibility report: Future breakage diagnostic: warning: trailing semicolon in macro used in expression position
diff --git a/tests/ui/lint/unused/auxiliary/must_use_result_unit_uninhabited_extern_crate.rs b/tests/ui/lint/unused/auxiliary/must_use_result_unit_uninhabited_extern_crate.rs new file mode 100644 index 0000000..a193dfa --- /dev/null +++ b/tests/ui/lint/unused/auxiliary/must_use_result_unit_uninhabited_extern_crate.rs
@@ -0,0 +1,4 @@ +pub enum MyUninhabited {} + +#[non_exhaustive] +pub enum MyUninhabitedNonexhaustive {}
diff --git a/tests/ui/lint/unused/must_use-result-unit-uninhabited.rs b/tests/ui/lint/unused/must_use-result-unit-uninhabited.rs new file mode 100644 index 0000000..8f63e4a --- /dev/null +++ b/tests/ui/lint/unused/must_use-result-unit-uninhabited.rs
@@ -0,0 +1,101 @@ +//@ edition: 2024 +//@ aux-crate:dep=must_use_result_unit_uninhabited_extern_crate.rs + +#![deny(unused_must_use)] +#![feature(never_type)] + +use core::ops::{ControlFlow, ControlFlow::Continue}; +use dep::{MyUninhabited, MyUninhabitedNonexhaustive}; + +fn result_unit_unit() -> Result<(), ()> { + Ok(()) +} + +fn result_unit_infallible() -> Result<(), core::convert::Infallible> { + Ok(()) +} + +fn result_unit_never() -> Result<(), !> { + Ok(()) +} + +fn result_unit_myuninhabited() -> Result<(), MyUninhabited> { + Ok(()) +} + +fn result_unit_myuninhabited_nonexhaustive() -> Result<(), MyUninhabitedNonexhaustive> { + Ok(()) +} + +trait AssocType { + type Error; +} + +struct S1; +impl AssocType for S1 { + type Error = !; +} + +struct S2; +impl AssocType for S2 { + type Error = (); +} + +fn result_unit_assoctype<AT: AssocType>(_: AT) -> Result<(), AT::Error> { + Ok(()) +} + +trait UsesAssocType { + type Error; + fn method_use_assoc_type(&self) -> Result<(), Self::Error>; +} + +impl UsesAssocType for S1 { + type Error = !; + fn method_use_assoc_type(&self) -> Result<(), Self::Error> { + Ok(()) + } +} + +impl UsesAssocType for S2 { + type Error = (); + fn method_use_assoc_type(&self) -> Result<(), Self::Error> { + Err(()) + } +} + +fn controlflow_unit() -> ControlFlow<()> { + Continue(()) +} + +fn controlflow_infallible_unit() -> ControlFlow<core::convert::Infallible, ()> { + Continue(()) +} + +fn controlflow_never() -> ControlFlow<!> { + Continue(()) +} + +fn main() { + result_unit_unit(); //~ ERROR: unused `Result` that must be used + result_unit_infallible(); + result_unit_never(); + result_unit_myuninhabited(); + result_unit_myuninhabited_nonexhaustive(); //~ ERROR: unused `Result` that must be used + result_unit_assoctype(S1); + result_unit_assoctype(S2); //~ ERROR: unused `Result` that must be used + S1.method_use_assoc_type(); + S2.method_use_assoc_type(); //~ ERROR: unused `Result` that must be used + + controlflow_unit(); //~ ERROR: unused `ControlFlow` that must be used + controlflow_infallible_unit(); + controlflow_never(); +} + +trait AssocTypeBeforeMonomorphisation { + type Error; + fn generate(&self) -> Result<(), Self::Error>; + fn process(&self) { + self.generate(); //~ ERROR: unused `Result` that must be used + } +}
diff --git a/tests/ui/lint/unused/must_use-result-unit-uninhabited.stderr b/tests/ui/lint/unused/must_use-result-unit-uninhabited.stderr new file mode 100644 index 0000000..31d6f6b --- /dev/null +++ b/tests/ui/lint/unused/must_use-result-unit-uninhabited.stderr
@@ -0,0 +1,78 @@ +error: unused `Result` that must be used + --> $DIR/must_use-result-unit-uninhabited.rs:80:5 + | +LL | result_unit_unit(); + | ^^^^^^^^^^^^^^^^^^ + | + = note: this `Result` may be an `Err` variant, which should be handled +note: the lint level is defined here + --> $DIR/must_use-result-unit-uninhabited.rs:4:9 + | +LL | #![deny(unused_must_use)] + | ^^^^^^^^^^^^^^^ +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = result_unit_unit(); + | +++++++ + +error: unused `Result` that must be used + --> $DIR/must_use-result-unit-uninhabited.rs:84:5 + | +LL | result_unit_myuninhabited_nonexhaustive(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this `Result` may be an `Err` variant, which should be handled +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = result_unit_myuninhabited_nonexhaustive(); + | +++++++ + +error: unused `Result` that must be used + --> $DIR/must_use-result-unit-uninhabited.rs:86:5 + | +LL | result_unit_assoctype(S2); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this `Result` may be an `Err` variant, which should be handled +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = result_unit_assoctype(S2); + | +++++++ + +error: unused `Result` that must be used + --> $DIR/must_use-result-unit-uninhabited.rs:88:5 + | +LL | S2.method_use_assoc_type(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this `Result` may be an `Err` variant, which should be handled +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = S2.method_use_assoc_type(); + | +++++++ + +error: unused `ControlFlow` that must be used + --> $DIR/must_use-result-unit-uninhabited.rs:90:5 + | +LL | controlflow_unit(); + | ^^^^^^^^^^^^^^^^^^ + | +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = controlflow_unit(); + | +++++++ + +error: unused `Result` that must be used + --> $DIR/must_use-result-unit-uninhabited.rs:99:9 + | +LL | self.generate(); + | ^^^^^^^^^^^^^^^ + | + = note: this `Result` may be an `Err` variant, which should be handled +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = self.generate(); + | +++++++ + +error: aborting due to 6 previous errors +
diff --git a/tests/ui/malformed/malformed-regressions.rs b/tests/ui/malformed/malformed-regressions.rs index 407920c..c0f8c0d 100644 --- a/tests/ui/malformed/malformed-regressions.rs +++ b/tests/ui/malformed/malformed-regressions.rs
@@ -5,6 +5,8 @@ #[inline = ""] //~ ERROR valid forms for the attribute are //~^ WARN this was previously accepted #[link] //~ ERROR malformed +//~^ WARN attribute should be applied to an `extern` block with non-Rust ABI +//~| WARN previously accepted #[link = ""] //~ ERROR malformed fn main() {}
diff --git a/tests/ui/malformed/malformed-regressions.stderr b/tests/ui/malformed/malformed-regressions.stderr index 850bcb6c..1812079 100644 --- a/tests/ui/malformed/malformed-regressions.stderr +++ b/tests/ui/malformed/malformed-regressions.stderr
@@ -29,7 +29,7 @@ = and 1 other candidate error[E0539]: malformed `link` attribute input - --> $DIR/malformed-regressions.rs:8:1 + --> $DIR/malformed-regressions.rs:10:1 | LL | #[link = ""] | ^^^^^^^^^^^^ expected this to be a list @@ -51,6 +51,18 @@ | = and 1 other candidate +warning: attribute should be applied to an `extern` block with non-Rust ABI + --> $DIR/malformed-regressions.rs:7:1 + | +LL | #[link] + | ^^^^^^^ +... +LL | fn main() {} + | ------------ not an `extern` block + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: requested on the command line with `-W unused-attributes` + error: valid forms for the attribute are `#[ignore = "reason"]` and `#[ignore]` --> $DIR/malformed-regressions.rs:3:1 | @@ -69,7 +81,7 @@ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571> -error: aborting due to 5 previous errors +error: aborting due to 5 previous errors; 1 warning emitted For more information about this error, try `rustc --explain E0539`. Future incompatibility report: Future breakage diagnostic:
diff --git a/tests/ui/malformed/malformed-special-attrs.stderr b/tests/ui/malformed/malformed-special-attrs.stderr index b6a1a6b..91e5939 100644 --- a/tests/ui/malformed/malformed-special-attrs.stderr +++ b/tests/ui/malformed/malformed-special-attrs.stderr
@@ -1,27 +1,24 @@ -error: malformed `cfg_attr` attribute input +error[E0539]: malformed `cfg_attr` attribute input --> $DIR/malformed-special-attrs.rs:1:1 | LL | #[cfg_attr] | ^^^^^^^^^^^ + | | + | expected this to be a list + | help: must be of the form: `#[cfg_attr(predicate, attr1, attr2, ...)]` | = note: for more information, visit <https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg_attr-attribute> -help: missing condition and attribute - | -LL | #[cfg_attr(condition, attribute, other_attribute, ...)] - | ++++++++++++++++++++++++++++++++++++++++++++ -error: malformed `cfg_attr` attribute input +error[E0539]: malformed `cfg_attr` attribute input --> $DIR/malformed-special-attrs.rs:4:1 | LL | #[cfg_attr = ""] | ^^^^^^^^^^^^^^^^ + | | + | expected this to be a list + | help: must be of the form: `#[cfg_attr(predicate, attr1, attr2, ...)]` | = note: for more information, visit <https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg_attr-attribute> -help: missing condition and attribute - | -LL - #[cfg_attr = ""] -LL + #[cfg_attr(condition, attribute, other_attribute, ...)] - | error: malformed `derive` attribute input --> $DIR/malformed-special-attrs.rs:7:1 @@ -37,3 +34,4 @@ error: aborting due to 4 previous errors +For more information about this error, try `rustc --explain E0539`.
diff --git a/tests/ui/mir/mir-cfg-unpretty-check-81918.rs b/tests/ui/mir/mir-cfg-unpretty-no-panic-81918.rs similarity index 100% rename from tests/ui/mir/mir-cfg-unpretty-check-81918.rs rename to tests/ui/mir/mir-cfg-unpretty-no-panic-81918.rs
diff --git a/tests/ui/never_type/defaulted-never-note.fallback.stderr b/tests/ui/never_type/defaulted-never-note.fallback.stderr index 7526a39..299f463 100644 --- a/tests/ui/never_type/defaulted-never-note.fallback.stderr +++ b/tests/ui/never_type/defaulted-never-note.fallback.stderr
@@ -1,5 +1,5 @@ error[E0277]: the trait bound `!: ImplementedForUnitButNotNever` is not satisfied - --> $DIR/defaulted-never-note.rs:32:9 + --> $DIR/defaulted-never-note.rs:31:9 | LL | foo(_x); | --- ^^ the trait `ImplementedForUnitButNotNever` is not implemented for `!` @@ -10,7 +10,7 @@ = note: this error might have been caused by changes to Rust's type-inference algorithm (see issue #48950 <https://github.com/rust-lang/rust/issues/48950> for more information) = help: you might have intended to use the type `()` here instead note: required by a bound in `foo` - --> $DIR/defaulted-never-note.rs:25:11 + --> $DIR/defaulted-never-note.rs:26:11 | LL | fn foo<T: ImplementedForUnitButNotNever>(_t: T) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `foo`
diff --git a/tests/ui/never_type/defaulted-never-note.nofallback.stderr b/tests/ui/never_type/defaulted-never-note.nofallback.stderr index b82bea0..05e5f6d 100644 --- a/tests/ui/never_type/defaulted-never-note.nofallback.stderr +++ b/tests/ui/never_type/defaulted-never-note.nofallback.stderr
@@ -1,41 +1,16 @@ -warning: this function depends on never type fallback being `()` - --> $DIR/defaulted-never-note.rs:28:1 - | -LL | fn smeg() { - | ^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! - = note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/never-type-fallback.html> - = help: specify the types explicitly -note: in edition 2024, the requirement `!: ImplementedForUnitButNotNever` will fail - --> $DIR/defaulted-never-note.rs:32:9 - | -LL | foo(_x); - | ^^ - = note: `#[warn(dependency_on_unit_never_type_fallback)]` (part of `#[warn(rust_2024_compatibility)]`) on by default -help: use `()` annotations to avoid fallback changes - | -LL | let _x: () = return; - | ++++ - -warning: 1 warning emitted - Future incompatibility report: Future breakage diagnostic: warning: this function depends on never type fallback being `()` - --> $DIR/defaulted-never-note.rs:28:1 + --> $DIR/defaulted-never-note.rs:29:1 | LL | fn smeg() { | ^^^^^^^^^ | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! - = note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/never-type-fallback.html> = help: specify the types explicitly note: in edition 2024, the requirement `!: ImplementedForUnitButNotNever` will fail - --> $DIR/defaulted-never-note.rs:32:9 + --> $DIR/defaulted-never-note.rs:31:9 | LL | foo(_x); | ^^ - = note: `#[warn(dependency_on_unit_never_type_fallback)]` (part of `#[warn(rust_2024_compatibility)]`) on by default help: use `()` annotations to avoid fallback changes | LL | let _x: () = return;
diff --git a/tests/ui/never_type/defaulted-never-note.rs b/tests/ui/never_type/defaulted-never-note.rs index 71f0d9f..8164d00 100644 --- a/tests/ui/never_type/defaulted-never-note.rs +++ b/tests/ui/never_type/defaulted-never-note.rs
@@ -7,6 +7,7 @@ #![cfg_attr(fallback, feature(never_type, never_type_fallback))] #![allow(unused)] +#![expect(dependency_on_unit_never_type_fallback)] trait Deserialize: Sized { fn deserialize() -> Result<Self, String>; @@ -23,19 +24,17 @@ trait ImplementedForUnitButNotNever {} impl ImplementedForUnitButNotNever for () {} fn foo<T: ImplementedForUnitButNotNever>(_t: T) {} -//[fallback]~^ NOTE required by this bound in `foo` -//[fallback]~| NOTE required by a bound in `foo` +//[fallback]~^ note: required by this bound in `foo` +//[fallback]~| note: required by a bound in `foo` fn smeg() { - //[nofallback]~^ warn: this function depends on never type fallback being `()` - //[nofallback]~| warn: this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! let _x = return; foo(_x); - //[fallback]~^ ERROR the trait bound - //[fallback]~| NOTE the trait `ImplementedForUnitButNotNever` is not implemented - //[fallback]~| HELP trait `ImplementedForUnitButNotNever` is implemented for `()` - //[fallback]~| NOTE this error might have been caused - //[fallback]~| NOTE required by a bound introduced by this call - //[fallback]~| HELP you might have intended to use the type `()` + //[fallback]~^ error: the trait bound + //[fallback]~| note: the trait `ImplementedForUnitButNotNever` is not implemented + //[fallback]~| help: trait `ImplementedForUnitButNotNever` is implemented for `()` + //[fallback]~| note: this error might have been caused + //[fallback]~| note: required by a bound introduced by this call + //[fallback]~| help: you might have intended to use the type `()` } fn main() {
diff --git a/tests/ui/never_type/dependency-on-fallback-to-unit.rs b/tests/ui/never_type/dependency-on-fallback-to-unit.rs index fad4c7c..9cbce58 100644 --- a/tests/ui/never_type/dependency-on-fallback-to-unit.rs +++ b/tests/ui/never_type/dependency-on-fallback-to-unit.rs
@@ -1,12 +1,10 @@ -//@ check-pass - fn main() { def(); _ = question_mark(); } fn def() { - //~^ warn: this function depends on never type fallback being `()` + //~^ error: this function depends on never type fallback being `()` //~| warn: this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! match true { false => <_>::default(), @@ -17,7 +15,7 @@ fn def() { // <https://github.com/rust-lang/rust/issues/51125> // <https://github.com/rust-lang/rust/issues/39216> fn question_mark() -> Result<(), ()> { - //~^ warn: this function depends on never type fallback being `()` + //~^ error: this function depends on never type fallback being `()` //~| warn: this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! deserialize()?; Ok(())
diff --git a/tests/ui/never_type/dependency-on-fallback-to-unit.stderr b/tests/ui/never_type/dependency-on-fallback-to-unit.stderr index 6394bab..0b8d965 100644 --- a/tests/ui/never_type/dependency-on-fallback-to-unit.stderr +++ b/tests/ui/never_type/dependency-on-fallback-to-unit.stderr
@@ -1,5 +1,5 @@ -warning: this function depends on never type fallback being `()` - --> $DIR/dependency-on-fallback-to-unit.rs:8:1 +error: this function depends on never type fallback being `()` + --> $DIR/dependency-on-fallback-to-unit.rs:6:1 | LL | fn def() { | ^^^^^^^^ @@ -8,19 +8,19 @@ = note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/never-type-fallback.html> = help: specify the types explicitly note: in edition 2024, the requirement `!: Default` will fail - --> $DIR/dependency-on-fallback-to-unit.rs:12:19 + --> $DIR/dependency-on-fallback-to-unit.rs:10:19 | LL | false => <_>::default(), | ^ - = note: `#[warn(dependency_on_unit_never_type_fallback)]` (part of `#[warn(rust_2024_compatibility)]`) on by default + = note: `#[deny(dependency_on_unit_never_type_fallback)]` (part of `#[deny(rust_2024_compatibility)]`) on by default help: use `()` annotations to avoid fallback changes | LL - false => <_>::default(), LL + false => <()>::default(), | -warning: this function depends on never type fallback being `()` - --> $DIR/dependency-on-fallback-to-unit.rs:19:1 +error: this function depends on never type fallback being `()` + --> $DIR/dependency-on-fallback-to-unit.rs:17:1 | LL | fn question_mark() -> Result<(), ()> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -29,7 +29,7 @@ = note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/never-type-fallback.html> = help: specify the types explicitly note: in edition 2024, the requirement `!: Default` will fail - --> $DIR/dependency-on-fallback-to-unit.rs:22:5 + --> $DIR/dependency-on-fallback-to-unit.rs:20:5 | LL | deserialize()?; | ^^^^^^^^^^^^^ @@ -38,11 +38,11 @@ LL | deserialize::<()>()?; | ++++++ -warning: 2 warnings emitted +error: aborting due to 2 previous errors Future incompatibility report: Future breakage diagnostic: -warning: this function depends on never type fallback being `()` - --> $DIR/dependency-on-fallback-to-unit.rs:8:1 +error: this function depends on never type fallback being `()` + --> $DIR/dependency-on-fallback-to-unit.rs:6:1 | LL | fn def() { | ^^^^^^^^ @@ -51,11 +51,11 @@ = note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/never-type-fallback.html> = help: specify the types explicitly note: in edition 2024, the requirement `!: Default` will fail - --> $DIR/dependency-on-fallback-to-unit.rs:12:19 + --> $DIR/dependency-on-fallback-to-unit.rs:10:19 | LL | false => <_>::default(), | ^ - = note: `#[warn(dependency_on_unit_never_type_fallback)]` (part of `#[warn(rust_2024_compatibility)]`) on by default + = note: `#[deny(dependency_on_unit_never_type_fallback)]` (part of `#[deny(rust_2024_compatibility)]`) on by default help: use `()` annotations to avoid fallback changes | LL - false => <_>::default(), @@ -63,8 +63,8 @@ | Future breakage diagnostic: -warning: this function depends on never type fallback being `()` - --> $DIR/dependency-on-fallback-to-unit.rs:19:1 +error: this function depends on never type fallback being `()` + --> $DIR/dependency-on-fallback-to-unit.rs:17:1 | LL | fn question_mark() -> Result<(), ()> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -73,11 +73,11 @@ = note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/never-type-fallback.html> = help: specify the types explicitly note: in edition 2024, the requirement `!: Default` will fail - --> $DIR/dependency-on-fallback-to-unit.rs:22:5 + --> $DIR/dependency-on-fallback-to-unit.rs:20:5 | LL | deserialize()?; | ^^^^^^^^^^^^^ - = note: `#[warn(dependency_on_unit_never_type_fallback)]` (part of `#[warn(rust_2024_compatibility)]`) on by default + = note: `#[deny(dependency_on_unit_never_type_fallback)]` (part of `#[deny(rust_2024_compatibility)]`) on by default help: use `()` annotations to avoid fallback changes | LL | deserialize::<()>()?;
diff --git a/tests/ui/never_type/diverging-fallback-control-flow.nofallback.stderr b/tests/ui/never_type/diverging-fallback-control-flow.nofallback.stderr index 7f857c8..49930e0 100644 --- a/tests/ui/never_type/diverging-fallback-control-flow.nofallback.stderr +++ b/tests/ui/never_type/diverging-fallback-control-flow.nofallback.stderr
@@ -1,60 +1,16 @@ -warning: this function depends on never type fallback being `()` - --> $DIR/diverging-fallback-control-flow.rs:30:1 - | -LL | fn assignment() { - | ^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! - = note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/never-type-fallback.html> - = help: specify the types explicitly -note: in edition 2024, the requirement `!: UnitDefault` will fail - --> $DIR/diverging-fallback-control-flow.rs:36:13 - | -LL | x = UnitDefault::default(); - | ^^^^^^^^^^^^^^^^^^^^^^ - = note: `#[warn(dependency_on_unit_never_type_fallback)]` (part of `#[warn(rust_2024_compatibility)]`) on by default -help: use `()` annotations to avoid fallback changes - | -LL | let x: (); - | ++++ - -warning: this function depends on never type fallback being `()` - --> $DIR/diverging-fallback-control-flow.rs:42:1 - | -LL | fn assignment_rev() { - | ^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! - = note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/never-type-fallback.html> - = help: specify the types explicitly -note: in edition 2024, the requirement `!: UnitDefault` will fail - --> $DIR/diverging-fallback-control-flow.rs:50:13 - | -LL | x = UnitDefault::default(); - | ^^^^^^^^^^^^^^^^^^^^^^ -help: use `()` annotations to avoid fallback changes - | -LL | let x: (); - | ++++ - -warning: 2 warnings emitted - Future incompatibility report: Future breakage diagnostic: warning: this function depends on never type fallback being `()` - --> $DIR/diverging-fallback-control-flow.rs:30:1 + --> $DIR/diverging-fallback-control-flow.rs:32:1 | LL | fn assignment() { | ^^^^^^^^^^^^^^^ | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! - = note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/never-type-fallback.html> = help: specify the types explicitly note: in edition 2024, the requirement `!: UnitDefault` will fail --> $DIR/diverging-fallback-control-flow.rs:36:13 | LL | x = UnitDefault::default(); | ^^^^^^^^^^^^^^^^^^^^^^ - = note: `#[warn(dependency_on_unit_never_type_fallback)]` (part of `#[warn(rust_2024_compatibility)]`) on by default help: use `()` annotations to avoid fallback changes | LL | let x: (); @@ -67,15 +23,12 @@ LL | fn assignment_rev() { | ^^^^^^^^^^^^^^^^^^^ | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! - = note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/never-type-fallback.html> = help: specify the types explicitly note: in edition 2024, the requirement `!: UnitDefault` will fail - --> $DIR/diverging-fallback-control-flow.rs:50:13 + --> $DIR/diverging-fallback-control-flow.rs:48:13 | LL | x = UnitDefault::default(); | ^^^^^^^^^^^^^^^^^^^^^^ - = note: `#[warn(dependency_on_unit_never_type_fallback)]` (part of `#[warn(rust_2024_compatibility)]`) on by default help: use `()` annotations to avoid fallback changes | LL | let x: ();
diff --git a/tests/ui/never_type/diverging-fallback-control-flow.rs b/tests/ui/never_type/diverging-fallback-control-flow.rs index 6476671..c00c97e 100644 --- a/tests/ui/never_type/diverging-fallback-control-flow.rs +++ b/tests/ui/never_type/diverging-fallback-control-flow.rs
@@ -1,10 +1,12 @@ //@ revisions: nofallback fallback -//@ run-pass +//@ check-pass #![allow(dead_code)] #![allow(unused_assignments)] #![allow(unused_variables)] #![allow(unreachable_code)] +#![cfg_attr(nofallback, expect(dependency_on_unit_never_type_fallback))] + // Test various cases where we permit an unconstrained variable // to fallback based on control-flow. In all of these cases, // the type variable winds up being the target of both a `!` coercion @@ -28,8 +30,6 @@ fn default() -> () { } fn assignment() { - //[nofallback]~^ warn: this function depends on never type fallback being `()` - //[nofallback]~| warn: this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! let x; if true { @@ -40,8 +40,6 @@ fn assignment() { } fn assignment_rev() { - //[nofallback]~^ warn: this function depends on never type fallback being `()` - //[nofallback]~| warn: this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! let x; if true {
diff --git a/tests/ui/never_type/diverging-fallback-no-leak.fallback.stderr b/tests/ui/never_type/diverging-fallback-no-leak.fallback.stderr index 610c687..56bff12 100644 --- a/tests/ui/never_type/diverging-fallback-no-leak.fallback.stderr +++ b/tests/ui/never_type/diverging-fallback-no-leak.fallback.stderr
@@ -1,5 +1,5 @@ error[E0277]: the trait bound `!: Test` is not satisfied - --> $DIR/diverging-fallback-no-leak.rs:20:23 + --> $DIR/diverging-fallback-no-leak.rs:18:23 | LL | unconstrained_arg(return); | ----------------- ^^^^^^ the trait `Test` is not implemented for `!` @@ -12,7 +12,7 @@ = note: this error might have been caused by changes to Rust's type-inference algorithm (see issue #48950 <https://github.com/rust-lang/rust/issues/48950> for more information) = help: you might have intended to use the type `()` here instead note: required by a bound in `unconstrained_arg` - --> $DIR/diverging-fallback-no-leak.rs:12:25 + --> $DIR/diverging-fallback-no-leak.rs:13:25 | LL | fn unconstrained_arg<T: Test>(_: T) {} | ^^^^ required by this bound in `unconstrained_arg`
diff --git a/tests/ui/never_type/diverging-fallback-no-leak.nofallback.stderr b/tests/ui/never_type/diverging-fallback-no-leak.nofallback.stderr index d4bb5f9..8423261 100644 --- a/tests/ui/never_type/diverging-fallback-no-leak.nofallback.stderr +++ b/tests/ui/never_type/diverging-fallback-no-leak.nofallback.stderr
@@ -1,41 +1,16 @@ -warning: this function depends on never type fallback being `()` - --> $DIR/diverging-fallback-no-leak.rs:14:1 - | -LL | fn main() { - | ^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! - = note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/never-type-fallback.html> - = help: specify the types explicitly -note: in edition 2024, the requirement `!: Test` will fail - --> $DIR/diverging-fallback-no-leak.rs:20:23 - | -LL | unconstrained_arg(return); - | ^^^^^^ - = note: `#[warn(dependency_on_unit_never_type_fallback)]` (part of `#[warn(rust_2024_compatibility)]`) on by default -help: use `()` annotations to avoid fallback changes - | -LL | unconstrained_arg::<()>(return); - | ++++++ - -warning: 1 warning emitted - Future incompatibility report: Future breakage diagnostic: warning: this function depends on never type fallback being `()` - --> $DIR/diverging-fallback-no-leak.rs:14:1 + --> $DIR/diverging-fallback-no-leak.rs:15:1 | LL | fn main() { | ^^^^^^^^^ | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! - = note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/never-type-fallback.html> = help: specify the types explicitly note: in edition 2024, the requirement `!: Test` will fail - --> $DIR/diverging-fallback-no-leak.rs:20:23 + --> $DIR/diverging-fallback-no-leak.rs:18:23 | LL | unconstrained_arg(return); | ^^^^^^ - = note: `#[warn(dependency_on_unit_never_type_fallback)]` (part of `#[warn(rust_2024_compatibility)]`) on by default help: use `()` annotations to avoid fallback changes | LL | unconstrained_arg::<()>(return);
diff --git a/tests/ui/never_type/diverging-fallback-no-leak.rs b/tests/ui/never_type/diverging-fallback-no-leak.rs index 75ca491..b00802d 100644 --- a/tests/ui/never_type/diverging-fallback-no-leak.rs +++ b/tests/ui/never_type/diverging-fallback-no-leak.rs
@@ -2,6 +2,7 @@ //@[nofallback] check-pass #![cfg_attr(fallback, feature(never_type, never_type_fallback))] +#![cfg_attr(nofallback, expect(dependency_on_unit_never_type_fallback))] fn make_unit() {} @@ -12,11 +13,8 @@ impl Test for () {} fn unconstrained_arg<T: Test>(_: T) {} fn main() { - //[nofallback]~^ warn: this function depends on never type fallback being `()` - //[nofallback]~| warn: this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! - // Here the type variable falls back to `!`, // and hence we get a type error. unconstrained_arg(return); - //[fallback]~^ ERROR trait bound `!: Test` is not satisfied + //[fallback]~^ error: trait bound `!: Test` is not satisfied }
diff --git a/tests/ui/never_type/diverging-fallback-unconstrained-return.nofallback.stderr b/tests/ui/never_type/diverging-fallback-unconstrained-return.nofallback.stderr index a706ad8..1a6ea52 100644 --- a/tests/ui/never_type/diverging-fallback-unconstrained-return.nofallback.stderr +++ b/tests/ui/never_type/diverging-fallback-unconstrained-return.nofallback.stderr
@@ -1,4 +1,4 @@ -warning: this function depends on never type fallback being `()` +error: this function depends on never type fallback being `()` --> $DIR/diverging-fallback-unconstrained-return.rs:28:1 | LL | fn main() { @@ -12,16 +12,16 @@ | LL | let _ = if true { unconstrained_return() } else { panic!() }; | ^^^^^^^^^^^^^^^^^^^^^^ - = note: `#[warn(dependency_on_unit_never_type_fallback)]` (part of `#[warn(rust_2024_compatibility)]`) on by default + = note: `#[deny(dependency_on_unit_never_type_fallback)]` (part of `#[deny(rust_2024_compatibility)]`) on by default help: use `()` annotations to avoid fallback changes | LL | let _: () = if true { unconstrained_return() } else { panic!() }; | ++++ -warning: 1 warning emitted +error: aborting due to 1 previous error Future incompatibility report: Future breakage diagnostic: -warning: this function depends on never type fallback being `()` +error: this function depends on never type fallback being `()` --> $DIR/diverging-fallback-unconstrained-return.rs:28:1 | LL | fn main() { @@ -35,7 +35,7 @@ | LL | let _ = if true { unconstrained_return() } else { panic!() }; | ^^^^^^^^^^^^^^^^^^^^^^ - = note: `#[warn(dependency_on_unit_never_type_fallback)]` (part of `#[warn(rust_2024_compatibility)]`) on by default + = note: `#[deny(dependency_on_unit_never_type_fallback)]` (part of `#[deny(rust_2024_compatibility)]`) on by default help: use `()` annotations to avoid fallback changes | LL | let _: () = if true { unconstrained_return() } else { panic!() };
diff --git a/tests/ui/never_type/diverging-fallback-unconstrained-return.rs b/tests/ui/never_type/diverging-fallback-unconstrained-return.rs index fdea3a9..6204291 100644 --- a/tests/ui/never_type/diverging-fallback-unconstrained-return.rs +++ b/tests/ui/never_type/diverging-fallback-unconstrained-return.rs
@@ -4,7 +4,7 @@ // in the objc crate, where changing the fallback from `!` to `()` // resulted in unsoundness. // -//@ check-pass +//@[fallback] check-pass //@ revisions: nofallback fallback @@ -26,7 +26,7 @@ fn unconstrained_return<T: UnitReturn>() -> T { } fn main() { - //[nofallback]~^ warn: this function depends on never type fallback being `()` + //[nofallback]~^ error: this function depends on never type fallback being `()` //[nofallback]~| warn: this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! // In Ye Olde Days, the `T` parameter of `unconstrained_return`
diff --git a/tests/ui/never_type/dont-suggest-turbofish-from-expansion.rs b/tests/ui/never_type/dont-suggest-turbofish-from-expansion.rs index 9a53358..7bae1dd 100644 --- a/tests/ui/never_type/dont-suggest-turbofish-from-expansion.rs +++ b/tests/ui/never_type/dont-suggest-turbofish-from-expansion.rs
@@ -1,5 +1,3 @@ -#![deny(dependency_on_unit_never_type_fallback)] - fn create_ok_default<C>() -> Result<C, ()> where C: Default,
diff --git a/tests/ui/never_type/dont-suggest-turbofish-from-expansion.stderr b/tests/ui/never_type/dont-suggest-turbofish-from-expansion.stderr index d2d108e..9795acf 100644 --- a/tests/ui/never_type/dont-suggest-turbofish-from-expansion.stderr +++ b/tests/ui/never_type/dont-suggest-turbofish-from-expansion.stderr
@@ -1,5 +1,5 @@ error: this function depends on never type fallback being `()` - --> $DIR/dont-suggest-turbofish-from-expansion.rs:10:1 + --> $DIR/dont-suggest-turbofish-from-expansion.rs:8:1 | LL | fn main() -> Result<(), ()> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -8,15 +8,11 @@ = note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/never-type-fallback.html> = help: specify the types explicitly note: in edition 2024, the requirement `!: Default` will fail - --> $DIR/dont-suggest-turbofish-from-expansion.rs:14:23 + --> $DIR/dont-suggest-turbofish-from-expansion.rs:12:23 | LL | let created = create_ok_default()?; | ^^^^^^^^^^^^^^^^^^^ -note: the lint level is defined here - --> $DIR/dont-suggest-turbofish-from-expansion.rs:1:9 - | -LL | #![deny(dependency_on_unit_never_type_fallback)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: `#[deny(dependency_on_unit_never_type_fallback)]` (part of `#[deny(rust_2024_compatibility)]`) on by default help: use `()` annotations to avoid fallback changes | LL | let created: () = create_ok_default()?; @@ -26,7 +22,7 @@ Future incompatibility report: Future breakage diagnostic: error: this function depends on never type fallback being `()` - --> $DIR/dont-suggest-turbofish-from-expansion.rs:10:1 + --> $DIR/dont-suggest-turbofish-from-expansion.rs:8:1 | LL | fn main() -> Result<(), ()> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -35,15 +31,11 @@ = note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/never-type-fallback.html> = help: specify the types explicitly note: in edition 2024, the requirement `!: Default` will fail - --> $DIR/dont-suggest-turbofish-from-expansion.rs:14:23 + --> $DIR/dont-suggest-turbofish-from-expansion.rs:12:23 | LL | let created = create_ok_default()?; | ^^^^^^^^^^^^^^^^^^^ -note: the lint level is defined here - --> $DIR/dont-suggest-turbofish-from-expansion.rs:1:9 - | -LL | #![deny(dependency_on_unit_never_type_fallback)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: `#[deny(dependency_on_unit_never_type_fallback)]` (part of `#[deny(rust_2024_compatibility)]`) on by default help: use `()` annotations to avoid fallback changes | LL | let created: () = create_ok_default()?;
diff --git a/tests/ui/never_type/fallback-closure-ret.nofallback.stderr b/tests/ui/never_type/fallback-closure-ret.nofallback.stderr index 39b40cd..3c5c248 100644 --- a/tests/ui/never_type/fallback-closure-ret.nofallback.stderr +++ b/tests/ui/never_type/fallback-closure-ret.nofallback.stderr
@@ -1,41 +1,16 @@ -warning: this function depends on never type fallback being `()` - --> $DIR/fallback-closure-ret.rs:21:1 - | -LL | fn main() { - | ^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! - = note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/never-type-fallback.html> - = help: specify the types explicitly -note: in edition 2024, the requirement `!: Bar` will fail - --> $DIR/fallback-closure-ret.rs:24:5 - | -LL | foo(|| panic!()); - | ^^^^^^^^^^^^^^^^ - = note: `#[warn(dependency_on_unit_never_type_fallback)]` (part of `#[warn(rust_2024_compatibility)]`) on by default -help: use `()` annotations to avoid fallback changes - | -LL | foo::<()>(|| panic!()); - | ++++++ - -warning: 1 warning emitted - Future incompatibility report: Future breakage diagnostic: warning: this function depends on never type fallback being `()` - --> $DIR/fallback-closure-ret.rs:21:1 + --> $DIR/fallback-closure-ret.rs:22:1 | LL | fn main() { | ^^^^^^^^^ | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! - = note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/never-type-fallback.html> = help: specify the types explicitly note: in edition 2024, the requirement `!: Bar` will fail - --> $DIR/fallback-closure-ret.rs:24:5 + --> $DIR/fallback-closure-ret.rs:23:5 | LL | foo(|| panic!()); | ^^^^^^^^^^^^^^^^ - = note: `#[warn(dependency_on_unit_never_type_fallback)]` (part of `#[warn(rust_2024_compatibility)]`) on by default help: use `()` annotations to avoid fallback changes | LL | foo::<()>(|| panic!());
diff --git a/tests/ui/never_type/fallback-closure-ret.rs b/tests/ui/never_type/fallback-closure-ret.rs index f142335..0d92b39 100644 --- a/tests/ui/never_type/fallback-closure-ret.rs +++ b/tests/ui/never_type/fallback-closure-ret.rs
@@ -11,6 +11,7 @@ //@ check-pass #![cfg_attr(fallback, feature(never_type_fallback))] +#![cfg_attr(nofallback, expect(dependency_on_unit_never_type_fallback))] trait Bar {} impl Bar for () {} @@ -19,7 +20,5 @@ impl Bar for u32 {} fn foo<R: Bar>(_: impl Fn() -> R) {} fn main() { - //[nofallback]~^ warn: this function depends on never type fallback being `()` - //[nofallback]~| warn: this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! foo(|| panic!()); }
diff --git a/tests/ui/never_type/impl_trait_fallback.rs b/tests/ui/never_type/impl_trait_fallback.rs index bd4caeb..dafbd5a 100644 --- a/tests/ui/never_type/impl_trait_fallback.rs +++ b/tests/ui/never_type/impl_trait_fallback.rs
@@ -1,4 +1,5 @@ //@ check-pass +#![expect(dependency_on_unit_never_type_fallback)] fn main() {} @@ -6,7 +7,5 @@ trait T {} impl T for () {} fn should_ret_unit() -> impl T { - //~^ warn: this function depends on never type fallback being `()` - //~| warn: this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! panic!() }
diff --git a/tests/ui/never_type/impl_trait_fallback.stderr b/tests/ui/never_type/impl_trait_fallback.stderr index 7d8624b..bdf6df9 100644 --- a/tests/ui/never_type/impl_trait_fallback.stderr +++ b/tests/ui/never_type/impl_trait_fallback.stderr
@@ -1,35 +1,14 @@ -warning: this function depends on never type fallback being `()` - --> $DIR/impl_trait_fallback.rs:8:1 - | -LL | fn should_ret_unit() -> impl T { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! - = note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/never-type-fallback.html> - = help: specify the types explicitly -note: in edition 2024, the requirement `!: T` will fail - --> $DIR/impl_trait_fallback.rs:8:25 - | -LL | fn should_ret_unit() -> impl T { - | ^^^^^^ - = note: `#[warn(dependency_on_unit_never_type_fallback)]` (part of `#[warn(rust_2024_compatibility)]`) on by default - -warning: 1 warning emitted - Future incompatibility report: Future breakage diagnostic: warning: this function depends on never type fallback being `()` - --> $DIR/impl_trait_fallback.rs:8:1 + --> $DIR/impl_trait_fallback.rs:9:1 | LL | fn should_ret_unit() -> impl T { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions! - = note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/never-type-fallback.html> = help: specify the types explicitly note: in edition 2024, the requirement `!: T` will fail - --> $DIR/impl_trait_fallback.rs:8:25 + --> $DIR/impl_trait_fallback.rs:9:25 | LL | fn should_ret_unit() -> impl T { | ^^^^^^ - = note: `#[warn(dependency_on_unit_never_type_fallback)]` (part of `#[warn(rust_2024_compatibility)]`) on by default
diff --git a/tests/ui/never_type/lint-breaking-2024-assign-underscore.fixed b/tests/ui/never_type/lint-breaking-2024-assign-underscore.fixed index f9f2b59..b235c6e 100644 --- a/tests/ui/never_type/lint-breaking-2024-assign-underscore.fixed +++ b/tests/ui/never_type/lint-breaking-2024-assign-underscore.fixed
@@ -1,7 +1,5 @@ //@ run-rustfix - #![allow(unused)] -#![deny(dependency_on_unit_never_type_fallback)] fn foo<T: Default>() -> Result<T, ()> { Err(())
diff --git a/tests/ui/never_type/lint-breaking-2024-assign-underscore.rs b/tests/ui/never_type/lint-breaking-2024-assign-underscore.rs index 8a2f3d3..14d8850 100644 --- a/tests/ui/never_type/lint-breaking-2024-assign-underscore.rs +++ b/tests/ui/never_type/lint-breaking-2024-assign-underscore.rs
@@ -1,7 +1,5 @@ //@ run-rustfix - #![allow(unused)] -#![deny(dependency_on_unit_never_type_fallback)] fn foo<T: Default>() -> Result<T, ()> { Err(())
diff --git a/tests/ui/never_type/lint-breaking-2024-assign-underscore.stderr b/tests/ui/never_type/lint-breaking-2024-assign-underscore.stderr index 6a85b99..96749de 100644 --- a/tests/ui/never_type/lint-breaking-2024-assign-underscore.stderr +++ b/tests/ui/never_type/lint-breaking-2024-assign-underscore.stderr
@@ -1,5 +1,5 @@ error: this function depends on never type fallback being `()` - --> $DIR/lint-breaking-2024-assign-underscore.rs:10:1 + --> $DIR/lint-breaking-2024-assign-underscore.rs:8:1 | LL | fn test() -> Result<(), ()> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -8,15 +8,11 @@ = note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/never-type-fallback.html> = help: specify the types explicitly note: in edition 2024, the requirement `!: Default` will fail - --> $DIR/lint-breaking-2024-assign-underscore.rs:13:9 + --> $DIR/lint-breaking-2024-assign-underscore.rs:11:9 | LL | _ = foo()?; | ^^^^^ -note: the lint level is defined here - --> $DIR/lint-breaking-2024-assign-underscore.rs:4:9 - | -LL | #![deny(dependency_on_unit_never_type_fallback)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: `#[deny(dependency_on_unit_never_type_fallback)]` (part of `#[deny(rust_2024_compatibility)]`) on by default help: use `()` annotations to avoid fallback changes | LL | _ = foo::<()>()?; @@ -26,7 +22,7 @@ Future incompatibility report: Future breakage diagnostic: error: this function depends on never type fallback being `()` - --> $DIR/lint-breaking-2024-assign-underscore.rs:10:1 + --> $DIR/lint-breaking-2024-assign-underscore.rs:8:1 | LL | fn test() -> Result<(), ()> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -35,15 +31,11 @@ = note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/never-type-fallback.html> = help: specify the types explicitly note: in edition 2024, the requirement `!: Default` will fail - --> $DIR/lint-breaking-2024-assign-underscore.rs:13:9 + --> $DIR/lint-breaking-2024-assign-underscore.rs:11:9 | LL | _ = foo()?; | ^^^^^ -note: the lint level is defined here - --> $DIR/lint-breaking-2024-assign-underscore.rs:4:9 - | -LL | #![deny(dependency_on_unit_never_type_fallback)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: `#[deny(dependency_on_unit_never_type_fallback)]` (part of `#[deny(rust_2024_compatibility)]`) on by default help: use `()` annotations to avoid fallback changes | LL | _ = foo::<()>()?;
diff --git a/tests/ui/never_type/lint-never-type-fallback-flowing-into-unsafe.e2015.stderr b/tests/ui/never_type/lint-never-type-fallback-flowing-into-unsafe.e2015.stderr index f9d0a89..84e143b 100644 --- a/tests/ui/never_type/lint-never-type-fallback-flowing-into-unsafe.e2015.stderr +++ b/tests/ui/never_type/lint-never-type-fallback-flowing-into-unsafe.e2015.stderr
@@ -1,5 +1,5 @@ -warning: never type fallback affects this call to an `unsafe` function - --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:12:18 +error: never type fallback affects this call to an `unsafe` function + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:10:18 | LL | unsafe { mem::zeroed() } | ^^^^^^^^^^^^^ @@ -7,14 +7,14 @@ = warning: this changes meaning in Rust 2024 and in a future release in all editions! = note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/never-type-fallback.html> = help: specify the type explicitly - = note: `#[warn(never_type_fallback_flowing_into_unsafe)]` (part of `#[warn(rust_2024_compatibility)]`) on by default + = note: `#[deny(never_type_fallback_flowing_into_unsafe)]` (part of `#[deny(rust_2024_compatibility)]`) on by default help: use `()` annotations to avoid fallback changes | LL | unsafe { mem::zeroed::<()>() } | ++++++ -warning: never type fallback affects this call to an `unsafe` function - --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:29:13 +error: never type fallback affects this call to an `unsafe` function + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:27:13 | LL | core::mem::transmute(Zst) | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -27,8 +27,8 @@ LL | core::mem::transmute::<_, ()>(Zst) | +++++++++ -warning: never type fallback affects this union access - --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:46:18 +error: never type fallback affects this union access + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:44:18 | LL | unsafe { Union { a: () }.b } | ^^^^^^^^^^^^^^^^^ @@ -37,8 +37,8 @@ = note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/never-type-fallback.html> = help: specify the type explicitly -warning: never type fallback affects this raw pointer dereference - --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:57:18 +error: never type fallback affects this raw pointer dereference + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:55:18 | LL | unsafe { *ptr::from_ref(&()).cast() } | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -51,8 +51,8 @@ LL | unsafe { *ptr::from_ref(&()).cast::<()>() } | ++++++ -warning: never type fallback affects this call to an `unsafe` function - --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:78:18 +error: never type fallback affects this call to an `unsafe` function + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:76:18 | LL | unsafe { internally_create(x) } | ^^^^^^^^^^^^^^^^^^^^ @@ -65,8 +65,8 @@ LL | unsafe { internally_create::<()>(x) } | ++++++ -warning: never type fallback affects this call to an `unsafe` function - --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:96:18 +error: never type fallback affects this call to an `unsafe` function + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:94:18 | LL | unsafe { zeroed() } | ^^^^^^^^ @@ -79,8 +79,8 @@ LL | let zeroed = mem::zeroed::<()>; | ++++++ -warning: never type fallback affects this `unsafe` function - --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:91:22 +error: never type fallback affects this `unsafe` function + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:89:22 | LL | let zeroed = mem::zeroed; | ^^^^^^^^^^^ @@ -93,8 +93,8 @@ LL | let zeroed = mem::zeroed::<()>; | ++++++ -warning: never type fallback affects this `unsafe` function - --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:114:17 +error: never type fallback affects this `unsafe` function + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:112:17 | LL | let f = internally_create; | ^^^^^^^^^^^^^^^^^ @@ -107,8 +107,8 @@ LL | let f = internally_create::<()>; | ++++++ -warning: never type fallback affects this call to an `unsafe` method - --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:139:13 +error: never type fallback affects this call to an `unsafe` method + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:137:13 | LL | S(marker::PhantomData).create_out_of_thin_air() | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -117,8 +117,8 @@ = note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/never-type-fallback.html> = help: specify the type explicitly -warning: never type fallback affects this call to an `unsafe` function - --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:157:19 +error: never type fallback affects this call to an `unsafe` function + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:155:19 | LL | match send_message::<_ /* ?0 */>() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -129,13 +129,13 @@ = warning: this changes meaning in Rust 2024 and in a future release in all editions! = note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/never-type-fallback.html> = help: specify the type explicitly - = note: this warning originates in the macro `msg_send` (in Nightly builds, run with -Z macro-backtrace for more info) + = note: this error originates in the macro `msg_send` (in Nightly builds, run with -Z macro-backtrace for more info) -warning: 10 warnings emitted +error: aborting due to 10 previous errors Future incompatibility report: Future breakage diagnostic: -warning: never type fallback affects this call to an `unsafe` function - --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:12:18 +error: never type fallback affects this call to an `unsafe` function + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:10:18 | LL | unsafe { mem::zeroed() } | ^^^^^^^^^^^^^ @@ -143,15 +143,15 @@ = warning: this changes meaning in Rust 2024 and in a future release in all editions! = note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/never-type-fallback.html> = help: specify the type explicitly - = note: `#[warn(never_type_fallback_flowing_into_unsafe)]` (part of `#[warn(rust_2024_compatibility)]`) on by default + = note: `#[deny(never_type_fallback_flowing_into_unsafe)]` (part of `#[deny(rust_2024_compatibility)]`) on by default help: use `()` annotations to avoid fallback changes | LL | unsafe { mem::zeroed::<()>() } | ++++++ Future breakage diagnostic: -warning: never type fallback affects this call to an `unsafe` function - --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:29:13 +error: never type fallback affects this call to an `unsafe` function + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:27:13 | LL | core::mem::transmute(Zst) | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -159,15 +159,15 @@ = warning: this changes meaning in Rust 2024 and in a future release in all editions! = note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/never-type-fallback.html> = help: specify the type explicitly - = note: `#[warn(never_type_fallback_flowing_into_unsafe)]` (part of `#[warn(rust_2024_compatibility)]`) on by default + = note: `#[deny(never_type_fallback_flowing_into_unsafe)]` (part of `#[deny(rust_2024_compatibility)]`) on by default help: use `()` annotations to avoid fallback changes | LL | core::mem::transmute::<_, ()>(Zst) | +++++++++ Future breakage diagnostic: -warning: never type fallback affects this union access - --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:46:18 +error: never type fallback affects this union access + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:44:18 | LL | unsafe { Union { a: () }.b } | ^^^^^^^^^^^^^^^^^ @@ -175,11 +175,11 @@ = warning: this changes meaning in Rust 2024 and in a future release in all editions! = note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/never-type-fallback.html> = help: specify the type explicitly - = note: `#[warn(never_type_fallback_flowing_into_unsafe)]` (part of `#[warn(rust_2024_compatibility)]`) on by default + = note: `#[deny(never_type_fallback_flowing_into_unsafe)]` (part of `#[deny(rust_2024_compatibility)]`) on by default Future breakage diagnostic: -warning: never type fallback affects this raw pointer dereference - --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:57:18 +error: never type fallback affects this raw pointer dereference + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:55:18 | LL | unsafe { *ptr::from_ref(&()).cast() } | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -187,15 +187,15 @@ = warning: this changes meaning in Rust 2024 and in a future release in all editions! = note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/never-type-fallback.html> = help: specify the type explicitly - = note: `#[warn(never_type_fallback_flowing_into_unsafe)]` (part of `#[warn(rust_2024_compatibility)]`) on by default + = note: `#[deny(never_type_fallback_flowing_into_unsafe)]` (part of `#[deny(rust_2024_compatibility)]`) on by default help: use `()` annotations to avoid fallback changes | LL | unsafe { *ptr::from_ref(&()).cast::<()>() } | ++++++ Future breakage diagnostic: -warning: never type fallback affects this call to an `unsafe` function - --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:78:18 +error: never type fallback affects this call to an `unsafe` function + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:76:18 | LL | unsafe { internally_create(x) } | ^^^^^^^^^^^^^^^^^^^^ @@ -203,15 +203,15 @@ = warning: this changes meaning in Rust 2024 and in a future release in all editions! = note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/never-type-fallback.html> = help: specify the type explicitly - = note: `#[warn(never_type_fallback_flowing_into_unsafe)]` (part of `#[warn(rust_2024_compatibility)]`) on by default + = note: `#[deny(never_type_fallback_flowing_into_unsafe)]` (part of `#[deny(rust_2024_compatibility)]`) on by default help: use `()` annotations to avoid fallback changes | LL | unsafe { internally_create::<()>(x) } | ++++++ Future breakage diagnostic: -warning: never type fallback affects this call to an `unsafe` function - --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:96:18 +error: never type fallback affects this call to an `unsafe` function + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:94:18 | LL | unsafe { zeroed() } | ^^^^^^^^ @@ -219,15 +219,15 @@ = warning: this changes meaning in Rust 2024 and in a future release in all editions! = note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/never-type-fallback.html> = help: specify the type explicitly - = note: `#[warn(never_type_fallback_flowing_into_unsafe)]` (part of `#[warn(rust_2024_compatibility)]`) on by default + = note: `#[deny(never_type_fallback_flowing_into_unsafe)]` (part of `#[deny(rust_2024_compatibility)]`) on by default help: use `()` annotations to avoid fallback changes | LL | let zeroed = mem::zeroed::<()>; | ++++++ Future breakage diagnostic: -warning: never type fallback affects this `unsafe` function - --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:91:22 +error: never type fallback affects this `unsafe` function + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:89:22 | LL | let zeroed = mem::zeroed; | ^^^^^^^^^^^ @@ -235,15 +235,15 @@ = warning: this changes meaning in Rust 2024 and in a future release in all editions! = note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/never-type-fallback.html> = help: specify the type explicitly - = note: `#[warn(never_type_fallback_flowing_into_unsafe)]` (part of `#[warn(rust_2024_compatibility)]`) on by default + = note: `#[deny(never_type_fallback_flowing_into_unsafe)]` (part of `#[deny(rust_2024_compatibility)]`) on by default help: use `()` annotations to avoid fallback changes | LL | let zeroed = mem::zeroed::<()>; | ++++++ Future breakage diagnostic: -warning: never type fallback affects this `unsafe` function - --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:114:17 +error: never type fallback affects this `unsafe` function + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:112:17 | LL | let f = internally_create; | ^^^^^^^^^^^^^^^^^ @@ -251,15 +251,15 @@ = warning: this changes meaning in Rust 2024 and in a future release in all editions! = note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/never-type-fallback.html> = help: specify the type explicitly - = note: `#[warn(never_type_fallback_flowing_into_unsafe)]` (part of `#[warn(rust_2024_compatibility)]`) on by default + = note: `#[deny(never_type_fallback_flowing_into_unsafe)]` (part of `#[deny(rust_2024_compatibility)]`) on by default help: use `()` annotations to avoid fallback changes | LL | let f = internally_create::<()>; | ++++++ Future breakage diagnostic: -warning: never type fallback affects this call to an `unsafe` method - --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:139:13 +error: never type fallback affects this call to an `unsafe` method + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:137:13 | LL | S(marker::PhantomData).create_out_of_thin_air() | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -267,11 +267,11 @@ = warning: this changes meaning in Rust 2024 and in a future release in all editions! = note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/never-type-fallback.html> = help: specify the type explicitly - = note: `#[warn(never_type_fallback_flowing_into_unsafe)]` (part of `#[warn(rust_2024_compatibility)]`) on by default + = note: `#[deny(never_type_fallback_flowing_into_unsafe)]` (part of `#[deny(rust_2024_compatibility)]`) on by default Future breakage diagnostic: -warning: never type fallback affects this call to an `unsafe` function - --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:157:19 +error: never type fallback affects this call to an `unsafe` function + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:155:19 | LL | match send_message::<_ /* ?0 */>() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -282,6 +282,6 @@ = warning: this changes meaning in Rust 2024 and in a future release in all editions! = note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/never-type-fallback.html> = help: specify the type explicitly - = note: `#[warn(never_type_fallback_flowing_into_unsafe)]` (part of `#[warn(rust_2024_compatibility)]`) on by default - = note: this warning originates in the macro `msg_send` (in Nightly builds, run with -Z macro-backtrace for more info) + = note: `#[deny(never_type_fallback_flowing_into_unsafe)]` (part of `#[deny(rust_2024_compatibility)]`) on by default + = note: this error originates in the macro `msg_send` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/tests/ui/never_type/lint-never-type-fallback-flowing-into-unsafe.e2024.stderr b/tests/ui/never_type/lint-never-type-fallback-flowing-into-unsafe.e2024.stderr index 7205c13..09e4d02 100644 --- a/tests/ui/never_type/lint-never-type-fallback-flowing-into-unsafe.e2024.stderr +++ b/tests/ui/never_type/lint-never-type-fallback-flowing-into-unsafe.e2024.stderr
@@ -1,5 +1,5 @@ error: never type fallback affects this call to an `unsafe` function - --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:12:18 + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:10:18 | LL | unsafe { mem::zeroed() } | ^^^^^^^^^^^^^ @@ -14,7 +14,7 @@ | ++++++ error: never type fallback affects this call to an `unsafe` function - --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:29:13 + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:27:13 | LL | core::mem::transmute(Zst) | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -28,7 +28,7 @@ | +++++++++ error: never type fallback affects this union access - --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:46:18 + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:44:18 | LL | unsafe { Union { a: () }.b } | ^^^^^^^^^^^^^^^^^ @@ -38,7 +38,7 @@ = help: specify the type explicitly error: never type fallback affects this raw pointer dereference - --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:57:18 + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:55:18 | LL | unsafe { *ptr::from_ref(&()).cast() } | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -52,7 +52,7 @@ | ++++++ error: never type fallback affects this call to an `unsafe` function - --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:78:18 + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:76:18 | LL | unsafe { internally_create(x) } | ^^^^^^^^^^^^^^^^^^^^ @@ -66,7 +66,7 @@ | ++++++ error: never type fallback affects this call to an `unsafe` function - --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:96:18 + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:94:18 | LL | unsafe { zeroed() } | ^^^^^^^^ @@ -80,7 +80,7 @@ | ++++++ error: never type fallback affects this `unsafe` function - --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:91:22 + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:89:22 | LL | let zeroed = mem::zeroed; | ^^^^^^^^^^^ @@ -94,7 +94,7 @@ | ++++++ error: never type fallback affects this `unsafe` function - --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:114:17 + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:112:17 | LL | let f = internally_create; | ^^^^^^^^^^^^^^^^^ @@ -108,7 +108,7 @@ | ++++++ error: never type fallback affects this call to an `unsafe` method - --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:139:13 + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:137:13 | LL | S(marker::PhantomData).create_out_of_thin_air() | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -118,7 +118,7 @@ = help: specify the type explicitly error: never type fallback affects this call to an `unsafe` function - --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:157:19 + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:155:19 | LL | match send_message::<_ /* ?0 */>() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -132,7 +132,7 @@ = note: this error originates in the macro `msg_send` (in Nightly builds, run with -Z macro-backtrace for more info) warning: the type `!` does not permit zero-initialization - --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:12:18 + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:10:18 | LL | unsafe { mem::zeroed() } | ^^^^^^^^^^^^^ this code causes undefined behavior when executed @@ -144,7 +144,7 @@ Future incompatibility report: Future breakage diagnostic: error: never type fallback affects this call to an `unsafe` function - --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:12:18 + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:10:18 | LL | unsafe { mem::zeroed() } | ^^^^^^^^^^^^^ @@ -160,7 +160,7 @@ Future breakage diagnostic: error: never type fallback affects this call to an `unsafe` function - --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:29:13 + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:27:13 | LL | core::mem::transmute(Zst) | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -176,7 +176,7 @@ Future breakage diagnostic: error: never type fallback affects this union access - --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:46:18 + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:44:18 | LL | unsafe { Union { a: () }.b } | ^^^^^^^^^^^^^^^^^ @@ -188,7 +188,7 @@ Future breakage diagnostic: error: never type fallback affects this raw pointer dereference - --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:57:18 + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:55:18 | LL | unsafe { *ptr::from_ref(&()).cast() } | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -204,7 +204,7 @@ Future breakage diagnostic: error: never type fallback affects this call to an `unsafe` function - --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:78:18 + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:76:18 | LL | unsafe { internally_create(x) } | ^^^^^^^^^^^^^^^^^^^^ @@ -220,7 +220,7 @@ Future breakage diagnostic: error: never type fallback affects this call to an `unsafe` function - --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:96:18 + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:94:18 | LL | unsafe { zeroed() } | ^^^^^^^^ @@ -236,7 +236,7 @@ Future breakage diagnostic: error: never type fallback affects this `unsafe` function - --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:91:22 + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:89:22 | LL | let zeroed = mem::zeroed; | ^^^^^^^^^^^ @@ -252,7 +252,7 @@ Future breakage diagnostic: error: never type fallback affects this `unsafe` function - --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:114:17 + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:112:17 | LL | let f = internally_create; | ^^^^^^^^^^^^^^^^^ @@ -268,7 +268,7 @@ Future breakage diagnostic: error: never type fallback affects this call to an `unsafe` method - --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:139:13 + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:137:13 | LL | S(marker::PhantomData).create_out_of_thin_air() | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -280,7 +280,7 @@ Future breakage diagnostic: error: never type fallback affects this call to an `unsafe` function - --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:157:19 + --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:155:19 | LL | match send_message::<_ /* ?0 */>() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/never_type/lint-never-type-fallback-flowing-into-unsafe.rs b/tests/ui/never_type/lint-never-type-fallback-flowing-into-unsafe.rs index 97e7a2f..744fff4 100644 --- a/tests/ui/never_type/lint-never-type-fallback-flowing-into-unsafe.rs +++ b/tests/ui/never_type/lint-never-type-fallback-flowing-into-unsafe.rs
@@ -1,6 +1,4 @@ //@ revisions: e2015 e2024 -//@[e2015] check-pass -//@[e2024] check-fail //@[e2024] edition:2024 use std::{marker, mem, ptr}; @@ -10,10 +8,10 @@ fn main() {} fn _zero() { if false { unsafe { mem::zeroed() } - //[e2015]~^ warn: never type fallback affects this call to an `unsafe` function + //[e2015]~^ error: never type fallback affects this call to an `unsafe` function //[e2024]~^^ error: never type fallback affects this call to an `unsafe` function //~| warn: this changes meaning in Rust 2024 and in a future release in all editions! - //[e2024]~| warning: the type `!` does not permit zero-initialization + //[e2024]~| warn: the type `!` does not permit zero-initialization } else { return; }; @@ -27,7 +25,7 @@ fn _trans() { unsafe { struct Zst; core::mem::transmute(Zst) - //[e2015]~^ warn: never type fallback affects this call to an `unsafe` function + //[e2015]~^ error: never type fallback affects this call to an `unsafe` function //[e2024]~^^ error: never type fallback affects this call to an `unsafe` function //~| warn: this changes meaning in Rust 2024 and in a future release in all editions! } @@ -44,7 +42,7 @@ union Union<T: Copy> { } unsafe { Union { a: () }.b } - //[e2015]~^ warn: never type fallback affects this union access + //[e2015]~^ error: never type fallback affects this union access //[e2024]~^^ error: never type fallback affects this union access //~| warn: this changes meaning in Rust 2024 and in a future release in all editions! } else { @@ -55,7 +53,7 @@ union Union<T: Copy> { fn _deref() { if false { unsafe { *ptr::from_ref(&()).cast() } - //[e2015]~^ warn: never type fallback affects this raw pointer dereference + //[e2015]~^ error: never type fallback affects this raw pointer dereference //[e2024]~^^ error: never type fallback affects this raw pointer dereference //~| warn: this changes meaning in Rust 2024 and in a future release in all editions! } else { @@ -76,7 +74,7 @@ unsafe fn internally_create<T>(_: Option<T>) { let x = None; unsafe { internally_create(x) } - //[e2015]~^ warn: never type fallback affects this call to an `unsafe` function + //[e2015]~^ error: never type fallback affects this call to an `unsafe` function //[e2024]~^^ error: never type fallback affects this call to an `unsafe` function //~| warn: this changes meaning in Rust 2024 and in a future release in all editions! @@ -89,12 +87,12 @@ unsafe fn internally_create<T>(_: Option<T>) { fn _stored_function() { if false { let zeroed = mem::zeroed; - //[e2015]~^ warn: never type fallback affects this `unsafe` function + //[e2015]~^ error: never type fallback affects this `unsafe` function //[e2024]~^^ error: never type fallback affects this `unsafe` function //~| warn: this changes meaning in Rust 2024 and in a future release in all editions! unsafe { zeroed() } - //[e2015]~^ warn: never type fallback affects this call to an `unsafe` function + //[e2015]~^ error: never type fallback affects this call to an `unsafe` function //[e2024]~^^ error: never type fallback affects this call to an `unsafe` function //~| warn: this changes meaning in Rust 2024 and in a future release in all editions! } else { @@ -112,7 +110,7 @@ unsafe fn internally_create<T>(_: Option<T>) { let x = None; let f = internally_create; - //[e2015]~^ warn: never type fallback affects this `unsafe` function + //[e2015]~^ error: never type fallback affects this `unsafe` function //[e2024]~^^ error: never type fallback affects this `unsafe` function //~| warn: this changes meaning in Rust 2024 and in a future release in all editions! @@ -137,7 +135,7 @@ unsafe fn create_out_of_thin_air(&self) -> T { if false { unsafe { S(marker::PhantomData).create_out_of_thin_air() - //[e2015]~^ warn: never type fallback affects this call to an `unsafe` method + //[e2015]~^ error: never type fallback affects this call to an `unsafe` method //[e2024]~^^ error: never type fallback affects this call to an `unsafe` method //~| warn: this changes meaning in Rust 2024 and in a future release in all editions! } @@ -155,7 +153,7 @@ pub unsafe fn send_message<R>() -> Result<R, ()> { macro_rules! msg_send { () => { match send_message::<_ /* ?0 */>() { - //[e2015]~^ warn: never type fallback affects this call to an `unsafe` function + //[e2015]~^ error: never type fallback affects this call to an `unsafe` function //[e2024]~^^ error: never type fallback affects this call to an `unsafe` function //~| warn: this changes meaning in Rust 2024 and in a future release in all editions! Ok(x) => x,
diff --git a/tests/ui/parser/inner-attr.rs b/tests/ui/parser/inner-attr.rs index 1b405e2..e66227c 100644 --- a/tests/ui/parser/inner-attr.rs +++ b/tests/ui/parser/inner-attr.rs
@@ -1,4 +1,4 @@ -#[feature(lang_items)] +#[feature(lang_items)] //~ WARN crate-level attribute should be an inner attribute #![recursion_limit="100"] //~ ERROR an inner attribute is not permitted following an outer attribute fn main() {}
diff --git a/tests/ui/parser/inner-attr.stderr b/tests/ui/parser/inner-attr.stderr index 18a82ea..3fb2d60 100644 --- a/tests/ui/parser/inner-attr.stderr +++ b/tests/ui/parser/inner-attr.stderr
@@ -11,5 +11,17 @@ | = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files -error: aborting due to 1 previous error +warning: crate-level attribute should be an inner attribute + --> $DIR/inner-attr.rs:1:1 + | +LL | #[feature(lang_items)] + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = note: requested on the command line with `-W unused-attributes` +help: add a `!` + | +LL | #![feature(lang_items)] + | + + +error: aborting due to 1 previous error; 1 warning emitted
diff --git a/tests/ui/parser/trait-object-trait-parens.stderr b/tests/ui/parser/trait-object-trait-parens.stderr index f498d7d..c43ca23 100644 --- a/tests/ui/parser/trait-object-trait-parens.stderr +++ b/tests/ui/parser/trait-object-trait-parens.stderr
@@ -3,18 +3,24 @@ | LL | let _: Box<(Obj) + (?Sized) + (for<'a> Trait<'a>)>; | ^^^^^^^^ + | + = note: trait object types are not implicitly bounded by `Sized`, so there is nothing to relax error: relaxed bounds are not permitted in trait object types --> $DIR/trait-object-trait-parens.rs:13:16 | LL | let _: Box<?Sized + (for<'a> Trait<'a>) + (Obj)>; | ^^^^^^ + | + = note: trait object types are not implicitly bounded by `Sized`, so there is nothing to relax error: relaxed bounds are not permitted in trait object types --> $DIR/trait-object-trait-parens.rs:18:44 | LL | let _: Box<for<'a> Trait<'a> + (Obj) + (?Sized)>; | ^^^^^^^^ + | + = note: trait object types are not implicitly bounded by `Sized`, so there is nothing to relax warning: trait objects without an explicit `dyn` are deprecated --> $DIR/trait-object-trait-parens.rs:8:16
diff --git a/tests/ui/pin/pin-deref-target-partial-eq-67039.rs b/tests/ui/pin/pin-deref-target-partial-eq-67039.rs new file mode 100644 index 0000000..5419600 --- /dev/null +++ b/tests/ui/pin/pin-deref-target-partial-eq-67039.rs
@@ -0,0 +1,28 @@ +// https://github.com/rust-lang/rust/issues/67039 +// Pin's PartialEq implementation allowed to access the pointer allowing for +// unsoundness by using Rc::get_mut to move value within Rc. +// See https://internals.rust-lang.org/t/unsoundness-in-pin/11311/73 for more details. + +use std::ops::Deref; +use std::pin::Pin; +use std::rc::Rc; + +struct Apple; + +impl Deref for Apple { + type Target = Apple; + fn deref(&self) -> &Apple { + &Apple + } +} + +impl PartialEq<Rc<Apple>> for Apple { + fn eq(&self, _rc: &Rc<Apple>) -> bool { + unreachable!() + } +} + +fn main() { + let _ = Pin::new(Apple) == Rc::pin(Apple); + //~^ ERROR type mismatch resolving +}
diff --git a/tests/ui/pin/pin-deref-target-partial-eq-67039.stderr b/tests/ui/pin/pin-deref-target-partial-eq-67039.stderr new file mode 100644 index 0000000..541656d --- /dev/null +++ b/tests/ui/pin/pin-deref-target-partial-eq-67039.stderr
@@ -0,0 +1,13 @@ +error[E0271]: type mismatch resolving `<Rc<Apple> as Deref>::Target == Rc<Apple>` + --> $DIR/pin-deref-target-partial-eq-67039.rs:26:29 + | +LL | let _ = Pin::new(Apple) == Rc::pin(Apple); + | ^^ expected `Rc<Apple>`, found `Apple` + | + = note: expected struct `Rc<Apple>` + found struct `Apple` + = note: required for `Pin<Apple>` to implement `PartialEq<Pin<Rc<Apple>>>` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0271`.
diff --git a/tests/ui/privacy/inaccessible-fields-pattern-matching-76077.fixed b/tests/ui/privacy/inaccessible-private-fields-76077.fixed similarity index 100% rename from tests/ui/privacy/inaccessible-fields-pattern-matching-76077.fixed rename to tests/ui/privacy/inaccessible-private-fields-76077.fixed
diff --git a/tests/ui/privacy/inaccessible-fields-pattern-matching-76077.rs b/tests/ui/privacy/inaccessible-private-fields-76077.rs similarity index 100% rename from tests/ui/privacy/inaccessible-fields-pattern-matching-76077.rs rename to tests/ui/privacy/inaccessible-private-fields-76077.rs
diff --git a/tests/ui/privacy/inaccessible-fields-pattern-matching-76077.stderr b/tests/ui/privacy/inaccessible-private-fields-76077.stderr similarity index 83% rename from tests/ui/privacy/inaccessible-fields-pattern-matching-76077.stderr rename to tests/ui/privacy/inaccessible-private-fields-76077.stderr index 070fa1a..7b9f495 100644 --- a/tests/ui/privacy/inaccessible-fields-pattern-matching-76077.stderr +++ b/tests/ui/privacy/inaccessible-private-fields-76077.stderr
@@ -1,5 +1,5 @@ error: pattern requires `..` due to inaccessible fields - --> $DIR/inaccessible-fields-pattern-matching-76077.rs:14:9 + --> $DIR/inaccessible-private-fields-76077.rs:14:9 | LL | let foo::Foo {} = foo::Foo::default(); | ^^^^^^^^^^^ @@ -10,7 +10,7 @@ | ++ error: pattern requires `..` due to inaccessible fields - --> $DIR/inaccessible-fields-pattern-matching-76077.rs:17:9 + --> $DIR/inaccessible-private-fields-76077.rs:17:9 | LL | let foo::Bar { visible } = foo::Bar::default(); | ^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/proc-macro/attributes-on-modules-fail.rs b/tests/ui/proc-macro/attributes-on-modules-fail.rs index 80300b4..59da87a 100644 --- a/tests/ui/proc-macro/attributes-on-modules-fail.rs +++ b/tests/ui/proc-macro/attributes-on-modules-fail.rs
@@ -17,11 +17,11 @@ mod m { mod n {} #[empty_attr] -mod module; //~ ERROR non-inline modules in proc macro input are unstable +mod module; //~ ERROR file modules in proc macro input are unstable #[empty_attr] mod outer { - mod inner; //~ ERROR non-inline modules in proc macro input are unstable + mod inner; //~ ERROR file modules in proc macro input are unstable mod inner_inline {} // OK } @@ -30,16 +30,16 @@ mod inner_inline {} // OK struct S { field: [u8; { #[path = "outer/inner.rs"] - mod inner; //~ ERROR non-inline modules in proc macro input are unstable + mod inner; //~ ERROR file modules in proc macro input are unstable mod inner_inline {} // OK 0 - }] + }], } #[identity_attr] fn f() { #[path = "outer/inner.rs"] - mod inner; //~ ERROR non-inline modules in proc macro input are unstable + mod inner; //~ ERROR file modules in proc macro input are unstable mod inner_inline {} // OK }
diff --git a/tests/ui/proc-macro/attributes-on-modules-fail.stderr b/tests/ui/proc-macro/attributes-on-modules-fail.stderr index e69ab78..26b20a3 100644 --- a/tests/ui/proc-macro/attributes-on-modules-fail.stderr +++ b/tests/ui/proc-macro/attributes-on-modules-fail.stderr
@@ -6,7 +6,7 @@ LL | mod n {} | -------- not a `struct`, `enum` or `union` -error[E0658]: non-inline modules in proc macro input are unstable +error[E0658]: file modules in proc macro input are unstable --> $DIR/attributes-on-modules-fail.rs:20:1 | LL | mod module; @@ -16,7 +16,7 @@ = help: add `#![feature(proc_macro_hygiene)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: non-inline modules in proc macro input are unstable +error[E0658]: file modules in proc macro input are unstable --> $DIR/attributes-on-modules-fail.rs:24:5 | LL | mod inner; @@ -26,7 +26,7 @@ = help: add `#![feature(proc_macro_hygiene)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: non-inline modules in proc macro input are unstable +error[E0658]: file modules in proc macro input are unstable --> $DIR/attributes-on-modules-fail.rs:33:9 | LL | mod inner; @@ -36,7 +36,7 @@ = help: add `#![feature(proc_macro_hygiene)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: non-inline modules in proc macro input are unstable +error[E0658]: file modules in proc macro input are unstable --> $DIR/attributes-on-modules-fail.rs:42:5 | LL | mod inner;
diff --git a/tests/ui/proc-macro/cfg-eval.rs b/tests/ui/proc-macro/cfg-eval.rs index ddf3708..9e9e469 100644 --- a/tests/ui/proc-macro/cfg-eval.rs +++ b/tests/ui/proc-macro/cfg-eval.rs
@@ -19,7 +19,7 @@ struct S1 { field_false: u8, #[cfg(all(/*true*/))] #[cfg_attr(FALSE, unknown_attr)] - #[cfg_attr(all(/*true*/), allow())] + #[cfg_attr(all(/*true*/), allow())] //~ WARN unused attribute field_true: u8, }
diff --git a/tests/ui/proc-macro/cfg-eval.stderr b/tests/ui/proc-macro/cfg-eval.stderr new file mode 100644 index 0000000..1429dbd --- /dev/null +++ b/tests/ui/proc-macro/cfg-eval.stderr
@@ -0,0 +1,11 @@ +warning: unused attribute + --> $DIR/cfg-eval.rs:22:5 + | +LL | #[cfg_attr(all(/*true*/), allow())] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | + = note: attribute `allow` with an empty list has no effect + = note: requested on the command line with `-W unused-attributes` + +warning: 1 warning emitted +
diff --git a/tests/ui/proc-macro/inner-attr-non-inline-mod.rs b/tests/ui/proc-macro/inner-attr-file-mod.rs similarity index 86% rename from tests/ui/proc-macro/inner-attr-non-inline-mod.rs rename to tests/ui/proc-macro/inner-attr-file-mod.rs index 2dcdbf3..e592331 100644 --- a/tests/ui/proc-macro/inner-attr-non-inline-mod.rs +++ b/tests/ui/proc-macro/inner-attr-file-mod.rs
@@ -9,7 +9,7 @@ #[deny(unused_attributes)] mod module_with_attrs; -//~^ ERROR non-inline modules in proc macro input are unstable +//~^ ERROR file modules in proc macro input are unstable //~| ERROR custom inner attributes are unstable fn main() {}
diff --git a/tests/ui/proc-macro/inner-attr-non-inline-mod.stderr b/tests/ui/proc-macro/inner-attr-file-mod.stderr similarity index 91% rename from tests/ui/proc-macro/inner-attr-non-inline-mod.stderr rename to tests/ui/proc-macro/inner-attr-file-mod.stderr index c0a9385..9226228 100644 --- a/tests/ui/proc-macro/inner-attr-non-inline-mod.stderr +++ b/tests/ui/proc-macro/inner-attr-file-mod.stderr
@@ -18,8 +18,8 @@ = help: add `#![feature(custom_inner_attributes)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: non-inline modules in proc macro input are unstable - --> $DIR/inner-attr-non-inline-mod.rs:11:1 +error[E0658]: file modules in proc macro input are unstable + --> $DIR/inner-attr-file-mod.rs:11:1 | LL | mod module_with_attrs; | ^^^^^^^^^^^^^^^^^^^^^^ @@ -29,7 +29,7 @@ = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: custom inner attributes are unstable - --> $DIR/inner-attr-non-inline-mod.rs:11:1 + --> $DIR/inner-attr-file-mod.rs:11:1 | LL | mod module_with_attrs; | ^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/proc-macro/inner-attr-file-mod.stdout b/tests/ui/proc-macro/inner-attr-file-mod.stdout new file mode 100644 index 0000000..6f89387 --- /dev/null +++ b/tests/ui/proc-macro/inner-attr-file-mod.stdout
@@ -0,0 +1,77 @@ +PRINT-ATTR INPUT (DISPLAY): #[deny(unused_attributes)] mod module_with_attrs { #![rustfmt::skip] } +PRINT-ATTR DEEP-RE-COLLECTED (DISPLAY): #[deny(unused_attributes)] mod module_with_attrs { #! [rustfmt :: skip] } +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: $DIR/inner-attr-file-mod.rs:11:1: 11:23 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "deny", + span: $DIR/inner-attr-file-mod.rs:11:1: 11:23 (#0), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [ + Ident { + ident: "unused_attributes", + span: $DIR/inner-attr-file-mod.rs:11:1: 11:23 (#0), + }, + ], + span: $DIR/inner-attr-file-mod.rs:11:1: 11:23 (#0), + }, + ], + span: $DIR/inner-attr-file-mod.rs:11:1: 11:23 (#0), + }, + Ident { + ident: "mod", + span: $DIR/inner-attr-file-mod.rs:11:1: 11:23 (#0), + }, + Ident { + ident: "module_with_attrs", + span: $DIR/inner-attr-file-mod.rs:11:1: 11:23 (#0), + }, + Group { + delimiter: Brace, + stream: TokenStream [ + Punct { + ch: '#', + spacing: Joint, + span: $DIR/inner-attr-file-mod.rs:11:1: 11:23 (#0), + }, + Punct { + ch: '!', + spacing: Alone, + span: $DIR/inner-attr-file-mod.rs:11:1: 11:23 (#0), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "rustfmt", + span: $DIR/inner-attr-file-mod.rs:11:1: 11:23 (#0), + }, + Punct { + ch: ':', + spacing: Joint, + span: $DIR/inner-attr-file-mod.rs:11:1: 11:23 (#0), + }, + Punct { + ch: ':', + spacing: Alone, + span: $DIR/inner-attr-file-mod.rs:11:1: 11:23 (#0), + }, + Ident { + ident: "skip", + span: $DIR/inner-attr-file-mod.rs:11:1: 11:23 (#0), + }, + ], + span: $DIR/inner-attr-file-mod.rs:11:1: 11:23 (#0), + }, + ], + span: $DIR/inner-attr-file-mod.rs:11:1: 11:23 (#0), + }, +]
diff --git a/tests/ui/proc-macro/inner-attr-non-inline-mod.stdout b/tests/ui/proc-macro/inner-attr-non-inline-mod.stdout deleted file mode 100644 index 219794a..0000000 --- a/tests/ui/proc-macro/inner-attr-non-inline-mod.stdout +++ /dev/null
@@ -1,77 +0,0 @@ -PRINT-ATTR INPUT (DISPLAY): #[deny(unused_attributes)] mod module_with_attrs { #![rustfmt::skip] } -PRINT-ATTR DEEP-RE-COLLECTED (DISPLAY): #[deny(unused_attributes)] mod module_with_attrs { #! [rustfmt :: skip] } -PRINT-ATTR INPUT (DEBUG): TokenStream [ - Punct { - ch: '#', - spacing: Alone, - span: $DIR/inner-attr-non-inline-mod.rs:11:1: 11:23 (#0), - }, - Group { - delimiter: Bracket, - stream: TokenStream [ - Ident { - ident: "deny", - span: $DIR/inner-attr-non-inline-mod.rs:11:1: 11:23 (#0), - }, - Group { - delimiter: Parenthesis, - stream: TokenStream [ - Ident { - ident: "unused_attributes", - span: $DIR/inner-attr-non-inline-mod.rs:11:1: 11:23 (#0), - }, - ], - span: $DIR/inner-attr-non-inline-mod.rs:11:1: 11:23 (#0), - }, - ], - span: $DIR/inner-attr-non-inline-mod.rs:11:1: 11:23 (#0), - }, - Ident { - ident: "mod", - span: $DIR/inner-attr-non-inline-mod.rs:11:1: 11:23 (#0), - }, - Ident { - ident: "module_with_attrs", - span: $DIR/inner-attr-non-inline-mod.rs:11:1: 11:23 (#0), - }, - Group { - delimiter: Brace, - stream: TokenStream [ - Punct { - ch: '#', - spacing: Joint, - span: $DIR/inner-attr-non-inline-mod.rs:11:1: 11:23 (#0), - }, - Punct { - ch: '!', - spacing: Alone, - span: $DIR/inner-attr-non-inline-mod.rs:11:1: 11:23 (#0), - }, - Group { - delimiter: Bracket, - stream: TokenStream [ - Ident { - ident: "rustfmt", - span: $DIR/inner-attr-non-inline-mod.rs:11:1: 11:23 (#0), - }, - Punct { - ch: ':', - spacing: Joint, - span: $DIR/inner-attr-non-inline-mod.rs:11:1: 11:23 (#0), - }, - Punct { - ch: ':', - spacing: Alone, - span: $DIR/inner-attr-non-inline-mod.rs:11:1: 11:23 (#0), - }, - Ident { - ident: "skip", - span: $DIR/inner-attr-non-inline-mod.rs:11:1: 11:23 (#0), - }, - ], - span: $DIR/inner-attr-non-inline-mod.rs:11:1: 11:23 (#0), - }, - ], - span: $DIR/inner-attr-non-inline-mod.rs:11:1: 11:23 (#0), - }, -]
diff --git a/tests/ui/repr/16-bit-repr-c-enum.rs b/tests/ui/repr/16-bit-repr-c-enum.rs index 964d056..b0f4025 100644 --- a/tests/ui/repr/16-bit-repr-c-enum.rs +++ b/tests/ui/repr/16-bit-repr-c-enum.rs
@@ -7,7 +7,7 @@ //@ [msp430] needs-llvm-components: msp430 //@ [msp430] compile-flags: --target=msp430-none-elf --crate-type=rlib //@ ignore-backends: gcc -#![feature(no_core, lang_items, intrinsics, staged_api, rustc_attrs)] +#![feature(no_core, intrinsics, staged_api, rustc_attrs)] #![no_core] #![crate_type = "lib"] #![stable(feature = "intrinsics_for_test", since = "3.3.3")]
diff --git a/tests/ui/repr/attr-usage-repr.rs b/tests/ui/repr/attr-usage-repr.rs index ca63ac5..10256a7 100644 --- a/tests/ui/repr/attr-usage-repr.rs +++ b/tests/ui/repr/attr-usage-repr.rs
@@ -46,9 +46,11 @@ enum EInt { } #[repr()] //~ ERROR attribute should be applied to a struct, enum, or union [E0517] +//~^ WARN unused attribute type SirThisIsAType = i32; #[repr()] +//~^ WARN unused attribute struct EmptyReprArgumentList(i32); fn main() {}
diff --git a/tests/ui/repr/attr-usage-repr.stderr b/tests/ui/repr/attr-usage-repr.stderr index a62992c..33aa3c2 100644 --- a/tests/ui/repr/attr-usage-repr.stderr +++ b/tests/ui/repr/attr-usage-repr.stderr
@@ -41,9 +41,27 @@ | LL | #[repr()] | ^^^^^^^^^ +LL | LL | type SirThisIsAType = i32; | -------------------------- not a struct, enum, or union -error: aborting due to 5 previous errors +warning: unused attribute + --> $DIR/attr-usage-repr.rs:48:1 + | +LL | #[repr()] + | ^^^^^^^^^ help: remove this attribute + | + = note: using `repr` with an empty list has no effect + = note: requested on the command line with `-W unused-attributes` + +warning: unused attribute + --> $DIR/attr-usage-repr.rs:52:1 + | +LL | #[repr()] + | ^^^^^^^^^ help: remove this attribute + | + = note: using `repr` with an empty list has no effect + +error: aborting due to 5 previous errors; 2 warnings emitted For more information about this error, try `rustc --explain E0517`.
diff --git a/tests/ui/issues/auxiliary/issue-73112.rs b/tests/ui/repr/auxiliary/aux-73112.rs similarity index 100% rename from tests/ui/issues/auxiliary/issue-73112.rs rename to tests/ui/repr/auxiliary/aux-73112.rs
diff --git a/tests/ui/issues/issue-74082.rs b/tests/ui/repr/invalid-repr-on-structs-74082.rs similarity index 78% rename from tests/ui/issues/issue-74082.rs rename to tests/ui/repr/invalid-repr-on-structs-74082.rs index e3e400c..8b9807f 100644 --- a/tests/ui/issues/issue-74082.rs +++ b/tests/ui/repr/invalid-repr-on-structs-74082.rs
@@ -1,3 +1,4 @@ +// https://github.com/rust-lang/rust/issues/74082 #![allow(dead_code)] #[repr(i128)] //~ ERROR: attribute should be applied to an enum
diff --git a/tests/ui/issues/issue-74082.stderr b/tests/ui/repr/invalid-repr-on-structs-74082.stderr similarity index 79% rename from tests/ui/issues/issue-74082.stderr rename to tests/ui/repr/invalid-repr-on-structs-74082.stderr index 12f5a3b..e11beb8 100644 --- a/tests/ui/issues/issue-74082.stderr +++ b/tests/ui/repr/invalid-repr-on-structs-74082.stderr
@@ -1,5 +1,5 @@ error[E0517]: attribute should be applied to an enum - --> $DIR/issue-74082.rs:3:8 + --> $DIR/invalid-repr-on-structs-74082.rs:4:8 | LL | #[repr(i128)] | ^^^^ @@ -7,7 +7,7 @@ | ----------- not an enum error[E0517]: attribute should be applied to an enum - --> $DIR/issue-74082.rs:6:8 + --> $DIR/invalid-repr-on-structs-74082.rs:7:8 | LL | #[repr(u128)] | ^^^^
diff --git a/tests/ui/repr/packed-struct-contains-aligned-type-73112.rs b/tests/ui/repr/packed-struct-contains-aligned-type-73112.rs new file mode 100644 index 0000000..baeb75b --- /dev/null +++ b/tests/ui/repr/packed-struct-contains-aligned-type-73112.rs
@@ -0,0 +1,14 @@ +// https://github.com/rust-lang/rust/issues/73112 +//@ aux-build:aux-73112.rs + +extern crate aux_73112; + +fn main() { + use aux_73112::PageTable; + + #[repr(C, packed)] + struct SomeStruct { + //~^ ERROR packed type cannot transitively contain a `#[repr(align)]` type [E0588] + page_table: PageTable, + } +}
diff --git a/tests/ui/issues/issue-73112.stderr b/tests/ui/repr/packed-struct-contains-aligned-type-73112.stderr similarity index 78% rename from tests/ui/issues/issue-73112.stderr rename to tests/ui/repr/packed-struct-contains-aligned-type-73112.stderr index c2c15ca..237c357 100644 --- a/tests/ui/issues/issue-73112.stderr +++ b/tests/ui/repr/packed-struct-contains-aligned-type-73112.stderr
@@ -1,11 +1,11 @@ error[E0588]: packed type cannot transitively contain a `#[repr(align)]` type - --> $DIR/issue-73112.rs:9:5 + --> $DIR/packed-struct-contains-aligned-type-73112.rs:10:5 | LL | struct SomeStruct { | ^^^^^^^^^^^^^^^^^ | note: `PageTable` has a `#[repr(align)]` attribute - --> $DIR/auxiliary/issue-73112.rs:8:1 + --> $DIR/auxiliary/aux-73112.rs:8:1 | LL | pub struct PageTable { | ^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/repr/repr-c-dead-variants.rs b/tests/ui/repr/repr-c-dead-variants.rs index 0cabafa..048e74c 100644 --- a/tests/ui/repr/repr-c-dead-variants.rs +++ b/tests/ui/repr/repr-c-dead-variants.rs
@@ -1,4 +1,4 @@ -#![feature(no_core, rustc_attrs, lang_items)] +#![feature(no_core, rustc_attrs)] #![allow(dead_code)] #![crate_type = "lib"] #![no_std]
diff --git a/tests/ui/repr/repr_align_greater_usize.rs b/tests/ui/repr/repr_align_greater_usize.rs index 7499e24..7bbf0b2 100644 --- a/tests/ui/repr/repr_align_greater_usize.rs +++ b/tests/ui/repr/repr_align_greater_usize.rs
@@ -9,7 +9,7 @@ // We should fail to compute alignment for types aligned higher than usize::MAX. // We can't handle alignments that require all 32 bits, so this only affects 16-bit. -#![feature(lang_items, no_core)] +#![feature(no_core)] #![no_core] #![crate_type = "lib"]
diff --git a/tests/ui/issues/issue-71406.rs b/tests/ui/resolve/function-module-ambiguity-error-71406.rs similarity index 73% rename from tests/ui/issues/issue-71406.rs rename to tests/ui/resolve/function-module-ambiguity-error-71406.rs index 6266112..a7964de 100644 --- a/tests/ui/issues/issue-71406.rs +++ b/tests/ui/resolve/function-module-ambiguity-error-71406.rs
@@ -1,3 +1,4 @@ +// https://github.com/rust-lang/rust/issues/71406 use std::sync::mpsc; fn main() {
diff --git a/tests/ui/issues/issue-71406.stderr b/tests/ui/resolve/function-module-ambiguity-error-71406.stderr similarity index 84% rename from tests/ui/issues/issue-71406.stderr rename to tests/ui/resolve/function-module-ambiguity-error-71406.stderr index cd7921f..c25bafa 100644 --- a/tests/ui/issues/issue-71406.stderr +++ b/tests/ui/resolve/function-module-ambiguity-error-71406.stderr
@@ -1,5 +1,5 @@ error[E0433]: failed to resolve: expected type, found function `channel` in `mpsc` - --> $DIR/issue-71406.rs:4:26 + --> $DIR/function-module-ambiguity-error-71406.rs:5:26 | LL | let (tx, rx) = mpsc::channel::new(1); | ^^^^^^^ expected type, found function `channel` in `mpsc`
diff --git a/tests/ui/rfcs/rfc-2091-track-caller/macro-declaration.rs b/tests/ui/rfcs/rfc-2091-track-caller/macro-declaration.rs index f003e40..053af25 100644 --- a/tests/ui/rfcs/rfc-2091-track-caller/macro-declaration.rs +++ b/tests/ui/rfcs/rfc-2091-track-caller/macro-declaration.rs
@@ -2,6 +2,8 @@ // See https://github.com/rust-lang/rust/issues/95151 #[track_caller] +//~^ WARN attribute cannot be used on macro defs +//~| WARN previously accepted macro_rules! _foo { () => {}; }
diff --git a/tests/ui/rfcs/rfc-2091-track-caller/macro-declaration.stderr b/tests/ui/rfcs/rfc-2091-track-caller/macro-declaration.stderr new file mode 100644 index 0000000..0a0e491 --- /dev/null +++ b/tests/ui/rfcs/rfc-2091-track-caller/macro-declaration.stderr
@@ -0,0 +1,12 @@ +warning: `#[track_caller]` attribute cannot be used on macro defs + --> $DIR/macro-declaration.rs:4:1 + | +LL | #[track_caller] + | ^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[track_caller]` can only be applied to functions + = note: requested on the command line with `-W unused-attributes` + +warning: 1 warning emitted +
diff --git a/tests/ui/rfcs/rfc-2091-track-caller/shim-does-not-modify-symbol.rs b/tests/ui/rfcs/rfc-2091-track-caller/shim-does-not-modify-symbol.rs new file mode 100644 index 0000000..255e2c1 --- /dev/null +++ b/tests/ui/rfcs/rfc-2091-track-caller/shim-does-not-modify-symbol.rs
@@ -0,0 +1,26 @@ +//@ run-pass +#![feature(rustc_attrs)] + +// The shim that is generated for a function annotated with `#[track_caller]` should not inherit +// attributes that modify its symbol name. Failing to remove these attributes from the shim +// leads to errors like `symbol `foo` is already defined`. +// +// See also https://github.com/rust-lang/rust/issues/143162. + +#[unsafe(no_mangle)] +#[track_caller] +pub fn foo() {} + +#[unsafe(export_name = "bar")] +#[track_caller] +pub fn bar() {} + +#[rustc_std_internal_symbol] +#[track_caller] +pub fn baz() {} + +fn main() { + let _a = foo as fn(); + let _b = bar as fn(); + let _c = baz as fn(); +}
diff --git a/tests/ui/rfcs/rfc-2091-track-caller/track-caller-ffi.rs b/tests/ui/rfcs/rfc-2091-track-caller/track-caller-ffi.rs index ee8be90..d82bd12 100644 --- a/tests/ui/rfcs/rfc-2091-track-caller/track-caller-ffi.rs +++ b/tests/ui/rfcs/rfc-2091-track-caller/track-caller-ffi.rs
@@ -2,14 +2,14 @@ use std::panic::Location; -extern "Rust" { +unsafe extern "Rust" { #[track_caller] - fn rust_track_caller_ffi_test_tracked() -> &'static Location<'static>; - fn rust_track_caller_ffi_test_untracked() -> &'static Location<'static>; + safe fn rust_track_caller_ffi_test_tracked() -> &'static Location<'static>; + safe fn rust_track_caller_ffi_test_untracked() -> &'static Location<'static>; } fn rust_track_caller_ffi_test_nested_tracked() -> &'static Location<'static> { - unsafe { rust_track_caller_ffi_test_tracked() } + rust_track_caller_ffi_test_tracked() } mod provides { @@ -31,12 +31,12 @@ fn main() { assert_eq!(location.line(), 29); assert_eq!(location.column(), 20); - let tracked = unsafe { rust_track_caller_ffi_test_tracked() }; + let tracked = rust_track_caller_ffi_test_tracked(); assert_eq!(tracked.file(), file!()); assert_eq!(tracked.line(), 34); - assert_eq!(tracked.column(), 28); + assert_eq!(tracked.column(), 19); - let untracked = unsafe { rust_track_caller_ffi_test_untracked() }; + let untracked = rust_track_caller_ffi_test_untracked(); assert_eq!(untracked.file(), file!()); assert_eq!(untracked.line(), 24); assert_eq!(untracked.column(), 9); @@ -44,5 +44,10 @@ fn main() { let contained = rust_track_caller_ffi_test_nested_tracked(); assert_eq!(contained.file(), file!()); assert_eq!(contained.line(), 12); - assert_eq!(contained.column(), 14); + assert_eq!(contained.column(), 5); + + let indirect = (rust_track_caller_ffi_test_tracked as fn() -> &'static Location<'static>)(); + assert_eq!(indirect.file(), file!()); + assert_eq!(indirect.line(), 7); + assert_eq!(indirect.column(), 5); }
diff --git a/tests/ui/rfcs/rfc-2565-param-attrs/param-attrs-builtin-attrs.rs b/tests/ui/rfcs/rfc-2565-param-attrs/param-attrs-builtin-attrs.rs index 151659e..bb6e770 100644 --- a/tests/ui/rfcs/rfc-2565-param-attrs/param-attrs-builtin-attrs.rs +++ b/tests/ui/rfcs/rfc-2565-param-attrs/param-attrs-builtin-attrs.rs
@@ -39,10 +39,14 @@ pub fn foo( //~^ ERROR documentation comments cannot be applied to function #[must_use] //~^ ERROR allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters + //~| WARN attribute cannot be used on + //~| WARN previously accepted /// Baz //~^ ERROR documentation comments cannot be applied to function #[no_mangle] b: i32, //~^ ERROR allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters + //~| WARN attribute cannot be used on + //~| WARN previously accepted ) {} struct SelfStruct {} @@ -59,10 +63,14 @@ fn foo( //~^ ERROR documentation comments cannot be applied to function #[must_use] //~^ ERROR allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters + //~| WARN attribute cannot be used on + //~| WARN previously accepted /// Qux //~^ ERROR documentation comments cannot be applied to function #[no_mangle] b: i32, //~^ ERROR allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters + //~| WARN attribute cannot be used on + //~| WARN previously accepted ) {} fn issue_64682_associated_fn( @@ -74,10 +82,14 @@ fn issue_64682_associated_fn( //~^ ERROR documentation comments cannot be applied to function #[must_use] //~^ ERROR allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters + //~| WARN attribute cannot be used on + //~| WARN previously accepted /// Qux //~^ ERROR documentation comments cannot be applied to function #[no_mangle] b: i32, //~^ ERROR allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters + //~| WARN attribute cannot be used on + //~| WARN previously accepted ) {} } @@ -95,10 +107,14 @@ fn foo( //~^ ERROR documentation comments cannot be applied to function #[must_use] //~^ ERROR allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters + //~| WARN attribute cannot be used on + //~| WARN previously accepted /// Qux //~^ ERROR documentation comments cannot be applied to function #[no_mangle] b: i32, //~^ ERROR allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters + //~| WARN attribute cannot be used on + //~| WARN previously accepted ) {} } trait RefTrait { @@ -114,10 +130,14 @@ fn foo( //~^ ERROR documentation comments cannot be applied to function #[must_use] //~^ ERROR allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters + //~| WARN attribute cannot be used on + //~| WARN previously accepted /// Qux //~^ ERROR documentation comments cannot be applied to function #[no_mangle] b: i32, //~^ ERROR allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters + //~| WARN attribute cannot be used on + //~| WARN previously accepted ) {} fn issue_64682_associated_fn( @@ -129,10 +149,14 @@ fn issue_64682_associated_fn( //~^ ERROR documentation comments cannot be applied to function #[must_use] //~^ ERROR allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters + //~| WARN attribute cannot be used on + //~| WARN previously accepted /// Qux //~^ ERROR documentation comments cannot be applied to function #[no_mangle] b: i32, //~^ ERROR allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters + //~| WARN attribute cannot be used on + //~| WARN previously accepted ) {} } @@ -149,10 +173,14 @@ fn foo( //~^ ERROR documentation comments cannot be applied to function #[must_use] //~^ ERROR allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters + //~| WARN attribute cannot be used on + //~| WARN previously accepted /// Qux //~^ ERROR documentation comments cannot be applied to function #[no_mangle] b: i32, //~^ ERROR allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters + //~| WARN attribute cannot be used on + //~| WARN previously accepted ) {} } @@ -166,9 +194,13 @@ fn main() { //~^ ERROR documentation comments cannot be applied to function #[must_use] //~^ ERROR allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters + //~| WARN attribute cannot be used on + //~| WARN previously accepted /// Baz //~^ ERROR documentation comments cannot be applied to function #[no_mangle] b: i32 //~^ ERROR allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters + //~| WARN attribute cannot be used on + //~| WARN previously accepted | {}; }
diff --git a/tests/ui/rfcs/rfc-2565-param-attrs/param-attrs-builtin-attrs.stderr b/tests/ui/rfcs/rfc-2565-param-attrs/param-attrs-builtin-attrs.stderr index 7573e39..cc08307 100644 --- a/tests/ui/rfcs/rfc-2565-param-attrs/param-attrs-builtin-attrs.stderr +++ b/tests/ui/rfcs/rfc-2565-param-attrs/param-attrs-builtin-attrs.stderr
@@ -17,31 +17,25 @@ | ^^^^ not a non-macro attribute error: expected non-macro attribute, found attribute macro `test` - --> $DIR/param-attrs-builtin-attrs.rs:56:11 + --> $DIR/param-attrs-builtin-attrs.rs:60:11 | LL | #[test] a: i32, | ^^^^ not a non-macro attribute error: expected non-macro attribute, found attribute macro `test` - --> $DIR/param-attrs-builtin-attrs.rs:71:11 + --> $DIR/param-attrs-builtin-attrs.rs:79:11 | LL | #[test] a: i32, | ^^^^ not a non-macro attribute error: expected non-macro attribute, found attribute macro `test` - --> $DIR/param-attrs-builtin-attrs.rs:92:11 + --> $DIR/param-attrs-builtin-attrs.rs:104:11 | LL | #[test] a: i32, | ^^^^ not a non-macro attribute error: expected non-macro attribute, found attribute macro `test` - --> $DIR/param-attrs-builtin-attrs.rs:111:11 - | -LL | #[test] a: i32, - | ^^^^ not a non-macro attribute - -error: expected non-macro attribute, found attribute macro `test` - --> $DIR/param-attrs-builtin-attrs.rs:126:11 + --> $DIR/param-attrs-builtin-attrs.rs:127:11 | LL | #[test] a: i32, | ^^^^ not a non-macro attribute @@ -53,7 +47,13 @@ | ^^^^ not a non-macro attribute error: expected non-macro attribute, found attribute macro `test` - --> $DIR/param-attrs-builtin-attrs.rs:163:11 + --> $DIR/param-attrs-builtin-attrs.rs:170:11 + | +LL | #[test] a: i32, + | ^^^^ not a non-macro attribute + +error: expected non-macro attribute, found attribute macro `test` + --> $DIR/param-attrs-builtin-attrs.rs:191:11 | LL | #[test] a: u32, | ^^^^ not a non-macro attribute @@ -137,195 +137,159 @@ | ^^^^^^^^^^^ error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:42:5 + --> $DIR/param-attrs-builtin-attrs.rs:44:5 | LL | /// Baz | ^^^^^^^ doc comments are not allowed here error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters - --> $DIR/param-attrs-builtin-attrs.rs:44:5 + --> $DIR/param-attrs-builtin-attrs.rs:46:5 | LL | #[no_mangle] b: i32, | ^^^^^^^^^^^^ error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:51:9 + --> $DIR/param-attrs-builtin-attrs.rs:55:9 | LL | /// Foo | ^^^^^^^ doc comments are not allowed here error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:54:9 - | -LL | /// Bar - | ^^^^^^^ doc comments are not allowed here - -error: documentation comments cannot be applied to function parameters --> $DIR/param-attrs-builtin-attrs.rs:58:9 | -LL | /// Baz +LL | /// Bar | ^^^^^^^ doc comments are not allowed here -error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters - --> $DIR/param-attrs-builtin-attrs.rs:60:9 - | -LL | #[must_use] - | ^^^^^^^^^^^ - error: documentation comments cannot be applied to function parameters --> $DIR/param-attrs-builtin-attrs.rs:62:9 | -LL | /// Qux +LL | /// Baz | ^^^^^^^ doc comments are not allowed here error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters --> $DIR/param-attrs-builtin-attrs.rs:64:9 | -LL | #[no_mangle] b: i32, - | ^^^^^^^^^^^^ +LL | #[must_use] + | ^^^^^^^^^^^ error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:69:9 + --> $DIR/param-attrs-builtin-attrs.rs:68:9 | -LL | /// Foo - | ^^^^^^^ doc comments are not allowed here - -error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:73:9 - | -LL | /// Baz +LL | /// Qux | ^^^^^^^ doc comments are not allowed here error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters - --> $DIR/param-attrs-builtin-attrs.rs:75:9 + --> $DIR/param-attrs-builtin-attrs.rs:70:9 | -LL | #[must_use] - | ^^^^^^^^^^^ +LL | #[no_mangle] b: i32, + | ^^^^^^^^^^^^ error: documentation comments cannot be applied to function parameters --> $DIR/param-attrs-builtin-attrs.rs:77:9 | -LL | /// Qux +LL | /// Foo + | ^^^^^^^ doc comments are not allowed here + +error: documentation comments cannot be applied to function parameters + --> $DIR/param-attrs-builtin-attrs.rs:81:9 + | +LL | /// Baz | ^^^^^^^ doc comments are not allowed here error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters - --> $DIR/param-attrs-builtin-attrs.rs:79:9 + --> $DIR/param-attrs-builtin-attrs.rs:83:9 | -LL | #[no_mangle] b: i32, - | ^^^^^^^^^^^^ +LL | #[must_use] + | ^^^^^^^^^^^ error: documentation comments cannot be applied to function parameters --> $DIR/param-attrs-builtin-attrs.rs:87:9 | -LL | /// Foo - | ^^^^^^^ doc comments are not allowed here - -error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:90:9 - | -LL | /// Bar - | ^^^^^^^ doc comments are not allowed here - -error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:94:9 - | -LL | /// Baz - | ^^^^^^^ doc comments are not allowed here - -error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters - --> $DIR/param-attrs-builtin-attrs.rs:96:9 - | -LL | #[must_use] - | ^^^^^^^^^^^ - -error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:98:9 - | LL | /// Qux | ^^^^^^^ doc comments are not allowed here error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters - --> $DIR/param-attrs-builtin-attrs.rs:100:9 + --> $DIR/param-attrs-builtin-attrs.rs:89:9 | LL | #[no_mangle] b: i32, | ^^^^^^^^^^^^ error: documentation comments cannot be applied to function parameters + --> $DIR/param-attrs-builtin-attrs.rs:99:9 + | +LL | /// Foo + | ^^^^^^^ doc comments are not allowed here + +error: documentation comments cannot be applied to function parameters + --> $DIR/param-attrs-builtin-attrs.rs:102:9 + | +LL | /// Bar + | ^^^^^^^ doc comments are not allowed here + +error: documentation comments cannot be applied to function parameters --> $DIR/param-attrs-builtin-attrs.rs:106:9 | +LL | /// Baz + | ^^^^^^^ doc comments are not allowed here + +error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters + --> $DIR/param-attrs-builtin-attrs.rs:108:9 + | +LL | #[must_use] + | ^^^^^^^^^^^ + +error: documentation comments cannot be applied to function parameters + --> $DIR/param-attrs-builtin-attrs.rs:112:9 + | +LL | /// Qux + | ^^^^^^^ doc comments are not allowed here + +error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters + --> $DIR/param-attrs-builtin-attrs.rs:114:9 + | +LL | #[no_mangle] b: i32, + | ^^^^^^^^^^^^ + +error: documentation comments cannot be applied to function parameters + --> $DIR/param-attrs-builtin-attrs.rs:122:9 + | LL | /// Foo | ^^^^^^^ doc comments are not allowed here error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:109:9 + --> $DIR/param-attrs-builtin-attrs.rs:125:9 | LL | /// Bar | ^^^^^^^ doc comments are not allowed here error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:113:9 + --> $DIR/param-attrs-builtin-attrs.rs:129:9 | LL | /// Baz | ^^^^^^^ doc comments are not allowed here error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters - --> $DIR/param-attrs-builtin-attrs.rs:115:9 + --> $DIR/param-attrs-builtin-attrs.rs:131:9 | LL | #[must_use] | ^^^^^^^^^^^ error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:117:9 + --> $DIR/param-attrs-builtin-attrs.rs:135:9 | LL | /// Qux | ^^^^^^^ doc comments are not allowed here error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters - --> $DIR/param-attrs-builtin-attrs.rs:119:9 + --> $DIR/param-attrs-builtin-attrs.rs:137:9 | LL | #[no_mangle] b: i32, | ^^^^^^^^^^^^ error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:124:9 - | -LL | /// Foo - | ^^^^^^^ doc comments are not allowed here - -error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:128:9 - | -LL | /// Baz - | ^^^^^^^ doc comments are not allowed here - -error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters - --> $DIR/param-attrs-builtin-attrs.rs:130:9 - | -LL | #[must_use] - | ^^^^^^^^^^^ - -error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:132:9 - | -LL | /// Qux - | ^^^^^^^ doc comments are not allowed here - -error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters - --> $DIR/param-attrs-builtin-attrs.rs:134:9 - | -LL | #[no_mangle] b: i32, - | ^^^^^^^^^^^^ - -error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:141:9 - | -LL | /// Foo - | ^^^^^^^ doc comments are not allowed here - -error: documentation comments cannot be applied to function parameters --> $DIR/param-attrs-builtin-attrs.rs:144:9 | -LL | /// Bar +LL | /// Foo | ^^^^^^^ doc comments are not allowed here error: documentation comments cannot be applied to function parameters @@ -341,46 +305,227 @@ | ^^^^^^^^^^^ error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:152:9 + --> $DIR/param-attrs-builtin-attrs.rs:154:9 | LL | /// Qux | ^^^^^^^ doc comments are not allowed here error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters - --> $DIR/param-attrs-builtin-attrs.rs:154:9 + --> $DIR/param-attrs-builtin-attrs.rs:156:9 | LL | #[no_mangle] b: i32, | ^^^^^^^^^^^^ error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:161:9 + --> $DIR/param-attrs-builtin-attrs.rs:165:9 | LL | /// Foo | ^^^^^^^ doc comments are not allowed here error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:165:9 + --> $DIR/param-attrs-builtin-attrs.rs:168:9 | LL | /// Bar | ^^^^^^^ doc comments are not allowed here -error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters - --> $DIR/param-attrs-builtin-attrs.rs:167:9 - | -LL | #[must_use] - | ^^^^^^^^^^^ - error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:169:9 + --> $DIR/param-attrs-builtin-attrs.rs:172:9 | LL | /// Baz | ^^^^^^^ doc comments are not allowed here error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters - --> $DIR/param-attrs-builtin-attrs.rs:171:9 + --> $DIR/param-attrs-builtin-attrs.rs:174:9 + | +LL | #[must_use] + | ^^^^^^^^^^^ + +error: documentation comments cannot be applied to function parameters + --> $DIR/param-attrs-builtin-attrs.rs:178:9 + | +LL | /// Qux + | ^^^^^^^ doc comments are not allowed here + +error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters + --> $DIR/param-attrs-builtin-attrs.rs:180:9 + | +LL | #[no_mangle] b: i32, + | ^^^^^^^^^^^^ + +error: documentation comments cannot be applied to function parameters + --> $DIR/param-attrs-builtin-attrs.rs:189:9 + | +LL | /// Foo + | ^^^^^^^ doc comments are not allowed here + +error: documentation comments cannot be applied to function parameters + --> $DIR/param-attrs-builtin-attrs.rs:193:9 + | +LL | /// Bar + | ^^^^^^^ doc comments are not allowed here + +error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters + --> $DIR/param-attrs-builtin-attrs.rs:195:9 + | +LL | #[must_use] + | ^^^^^^^^^^^ + +error: documentation comments cannot be applied to function parameters + --> $DIR/param-attrs-builtin-attrs.rs:199:9 + | +LL | /// Baz + | ^^^^^^^ doc comments are not allowed here + +error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters + --> $DIR/param-attrs-builtin-attrs.rs:201:9 | LL | #[no_mangle] b: i32 | ^^^^^^^^^^^^ -error: aborting due to 64 previous errors +warning: `#[must_use]` attribute cannot be used on function params + --> $DIR/param-attrs-builtin-attrs.rs:40:5 + | +LL | #[must_use] + | ^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[must_use]` can be applied to data types, functions, traits, and unions + = note: requested on the command line with `-W unused-attributes` + +warning: `#[no_mangle]` attribute cannot be used on function params + --> $DIR/param-attrs-builtin-attrs.rs:46:5 + | +LL | #[no_mangle] b: i32, + | ^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[no_mangle]` can be applied to functions and statics + +warning: `#[must_use]` attribute cannot be used on function params + --> $DIR/param-attrs-builtin-attrs.rs:64:9 + | +LL | #[must_use] + | ^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[must_use]` can be applied to data types, functions, traits, and unions + +warning: `#[no_mangle]` attribute cannot be used on function params + --> $DIR/param-attrs-builtin-attrs.rs:70:9 + | +LL | #[no_mangle] b: i32, + | ^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[no_mangle]` can be applied to functions and statics + +warning: `#[must_use]` attribute cannot be used on function params + --> $DIR/param-attrs-builtin-attrs.rs:83:9 + | +LL | #[must_use] + | ^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[must_use]` can be applied to data types, functions, traits, and unions + +warning: `#[no_mangle]` attribute cannot be used on function params + --> $DIR/param-attrs-builtin-attrs.rs:89:9 + | +LL | #[no_mangle] b: i32, + | ^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[no_mangle]` can be applied to functions and statics + +warning: `#[must_use]` attribute cannot be used on function params + --> $DIR/param-attrs-builtin-attrs.rs:108:9 + | +LL | #[must_use] + | ^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[must_use]` can be applied to data types, functions, traits, and unions + +warning: `#[no_mangle]` attribute cannot be used on function params + --> $DIR/param-attrs-builtin-attrs.rs:114:9 + | +LL | #[no_mangle] b: i32, + | ^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[no_mangle]` can be applied to functions and statics + +warning: `#[must_use]` attribute cannot be used on function params + --> $DIR/param-attrs-builtin-attrs.rs:131:9 + | +LL | #[must_use] + | ^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[must_use]` can be applied to data types, functions, traits, and unions + +warning: `#[no_mangle]` attribute cannot be used on function params + --> $DIR/param-attrs-builtin-attrs.rs:137:9 + | +LL | #[no_mangle] b: i32, + | ^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[no_mangle]` can be applied to functions and statics + +warning: `#[must_use]` attribute cannot be used on function params + --> $DIR/param-attrs-builtin-attrs.rs:150:9 + | +LL | #[must_use] + | ^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[must_use]` can be applied to data types, functions, traits, and unions + +warning: `#[no_mangle]` attribute cannot be used on function params + --> $DIR/param-attrs-builtin-attrs.rs:156:9 + | +LL | #[no_mangle] b: i32, + | ^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[no_mangle]` can be applied to functions and statics + +warning: `#[must_use]` attribute cannot be used on function params + --> $DIR/param-attrs-builtin-attrs.rs:174:9 + | +LL | #[must_use] + | ^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[must_use]` can be applied to data types, functions, traits, and unions + +warning: `#[no_mangle]` attribute cannot be used on function params + --> $DIR/param-attrs-builtin-attrs.rs:180:9 + | +LL | #[no_mangle] b: i32, + | ^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[no_mangle]` can be applied to functions and statics + +warning: `#[must_use]` attribute cannot be used on function params + --> $DIR/param-attrs-builtin-attrs.rs:195:9 + | +LL | #[must_use] + | ^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[must_use]` can be applied to data types, functions, traits, and unions + +warning: `#[no_mangle]` attribute cannot be used on function params + --> $DIR/param-attrs-builtin-attrs.rs:201:9 + | +LL | #[no_mangle] b: i32 + | ^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[no_mangle]` can be applied to functions and statics + +error: aborting due to 64 previous errors; 16 warnings emitted
diff --git a/tests/ui/rust-2018/removing-extern-crate-malformed-cfg.fixed b/tests/ui/rust-2018/removing-extern-crate-malformed-cfg.fixed index 028f86eb0..b4b47dc 100644 --- a/tests/ui/rust-2018/removing-extern-crate-malformed-cfg.fixed +++ b/tests/ui/rust-2018/removing-extern-crate-malformed-cfg.fixed
@@ -1,6 +1,7 @@ //@ edition:2018 //@ aux-build: remove-extern-crate.rs //@ run-rustfix +//@ rustfix-only-machine-applicable #![warn(rust_2018_idioms)]
diff --git a/tests/ui/rust-2018/removing-extern-crate-malformed-cfg.rs b/tests/ui/rust-2018/removing-extern-crate-malformed-cfg.rs index 1acf531..f3c591a 100644 --- a/tests/ui/rust-2018/removing-extern-crate-malformed-cfg.rs +++ b/tests/ui/rust-2018/removing-extern-crate-malformed-cfg.rs
@@ -1,6 +1,7 @@ //@ edition:2018 //@ aux-build: remove-extern-crate.rs //@ run-rustfix +//@ rustfix-only-machine-applicable #![warn(rust_2018_idioms)]
diff --git a/tests/ui/rust-2018/removing-extern-crate-malformed-cfg.stderr b/tests/ui/rust-2018/removing-extern-crate-malformed-cfg.stderr index 632ecd6..fc6afa5 100644 --- a/tests/ui/rust-2018/removing-extern-crate-malformed-cfg.stderr +++ b/tests/ui/rust-2018/removing-extern-crate-malformed-cfg.stderr
@@ -1,29 +1,33 @@ error: expected identifier, found `"macro_use"` - --> $DIR/removing-extern-crate-malformed-cfg.rs:7:18 + --> $DIR/removing-extern-crate-malformed-cfg.rs:8:18 | LL | #[cfg_attr(test, "macro_use")] - | ^^^^^^^^^^^ expected identifier + | -----------------^^^^^^^^^^^-- + | | | + | | expected identifier + | help: must be of the form: `#[cfg_attr(predicate, attr1, attr2, ...)]` | - = help: the valid syntax is `#[cfg_attr(condition, attribute, other_attribute, ...)]` = note: for more information, visit <https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg_attr-attribute> error: expected one of `(`, `,`, `::`, or `=`, found `<eof>` - --> $DIR/removing-extern-crate-malformed-cfg.rs:12:16 + --> $DIR/removing-extern-crate-malformed-cfg.rs:13:16 | LL | #[cfg_attr(test)] - | ^^^^ expected one of `(`, `,`, `::`, or `=` + | -----------^^^^-- + | | | + | | expected one of `(`, `,`, `::`, or `=` + | help: must be of the form: `#[cfg_attr(predicate, attr1, attr2, ...)]` | - = help: the valid syntax is `#[cfg_attr(condition, attribute, other_attribute, ...)]` = note: for more information, visit <https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg_attr-attribute> warning: unused extern crate - --> $DIR/removing-extern-crate-malformed-cfg.rs:8:1 + --> $DIR/removing-extern-crate-malformed-cfg.rs:9:1 | LL | extern crate remove_extern_crate as foo; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unused | note: the lint level is defined here - --> $DIR/removing-extern-crate-malformed-cfg.rs:5:9 + --> $DIR/removing-extern-crate-malformed-cfg.rs:6:9 | LL | #![warn(rust_2018_idioms)] | ^^^^^^^^^^^^^^^^ @@ -36,7 +40,7 @@ | warning: unused extern crate - --> $DIR/removing-extern-crate-malformed-cfg.rs:9:1 + --> $DIR/removing-extern-crate-malformed-cfg.rs:10:1 | LL | extern crate core; | ^^^^^^^^^^^^^^^^^^ unused @@ -48,7 +52,7 @@ | warning: unused extern crate - --> $DIR/removing-extern-crate-malformed-cfg.rs:13:5 + --> $DIR/removing-extern-crate-malformed-cfg.rs:14:5 | LL | extern crate remove_extern_crate as foo; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unused @@ -61,7 +65,7 @@ | warning: unused extern crate - --> $DIR/removing-extern-crate-malformed-cfg.rs:14:5 + --> $DIR/removing-extern-crate-malformed-cfg.rs:15:5 | LL | extern crate core; | ^^^^^^^^^^^^^^^^^^ unused
diff --git a/tests/ui/sanitizer/cfg-kasan.rs b/tests/ui/sanitizer/cfg-kasan.rs index 9b168b4..0f45608 100644 --- a/tests/ui/sanitizer/cfg-kasan.rs +++ b/tests/ui/sanitizer/cfg-kasan.rs
@@ -16,7 +16,7 @@ //@ ignore-backends: gcc #![crate_type = "rlib"] -#![feature(cfg_sanitize, no_core, lang_items)] +#![feature(cfg_sanitize, no_core)] #![no_core] extern crate minicore;
diff --git a/tests/ui/sanitizer/cfg.rs b/tests/ui/sanitizer/cfg.rs index edc0dca..42b1d3c 100644 --- a/tests/ui/sanitizer/cfg.rs +++ b/tests/ui/sanitizer/cfg.rs
@@ -21,7 +21,7 @@ //@[thread]compile-flags: -Zsanitizer=thread //@ ignore-backends: gcc -#![feature(cfg_sanitize, no_core, lang_items)] +#![feature(cfg_sanitize, no_core)] #![crate_type="lib"] #![no_core]
diff --git a/tests/ui/sized-hierarchy/default-supertrait.rs b/tests/ui/sized-hierarchy/default-supertrait.rs index ab3b28e..d5bf152 100644 --- a/tests/ui/sized-hierarchy/default-supertrait.rs +++ b/tests/ui/sized-hierarchy/default-supertrait.rs
@@ -12,12 +12,17 @@ trait MetaSized_: MetaSized { } trait NegMetaSized: ?MetaSized { } //~^ ERROR relaxed bounds are not permitted in supertrait bounds - +//~| ERROR bound modifier `?` can only be applied to `Sized` +//~| ERROR bound modifier `?` can only be applied to `Sized` +//~| ERROR bound modifier `?` can only be applied to `Sized` trait PointeeSized_: PointeeSized { } trait NegPointeeSized: ?PointeeSized { } //~^ ERROR relaxed bounds are not permitted in supertrait bounds +//~| ERROR bound modifier `?` can only be applied to `Sized` +//~| ERROR bound modifier `?` can only be applied to `Sized` +//~| ERROR bound modifier `?` can only be applied to `Sized` trait Bare {}
diff --git a/tests/ui/sized-hierarchy/default-supertrait.stderr b/tests/ui/sized-hierarchy/default-supertrait.stderr index f5589d6..2a521dc 100644 --- a/tests/ui/sized-hierarchy/default-supertrait.stderr +++ b/tests/ui/sized-hierarchy/default-supertrait.stderr
@@ -4,7 +4,7 @@ LL | trait NegSized: ?Sized { } | ^^^^^^ | - = note: traits are `?Sized` by default + = note: traits are not implicitly bounded by `Sized`, so there is nothing to relax error: relaxed bounds are not permitted in supertrait bounds --> $DIR/default-supertrait.rs:13:21 @@ -13,19 +13,63 @@ | ^^^^^^^^^^ error: relaxed bounds are not permitted in supertrait bounds - --> $DIR/default-supertrait.rs:19:24 + --> $DIR/default-supertrait.rs:21:24 | LL | trait NegPointeeSized: ?PointeeSized { } | ^^^^^^^^^^^^^ +error: bound modifier `?` can only be applied to `Sized` + --> $DIR/default-supertrait.rs:13:21 + | +LL | trait NegMetaSized: ?MetaSized { } + | ^^^^^^^^^^ + +error: bound modifier `?` can only be applied to `Sized` + --> $DIR/default-supertrait.rs:13:21 + | +LL | trait NegMetaSized: ?MetaSized { } + | ^^^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: bound modifier `?` can only be applied to `Sized` + --> $DIR/default-supertrait.rs:13:21 + | +LL | trait NegMetaSized: ?MetaSized { } + | ^^^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: bound modifier `?` can only be applied to `Sized` + --> $DIR/default-supertrait.rs:21:24 + | +LL | trait NegPointeeSized: ?PointeeSized { } + | ^^^^^^^^^^^^^ + +error: bound modifier `?` can only be applied to `Sized` + --> $DIR/default-supertrait.rs:21:24 + | +LL | trait NegPointeeSized: ?PointeeSized { } + | ^^^^^^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: bound modifier `?` can only be applied to `Sized` + --> $DIR/default-supertrait.rs:21:24 + | +LL | trait NegPointeeSized: ?PointeeSized { } + | ^^^^^^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + error[E0277]: the size for values of type `T` cannot be known - --> $DIR/default-supertrait.rs:52:38 + --> $DIR/default-supertrait.rs:57:38 | LL | fn with_bare_trait<T: PointeeSized + Bare>() { | ^^^^ doesn't have a known size | note: required by a bound in `Bare` - --> $DIR/default-supertrait.rs:22:1 + --> $DIR/default-supertrait.rs:27:1 | LL | trait Bare {} | ^^^^^^^^^^^^^ required by this bound in `Bare` @@ -35,7 +79,7 @@ | ++++++++++++++++++++++++ error[E0277]: the size for values of type `T` cannot be known at compilation time - --> $DIR/default-supertrait.rs:35:22 + --> $DIR/default-supertrait.rs:40:22 | LL | fn with_metasized_supertrait<T: PointeeSized + MetaSized_>() { | - this type parameter needs to be `Sized` @@ -43,13 +87,13 @@ | ^ doesn't have a size known at compile-time | note: required by a bound in `requires_sized` - --> $DIR/default-supertrait.rs:24:22 + --> $DIR/default-supertrait.rs:29:22 | LL | fn requires_sized<T: Sized>() {} | ^^^^^ required by this bound in `requires_sized` error[E0277]: the size for values of type `T` cannot be known at compilation time - --> $DIR/default-supertrait.rs:43:22 + --> $DIR/default-supertrait.rs:48:22 | LL | fn with_pointeesized_supertrait<T: PointeeSized + PointeeSized_>() { | - this type parameter needs to be `Sized` @@ -57,19 +101,19 @@ | ^ doesn't have a size known at compile-time | note: required by a bound in `requires_sized` - --> $DIR/default-supertrait.rs:24:22 + --> $DIR/default-supertrait.rs:29:22 | LL | fn requires_sized<T: Sized>() {} | ^^^^^ required by this bound in `requires_sized` error[E0277]: the size for values of type `T` cannot be known - --> $DIR/default-supertrait.rs:45:26 + --> $DIR/default-supertrait.rs:50:26 | LL | requires_metasized::<T>(); | ^ doesn't have a known size | note: required by a bound in `requires_metasized` - --> $DIR/default-supertrait.rs:25:26 + --> $DIR/default-supertrait.rs:30:26 | LL | fn requires_metasized<T: MetaSized>() {} | ^^^^^^^^^ required by this bound in `requires_metasized` @@ -79,7 +123,7 @@ | ++++++++++++++++++++++++ error[E0277]: the size for values of type `T` cannot be known at compilation time - --> $DIR/default-supertrait.rs:54:22 + --> $DIR/default-supertrait.rs:59:22 | LL | fn with_bare_trait<T: PointeeSized + Bare>() { | - this type parameter needs to be `Sized` @@ -88,19 +132,19 @@ | ^ doesn't have a size known at compile-time | note: required by a bound in `requires_sized` - --> $DIR/default-supertrait.rs:24:22 + --> $DIR/default-supertrait.rs:29:22 | LL | fn requires_sized<T: Sized>() {} | ^^^^^ required by this bound in `requires_sized` error[E0277]: the size for values of type `T` cannot be known - --> $DIR/default-supertrait.rs:56:26 + --> $DIR/default-supertrait.rs:61:26 | LL | requires_metasized::<T>(); | ^ doesn't have a known size | note: required by a bound in `requires_metasized` - --> $DIR/default-supertrait.rs:25:26 + --> $DIR/default-supertrait.rs:30:26 | LL | fn requires_metasized<T: MetaSized>() {} | ^^^^^^^^^ required by this bound in `requires_metasized` @@ -109,6 +153,6 @@ LL | fn with_bare_trait<T: PointeeSized + Bare + std::marker::MetaSized>() { | ++++++++++++++++++++++++ -error: aborting due to 9 previous errors +error: aborting due to 15 previous errors For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/sized-hierarchy/trait-aliases.rs b/tests/ui/sized-hierarchy/trait-aliases.rs deleted file mode 100644 index ffec302..0000000 --- a/tests/ui/sized-hierarchy/trait-aliases.rs +++ /dev/null
@@ -1,9 +0,0 @@ -//@ check-pass -//@ compile-flags: --crate-type=lib -#![feature(trait_alias)] - -// Checks that `?Sized` in a trait alias doesn't trigger an ICE. - -use std::ops::{Index, IndexMut}; - -pub trait SlicePrereq<T> = ?Sized + IndexMut<usize, Output = <[T] as Index<usize>>::Output>;
diff --git a/tests/ui/sized/relaxing-default-bound-error-37534.rs b/tests/ui/sized/relaxing-default-bound-error-37534.rs index d30e9f9..5aca030 100644 --- a/tests/ui/sized/relaxing-default-bound-error-37534.rs +++ b/tests/ui/sized/relaxing-default-bound-error-37534.rs
@@ -1,7 +1,5 @@ -struct Foo<T: ?Hash> {} -//~^ ERROR expected trait, found derive macro `Hash` -//~| ERROR bound modifier `?` can only be applied to `Sized` +// issue: <https://github.com/rust-lang/rust/issues/37534> + +struct Foo<T: ?Hash> {} //~ ERROR expected trait, found derive macro `Hash` fn main() {} - -// https://github.com/rust-lang/rust/issues/37534
diff --git a/tests/ui/sized/relaxing-default-bound-error-37534.stderr b/tests/ui/sized/relaxing-default-bound-error-37534.stderr index 8b9597f..5de8220 100644 --- a/tests/ui/sized/relaxing-default-bound-error-37534.stderr +++ b/tests/ui/sized/relaxing-default-bound-error-37534.stderr
@@ -1,5 +1,5 @@ error[E0404]: expected trait, found derive macro `Hash` - --> $DIR/relaxing-default-bound-error-37534.rs:1:16 + --> $DIR/relaxing-default-bound-error-37534.rs:3:16 | LL | struct Foo<T: ?Hash> {} | ^^^^ not a trait @@ -9,12 +9,6 @@ LL + use std::hash::Hash; | -error: bound modifier `?` can only be applied to `Sized` - --> $DIR/relaxing-default-bound-error-37534.rs:1:15 - | -LL | struct Foo<T: ?Hash> {} - | ^^^^^ - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0404`.
diff --git a/tests/ui/static/static_sized_requirement.rs b/tests/ui/static/static_sized_requirement.rs index 25e1359..a0f4759 100644 --- a/tests/ui/static/static_sized_requirement.rs +++ b/tests/ui/static/static_sized_requirement.rs
@@ -1,7 +1,7 @@ //@ add-core-stubs //@ check-pass -#![feature(no_core, lang_items)] +#![feature(no_core)] #![no_core] #![crate_type = "lib"]
diff --git a/tests/ui/track-diagnostics/track-caller-for-once-87707.rs b/tests/ui/sync/track-caller-for-once-87707.rs similarity index 100% rename from tests/ui/track-diagnostics/track-caller-for-once-87707.rs rename to tests/ui/sync/track-caller-for-once-87707.rs
diff --git a/tests/ui/track-diagnostics/track-caller-for-once-87707.run.stderr b/tests/ui/sync/track-caller-for-once-87707.run.stderr similarity index 100% rename from tests/ui/track-diagnostics/track-caller-for-once-87707.run.stderr rename to tests/ui/sync/track-caller-for-once-87707.run.stderr
diff --git a/tests/ui/target-feature/abi-incompatible-target-feature-attribute-fcw.rs b/tests/ui/target-feature/abi-incompatible-target-feature-attribute-fcw.rs index 41d5de8..a604a85 100644 --- a/tests/ui/target-feature/abi-incompatible-target-feature-attribute-fcw.rs +++ b/tests/ui/target-feature/abi-incompatible-target-feature-attribute-fcw.rs
@@ -1,18 +1,13 @@ //@ compile-flags: --crate-type=lib //@ compile-flags: --target=aarch64-unknown-none-softfloat //@ needs-llvm-components: aarch64 -#![feature(no_core, lang_items)] +//@ add-core-stubs +#![feature(no_core)] #![no_core] #![deny(aarch64_softfloat_neon)] -#[lang = "pointee_sized"] -pub trait PointeeSized {} - -#[lang = "meta_sized"] -pub trait MetaSized: PointeeSized {} - -#[lang = "sized"] -pub trait Sized: MetaSized {} +extern crate minicore; +use minicore::*; #[target_feature(enable = "neon")] //~^ERROR: enabling the `neon` target feature on the current target is unsound
diff --git a/tests/ui/target-feature/abi-incompatible-target-feature-attribute-fcw.stderr b/tests/ui/target-feature/abi-incompatible-target-feature-attribute-fcw.stderr index a8a7063..e3bb8be 100644 --- a/tests/ui/target-feature/abi-incompatible-target-feature-attribute-fcw.stderr +++ b/tests/ui/target-feature/abi-incompatible-target-feature-attribute-fcw.stderr
@@ -1,5 +1,5 @@ error: enabling the `neon` target feature on the current target is unsound due to ABI issues - --> $DIR/abi-incompatible-target-feature-attribute-fcw.rs:17:18 + --> $DIR/abi-incompatible-target-feature-attribute-fcw.rs:12:18 | LL | #[target_feature(enable = "neon")] | ^^^^^^^^^^^^^^^ @@ -7,7 +7,7 @@ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #134375 <https://github.com/rust-lang/rust/issues/134375> note: the lint level is defined here - --> $DIR/abi-incompatible-target-feature-attribute-fcw.rs:6:9 + --> $DIR/abi-incompatible-target-feature-attribute-fcw.rs:7:9 | LL | #![deny(aarch64_softfloat_neon)] | ^^^^^^^^^^^^^^^^^^^^^^ @@ -16,7 +16,7 @@ Future incompatibility report: Future breakage diagnostic: error: enabling the `neon` target feature on the current target is unsound due to ABI issues - --> $DIR/abi-incompatible-target-feature-attribute-fcw.rs:17:18 + --> $DIR/abi-incompatible-target-feature-attribute-fcw.rs:12:18 | LL | #[target_feature(enable = "neon")] | ^^^^^^^^^^^^^^^ @@ -24,7 +24,7 @@ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #134375 <https://github.com/rust-lang/rust/issues/134375> note: the lint level is defined here - --> $DIR/abi-incompatible-target-feature-attribute-fcw.rs:6:9 + --> $DIR/abi-incompatible-target-feature-attribute-fcw.rs:7:9 | LL | #![deny(aarch64_softfloat_neon)] | ^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/target-feature/abi-incompatible-target-feature-attribute.riscv.stderr b/tests/ui/target-feature/abi-incompatible-target-feature-attribute.riscv.stderr index dab21d1..27dd01c 100644 --- a/tests/ui/target-feature/abi-incompatible-target-feature-attribute.riscv.stderr +++ b/tests/ui/target-feature/abi-incompatible-target-feature-attribute.riscv.stderr
@@ -1,5 +1,5 @@ error: target feature `d` cannot be enabled with `#[target_feature]`: this feature is incompatible with the target ABI - --> $DIR/abi-incompatible-target-feature-attribute.rs:22:90 + --> $DIR/abi-incompatible-target-feature-attribute.rs:17:90 | LL | #[cfg_attr(x86, target_feature(enable = "soft-float"))] #[cfg_attr(riscv, target_feature(enable = "d"))] | ^^^^^^^^^^^^
diff --git a/tests/ui/target-feature/abi-incompatible-target-feature-attribute.rs b/tests/ui/target-feature/abi-incompatible-target-feature-attribute.rs index c99c78a..aab2be7a 100644 --- a/tests/ui/target-feature/abi-incompatible-target-feature-attribute.rs +++ b/tests/ui/target-feature/abi-incompatible-target-feature-attribute.rs
@@ -7,17 +7,12 @@ //@[riscv] compile-flags: --target=riscv32e-unknown-none-elf //@[riscv] needs-llvm-components: riscv //@ ignore-backends: gcc -#![feature(no_core, lang_items, riscv_target_feature, x87_target_feature)] +//@ add-core-stubs +#![feature(no_core, riscv_target_feature, x87_target_feature)] #![no_core] -#[lang = "pointee_sized"] -pub trait PointeeSized {} - -#[lang = "meta_sized"] -pub trait MetaSized: PointeeSized {} - -#[lang = "sized"] -pub trait Sized {} +extern crate minicore; +use minicore::*; #[cfg_attr(x86, target_feature(enable = "soft-float"))] #[cfg_attr(riscv, target_feature(enable = "d"))] //~^ERROR: cannot be enabled with
diff --git a/tests/ui/target-feature/abi-incompatible-target-feature-attribute.x86.stderr b/tests/ui/target-feature/abi-incompatible-target-feature-attribute.x86.stderr index ef6c8006..fd9d693 100644 --- a/tests/ui/target-feature/abi-incompatible-target-feature-attribute.x86.stderr +++ b/tests/ui/target-feature/abi-incompatible-target-feature-attribute.x86.stderr
@@ -1,5 +1,5 @@ error: target feature `soft-float` cannot be enabled with `#[target_feature]`: this feature is incompatible with the target ABI - --> $DIR/abi-incompatible-target-feature-attribute.rs:22:32 + --> $DIR/abi-incompatible-target-feature-attribute.rs:17:32 | LL | #[cfg_attr(x86, target_feature(enable = "soft-float"))] #[cfg_attr(riscv, target_feature(enable = "d"))] | ^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/target-feature/abi-incompatible-target-feature-flag-enable.rs b/tests/ui/target-feature/abi-incompatible-target-feature-flag-enable.rs index 71e25d5..ee932da 100644 --- a/tests/ui/target-feature/abi-incompatible-target-feature-flag-enable.rs +++ b/tests/ui/target-feature/abi-incompatible-target-feature-flag-enable.rs
@@ -6,22 +6,17 @@ //@[x86] compile-flags: --target=x86_64-unknown-linux-gnu -Ctarget-feature=+soft-float //@[x86] needs-llvm-components: x86 //@[riscv] compile-flags: --target=riscv32e-unknown-none-elf -Ctarget-feature=+d +// FIXME(#147881): *disable* the feature again for minicore as otherwise that will fail to build. +//@[riscv] core-stubs-compile-flags: -Ctarget-feature=-d //@[riscv] needs-llvm-components: riscv //@ ignore-backends: gcc +//@ add-core-stubs -#![feature(no_core, lang_items, riscv_target_feature)] +#![feature(no_core, riscv_target_feature)] #![no_core] -#[lang = "pointee_sized"] -pub trait PointeeSized {} - -#[lang = "meta_sized"] -pub trait MetaSized: PointeeSized {} - -#[lang = "sized"] -pub trait Sized {} -#[lang = "freeze"] -pub trait Freeze {} +extern crate minicore; +use minicore::*; //~? WARN must be disabled to ensure that the ABI of the current target can be implemented correctly //~? WARN unstable feature specified for `-Ctarget-feature`
diff --git a/tests/ui/target-feature/abi-irrelevant-target-feature-flag-disable.rs b/tests/ui/target-feature/abi-irrelevant-target-feature-flag-disable.rs index 1b4c7a6..e5fe9d1 100644 --- a/tests/ui/target-feature/abi-irrelevant-target-feature-flag-disable.rs +++ b/tests/ui/target-feature/abi-irrelevant-target-feature-flag-disable.rs
@@ -6,16 +6,11 @@ //@ compile-flags: -Ctarget-feature=-x87 //@ build-pass //@ ignore-backends: gcc -#![feature(no_core, lang_items)] +//@ add-core-stubs +#![feature(no_core)] #![no_core] -#[lang = "pointee_sized"] -pub trait PointeeSized {} - -#[lang = "meta_sized"] -pub trait MetaSized: PointeeSized {} - -#[lang = "sized"] -pub trait Sized: MetaSized {} +extern crate minicore; +use minicore::*; //~? WARN unstable feature specified for `-Ctarget-feature`: `x87`
diff --git a/tests/ui/target-feature/abi-required-target-feature-attribute.rs b/tests/ui/target-feature/abi-required-target-feature-attribute.rs index 3cd33d6..747c00e 100644 --- a/tests/ui/target-feature/abi-required-target-feature-attribute.rs +++ b/tests/ui/target-feature/abi-required-target-feature-attribute.rs
@@ -4,17 +4,12 @@ //@ needs-llvm-components: x86 //@ build-pass //@ ignore-backends: gcc -#![feature(no_core, lang_items, x87_target_feature)] +//@ add-core-stubs +#![feature(no_core, x87_target_feature)] #![no_core] -#[lang = "pointee_sized"] -pub trait PointeeSized {} - -#[lang = "meta_sized"] -pub trait MetaSized: PointeeSized {} - -#[lang = "sized"] -pub trait Sized: MetaSized {} +extern crate minicore; +use minicore::*; #[target_feature(enable = "x87")] pub unsafe fn my_fun() {}
diff --git a/tests/ui/target-feature/abi-required-target-feature-flag-disable.rs b/tests/ui/target-feature/abi-required-target-feature-flag-disable.rs index d66b36d..3b4bdb8 100644 --- a/tests/ui/target-feature/abi-required-target-feature-flag-disable.rs +++ b/tests/ui/target-feature/abi-required-target-feature-flag-disable.rs
@@ -17,18 +17,13 @@ // Remove some LLVM warnings that only show up sometimes. //@ normalize-stderr: "\n[^\n]*(target-abi|lp64f)[^\n]*" -> "" //@ ignore-backends: gcc +//@ add-core-stubs -#![feature(no_core, lang_items)] +#![feature(no_core)] #![no_core] -#[lang = "pointee_sized"] -pub trait PointeeSized {} - -#[lang = "meta_sized"] -pub trait MetaSized: PointeeSized {} - -#[lang = "sized"] -pub trait Sized {} +extern crate minicore; +use minicore::*; //~? WARN must be enabled to ensure that the ABI of the current target can be implemented correctly //[x86,riscv]~? WARN unstable feature specified for `-Ctarget-feature`
diff --git a/tests/ui/target-feature/feature-hierarchy.rs b/tests/ui/target-feature/feature-hierarchy.rs index ccf32a3..9ea24c1 100644 --- a/tests/ui/target-feature/feature-hierarchy.rs +++ b/tests/ui/target-feature/feature-hierarchy.rs
@@ -4,27 +4,16 @@ //@ [aarch64-sve2] compile-flags: -Ctarget-feature=-neon,+sve2 --target=aarch64-unknown-linux-gnu //@ [aarch64-sve2] needs-llvm-components: aarch64 //@ build-pass +//@ add-core-stubs #![no_core] #![crate_type = "rlib"] -#![feature(intrinsics, rustc_attrs, no_core, lang_items, staged_api)] +#![feature(intrinsics, rustc_attrs, no_core, staged_api)] #![stable(feature = "test", since = "1.0.0")] // Tests vetting "feature hierarchies" in the cases where we impose them. -// Supporting minimal rust core code -#[lang = "pointee_sized"] -trait PointeeSized {} - -#[lang = "meta_sized"] -trait MetaSized: PointeeSized {} - -#[lang = "sized"] -trait Sized: MetaSized {} - -#[lang = "copy"] -trait Copy {} - -impl Copy for bool {} +extern crate minicore; +use minicore::*; #[stable(feature = "test", since = "1.0.0")] #[rustc_const_stable(feature = "test", since = "1.0.0")]
diff --git a/tests/ui/target-feature/forbidden-hardfloat-target-feature-attribute-e-d.rs b/tests/ui/target-feature/forbidden-hardfloat-target-feature-attribute-e-d.rs index a8ff36d..975cf3e 100644 --- a/tests/ui/target-feature/forbidden-hardfloat-target-feature-attribute-e-d.rs +++ b/tests/ui/target-feature/forbidden-hardfloat-target-feature-attribute-e-d.rs
@@ -2,17 +2,12 @@ //@ compile-flags: --target=riscv32e-unknown-none-elf --crate-type=lib //@ needs-llvm-components: riscv //@ ignore-backends: gcc -#![feature(no_core, lang_items, riscv_target_feature)] +//@ add-core-stubs +#![feature(no_core, riscv_target_feature)] #![no_core] -#[lang = "pointee_sized"] -pub trait PointeeSized {} - -#[lang = "meta_sized"] -pub trait MetaSized: PointeeSized {} - -#[lang = "sized"] -pub trait Sized: MetaSized {} +extern crate minicore; +use minicore::*; #[target_feature(enable = "d")] //~^ERROR: cannot be enabled with
diff --git a/tests/ui/target-feature/forbidden-hardfloat-target-feature-attribute-e-d.stderr b/tests/ui/target-feature/forbidden-hardfloat-target-feature-attribute-e-d.stderr index 2efbd64..92e789e 100644 --- a/tests/ui/target-feature/forbidden-hardfloat-target-feature-attribute-e-d.stderr +++ b/tests/ui/target-feature/forbidden-hardfloat-target-feature-attribute-e-d.stderr
@@ -1,5 +1,5 @@ error: target feature `d` cannot be enabled with `#[target_feature]`: this feature is incompatible with the target ABI - --> $DIR/forbidden-hardfloat-target-feature-attribute-e-d.rs:17:18 + --> $DIR/forbidden-hardfloat-target-feature-attribute-e-d.rs:12:18 | LL | #[target_feature(enable = "d")] | ^^^^^^^^^^^^
diff --git a/tests/ui/target-feature/forbidden-hardfloat-target-feature-attribute-f-zfinx.rs b/tests/ui/target-feature/forbidden-hardfloat-target-feature-attribute-f-zfinx.rs index 9723e32..1570c8e 100644 --- a/tests/ui/target-feature/forbidden-hardfloat-target-feature-attribute-f-zfinx.rs +++ b/tests/ui/target-feature/forbidden-hardfloat-target-feature-attribute-f-zfinx.rs
@@ -2,17 +2,12 @@ //@ compile-flags: --target=riscv64gc-unknown-linux-gnu --crate-type=lib //@ needs-llvm-components: riscv //@ ignore-backends: gcc -#![feature(no_core, lang_items, riscv_target_feature)] +//@ add-core-stubs +#![feature(no_core, riscv_target_feature)] #![no_core] -#[lang = "pointee_sized"] -pub trait PointeeSized {} - -#[lang = "meta_sized"] -pub trait MetaSized: PointeeSized {} - -#[lang = "sized"] -pub trait Sized {} +extern crate minicore; +use minicore::*; #[target_feature(enable = "zdinx")] //~^ERROR: cannot be enabled with
diff --git a/tests/ui/target-feature/forbidden-hardfloat-target-feature-attribute-f-zfinx.stderr b/tests/ui/target-feature/forbidden-hardfloat-target-feature-attribute-f-zfinx.stderr index 713cb236..945ebd0 100644 --- a/tests/ui/target-feature/forbidden-hardfloat-target-feature-attribute-f-zfinx.stderr +++ b/tests/ui/target-feature/forbidden-hardfloat-target-feature-attribute-f-zfinx.stderr
@@ -1,5 +1,5 @@ error: target feature `zfinx` cannot be enabled with `#[target_feature]`: this feature is incompatible with the target ABI - --> $DIR/forbidden-hardfloat-target-feature-attribute-f-zfinx.rs:17:18 + --> $DIR/forbidden-hardfloat-target-feature-attribute-f-zfinx.rs:12:18 | LL | #[target_feature(enable = "zdinx")] | ^^^^^^^^^^^^^^^^
diff --git a/tests/ui/target-feature/forbidden-hardfloat-target-feature-cfg.rs b/tests/ui/target-feature/forbidden-hardfloat-target-feature-cfg.rs index 2692cf8..7e7d7fd 100644 --- a/tests/ui/target-feature/forbidden-hardfloat-target-feature-cfg.rs +++ b/tests/ui/target-feature/forbidden-hardfloat-target-feature-cfg.rs
@@ -1,18 +1,13 @@ //@ compile-flags: --target=x86_64-unknown-linux-gnu --crate-type=lib //@ needs-llvm-components: x86 //@ check-pass -#![feature(no_core, lang_items)] +//@ add-core-stubs +#![feature(no_core)] #![no_core] #![allow(unexpected_cfgs)] -#[lang = "pointee_sized"] -pub trait PointeeSized {} - -#[lang = "meta_sized"] -pub trait MetaSized: PointeeSized {} - -#[lang = "sized"] -pub trait Sized: MetaSized {} +extern crate minicore; +use minicore::*; // The compile_error macro does not exist, so if the `cfg` evaluates to `true` this // complains about the missing macro rather than showing the error... but that's good enough.
diff --git a/tests/ui/target-feature/forbidden-target-feature-attribute.rs b/tests/ui/target-feature/forbidden-target-feature-attribute.rs index ef4dcbb..d2c5f14 100644 --- a/tests/ui/target-feature/forbidden-target-feature-attribute.rs +++ b/tests/ui/target-feature/forbidden-target-feature-attribute.rs
@@ -2,17 +2,12 @@ //@ compile-flags: --target=riscv32e-unknown-none-elf --crate-type=lib //@ needs-llvm-components: riscv //@ ignore-backends: gcc -#![feature(no_core, lang_items)] +//@ add-core-stubs +#![feature(no_core)] #![no_core] -#[lang = "pointee_sized"] -pub trait PointeeSized {} - -#[lang = "meta_sized"] -pub trait MetaSized: PointeeSized {} - -#[lang = "sized"] -pub trait Sized: MetaSized {} +extern crate minicore; +use minicore::*; #[target_feature(enable = "forced-atomics")] //~^ERROR: cannot be enabled with
diff --git a/tests/ui/target-feature/forbidden-target-feature-attribute.stderr b/tests/ui/target-feature/forbidden-target-feature-attribute.stderr index f7f9614..f702dfd 100644 --- a/tests/ui/target-feature/forbidden-target-feature-attribute.stderr +++ b/tests/ui/target-feature/forbidden-target-feature-attribute.stderr
@@ -1,5 +1,5 @@ error: target feature `forced-atomics` cannot be enabled with `#[target_feature]`: unsound because it changes the ABI of atomic operations - --> $DIR/forbidden-target-feature-attribute.rs:17:18 + --> $DIR/forbidden-target-feature-attribute.rs:12:18 | LL | #[target_feature(enable = "forced-atomics")] | ^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/target-feature/forbidden-target-feature-cfg.rs b/tests/ui/target-feature/forbidden-target-feature-cfg.rs index 521f527..b61e83c 100644 --- a/tests/ui/target-feature/forbidden-target-feature-cfg.rs +++ b/tests/ui/target-feature/forbidden-target-feature-cfg.rs
@@ -3,18 +3,13 @@ //@ needs-llvm-components: riscv //@ check-pass //@ ignore-backends: gcc -#![feature(no_core, lang_items)] +//@ add-core-stubs +#![feature(no_core)] #![no_core] #![allow(unexpected_cfgs)] -#[lang = "pointee_sized"] -pub trait PointeeSized {} - -#[lang = "meta_sized"] -pub trait MetaSized: PointeeSized {} - -#[lang = "sized"] -pub trait Sized: MetaSized {} +extern crate minicore; +use minicore::*; // The compile_error macro does not exist, so if the `cfg` evaluates to `true` this // complains about the missing macro rather than showing the error... but that's good enough.
diff --git a/tests/ui/target-feature/forbidden-target-feature-flag-disable.rs b/tests/ui/target-feature/forbidden-target-feature-flag-disable.rs index d9d6cc4..f0f7770 100644 --- a/tests/ui/target-feature/forbidden-target-feature-flag-disable.rs +++ b/tests/ui/target-feature/forbidden-target-feature-flag-disable.rs
@@ -5,17 +5,12 @@ // For now this is just a warning. //@ build-pass //@ ignore-backends: gcc +//@ add-core-stubs -#![feature(no_core, lang_items)] +#![feature(no_core)] #![no_core] -#[lang = "pointee_sized"] -pub trait PointeeSized {} - -#[lang = "meta_sized"] -pub trait MetaSized: PointeeSized {} - -#[lang = "sized"] -pub trait Sized: MetaSized {} +extern crate minicore; +use minicore::*; //~? WARN target feature `forced-atomics` cannot be disabled with `-Ctarget-feature`: unsound because it changes the ABI of atomic operations
diff --git a/tests/ui/target-feature/forbidden-target-feature-flag.rs b/tests/ui/target-feature/forbidden-target-feature-flag.rs index bfacd7b..5cb3997 100644 --- a/tests/ui/target-feature/forbidden-target-feature-flag.rs +++ b/tests/ui/target-feature/forbidden-target-feature-flag.rs
@@ -5,17 +5,12 @@ // For now this is just a warning. //@ build-pass //@ ignore-backends: gcc +//@ add-core-stubs -#![feature(no_core, lang_items)] +#![feature(no_core)] #![no_core] -#[lang = "pointee_sized"] -pub trait PointeeSized {} - -#[lang = "meta_sized"] -pub trait MetaSized: PointeeSized {} - -#[lang = "sized"] -pub trait Sized: MetaSized {} +extern crate minicore; +use minicore::*; //~? WARN target feature `forced-atomics` cannot be enabled with `-Ctarget-feature`: unsound because it changes the ABI of atomic operations
diff --git a/tests/ui/target-feature/no-llvm-leaks.rs b/tests/ui/target-feature/no-llvm-leaks.rs index 50544b9..707e53f 100644 --- a/tests/ui/target-feature/no-llvm-leaks.rs +++ b/tests/ui/target-feature/no-llvm-leaks.rs
@@ -7,7 +7,7 @@ //@ build-pass #![no_core] #![crate_type = "rlib"] -#![feature(intrinsics, rustc_attrs, no_core, lang_items, staged_api)] +#![feature(intrinsics, rustc_attrs, no_core, staged_api)] #![stable(feature = "test", since = "1.0.0")] extern crate minicore;
diff --git a/tests/ui/target-feature/target-cpu-lacks-required-target-feature.rs b/tests/ui/target-feature/target-cpu-lacks-required-target-feature.rs index c4a5003..691be09 100644 --- a/tests/ui/target-feature/target-cpu-lacks-required-target-feature.rs +++ b/tests/ui/target-feature/target-cpu-lacks-required-target-feature.rs
@@ -4,17 +4,12 @@ // For now this is just a warning. //@ build-pass //@ ignore-backends: gcc +//@ add-core-stubs -#![feature(no_core, lang_items)] +#![feature(no_core)] #![no_core] -#[lang = "pointee_sized"] -pub trait PointeeSized {} - -#[lang = "meta_sized"] -pub trait MetaSized: PointeeSized {} - -#[lang = "sized"] -pub trait Sized: MetaSized {} +extern crate minicore; +use minicore::*; //~? WARN target feature `sse2` must be enabled to ensure that the ABI of the current target can be implemented correctly
diff --git a/tests/ui/target-feature/tied-features-cli.rs b/tests/ui/target-feature/tied-features-cli.rs index f60697c..020c3b1 100644 --- a/tests/ui/target-feature/tied-features-cli.rs +++ b/tests/ui/target-feature/tied-features-cli.rs
@@ -12,17 +12,14 @@ //@ [four] build-pass //@ [four] compile-flags: -C target-feature=-paca,+pacg -C target-feature=+paca //@ ignore-backends: gcc -#![feature(no_core, lang_items)] +//@ add-core-stubs +// FIXME(#147881): *disable* the features again for minicore as otherwise that will fail to build. +//@ core-stubs-compile-flags: -C target-feature=-pacg,-paca +#![feature(no_core)] #![no_core] -#[lang = "pointee_sized"] -pub trait PointeeSized {} - -#[lang = "meta_sized"] -pub trait MetaSized: PointeeSized {} - -#[lang = "sized"] -pub trait Sized: MetaSized {} +extern crate minicore; +use minicore::*; fn main() {}
diff --git a/tests/ui/target-feature/tied-features-no-implication-1.rs b/tests/ui/target-feature/tied-features-no-implication-1.rs index 9fcbe91..9cf6eb9 100644 --- a/tests/ui/target-feature/tied-features-no-implication-1.rs +++ b/tests/ui/target-feature/tied-features-no-implication-1.rs
@@ -4,17 +4,14 @@ //@[paca] compile-flags: -Ctarget-feature=+paca //@[pacg] compile-flags: -Ctarget-feature=+pacg //@ ignore-backends: gcc -#![feature(no_core, lang_items)] +//@ add-core-stubs +// FIXME(#147881): *disable* the features again for minicore as otherwise that will fail to build. +//@ core-stubs-compile-flags: -C target-feature=-pacg,-paca +#![feature(no_core)] #![no_core] -#[lang = "pointee_sized"] -pub trait PointeeSized {} - -#[lang = "meta_sized"] -pub trait MetaSized: PointeeSized {} - -#[lang = "sized"] -pub trait Sized: MetaSized {} +extern crate minicore; +use minicore::*; // In this test, demonstrate that +paca and +pacg both result in the tied feature error if there // isn't something causing an error.
diff --git a/tests/ui/target-feature/tied-features-no-implication.pacg.stderr b/tests/ui/target-feature/tied-features-no-implication.pacg.stderr index d5476fc..f82c500 100644 --- a/tests/ui/target-feature/tied-features-no-implication.pacg.stderr +++ b/tests/ui/target-feature/tied-features-no-implication.pacg.stderr
@@ -1,5 +1,5 @@ error[E0428]: the name `foo` is defined multiple times - --> $DIR/tied-features-no-implication.rs:34:1 + --> $DIR/tied-features-no-implication.rs:31:1 | LL | fn foo() {} | -------- previous definition of the value `foo` here
diff --git a/tests/ui/target-feature/tied-features-no-implication.rs b/tests/ui/target-feature/tied-features-no-implication.rs index 2000e00..821a3b8 100644 --- a/tests/ui/target-feature/tied-features-no-implication.rs +++ b/tests/ui/target-feature/tied-features-no-implication.rs
@@ -4,18 +4,15 @@ //@[paca] compile-flags: -Ctarget-feature=+paca //@[pacg] compile-flags: -Ctarget-feature=+pacg //@ ignore-backends: gcc +//@ add-core-stubs +// FIXME(#147881): *disable* the features again for minicore as otherwise that will fail to build. +//@ core-stubs-compile-flags: -C target-feature=-pacg,-paca -#![feature(no_core, lang_items)] +#![feature(no_core)] #![no_core] -#[lang = "pointee_sized"] -pub trait PointeeSized {} - -#[lang = "meta_sized"] -pub trait MetaSized: PointeeSized {} - -#[lang = "sized"] -pub trait Sized: MetaSized {} +extern crate minicore; +use minicore::*; // Can't use `compile_error!` here without `core`/`std` but requiring these makes this test only // work if you have libcore built in the sysroot for `aarch64-unknown-linux-gnu`. Can't run this
diff --git a/tests/ui/target-feature/tied-features.rs b/tests/ui/target-feature/tied-features.rs index 8861fb6..1c3b171 100644 --- a/tests/ui/target-feature/tied-features.rs +++ b/tests/ui/target-feature/tied-features.rs
@@ -2,7 +2,8 @@ //@ compile-flags: --crate-type=rlib --target=aarch64-unknown-linux-gnu //@ needs-llvm-components: aarch64 //@ ignore-backends: gcc -#![feature(no_core, lang_items)] +//@ add-core-stubs +#![feature(no_core)] #![no_core] extern crate minicore;
diff --git a/tests/ui/target-feature/tied-features.stderr b/tests/ui/target-feature/tied-features.stderr index b6a97fb..6a2c909 100644 --- a/tests/ui/target-feature/tied-features.stderr +++ b/tests/ui/target-feature/tied-features.stderr
@@ -1,5 +1,5 @@ error: the target features paca, pacg must all be either enabled or disabled together - --> $DIR/tied-features.rs:12:5 + --> $DIR/tied-features.rs:13:5 | LL | #[target_feature(enable = "pacg")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,7 +7,7 @@ = help: add the missing features in a `target_feature` attribute error: the target features paca, pacg must all be either enabled or disabled together - --> $DIR/tied-features.rs:24:1 + --> $DIR/tied-features.rs:25:1 | LL | #[target_feature(enable = "paca")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -15,7 +15,7 @@ = help: add the missing features in a `target_feature` attribute error: the target features paca, pacg must all be either enabled or disabled together - --> $DIR/tied-features.rs:37:1 + --> $DIR/tied-features.rs:38:1 | LL | #[target_feature(enable = "paca")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/issues/issue-70673.rs b/tests/ui/thread-local/thread-local-static-reference-70673.rs similarity index 100% rename from tests/ui/issues/issue-70673.rs rename to tests/ui/thread-local/thread-local-static-reference-70673.rs
diff --git a/tests/ui/trait-bounds/relaxed-bounds-assumed-unsized-87199.rs b/tests/ui/trait-bounds/invalid-bound-modifier-87199.rs similarity index 100% rename from tests/ui/trait-bounds/relaxed-bounds-assumed-unsized-87199.rs rename to tests/ui/trait-bounds/invalid-bound-modifier-87199.rs
diff --git a/tests/ui/trait-bounds/relaxed-bounds-assumed-unsized-87199.stderr b/tests/ui/trait-bounds/invalid-bound-modifier-87199.stderr similarity index 80% rename from tests/ui/trait-bounds/relaxed-bounds-assumed-unsized-87199.stderr rename to tests/ui/trait-bounds/invalid-bound-modifier-87199.stderr index 1622367..692f2d4 100644 --- a/tests/ui/trait-bounds/relaxed-bounds-assumed-unsized-87199.stderr +++ b/tests/ui/trait-bounds/invalid-bound-modifier-87199.stderr
@@ -1,23 +1,23 @@ error: bound modifier `?` can only be applied to `Sized` - --> $DIR/relaxed-bounds-assumed-unsized-87199.rs:9:11 + --> $DIR/invalid-bound-modifier-87199.rs:9:11 | LL | fn arg<T: ?Send>(_: T) {} | ^^^^^ error: bound modifier `?` can only be applied to `Sized` - --> $DIR/relaxed-bounds-assumed-unsized-87199.rs:11:15 + --> $DIR/invalid-bound-modifier-87199.rs:11:15 | LL | fn ref_arg<T: ?Send>(_: &T) {} | ^^^^^ error: bound modifier `?` can only be applied to `Sized` - --> $DIR/relaxed-bounds-assumed-unsized-87199.rs:13:40 + --> $DIR/invalid-bound-modifier-87199.rs:13:40 | LL | fn ret() -> impl Iterator<Item = ()> + ?Send { std::iter::empty() } | ^^^^^ error: bound modifier `?` can only be applied to `Sized` - --> $DIR/relaxed-bounds-assumed-unsized-87199.rs:13:40 + --> $DIR/invalid-bound-modifier-87199.rs:13:40 | LL | fn ret() -> impl Iterator<Item = ()> + ?Send { std::iter::empty() } | ^^^^^ @@ -25,14 +25,14 @@ = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0277]: the size for values of type `[i32]` cannot be known at compilation time - --> $DIR/relaxed-bounds-assumed-unsized-87199.rs:20:15 + --> $DIR/invalid-bound-modifier-87199.rs:20:15 | LL | ref_arg::<[i32]>(&[5]); | ^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `[i32]` note: required by an implicit `Sized` bound in `ref_arg` - --> $DIR/relaxed-bounds-assumed-unsized-87199.rs:11:12 + --> $DIR/invalid-bound-modifier-87199.rs:11:12 | LL | fn ref_arg<T: ?Send>(_: &T) {} | ^ required by the implicit `Sized` requirement on this type parameter in `ref_arg`
diff --git a/tests/ui/trait-bounds/more_maybe_bounds.rs b/tests/ui/trait-bounds/more_maybe_bounds.rs index ddd4313..e719327 100644 --- a/tests/ui/trait-bounds/more_maybe_bounds.rs +++ b/tests/ui/trait-bounds/more_maybe_bounds.rs
@@ -1,40 +1,40 @@ -// FIXME(more_maybe_bounds): Even under `more_maybe_bounds` / `-Zexperimental-default-bounds`, -// trying to relax non-default bounds should still be an error in all contexts! As you can see -// there are places like supertrait bounds, trait object types or associated type bounds (ATB) -// where we currently don't perform this check. #![feature(auto_traits, more_maybe_bounds, negative_impls)] trait Trait1 {} auto trait Trait2 {} -// FIXME: `?Trait1` should be rejected, `Trait1` isn't marked `#[lang = "default_traitN"]`. trait Trait3: ?Trait1 {} +//~^ ERROR bound modifier `?` can only be applied to default traits +//~| ERROR bound modifier `?` can only be applied to default traits +//~| ERROR bound modifier `?` can only be applied to default traits trait Trait4 where Self: Trait1 {} -// FIXME: `?Trait2` should be rejected, `Trait2` isn't marked `#[lang = "default_traitN"]`. + fn foo(_: Box<(dyn Trait3 + ?Trait2)>) {} +//~^ ERROR bound modifier `?` can only be applied to default traits fn bar<T: ?Sized + ?Trait2 + ?Trait1 + ?Trait4>(_: &T) {} -//~^ ERROR bound modifier `?` can only be applied to default traits like `Sized` -//~| ERROR bound modifier `?` can only be applied to default traits like `Sized` -//~| ERROR bound modifier `?` can only be applied to default traits like `Sized` +//~^ ERROR bound modifier `?` can only be applied to default traits +//~| ERROR bound modifier `?` can only be applied to default traits +//~| ERROR bound modifier `?` can only be applied to default traits -// FIXME: `?Trait1` should be rejected, `Trait1` isn't marked `#[lang = "default_traitN"]`. fn baz<T>() where T: Iterator<Item: ?Trait1> {} //~^ ERROR this relaxed bound is not permitted here +//~| ERROR bound modifier `?` can only be applied to default traits struct S1<T>(T); impl<T> S1<T> { fn f() where T: ?Trait1 {} //~^ ERROR this relaxed bound is not permitted here + //~| ERROR bound modifier `?` can only be applied to default traits } trait Trait5<'a> {} struct S2<T>(T) where for<'a> T: ?Trait5<'a>; //~^ ERROR this relaxed bound is not permitted here -//~| ERROR bound modifier `?` can only be applied to default traits like `Sized` +//~| ERROR bound modifier `?` can only be applied to default traits struct S; impl !Trait2 for S {}
diff --git a/tests/ui/trait-bounds/more_maybe_bounds.stderr b/tests/ui/trait-bounds/more_maybe_bounds.stderr index 0d78cfd..ef07921 100644 --- a/tests/ui/trait-bounds/more_maybe_bounds.stderr +++ b/tests/ui/trait-bounds/more_maybe_bounds.stderr
@@ -1,18 +1,18 @@ error: this relaxed bound is not permitted here - --> $DIR/more_maybe_bounds.rs:23:37 + --> $DIR/more_maybe_bounds.rs:21:37 | LL | fn baz<T>() where T: Iterator<Item: ?Trait1> {} | ^^^^^^^ | - = note: in this context, relaxed bounds are only allowed on type parameters defined by the closest item + = note: in this context, relaxed bounds are only allowed on type parameters defined on the closest item error: this relaxed bound is not permitted here - --> $DIR/more_maybe_bounds.rs:29:21 + --> $DIR/more_maybe_bounds.rs:28:21 | LL | fn f() where T: ?Trait1 {} | ^^^^^^^ | - = note: in this context, relaxed bounds are only allowed on type parameters defined by the closest item + = note: in this context, relaxed bounds are only allowed on type parameters defined on the closest item error: this relaxed bound is not permitted here --> $DIR/more_maybe_bounds.rs:35:34 @@ -20,31 +20,71 @@ LL | struct S2<T>(T) where for<'a> T: ?Trait5<'a>; | ^^^^^^^^^^^ | - = note: in this context, relaxed bounds are only allowed on type parameters defined by the closest item + = note: in this context, relaxed bounds are only allowed on type parameters defined on the closest item -error: bound modifier `?` can only be applied to default traits like `Sized` - --> $DIR/more_maybe_bounds.rs:17:20 +error: bound modifier `?` can only be applied to default traits + --> $DIR/more_maybe_bounds.rs:6:15 + | +LL | trait Trait3: ?Trait1 {} + | ^^^^^^^ + +error: bound modifier `?` can only be applied to default traits + --> $DIR/more_maybe_bounds.rs:6:15 + | +LL | trait Trait3: ?Trait1 {} + | ^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: bound modifier `?` can only be applied to default traits + --> $DIR/more_maybe_bounds.rs:6:15 + | +LL | trait Trait3: ?Trait1 {} + | ^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: bound modifier `?` can only be applied to default traits + --> $DIR/more_maybe_bounds.rs:13:29 + | +LL | fn foo(_: Box<(dyn Trait3 + ?Trait2)>) {} + | ^^^^^^^ + +error: bound modifier `?` can only be applied to default traits + --> $DIR/more_maybe_bounds.rs:16:20 | LL | fn bar<T: ?Sized + ?Trait2 + ?Trait1 + ?Trait4>(_: &T) {} | ^^^^^^^ -error: bound modifier `?` can only be applied to default traits like `Sized` - --> $DIR/more_maybe_bounds.rs:17:30 +error: bound modifier `?` can only be applied to default traits + --> $DIR/more_maybe_bounds.rs:16:30 | LL | fn bar<T: ?Sized + ?Trait2 + ?Trait1 + ?Trait4>(_: &T) {} | ^^^^^^^ -error: bound modifier `?` can only be applied to default traits like `Sized` - --> $DIR/more_maybe_bounds.rs:17:40 +error: bound modifier `?` can only be applied to default traits + --> $DIR/more_maybe_bounds.rs:16:40 | LL | fn bar<T: ?Sized + ?Trait2 + ?Trait1 + ?Trait4>(_: &T) {} | ^^^^^^^ -error: bound modifier `?` can only be applied to default traits like `Sized` +error: bound modifier `?` can only be applied to default traits + --> $DIR/more_maybe_bounds.rs:21:37 + | +LL | fn baz<T>() where T: Iterator<Item: ?Trait1> {} + | ^^^^^^^ + +error: bound modifier `?` can only be applied to default traits --> $DIR/more_maybe_bounds.rs:35:34 | LL | struct S2<T>(T) where for<'a> T: ?Trait5<'a>; | ^^^^^^^^^^^ -error: aborting due to 7 previous errors +error: bound modifier `?` can only be applied to default traits + --> $DIR/more_maybe_bounds.rs:28:21 + | +LL | fn f() where T: ?Trait1 {} + | ^^^^^^^ + +error: aborting due to 13 previous errors
diff --git a/tests/ui/issues/issue-69455.rs b/tests/ui/trait-bounds/projection-predicate-not-satisfied-69455.rs similarity index 100% rename from tests/ui/issues/issue-69455.rs rename to tests/ui/trait-bounds/projection-predicate-not-satisfied-69455.rs
diff --git a/tests/ui/issues/issue-69455.stderr b/tests/ui/trait-bounds/projection-predicate-not-satisfied-69455.stderr similarity index 87% rename from tests/ui/issues/issue-69455.stderr rename to tests/ui/trait-bounds/projection-predicate-not-satisfied-69455.stderr index d3e307f..48b3ba7 100644 --- a/tests/ui/issues/issue-69455.stderr +++ b/tests/ui/trait-bounds/projection-predicate-not-satisfied-69455.stderr
@@ -1,5 +1,5 @@ error[E0284]: type annotations needed - --> $DIR/issue-69455.rs:29:41 + --> $DIR/projection-predicate-not-satisfied-69455.rs:29:41 | LL | println!("{}", 23u64.test(xs.iter().sum())); | ---- ^^^ cannot infer type of the type parameter `S` declared on the method `sum` @@ -13,7 +13,7 @@ | +++++ error[E0283]: type annotations needed - --> $DIR/issue-69455.rs:29:41 + --> $DIR/projection-predicate-not-satisfied-69455.rs:29:41 | LL | println!("{}", 23u64.test(xs.iter().sum())); | ---- ^^^ cannot infer type of the type parameter `S` declared on the method `sum` @@ -21,7 +21,7 @@ | required by a bound introduced by this call | note: multiple `impl`s satisfying `u64: Test<_>` found - --> $DIR/issue-69455.rs:11:1 + --> $DIR/projection-predicate-not-satisfied-69455.rs:11:1 | LL | impl Test<u32> for u64 { | ^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/traits/alias/effectively-empty-trait-object-type.rs b/tests/ui/traits/alias/effectively-empty-trait-object-type.rs new file mode 100644 index 0000000..f7e8daa --- /dev/null +++ b/tests/ui/traits/alias/effectively-empty-trait-object-type.rs
@@ -0,0 +1,20 @@ +// Test that we reject trait object types that effectively (i.e., after trait alias expansion) +// don't contain any bounds. + +#![feature(trait_alias)] + +trait Empty0 =; + +// Nest a couple of levels deep: +trait Empty1 = Empty0; +trait Empty2 = Empty1; + +// Straight list expansion: +type Type0 = dyn Empty2; //~ ERROR at least one trait is required for an object type [E0224] + +// Twice: +trait Empty3 = Empty2 + Empty2; + +type Type1 = dyn Empty3; //~ ERROR at least one trait is required for an object type [E0224] + +fn main() {}
diff --git a/tests/ui/traits/alias/effectively-empty-trait-object-type.stderr b/tests/ui/traits/alias/effectively-empty-trait-object-type.stderr new file mode 100644 index 0000000..dbef9c3 --- /dev/null +++ b/tests/ui/traits/alias/effectively-empty-trait-object-type.stderr
@@ -0,0 +1,21 @@ +error[E0224]: at least one trait is required for an object type + --> $DIR/effectively-empty-trait-object-type.rs:13:14 + | +LL | trait Empty2 = Empty1; + | ------------ this alias does not contain a trait +... +LL | type Type0 = dyn Empty2; + | ^^^^^^^^^^ + +error[E0224]: at least one trait is required for an object type + --> $DIR/effectively-empty-trait-object-type.rs:18:14 + | +LL | trait Empty3 = Empty2 + Empty2; + | ------------ this alias does not contain a trait +LL | +LL | type Type1 = dyn Empty3; + | ^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0224`.
diff --git a/tests/ui/traits/alias/empty.rs b/tests/ui/traits/alias/empty.rs new file mode 100644 index 0000000..68d642f --- /dev/null +++ b/tests/ui/traits/alias/empty.rs
@@ -0,0 +1,17 @@ +// Ensure that there are straightforward ways to define "empty" / "trivial" / "unit" trait aliases +// which don't impose any constraints when used as a bound (since they expand to nothing). +//@ check-pass +#![feature(trait_alias)] + +trait Empty =; + +trait Trivial = where; + +trait Unit = where Self:; + +fn check<T: ?Sized + Empty>() {} + +fn main() { + check::<()>(); // OK. "`(): Empty`" is trivially satisfied + check::<str>(); // OK. `Empty` is truly empty and isn't implicitly bounded by `Sized`. +}
diff --git a/tests/ui/traits/alias/maybe-bound.rs b/tests/ui/traits/alias/maybe-bound.rs deleted file mode 100644 index 9fdeb71..0000000 --- a/tests/ui/traits/alias/maybe-bound.rs +++ /dev/null
@@ -1,29 +0,0 @@ -//@ build-pass (FIXME(62277): could be check-pass?) - -// Test that `dyn ... + ?Sized + ...` resulting from the expansion of trait aliases is okay. - -#![feature(trait_alias)] - -trait Foo {} - -trait S = ?Sized; - -// Nest a couple of levels deep: -trait _0 = S; -trait _1 = _0; - -// Straight list expansion: -type _T0 = dyn _1 + Foo; - -// In second position: -type _T1 = dyn Foo + _1; - -// ... and with an auto trait: -type _T2 = dyn Foo + Send + _1; - -// Twice: -trait _2 = _1 + _1; - -type _T3 = dyn _2 + Foo; - -fn main() {}
diff --git a/tests/ui/traits/alias/only-maybe-bound.rs b/tests/ui/traits/alias/only-maybe-bound.rs deleted file mode 100644 index e4abf31..0000000 --- a/tests/ui/traits/alias/only-maybe-bound.rs +++ /dev/null
@@ -1,22 +0,0 @@ -// Test that `dyn ?Sized` (i.e., a trait object with only a maybe buond) is not allowed, when just -// `?Sized` results from trait alias expansion. - -#![feature(trait_alias)] - -trait S = ?Sized; - -// Nest a couple of levels deep: -trait _0 = S; -trait _1 = _0; - -// Straight list expansion: -type _T0 = dyn _1; -//~^ ERROR at least one trait is required for an object type [E0224] - -// Twice: -trait _2 = _1 + _1; - -type _T1 = dyn _2; -//~^ ERROR at least one trait is required for an object type [E0224] - -fn main() {}
diff --git a/tests/ui/traits/alias/only-maybe-bound.stderr b/tests/ui/traits/alias/only-maybe-bound.stderr deleted file mode 100644 index 175ec81..0000000 --- a/tests/ui/traits/alias/only-maybe-bound.stderr +++ /dev/null
@@ -1,21 +0,0 @@ -error[E0224]: at least one trait is required for an object type - --> $DIR/only-maybe-bound.rs:13:12 - | -LL | trait _1 = _0; - | -------- this alias does not contain a trait -... -LL | type _T0 = dyn _1; - | ^^^^^^ - -error[E0224]: at least one trait is required for an object type - --> $DIR/only-maybe-bound.rs:19:12 - | -LL | trait _2 = _1 + _1; - | -------- this alias does not contain a trait -LL | -LL | type _T1 = dyn _2; - | ^^^^^^ - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0224`.
diff --git a/tests/ui/traits/alias/relaxed-bounds.rs b/tests/ui/traits/alias/relaxed-bounds.rs new file mode 100644 index 0000000..88e092c --- /dev/null +++ b/tests/ui/traits/alias/relaxed-bounds.rs
@@ -0,0 +1,19 @@ +#![feature(trait_alias)] + +// Ensure that relaxed bounds are not permitted in the `Self` bounds of trait aliases because trait +// aliases (like traits) aren't implicitly bounded by `Sized` so there's nothing to relax. + +trait Alias0 = ?Sized; //~ ERROR relaxed bounds are not permitted in trait alias bounds +trait Alias1 = where Self: ?Sized; //~ ERROR this relaxed bound is not permitted here + +trait Alias2<T: ?Sized> =; // OK +trait Alias3<T> = where T: ?Sized; // OK + +// Make sure that we don't permit "relaxing" trait aliases since we don't want to expand trait +// aliases during sized elaboration for simplicity as we'd need to handle relaxing arbitrary bounds +// (e.g., ones with modifiers, outlives-bounds, …) and where-clauses. + +trait SizedAlias = Sized; +fn take<T: ?SizedAlias>() {} //~ ERROR bound modifier `?` can only be applied to `Sized` + +fn main() {}
diff --git a/tests/ui/traits/alias/relaxed-bounds.stderr b/tests/ui/traits/alias/relaxed-bounds.stderr new file mode 100644 index 0000000..d7782b7 --- /dev/null +++ b/tests/ui/traits/alias/relaxed-bounds.stderr
@@ -0,0 +1,24 @@ +error: relaxed bounds are not permitted in trait alias bounds + --> $DIR/relaxed-bounds.rs:6:16 + | +LL | trait Alias0 = ?Sized; + | ^^^^^^ + | + = note: trait aliases are not implicitly bounded by `Sized`, so there is nothing to relax + +error: this relaxed bound is not permitted here + --> $DIR/relaxed-bounds.rs:7:28 + | +LL | trait Alias1 = where Self: ?Sized; + | ^^^^^^ + | + = note: in this context, relaxed bounds are only allowed on type parameters defined on the closest item + +error: bound modifier `?` can only be applied to `Sized` + --> $DIR/relaxed-bounds.rs:17:12 + | +LL | fn take<T: ?SizedAlias>() {} + | ^^^^^^^^^^^ + +error: aborting due to 3 previous errors +
diff --git a/tests/ui/issues/issue-73229.rs b/tests/ui/traits/callback-trait-implementation-73229.rs similarity index 89% rename from tests/ui/issues/issue-73229.rs rename to tests/ui/traits/callback-trait-implementation-73229.rs index 6d5eec2..56bcf7a 100644 --- a/tests/ui/issues/issue-73229.rs +++ b/tests/ui/traits/callback-trait-implementation-73229.rs
@@ -1,3 +1,4 @@ +// https://github.com/rust-lang/rust/issues/73229 //@ check-pass fn any<T>() -> T {
diff --git a/tests/ui/traits/const-traits/parse-const-unsafe-trait.rs b/tests/ui/traits/const-traits/parse-const-unsafe-trait.rs new file mode 100644 index 0000000..3d62405 --- /dev/null +++ b/tests/ui/traits/const-traits/parse-const-unsafe-trait.rs
@@ -0,0 +1,13 @@ +// Test that `const unsafe trait` and `const unsafe auto trait` works. + +//@ check-pass + +#![feature(const_trait_impl)] +#![feature(auto_traits)] + +pub const unsafe trait Owo {} +const unsafe trait OwO {} +pub const unsafe auto trait UwU {} +const unsafe auto trait Uwu {} + +fn main() {}
diff --git a/tests/ui/generics/duplicate-generic-parameter-error-86756.rs b/tests/ui/traits/duplicate-generic-parameter-error-86756.rs similarity index 100% rename from tests/ui/generics/duplicate-generic-parameter-error-86756.rs rename to tests/ui/traits/duplicate-generic-parameter-error-86756.rs
diff --git a/tests/ui/generics/duplicate-generic-parameter-error-86756.stderr b/tests/ui/traits/duplicate-generic-parameter-error-86756.stderr similarity index 100% rename from tests/ui/generics/duplicate-generic-parameter-error-86756.stderr rename to tests/ui/traits/duplicate-generic-parameter-error-86756.stderr
diff --git a/tests/ui/issues/issue-69602-type-err-during-codegen-ice.rs b/tests/ui/traits/trait-implementation-ambiguity-69602.rs similarity index 87% rename from tests/ui/issues/issue-69602-type-err-during-codegen-ice.rs rename to tests/ui/traits/trait-implementation-ambiguity-69602.rs index 2c5257c..74198b9 100644 --- a/tests/ui/issues/issue-69602-type-err-during-codegen-ice.rs +++ b/tests/ui/traits/trait-implementation-ambiguity-69602.rs
@@ -1,3 +1,4 @@ +// https://github.com/rust-lang/rust/issues/69602 trait TraitA { const VALUE: usize; }
diff --git a/tests/ui/issues/issue-69602-type-err-during-codegen-ice.stderr b/tests/ui/traits/trait-implementation-ambiguity-69602.stderr similarity index 81% rename from tests/ui/issues/issue-69602-type-err-during-codegen-ice.stderr rename to tests/ui/traits/trait-implementation-ambiguity-69602.stderr index fa1d7df..c771740 100644 --- a/tests/ui/issues/issue-69602-type-err-during-codegen-ice.stderr +++ b/tests/ui/traits/trait-implementation-ambiguity-69602.stderr
@@ -1,11 +1,11 @@ error[E0437]: type `M` is not a member of trait `TraitB` - --> $DIR/issue-69602-type-err-during-codegen-ice.rs:17:5 + --> $DIR/trait-implementation-ambiguity-69602.rs:18:5 | LL | type M = A; | ^^^^^^^^^^^^^ not a member of trait `TraitB` error[E0046]: not all trait items implemented, missing: `MyA` - --> $DIR/issue-69602-type-err-during-codegen-ice.rs:16:1 + --> $DIR/trait-implementation-ambiguity-69602.rs:17:1 | LL | type MyA: TraitA; | ---------------- `MyA` from trait
diff --git a/tests/ui/traits/wf-object/only-maybe-bound.rs b/tests/ui/traits/wf-object/only-maybe-bound.rs deleted file mode 100644 index 96360e0..0000000 --- a/tests/ui/traits/wf-object/only-maybe-bound.rs +++ /dev/null
@@ -1,7 +0,0 @@ -// Test that `dyn ?Sized` (i.e., a trait object with only a maybe buond) is not allowed. - -type _0 = dyn ?Sized; -//~^ ERROR at least one trait is required for an object type [E0224] -//~| ERROR relaxed bounds are not permitted in trait object types - -fn main() {}
diff --git a/tests/ui/traits/wf-object/only-maybe-bound.stderr b/tests/ui/traits/wf-object/only-maybe-bound.stderr deleted file mode 100644 index 6ae4568..0000000 --- a/tests/ui/traits/wf-object/only-maybe-bound.stderr +++ /dev/null
@@ -1,15 +0,0 @@ -error: relaxed bounds are not permitted in trait object types - --> $DIR/only-maybe-bound.rs:3:15 - | -LL | type _0 = dyn ?Sized; - | ^^^^^^ - -error[E0224]: at least one trait is required for an object type - --> $DIR/only-maybe-bound.rs:3:11 - | -LL | type _0 = dyn ?Sized; - | ^^^^^^^^^^ - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0224`.
diff --git a/tests/ui/typeck/return-unsized-coercion.rs b/tests/ui/typeck/return-unsized-coercion.rs new file mode 100644 index 0000000..17706ea --- /dev/null +++ b/tests/ui/typeck/return-unsized-coercion.rs
@@ -0,0 +1,8 @@ +// Regression test for issue <https://github.com/rust-lang/rust/issues/134355> + +fn digit() -> str { + //~^ ERROR the size for values of type `str` cannot be known at compilation time + return { i32::MIN }; +} + +fn main() {}
diff --git a/tests/ui/typeck/return-unsized-coercion.stderr b/tests/ui/typeck/return-unsized-coercion.stderr new file mode 100644 index 0000000..9736d26 --- /dev/null +++ b/tests/ui/typeck/return-unsized-coercion.stderr
@@ -0,0 +1,12 @@ +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/return-unsized-coercion.rs:3:15 + | +LL | fn digit() -> str { + | ^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `str` + = note: the return type of a function must have a statically known size + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/issues/issue-69683.rs b/tests/ui/typeck/type-inference-for-associated-types-69683.rs similarity index 90% rename from tests/ui/issues/issue-69683.rs rename to tests/ui/typeck/type-inference-for-associated-types-69683.rs index 7a76e9e..f18adca 100644 --- a/tests/ui/issues/issue-69683.rs +++ b/tests/ui/typeck/type-inference-for-associated-types-69683.rs
@@ -1,3 +1,4 @@ +// https://github.com/rust-lang/rust/issues/69683 pub trait Element<S> { type Array; }
diff --git a/tests/ui/issues/issue-69683.stderr b/tests/ui/typeck/type-inference-for-associated-types-69683.stderr similarity index 82% rename from tests/ui/issues/issue-69683.stderr rename to tests/ui/typeck/type-inference-for-associated-types-69683.stderr index b8e9e89..5d49d44 100644 --- a/tests/ui/issues/issue-69683.stderr +++ b/tests/ui/typeck/type-inference-for-associated-types-69683.stderr
@@ -1,5 +1,5 @@ error[E0284]: type annotations needed - --> $DIR/issue-69683.rs:30:10 + --> $DIR/type-inference-for-associated-types-69683.rs:31:10 | LL | 0u16.foo(b); | ^^^ @@ -12,13 +12,13 @@ | error[E0283]: type annotations needed - --> $DIR/issue-69683.rs:30:10 + --> $DIR/type-inference-for-associated-types-69683.rs:31:10 | LL | 0u16.foo(b); | ^^^ | note: multiple `impl`s satisfying `u8: Element<_>` found - --> $DIR/issue-69683.rs:5:1 + --> $DIR/type-inference-for-associated-types-69683.rs:6:1 | LL | impl<T> Element<()> for T { | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -26,7 +26,7 @@ LL | impl<T: Element<S>, S> Element<[S; 3]> for T { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: required by a bound in `Foo::foo` - --> $DIR/issue-69683.rs:15:9 + --> $DIR/type-inference-for-associated-types-69683.rs:16:9 | LL | u8: Element<I>, | ^^^^^^^^^^ required by this bound in `Foo::foo`
diff --git a/tests/ui/issues/issue-70746.rs b/tests/ui/unboxed-closures/callback-trait-prediction-70746.rs similarity index 91% rename from tests/ui/issues/issue-70746.rs rename to tests/ui/unboxed-closures/callback-trait-prediction-70746.rs index e7b4855..c0f0eb5 100644 --- a/tests/ui/issues/issue-70746.rs +++ b/tests/ui/unboxed-closures/callback-trait-prediction-70746.rs
@@ -1,3 +1,4 @@ +// https://github.com/rust-lang/rust/issues/70746 //@ check-pass pub trait Trait1 {
diff --git a/tests/ui/unboxed-closures/unboxed-closures-all-traits.rs b/tests/ui/unboxed-closures/unboxed-closures-all-traits.rs index 0ca4de5..c1020a0 100644 --- a/tests/ui/unboxed-closures/unboxed-closures-all-traits.rs +++ b/tests/ui/unboxed-closures/unboxed-closures-all-traits.rs
@@ -1,5 +1,4 @@ //@ run-pass -#![feature(lang_items)] fn a<F:Fn(isize, isize) -> isize>(f: F) -> isize { f(1, 2)
diff --git a/tests/ui/unboxed-closures/unboxed-closures-blanket-fn-mut.rs b/tests/ui/unboxed-closures/unboxed-closures-blanket-fn-mut.rs index 1cf4863..805af28 100644 --- a/tests/ui/unboxed-closures/unboxed-closures-blanket-fn-mut.rs +++ b/tests/ui/unboxed-closures/unboxed-closures-blanket-fn-mut.rs
@@ -2,8 +2,6 @@ #![allow(unused_variables)] // Test that you can supply `&F` where `F: FnMut()`. -#![feature(lang_items)] - fn a<F:FnMut() -> i32>(mut f: F) -> i32 { f() }
diff --git a/tests/ui/unboxed-closures/unboxed-closures-blanket-fn.rs b/tests/ui/unboxed-closures/unboxed-closures-blanket-fn.rs index 921bd94..c31e85e 100644 --- a/tests/ui/unboxed-closures/unboxed-closures-blanket-fn.rs +++ b/tests/ui/unboxed-closures/unboxed-closures-blanket-fn.rs
@@ -2,8 +2,6 @@ #![allow(unused_variables)] // Test that you can supply `&F` where `F: Fn()`. -#![feature(lang_items)] - fn a<F:Fn() -> i32>(f: F) -> i32 { f() }
diff --git a/tests/ui/thir-print/break-outside-loop-error-83048.rs b/tests/ui/unpretty/thir-tree-break-outside-loop-83048.rs similarity index 100% rename from tests/ui/thir-print/break-outside-loop-error-83048.rs rename to tests/ui/unpretty/thir-tree-break-outside-loop-83048.rs
diff --git a/tests/ui/thir-print/break-outside-loop-error-83048.stderr b/tests/ui/unpretty/thir-tree-break-outside-loop-83048.stderr similarity index 82% rename from tests/ui/thir-print/break-outside-loop-error-83048.stderr rename to tests/ui/unpretty/thir-tree-break-outside-loop-83048.stderr index 65a08e62e..72ae6ae 100644 --- a/tests/ui/thir-print/break-outside-loop-error-83048.stderr +++ b/tests/ui/unpretty/thir-tree-break-outside-loop-83048.stderr
@@ -1,5 +1,5 @@ error[E0268]: `break` outside of a loop or labeled block - --> $DIR/break-outside-loop-error-83048.rs:5:5 + --> $DIR/thir-tree-break-outside-loop-83048.rs:5:5 | LL | break; | ^^^^^ cannot `break` outside of a loop or labeled block
diff --git a/tests/ui/unsized/relaxed-bounds-invalid-places.rs b/tests/ui/unsized/relaxed-bounds-invalid-places.rs index 4c1f242..5aa1dbb 100644 --- a/tests/ui/unsized/relaxed-bounds-invalid-places.rs +++ b/tests/ui/unsized/relaxed-bounds-invalid-places.rs
@@ -30,6 +30,9 @@ trait Tr: ?Sized {} //~ ERROR relaxed bounds are not permitted in supertrait bou // Test that relaxed `Sized` bounds are rejected in trait object types: +type O0 = dyn ?Sized; +//~^ ERROR relaxed bounds are not permitted in trait object types +//~| ERROR at least one trait is required for an object type [E0224] type O1 = dyn Tr + ?Sized; //~ ERROR relaxed bounds are not permitted in trait object types type O2 = dyn ?Sized + ?Sized + Tr; //~^ ERROR relaxed bounds are not permitted in trait object types
diff --git a/tests/ui/unsized/relaxed-bounds-invalid-places.stderr b/tests/ui/unsized/relaxed-bounds-invalid-places.stderr index d3f0535..7f54d04 100644 --- a/tests/ui/unsized/relaxed-bounds-invalid-places.stderr +++ b/tests/ui/unsized/relaxed-bounds-invalid-places.stderr
@@ -4,7 +4,7 @@ LL | struct S1<T>(T) where (T): ?Sized; | ^^^^^^ | - = note: in this context, relaxed bounds are only allowed on type parameters defined by the closest item + = note: in this context, relaxed bounds are only allowed on type parameters defined on the closest item error: this relaxed bound is not permitted here --> $DIR/relaxed-bounds-invalid-places.rs:8:27 @@ -12,7 +12,7 @@ LL | struct S2<T>(T) where u8: ?Sized; | ^^^^^^ | - = note: in this context, relaxed bounds are only allowed on type parameters defined by the closest item + = note: in this context, relaxed bounds are only allowed on type parameters defined on the closest item error: this relaxed bound is not permitted here --> $DIR/relaxed-bounds-invalid-places.rs:10:35 @@ -20,7 +20,7 @@ LL | struct S3<T>(T) where &'static T: ?Sized; | ^^^^^^ | - = note: in this context, relaxed bounds are only allowed on type parameters defined by the closest item + = note: in this context, relaxed bounds are only allowed on type parameters defined on the closest item error: this relaxed bound is not permitted here --> $DIR/relaxed-bounds-invalid-places.rs:14:34 @@ -28,7 +28,7 @@ LL | struct S4<T>(T) where for<'a> T: ?Trait<'a>; | ^^^^^^^^^^ | - = note: in this context, relaxed bounds are only allowed on type parameters defined by the closest item + = note: in this context, relaxed bounds are only allowed on type parameters defined on the closest item error: this relaxed bound is not permitted here --> $DIR/relaxed-bounds-invalid-places.rs:22:21 @@ -36,7 +36,7 @@ LL | fn f() where T: ?Sized {} | ^^^^^^ | - = note: in this context, relaxed bounds are only allowed on type parameters defined by the closest item + = note: in this context, relaxed bounds are only allowed on type parameters defined on the closest item error: this relaxed bound is not permitted here --> $DIR/relaxed-bounds-invalid-places.rs:27:41 @@ -44,7 +44,7 @@ LL | struct S6<T>(T) where T: Iterator<Item: ?Sized>; | ^^^^^^ | - = note: in this context, relaxed bounds are only allowed on type parameters defined by the closest item + = note: in this context, relaxed bounds are only allowed on type parameters defined on the closest item error: relaxed bounds are not permitted in supertrait bounds --> $DIR/relaxed-bounds-invalid-places.rs:29:11 @@ -52,25 +52,39 @@ LL | trait Tr: ?Sized {} | ^^^^^^ | - = note: traits are `?Sized` by default + = note: traits are not implicitly bounded by `Sized`, so there is nothing to relax error: relaxed bounds are not permitted in trait object types - --> $DIR/relaxed-bounds-invalid-places.rs:33:20 + --> $DIR/relaxed-bounds-invalid-places.rs:33:15 + | +LL | type O0 = dyn ?Sized; + | ^^^^^^ + | + = note: trait object types are not implicitly bounded by `Sized`, so there is nothing to relax + +error: relaxed bounds are not permitted in trait object types + --> $DIR/relaxed-bounds-invalid-places.rs:36:20 | LL | type O1 = dyn Tr + ?Sized; | ^^^^^^ + | + = note: trait object types are not implicitly bounded by `Sized`, so there is nothing to relax error: relaxed bounds are not permitted in trait object types - --> $DIR/relaxed-bounds-invalid-places.rs:34:15 + --> $DIR/relaxed-bounds-invalid-places.rs:37:15 | LL | type O2 = dyn ?Sized + ?Sized + Tr; | ^^^^^^ + | + = note: trait object types are not implicitly bounded by `Sized`, so there is nothing to relax error: relaxed bounds are not permitted in trait object types - --> $DIR/relaxed-bounds-invalid-places.rs:34:24 + --> $DIR/relaxed-bounds-invalid-places.rs:37:24 | LL | type O2 = dyn ?Sized + ?Sized + Tr; | ^^^^^^ + | + = note: trait object types are not implicitly bounded by `Sized`, so there is nothing to relax error: bound modifier `?` can only be applied to `Sized` --> $DIR/relaxed-bounds-invalid-places.rs:14:34 @@ -84,5 +98,12 @@ LL | struct S5<T>(*const T) where T: ?Trait<'static> + ?Sized; | ^^^^^^^^^^^^^^^ -error: aborting due to 12 previous errors +error[E0224]: at least one trait is required for an object type + --> $DIR/relaxed-bounds-invalid-places.rs:33:11 + | +LL | type O0 = dyn ?Sized; + | ^^^^^^^^^^ +error: aborting due to 14 previous errors + +For more information about this error, try `rustc --explain E0224`.
diff --git a/triagebot.toml b/triagebot.toml index 605145f..fbe29dd 100644 --- a/triagebot.toml +++ b/triagebot.toml
@@ -1050,6 +1050,12 @@ [mentions."src/tools/compiletest"] cc = ["@jieyouxu"] +[mentions."src/tools/compiletest/src/directives"] +message = """ +`compiletest` directives have been modified. Please add or update docs for the +new or modified directive in `src/doc/rustc-dev-guide/`. +""" + [mentions."src/tools/miri"] message = "The Miri subtree was changed" cc = ["@rust-lang/miri"]