diff options
219 files changed, 2677 insertions, 1179 deletions
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 8160ed3cc46..87c9c797ea5 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -3661,15 +3661,19 @@ pub struct TyAlias { #[derive(Clone, Encodable, Decodable, Debug)] pub struct Impl { + pub generics: Generics, + pub of_trait: Option<Box<TraitImplHeader>>, + pub self_ty: Box<Ty>, + pub items: ThinVec<Box<AssocItem>>, +} + +#[derive(Clone, Encodable, Decodable, Debug)] +pub struct TraitImplHeader { pub defaultness: Defaultness, pub safety: Safety, - pub generics: Generics, pub constness: Const, pub polarity: ImplPolarity, - /// The trait being implemented, if any. - pub of_trait: Option<TraitRef>, - pub self_ty: Box<Ty>, - pub items: ThinVec<Box<AssocItem>>, + pub trait_ref: TraitRef, } #[derive(Clone, Encodable, Decodable, Debug, Default, Walkable)] @@ -3793,7 +3797,7 @@ pub enum ItemKind { /// An implementation. /// /// E.g., `impl<A> Foo<A> { .. }` or `impl<A> Trait for Foo<A> { .. }`. - Impl(Box<Impl>), + Impl(Impl), /// A macro invocation. /// /// E.g., `foo!(..)`. @@ -3880,7 +3884,7 @@ impl ItemKind { | Self::Union(_, generics, _) | Self::Trait(box Trait { generics, .. }) | Self::TraitAlias(_, generics, _) - | Self::Impl(box Impl { generics, .. }) => Some(generics), + | Self::Impl(Impl { generics, .. }) => Some(generics), _ => None, } } @@ -4040,7 +4044,7 @@ mod size_asserts { static_assert_size!(GenericArg, 24); static_assert_size!(GenericBound, 88); static_assert_size!(Generics, 40); - static_assert_size!(Impl, 136); + static_assert_size!(Impl, 64); static_assert_size!(Item, 144); static_assert_size!(ItemKind, 80); static_assert_size!(LitKind, 24); @@ -4053,6 +4057,7 @@ mod size_asserts { static_assert_size!(PathSegment, 24); static_assert_size!(Stmt, 32); static_assert_size!(StmtKind, 16); + static_assert_size!(TraitImplHeader, 80); static_assert_size!(Ty, 64); static_assert_size!(TyKind, 40); // tidy-alphabetical-end diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index 5fdce27db53..68b3d2b0368 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -929,8 +929,13 @@ macro_rules! common_visitor_and_walkers { } impl_walkable!(|&$($mut)? $($lt)? self: Impl, vis: &mut V| { - let Impl { defaultness, safety, generics, constness, polarity, of_trait, self_ty, items } = self; - visit_visitable!($($mut)? vis, defaultness, safety, generics, constness, polarity, of_trait, self_ty); + let Impl { generics, of_trait, self_ty, items } = self; + try_visit!(vis.visit_generics(generics)); + if let Some(box of_trait) = of_trait { + let TraitImplHeader { defaultness, safety, constness, polarity, trait_ref } = of_trait; + visit_visitable!($($mut)? vis, defaultness, safety, constness, polarity, trait_ref); + } + try_visit!(vis.visit_ty(self_ty)); visit_visitable_with!($($mut)? vis, items, AssocCtxt::Impl { of_trait: of_trait.is_some() }); V::Result::output() }); diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index ac6fac4c08e..235573c96e4 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -340,13 +340,9 @@ impl<'hir> LoweringContext<'_, 'hir> { ); hir::ItemKind::Union(ident, generics, vdata) } - ItemKind::Impl(box Impl { - safety, - polarity, - defaultness, - constness, + ItemKind::Impl(Impl { generics: ast_generics, - of_trait: trait_ref, + of_trait, self_ty: ty, items: impl_items, }) => { @@ -364,54 +360,30 @@ impl<'hir> LoweringContext<'_, 'hir> { // lifetime to be added, but rather a reference to a // parent lifetime. let itctx = ImplTraitContext::Universal; - let (generics, (trait_ref, lowered_ty)) = + let (generics, (of_trait, lowered_ty)) = self.lower_generics(ast_generics, id, itctx, |this| { - let modifiers = TraitBoundModifiers { - constness: BoundConstness::Never, - asyncness: BoundAsyncness::Normal, - // we don't use this in bound lowering - polarity: BoundPolarity::Positive, - }; - - let trait_ref = trait_ref.as_ref().map(|trait_ref| { - this.lower_trait_ref( - modifiers, - trait_ref, - ImplTraitContext::Disallowed(ImplTraitPosition::Trait), - ) - }); + let of_trait = of_trait + .as_deref() + .map(|of_trait| this.lower_trait_impl_header(of_trait)); let lowered_ty = this.lower_ty( ty, ImplTraitContext::Disallowed(ImplTraitPosition::ImplSelf), ); - (trait_ref, lowered_ty) + (of_trait, lowered_ty) }); let new_impl_items = self .arena .alloc_from_iter(impl_items.iter().map(|item| self.lower_impl_item_ref(item))); - // `defaultness.has_value()` is never called for an `impl`, always `true` in order - // to not cause an assertion failure inside the `lower_defaultness` function. - let has_val = true; - let (defaultness, defaultness_span) = self.lower_defaultness(*defaultness, has_val); - let polarity = match polarity { - ImplPolarity::Positive => ImplPolarity::Positive, - ImplPolarity::Negative(s) => ImplPolarity::Negative(self.lower_span(*s)), - }; - hir::ItemKind::Impl(self.arena.alloc(hir::Impl { - constness: self.lower_constness(*constness), - safety: self.lower_safety(*safety, hir::Safety::Safe), - polarity, - defaultness, - defaultness_span, + hir::ItemKind::Impl(hir::Impl { generics, - of_trait: trait_ref, + of_trait, self_ty: lowered_ty, items: new_impl_items, - })) + }) } ItemKind::Trait(box Trait { constness, @@ -982,6 +954,44 @@ impl<'hir> LoweringContext<'_, 'hir> { self.expr(span, hir::ExprKind::Err(guar)) } + fn lower_trait_impl_header( + &mut self, + trait_impl_header: &TraitImplHeader, + ) -> &'hir hir::TraitImplHeader<'hir> { + let TraitImplHeader { constness, safety, polarity, defaultness, ref trait_ref } = + *trait_impl_header; + let constness = self.lower_constness(constness); + let safety = self.lower_safety(safety, hir::Safety::Safe); + let polarity = match polarity { + ImplPolarity::Positive => ImplPolarity::Positive, + ImplPolarity::Negative(s) => ImplPolarity::Negative(self.lower_span(s)), + }; + // `defaultness.has_value()` is never called for an `impl`, always `true` in order + // to not cause an assertion failure inside the `lower_defaultness` function. + let has_val = true; + let (defaultness, defaultness_span) = self.lower_defaultness(defaultness, has_val); + let modifiers = TraitBoundModifiers { + constness: BoundConstness::Never, + asyncness: BoundAsyncness::Normal, + // we don't use this in bound lowering + polarity: BoundPolarity::Positive, + }; + let trait_ref = self.lower_trait_ref( + modifiers, + trait_ref, + ImplTraitContext::Disallowed(ImplTraitPosition::Trait), + ); + + self.arena.alloc(hir::TraitImplHeader { + constness, + safety, + polarity, + defaultness, + defaultness_span, + trait_ref, + }) + } + fn lower_impl_item( &mut self, i: &AssocItem, diff --git a/compiler/rustc_ast_passes/messages.ftl b/compiler/rustc_ast_passes/messages.ftl index 53e64439afc..340a1a239c5 100644 --- a/compiler/rustc_ast_passes/messages.ftl +++ b/compiler/rustc_ast_passes/messages.ftl @@ -175,11 +175,6 @@ ast_passes_generic_default_trailing = generic parameters with a default must be ast_passes_incompatible_features = `{$f1}` and `{$f2}` are incompatible, using them at the same time is not allowed .help = remove one of these features -ast_passes_inherent_cannot_be = inherent impls cannot be {$annotation} - .because = {$annotation} because of this - .type = inherent impl for this type - .only_trait = only trait implementations may be annotated with {$annotation} - ast_passes_item_invalid_safety = items outside of `unsafe extern {"{ }"}` cannot be declared with `safe` safety qualifier .suggestion = remove safe from this item diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 9d3b0969ef3..dc2eb17589c 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -954,13 +954,16 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } match &item.kind { - ItemKind::Impl(box Impl { - safety, - polarity, - defaultness: _, - constness, + ItemKind::Impl(Impl { generics, - of_trait: Some(t), + of_trait: + Some(box TraitImplHeader { + safety, + polarity, + defaultness: _, + constness, + trait_ref: t, + }), self_ty, items, }) => { @@ -992,46 +995,12 @@ impl<'a> Visitor<'a> for AstValidator<'a> { walk_list!(this, visit_assoc_item, items, AssocCtxt::Impl { of_trait: true }); }); } - ItemKind::Impl(box Impl { - safety, - polarity, - defaultness, - constness, - generics, - of_trait: None, - self_ty, - items, - }) => { - let error = |annotation_span, annotation, only_trait| errors::InherentImplCannot { - span: self_ty.span, - annotation_span, - annotation, - self_ty: self_ty.span, - only_trait, - }; - + ItemKind::Impl(Impl { generics, of_trait: None, self_ty, items }) => { self.visit_attrs_vis(&item.attrs, &item.vis); self.visibility_not_permitted( &item.vis, errors::VisibilityNotPermittedNote::IndividualImplItems, ); - if let &Safety::Unsafe(span) = safety { - self.dcx().emit_err(errors::InherentImplCannotUnsafe { - span: self_ty.span, - annotation_span: span, - annotation: "unsafe", - self_ty: self_ty.span, - }); - } - if let &ImplPolarity::Negative(span) = polarity { - self.dcx().emit_err(error(span, "negative", false)); - } - if let &Defaultness::Default(def_span) = defaultness { - self.dcx().emit_err(error(def_span, "`default`", true)); - } - if let &Const::Yes(span) = constness { - self.dcx().emit_err(error(span, "`const`", true)); - } self.with_tilde_const(Some(TildeConstReason::Impl { span: item.span }), |this| { this.visit_generics(generics) diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs index 60f47490f12..1cb2493afe8 100644 --- a/compiler/rustc_ast_passes/src/errors.rs +++ b/compiler/rustc_ast_passes/src/errors.rs @@ -465,32 +465,6 @@ pub(crate) struct UnsafeNegativeImpl { } #[derive(Diagnostic)] -#[diag(ast_passes_inherent_cannot_be)] -pub(crate) struct InherentImplCannot<'a> { - #[primary_span] - pub span: Span, - #[label(ast_passes_because)] - pub annotation_span: Span, - pub annotation: &'a str, - #[label(ast_passes_type)] - pub self_ty: Span, - #[note(ast_passes_only_trait)] - pub only_trait: bool, -} - -#[derive(Diagnostic)] -#[diag(ast_passes_inherent_cannot_be, code = E0197)] -pub(crate) struct InherentImplCannotUnsafe<'a> { - #[primary_span] - pub span: Span, - #[label(ast_passes_because)] - pub annotation_span: Span, - pub annotation: &'a str, - #[label(ast_passes_type)] - pub self_ty: Span, -} - -#[derive(Diagnostic)] #[diag(ast_passes_unsafe_item)] pub(crate) struct UnsafeItem { #[primary_span] diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 662357ce884..c9344a76a7b 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -217,18 +217,18 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { } } - ast::ItemKind::Impl(box ast::Impl { polarity, defaultness, of_trait, .. }) => { - if let &ast::ImplPolarity::Negative(span) = polarity { + ast::ItemKind::Impl(ast::Impl { of_trait: Some(of_trait), .. }) => { + if let ast::ImplPolarity::Negative(span) = of_trait.polarity { gate!( &self, negative_impls, - span.to(of_trait.as_ref().map_or(span, |t| t.path.span)), + span.to(of_trait.trait_ref.path.span), "negative trait bounds are not fully implemented; \ use marker types for now" ); } - if let ast::Defaultness::Default(_) = defaultness { + if let ast::Defaultness::Default(_) = of_trait.defaultness { gate!(&self, specialization, i.span, "specialization is unstable"); } } diff --git a/compiler/rustc_ast_pretty/src/pprust/state/item.rs b/compiler/rustc_ast_pretty/src/pprust/state/item.rs index 6e34d1b61db..ab402cbb8dc 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state/item.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state/item.rs @@ -308,39 +308,41 @@ impl<'a> State<'a> { let (cb, ib) = self.head(visibility_qualified(&item.vis, "union")); self.print_struct(struct_def, generics, *ident, item.span, true, cb, ib); } - ast::ItemKind::Impl(box ast::Impl { - safety, - polarity, - defaultness, - constness, - generics, - of_trait, - self_ty, - items, - }) => { + ast::ItemKind::Impl(ast::Impl { generics, of_trait, self_ty, items }) => { let (cb, ib) = self.head(""); self.print_visibility(&item.vis); - self.print_defaultness(*defaultness); - self.print_safety(*safety); - self.word("impl"); - - if generics.params.is_empty() { - self.nbsp(); - } else { - self.print_generic_params(&generics.params); - self.space(); - } - self.print_constness(*constness); + let impl_generics = |this: &mut Self| { + this.word("impl"); - if let ast::ImplPolarity::Negative(_) = polarity { - self.word("!"); - } - - if let Some(t) = of_trait { - self.print_trait_ref(t); + if generics.params.is_empty() { + this.nbsp(); + } else { + this.print_generic_params(&generics.params); + this.space(); + } + }; + + if let Some(box of_trait) = of_trait { + let ast::TraitImplHeader { + defaultness, + safety, + constness, + polarity, + ref trait_ref, + } = *of_trait; + self.print_defaultness(defaultness); + self.print_safety(safety); + impl_generics(self); + self.print_constness(constness); + if let ast::ImplPolarity::Negative(_) = polarity { + self.word("!"); + } + self.print_trait_ref(trait_ref); self.space(); self.word_space("for"); + } else { + impl_generics(self); } self.print_type(self_ty); diff --git a/compiler/rustc_attr_parsing/messages.ftl b/compiler/rustc_attr_parsing/messages.ftl index 35ff48cb5f2..de22ea322c7 100644 --- a/compiler/rustc_attr_parsing/messages.ftl +++ b/compiler/rustc_attr_parsing/messages.ftl @@ -132,6 +132,7 @@ attr_parsing_unknown_version_literal = attr_parsing_unrecognized_repr_hint = unrecognized representation hint .help = valid reprs are `Rust` (default), `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize` + .note = for more information, visit <https://doc.rust-lang.org/reference/type-layout.html?highlight=repr#representations> attr_parsing_unstable_cfg_target_compact = compact `cfg(target(..))` is experimental and subject to change diff --git a/compiler/rustc_attr_parsing/src/attributes/allow_unstable.rs b/compiler/rustc_attr_parsing/src/attributes/allow_unstable.rs index 95104b896ac..b3393e93de8 100644 --- a/compiler/rustc_attr_parsing/src/attributes/allow_unstable.rs +++ b/compiler/rustc_attr_parsing/src/attributes/allow_unstable.rs @@ -15,7 +15,7 @@ impl<S: Stage> CombineAttributeParser<S> for AllowInternalUnstableParser { type Item = (Symbol, Span); const CONVERT: ConvertFn<Self::Item> = |items, span| AttributeKind::AllowInternalUnstable(items, span); - const TEMPLATE: AttributeTemplate = template!(Word, List: "feat1, feat2, ..."); + const TEMPLATE: AttributeTemplate = template!(Word, List: &["feat1, feat2, ..."]); fn extend<'c>( cx: &'c mut AcceptContext<'_, '_, S>, @@ -32,7 +32,7 @@ impl<S: Stage> CombineAttributeParser<S> for UnstableFeatureBoundParser { const PATH: &'static [rustc_span::Symbol] = &[sym::unstable_feature_bound]; type Item = (Symbol, Span); const CONVERT: ConvertFn<Self::Item> = |items, _| AttributeKind::UnstableFeatureBound(items); - const TEMPLATE: AttributeTemplate = template!(Word, List: "feat1, feat2, ..."); + const TEMPLATE: AttributeTemplate = template!(Word, List: &["feat1, feat2, ..."]); fn extend<'c>( cx: &'c mut AcceptContext<'_, '_, S>, @@ -53,7 +53,7 @@ impl<S: Stage> CombineAttributeParser<S> for AllowConstFnUnstableParser { type Item = Symbol; const CONVERT: ConvertFn<Self::Item> = |items, first_span| AttributeKind::AllowConstFnUnstable(items, first_span); - const TEMPLATE: AttributeTemplate = template!(Word, List: "feat1, feat2, ..."); + const TEMPLATE: AttributeTemplate = template!(Word, List: &["feat1, feat2, ..."]); fn extend<'c>( cx: &'c mut AcceptContext<'_, '_, S>, diff --git a/compiler/rustc_attr_parsing/src/attributes/cfg.rs b/compiler/rustc_attr_parsing/src/attributes/cfg.rs index 947be28bc95..695ee666476 100644 --- a/compiler/rustc_attr_parsing/src/attributes/cfg.rs +++ b/compiler/rustc_attr_parsing/src/attributes/cfg.rs @@ -16,7 +16,10 @@ use crate::{ CfgMatchesLintEmitter, fluent_generated, parse_version, session_diagnostics, try_gate_cfg, }; -pub const CFG_TEMPLATE: AttributeTemplate = template!(List: "predicate"); +pub const CFG_TEMPLATE: AttributeTemplate = template!( + List: &["predicate"], + "https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg-attribute" +); pub fn parse_cfg_attr<'c, S: Stage>( cx: &'c mut AcceptContext<'_, '_, S>, diff --git a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs index c5fb11dbf6a..a9f77195d1b 100644 --- a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs @@ -17,7 +17,7 @@ impl<S: Stage> SingleAttributeParser<S> for OptimizeParser { const PATH: &[Symbol] = &[sym::optimize]; const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost; const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError; - const TEMPLATE: AttributeTemplate = template!(List: "size|speed|none"); + const TEMPLATE: AttributeTemplate = template!(List: &["size", "speed", "none"]); fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> { let Some(list) = args.list() else { @@ -253,7 +253,7 @@ pub(crate) struct UsedParser { impl<S: Stage> AttributeParser<S> for UsedParser { const ATTRIBUTES: AcceptMapping<Self, S> = &[( &[sym::used], - template!(Word, List: "compiler|linker"), + template!(Word, List: &["compiler", "linker"]), |group: &mut Self, cx, args| { let used_by = match args { ArgParser::NoArgs => UsedBy::Linker, @@ -327,7 +327,7 @@ impl<S: Stage> CombineAttributeParser<S> for TargetFeatureParser { type Item = (Symbol, Span); const PATH: &[Symbol] = &[sym::target_feature]; const CONVERT: ConvertFn<Self::Item> = |items, span| AttributeKind::TargetFeature(items, span); - const TEMPLATE: AttributeTemplate = template!(List: "enable = \"feat1, feat2\""); + const TEMPLATE: AttributeTemplate = template!(List: &["enable = \"feat1, feat2\""]); fn extend<'c>( cx: &'c mut AcceptContext<'_, '_, S>, diff --git a/compiler/rustc_attr_parsing/src/attributes/confusables.rs b/compiler/rustc_attr_parsing/src/attributes/confusables.rs index 7d24c89a6e8..edd22172ca2 100644 --- a/compiler/rustc_attr_parsing/src/attributes/confusables.rs +++ b/compiler/rustc_attr_parsing/src/attributes/confusables.rs @@ -16,7 +16,7 @@ pub(crate) struct ConfusablesParser { impl<S: Stage> AttributeParser<S> for ConfusablesParser { const ATTRIBUTES: AcceptMapping<Self, S> = &[( &[sym::rustc_confusables], - template!(List: r#""name1", "name2", ..."#), + template!(List: &[r#""name1", "name2", ..."#]), |this, cx, args| { let Some(list) = args.list() else { cx.expected_list(cx.attr_span); diff --git a/compiler/rustc_attr_parsing/src/attributes/deprecation.rs b/compiler/rustc_attr_parsing/src/attributes/deprecation.rs index 38ec4bd5645..e57ea8bbb5c 100644 --- a/compiler/rustc_attr_parsing/src/attributes/deprecation.rs +++ b/compiler/rustc_attr_parsing/src/attributes/deprecation.rs @@ -40,7 +40,7 @@ impl<S: Stage> SingleAttributeParser<S> for DeprecationParser { const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error; const TEMPLATE: AttributeTemplate = template!( Word, - List: r#"/*opt*/ since = "version", /*opt*/ note = "reason""#, + List: &[r#"since = "version""#, r#"note = "reason""#, r#"since = "version", note = "reason""#], NameValueStr: "reason" ); diff --git a/compiler/rustc_attr_parsing/src/attributes/inline.rs b/compiler/rustc_attr_parsing/src/attributes/inline.rs index 8437713206e..e9a45f20bff 100644 --- a/compiler/rustc_attr_parsing/src/attributes/inline.rs +++ b/compiler/rustc_attr_parsing/src/attributes/inline.rs @@ -18,7 +18,11 @@ impl<S: Stage> SingleAttributeParser<S> for InlineParser { const PATH: &'static [Symbol] = &[sym::inline]; const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost; const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError; - const TEMPLATE: AttributeTemplate = template!(Word, List: "always|never"); + const TEMPLATE: AttributeTemplate = template!( + Word, + List: &["always", "never"], + "https://doc.rust-lang.org/reference/attributes/codegen.html#the-inline-attribute" + ); fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> { match args { @@ -59,7 +63,7 @@ impl<S: Stage> SingleAttributeParser<S> for RustcForceInlineParser { const PATH: &'static [Symbol] = &[sym::rustc_force_inline]; const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost; const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError; - const TEMPLATE: AttributeTemplate = template!(Word, List: "reason", NameValueStr: "reason"); + const TEMPLATE: AttributeTemplate = template!(Word, List: &["reason"], NameValueStr: "reason"); fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> { let reason = match args { diff --git a/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs index 7eab3090870..d406c30b83e 100644 --- a/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs @@ -16,7 +16,10 @@ impl<S: Stage> SingleAttributeParser<S> for LinkNameParser { const PATH: &[Symbol] = &[sym::link_name]; const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost; const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError; - const TEMPLATE: AttributeTemplate = template!(NameValueStr: "name"); + const TEMPLATE: AttributeTemplate = template!( + NameValueStr: "name", + "https://doc.rust-lang.org/reference/items/external-blocks.html#the-link_name-attribute" + ); fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> { let Some(nv) = args.name_value() else { @@ -38,7 +41,10 @@ impl<S: Stage> SingleAttributeParser<S> for LinkSectionParser { const PATH: &[Symbol] = &[sym::link_section]; const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost; const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError; - const TEMPLATE: AttributeTemplate = template!(NameValueStr: "name"); + const TEMPLATE: AttributeTemplate = template!( + NameValueStr: "name", + "https://doc.rust-lang.org/reference/abi.html#the-link_section-attribute" + ); fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> { let Some(nv) = args.name_value() else { @@ -94,7 +100,10 @@ impl<S: Stage> SingleAttributeParser<S> for LinkOrdinalParser { const PATH: &[Symbol] = &[sym::link_ordinal]; const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost; const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error; - const TEMPLATE: AttributeTemplate = template!(List: "ordinal"); + const TEMPLATE: AttributeTemplate = template!( + List: &["ordinal"], + "https://doc.rust-lang.org/reference/items/external-blocks.html#the-link_ordinal-attribute" + ); fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> { let ordinal = parse_single_integer(cx, args)?; diff --git a/compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs index 886f7a889d3..a1166bf9ac5 100644 --- a/compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs @@ -31,7 +31,10 @@ pub(crate) struct MacroUseParser { first_span: Option<Span>, } -const MACRO_USE_TEMPLATE: AttributeTemplate = template!(Word, List: "name1, name2, ..."); +const MACRO_USE_TEMPLATE: AttributeTemplate = template!( + Word, List: &["name1, name2, ..."], + "https://doc.rust-lang.org/reference/macros-by-example.html#the-macro_use-attribute" +); impl<S: Stage> AttributeParser<S> for MacroUseParser { const ATTRIBUTES: AcceptMapping<Self, S> = &[( @@ -113,3 +116,11 @@ impl<S: Stage> AttributeParser<S> for MacroUseParser { Some(AttributeKind::MacroUse { span: self.first_span?, arguments: self.state }) } } + +pub(crate) struct AllowInternalUnsafeParser; + +impl<S: Stage> NoArgsAttributeParser<S> for AllowInternalUnsafeParser { + const PATH: &[Symbol] = &[sym::allow_internal_unsafe]; + const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Ignore; + const CREATE: fn(Span) -> AttributeKind = |span| AttributeKind::AllowInternalUnsafe(span); +} diff --git a/compiler/rustc_attr_parsing/src/attributes/must_use.rs b/compiler/rustc_attr_parsing/src/attributes/must_use.rs index d767abbc250..c88bb5a69e5 100644 --- a/compiler/rustc_attr_parsing/src/attributes/must_use.rs +++ b/compiler/rustc_attr_parsing/src/attributes/must_use.rs @@ -14,7 +14,10 @@ impl<S: Stage> SingleAttributeParser<S> for MustUseParser { const PATH: &[Symbol] = &[sym::must_use]; const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost; const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError; - const TEMPLATE: AttributeTemplate = template!(Word, NameValueStr: "reason"); + const TEMPLATE: AttributeTemplate = template!( + Word, NameValueStr: "reason", + "https://doc.rust-lang.org/reference/attributes/diagnostics.html#the-must_use-attribute" + ); fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> { Some(AttributeKind::MustUse { diff --git a/compiler/rustc_attr_parsing/src/attributes/path.rs b/compiler/rustc_attr_parsing/src/attributes/path.rs index 5700d780d71..c1c3de8cbfc 100644 --- a/compiler/rustc_attr_parsing/src/attributes/path.rs +++ b/compiler/rustc_attr_parsing/src/attributes/path.rs @@ -12,7 +12,10 @@ impl<S: Stage> SingleAttributeParser<S> for PathParser { const PATH: &[Symbol] = &[sym::path]; const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost; const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError; - const TEMPLATE: AttributeTemplate = template!(NameValueStr: "file"); + const TEMPLATE: AttributeTemplate = template!( + NameValueStr: "file", + "https://doc.rust-lang.org/reference/items/modules.html#the-path-attribute" + ); fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> { let Some(nv) = args.name_value() else { diff --git a/compiler/rustc_attr_parsing/src/attributes/proc_macro_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/proc_macro_attrs.rs index b156a7c5845..b267980914c 100644 --- a/compiler/rustc_attr_parsing/src/attributes/proc_macro_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/proc_macro_attrs.rs @@ -28,8 +28,10 @@ impl<S: Stage> SingleAttributeParser<S> for ProcMacroDeriveParser { const PATH: &[Symbol] = &[sym::proc_macro_derive]; const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost; const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error; - const TEMPLATE: AttributeTemplate = - template!(List: "TraitName, /*opt*/ attributes(name1, name2, ...)"); + const TEMPLATE: AttributeTemplate = template!( + List: &["TraitName", "TraitName, attributes(name1, name2, ...)"], + "https://doc.rust-lang.org/reference/procedural-macros.html#derive-macros" + ); fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> { let (trait_name, helper_attrs) = parse_derive_like(cx, args, true)?; @@ -47,7 +49,7 @@ impl<S: Stage> SingleAttributeParser<S> for RustcBuiltinMacroParser { const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost; const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error; const TEMPLATE: AttributeTemplate = - template!(List: "TraitName, /*opt*/ attributes(name1, name2, ...)"); + template!(List: &["TraitName", "TraitName, attributes(name1, name2, ...)"]); fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> { let (builtin_name, helper_attrs) = parse_derive_like(cx, args, false)?; diff --git a/compiler/rustc_attr_parsing/src/attributes/repr.rs b/compiler/rustc_attr_parsing/src/attributes/repr.rs index 6087afe6ded..996d2af5f37 100644 --- a/compiler/rustc_attr_parsing/src/attributes/repr.rs +++ b/compiler/rustc_attr_parsing/src/attributes/repr.rs @@ -26,8 +26,10 @@ impl<S: Stage> CombineAttributeParser<S> for ReprParser { const CONVERT: ConvertFn<Self::Item> = |items, first_span| AttributeKind::Repr { reprs: items, first_span }; // FIXME(jdonszelmann): never used - const TEMPLATE: AttributeTemplate = - template!(List: "C | Rust | align(...) | packed(...) | <integer type> | transparent"); + const TEMPLATE: AttributeTemplate = template!( + List: &["C", "Rust", "transparent", "align(...)", "packed(...)", "<integer type>"], + "https://doc.rust-lang.org/reference/type-layout.html#representations" + ); fn extend<'c>( cx: &'c mut AcceptContext<'_, '_, S>, @@ -275,7 +277,7 @@ pub(crate) struct AlignParser(Option<(Align, Span)>); impl AlignParser { const PATH: &'static [Symbol] = &[sym::rustc_align]; - const TEMPLATE: AttributeTemplate = template!(List: "<alignment in bytes>"); + const TEMPLATE: AttributeTemplate = template!(List: &["<alignment in bytes>"]); fn parse<'c, S: Stage>( &mut self, diff --git a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs index b465d2e62ff..1a668b4416f 100644 --- a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs +++ b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs @@ -12,7 +12,7 @@ impl<S: Stage> SingleAttributeParser<S> for RustcLayoutScalarValidRangeStart { const PATH: &'static [Symbol] = &[sym::rustc_layout_scalar_valid_range_start]; const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost; const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error; - const TEMPLATE: AttributeTemplate = template!(List: "start"); + const TEMPLATE: AttributeTemplate = template!(List: &["start"]); fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> { parse_single_integer(cx, args) @@ -26,7 +26,7 @@ impl<S: Stage> SingleAttributeParser<S> for RustcLayoutScalarValidRangeEnd { const PATH: &'static [Symbol] = &[sym::rustc_layout_scalar_valid_range_end]; const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost; const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error; - const TEMPLATE: AttributeTemplate = template!(List: "end"); + const TEMPLATE: AttributeTemplate = template!(List: &["end"]); fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> { parse_single_integer(cx, args) diff --git a/compiler/rustc_attr_parsing/src/attributes/stability.rs b/compiler/rustc_attr_parsing/src/attributes/stability.rs index 3c4ec133d51..c6707f5048b 100644 --- a/compiler/rustc_attr_parsing/src/attributes/stability.rs +++ b/compiler/rustc_attr_parsing/src/attributes/stability.rs @@ -48,7 +48,7 @@ impl<S: Stage> AttributeParser<S> for StabilityParser { const ATTRIBUTES: AcceptMapping<Self, S> = &[ ( &[sym::stable], - template!(List: r#"feature = "name", since = "version""#), + template!(List: &[r#"feature = "name", since = "version""#]), |this, cx, args| { reject_outside_std!(cx); if !this.check_duplicate(cx) @@ -60,7 +60,7 @@ impl<S: Stage> AttributeParser<S> for StabilityParser { ), ( &[sym::unstable], - template!(List: r#"feature = "name", reason = "...", issue = "N""#), + template!(List: &[r#"feature = "name", reason = "...", issue = "N""#]), |this, cx, args| { reject_outside_std!(cx); if !this.check_duplicate(cx) @@ -131,7 +131,7 @@ pub(crate) struct BodyStabilityParser { impl<S: Stage> AttributeParser<S> for BodyStabilityParser { const ATTRIBUTES: AcceptMapping<Self, S> = &[( &[sym::rustc_default_body_unstable], - template!(List: r#"feature = "name", reason = "...", issue = "N""#), + template!(List: &[r#"feature = "name", reason = "...", issue = "N""#]), |this, cx, args| { reject_outside_std!(cx); if this.stability.is_some() { @@ -177,29 +177,37 @@ impl ConstStabilityParser { impl<S: Stage> AttributeParser<S> for ConstStabilityParser { const ATTRIBUTES: AcceptMapping<Self, S> = &[ - (&[sym::rustc_const_stable], template!(List: r#"feature = "name""#), |this, cx, args| { - reject_outside_std!(cx); + ( + &[sym::rustc_const_stable], + template!(List: &[r#"feature = "name""#]), + |this, cx, args| { + reject_outside_std!(cx); - if !this.check_duplicate(cx) - && let Some((feature, level)) = parse_stability(cx, args) - { - this.stability = Some(( - PartialConstStability { level, feature, promotable: false }, - cx.attr_span, - )); - } - }), - (&[sym::rustc_const_unstable], template!(List: r#"feature = "name""#), |this, cx, args| { - reject_outside_std!(cx); - if !this.check_duplicate(cx) - && let Some((feature, level)) = parse_unstability(cx, args) - { - this.stability = Some(( - PartialConstStability { level, feature, promotable: false }, - cx.attr_span, - )); - } - }), + if !this.check_duplicate(cx) + && let Some((feature, level)) = parse_stability(cx, args) + { + this.stability = Some(( + PartialConstStability { level, feature, promotable: false }, + cx.attr_span, + )); + } + }, + ), + ( + &[sym::rustc_const_unstable], + template!(List: &[r#"feature = "name""#]), + |this, cx, args| { + reject_outside_std!(cx); + if !this.check_duplicate(cx) + && let Some((feature, level)) = parse_unstability(cx, args) + { + this.stability = Some(( + PartialConstStability { level, feature, promotable: false }, + cx.attr_span, + )); + } + }, + ), (&[sym::rustc_promotable], template!(Word), |this, cx, _| { reject_outside_std!(cx); this.promotable = true; diff --git a/compiler/rustc_attr_parsing/src/attributes/test_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/test_attrs.rs index 77b494328c7..3267855fb0d 100644 --- a/compiler/rustc_attr_parsing/src/attributes/test_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/test_attrs.rs @@ -13,7 +13,10 @@ impl<S: Stage> SingleAttributeParser<S> for IgnoreParser { const PATH: &[Symbol] = &[sym::ignore]; const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost; const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn; - const TEMPLATE: AttributeTemplate = template!(Word, NameValueStr: "reason"); + const TEMPLATE: AttributeTemplate = template!( + Word, NameValueStr: "reason", + "https://doc.rust-lang.org/reference/attributes/testing.html#the-ignore-attribute" + ); fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> { Some(AttributeKind::Ignore { @@ -51,8 +54,10 @@ impl<S: Stage> SingleAttributeParser<S> for ShouldPanicParser { const PATH: &[Symbol] = &[sym::should_panic]; const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost; const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError; - const TEMPLATE: AttributeTemplate = - template!(Word, List: r#"expected = "reason""#, NameValueStr: "reason"); + const TEMPLATE: AttributeTemplate = template!( + Word, List: &[r#"expected = "reason""#], NameValueStr: "reason", + "https://doc.rust-lang.org/reference/attributes/testing.html#the-should_panic-attribute" + ); fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> { Some(AttributeKind::ShouldPanic { diff --git a/compiler/rustc_attr_parsing/src/attributes/traits.rs b/compiler/rustc_attr_parsing/src/attributes/traits.rs index a954617ca57..8514d799aa4 100644 --- a/compiler/rustc_attr_parsing/src/attributes/traits.rs +++ b/compiler/rustc_attr_parsing/src/attributes/traits.rs @@ -16,7 +16,7 @@ impl<S: Stage> SingleAttributeParser<S> for SkipDuringMethodDispatchParser { const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost; const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error; - const TEMPLATE: AttributeTemplate = template!(List: "array, boxed_slice"); + const TEMPLATE: AttributeTemplate = template!(List: &["array, boxed_slice"]); fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> { let mut array = false; diff --git a/compiler/rustc_attr_parsing/src/attributes/transparency.rs b/compiler/rustc_attr_parsing/src/attributes/transparency.rs index 1c57dc1ebe2..d4d68eb8b27 100644 --- a/compiler/rustc_attr_parsing/src/attributes/transparency.rs +++ b/compiler/rustc_attr_parsing/src/attributes/transparency.rs @@ -19,7 +19,7 @@ impl<S: Stage> SingleAttributeParser<S> for TransparencyParser { cx.dcx().span_err(vec![used, unused], "multiple macro transparency attributes"); }); const TEMPLATE: AttributeTemplate = - template!(NameValueStr: "transparent|semitransparent|opaque"); + template!(NameValueStr: ["transparent", "semitransparent", "opaque"]); fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> { let Some(nv) = args.name_value() else { diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index 80dfdffdb55..1420753a44e 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -33,7 +33,9 @@ use crate::attributes::lint_helpers::{ AsPtrParser, AutomaticallyDerivedParser, PassByValueParser, PubTransparentParser, }; use crate::attributes::loop_match::{ConstContinueParser, LoopMatchParser}; -use crate::attributes::macro_attrs::{MacroEscapeParser, MacroUseParser}; +use crate::attributes::macro_attrs::{ + AllowInternalUnsafeParser, MacroEscapeParser, MacroUseParser, +}; use crate::attributes::must_use::MustUseParser; use crate::attributes::no_implicit_prelude::NoImplicitPreludeParser; use crate::attributes::non_exhaustive::NonExhaustiveParser; @@ -178,6 +180,7 @@ attribute_parsers!( Single<SkipDuringMethodDispatchParser>, Single<TransparencyParser>, Single<WithoutArgs<AllowIncoherentImplParser>>, + Single<WithoutArgs<AllowInternalUnsafeParser>>, Single<WithoutArgs<AsPtrParser>>, Single<WithoutArgs<AutomaticallyDerivedParser>>, Single<WithoutArgs<CoherenceIsCoreParser>>, diff --git a/compiler/rustc_attr_parsing/src/session_diagnostics.rs b/compiler/rustc_attr_parsing/src/session_diagnostics.rs index 1de25ca252b..41179844152 100644 --- a/compiler/rustc_attr_parsing/src/session_diagnostics.rs +++ b/compiler/rustc_attr_parsing/src/session_diagnostics.rs @@ -498,6 +498,7 @@ pub(crate) struct ReprIdent { #[derive(Diagnostic)] #[diag(attr_parsing_unrecognized_repr_hint, code = E0552)] #[help] +#[note] pub(crate) struct UnrecognizedReprHint { #[primary_span] pub span: Span, @@ -690,6 +691,9 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for AttributeParseError { } } + if let Some(link) = self.template.docs { + diag.note(format!("for more information, visit <{link}>")); + } let suggestions = self.template.suggestions(false, &name); diag.span_suggestions( self.attr_span, diff --git a/compiler/rustc_builtin_macros/src/cfg_accessible.rs b/compiler/rustc_builtin_macros/src/cfg_accessible.rs index 5f203dd5d11..f7d8f4aa783 100644 --- a/compiler/rustc_builtin_macros/src/cfg_accessible.rs +++ b/compiler/rustc_builtin_macros/src/cfg_accessible.rs @@ -44,7 +44,7 @@ impl MultiItemModifier for Expander { item: Annotatable, _is_derive_const: bool, ) -> ExpandResult<Vec<Annotatable>, Annotatable> { - let template = AttributeTemplate { list: Some("path"), ..Default::default() }; + let template = AttributeTemplate { list: Some(&["path"]), ..Default::default() }; validate_attr::check_builtin_meta_item( &ecx.sess.psess, meta_item, diff --git a/compiler/rustc_builtin_macros/src/derive.rs b/compiler/rustc_builtin_macros/src/derive.rs index e259f5b3955..a33eca43de5 100644 --- a/compiler/rustc_builtin_macros/src/derive.rs +++ b/compiler/rustc_builtin_macros/src/derive.rs @@ -34,8 +34,10 @@ impl MultiItemModifier for Expander { let (sess, features) = (ecx.sess, ecx.ecfg.features); let result = ecx.resolver.resolve_derives(ecx.current_expansion.id, ecx.force_mode, &|| { - let template = - AttributeTemplate { list: Some("Trait1, Trait2, ..."), ..Default::default() }; + let template = AttributeTemplate { + list: Some(&["Trait1, Trait2, ..."]), + ..Default::default() + }; validate_attr::check_builtin_meta_item( &sess.psess, meta_item, diff --git a/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs b/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs index 6082e376435..75db5d77783 100644 --- a/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs +++ b/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs @@ -108,11 +108,7 @@ pub(crate) fn expand_deriving_coerce_pointee( cx.item( span, attrs.clone(), - ast::ItemKind::Impl(Box::new(ast::Impl { - safety: ast::Safety::Default, - polarity: ast::ImplPolarity::Positive, - defaultness: ast::Defaultness::Final, - constness: ast::Const::No, + ast::ItemKind::Impl(ast::Impl { generics: Generics { params: generics .params @@ -137,10 +133,16 @@ pub(crate) fn expand_deriving_coerce_pointee( where_clause: generics.where_clause.clone(), span: generics.span, }, - of_trait: Some(trait_ref), + of_trait: Some(Box::new(ast::TraitImplHeader { + safety: ast::Safety::Default, + polarity: ast::ImplPolarity::Positive, + defaultness: ast::Defaultness::Final, + constness: ast::Const::No, + trait_ref, + })), self_ty: self_type.clone(), items: ThinVec::new(), - })), + }), ), )); } @@ -152,16 +154,18 @@ pub(crate) fn expand_deriving_coerce_pointee( let item = cx.item( span, attrs.clone(), - ast::ItemKind::Impl(Box::new(ast::Impl { - safety: ast::Safety::Default, - polarity: ast::ImplPolarity::Positive, - defaultness: ast::Defaultness::Final, - constness: ast::Const::No, + ast::ItemKind::Impl(ast::Impl { generics, - of_trait: Some(trait_ref), + of_trait: Some(Box::new(ast::TraitImplHeader { + safety: ast::Safety::Default, + polarity: ast::ImplPolarity::Positive, + defaultness: ast::Defaultness::Final, + constness: ast::Const::No, + trait_ref, + })), self_ty: self_type.clone(), items: ThinVec::new(), - })), + }), ); push(Annotatable::Item(item)); }; diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs index 3f4b47152c4..3fcf9da9450 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs @@ -826,21 +826,25 @@ impl<'a> TraitDef<'a> { ) } - let opt_trait_ref = Some(trait_ref); - cx.item( self.span, attrs, - ast::ItemKind::Impl(Box::new(ast::Impl { - safety: ast::Safety::Default, - polarity: ast::ImplPolarity::Positive, - defaultness: ast::Defaultness::Final, - constness: if self.is_const { ast::Const::Yes(DUMMY_SP) } else { ast::Const::No }, + ast::ItemKind::Impl(ast::Impl { generics: trait_generics, - of_trait: opt_trait_ref, + of_trait: Some(Box::new(ast::TraitImplHeader { + safety: ast::Safety::Default, + polarity: ast::ImplPolarity::Positive, + defaultness: ast::Defaultness::Final, + constness: if self.is_const { + ast::Const::Yes(DUMMY_SP) + } else { + ast::Const::No + }, + trait_ref, + })), self_ty: self_type, items: methods.into_iter().chain(associated_types).collect(), - })), + }), ) } diff --git a/compiler/rustc_codegen_ssa/messages.ftl b/compiler/rustc_codegen_ssa/messages.ftl index 3ca070acc9d..b6cfea88363 100644 --- a/compiler/rustc_codegen_ssa/messages.ftl +++ b/compiler/rustc_codegen_ssa/messages.ftl @@ -401,6 +401,9 @@ codegen_ssa_version_script_write_failure = failed to write version script: {$err codegen_ssa_visual_studio_not_installed = you may need to install Visual Studio build tools with the "C++ build tools" workload +codegen_ssa_xcrun_about = + the SDK is needed by the linker to know where to find symbols in system libraries and for embedding the SDK version in the final object file + codegen_ssa_xcrun_command_line_tools_insufficient = when compiling for iOS, tvOS, visionOS or watchOS, you need a full installation of Xcode diff --git a/compiler/rustc_codegen_ssa/src/back/apple.rs b/compiler/rustc_codegen_ssa/src/back/apple.rs index 2f68bad1695..2274450e20e 100644 --- a/compiler/rustc_codegen_ssa/src/back/apple.rs +++ b/compiler/rustc_codegen_ssa/src/back/apple.rs @@ -160,6 +160,10 @@ pub(super) fn add_version_to_llvm_target( pub(super) fn get_sdk_root(sess: &Session) -> Option<PathBuf> { let sdk_name = sdk_name(&sess.target); + // Attempt to invoke `xcrun` to find the SDK. + // + // Note that when cross-compiling from e.g. Linux, the `xcrun` binary may sometimes be provided + // as a shim by a cross-compilation helper tool. It usually isn't, but we still try nonetheless. match xcrun_show_sdk_path(sdk_name, sess.verbose_internals()) { Ok((path, stderr)) => { // Emit extra stderr, such as if `-verbose` was passed, or if `xcrun` emitted a warning. @@ -169,7 +173,19 @@ pub(super) fn get_sdk_root(sess: &Session) -> Option<PathBuf> { Some(path) } Err(err) => { - let mut diag = sess.dcx().create_err(err); + // Failure to find the SDK is not a hard error, since the user might have specified it + // in a manner unknown to us (moreso if cross-compiling): + // - A compiler driver like `zig cc` which links using an internally bundled SDK. + // - Extra linker arguments (`-Clink-arg=-syslibroot`). + // - A custom linker or custom compiler driver. + // + // Though we still warn, since such cases are uncommon, and it is very hard to debug if + // you do not know the details. + // + // FIXME(madsmtm): Make this a lint, to allow deny warnings to work. + // (Or fix <https://github.com/rust-lang/rust/issues/21204>). + let mut diag = sess.dcx().create_warn(err); + diag.note(fluent::codegen_ssa_xcrun_about); // Recognize common error cases, and give more Rust-specific error messages for those. if let Some(developer_dir) = xcode_select_developer_dir() { @@ -209,6 +225,8 @@ fn xcrun_show_sdk_path( sdk_name: &'static str, verbose: bool, ) -> Result<(PathBuf, String), XcrunError> { + // Intentionally invoke the `xcrun` in PATH, since e.g. nixpkgs provide an `xcrun` shim, so we + // don't want to require `/usr/bin/xcrun`. let mut cmd = Command::new("xcrun"); if verbose { cmd.arg("--verbose"); @@ -280,7 +298,7 @@ fn stdout_to_path(mut stdout: Vec<u8>) -> PathBuf { } #[cfg(unix)] let path = <OsString as std::os::unix::ffi::OsStringExt>::from_vec(stdout); - #[cfg(not(unix))] // Unimportant, this is only used on macOS - let path = OsString::from(String::from_utf8(stdout).unwrap()); + #[cfg(not(unix))] // Not so important, this is mostly used on macOS + let path = OsString::from(String::from_utf8(stdout).expect("stdout must be UTF-8")); PathBuf::from(path) } diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 3ec0d900994..4ebe59dc2a7 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -3194,39 +3194,60 @@ fn add_apple_link_args(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavo } fn add_apple_sdk(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) -> Option<PathBuf> { - let os = &sess.target.os; - if sess.target.vendor != "apple" - || !matches!(os.as_ref(), "ios" | "tvos" | "watchos" | "visionos" | "macos") - || !matches!(flavor, LinkerFlavor::Darwin(..)) - { + if !sess.target.is_like_darwin { return None; } - - if os == "macos" && !matches!(flavor, LinkerFlavor::Darwin(Cc::No, _)) { + let LinkerFlavor::Darwin(cc, _) = flavor else { return None; - } - - let sdk_root = sess.time("get_apple_sdk_root", || get_apple_sdk_root(sess))?; + }; - match flavor { - LinkerFlavor::Darwin(Cc::Yes, _) => { - // Use `-isysroot` instead of `--sysroot`, as only the former - // makes Clang treat it as a platform SDK. - // - // This is admittedly a bit strange, as on most targets - // `-isysroot` only applies to include header files, but on Apple - // targets this also applies to libraries and frameworks. - cmd.cc_arg("-isysroot"); - cmd.cc_arg(&sdk_root); - } - LinkerFlavor::Darwin(Cc::No, _) => { - cmd.link_arg("-syslibroot"); - cmd.link_arg(&sdk_root); - } - _ => unreachable!(), + // The default compiler driver on macOS is at `/usr/bin/cc`. This is a trampoline binary that + // effectively invokes `xcrun cc` internally to look up both the compiler binary and the SDK + // root from the current Xcode installation. When cross-compiling, when `rustc` is invoked + // inside Xcode, or when invoking the linker directly, this default logic is unsuitable, so + // instead we invoke `xcrun` manually. + // + // (Note that this doesn't mean we get a duplicate lookup here - passing `SDKROOT` below will + // cause the trampoline binary to skip looking up the SDK itself). + let sdkroot = sess.time("get_apple_sdk_root", || get_apple_sdk_root(sess))?; + + if cc == Cc::Yes { + // There are a few options to pass the SDK root when linking with a C/C++ compiler: + // - The `--sysroot` flag. + // - The `-isysroot` flag. + // - The `SDKROOT` environment variable. + // + // `--sysroot` isn't actually enough to get Clang to treat it as a platform SDK, you need + // to specify `-isysroot`. This is admittedly a bit strange, as on most targets `-isysroot` + // only applies to include header files, but on Apple targets it also applies to libraries + // and frameworks. + // + // This leaves the choice between `-isysroot` and `SDKROOT`. Both are supported by Clang and + // GCC, though they may not be supported by all compiler drivers. We choose `SDKROOT`, + // primarily because that is the same interface that is used when invoking the tool under + // `xcrun -sdk macosx $tool`. + // + // In that sense, if a given compiler driver does not support `SDKROOT`, the blame is fairly + // clearly in the tool in question, since they also don't support being run under `xcrun`. + // + // Additionally, `SDKROOT` is an environment variable and thus optional. It also has lower + // precedence than `-isysroot`, so a custom compiler driver that does not support it and + // instead figures out the SDK on their own can easily do so by using `-isysroot`. + // + // (This in particular affects Clang built with the `DEFAULT_SYSROOT` CMake flag, such as + // the one provided by some versions of Homebrew's `llvm` package. Those will end up + // ignoring the value we set here, and instead use their built-in sysroot). + cmd.cmd().env("SDKROOT", &sdkroot); + } else { + // When invoking the linker directly, we use the `-syslibroot` parameter. `SDKROOT` is not + // read by the linker, so it's really the only option. + // + // This is also what Clang does. + cmd.link_arg("-syslibroot"); + cmd.link_arg(&sdkroot); } - Some(sdk_root) + Some(sdkroot) } fn get_apple_sdk_root(sess: &Session) -> Option<PathBuf> { @@ -3255,7 +3276,13 @@ fn get_apple_sdk_root(sess: &Session) -> Option<PathBuf> { } "macosx" if sdkroot.contains("iPhoneOS.platform") - || sdkroot.contains("iPhoneSimulator.platform") => {} + || sdkroot.contains("iPhoneSimulator.platform") + || sdkroot.contains("AppleTVOS.platform") + || sdkroot.contains("AppleTVSimulator.platform") + || sdkroot.contains("WatchOS.platform") + || sdkroot.contains("WatchSimulator.platform") + || sdkroot.contains("XROS.platform") + || sdkroot.contains("XRSimulator.platform") => {} "watchos" if sdkroot.contains("WatchSimulator.platform") || sdkroot.contains("MacOSX.platform") => {} diff --git a/compiler/rustc_const_eval/src/interpret/call.rs b/compiler/rustc_const_eval/src/interpret/call.rs index a0160d1188d..b1cc0cc2878 100644 --- a/compiler/rustc_const_eval/src/interpret/call.rs +++ b/compiler/rustc_const_eval/src/interpret/call.rs @@ -346,7 +346,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { destination: &PlaceTy<'tcx, M::Provenance>, mut cont: ReturnContinuation, ) -> InterpResult<'tcx> { - let _span = enter_trace_span!(M, step::init_stack_frame, %instance, tracing_separate_thread = Empty); + let _trace = enter_trace_span!(M, step::init_stack_frame, %instance, tracing_separate_thread = Empty); // Compute callee information. // FIXME: for variadic support, do we have to somehow determine callee's extra_args? @@ -527,7 +527,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { target: Option<mir::BasicBlock>, unwind: mir::UnwindAction, ) -> InterpResult<'tcx> { - let _span = + let _trace = enter_trace_span!(M, step::init_fn_call, tracing_separate_thread = Empty, ?fn_val) .or_if_tracing_disabled(|| trace!("init_fn_call: {:#?}", fn_val)); diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs index c4b705d7124..d4f2bb8257d 100644 --- a/compiler/rustc_const_eval/src/interpret/eval_context.rs +++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs @@ -113,7 +113,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { /// See [LayoutOf::layout_of] for the original documentation. #[inline(always)] pub fn layout_of(&self, ty: Ty<'tcx>) -> <Self as LayoutOfHelpers<'tcx>>::LayoutOfResult { - let _span = enter_trace_span!(M, layouting::layout_of, ty = ?ty.kind()); + let _trace = enter_trace_span!(M, layouting::layout_of, ty = ?ty.kind()); LayoutOf::layout_of(self, ty) } @@ -126,7 +126,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { sig: ty::PolyFnSig<'tcx>, extra_args: &'tcx ty::List<Ty<'tcx>>, ) -> <Self as FnAbiOfHelpers<'tcx>>::FnAbiOfResult { - let _span = enter_trace_span!(M, layouting::fn_abi_of_fn_ptr, ?sig, ?extra_args); + let _trace = enter_trace_span!(M, layouting::fn_abi_of_fn_ptr, ?sig, ?extra_args); FnAbiOf::fn_abi_of_fn_ptr(self, sig, extra_args) } @@ -139,7 +139,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { instance: ty::Instance<'tcx>, extra_args: &'tcx ty::List<Ty<'tcx>>, ) -> <Self as FnAbiOfHelpers<'tcx>>::FnAbiOfResult { - let _span = enter_trace_span!(M, layouting::fn_abi_of_instance, ?instance, ?extra_args); + let _trace = enter_trace_span!(M, layouting::fn_abi_of_instance, ?instance, ?extra_args); FnAbiOf::fn_abi_of_instance(self, instance, extra_args) } } @@ -322,7 +322,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { frame: &Frame<'tcx, M::Provenance, M::FrameExtra>, value: T, ) -> Result<T, ErrorHandled> { - let _span = enter_trace_span!( + let _trace = enter_trace_span!( M, "instantiate_from_frame_and_normalize_erasing_regions", "{}", diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs index 14541809070..53a440b646b 100644 --- a/compiler/rustc_const_eval/src/interpret/operand.rs +++ b/compiler/rustc_const_eval/src/interpret/operand.rs @@ -773,7 +773,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { mir_place: mir::Place<'tcx>, layout: Option<TyAndLayout<'tcx>>, ) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> { - let _span = enter_trace_span!( + let _trace = enter_trace_span!( M, step::eval_place_to_op, ?mir_place, @@ -823,7 +823,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { mir_op: &mir::Operand<'tcx>, layout: Option<TyAndLayout<'tcx>>, ) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> { - let _span = + let _trace = enter_trace_span!(M, step::eval_operand, ?mir_op, tracing_separate_thread = Empty); use rustc_middle::mir::Operand::*; diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs index 45c4edb8503..6ff50dc700f 100644 --- a/compiler/rustc_const_eval/src/interpret/place.rs +++ b/compiler/rustc_const_eval/src/interpret/place.rs @@ -526,7 +526,7 @@ where &self, mir_place: mir::Place<'tcx>, ) -> InterpResult<'tcx, PlaceTy<'tcx, M::Provenance>> { - let _span = + let _trace = enter_trace_span!(M, step::eval_place, ?mir_place, tracing_separate_thread = Empty); let mut place = self.local_to_place(mir_place.local)?; diff --git a/compiler/rustc_const_eval/src/interpret/step.rs b/compiler/rustc_const_eval/src/interpret/step.rs index 9df49c0f4cc..76e470b69dc 100644 --- a/compiler/rustc_const_eval/src/interpret/step.rs +++ b/compiler/rustc_const_eval/src/interpret/step.rs @@ -76,7 +76,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { /// /// This does NOT move the statement counter forward, the caller has to do that! pub fn eval_statement(&mut self, stmt: &mir::Statement<'tcx>) -> InterpResult<'tcx> { - let _span = enter_trace_span!( + let _trace = enter_trace_span!( M, step::eval_statement, stmt = ?stmt.kind, @@ -465,7 +465,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { } fn eval_terminator(&mut self, terminator: &mir::Terminator<'tcx>) -> InterpResult<'tcx> { - let _span = enter_trace_span!( + let _trace = enter_trace_span!( M, step::eval_terminator, terminator = ?terminator.kind, diff --git a/compiler/rustc_const_eval/src/interpret/util.rs b/compiler/rustc_const_eval/src/interpret/util.rs index 71800950faa..72bee345406 100644 --- a/compiler/rustc_const_eval/src/interpret/util.rs +++ b/compiler/rustc_const_eval/src/interpret/util.rs @@ -85,11 +85,11 @@ impl EnteredTraceSpan for tracing::span::EnteredSpan { /// # let my_debug_var = String::new(); /// // logs a span named "hello" with a field named "arg" of value 42 (works only because /// // 42 implements the tracing::Value trait, otherwise use one of the options below) -/// let _span = enter_trace_span!(M, "hello", arg = 42); +/// let _trace = enter_trace_span!(M, "hello", arg = 42); /// // logs a field called "my_display_var" using the Display implementation -/// let _span = enter_trace_span!(M, "hello", %my_display_var); +/// let _trace = enter_trace_span!(M, "hello", %my_display_var); /// // logs a field called "my_debug_var" using the Debug implementation -/// let _span = enter_trace_span!(M, "hello", ?my_debug_var); +/// let _trace = enter_trace_span!(M, "hello", ?my_debug_var); /// ``` /// /// ### `NAME::SUBNAME` syntax @@ -107,8 +107,8 @@ impl EnteredTraceSpan for tracing::span::EnteredSpan { /// # use rustc_const_eval::enter_trace_span; /// # type M = rustc_const_eval::const_eval::CompileTimeMachine<'static>; /// // for example, the first will expand to the second -/// let _span = enter_trace_span!(M, borrow_tracker::on_stack_pop, /* ... */); -/// let _span = enter_trace_span!(M, "borrow_tracker", borrow_tracker = "on_stack_pop", /* ... */); +/// let _trace = enter_trace_span!(M, borrow_tracker::on_stack_pop, /* ... */); +/// let _trace = enter_trace_span!(M, "borrow_tracker", borrow_tracker = "on_stack_pop", /* ... */); /// ``` /// /// ### `tracing_separate_thread` parameter @@ -124,7 +124,7 @@ impl EnteredTraceSpan for tracing::span::EnteredSpan { /// ```rust /// # use rustc_const_eval::enter_trace_span; /// # type M = rustc_const_eval::const_eval::CompileTimeMachine<'static>; -/// let _span = enter_trace_span!(M, step::eval_statement, tracing_separate_thread = tracing::field::Empty); +/// let _trace = enter_trace_span!(M, step::eval_statement, tracing_separate_thread = tracing::field::Empty); /// ``` /// /// ### Executing something else when tracing is disabled @@ -136,7 +136,7 @@ impl EnteredTraceSpan for tracing::span::EnteredSpan { /// # use rustc_const_eval::enter_trace_span; /// # use rustc_const_eval::interpret::EnteredTraceSpan; /// # type M = rustc_const_eval::const_eval::CompileTimeMachine<'static>; -/// let _span = enter_trace_span!(M, step::eval_statement) +/// let _trace = enter_trace_span!(M, step::eval_statement) /// .or_if_tracing_disabled(|| tracing::info!("eval_statement")); /// ``` #[macro_export] diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index ed48f53c310..ab0c0665d51 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -1415,7 +1415,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { recursive: bool, reset_provenance_and_padding: bool, ) -> InterpResult<'tcx> { - let _span = enter_trace_span!( + let _trace = enter_trace_span!( M, "validate_operand", "recursive={recursive}, reset_provenance_and_padding={reset_provenance_and_padding}, val={val:?}" diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index c234aa43c09..7da3bf27eb5 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -904,10 +904,7 @@ impl SyntaxExtension { find_attr!(attrs, AttributeKind::AllowInternalUnstable(i, _) => i) .map(|i| i.as_slice()) .unwrap_or_default(); - // FIXME(jdonszelman): allow_internal_unsafe isn't yet new-style - // let allow_internal_unsafe = find_attr!(attrs, AttributeKind::AllowInternalUnsafe); - let allow_internal_unsafe = - ast::attr::find_by_name(attrs, sym::allow_internal_unsafe).is_some(); + let allow_internal_unsafe = find_attr!(attrs, AttributeKind::AllowInternalUnsafe(_)); let local_inner_macros = ast::attr::find_by_name(attrs, sym::macro_export) .and_then(|macro_export| macro_export.meta_item_list()) diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index 5c63d4808db..ab6b8f92802 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -120,13 +120,15 @@ pub struct AttributeTemplate { /// If `true`, the attribute is allowed to be a bare word like `#[test]`. pub word: bool, /// If `Some`, the attribute is allowed to take a list of items like `#[allow(..)]`. - pub list: Option<&'static str>, + pub list: Option<&'static [&'static str]>, /// If non-empty, the attribute is allowed to take a list containing exactly /// one of the listed words, like `#[coverage(off)]`. pub one_of: &'static [Symbol], /// If `Some`, the attribute is allowed to be a name/value pair where the /// value is a string, like `#[must_use = "reason"]`. - pub name_value_str: Option<&'static str>, + pub name_value_str: Option<&'static [&'static str]>, + /// A link to the document for this attribute. + pub docs: Option<&'static str>, } impl AttributeTemplate { @@ -137,11 +139,15 @@ impl AttributeTemplate { suggestions.push(format!("#{inner}[{name}]")); } if let Some(descr) = self.list { - suggestions.push(format!("#{inner}[{name}({descr})]")); + for descr in descr { + suggestions.push(format!("#{inner}[{name}({descr})]")); + } } suggestions.extend(self.one_of.iter().map(|&word| format!("#{inner}[{name}({word})]"))); if let Some(descr) = self.name_value_str { - suggestions.push(format!("#{inner}[{name} = \"{descr}\"]")); + for descr in descr { + suggestions.push(format!("#{inner}[{name} = \"{descr}\"]")); + } } suggestions.sort(); @@ -205,20 +211,33 @@ pub enum AttributeDuplicates { /// supports forms `#[attr]` and `#[attr(description)]`. #[macro_export] macro_rules! template { - (Word) => { $crate::template!(@ true, None, &[], None) }; - (List: $descr: expr) => { $crate::template!(@ false, Some($descr), &[], None) }; - (OneOf: $one_of: expr) => { $crate::template!(@ false, None, $one_of, None) }; - (NameValueStr: $descr: expr) => { $crate::template!(@ false, None, &[], Some($descr)) }; - (Word, List: $descr: expr) => { $crate::template!(@ true, Some($descr), &[], None) }; - (Word, NameValueStr: $descr: expr) => { $crate::template!(@ true, None, &[], Some($descr)) }; + (Word) => { $crate::template!(@ true, None, &[], None, None) }; + (Word, $link: literal) => { $crate::template!(@ true, None, &[], None, Some($link)) }; + (List: $descr: expr) => { $crate::template!(@ false, Some($descr), &[], None, None) }; + (List: $descr: expr, $link: literal) => { $crate::template!(@ false, Some($descr), &[], None, Some($link)) }; + (OneOf: $one_of: expr) => { $crate::template!(@ false, None, $one_of, None, None) }; + (NameValueStr: [$($descr: literal),* $(,)?]) => { $crate::template!(@ false, None, &[], Some(&[$($descr,)*]), None) }; + (NameValueStr: [$($descr: literal),* $(,)?], $link: literal) => { $crate::template!(@ false, None, &[], Some(&[$($descr,)*]), Some($link)) }; + (NameValueStr: $descr: literal) => { $crate::template!(@ false, None, &[], Some(&[$descr]), None) }; + (NameValueStr: $descr: literal, $link: literal) => { $crate::template!(@ false, None, &[], Some(&[$descr]), Some($link)) }; + (Word, List: $descr: expr) => { $crate::template!(@ true, Some($descr), &[], None, None) }; + (Word, List: $descr: expr, $link: literal) => { $crate::template!(@ true, Some($descr), &[], None, Some($link)) }; + (Word, NameValueStr: $descr: expr) => { $crate::template!(@ true, None, &[], Some(&[$descr]), None) }; + (Word, NameValueStr: $descr: expr, $link: literal) => { $crate::template!(@ true, None, &[], Some(&[$descr]), Some($link)) }; (List: $descr1: expr, NameValueStr: $descr2: expr) => { - $crate::template!(@ false, Some($descr1), &[], Some($descr2)) + $crate::template!(@ false, Some($descr1), &[], Some(&[$descr2]), None) + }; + (List: $descr1: expr, NameValueStr: $descr2: expr, $link: literal) => { + $crate::template!(@ false, Some($descr1), &[], Some(&[$descr2]), Some($link)) }; (Word, List: $descr1: expr, NameValueStr: $descr2: expr) => { - $crate::template!(@ true, Some($descr1), &[], Some($descr2)) + $crate::template!(@ true, Some($descr1), &[], Some(&[$descr2]), None) }; - (@ $word: expr, $list: expr, $one_of: expr, $name_value_str: expr) => { $crate::AttributeTemplate { - word: $word, list: $list, one_of: $one_of, name_value_str: $name_value_str + (Word, List: $descr1: expr, NameValueStr: $descr2: expr, $link: literal) => { + $crate::template!(@ true, Some($descr1), &[], Some(&[$descr2]), Some($link)) + }; + (@ $word: expr, $list: expr, $one_of: expr, $name_value_str: expr, $link: expr) => { $crate::AttributeTemplate { + word: $word, list: $list, one_of: $one_of, name_value_str: $name_value_str, docs: $link, } }; } @@ -391,18 +410,42 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ // ========================================================================== // Conditional compilation: - ungated!(cfg, Normal, template!(List: "predicate"), DuplicatesOk, EncodeCrossCrate::Yes), - ungated!(cfg_attr, Normal, template!(List: "predicate, attr1, attr2, ..."), DuplicatesOk, EncodeCrossCrate::Yes), + ungated!( + cfg, Normal, + template!( + List: &["predicate"], + "https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg-attribute" + ), + DuplicatesOk, EncodeCrossCrate::Yes + ), + ungated!( + cfg_attr, Normal, + template!( + List: &["predicate, attr1, attr2, ..."], + "https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg_attr-attribute" + ), + DuplicatesOk, EncodeCrossCrate::Yes + ), // Testing: ungated!( - ignore, Normal, template!(Word, NameValueStr: "reason"), WarnFollowing, - EncodeCrossCrate::No, + ignore, Normal, + template!( + Word, + NameValueStr: "reason", + "https://doc.rust-lang.org/reference/attributes/testing.html#the-ignore-attribute" + ), + WarnFollowing, EncodeCrossCrate::No, ), ungated!( should_panic, Normal, - template!(Word, List: r#"expected = "reason""#, NameValueStr: "reason"), FutureWarnFollowing, - EncodeCrossCrate::No, + template!( + Word, + List: &[r#"expected = "reason""#], + NameValueStr: "reason", + "https://doc.rust-lang.org/reference/attributes/testing.html#the-should_panic-attribute" + ), + FutureWarnFollowing, EncodeCrossCrate::No, ), // FIXME(Centril): This can be used on stable but shouldn't. ungated!( @@ -411,46 +454,102 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ ), // Macros: - ungated!(automatically_derived, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::Yes), ungated!( - macro_use, Normal, template!(Word, List: "name1, name2, ..."), WarnFollowingWordOnly, - EncodeCrossCrate::No, + automatically_derived, Normal, + template!( + Word, + "https://doc.rust-lang.org/reference/attributes/derive.html#the-automatically_derived-attribute" + ), + WarnFollowing, EncodeCrossCrate::Yes + ), + ungated!( + macro_use, Normal, + template!( + Word, + List: &["name1, name2, ..."], + "https://doc.rust-lang.org/reference/macros-by-example.html#the-macro_use-attribute" + ), + WarnFollowingWordOnly, EncodeCrossCrate::No, ), ungated!(macro_escape, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::No), // Deprecated synonym for `macro_use`. ungated!( - macro_export, Normal, template!(Word, List: "local_inner_macros"), + macro_export, Normal, + template!( + Word, + List: &["local_inner_macros"], + "https://doc.rust-lang.org/reference/macros-by-example.html#path-based-scope" + ), WarnFollowing, EncodeCrossCrate::Yes ), - ungated!(proc_macro, Normal, template!(Word), ErrorFollowing, EncodeCrossCrate::No), ungated!( - proc_macro_derive, Normal, template!(List: "TraitName, /*opt*/ attributes(name1, name2, ...)"), + proc_macro, Normal, + template!( + Word, + "https://doc.rust-lang.org/reference/procedural-macros.html#function-like-procedural-macros"), + ErrorFollowing, EncodeCrossCrate::No + ), + ungated!( + proc_macro_derive, Normal, + template!( + List: &["TraitName", "TraitName, attributes(name1, name2, ...)"], + "https://doc.rust-lang.org/reference/procedural-macros.html#derive-macros" + ), ErrorFollowing, EncodeCrossCrate::No, ), - ungated!(proc_macro_attribute, Normal, template!(Word), ErrorFollowing, EncodeCrossCrate::No), + ungated!( + proc_macro_attribute, Normal, + template!(Word, "https://doc.rust-lang.org/reference/procedural-macros.html#attribute-macros"), + ErrorFollowing, EncodeCrossCrate::No + ), // Lints: ungated!( - warn, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#), + warn, Normal, + template!( + List: &["lint1", "lint1, lint2, ...", r#"lint1, lint2, lint3, reason = "...""#], + "https://doc.rust-lang.org/reference/attributes/diagnostics.html#lint-check-attributes" + ), DuplicatesOk, EncodeCrossCrate::No, ), ungated!( - allow, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#), + allow, Normal, + template!( + List: &["lint1", "lint1, lint2, ...", r#"lint1, lint2, lint3, reason = "...""#], + "https://doc.rust-lang.org/reference/attributes/diagnostics.html#lint-check-attributes" + ), DuplicatesOk, EncodeCrossCrate::No, ), ungated!( - expect, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#), + expect, Normal, + template!( + List: &["lint1", "lint1, lint2, ...", r#"lint1, lint2, lint3, reason = "...""#], + "https://doc.rust-lang.org/reference/attributes/diagnostics.html#lint-check-attributes" + ), DuplicatesOk, EncodeCrossCrate::No, ), ungated!( - forbid, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#), + forbid, Normal, + template!( + List: &["lint1", "lint1, lint2, ...", r#"lint1, lint2, lint3, reason = "...""#], + "https://doc.rust-lang.org/reference/attributes/diagnostics.html#lint-check-attributes" + ), DuplicatesOk, EncodeCrossCrate::No ), ungated!( - deny, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#), + deny, Normal, + template!( + List: &["lint1", "lint1, lint2, ...", r#"lint1, lint2, lint3, reason = "...""#], + "https://doc.rust-lang.org/reference/attributes/diagnostics.html#lint-check-attributes" + ), DuplicatesOk, EncodeCrossCrate::No ), ungated!( - must_use, Normal, template!(Word, NameValueStr: "reason"), + must_use, Normal, + template!( + Word, + NameValueStr: "reason", + "https://doc.rust-lang.org/reference/attributes/diagnostics.html#the-must_use-attribute" + ), FutureWarnFollowing, EncodeCrossCrate::Yes ), gated!( @@ -461,52 +560,104 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ deprecated, Normal, template!( Word, - List: r#"/*opt*/ since = "version", /*opt*/ note = "reason""#, - NameValueStr: "reason" + List: &[r#"/*opt*/ since = "version", /*opt*/ note = "reason""#], + NameValueStr: "reason", + "https://doc.rust-lang.org/reference/attributes/diagnostics.html#the-deprecated-attribute" ), ErrorFollowing, EncodeCrossCrate::Yes ), // Crate properties: ungated!( - crate_name, CrateLevel, template!(NameValueStr: "name"), FutureWarnFollowing, - EncodeCrossCrate::No, + crate_name, CrateLevel, + template!( + NameValueStr: "name", + "https://doc.rust-lang.org/reference/crates-and-source-files.html#the-crate_name-attribute" + ), + FutureWarnFollowing, EncodeCrossCrate::No, ), ungated!( - crate_type, CrateLevel, template!(NameValueStr: "bin|lib|..."), DuplicatesOk, - EncodeCrossCrate::No, + crate_type, CrateLevel, + template!( + NameValueStr: ["bin", "lib", "dylib", "cdylib", "rlib", "staticlib", "sdylib", "proc-macro"], + "https://doc.rust-lang.org/reference/linkage.html" + ), + DuplicatesOk, EncodeCrossCrate::No, ), // ABI, linking, symbols, and FFI ungated!( link, Normal, - template!(List: r#"name = "...", /*opt*/ kind = "dylib|static|...", /*opt*/ wasm_import_module = "...", /*opt*/ import_name_type = "decorated|noprefix|undecorated""#), - DuplicatesOk, - EncodeCrossCrate::No, + template!(List: &[ + r#"name = "...""#, + r#"name = "...", kind = "dylib|static|...""#, + r#"name = "...", wasm_import_module = "...""#, + r#"name = "...", import_name_type = "decorated|noprefix|undecorated""#, + r#"name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated""#, + ], "https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute"), + DuplicatesOk, EncodeCrossCrate::No, ), ungated!( - link_name, Normal, template!(NameValueStr: "name"), + link_name, Normal, + template!(NameValueStr: "name", "https://doc.rust-lang.org/reference/items/external-blocks.html#the-link_name-attribute"), FutureWarnPreceding, EncodeCrossCrate::Yes ), - ungated!(no_link, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::No), - ungated!(repr, Normal, template!(List: "C"), DuplicatesOk, EncodeCrossCrate::No), + ungated!( + no_link, Normal, + template!(Word, "https://doc.rust-lang.org/reference/items/extern-crates.html#the-no_link-attribute"), + WarnFollowing, EncodeCrossCrate::No + ), + ungated!( + repr, Normal, + template!( + List: &["C", "Rust", "transparent", "align(...)", "packed(...)", "<integer type>"], + "https://doc.rust-lang.org/reference/type-layout.html#representations" + ), + DuplicatesOk, EncodeCrossCrate::No + ), // FIXME(#82232, #143834): temporarily renamed to mitigate `#[align]` nameres ambiguity - gated!(rustc_align, Normal, template!(List: "alignment"), DuplicatesOk, EncodeCrossCrate::No, fn_align, experimental!(rustc_align)), - ungated!(unsafe(Edition2024) export_name, Normal, template!(NameValueStr: "name"), FutureWarnPreceding, EncodeCrossCrate::No), - ungated!(unsafe(Edition2024) link_section, Normal, template!(NameValueStr: "name"), FutureWarnPreceding, EncodeCrossCrate::No), - ungated!(unsafe(Edition2024) no_mangle, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::No), - ungated!(used, Normal, template!(Word, List: "compiler|linker"), WarnFollowing, EncodeCrossCrate::No), - ungated!(link_ordinal, Normal, template!(List: "ordinal"), ErrorPreceding, EncodeCrossCrate::Yes), - ungated!(unsafe naked, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::No), + gated!(rustc_align, Normal, template!(List: &["alignment"]), DuplicatesOk, EncodeCrossCrate::No, fn_align, experimental!(rustc_align)), + ungated!( + unsafe(Edition2024) export_name, Normal, + template!(NameValueStr: "name", "https://doc.rust-lang.org/reference/abi.html#the-export_name-attribute"), + FutureWarnPreceding, EncodeCrossCrate::No + ), + ungated!( + unsafe(Edition2024) link_section, Normal, + template!(NameValueStr: "name", "https://doc.rust-lang.org/reference/abi.html#the-link_section-attribute"), + FutureWarnPreceding, EncodeCrossCrate::No + ), + ungated!( + unsafe(Edition2024) no_mangle, Normal, + template!(Word, "https://doc.rust-lang.org/reference/abi.html#the-no_mangle-attribute"), + WarnFollowing, EncodeCrossCrate::No + ), + ungated!( + used, Normal, + template!(Word, List: &["compiler", "linker"], "https://doc.rust-lang.org/reference/abi.html#the-used-attribute"), + WarnFollowing, EncodeCrossCrate::No + ), + ungated!( + link_ordinal, Normal, + template!(List: &["ordinal"], "https://doc.rust-lang.org/reference/items/external-blocks.html#the-link_ordinal-attribute"), + ErrorPreceding, EncodeCrossCrate::Yes + ), + ungated!( + unsafe naked, Normal, + template!(Word, "https://doc.rust-lang.org/reference/attributes/codegen.html#the-naked-attribute"), + WarnFollowing, EncodeCrossCrate::No + ), // Limits: ungated!( - recursion_limit, CrateLevel, template!(NameValueStr: "N"), FutureWarnFollowing, - EncodeCrossCrate::No + recursion_limit, CrateLevel, + template!(NameValueStr: "N", "https://doc.rust-lang.org/reference/attributes/limits.html#the-recursion_limit-attribute"), + FutureWarnFollowing, EncodeCrossCrate::No ), ungated!( - type_length_limit, CrateLevel, template!(NameValueStr: "N"), FutureWarnFollowing, - EncodeCrossCrate::No + type_length_limit, CrateLevel, + template!(NameValueStr: "N", "https://doc.rust-lang.org/reference/attributes/limits.html#the-type_length_limit-attribute"), + FutureWarnFollowing, EncodeCrossCrate::No ), gated!( move_size_limit, CrateLevel, template!(NameValueStr: "N"), ErrorFollowing, @@ -514,35 +665,84 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ ), // Entry point: - ungated!(no_main, CrateLevel, template!(Word), WarnFollowing, EncodeCrossCrate::No), + ungated!( + no_main, CrateLevel, + template!(Word, "https://doc.rust-lang.org/reference/crates-and-source-files.html#the-no_main-attribute"), + WarnFollowing, EncodeCrossCrate::No + ), // Modules, prelude, and resolution: - ungated!(path, Normal, template!(NameValueStr: "file"), FutureWarnFollowing, EncodeCrossCrate::No), - ungated!(no_std, CrateLevel, template!(Word), WarnFollowing, EncodeCrossCrate::No), - ungated!(no_implicit_prelude, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::No), - ungated!(non_exhaustive, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::Yes), + ungated!( + path, Normal, + template!(NameValueStr: "file", "https://doc.rust-lang.org/reference/items/modules.html#the-path-attribute"), + FutureWarnFollowing, EncodeCrossCrate::No + ), + ungated!( + no_std, CrateLevel, + template!(Word, "https://doc.rust-lang.org/reference/names/preludes.html#the-no_std-attribute"), + WarnFollowing, EncodeCrossCrate::No + ), + ungated!( + no_implicit_prelude, Normal, + template!(Word, "https://doc.rust-lang.org/reference/names/preludes.html#the-no_implicit_prelude-attribute"), + WarnFollowing, EncodeCrossCrate::No + ), + ungated!( + non_exhaustive, Normal, + template!(Word, "https://doc.rust-lang.org/reference/attributes/type_system.html#the-non_exhaustive-attribute"), + WarnFollowing, EncodeCrossCrate::Yes + ), // Runtime ungated!( windows_subsystem, CrateLevel, - template!(NameValueStr: "windows|console"), FutureWarnFollowing, - EncodeCrossCrate::No + template!(NameValueStr: ["windows", "console"], "https://doc.rust-lang.org/reference/runtime.html#the-windows_subsystem-attribute"), + FutureWarnFollowing, EncodeCrossCrate::No + ), + ungated!( // RFC 2070 + panic_handler, Normal, + template!(Word, "https://doc.rust-lang.org/reference/panic.html#the-panic_handler-attribute"), + WarnFollowing, EncodeCrossCrate::Yes ), - ungated!(panic_handler, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::Yes), // RFC 2070 // Code generation: - ungated!(inline, Normal, template!(Word, List: "always|never"), FutureWarnFollowing, EncodeCrossCrate::No), - ungated!(cold, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::No), - ungated!(no_builtins, CrateLevel, template!(Word), WarnFollowing, EncodeCrossCrate::Yes), ungated!( - target_feature, Normal, template!(List: r#"enable = "name""#), + inline, Normal, + template!( + Word, + List: &["always", "never"], + "https://doc.rust-lang.org/reference/attributes/codegen.html#the-inline-attribute" + ), + FutureWarnFollowing, EncodeCrossCrate::No + ), + ungated!( + cold, Normal, + template!(Word, "https://doc.rust-lang.org/reference/attributes/codegen.html#the-cold-attribute"), + WarnFollowing, EncodeCrossCrate::No + ), + ungated!( + no_builtins, CrateLevel, + template!(Word, "https://doc.rust-lang.org/reference/attributes/codegen.html#the-no_builtins-attribute"), + WarnFollowing, EncodeCrossCrate::Yes + ), + ungated!( + target_feature, Normal, + template!(List: &[r#"enable = "name""#], "https://doc.rust-lang.org/reference/attributes/codegen.html#the-target_feature-attribute"), DuplicatesOk, EncodeCrossCrate::No, ), - ungated!(track_caller, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::Yes), - ungated!(instruction_set, Normal, template!(List: "set"), ErrorPreceding, EncodeCrossCrate::No), + ungated!( + track_caller, Normal, + template!(Word, "https://doc.rust-lang.org/reference/attributes/codegen.html#the-track_caller-attribute"), + WarnFollowing, EncodeCrossCrate::Yes + ), + ungated!( + instruction_set, Normal, + template!(List: &["set"], "https://doc.rust-lang.org/reference/attributes/codegen.html#the-instruction_set-attribute"), + ErrorPreceding, EncodeCrossCrate::No + ), gated!( no_sanitize, Normal, - template!(List: "address, kcfi, memory, thread"), DuplicatesOk, + template!(List: &["address, kcfi, memory, thread"]), DuplicatesOk, EncodeCrossCrate::No, experimental!(no_sanitize) ), gated!( @@ -552,18 +752,31 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ ), ungated!( - doc, Normal, template!(List: "hidden|inline|...", NameValueStr: "string"), DuplicatesOk, - EncodeCrossCrate::Yes + doc, Normal, + template!( + List: &["hidden", "inline"], + NameValueStr: "string", + "https://doc.rust-lang.org/rustdoc/write-documentation/the-doc-attribute.html" + ), + DuplicatesOk, EncodeCrossCrate::Yes ), // Debugging ungated!( debugger_visualizer, Normal, - template!(List: r#"natvis_file = "...", gdb_script_file = "...""#), + template!( + List: &[r#"natvis_file = "...", gdb_script_file = "...""#], + "https://doc.rust-lang.org/reference/attributes/debugger.html#the-debugger_visualizer-attribute" + ), DuplicatesOk, EncodeCrossCrate::No ), - ungated!(collapse_debuginfo, Normal, template!(List: "no|external|yes"), ErrorFollowing, - EncodeCrossCrate::Yes + ungated!( + collapse_debuginfo, Normal, + template!( + List: &["no", "external", "yes"], + "https://doc.rust-lang.org/reference/attributes/debugger.html#the-collapse_debuginfo-attribute" + ), + ErrorFollowing, EncodeCrossCrate::Yes ), // ========================================================================== @@ -578,7 +791,7 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ // Testing: gated!( - test_runner, CrateLevel, template!(List: "path"), ErrorFollowing, + test_runner, CrateLevel, template!(List: &["path"]), ErrorFollowing, EncodeCrossCrate::Yes, custom_test_frameworks, "custom test frameworks are an unstable feature", ), @@ -597,7 +810,7 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ ), // RFC 2412 gated!( - optimize, Normal, template!(List: "none|size|speed"), ErrorPreceding, + optimize, Normal, template!(List: &["none", "size", "speed"]), ErrorPreceding, EncodeCrossCrate::No, optimize_attribute, experimental!(optimize) ), @@ -610,7 +823,7 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ EncodeCrossCrate::No, experimental!(ffi_const) ), gated!( - register_tool, CrateLevel, template!(List: "tool1, tool2, ..."), DuplicatesOk, + register_tool, CrateLevel, template!(List: &["tool1, tool2, ..."]), DuplicatesOk, EncodeCrossCrate::No, experimental!(register_tool), ), @@ -624,7 +837,7 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ ), // lang-team MCP 147 gated!( - deprecated_safe, Normal, template!(List: r#"since = "version", note = "...""#), ErrorFollowing, + deprecated_safe, Normal, template!(List: &[r#"since = "version", note = "...""#]), ErrorFollowing, EncodeCrossCrate::Yes, experimental!(deprecated_safe), ), @@ -643,7 +856,7 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ // RFC 3543 // `#[patchable_function_entry(prefix_nops = m, entry_nops = n)]` gated!( - patchable_function_entry, Normal, template!(List: "prefix_nops = m, entry_nops = n"), ErrorPreceding, + patchable_function_entry, Normal, template!(List: &["prefix_nops = m, entry_nops = n"]), ErrorPreceding, EncodeCrossCrate::Yes, experimental!(patchable_function_entry) ), @@ -673,37 +886,37 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ ungated!( feature, CrateLevel, - template!(List: "name1, name2, ..."), DuplicatesOk, EncodeCrossCrate::No, + template!(List: &["name1, name2, ..."]), DuplicatesOk, EncodeCrossCrate::No, ), // DuplicatesOk since it has its own validation ungated!( stable, Normal, - template!(List: r#"feature = "name", since = "version""#), DuplicatesOk, EncodeCrossCrate::No, + template!(List: &[r#"feature = "name", since = "version""#]), DuplicatesOk, EncodeCrossCrate::No, ), ungated!( unstable, Normal, - template!(List: r#"feature = "name", reason = "...", issue = "N""#), DuplicatesOk, + template!(List: &[r#"feature = "name", reason = "...", issue = "N""#]), DuplicatesOk, EncodeCrossCrate::Yes ), ungated!( - unstable_feature_bound, Normal, template!(Word, List: "feat1, feat2, ..."), + unstable_feature_bound, Normal, template!(Word, List: &["feat1, feat2, ..."]), DuplicatesOk, EncodeCrossCrate::No, ), ungated!( - rustc_const_unstable, Normal, template!(List: r#"feature = "name""#), + rustc_const_unstable, Normal, template!(List: &[r#"feature = "name""#]), DuplicatesOk, EncodeCrossCrate::Yes ), ungated!( rustc_const_stable, Normal, - template!(List: r#"feature = "name""#), DuplicatesOk, EncodeCrossCrate::No, + template!(List: &[r#"feature = "name""#]), DuplicatesOk, EncodeCrossCrate::No, ), ungated!( rustc_default_body_unstable, Normal, - template!(List: r#"feature = "name", reason = "...", issue = "N""#), + template!(List: &[r#"feature = "name", reason = "...", issue = "N""#]), DuplicatesOk, EncodeCrossCrate::No ), gated!( - allow_internal_unstable, Normal, template!(Word, List: "feat1, feat2, ..."), + allow_internal_unstable, Normal, template!(Word, List: &["feat1, feat2, ..."]), DuplicatesOk, EncodeCrossCrate::Yes, "allow_internal_unstable side-steps feature gating and stability checks", ), @@ -718,7 +931,7 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ through unstable paths" ), rustc_attr!( - rustc_deprecated_safe_2024, Normal, template!(List: r#"audit_that = "...""#), + rustc_deprecated_safe_2024, Normal, template!(List: &[r#"audit_that = "...""#]), ErrorFollowing, EncodeCrossCrate::Yes, "`#[rustc_deprecated_safe_2024]` is used to declare functions unsafe across the edition 2024 boundary", ), @@ -743,7 +956,13 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ rustc_attr!( rustc_never_type_options, Normal, - template!(List: r#"/*opt*/ fallback = "unit|niko|never|no""#), + template!(List: &[ + "", + r#"fallback = "unit""#, + r#"fallback = "niko""#, + r#"fallback = "never""#, + r#"fallback = "no""#, + ]), ErrorFollowing, EncodeCrossCrate::No, "`rustc_never_type_options` is used to experiment with never type fallback and work on \ @@ -808,7 +1027,17 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ // ========================================================================== gated!( - linkage, Normal, template!(NameValueStr: "external|internal|..."), + linkage, Normal, template!(NameValueStr: [ + "available_externally", + "common", + "extern_weak", + "external", + "internal", + "linkonce", + "linkonce_odr", + "weak", + "weak_odr", + ], "https://doc.rust-lang.org/reference/linkage.html"), ErrorPreceding, EncodeCrossCrate::No, "the `linkage` attribute is experimental and not portable across platforms", ), @@ -823,7 +1052,7 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ rustc_attr!( rustc_builtin_macro, Normal, - template!(Word, List: "name, /*opt*/ attributes(name1, name2, ...)"), ErrorFollowing, + template!(Word, List: &["name", "name, /*opt*/ attributes(name1, name2, ...)"]), ErrorFollowing, EncodeCrossCrate::Yes, ), rustc_attr!( @@ -832,12 +1061,12 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ ), rustc_attr!( rustc_macro_transparency, Normal, - template!(NameValueStr: "transparent|semiopaque|opaque"), ErrorFollowing, + template!(NameValueStr: ["transparent", "semiopaque", "opaque"]), ErrorFollowing, EncodeCrossCrate::Yes, "used internally for testing macro hygiene", ), rustc_attr!( rustc_autodiff, Normal, - template!(Word, List: r#""...""#), DuplicatesOk, + template!(Word, List: &[r#""...""#]), DuplicatesOk, EncodeCrossCrate::Yes, ), // Traces that are left when `cfg` and `cfg_attr` attributes are expanded. @@ -860,7 +1089,7 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ rustc_attr!( rustc_on_unimplemented, Normal, template!( - List: r#"/*opt*/ message = "...", /*opt*/ label = "...", /*opt*/ note = "...""#, + List: &[r#"/*opt*/ message = "...", /*opt*/ label = "...", /*opt*/ note = "...""#], NameValueStr: "message" ), ErrorFollowing, EncodeCrossCrate::Yes, @@ -868,7 +1097,7 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ ), rustc_attr!( rustc_confusables, Normal, - template!(List: r#""name1", "name2", ..."#), + template!(List: &[r#""name1", "name2", ..."#]), ErrorFollowing, EncodeCrossCrate::Yes, ), // Enumerates "identity-like" conversion methods to suggest on type mismatch. @@ -909,7 +1138,7 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ // Used by the `rustc::bad_opt_access` lint on fields // types (as well as any others in future). rustc_attr!( - rustc_lint_opt_deny_field_access, Normal, template!(List: "message"), + rustc_lint_opt_deny_field_access, Normal, template!(List: &["message"]), WarnFollowing, EncodeCrossCrate::Yes, ), @@ -921,7 +1150,7 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ rustc_promotable, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::No, ), rustc_attr!( - rustc_legacy_const_generics, Normal, template!(List: "N"), ErrorFollowing, + rustc_legacy_const_generics, Normal, template!(List: &["N"]), ErrorFollowing, EncodeCrossCrate::Yes, ), // Do not const-check this function's body. It will always get replaced during CTFE via `hook_special_const_fn`. @@ -946,7 +1175,7 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ ), gated!( rustc_allow_const_fn_unstable, Normal, - template!(Word, List: "feat1, feat2, ..."), DuplicatesOk, EncodeCrossCrate::No, + template!(Word, List: &["feat1, feat2, ..."]), DuplicatesOk, EncodeCrossCrate::No, "rustc_allow_const_fn_unstable side-steps feature gating and stability checks" ), @@ -955,13 +1184,13 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ // ========================================================================== rustc_attr!( - rustc_layout_scalar_valid_range_start, Normal, template!(List: "value"), ErrorFollowing, + rustc_layout_scalar_valid_range_start, Normal, template!(List: &["value"]), ErrorFollowing, EncodeCrossCrate::Yes, "the `#[rustc_layout_scalar_valid_range_start]` attribute is just used to enable \ niche optimizations in the standard library", ), rustc_attr!( - rustc_layout_scalar_valid_range_end, Normal, template!(List: "value"), ErrorFollowing, + rustc_layout_scalar_valid_range_end, Normal, template!(List: &["value"]), ErrorFollowing, EncodeCrossCrate::Yes, "the `#[rustc_layout_scalar_valid_range_end]` attribute is just used to enable \ niche optimizations in the standard library", @@ -1097,14 +1326,14 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ "the `#[rustc_main]` attribute is used internally to specify test entry point function", ), rustc_attr!( - rustc_skip_during_method_dispatch, Normal, template!(List: "array, boxed_slice"), ErrorFollowing, + rustc_skip_during_method_dispatch, Normal, template!(List: &["array, boxed_slice"]), ErrorFollowing, EncodeCrossCrate::No, "the `#[rustc_skip_during_method_dispatch]` attribute is used to exclude a trait \ from method dispatch when the receiver is of the following type, for compatibility in \ editions < 2021 (array) or editions < 2024 (boxed_slice)." ), rustc_attr!( - rustc_must_implement_one_of, Normal, template!(List: "function1, function2, ..."), + rustc_must_implement_one_of, Normal, template!(List: &["function1, function2, ..."]), ErrorFollowing, EncodeCrossCrate::No, "the `#[rustc_must_implement_one_of]` attribute is used to change minimal complete \ definition of a trait. Its syntax and semantics are highly experimental and will be \ @@ -1166,11 +1395,11 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ WarnFollowing, EncodeCrossCrate::No ), rustc_attr!( - TEST, rustc_layout, Normal, template!(List: "field1, field2, ..."), + TEST, rustc_layout, Normal, template!(List: &["field1, field2, ..."]), WarnFollowing, EncodeCrossCrate::Yes ), rustc_attr!( - TEST, rustc_abi, Normal, template!(List: "field1, field2, ..."), + TEST, rustc_abi, Normal, template!(List: &["field1, field2, ..."]), WarnFollowing, EncodeCrossCrate::No ), rustc_attr!( @@ -1191,29 +1420,29 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ EncodeCrossCrate::Yes ), rustc_attr!( - TEST, rustc_if_this_changed, Normal, template!(Word, List: "DepNode"), DuplicatesOk, + TEST, rustc_if_this_changed, Normal, template!(Word, List: &["DepNode"]), DuplicatesOk, EncodeCrossCrate::No ), rustc_attr!( - TEST, rustc_then_this_would_need, Normal, template!(List: "DepNode"), DuplicatesOk, + TEST, rustc_then_this_would_need, Normal, template!(List: &["DepNode"]), DuplicatesOk, EncodeCrossCrate::No ), rustc_attr!( TEST, rustc_clean, Normal, - template!(List: r#"cfg = "...", /*opt*/ label = "...", /*opt*/ except = "...""#), + template!(List: &[r#"cfg = "...", /*opt*/ label = "...", /*opt*/ except = "...""#]), DuplicatesOk, EncodeCrossCrate::No ), rustc_attr!( TEST, rustc_partition_reused, Normal, - template!(List: r#"cfg = "...", module = "...""#), DuplicatesOk, EncodeCrossCrate::No + template!(List: &[r#"cfg = "...", module = "...""#]), DuplicatesOk, EncodeCrossCrate::No ), rustc_attr!( TEST, rustc_partition_codegened, Normal, - template!(List: r#"cfg = "...", module = "...""#), DuplicatesOk, EncodeCrossCrate::No + template!(List: &[r#"cfg = "...", module = "...""#]), DuplicatesOk, EncodeCrossCrate::No ), rustc_attr!( TEST, rustc_expected_cgu_reuse, Normal, - template!(List: r#"cfg = "...", module = "...", kind = "...""#), DuplicatesOk, + template!(List: &[r#"cfg = "...", module = "...", kind = "...""#]), DuplicatesOk, EncodeCrossCrate::No ), rustc_attr!( @@ -1225,11 +1454,11 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ WarnFollowing, EncodeCrossCrate::No ), rustc_attr!( - TEST, rustc_mir, Normal, template!(List: "arg1, arg2, ..."), + TEST, rustc_mir, Normal, template!(List: &["arg1, arg2, ..."]), DuplicatesOk, EncodeCrossCrate::Yes ), gated!( - custom_mir, Normal, template!(List: r#"dialect = "...", phase = "...""#), + custom_mir, Normal, template!(List: &[r#"dialect = "...", phase = "...""#]), ErrorFollowing, EncodeCrossCrate::No, "the `#[custom_mir]` attribute is just used for the Rust test suite", ), diff --git a/compiler/rustc_hir/src/attrs/data_structures.rs b/compiler/rustc_hir/src/attrs/data_structures.rs index 5f419315467..e02edf5fe24 100644 --- a/compiler/rustc_hir/src/attrs/data_structures.rs +++ b/compiler/rustc_hir/src/attrs/data_structures.rs @@ -249,6 +249,9 @@ pub enum AttributeKind { /// Represents `#[rustc_allow_incoherent_impl]`. AllowIncoherentImpl(Span), + /// Represents `#[allow_internal_unsafe]`. + AllowInternalUnsafe(Span), + /// Represents `#[allow_internal_unstable]`. AllowInternalUnstable(ThinVec<(Symbol, Span)>, Span), diff --git a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs index e3a7f0b97a8..7ce624dcc55 100644 --- a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs +++ b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs @@ -16,6 +16,7 @@ impl AttributeKind { Align { .. } => No, AllowConstFnUnstable(..) => No, AllowIncoherentImpl(..) => No, + AllowInternalUnsafe(..) => Yes, AllowInternalUnstable(..) => Yes, AsPtr(..) => Yes, AutomaticallyDerived(..) => Yes, diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 34db6f92d92..b27c223527e 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -1310,6 +1310,7 @@ impl AttributeExt for Attribute { Attribute::Parsed(AttributeKind::Ignore { span, .. }) => *span, Attribute::Parsed(AttributeKind::ShouldPanic { span, .. }) => *span, Attribute::Parsed(AttributeKind::AutomaticallyDerived(span)) => *span, + Attribute::Parsed(AttributeKind::AllowInternalUnsafe(span)) => *span, a => panic!("can't get the span of an arbitrary parsed attribute: {a:?}"), } } @@ -4194,7 +4195,7 @@ impl<'hir> Item<'hir> { expect_trait_alias, (Ident, &'hir Generics<'hir>, GenericBounds<'hir>), ItemKind::TraitAlias(ident, generics, bounds), (*ident, generics, bounds); - expect_impl, &'hir Impl<'hir>, ItemKind::Impl(imp), imp; + expect_impl, &Impl<'hir>, ItemKind::Impl(imp), imp; } } @@ -4372,7 +4373,7 @@ pub enum ItemKind<'hir> { TraitAlias(Ident, &'hir Generics<'hir>, GenericBounds<'hir>), /// An implementation, e.g., `impl<A> Trait for Foo { .. }`. - Impl(&'hir Impl<'hir>), + Impl(Impl<'hir>), } /// Represents an impl block declaration. @@ -4381,6 +4382,14 @@ pub enum ItemKind<'hir> { /// Refer to [`ImplItem`] for an associated item within an impl block. #[derive(Debug, Clone, Copy, HashStable_Generic)] pub struct Impl<'hir> { + pub generics: &'hir Generics<'hir>, + pub of_trait: Option<&'hir TraitImplHeader<'hir>>, + pub self_ty: &'hir Ty<'hir>, + pub items: &'hir [ImplItemId], +} + +#[derive(Debug, Clone, Copy, HashStable_Generic)] +pub struct TraitImplHeader<'hir> { pub constness: Constness, pub safety: Safety, pub polarity: ImplPolarity, @@ -4388,13 +4397,7 @@ pub struct Impl<'hir> { // We do not put a `Span` in `Defaultness` because it breaks foreign crate metadata // decoding as `Span`s cannot be decoded when a `Session` is not available. pub defaultness_span: Option<Span>, - pub generics: &'hir Generics<'hir>, - - /// The trait being implemented, if any. - pub of_trait: Option<TraitRef<'hir>>, - - pub self_ty: &'hir Ty<'hir>, - pub items: &'hir [ImplItemId], + pub trait_ref: TraitRef<'hir>, } impl ItemKind<'_> { @@ -4756,8 +4759,8 @@ impl<'hir> Node<'hir> { /// Get a `hir::Impl` if the node is an impl block for the given `trait_def_id`. pub fn impl_block_of_trait(self, trait_def_id: DefId) -> Option<&'hir Impl<'hir>> { if let Node::Item(Item { kind: ItemKind::Impl(impl_block), .. }) = self - && let Some(trait_ref) = impl_block.of_trait - && let Some(trait_id) = trait_ref.trait_def_id() + && let Some(of_trait) = impl_block.of_trait + && let Some(trait_id) = of_trait.trait_ref.trait_def_id() && trait_id == trait_def_id { Some(impl_block) @@ -4952,7 +4955,7 @@ mod size_asserts { static_assert_size!(GenericArg<'_>, 16); static_assert_size!(GenericBound<'_>, 64); static_assert_size!(Generics<'_>, 56); - static_assert_size!(Impl<'_>, 80); + static_assert_size!(Impl<'_>, 40); static_assert_size!(ImplItem<'_>, 96); static_assert_size!(ImplItemKind<'_>, 40); static_assert_size!(Item<'_>, 88); @@ -4967,6 +4970,7 @@ mod size_asserts { static_assert_size!(Res, 12); static_assert_size!(Stmt<'_>, 32); static_assert_size!(StmtKind<'_>, 16); + static_assert_size!(TraitImplHeader<'_>, 48); static_assert_size!(TraitItem<'_>, 88); static_assert_size!(TraitItemKind<'_>, 48); static_assert_size!(Ty<'_>, 48); diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index 23fa466859a..9b2f8ae75fa 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -590,21 +590,21 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) -> V:: try_visit!(visitor.visit_generics(generics)); try_visit!(visitor.visit_enum_def(enum_definition)); } - ItemKind::Impl(Impl { - constness: _, - safety: _, - defaultness: _, - polarity: _, - defaultness_span: _, - generics, - of_trait, - self_ty, - items, - }) => { + ItemKind::Impl(Impl { generics, of_trait, self_ty, items }) => { try_visit!(visitor.visit_generics(generics)); - visit_opt!(visitor, visit_trait_ref, of_trait); + if let Some(TraitImplHeader { + constness: _, + safety: _, + polarity: _, + defaultness: _, + defaultness_span: _, + trait_ref, + }) = of_trait + { + try_visit!(visitor.visit_trait_ref(trait_ref)); + } try_visit!(visitor.visit_ty_unambig(self_ty)); - walk_list!(visitor, visit_impl_item_ref, *items); + walk_list!(visitor, visit_impl_item_ref, items); } ItemKind::Struct(ident, ref generics, ref struct_definition) | ItemKind::Union(ident, ref generics, ref struct_definition) => { diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index a62efed13bc..c642435b989 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -244,48 +244,48 @@ pub(super) fn check_item<'tcx>( // // won't be allowed unless there's an *explicit* implementation of `Send` // for `T` - hir::ItemKind::Impl(impl_) => { - let header = tcx.impl_trait_header(def_id); - let is_auto = header - .is_some_and(|header| tcx.trait_is_auto(header.trait_ref.skip_binder().def_id)); - + hir::ItemKind::Impl(ref impl_) => { crate::impl_wf_check::check_impl_wf(tcx, def_id)?; let mut res = Ok(()); - if let (hir::Defaultness::Default { .. }, true) = (impl_.defaultness, is_auto) { - let sp = impl_.of_trait.as_ref().map_or(item.span, |t| t.path.span); - res = Err(tcx - .dcx() - .struct_span_err(sp, "impls of auto traits cannot be default") - .with_span_labels(impl_.defaultness_span, "default because of this") - .with_span_label(sp, "auto trait") - .emit()); - } - // We match on both `ty::ImplPolarity` and `ast::ImplPolarity` just to get the `!` span. - match header.map(|h| h.polarity) { - // `None` means this is an inherent impl - Some(ty::ImplPolarity::Positive) | None => { - res = res.and(check_impl(tcx, item, impl_.self_ty, &impl_.of_trait)); - } - Some(ty::ImplPolarity::Negative) => { - let ast::ImplPolarity::Negative(span) = impl_.polarity else { - bug!("impl_polarity query disagrees with impl's polarity in HIR"); - }; - // FIXME(#27579): what amount of WF checking do we need for neg impls? - if let hir::Defaultness::Default { .. } = impl_.defaultness { - let mut spans = vec![span]; - spans.extend(impl_.defaultness_span); - res = Err(struct_span_code_err!( - tcx.dcx(), - spans, - E0750, - "negative impls cannot be default impls" - ) + if let Some(of_trait) = impl_.of_trait { + let header = tcx.impl_trait_header(def_id).unwrap(); + 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; + res = Err(tcx + .dcx() + .struct_span_err(sp, "impls of auto traits cannot be default") + .with_span_labels(of_trait.defaultness_span, "default because of this") + .with_span_label(sp, "auto trait") .emit()); - } } - Some(ty::ImplPolarity::Reservation) => { - // FIXME: what amount of WF checking do we need for reservation impls? + match header.polarity { + ty::ImplPolarity::Positive => { + res = res.and(check_impl(tcx, item, impl_)); + } + ty::ImplPolarity::Negative => { + let ast::ImplPolarity::Negative(span) = of_trait.polarity else { + bug!("impl_polarity query disagrees with impl's polarity in HIR"); + }; + // FIXME(#27579): what amount of WF checking do we need for neg impls? + if let hir::Defaultness::Default { .. } = of_trait.defaultness { + let mut spans = vec![span]; + spans.extend(of_trait.defaultness_span); + res = Err(struct_span_code_err!( + tcx.dcx(), + spans, + E0750, + "negative impls cannot be default impls" + ) + .emit()); + } + } + ty::ImplPolarity::Reservation => { + // FIXME: what amount of WF checking do we need for reservation impls? + } } + } else { + res = res.and(check_impl(tcx, item, impl_)); } res } @@ -1258,16 +1258,15 @@ pub(crate) fn check_const_item(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<() }) } -#[instrument(level = "debug", skip(tcx, hir_self_ty, hir_trait_ref))] +#[instrument(level = "debug", skip(tcx, impl_))] fn check_impl<'tcx>( tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>, - hir_self_ty: &hir::Ty<'_>, - hir_trait_ref: &Option<hir::TraitRef<'_>>, + impl_: &hir::Impl<'_>, ) -> Result<(), ErrorGuaranteed> { enter_wf_checking_ctxt(tcx, item.owner_id.def_id, |wfcx| { - match hir_trait_ref { - Some(hir_trait_ref) => { + match impl_.of_trait { + Some(of_trait) => { // `#[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). @@ -1275,7 +1274,7 @@ fn check_impl<'tcx>( // 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)?; - let trait_span = hir_trait_ref.path.span; + let trait_span = of_trait.trait_ref.path.span; let trait_ref = wfcx.deeply_normalize( trait_span, Some(WellFormedLoc::Ty(item.hir_id().expect_owner().def_id)), @@ -1299,12 +1298,12 @@ fn check_impl<'tcx>( if let Some(pred) = obligation.predicate.as_trait_clause() && pred.skip_binder().self_ty() == trait_ref.self_ty() { - obligation.cause.span = hir_self_ty.span; + obligation.cause.span = impl_.self_ty.span; } if let Some(pred) = obligation.predicate.as_projection_clause() && pred.skip_binder().self_ty() == trait_ref.self_ty() { - obligation.cause.span = hir_self_ty.span; + obligation.cause.span = impl_.self_ty.span; } } @@ -1321,7 +1320,7 @@ fn check_impl<'tcx>( wfcx.register_obligation(Obligation::new( tcx, ObligationCause::new( - hir_self_ty.span, + impl_.self_ty.span, wfcx.body_def_id, ObligationCauseCode::WellFormed(None), ), @@ -1342,7 +1341,7 @@ fn check_impl<'tcx>( self_ty, ); wfcx.register_wf_obligation( - hir_self_ty.span, + impl_.self_ty.span, Some(WellFormedLoc::Ty(item.hir_id().expect_owner().def_id)), self_ty.into(), ); diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs index 27948f50a4a..32b175611ce 100644 --- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs +++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs @@ -531,8 +531,10 @@ pub(crate) fn coerce_unsized_info<'tcx>( })); } else if diff_fields.len() > 1 { let item = tcx.hir_expect_item(impl_did); - let span = if let ItemKind::Impl(hir::Impl { of_trait: Some(t), .. }) = &item.kind { - t.path.span + let span = if let ItemKind::Impl(hir::Impl { of_trait: Some(of_trait), .. }) = + &item.kind + { + of_trait.trait_ref.path.span } else { tcx.def_span(impl_did) }; diff --git a/compiler/rustc_hir_analysis/src/coherence/orphan.rs b/compiler/rustc_hir_analysis/src/coherence/orphan.rs index c75fef9f716..f707196c816 100644 --- a/compiler/rustc_hir_analysis/src/coherence/orphan.rs +++ b/compiler/rustc_hir_analysis/src/coherence/orphan.rs @@ -384,7 +384,7 @@ fn emit_orphan_check_error<'tcx>( traits::OrphanCheckErr::NonLocalInputType(tys) => { let item = tcx.hir_expect_item(impl_def_id); let impl_ = item.expect_impl(); - let hir_trait_ref = impl_.of_trait.as_ref().unwrap(); + let of_trait = impl_.of_trait.unwrap(); let span = tcx.def_span(impl_def_id); let mut diag = tcx.dcx().create_err(match trait_ref.self_ty().kind() { @@ -401,7 +401,7 @@ fn emit_orphan_check_error<'tcx>( impl_.self_ty.span } else { // Point at `C<B>` in `impl<A, B> for C<B> in D<A>` - hir_trait_ref.path.span + of_trait.trait_ref.path.span }; ty = tcx.erase_regions(ty); diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 8ccbfbbb3b4..b72e743f95b 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -1295,18 +1295,22 @@ fn impl_trait_header(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<ty::ImplTrai let icx = ItemCtxt::new(tcx, def_id); let item = tcx.hir_expect_item(def_id); let impl_ = item.expect_impl(); - impl_.of_trait.as_ref().map(|ast_trait_ref| { + 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"); + } + impl_.of_trait.map(|of_trait| { let selfty = tcx.type_of(def_id).instantiate_identity(); - check_impl_constness(tcx, impl_.constness, ast_trait_ref); + check_impl_constness(tcx, of_trait.constness, &of_trait.trait_ref); - let trait_ref = icx.lowerer().lower_impl_trait_ref(ast_trait_ref, selfty); + let trait_ref = icx.lowerer().lower_impl_trait_ref(&of_trait.trait_ref, selfty); ty::ImplTraitHeader { trait_ref: ty::EarlyBinder::bind(trait_ref), - safety: impl_.safety, - polarity: polarity_of_impl(tcx, def_id, impl_, item.span), - constness: impl_.constness, + safety: of_trait.safety, + polarity: polarity_of_impl(tcx, of_trait, is_rustc_reservation), + constness: of_trait.constness, } }) } @@ -1350,26 +1354,18 @@ fn check_impl_constness( fn polarity_of_impl( tcx: TyCtxt<'_>, - def_id: LocalDefId, - impl_: &hir::Impl<'_>, - span: Span, + of_trait: &hir::TraitImplHeader<'_>, + is_rustc_reservation: bool, ) -> ty::ImplPolarity { - let is_rustc_reservation = tcx.has_attr(def_id, sym::rustc_reservation_impl); - match &impl_ { - hir::Impl { polarity: hir::ImplPolarity::Negative(span), of_trait, .. } => { + match of_trait.polarity { + hir::ImplPolarity::Negative(span) => { if is_rustc_reservation { - let span = span.to(of_trait.as_ref().map_or(*span, |t| t.path.span)); + let span = span.to(of_trait.trait_ref.path.span); tcx.dcx().span_err(span, "reservation impls can't be negative"); } ty::ImplPolarity::Negative } - hir::Impl { polarity: hir::ImplPolarity::Positive, of_trait: None, .. } => { - if is_rustc_reservation { - tcx.dcx().span_err(span, "reservation impls can't be inherent"); - } - ty::ImplPolarity::Positive - } - hir::Impl { polarity: hir::ImplPolarity::Positive, of_trait: Some(_), .. } => { + hir::ImplPolarity::Positive => { if is_rustc_reservation { ty::ImplPolarity::Reservation } else { diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index 8dd13da4fa7..b59dc4bd132 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -158,7 +158,9 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen if let Node::Item(item) = node { match item.kind { ItemKind::Impl(impl_) => { - if impl_.defaultness.is_default() { + 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())); diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs index eb3492f5de6..8133f9f6823 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -604,13 +604,10 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { #[instrument(level = "debug", skip(self))] fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) { - match &item.kind { - hir::ItemKind::Impl(hir::Impl { of_trait, .. }) => { - if let Some(of_trait) = of_trait { - self.record_late_bound_vars(of_trait.hir_ref_id, Vec::default()); - } - } - _ => {} + if let hir::ItemKind::Impl(impl_) = item.kind + && let Some(of_trait) = impl_.of_trait + { + self.record_late_bound_vars(of_trait.trait_ref.hir_ref_id, Vec::default()); } match item.kind { hir::ItemKind::Fn { generics, .. } => { @@ -636,7 +633,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { | hir::ItemKind::Union(_, generics, _) | hir::ItemKind::Trait(_, _, _, _, generics, ..) | hir::ItemKind::TraitAlias(_, generics, ..) - | hir::ItemKind::Impl(&hir::Impl { generics, .. }) => { + | hir::ItemKind::Impl(hir::Impl { generics, .. }) => { // These kinds of items have only early-bound lifetime parameters. self.visit_early(item.hir_id(), generics, |this| intravisit::walk_item(this, item)); } @@ -2106,7 +2103,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { // If we have a self type alias (in an impl), try to resolve an // associated item from one of the supertraits of the impl's trait. Res::SelfTyAlias { alias_to: impl_def_id, is_trait_impl: true, .. } => { - let hir::ItemKind::Impl(hir::Impl { of_trait: Some(trait_ref), .. }) = self + let hir::ItemKind::Impl(hir::Impl { of_trait: Some(of_trait), .. }) = self .tcx .hir_node_by_def_id(impl_def_id.expect_local()) .expect_item() @@ -2114,7 +2111,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { else { return; }; - let Some(trait_def_id) = trait_ref.trait_def_id() else { + let Some(trait_def_id) = of_trait.trait_ref.trait_def_id() else { return; }; let Some((bound_vars, assoc_item)) = BoundVarContext::supertrait_hrtb_vars( diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index 22fb02714dd..62125c99d80 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -251,7 +251,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_ .emit_err(crate::errors::SelfInImplSelf { span: spans.into(), note: () }); Ty::new_error(tcx, guar) } - _ => icx.lower_ty(*self_ty), + _ => icx.lower_ty(self_ty), }, ItemKind::Fn { .. } => { let args = ty::GenericArgs::identity_for_item(tcx, def_id); diff --git a/compiler/rustc_hir_analysis/src/errors/wrong_number_of_generic_args.rs b/compiler/rustc_hir_analysis/src/errors/wrong_number_of_generic_args.rs index 835f8e8cdae..8a9f9130fea 100644 --- a/compiler/rustc_hir_analysis/src/errors/wrong_number_of_generic_args.rs +++ b/compiler/rustc_hir_analysis/src/errors/wrong_number_of_generic_args.rs @@ -147,7 +147,11 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> { let hir::Node::Item(hir::Item { kind: hir::ItemKind::Impl(hir::Impl { - of_trait: Some(hir::TraitRef { hir_ref_id: id_in_of_trait, .. }), + of_trait: + Some(hir::TraitImplHeader { + trait_ref: hir::TraitRef { hir_ref_id: id_in_of_trait, .. }, + .. + }), .. }), .. diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs index 646ff3ca08d..56998b5b53c 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs @@ -200,7 +200,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { }) = tcx.hir_node_by_def_id(parent_id) && self_ty.hir_id == impl_self_ty.hir_id { - let Some(of_trait_ref) = of_trait else { + let Some(of_trait) = of_trait else { diag.span_suggestion_verbose( impl_self_ty.span.shrink_to_hi(), "you might have intended to implement this trait for a given type", @@ -209,10 +209,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { ); return; }; - if !of_trait_ref.trait_def_id().is_some_and(|def_id| def_id.is_local()) { + if !of_trait.trait_ref.trait_def_id().is_some_and(|def_id| def_id.is_local()) { return; } - let of_trait_span = of_trait_ref.path.span; + let of_trait_span = of_trait.trait_ref.path.span; // make sure that we are not calling unwrap to abort during the compilation let Ok(of_trait_name) = tcx.sess.source_map().span_to_snippet(of_trait_span) else { return; 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 1675aecd2b8..c7b984d9b25 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -2732,7 +2732,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { }; let i = tcx.parent_hir_node(fn_hir_id).expect_item().expect_impl(); - let trait_ref = self.lower_impl_trait_ref(i.of_trait.as_ref()?, self.lower_ty(i.self_ty)); + let trait_ref = self.lower_impl_trait_ref(&i.of_trait?.trait_ref, self.lower_ty(i.self_ty)); let assoc = tcx.associated_items(trait_ref.def_id).find_by_ident_and_kind( tcx, diff --git a/compiler/rustc_hir_analysis/src/hir_wf_check.rs b/compiler/rustc_hir_analysis/src/hir_wf_check.rs index 3fddaee8cef..d8578970adc 100644 --- a/compiler/rustc_hir_analysis/src/hir_wf_check.rs +++ b/compiler/rustc_hir_analysis/src/hir_wf_check.rs @@ -154,8 +154,9 @@ pub(super) fn diagnostic_hir_wf_check<'tcx>( hir::ItemKind::TyAlias(_, _, ty) | hir::ItemKind::Static(_, _, ty, _) | hir::ItemKind::Const(_, _, ty, _) => vec![ty], - hir::ItemKind::Impl(impl_) => match &impl_.of_trait { - Some(t) => t + hir::ItemKind::Impl(impl_) => match impl_.of_trait { + Some(of_trait) => of_trait + .trait_ref .path .segments .last() diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 235eec96d74..be5859b57c5 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -690,39 +690,44 @@ impl<'a> State<'a> { let (cb, ib) = self.head("union"); self.print_struct(ident.name, generics, struct_def, item.span, true, cb, ib); } - hir::ItemKind::Impl(&hir::Impl { - constness, - safety, - polarity, - defaultness, - defaultness_span: _, - generics, - ref of_trait, - self_ty, - items, - }) => { + hir::ItemKind::Impl(hir::Impl { generics, of_trait, self_ty, items }) => { let (cb, ib) = self.head(""); - self.print_defaultness(defaultness); - self.print_safety(safety); - self.word_nbsp("impl"); - if let hir::Constness::Const = constness { - self.word_nbsp("const"); - } + let impl_generics = |this: &mut Self| { + this.word_nbsp("impl"); + if !generics.params.is_empty() { + this.print_generic_params(generics.params); + this.space(); + } + }; - if !generics.params.is_empty() { - self.print_generic_params(generics.params); - self.space(); - } + match of_trait { + None => impl_generics(self), + Some(&hir::TraitImplHeader { + constness, + safety, + polarity, + defaultness, + defaultness_span: _, + ref trait_ref, + }) => { + self.print_defaultness(defaultness); + self.print_safety(safety); + + impl_generics(self); + + if let hir::Constness::Const = constness { + self.word_nbsp("const"); + } - if let hir::ImplPolarity::Negative(_) = polarity { - self.word("!"); - } + if let hir::ImplPolarity::Negative(_) = polarity { + self.word("!"); + } - if let Some(t) = of_trait { - self.print_trait_ref(t); - self.space(); - self.word_space("for"); + self.print_trait_ref(trait_ref); + self.space(); + self.word_space("for"); + } } self.print_type(self_ty); diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 2345cdab208..6013430e1ff 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -936,7 +936,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Node::ImplItem(item) => { // If it doesn't impl a trait, we can add a return type let Node::Item(&hir::Item { - kind: hir::ItemKind::Impl(&hir::Impl { of_trait, .. }), + kind: hir::ItemKind::Impl(hir::Impl { of_trait, .. }), .. }) = self.tcx.parent_hir_node(item.hir_id()) else { diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index f7430f7af4e..824d592fa6c 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -1103,7 +1103,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self_ty.span.ctxt().outer_expn_data().kind, ExpnKind::Macro(MacroKind::Derive, _) ) || matches!( - of_trait.as_ref().map(|t| t.path.span.ctxt().outer_expn_data().kind), + of_trait.map(|t| t.trait_ref.path.span.ctxt().outer_expn_data().kind), Some(ExpnKind::Macro(MacroKind::Derive, _)) ) => { @@ -1165,13 +1165,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { entry.0.insert(cause_span); entry.1.insert((cause_span, "unsatisfied trait bound introduced here")); } else { - if let Some(trait_ref) = of_trait { - entry.0.insert(trait_ref.path.span); + if let Some(of_trait) = of_trait { + entry.0.insert(of_trait.trait_ref.path.span); } entry.0.insert(self_ty.span); }; - if let Some(trait_ref) = of_trait { - entry.1.insert((trait_ref.path.span, "")); + if let Some(of_trait) = of_trait { + entry.1.insert((of_trait.trait_ref.path.span, "")); } entry.1.insert((self_ty.span, "")); } diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 4d0c0c94a81..776d8d35e05 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -349,6 +349,7 @@ lint_ill_formed_attribute_input = {$num_suggestions -> [1] attribute must be of the form {$suggestions} *[other] valid forms for the attribute are {$suggestions} } + .note = for more information, visit <{$docs}> lint_impl_trait_overcaptures = `{$self_ty}` will capture more lifetimes than possibly intended in edition 2024 .note = specifically, {$num_captured -> diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index c893b723375..8006cfcf30f 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -21,6 +21,7 @@ use rustc_ast::tokenstream::{TokenStream, TokenTree}; use rustc_ast::visit::{FnCtxt, FnKind}; use rustc_ast::{self as ast, *}; use rustc_ast_pretty::pprust::expr_to_string; +use rustc_attr_parsing::AttributeParser; use rustc_errors::{Applicability, LintDiagnostic}; use rustc_feature::GateIssue; use rustc_hir as hir; @@ -248,12 +249,6 @@ impl UnsafeCode { } impl EarlyLintPass for UnsafeCode { - fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &ast::Attribute) { - if attr.has_name(sym::allow_internal_unsafe) { - self.report_unsafe(cx, attr.span, BuiltinUnsafe::AllowInternalUnsafe); - } - } - #[inline] fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &ast::Expr) { if let ast::ExprKind::Block(ref blk, _) = e.kind { @@ -270,7 +265,10 @@ impl EarlyLintPass for UnsafeCode { self.report_unsafe(cx, it.span, BuiltinUnsafe::UnsafeTrait); } - ast::ItemKind::Impl(box ast::Impl { safety: ast::Safety::Unsafe(_), .. }) => { + ast::ItemKind::Impl(ast::Impl { + of_trait: Some(box ast::TraitImplHeader { safety: ast::Safety::Unsafe(_), .. }), + .. + }) => { self.report_unsafe(cx, it.span, BuiltinUnsafe::UnsafeImpl); } @@ -312,6 +310,19 @@ impl EarlyLintPass for UnsafeCode { } } + ast::ItemKind::MacroDef(..) => { + if let Some(attr) = AttributeParser::parse_limited( + cx.builder.sess(), + &it.attrs, + sym::allow_internal_unsafe, + it.span, + DUMMY_NODE_ID, + Some(cx.builder.features()), + ) { + self.report_unsafe(cx, attr.span(), BuiltinUnsafe::AllowInternalUnsafe); + } + } + _ => {} } } diff --git a/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs b/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs index dd16117db1c..943fcc0801b 100644 --- a/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs +++ b/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs @@ -61,8 +61,8 @@ impl<'tcx> LateLintPass<'tcx> for DerefIntoDynSupertrait { // `Deref` is being implemented for `t` if let hir::ItemKind::Impl(impl_) = item.kind // the trait is a `Deref` implementation - && let Some(trait_) = &impl_.of_trait - && let Some(did) = trait_.trait_def_id() + && let Some(of_trait) = &impl_.of_trait + && let Some(did) = of_trait.trait_ref.trait_def_id() && tcx.is_lang_item(did, LangItem::Deref) // the self type is `dyn t_principal` && let self_ty = tcx.type_of(item.owner_id).instantiate_identity() diff --git a/compiler/rustc_lint/src/early/diagnostics.rs b/compiler/rustc_lint/src/early/diagnostics.rs index f0fbf5bc81e..1e4bc79ce70 100644 --- a/compiler/rustc_lint/src/early/diagnostics.rs +++ b/compiler/rustc_lint/src/early/diagnostics.rs @@ -447,12 +447,14 @@ pub fn decorate_builtin_lint( BuiltinLintDiag::UnusedCrateDependency { extern_crate, local_crate } => { lints::UnusedCrateDependency { extern_crate, local_crate }.decorate_lint(diag) } - BuiltinLintDiag::IllFormedAttributeInput { suggestions } => { + BuiltinLintDiag::IllFormedAttributeInput { suggestions, docs } => { lints::IllFormedAttributeInput { num_suggestions: suggestions.len(), suggestions: DiagArgValue::StrListSepByAnd( suggestions.into_iter().map(|s| format!("`{s}`").into()).collect(), ), + has_docs: docs.is_some(), + docs: docs.unwrap_or(""), } .decorate_lint(diag) } diff --git a/compiler/rustc_lint/src/internal.rs b/compiler/rustc_lint/src/internal.rs index 7dafcc199a3..016ff17f5d7 100644 --- a/compiler/rustc_lint/src/internal.rs +++ b/compiler/rustc_lint/src/internal.rs @@ -411,11 +411,11 @@ declare_lint_pass!(LintPassImpl => [LINT_PASS_IMPL_WITHOUT_MACRO]); impl EarlyLintPass for LintPassImpl { fn check_item(&mut self, cx: &EarlyContext<'_>, item: &ast::Item) { - if let ast::ItemKind::Impl(box ast::Impl { of_trait: Some(lint_pass), .. }) = &item.kind - && let Some(last) = lint_pass.path.segments.last() + if let ast::ItemKind::Impl(ast::Impl { of_trait: Some(of_trait), .. }) = &item.kind + && let Some(last) = of_trait.trait_ref.path.segments.last() && last.ident.name == sym::LintPass { - let expn_data = lint_pass.path.span.ctxt().outer_expn_data(); + let expn_data = of_trait.trait_ref.path.span.ctxt().outer_expn_data(); let call_site = expn_data.call_site; if expn_data.kind != ExpnKind::Macro(MacroKind::Bang, sym::impl_lint_pass) && call_site.ctxt().outer_expn_data().kind @@ -423,7 +423,7 @@ impl EarlyLintPass for LintPassImpl { { cx.emit_span_lint( LINT_PASS_IMPL_WITHOUT_MACRO, - lint_pass.path.span, + of_trait.trait_ref.path.span, LintPassByHand, ); } @@ -582,8 +582,8 @@ impl Diagnostics { for (_hir_id, parent) in cx.tcx.hir_parent_iter(current_id) { debug!(?parent); if let hir::Node::Item(hir::Item { kind: hir::ItemKind::Impl(impl_), .. }) = parent - && let hir::Impl { of_trait: Some(of_trait), .. } = impl_ - && let Some(def_id) = of_trait.trait_def_id() + && let Some(of_trait) = impl_.of_trait + && let Some(def_id) = of_trait.trait_ref.trait_def_id() && let Some(name) = cx.tcx.get_diagnostic_name(def_id) && matches!(name, sym::Diagnostic | sym::Subdiagnostic | sym::LintDiagnostic) { diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 73e69a1791a..ba0112c8ac6 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -2685,6 +2685,9 @@ pub(crate) struct UnusedCrateDependency { pub(crate) struct IllFormedAttributeInput { pub num_suggestions: usize, pub suggestions: DiagArgValue, + #[note] + pub has_docs: bool, + pub docs: &'static str, } #[derive(LintDiagnostic)] diff --git a/compiler/rustc_lint/src/non_local_def.rs b/compiler/rustc_lint/src/non_local_def.rs index b877f909fc0..2dd3425e66c 100644 --- a/compiler/rustc_lint/src/non_local_def.rs +++ b/compiler/rustc_lint/src/non_local_def.rs @@ -129,8 +129,8 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions { // of the `impl` definition let mut collector = PathCollector { paths: Vec::new() }; collector.visit_ty_unambig(&impl_.self_ty); - if let Some(of_trait) = &impl_.of_trait { - collector.visit_trait_ref(of_trait); + if let Some(of_trait) = impl_.of_trait { + collector.visit_trait_ref(&of_trait.trait_ref); } // 1.5. Remove any path that doesn't resolve to a `DefId` or if it resolve to a diff --git a/compiler/rustc_lint/src/nonstandard_style.rs b/compiler/rustc_lint/src/nonstandard_style.rs index 7e5f43ba77f..8fafaa33d0c 100644 --- a/compiler/rustc_lint/src/nonstandard_style.rs +++ b/compiler/rustc_lint/src/nonstandard_style.rs @@ -187,7 +187,7 @@ impl EarlyLintPass for NonCamelCaseTypes { // N.B. This check is only for inherent associated types, so that we don't lint against // trait impls where we should have warned for the trait definition already. - ast::ItemKind::Impl(box ast::Impl { of_trait: None, items, .. }) => { + ast::ItemKind::Impl(ast::Impl { of_trait: None, items, .. }) => { for it in items { // FIXME: this doesn't respect `#[allow(..)]` on the item itself. if let ast::AssocItemKind::Type(alias) = &it.kind { diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index fe068d96b74..dc5ea3922f1 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -793,6 +793,7 @@ pub enum BuiltinLintDiag { }, IllFormedAttributeInput { suggestions: Vec<String>, + docs: Option<&'static str>, }, InnerAttributeUnstable { is_macro: bool, diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl index aaf1b6c05bf..3a21eea3d0a 100644 --- a/compiler/rustc_parse/messages.ftl +++ b/compiler/rustc_parse/messages.ftl @@ -869,6 +869,11 @@ parse_trait_alias_cannot_be_auto = trait aliases cannot be `auto` parse_trait_alias_cannot_be_const = trait aliases cannot be `const` parse_trait_alias_cannot_be_unsafe = trait aliases cannot be `unsafe` +parse_trait_impl_modifier_in_inherent_impl = inherent impls cannot be {$modifier_name} + .because = {$modifier_name} because of this + .type = inherent impl for this type + .note = only trait implementations may be annotated with `{$modifier}` + parse_transpose_dyn_or_impl = `for<...>` expected after `{$kw}`, not before .suggestion = move `{$kw}` before the `for<...>` diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index ddb2c545c78..a07d0606fd0 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -71,6 +71,20 @@ pub(crate) struct BadQPathStage2 { pub wrap: WrapType, } +#[derive(Diagnostic)] +#[diag(parse_trait_impl_modifier_in_inherent_impl)] +#[note] +pub(crate) struct TraitImplModifierInInherentImpl { + #[primary_span] + pub span: Span, + pub modifier: &'static str, + pub modifier_name: &'static str, + #[label(parse_because)] + pub modifier_span: Span, + #[label(parse_type)] + pub self_ty: Span, +} + #[derive(Subdiagnostic)] #[multipart_suggestion(parse_suggestion, applicability = "machine-applicable")] pub(crate) struct WrapType { diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 14a90e74049..607adaf0829 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -663,20 +663,44 @@ impl<'a> Parser<'a> { }; let trait_ref = TraitRef { path, ref_id: ty_first.id }; - (Some(trait_ref), ty_second) + let of_trait = Some(Box::new(TraitImplHeader { + defaultness, + safety, + constness, + polarity, + trait_ref, + })); + (of_trait, ty_second) + } + None => { + let self_ty = ty_first; + let error = |modifier, modifier_name, modifier_span| { + self.dcx().create_err(errors::TraitImplModifierInInherentImpl { + span: self_ty.span, + modifier, + modifier_name, + modifier_span, + self_ty: self_ty.span, + }) + }; + + if let Safety::Unsafe(span) = safety { + error("unsafe", "unsafe", span).with_code(E0197).emit(); + } + if let ImplPolarity::Negative(span) = polarity { + error("!", "negative", span).emit(); + } + if let Defaultness::Default(def_span) = defaultness { + error("default", "default", def_span).emit(); + } + if let Const::Yes(span) = constness { + error("const", "const", span).emit(); + } + (None, self_ty) } - None => (None, ty_first), // impl Type }; - Ok(ItemKind::Impl(Box::new(Impl { - safety, - polarity, - defaultness, - constness, - generics, - of_trait, - self_ty, - items: impl_items, - }))) + + Ok(ItemKind::Impl(Impl { generics, of_trait, self_ty, items: impl_items })) } fn parse_item_delegation(&mut self) -> PResult<'a, ItemKind> { @@ -1364,10 +1388,10 @@ impl<'a> Parser<'a> { }; match &mut item_kind { - ItemKind::Impl(box Impl { of_trait: Some(trai), constness, .. }) => { - *constness = Const::Yes(const_span); + ItemKind::Impl(Impl { of_trait: Some(of_trait), .. }) => { + of_trait.constness = Const::Yes(const_span); - let before_trait = trai.path.span.shrink_to_lo(); + let before_trait = of_trait.trait_ref.path.span.shrink_to_lo(); let const_up_to_impl = const_span.with_hi(impl_span.lo()); err.with_multipart_suggestion( "you might have meant to write a const trait impl", diff --git a/compiler/rustc_parse/src/validate_attr.rs b/compiler/rustc_parse/src/validate_attr.rs index a7f8d3b9139..68ef6d6f32c 100644 --- a/compiler/rustc_parse/src/validate_attr.rs +++ b/compiler/rustc_parse/src/validate_attr.rs @@ -298,35 +298,42 @@ fn emit_malformed_attribute( suggestions.push(format!("#{inner}[{name}]")); } if let Some(descr) = template.list { - suggestions.push(format!("#{inner}[{name}({descr})]")); + for descr in descr { + suggestions.push(format!("#{inner}[{name}({descr})]")); + } } suggestions.extend(template.one_of.iter().map(|&word| format!("#{inner}[{name}({word})]"))); if let Some(descr) = template.name_value_str { - suggestions.push(format!("#{inner}[{name} = \"{descr}\"]")); + for descr in descr { + suggestions.push(format!("#{inner}[{name} = \"{descr}\"]")); + } } if should_warn(name) { psess.buffer_lint( ILL_FORMED_ATTRIBUTE_INPUT, span, ast::CRATE_NODE_ID, - BuiltinLintDiag::IllFormedAttributeInput { suggestions: suggestions.clone() }, + BuiltinLintDiag::IllFormedAttributeInput { + suggestions: suggestions.clone(), + docs: template.docs, + }, ); } else { suggestions.sort(); - psess - .dcx() - .struct_span_err(span, error_msg) - .with_span_suggestions( - span, - if suggestions.len() == 1 { - "must be of the form" - } else { - "the following are the possible correct uses" - }, - suggestions, - Applicability::HasPlaceholders, - ) - .emit(); + let mut err = psess.dcx().struct_span_err(span, error_msg).with_span_suggestions( + span, + if suggestions.len() == 1 { + "must be of the form" + } else { + "the following are the possible correct uses" + }, + suggestions, + Applicability::HasPlaceholders, + ); + if let Some(link) = template.docs { + err.note(format!("for more information, visit <{link}>")); + } + err.emit(); } } diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index 6a28fe2617e..b5031f5d02e 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -29,7 +29,7 @@ passes_allow_incoherent_impl = `rustc_allow_incoherent_impl` attribute should be applied to impl items .label = the only currently supported targets are inherent methods -passes_allow_internal_unstable = +passes_macro_only_attribute = attribute should be applied to a macro .label = not a macro @@ -669,8 +669,8 @@ passes_rustc_std_internal_symbol = .label = not a function or static passes_rustc_unstable_feature_bound = - attribute should be applied to `impl` or free function outside of any `impl` or trait - .label = not an `impl` or free function + attribute should be applied to `impl`, trait or free function + .label = not an `impl`, trait or free function passes_should_be_applied_to_fn = attribute should be applied to a function definition diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 10c532b436a..93b94a8ba14 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -207,6 +207,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> { Attribute::Parsed(AttributeKind::ConstContinue(attr_span)) => { self.check_const_continue(hir_id, *attr_span, target) } + Attribute::Parsed(AttributeKind::AllowInternalUnsafe(attr_span)) => { + self.check_allow_internal_unsafe(hir_id, *attr_span, span, target, attrs) + } Attribute::Parsed(AttributeKind::AllowInternalUnstable(_, first_span)) => { self.check_allow_internal_unstable(hir_id, *first_span, span, target, attrs) } @@ -413,7 +416,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { // internal | sym::prelude_import | sym::panic_handler - | sym::allow_internal_unsafe | sym::lang | sym::needs_allocator | sym::default_lib_allocator @@ -1155,8 +1157,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { let is_valid = doc_fake_variadic_is_allowed_self_ty(i.self_ty) || if let Some(&[hir::GenericArg::Type(ty)]) = i .of_trait - .as_ref() - .and_then(|trait_ref| trait_ref.path.segments.last()) + .and_then(|of_trait| of_trait.trait_ref.path.segments.last()) .map(|last_segment| last_segment.args().args) { matches!(&ty.kind, hir::TyKind::Tup([_])) @@ -1646,8 +1647,8 @@ impl<'tcx> CheckAttrVisitor<'tcx> { && let parent_hir_id = self.tcx.parent_hir_id(hir_id) && let hir::Node::Item(item) = self.tcx.hir_node(parent_hir_id) && let hir::ItemKind::Impl(impl_) = item.kind - && let Some(trait_) = impl_.of_trait - && let Some(def_id) = trait_.trait_def_id() + && let Some(of_trait) = impl_.of_trait + && let Some(def_id) = of_trait.trait_ref.trait_def_id() && self.tcx.is_lang_item(def_id, hir::LangItem::Drop) { return; @@ -2212,7 +2213,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { /// Outputs an error for `#[allow_internal_unstable]` which can only be applied to macros. /// (Allows proc_macro functions) - // FIXME(jdonszelmann): if possible, move to attr parsing fn check_allow_internal_unstable( &self, hir_id: HirId, @@ -2221,6 +2221,42 @@ impl<'tcx> CheckAttrVisitor<'tcx> { target: Target, attrs: &[Attribute], ) { + self.check_macro_only_attr( + hir_id, + attr_span, + span, + target, + attrs, + "allow_internal_unstable", + ) + } + + /// Outputs an error for `#[allow_internal_unsafe]` which can only be applied to macros. + /// (Allows proc_macro functions) + fn check_allow_internal_unsafe( + &self, + hir_id: HirId, + attr_span: Span, + span: Span, + target: Target, + attrs: &[Attribute], + ) { + self.check_macro_only_attr(hir_id, attr_span, span, target, attrs, "allow_internal_unsafe") + } + + /// Outputs an error for attributes that can only be applied to macros, such as + /// `#[allow_internal_unsafe]` and `#[allow_internal_unstable]`. + /// (Allows proc_macro functions) + // FIXME(jdonszelmann): if possible, move to attr parsing + fn check_macro_only_attr( + &self, + hir_id: HirId, + attr_span: Span, + span: Span, + target: Target, + attrs: &[Attribute], + attr_name: &str, + ) { match target { Target::Fn => { for attr in attrs { @@ -2238,18 +2274,14 @@ impl<'tcx> CheckAttrVisitor<'tcx> { // erroneously allowed it and some crates used it accidentally, to be compatible // with crates depending on them, we can't throw an error here. Target::Field | Target::Arm => { - self.inline_attr_str_error_without_macro_def( - hir_id, - attr_span, - "allow_internal_unstable", - ); + self.inline_attr_str_error_without_macro_def(hir_id, attr_span, attr_name); return; } // otherwise continue out of the match _ => {} } - self.tcx.dcx().emit_err(errors::AllowInternalUnstable { attr_span, span }); + self.tcx.dcx().emit_err(errors::MacroOnlyAttribute { attr_span, span }); } /// Checks if the items on the `#[debugger_visualizer]` attribute are valid. @@ -2294,7 +2326,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { match target { // FIXME(staged_api): There's no reason we can't support more targets here. We're just // being conservative to begin with. - Target::Fn | Target::Impl { .. } => {} + Target::Fn | Target::Impl { .. } | Target::Trait => {} Target::ExternCrate | Target::Use | Target::Static @@ -2309,7 +2341,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | Target::Struct | Target::Field | Target::Union - | Target::Trait | Target::TraitAlias | Target::Expression | Target::Statement diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index fa9d0c7b1b7..d5d7cc5dc2e 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -172,7 +172,6 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { } } - #[allow(dead_code)] // FIXME(81658): should be used + lint reinstated after #83171 relands. fn handle_assign(&mut self, expr: &'tcx hir::Expr<'tcx>) { if self .typeck_results() @@ -189,7 +188,6 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { } } - #[allow(dead_code)] // FIXME(81658): should be used + lint reinstated after #83171 relands. fn check_for_self_assign(&mut self, assign: &'tcx hir::Expr<'tcx>) { fn check_for_self_assign_helper<'tcx>( typeck_results: &'tcx ty::TypeckResults<'tcx>, @@ -576,6 +574,10 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> { hir::ExprKind::OffsetOf(..) => { self.handle_offset_of(expr); } + hir::ExprKind::Assign(ref lhs, ..) => { + self.handle_assign(lhs); + self.check_for_self_assign(expr); + } _ => (), } diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index c6ab6b0d601..10b30fbe8c9 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -643,8 +643,8 @@ pub(crate) struct UsedStatic { } #[derive(Diagnostic)] -#[diag(passes_allow_internal_unstable)] -pub(crate) struct AllowInternalUnstable { +#[diag(passes_macro_only_attribute)] +pub(crate) struct MacroOnlyAttribute { #[primary_span] pub attr_span: Span, #[label] diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs index e2f223325df..71650c6b9b9 100644 --- a/compiler/rustc_passes/src/stability.rs +++ b/compiler/rustc_passes/src/stability.rs @@ -590,9 +590,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> { // For implementations of traits, check the stability of each item // individually as it's possible to have a stable trait with unstable // items. - hir::ItemKind::Impl(hir::Impl { - of_trait: Some(t), self_ty, items, constness, .. - }) => { + hir::ItemKind::Impl(hir::Impl { of_trait: Some(of_trait), self_ty, items, .. }) => { let features = self.tcx.features(); if features.staged_api() { let attrs = self.tcx.hir_attrs(item.hir_id()); @@ -628,7 +626,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> { { let mut c = CheckTraitImplStable { tcx: self.tcx, fully_stable: true }; c.visit_ty_unambig(self_ty); - c.visit_trait_ref(t); + c.visit_trait_ref(&of_trait.trait_ref); // Skip the lint if the impl is marked as unstable using // #[unstable_feature_bound(..)] @@ -641,7 +639,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> { // do not lint when the trait isn't resolved, since resolution error should // be fixed first - if t.path.res != Res::Err + if of_trait.trait_ref.path.res != Res::Err && c.fully_stable && !unstable_feature_bound_in_effect { @@ -655,7 +653,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> { } if features.const_trait_impl() - && let hir::Constness::Const = constness + && let hir::Constness::Const = of_trait.constness { let stable_or_implied_stable = match const_stab { None => true, @@ -671,7 +669,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> { Some(_) => false, }; - if let Some(trait_id) = t.trait_def_id() + if let Some(trait_id) = of_trait.trait_ref.trait_def_id() && let Some(const_stab) = self.tcx.lookup_const_stability(trait_id) { // the const stability of a trait impl must match the const stability on the trait. @@ -699,14 +697,18 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> { } } - if let hir::Constness::Const = constness - && let Some(def_id) = t.trait_def_id() + if let hir::Constness::Const = of_trait.constness + && let Some(def_id) = of_trait.trait_ref.trait_def_id() { // FIXME(const_trait_impl): Improve the span here. - self.tcx.check_const_stability(def_id, t.path.span, t.path.span); + self.tcx.check_const_stability( + def_id, + of_trait.trait_ref.path.span, + of_trait.trait_ref.path.span, + ); } - for impl_item_ref in *items { + for impl_item_ref in items { let impl_item = self.tcx.associated_item(impl_item_ref.owner_id); if let Some(def_id) = impl_item.trait_item_def_id { diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 5d02c02b23c..1bddbd03cc3 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -1779,7 +1779,8 @@ 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 = trait_ref.instantiate_identity(); - visitor.span = tcx.hir_expect_item(def_id).expect_impl().of_trait.unwrap().path.span; + visitor.span = + tcx.hir_expect_item(def_id).expect_impl().of_trait.unwrap().trait_ref.path.span; let _ = visitor.visit_def_id(trait_ref.def_id, "trait", &trait_ref.print_only_trait_path()); } diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index d18d0fc16a8..3fee2ab6afe 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -11,7 +11,7 @@ use std::sync::Arc; use rustc_ast::visit::{self, AssocCtxt, Visitor, WalkItemKind}; use rustc_ast::{ self as ast, AssocItem, AssocItemKind, Block, ConstItem, Delegation, Fn, ForeignItem, - ForeignItemKind, Impl, Item, ItemKind, NodeId, StaticItem, StmtKind, TyAlias, + ForeignItemKind, Item, ItemKind, NodeId, StaticItem, StmtKind, TyAlias, }; use rustc_attr_parsing as attr; use rustc_attr_parsing::AttributeParser; @@ -906,10 +906,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { } // These items do not add names to modules. - ItemKind::Impl(box Impl { of_trait: Some(..), .. }) - | ItemKind::Impl { .. } - | ItemKind::ForeignMod(..) - | ItemKind::GlobalAsm(..) => {} + ItemKind::Impl { .. } | ItemKind::ForeignMod(..) | ItemKind::GlobalAsm(..) => {} ItemKind::MacroDef(..) | ItemKind::MacCall(_) | ItemKind::DelegationMac(..) => { unreachable!() diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 953b72fd72b..e52cbeb733a 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -2620,7 +2620,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { self.resolve_adt(item, generics); } - ItemKind::Impl(box Impl { + ItemKind::Impl(Impl { ref generics, ref of_trait, ref self_ty, @@ -2631,7 +2631,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { self.resolve_implementation( &item.attrs, generics, - of_trait, + of_trait.as_deref(), self_ty, item.id, impl_items, @@ -3177,7 +3177,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { &mut self, attrs: &[ast::Attribute], generics: &'ast Generics, - opt_trait_reference: &'ast Option<TraitRef>, + of_trait: Option<&'ast ast::TraitImplHeader>, self_type: &'ast Ty, item_id: NodeId, impl_items: &'ast [Box<AssocItem>], @@ -3201,7 +3201,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { |this| { // Resolve the trait reference, if necessary. this.with_optional_trait_ref( - opt_trait_reference.as_ref(), + of_trait.map(|t| &t.trait_ref), self_type, |this, trait_id| { this.resolve_doc_links(attrs, MaybeExported::Impl(trait_id)); @@ -3224,9 +3224,9 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { is_trait_impl: trait_id.is_some() }; this.with_self_rib(res, |this| { - if let Some(trait_ref) = opt_trait_reference.as_ref() { + if let Some(of_trait) = of_trait { // Resolve type arguments in the trait path. - visit::walk_trait_ref(this, trait_ref); + visit::walk_trait_ref(this, &of_trait.trait_ref); } // Resolve the self type. this.visit_ty(self_type); @@ -5183,7 +5183,7 @@ impl<'ast> Visitor<'ast> for ItemInfoCollector<'_, '_, '_> { | ItemKind::Enum(_, generics, _) | ItemKind::Struct(_, generics, _) | ItemKind::Union(_, generics, _) - | ItemKind::Impl(box Impl { generics, .. }) + | ItemKind::Impl(Impl { generics, .. }) | ItemKind::Trait(box Trait { generics, .. }) | ItemKind::TraitAlias(_, generics, _) => { if let ItemKind::Fn(box Fn { sig, .. }) = &item.kind { diff --git a/compiler/rustc_target/src/spec/base/apple/mod.rs b/compiler/rustc_target/src/spec/base/apple/mod.rs index da9f96ce37d..ecc74264160 100644 --- a/compiler/rustc_target/src/spec/base/apple/mod.rs +++ b/compiler/rustc_target/src/spec/base/apple/mod.rs @@ -1,5 +1,4 @@ use std::borrow::Cow; -use std::env; use std::fmt::{Display, from_fn}; use std::num::ParseIntError; use std::str::FromStr; @@ -209,29 +208,10 @@ fn link_env_remove(os: &'static str) -> StaticCow<[StaticCow<str>]> { // that's only applicable to cross-OS compilation. Always leave anything for the // host OS alone though. if os == "macos" { - let mut env_remove = Vec::with_capacity(2); - // Remove the `SDKROOT` environment variable if it's clearly set for the wrong platform, which - // may occur when we're linking a custom build script while targeting iOS for example. - if let Ok(sdkroot) = env::var("SDKROOT") { - if sdkroot.contains("iPhoneOS.platform") - || sdkroot.contains("iPhoneSimulator.platform") - || sdkroot.contains("AppleTVOS.platform") - || sdkroot.contains("AppleTVSimulator.platform") - || sdkroot.contains("WatchOS.platform") - || sdkroot.contains("WatchSimulator.platform") - || sdkroot.contains("XROS.platform") - || sdkroot.contains("XRSimulator.platform") - { - env_remove.push("SDKROOT".into()) - } - } - // Additionally, `IPHONEOS_DEPLOYMENT_TARGET` must not be set when using the Xcode linker at + // `IPHONEOS_DEPLOYMENT_TARGET` must not be set when using the Xcode linker at // "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ld", // although this is apparently ignored when using the linker at "/usr/bin/ld". - env_remove.push("IPHONEOS_DEPLOYMENT_TARGET".into()); - env_remove.push("TVOS_DEPLOYMENT_TARGET".into()); - env_remove.push("XROS_DEPLOYMENT_TARGET".into()); - env_remove.into() + cvs!["IPHONEOS_DEPLOYMENT_TARGET", "TVOS_DEPLOYMENT_TARGET", "XROS_DEPLOYMENT_TARGET"] } else { // Otherwise if cross-compiling for a different OS/SDK (including Mac Catalyst), remove any part // of the linking environment that's wrong and reversed. diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index ae72178c052..bc8c8a44405 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -3471,8 +3471,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { .. })) => { let mut spans = Vec::with_capacity(2); - if let Some(trait_ref) = of_trait { - spans.push(trait_ref.path.span); + if let Some(of_trait) = of_trait { + spans.push(of_trait.trait_ref.path.span); } spans.push(self_ty.span); let mut spans: MultiSpan = spans.into(); @@ -3480,7 +3480,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { self_ty.span.ctxt().outer_expn_data().kind, ExpnKind::Macro(MacroKind::Derive, _) ) || matches!( - of_trait.as_ref().map(|t| t.path.span.ctxt().outer_expn_data().kind), + of_trait.map(|t| t.trait_ref.path.span.ctxt().outer_expn_data().kind), Some(ExpnKind::Macro(MacroKind::Derive, _)) ) { spans.push_span_label( @@ -3592,7 +3592,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { .. })) => { let mut spans = vec![self_ty.span]; - spans.extend(of_trait.as_ref().map(|t| t.path.span)); + spans.extend(of_trait.map(|t| t.trait_ref.path.span)); let mut spans: MultiSpan = spans.into(); spans.push_span_label(data.span, "unsatisfied trait bound introduced here"); err.span_note(spans, msg); diff --git a/compiler/rustc_ty_utils/src/assoc.rs b/compiler/rustc_ty_utils/src/assoc.rs index 37cb64511c7..e9629e31482 100644 --- a/compiler/rustc_ty_utils/src/assoc.rs +++ b/compiler/rustc_ty_utils/src/assoc.rs @@ -174,10 +174,10 @@ fn associated_types_for_impl_traits_in_trait_or_impl<'tcx>( }) .collect(), ItemKind::Impl(impl_) => { - let Some(trait_ref) = impl_.of_trait else { + let Some(of_trait) = impl_.of_trait else { return Default::default(); }; - let Some(trait_def_id) = trait_ref.trait_def_id() else { + let Some(trait_def_id) = of_trait.trait_ref.trait_def_id() else { return Default::default(); }; let in_trait_def = tcx.associated_types_for_impl_traits_in_trait_or_impl(trait_def_id); diff --git a/compiler/rustc_ty_utils/src/implied_bounds.rs b/compiler/rustc_ty_utils/src/implied_bounds.rs index 6fa763f18ef..cdfb93c4e7d 100644 --- a/compiler/rustc_ty_utils/src/implied_bounds.rs +++ b/compiler/rustc_ty_utils/src/implied_bounds.rs @@ -172,10 +172,12 @@ fn impl_spans(tcx: TyCtxt<'_>, def_id: LocalDefId) -> impl Iterator<Item = Span> let trait_args = impl_ .of_trait .into_iter() - .flat_map(|trait_ref| trait_ref.path.segments.last().unwrap().args().args) + .flat_map(|of_trait| of_trait.trait_ref.path.segments.last().unwrap().args().args) .map(|arg| arg.span()); - let dummy_spans_for_default_args = - impl_.of_trait.into_iter().flat_map(|trait_ref| iter::repeat(trait_ref.path.span)); + let dummy_spans_for_default_args = impl_ + .of_trait + .into_iter() + .flat_map(|of_trait| iter::repeat(of_trait.trait_ref.path.span)); iter::once(impl_.self_ty.span).chain(trait_args).chain(dummy_spans_for_default_args) } else { bug!("unexpected item for impl {def_id:?}: {item:?}") diff --git a/compiler/rustc_ty_utils/src/sig_types.rs b/compiler/rustc_ty_utils/src/sig_types.rs index dc6009116ac..d95660810e5 100644 --- a/compiler/rustc_ty_utils/src/sig_types.rs +++ b/compiler/rustc_ty_utils/src/sig_types.rs @@ -87,7 +87,7 @@ pub fn walk_types<'tcx, V: SpannedTypeVisitor<'tcx>>( DefKind::InlineConst | DefKind::Closure | DefKind::SyntheticCoroutineBody => {} DefKind::Impl { of_trait } => { if of_trait { - let span = tcx.hir_node_by_def_id(item).expect_item().expect_impl().of_trait.unwrap().path.span; + 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..]; try_visit!(visitor.visit(span, args)); } diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index 2e0b16d9227..b22c326b9f2 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -81,7 +81,11 @@ fn sizedness_constraint_for_ty<'tcx>( fn defaultness(tcx: TyCtxt<'_>, def_id: LocalDefId) -> hir::Defaultness { match tcx.hir_node_by_def_id(def_id) { hir::Node::Item(hir::Item { - kind: hir::ItemKind::Impl(hir::Impl { defaultness, of_trait: Some(_), .. }), + kind: + hir::ItemKind::Impl(hir::Impl { + of_trait: Some(hir::TraitImplHeader { defaultness, .. }), + .. + }), .. }) | hir::Node::ImplItem(hir::ImplItem { defaultness, .. }) diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 2321aab2c51..8001faf9d20 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -49,7 +49,27 @@ //! v[1] = v[1] + 5; //! ``` //! +//! # Memory layout +//! +//! When the type is non-zero-sized and the capacity is nonzero, [`Vec`] uses the [`Global`] +//! allocator for its allocation. It is valid to convert both ways between such a [`Vec`] and a raw +//! pointer allocated with the [`Global`] allocator, provided that the [`Layout`] used with the +//! allocator is correct for a sequence of `capacity` elements of the type, and the first `len` +//! values pointed to by the raw pointer are valid. More precisely, a `ptr: *mut T` that has been +//! allocated with the [`Global`] allocator with [`Layout::array::<T>(capacity)`][Layout::array] may +//! be converted into a vec using +//! [`Vec::<T>::from_raw_parts(ptr, len, capacity)`](Vec::from_raw_parts). Conversely, the memory +//! backing a `value: *mut T` obtained from [`Vec::<T>::as_mut_ptr`] may be deallocated using the +//! [`Global`] allocator with the same layout. +//! +//! For zero-sized types (ZSTs), or when the capacity is zero, the `Vec` pointer must be non-null +//! and sufficiently aligned. The recommended way to build a `Vec` of ZSTs if [`vec!`] cannot be +//! used is to use [`ptr::NonNull::dangling`]. +//! //! [`push`]: Vec::push +//! [`ptr::NonNull::dangling`]: NonNull::dangling +//! [`Layout`]: crate::alloc::Layout +//! [Layout::array]: crate::alloc::Layout::array #![stable(feature = "rust1", since = "1.0.0")] @@ -523,18 +543,23 @@ impl<T> Vec<T> { /// This is highly unsafe, due to the number of invariants that aren't /// checked: /// - /// * `ptr` must have been allocated using the global allocator, such as via - /// the [`alloc::alloc`] function. - /// * `T` needs to have the same alignment as what `ptr` was allocated with. + /// * If `T` is not a zero-sized type and the capacity is nonzero, `ptr` must have + /// been allocated using the global allocator, such as via the [`alloc::alloc`] + /// function. If `T` is a zero-sized type or the capacity is zero, `ptr` need + /// only be non-null and aligned. + /// * `T` needs to have the same alignment as what `ptr` was allocated with, + /// if the pointer is required to be allocated. /// (`T` having a less strict alignment is not sufficient, the alignment really /// needs to be equal to satisfy the [`dealloc`] requirement that memory must be /// allocated and deallocated with the same layout.) - /// * The size of `T` times the `capacity` (ie. the allocated size in bytes) needs - /// to be the same size as the pointer was allocated with. (Because similar to - /// alignment, [`dealloc`] must be called with the same layout `size`.) + /// * The size of `T` times the `capacity` (ie. the allocated size in bytes), if + /// nonzero, needs to be the same size as the pointer was allocated with. + /// (Because similar to alignment, [`dealloc`] must be called with the same + /// layout `size`.) /// * `length` needs to be less than or equal to `capacity`. /// * The first `length` values must be properly initialized values of type `T`. - /// * `capacity` needs to be the capacity that the pointer was allocated with. + /// * `capacity` needs to be the capacity that the pointer was allocated with, + /// if the pointer is required to be allocated. /// * The allocated size in bytes must be no larger than `isize::MAX`. /// See the safety documentation of [`pointer::offset`]. /// @@ -770,12 +795,16 @@ impl<T> Vec<T> { /// order as the arguments to [`from_raw_parts`]. /// /// After calling this function, the caller is responsible for the - /// memory previously managed by the `Vec`. The only way to do - /// this is to convert the raw pointer, length, and capacity back - /// into a `Vec` with the [`from_raw_parts`] function, allowing - /// the destructor to perform the cleanup. + /// memory previously managed by the `Vec`. Most often, one does + /// this by converting the raw pointer, length, and capacity back + /// into a `Vec` with the [`from_raw_parts`] function; more generally, + /// if `T` is non-zero-sized and the capacity is nonzero, one may use + /// any method that calls [`dealloc`] with a layout of + /// `Layout::array::<T>(capacity)`; if `T` is zero-sized or the + /// capacity is zero, nothing needs to be done. /// /// [`from_raw_parts`]: Vec::from_raw_parts + /// [`dealloc`]: crate::alloc::GlobalAlloc::dealloc /// /// # Examples /// @@ -1755,6 +1784,12 @@ impl<T, A: Allocator> Vec<T, A> { /// may still invalidate this pointer. /// See the second example below for how this guarantee can be used. /// + /// The method also guarantees that, as long as `T` is not zero-sized and the capacity is + /// nonzero, the pointer may be passed into [`dealloc`] with a layout of + /// `Layout::array::<T>(capacity)` in order to deallocate the backing memory. If this is done, + /// be careful not to run the destructor of the `Vec`, as dropping it will result in + /// double-frees. Wrapping the `Vec` in a [`ManuallyDrop`] is the typical way to achieve this. + /// /// # Examples /// /// ``` @@ -1787,9 +1822,24 @@ impl<T, A: Allocator> Vec<T, A> { /// } /// ``` /// + /// Deallocating a vector using [`Box`] (which uses [`dealloc`] internally): + /// + /// ``` + /// use std::mem::{ManuallyDrop, MaybeUninit}; + /// + /// let mut v = ManuallyDrop::new(vec![0, 1, 2]); + /// let ptr = v.as_mut_ptr(); + /// let capacity = v.capacity(); + /// let slice_ptr: *mut [MaybeUninit<i32>] = + /// std::ptr::slice_from_raw_parts_mut(ptr.cast(), capacity); + /// drop(unsafe { Box::from_raw(slice_ptr) }); + /// ``` + /// /// [`as_mut_ptr`]: Vec::as_mut_ptr /// [`as_ptr`]: Vec::as_ptr /// [`as_non_null`]: Vec::as_non_null + /// [`dealloc`]: crate::alloc::GlobalAlloc::dealloc + /// [`ManuallyDrop`]: core::mem::ManuallyDrop #[stable(feature = "vec_as_ptr", since = "1.37.0")] #[rustc_const_stable(feature = "const_vec_string_slice", since = "1.87.0")] #[rustc_never_returns_null_ptr] diff --git a/library/std/src/sys/pal/uefi/tests.rs b/library/std/src/sys/pal/uefi/tests.rs index 49e75a1a70d..56ca999cc7e 100644 --- a/library/std/src/sys/pal/uefi/tests.rs +++ b/library/std/src/sys/pal/uefi/tests.rs @@ -1,8 +1,13 @@ +//! These tests are not run automatically right now. Please run these tests manually by copying them +//! to a separate project when modifying any related code. + use super::alloc::*; -use super::time::*; +use super::time::system_time_internal::{from_uefi, to_uefi}; use crate::io::{IoSlice, IoSliceMut}; use crate::time::Duration; +const SECS_IN_MINUTE: u64 = 60; + #[test] fn align() { // UEFI ABI specifies that allocation alignment minimum is always 8. So this can be @@ -24,21 +29,61 @@ fn align() { } #[test] -fn epoch() { - let t = r_efi::system::Time { - year: 1970, +fn systemtime_start() { + let t = r_efi::efi::Time { + year: 1900, + month: 1, + day: 1, + hour: 0, + minute: 0, + second: 0, + nanosecond: 0, + timezone: -1440, + daylight: 0, + pad2: 0, + }; + assert_eq!(from_uefi(&t), Duration::new(0, 0)); + assert_eq!(t, to_uefi(&from_uefi(&t), -1440, 0).unwrap()); + assert!(to_uefi(&from_uefi(&t), 0, 0).is_none()); +} + +#[test] +fn systemtime_utc_start() { + let t = r_efi::efi::Time { + year: 1900, month: 1, day: 1, hour: 0, minute: 0, second: 0, + pad1: 0, nanosecond: 0, - timezone: r_efi::efi::UNSPECIFIED_TIMEZONE, + timezone: 0, daylight: 0, + pad2: 0, + }; + assert_eq!(from_uefi(&t), Duration::new(1440 * SECS_IN_MINUTE, 0)); + assert_eq!(t, to_uefi(&from_uefi(&t), 0, 0).unwrap()); + assert!(to_uefi(&from_uefi(&t), -1440, 0).is_some()); +} + +#[test] +fn systemtime_end() { + let t = r_efi::efi::Time { + year: 9999, + month: 12, + day: 31, + hour: 23, + minute: 59, + second: 59, pad1: 0, + nanosecond: 0, + timezone: 1440, + daylight: 0, pad2: 0, }; - assert_eq!(system_time_internal::uefi_time_to_duration(t), Duration::new(0, 0)); + assert!(to_uefi(&from_uefi(&t), 1440, 0).is_some()); + assert!(to_uefi(&from_uefi(&t), 1439, 0).is_none()); } // UEFI IoSlice and IoSliceMut Tests diff --git a/library/std/src/sys/pal/uefi/time.rs b/library/std/src/sys/pal/uefi/time.rs index eeb2c35ffbb..a5ab7690327 100644 --- a/library/std/src/sys/pal/uefi/time.rs +++ b/library/std/src/sys/pal/uefi/time.rs @@ -1,16 +1,42 @@ use crate::time::Duration; -const SECS_IN_MINUTE: u64 = 60; -const SECS_IN_HOUR: u64 = SECS_IN_MINUTE * 60; -const SECS_IN_DAY: u64 = SECS_IN_HOUR * 24; - #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] pub struct Instant(Duration); +/// When a Timezone is specified, the stored Duration is in UTC. If timezone is unspecified, then +/// the timezone is assumed to be in UTC. +/// +/// UEFI SystemTime is stored as Duration from 1900-01-01-00:00:00 with timezone -1440 as anchor #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] pub struct SystemTime(Duration); -pub const UNIX_EPOCH: SystemTime = SystemTime(Duration::from_secs(0)); +pub const UNIX_EPOCH: SystemTime = SystemTime::from_uefi(r_efi::efi::Time { + year: 1970, + month: 1, + day: 1, + hour: 0, + minute: 0, + second: 0, + nanosecond: 0, + timezone: 0, + daylight: 0, + pad1: 0, + pad2: 0, +}); + +const MAX_UEFI_TIME: SystemTime = SystemTime::from_uefi(r_efi::efi::Time { + year: 9999, + month: 12, + day: 31, + hour: 23, + minute: 59, + second: 59, + nanosecond: 999_999_999, + timezone: 1440, + daylight: 0, + pad1: 0, + pad2: 0, +}); impl Instant { pub fn now() -> Instant { @@ -40,6 +66,15 @@ impl Instant { } impl SystemTime { + pub(crate) const fn from_uefi(t: r_efi::efi::Time) -> Self { + Self(system_time_internal::from_uefi(&t)) + } + + #[expect(dead_code)] + pub(crate) const fn to_uefi(self, timezone: i16, daylight: u8) -> Option<r_efi::efi::Time> { + system_time_internal::to_uefi(&self.0, timezone, daylight) + } + pub fn now() -> SystemTime { system_time_internal::now() .unwrap_or_else(|| panic!("time not implemented on this platform")) @@ -50,11 +85,14 @@ impl SystemTime { } pub fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> { - Some(SystemTime(self.0.checked_add(*other)?)) + let temp = Self(self.0.checked_add(*other)?); + + // Check if can be represented in UEFI + if temp <= MAX_UEFI_TIME { Some(temp) } else { None } } pub fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> { - Some(SystemTime(self.0.checked_sub(*other)?)) + self.0.checked_sub(*other).map(Self) } } @@ -66,51 +104,132 @@ pub(crate) mod system_time_internal { use crate::mem::MaybeUninit; use crate::ptr::NonNull; + const SECS_IN_MINUTE: u64 = 60; + const SECS_IN_HOUR: u64 = SECS_IN_MINUTE * 60; + const SECS_IN_DAY: u64 = SECS_IN_HOUR * 24; + const TIMEZONE_DELTA: u64 = 1440 * SECS_IN_MINUTE; + pub fn now() -> Option<SystemTime> { let runtime_services: NonNull<RuntimeServices> = helpers::runtime_services()?; let mut t: MaybeUninit<Time> = MaybeUninit::uninit(); let r = unsafe { ((*runtime_services.as_ptr()).get_time)(t.as_mut_ptr(), crate::ptr::null_mut()) }; - if r.is_error() { return None; } let t = unsafe { t.assume_init() }; - Some(SystemTime(uefi_time_to_duration(t))) + Some(SystemTime::from_uefi(t)) } - // This algorithm is based on the one described in the post - // https://blog.reverberate.org/2020/05/12/optimizing-date-algorithms.html - pub(crate) const fn uefi_time_to_duration(t: r_efi::system::Time) -> Duration { - assert!(t.month <= 12); - assert!(t.month != 0); + /// This algorithm is a modified form of the one described in the post + /// https://blog.reverberate.org/2020/05/12/optimizing-date-algorithms.html + /// + /// The changes are to use 1900-01-01-00:00:00 with timezone -1440 as anchor instead of UNIX + /// epoch used in the original algorithm. + pub(crate) const fn from_uefi(t: &Time) -> Duration { + assert!(t.month <= 12 && t.month != 0); + assert!(t.year >= 1900 && t.year <= 9999); + assert!(t.day <= 31 && t.day != 0); + + assert!(t.second < 60); + assert!(t.minute < 60); + assert!(t.hour < 24); + assert!(t.nanosecond < 1_000_000_000); + + assert!( + (t.timezone <= 1440 && t.timezone >= -1440) + || t.timezone == r_efi::efi::UNSPECIFIED_TIMEZONE + ); const YEAR_BASE: u32 = 4800; /* Before min year, multiple of 400. */ - // Calculate the number of days since 1/1/1970 + // Calculate the number of days since 1/1/1900. This is the earliest supported date in UEFI + // time. // Use 1 March as the start let (m_adj, overflow): (u32, bool) = (t.month as u32).overflowing_sub(3); let (carry, adjust): (u32, u32) = if overflow { (1, 12) } else { (0, 0) }; let y_adj: u32 = (t.year as u32) + YEAR_BASE - carry; let month_days: u32 = (m_adj.wrapping_add(adjust) * 62719 + 769) / 2048; let leap_days: u32 = y_adj / 4 - y_adj / 100 + y_adj / 400; - let days: u32 = y_adj * 365 + leap_days + month_days + (t.day as u32 - 1) - 2472632; + let days: u32 = y_adj * 365 + leap_days + month_days + (t.day as u32 - 1) - 2447065; let localtime_epoch: u64 = (days as u64) * SECS_IN_DAY + (t.second as u64) + (t.minute as u64) * SECS_IN_MINUTE + (t.hour as u64) * SECS_IN_HOUR; - let utc_epoch: u64 = if t.timezone == r_efi::efi::UNSPECIFIED_TIMEZONE { - localtime_epoch + // Calculate the offset from 1/1/1900 at timezone -1440 min + let adjusted_localtime_epoc: u64 = localtime_epoch + TIMEZONE_DELTA; + + let epoch: u64 = if t.timezone == r_efi::efi::UNSPECIFIED_TIMEZONE { + adjusted_localtime_epoc } else { - (localtime_epoch as i64 + (t.timezone as i64) * SECS_IN_MINUTE as i64) as u64 + adjusted_localtime_epoc + .checked_add_signed((t.timezone as i64) * SECS_IN_MINUTE as i64) + .unwrap() }; - Duration::new(utc_epoch, t.nanosecond) + Duration::new(epoch, t.nanosecond) + } + + /// This algorithm is a modifed version of the one described in the post: + /// https://howardhinnant.github.io/date_algorithms.html#clive_from_days + /// + /// The changes are to use 1900-01-01-00:00:00 with timezone -1440 as anchor instead of UNIX + /// epoch used in the original algorithm. + pub(crate) const fn to_uefi(dur: &Duration, timezone: i16, daylight: u8) -> Option<Time> { + // Check timzone validity + assert!(timezone <= 1440 && timezone >= -1440); + + // FIXME(#126043): use checked_sub_signed once stablized + let secs = + dur.as_secs().checked_add_signed((-timezone as i64) * SECS_IN_MINUTE as i64).unwrap(); + + // Convert to seconds since 1900-01-01-00:00:00 in timezone. + let Some(secs) = secs.checked_sub(TIMEZONE_DELTA) else { return None }; + + let days = secs / SECS_IN_DAY; + let remaining_secs = secs % SECS_IN_DAY; + + let z = days + 693901; + let era = z / 146097; + let doe = z - (era * 146097); + let yoe = (doe - doe / 1460 + doe / 36524 - doe / 146096) / 365; + let mut y = yoe + era * 400; + let doy = doe - (365 * yoe + yoe / 4 - yoe / 100); + let mp = (5 * doy + 2) / 153; + let d = doy - (153 * mp + 2) / 5 + 1; + let m = if mp < 10 { mp + 3 } else { mp - 9 }; + + if m <= 2 { + y += 1; + } + + let hour = (remaining_secs / SECS_IN_HOUR) as u8; + let minute = ((remaining_secs % SECS_IN_HOUR) / SECS_IN_MINUTE) as u8; + let second = (remaining_secs % SECS_IN_MINUTE) as u8; + + // Check Bounds + if y >= 1900 && y <= 9999 { + Some(Time { + year: y as u16, + month: m as u8, + day: d as u8, + hour, + minute, + second, + nanosecond: dur.subsec_nanos(), + timezone, + daylight, + pad1: 0, + pad2: 0, + }) + } else { + None + } } } diff --git a/src/ci/docker/host-x86_64/pr-check-2/Dockerfile b/src/ci/docker/host-x86_64/pr-check-2/Dockerfile index 1a219125593..6fea2437276 100644 --- a/src/ci/docker/host-x86_64/pr-check-2/Dockerfile +++ b/src/ci/docker/host-x86_64/pr-check-2/Dockerfile @@ -33,11 +33,11 @@ ENV SCRIPT \ python3 ../x.py test --stage 1 src/tools/compiletest && \ python3 ../x.py doc bootstrap && \ # Build both public and internal documentation. - RUSTDOCFLAGS=\"--document-private-items --document-hidden-items\" python3 ../x.py doc compiler --stage 2 && \ - RUSTDOCFLAGS=\"--document-private-items --document-hidden-items\" python3 ../x.py doc library --stage 2 && \ + RUSTDOCFLAGS=\"--document-private-items --document-hidden-items\" python3 ../x.py doc compiler --stage 1 && \ + RUSTDOCFLAGS=\"--document-private-items --document-hidden-items\" python3 ../x.py doc library --stage 1 && \ mkdir -p /checkout/obj/staging/doc && \ cp -r build/x86_64-unknown-linux-gnu/doc /checkout/obj/staging && \ - RUSTDOCFLAGS=\"--document-private-items --document-hidden-items\" python3 ../x.py doc library/test --stage 2 && \ + RUSTDOCFLAGS=\"--document-private-items --document-hidden-items\" python3 ../x.py doc library/test --stage 1 && \ # The BOOTSTRAP_TRACING flag is added to verify whether the # bootstrap process compiles successfully with this flag enabled. BOOTSTRAP_TRACING=1 python3 ../x.py --help diff --git a/src/doc/reference b/src/doc/reference -Subproject 1be151c051a082b542548c62cafbcb055fa8944 +Subproject 59b8af811886313577615c2cf0e045f01faed88 diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example -Subproject bd1279cdc9865bfff605e741fb76a0b2f07314a +Subproject adc1f3b9012ad3255eea2054ca30596a953d053 diff --git a/src/doc/rustc-dev-guide/src/stability.md b/src/doc/rustc-dev-guide/src/stability.md index c26d34273d7..3c4c65fdd5a 100644 --- a/src/doc/rustc-dev-guide/src/stability.md +++ b/src/doc/rustc-dev-guide/src/stability.md @@ -182,6 +182,11 @@ of the standard library raises it to a warning with `#![warn(deprecated_in_future)]`. ## unstable_feature_bound -The `#[unstable_feature_bound(foo)]` attribute can be used together with `#[unstable]` attribute to mark an `impl` of stable type and stable trait as unstable. In std/core, an item annotated with `#[unstable_feature_bound(foo)]` can only be used by another item that is also annotated with `#[unstable_feature_bound(foo)]`. Outside of std/core, using an item with `#[unstable_feature_bound(foo)]` requires the feature to be enabled with `#![feature(foo)]` attribute on the crate. Currently, only `impl`s and free functions can be annotated with `#[unstable_feature_bound]`. +The `#[unstable_feature_bound(foo)]` attribute can be used together with `#[unstable]` attribute to mark an `impl` of stable type and stable trait as unstable. In std/core, an item annotated with `#[unstable_feature_bound(foo)]` can only be used by another item that is also annotated with `#[unstable_feature_bound(foo)]`. Outside of std/core, using an item with `#[unstable_feature_bound(foo)]` requires the feature to be enabled with `#![feature(foo)]` attribute on the crate. + +Currently, the items that can be annotated with `#[unstable_feature_bound]` are: +- `impl` +- free function +- trait [blog]: https://www.ralfj.de/blog/2018/07/19/const.html diff --git a/src/doc/unstable-book/src/compiler-environment-variables/SDKROOT.md b/src/doc/unstable-book/src/compiler-environment-variables/SDKROOT.md index be9ed02f54d..6d371ae289f 100644 --- a/src/doc/unstable-book/src/compiler-environment-variables/SDKROOT.md +++ b/src/doc/unstable-book/src/compiler-environment-variables/SDKROOT.md @@ -1,6 +1,6 @@ # `SDKROOT` This environment variable is used on Apple targets. -It is passed through to the linker (currently either as `-isysroot` or `-syslibroot`). +It is passed through to the linker (currently either directly or via the `-syslibroot` flag). Note that this variable is not always respected. When the SDKROOT is clearly wrong (e.g. when the platform of the SDK does not match the `--target` used by rustc), this is ignored and rustc does its own detection. diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 7194c2fcede..890bfaced6c 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2768,7 +2768,7 @@ fn clean_maybe_renamed_item<'tcx>( // These kinds of item either don't need a `name` or accept a `None` one so we handle them // before. match item.kind { - ItemKind::Impl(impl_) => return clean_impl(impl_, item.owner_id.def_id, cx), + ItemKind::Impl(ref impl_) => return clean_impl(impl_, item.owner_id.def_id, cx), ItemKind::Use(path, kind) => { return clean_use_statement( item, @@ -2896,7 +2896,7 @@ fn clean_impl<'tcx>( ) -> Vec<Item> { let tcx = cx.tcx; let mut ret = Vec::new(); - let trait_ = impl_.of_trait.as_ref().map(|t| clean_trait_ref(t, cx)); + let trait_ = impl_.of_trait.map(|t| clean_trait_ref(&t.trait_ref, cx)); let items = impl_ .items .iter() @@ -2922,7 +2922,10 @@ fn clean_impl<'tcx>( }); let mut make_item = |trait_: Option<Path>, for_: Type, items: Vec<Item>| { let kind = ImplItem(Box::new(Impl { - safety: impl_.safety, + safety: match impl_.of_trait { + Some(of_trait) => of_trait.safety, + None => hir::Safety::Safe, + }, generics: clean_generics(impl_.generics, cx), trait_, for_, diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index 02ee34aaac6..759f53974f5 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -1656,11 +1656,9 @@ fn display_c_like_variant( } else if should_show_enum_discriminant { let adt_def = cx.tcx().adt_def(enum_def_id); let discr = adt_def.discriminant_for_variant(cx.tcx(), index); - if discr.ty.is_signed() { - write!(w, "{} = {}", name.as_str(), discr.val as i128)?; - } else { - write!(w, "{} = {}", name.as_str(), discr.val)?; - } + // Use `discr`'s `Display` impl to render the value with the correct + // signedness, including proper sign-extension for signed types. + write!(w, "{} = {}", name.as_str(), discr)?; } else { write!(w, "{name}")?; } diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index bcb676cd1f1..40191551e4f 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -997,6 +997,7 @@ fn preprocess_link( } }; + let is_shortcut_style = ori_link.kind == LinkType::ShortcutUnknown; // If there's no backticks, be lenient and revert to the old behavior. // This is to prevent churn by linting on stuff that isn't meant to be a link. // only shortcut links have simple enough syntax that they @@ -1013,11 +1014,22 @@ fn preprocess_link( // | has backtick | never ignore | never ignore | // | no backtick | ignore if url-like | never ignore | // |-------------------------------------------------------| - let ignore_urllike = - can_be_url || (ori_link.kind == LinkType::ShortcutUnknown && !ori_link.link.contains('`')); + let ignore_urllike = can_be_url || (is_shortcut_style && !ori_link.link.contains('`')); if ignore_urllike && should_ignore_link(path_str) { return None; } + // If we have an intra-doc link starting with `!` (which isn't `[!]` because this is the never type), we ignore it + // as it is never valid. + // + // The case is common enough because of cases like `#[doc = include_str!("../README.md")]` which often + // uses GitHub-flavored Markdown (GFM) admonitions, such as `[!NOTE]`. + if is_shortcut_style + && let Some(suffix) = ori_link.link.strip_prefix('!') + && !suffix.is_empty() + && suffix.chars().all(|c| c.is_ascii_alphabetic()) + { + return None; + } // Strip generics from the path. let path_str = match strip_generics_from_path(path_str) { diff --git a/src/tools/clippy/clippy_lints/src/arbitrary_source_item_ordering.rs b/src/tools/clippy/clippy_lints/src/arbitrary_source_item_ordering.rs index d6469d32931..36498adff50 100644 --- a/src/tools/clippy/clippy_lints/src/arbitrary_source_item_ordering.rs +++ b/src/tools/clippy/clippy_lints/src/arbitrary_source_item_ordering.rs @@ -534,6 +534,7 @@ fn get_item_name(item: &Item<'_>) -> Option<String> { if let Some(of_trait) = im.of_trait { let mut trait_segs: Vec<String> = of_trait + .trait_ref .path .segments .iter() diff --git a/src/tools/clippy/clippy_lints/src/bool_assert_comparison.rs b/src/tools/clippy/clippy_lints/src/bool_assert_comparison.rs index 581fe33ea0b..f31b67f470f 100644 --- a/src/tools/clippy/clippy_lints/src/bool_assert_comparison.rs +++ b/src/tools/clippy/clippy_lints/src/bool_assert_comparison.rs @@ -130,18 +130,22 @@ impl<'tcx> LateLintPass<'tcx> for BoolAssertComparison { let mut suggestions = vec![(name_span, non_eq_mac.to_string()), (lit_span, String::new())]; - if bool_value ^ eq_macro { - let Some(sugg) = Sugg::hir_opt(cx, non_lit_expr) else { - return; + if let Some(sugg) = Sugg::hir_opt(cx, non_lit_expr) { + let sugg = if bool_value ^ eq_macro { + !sugg.maybe_paren() + } else if ty::Bool == *non_lit_ty.kind() { + sugg + } else { + !!sugg.maybe_paren() }; - suggestions.push((non_lit_expr.span, (!sugg).to_string())); - } + suggestions.push((non_lit_expr.span, sugg.to_string())); - diag.multipart_suggestion( - format!("replace it with `{non_eq_mac}!(..)`"), - suggestions, - Applicability::MachineApplicable, - ); + diag.multipart_suggestion( + format!("replace it with `{non_eq_mac}!(..)`"), + suggestions, + Applicability::MachineApplicable, + ); + } }, ); } diff --git a/src/tools/clippy/clippy_lints/src/copy_iterator.rs b/src/tools/clippy/clippy_lints/src/copy_iterator.rs index 4ecf3e41611..51aebd8b0cf 100644 --- a/src/tools/clippy/clippy_lints/src/copy_iterator.rs +++ b/src/tools/clippy/clippy_lints/src/copy_iterator.rs @@ -37,12 +37,12 @@ declare_lint_pass!(CopyIterator => [COPY_ITERATOR]); impl<'tcx> LateLintPass<'tcx> for CopyIterator { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) { if let ItemKind::Impl(Impl { - of_trait: Some(trait_ref), + of_trait: Some(of_trait), .. }) = item.kind && let ty = cx.tcx.type_of(item.owner_id).instantiate_identity() && is_copy(cx, ty) - && let Some(trait_id) = trait_ref.trait_def_id() + && let Some(trait_id) = of_trait.trait_ref.trait_def_id() && cx.tcx.is_diagnostic_item(sym::Iterator, trait_id) { span_lint_and_note( diff --git a/src/tools/clippy/clippy_lints/src/derivable_impls.rs b/src/tools/clippy/clippy_lints/src/derivable_impls.rs index 0a481ddcd12..7580d6cab66 100644 --- a/src/tools/clippy/clippy_lints/src/derivable_impls.rs +++ b/src/tools/clippy/clippy_lints/src/derivable_impls.rs @@ -183,14 +183,14 @@ fn check_enum<'tcx>(cx: &LateContext<'tcx>, item: &'tcx Item<'_>, func_expr: &Ex impl<'tcx> LateLintPass<'tcx> for DerivableImpls { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) { if let ItemKind::Impl(Impl { - of_trait: Some(trait_ref), + of_trait: Some(of_trait), items: [child], self_ty, .. }) = item.kind && !cx.tcx.is_automatically_derived(item.owner_id.to_def_id()) && !item.span.from_expansion() - && let Some(def_id) = trait_ref.trait_def_id() + && let Some(def_id) = of_trait.trait_ref.trait_def_id() && cx.tcx.is_diagnostic_item(sym::Default, def_id) && let impl_item_hir = child.hir_id() && let Node::ImplItem(impl_item) = cx.tcx.hir_node(impl_item_hir) diff --git a/src/tools/clippy/clippy_lints/src/derive.rs b/src/tools/clippy/clippy_lints/src/derive.rs index 49dd1bb09c6..c53a957f6a8 100644 --- a/src/tools/clippy/clippy_lints/src/derive.rs +++ b/src/tools/clippy/clippy_lints/src/derive.rs @@ -201,10 +201,11 @@ declare_lint_pass!(Derive => [ impl<'tcx> LateLintPass<'tcx> for Derive { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) { if let ItemKind::Impl(Impl { - of_trait: Some(trait_ref), + of_trait: Some(of_trait), .. }) = item.kind { + let trait_ref = &of_trait.trait_ref; let ty = cx.tcx.type_of(item.owner_id).instantiate_identity(); let is_automatically_derived = cx.tcx.is_automatically_derived(item.owner_id.to_def_id()); diff --git a/src/tools/clippy/clippy_lints/src/empty_drop.rs b/src/tools/clippy/clippy_lints/src/empty_drop.rs index 4e948701da4..2b822188434 100644 --- a/src/tools/clippy/clippy_lints/src/empty_drop.rs +++ b/src/tools/clippy/clippy_lints/src/empty_drop.rs @@ -36,11 +36,11 @@ declare_lint_pass!(EmptyDrop => [EMPTY_DROP]); impl LateLintPass<'_> for EmptyDrop { fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) { if let ItemKind::Impl(Impl { - of_trait: Some(trait_ref), + of_trait: Some(of_trait), items: [child], .. }) = item.kind - && trait_ref.trait_def_id() == cx.tcx.lang_items().drop_trait() + && of_trait.trait_ref.trait_def_id() == cx.tcx.lang_items().drop_trait() && let impl_item_hir = child.hir_id() && let Node::ImplItem(impl_item) = cx.tcx.hir_node(impl_item_hir) && let ImplItemKind::Fn(_, b) = &impl_item.kind diff --git a/src/tools/clippy/clippy_lints/src/error_impl_error.rs b/src/tools/clippy/clippy_lints/src/error_impl_error.rs index 6525648efb1..3018e1f1273 100644 --- a/src/tools/clippy/clippy_lints/src/error_impl_error.rs +++ b/src/tools/clippy/clippy_lints/src/error_impl_error.rs @@ -52,7 +52,7 @@ impl<'tcx> LateLintPass<'tcx> for ErrorImplError { ); }, ItemKind::Impl(imp) - if let Some(trait_def_id) = imp.of_trait.and_then(|t| t.trait_def_id()) + if let Some(trait_def_id) = imp.of_trait.and_then(|t| t.trait_ref.trait_def_id()) && let Some(error_def_id) = cx.tcx.get_diagnostic_item(sym::Error) && error_def_id == trait_def_id && let Some(def_id) = path_res(cx, imp.self_ty).opt_def_id().and_then(DefId::as_local) diff --git a/src/tools/clippy/clippy_lints/src/format_impl.rs b/src/tools/clippy/clippy_lints/src/format_impl.rs index 0535ecf5240..416aea51ea1 100644 --- a/src/tools/clippy/clippy_lints/src/format_impl.rs +++ b/src/tools/clippy/clippy_lints/src/format_impl.rs @@ -254,10 +254,10 @@ fn is_format_trait_impl(cx: &LateContext<'_>, impl_item: &ImplItem<'_>) -> Optio if impl_item.ident.name == sym::fmt && let ImplItemKind::Fn(_, body_id) = impl_item.kind && let Some(Impl { - of_trait: Some(trait_ref), + of_trait: Some(of_trait), .. }) = get_parent_as_impl(cx.tcx, impl_item.hir_id()) - && let Some(did) = trait_ref.trait_def_id() + && let Some(did) = of_trait.trait_ref.trait_def_id() && let Some(name) = cx.tcx.get_diagnostic_name(did) && matches!(name, sym::Debug | sym::Display) { 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 1da6952eb64..e3bb5ee10db 100644 --- a/src/tools/clippy/clippy_lints/src/from_over_into.rs +++ b/src/tools/clippy/clippy_lints/src/from_over_into.rs @@ -67,12 +67,12 @@ impl_lint_pass!(FromOverInto => [FROM_OVER_INTO]); impl<'tcx> LateLintPass<'tcx> for FromOverInto { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) { if let ItemKind::Impl(Impl { - of_trait: Some(hir_trait_ref), + of_trait: Some(of_trait), self_ty, items: [impl_item_ref], .. }) = item.kind - && let Some(into_trait_seg) = hir_trait_ref.path.segments.last() + && let Some(into_trait_seg) = of_trait.trait_ref.path.segments.last() // `impl Into<target_ty> for self_ty` && let Some(GenericArgs { args: [GenericArg::Type(target_ty)], .. }) = into_trait_seg.args && span_is_local(item.span) diff --git a/src/tools/clippy/clippy_lints/src/functions/impl_trait_in_params.rs b/src/tools/clippy/clippy_lints/src/functions/impl_trait_in_params.rs index cb83b1395d2..3105e303ae3 100644 --- a/src/tools/clippy/clippy_lints/src/functions/impl_trait_in_params.rs +++ b/src/tools/clippy/clippy_lints/src/functions/impl_trait_in_params.rs @@ -54,8 +54,7 @@ pub(super) fn check_impl_item(cx: &LateContext<'_>, impl_item: &ImplItem<'_>) { if let ImplItemKind::Fn(_, body_id) = impl_item.kind && let hir::Node::Item(item) = cx.tcx.parent_hir_node(impl_item.hir_id()) && let hir::ItemKind::Impl(impl_) = item.kind - && let hir::Impl { of_trait, .. } = *impl_ - && of_trait.is_none() + && let hir::Impl { of_trait: None, .. } = impl_ && let body = cx.tcx.hir_body(body_id) && cx.tcx.visibility(cx.tcx.hir_body_owner_def_id(body.id())).is_public() && !is_in_test(cx.tcx, impl_item.hir_id()) diff --git a/src/tools/clippy/clippy_lints/src/functions/renamed_function_params.rs b/src/tools/clippy/clippy_lints/src/functions/renamed_function_params.rs index 0d6191f2c97..0a7c6e9d5f8 100644 --- a/src/tools/clippy/clippy_lints/src/functions/renamed_function_params.rs +++ b/src/tools/clippy/clippy_lints/src/functions/renamed_function_params.rs @@ -15,11 +15,11 @@ pub(super) fn check_impl_item(cx: &LateContext<'_>, item: &ImplItem<'_>, ignored && let parent_node = cx.tcx.parent_hir_node(item.hir_id()) && let Node::Item(parent_item) = parent_node && let ItemKind::Impl(Impl { - of_trait: Some(trait_ref), + of_trait: Some(of_trait), .. }) = &parent_item.kind && let Some(did) = trait_item_def_id_of_impl(cx, item.owner_id) - && !is_from_ignored_trait(trait_ref, ignored_traits) + && !is_from_ignored_trait(&of_trait.trait_ref, ignored_traits) { let mut param_idents_iter = cx.tcx.hir_body_param_idents(body_id); let mut default_param_idents_iter = cx.tcx.fn_arg_idents(did).iter().copied(); diff --git a/src/tools/clippy/clippy_lints/src/impl_hash_with_borrow_str_and_bytes.rs b/src/tools/clippy/clippy_lints/src/impl_hash_with_borrow_str_and_bytes.rs index 940adbae428..f73182d3af0 100644 --- a/src/tools/clippy/clippy_lints/src/impl_hash_with_borrow_str_and_bytes.rs +++ b/src/tools/clippy/clippy_lints/src/impl_hash_with_borrow_str_and_bytes.rs @@ -1,7 +1,7 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::ty::implements_trait; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::{Item, ItemKind, Path, TraitRef}; +use rustc_hir::{Item, ItemKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::Ty; use rustc_session::declare_lint_pass; @@ -76,10 +76,10 @@ impl LateLintPass<'_> for ImplHashWithBorrowStrBytes { /// three of `Hash`, `Borrow<str>` and `Borrow<[u8]>`. fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) { if let ItemKind::Impl(imp) = item.kind - && let Some(TraitRef {path: Path {span, res, ..}, ..}) = imp.of_trait + && let Some(of_trait) = imp.of_trait && let ty = cx.tcx.type_of(item.owner_id).instantiate_identity() && let Some(hash_id) = cx.tcx.get_diagnostic_item(sym::Hash) - && Res::Def(DefKind::Trait, hash_id) == *res + && Res::Def(DefKind::Trait, hash_id) == of_trait.trait_ref.path.res && let Some(borrow_id) = cx.tcx.get_diagnostic_item(sym::Borrow) // since we are in the `Hash` impl, we don't need to check for that. // we need only to check for `Borrow<str>` and `Borrow<[u8]>` @@ -89,7 +89,7 @@ impl LateLintPass<'_> for ImplHashWithBorrowStrBytes { span_lint_and_then( cx, IMPL_HASH_BORROW_WITH_STR_AND_BYTES, - *span, + of_trait.trait_ref.path.span, "the semantics of `Borrow<T>` around `Hash` can't be satisfied when both `Borrow<str>` and `Borrow<[u8]>` are implemented", |diag| { diag.note("the `Borrow` semantics require that `Hash` must behave the same for all implementations of Borrow<T>"); diff --git a/src/tools/clippy/clippy_lints/src/infallible_try_from.rs b/src/tools/clippy/clippy_lints/src/infallible_try_from.rs index 589c294a678..36df07a4370 100644 --- a/src/tools/clippy/clippy_lints/src/infallible_try_from.rs +++ b/src/tools/clippy/clippy_lints/src/infallible_try_from.rs @@ -45,8 +45,8 @@ declare_lint_pass!(InfallibleTryFrom => [INFALLIBLE_TRY_FROM]); impl<'tcx> LateLintPass<'tcx> for InfallibleTryFrom { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) { let ItemKind::Impl(imp) = item.kind else { return }; - let Some(r#trait) = imp.of_trait else { return }; - let Some(trait_def_id) = r#trait.trait_def_id() else { + let Some(of_trait) = imp.of_trait else { return }; + let Some(trait_def_id) = of_trait.trait_ref.trait_def_id() else { return; }; if !cx.tcx.is_diagnostic_item(sym::TryFrom, trait_def_id) { diff --git a/src/tools/clippy/clippy_lints/src/iter_without_into_iter.rs b/src/tools/clippy/clippy_lints/src/iter_without_into_iter.rs index b89f91f7255..645e0f981f2 100644 --- a/src/tools/clippy/clippy_lints/src/iter_without_into_iter.rs +++ b/src/tools/clippy/clippy_lints/src/iter_without_into_iter.rs @@ -125,8 +125,9 @@ impl LateLintPass<'_> for IterWithoutIntoIter { fn check_item(&mut self, cx: &LateContext<'_>, item: &rustc_hir::Item<'_>) { if let ItemKind::Impl(imp) = item.kind && let TyKind::Ref(_, self_ty_without_ref) = &imp.self_ty.kind - && let Some(trait_ref) = imp.of_trait - && trait_ref + && let Some(of_trait) = imp.of_trait + && of_trait + .trait_ref .trait_def_id() .is_some_and(|did| cx.tcx.is_diagnostic_item(sym::IntoIterator, did)) && !item.span.in_external_macro(cx.sess().source_map()) diff --git a/src/tools/clippy/clippy_lints/src/lifetimes.rs b/src/tools/clippy/clippy_lints/src/lifetimes.rs index 35c9d2fd4eb..149ae5e710c 100644 --- a/src/tools/clippy/clippy_lints/src/lifetimes.rs +++ b/src/tools/clippy/clippy_lints/src/lifetimes.rs @@ -150,7 +150,7 @@ impl<'tcx> LateLintPass<'tcx> for Lifetimes { } = item.kind { check_fn_inner(cx, sig, Some(id), None, generics, item.span, true, self.msrv); - } else if let ItemKind::Impl(impl_) = item.kind + } else if let ItemKind::Impl(impl_) = &item.kind && !item.span.from_expansion() { report_extra_impl_lifetimes(cx, impl_); @@ -712,8 +712,8 @@ fn report_extra_impl_lifetimes<'tcx>(cx: &LateContext<'tcx>, impl_: &'tcx Impl<' let mut checker = LifetimeChecker::<middle_nested_filter::All>::new(cx, impl_.generics); walk_generics(&mut checker, impl_.generics); - if let Some(ref trait_ref) = impl_.of_trait { - walk_trait_ref(&mut checker, trait_ref); + if let Some(of_trait) = impl_.of_trait { + walk_trait_ref(&mut checker, &of_trait.trait_ref); } walk_unambig_ty(&mut checker, impl_.self_ty); for &item in impl_.items { diff --git a/src/tools/clippy/clippy_lints/src/missing_fields_in_debug.rs b/src/tools/clippy/clippy_lints/src/missing_fields_in_debug.rs index 18e2b384a46..8822b32b1c3 100644 --- a/src/tools/clippy/clippy_lints/src/missing_fields_in_debug.rs +++ b/src/tools/clippy/clippy_lints/src/missing_fields_in_debug.rs @@ -198,8 +198,8 @@ fn check_struct<'tcx>( impl<'tcx> LateLintPass<'tcx> for MissingFieldsInDebug { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) { // is this an `impl Debug for X` block? - if let ItemKind::Impl(Impl { of_trait: Some(trait_ref), self_ty, .. }) = item.kind - && let Res::Def(DefKind::Trait, trait_def_id) = trait_ref.path.res + if let ItemKind::Impl(Impl { of_trait: Some(of_trait), self_ty, .. }) = item.kind + && let Res::Def(DefKind::Trait, trait_def_id) = of_trait.trait_ref.path.res && let TyKind::Path(QPath::Resolved(_, self_path)) = &self_ty.kind // make sure that the self type is either a struct, an enum or a union // this prevents ICEs such as when self is a type parameter or a primitive type diff --git a/src/tools/clippy/clippy_lints/src/missing_trait_methods.rs b/src/tools/clippy/clippy_lints/src/missing_trait_methods.rs index 399bf4e1806..9cc93bf0653 100644 --- a/src/tools/clippy/clippy_lints/src/missing_trait_methods.rs +++ b/src/tools/clippy/clippy_lints/src/missing_trait_methods.rs @@ -61,10 +61,10 @@ impl<'tcx> LateLintPass<'tcx> for MissingTraitMethods { if !is_lint_allowed(cx, MISSING_TRAIT_METHODS, item.hir_id()) && span_is_local(item.span) && let ItemKind::Impl(Impl { - of_trait: Some(trait_ref), + of_trait: Some(of_trait), .. }) = item.kind - && let Some(trait_id) = trait_ref.trait_def_id() + && let Some(trait_id) = of_trait.trait_ref.trait_def_id() { let trait_item_ids: DefIdSet = cx .tcx diff --git a/src/tools/clippy/clippy_lints/src/non_copy_const.rs b/src/tools/clippy/clippy_lints/src/non_copy_const.rs index 388c029c9ef..8a5a6f4a4dc 100644 --- a/src/tools/clippy/clippy_lints/src/non_copy_const.rs +++ b/src/tools/clippy/clippy_lints/src/non_copy_const.rs @@ -778,7 +778,7 @@ impl<'tcx> LateLintPass<'tcx> for NonCopyConst<'tcx> { if let Node::Item(parent_item) = cx.tcx.parent_hir_node(item.hir_id()) && let ItemKind::Impl(impl_block) = parent_item.kind && let Some(of_trait) = impl_block.of_trait - && let Some(trait_id) = of_trait.trait_def_id() + && let Some(trait_id) = of_trait.trait_ref.trait_def_id() { // Replace all instances of `<Self as Trait>::AssocType` with the // unit type and check again. If the result is the same then the 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 8ff78ec7c58..b810bc01fbd 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 @@ -83,10 +83,10 @@ impl<'tcx> LateLintPass<'tcx> for NonSendFieldInSendTy { if !item.span.in_external_macro(cx.tcx.sess.source_map()) && let Some(send_trait) = cx.tcx.get_diagnostic_item(sym::Send) && let ItemKind::Impl(hir_impl) = &item.kind - && let Some(trait_ref) = &hir_impl.of_trait - && let Some(trait_id) = trait_ref.trait_def_id() + && let Some(of_trait) = &hir_impl.of_trait + && let Some(trait_id) = of_trait.trait_ref.trait_def_id() && send_trait == trait_id - && hir_impl.polarity == ImplPolarity::Positive + && of_trait.polarity == ImplPolarity::Positive && let Some(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/operators/op_ref.rs b/src/tools/clippy/clippy_lints/src/operators/op_ref.rs index 0a1f2625f4c..9c160ff680e 100644 --- a/src/tools/clippy/clippy_lints/src/operators/op_ref.rs +++ b/src/tools/clippy/clippy_lints/src/operators/op_ref.rs @@ -183,7 +183,7 @@ fn in_impl<'tcx>( && let item = cx.tcx.hir_expect_item(impl_def_id.expect_local()) && let ItemKind::Impl(item) = &item.kind && let Some(of_trait) = &item.of_trait - && let Some(seg) = of_trait.path.segments.last() + && let Some(seg) = of_trait.trait_ref.path.segments.last() && let Res::Def(_, trait_id) = seg.res && trait_id == bin_op && let Some(generic_args) = seg.args diff --git a/src/tools/clippy/clippy_lints/src/partialeq_ne_impl.rs b/src/tools/clippy/clippy_lints/src/partialeq_ne_impl.rs index 301b2cd4bf2..77751e75a8e 100644 --- a/src/tools/clippy/clippy_lints/src/partialeq_ne_impl.rs +++ b/src/tools/clippy/clippy_lints/src/partialeq_ne_impl.rs @@ -34,15 +34,15 @@ declare_lint_pass!(PartialEqNeImpl => [PARTIALEQ_NE_IMPL]); impl<'tcx> LateLintPass<'tcx> for PartialEqNeImpl { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) { if let ItemKind::Impl(Impl { - of_trait: Some(trait_ref), + of_trait: Some(of_trait), items: impl_items, .. }) = item.kind && !cx.tcx.is_automatically_derived(item.owner_id.to_def_id()) && let Some(eq_trait) = cx.tcx.lang_items().eq_trait() - && trait_ref.path.res.def_id() == eq_trait + && of_trait.trait_ref.path.res.def_id() == eq_trait { - for impl_item in *impl_items { + for impl_item in impl_items { if cx.tcx.item_name(impl_item.owner_id) == sym::ne { span_lint_hir( cx, diff --git a/src/tools/clippy/clippy_lints/src/same_name_method.rs b/src/tools/clippy/clippy_lints/src/same_name_method.rs index 67eb71f7d07..b87751f4986 100644 --- a/src/tools/clippy/clippy_lints/src/same_name_method.rs +++ b/src/tools/clippy/clippy_lints/src/same_name_method.rs @@ -68,9 +68,9 @@ impl<'tcx> LateLintPass<'tcx> for SameNameMethod { let existing_name = map.get_mut(res).unwrap(); match of_trait { - Some(trait_ref) => { + Some(of_trait) => { let mut methods_in_trait: BTreeSet<Symbol> = if let Node::TraitRef(TraitRef { path, .. }) = - cx.tcx.hir_node(trait_ref.hir_ref_id) + cx.tcx.hir_node(of_trait.trait_ref.hir_ref_id) && let Res::Def(DefKind::Trait, did) = path.res { // FIXME: if diff --git a/src/tools/clippy/clippy_lints/src/serde_api.rs b/src/tools/clippy/clippy_lints/src/serde_api.rs index 2de22e4b6a3..01c7f394b9a 100644 --- a/src/tools/clippy/clippy_lints/src/serde_api.rs +++ b/src/tools/clippy/clippy_lints/src/serde_api.rs @@ -26,16 +26,16 @@ declare_lint_pass!(SerdeApi => [SERDE_API_MISUSE]); impl<'tcx> LateLintPass<'tcx> for SerdeApi { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) { if let ItemKind::Impl(Impl { - of_trait: Some(trait_ref), + of_trait: Some(of_trait), items, .. }) = item.kind { - let did = trait_ref.path.res.def_id(); + let did = of_trait.trait_ref.path.res.def_id(); if paths::SERDE_DE_VISITOR.matches(cx, did) { let mut seen_str = None; let mut seen_string = None; - for item in *items { + for item in items { match cx.tcx.item_name(item.owner_id) { sym::visit_str => seen_str = Some(cx.tcx.def_span(item.owner_id)), sym::visit_string => seen_string = Some(cx.tcx.def_span(item.owner_id)), diff --git a/src/tools/clippy/clippy_lints/src/to_string_trait_impl.rs b/src/tools/clippy/clippy_lints/src/to_string_trait_impl.rs index 9596b85664b..303f6028bd5 100644 --- a/src/tools/clippy/clippy_lints/src/to_string_trait_impl.rs +++ b/src/tools/clippy/clippy_lints/src/to_string_trait_impl.rs @@ -48,10 +48,10 @@ declare_lint_pass!(ToStringTraitImpl => [TO_STRING_TRAIT_IMPL]); impl<'tcx> LateLintPass<'tcx> for ToStringTraitImpl { fn check_item(&mut self, cx: &LateContext<'tcx>, it: &'tcx Item<'tcx>) { if let ItemKind::Impl(Impl { - of_trait: Some(trait_ref), + of_trait: Some(of_trait), .. }) = it.kind - && let Some(trait_did) = trait_ref.trait_def_id() + && let Some(trait_did) = of_trait.trait_ref.trait_def_id() && cx.tcx.is_diagnostic_item(sym::ToString, trait_did) { span_lint_and_help( diff --git a/src/tools/clippy/clippy_lints/src/unconditional_recursion.rs b/src/tools/clippy/clippy_lints/src/unconditional_recursion.rs index dcddff557d1..e843e169113 100644 --- a/src/tools/clippy/clippy_lints/src/unconditional_recursion.rs +++ b/src/tools/clippy/clippy_lints/src/unconditional_recursion.rs @@ -137,9 +137,9 @@ fn get_impl_trait_def_id(cx: &LateContext<'_>, method_def_id: LocalDefId) -> Opt // We exclude `impl` blocks generated from rustc's proc macros. && !cx.tcx.is_automatically_derived(owner_id.to_def_id()) // It is a implementation of a trait. - && let Some(trait_) = impl_.of_trait + && let Some(of_trait) = impl_.of_trait { - trait_.trait_def_id() + of_trait.trait_ref.trait_def_id() } else { None } @@ -242,8 +242,8 @@ fn check_to_string(cx: &LateContext<'_>, method_span: Span, method_def_id: Local // We exclude `impl` blocks generated from rustc's proc macros. && !cx.tcx.is_automatically_derived(owner_id.to_def_id()) // It is a implementation of a trait. - && let Some(trait_) = impl_.of_trait - && let Some(trait_def_id) = trait_.trait_def_id() + && let Some(of_trait) = impl_.of_trait + && let Some(trait_def_id) = of_trait.trait_ref.trait_def_id() // The trait is `ToString`. && cx.tcx.is_diagnostic_item(sym::ToString, trait_def_id) { diff --git a/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs b/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs index cf603c6190b..1c52de52619 100644 --- a/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs +++ b/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs @@ -8,7 +8,7 @@ use clippy_utils::source::walk_span_to_context; use clippy_utils::visitors::{Descend, for_each_expr}; use hir::HirId; use rustc_hir as hir; -use rustc_hir::{Block, BlockCheckMode, ItemKind, Node, UnsafeSource}; +use rustc_hir::{Block, BlockCheckMode, Impl, ItemKind, Node, UnsafeSource}; use rustc_lexer::{FrontmatterAllowed, TokenKind, tokenize}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_session::impl_lint_pass; @@ -204,7 +204,7 @@ impl<'tcx> LateLintPass<'tcx> for UndocumentedUnsafeBlocks { let item_has_safety_comment = item_has_safety_comment(cx, item); match (&item.kind, item_has_safety_comment) { // lint unsafe impl without safety comment - (ItemKind::Impl(impl_), HasSafetyComment::No) if impl_.safety.is_unsafe() => { + (ItemKind::Impl(Impl { of_trait: Some(of_trait), .. }), HasSafetyComment::No) if of_trait.safety.is_unsafe() => { if !is_lint_allowed(cx, UNDOCUMENTED_UNSAFE_BLOCKS, item.hir_id()) && !is_unsafe_from_proc_macro(cx, item.span) { @@ -228,7 +228,7 @@ impl<'tcx> LateLintPass<'tcx> for UndocumentedUnsafeBlocks { } }, // lint safe impl with unnecessary safety comment - (ItemKind::Impl(impl_), HasSafetyComment::Yes(pos)) if impl_.safety.is_safe() => { + (ItemKind::Impl(Impl { of_trait: Some(of_trait), .. }), HasSafetyComment::Yes(pos)) if of_trait.safety.is_safe() => { if !is_lint_allowed(cx, UNNECESSARY_SAFETY_COMMENT, item.hir_id()) { let (span, help_span) = mk_spans(pos); diff --git a/src/tools/clippy/clippy_lints/src/write.rs b/src/tools/clippy/clippy_lints/src/write.rs index d9a007635ca..a15e4e42e71 100644 --- a/src/tools/clippy/clippy_lints/src/write.rs +++ b/src/tools/clippy/clippy_lints/src/write.rs @@ -347,10 +347,10 @@ impl<'tcx> LateLintPass<'tcx> for Write { fn is_debug_impl(cx: &LateContext<'_>, item: &Item<'_>) -> bool { if let ItemKind::Impl(Impl { - of_trait: Some(trait_ref), + of_trait: Some(of_trait), .. }) = &item.kind - && let Some(trait_id) = trait_ref.trait_def_id() + && let Some(trait_id) = of_trait.trait_ref.trait_def_id() { cx.tcx.is_diagnostic_item(sym::Debug, trait_id) } else { diff --git a/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs b/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs index 0312bf56e59..24e017f7cf7 100644 --- a/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs +++ b/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs @@ -473,33 +473,27 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool { eq_id(*li, *ri) && eq_generics(lg, rg) && over(lb, rb, eq_generic_bound) }, ( - Impl(box ast::Impl { - safety: lu, - polarity: lp, - defaultness: ld, - constness: lc, + Impl(ast::Impl { generics: lg, of_trait: lot, self_ty: lst, items: li, }), - Impl(box ast::Impl { - safety: ru, - polarity: rp, - defaultness: rd, - constness: rc, + Impl(ast::Impl { generics: rg, of_trait: rot, self_ty: rst, items: ri, }), ) => { - matches!(lu, Safety::Default) == matches!(ru, Safety::Default) - && matches!(lp, ImplPolarity::Positive) == matches!(rp, ImplPolarity::Positive) - && eq_defaultness(*ld, *rd) - && matches!(lc, ast::Const::No) == matches!(rc, ast::Const::No) - && eq_generics(lg, rg) - && both(lot.as_ref(), rot.as_ref(), |l, r| eq_path(&l.path, &r.path)) + eq_generics(lg, rg) + && both(lot.as_deref(), rot.as_deref(), |l, r| { + matches!(l.safety, Safety::Default) == matches!(r.safety, Safety::Default) + && matches!(l.polarity, ImplPolarity::Positive) == matches!(r.polarity, ImplPolarity::Positive) + && eq_defaultness(l.defaultness, r.defaultness) + && matches!(l.constness, ast::Const::No) == matches!(r.constness, ast::Const::No) + && eq_path(&l.trait_ref.path, &r.trait_ref.path) + }) && eq_ty(lst, rst) && over(li, ri, |l, r| eq_item(l, r, eq_assoc_item_kind)) }, diff --git a/src/tools/clippy/clippy_utils/src/check_proc_macro.rs b/src/tools/clippy/clippy_utils/src/check_proc_macro.rs index dc31ed08fb7..e0c1b9d445a 100644 --- a/src/tools/clippy/clippy_utils/src/check_proc_macro.rs +++ b/src/tools/clippy/clippy_utils/src/check_proc_macro.rs @@ -19,8 +19,8 @@ use rustc_ast::token::CommentKind; use rustc_hir::intravisit::FnKind; use rustc_hir::{ Block, BlockCheckMode, Body, Closure, Destination, Expr, ExprKind, FieldDef, FnHeader, FnRetTy, HirId, Impl, - ImplItem, ImplItemKind, IsAuto, Item, ItemKind, Lit, LoopSource, MatchSource, MutTy, Node, Path, QPath, Safety, - TraitItem, TraitItemKind, Ty, TyKind, UnOp, UnsafeSource, Variant, VariantData, YieldSource, + ImplItem, ImplItemKind, TraitImplHeader, IsAuto, Item, ItemKind, Lit, LoopSource, MatchSource, MutTy, Node, Path, + QPath, Safety, TraitItem, TraitItemKind, Ty, TyKind, UnOp, UnsafeSource, Variant, VariantData, YieldSource, }; use rustc_lint::{EarlyContext, LateContext, LintContext}; use rustc_middle::ty::TyCtxt; @@ -254,7 +254,7 @@ fn item_search_pat(item: &Item<'_>) -> (Pat, Pat) { ItemKind::Union(..) => (Pat::Str("union"), Pat::Str("}")), ItemKind::Trait(_, _, Safety::Unsafe, ..) | ItemKind::Impl(Impl { - safety: Safety::Unsafe, .. + of_trait: Some(TraitImplHeader { safety: Safety::Unsafe, .. }), .. }) => (Pat::Str("unsafe"), Pat::Str("}")), ItemKind::Trait(_, IsAuto::Yes, ..) => (Pat::Str("auto"), Pat::Str("}")), ItemKind::Trait(..) => (Pat::Str("trait"), Pat::Str("}")), diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index fc716d86fc6..fcc120656e3 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -528,8 +528,9 @@ pub fn path_def_id<'tcx>(cx: &LateContext<'_>, maybe_path: &impl MaybePath<'tcx> pub fn trait_ref_of_method<'tcx>(cx: &LateContext<'tcx>, owner: OwnerId) -> Option<&'tcx TraitRef<'tcx>> { if let Node::Item(item) = cx.tcx.hir_node(cx.tcx.hir_owner_parent(owner)) && let ItemKind::Impl(impl_) = &item.kind + && let Some(of_trait) = impl_.of_trait { - return impl_.of_trait.as_ref(); + return Some(&of_trait.trait_ref); } None } diff --git a/src/tools/clippy/clippy_utils/src/visitors.rs b/src/tools/clippy/clippy_utils/src/visitors.rs index ba5cbc73836..c9f5401ebe7 100644 --- a/src/tools/clippy/clippy_utils/src/visitors.rs +++ b/src/tools/clippy/clippy_utils/src/visitors.rs @@ -460,7 +460,8 @@ pub fn is_expr_unsafe<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> bool { } fn visit_nested_item(&mut self, id: ItemId) -> Self::Result { if let ItemKind::Impl(i) = &self.cx.tcx.hir_item(id).kind - && i.safety.is_unsafe() + && let Some(of_trait) = i.of_trait + && of_trait.safety.is_unsafe() { ControlFlow::Break(()) } else { diff --git a/src/tools/clippy/tests/ui/bool_assert_comparison.fixed b/src/tools/clippy/tests/ui/bool_assert_comparison.fixed index 721d8b2c2dc..ec76abbef05 100644 --- a/src/tools/clippy/tests/ui/bool_assert_comparison.fixed +++ b/src/tools/clippy/tests/ui/bool_assert_comparison.fixed @@ -1,7 +1,7 @@ #![allow(unused, clippy::assertions_on_constants, clippy::const_is_empty)] #![warn(clippy::bool_assert_comparison)] -use std::ops::Not; +use std::ops::{Add, Not}; macro_rules! a { () => { @@ -62,6 +62,14 @@ impl Not for ImplNotTraitWithBool { } } +impl Add for ImplNotTraitWithBool { + type Output = Self; + + fn add(self, other: Self) -> Self::Output { + self + } +} + #[derive(Debug)] struct NonCopy; @@ -94,7 +102,7 @@ fn main() { assert_eq!(a!(), "".is_empty()); assert_eq!("".is_empty(), b!()); assert_eq!(a, true); - assert!(b); + assert!(!!b); //~^ bool_assert_comparison assert_ne!("a".len(), 1); @@ -122,7 +130,7 @@ fn main() { debug_assert_eq!(a!(), "".is_empty()); debug_assert_eq!("".is_empty(), b!()); debug_assert_eq!(a, true); - debug_assert!(b); + debug_assert!(!!b); //~^ bool_assert_comparison debug_assert_ne!("a".len(), 1); @@ -167,7 +175,7 @@ fn main() { use debug_assert_eq as renamed; renamed!(a, true); - debug_assert!(b); + debug_assert!(!!b); //~^ bool_assert_comparison let non_copy = NonCopy; @@ -199,4 +207,12 @@ fn main() { //~^ bool_assert_comparison debug_assert!(!"requires negation".is_empty()); //~^ bool_assert_comparison + assert!(!b); + //~^ bool_assert_comparison + assert!(!(!b)); + //~^ bool_assert_comparison + assert!(!!(b + b)); + //~^ bool_assert_comparison + assert!(!(b + b)); + //~^ bool_assert_comparison } diff --git a/src/tools/clippy/tests/ui/bool_assert_comparison.rs b/src/tools/clippy/tests/ui/bool_assert_comparison.rs index 5ab4f475b06..40824a23c82 100644 --- a/src/tools/clippy/tests/ui/bool_assert_comparison.rs +++ b/src/tools/clippy/tests/ui/bool_assert_comparison.rs @@ -1,7 +1,7 @@ #![allow(unused, clippy::assertions_on_constants, clippy::const_is_empty)] #![warn(clippy::bool_assert_comparison)] -use std::ops::Not; +use std::ops::{Add, Not}; macro_rules! a { () => { @@ -62,6 +62,14 @@ impl Not for ImplNotTraitWithBool { } } +impl Add for ImplNotTraitWithBool { + type Output = Self; + + fn add(self, other: Self) -> Self::Output { + self + } +} + #[derive(Debug)] struct NonCopy; @@ -199,4 +207,12 @@ fn main() { //~^ bool_assert_comparison debug_assert_eq!("requires negation".is_empty(), false); //~^ bool_assert_comparison + assert_eq!(!b, true); + //~^ bool_assert_comparison + assert_eq!(!b, false); + //~^ bool_assert_comparison + assert_eq!(b + b, true); + //~^ bool_assert_comparison + assert_eq!(b + b, false); + //~^ bool_assert_comparison } diff --git a/src/tools/clippy/tests/ui/bool_assert_comparison.stderr b/src/tools/clippy/tests/ui/bool_assert_comparison.stderr index a1d0af54361..f823f08f31d 100644 --- a/src/tools/clippy/tests/ui/bool_assert_comparison.stderr +++ b/src/tools/clippy/tests/ui/bool_assert_comparison.stderr @@ -1,5 +1,5 @@ error: used `assert_eq!` with a literal bool - --> tests/ui/bool_assert_comparison.rs:87:5 + --> tests/ui/bool_assert_comparison.rs:95:5 | LL | assert_eq!("a".is_empty(), false); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,7 +13,7 @@ LL + assert!(!"a".is_empty()); | error: used `assert_eq!` with a literal bool - --> tests/ui/bool_assert_comparison.rs:89:5 + --> tests/ui/bool_assert_comparison.rs:97:5 | LL | assert_eq!("".is_empty(), true); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -25,7 +25,7 @@ LL + assert!("".is_empty()); | error: used `assert_eq!` with a literal bool - --> tests/ui/bool_assert_comparison.rs:91:5 + --> tests/ui/bool_assert_comparison.rs:99:5 | LL | assert_eq!(true, "".is_empty()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -37,7 +37,7 @@ LL + assert!("".is_empty()); | error: used `assert_eq!` with a literal bool - --> tests/ui/bool_assert_comparison.rs:97:5 + --> tests/ui/bool_assert_comparison.rs:105:5 | LL | assert_eq!(b, true); | ^^^^^^^^^^^^^^^^^^^ @@ -45,11 +45,11 @@ LL | assert_eq!(b, true); help: replace it with `assert!(..)` | LL - assert_eq!(b, true); -LL + assert!(b); +LL + assert!(!!b); | error: used `assert_ne!` with a literal bool - --> tests/ui/bool_assert_comparison.rs:101:5 + --> tests/ui/bool_assert_comparison.rs:109:5 | LL | assert_ne!("a".is_empty(), false); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -61,7 +61,7 @@ LL + assert!("a".is_empty()); | error: used `assert_ne!` with a literal bool - --> tests/ui/bool_assert_comparison.rs:103:5 + --> tests/ui/bool_assert_comparison.rs:111:5 | LL | assert_ne!("".is_empty(), true); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -73,7 +73,7 @@ LL + assert!(!"".is_empty()); | error: used `assert_ne!` with a literal bool - --> tests/ui/bool_assert_comparison.rs:105:5 + --> tests/ui/bool_assert_comparison.rs:113:5 | LL | assert_ne!(true, "".is_empty()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -85,7 +85,7 @@ LL + assert!(!"".is_empty()); | error: used `assert_ne!` with a literal bool - --> tests/ui/bool_assert_comparison.rs:111:5 + --> tests/ui/bool_assert_comparison.rs:119:5 | LL | assert_ne!(b, true); | ^^^^^^^^^^^^^^^^^^^ @@ -97,7 +97,7 @@ LL + assert!(!b); | error: used `debug_assert_eq!` with a literal bool - --> tests/ui/bool_assert_comparison.rs:115:5 + --> tests/ui/bool_assert_comparison.rs:123:5 | LL | debug_assert_eq!("a".is_empty(), false); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -109,7 +109,7 @@ LL + debug_assert!(!"a".is_empty()); | error: used `debug_assert_eq!` with a literal bool - --> tests/ui/bool_assert_comparison.rs:117:5 + --> tests/ui/bool_assert_comparison.rs:125:5 | LL | debug_assert_eq!("".is_empty(), true); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -121,7 +121,7 @@ LL + debug_assert!("".is_empty()); | error: used `debug_assert_eq!` with a literal bool - --> tests/ui/bool_assert_comparison.rs:119:5 + --> tests/ui/bool_assert_comparison.rs:127:5 | LL | debug_assert_eq!(true, "".is_empty()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -133,7 +133,7 @@ LL + debug_assert!("".is_empty()); | error: used `debug_assert_eq!` with a literal bool - --> tests/ui/bool_assert_comparison.rs:125:5 + --> tests/ui/bool_assert_comparison.rs:133:5 | LL | debug_assert_eq!(b, true); | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -141,11 +141,11 @@ LL | debug_assert_eq!(b, true); help: replace it with `debug_assert!(..)` | LL - debug_assert_eq!(b, true); -LL + debug_assert!(b); +LL + debug_assert!(!!b); | error: used `debug_assert_ne!` with a literal bool - --> tests/ui/bool_assert_comparison.rs:129:5 + --> tests/ui/bool_assert_comparison.rs:137:5 | LL | debug_assert_ne!("a".is_empty(), false); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -157,7 +157,7 @@ LL + debug_assert!("a".is_empty()); | error: used `debug_assert_ne!` with a literal bool - --> tests/ui/bool_assert_comparison.rs:131:5 + --> tests/ui/bool_assert_comparison.rs:139:5 | LL | debug_assert_ne!("".is_empty(), true); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -169,7 +169,7 @@ LL + debug_assert!(!"".is_empty()); | error: used `debug_assert_ne!` with a literal bool - --> tests/ui/bool_assert_comparison.rs:133:5 + --> tests/ui/bool_assert_comparison.rs:141:5 | LL | debug_assert_ne!(true, "".is_empty()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -181,7 +181,7 @@ LL + debug_assert!(!"".is_empty()); | error: used `debug_assert_ne!` with a literal bool - --> tests/ui/bool_assert_comparison.rs:139:5 + --> tests/ui/bool_assert_comparison.rs:147:5 | LL | debug_assert_ne!(b, true); | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -193,7 +193,7 @@ LL + debug_assert!(!b); | error: used `assert_eq!` with a literal bool - --> tests/ui/bool_assert_comparison.rs:145:5 + --> tests/ui/bool_assert_comparison.rs:153:5 | LL | assert_eq!("a".is_empty(), false, "tadam {}", 1); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -205,7 +205,7 @@ LL + assert!(!"a".is_empty(), "tadam {}", 1); | error: used `assert_eq!` with a literal bool - --> tests/ui/bool_assert_comparison.rs:147:5 + --> tests/ui/bool_assert_comparison.rs:155:5 | LL | assert_eq!("a".is_empty(), false, "tadam {}", true); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -217,7 +217,7 @@ LL + assert!(!"a".is_empty(), "tadam {}", true); | error: used `assert_eq!` with a literal bool - --> tests/ui/bool_assert_comparison.rs:149:5 + --> tests/ui/bool_assert_comparison.rs:157:5 | LL | assert_eq!(false, "a".is_empty(), "tadam {}", true); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -229,7 +229,7 @@ LL + assert!(!"a".is_empty(), "tadam {}", true); | error: used `debug_assert_eq!` with a literal bool - --> tests/ui/bool_assert_comparison.rs:155:5 + --> tests/ui/bool_assert_comparison.rs:163:5 | LL | debug_assert_eq!("a".is_empty(), false, "tadam {}", 1); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -241,7 +241,7 @@ LL + debug_assert!(!"a".is_empty(), "tadam {}", 1); | error: used `debug_assert_eq!` with a literal bool - --> tests/ui/bool_assert_comparison.rs:157:5 + --> tests/ui/bool_assert_comparison.rs:165:5 | LL | debug_assert_eq!("a".is_empty(), false, "tadam {}", true); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -253,7 +253,7 @@ LL + debug_assert!(!"a".is_empty(), "tadam {}", true); | error: used `debug_assert_eq!` with a literal bool - --> tests/ui/bool_assert_comparison.rs:159:5 + --> tests/ui/bool_assert_comparison.rs:167:5 | LL | debug_assert_eq!(false, "a".is_empty(), "tadam {}", true); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -265,31 +265,35 @@ LL + debug_assert!(!"a".is_empty(), "tadam {}", true); | error: used `assert_eq!` with a literal bool - --> tests/ui/bool_assert_comparison.rs:163:5 + --> tests/ui/bool_assert_comparison.rs:171:5 | LL | assert_eq!(a!(), true); | ^^^^^^^^^^^^^^^^^^^^^^ | help: replace it with `assert!(..)` | -LL - assert_eq!(a!(), true); -LL + assert!(a!()); +LL | true +... +LL | +LL ~ assert!(a!()); | error: used `assert_eq!` with a literal bool - --> tests/ui/bool_assert_comparison.rs:165:5 + --> tests/ui/bool_assert_comparison.rs:173:5 | LL | assert_eq!(true, b!()); | ^^^^^^^^^^^^^^^^^^^^^^ | help: replace it with `assert!(..)` | -LL - assert_eq!(true, b!()); -LL + assert!(b!()); +LL | true +... +LL | +LL ~ assert!(b!()); | error: used `debug_assert_eq!` with a literal bool - --> tests/ui/bool_assert_comparison.rs:170:5 + --> tests/ui/bool_assert_comparison.rs:178:5 | LL | renamed!(b, true); | ^^^^^^^^^^^^^^^^^ @@ -297,11 +301,11 @@ LL | renamed!(b, true); help: replace it with `debug_assert!(..)` | LL - renamed!(b, true); -LL + debug_assert!(b); +LL + debug_assert!(!!b); | error: used `assert_eq!` with a literal bool - --> tests/ui/bool_assert_comparison.rs:185:5 + --> tests/ui/bool_assert_comparison.rs:193:5 | LL | assert_eq!("".is_empty(), true); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -313,7 +317,7 @@ LL + assert!("".is_empty()); | error: used `assert_ne!` with a literal bool - --> tests/ui/bool_assert_comparison.rs:187:5 + --> tests/ui/bool_assert_comparison.rs:195:5 | LL | assert_ne!("".is_empty(), false); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -325,7 +329,7 @@ LL + assert!("".is_empty()); | error: used `assert_ne!` with a literal bool - --> tests/ui/bool_assert_comparison.rs:189:5 + --> tests/ui/bool_assert_comparison.rs:197:5 | LL | assert_ne!("requires negation".is_empty(), true); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -337,7 +341,7 @@ LL + assert!(!"requires negation".is_empty()); | error: used `assert_eq!` with a literal bool - --> tests/ui/bool_assert_comparison.rs:191:5 + --> tests/ui/bool_assert_comparison.rs:199:5 | LL | assert_eq!("requires negation".is_empty(), false); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -349,7 +353,7 @@ LL + assert!(!"requires negation".is_empty()); | error: used `debug_assert_eq!` with a literal bool - --> tests/ui/bool_assert_comparison.rs:194:5 + --> tests/ui/bool_assert_comparison.rs:202:5 | LL | debug_assert_eq!("".is_empty(), true); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -361,7 +365,7 @@ LL + debug_assert!("".is_empty()); | error: used `debug_assert_ne!` with a literal bool - --> tests/ui/bool_assert_comparison.rs:196:5 + --> tests/ui/bool_assert_comparison.rs:204:5 | LL | debug_assert_ne!("".is_empty(), false); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -373,7 +377,7 @@ LL + debug_assert!("".is_empty()); | error: used `debug_assert_ne!` with a literal bool - --> tests/ui/bool_assert_comparison.rs:198:5 + --> tests/ui/bool_assert_comparison.rs:206:5 | LL | debug_assert_ne!("requires negation".is_empty(), true); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -385,7 +389,7 @@ LL + debug_assert!(!"requires negation".is_empty()); | error: used `debug_assert_eq!` with a literal bool - --> tests/ui/bool_assert_comparison.rs:200:5 + --> tests/ui/bool_assert_comparison.rs:208:5 | LL | debug_assert_eq!("requires negation".is_empty(), false); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -396,5 +400,53 @@ LL - debug_assert_eq!("requires negation".is_empty(), false); LL + debug_assert!(!"requires negation".is_empty()); | -error: aborting due to 33 previous errors +error: used `assert_eq!` with a literal bool + --> tests/ui/bool_assert_comparison.rs:210:5 + | +LL | assert_eq!(!b, true); + | ^^^^^^^^^^^^^^^^^^^^ + | +help: replace it with `assert!(..)` + | +LL - assert_eq!(!b, true); +LL + assert!(!b); + | + +error: used `assert_eq!` with a literal bool + --> tests/ui/bool_assert_comparison.rs:212:5 + | +LL | assert_eq!(!b, false); + | ^^^^^^^^^^^^^^^^^^^^^ + | +help: replace it with `assert!(..)` + | +LL - assert_eq!(!b, false); +LL + assert!(!(!b)); + | + +error: used `assert_eq!` with a literal bool + --> tests/ui/bool_assert_comparison.rs:214:5 + | +LL | assert_eq!(b + b, true); + | ^^^^^^^^^^^^^^^^^^^^^^^ + | +help: replace it with `assert!(..)` + | +LL - assert_eq!(b + b, true); +LL + assert!(!!(b + b)); + | + +error: used `assert_eq!` with a literal bool + --> tests/ui/bool_assert_comparison.rs:216:5 + | +LL | assert_eq!(b + b, false); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: replace it with `assert!(..)` + | +LL - assert_eq!(b + b, false); +LL + assert!(!(b + b)); + | + +error: aborting due to 37 previous errors diff --git a/src/tools/clippy/tests/ui/crashes/ice-96721.stderr b/src/tools/clippy/tests/ui/crashes/ice-96721.stderr index f0778a4b32b..23f7300178e 100644 --- a/src/tools/clippy/tests/ui/crashes/ice-96721.stderr +++ b/src/tools/clippy/tests/ui/crashes/ice-96721.stderr @@ -3,6 +3,8 @@ error: malformed `path` attribute input | LL | #[path = foo!()] | ^^^^^^^^^^^^^^^^ help: must be of the form: `#[path = "file"]` + | + = note: for more information, visit <https://doc.rust-lang.org/reference/items/modules.html#the-path-attribute> error: aborting due to 1 previous error diff --git a/src/tools/miri/src/borrow_tracker/mod.rs b/src/tools/miri/src/borrow_tracker/mod.rs index ec6c2c60ca9..89bd93edae1 100644 --- a/src/tools/miri/src/borrow_tracker/mod.rs +++ b/src/tools/miri/src/borrow_tracker/mod.rs @@ -260,7 +260,7 @@ impl GlobalStateInner { kind: MemoryKind, machine: &MiriMachine<'_>, ) -> AllocState { - let _span = enter_trace_span!(borrow_tracker::new_allocation, ?id, ?alloc_size, ?kind); + let _trace = enter_trace_span!(borrow_tracker::new_allocation, ?id, ?alloc_size, ?kind); match self.borrow_tracker_method { BorrowTrackerMethod::StackedBorrows => AllocState::StackedBorrows(Box::new(RefCell::new(Stacks::new_allocation( @@ -281,7 +281,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { kind: RetagKind, val: &ImmTy<'tcx>, ) -> InterpResult<'tcx, ImmTy<'tcx>> { - let _span = enter_trace_span!(borrow_tracker::retag_ptr_value, ?kind, ?val.layout); + let _trace = enter_trace_span!(borrow_tracker::retag_ptr_value, ?kind, ?val.layout); let this = self.eval_context_mut(); let method = this.machine.borrow_tracker.as_ref().unwrap().borrow().borrow_tracker_method; match method { @@ -295,7 +295,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { kind: RetagKind, place: &PlaceTy<'tcx>, ) -> InterpResult<'tcx> { - let _span = enter_trace_span!(borrow_tracker::retag_place_contents, ?kind, ?place); + let _trace = enter_trace_span!(borrow_tracker::retag_place_contents, ?kind, ?place); let this = self.eval_context_mut(); let method = this.machine.borrow_tracker.as_ref().unwrap().borrow().borrow_tracker_method; match method { @@ -305,7 +305,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } fn protect_place(&mut self, place: &MPlaceTy<'tcx>) -> InterpResult<'tcx, MPlaceTy<'tcx>> { - let _span = enter_trace_span!(borrow_tracker::protect_place, ?place); + let _trace = enter_trace_span!(borrow_tracker::protect_place, ?place); let this = self.eval_context_mut(); let method = this.machine.borrow_tracker.as_ref().unwrap().borrow().borrow_tracker_method; match method { @@ -315,7 +315,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } fn expose_tag(&self, alloc_id: AllocId, tag: BorTag) -> InterpResult<'tcx> { - let _span = + let _trace = enter_trace_span!(borrow_tracker::expose_tag, alloc_id = alloc_id.0, tag = tag.0); let this = self.eval_context_ref(); let method = this.machine.borrow_tracker.as_ref().unwrap().borrow().borrow_tracker_method; @@ -360,7 +360,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { &self, frame: &Frame<'tcx, Provenance, FrameExtra<'tcx>>, ) -> InterpResult<'tcx> { - let _span = enter_trace_span!(borrow_tracker::on_stack_pop); + let _trace = enter_trace_span!(borrow_tracker::on_stack_pop); let this = self.eval_context_ref(); let borrow_tracker = this.machine.borrow_tracker.as_ref().unwrap(); // The body of this loop needs `borrow_tracker` immutably @@ -438,7 +438,7 @@ impl AllocState { range: AllocRange, machine: &MiriMachine<'tcx>, ) -> InterpResult<'tcx> { - let _span = enter_trace_span!(borrow_tracker::before_memory_read, alloc_id = alloc_id.0); + let _trace = enter_trace_span!(borrow_tracker::before_memory_read, alloc_id = alloc_id.0); match self { AllocState::StackedBorrows(sb) => sb.borrow_mut().before_memory_read(alloc_id, prov_extra, range, machine), @@ -460,7 +460,7 @@ impl AllocState { range: AllocRange, machine: &MiriMachine<'tcx>, ) -> InterpResult<'tcx> { - let _span = enter_trace_span!(borrow_tracker::before_memory_write, alloc_id = alloc_id.0); + let _trace = enter_trace_span!(borrow_tracker::before_memory_write, alloc_id = alloc_id.0); match self { AllocState::StackedBorrows(sb) => sb.get_mut().before_memory_write(alloc_id, prov_extra, range, machine), @@ -482,7 +482,7 @@ impl AllocState { size: Size, machine: &MiriMachine<'tcx>, ) -> InterpResult<'tcx> { - let _span = + let _trace = enter_trace_span!(borrow_tracker::before_memory_deallocation, alloc_id = alloc_id.0); match self { AllocState::StackedBorrows(sb) => @@ -493,7 +493,7 @@ impl AllocState { } pub fn remove_unreachable_tags(&self, tags: &FxHashSet<BorTag>) { - let _span = enter_trace_span!(borrow_tracker::remove_unreachable_tags); + let _trace = enter_trace_span!(borrow_tracker::remove_unreachable_tags); match self { AllocState::StackedBorrows(sb) => sb.borrow_mut().remove_unreachable_tags(tags), AllocState::TreeBorrows(tb) => tb.borrow_mut().remove_unreachable_tags(tags), @@ -508,7 +508,7 @@ impl AllocState { tag: BorTag, alloc_id: AllocId, // diagnostics ) -> InterpResult<'tcx> { - let _span = enter_trace_span!( + let _trace = enter_trace_span!( borrow_tracker::release_protector, alloc_id = alloc_id.0, tag = tag.0 @@ -523,7 +523,7 @@ impl AllocState { impl VisitProvenance for AllocState { fn visit_provenance(&self, visit: &mut VisitWith<'_>) { - let _span = enter_trace_span!(borrow_tracker::visit_provenance); + let _trace = enter_trace_span!(borrow_tracker::visit_provenance); match self { AllocState::StackedBorrows(sb) => sb.visit_provenance(visit), AllocState::TreeBorrows(tb) => tb.visit_provenance(visit), diff --git a/src/tools/rustfmt/src/items.rs b/src/tools/rustfmt/src/items.rs index 57d4142ebe4..10df6f96702 100644 --- a/src/tools/rustfmt/src/items.rs +++ b/src/tools/rustfmt/src/items.rs @@ -958,20 +958,19 @@ fn format_impl_ref_and_type( offset: Indent, ) -> Option<String> { let ast::Impl { - safety, - polarity, - defaultness, - constness, - ref generics, - of_trait: ref trait_ref, - ref self_ty, - .. - } = *iimpl; + generics, + of_trait, + self_ty, + items: _, + } = iimpl; let mut result = String::with_capacity(128); result.push_str(&format_visibility(context, &item.vis)); - result.push_str(format_defaultness(defaultness)); - result.push_str(format_safety(safety)); + + if let Some(of_trait) = of_trait.as_deref() { + result.push_str(format_defaultness(of_trait.defaultness)); + result.push_str(format_safety(of_trait.safety)); + } let shape = if context.config.style_edition() >= StyleEdition::Edition2024 { Shape::indented(offset + last_line_width(&result), context.config) @@ -984,28 +983,24 @@ fn format_impl_ref_and_type( }; let generics_str = rewrite_generics(context, "impl", generics, shape).ok()?; result.push_str(&generics_str); - result.push_str(format_constness_right(constness)); - let polarity_str = match polarity { - ast::ImplPolarity::Negative(_) => "!", - ast::ImplPolarity::Positive => "", - }; - - let polarity_overhead; let trait_ref_overhead; - if let Some(ref trait_ref) = *trait_ref { + if let Some(of_trait) = of_trait.as_deref() { + result.push_str(format_constness_right(of_trait.constness)); + let polarity_str = match of_trait.polarity { + ast::ImplPolarity::Negative(_) => "!", + ast::ImplPolarity::Positive => "", + }; let result_len = last_line_width(&result); result.push_str(&rewrite_trait_ref( context, - trait_ref, + &of_trait.trait_ref, offset, polarity_str, result_len, )?); - polarity_overhead = 0; // already written trait_ref_overhead = " for".len(); } else { - polarity_overhead = polarity_str.len(); trait_ref_overhead = 0; } @@ -1020,17 +1015,15 @@ fn format_impl_ref_and_type( } else { 0 }; - let used_space = - last_line_width(&result) + polarity_overhead + trait_ref_overhead + curly_brace_overhead; + let used_space = last_line_width(&result) + trait_ref_overhead + curly_brace_overhead; // 1 = space before the type. let budget = context.budget(used_space + 1); if let Some(self_ty_str) = self_ty.rewrite(context, Shape::legacy(budget, offset)) { if !self_ty_str.contains('\n') { - if trait_ref.is_some() { + if of_trait.is_some() { result.push_str(" for "); } else { result.push(' '); - result.push_str(polarity_str); } result.push_str(&self_ty_str); return Some(result); @@ -1042,12 +1035,10 @@ fn format_impl_ref_and_type( // Add indentation of one additional tab. let new_line_offset = offset.block_indent(context.config); result.push_str(&new_line_offset.to_string(context.config)); - if trait_ref.is_some() { + if of_trait.is_some() { result.push_str("for "); - } else { - result.push_str(polarity_str); } - let budget = context.budget(last_line_width(&result) + polarity_overhead); + let budget = context.budget(last_line_width(&result)); let type_offset = match context.config.indent_style() { IndentStyle::Visual => new_line_offset + trait_ref_overhead, IndentStyle::Block => new_line_offset, diff --git a/src/tools/rustfmt/tests/source/negative-impl.rs b/src/tools/rustfmt/tests/source/negative-impl.rs index da242d4f3dc..e8f9508e656 100644 --- a/src/tools/rustfmt/tests/source/negative-impl.rs +++ b/src/tools/rustfmt/tests/source/negative-impl.rs @@ -1,7 +1,3 @@ impl ! Display for JoinHandle { } -impl ! Box < JoinHandle > { } - impl ! std :: fmt :: Display for JoinHandle < T : std :: future :: Future + std :: marker :: Send + std :: marker :: Sync > { } - -impl ! JoinHandle < T : std :: future :: Future < Output > + std :: marker :: Send + std :: marker :: Sync + 'static > + 'static { } diff --git a/src/tools/rustfmt/tests/target/negative-impl.rs b/src/tools/rustfmt/tests/target/negative-impl.rs index 16ce7e26a99..bb53048dbc6 100644 --- a/src/tools/rustfmt/tests/target/negative-impl.rs +++ b/src/tools/rustfmt/tests/target/negative-impl.rs @@ -1,14 +1,6 @@ impl !Display for JoinHandle {} -impl !Box<JoinHandle> {} - impl !std::fmt::Display for JoinHandle<T: std::future::Future + std::marker::Send + std::marker::Sync> { } - -impl - !JoinHandle<T: std::future::Future<Output> + std::marker::Send + std::marker::Sync + 'static> - + 'static -{ -} diff --git a/tests/run-make/link-under-xcode/foo.rs b/tests/run-make/link-under-xcode/foo.rs new file mode 100644 index 00000000000..f328e4d9d04 --- /dev/null +++ b/tests/run-make/link-under-xcode/foo.rs @@ -0,0 +1 @@ +fn main() {} diff --git a/tests/run-make/link-under-xcode/rmake.rs b/tests/run-make/link-under-xcode/rmake.rs new file mode 100644 index 00000000000..c9394feb000 --- /dev/null +++ b/tests/run-make/link-under-xcode/rmake.rs @@ -0,0 +1,32 @@ +//! Test that linking works under an environment similar to what Xcode sets up. +//! +//! Regression test for https://github.com/rust-lang/rust/issues/80817. + +//@ only-apple + +use run_make_support::{cmd, rustc, target}; + +fn main() { + // Fetch toolchain `/usr/bin` directory. Usually: + // /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin + let clang_bin = cmd("xcrun").arg("--find").arg("clang").run().stdout_utf8(); + let toolchain_bin = clang_bin.trim().strip_suffix("/clang").unwrap(); + + // Put toolchain directory at the front of PATH. + let path = format!("{}:{}", toolchain_bin, std::env::var("PATH").unwrap()); + + // Check that compiling and linking still works. + // + // Removing `SDKROOT` is necessary for the test to excercise what we want, since bootstrap runs + // under `/usr/bin/python3`, which will set SDKROOT for us. + rustc().target(target()).env_remove("SDKROOT").env("PATH", &path).input("foo.rs").run(); + + // Also check linking directly with the system linker. + rustc() + .target(target()) + .env_remove("SDKROOT") + .env("PATH", &path) + .input("foo.rs") + .arg("-Clinker-flavor=ld") + .run(); +} diff --git a/tests/rustdoc-ui/intra-doc/github-flavored-admonitions.rs b/tests/rustdoc-ui/intra-doc/github-flavored-admonitions.rs new file mode 100644 index 00000000000..d5fa72eb993 --- /dev/null +++ b/tests/rustdoc-ui/intra-doc/github-flavored-admonitions.rs @@ -0,0 +1,6 @@ +// regression test for https://github.com/rust-lang/rust/issues/141866 +//@ check-pass +#![deny(rustdoc::broken_intra_doc_links)] + +//! > [!NOTE] +//! > This should not cause any warnings diff --git a/tests/rustdoc/enum/enum-variant-value.rs b/tests/rustdoc/enum/enum-variant-value.rs index 1670de8a24f..9cc85dfe10d 100644 --- a/tests/rustdoc/enum/enum-variant-value.rs +++ b/tests/rustdoc/enum/enum-variant-value.rs @@ -189,3 +189,25 @@ pub use bar::P; //@ has - '//*[@id="variant.A"]/h3' 'A(u32)' //@ matches - '//*[@id="variant.B"]/h3' '^B$' pub use bar::Q; + +// Ensure signed implicit discriminants are rendered correctly after a negative explicit value. +//@ has 'foo/enum.R.html' +//@ has - '//*[@class="rust item-decl"]/code' 'A = -2,' +//@ has - '//*[@class="rust item-decl"]/code' 'B = -1,' +//@ matches - '//*[@id="variant.A"]/h3' '^A = -2$' +//@ matches - '//*[@id="variant.B"]/h3' '^B = -1$' +pub enum R { + A = -2, + B, +} + +// Also check that incrementing -1 yields 0 for the next implicit variant. +//@ has 'foo/enum.S.html' +//@ has - '//*[@class="rust item-decl"]/code' 'A = -1,' +//@ has - '//*[@class="rust item-decl"]/code' 'B = 0,' +//@ matches - '//*[@id="variant.A"]/h3' '^A = -1$' +//@ matches - '//*[@id="variant.B"]/h3' '^B = 0$' +pub enum S { + A = -1, + B, +} diff --git a/tests/ui/attributes/crate-name-macro-call.stderr b/tests/ui/attributes/crate-name-macro-call.stderr index ab562b41a31..56827aa11a4 100644 --- a/tests/ui/attributes/crate-name-macro-call.stderr +++ b/tests/ui/attributes/crate-name-macro-call.stderr @@ -3,6 +3,8 @@ error: malformed `crate_name` attribute input | LL | #![crate_name = concat!("my", "crate")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#![crate_name = "name"]` + | + = note: for more information, visit <https://doc.rust-lang.org/reference/crates-and-source-files.html#the-crate_name-attribute> error: aborting due to 1 previous error diff --git a/tests/ui/attributes/crate-type-delimited.stderr b/tests/ui/attributes/crate-type-delimited.stderr index 0bbbe07b198..7f080f74838 100644 --- a/tests/ui/attributes/crate-type-delimited.stderr +++ b/tests/ui/attributes/crate-type-delimited.stderr @@ -2,7 +2,24 @@ error: malformed `crate_type` attribute input --> $DIR/crate-type-delimited.rs:2:1 | LL | #![crate_type(lib)] - | ^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#![crate_type = "bin|lib|..."]` + | ^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, visit <https://doc.rust-lang.org/reference/linkage.html> +help: the following are the possible correct uses + | +LL - #![crate_type(lib)] +LL + #![crate_type = "bin"] + | +LL - #![crate_type(lib)] +LL + #![crate_type = "cdylib"] + | +LL - #![crate_type(lib)] +LL + #![crate_type = "dylib"] + | +LL - #![crate_type(lib)] +LL + #![crate_type = "lib"] + | + = and 4 other candidates error: aborting due to 1 previous error diff --git a/tests/ui/attributes/crate-type-empty.stderr b/tests/ui/attributes/crate-type-empty.stderr index b9279d961ee..f50bb33d6bb 100644 --- a/tests/ui/attributes/crate-type-empty.stderr +++ b/tests/ui/attributes/crate-type-empty.stderr @@ -2,7 +2,20 @@ error: malformed `crate_type` attribute input --> $DIR/crate-type-empty.rs:2:1 | LL | #![crate_type] - | ^^^^^^^^^^^^^^ help: must be of the form: `#![crate_type = "bin|lib|..."]` + | ^^^^^^^^^^^^^^ + | + = note: for more information, visit <https://doc.rust-lang.org/reference/linkage.html> +help: the following are the possible correct uses + | +LL | #![crate_type = "bin"] + | +++++++ +LL | #![crate_type = "cdylib"] + | ++++++++++ +LL | #![crate_type = "dylib"] + | +++++++++ +LL | #![crate_type = "lib"] + | +++++++ + = and 4 other candidates error: aborting due to 1 previous error diff --git a/tests/ui/attributes/crate-type-macro-call.stderr b/tests/ui/attributes/crate-type-macro-call.stderr index 6ccc3edf885..97938f7af24 100644 --- a/tests/ui/attributes/crate-type-macro-call.stderr +++ b/tests/ui/attributes/crate-type-macro-call.stderr @@ -2,7 +2,24 @@ error: malformed `crate_type` attribute input --> $DIR/crate-type-macro-call.rs:1:1 | LL | #![crate_type = foo!()] - | ^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#![crate_type = "bin|lib|..."]` + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, visit <https://doc.rust-lang.org/reference/linkage.html> +help: the following are the possible correct uses + | +LL - #![crate_type = foo!()] +LL + #![crate_type = "bin"] + | +LL - #![crate_type = foo!()] +LL + #![crate_type = "cdylib"] + | +LL - #![crate_type = foo!()] +LL + #![crate_type = "dylib"] + | +LL - #![crate_type = foo!()] +LL + #![crate_type = "lib"] + | + = and 4 other candidates error: aborting due to 1 previous error diff --git a/tests/ui/attributes/invalid-macro-use.rs b/tests/ui/attributes/invalid-macro-use.rs index cfb13fd183c..52e4608303f 100644 --- a/tests/ui/attributes/invalid-macro-use.rs +++ b/tests/ui/attributes/invalid-macro-use.rs @@ -8,21 +8,25 @@ extern crate std as s1; #[macro_use(5)] //~^ ERROR malformed `macro_use` attribute input //~| NOTE expected a valid identifier here +//~| NOTE for more information, visit extern crate std as s2; #[macro_use(a = "b")] //~^ ERROR malformed `macro_use` attribute input //~| NOTE didn't expect any arguments here +//~| NOTE for more information, visit extern crate std as s3; #[macro_use(a(b))] //~^ ERROR malformed `macro_use` attribute input //~| NOTE didn't expect any arguments here +//~| NOTE for more information, visit extern crate std as s4; #[macro_use(a::b)] //~^ ERROR malformed `macro_use` attribute input //~| NOTE expected a valid identifier here +//~| NOTE for more information, visit extern crate std as s5; #[macro_use(a)] diff --git a/tests/ui/attributes/invalid-macro-use.stderr b/tests/ui/attributes/invalid-macro-use.stderr index 4f5db5c558a..ff3ed6196d3 100644 --- a/tests/ui/attributes/invalid-macro-use.stderr +++ b/tests/ui/attributes/invalid-macro-use.stderr @@ -1,11 +1,11 @@ error[E0469]: imported macro not found - --> $DIR/invalid-macro-use.rs:47:13 + --> $DIR/invalid-macro-use.rs:51:13 | LL | #[macro_use(a)] | ^ error[E0469]: imported macro not found - --> $DIR/invalid-macro-use.rs:49:13 + --> $DIR/invalid-macro-use.rs:53:13 | LL | #[macro_use(b)] | ^ @@ -24,6 +24,7 @@ LL | #[macro_use(5)] | | | expected a valid identifier here | + = note: for more information, visit <https://doc.rust-lang.org/reference/macros-by-example.html#the-macro_use-attribute> help: try changing it to one of the following valid forms of the attribute | LL - #[macro_use(5)] @@ -34,13 +35,14 @@ LL + #[macro_use] | error[E0565]: malformed `macro_use` attribute input - --> $DIR/invalid-macro-use.rs:13:1 + --> $DIR/invalid-macro-use.rs:14:1 | LL | #[macro_use(a = "b")] | ^^^^^^^^^^^^^^-----^^ | | | didn't expect any arguments here | + = note: for more information, visit <https://doc.rust-lang.org/reference/macros-by-example.html#the-macro_use-attribute> help: try changing it to one of the following valid forms of the attribute | LL - #[macro_use(a = "b")] @@ -51,13 +53,14 @@ LL + #[macro_use] | error[E0565]: malformed `macro_use` attribute input - --> $DIR/invalid-macro-use.rs:18:1 + --> $DIR/invalid-macro-use.rs:20:1 | LL | #[macro_use(a(b))] | ^^^^^^^^^^^^^---^^ | | | didn't expect any arguments here | + = note: for more information, visit <https://doc.rust-lang.org/reference/macros-by-example.html#the-macro_use-attribute> help: try changing it to one of the following valid forms of the attribute | LL - #[macro_use(a(b))] @@ -68,13 +71,14 @@ LL + #[macro_use] | error[E0539]: malformed `macro_use` attribute input - --> $DIR/invalid-macro-use.rs:23:1 + --> $DIR/invalid-macro-use.rs:26:1 | LL | #[macro_use(a::b)] | ^^^^^^^^^^^^----^^ | | | expected a valid identifier here | + = note: for more information, visit <https://doc.rust-lang.org/reference/macros-by-example.html#the-macro_use-attribute> help: try changing it to one of the following valid forms of the attribute | LL - #[macro_use(a::b)] @@ -85,13 +89,13 @@ LL + #[macro_use] | error: unused attribute - --> $DIR/invalid-macro-use.rs:28:1 + --> $DIR/invalid-macro-use.rs:32:1 | LL | #[macro_use(a)] | ^^^^^^^^^^^^^^^ help: remove this attribute | note: attribute also specified here - --> $DIR/invalid-macro-use.rs:30:1 + --> $DIR/invalid-macro-use.rs:34:1 | LL | #[macro_use] | ^^^^^^^^^^^^ @@ -102,25 +106,25 @@ LL | #![deny(unused_attributes)] | ^^^^^^^^^^^^^^^^^ error: unused attribute - --> $DIR/invalid-macro-use.rs:36:1 + --> $DIR/invalid-macro-use.rs:40:1 | LL | #[macro_use(a)] | ^^^^^^^^^^^^^^^ help: remove this attribute | note: attribute also specified here - --> $DIR/invalid-macro-use.rs:34:1 + --> $DIR/invalid-macro-use.rs:38:1 | LL | #[macro_use] | ^^^^^^^^^^^^ error: unused attribute - --> $DIR/invalid-macro-use.rs:42:1 + --> $DIR/invalid-macro-use.rs:46:1 | LL | #[macro_use] | ^^^^^^^^^^^^ help: remove this attribute | note: attribute also specified here - --> $DIR/invalid-macro-use.rs:40:1 + --> $DIR/invalid-macro-use.rs:44:1 | LL | #[macro_use] | ^^^^^^^^^^^^ diff --git a/tests/ui/attributes/invalid-reprs.stderr b/tests/ui/attributes/invalid-reprs.stderr index 415b969b244..72aaff92bd0 100644 --- a/tests/ui/attributes/invalid-reprs.stderr +++ b/tests/ui/attributes/invalid-reprs.stderr @@ -26,6 +26,7 @@ LL | let y = #[repr(uwu(4))] | ^^^^^^ | = help: valid reprs are `Rust` (default), `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize` + = note: for more information, visit <https://doc.rust-lang.org/reference/type-layout.html?highlight=repr#representations> error: aborting due to 3 previous errors diff --git a/tests/ui/attributes/lint_on_root.rs b/tests/ui/attributes/lint_on_root.rs index 93d47bf0d71..9029da7dc97 100644 --- a/tests/ui/attributes/lint_on_root.rs +++ b/tests/ui/attributes/lint_on_root.rs @@ -1,7 +1,7 @@ // NOTE: this used to panic in debug builds (by a sanity assertion) // and not emit any lint on release builds. See https://github.com/rust-lang/rust/issues/142891. #![inline = ""] -//~^ ERROR valid forms for the attribute are `#[inline(always|never)]` and `#[inline]` +//~^ ERROR: valid forms for the attribute are `#[inline(always)]`, `#[inline(never)]`, and `#[inline]` [ill_formed_attribute_input] //~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! fn main() {} diff --git a/tests/ui/attributes/lint_on_root.stderr b/tests/ui/attributes/lint_on_root.stderr index aa0645b6194..91b72730530 100644 --- a/tests/ui/attributes/lint_on_root.stderr +++ b/tests/ui/attributes/lint_on_root.stderr @@ -1,4 +1,4 @@ -error: valid forms for the attribute are `#[inline(always|never)]` and `#[inline]` +error: valid forms for the attribute are `#[inline(always)]`, `#[inline(never)]`, and `#[inline]` --> $DIR/lint_on_root.rs:3:1 | LL | #![inline = ""] @@ -11,7 +11,7 @@ LL | #![inline = ""] error: aborting due to 1 previous error Future incompatibility report: Future breakage diagnostic: -error: valid forms for the attribute are `#[inline(always|never)]` and `#[inline]` +error: valid forms for the attribute are `#[inline(always)]`, `#[inline(never)]`, and `#[inline]` --> $DIR/lint_on_root.rs:3:1 | LL | #![inline = ""] diff --git a/tests/ui/attributes/malformed-attrs.rs b/tests/ui/attributes/malformed-attrs.rs index 0d5bf69d548..3261b29fe7e 100644 --- a/tests/ui/attributes/malformed-attrs.rs +++ b/tests/ui/attributes/malformed-attrs.rs @@ -78,7 +78,7 @@ #[export_stable = 1] //~^ ERROR malformed #[link] -//~^ ERROR attribute must be of the form +//~^ ERROR valid forms for the attribute are //~| WARN this was previously accepted by the compiler #[link_name] //~^ ERROR malformed diff --git a/tests/ui/attributes/malformed-attrs.stderr b/tests/ui/attributes/malformed-attrs.stderr index dd9dd3a6ce7..705050e9a7d 100644 --- a/tests/ui/attributes/malformed-attrs.stderr +++ b/tests/ui/attributes/malformed-attrs.stderr @@ -6,6 +6,8 @@ LL | #[cfg] | | | expected this to be a list | 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: malformed `cfg_attr` attribute input --> $DIR/malformed-attrs.rs:101:1 @@ -29,13 +31,23 @@ error: malformed `windows_subsystem` attribute input --> $DIR/malformed-attrs.rs:26:1 | LL | #![windows_subsystem] - | ^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#![windows_subsystem = "windows|console"]` + | ^^^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, visit <https://doc.rust-lang.org/reference/runtime.html#the-windows_subsystem-attribute> +help: the following are the possible correct uses + | +LL | #![windows_subsystem = "console"] + | +++++++++++ +LL | #![windows_subsystem = "windows"] + | +++++++++++ error: malformed `crate_name` attribute input --> $DIR/malformed-attrs.rs:71:1 | LL | #[crate_name] | ^^^^^^^^^^^^^ help: must be of the form: `#[crate_name = "name"]` + | + = note: for more information, visit <https://doc.rust-lang.org/reference/crates-and-source-files.html#the-crate_name-attribute> error: malformed `no_sanitize` attribute input --> $DIR/malformed-attrs.rs:89:1 @@ -48,6 +60,8 @@ error: malformed `instruction_set` attribute input | LL | #[instruction_set] | ^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[instruction_set(set)]` + | + = 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:105:1 @@ -80,43 +94,108 @@ error: malformed `linkage` attribute input --> $DIR/malformed-attrs.rs:170:5 | LL | #[linkage] - | ^^^^^^^^^^ help: must be of the form: `#[linkage = "external|internal|..."]` + | ^^^^^^^^^^ + | + = note: for more information, visit <https://doc.rust-lang.org/reference/linkage.html> +help: the following are the possible correct uses + | +LL | #[linkage = "available_externally"] + | ++++++++++++++++++++++++ +LL | #[linkage = "common"] + | ++++++++++ +LL | #[linkage = "extern_weak"] + | +++++++++++++++ +LL | #[linkage = "external"] + | ++++++++++++ + = and 5 other candidates error: malformed `allow` attribute input --> $DIR/malformed-attrs.rs:175:1 | LL | #[allow] - | ^^^^^^^^ help: must be of the form: `#[allow(lint1, lint2, ..., /*opt*/ reason = "...")]` + | ^^^^^^^^ + | + = note: for more information, visit <https://doc.rust-lang.org/reference/attributes/diagnostics.html#lint-check-attributes> +help: the following are the possible correct uses + | +LL | #[allow(lint1)] + | +++++++ +LL | #[allow(lint1, lint2, ...)] + | +++++++++++++++++++ +LL | #[allow(lint1, lint2, lint3, reason = "...")] + | +++++++++++++++++++++++++++++++++++++ error: malformed `expect` attribute input --> $DIR/malformed-attrs.rs:177:1 | LL | #[expect] - | ^^^^^^^^^ help: must be of the form: `#[expect(lint1, lint2, ..., /*opt*/ reason = "...")]` + | ^^^^^^^^^ + | + = note: for more information, visit <https://doc.rust-lang.org/reference/attributes/diagnostics.html#lint-check-attributes> +help: the following are the possible correct uses + | +LL | #[expect(lint1)] + | +++++++ +LL | #[expect(lint1, lint2, ...)] + | +++++++++++++++++++ +LL | #[expect(lint1, lint2, lint3, reason = "...")] + | +++++++++++++++++++++++++++++++++++++ error: malformed `warn` attribute input --> $DIR/malformed-attrs.rs:179:1 | LL | #[warn] - | ^^^^^^^ help: must be of the form: `#[warn(lint1, lint2, ..., /*opt*/ reason = "...")]` + | ^^^^^^^ + | + = note: for more information, visit <https://doc.rust-lang.org/reference/attributes/diagnostics.html#lint-check-attributes> +help: the following are the possible correct uses + | +LL | #[warn(lint1)] + | +++++++ +LL | #[warn(lint1, lint2, ...)] + | +++++++++++++++++++ +LL | #[warn(lint1, lint2, lint3, reason = "...")] + | +++++++++++++++++++++++++++++++++++++ error: malformed `deny` attribute input --> $DIR/malformed-attrs.rs:181:1 | LL | #[deny] - | ^^^^^^^ help: must be of the form: `#[deny(lint1, lint2, ..., /*opt*/ reason = "...")]` + | ^^^^^^^ + | + = note: for more information, visit <https://doc.rust-lang.org/reference/attributes/diagnostics.html#lint-check-attributes> +help: the following are the possible correct uses + | +LL | #[deny(lint1)] + | +++++++ +LL | #[deny(lint1, lint2, ...)] + | +++++++++++++++++++ +LL | #[deny(lint1, lint2, lint3, reason = "...")] + | +++++++++++++++++++++++++++++++++++++ error: malformed `forbid` attribute input --> $DIR/malformed-attrs.rs:183:1 | LL | #[forbid] - | ^^^^^^^^^ help: must be of the form: `#[forbid(lint1, lint2, ..., /*opt*/ reason = "...")]` + | ^^^^^^^^^ + | + = note: for more information, visit <https://doc.rust-lang.org/reference/attributes/diagnostics.html#lint-check-attributes> +help: the following are the possible correct uses + | +LL | #[forbid(lint1)] + | +++++++ +LL | #[forbid(lint1, lint2, ...)] + | +++++++++++++++++++ +LL | #[forbid(lint1, lint2, lint3, reason = "...")] + | +++++++++++++++++++++++++++++++++++++ error: malformed `debugger_visualizer` attribute input --> $DIR/malformed-attrs.rs:185:1 | LL | #[debugger_visualizer] | ^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[debugger_visualizer(natvis_file = "...", gdb_script_file = "...")]` + | + = note: for more information, visit <https://doc.rust-lang.org/reference/attributes/debugger.html#the-debugger_visualizer-attribute> error: malformed `thread_local` attribute input --> $DIR/malformed-attrs.rs:200:1 @@ -129,6 +208,8 @@ error: malformed `no_link` attribute input | LL | #[no_link()] | ^^^^^^^^^^^^ help: must be of the form: `#[no_link]` + | + = note: for more information, visit <https://doc.rust-lang.org/reference/items/extern-crates.html#the-no_link-attribute> error: malformed `macro_export` attribute input --> $DIR/malformed-attrs.rs:211:1 @@ -136,6 +217,7 @@ error: malformed `macro_export` attribute input LL | #[macro_export = 18] | ^^^^^^^^^^^^^^^^^^^^ | + = note: for more information, visit <https://doc.rust-lang.org/reference/macros-by-example.html#path-based-scope> help: the following are the possible correct uses | LL - #[macro_export = 18] @@ -145,12 +227,6 @@ LL - #[macro_export = 18] LL + #[macro_export] | -error: malformed `allow_internal_unsafe` attribute input - --> $DIR/malformed-attrs.rs:213:1 - | -LL | #[allow_internal_unsafe = 1] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[allow_internal_unsafe]` - error: the `#[proc_macro]` attribute is only usable with crates of the `proc-macro` crate type --> $DIR/malformed-attrs.rs:96:1 | @@ -178,7 +254,7 @@ LL | #[allow_internal_unsafe = 1] = help: add `#![feature(allow_internal_unsafe)]` 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: valid forms for the attribute are `#[doc(hidden|inline|...)]` and `#[doc = "string"]` +error: valid forms for the attribute are `#[doc(hidden)]`, `#[doc(inline)]`, and `#[doc = "string"]` --> $DIR/malformed-attrs.rs:40:1 | LL | #[doc] @@ -186,9 +262,10 @@ LL | #[doc] | = 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> + = note: for more information, visit <https://doc.rust-lang.org/rustdoc/write-documentation/the-doc-attribute.html> = note: `#[deny(ill_formed_attribute_input)]` on by default -error: valid forms for the attribute are `#[doc(hidden|inline|...)]` and `#[doc = "string"]` +error: valid forms for the attribute are `#[doc(hidden)]`, `#[doc(inline)]`, and `#[doc = "string"]` --> $DIR/malformed-attrs.rs:73:1 | LL | #[doc] @@ -196,8 +273,9 @@ LL | #[doc] | = 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> + = note: for more information, visit <https://doc.rust-lang.org/rustdoc/write-documentation/the-doc-attribute.html> -error: attribute must be of the form `#[link(name = "...", /*opt*/ kind = "dylib|static|...", /*opt*/ wasm_import_module = "...", /*opt*/ import_name_type = "decorated|noprefix|undecorated")]` +error: valid forms for the attribute are `#[link(name = "...")]`, `#[link(name = "...", kind = "dylib|static|...")]`, `#[link(name = "...", wasm_import_module = "...")]`, `#[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]`, and `#[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]` --> $DIR/malformed-attrs.rs:80:1 | LL | #[link] @@ -205,6 +283,7 @@ LL | #[link] | = 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> + = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute> error: invalid argument --> $DIR/malformed-attrs.rs:185:1 @@ -257,26 +336,49 @@ LL - #[deprecated = 5] LL + #[deprecated = "reason"] | LL - #[deprecated = 5] -LL + #[deprecated(/*opt*/ since = "version", /*opt*/ note = "reason")] +LL + #[deprecated(note = "reason")] | LL - #[deprecated = 5] -LL + #[deprecated] +LL + #[deprecated(since = "version")] | +LL - #[deprecated = 5] +LL + #[deprecated(since = "version", note = "reason")] + | + = and 1 other candidate error[E0539]: malformed `rustc_macro_transparency` attribute input --> $DIR/malformed-attrs.rs:43:1 | LL | #[rustc_macro_transparency] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[rustc_macro_transparency = "transparent|semitransparent|opaque"]` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try changing it to one of the following valid forms of the attribute + | +LL | #[rustc_macro_transparency = "opaque"] + | ++++++++++ +LL | #[rustc_macro_transparency = "semitransparent"] + | +++++++++++++++++++ +LL | #[rustc_macro_transparency = "transparent"] + | +++++++++++++++ error[E0539]: malformed `repr` attribute input --> $DIR/malformed-attrs.rs:45:1 | LL | #[repr] - | ^^^^^^^ - | | - | expected this to be a list - | help: must be of the form: `#[repr(C | Rust | align(...) | packed(...) | <integer type> | transparent)]` + | ^^^^^^^ expected this to be a list + | + = note: for more information, visit <https://doc.rust-lang.org/reference/type-layout.html#representations> +help: try changing it to one of the following valid forms of the attribute + | +LL | #[repr(<integer type>)] + | ++++++++++++++++ +LL | #[repr(C)] + | +++ +LL | #[repr(Rust)] + | ++++++ +LL | #[repr(align(...))] + | ++++++++++++ + = and 2 other candidates error[E0565]: malformed `rustc_as_ptr` attribute input --> $DIR/malformed-attrs.rs:48:1 @@ -300,10 +402,16 @@ error[E0539]: malformed `optimize` attribute input --> $DIR/malformed-attrs.rs:55:1 | LL | #[optimize] - | ^^^^^^^^^^^ - | | - | expected this to be a list - | help: must be of the form: `#[optimize(size|speed|none)]` + | ^^^^^^^^^^^ expected this to be a list + | +help: try changing it to one of the following valid forms of the attribute + | +LL | #[optimize(none)] + | ++++++ +LL | #[optimize(size)] + | ++++++ +LL | #[optimize(speed)] + | +++++++ error[E0565]: malformed `cold` attribute input --> $DIR/malformed-attrs.rs:57:1 @@ -363,8 +471,10 @@ LL | #[used()] | help: try changing it to one of the following valid forms of the attribute | -LL | #[used(compiler|linker)] - | +++++++++++++++ +LL | #[used(compiler)] + | ++++++++ +LL | #[used(linker)] + | ++++++ LL - #[used()] LL + #[used] | @@ -392,12 +502,16 @@ error[E0539]: malformed `link_name` attribute input | LL | #[link_name] | ^^^^^^^^^^^^ help: must be of the form: `#[link_name = "name"]` + | + = 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:85:1 | LL | #[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[E0539]: malformed `coverage` attribute input --> $DIR/malformed-attrs.rs:87:1 @@ -456,6 +570,7 @@ LL | #[must_use = 1] | | | expected a string literal here | + = note: for more information, visit <https://doc.rust-lang.org/reference/attributes/diagnostics.html#the-must_use-attribute> help: try changing it to one of the following valid forms of the attribute | LL - #[must_use = 1] @@ -469,10 +584,15 @@ error[E0539]: malformed `proc_macro_derive` attribute input --> $DIR/malformed-attrs.rs:120:1 | LL | #[proc_macro_derive] - | ^^^^^^^^^^^^^^^^^^^^ - | | - | expected this to be a list - | help: must be of the form: `#[proc_macro_derive(TraitName, /*opt*/ attributes(name1, name2, ...))]` + | ^^^^^^^^^^^^^^^^^^^^ expected this to be a list + | + = note: for more information, visit <https://doc.rust-lang.org/reference/procedural-macros.html#derive-macros> +help: try changing it to one of the following valid forms of the attribute + | +LL | #[proc_macro_derive(TraitName)] + | +++++++++++ +LL | #[proc_macro_derive(TraitName, attributes(name1, name2, ...))] + | ++++++++++++++++++++++++++++++++++++++++++ error[E0539]: malformed `rustc_layout_scalar_valid_range_start` attribute input --> $DIR/malformed-attrs.rs:125:1 @@ -527,6 +647,8 @@ LL | #[link_ordinal] | | | expected this to be a list | help: must be of the form: `#[link_ordinal(ordinal)]` + | + = 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:168:5 @@ -561,6 +683,15 @@ error: valid forms for the attribute are `#[macro_use(name1, name2, ...)]` and ` LL | #[macro_use = 1] | ^^^^^^^^^^^^^^^^ +error[E0565]: malformed `allow_internal_unsafe` attribute input + --> $DIR/malformed-attrs.rs:213:1 + | +LL | #[allow_internal_unsafe = 1] + | ^^^^^^^^^^^^^^^^^^^^^^^^---^ + | | | + | | didn't expect any arguments here + | help: must be of the form: `#[allow_internal_unsafe]` + error[E0565]: malformed `type_const` attribute input --> $DIR/malformed-attrs.rs:140:5 | @@ -618,7 +749,7 @@ LL | #[diagnostic::on_unimplemented = 1] | = help: only `message`, `note` and `label` are allowed as options -error: valid forms for the attribute are `#[inline(always|never)]` and `#[inline]` +error: valid forms for the attribute are `#[inline(always)]`, `#[inline(never)]`, and `#[inline]` --> $DIR/malformed-attrs.rs:50:1 | LL | #[inline = 5] @@ -661,7 +792,7 @@ error: aborting due to 74 previous errors; 3 warnings emitted Some errors have detailed explanations: E0308, E0463, E0539, E0565, E0658, E0805. For more information about an error, try `rustc --explain E0308`. Future incompatibility report: Future breakage diagnostic: -error: valid forms for the attribute are `#[doc(hidden|inline|...)]` and `#[doc = "string"]` +error: valid forms for the attribute are `#[doc(hidden)]`, `#[doc(inline)]`, and `#[doc = "string"]` --> $DIR/malformed-attrs.rs:40:1 | LL | #[doc] @@ -669,10 +800,11 @@ LL | #[doc] | = 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> + = note: for more information, visit <https://doc.rust-lang.org/rustdoc/write-documentation/the-doc-attribute.html> = note: `#[deny(ill_formed_attribute_input)]` on by default Future breakage diagnostic: -error: valid forms for the attribute are `#[doc(hidden|inline|...)]` and `#[doc = "string"]` +error: valid forms for the attribute are `#[doc(hidden)]`, `#[doc(inline)]`, and `#[doc = "string"]` --> $DIR/malformed-attrs.rs:73:1 | LL | #[doc] @@ -680,10 +812,11 @@ LL | #[doc] | = 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> + = note: for more information, visit <https://doc.rust-lang.org/rustdoc/write-documentation/the-doc-attribute.html> = note: `#[deny(ill_formed_attribute_input)]` on by default Future breakage diagnostic: -error: attribute must be of the form `#[link(name = "...", /*opt*/ kind = "dylib|static|...", /*opt*/ wasm_import_module = "...", /*opt*/ import_name_type = "decorated|noprefix|undecorated")]` +error: valid forms for the attribute are `#[link(name = "...")]`, `#[link(name = "...", kind = "dylib|static|...")]`, `#[link(name = "...", wasm_import_module = "...")]`, `#[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]`, and `#[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]` --> $DIR/malformed-attrs.rs:80:1 | LL | #[link] @@ -691,10 +824,11 @@ LL | #[link] | = 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> + = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute> = note: `#[deny(ill_formed_attribute_input)]` on by default Future breakage diagnostic: -error: valid forms for the attribute are `#[inline(always|never)]` and `#[inline]` +error: valid forms for the attribute are `#[inline(always)]`, `#[inline(never)]`, and `#[inline]` --> $DIR/malformed-attrs.rs:50:1 | LL | #[inline = 5] diff --git a/tests/ui/attributes/malformed-reprs.stderr b/tests/ui/attributes/malformed-reprs.stderr index c39c98dde31..43085b9c341 100644 --- a/tests/ui/attributes/malformed-reprs.stderr +++ b/tests/ui/attributes/malformed-reprs.stderr @@ -2,10 +2,24 @@ error[E0539]: malformed `repr` attribute input --> $DIR/malformed-reprs.rs:4:1 | LL | #![repr] - | ^^^^^^^^ - | | - | expected this to be a list - | help: must be of the form: `#[repr(C | Rust | align(...) | packed(...) | <integer type> | transparent)]` + | ^^^^^^^^ expected this to be a list + | + = note: for more information, visit <https://doc.rust-lang.org/reference/type-layout.html#representations> +help: try changing it to one of the following valid forms of the attribute + | +LL - #![repr] +LL + #[repr(<integer type>)] + | +LL - #![repr] +LL + #[repr(C)] + | +LL - #![repr] +LL + #[repr(Rust)] + | +LL - #![repr] +LL + #[repr(align(...))] + | + = and 2 other candidates error[E0589]: invalid `repr(align)` attribute: not a power of two --> $DIR/malformed-reprs.rs:9:14 diff --git a/tests/ui/attributes/unsafe/proc-unsafe-attributes.stderr b/tests/ui/attributes/unsafe/proc-unsafe-attributes.stderr index 884e7663c85..107e053ae0c 100644 --- a/tests/ui/attributes/unsafe/proc-unsafe-attributes.stderr +++ b/tests/ui/attributes/unsafe/proc-unsafe-attributes.stderr @@ -119,9 +119,18 @@ error[E0565]: malformed `proc_macro_derive` attribute input | LL | #[proc_macro_derive(unsafe(Foo))] | ^^^^^^^^^^^^^^^^^^^^^^^^^^-----^^ - | | | - | | didn't expect any arguments here - | help: must be of the form: `#[proc_macro_derive(TraitName, /*opt*/ attributes(name1, name2, ...))]` + | | + | didn't expect any arguments here + | + = note: for more information, visit <https://doc.rust-lang.org/reference/procedural-macros.html#derive-macros> +help: try changing it to one of the following valid forms of the attribute + | +LL - #[proc_macro_derive(unsafe(Foo))] +LL + #[proc_macro_derive(TraitName)] + | +LL - #[proc_macro_derive(unsafe(Foo))] +LL + #[proc_macro_derive(TraitName, attributes(name1, name2, ...))] + | error[E0452]: malformed lint attribute input --> $DIR/proc-unsafe-attributes.rs:27:16 diff --git a/tests/ui/attributes/used_with_multi_args.stderr b/tests/ui/attributes/used_with_multi_args.stderr index e48209cf204..308f0519b8c 100644 --- a/tests/ui/attributes/used_with_multi_args.stderr +++ b/tests/ui/attributes/used_with_multi_args.stderr @@ -9,7 +9,10 @@ LL | #[used(compiler, linker)] help: try changing it to one of the following valid forms of the attribute | LL - #[used(compiler, linker)] -LL + #[used(compiler|linker)] +LL + #[used(compiler)] + | +LL - #[used(compiler, linker)] +LL + #[used(linker)] | LL - #[used(compiler, linker)] LL + #[used] diff --git a/tests/ui/cfg/cfg-target-compact-errors.stderr b/tests/ui/cfg/cfg-target-compact-errors.stderr index 7df6729e881..cf61f94278a 100644 --- a/tests/ui/cfg/cfg-target-compact-errors.stderr +++ b/tests/ui/cfg/cfg-target-compact-errors.stderr @@ -6,6 +6,8 @@ LL | #[cfg(target(o::o))] | | | | | expected this to be of the form `... = "..."` | 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[E0539]: malformed `cfg` attribute input --> $DIR/cfg-target-compact-errors.rs:9:1 @@ -15,6 +17,8 @@ LL | #[cfg(target(os = 8))] | | | | | expected a string literal 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[E0539]: malformed `cfg` attribute input --> $DIR/cfg-target-compact-errors.rs:13:1 @@ -24,6 +28,8 @@ LL | #[cfg(target(os = "linux", pointer(width = "64")))] | | | | | expected this to be of the form `... = "..."` | 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[E0539]: malformed `cfg` attribute input --> $DIR/cfg-target-compact-errors.rs:17:1 @@ -33,6 +39,8 @@ LL | #[cfg(target(true))] | | | | | expected this to be of the form `... = "..."` | 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-target-compact-errors.rs:21:14 diff --git a/tests/ui/conditional-compilation/cfg-attr-syntax-validation.rs b/tests/ui/conditional-compilation/cfg-attr-syntax-validation.rs index df87a3d846e..126a534dc6f 100644 --- a/tests/ui/conditional-compilation/cfg-attr-syntax-validation.rs +++ b/tests/ui/conditional-compilation/cfg-attr-syntax-validation.rs @@ -1,21 +1,25 @@ #[cfg] //~^ ERROR malformed `cfg` attribute //~| NOTE expected this to be a list +//~| NOTE for more information, visit struct S1; #[cfg = 10] //~^ ERROR malformed `cfg` attribute //~| NOTE expected this to be a list +//~| NOTE for more information, visit struct S2; #[cfg()] //~^ ERROR malformed `cfg` attribute //~| NOTE expected a single argument here +//~| NOTE for more information, visit struct S3; #[cfg(a, b)] //~^ ERROR malformed `cfg` attribute //~| NOTE expected a single argument here +//~| NOTE for more information, visit struct S4; #[cfg("str")] //~ ERROR `cfg` predicate key must be an identifier @@ -29,6 +33,7 @@ struct S7; #[cfg(a = 10)] //~ ERROR malformed `cfg` attribute input //~^ NOTE expected a string literal here +//~| NOTE for more information, visit struct S8; #[cfg(a = b"hi")] //~ ERROR malformed `cfg` attribute input diff --git a/tests/ui/conditional-compilation/cfg-attr-syntax-validation.stderr b/tests/ui/conditional-compilation/cfg-attr-syntax-validation.stderr index 75e9b9209c0..6acde758ea5 100644 --- a/tests/ui/conditional-compilation/cfg-attr-syntax-validation.stderr +++ b/tests/ui/conditional-compilation/cfg-attr-syntax-validation.stderr @@ -6,63 +6,73 @@ LL | #[cfg] | | | expected this to be a list | 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[E0539]: malformed `cfg` attribute input - --> $DIR/cfg-attr-syntax-validation.rs:6:1 + --> $DIR/cfg-attr-syntax-validation.rs:7:1 | LL | #[cfg = 10] | ^^^^^^^^^^^ | | | expected this to be a list | 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[E0805]: malformed `cfg` attribute input - --> $DIR/cfg-attr-syntax-validation.rs:11:1 + --> $DIR/cfg-attr-syntax-validation.rs:13:1 | LL | #[cfg()] | ^^^^^--^ | | | | | expected a single argument 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[E0805]: malformed `cfg` attribute input - --> $DIR/cfg-attr-syntax-validation.rs:16:1 + --> $DIR/cfg-attr-syntax-validation.rs:19:1 | LL | #[cfg(a, b)] | ^^^^^------^ | | | | | expected a single argument 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:21:7 + --> $DIR/cfg-attr-syntax-validation.rs:25:7 | LL | #[cfg("str")] | ^^^^^ error: `cfg` predicate key must be an identifier - --> $DIR/cfg-attr-syntax-validation.rs:24:7 + --> $DIR/cfg-attr-syntax-validation.rs:28:7 | LL | #[cfg(a::b)] | ^^^^ error[E0537]: invalid predicate `a` - --> $DIR/cfg-attr-syntax-validation.rs:27:7 + --> $DIR/cfg-attr-syntax-validation.rs:31:7 | LL | #[cfg(a())] | ^^^ error[E0539]: malformed `cfg` attribute input - --> $DIR/cfg-attr-syntax-validation.rs:30:1 + --> $DIR/cfg-attr-syntax-validation.rs:34:1 | LL | #[cfg(a = 10)] | ^^^^^^^^^^--^^ | | | | | expected a string literal 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[E0539]: malformed `cfg` attribute input - --> $DIR/cfg-attr-syntax-validation.rs:34:1 + --> $DIR/cfg-attr-syntax-validation.rs:39:1 | LL | #[cfg(a = b"hi")] | ^^^^^^^^^^-^^^^^^ @@ -72,7 +82,7 @@ LL | #[cfg(a = b"hi")] = note: expected a normal string literal, not a byte string literal error: expected unsuffixed literal, found `expr` metavariable - --> $DIR/cfg-attr-syntax-validation.rs:40:25 + --> $DIR/cfg-attr-syntax-validation.rs:45:25 | LL | #[cfg(feature = $expr)] | ^^^^^ diff --git a/tests/ui/deprecation/deprecation-sanity.stderr b/tests/ui/deprecation/deprecation-sanity.stderr index f1b4697485c..856f51a4b24 100644 --- a/tests/ui/deprecation/deprecation-sanity.stderr +++ b/tests/ui/deprecation/deprecation-sanity.stderr @@ -18,11 +18,15 @@ LL - #[deprecated(since = "a", note)] LL + #[deprecated = "reason"] | LL - #[deprecated(since = "a", note)] -LL + #[deprecated(/*opt*/ since = "version", /*opt*/ note = "reason")] +LL + #[deprecated(note = "reason")] | LL - #[deprecated(since = "a", note)] -LL + #[deprecated] +LL + #[deprecated(since = "version")] | +LL - #[deprecated(since = "a", note)] +LL + #[deprecated(since = "version", note = "reason")] + | + = and 1 other candidate error[E0539]: malformed `deprecated` attribute input --> $DIR/deprecation-sanity.rs:10:5 @@ -38,11 +42,15 @@ LL - #[deprecated(since, note = "a")] LL + #[deprecated = "reason"] | LL - #[deprecated(since, note = "a")] -LL + #[deprecated(/*opt*/ since = "version", /*opt*/ note = "reason")] +LL + #[deprecated(note = "reason")] + | +LL - #[deprecated(since, note = "a")] +LL + #[deprecated(since = "version")] | LL - #[deprecated(since, note = "a")] -LL + #[deprecated] +LL + #[deprecated(since = "version", note = "reason")] | + = and 1 other candidate error[E0539]: malformed `deprecated` attribute input --> $DIR/deprecation-sanity.rs:13:5 @@ -58,11 +66,15 @@ LL - #[deprecated(since = "a", note(b))] LL + #[deprecated = "reason"] | LL - #[deprecated(since = "a", note(b))] -LL + #[deprecated(/*opt*/ since = "version", /*opt*/ note = "reason")] +LL + #[deprecated(note = "reason")] + | +LL - #[deprecated(since = "a", note(b))] +LL + #[deprecated(since = "version")] | LL - #[deprecated(since = "a", note(b))] -LL + #[deprecated] +LL + #[deprecated(since = "version", note = "reason")] | + = and 1 other candidate error[E0539]: malformed `deprecated` attribute input --> $DIR/deprecation-sanity.rs:16:5 @@ -78,11 +90,15 @@ LL - #[deprecated(since(b), note = "a")] LL + #[deprecated = "reason"] | LL - #[deprecated(since(b), note = "a")] -LL + #[deprecated(/*opt*/ since = "version", /*opt*/ note = "reason")] +LL + #[deprecated(note = "reason")] | LL - #[deprecated(since(b), note = "a")] -LL + #[deprecated] +LL + #[deprecated(since = "version")] | +LL - #[deprecated(since(b), note = "a")] +LL + #[deprecated(since = "version", note = "reason")] + | + = and 1 other candidate error[E0539]: malformed `deprecated` attribute input --> $DIR/deprecation-sanity.rs:19:5 @@ -108,11 +124,15 @@ LL - #[deprecated("test")] LL + #[deprecated = "reason"] | LL - #[deprecated("test")] -LL + #[deprecated(/*opt*/ since = "version", /*opt*/ note = "reason")] +LL + #[deprecated(note = "reason")] + | +LL - #[deprecated("test")] +LL + #[deprecated(since = "version")] | LL - #[deprecated("test")] -LL + #[deprecated] +LL + #[deprecated(since = "version", note = "reason")] | + = and 1 other candidate error: multiple `deprecated` attributes --> $DIR/deprecation-sanity.rs:27:1 @@ -140,11 +160,15 @@ LL - #[deprecated(since = "a", since = "b", note = "c")] LL + #[deprecated = "reason"] | LL - #[deprecated(since = "a", since = "b", note = "c")] -LL + #[deprecated(/*opt*/ since = "version", /*opt*/ note = "reason")] +LL + #[deprecated(note = "reason")] + | +LL - #[deprecated(since = "a", since = "b", note = "c")] +LL + #[deprecated(since = "version")] | LL - #[deprecated(since = "a", since = "b", note = "c")] -LL + #[deprecated] +LL + #[deprecated(since = "version", note = "reason")] | + = and 1 other candidate error: this `#[deprecated]` annotation has no effect --> $DIR/deprecation-sanity.rs:35:1 diff --git a/tests/ui/error-codes/E0197.stderr b/tests/ui/error-codes/E0197.stderr index c06777396e8..04c6174b9f1 100644 --- a/tests/ui/error-codes/E0197.stderr +++ b/tests/ui/error-codes/E0197.stderr @@ -5,6 +5,8 @@ LL | unsafe impl Foo { } | ------ ^^^ inherent impl for this type | | | unsafe because of this + | + = note: only trait implementations may be annotated with `unsafe` error: aborting due to 1 previous error diff --git a/tests/ui/error-codes/E0540.stderr b/tests/ui/error-codes/E0540.stderr index 3e5f408feb5..ae23dce5c50 100644 --- a/tests/ui/error-codes/E0540.stderr +++ b/tests/ui/error-codes/E0540.stderr @@ -6,10 +6,13 @@ LL | #[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 | #[inline(always|never)] - | ++++++++++++ +LL | #[inline(always)] + | ++++++ +LL | #[inline(never)] + | +++++ LL - #[inline()] LL + #[inline] | diff --git a/tests/ui/error-codes/E0565-1.stderr b/tests/ui/error-codes/E0565-1.stderr index 6277e6400d7..52daf2a62fc 100644 --- a/tests/ui/error-codes/E0565-1.stderr +++ b/tests/ui/error-codes/E0565-1.stderr @@ -12,11 +12,15 @@ LL - #[deprecated("since")] LL + #[deprecated = "reason"] | LL - #[deprecated("since")] -LL + #[deprecated(/*opt*/ since = "version", /*opt*/ note = "reason")] +LL + #[deprecated(note = "reason")] | LL - #[deprecated("since")] -LL + #[deprecated] +LL + #[deprecated(since = "version")] | +LL - #[deprecated("since")] +LL + #[deprecated(since = "version", note = "reason")] + | + = and 1 other candidate error: aborting due to 1 previous error diff --git a/tests/ui/extern/issue-47725.rs b/tests/ui/extern/issue-47725.rs index 60d0cd62347..8ac866dc7d9 100644 --- a/tests/ui/extern/issue-47725.rs +++ b/tests/ui/extern/issue-47725.rs @@ -17,6 +17,7 @@ extern "C" { #[link_name] //~^ ERROR malformed `link_name` attribute input //~| HELP must be of the form +//~| NOTE for more information, visit extern "C" { fn bar() -> u32; } diff --git a/tests/ui/extern/issue-47725.stderr b/tests/ui/extern/issue-47725.stderr index 4fd02a1778b..c5af54b8029 100644 --- a/tests/ui/extern/issue-47725.stderr +++ b/tests/ui/extern/issue-47725.stderr @@ -3,6 +3,8 @@ error[E0539]: malformed `link_name` attribute input | LL | #[link_name] | ^^^^^^^^^^^^ help: must be of the form: `#[link_name = "name"]` + | + = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link_name-attribute> warning: attribute should be applied to a foreign function or static --> $DIR/issue-47725.rs:3:1 diff --git a/tests/ui/feature-gates/feature-gate-optimize_attribute.stderr b/tests/ui/feature-gates/feature-gate-optimize_attribute.stderr index e7e62b4f989..646abf8e4a1 100644 --- a/tests/ui/feature-gates/feature-gate-optimize_attribute.stderr +++ b/tests/ui/feature-gates/feature-gate-optimize_attribute.stderr @@ -43,9 +43,20 @@ error[E0539]: malformed `optimize` attribute input | LL | #[optimize(banana)] | ^^^^^^^^^^^------^^ - | | | - | | valid arguments are `size`, `speed` or `none` - | help: must be of the form: `#[optimize(size|speed|none)]` + | | + | valid arguments are `size`, `speed` or `none` + | +help: try changing it to one of the following valid forms of the attribute + | +LL - #[optimize(banana)] +LL + #[optimize(none)] + | +LL - #[optimize(banana)] +LL + #[optimize(size)] + | +LL - #[optimize(banana)] +LL + #[optimize(speed)] + | error: aborting due to 5 previous errors 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 324f7e9fd8a..7550e26f4a7 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 @@ -304,7 +304,7 @@ error[E0517]: attribute should be applied to a struct, enum, or union LL | #[repr(Rust)] impl S { } | ^^^^ ---------- not a struct, enum, or union -error: valid forms for the attribute are `#[inline(always|never)]` and `#[inline]` +error: valid forms for the attribute are `#[inline(always)]`, `#[inline(never)]`, and `#[inline]` --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:46:5 | LL | #[inline = "2100"] fn f() { } @@ -319,7 +319,7 @@ error: aborting due to 38 previous errors Some errors have detailed explanations: E0517, E0518, 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|never)]` and `#[inline]` +error: valid forms for the attribute are `#[inline(always)]`, `#[inline(never)]`, and `#[inline]` --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:46:5 | LL | #[inline = "2100"] fn f() { } diff --git a/tests/ui/invalid-compile-flags/print-crate-name-request-malformed-crate-name.stderr b/tests/ui/invalid-compile-flags/print-crate-name-request-malformed-crate-name.stderr index 6bf09a2b131..b773f7c97aa 100644 --- a/tests/ui/invalid-compile-flags/print-crate-name-request-malformed-crate-name.stderr +++ b/tests/ui/invalid-compile-flags/print-crate-name-request-malformed-crate-name.stderr @@ -3,6 +3,8 @@ error: malformed `crate_name` attribute input | LL | #![crate_name = concat!("wrapped")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#![crate_name = "name"]` + | + = note: for more information, visit <https://doc.rust-lang.org/reference/crates-and-source-files.html#the-crate_name-attribute> error: aborting due to 1 previous error diff --git a/tests/ui/invalid-compile-flags/print-file-names-request-malformed-crate-name-1.stderr b/tests/ui/invalid-compile-flags/print-file-names-request-malformed-crate-name-1.stderr index de62aed79fc..64e38ed8533 100644 --- a/tests/ui/invalid-compile-flags/print-file-names-request-malformed-crate-name-1.stderr +++ b/tests/ui/invalid-compile-flags/print-file-names-request-malformed-crate-name-1.stderr @@ -3,6 +3,8 @@ error: malformed `crate_name` attribute input | LL | #![crate_name] | ^^^^^^^^^^^^^^ help: must be of the form: `#![crate_name = "name"]` + | + = note: for more information, visit <https://doc.rust-lang.org/reference/crates-and-source-files.html#the-crate_name-attribute> error: aborting due to 1 previous error diff --git a/tests/ui/invalid-compile-flags/print-file-names-request-malformed-crate-name-2.stderr b/tests/ui/invalid-compile-flags/print-file-names-request-malformed-crate-name-2.stderr index 42c33de1221..e9a5b58e4f9 100644 --- a/tests/ui/invalid-compile-flags/print-file-names-request-malformed-crate-name-2.stderr +++ b/tests/ui/invalid-compile-flags/print-file-names-request-malformed-crate-name-2.stderr @@ -3,6 +3,8 @@ error: malformed `crate_name` attribute input | LL | #![crate_name = concat!("this_one_is_not")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#![crate_name = "name"]` + | + = note: for more information, visit <https://doc.rust-lang.org/reference/crates-and-source-files.html#the-crate_name-attribute> error: aborting due to 1 previous error diff --git a/tests/ui/invalid-compile-flags/print-file-names-request-malformed-crate-name.stderr b/tests/ui/invalid-compile-flags/print-file-names-request-malformed-crate-name.stderr index cb5ffaab9ca..e63525c6a5d 100644 --- a/tests/ui/invalid-compile-flags/print-file-names-request-malformed-crate-name.stderr +++ b/tests/ui/invalid-compile-flags/print-file-names-request-malformed-crate-name.stderr @@ -3,6 +3,8 @@ error: malformed `crate_name` attribute input | LL | #![crate_name = concat!("wrapped")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#![crate_name = "name"]` + | + = note: for more information, visit <https://doc.rust-lang.org/reference/crates-and-source-files.html#the-crate_name-attribute> error: aborting due to 1 previous error diff --git a/tests/ui/invalid/invalid-inline.stderr b/tests/ui/invalid/invalid-inline.stderr index 54e6b2b5408..78ffe3270a7 100644 --- a/tests/ui/invalid/invalid-inline.stderr +++ b/tests/ui/invalid/invalid-inline.stderr @@ -6,10 +6,14 @@ LL | #[inline(please,no)] | | | 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 - #[inline(please,no)] -LL + #[inline(always|never)] +LL + #[inline(always)] + | +LL - #[inline(please,no)] +LL + #[inline(never)] | LL - #[inline(please,no)] LL + #[inline] @@ -23,10 +27,13 @@ LL | #[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 | #[inline(always|never)] - | ++++++++++++ +LL | #[inline(always)] + | ++++++ +LL | #[inline(never)] + | +++++ LL - #[inline()] LL + #[inline] | diff --git a/tests/ui/issues/issue-43988.stderr b/tests/ui/issues/issue-43988.stderr index fe61e136a51..b50d691e685 100644 --- a/tests/ui/issues/issue-43988.stderr +++ b/tests/ui/issues/issue-43988.stderr @@ -6,10 +6,14 @@ LL | #[inline(XYZ)] | | | valid arguments are `always` or `never` | + = 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 - #[inline(XYZ)] -LL + #[inline(always|never)] +LL + #[inline(always)] + | +LL - #[inline(XYZ)] +LL + #[inline(never)] | LL - #[inline(XYZ)] LL + #[inline] @@ -22,6 +26,7 @@ LL | #[repr(nothing)] | ^^^^^^^ | = help: valid reprs are `Rust` (default), `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize` + = note: for more information, visit <https://doc.rust-lang.org/reference/type-layout.html?highlight=repr#representations> error[E0552]: unrecognized representation hint --> $DIR/issue-43988.rs:18:12 @@ -30,15 +35,26 @@ LL | #[repr(something_not_real)] | ^^^^^^^^^^^^^^^^^^ | = help: valid reprs are `Rust` (default), `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize` + = note: for more information, visit <https://doc.rust-lang.org/reference/type-layout.html?highlight=repr#representations> error[E0539]: malformed `repr` attribute input --> $DIR/issue-43988.rs:24:5 | LL | #[repr] - | ^^^^^^^ - | | - | expected this to be a list - | help: must be of the form: `#[repr(C | Rust | align(...) | packed(...) | <integer type> | transparent)]` + | ^^^^^^^ expected this to be a list + | + = note: for more information, visit <https://doc.rust-lang.org/reference/type-layout.html#representations> +help: try changing it to one of the following valid forms of the attribute + | +LL | #[repr(<integer type>)] + | ++++++++++++++++ +LL | #[repr(C)] + | +++ +LL | #[repr(Rust)] + | ++++++ +LL | #[repr(align(...))] + | ++++++++++++ + = and 2 other candidates error[E0539]: malformed `inline` attribute input --> $DIR/issue-43988.rs:30:5 @@ -48,10 +64,14 @@ LL | #[inline(ABC)] | | | valid arguments are `always` or `never` | + = 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 - #[inline(ABC)] -LL + #[inline(always|never)] +LL + #[inline(always)] + | +LL - #[inline(ABC)] +LL + #[inline(never)] | LL - #[inline(ABC)] LL + #[inline] @@ -61,10 +81,20 @@ error[E0539]: malformed `repr` attribute input --> $DIR/issue-43988.rs:34:14 | LL | let _z = #[repr] 1; - | ^^^^^^^ - | | - | expected this to be a list - | help: must be of the form: `#[repr(C | Rust | align(...) | packed(...) | <integer type> | transparent)]` + | ^^^^^^^ expected this to be a list + | + = note: for more information, visit <https://doc.rust-lang.org/reference/type-layout.html#representations> +help: try changing it to one of the following valid forms of the attribute + | +LL | let _z = #[repr(<integer type>)] 1; + | ++++++++++++++++ +LL | let _z = #[repr(C)] 1; + | +++ +LL | let _z = #[repr(Rust)] 1; + | ++++++ +LL | let _z = #[repr(align(...))] 1; + | ++++++++++++ + = and 2 other candidates error[E0518]: attribute should be applied to function or closure --> $DIR/issue-43988.rs:5:5 diff --git a/tests/ui/link-native-libs/link-attr-validation-early.rs b/tests/ui/link-native-libs/link-attr-validation-early.rs index b9a835fb5e9..a7dd80f8920 100644 --- a/tests/ui/link-native-libs/link-attr-validation-early.rs +++ b/tests/ui/link-native-libs/link-attr-validation-early.rs @@ -1,7 +1,7 @@ // Top-level ill-formed -#[link] //~ ERROR attribute must be of the form +#[link] //~ ERROR valid forms for the attribute are //~| WARN this was previously accepted -#[link = "foo"] //~ ERROR attribute must be of the form +#[link = "foo"] //~ ERROR valid forms for the attribute are //~| WARN this was previously accepted extern "C" {} diff --git a/tests/ui/link-native-libs/link-attr-validation-early.stderr b/tests/ui/link-native-libs/link-attr-validation-early.stderr index c69899275d5..36cca6f27ef 100644 --- a/tests/ui/link-native-libs/link-attr-validation-early.stderr +++ b/tests/ui/link-native-libs/link-attr-validation-early.stderr @@ -1,4 +1,4 @@ -error: attribute must be of the form `#[link(name = "...", /*opt*/ kind = "dylib|static|...", /*opt*/ wasm_import_module = "...", /*opt*/ import_name_type = "decorated|noprefix|undecorated")]` +error: valid forms for the attribute are `#[link(name = "...")]`, `#[link(name = "...", kind = "dylib|static|...")]`, `#[link(name = "...", wasm_import_module = "...")]`, `#[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]`, and `#[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]` --> $DIR/link-attr-validation-early.rs:2:1 | LL | #[link] @@ -6,9 +6,10 @@ LL | #[link] | = 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> + = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute> = note: `#[deny(ill_formed_attribute_input)]` on by default -error: attribute must be of the form `#[link(name = "...", /*opt*/ kind = "dylib|static|...", /*opt*/ wasm_import_module = "...", /*opt*/ import_name_type = "decorated|noprefix|undecorated")]` +error: valid forms for the attribute are `#[link(name = "...")]`, `#[link(name = "...", kind = "dylib|static|...")]`, `#[link(name = "...", wasm_import_module = "...")]`, `#[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]`, and `#[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]` --> $DIR/link-attr-validation-early.rs:4:1 | LL | #[link = "foo"] @@ -16,11 +17,12 @@ LL | #[link = "foo"] | = 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> + = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute> error: aborting due to 2 previous errors Future incompatibility report: Future breakage diagnostic: -error: attribute must be of the form `#[link(name = "...", /*opt*/ kind = "dylib|static|...", /*opt*/ wasm_import_module = "...", /*opt*/ import_name_type = "decorated|noprefix|undecorated")]` +error: valid forms for the attribute are `#[link(name = "...")]`, `#[link(name = "...", kind = "dylib|static|...")]`, `#[link(name = "...", wasm_import_module = "...")]`, `#[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]`, and `#[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]` --> $DIR/link-attr-validation-early.rs:2:1 | LL | #[link] @@ -28,10 +30,11 @@ LL | #[link] | = 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> + = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute> = note: `#[deny(ill_formed_attribute_input)]` on by default Future breakage diagnostic: -error: attribute must be of the form `#[link(name = "...", /*opt*/ kind = "dylib|static|...", /*opt*/ wasm_import_module = "...", /*opt*/ import_name_type = "decorated|noprefix|undecorated")]` +error: valid forms for the attribute are `#[link(name = "...")]`, `#[link(name = "...", kind = "dylib|static|...")]`, `#[link(name = "...", wasm_import_module = "...")]`, `#[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]`, and `#[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]` --> $DIR/link-attr-validation-early.rs:4:1 | LL | #[link = "foo"] @@ -39,5 +42,6 @@ LL | #[link = "foo"] | = 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> + = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute> = note: `#[deny(ill_formed_attribute_input)]` on by default diff --git a/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-invalid-format.stderr b/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-invalid-format.stderr index ffae30aabcc..6bf1eab311a 100644 --- a/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-invalid-format.stderr +++ b/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-invalid-format.stderr @@ -6,6 +6,8 @@ LL | #[link_ordinal("JustMonika")] | | | | | expected an integer literal here | help: must be of the form: `#[link_ordinal(ordinal)]` + | + = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link_ordinal-attribute> error[E0539]: malformed `link_ordinal` attribute input --> $DIR/link-ordinal-invalid-format.rs:6:5 @@ -15,6 +17,8 @@ LL | #[link_ordinal("JustMonika")] | | | | | expected an integer literal here | help: must be of the form: `#[link_ordinal(ordinal)]` + | + = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link_ordinal-attribute> error: aborting due to 2 previous errors diff --git a/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-missing-argument.rs b/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-missing-argument.rs index 2a8b9ebacf7..58f19085540 100644 --- a/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-missing-argument.rs +++ b/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-missing-argument.rs @@ -3,10 +3,12 @@ extern "C" { #[link_ordinal()] //~^ ERROR malformed `link_ordinal` attribute input //~| NOTE expected a single argument + //~| NOTE for more information, visit fn foo(); #[link_ordinal()] //~^ ERROR malformed `link_ordinal` attribute input //~| NOTE expected a single argument + //~| NOTE for more information, visit static mut imported_variable: i32; } diff --git a/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-missing-argument.stderr b/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-missing-argument.stderr index c6b8a18d03a..d575b0961af 100644 --- a/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-missing-argument.stderr +++ b/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-missing-argument.stderr @@ -6,15 +6,19 @@ LL | #[link_ordinal()] | | | | | expected a single argument here | help: must be of the form: `#[link_ordinal(ordinal)]` + | + = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link_ordinal-attribute> error[E0805]: malformed `link_ordinal` attribute input - --> $DIR/link-ordinal-missing-argument.rs:7:5 + --> $DIR/link-ordinal-missing-argument.rs:8:5 | LL | #[link_ordinal()] | ^^^^^^^^^^^^^^--^ | | | | | expected a single argument here | help: must be of the form: `#[link_ordinal(ordinal)]` + | + = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link_ordinal-attribute> error: aborting due to 2 previous errors diff --git a/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-too-many-arguments.rs b/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-too-many-arguments.rs index ddf9583352f..55b18ae0d96 100644 --- a/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-too-many-arguments.rs +++ b/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-too-many-arguments.rs @@ -3,10 +3,12 @@ extern "C" { #[link_ordinal(3, 4)] //~^ ERROR malformed `link_ordinal` attribute input //~| NOTE expected a single argument + //~| NOTE for more information, visit fn foo(); #[link_ordinal(3, 4)] //~^ ERROR malformed `link_ordinal` attribute input //~| NOTE expected a single argument + //~| NOTE for more information, visit static mut imported_variable: i32; } diff --git a/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-too-many-arguments.stderr b/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-too-many-arguments.stderr index 7d63304f598..a84fef9f9e4 100644 --- a/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-too-many-arguments.stderr +++ b/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-too-many-arguments.stderr @@ -6,15 +6,19 @@ LL | #[link_ordinal(3, 4)] | | | | | expected a single argument here | help: must be of the form: `#[link_ordinal(ordinal)]` + | + = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link_ordinal-attribute> error[E0805]: malformed `link_ordinal` attribute input - --> $DIR/link-ordinal-too-many-arguments.rs:7:5 + --> $DIR/link-ordinal-too-many-arguments.rs:8:5 | LL | #[link_ordinal(3, 4)] | ^^^^^^^^^^^^^^------^ | | | | | expected a single argument here | help: must be of the form: `#[link_ordinal(ordinal)]` + | + = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link_ordinal-attribute> error: aborting due to 2 previous errors diff --git a/tests/ui/lint/dead-code/self-assign.rs b/tests/ui/lint/dead-code/self-assign.rs index 357846baf22..ce91f53cbf1 100644 --- a/tests/ui/lint/dead-code/self-assign.rs +++ b/tests/ui/lint/dead-code/self-assign.rs @@ -7,23 +7,20 @@ //! - `dead_code` lint expansion for self-assignments was implemented in #87129. //! - Unfortunately implementation components of #87129 had to be disabled as part of reverts //! #86212, #83171 (to revert #81473) to address regressions #81626 and #81658. -//! - Consequently, none of the following warnings are emitted. +//! - Re-enabled in current version to properly detect self-assignments. //@ check-pass -// Implementation of self-assignment `dead_code` lint expansions disabled due to reverts. -//@ known-bug: #75356 - #![allow(unused_assignments)] #![warn(dead_code)] fn main() { let mut x = 0; x = x; - // FIXME ~^ WARNING: useless assignment of variable of type `i32` to itself + //~^ WARNING: useless assignment of variable of type `i32` to itself x = (x); - // FIXME ~^ WARNING: useless assignment of variable of type `i32` to itself + //~^ WARNING: useless assignment of variable of type `i32` to itself x = {x}; // block expressions don't count as self-assignments @@ -32,10 +29,10 @@ fn main() { struct S<'a> { f: &'a str } let mut s = S { f: "abc" }; s = s; - // FIXME ~^ WARNING: useless assignment of variable of type `S` to itself + //~^ WARNING: useless assignment of variable of type `S<'_>` to itself s.f = s.f; - // FIXME ~^ WARNING: useless assignment of field of type `&str` to itself + //~^ WARNING: useless assignment of field of type `&str` to itself struct N0 { x: Box<i32> } @@ -44,11 +41,11 @@ fn main() { struct N3 { n: N2 }; let mut n3 = N3 { n: N2(N1 { n: N0 { x: Box::new(42) } }) }; n3.n.0.n.x = n3.n.0.n.x; - // FIXME ~^ WARNING: useless assignment of field of type `Box<i32>` to itself + //~^ WARNING: useless assignment of field of type `Box<i32>` to itself let mut t = (1, ((2, 3, (4, 5)),)); t.1.0.2.1 = t.1.0.2.1; - // FIXME ~^ WARNING: useless assignment of field of type `i32` to itself + //~^ WARNING: useless assignment of field of type `i32` to itself let mut y = 0; diff --git a/tests/ui/lint/dead-code/self-assign.stderr b/tests/ui/lint/dead-code/self-assign.stderr new file mode 100644 index 00000000000..408ebdb658b --- /dev/null +++ b/tests/ui/lint/dead-code/self-assign.stderr @@ -0,0 +1,44 @@ +warning: useless assignment of variable of type `i32` to itself + --> $DIR/self-assign.rs:19:5 + | +LL | x = x; + | ^^^^^ + | +note: the lint level is defined here + --> $DIR/self-assign.rs:15:9 + | +LL | #![warn(dead_code)] + | ^^^^^^^^^ + +warning: useless assignment of variable of type `i32` to itself + --> $DIR/self-assign.rs:22:5 + | +LL | x = (x); + | ^^^^^^^ + +warning: useless assignment of variable of type `S<'_>` to itself + --> $DIR/self-assign.rs:31:5 + | +LL | s = s; + | ^^^^^ + +warning: useless assignment of field of type `&str` to itself + --> $DIR/self-assign.rs:34:5 + | +LL | s.f = s.f; + | ^^^^^^^^^ + +warning: useless assignment of field of type `Box<i32>` to itself + --> $DIR/self-assign.rs:43:5 + | +LL | n3.n.0.n.x = n3.n.0.n.x; + | ^^^^^^^^^^^^^^^^^^^^^^^ + +warning: useless assignment of field of type `i32` to itself + --> $DIR/self-assign.rs:47:5 + | +LL | t.1.0.2.1 = t.1.0.2.1; + | ^^^^^^^^^^^^^^^^^^^^^ + +warning: 6 warnings emitted + diff --git a/tests/ui/lint/lint-malformed.stderr b/tests/ui/lint/lint-malformed.stderr index 0bdcc293b65..25a4298bd75 100644 --- a/tests/ui/lint/lint-malformed.stderr +++ b/tests/ui/lint/lint-malformed.stderr @@ -16,7 +16,20 @@ error: malformed `deny` attribute input --> $DIR/lint-malformed.rs:1:1 | LL | #![deny = "foo"] - | ^^^^^^^^^^^^^^^^ help: must be of the form: `#![deny(lint1, lint2, ..., /*opt*/ reason = "...")]` + | ^^^^^^^^^^^^^^^^ + | + = note: for more information, visit <https://doc.rust-lang.org/reference/attributes/diagnostics.html#lint-check-attributes> +help: the following are the possible correct uses + | +LL - #![deny = "foo"] +LL + #![deny(lint1)] + | +LL - #![deny = "foo"] +LL + #![deny(lint1, lint2, ...)] + | +LL - #![deny = "foo"] +LL + #![deny(lint1, lint2, lint3, reason = "...")] + | error[E0452]: malformed lint attribute input --> $DIR/lint-malformed.rs:2:10 diff --git a/tests/ui/macros/macro-use-bad-args-1.stderr b/tests/ui/macros/macro-use-bad-args-1.stderr index 2f43d0997df..542b4ae2b7a 100644 --- a/tests/ui/macros/macro-use-bad-args-1.stderr +++ b/tests/ui/macros/macro-use-bad-args-1.stderr @@ -6,6 +6,7 @@ LL | #[macro_use(foo(bar))] | | | didn't expect any arguments here | + = note: for more information, visit <https://doc.rust-lang.org/reference/macros-by-example.html#the-macro_use-attribute> help: try changing it to one of the following valid forms of the attribute | LL - #[macro_use(foo(bar))] diff --git a/tests/ui/macros/macro-use-bad-args-2.stderr b/tests/ui/macros/macro-use-bad-args-2.stderr index d7b03c93588..2db9ffe50b0 100644 --- a/tests/ui/macros/macro-use-bad-args-2.stderr +++ b/tests/ui/macros/macro-use-bad-args-2.stderr @@ -6,6 +6,7 @@ LL | #[macro_use(foo="bar")] | | | didn't expect any arguments here | + = note: for more information, visit <https://doc.rust-lang.org/reference/macros-by-example.html#the-macro_use-attribute> help: try changing it to one of the following valid forms of the attribute | LL - #[macro_use(foo="bar")] diff --git a/tests/ui/malformed/malformed-regressions.rs b/tests/ui/malformed/malformed-regressions.rs index f0a7aac59c1..99f0fc904a9 100644 --- a/tests/ui/malformed/malformed-regressions.rs +++ b/tests/ui/malformed/malformed-regressions.rs @@ -4,9 +4,9 @@ //~^ WARN this was previously accepted #[inline = ""] //~ ERROR valid forms for the attribute are //~^ WARN this was previously accepted -#[link] //~ ERROR attribute must be of the form +#[link] //~ ERROR valid forms for the attribute are //~^ WARN this was previously accepted -#[link = ""] //~ ERROR attribute must be of the form +#[link = ""] //~ ERROR valid forms for the attribute are //~^ WARN this was previously accepted fn main() {} diff --git a/tests/ui/malformed/malformed-regressions.stderr b/tests/ui/malformed/malformed-regressions.stderr index 60ea5da761d..4a00c9b4a7d 100644 --- a/tests/ui/malformed/malformed-regressions.stderr +++ b/tests/ui/malformed/malformed-regressions.stderr @@ -1,4 +1,4 @@ -error: valid forms for the attribute are `#[doc(hidden|inline|...)]` and `#[doc = "string"]` +error: valid forms for the attribute are `#[doc(hidden)]`, `#[doc(inline)]`, and `#[doc = "string"]` --> $DIR/malformed-regressions.rs:1:1 | LL | #[doc] @@ -6,9 +6,10 @@ LL | #[doc] | = 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> + = note: for more information, visit <https://doc.rust-lang.org/rustdoc/write-documentation/the-doc-attribute.html> = note: `#[deny(ill_formed_attribute_input)]` on by default -error: attribute must be of the form `#[link(name = "...", /*opt*/ kind = "dylib|static|...", /*opt*/ wasm_import_module = "...", /*opt*/ import_name_type = "decorated|noprefix|undecorated")]` +error: valid forms for the attribute are `#[link(name = "...")]`, `#[link(name = "...", kind = "dylib|static|...")]`, `#[link(name = "...", wasm_import_module = "...")]`, `#[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]`, and `#[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]` --> $DIR/malformed-regressions.rs:7:1 | LL | #[link] @@ -16,8 +17,9 @@ LL | #[link] | = 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> + = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute> -error: attribute must be of the form `#[link(name = "...", /*opt*/ kind = "dylib|static|...", /*opt*/ wasm_import_module = "...", /*opt*/ import_name_type = "decorated|noprefix|undecorated")]` +error: valid forms for the attribute are `#[link(name = "...")]`, `#[link(name = "...", kind = "dylib|static|...")]`, `#[link(name = "...", wasm_import_module = "...")]`, `#[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]`, and `#[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]` --> $DIR/malformed-regressions.rs:9:1 | LL | #[link = ""] @@ -25,6 +27,7 @@ LL | #[link = ""] | = 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> + = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute> error: valid forms for the attribute are `#[ignore = "reason"]` and `#[ignore]` --> $DIR/malformed-regressions.rs:3:1 @@ -35,7 +38,7 @@ LL | #[ignore()] = 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: valid forms for the attribute are `#[inline(always|never)]` and `#[inline]` +error: valid forms for the attribute are `#[inline(always)]`, `#[inline(never)]`, and `#[inline]` --> $DIR/malformed-regressions.rs:5:1 | LL | #[inline = ""] @@ -47,7 +50,7 @@ LL | #[inline = ""] error: aborting due to 5 previous errors Future incompatibility report: Future breakage diagnostic: -error: valid forms for the attribute are `#[doc(hidden|inline|...)]` and `#[doc = "string"]` +error: valid forms for the attribute are `#[doc(hidden)]`, `#[doc(inline)]`, and `#[doc = "string"]` --> $DIR/malformed-regressions.rs:1:1 | LL | #[doc] @@ -55,10 +58,11 @@ LL | #[doc] | = 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> + = note: for more information, visit <https://doc.rust-lang.org/rustdoc/write-documentation/the-doc-attribute.html> = note: `#[deny(ill_formed_attribute_input)]` on by default Future breakage diagnostic: -error: attribute must be of the form `#[link(name = "...", /*opt*/ kind = "dylib|static|...", /*opt*/ wasm_import_module = "...", /*opt*/ import_name_type = "decorated|noprefix|undecorated")]` +error: valid forms for the attribute are `#[link(name = "...")]`, `#[link(name = "...", kind = "dylib|static|...")]`, `#[link(name = "...", wasm_import_module = "...")]`, `#[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]`, and `#[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]` --> $DIR/malformed-regressions.rs:7:1 | LL | #[link] @@ -66,10 +70,11 @@ LL | #[link] | = 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> + = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute> = note: `#[deny(ill_formed_attribute_input)]` on by default Future breakage diagnostic: -error: attribute must be of the form `#[link(name = "...", /*opt*/ kind = "dylib|static|...", /*opt*/ wasm_import_module = "...", /*opt*/ import_name_type = "decorated|noprefix|undecorated")]` +error: valid forms for the attribute are `#[link(name = "...")]`, `#[link(name = "...", kind = "dylib|static|...")]`, `#[link(name = "...", wasm_import_module = "...")]`, `#[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]`, and `#[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]` --> $DIR/malformed-regressions.rs:9:1 | LL | #[link = ""] @@ -77,6 +82,7 @@ LL | #[link = ""] | = 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> + = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute> = note: `#[deny(ill_formed_attribute_input)]` on by default Future breakage diagnostic: @@ -91,7 +97,7 @@ LL | #[ignore()] = note: `#[deny(ill_formed_attribute_input)]` on by default Future breakage diagnostic: -error: valid forms for the attribute are `#[inline(always|never)]` and `#[inline]` +error: valid forms for the attribute are `#[inline(always)]`, `#[inline(never)]`, and `#[inline]` --> $DIR/malformed-regressions.rs:5:1 | LL | #[inline = ""] diff --git a/tests/ui/modules/path-invalid-form.stderr b/tests/ui/modules/path-invalid-form.stderr index e8ded1343f7..4e9a62fa7a9 100644 --- a/tests/ui/modules/path-invalid-form.stderr +++ b/tests/ui/modules/path-invalid-form.stderr @@ -3,6 +3,8 @@ error: malformed `path` attribute input | LL | #[path = 123] | ^^^^^^^^^^^^^ help: must be of the form: `#[path = "file"]` + | + = note: for more information, visit <https://doc.rust-lang.org/reference/items/modules.html#the-path-attribute> error: aborting due to 1 previous error diff --git a/tests/ui/modules/path-macro.stderr b/tests/ui/modules/path-macro.stderr index eb02c721edd..fd93871f3a6 100644 --- a/tests/ui/modules/path-macro.stderr +++ b/tests/ui/modules/path-macro.stderr @@ -3,6 +3,8 @@ error: malformed `path` attribute input | LL | #[path = foo!()] | ^^^^^^^^^^^^^^^^ help: must be of the form: `#[path = "file"]` + | + = note: for more information, visit <https://doc.rust-lang.org/reference/items/modules.html#the-path-attribute> error: aborting due to 1 previous error diff --git a/tests/ui/parser/bad-lit-suffixes.stderr b/tests/ui/parser/bad-lit-suffixes.stderr index 7876d75c5a4..9a51cf70960 100644 --- a/tests/ui/parser/bad-lit-suffixes.stderr +++ b/tests/ui/parser/bad-lit-suffixes.stderr @@ -158,6 +158,7 @@ LL | #[must_use = "string"suffix] | | | expected a string literal here | + = note: for more information, visit <https://doc.rust-lang.org/reference/attributes/diagnostics.html#the-must_use-attribute> help: try changing it to one of the following valid forms of the attribute | LL - #[must_use = "string"suffix] diff --git a/tests/ui/parser/default-on-wrong-item-kind.rs b/tests/ui/parser/default-on-wrong-item-kind.rs index da990a4b421..9de85640565 100644 --- a/tests/ui/parser/default-on-wrong-item-kind.rs +++ b/tests/ui/parser/default-on-wrong-item-kind.rs @@ -19,7 +19,7 @@ mod free_items { default union foo {} //~ ERROR a union cannot be `default` default trait foo {} //~ ERROR a trait cannot be `default` default trait foo = Ord; //~ ERROR a trait alias cannot be `default` - default impl foo {} + default impl foo {} //~ ERROR inherent impls cannot be default default!(); default::foo::bar!(); default default!(); //~ ERROR an item macro invocation cannot be `default` @@ -53,7 +53,7 @@ extern "C" { //~^ ERROR trait is not supported in `extern` blocks default trait foo = Ord; //~ ERROR a trait alias cannot be `default` //~^ ERROR trait alias is not supported in `extern` blocks - default impl foo {} + default impl foo {} //~ ERROR inherent impls cannot be default //~^ ERROR implementation is not supported in `extern` blocks default!(); default::foo::bar!(); @@ -90,7 +90,7 @@ impl S { //~^ ERROR trait is not supported in `trait`s or `impl`s default trait foo = Ord; //~ ERROR a trait alias cannot be `default` //~^ ERROR trait alias is not supported in `trait`s or `impl`s - default impl foo {} + default impl foo {} //~ ERROR inherent impls cannot be default //~^ ERROR implementation is not supported in `trait`s or `impl`s default!(); default::foo::bar!(); @@ -127,7 +127,7 @@ trait T { //~^ ERROR trait is not supported in `trait`s or `impl`s default trait foo = Ord; //~ ERROR a trait alias cannot be `default` //~^ ERROR trait alias is not supported in `trait`s or `impl`s - default impl foo {} + default impl foo {} //~ ERROR inherent impls cannot be default //~^ ERROR implementation is not supported in `trait`s or `impl`s default!(); default::foo::bar!(); diff --git a/tests/ui/parser/default-on-wrong-item-kind.stderr b/tests/ui/parser/default-on-wrong-item-kind.stderr index 56641565b16..0380fcdf775 100644 --- a/tests/ui/parser/default-on-wrong-item-kind.stderr +++ b/tests/ui/parser/default-on-wrong-item-kind.stderr @@ -78,6 +78,16 @@ LL | default trait foo = Ord; | = note: only associated `fn`, `const`, and `type` items can be `default` +error: inherent impls cannot be default + --> $DIR/default-on-wrong-item-kind.rs:22:18 + | +LL | default impl foo {} + | ------- ^^^ inherent impl for this type + | | + | default because of this + | + = note: only trait implementations may be annotated with `default` + error: an item macro invocation cannot be `default` --> $DIR/default-on-wrong-item-kind.rs:25:5 | @@ -275,6 +285,16 @@ LL | default trait foo = Ord; | = help: consider moving the trait alias out to a nearby module scope +error: inherent impls cannot be default + --> $DIR/default-on-wrong-item-kind.rs:56:18 + | +LL | default impl foo {} + | ------- ^^^ inherent impl for this type + | | + | default because of this + | + = note: only trait implementations may be annotated with `default` + error: implementation is not supported in `extern` blocks --> $DIR/default-on-wrong-item-kind.rs:56:5 | @@ -489,6 +509,16 @@ LL | default trait foo = Ord; | = help: consider moving the trait alias out to a nearby module scope +error: inherent impls cannot be default + --> $DIR/default-on-wrong-item-kind.rs:93:18 + | +LL | default impl foo {} + | ------- ^^^ inherent impl for this type + | | + | default because of this + | + = note: only trait implementations may be annotated with `default` + error: implementation is not supported in `trait`s or `impl`s --> $DIR/default-on-wrong-item-kind.rs:93:5 | @@ -703,6 +733,16 @@ LL | default trait foo = Ord; | = help: consider moving the trait alias out to a nearby module scope +error: inherent impls cannot be default + --> $DIR/default-on-wrong-item-kind.rs:130:18 + | +LL | default impl foo {} + | ------- ^^^ inherent impl for this type + | | + | default because of this + | + = note: only trait implementations may be annotated with `default` + error: implementation is not supported in `trait`s or `impl`s --> $DIR/default-on-wrong-item-kind.rs:130:5 | @@ -759,5 +799,5 @@ LL | default macro_rules! foo {} | = help: consider moving the macro definition out to a nearby module scope -error: aborting due to 95 previous errors +error: aborting due to 99 previous errors diff --git a/tests/ui/proc-macro/attribute.rs b/tests/ui/proc-macro/attribute.rs index 988cdcd0403..dfb26738377 100644 --- a/tests/ui/proc-macro/attribute.rs +++ b/tests/ui/proc-macro/attribute.rs @@ -9,46 +9,55 @@ use proc_macro::*; #[proc_macro_derive] //~^ ERROR malformed `proc_macro_derive` attribute //~| NOTE expected this to be a list +//~| NOTE for more information, visit pub fn foo1(input: TokenStream) -> TokenStream { input } #[proc_macro_derive = ""] //~^ ERROR malformed `proc_macro_derive` attribute //~| NOTE expected this to be a list +//~| NOTE for more information, visit pub fn foo2(input: TokenStream) -> TokenStream { input } #[proc_macro_derive(d3, a, b)] //~^ ERROR malformed `proc_macro_derive` attribute //~| NOTE the only valid argument here is `attributes` +//~| NOTE for more information, visit pub fn foo3(input: TokenStream) -> TokenStream { input } #[proc_macro_derive(d4, attributes(a), b)] //~^ ERROR malformed `proc_macro_derive` attribute //~| NOTE didn't expect any arguments here +//~| NOTE for more information, visit pub fn foo4(input: TokenStream) -> TokenStream { input } #[proc_macro_derive("a")] //~^ ERROR malformed `proc_macro_derive` attribute //~| NOTE didn't expect a literal here +//~| NOTE for more information, visit pub fn foo5(input: TokenStream) -> TokenStream { input } #[proc_macro_derive(d6 = "")] //~^ ERROR malformed `proc_macro_derive` attribute //~| NOTE didn't expect any arguments here +//~| NOTE for more information, visit pub fn foo6(input: TokenStream) -> TokenStream { input } #[proc_macro_derive(m::d7)] //~^ ERROR malformed `proc_macro_derive` attribute //~| NOTE expected a valid identifier here +//~| NOTE for more information, visit pub fn foo7(input: TokenStream) -> TokenStream { input } #[proc_macro_derive(d8(a))] //~^ ERROR malformed `proc_macro_derive` attribute //~| NOTE didn't expect any arguments here +//~| NOTE for more information, visit pub fn foo8(input: TokenStream) -> TokenStream { input } #[proc_macro_derive(self)] //~^ ERROR malformed `proc_macro_derive` attribute //~| NOTE expected a valid identifier here +//~| NOTE for more information, visit pub fn foo9(input: TokenStream) -> TokenStream { input } #[proc_macro_derive(PartialEq)] // OK @@ -57,34 +66,41 @@ pub fn foo10(input: TokenStream) -> TokenStream { input } #[proc_macro_derive(d11, a)] //~^ ERROR malformed `proc_macro_derive` attribute //~| NOTE the only valid argument here is `attributes` +//~| NOTE for more information, visit pub fn foo11(input: TokenStream) -> TokenStream { input } #[proc_macro_derive(d12, attributes)] //~^ ERROR malformed `proc_macro_derive` attribute //~| NOTE expected this to be a list +//~| NOTE for more information, visit pub fn foo12(input: TokenStream) -> TokenStream { input } #[proc_macro_derive(d13, attributes("a"))] //~^ ERROR malformed `proc_macro_derive` attribute //~| NOTE expected a valid identifier here +//~| NOTE for more information, visit pub fn foo13(input: TokenStream) -> TokenStream { input } #[proc_macro_derive(d14, attributes(a = ""))] //~^ ERROR malformed `proc_macro_derive` attribute //~| NOTE didn't expect any arguments here +//~| NOTE for more information, visit pub fn foo14(input: TokenStream) -> TokenStream { input } #[proc_macro_derive(d15, attributes(m::a))] //~^ ERROR malformed `proc_macro_derive` attribute //~| NOTE expected a valid identifier here +//~| NOTE for more information, visit pub fn foo15(input: TokenStream) -> TokenStream { input } #[proc_macro_derive(d16, attributes(a(b)))] //~^ ERROR malformed `proc_macro_derive` attribute //~| NOTE didn't expect any arguments here +//~| NOTE for more information, visit pub fn foo16(input: TokenStream) -> TokenStream { input } #[proc_macro_derive(d17, attributes(self))] //~^ ERROR malformed `proc_macro_derive` attribute //~| NOTE expected a valid identifier here +//~| NOTE for more information, visit pub fn foo17(input: TokenStream) -> TokenStream { input } diff --git a/tests/ui/proc-macro/attribute.stderr b/tests/ui/proc-macro/attribute.stderr index db59a1fdfb3..e7127c8ef1d 100644 --- a/tests/ui/proc-macro/attribute.stderr +++ b/tests/ui/proc-macro/attribute.stderr @@ -2,145 +2,283 @@ error[E0539]: malformed `proc_macro_derive` attribute input --> $DIR/attribute.rs:9:1 | LL | #[proc_macro_derive] - | ^^^^^^^^^^^^^^^^^^^^ - | | - | expected this to be a list - | help: must be of the form: `#[proc_macro_derive(TraitName, /*opt*/ attributes(name1, name2, ...))]` + | ^^^^^^^^^^^^^^^^^^^^ expected this to be a list + | + = note: for more information, visit <https://doc.rust-lang.org/reference/procedural-macros.html#derive-macros> +help: try changing it to one of the following valid forms of the attribute + | +LL | #[proc_macro_derive(TraitName)] + | +++++++++++ +LL | #[proc_macro_derive(TraitName, attributes(name1, name2, ...))] + | ++++++++++++++++++++++++++++++++++++++++++ error[E0539]: malformed `proc_macro_derive` attribute input - --> $DIR/attribute.rs:14:1 + --> $DIR/attribute.rs:15:1 | LL | #[proc_macro_derive = ""] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | | - | expected this to be a list - | help: must be of the form: `#[proc_macro_derive(TraitName, /*opt*/ attributes(name1, name2, ...))]` + | ^^^^^^^^^^^^^^^^^^^^^^^^^ expected this to be a list + | + = note: for more information, visit <https://doc.rust-lang.org/reference/procedural-macros.html#derive-macros> +help: try changing it to one of the following valid forms of the attribute + | +LL - #[proc_macro_derive = ""] +LL + #[proc_macro_derive(TraitName)] + | +LL - #[proc_macro_derive = ""] +LL + #[proc_macro_derive(TraitName, attributes(name1, name2, ...))] + | error[E0539]: malformed `proc_macro_derive` attribute input - --> $DIR/attribute.rs:19:1 + --> $DIR/attribute.rs:21:1 | LL | #[proc_macro_derive(d3, a, b)] | ^^^^^^^^^^^^^^^^^^^^^^^^-^^^^^ - | | | - | | the only valid argument here is `attributes` - | help: must be of the form: `#[proc_macro_derive(TraitName, /*opt*/ attributes(name1, name2, ...))]` + | | + | the only valid argument here is `attributes` + | + = note: for more information, visit <https://doc.rust-lang.org/reference/procedural-macros.html#derive-macros> +help: try changing it to one of the following valid forms of the attribute + | +LL - #[proc_macro_derive(d3, a, b)] +LL + #[proc_macro_derive(TraitName)] + | +LL - #[proc_macro_derive(d3, a, b)] +LL + #[proc_macro_derive(TraitName, attributes(name1, name2, ...))] + | error[E0565]: malformed `proc_macro_derive` attribute input - --> $DIR/attribute.rs:24:1 + --> $DIR/attribute.rs:27:1 | LL | #[proc_macro_derive(d4, attributes(a), b)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-^^ - | | | - | | didn't expect any arguments here - | help: must be of the form: `#[proc_macro_derive(TraitName, /*opt*/ attributes(name1, name2, ...))]` + | | + | didn't expect any arguments here + | + = note: for more information, visit <https://doc.rust-lang.org/reference/procedural-macros.html#derive-macros> +help: try changing it to one of the following valid forms of the attribute + | +LL - #[proc_macro_derive(d4, attributes(a), b)] +LL + #[proc_macro_derive(TraitName)] + | +LL - #[proc_macro_derive(d4, attributes(a), b)] +LL + #[proc_macro_derive(TraitName, attributes(name1, name2, ...))] + | error[E0565]: malformed `proc_macro_derive` attribute input - --> $DIR/attribute.rs:29:1 + --> $DIR/attribute.rs:33:1 | LL | #[proc_macro_derive("a")] | ^^^^^^^^^^^^^^^^^^^^---^^ - | | | - | | didn't expect a literal here - | help: must be of the form: `#[proc_macro_derive(TraitName, /*opt*/ attributes(name1, name2, ...))]` + | | + | didn't expect a literal here + | + = note: for more information, visit <https://doc.rust-lang.org/reference/procedural-macros.html#derive-macros> +help: try changing it to one of the following valid forms of the attribute + | +LL - #[proc_macro_derive("a")] +LL + #[proc_macro_derive(TraitName)] + | +LL - #[proc_macro_derive("a")] +LL + #[proc_macro_derive(TraitName, attributes(name1, name2, ...))] + | error[E0565]: malformed `proc_macro_derive` attribute input - --> $DIR/attribute.rs:34:1 + --> $DIR/attribute.rs:39:1 | LL | #[proc_macro_derive(d6 = "")] | ^^^^^^^^^^^^^^^^^^^^^^^----^^ - | | | - | | didn't expect any arguments here - | help: must be of the form: `#[proc_macro_derive(TraitName, /*opt*/ attributes(name1, name2, ...))]` + | | + | didn't expect any arguments here + | + = note: for more information, visit <https://doc.rust-lang.org/reference/procedural-macros.html#derive-macros> +help: try changing it to one of the following valid forms of the attribute + | +LL - #[proc_macro_derive(d6 = "")] +LL + #[proc_macro_derive(TraitName)] + | +LL - #[proc_macro_derive(d6 = "")] +LL + #[proc_macro_derive(TraitName, attributes(name1, name2, ...))] + | error[E0539]: malformed `proc_macro_derive` attribute input - --> $DIR/attribute.rs:39:1 + --> $DIR/attribute.rs:45:1 | LL | #[proc_macro_derive(m::d7)] | ^^^^^^^^^^^^^^^^^^^^-----^^ - | | | - | | expected a valid identifier here - | help: must be of the form: `#[proc_macro_derive(TraitName, /*opt*/ attributes(name1, name2, ...))]` + | | + | expected a valid identifier here + | + = note: for more information, visit <https://doc.rust-lang.org/reference/procedural-macros.html#derive-macros> +help: try changing it to one of the following valid forms of the attribute + | +LL - #[proc_macro_derive(m::d7)] +LL + #[proc_macro_derive(TraitName)] + | +LL - #[proc_macro_derive(m::d7)] +LL + #[proc_macro_derive(TraitName, attributes(name1, name2, ...))] + | error[E0565]: malformed `proc_macro_derive` attribute input - --> $DIR/attribute.rs:44:1 + --> $DIR/attribute.rs:51:1 | LL | #[proc_macro_derive(d8(a))] | ^^^^^^^^^^^^^^^^^^^^^^---^^ - | | | - | | didn't expect any arguments here - | help: must be of the form: `#[proc_macro_derive(TraitName, /*opt*/ attributes(name1, name2, ...))]` + | | + | didn't expect any arguments here + | + = note: for more information, visit <https://doc.rust-lang.org/reference/procedural-macros.html#derive-macros> +help: try changing it to one of the following valid forms of the attribute + | +LL - #[proc_macro_derive(d8(a))] +LL + #[proc_macro_derive(TraitName)] + | +LL - #[proc_macro_derive(d8(a))] +LL + #[proc_macro_derive(TraitName, attributes(name1, name2, ...))] + | error[E0539]: malformed `proc_macro_derive` attribute input - --> $DIR/attribute.rs:49:1 + --> $DIR/attribute.rs:57:1 | LL | #[proc_macro_derive(self)] | ^^^^^^^^^^^^^^^^^^^^----^^ - | | | - | | expected a valid identifier here - | help: must be of the form: `#[proc_macro_derive(TraitName, /*opt*/ attributes(name1, name2, ...))]` + | | + | expected a valid identifier here + | + = note: for more information, visit <https://doc.rust-lang.org/reference/procedural-macros.html#derive-macros> +help: try changing it to one of the following valid forms of the attribute + | +LL - #[proc_macro_derive(self)] +LL + #[proc_macro_derive(TraitName)] + | +LL - #[proc_macro_derive(self)] +LL + #[proc_macro_derive(TraitName, attributes(name1, name2, ...))] + | error[E0539]: malformed `proc_macro_derive` attribute input - --> $DIR/attribute.rs:57:1 + --> $DIR/attribute.rs:66:1 | LL | #[proc_macro_derive(d11, a)] | ^^^^^^^^^^^^^^^^^^^^^^^^^-^^ - | | | - | | the only valid argument here is `attributes` - | help: must be of the form: `#[proc_macro_derive(TraitName, /*opt*/ attributes(name1, name2, ...))]` + | | + | the only valid argument here is `attributes` + | + = note: for more information, visit <https://doc.rust-lang.org/reference/procedural-macros.html#derive-macros> +help: try changing it to one of the following valid forms of the attribute + | +LL - #[proc_macro_derive(d11, a)] +LL + #[proc_macro_derive(TraitName)] + | +LL - #[proc_macro_derive(d11, a)] +LL + #[proc_macro_derive(TraitName, attributes(name1, name2, ...))] + | error[E0539]: malformed `proc_macro_derive` attribute input - --> $DIR/attribute.rs:62:1 + --> $DIR/attribute.rs:72:1 | LL | #[proc_macro_derive(d12, attributes)] | ^^^^^^^^^^^^^^^^^^^^^^^^^----------^^ - | | | - | | expected this to be a list - | help: must be of the form: `#[proc_macro_derive(TraitName, /*opt*/ attributes(name1, name2, ...))]` + | | + | expected this to be a list + | + = note: for more information, visit <https://doc.rust-lang.org/reference/procedural-macros.html#derive-macros> +help: try changing it to one of the following valid forms of the attribute + | +LL - #[proc_macro_derive(d12, attributes)] +LL + #[proc_macro_derive(TraitName)] + | +LL - #[proc_macro_derive(d12, attributes)] +LL + #[proc_macro_derive(TraitName, attributes(name1, name2, ...))] + | error[E0539]: malformed `proc_macro_derive` attribute input - --> $DIR/attribute.rs:67:1 + --> $DIR/attribute.rs:78:1 | LL | #[proc_macro_derive(d13, attributes("a"))] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---^^^ - | | | - | | expected a valid identifier here - | help: must be of the form: `#[proc_macro_derive(TraitName, /*opt*/ attributes(name1, name2, ...))]` + | | + | expected a valid identifier here + | + = note: for more information, visit <https://doc.rust-lang.org/reference/procedural-macros.html#derive-macros> +help: try changing it to one of the following valid forms of the attribute + | +LL - #[proc_macro_derive(d13, attributes("a"))] +LL + #[proc_macro_derive(TraitName)] + | +LL - #[proc_macro_derive(d13, attributes("a"))] +LL + #[proc_macro_derive(TraitName, attributes(name1, name2, ...))] + | error[E0565]: malformed `proc_macro_derive` attribute input - --> $DIR/attribute.rs:72:1 + --> $DIR/attribute.rs:84:1 | LL | #[proc_macro_derive(d14, attributes(a = ""))] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^----^^^ - | | | - | | didn't expect any arguments here - | help: must be of the form: `#[proc_macro_derive(TraitName, /*opt*/ attributes(name1, name2, ...))]` + | | + | didn't expect any arguments here + | + = note: for more information, visit <https://doc.rust-lang.org/reference/procedural-macros.html#derive-macros> +help: try changing it to one of the following valid forms of the attribute + | +LL - #[proc_macro_derive(d14, attributes(a = ""))] +LL + #[proc_macro_derive(TraitName)] + | +LL - #[proc_macro_derive(d14, attributes(a = ""))] +LL + #[proc_macro_derive(TraitName, attributes(name1, name2, ...))] + | error[E0539]: malformed `proc_macro_derive` attribute input - --> $DIR/attribute.rs:77:1 + --> $DIR/attribute.rs:90:1 | LL | #[proc_macro_derive(d15, attributes(m::a))] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^----^^^ - | | | - | | expected a valid identifier here - | help: must be of the form: `#[proc_macro_derive(TraitName, /*opt*/ attributes(name1, name2, ...))]` + | | + | expected a valid identifier here + | + = note: for more information, visit <https://doc.rust-lang.org/reference/procedural-macros.html#derive-macros> +help: try changing it to one of the following valid forms of the attribute + | +LL - #[proc_macro_derive(d15, attributes(m::a))] +LL + #[proc_macro_derive(TraitName)] + | +LL - #[proc_macro_derive(d15, attributes(m::a))] +LL + #[proc_macro_derive(TraitName, attributes(name1, name2, ...))] + | error[E0565]: malformed `proc_macro_derive` attribute input - --> $DIR/attribute.rs:82:1 + --> $DIR/attribute.rs:96:1 | LL | #[proc_macro_derive(d16, attributes(a(b)))] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---^^^ - | | | - | | didn't expect any arguments here - | help: must be of the form: `#[proc_macro_derive(TraitName, /*opt*/ attributes(name1, name2, ...))]` + | | + | didn't expect any arguments here + | + = note: for more information, visit <https://doc.rust-lang.org/reference/procedural-macros.html#derive-macros> +help: try changing it to one of the following valid forms of the attribute + | +LL - #[proc_macro_derive(d16, attributes(a(b)))] +LL + #[proc_macro_derive(TraitName)] + | +LL - #[proc_macro_derive(d16, attributes(a(b)))] +LL + #[proc_macro_derive(TraitName, attributes(name1, name2, ...))] + | error[E0539]: malformed `proc_macro_derive` attribute input - --> $DIR/attribute.rs:87:1 + --> $DIR/attribute.rs:102:1 | LL | #[proc_macro_derive(d17, attributes(self))] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^----^^^ - | | | - | | expected a valid identifier here - | help: must be of the form: `#[proc_macro_derive(TraitName, /*opt*/ attributes(name1, name2, ...))]` + | | + | expected a valid identifier here + | + = note: for more information, visit <https://doc.rust-lang.org/reference/procedural-macros.html#derive-macros> +help: try changing it to one of the following valid forms of the attribute + | +LL - #[proc_macro_derive(d17, attributes(self))] +LL + #[proc_macro_derive(TraitName)] + | +LL - #[proc_macro_derive(d17, attributes(self))] +LL + #[proc_macro_derive(TraitName, attributes(name1, name2, ...))] + | error: aborting due to 16 previous errors diff --git a/tests/ui/recursion_limit/invalid_digit_type.stderr b/tests/ui/recursion_limit/invalid_digit_type.stderr index 94442b5747f..a122262f1df 100644 --- a/tests/ui/recursion_limit/invalid_digit_type.stderr +++ b/tests/ui/recursion_limit/invalid_digit_type.stderr @@ -3,6 +3,8 @@ error: malformed `recursion_limit` attribute input | LL | #![recursion_limit = 123] | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#![recursion_limit = "N"]` + | + = note: for more information, visit <https://doc.rust-lang.org/reference/attributes/limits.html#the-recursion_limit-attribute> error: aborting due to 1 previous error diff --git a/tests/ui/recursion_limit/invalid_macro.stderr b/tests/ui/recursion_limit/invalid_macro.stderr index aa4894ec4d8..b4dbc9fcb13 100644 --- a/tests/ui/recursion_limit/invalid_macro.stderr +++ b/tests/ui/recursion_limit/invalid_macro.stderr @@ -3,6 +3,8 @@ error: malformed `recursion_limit` attribute input | LL | #![recursion_limit = foo!()] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#![recursion_limit = "N"]` + | + = note: for more information, visit <https://doc.rust-lang.org/reference/attributes/limits.html#the-recursion_limit-attribute> error: aborting due to 1 previous error diff --git a/tests/ui/recursion_limit/no-value.stderr b/tests/ui/recursion_limit/no-value.stderr index b2e8c46c372..4a0ad04f271 100644 --- a/tests/ui/recursion_limit/no-value.stderr +++ b/tests/ui/recursion_limit/no-value.stderr @@ -3,6 +3,8 @@ error: malformed `recursion_limit` attribute input | LL | #![recursion_limit] | ^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#![recursion_limit = "N"]` + | + = note: for more information, visit <https://doc.rust-lang.org/reference/attributes/limits.html#the-recursion_limit-attribute> error: aborting due to 1 previous error diff --git a/tests/ui/repr/invalid_repr_list_help.stderr b/tests/ui/repr/invalid_repr_list_help.stderr index 763ad9c2795..f9d1593275e 100644 --- a/tests/ui/repr/invalid_repr_list_help.stderr +++ b/tests/ui/repr/invalid_repr_list_help.stderr @@ -5,6 +5,7 @@ LL | #[repr(uwu)] | ^^^ | = help: valid reprs are `Rust` (default), `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize` + = note: for more information, visit <https://doc.rust-lang.org/reference/type-layout.html?highlight=repr#representations> error[E0552]: unrecognized representation hint --> $DIR/invalid_repr_list_help.rs:6:8 @@ -13,6 +14,7 @@ LL | #[repr(uwu = "a")] | ^^^^^^^^^ | = help: valid reprs are `Rust` (default), `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize` + = note: for more information, visit <https://doc.rust-lang.org/reference/type-layout.html?highlight=repr#representations> error[E0552]: unrecognized representation hint --> $DIR/invalid_repr_list_help.rs:9:8 @@ -21,6 +23,7 @@ LL | #[repr(uwu(4))] | ^^^^^^ | = help: valid reprs are `Rust` (default), `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize` + = note: for more information, visit <https://doc.rust-lang.org/reference/type-layout.html?highlight=repr#representations> error[E0552]: unrecognized representation hint --> $DIR/invalid_repr_list_help.rs:14:8 @@ -29,6 +32,7 @@ LL | #[repr(uwu, u8)] | ^^^ | = help: valid reprs are `Rust` (default), `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize` + = note: for more information, visit <https://doc.rust-lang.org/reference/type-layout.html?highlight=repr#representations> error[E0552]: unrecognized representation hint --> $DIR/invalid_repr_list_help.rs:19:8 @@ -37,6 +41,7 @@ LL | #[repr(uwu)] | ^^^ | = help: valid reprs are `Rust` (default), `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize` + = note: for more information, visit <https://doc.rust-lang.org/reference/type-layout.html?highlight=repr#representations> error: unknown `doc` attribute `owo` --> $DIR/invalid_repr_list_help.rs:20:7 diff --git a/tests/ui/repr/repr.stderr b/tests/ui/repr/repr.stderr index 9e581332278..d4faea12517 100644 --- a/tests/ui/repr/repr.stderr +++ b/tests/ui/repr/repr.stderr @@ -2,28 +2,66 @@ error[E0539]: malformed `repr` attribute input --> $DIR/repr.rs:1:1 | LL | #[repr] - | ^^^^^^^ - | | - | expected this to be a list - | help: must be of the form: `#[repr(C | Rust | align(...) | packed(...) | <integer type> | transparent)]` + | ^^^^^^^ expected this to be a list + | + = note: for more information, visit <https://doc.rust-lang.org/reference/type-layout.html#representations> +help: try changing it to one of the following valid forms of the attribute + | +LL | #[repr(<integer type>)] + | ++++++++++++++++ +LL | #[repr(C)] + | +++ +LL | #[repr(Rust)] + | ++++++ +LL | #[repr(align(...))] + | ++++++++++++ + = and 2 other candidates error[E0539]: malformed `repr` attribute input --> $DIR/repr.rs:4:1 | LL | #[repr = "B"] - | ^^^^^^^^^^^^^ - | | - | expected this to be a list - | help: must be of the form: `#[repr(C | Rust | align(...) | packed(...) | <integer type> | transparent)]` + | ^^^^^^^^^^^^^ expected this to be a list + | + = note: for more information, visit <https://doc.rust-lang.org/reference/type-layout.html#representations> +help: try changing it to one of the following valid forms of the attribute + | +LL - #[repr = "B"] +LL + #[repr(<integer type>)] + | +LL - #[repr = "B"] +LL + #[repr(C)] + | +LL - #[repr = "B"] +LL + #[repr(Rust)] + | +LL - #[repr = "B"] +LL + #[repr(align(...))] + | + = and 2 other candidates error[E0539]: malformed `repr` attribute input --> $DIR/repr.rs:7:1 | LL | #[repr = "C"] - | ^^^^^^^^^^^^^ - | | - | expected this to be a list - | help: must be of the form: `#[repr(C | Rust | align(...) | packed(...) | <integer type> | transparent)]` + | ^^^^^^^^^^^^^ expected this to be a list + | + = note: for more information, visit <https://doc.rust-lang.org/reference/type-layout.html#representations> +help: try changing it to one of the following valid forms of the attribute + | +LL - #[repr = "C"] +LL + #[repr(<integer type>)] + | +LL - #[repr = "C"] +LL + #[repr(C)] + | +LL - #[repr = "C"] +LL + #[repr(Rust)] + | +LL - #[repr = "C"] +LL + #[repr(align(...))] + | + = and 2 other candidates error: aborting due to 3 previous errors diff --git a/tests/ui/resolve/path-attr-in-const-block.stderr b/tests/ui/resolve/path-attr-in-const-block.stderr index 0b5942a287d..f3ae5b60c4f 100644 --- a/tests/ui/resolve/path-attr-in-const-block.stderr +++ b/tests/ui/resolve/path-attr-in-const-block.stderr @@ -12,6 +12,8 @@ LL | #![path = foo!()] | | | | | expected a string literal here | help: must be of the form: `#[path = "file"]` + | + = note: for more information, visit <https://doc.rust-lang.org/reference/items/modules.html#the-path-attribute> error: aborting due to 2 previous errors diff --git a/tests/ui/span/E0539.stderr b/tests/ui/span/E0539.stderr index 01f091a2676..34d81b73cb5 100644 --- a/tests/ui/span/E0539.stderr +++ b/tests/ui/span/E0539.stderr @@ -6,10 +6,14 @@ LL | #[inline(unknown)] | | | valid arguments are `always` or `never` | + = 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 - #[inline(unknown)] -LL + #[inline(always|never)] +LL + #[inline(always)] + | +LL - #[inline(unknown)] +LL + #[inline(never)] | LL - #[inline(unknown)] LL + #[inline] diff --git a/tests/ui/specialization/defaultimpl/validation.rs b/tests/ui/specialization/defaultimpl/validation.rs index 14771be8982..78f6099c3dd 100644 --- a/tests/ui/specialization/defaultimpl/validation.rs +++ b/tests/ui/specialization/defaultimpl/validation.rs @@ -4,7 +4,7 @@ struct S; struct Z; -default impl S {} //~ ERROR inherent impls cannot be `default` +default impl S {} //~ ERROR inherent impls cannot be default default unsafe impl Send for S {} //~^ ERROR impls of auto traits cannot be default diff --git a/tests/ui/specialization/defaultimpl/validation.stderr b/tests/ui/specialization/defaultimpl/validation.stderr index 82a33bf9cdc..a8dfef2dcfb 100644 --- a/tests/ui/specialization/defaultimpl/validation.stderr +++ b/tests/ui/specialization/defaultimpl/validation.stderr @@ -1,10 +1,10 @@ -error: inherent impls cannot be `default` +error: inherent impls cannot be default --> $DIR/validation.rs:7:14 | LL | default impl S {} | ------- ^ inherent impl for this type | | - | `default` because of this + | default because of this | = note: only trait implementations may be annotated with `default` diff --git a/tests/ui/test-attrs/test-should-panic-attr.rs b/tests/ui/test-attrs/test-should-panic-attr.rs index af54689551c..e6de07d0094 100644 --- a/tests/ui/test-attrs/test-should-panic-attr.rs +++ b/tests/ui/test-attrs/test-should-panic-attr.rs @@ -10,6 +10,7 @@ fn test1() { #[should_panic(expected)] //~^ ERROR malformed `should_panic` attribute input //~| NOTE expected this to be of the form `expected = "..."` +//~| NOTE for more information, visit fn test2() { panic!(); } @@ -18,6 +19,7 @@ fn test2() { #[should_panic(expect)] //~^ ERROR malformed `should_panic` attribute input //~| NOTE the only valid argument here is "expected" +//~| NOTE for more information, visit fn test3() { panic!(); } @@ -26,6 +28,7 @@ fn test3() { #[should_panic(expected(foo, bar))] //~^ ERROR malformed `should_panic` attribute input //~| NOTE expected this to be of the form `expected = "..."` +//~| NOTE for more information, visit fn test4() { panic!(); } @@ -34,6 +37,7 @@ fn test4() { #[should_panic(expected = "foo", bar)] //~^ ERROR malformed `should_panic` attribute input //~| NOTE expected a single argument here +//~| NOTE for more information, visit fn test5() { panic!(); } diff --git a/tests/ui/test-attrs/test-should-panic-attr.stderr b/tests/ui/test-attrs/test-should-panic-attr.stderr index 5dfc8e503e8..475a55ad0cb 100644 --- a/tests/ui/test-attrs/test-should-panic-attr.stderr +++ b/tests/ui/test-attrs/test-should-panic-attr.stderr @@ -6,6 +6,7 @@ LL | #[should_panic(expected)] | | | expected this to be of the form `expected = "..."` | + = note: for more information, visit <https://doc.rust-lang.org/reference/attributes/testing.html#the-should_panic-attribute> help: try changing it to one of the following valid forms of the attribute | LL - #[should_panic(expected)] @@ -18,13 +19,14 @@ LL + #[should_panic] | error[E0539]: malformed `should_panic` attribute input - --> $DIR/test-should-panic-attr.rs:18:1 + --> $DIR/test-should-panic-attr.rs:19:1 | LL | #[should_panic(expect)] | ^^^^^^^^^^^^^^--------^ | | | the only valid argument here is "expected" | + = note: for more information, visit <https://doc.rust-lang.org/reference/attributes/testing.html#the-should_panic-attribute> help: try changing it to one of the following valid forms of the attribute | LL - #[should_panic(expect)] @@ -37,13 +39,14 @@ LL + #[should_panic] | error[E0539]: malformed `should_panic` attribute input - --> $DIR/test-should-panic-attr.rs:26:1 + --> $DIR/test-should-panic-attr.rs:28:1 | LL | #[should_panic(expected(foo, bar))] | ^^^^^^^^^^^^^^^------------------^^ | | | expected this to be of the form `expected = "..."` | + = note: for more information, visit <https://doc.rust-lang.org/reference/attributes/testing.html#the-should_panic-attribute> help: try changing it to one of the following valid forms of the attribute | LL - #[should_panic(expected(foo, bar))] @@ -57,13 +60,14 @@ LL + #[should_panic] | error[E0805]: malformed `should_panic` attribute input - --> $DIR/test-should-panic-attr.rs:34:1 + --> $DIR/test-should-panic-attr.rs:37:1 | LL | #[should_panic(expected = "foo", bar)] | ^^^^^^^^^^^^^^-----------------------^ | | | expected a single argument here | + = note: for more information, visit <https://doc.rust-lang.org/reference/attributes/testing.html#the-should_panic-attribute> help: try changing it to one of the following valid forms of the attribute | LL - #[should_panic(expected = "foo", bar)] diff --git a/tests/ui/traits/const-traits/inherent-impl.rs b/tests/ui/traits/const-traits/inherent-impl.rs index 07b23adf9e1..5ca4c5d7863 100644 --- a/tests/ui/traits/const-traits/inherent-impl.rs +++ b/tests/ui/traits/const-traits/inherent-impl.rs @@ -5,9 +5,9 @@ struct S; trait T {} impl const S {} -//~^ ERROR inherent impls cannot be `const` +//~^ ERROR inherent impls cannot be const impl const dyn T {} -//~^ ERROR inherent impls cannot be `const` +//~^ ERROR inherent impls cannot be const fn main() {} diff --git a/tests/ui/traits/const-traits/inherent-impl.stderr b/tests/ui/traits/const-traits/inherent-impl.stderr index e4ec1e807b0..d828ecb6349 100644 --- a/tests/ui/traits/const-traits/inherent-impl.stderr +++ b/tests/ui/traits/const-traits/inherent-impl.stderr @@ -1,20 +1,20 @@ -error: inherent impls cannot be `const` +error: inherent impls cannot be const --> $DIR/inherent-impl.rs:7:12 | LL | impl const S {} | ----- ^ inherent impl for this type | | - | `const` because of this + | const because of this | = note: only trait implementations may be annotated with `const` -error: inherent impls cannot be `const` +error: inherent impls cannot be const --> $DIR/inherent-impl.rs:10:12 | LL | impl const dyn T {} | ----- ^^^^^ inherent impl for this type | | - | `const` because of this + | const because of this | = note: only trait implementations may be annotated with `const` diff --git a/tests/ui/traits/const-traits/macro-const-trait-bound-theoretical-regression.stderr b/tests/ui/traits/const-traits/macro-const-trait-bound-theoretical-regression.stderr index af160a45f3e..9fad260f0be 100644 --- a/tests/ui/traits/const-traits/macro-const-trait-bound-theoretical-regression.stderr +++ b/tests/ui/traits/const-traits/macro-const-trait-bound-theoretical-regression.stderr @@ -1,15 +1,4 @@ -error: macro expansion ignores keyword `dyn` and any tokens following - --> $DIR/macro-const-trait-bound-theoretical-regression.rs:14:31 - | -LL | (dyn $c:ident Trait) => { dyn $c Trait {} }; - | ^^^ -... -LL | demo! { dyn const Trait } - | ------------------------- caused by the macro expansion here - | - = note: the usage of `demo!` is likely invalid in item context - -error: inherent impls cannot be `const` +error: inherent impls cannot be const --> $DIR/macro-const-trait-bound-theoretical-regression.rs:10:40 | LL | (impl $c:ident Trait) => { impl $c Trait {} }; @@ -18,12 +7,23 @@ LL | (impl $c:ident Trait) => { impl $c Trait {} }; LL | demo! { impl const Trait } | -------------------------- | | | - | | `const` because of this + | | const because of this | in this macro invocation | = note: only trait implementations may be annotated with `const` = note: this error originates in the macro `demo` (in Nightly builds, run with -Z macro-backtrace for more info) +error: macro expansion ignores keyword `dyn` and any tokens following + --> $DIR/macro-const-trait-bound-theoretical-regression.rs:14:31 + | +LL | (dyn $c:ident Trait) => { dyn $c Trait {} }; + | ^^^ +... +LL | demo! { dyn const Trait } + | ------------------------- caused by the macro expansion here + | + = note: the usage of `demo!` is likely invalid in item context + error[E0658]: const trait impls are experimental --> $DIR/macro-const-trait-bound-theoretical-regression.rs:17:14 | diff --git a/tests/ui/traits/const-traits/span-bug-issue-121418.rs b/tests/ui/traits/const-traits/span-bug-issue-121418.rs index 50a7e12f2a7..593180ac094 100644 --- a/tests/ui/traits/const-traits/span-bug-issue-121418.rs +++ b/tests/ui/traits/const-traits/span-bug-issue-121418.rs @@ -4,7 +4,7 @@ struct S; trait T {} impl const dyn T { - //~^ ERROR inherent impls cannot be `const` + //~^ ERROR inherent impls cannot be const pub const fn new() -> std::sync::Mutex<dyn T> {} //~^ ERROR mismatched types //~| ERROR cannot be known at compilation time diff --git a/tests/ui/traits/const-traits/span-bug-issue-121418.stderr b/tests/ui/traits/const-traits/span-bug-issue-121418.stderr index f31129d9cb7..0c8ca918a3e 100644 --- a/tests/ui/traits/const-traits/span-bug-issue-121418.stderr +++ b/tests/ui/traits/const-traits/span-bug-issue-121418.stderr @@ -1,10 +1,10 @@ -error: inherent impls cannot be `const` +error: inherent impls cannot be const --> $DIR/span-bug-issue-121418.rs:6:12 | LL | impl const dyn T { | ----- ^^^^^ inherent impl for this type | | - | `const` because of this + | const because of this | = note: only trait implementations may be annotated with `const` diff --git a/tests/ui/traits/safety-inherent-impl.stderr b/tests/ui/traits/safety-inherent-impl.stderr index 2513fef909e..45cdbe2b523 100644 --- a/tests/ui/traits/safety-inherent-impl.stderr +++ b/tests/ui/traits/safety-inherent-impl.stderr @@ -5,6 +5,8 @@ LL | unsafe impl SomeStruct { | ------ ^^^^^^^^^^ inherent impl for this type | | | unsafe because of this + | + = note: only trait implementations may be annotated with `unsafe` error: aborting due to 1 previous error diff --git a/tests/ui/traits/syntax-trait-polarity.stderr b/tests/ui/traits/syntax-trait-polarity.stderr index 1fd40fb6657..8ffcdc7d8b5 100644 --- a/tests/ui/traits/syntax-trait-polarity.stderr +++ b/tests/ui/traits/syntax-trait-polarity.stderr @@ -5,15 +5,8 @@ LL | impl !TestType {} | -^^^^^^^^ inherent impl for this type | | | negative because of this - -error[E0198]: negative impls cannot be unsafe - --> $DIR/syntax-trait-polarity.rs:12:13 | -LL | unsafe impl !Send for TestType {} - | ------ -^^^^ - | | | - | | negative because of this - | unsafe because of this + = note: only trait implementations may be annotated with `!` error: inherent impls cannot be negative --> $DIR/syntax-trait-polarity.rs:18:10 @@ -22,6 +15,17 @@ LL | impl<T> !TestType2<T> {} | -^^^^^^^^^^^^ inherent impl for this type | | | negative because of this + | + = note: only trait implementations may be annotated with `!` + +error[E0198]: negative impls cannot be unsafe + --> $DIR/syntax-trait-polarity.rs:12:13 + | +LL | unsafe impl !Send for TestType {} + | ------ -^^^^ + | | | + | | negative because of this + | unsafe because of this error[E0198]: negative impls cannot be unsafe --> $DIR/syntax-trait-polarity.rs:21:16 diff --git a/tests/ui/unpretty/exhaustive.hir.stdout b/tests/ui/unpretty/exhaustive.hir.stdout index 9cfa65f5801..e9823c9575b 100644 --- a/tests/ui/unpretty/exhaustive.hir.stdout +++ b/tests/ui/unpretty/exhaustive.hir.stdout @@ -509,7 +509,7 @@ mod items { impl () { } impl <T> () { } impl Default for () { } - impl const <T> Default for () { } + impl <T> const Default for () { } } /// ItemKind::MacCall mod item_mac_call { } diff --git a/tests/ui/unstable-feature-bound/unstable_feature_bound_on_trait.fail.stderr b/tests/ui/unstable-feature-bound/unstable_feature_bound_on_trait.fail.stderr new file mode 100644 index 00000000000..69be101a40d --- /dev/null +++ b/tests/ui/unstable-feature-bound/unstable_feature_bound_on_trait.fail.stderr @@ -0,0 +1,18 @@ +error: unstable feature `foo` is used without being enabled. + --> $DIR/unstable_feature_bound_on_trait.rs:28:5 + | +LL | Foo::bar(); + | ^^^^^^^^^^ + | + = help: The feature can be enabled by marking the current item with `#[unstable_feature_bound(foo)]` +note: required by a bound in `Bar::bar` + --> $DIR/unstable_feature_bound_on_trait.rs:16:1 + | +LL | #[unstable_feature_bound(foo)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Bar::bar` +... +LL | fn bar() {} + | --- required by a bound in this associated function + +error: aborting due to 1 previous error + diff --git a/tests/ui/unstable-feature-bound/unstable_feature_bound_on_trait.rs b/tests/ui/unstable-feature-bound/unstable_feature_bound_on_trait.rs new file mode 100644 index 00000000000..0ee00d5e7fb --- /dev/null +++ b/tests/ui/unstable-feature-bound/unstable_feature_bound_on_trait.rs @@ -0,0 +1,33 @@ +//@ revisions: pass fail +//@[pass] check-pass + +#![allow(internal_features)] +#![feature(staged_api)] +#![stable(feature = "a", since = "1.1.1" )] + +/// Test the behaviour of marking a trait with #[unstable_feature_bound]. +/// In this testcase, even though the trait method `bar` and the `struct Foo` are +/// both stable, #[unstable_feature_bound] is still needed at the call site of Foo::bar(). + +#[stable(feature = "a", since = "1.1.1" )] +struct Foo; + +#[unstable(feature = "foo", issue = "none" )] +#[unstable_feature_bound(foo)] +trait Bar { + #[stable(feature = "a", since = "1.1.1" )] + fn bar() {} +} + +#[unstable_feature_bound(foo)] +impl Bar for Foo { +} + +#[cfg_attr(pass, unstable_feature_bound(foo))] +fn moo() { + Foo::bar(); + //[fail]~^ ERROR: unstable feature `foo` is used without being enabled. +} + + +fn main() {} diff --git a/tests/ui/unstable-feature-bound/unstable_inherent_method.rs b/tests/ui/unstable-feature-bound/unstable_inherent_method.rs index 5f3095430a8..0d6e4ebb408 100644 --- a/tests/ui/unstable-feature-bound/unstable_inherent_method.rs +++ b/tests/ui/unstable-feature-bound/unstable_inherent_method.rs @@ -9,14 +9,14 @@ pub trait Trait { #[unstable(feature = "feat", issue = "none" )] #[unstable_feature_bound(foo)] - //~^ ERROR: attribute should be applied to `impl` or free function outside of any `impl` or trait + //~^ ERROR: attribute should be applied to `impl`, trait or free function fn foo(); } #[stable(feature = "a", since = "1.1.1" )] impl Trait for u8 { #[unstable_feature_bound(foo)] - //~^ ERROR: attribute should be applied to `impl` or free function outside of any `impl` or trait + //~^ ERROR: attribute should be applied to `impl`, trait or free function fn foo() {} } diff --git a/tests/ui/unstable-feature-bound/unstable_inherent_method.stderr b/tests/ui/unstable-feature-bound/unstable_inherent_method.stderr index fa1c39db259..90cbb32df7c 100644 --- a/tests/ui/unstable-feature-bound/unstable_inherent_method.stderr +++ b/tests/ui/unstable-feature-bound/unstable_inherent_method.stderr @@ -1,20 +1,20 @@ -error: attribute should be applied to `impl` or free function outside of any `impl` or trait +error: attribute should be applied to `impl`, trait or free function --> $DIR/unstable_inherent_method.rs:11:5 | LL | #[unstable_feature_bound(foo)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ LL | LL | fn foo(); - | --------- not an `impl` or free function + | --------- not an `impl`, trait or free function -error: attribute should be applied to `impl` or free function outside of any `impl` or trait +error: attribute should be applied to `impl`, trait or free function --> $DIR/unstable_inherent_method.rs:18:5 | LL | #[unstable_feature_bound(foo)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ LL | LL | fn foo() {} - | ----------- not an `impl` or free function + | ----------- not an `impl`, trait or free function error: aborting due to 2 previous errors diff --git a/triagebot.toml b/triagebot.toml index 71f1ed0fda3..6f6e95c5b50 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -207,6 +207,7 @@ trigger_labels = [ "regression-from-stable-to-beta", "regression-from-stable-to-nightly", "I-unsound", + "I-miscompile", ] exclude_labels = [ "P-*", |
