From ef05f9e2881c889197e54ce10dde355daeef3988 Mon Sep 17 00:00:00 2001 From: Cameron Steffen Date: Wed, 30 Jul 2025 16:13:22 -0500 Subject: [PATCH 1/5] Factor out InherentImplCannotUnsafe --- .../rustc_ast_passes/src/ast_validation.rs | 18 +++++++++++------- compiler/rustc_ast_passes/src/errors.rs | 12 ------------ tests/ui/error-codes/E0197.stderr | 2 ++ tests/ui/traits/safety-inherent-impl.stderr | 2 ++ 4 files changed, 15 insertions(+), 19 deletions(-) diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 895a457ec1d56..e1f01b6ca14bb 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -27,7 +27,7 @@ use rustc_ast::visit::{AssocCtxt, BoundKind, FnCtxt, FnKind, Visitor, walk_list} use rustc_ast::*; use rustc_ast_pretty::pprust::{self, State}; use rustc_data_structures::fx::FxIndexMap; -use rustc_errors::DiagCtxtHandle; +use rustc_errors::{DiagCtxtHandle, E0197}; use rustc_feature::Features; use rustc_parse::validate_attr; use rustc_session::Session; @@ -1013,12 +1013,16 @@ impl<'a> Visitor<'a> for AstValidator<'a> { 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, - }); + self.dcx() + .create_err(errors::InherentImplCannot { + span: self_ty.span, + annotation_span: span, + annotation: "unsafe", + self_ty: self_ty.span, + only_trait: true, + }) + .with_code(E0197) + .emit(); } if let &ImplPolarity::Negative(span) = polarity { self.dcx().emit_err(error(span, "negative", false)); diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs index fd4b2528541e3..6e4affc46c172 100644 --- a/compiler/rustc_ast_passes/src/errors.rs +++ b/compiler/rustc_ast_passes/src/errors.rs @@ -477,18 +477,6 @@ pub(crate) struct InherentImplCannot<'a> { 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 { diff --git a/tests/ui/error-codes/E0197.stderr b/tests/ui/error-codes/E0197.stderr index c06777396e87e..e3d3c7dde9c35 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/traits/safety-inherent-impl.stderr b/tests/ui/traits/safety-inherent-impl.stderr index 2513fef909ef1..f4443857dc929 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 From 1ee8579b4f95e3faeb0ba8065925f34d024c99e7 Mon Sep 17 00:00:00 2001 From: Cameron Steffen Date: Wed, 30 Jul 2025 16:33:59 -0500 Subject: [PATCH 2/5] Move trait impl modifier errors to parsing This is a technically a breaking change for what can be parsed in `#[cfg(false)]`. --- compiler/rustc_ast_passes/messages.ftl | 5 --- .../rustc_ast_passes/src/ast_validation.rs | 39 +++-------------- compiler/rustc_ast_passes/src/errors.rs | 14 ------- compiler/rustc_parse/messages.ftl | 5 +++ compiler/rustc_parse/src/errors.rs | 14 +++++++ compiler/rustc_parse/src/parser/item.rs | 36 +++++++++++++++- tests/ui/parser/default-on-wrong-item-kind.rs | 8 ++-- .../parser/default-on-wrong-item-kind.stderr | 42 ++++++++++++++++++- ...-trait-bound-theoretical-regression.stderr | 22 +++++----- tests/ui/traits/syntax-trait-polarity.stderr | 16 +++---- 10 files changed, 123 insertions(+), 78 deletions(-) diff --git a/compiler/rustc_ast_passes/messages.ftl b/compiler/rustc_ast_passes/messages.ftl index af93d55c89826..34d06493b928f 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 e1f01b6ca14bb..b6c643b8fbc11 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -27,7 +27,7 @@ use rustc_ast::visit::{AssocCtxt, BoundKind, FnCtxt, FnKind, Visitor, walk_list} use rustc_ast::*; use rustc_ast_pretty::pprust::{self, State}; use rustc_data_structures::fx::FxIndexMap; -use rustc_errors::{DiagCtxtHandle, E0197}; +use rustc_errors::DiagCtxtHandle; use rustc_feature::Features; use rustc_parse::validate_attr; use rustc_session::Session; @@ -990,49 +990,20 @@ impl<'a> Visitor<'a> for AstValidator<'a> { }); } ItemKind::Impl(box Impl { - safety, - polarity, - defaultness, - constness, + 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, - }; - 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() - .create_err(errors::InherentImplCannot { - span: self_ty.span, - annotation_span: span, - annotation: "unsafe", - self_ty: self_ty.span, - only_trait: true, - }) - .with_code(E0197) - .emit(); - } - 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 6e4affc46c172..da59010f31a7a 100644 --- a/compiler/rustc_ast_passes/src/errors.rs +++ b/compiler/rustc_ast_passes/src/errors.rs @@ -463,20 +463,6 @@ pub(crate) struct UnsafeNegativeImpl { pub r#unsafe: Span, } -#[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_unsafe_item)] pub(crate) struct UnsafeItem { diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl index 859118a4adee5..60f0b9d71944a 100644 --- a/compiler/rustc_parse/messages.ftl +++ b/compiler/rustc_parse/messages.ftl @@ -858,6 +858,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 {$annotation} + .because = {$annotation} because of this + .type = inherent impl for this type + .only_trait = only trait implementations may be annotated with {$annotation} + 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 4aaaba01faeb3..b11bb489d8d0a 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)] +pub(crate) struct TraitImplModifierInInherentImpl<'a> { + #[primary_span] + pub span: Span, + #[label(parse_because)] + pub annotation_span: Span, + pub annotation: &'a str, + #[label(parse_type)] + pub self_ty: Span, + #[note(parse_only_trait)] + pub only_trait: bool, +} + #[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 65d84b3e3d9d5..ce4eaf91809e9 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -666,7 +666,41 @@ impl<'a> Parser<'a> { (Some(trait_ref), ty_second) } - None => (None, ty_first), // impl Type + None => { + let self_ty = ty_first; + let error = |annotation_span, annotation, only_trait| { + errors::TraitImplModifierInInherentImpl { + span: self_ty.span, + annotation_span, + annotation, + self_ty: self_ty.span, + only_trait, + } + }; + + if let Safety::Unsafe(span) = safety { + self.dcx() + .create_err(errors::TraitImplModifierInInherentImpl { + span: self_ty.span, + annotation_span: span, + annotation: "unsafe", + self_ty: self_ty.span, + only_trait: true, + }) + .with_code(E0197) + .emit(); + } + 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)); + } + (None, self_ty) + } }; Ok(ItemKind::Impl(Box::new(Impl { safety, diff --git a/tests/ui/parser/default-on-wrong-item-kind.rs b/tests/ui/parser/default-on-wrong-item-kind.rs index da990a4b42123..db4e41a28ac26 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 56641565b1668..fb15af832caa6 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/traits/const-traits/macro-const-trait-bound-theoretical-regression.stderr b/tests/ui/traits/const-traits/macro-const-trait-bound-theoretical-regression.stderr index af160a45f3e66..58d38a62c6791 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,14 +1,3 @@ -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` --> $DIR/macro-const-trait-bound-theoretical-regression.rs:10:40 | @@ -24,6 +13,17 @@ LL | demo! { impl const Trait } = 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/syntax-trait-polarity.stderr b/tests/ui/traits/syntax-trait-polarity.stderr index 1fd40fb66570d..a623cdbef3aca 100644 --- a/tests/ui/traits/syntax-trait-polarity.stderr +++ b/tests/ui/traits/syntax-trait-polarity.stderr @@ -6,6 +6,14 @@ LL | impl !TestType {} | | | negative because of this +error: inherent impls cannot be negative + --> $DIR/syntax-trait-polarity.rs:18:10 + | +LL | impl !TestType2 {} + | -^^^^^^^^^^^^ inherent impl for this type + | | + | negative because of this + error[E0198]: negative impls cannot be unsafe --> $DIR/syntax-trait-polarity.rs:12:13 | @@ -15,14 +23,6 @@ LL | unsafe impl !Send for TestType {} | | negative because of this | unsafe because of this -error: inherent impls cannot be negative - --> $DIR/syntax-trait-polarity.rs:18:10 - | -LL | impl !TestType2 {} - | -^^^^^^^^^^^^ inherent impl for this type - | | - | negative because of this - error[E0198]: negative impls cannot be unsafe --> $DIR/syntax-trait-polarity.rs:21:16 | From 3dc0602fbce132dabbe42ac89b4e246faa98b92b Mon Sep 17 00:00:00 2001 From: Cameron Steffen Date: Wed, 30 Jul 2025 18:00:53 -0500 Subject: [PATCH 3/5] Tweak trait modifier errors --- compiler/rustc_parse/messages.ftl | 6 ++-- compiler/rustc_parse/src/errors.rs | 10 +++---- compiler/rustc_parse/src/parser/item.rs | 29 +++++++------------ tests/ui/error-codes/E0197.stderr | 2 +- tests/ui/parser/default-on-wrong-item-kind.rs | 8 ++--- .../parser/default-on-wrong-item-kind.stderr | 16 +++++----- .../specialization/defaultimpl/validation.rs | 2 +- .../defaultimpl/validation.stderr | 4 +-- tests/ui/traits/const-traits/inherent-impl.rs | 4 +-- .../traits/const-traits/inherent-impl.stderr | 8 ++--- ...-trait-bound-theoretical-regression.stderr | 4 +-- .../const-traits/span-bug-issue-121418.rs | 2 +- .../const-traits/span-bug-issue-121418.stderr | 4 +-- tests/ui/traits/safety-inherent-impl.stderr | 2 +- tests/ui/traits/syntax-trait-polarity.stderr | 4 +++ 15 files changed, 50 insertions(+), 55 deletions(-) diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl index 60f0b9d71944a..5ae67c8f72069 100644 --- a/compiler/rustc_parse/messages.ftl +++ b/compiler/rustc_parse/messages.ftl @@ -858,10 +858,10 @@ 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 {$annotation} - .because = {$annotation} because of this +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 - .only_trait = only trait implementations may be annotated with {$annotation} + .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 b11bb489d8d0a..c3f075a383e22 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -73,16 +73,16 @@ pub(crate) struct BadQPathStage2 { #[derive(Diagnostic)] #[diag(parse_trait_impl_modifier_in_inherent_impl)] -pub(crate) struct TraitImplModifierInInherentImpl<'a> { +#[note] +pub(crate) struct TraitImplModifierInInherentImpl { #[primary_span] pub span: Span, + pub modifier: &'static str, + pub modifier_name: &'static str, #[label(parse_because)] - pub annotation_span: Span, - pub annotation: &'a str, + pub modifier_span: Span, #[label(parse_type)] pub self_ty: Span, - #[note(parse_only_trait)] - pub only_trait: bool, } #[derive(Subdiagnostic)] diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index ce4eaf91809e9..cee356fe067d7 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -668,36 +668,27 @@ impl<'a> Parser<'a> { } None => { let self_ty = ty_first; - let error = |annotation_span, annotation, only_trait| { - errors::TraitImplModifierInInherentImpl { + let error = |modifier, modifier_name, modifier_span| { + self.dcx().create_err(errors::TraitImplModifierInInherentImpl { span: self_ty.span, - annotation_span, - annotation, + modifier, + modifier_name, + modifier_span, self_ty: self_ty.span, - only_trait, - } + }) }; if let Safety::Unsafe(span) = safety { - self.dcx() - .create_err(errors::TraitImplModifierInInherentImpl { - span: self_ty.span, - annotation_span: span, - annotation: "unsafe", - self_ty: self_ty.span, - only_trait: true, - }) - .with_code(E0197) - .emit(); + error("unsafe", "unsafe", span).with_code(E0197).emit(); } if let ImplPolarity::Negative(span) = polarity { - self.dcx().emit_err(error(span, "negative", false)); + error("!", "negative", span).emit(); } if let Defaultness::Default(def_span) = defaultness { - self.dcx().emit_err(error(def_span, "`default`", true)); + error("default", "default", def_span).emit(); } if let Const::Yes(span) = constness { - self.dcx().emit_err(error(span, "`const`", true)); + error("const", "const", span).emit(); } (None, self_ty) } diff --git a/tests/ui/error-codes/E0197.stderr b/tests/ui/error-codes/E0197.stderr index e3d3c7dde9c35..04c6174b9f1d5 100644 --- a/tests/ui/error-codes/E0197.stderr +++ b/tests/ui/error-codes/E0197.stderr @@ -6,7 +6,7 @@ LL | unsafe impl Foo { } | | | unsafe because of this | - = note: only trait implementations may be annotated with unsafe + = note: only trait implementations may be annotated with `unsafe` error: aborting due to 1 previous error diff --git a/tests/ui/parser/default-on-wrong-item-kind.rs b/tests/ui/parser/default-on-wrong-item-kind.rs index db4e41a28ac26..9de8564056560 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 {} //~ ERROR inherent impls cannot be `default` + 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 {} //~ ERROR inherent impls cannot be `default` + 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 {} //~ ERROR inherent impls cannot be `default` + 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 {} //~ ERROR inherent impls cannot be `default` + 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 fb15af832caa6..0380fcdf775f8 100644 --- a/tests/ui/parser/default-on-wrong-item-kind.stderr +++ b/tests/ui/parser/default-on-wrong-item-kind.stderr @@ -78,13 +78,13 @@ LL | default trait foo = Ord; | = note: only associated `fn`, `const`, and `type` items can be `default` -error: inherent impls cannot 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 + | default because of this | = note: only trait implementations may be annotated with `default` @@ -285,13 +285,13 @@ LL | default trait foo = Ord; | = help: consider moving the trait alias out to a nearby module scope -error: inherent impls cannot be `default` +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 + | default because of this | = note: only trait implementations may be annotated with `default` @@ -509,13 +509,13 @@ LL | default trait foo = Ord; | = help: consider moving the trait alias out to a nearby module scope -error: inherent impls cannot be `default` +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 + | default because of this | = note: only trait implementations may be annotated with `default` @@ -733,13 +733,13 @@ LL | default trait foo = Ord; | = help: consider moving the trait alias out to a nearby module scope -error: inherent impls cannot be `default` +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 + | default because of this | = note: only trait implementations may be annotated with `default` diff --git a/tests/ui/specialization/defaultimpl/validation.rs b/tests/ui/specialization/defaultimpl/validation.rs index 14771be8982dd..78f6099c3dd99 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 82a33bf9cdc39..a8dfef2dcfb14 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/traits/const-traits/inherent-impl.rs b/tests/ui/traits/const-traits/inherent-impl.rs index 07b23adf9e1f6..5ca4c5d7863d2 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 e4ec1e807b0e3..d828ecb6349e8 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 58d38a62c6791..9fad260f0bea2 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,4 +1,4 @@ -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 {} }; @@ -7,7 +7,7 @@ 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` 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 50a7e12f2a78a..593180ac09461 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 {} //~^ 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 f31129d9cb7c7..0c8ca918a3e1c 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 f4443857dc929..45cdbe2b523b2 100644 --- a/tests/ui/traits/safety-inherent-impl.stderr +++ b/tests/ui/traits/safety-inherent-impl.stderr @@ -6,7 +6,7 @@ LL | unsafe impl SomeStruct { | | | unsafe because of this | - = note: only trait implementations may be annotated with unsafe + = 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 a623cdbef3aca..8ffcdc7d8b555 100644 --- a/tests/ui/traits/syntax-trait-polarity.stderr +++ b/tests/ui/traits/syntax-trait-polarity.stderr @@ -5,6 +5,8 @@ LL | impl !TestType {} | -^^^^^^^^ inherent impl for this type | | | negative because of this + | + = note: only trait implementations may be annotated with `!` error: inherent impls cannot be negative --> $DIR/syntax-trait-polarity.rs:18:10 @@ -13,6 +15,8 @@ LL | impl !TestType2 {} | -^^^^^^^^^^^^ 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 From 7ef7c7b160c28709ca061b2a2f143afcc1ff2c53 Mon Sep 17 00:00:00 2001 From: Cameron Steffen Date: Mon, 21 Jul 2025 20:05:16 -0500 Subject: [PATCH 4/5] Extract ast TraitImplHeader --- compiler/rustc_ast/src/ast.rs | 21 ++++--- compiler/rustc_ast/src/visit.rs | 9 ++- compiler/rustc_ast_lowering/src/item.rs | 45 ++++++++++----- .../rustc_ast_passes/src/ast_validation.rs | 26 ++++----- compiler/rustc_ast_passes/src/feature_gate.rs | 8 +-- .../rustc_ast_pretty/src/pprust/state/item.rs | 56 ++++++++++--------- .../src/deriving/coerce_pointee.rs | 32 ++++++----- .../src/deriving/generic/mod.rs | 22 +++++--- compiler/rustc_lint/src/builtin.rs | 5 +- compiler/rustc_lint/src/internal.rs | 8 +-- compiler/rustc_lint/src/nonstandard_style.rs | 2 +- compiler/rustc_parse/src/parser/item.rs | 27 +++++---- .../rustc_resolve/src/build_reduced_graph.rs | 7 +-- compiler/rustc_resolve/src/late.rs | 14 ++--- .../clippy/clippy_utils/src/ast_utils/mod.rs | 26 ++++----- src/tools/rustfmt/src/items.rs | 51 +++++++---------- .../rustfmt/tests/source/negative-impl.rs | 4 -- .../rustfmt/tests/target/negative-impl.rs | 8 --- 18 files changed, 187 insertions(+), 184 deletions(-) diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 984b280e81b5a..083399bfa3968 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -3761,15 +3761,19 @@ pub struct TyAlias { #[derive(Clone, Encodable, Decodable, Debug)] pub struct Impl { + pub generics: Generics, + pub of_trait: Option>, + pub self_ty: P, + pub items: ThinVec>, +} + +#[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, - pub self_ty: P, - pub items: ThinVec>, + pub trait_ref: TraitRef, } #[derive(Clone, Encodable, Decodable, Debug, Default, Walkable)] @@ -3893,7 +3897,7 @@ pub enum ItemKind { /// An implementation. /// /// E.g., `impl Foo { .. }` or `impl Trait for Foo { .. }`. - Impl(Box), + Impl(Impl), /// A macro invocation. /// /// E.g., `foo!(..)`. @@ -3980,7 +3984,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, } } @@ -4140,7 +4144,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); @@ -4153,6 +4157,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 ab15cb28fa12d..2f59c2f5d955a 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -930,8 +930,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 1899dcda3619c..21615137f9825 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -341,13 +341,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, }) => { @@ -374,10 +370,10 @@ impl<'hir> LoweringContext<'_, 'hir> { polarity: BoundPolarity::Positive, }; - let trait_ref = trait_ref.as_ref().map(|trait_ref| { + let trait_ref = of_trait.as_ref().map(|of_trait| { this.lower_trait_ref( modifiers, - trait_ref, + &of_trait.trait_ref, ImplTraitContext::Disallowed(ImplTraitPosition::Trait), ) }); @@ -397,14 +393,35 @@ impl<'hir> LoweringContext<'_, 'hir> { // `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)), + let (constness, safety, polarity, defaultness, defaultness_span) = match *of_trait { + Some(box TraitImplHeader { + constness, + safety, + polarity, + defaultness, + trait_ref: _, + }) => { + 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)), + }; + let (defaultness, defaultness_span) = + self.lower_defaultness(defaultness, has_val); + (constness, safety, polarity, defaultness, defaultness_span) + } + None => ( + hir::Constness::NotConst, + hir::Safety::Safe, + ImplPolarity::Positive, + hir::Defaultness::Final, + None, + ), }; hir::ItemKind::Impl(self.arena.alloc(hir::Impl { - constness: self.lower_constness(*constness), - safety: self.lower_safety(*safety, hir::Safety::Safe), + constness, + safety, polarity, defaultness, defaultness_span, diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index b6c643b8fbc11..7054000aeda47 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -951,13 +951,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, }) => { @@ -989,16 +992,7 @@ 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, - }) => { + ItemKind::Impl(Impl { generics, of_trait: None, self_ty, items }) => { self.visit_attrs_vis(&item.attrs, &item.vis); self.visibility_not_permitted( &item.vis, diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 662357ce88413..c9344a76a7b35 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 11c97a552c69f..19a3011df4ddf 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state/item.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state/item.rs @@ -309,39 +309,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_builtin_macros/src/deriving/coerce_pointee.rs b/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs index 6082e376435a7..75db5d77783eb 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 b24e55637613a..b4fd9539d240b 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs @@ -827,21 +827,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_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 152971c4ed691..f2d10fcbb7740 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -270,7 +270,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); } diff --git a/compiler/rustc_lint/src/internal.rs b/compiler/rustc_lint/src/internal.rs index 7dafcc199a326..9f02f1f0df38e 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, ); } diff --git a/compiler/rustc_lint/src/nonstandard_style.rs b/compiler/rustc_lint/src/nonstandard_style.rs index 76e374deef6ac..7a7f2fdc24b08 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_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index cee356fe067d7..3194ba4ed2be1 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -664,7 +664,14 @@ 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; @@ -693,16 +700,8 @@ impl<'a> Parser<'a> { (None, self_ty) } }; - 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> { @@ -1387,10 +1386,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_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 7912345ec56ac..d33cf2bffa9ff 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_data_structures::{AttributeKind, MacroUseArgs}; use rustc_attr_parsing as attr; @@ -902,10 +902,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 261d099abdc09..15955decd57a4 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -2619,7 +2619,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, @@ -2630,7 +2630,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, @@ -3176,7 +3176,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { &mut self, attrs: &[ast::Attribute], generics: &'ast Generics, - opt_trait_reference: &'ast Option, + of_trait: Option<&'ast ast::TraitImplHeader>, self_type: &'ast Ty, item_id: NodeId, impl_items: &'ast [P], @@ -3200,7 +3200,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)); @@ -3223,9 +3223,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); @@ -5168,7 +5168,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/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs b/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs index 96f0273c43969..bb6b1aa92eec3 100644 --- a/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs +++ b/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs @@ -474,33 +474,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/rustfmt/src/items.rs b/src/tools/rustfmt/src/items.rs index 7084639aca9a9..4e8cebaef50d3 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 { 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 da242d4f3dca4..e8f9508e6563f 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 16ce7e26a99aa..bb53048dbc62b 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 {} - impl !std::fmt::Display for JoinHandle { } - -impl - !JoinHandle + std::marker::Send + std::marker::Sync + 'static> - + 'static -{ -} From ae4cbbfbebb2050436ba3967050b49f1e7e8a9dd Mon Sep 17 00:00:00 2001 From: Cameron Steffen Date: Thu, 24 Jul 2025 09:32:58 -0500 Subject: [PATCH 5/5] Propagate TraitImplHeader to hir --- compiler/rustc_ast_lowering/src/item.rs | 99 +++++++++---------- compiler/rustc_hir/src/hir.rs | 27 ++--- compiler/rustc_hir/src/intravisit.rs | 26 ++--- .../rustc_hir_analysis/src/check/wfcheck.rs | 93 +++++++++-------- .../src/coherence/builtin.rs | 6 +- .../src/coherence/orphan.rs | 4 +- compiler/rustc_hir_analysis/src/collect.rs | 36 +++---- .../src/collect/predicates_of.rs | 4 +- .../src/collect/resolve_bound_vars.rs | 17 ++-- .../rustc_hir_analysis/src/collect/type_of.rs | 2 +- .../errors/wrong_number_of_generic_args.rs | 6 +- .../src/hir_ty_lowering/lint.rs | 6 +- .../src/hir_ty_lowering/mod.rs | 2 +- .../rustc_hir_analysis/src/hir_wf_check.rs | 5 +- compiler/rustc_hir_pretty/src/lib.rs | 61 ++++++------ .../src/fn_ctxt/suggestions.rs | 2 +- .../rustc_hir_typeck/src/method/suggest.rs | 10 +- .../src/deref_into_dyn_supertrait.rs | 4 +- compiler/rustc_lint/src/internal.rs | 4 +- compiler/rustc_lint/src/non_local_def.rs | 4 +- compiler/rustc_passes/src/check_attr.rs | 7 +- compiler/rustc_passes/src/stability.rs | 24 ++--- compiler/rustc_privacy/src/lib.rs | 3 +- .../src/error_reporting/traits/suggestions.rs | 8 +- compiler/rustc_ty_utils/src/assoc.rs | 4 +- compiler/rustc_ty_utils/src/implied_bounds.rs | 8 +- compiler/rustc_ty_utils/src/sig_types.rs | 2 +- compiler/rustc_ty_utils/src/ty.rs | 6 +- src/librustdoc/clean/mod.rs | 9 +- .../src/arbitrary_source_item_ordering.rs | 1 + .../clippy/clippy_lints/src/copy_iterator.rs | 4 +- .../clippy_lints/src/derivable_impls.rs | 4 +- src/tools/clippy/clippy_lints/src/derive.rs | 3 +- .../clippy/clippy_lints/src/empty_drop.rs | 4 +- .../clippy_lints/src/error_impl_error.rs | 2 +- .../clippy/clippy_lints/src/format_impl.rs | 4 +- .../clippy/clippy_lints/src/from_over_into.rs | 4 +- .../src/functions/impl_trait_in_params.rs | 3 +- .../src/functions/renamed_function_params.rs | 4 +- .../impl_hash_with_borrow_str_and_bytes.rs | 8 +- .../clippy_lints/src/infallible_try_from.rs | 4 +- .../src/iter_without_into_iter.rs | 5 +- .../clippy/clippy_lints/src/lifetimes.rs | 6 +- .../src/missing_fields_in_debug.rs | 4 +- .../clippy_lints/src/missing_trait_methods.rs | 4 +- .../clippy/clippy_lints/src/non_copy_const.rs | 2 +- .../src/non_send_fields_in_send_ty.rs | 6 +- .../clippy_lints/src/operators/op_ref.rs | 2 +- .../clippy_lints/src/partialeq_ne_impl.rs | 6 +- .../clippy_lints/src/same_name_method.rs | 4 +- .../clippy/clippy_lints/src/serde_api.rs | 6 +- .../clippy_lints/src/to_string_trait_impl.rs | 4 +- .../src/unconditional_recursion.rs | 8 +- .../src/undocumented_unsafe_blocks.rs | 6 +- src/tools/clippy/clippy_lints/src/write.rs | 4 +- .../clippy_utils/src/check_proc_macro.rs | 6 +- src/tools/clippy/clippy_utils/src/lib.rs | 3 +- src/tools/clippy/clippy_utils/src/visitors.rs | 3 +- tests/ui/unpretty/exhaustive.hir.stdout | 2 +- 59 files changed, 316 insertions(+), 299 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 21615137f9825..65a06df061f6e 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -361,75 +361,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 = of_trait.as_ref().map(|of_trait| { - this.lower_trait_ref( - modifiers, - &of_trait.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 (constness, safety, polarity, defaultness, defaultness_span) = match *of_trait { - Some(box TraitImplHeader { - constness, - safety, - polarity, - defaultness, - trait_ref: _, - }) => { - 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)), - }; - let (defaultness, defaultness_span) = - self.lower_defaultness(defaultness, has_val); - (constness, safety, polarity, defaultness, defaultness_span) - } - None => ( - hir::Constness::NotConst, - hir::Safety::Safe, - ImplPolarity::Positive, - hir::Defaultness::Final, - None, - ), - }; - hir::ItemKind::Impl(self.arena.alloc(hir::Impl { - constness, - safety, - 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, @@ -1000,6 +955,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_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 4ccc2e5a97c77..04aced8bf2a56 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -4194,7 +4194,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 +4372,7 @@ pub enum ItemKind<'hir> { TraitAlias(Ident, &'hir Generics<'hir>, GenericBounds<'hir>), /// An implementation, e.g., `impl Trait for Foo { .. }`. - Impl(&'hir Impl<'hir>), + Impl(Impl<'hir>), } /// Represents an impl block declaration. @@ -4381,6 +4381,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 +4396,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, - pub generics: &'hir Generics<'hir>, - - /// The trait being implemented, if any. - pub of_trait: Option>, - - pub self_ty: &'hir Ty<'hir>, - pub items: &'hir [ImplItemId], + pub trait_ref: TraitRef<'hir>, } impl ItemKind<'_> { @@ -4756,8 +4758,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 +4954,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 +4969,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 f33915d5b0773..ba4b2857c142a 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -596,21 +596,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 a62efed13bc79..c642435b9893c 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>, + 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 27948f50a4ad5..32b175611ceb5 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 c75fef9f716d6..f707196c81635 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` in `impl for C in D` - 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 afe79bed851cc..6bc13ba26bc02 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, - 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 cc53919626e63..a84bdf035a5bc 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -157,7 +157,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 eb3492f5de6e7..8133f9f68234b 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 22fb02714dd79..62125c99d8021 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 835f8e8cdaeed..8a9f9130feacb 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 646ff3ca08d24..56998b5b53cc4 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 d768799835867..9869f126160cb 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -2729,7 +2729,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 3fddaee8cef4d..d8578970adc94 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 bda02042aa66b..9ce3addc87e19 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 2345cdab208e3..6013430e1ff3d 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 e64af8fb7b38f..8c6a82e333d68 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -1117,7 +1117,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, _)) ) => { @@ -1179,13 +1179,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/src/deref_into_dyn_supertrait.rs b/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs index dd16117db1c5e..943fcc0801b1e 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/internal.rs b/compiler/rustc_lint/src/internal.rs index 9f02f1f0df38e..016ff17f5d7ea 100644 --- a/compiler/rustc_lint/src/internal.rs +++ b/compiler/rustc_lint/src/internal.rs @@ -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/non_local_def.rs b/compiler/rustc_lint/src/non_local_def.rs index b877f909fc029..2dd3425e66cf4 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_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 0b329cc38b070..e262cf5f8cadb 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -1159,8 +1159,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([_])) @@ -1650,8 +1649,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; diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs index 9ed7293873f5f..0b206bf1fa5ca 100644 --- a/compiler/rustc_passes/src/stability.rs +++ b/compiler/rustc_passes/src/stability.rs @@ -638,9 +638,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()); @@ -676,7 +674,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(..)] @@ -689,7 +687,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 { @@ -703,7 +701,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, @@ -719,7 +717,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. @@ -747,14 +745,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 b4fa11a8eb37e..1084098ce6c7b 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -1765,7 +1765,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_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index c182fd99b17bd..8301d4f1faf3d 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -3459,8 +3459,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(); @@ -3468,7 +3468,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( @@ -3574,7 +3574,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 37cb64511c7a2..e9629e31482a2 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 6fa763f18ef19..cdfb93c4e7d56 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 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 dc6009116ac57..d95660810e5ff 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 2e0b16d922763..b22c326b9f2ab 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/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 14295ce0a31d3..cf76166e82a64 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 { 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, for_: Type, items: Vec| { 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/tools/clippy/clippy_lints/src/arbitrary_source_item_ordering.rs b/src/tools/clippy/clippy_lints/src/arbitrary_source_item_ordering.rs index 7b4cf03367418..dbd5317368b37 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 { if let Some(of_trait) = im.of_trait { let mut trait_segs: Vec = of_trait + .trait_ref .path .segments .iter() diff --git a/src/tools/clippy/clippy_lints/src/copy_iterator.rs b/src/tools/clippy/clippy_lints/src/copy_iterator.rs index 4ecf3e41611b1..51aebd8b0cfba 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 0a481ddcd12e4..7580d6cab66d4 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 49dd1bb09c61c..c53a957f6a8b7 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 4e948701da4ff..2b8221884344f 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 6525648efb1e9..3018e1f127347 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 0535ecf5240f9..416aea51ea195 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 1da6952eb64c4..e3bb5ee10db7c 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 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 cb83b1395d260..3105e303ae31f 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 0d6191f2c9715..0a7c6e9d5f8e1 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 940adbae428e8..f73182d3af0d2 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` 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` 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` around `Hash` can't be satisfied when both `Borrow` and `Borrow<[u8]>` are implemented", |diag| { diag.note("the `Borrow` semantics require that `Hash` must behave the same for all implementations of Borrow"); 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 f7cdf05359a3e..7735e517c0715 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 b89f91f7255fb..645e0f981f27e 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 35c9d2fd4eb86..149ae5e710c1f 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::::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 18e2b384a463d..8822b32b1c3d6 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 399bf4e18064c..9cc93bf06531a 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 388c029c9ef45..8a5a6f4a4dc1e 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 `::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 8ff78ec7c580d..b810bc01fbdcb 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 0a1f2625f4cfc..9c160ff680ec8 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 301b2cd4bf2fc..77751e75a8e14 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 67eb71f7d0747..b87751f498643 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 = 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 2de22e4b6a360..01c7f394b9adc 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 9596b85664b34..303f6028bd51f 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 dcddff557d1c7..e843e169113e7 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 cf603c6190ba1..1c52de52619ef 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 d9a007635cae1..a15e4e42e71df 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/check_proc_macro.rs b/src/tools/clippy/clippy_utils/src/check_proc_macro.rs index dc31ed08fb712..e0c1b9d445a2a 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 67e09e772a772..704ec161070ee 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -529,8 +529,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 ba5cbc738361f..c9f5401ebe776 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/tests/ui/unpretty/exhaustive.hir.stdout b/tests/ui/unpretty/exhaustive.hir.stdout index 9cfa65f580126..e9823c9575bc9 100644 --- a/tests/ui/unpretty/exhaustive.hir.stdout +++ b/tests/ui/unpretty/exhaustive.hir.stdout @@ -509,7 +509,7 @@ mod items { impl () { } impl () { } impl Default for () { } - impl const Default for () { } + impl const Default for () { } } /// ItemKind::MacCall mod item_mac_call { }