From d83df84eb5f7a50a1ffae16ace8a1b29918b9b94 Mon Sep 17 00:00:00 2001 From: Raushan Singh Date: Thu, 27 Aug 2026 14:10:24 +0000 Subject: [PATCH 01/23] test(parser): capture current behavior for fields in traits --- .../parser/trait-item-field-colon-syntax.rs | 9 ++++++++ .../trait-item-field-colon-syntax.stderr | 22 +++++++++++++++++++ 2 files changed, 31 insertions(+) create mode 100644 tests/ui/parser/trait-item-field-colon-syntax.rs create mode 100644 tests/ui/parser/trait-item-field-colon-syntax.stderr diff --git a/tests/ui/parser/trait-item-field-colon-syntax.rs b/tests/ui/parser/trait-item-field-colon-syntax.rs new file mode 100644 index 0000000000000..f9c5a92d05613 --- /dev/null +++ b/tests/ui/parser/trait-item-field-colon-syntax.rs @@ -0,0 +1,9 @@ +fn main() {} + +trait Trait1 { + field_name: String, //~ ERROR expected one of `!` or `::`, found `:` +} + +trait Trait2 { + self: String, //~ ERROR expected one of `!` or `::`, found `:` +} diff --git a/tests/ui/parser/trait-item-field-colon-syntax.stderr b/tests/ui/parser/trait-item-field-colon-syntax.stderr new file mode 100644 index 0000000000000..a0d58f7a6bcd1 --- /dev/null +++ b/tests/ui/parser/trait-item-field-colon-syntax.stderr @@ -0,0 +1,22 @@ +error: expected one of `!` or `::`, found `:` + --> $DIR/trait-item-field-colon-syntax.rs:4:15 + | +LL | trait Trait1 { + | - while parsing this item list starting here +LL | field_name: String, + | ^ expected one of `!` or `::` +LL | } + | - the item list ends here + +error: expected one of `!` or `::`, found `:` + --> $DIR/trait-item-field-colon-syntax.rs:8:9 + | +LL | trait Trait2 { + | - while parsing this item list starting here +LL | self: String, + | ^ expected one of `!` or `::` +LL | } + | - the item list ends here + +error: aborting due to 2 previous errors + From 6b9210cf005dcdc61afdebb28e662e7154fe4a5c Mon Sep 17 00:00:00 2001 From: Raushan Singh Date: Mon, 31 Aug 2026 12:39:08 +0000 Subject: [PATCH 02/23] fix(parser): emit targeted diagnostic for fields inside traits Detect `ident: Type` or `self: Type` inside trait bodies to emit a clearer diagnostics. --- compiler/rustc_parse/src/diagnostics.rs | 17 ++++++++ compiler/rustc_parse/src/parser/item.rs | 37 ++++++++++++++++ .../parser/trait-item-field-colon-syntax.rs | 12 +++++- .../trait-item-field-colon-syntax.stderr | 42 +++++++++++++++---- 4 files changed, 99 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_parse/src/diagnostics.rs b/compiler/rustc_parse/src/diagnostics.rs index 2be549703e4e6..7517f04bf5846 100644 --- a/compiler/rustc_parse/src/diagnostics.rs +++ b/compiler/rustc_parse/src/diagnostics.rs @@ -2495,6 +2495,23 @@ pub(crate) struct AssociatedStaticItemNotAllowed { pub span: Span, } +#[derive(Subdiagnostic)] +pub(crate) enum FieldNotAllowedInTraitSugg { + #[help("consider using a method instead: `fn {$ident}(&self) -> {$ty};`")] + Method { ident: String, ty: String }, + #[note("`self` can only appear as a method receiver; consider `fn method(self: {$ty})`")] + SelfReceiver { ty: String }, +} + +#[derive(Diagnostic)] +#[diag("fields are not allowed in trait definitions")] +pub(crate) struct FieldNotAllowedInTrait { + #[primary_span] + pub span: Span, + #[subdiagnostic] + pub sugg: FieldNotAllowedInTraitSugg, +} + #[derive(Diagnostic)] #[diag("crate name using dashes are not valid in `extern crate` statements")] pub(crate) struct ExternCrateNameWithDashes { diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 46fd2445d7c55..8957cc388959e 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -404,6 +404,14 @@ impl<'a> Parser<'a> { Case::Insensitive, ); } else if macros_allowed && self.check_path() { + // Detect `field_name: Type` or `self: Type` inside a trait body and emit + // a clearer diagnostic before falling through to the macro invocation path. + let is_field_in_trait = fn_parse_mode.context == FnContext::Trait + && self.token.is_path_start() + && self.look_ahead(1, |t| t.kind == token::Colon); + if is_field_in_trait { + return self.recover_field_in_trait(); + } if self.isnt_macro_invocation() { self.recover_missing_kw_before_item()?; } @@ -433,6 +441,35 @@ impl<'a> Parser<'a> { } } + fn recover_field_in_trait(&mut self) -> PResult<'a, Option> { + let ident_span = self.token.span; + let ident_str = pprust::token_to_string(&self.token).into_owned(); + let is_self = self.token.is_keyword(kw::SelfLower); + + self.bump(); // identifier or `self` + self.bump(); // `:` + + let ty_str = match self.parse_ty() { + Ok(ty) => pprust::ty_to_string(&ty), + Err(e) => { + e.cancel(); + String::from("Type") + } + }; + // Eat the trailing separator so the parser doesn't trip over it. + let _ = self.eat(exp!(Comma)); + let _ = self.eat(exp!(Semi)); + + let span = ident_span.to(self.prev_token.span); + let sugg = if is_self { + diagnostics::FieldNotAllowedInTraitSugg::SelfReceiver { ty: ty_str } + } else { + diagnostics::FieldNotAllowedInTraitSugg::Method { ident: ident_str, ty: ty_str } + }; + let err = self.dcx().create_err(diagnostics::FieldNotAllowedInTrait { span, sugg }); + Err(err) + } + fn parse_use_item(&mut self) -> PResult<'a, ItemKind> { let use_token_span = self.prev_token.span; let tree = self.parse_use_tree(use_token_span, None)?; diff --git a/tests/ui/parser/trait-item-field-colon-syntax.rs b/tests/ui/parser/trait-item-field-colon-syntax.rs index f9c5a92d05613..0772f0f59bcae 100644 --- a/tests/ui/parser/trait-item-field-colon-syntax.rs +++ b/tests/ui/parser/trait-item-field-colon-syntax.rs @@ -1,9 +1,17 @@ fn main() {} trait Trait1 { - field_name: String, //~ ERROR expected one of `!` or `::`, found `:` + field_name: String, //~ ERROR fields are not allowed in trait definitions } trait Trait2 { - self: String, //~ ERROR expected one of `!` or `::`, found `:` + self: String, //~ ERROR fields are not allowed in trait definitions +} + +trait Trait3 { + field_name: String //~ ERROR fields are not allowed in trait definitions +} + +trait Trait4 { + self: String //~ ERROR fields are not allowed in trait definitions } diff --git a/tests/ui/parser/trait-item-field-colon-syntax.stderr b/tests/ui/parser/trait-item-field-colon-syntax.stderr index a0d58f7a6bcd1..f073b54ecb34a 100644 --- a/tests/ui/parser/trait-item-field-colon-syntax.stderr +++ b/tests/ui/parser/trait-item-field-colon-syntax.stderr @@ -1,22 +1,50 @@ -error: expected one of `!` or `::`, found `:` - --> $DIR/trait-item-field-colon-syntax.rs:4:15 +error: fields are not allowed in trait definitions + --> $DIR/trait-item-field-colon-syntax.rs:4:5 | LL | trait Trait1 { | - while parsing this item list starting here LL | field_name: String, - | ^ expected one of `!` or `::` + | ^^^^^^^^^^^^^^^^^^^ LL | } | - the item list ends here + | + = help: consider using a method instead: `fn field_name(&self) -> String;` -error: expected one of `!` or `::`, found `:` - --> $DIR/trait-item-field-colon-syntax.rs:8:9 +error: fields are not allowed in trait definitions + --> $DIR/trait-item-field-colon-syntax.rs:8:5 | LL | trait Trait2 { | - while parsing this item list starting here LL | self: String, - | ^ expected one of `!` or `::` + | ^^^^^^^^^^^^^ +LL | } + | - the item list ends here + | + = note: `self` can only appear as a method receiver; consider `fn method(self: String)` + +error: fields are not allowed in trait definitions + --> $DIR/trait-item-field-colon-syntax.rs:12:5 + | +LL | trait Trait3 { + | - while parsing this item list starting here +LL | field_name: String + | ^^^^^^^^^^^^^^^^^^ LL | } | - the item list ends here + | + = help: consider using a method instead: `fn field_name(&self) -> String;` + +error: fields are not allowed in trait definitions + --> $DIR/trait-item-field-colon-syntax.rs:16:5 + | +LL | trait Trait4 { + | - while parsing this item list starting here +LL | self: String + | ^^^^^^^^^^^^ +LL | } + | - the item list ends here + | + = note: `self` can only appear as a method receiver; consider `fn method(self: String)` -error: aborting due to 2 previous errors +error: aborting due to 4 previous errors From 0d1e323c71766039046ffc2b3012e4b887014c1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Sat, 5 Sep 2026 18:50:20 +0200 Subject: [PATCH 03/23] =?UTF-8?q?When=20trying=20to=20recover=20from=20`fo?= =?UTF-8?q?r<=E2=80=A6>=20dyn=20=E2=80=A6`=20don't=20unconditionally=20tre?= =?UTF-8?q?at=20`dyn`=20as=20a=20keyword?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- compiler/rustc_parse/src/parser/ty.rs | 43 ++++++++++--------- .../ui/parser/dyn-2015-identifier.fail.stderr | 21 ++++++++- tests/ui/parser/dyn-2015-identifier.rs | 8 ++++ .../parser/recover-hrtb-before-dyn-impl-kw.rs | 4 -- .../recover-hrtb-before-dyn-impl-kw.stderr | 8 +--- 5 files changed, 51 insertions(+), 33 deletions(-) diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index 31732882f7e86..2b098d8fdbbbf 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -83,20 +83,22 @@ enum AllowCVariadic { /// Determine if the given token can begin a bound assuming it follows Rust 2015 identifier `dyn`. /// /// In Rust 2015, `dyn` is a contextual keyword, not a full one. -fn can_begin_dyn_bound_in_edition_2015(t: Token) -> bool { - if t.is_path_start() { - // In `dyn::x`, `dyn` and `dyn<::Y>`, `dyn` should (continue to) denote a regular path - // segment for backward compatibility. We make an exception for `dyn(X)` which used to be - // interpreted as a path with parenthesized generic arguments which can be semantically - // well-formed (consider: `use std::ops::Fn as dyn;`). Instead, we treat it as a trait - // object type whose first bound is parenthesized. - return t != token::PathSep && t != token::Lt && t != token::Shl; - } +fn can_begin_dyn_bound_in_rust_2015(t: Token) -> bool { + // In `dyn::x`, `dyn` and `dyn<::Y>`, `dyn` should (continue to) denote a regular path + // segment for backward compatibility. We make an exception for `dyn(X)` which used to be + // interpreted as a path with parenthesized generic arguments which can be semantically + // well-formed (consider: `use std::ops::Fn as dyn;`). Instead, we treat it as a trait + // object type whose first bound is parenthesized. // Contrary to `Parser::can_begin_bound`, `!`, `const`, `[` and `async` are deliberately not // part of this list to contain the number of potential regressions esp. in MBE code. // `const` and `[` would regress UI test `macro-dyn-const-2015.rs` and // `!` would regress `dyn!(...)` macro calls in Rust 2015 for example. + + if t.is_path_start() { + return t != token::PathSep && t != token::Lt && t != token::Shl; + } + t == token::OpenParen || t == token::Question || t.is_lifetime() || t.is_keyword(kw::For) } @@ -347,9 +349,10 @@ impl<'a> Parser<'a> { } else { // Try to recover `for<'a> dyn Trait` or `for<'a> impl Trait`. if self.may_recover() - && (self.eat_keyword_noexpect(kw::Impl) || self.eat_keyword_noexpect(kw::Dyn)) + && (self.token.is_keyword(kw::Impl) || self.can_begin_dyn_ty()) { - let kw = self.prev_token.ident().unwrap().0; + self.bump(); + let (kw, _) = self.prev_token.ident().unwrap(); let removal_span = kw.span.with_hi(self.token.span.lo()); let path = self.parse_path(PathStyle::Type)?; let parse_plus = allow_plus == AllowPlus::Yes && self.check_plus(); @@ -397,7 +400,7 @@ impl<'a> Parser<'a> { } } else if self.eat_keyword(exp!(Impl)) { self.parse_impl_ty(&mut impl_dyn_multi)? - } else if self.is_explicit_dyn_type() { + } else if self.can_begin_dyn_ty() { self.parse_dyn_ty(&mut impl_dyn_multi)? } else if self.eat_lt() { // Qualified path @@ -1000,16 +1003,14 @@ impl<'a> Parser<'a> { Ok(GenericBound::Use(args, lo.to(self.prev_token.span))) } - /// Is a `dyn B0 + ... + Bn` type allowed here? - fn is_explicit_dyn_type(&mut self) -> bool { - self.check_keyword(exp!(Dyn)) + /// Can the current token begin a `dyn`-prefixed trait object type? + fn can_begin_dyn_ty(&mut self) -> bool { + self.token.is_keyword(kw::Dyn) && (self.token_uninterpolated_span().at_least_rust_2018() - || self.look_ahead(1, |&t| can_begin_dyn_bound_in_edition_2015(t))) + || self.look_ahead(1, |&t| can_begin_dyn_bound_in_rust_2015(t))) } - /// Parses a `dyn B0 + ... + Bn` type. - /// - /// Note that this does *not* parse bare trait objects. + /// Parse a `dyn`-prefixed trait object type. fn parse_dyn_ty(&mut self, impl_dyn_multi: &mut bool) -> PResult<'a, TyKind> { self.bump(); // `dyn` @@ -1067,8 +1068,8 @@ impl<'a> Parser<'a> { && (self.token.can_begin_type() || (self.token.is_reserved_ident() && !self.token.is_keyword(kw::Where)))) { - if self.token.is_keyword(kw::Dyn) && self.token.span.edition().at_least_rust_2018() { - // Account for `&dyn Trait + dyn Other`. + // Account for `&dyn Trait + dyn Other`. + if self.can_begin_dyn_ty() { self.bump(); self.dcx().emit_err(InvalidDynKeyword { span: self.prev_token.span, diff --git a/tests/ui/parser/dyn-2015-identifier.fail.stderr b/tests/ui/parser/dyn-2015-identifier.fail.stderr index da82a9f2d067f..43ca1a2ffd996 100644 --- a/tests/ui/parser/dyn-2015-identifier.fail.stderr +++ b/tests/ui/parser/dyn-2015-identifier.fail.stderr @@ -52,6 +52,12 @@ error[E0405]: cannot find trait `dyn` in this scope LL | type A4 = dyn + dyn; | ^^^ not found in this scope +error[E0405]: cannot find trait `dyn` in this scope + --> $DIR/dyn-2015-identifier.rs:33:17 + | +LL | type A5 = for<> dyn; + | ^^^ not found in this scope + warning: trait objects without an explicit `dyn` are deprecated --> $DIR/dyn-2015-identifier.rs:24:11 | @@ -66,6 +72,19 @@ help: if this is a dyn-compatible trait, use `dyn` LL | type A4 = dyn dyn + dyn; | +++ +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/dyn-2015-identifier.rs:33:11 + | +LL | type A5 = for<> dyn; + | ^^^^^^^^^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see +help: if this is a dyn-compatible trait, use `dyn` + | +LL | type A5 = dyn for<> dyn; + | +++ + error[E0433]: cannot find module or crate `dyn` in this scope --> $DIR/dyn-2015-identifier.rs:10:11 | @@ -74,7 +93,7 @@ LL | type A1 = dyn::dyn; | = help: you might be missing a crate named `dyn` -error: aborting due to 10 previous errors; 1 warning emitted +error: aborting due to 11 previous errors; 2 warnings emitted Some errors have detailed explanations: E0405, E0425, E0433. For more information about an error, try `rustc --explain E0405`. diff --git a/tests/ui/parser/dyn-2015-identifier.rs b/tests/ui/parser/dyn-2015-identifier.rs index 3bac8d2b631dc..53a09c8895a69 100644 --- a/tests/ui/parser/dyn-2015-identifier.rs +++ b/tests/ui/parser/dyn-2015-identifier.rs @@ -26,3 +26,11 @@ type A4 = dyn + dyn; //[fail]~| ERROR cannot find trait `dyn` in this scope //[fail]~| WARN trait objects without an explicit `dyn` are deprecated //[fail]~| WARN this is accepted in the current edition + +// The `for<…> dyn …` -> `dyn for<…> …` recovery code used to incorrectly treat `dyn` as a keyword +// in Rust 2015 even it's not followed by a token in the "trigger set". +// What's more, this also used to ICE for a period of time (see also #118564). +type A5 = for<> dyn; +//[fail]~^ ERROR cannot find trait `dyn` in this scope +//[fail]~| WARN trait objects without an explicit `dyn` are deprecated +//[fail]~| WARN this is accepted in the current edition diff --git a/tests/ui/parser/recover-hrtb-before-dyn-impl-kw.rs b/tests/ui/parser/recover-hrtb-before-dyn-impl-kw.rs index b78832bbe3dc0..56eb102b225ee 100644 --- a/tests/ui/parser/recover-hrtb-before-dyn-impl-kw.rs +++ b/tests/ui/parser/recover-hrtb-before-dyn-impl-kw.rs @@ -8,8 +8,4 @@ fn test(_: &for<'a> dyn Trait) {} fn test2(_: for<'a> impl Trait) {} //~^ ERROR `for<...>` expected after `impl`, not before -// Issue #118564 -type A2 = dyn dyn>; -//~^ ERROR expected identifier, found `>` - fn main() {} diff --git a/tests/ui/parser/recover-hrtb-before-dyn-impl-kw.stderr b/tests/ui/parser/recover-hrtb-before-dyn-impl-kw.stderr index 3745cf8b07790..e1032b8fdf232 100644 --- a/tests/ui/parser/recover-hrtb-before-dyn-impl-kw.stderr +++ b/tests/ui/parser/recover-hrtb-before-dyn-impl-kw.stderr @@ -22,11 +22,5 @@ LL - fn test2(_: for<'a> impl Trait) {} LL + fn test2(_: impl for<'a> Trait) {} | -error: expected identifier, found `>` - --> $DIR/recover-hrtb-before-dyn-impl-kw.rs:12:24 - | -LL | type A2 = dyn dyn>; - | ^ expected identifier - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors From c98b78666ff1f33896bb6dd519c4ef974306f149 Mon Sep 17 00:00:00 2001 From: Joao Roberto Date: Sat, 29 Aug 2026 15:20:23 -0300 Subject: [PATCH 04/23] Handle reflexive solver region constraints --- compiler/rustc_type_ir/src/region_constraint.rs | 4 ++++ .../reflexive-placeholder-outlives.rs | 17 +++++++++++++++++ 2 files changed, 21 insertions(+) create mode 100644 tests/ui/assumptions_on_binders/reflexive-placeholder-outlives.rs diff --git a/compiler/rustc_type_ir/src/region_constraint.rs b/compiler/rustc_type_ir/src/region_constraint.rs index 9a643b538d93f..9c6fd993b180a 100644 --- a/compiler/rustc_type_ir/src/region_constraint.rs +++ b/compiler/rustc_type_ir/src/region_constraint.rs @@ -645,6 +645,10 @@ fn pull_region_outlives_constraints_out_of_universe< pulled_constraints.push(Or::new_leaf(c.clone())); } RegionOutlives(region_1, region_2, ()) => { + if region_1 == region_2 { + continue; + } + let region_1_u = max_universe(infcx, region_1); let region_2_u = max_universe(infcx, region_2); diff --git a/tests/ui/assumptions_on_binders/reflexive-placeholder-outlives.rs b/tests/ui/assumptions_on_binders/reflexive-placeholder-outlives.rs new file mode 100644 index 0000000000000..5ae97af1198d0 --- /dev/null +++ b/tests/ui/assumptions_on_binders/reflexive-placeholder-outlives.rs @@ -0,0 +1,17 @@ +//@ check-pass +//@ compile-flags: -Zassumptions-on-binders + +#![feature(test_binder_constraints, non_lifetime_binders)] +#![expect(incomplete_features)] + +// Regression test for rust-lang/project-assumptions-on-binders#19. +core::test_binder_constraints! { + impl<> { + forall<'a> { + 'a: 'a + } expect { + } + } +} + +fn main() {} From f88e474b8eac1d87afefce3f7588931caabdf9f7 Mon Sep 17 00:00:00 2001 From: Joao Roberto Date: Sat, 29 Aug 2026 21:04:16 -0300 Subject: [PATCH 05/23] Discharge region constraints entailed by assumptions --- .../rustc_type_ir/src/region_constraint.rs | 8 +++ .../reflexive-placeholder-outlives.rs | 17 ----- .../same-universe-placeholder-outlives.rs | 64 +++++++++++++++++++ 3 files changed, 72 insertions(+), 17 deletions(-) delete mode 100644 tests/ui/assumptions_on_binders/reflexive-placeholder-outlives.rs create mode 100644 tests/ui/assumptions_on_binders/same-universe-placeholder-outlives.rs diff --git a/compiler/rustc_type_ir/src/region_constraint.rs b/compiler/rustc_type_ir/src/region_constraint.rs index 9c6fd993b180a..7b661c400b1ea 100644 --- a/compiler/rustc_type_ir/src/region_constraint.rs +++ b/compiler/rustc_type_ir/src/region_constraint.rs @@ -665,6 +665,14 @@ fn pull_region_outlives_constraints_out_of_universe< } }; + // The constraint may already be entailed by the assumptions of the binder we are + // leaving, e.g. `for<'a, 'b> where 'b: 'a { 'b: 'a }`. There is nothing to lift into + // a smaller universe in that case, and looking for lower universe candidates would + // wrongly result in `Or([])` whenever the placeholders have no lower universe bounds. + if regions_outlived_by(region_1, assumptions).any(|r| r == region_2) { + continue; + } + let mut candidates = vec![]; for ub in regions_outlived_by(region_1, assumptions) diff --git a/tests/ui/assumptions_on_binders/reflexive-placeholder-outlives.rs b/tests/ui/assumptions_on_binders/reflexive-placeholder-outlives.rs deleted file mode 100644 index 5ae97af1198d0..0000000000000 --- a/tests/ui/assumptions_on_binders/reflexive-placeholder-outlives.rs +++ /dev/null @@ -1,17 +0,0 @@ -//@ check-pass -//@ compile-flags: -Zassumptions-on-binders - -#![feature(test_binder_constraints, non_lifetime_binders)] -#![expect(incomplete_features)] - -// Regression test for rust-lang/project-assumptions-on-binders#19. -core::test_binder_constraints! { - impl<> { - forall<'a> { - 'a: 'a - } expect { - } - } -} - -fn main() {} diff --git a/tests/ui/assumptions_on_binders/same-universe-placeholder-outlives.rs b/tests/ui/assumptions_on_binders/same-universe-placeholder-outlives.rs new file mode 100644 index 0000000000000..6d292416cd4cf --- /dev/null +++ b/tests/ui/assumptions_on_binders/same-universe-placeholder-outlives.rs @@ -0,0 +1,64 @@ +//@ check-pass +//@ compile-flags: -Zassumptions-on-binders + +#![feature(test_binder_constraints, non_lifetime_binders)] +#![expect(incomplete_features)] + +// Regression test for rust-lang/project-assumptions-on-binders#19. +// +// When leaving a binder we lift its region constraints into a smaller universe. Constraints +// which already hold inside of the binder have no lower universe candidates to be lifted to, +// so they used to turn into `Or([])`, i.e. `false`. They have to be discharged instead. + +// Outlives is reflexive. +core::test_binder_constraints! { + impl<> { + forall<'a> { + 'a: 'a + } expect { + } + } +} + +// Directly entailed by an assumption of the binder we're leaving. +core::test_binder_constraints! { + impl<> { + forall<'a, 'b> where 'b: 'a { + 'b: 'a + } expect { + } + } +} + +// Transitively entailed by the assumptions of the binder we're leaving. +core::test_binder_constraints! { + impl<> { + forall<'a, 'b, 'c> where 'c: 'b, 'b: 'a { + 'c: 'a + } expect { + } + } +} + +// Discharging entailed constraints must not swallow the ones which still have to be lifted +// into the outer universe. Here `'a: 'a` and `'b: 'a` are discharged inside the binder while +// `'c: 'a` is lifted, as `'c` outlives every lower universe region that `'a` outlives. +// +// FIXME(-Zassumptions-on-binders): this should be `impl<'b, 'c: 'b>`, not +// `impl<'b, 'c: 'b + 'static>`, but OR isn't actually implemented yet +core::test_binder_constraints! { + impl<'b, 'c: 'b + 'static> { + forall<'a> where 'b: 'a { + 'a: 'a, + 'b: 'a, + 'c: 'a, + } expect { + or { + 'c: 'b, + 'c: 'static, + } + } + } +} + +fn main() {} From 5cbee6e22b49e219570a7745599e35401fa6e53a Mon Sep 17 00:00:00 2001 From: Joao Roberto Date: Sat, 29 Aug 2026 21:08:04 -0300 Subject: [PATCH 06/23] Include implied regions in outlives assumptions --- .../rustc_hir_analysis/src/check/wfcheck.rs | 7 +++- .../src/infer/outlives/obligations.rs | 17 +++++++- .../eval_ctxt/solver_region_constraints.rs | 5 ++- .../rustc_type_ir/src/region_constraint.rs | 42 +++++++++++++++++++ .../same-universe-placeholder-outlives.rs | 22 ++++++++++ 5 files changed, 88 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 0dee9690737df..34f8ae70abac4 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -2406,8 +2406,11 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> { for &(r1, r2) in &body.region_outlives { builder.add(r1, r2); } - let assumptions = - ty::region_constraint::Assumptions::new(body.type_outlives, builder.freeze()); + let assumptions = ty::region_constraint::Assumptions::new( + self.tcx(), + body.type_outlives, + builder.freeze(), + ); self.infcx.insert_placeholder_assumptions(u, Some(assumptions)); self.check_test_binder_body(body.value); let solver_region_constraint = self.infcx.get_solver_region_constraint(); diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs index cbbf5e3c91c42..23eb48d43dfb7 100644 --- a/compiler/rustc_infer/src/infer/outlives/obligations.rs +++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs @@ -234,8 +234,22 @@ impl<'tcx> InferCtxt<'tcx> { &self, outlives_env: &OutlivesEnvironment<'tcx>, ) { + // `known_type_outlives` only contains the explicit `Ty: 'a` where clauses. The implied + // bounds, e.g. `T: 'a` from a `&'a T` argument, are only tracked in `region_bound_pairs` + // so we have to pull them in separately. Without them we'd fail to prove `T: 'a` for a + // `&'a T` argument whenever the only explicit bound on `T` mentions a different region. + let mut known_type_outlives = outlives_env.known_type_outlives().to_vec(); + for &ty::OutlivesClause(kind, r) in outlives_env.region_bound_pairs() { + let ty = match kind { + GenericKind::Param(p) => Ty::new_param(self.tcx, p.index, p.name), + GenericKind::Placeholder(p) => Ty::new_placeholder(self.tcx, p), + GenericKind::Alias(alias) => alias.to_ty(self.tcx, ty::IsRigid::Yes), + }; + known_type_outlives.push(ty::Binder::dummy(ty::OutlivesClause(ty, r))); + } let assumptions = rustc_type_ir::region_constraint::Assumptions::new( - outlives_env.known_type_outlives().into_iter().cloned().collect(), + self.tcx, + known_type_outlives, outlives_env.free_region_map().relation.clone(), ); self.destructure_solver_region_constraints(assumptions, self); @@ -249,6 +263,7 @@ impl<'tcx> InferCtxt<'tcx> { region_outlives: TransitiveRelation, ) { let assumptions = region_constraint::Assumptions::new( + self.tcx, known_type_outlives.into_iter().cloned().collect(), region_outlives.maybe_map(|r| Some(Region::new_var(self.tcx, r))).unwrap(), ); diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/solver_region_constraints.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/solver_region_constraints.rs index 5a4daa5e44fc5..d67e4cf0275bb 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/solver_region_constraints.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/solver_region_constraints.rs @@ -102,8 +102,9 @@ where // FIXME(-Zassumptions-on-binders): we need to normalize here/somewhere // as we assume the type outlives assumptions only have rigid types :> + let cx = self.cx(); let clauses = rustc_type_ir::elaborate::elaborate( - self.cx(), + cx, reqs.into_iter().filter_map(|goal| goal.predicate.as_clause()), ); @@ -120,7 +121,7 @@ where }, ); - Some(Assumptions::new(type_outlives, region_outlives_builder.freeze())) + Some(Assumptions::new(cx, type_outlives, region_outlives_builder.freeze())) } #[instrument(level = "debug", skip(self), ret)] diff --git a/compiler/rustc_type_ir/src/region_constraint.rs b/compiler/rustc_type_ir/src/region_constraint.rs index 7b661c400b1ea..b0e931f5ab6bf 100644 --- a/compiler/rustc_type_ir/src/region_constraint.rs +++ b/compiler/rustc_type_ir/src/region_constraint.rs @@ -49,6 +49,7 @@ impl Default for TransitiveRelationBuilder { use crate::data_structures::IndexMap; use crate::fold::TypeSuperFoldable; use crate::inherent::*; +use crate::outlives::{Component, push_outlives_components}; use crate::relate::{Relate, RelateResult, TypeRelation, VarianceDiagInfo}; use crate::{ AliasTy, Binder, BoundRegion, BoundVar, BoundVariableKind, DebruijnIndex, InferCtxtLike, @@ -73,9 +74,50 @@ impl Assumptions { } pub fn new( + cx: I, type_outlives: Vec>>, region_outlives: TransitiveRelation>, ) -> Self { + // A `Ty: 'a` assumption also tells us that every region component of `Ty` outlives `'a`, + // e.g. `&'b u8: 'a` implies `'b: 'a`. Callers do not necessarily hand us an elaborated set + // of assumptions so we destructure them here, otherwise we'd fail to prove `'b: 'a` when + // leaving the binder these assumptions belong to. + // + // The type outlives assumptions are still kept around as they are required for proving + // placeholder and alias outlives. + // + // This mirrors `elaborate`, in particular in how it deals with binders: they're simply + // skipped, so `for<'c> Foo<'a, 'c>: 'b` still gives us `'a: 'b`. + let mut implied_region_outlives = vec![]; + for clause in &type_outlives { + let OutlivesClause(ty, r) = clause.clone().skip_binder(); + // Ignore `for<'a> Ty: 'a`. We could treat this as evidence for `Ty: 'static` but + // `elaborate` conservatively doesn't, so neither do we. + if r.is_bound() { + continue; + } + let mut components = Default::default(); + push_outlives_components(cx, ty, &mut components); + implied_region_outlives.extend(components.into_iter().filter_map(|c| match c { + // Regions bound *inside* of `ty` don't relate to anything in scope here. + Component::Region(c_r) if !c_r.is_bound() => Some((c_r, r)), + _ => None, + })); + } + + let region_outlives = if implied_region_outlives.is_empty() { + region_outlives + } else { + let mut builder = TransitiveRelationBuilder::default(); + for (r1, r2) in region_outlives.base_edges() { + builder.add(r1, r2); + } + for (r1, r2) in implied_region_outlives { + builder.add(r1, r2); + } + builder.freeze() + }; + Self { inverse_region_outlives: { let mut builder = TransitiveRelationBuilder::default(); diff --git a/tests/ui/assumptions_on_binders/same-universe-placeholder-outlives.rs b/tests/ui/assumptions_on_binders/same-universe-placeholder-outlives.rs index 6d292416cd4cf..56bbf8eacbbcd 100644 --- a/tests/ui/assumptions_on_binders/same-universe-placeholder-outlives.rs +++ b/tests/ui/assumptions_on_binders/same-universe-placeholder-outlives.rs @@ -40,6 +40,28 @@ core::test_binder_constraints! { } } +// `&'b u8: 'a` implies `'b: 'a`, so type outlives assumptions have to be destructured into +// region outlives assumptions. +core::test_binder_constraints! { + impl<> { + forall<'a, 'b> where &'b u8: 'a { + 'b: 'a + } expect { + } + } +} + +// Binders in a type outlives assumption are skipped rather than bailed on, so +// `for<'c> fn(&'c (), &'b u8): 'a` still gives us `'b: 'a`. +core::test_binder_constraints! { + impl<> { + forall<'a, 'b> where for<'c> fn(&'c (), &'b u8): 'a { + 'b: 'a + } expect { + } + } +} + // Discharging entailed constraints must not swallow the ones which still have to be lifted // into the outer universe. Here `'a: 'a` and `'b: 'a` are discharged inside the binder while // `'c: 'a` is lifted, as `'c` outlives every lower universe region that `'a` outlives. From fdc2acbb46d64fd4638168350a020d7759e12405 Mon Sep 17 00:00:00 2001 From: Joao Roberto Date: Sat, 29 Aug 2026 21:10:50 -0300 Subject: [PATCH 07/23] Evaluate reflexive region constraints at the root --- .../rustc_type_ir/src/region_constraint.rs | 27 +++++++++++++----- .../reflexive-outlives-in-root.rs | 28 +++++++++++++++++++ 2 files changed, 48 insertions(+), 7 deletions(-) create mode 100644 tests/ui/assumptions_on_binders/reflexive-outlives-in-root.rs diff --git a/compiler/rustc_type_ir/src/region_constraint.rs b/compiler/rustc_type_ir/src/region_constraint.rs index b0e931f5ab6bf..d0de852f60b3b 100644 --- a/compiler/rustc_type_ir/src/region_constraint.rs +++ b/compiler/rustc_type_ir/src/region_constraint.rs @@ -687,6 +687,8 @@ fn pull_region_outlives_constraints_out_of_universe< pulled_constraints.push(Or::new_leaf(c.clone())); } RegionOutlives(region_1, region_2, ()) => { + // Outlives is reflexive, so this holds no matter which universes are involved + // and regardless of whether we know the assumptions for `u`. if region_1 == region_2 { continue; } @@ -771,16 +773,27 @@ pub fn destructure_type_outlives_constraints_in_root< let mut destructured_constraints = Vec::new(); for c in &and.0 { match c { + // Outlives is reflexive. Discharging this here and not just when leaving a universe + // matters as constraints are also destructured in the root, where reflexive candidates + // are the whole reason an OR is satisfiable. E.g. `!T: 'a` with a `!T: 'a` assumption + // ends up as `Or([.., RegionOutlives('a, 'a)])`. + RegionOutlives(r1, r2, _) if r1 == r2 => {} Ambiguity(_) | RegionOutlives(..) => { destructured_constraints.push(Or::new_leaf(c.clone())) } - PlaceholderTyOutlives(ty, r, span) => destructured_constraints.push(Or::new( - regions_outlived_by_placeholder(*ty, assumptions, infcx.cx()).map( - move |assumption_r| { - And::new([RegionOutlives(assumption_r, *r, span.clone())]) - }, - ), - )), + PlaceholderTyOutlives(ty, r, span) => { + let candidates = + regions_outlived_by_placeholder(*ty, assumptions, infcx.cx()).collect::>(); + if candidates.contains(r) { + destructured_constraints.push(Or::new_true()); + } else { + destructured_constraints.push(Or::new(candidates.into_iter().map( + move |assumption_r| { + And::new([RegionOutlives(assumption_r, *r, span.clone())]) + }, + ))); + } + } AliasTyOutlivesViaEnv(bound_outlives, span) => { destructured_constraints.push( alias_outlives_candidates_from_assumptions( diff --git a/tests/ui/assumptions_on_binders/reflexive-outlives-in-root.rs b/tests/ui/assumptions_on_binders/reflexive-outlives-in-root.rs new file mode 100644 index 0000000000000..c6e7f025219dc --- /dev/null +++ b/tests/ui/assumptions_on_binders/reflexive-outlives-in-root.rs @@ -0,0 +1,28 @@ +//@ check-pass +//@ compile-flags: -Zassumptions-on-binders + +// Regression test for rust-lang/project-assumptions-on-binders#19, minimized from `syn`. +// +// Proving `I: '_` for the `&'_ self` receiver destructures to an OR over every region which +// `I` is known to outlive. Two things are needed for that OR to be satisfiable: +// +// - the implied bound `I: '_` from `&'_ self` has to be part of the root assumptions, not just +// the explicit `I: 'a` where clause, as `'a: '_` does not hold +// - the resulting `RegionOutlives('_, '_)` candidate has to be discharged, which happens when +// evaluating the constraint rather than when leaving a universe + +trait IterTrait<'a, T: 'a>: Iterator { + fn clone_box(&self) -> Box + 'a>; +} + +impl<'a, T, I> IterTrait<'a, T> for I +where + T: 'a, + I: Iterator + Clone + 'a, +{ + fn clone_box(&self) -> Box + 'a> { + Box::new(self.clone()) + } +} + +fn main() {} From 4b73b07cc424d06a9fb7c7ce1c18d55b4f1bfb42 Mon Sep 17 00:00:00 2001 From: Joao Roberto Date: Thu, 3 Sep 2026 10:11:05 -0300 Subject: [PATCH 08/23] Keep reflexive constraint handling self-contained --- .../rustc_hir_analysis/src/check/wfcheck.rs | 7 +-- .../src/infer/outlives/obligations.rs | 17 +----- .../eval_ctxt/solver_region_constraints.rs | 5 +- .../rustc_type_ir/src/region_constraint.rs | 60 ++----------------- .../reflexive-outlives-in-root.rs | 29 +++------ .../same-universe-placeholder-outlives.rs | 22 ------- 6 files changed, 19 insertions(+), 121 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 34f8ae70abac4..0dee9690737df 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -2406,11 +2406,8 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> { for &(r1, r2) in &body.region_outlives { builder.add(r1, r2); } - let assumptions = ty::region_constraint::Assumptions::new( - self.tcx(), - body.type_outlives, - builder.freeze(), - ); + let assumptions = + ty::region_constraint::Assumptions::new(body.type_outlives, builder.freeze()); self.infcx.insert_placeholder_assumptions(u, Some(assumptions)); self.check_test_binder_body(body.value); let solver_region_constraint = self.infcx.get_solver_region_constraint(); diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs index 23eb48d43dfb7..cbbf5e3c91c42 100644 --- a/compiler/rustc_infer/src/infer/outlives/obligations.rs +++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs @@ -234,22 +234,8 @@ impl<'tcx> InferCtxt<'tcx> { &self, outlives_env: &OutlivesEnvironment<'tcx>, ) { - // `known_type_outlives` only contains the explicit `Ty: 'a` where clauses. The implied - // bounds, e.g. `T: 'a` from a `&'a T` argument, are only tracked in `region_bound_pairs` - // so we have to pull them in separately. Without them we'd fail to prove `T: 'a` for a - // `&'a T` argument whenever the only explicit bound on `T` mentions a different region. - let mut known_type_outlives = outlives_env.known_type_outlives().to_vec(); - for &ty::OutlivesClause(kind, r) in outlives_env.region_bound_pairs() { - let ty = match kind { - GenericKind::Param(p) => Ty::new_param(self.tcx, p.index, p.name), - GenericKind::Placeholder(p) => Ty::new_placeholder(self.tcx, p), - GenericKind::Alias(alias) => alias.to_ty(self.tcx, ty::IsRigid::Yes), - }; - known_type_outlives.push(ty::Binder::dummy(ty::OutlivesClause(ty, r))); - } let assumptions = rustc_type_ir::region_constraint::Assumptions::new( - self.tcx, - known_type_outlives, + outlives_env.known_type_outlives().into_iter().cloned().collect(), outlives_env.free_region_map().relation.clone(), ); self.destructure_solver_region_constraints(assumptions, self); @@ -263,7 +249,6 @@ impl<'tcx> InferCtxt<'tcx> { region_outlives: TransitiveRelation, ) { let assumptions = region_constraint::Assumptions::new( - self.tcx, known_type_outlives.into_iter().cloned().collect(), region_outlives.maybe_map(|r| Some(Region::new_var(self.tcx, r))).unwrap(), ); diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/solver_region_constraints.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/solver_region_constraints.rs index d67e4cf0275bb..5a4daa5e44fc5 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/solver_region_constraints.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/solver_region_constraints.rs @@ -102,9 +102,8 @@ where // FIXME(-Zassumptions-on-binders): we need to normalize here/somewhere // as we assume the type outlives assumptions only have rigid types :> - let cx = self.cx(); let clauses = rustc_type_ir::elaborate::elaborate( - cx, + self.cx(), reqs.into_iter().filter_map(|goal| goal.predicate.as_clause()), ); @@ -121,7 +120,7 @@ where }, ); - Some(Assumptions::new(cx, type_outlives, region_outlives_builder.freeze())) + Some(Assumptions::new(type_outlives, region_outlives_builder.freeze())) } #[instrument(level = "debug", skip(self), ret)] diff --git a/compiler/rustc_type_ir/src/region_constraint.rs b/compiler/rustc_type_ir/src/region_constraint.rs index d0de852f60b3b..ff7b00fdbbd98 100644 --- a/compiler/rustc_type_ir/src/region_constraint.rs +++ b/compiler/rustc_type_ir/src/region_constraint.rs @@ -49,7 +49,6 @@ impl Default for TransitiveRelationBuilder { use crate::data_structures::IndexMap; use crate::fold::TypeSuperFoldable; use crate::inherent::*; -use crate::outlives::{Component, push_outlives_components}; use crate::relate::{Relate, RelateResult, TypeRelation, VarianceDiagInfo}; use crate::{ AliasTy, Binder, BoundRegion, BoundVar, BoundVariableKind, DebruijnIndex, InferCtxtLike, @@ -74,50 +73,9 @@ impl Assumptions { } pub fn new( - cx: I, type_outlives: Vec>>, region_outlives: TransitiveRelation>, ) -> Self { - // A `Ty: 'a` assumption also tells us that every region component of `Ty` outlives `'a`, - // e.g. `&'b u8: 'a` implies `'b: 'a`. Callers do not necessarily hand us an elaborated set - // of assumptions so we destructure them here, otherwise we'd fail to prove `'b: 'a` when - // leaving the binder these assumptions belong to. - // - // The type outlives assumptions are still kept around as they are required for proving - // placeholder and alias outlives. - // - // This mirrors `elaborate`, in particular in how it deals with binders: they're simply - // skipped, so `for<'c> Foo<'a, 'c>: 'b` still gives us `'a: 'b`. - let mut implied_region_outlives = vec![]; - for clause in &type_outlives { - let OutlivesClause(ty, r) = clause.clone().skip_binder(); - // Ignore `for<'a> Ty: 'a`. We could treat this as evidence for `Ty: 'static` but - // `elaborate` conservatively doesn't, so neither do we. - if r.is_bound() { - continue; - } - let mut components = Default::default(); - push_outlives_components(cx, ty, &mut components); - implied_region_outlives.extend(components.into_iter().filter_map(|c| match c { - // Regions bound *inside* of `ty` don't relate to anything in scope here. - Component::Region(c_r) if !c_r.is_bound() => Some((c_r, r)), - _ => None, - })); - } - - let region_outlives = if implied_region_outlives.is_empty() { - region_outlives - } else { - let mut builder = TransitiveRelationBuilder::default(); - for (r1, r2) in region_outlives.base_edges() { - builder.add(r1, r2); - } - for (r1, r2) in implied_region_outlives { - builder.add(r1, r2); - } - builder.freeze() - }; - Self { inverse_region_outlives: { let mut builder = TransitiveRelationBuilder::default(); @@ -687,12 +645,6 @@ fn pull_region_outlives_constraints_out_of_universe< pulled_constraints.push(Or::new_leaf(c.clone())); } RegionOutlives(region_1, region_2, ()) => { - // Outlives is reflexive, so this holds no matter which universes are involved - // and regardless of whether we know the assumptions for `u`. - if region_1 == region_2 { - continue; - } - let region_1_u = max_universe(infcx, region_1); let region_2_u = max_universe(infcx, region_2); @@ -773,17 +725,16 @@ pub fn destructure_type_outlives_constraints_in_root< let mut destructured_constraints = Vec::new(); for c in &and.0 { match c { - // Outlives is reflexive. Discharging this here and not just when leaving a universe - // matters as constraints are also destructured in the root, where reflexive candidates - // are the whole reason an OR is satisfiable. E.g. `!T: 'a` with a `!T: 'a` assumption - // ends up as `Or([.., RegionOutlives('a, 'a)])`. + // Root constraints never go through `pull_region_outlives_constraints_out_of_universe`. + // A reflexive leaf may be the candidate which makes a root OR true, so discharge it here + // instead of requiring the remaining candidates to hold. RegionOutlives(r1, r2, _) if r1 == r2 => {} Ambiguity(_) | RegionOutlives(..) => { destructured_constraints.push(Or::new_leaf(c.clone())) } PlaceholderTyOutlives(ty, r, span) => { - let candidates = - regions_outlived_by_placeholder(*ty, assumptions, infcx.cx()).collect::>(); + let candidates = regions_outlived_by_placeholder(*ty, assumptions, infcx.cx()) + .collect::>(); if candidates.contains(r) { destructured_constraints.push(Or::new_true()); } else { @@ -1059,7 +1010,6 @@ pub fn regions_outlived_by( r: Region, assumptions: &Assumptions, ) -> impl Iterator> { - // FIXME(-Zassumptions-on-binders): do we need to be adding the reflexive edge here? assumptions.region_outlives.reachable_from(r).into_iter().chain([r]) } diff --git a/tests/ui/assumptions_on_binders/reflexive-outlives-in-root.rs b/tests/ui/assumptions_on_binders/reflexive-outlives-in-root.rs index c6e7f025219dc..9cac9e0eaeed3 100644 --- a/tests/ui/assumptions_on_binders/reflexive-outlives-in-root.rs +++ b/tests/ui/assumptions_on_binders/reflexive-outlives-in-root.rs @@ -1,27 +1,16 @@ //@ check-pass //@ compile-flags: -Zassumptions-on-binders -// Regression test for rust-lang/project-assumptions-on-binders#19, minimized from `syn`. -// -// Proving `I: '_` for the `&'_ self` receiver destructures to an OR over every region which -// `I` is known to outlive. Two things are needed for that OR to be satisfiable: -// -// - the implied bound `I: '_` from `&'_ self` has to be part of the root assumptions, not just -// the explicit `I: 'a` where clause, as `'a: '_` does not hold -// - the resulting `RegionOutlives('_, '_)` candidate has to be discharged, which happens when -// evaluating the constraint rather than when leaving a universe +#![feature(test_binder_constraints, non_lifetime_binders)] +#![expect(incomplete_features)] -trait IterTrait<'a, T: 'a>: Iterator { - fn clone_box(&self) -> Box + 'a>; -} - -impl<'a, T, I> IterTrait<'a, T> for I -where - T: 'a, - I: Iterator + Clone + 'a, -{ - fn clone_box(&self) -> Box + 'a> { - Box::new(self.clone()) +// Root type outlives constraints are destructured into an OR over every region the type is known +// to outlive. The reflexive `'b: 'b` candidate makes this OR true even though the unrelated +// `'a: 'b` candidate does not hold. Root constraints never go through the universe-pulling code, +// so evaluation has to recognize the reflexive candidate itself. +core::test_binder_constraints! { + impl<'a, 'b, T: 'a + 'b> { + T: 'b } } diff --git a/tests/ui/assumptions_on_binders/same-universe-placeholder-outlives.rs b/tests/ui/assumptions_on_binders/same-universe-placeholder-outlives.rs index 56bbf8eacbbcd..6d292416cd4cf 100644 --- a/tests/ui/assumptions_on_binders/same-universe-placeholder-outlives.rs +++ b/tests/ui/assumptions_on_binders/same-universe-placeholder-outlives.rs @@ -40,28 +40,6 @@ core::test_binder_constraints! { } } -// `&'b u8: 'a` implies `'b: 'a`, so type outlives assumptions have to be destructured into -// region outlives assumptions. -core::test_binder_constraints! { - impl<> { - forall<'a, 'b> where &'b u8: 'a { - 'b: 'a - } expect { - } - } -} - -// Binders in a type outlives assumption are skipped rather than bailed on, so -// `for<'c> fn(&'c (), &'b u8): 'a` still gives us `'b: 'a`. -core::test_binder_constraints! { - impl<> { - forall<'a, 'b> where for<'c> fn(&'c (), &'b u8): 'a { - 'b: 'a - } expect { - } - } -} - // Discharging entailed constraints must not swallow the ones which still have to be lifted // into the outer universe. Here `'a: 'a` and `'b: 'a` are discharged inside the binder while // `'c: 'a` is lifted, as `'c` outlives every lower universe region that `'a` outlives. From ca6e6f04149170fd7ebd78d6559b03a5dedcc6ae Mon Sep 17 00:00:00 2001 From: Joao Roberto Date: Mon, 7 Sep 2026 10:07:09 -0300 Subject: [PATCH 09/23] Drop trivially true region constraints when canonicalizing A reflexive `'a: 'a` leaf is always satisfied, so filter it out in `And::new` instead of pattern matching for it in the places which happen to build such a constraint. An AND which ends up empty is trivially true, which makes the OR containing it true. This is how a reflexive candidate discharges a root type outlives constraint, so `destructure_type_outlives_constraints_in_root` no longer has to look at region outlives leaves at all. --- .../rustc_type_ir/src/region_constraint.rs | 46 +++++++++++-------- .../reflexive-outlives-in-root.rs | 4 +- .../test-infra-fails-properly.rs | 2 +- .../test-infra-fails-properly.stderr | 4 +- 4 files changed, 32 insertions(+), 24 deletions(-) diff --git a/compiler/rustc_type_ir/src/region_constraint.rs b/compiler/rustc_type_ir/src/region_constraint.rs index ff7b00fdbbd98..fcea7db55df1a 100644 --- a/compiler/rustc_type_ir/src/region_constraint.rs +++ b/compiler/rustc_type_ir/src/region_constraint.rs @@ -165,6 +165,7 @@ impl LeafRegionC /// An OR of AND of LEAF constraints. Always in "canonical form" meaning: /// - No two ANDs are equivalent /// - All ANDs are in canonical form +/// - If any AND is empty, i.e. trivially true, it is the only AND pub struct Or(pub Box<[And]>); impl Or { pub fn with_spans( @@ -204,6 +205,13 @@ impl Or { let mut new_ands: Vec> = Vec::new(); for and in ands { + // An empty AND is trivially true, which makes the whole OR true no matter what the + // other candidates are. `And::new` discards leaf constraints which are trivially + // true, so this is how e.g. a reflexive `'a: 'a` candidate discharges an OR. + if and.0.is_empty() { + return Self::new_true(); + } + if new_ands.iter().all(|c| !c.is_and_equivalent_to(&and)) { new_ands.push(and) } @@ -217,7 +225,7 @@ impl Or { } pub fn new_leaf(l: LeafRegionConstraint) -> Self { - Or(Box::new([And(Box::new([l]))])) + Or::new([And::new([l])]) } pub fn build_and(a: Or, b: Or) -> Self { @@ -249,6 +257,7 @@ impl Or { #[cfg_attr(feature = "nightly", derive(StableHash_NoContext))] /// An AND of leaf constraints. Always in "canonical form", meaning: /// - No leaf constraints are present twice in this AND +/// - No leaf constraint is trivially true, i.e. a reflexive `'a: 'a` pub struct And(pub Box<[LeafRegionConstraint]>); impl And { pub fn with_spans( @@ -264,6 +273,15 @@ impl And { And(i .into_iter() .filter(|leaf| { + // Outlives is reflexive so a `'a: 'a` leaf is always true and carries no + // information. Dropping it here keeps the rest of the code from having to special + // case it, and is what lets an OR with a reflexive candidate be recognized as true. + if let LeafRegionConstraint::RegionOutlives(r1, r2, _) = leaf + && r1 == r2 + { + return false; + } + if seen.contains(&leaf.clone().without_span()) { false } else { @@ -409,7 +427,7 @@ impl RegionConst } pub fn new_leaf(l: LeafRegionConstraint) -> Self { - RegionConstraint { and_constraint: And(Box::new([l])), or_constraint: Or::new_true() } + RegionConstraint { and_constraint: And::new([l]), or_constraint: Or::new_true() } } } @@ -725,26 +743,16 @@ pub fn destructure_type_outlives_constraints_in_root< let mut destructured_constraints = Vec::new(); for c in &and.0 { match c { - // Root constraints never go through `pull_region_outlives_constraints_out_of_universe`. - // A reflexive leaf may be the candidate which makes a root OR true, so discharge it here - // instead of requiring the remaining candidates to hold. - RegionOutlives(r1, r2, _) if r1 == r2 => {} Ambiguity(_) | RegionOutlives(..) => { destructured_constraints.push(Or::new_leaf(c.clone())) } - PlaceholderTyOutlives(ty, r, span) => { - let candidates = regions_outlived_by_placeholder(*ty, assumptions, infcx.cx()) - .collect::>(); - if candidates.contains(r) { - destructured_constraints.push(Or::new_true()); - } else { - destructured_constraints.push(Or::new(candidates.into_iter().map( - move |assumption_r| { - And::new([RegionOutlives(assumption_r, *r, span.clone())]) - }, - ))); - } - } + PlaceholderTyOutlives(ty, r, span) => destructured_constraints.push(Or::new( + regions_outlived_by_placeholder(*ty, assumptions, infcx.cx()).map( + move |assumption_r| { + And::new([RegionOutlives(assumption_r, *r, span.clone())]) + }, + ), + )), AliasTyOutlivesViaEnv(bound_outlives, span) => { destructured_constraints.push( alias_outlives_candidates_from_assumptions( diff --git a/tests/ui/assumptions_on_binders/reflexive-outlives-in-root.rs b/tests/ui/assumptions_on_binders/reflexive-outlives-in-root.rs index 9cac9e0eaeed3..641ac3951d76a 100644 --- a/tests/ui/assumptions_on_binders/reflexive-outlives-in-root.rs +++ b/tests/ui/assumptions_on_binders/reflexive-outlives-in-root.rs @@ -6,8 +6,8 @@ // Root type outlives constraints are destructured into an OR over every region the type is known // to outlive. The reflexive `'b: 'b` candidate makes this OR true even though the unrelated -// `'a: 'b` candidate does not hold. Root constraints never go through the universe-pulling code, -// so evaluation has to recognize the reflexive candidate itself. +// `'a: 'b` candidate does not hold. Reflexive leaves are dropped when building an AND, which +// leaves an empty, i.e. trivially true, AND as one of the candidates of the OR. core::test_binder_constraints! { impl<'a, 'b, T: 'a + 'b> { T: 'b diff --git a/tests/ui/assumptions_on_binders/test-infra-fails-properly.rs b/tests/ui/assumptions_on_binders/test-infra-fails-properly.rs index 240b64e770f51..97629627ad556 100644 --- a/tests/ui/assumptions_on_binders/test-infra-fails-properly.rs +++ b/tests/ui/assumptions_on_binders/test-infra-fails-properly.rs @@ -60,7 +60,7 @@ core::test_binder_constraints! { } expect { or { 'c: 'b, - 'c: 'c, + 'b: 'c, //~^ ERROR forall expect clause failed } } diff --git a/tests/ui/assumptions_on_binders/test-infra-fails-properly.stderr b/tests/ui/assumptions_on_binders/test-infra-fails-properly.stderr index 2931a37c0f340..ab025b0e0b9d6 100644 --- a/tests/ui/assumptions_on_binders/test-infra-fails-properly.stderr +++ b/tests/ui/assumptions_on_binders/test-infra-fails-properly.stderr @@ -53,7 +53,7 @@ LL | T: 'a, error: forall expect clause failed --> $DIR/test-infra-fails-properly.rs:63:17 | -LL | 'c: 'c, +LL | 'b: 'c, | ^^^^^^ | note: constraint from here @@ -62,7 +62,7 @@ note: constraint from here LL | forall<'a> where 'b: 'a { | ^^^^^^ = note: expected: RegionOutlives( - 'c/#1, + 'b/#0, 'c/#1, $DIR/test-infra-fails-properly.rs:63:17: 63:23 (#0), ) From b532a132d668cf7899a1720fe1eefb358bf17d11 Mon Sep 17 00:00:00 2001 From: Joao Roberto Date: Tue, 8 Sep 2026 10:03:23 -0300 Subject: [PATCH 10/23] Note that OR canonicalization could drop superset ANDs --- compiler/rustc_type_ir/src/region_constraint.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/compiler/rustc_type_ir/src/region_constraint.rs b/compiler/rustc_type_ir/src/region_constraint.rs index fcea7db55df1a..da7b0be16cf64 100644 --- a/compiler/rustc_type_ir/src/region_constraint.rs +++ b/compiler/rustc_type_ir/src/region_constraint.rs @@ -166,6 +166,12 @@ impl LeafRegionC /// - No two ANDs are equivalent /// - All ANDs are in canonical form /// - If any AND is empty, i.e. trivially true, it is the only AND +/// +/// FIXME(-Zassumptions-on-binders): We should consider a more general canonical form which also +/// drops any AND that is a superset of another AND. Proving the superset requires strictly more +/// than proving the subset, so it can never be the candidate which makes the OR hold. E.g. +/// `OR(AND('a: 'b), AND('a: 'b, 'b: 'c))` really ought to just be `OR(AND('a: 'b))`. Only keeping +/// an empty AND is the degenerate case of that rule. pub struct Or(pub Box<[And]>); impl Or { pub fn with_spans( @@ -212,6 +218,10 @@ impl Or { return Self::new_true(); } + // FIXME(-Zassumptions-on-binders): We only discard an AND which is equivalent to one + // we already have. More generally we should discard any AND which is a superset of + // another, as it requires strictly more to hold. E.g. the second AND in + // `OR(AND('a: 'b), AND('a: 'b, 'b: 'c))` is never the one which makes the OR true. if new_ands.iter().all(|c| !c.is_and_equivalent_to(&and)) { new_ands.push(and) } From ebff12b6980fc65de1826fb39a11825a7f65e754 Mon Sep 17 00:00:00 2001 From: zakrad <49591476+zakrad@users.noreply.github.com> Date: Mon, 14 Sep 2026 11:06:57 +0330 Subject: [PATCH 11/23] Add regression test for first token source file from TokenStream FromStr --- .../auxiliary/span-first-token-file-48944.rs | 13 +++++++++++++ tests/ui/proc-macro/span-first-token-file-48944.rs | 13 +++++++++++++ 2 files changed, 26 insertions(+) create mode 100644 tests/ui/proc-macro/auxiliary/span-first-token-file-48944.rs create mode 100644 tests/ui/proc-macro/span-first-token-file-48944.rs diff --git a/tests/ui/proc-macro/auxiliary/span-first-token-file-48944.rs b/tests/ui/proc-macro/auxiliary/span-first-token-file-48944.rs new file mode 100644 index 0000000000000..562bd99fdcc72 --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/span-first-token-file-48944.rs @@ -0,0 +1,13 @@ +extern crate proc_macro; + +use proc_macro::TokenStream; + +// Parses a multi-token string with `FromStr` and checks that every token reports the same +// source file. The first token used to get a different file than the rest. +#[proc_macro] +pub fn check_first_token_file(_: TokenStream) -> TokenStream { + let tokens: Vec<_> = "aaa\nbbb".parse::().unwrap().into_iter().collect(); + assert_eq!(tokens.len(), 2); + assert_eq!(tokens[0].span().file(), tokens[1].span().file()); + TokenStream::new() +} diff --git a/tests/ui/proc-macro/span-first-token-file-48944.rs b/tests/ui/proc-macro/span-first-token-file-48944.rs new file mode 100644 index 0000000000000..b65109a81f107 --- /dev/null +++ b/tests/ui/proc-macro/span-first-token-file-48944.rs @@ -0,0 +1,13 @@ +//! Regression test for . +//! +//! The first token parsed from a string with `FromStr` for `TokenStream` used to report a +//! different source file than the tokens after it. + +//@ check-pass +//@ proc-macro: span-first-token-file-48944.rs + +extern crate span_first_token_file_48944; + +span_first_token_file_48944::check_first_token_file!(); + +fn main() {} From e478abb6124a09fa44d093bed1ad127a74ed4c43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 21 Sep 2026 14:48:04 +0000 Subject: [PATCH 12/23] Point at `'static` obligations from an fn being called Add this note to lifetime errors: ```text error[E0521]: borrowed data escapes outside of function --> $DIR/static-impl-obligation.rs:163:9 | LL | fn bar<'a>(x: &'a &'a u32) { | -- - `x` is a reference that is only valid in the function body | | | lifetime `'a` defined here LL | let y: &dyn Foo = x; LL | y.hello(); | ^^^^^^^^^ | | | `x` escapes the function body here | argument requires that `'a` must outlive `'static` | note: `'static` requirement for `<(dyn o::Foo + 'static)>::hello` introduced here --> $DIR/static-impl-obligation.rs:158:40 | LL | impl dyn Foo + 'static where Self: 'static { | ^^^^^^^ `'static` requirement introduced here LL | fn hello(&'static self) where Self: 'static {} | ^^^^^^^ `'static` requirement introduced here ``` This currently only accounts for explicit bounds, other obligations like those arising from `Self` in a `impl dyn Trait {}` or from the receiver in `fn foo(&'static self)` are not accounted for. --- .../src/diagnostics/region_errors.rs | 88 +++ .../ui/async-await/issues/issue-62097.stderr | 8 + tests/ui/async-await/issues/issue-72312.rs | 2 + .../ui/async-await/issues/issue-72312.stderr | 8 +- tests/ui/borrowck/issue-103624.stderr | 6 + ...g-lifetime-but-unused-not-mentioned.stderr | 6 + ...bounds-static-cant-capture-borrowed.stderr | 6 + .../ui/coroutine/resume-arg-outlives-2.stderr | 9 + tests/ui/lifetimes/static-impl-obligation.rs | 290 ++++++++++ .../lifetimes/static-impl-obligation.stderr | 537 ++++++++++++++++++ .../regions-static-bound-on-type-param.rs | 7 + .../regions-static-bound-on-type-param.stderr | 22 + tests/ui/regions/regions-static-bound.stderr | 14 + 13 files changed, 1002 insertions(+), 1 deletion(-) create mode 100644 tests/ui/lifetimes/static-impl-obligation.rs create mode 100644 tests/ui/lifetimes/static-impl-obligation.stderr create mode 100644 tests/ui/regions/regions-static-bound-on-type-param.rs create mode 100644 tests/ui/regions/regions-static-bound-on-type-param.stderr diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index 414f8dd58d439..a8ba8127dd83a 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -6,6 +6,7 @@ use rustc_hir as hir; use rustc_hir::GenericBound::Trait; use rustc_hir::QPath::Resolved; use rustc_hir::WherePredicateKind::BoundPredicate; +use rustc_hir::def::DefKind; use rustc_hir::def::Res::Def; use rustc_hir::def_id::DefId; use rustc_hir::intravisit::Visitor; @@ -391,6 +392,89 @@ impl<'diag, 'tcx> MirBorrowckCtxt<'_, 'diag, 'tcx> { outlives_suggestion.add_suggestion(self); } + /// Point at `'static` obligations from the item being called. + /// + /// ```text + /// error[E0521]: borrowed data escapes outside of function + /// --> $DIR/static-impl-obligation.rs:163:9 + /// | + /// LL | fn bar<'a>(x: &'a &'a u32) { + /// | -- - `x` is a reference that is only valid in the function body + /// | | + /// | lifetime `'a` defined here + /// LL | let y: &dyn Foo = x; + /// LL | y.hello(); + /// | ^^^^^^^^^ + /// | | + /// | `x` escapes the function body here + /// | argument requires that `'a` must outlive `'static` + /// | + /// note: `'static` requirement for `<(dyn o::Foo + 'static)>::hello` introduced here + /// --> $DIR/static-impl-obligation.rs:158:40 + /// | + /// LL | impl dyn Foo + 'static where Self: 'static { + /// | ^^^^^^^ `'static` requirement introduced here + /// LL | fn hello(&'static self) where Self: 'static {} + /// | ^^^^^^^ `'static` requirement introduced here + /// ``` + fn explain_impl_static_obligation( + &self, + diag: &mut Diag<'_>, + ty: Ty<'tcx>, + outlived_fr: RegionVid, + ) { + let tcx = self.infcx.tcx; + if self.regioncx.to_error_region(outlived_fr) != Some(tcx.lifetimes.re_static) { + return; + } + let ty::FnDef(def_id, args) = ty.kind() else { + return; + }; + let Ok(Some(instance)) = ty::Instance::try_resolve( + tcx, + self.infcx.typing_env(self.infcx.param_env), + *def_id, + self.infcx.deeply_resolve_ignoring_regions(args.no_bound_vars().unwrap()), + ) else { + return; + }; + let def_id = instance.def_id(); + let bounds = + tcx.clauses_of(def_id) + .instantiate(tcx, instance.args) + .into_iter() + .map(|(c, sp)| (c.skip_norm_wip().as_predicate(), sp)) + .filter(|(pred, _)| match pred.kind().skip_binder() { + ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives( + ty::OutlivesClause(_, lt), + )) + | ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives( + ty::OutlivesClause(_, lt), + )) if lt.is_static() => true, + _ => false, + }) + .map(|(_, sp)| sp) + .collect::>(); + if !bounds.is_empty() { + let mut multispan: MultiSpan = bounds.clone().into(); + for span in bounds { + multispan.push_span_label(span, "lifetime requirement introduced here"); + } + multispan.push_span_context(tcx.def_span(def_id).shrink_to_lo()); + let parent = tcx.parent(def_id); + if let DefKind::Impl { .. } | DefKind::Trait = tcx.def_kind(parent) { + multispan.push_span_context(tcx.def_span(parent).shrink_to_lo()); + } + diag.span_note( + multispan, + format!( + "`'static` lifetime requirement from `{}` introduced here", + tcx.def_path_str(def_id) + ), + ); + } + } + /// Report that `longer_fr: error_vid`, which doesn't hold, /// where `longer_fr` is a placeholder. fn report_erroneous_rvid_reaches_placeholder( @@ -503,6 +587,10 @@ impl<'diag, 'tcx> MirBorrowckCtxt<'_, 'diag, 'tcx> { } }; + if let ConstraintCategory::CallArgument(Some(ty)) = category { + self.explain_impl_static_obligation(&mut diag, ty, outlived_fr); + } + match variance_info { ty::VarianceDiagInfo::None => {} ty::VarianceDiagInfo::Invariant { ty, param_index } => { diff --git a/tests/ui/async-await/issues/issue-62097.stderr b/tests/ui/async-await/issues/issue-62097.stderr index 1422d315f88b0..0edb27f059e64 100644 --- a/tests/ui/async-await/issues/issue-62097.stderr +++ b/tests/ui/async-await/issues/issue-62097.stderr @@ -11,6 +11,14 @@ LL | foo(|| self.bar()).await; | | | `self` escapes the method body here | argument requires that `'1` must outlive `'static` + | +note: `'static` lifetime requirement from `foo` introduced here + --> $DIR/issue-62097.rs:4:19 + | +LL | async fn foo(fun: F) +LL | where +LL | F: FnOnce() + 'static + | ^^^^^^^ lifetime requirement introduced here error[E0373]: closure may outlive the current function, but it borrows `self`, which is owned by the current function --> $DIR/issue-62097.rs:13:13 diff --git a/tests/ui/async-await/issues/issue-72312.rs b/tests/ui/async-await/issues/issue-72312.rs index c2f01071f4a42..e2202fe628acf 100644 --- a/tests/ui/async-await/issues/issue-72312.rs +++ b/tests/ui/async-await/issues/issue-72312.rs @@ -1,5 +1,7 @@ //@ edition:2018 fn require_static(val: T) -> T { + //~^ NOTE: `'static` lifetime requirement from `require_static` introduced here + //~| NOTE: lifetime requirement introduced here val } diff --git a/tests/ui/async-await/issues/issue-72312.stderr b/tests/ui/async-await/issues/issue-72312.stderr index 33092a1abd3ab..5dbe7c18005ba 100644 --- a/tests/ui/async-await/issues/issue-72312.stderr +++ b/tests/ui/async-await/issues/issue-72312.stderr @@ -1,5 +1,5 @@ error[E0521]: borrowed data escapes outside of method - --> $DIR/issue-72312.rs:12:9 + --> $DIR/issue-72312.rs:14:9 | LL | pub async fn start(&self) { | ----- @@ -14,6 +14,12 @@ LL | | }); | | | | |__________`self` escapes the method body here | argument requires that `'1` must outlive `'static` + | +note: `'static` lifetime requirement from `require_static` introduced here + --> $DIR/issue-72312.rs:2:22 + | +LL | fn require_static(val: T) -> T { + | ^^^^^^^ lifetime requirement introduced here error: aborting due to 1 previous error diff --git a/tests/ui/borrowck/issue-103624.stderr b/tests/ui/borrowck/issue-103624.stderr index 77e961ee48fc2..cbcbbca813ca3 100644 --- a/tests/ui/borrowck/issue-103624.stderr +++ b/tests/ui/borrowck/issue-103624.stderr @@ -16,6 +16,12 @@ LL | | }) | | | | |__________`self` escapes the method body here | argument requires that `'1` must outlive `'static` + | +note: `'static` lifetime requirement from `spawn_blocking` introduced here + --> $DIR/issue-103624.rs:7:64 + | +LL | async fn spawn_blocking(f: impl (Fn() -> T) + Send + Sync + 'static) -> T { + | ^^^^^^^ lifetime requirement introduced here error[E0507]: cannot move out of `self.b`, as `self` is a captured variable in an `Fn` closure --> $DIR/issue-103624.rs:16:13 diff --git a/tests/ui/borrowck/var-matching-lifetime-but-unused-not-mentioned.stderr b/tests/ui/borrowck/var-matching-lifetime-but-unused-not-mentioned.stderr index a3cde891b7cac..e43e257cd9d5b 100644 --- a/tests/ui/borrowck/var-matching-lifetime-but-unused-not-mentioned.stderr +++ b/tests/ui/borrowck/var-matching-lifetime-but-unused-not-mentioned.stderr @@ -11,6 +11,12 @@ LL | consume(c); | | | `used_arg` escapes the function body here | argument requires that `'a` must outlive `'static` + | +note: `'static` lifetime requirement from `consume` introduced here + --> $DIR/var-matching-lifetime-but-unused-not-mentioned.rs:5:15 + | +LL | fn consume(_: T) {} + | ^^^^^^^ lifetime requirement introduced here error: aborting due to 1 previous error diff --git a/tests/ui/closures/closure-bounds-static-cant-capture-borrowed.stderr b/tests/ui/closures/closure-bounds-static-cant-capture-borrowed.stderr index 654ca665ae09c..37316a331779a 100644 --- a/tests/ui/closures/closure-bounds-static-cant-capture-borrowed.stderr +++ b/tests/ui/closures/closure-bounds-static-cant-capture-borrowed.stderr @@ -14,6 +14,12 @@ LL | | }) | | | | |______`x` escapes the function body here | argument requires that `'1` must outlive `'static` + | +note: `'static` lifetime requirement from `bar` introduced here + --> $DIR/closure-bounds-static-cant-capture-borrowed.rs:2:39 + | +LL | fn bar(blk: F) where F: FnOnce() + 'static { + | ^^^^^^^ lifetime requirement introduced here error[E0373]: closure may outlive the current function, but it borrows `x`, which is owned by the current function --> $DIR/closure-bounds-static-cant-capture-borrowed.rs:6:9 diff --git a/tests/ui/coroutine/resume-arg-outlives-2.stderr b/tests/ui/coroutine/resume-arg-outlives-2.stderr index 9f6aab8d97ba7..49d3fee47fa9d 100644 --- a/tests/ui/coroutine/resume-arg-outlives-2.stderr +++ b/tests/ui/coroutine/resume-arg-outlives-2.stderr @@ -15,6 +15,15 @@ LL | | }) | | | | |______`s` escapes the function body here | argument requires that `'not_static` must outlive `'static` + | +note: `'static` lifetime requirement from `spawn` introduced here + --> $SRC_DIR/std/src/thread/functions.rs:LL:COL + ::: $SRC_DIR/std/src/thread/functions.rs:LL:COL + | + = note: lifetime requirement introduced here + ::: $SRC_DIR/std/src/thread/functions.rs:LL:COL + | + = note: lifetime requirement introduced here error: aborting due to 1 previous error diff --git a/tests/ui/lifetimes/static-impl-obligation.rs b/tests/ui/lifetimes/static-impl-obligation.rs new file mode 100644 index 0000000000000..106f300bb2352 --- /dev/null +++ b/tests/ui/lifetimes/static-impl-obligation.rs @@ -0,0 +1,290 @@ +mod a { + trait Foo {} + impl<'a> Foo for &'a u32 {} + impl dyn Foo { + fn hello(&self) {} + } + fn bar<'a>(x: &'a &'a u32) { + let y: &dyn Foo = x; + y.hello(); //~ ERROR borrowed data escapes outside of function + } +} +mod b { + trait Foo {} + impl<'a> Foo for &'a u32 {} + impl dyn Foo { + fn hello(&'static self) {} + } + fn bar<'a>(x: &'a &'a u32) { + let y: &dyn Foo = x; + y.hello(); //~ ERROR borrowed data escapes outside of function + } +} +mod c { + trait Foo {} + impl<'a> Foo for &'a u32 {} + impl dyn Foo { + fn hello(&'static self) where Self: 'static {} + } + fn bar<'a>(x: &'a &'a u32) { + let y: &dyn Foo = x; + y.hello(); //~ ERROR borrowed data escapes outside of function + } +} +mod d { + trait Foo {} + impl<'a> Foo for &'a u32 {} + impl dyn Foo { + fn hello(&self) where Self: 'static {} + } + fn bar<'a>(x: &'a &'a u32) { + let y: &dyn Foo = x; + y.hello(); //~ ERROR borrowed data escapes outside of function + } +} +mod e { + trait Foo {} + impl<'a> Foo for &'a u32 {} + impl dyn Foo + 'static { + fn hello(&self) {} + } + fn bar<'a>(x: &'a &'a u32) { + let y: &dyn Foo = x; + y.hello(); //~ ERROR borrowed data escapes outside of function + } +} +mod f { + trait Foo {} + impl<'a> Foo for &'a u32 {} + impl dyn Foo + 'static { + fn hello(&'static self) {} + } + fn bar<'a>(x: &'a &'a u32) { + let y: &dyn Foo = x; + y.hello(); //~ ERROR borrowed data escapes outside of function + } +} +mod g { + trait Foo {} + impl<'a> Foo for &'a u32 {} + impl dyn Foo + 'static { + fn hello(&'static self) where Self: 'static {} + } + fn bar<'a>(x: &'a &'a u32) { + let y: &dyn Foo = x; + y.hello(); //~ ERROR borrowed data escapes outside of function + } +} +mod h { + trait Foo {} + impl<'a> Foo for &'a u32 {} + impl dyn Foo + 'static { + fn hello(&self) where Self: 'static {} + } + fn bar<'a>(x: &'a &'a u32) { + let y: &dyn Foo = x; + y.hello(); //~ ERROR borrowed data escapes outside of function + } +} +mod i { + trait Foo {} + impl<'a> Foo for &'a u32 {} + impl dyn Foo where Self: 'static { + fn hello(&self) {} + } + fn bar<'a>(x: &'a &'a u32) { + let y: &dyn Foo = x; + y.hello(); //~ ERROR borrowed data escapes outside of function + } +} +mod j { + trait Foo {} + impl<'a> Foo for &'a u32 {} + impl dyn Foo where Self: 'static { + fn hello(&'static self) {} + } + fn bar<'a>(x: &'a &'a u32) { + let y: &dyn Foo = x; + y.hello(); //~ ERROR borrowed data escapes outside of function + } +} +mod k { + trait Foo {} + impl<'a> Foo for &'a u32 {} + impl dyn Foo where Self: 'static { + fn hello(&'static self) where Self: 'static {} + } + fn bar<'a>(x: &'a &'a u32) { + let y: &dyn Foo = x; + y.hello(); //~ ERROR borrowed data escapes outside of function + } +} +mod l { + trait Foo {} + impl<'a> Foo for &'a u32 {} + impl dyn Foo where Self: 'static { + fn hello(&self) where Self: 'static {} + } + fn bar<'a>(x: &'a &'a u32) { + let y: &dyn Foo = x; + y.hello(); //~ ERROR borrowed data escapes outside of function + } +} +mod m { + trait Foo {} + impl<'a> Foo for &'a u32 {} + impl dyn Foo + 'static where Self: 'static { + fn hello(&self) {} + } + fn bar<'a>(x: &'a &'a u32) { + let y: &dyn Foo = x; + y.hello(); //~ ERROR borrowed data escapes outside of function + } +} +mod n { + trait Foo {} + impl<'a> Foo for &'a u32 {} + impl dyn Foo + 'static where Self: 'static { + fn hello(&'static self) {} + } + fn bar<'a>(x: &'a &'a u32) { + let y: &dyn Foo = x; + y.hello(); //~ ERROR borrowed data escapes outside of function + } +} +mod o { + trait Foo {} + impl<'a> Foo for &'a u32 {} + impl dyn Foo + 'static where Self: 'static { + fn hello(&'static self) where Self: 'static {} + } + fn bar<'a>(x: &'a &'a u32) { + let y: &dyn Foo = x; + y.hello(); //~ ERROR borrowed data escapes outside of function + } +} +mod p { + trait Foo {} + impl<'a> Foo for &'a u32 {} + impl dyn Foo + 'static where Self: 'static { + fn hello(&self) where Self: 'static {} + } + fn bar<'a>(x: &'a &'a u32) { + let y: &dyn Foo = x; + y.hello(); //~ ERROR borrowed data escapes outside of function + } +} +mod q { + struct Foo {} + impl Foo { + fn hello(&'static self) {} + } + fn bar<'a>(x: &'a &'a Foo) { + x.hello(); //~ ERROR borrowed data escapes outside of function + } +} +mod r { + struct Foo {} + impl Foo { + fn hello(&'static self) where Self: 'static {} + } + fn bar<'a>(x: &'a &'a Foo) { + x.hello(); //~ ERROR borrowed data escapes outside of function + } +} +mod s { + trait Foo {} + impl<'a> Foo for &'a u32 {} + + trait Trait { fn hello(&self) {} } + + impl Trait for dyn Foo { + fn hello(&self) {} + } + fn convert<'a>(x: &'a &'a u32) { + let y: &dyn Foo = x; + y.hello(); //~ ERROR borrowed data escapes outside of function + } +} +mod t { + trait OtherTrait<'a> {} + impl<'a> OtherTrait<'a> for &'a () {} + + trait ObjectTrait {} + trait MyTrait where Self: 'static { + fn use_self(&self) -> &() where Self: 'static { panic!() } + } + trait Irrelevant { + fn use_self(&self) -> &() { panic!() } + } + + impl MyTrait for dyn ObjectTrait + '_ {} //~ ERROR lifetime bound not satisfied + //~^ ERROR: cannot infer an appropriate lifetime for lifetime parameter `'_` + + fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { + val.use_self() //~ ERROR borrowed data escapes + } +} +mod u { + trait OtherTrait<'a> {} + impl<'a> OtherTrait<'a> for &'a () {} + + trait ObjectTrait {} + trait MyTrait { + fn use_self(&self) -> &() where Self: 'static { panic!() } + } + trait Irrelevant { + fn use_self(&self) -> &() { panic!() } + } + + impl MyTrait for dyn ObjectTrait + '_ {} + + fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { + val.use_self() //~ ERROR borrowed data escapes + } +} +mod v { + trait OtherTrait<'a> {} + impl<'a> OtherTrait<'a> for &'a () {} + + trait ObjectTrait {} + trait MyTrait where Self: 'static { + fn use_self(&'static self) -> &() { panic!() } + } + trait Irrelevant { + fn use_self(&self) -> &() { panic!() } + } + + impl MyTrait for dyn ObjectTrait {} + + fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { + val.use_self() //~ ERROR borrowed data escapes + } +} +mod w { + trait Foo {} + impl<'a> Foo for &'a u32 {} + + trait Trait where Self: 'static { fn hello(&self) {} } + + impl Trait for dyn Foo + '_ { //~ERROR lifetime bound not satisfied + //~^ ERROR: cannot infer an appropriate lifetime for lifetime parameter `'_` + fn hello(&self) {} + } + fn convert<'a>(x: &'a &'a u32) { + let y: &dyn Foo = x; + y.hello(); //~ ERROR borrowed data escapes outside of function + } +} +mod x { + trait Foo {} + impl<'a> Foo for &'a u32 {} + impl dyn Foo + '_ where Self: '_ { //~ ERROR `'_` cannot be used here + fn hello(&self) {} + } + fn convert<'a>(x: &'a &'a u32) { + let y: &dyn Foo = x; + y.hello(); + } +} +fn main() {} diff --git a/tests/ui/lifetimes/static-impl-obligation.stderr b/tests/ui/lifetimes/static-impl-obligation.stderr new file mode 100644 index 0000000000000..8b080d11ddf98 --- /dev/null +++ b/tests/ui/lifetimes/static-impl-obligation.stderr @@ -0,0 +1,537 @@ +error[E0637]: `'_` cannot be used here + --> $DIR/static-impl-obligation.rs:282:35 + | +LL | impl dyn Foo + '_ where Self: '_ { + | ^^ `'_` is a reserved lifetime name + +error[E0478]: lifetime bound not satisfied + --> $DIR/static-impl-obligation.rs:221:10 + | +LL | impl MyTrait for dyn ObjectTrait + '_ {} + | ^^^^^^^ + | +note: lifetime parameter instantiated with the anonymous lifetime as defined here + --> $DIR/static-impl-obligation.rs:221:40 + | +LL | impl MyTrait for dyn ObjectTrait + '_ {} + | ^^ + = note: but lifetime parameter must outlive the static lifetime + +error[E0803]: cannot infer an appropriate lifetime for lifetime parameter `'_` due to conflicting requirements + --> $DIR/static-impl-obligation.rs:221:22 + | +LL | impl MyTrait for dyn ObjectTrait + '_ {} + | ^^^^^^^^^^^^^^^^^^^^ + | +note: first, the lifetime cannot outlive the anonymous lifetime as defined here... + --> $DIR/static-impl-obligation.rs:221:40 + | +LL | impl MyTrait for dyn ObjectTrait + '_ {} + | ^^ +note: ...so that the types are compatible + --> $DIR/static-impl-obligation.rs:221:22 + | +LL | impl MyTrait for dyn ObjectTrait + '_ {} + | ^^^^^^^^^^^^^^^^^^^^ + = note: expected `` + found `` + = note: but, the lifetime must be valid for the static lifetime... +note: ...so that the declared lifetime parameter bounds are satisfied + --> $DIR/static-impl-obligation.rs:221:22 + | +LL | impl MyTrait for dyn ObjectTrait + '_ {} + | ^^^^^^^^^^^^^^^^^^^^ + +error[E0478]: lifetime bound not satisfied + --> $DIR/static-impl-obligation.rs:270:10 + | +LL | impl Trait for dyn Foo + '_ { + | ^^^^^ + | +note: lifetime parameter instantiated with the anonymous lifetime as defined here + --> $DIR/static-impl-obligation.rs:270:30 + | +LL | impl Trait for dyn Foo + '_ { + | ^^ + = note: but lifetime parameter must outlive the static lifetime + +error[E0803]: cannot infer an appropriate lifetime for lifetime parameter `'_` due to conflicting requirements + --> $DIR/static-impl-obligation.rs:270:20 + | +LL | impl Trait for dyn Foo + '_ { + | ^^^^^^^^^^^^ + | +note: first, the lifetime cannot outlive the anonymous lifetime as defined here... + --> $DIR/static-impl-obligation.rs:270:30 + | +LL | impl Trait for dyn Foo + '_ { + | ^^ +note: ...so that the types are compatible + --> $DIR/static-impl-obligation.rs:270:20 + | +LL | impl Trait for dyn Foo + '_ { + | ^^^^^^^^^^^^ + = note: expected `` + found `` + = note: but, the lifetime must be valid for the static lifetime... +note: ...so that the declared lifetime parameter bounds are satisfied + --> $DIR/static-impl-obligation.rs:270:20 + | +LL | impl Trait for dyn Foo + '_ { + | ^^^^^^^^^^^^ + +error[E0521]: borrowed data escapes outside of function + --> $DIR/static-impl-obligation.rs:225:9 + | +LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { + | -- --- `val` is only valid in the function body + | | + | lifetime `'a` defined here +LL | val.use_self() + | ^^^^^^^^^^^^^^ + | | + | `val` escapes the function body here + | argument requires that `'a` must outlive `'static` + | +note: `'static` lifetime requirement from `t::MyTrait::use_self` introduced here + --> $DIR/static-impl-obligation.rs:214:31 + | +LL | trait MyTrait where Self: 'static { + | ^^^^^^^ lifetime requirement introduced here +LL | fn use_self(&self) -> &() where Self: 'static { panic!() } + | ^^^^^^^ lifetime requirement introduced here + +error[E0521]: borrowed data escapes outside of function + --> $DIR/static-impl-obligation.rs:243:9 + | +LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { + | -- --- `val` is only valid in the function body + | | + | lifetime `'a` defined here +LL | val.use_self() + | ^^^^^^^^^^^^^^ + | | + | `val` escapes the function body here + | argument requires that `'a` must outlive `'static` + | +note: `'static` lifetime requirement from `u::MyTrait::use_self` introduced here + --> $DIR/static-impl-obligation.rs:234:47 + | +LL | trait MyTrait { +LL | fn use_self(&self) -> &() where Self: 'static { panic!() } + | ^^^^^^^ lifetime requirement introduced here + +error[E0521]: borrowed data escapes outside of function + --> $DIR/static-impl-obligation.rs:261:9 + | +LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { + | -- --- `val` is only valid in the function body + | | + | lifetime `'a` defined here +LL | val.use_self() + | ^^^^^^^^^^^^^^ + | | + | `val` escapes the function body here + | argument requires that `'a` must outlive `'static` + | +note: the used `impl` has a `'static` requirement + --> $DIR/static-impl-obligation.rs:258:26 + | +LL | fn use_self(&'static self) -> &() { panic!() } + | -------- calling this method introduces the `impl`'s `'static` requirement +... +LL | impl MyTrait for dyn ObjectTrait {} + | ^^^^^^^^^^^ this has an implicit `'static` lifetime requirement +note: `'static` lifetime requirement from `v::MyTrait::use_self` introduced here + --> $DIR/static-impl-obligation.rs:251:31 + | +LL | trait MyTrait where Self: 'static { + | ^^^^^^^ lifetime requirement introduced here +LL | fn use_self(&'static self) -> &() { panic!() } + | +help: consider relaxing the implicit `'static` requirement + | +LL | impl MyTrait for dyn ObjectTrait + '_ {} + | ++++ + +error[E0521]: borrowed data escapes outside of function + --> $DIR/static-impl-obligation.rs:9:9 + | +LL | fn bar<'a>(x: &'a &'a u32) { + | -- - `x` is only valid in the function body + | | + | lifetime `'a` defined here +LL | let y: &dyn Foo = x; +LL | y.hello(); + | ^^^^^^^^^ + | | + | `x` escapes the function body here + | argument requires that `'a` must outlive `'static` + +error[E0521]: borrowed data escapes outside of function + --> $DIR/static-impl-obligation.rs:20:9 + | +LL | fn bar<'a>(x: &'a &'a u32) { + | -- - `x` is only valid in the function body + | | + | lifetime `'a` defined here +LL | let y: &dyn Foo = x; +LL | y.hello(); + | ^^^^^^^^^ + | | + | `x` escapes the function body here + | argument requires that `'a` must outlive `'static` + +error[E0521]: borrowed data escapes outside of function + --> $DIR/static-impl-obligation.rs:31:9 + | +LL | fn bar<'a>(x: &'a &'a u32) { + | -- - `x` is only valid in the function body + | | + | lifetime `'a` defined here +LL | let y: &dyn Foo = x; +LL | y.hello(); + | ^^^^^^^^^ + | | + | `x` escapes the function body here + | argument requires that `'a` must outlive `'static` + | +note: `'static` lifetime requirement from `<(dyn c::Foo + 'static)>::hello` introduced here + --> $DIR/static-impl-obligation.rs:27:45 + | +LL | impl dyn Foo { +LL | fn hello(&'static self) where Self: 'static {} + | ^^^^^^^ lifetime requirement introduced here + +error[E0521]: borrowed data escapes outside of function + --> $DIR/static-impl-obligation.rs:42:9 + | +LL | fn bar<'a>(x: &'a &'a u32) { + | -- - `x` is only valid in the function body + | | + | lifetime `'a` defined here +LL | let y: &dyn Foo = x; +LL | y.hello(); + | ^^^^^^^^^ + | | + | `x` escapes the function body here + | argument requires that `'a` must outlive `'static` + | +note: `'static` lifetime requirement from `<(dyn d::Foo + 'static)>::hello` introduced here + --> $DIR/static-impl-obligation.rs:38:37 + | +LL | impl dyn Foo { +LL | fn hello(&self) where Self: 'static {} + | ^^^^^^^ lifetime requirement introduced here + +error[E0521]: borrowed data escapes outside of function + --> $DIR/static-impl-obligation.rs:53:9 + | +LL | fn bar<'a>(x: &'a &'a u32) { + | -- - `x` is only valid in the function body + | | + | lifetime `'a` defined here +LL | let y: &dyn Foo = x; +LL | y.hello(); + | ^^^^^^^^^ + | | + | `x` escapes the function body here + | argument requires that `'a` must outlive `'static` + +error[E0521]: borrowed data escapes outside of function + --> $DIR/static-impl-obligation.rs:64:9 + | +LL | fn bar<'a>(x: &'a &'a u32) { + | -- - `x` is only valid in the function body + | | + | lifetime `'a` defined here +LL | let y: &dyn Foo = x; +LL | y.hello(); + | ^^^^^^^^^ + | | + | `x` escapes the function body here + | argument requires that `'a` must outlive `'static` + +error[E0521]: borrowed data escapes outside of function + --> $DIR/static-impl-obligation.rs:75:9 + | +LL | fn bar<'a>(x: &'a &'a u32) { + | -- - `x` is only valid in the function body + | | + | lifetime `'a` defined here +LL | let y: &dyn Foo = x; +LL | y.hello(); + | ^^^^^^^^^ + | | + | `x` escapes the function body here + | argument requires that `'a` must outlive `'static` + | +note: `'static` lifetime requirement from `<(dyn g::Foo + 'static)>::hello` introduced here + --> $DIR/static-impl-obligation.rs:71:45 + | +LL | impl dyn Foo + 'static { +LL | fn hello(&'static self) where Self: 'static {} + | ^^^^^^^ lifetime requirement introduced here + +error[E0521]: borrowed data escapes outside of function + --> $DIR/static-impl-obligation.rs:86:9 + | +LL | fn bar<'a>(x: &'a &'a u32) { + | -- - `x` is only valid in the function body + | | + | lifetime `'a` defined here +LL | let y: &dyn Foo = x; +LL | y.hello(); + | ^^^^^^^^^ + | | + | `x` escapes the function body here + | argument requires that `'a` must outlive `'static` + | +note: `'static` lifetime requirement from `<(dyn h::Foo + 'static)>::hello` introduced here + --> $DIR/static-impl-obligation.rs:82:37 + | +LL | impl dyn Foo + 'static { +LL | fn hello(&self) where Self: 'static {} + | ^^^^^^^ lifetime requirement introduced here + +error[E0521]: borrowed data escapes outside of function + --> $DIR/static-impl-obligation.rs:97:9 + | +LL | fn bar<'a>(x: &'a &'a u32) { + | -- - `x` is only valid in the function body + | | + | lifetime `'a` defined here +LL | let y: &dyn Foo = x; +LL | y.hello(); + | ^^^^^^^^^ + | | + | `x` escapes the function body here + | argument requires that `'a` must outlive `'static` + | +note: `'static` lifetime requirement from `<(dyn i::Foo + 'static)>::hello` introduced here + --> $DIR/static-impl-obligation.rs:92:30 + | +LL | impl dyn Foo where Self: 'static { + | ^^^^^^^ lifetime requirement introduced here +LL | fn hello(&self) {} + | + +error[E0521]: borrowed data escapes outside of function + --> $DIR/static-impl-obligation.rs:108:9 + | +LL | fn bar<'a>(x: &'a &'a u32) { + | -- - `x` is only valid in the function body + | | + | lifetime `'a` defined here +LL | let y: &dyn Foo = x; +LL | y.hello(); + | ^^^^^^^^^ + | | + | `x` escapes the function body here + | argument requires that `'a` must outlive `'static` + | +note: `'static` lifetime requirement from `<(dyn j::Foo + 'static)>::hello` introduced here + --> $DIR/static-impl-obligation.rs:103:30 + | +LL | impl dyn Foo where Self: 'static { + | ^^^^^^^ lifetime requirement introduced here +LL | fn hello(&'static self) {} + | + +error[E0521]: borrowed data escapes outside of function + --> $DIR/static-impl-obligation.rs:119:9 + | +LL | fn bar<'a>(x: &'a &'a u32) { + | -- - `x` is only valid in the function body + | | + | lifetime `'a` defined here +LL | let y: &dyn Foo = x; +LL | y.hello(); + | ^^^^^^^^^ + | | + | `x` escapes the function body here + | argument requires that `'a` must outlive `'static` + | +note: `'static` lifetime requirement from `<(dyn k::Foo + 'static)>::hello` introduced here + --> $DIR/static-impl-obligation.rs:114:30 + | +LL | impl dyn Foo where Self: 'static { + | ^^^^^^^ lifetime requirement introduced here +LL | fn hello(&'static self) where Self: 'static {} + | ^^^^^^^ lifetime requirement introduced here + +error[E0521]: borrowed data escapes outside of function + --> $DIR/static-impl-obligation.rs:130:9 + | +LL | fn bar<'a>(x: &'a &'a u32) { + | -- - `x` is only valid in the function body + | | + | lifetime `'a` defined here +LL | let y: &dyn Foo = x; +LL | y.hello(); + | ^^^^^^^^^ + | | + | `x` escapes the function body here + | argument requires that `'a` must outlive `'static` + | +note: `'static` lifetime requirement from `<(dyn l::Foo + 'static)>::hello` introduced here + --> $DIR/static-impl-obligation.rs:125:30 + | +LL | impl dyn Foo where Self: 'static { + | ^^^^^^^ lifetime requirement introduced here +LL | fn hello(&self) where Self: 'static {} + | ^^^^^^^ lifetime requirement introduced here + +error[E0521]: borrowed data escapes outside of function + --> $DIR/static-impl-obligation.rs:141:9 + | +LL | fn bar<'a>(x: &'a &'a u32) { + | -- - `x` is only valid in the function body + | | + | lifetime `'a` defined here +LL | let y: &dyn Foo = x; +LL | y.hello(); + | ^^^^^^^^^ + | | + | `x` escapes the function body here + | argument requires that `'a` must outlive `'static` + | +note: `'static` lifetime requirement from `<(dyn m::Foo + 'static)>::hello` introduced here + --> $DIR/static-impl-obligation.rs:136:40 + | +LL | impl dyn Foo + 'static where Self: 'static { + | ^^^^^^^ lifetime requirement introduced here +LL | fn hello(&self) {} + | + +error[E0521]: borrowed data escapes outside of function + --> $DIR/static-impl-obligation.rs:152:9 + | +LL | fn bar<'a>(x: &'a &'a u32) { + | -- - `x` is only valid in the function body + | | + | lifetime `'a` defined here +LL | let y: &dyn Foo = x; +LL | y.hello(); + | ^^^^^^^^^ + | | + | `x` escapes the function body here + | argument requires that `'a` must outlive `'static` + | +note: `'static` lifetime requirement from `<(dyn n::Foo + 'static)>::hello` introduced here + --> $DIR/static-impl-obligation.rs:147:40 + | +LL | impl dyn Foo + 'static where Self: 'static { + | ^^^^^^^ lifetime requirement introduced here +LL | fn hello(&'static self) {} + | + +error[E0521]: borrowed data escapes outside of function + --> $DIR/static-impl-obligation.rs:163:9 + | +LL | fn bar<'a>(x: &'a &'a u32) { + | -- - `x` is only valid in the function body + | | + | lifetime `'a` defined here +LL | let y: &dyn Foo = x; +LL | y.hello(); + | ^^^^^^^^^ + | | + | `x` escapes the function body here + | argument requires that `'a` must outlive `'static` + | +note: `'static` lifetime requirement from `<(dyn o::Foo + 'static)>::hello` introduced here + --> $DIR/static-impl-obligation.rs:158:40 + | +LL | impl dyn Foo + 'static where Self: 'static { + | ^^^^^^^ lifetime requirement introduced here +LL | fn hello(&'static self) where Self: 'static {} + | ^^^^^^^ lifetime requirement introduced here + +error[E0521]: borrowed data escapes outside of function + --> $DIR/static-impl-obligation.rs:174:9 + | +LL | fn bar<'a>(x: &'a &'a u32) { + | -- - `x` is only valid in the function body + | | + | lifetime `'a` defined here +LL | let y: &dyn Foo = x; +LL | y.hello(); + | ^^^^^^^^^ + | | + | `x` escapes the function body here + | argument requires that `'a` must outlive `'static` + | +note: `'static` lifetime requirement from `<(dyn p::Foo + 'static)>::hello` introduced here + --> $DIR/static-impl-obligation.rs:169:40 + | +LL | impl dyn Foo + 'static where Self: 'static { + | ^^^^^^^ lifetime requirement introduced here +LL | fn hello(&self) where Self: 'static {} + | ^^^^^^^ lifetime requirement introduced here + +error[E0521]: borrowed data escapes outside of function + --> $DIR/static-impl-obligation.rs:183:9 + | +LL | fn bar<'a>(x: &'a &'a Foo) { + | -- - `x` is only valid in the function body + | | + | lifetime `'a` defined here +LL | x.hello(); + | ^^^^^^^^^ + | | + | `x` escapes the function body here + | argument requires that `'a` must outlive `'static` + +error[E0521]: borrowed data escapes outside of function + --> $DIR/static-impl-obligation.rs:192:9 + | +LL | fn bar<'a>(x: &'a &'a Foo) { + | -- - `x` is only valid in the function body + | | + | lifetime `'a` defined here +LL | x.hello(); + | ^^^^^^^^^ + | | + | `x` escapes the function body here + | argument requires that `'a` must outlive `'static` + | +note: `'static` lifetime requirement from `r::Foo::hello` introduced here + --> $DIR/static-impl-obligation.rs:189:45 + | +LL | impl Foo { +LL | fn hello(&'static self) where Self: 'static {} + | ^^^^^^^ lifetime requirement introduced here + +error[E0521]: borrowed data escapes outside of function + --> $DIR/static-impl-obligation.rs:206:9 + | +LL | fn convert<'a>(x: &'a &'a u32) { + | -- - `x` is only valid in the function body + | | + | lifetime `'a` defined here +LL | let y: &dyn Foo = x; +LL | y.hello(); + | ^^^^^^^^^ + | | + | `x` escapes the function body here + | argument requires that `'a` must outlive `'static` + +error[E0521]: borrowed data escapes outside of function + --> $DIR/static-impl-obligation.rs:276:9 + | +LL | fn convert<'a>(x: &'a &'a u32) { + | -- - `x` is only valid in the function body + | | + | lifetime `'a` defined here +LL | let y: &dyn Foo = x; +LL | y.hello(); + | ^^^^^^^^^ + | | + | `x` escapes the function body here + | argument requires that `'a` must outlive `'static` + +error: aborting due to 28 previous errors + +Some errors have detailed explanations: E0478, E0521, E0637, E0803. +For more information about an error, try `rustc --explain E0478`. diff --git a/tests/ui/regions/regions-static-bound-on-type-param.rs b/tests/ui/regions/regions-static-bound-on-type-param.rs new file mode 100644 index 0000000000000..176c120b57285 --- /dev/null +++ b/tests/ui/regions/regions-static-bound-on-type-param.rs @@ -0,0 +1,7 @@ +// https://github.com/rust-lang/rust/issues/162882 + +use std::error::Error; +fn err_is(err: &dyn Error) -> bool { + err.is::() //~ ERROR: borrowed data escapes outside of function +} +fn main() {} diff --git a/tests/ui/regions/regions-static-bound-on-type-param.stderr b/tests/ui/regions/regions-static-bound-on-type-param.stderr new file mode 100644 index 0000000000000..d30f1fbe62782 --- /dev/null +++ b/tests/ui/regions/regions-static-bound-on-type-param.stderr @@ -0,0 +1,22 @@ +error[E0521]: borrowed data escapes outside of function + --> $DIR/regions-static-bound-on-type-param.rs:5:5 + | +LL | fn err_is(err: &dyn Error) -> bool { + | --- - let's call the lifetime of this reference `'1` + | | + | `err` is only valid in the function body +LL | err.is::() + | ^^^^^^^^^^^^^ + | | + | `err` escapes the function body here + | argument requires that `'1` must outlive `'static` + | +note: `'static` lifetime requirement from `<(dyn std::error::Error + 'static)>::is` introduced here + --> $SRC_DIR/core/src/error.rs:LL:COL + ::: $SRC_DIR/core/src/error.rs:LL:COL + | + = note: lifetime requirement introduced here + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0521`. diff --git a/tests/ui/regions/regions-static-bound.stderr b/tests/ui/regions/regions-static-bound.stderr index df31a17ecf113..bea7b6f87bf8c 100644 --- a/tests/ui/regions/regions-static-bound.stderr +++ b/tests/ui/regions/regions-static-bound.stderr @@ -61,6 +61,12 @@ LL | static_id(&u); | | | `u` escapes the function body here | argument requires that `'1` must outlive `'static` + | +note: `'static` lifetime requirement from `static_id` introduced here + --> $DIR/regions-static-bound.rs:3:57 + | +LL | fn static_id<'a,'b>(t: &'a ()) -> &'static () where 'a: 'static { t } + | ^^^^^^^ lifetime requirement introduced here error[E0521]: borrowed data escapes outside of function --> $DIR/regions-static-bound.rs:20:5 @@ -75,6 +81,14 @@ LL | static_id_indirect(&v); | | | `v` escapes the function body here | argument requires that `'2` must outlive `'static` + | +note: `'static` lifetime requirement from `static_id_indirect` introduced here + --> $DIR/regions-static-bound.rs:10:23 + | +LL | fn static_id_indirect<'a,'b>(t: &'a ()) -> &'static () +... +LL | where 'a: 'b, 'b: 'static { t } + | ^^^^^^^ lifetime requirement introduced here error: aborting due to 3 previous errors; 4 warnings emitted From 931b8bb93ad7cef2915f64743ca6c3a1e616b149 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 21 Sep 2026 21:05:25 +0000 Subject: [PATCH 13/23] Point at `'static` receiver ``` note: `'static` lifetime requirement from `<(dyn b::Foo + 'static)>::hello` introduced here --> $DIR/static-impl-obligation.rs:16:18 | LL | impl dyn Foo { LL | fn hello(&'static self) {} | ^^^^^^^^^^^^^ lifetime requirement introduced here ``` --- .../src/diagnostics/region_errors.rs | 33 +++++++++++- .../lifetimes/static-impl-obligation.stderr | 53 +++++++++++++++---- 2 files changed, 74 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index a8ba8127dd83a..acfcc95d08257 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -439,7 +439,7 @@ impl<'diag, 'tcx> MirBorrowckCtxt<'_, 'diag, 'tcx> { return; }; let def_id = instance.def_id(); - let bounds = + let mut bounds = tcx.clauses_of(def_id) .instantiate(tcx, instance.args) .into_iter() @@ -455,6 +455,37 @@ impl<'diag, 'tcx> MirBorrowckCtxt<'_, 'diag, 'tcx> { }) .map(|(_, sp)| sp) .collect::>(); + + // Look at the receiver for `&'static self`, which introduces a `'static` obligation. + // ``` + // impl Foo { + // fn foo(&'static self) {} + // ^^^^^^^^^^^^^ + // ``` + if let Some(recv) = + tcx.fn_sig(def_id).instantiate_identity().skip_norm_wip().inputs().skip_binder().get(0) + && let ty::Ref(region, _, _) = recv.kind() + && *region == tcx.lifetimes.re_static + && let Some(assoc) = tcx.opt_associated_item(def_id) + && assoc.is_method() + { + let def_span = tcx.def_span(def_id); + // We have a `&'static self` receiver. + if let Some(def_id) = def_id.as_local() + && let owner = tcx.expect_hir_owner_node(def_id) + && let Some(decl) = owner.fn_decl() + && let Some(ty) = decl.inputs.get(0) + { + // Point at the `&'static self` receiver. + bounds.push(ty.span); + } else if !bounds.iter().any(|sp| sp.overlaps(def_span)) { + // The method is not defined on the local crate, point at the signature instead of + // just the receiver as an approximation. We don't add it if there are already + // other spans with overlap with the def `Span`, as the other will be more specific. + bounds.push(def_span) + } + } + if !bounds.is_empty() { let mut multispan: MultiSpan = bounds.clone().into(); for span in bounds { diff --git a/tests/ui/lifetimes/static-impl-obligation.stderr b/tests/ui/lifetimes/static-impl-obligation.stderr index 8b080d11ddf98..3fe8162ed519d 100644 --- a/tests/ui/lifetimes/static-impl-obligation.stderr +++ b/tests/ui/lifetimes/static-impl-obligation.stderr @@ -148,7 +148,7 @@ note: `'static` lifetime requirement from `v::MyTrait::use_self` introduced here LL | trait MyTrait where Self: 'static { | ^^^^^^^ lifetime requirement introduced here LL | fn use_self(&'static self) -> &() { panic!() } - | + | ^^^^^^^^^^^^^ lifetime requirement introduced here help: consider relaxing the implicit `'static` requirement | LL | impl MyTrait for dyn ObjectTrait + '_ {} @@ -181,6 +181,13 @@ LL | y.hello(); | | | `x` escapes the function body here | argument requires that `'a` must outlive `'static` + | +note: `'static` lifetime requirement from `<(dyn b::Foo + 'static)>::hello` introduced here + --> $DIR/static-impl-obligation.rs:16:18 + | +LL | impl dyn Foo { +LL | fn hello(&'static self) {} + | ^^^^^^^^^^^^^ lifetime requirement introduced here error[E0521]: borrowed data escapes outside of function --> $DIR/static-impl-obligation.rs:31:9 @@ -197,11 +204,13 @@ LL | y.hello(); | argument requires that `'a` must outlive `'static` | note: `'static` lifetime requirement from `<(dyn c::Foo + 'static)>::hello` introduced here - --> $DIR/static-impl-obligation.rs:27:45 + --> $DIR/static-impl-obligation.rs:27:18 | LL | impl dyn Foo { LL | fn hello(&'static self) where Self: 'static {} - | ^^^^^^^ lifetime requirement introduced here + | ^^^^^^^^^^^^^ ^^^^^^^ lifetime requirement introduced here + | | + | lifetime requirement introduced here error[E0521]: borrowed data escapes outside of function --> $DIR/static-impl-obligation.rs:42:9 @@ -251,6 +260,13 @@ LL | y.hello(); | | | `x` escapes the function body here | argument requires that `'a` must outlive `'static` + | +note: `'static` lifetime requirement from `<(dyn f::Foo + 'static)>::hello` introduced here + --> $DIR/static-impl-obligation.rs:60:18 + | +LL | impl dyn Foo + 'static { +LL | fn hello(&'static self) {} + | ^^^^^^^^^^^^^ lifetime requirement introduced here error[E0521]: borrowed data escapes outside of function --> $DIR/static-impl-obligation.rs:75:9 @@ -267,11 +283,13 @@ LL | y.hello(); | argument requires that `'a` must outlive `'static` | note: `'static` lifetime requirement from `<(dyn g::Foo + 'static)>::hello` introduced here - --> $DIR/static-impl-obligation.rs:71:45 + --> $DIR/static-impl-obligation.rs:71:18 | LL | impl dyn Foo + 'static { LL | fn hello(&'static self) where Self: 'static {} - | ^^^^^^^ lifetime requirement introduced here + | ^^^^^^^^^^^^^ ^^^^^^^ lifetime requirement introduced here + | | + | lifetime requirement introduced here error[E0521]: borrowed data escapes outside of function --> $DIR/static-impl-obligation.rs:86:9 @@ -336,7 +354,7 @@ note: `'static` lifetime requirement from `<(dyn j::Foo + 'static)>::hello` intr LL | impl dyn Foo where Self: 'static { | ^^^^^^^ lifetime requirement introduced here LL | fn hello(&'static self) {} - | + | ^^^^^^^^^^^^^ lifetime requirement introduced here error[E0521]: borrowed data escapes outside of function --> $DIR/static-impl-obligation.rs:119:9 @@ -358,7 +376,9 @@ note: `'static` lifetime requirement from `<(dyn k::Foo + 'static)>::hello` intr LL | impl dyn Foo where Self: 'static { | ^^^^^^^ lifetime requirement introduced here LL | fn hello(&'static self) where Self: 'static {} - | ^^^^^^^ lifetime requirement introduced here + | ^^^^^^^^^^^^^ ^^^^^^^ lifetime requirement introduced here + | | + | lifetime requirement introduced here error[E0521]: borrowed data escapes outside of function --> $DIR/static-impl-obligation.rs:130:9 @@ -424,7 +444,7 @@ note: `'static` lifetime requirement from `<(dyn n::Foo + 'static)>::hello` intr LL | impl dyn Foo + 'static where Self: 'static { | ^^^^^^^ lifetime requirement introduced here LL | fn hello(&'static self) {} - | + | ^^^^^^^^^^^^^ lifetime requirement introduced here error[E0521]: borrowed data escapes outside of function --> $DIR/static-impl-obligation.rs:163:9 @@ -446,7 +466,9 @@ note: `'static` lifetime requirement from `<(dyn o::Foo + 'static)>::hello` intr LL | impl dyn Foo + 'static where Self: 'static { | ^^^^^^^ lifetime requirement introduced here LL | fn hello(&'static self) where Self: 'static {} - | ^^^^^^^ lifetime requirement introduced here + | ^^^^^^^^^^^^^ ^^^^^^^ lifetime requirement introduced here + | | + | lifetime requirement introduced here error[E0521]: borrowed data escapes outside of function --> $DIR/static-impl-obligation.rs:174:9 @@ -482,6 +504,13 @@ LL | x.hello(); | | | `x` escapes the function body here | argument requires that `'a` must outlive `'static` + | +note: `'static` lifetime requirement from `q::Foo::hello` introduced here + --> $DIR/static-impl-obligation.rs:180:18 + | +LL | impl Foo { +LL | fn hello(&'static self) {} + | ^^^^^^^^^^^^^ lifetime requirement introduced here error[E0521]: borrowed data escapes outside of function --> $DIR/static-impl-obligation.rs:192:9 @@ -497,11 +526,13 @@ LL | x.hello(); | argument requires that `'a` must outlive `'static` | note: `'static` lifetime requirement from `r::Foo::hello` introduced here - --> $DIR/static-impl-obligation.rs:189:45 + --> $DIR/static-impl-obligation.rs:189:18 | LL | impl Foo { LL | fn hello(&'static self) where Self: 'static {} - | ^^^^^^^ lifetime requirement introduced here + | ^^^^^^^^^^^^^ ^^^^^^^ lifetime requirement introduced here + | | + | lifetime requirement introduced here error[E0521]: borrowed data escapes outside of function --> $DIR/static-impl-obligation.rs:206:9 From ffa9001a7062af82546074304e56e0d5a9fedfa9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 22 Sep 2026 03:56:31 +0000 Subject: [PATCH 14/23] Point at `impl dyn Trait` `'static` obligation ``` note: `'static` lifetime requirement from `<(dyn a::Foo + 'static)>::hello` introduced here --> $DIR/static-impl-obligation.rs:4:5 | LL | impl dyn Foo { | ^^^^^^^^^^^^ lifetime requirement introduced here LL | fn hello(&self) {} | ``` --- .../src/diagnostics/region_errors.rs | 70 ++++++++++++------- .../lifetimes/static-impl-obligation.stderr | 42 +++++++++-- tests/ui/regions/issue-78262.base.stderr | 8 +++ tests/ui/regions/issue-78262.polonius.stderr | 8 +++ .../regions-static-bound-on-type-param.stderr | 2 + ...yn-trait-with-implicit-static-bound.stderr | 21 ++++++ 6 files changed, 119 insertions(+), 32 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index acfcc95d08257..a085ffa64d409 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -430,9 +430,10 @@ impl<'diag, 'tcx> MirBorrowckCtxt<'_, 'diag, 'tcx> { let ty::FnDef(def_id, args) = ty.kind() else { return; }; + let typing_env = self.infcx.typing_env(self.infcx.param_env); let Ok(Some(instance)) = ty::Instance::try_resolve( tcx, - self.infcx.typing_env(self.infcx.param_env), + typing_env, *def_id, self.infcx.deeply_resolve_ignoring_regions(args.no_bound_vars().unwrap()), ) else { @@ -456,33 +457,51 @@ impl<'diag, 'tcx> MirBorrowckCtxt<'_, 'diag, 'tcx> { .map(|(_, sp)| sp) .collect::>(); - // Look at the receiver for `&'static self`, which introduces a `'static` obligation. - // ``` - // impl Foo { - // fn foo(&'static self) {} - // ^^^^^^^^^^^^^ - // ``` - if let Some(recv) = + let parent = tcx.parent(def_id); + if let Some(rcvr) = tcx.fn_sig(def_id).instantiate_identity().skip_norm_wip().inputs().skip_binder().get(0) - && let ty::Ref(region, _, _) = recv.kind() - && *region == tcx.lifetimes.re_static - && let Some(assoc) = tcx.opt_associated_item(def_id) - && assoc.is_method() { - let def_span = tcx.def_span(def_id); - // We have a `&'static self` receiver. - if let Some(def_id) = def_id.as_local() - && let owner = tcx.expect_hir_owner_node(def_id) - && let Some(decl) = owner.fn_decl() - && let Some(ty) = decl.inputs.get(0) + // Look at the receiver for `&'static self`, which introduces a `'static` obligation. + // ``` + // impl Foo { + // fn foo(&'static self) {} + // ^^^^^^^^^^^^^ + // ``` + if let ty::Ref(region, _, _) = rcvr.kind() + && *region == tcx.lifetimes.re_static + && let Some(assoc) = tcx.opt_associated_item(def_id) + && assoc.is_method() { - // Point at the `&'static self` receiver. - bounds.push(ty.span); - } else if !bounds.iter().any(|sp| sp.overlaps(def_span)) { - // The method is not defined on the local crate, point at the signature instead of - // just the receiver as an approximation. We don't add it if there are already - // other spans with overlap with the def `Span`, as the other will be more specific. - bounds.push(def_span) + let def_span = tcx.def_span(def_id); + // We have a `&'static self` receiver. + if let Some(def_id) = def_id.as_local() + && let owner = tcx.expect_hir_owner_node(def_id) + && let Some(decl) = owner.fn_decl() + && let Some(ty) = decl.inputs.get(0) + { + // Point at the `&'static self` receiver. + bounds.push(ty.span); + } else if !bounds.iter().any(|sp| sp.overlaps(def_span)) { + // The method is not defined on the local crate, point at the signature instead of + // just the receiver as an approximation. We don't add it if there are already + // other spans with overlap with the def `Span`, as the other will be more specific. + bounds.push(def_span) + } + } + + if let DefKind::Impl { .. } = tcx.def_kind(parent) + && let ty = tcx.type_of(parent).instantiate_identity().skip_norm_wip() + && let ty::Dynamic(_, region) = ty.kind() + && *region == tcx.lifetimes.re_static + { + // We have a call into a method of either `impl dyn Trait {}` or + // `impl dyn Trait + 'static {}`. We point at the whole def `Span` for now. We + // should instead point only at the `dyn Trait` with an explanation of where the + // `'static` obligation comes from, or only the `'static` when it is explicit. + let def_span = tcx.def_span(parent); + if !bounds.iter().any(|sp| sp.overlaps(def_span)) { + bounds.push(def_span); + } } } @@ -492,7 +511,6 @@ impl<'diag, 'tcx> MirBorrowckCtxt<'_, 'diag, 'tcx> { multispan.push_span_label(span, "lifetime requirement introduced here"); } multispan.push_span_context(tcx.def_span(def_id).shrink_to_lo()); - let parent = tcx.parent(def_id); if let DefKind::Impl { .. } | DefKind::Trait = tcx.def_kind(parent) { multispan.push_span_context(tcx.def_span(parent).shrink_to_lo()); } diff --git a/tests/ui/lifetimes/static-impl-obligation.stderr b/tests/ui/lifetimes/static-impl-obligation.stderr index 3fe8162ed519d..25da231557094 100644 --- a/tests/ui/lifetimes/static-impl-obligation.stderr +++ b/tests/ui/lifetimes/static-impl-obligation.stderr @@ -167,6 +167,14 @@ LL | y.hello(); | | | `x` escapes the function body here | argument requires that `'a` must outlive `'static` + | +note: `'static` lifetime requirement from `<(dyn a::Foo + 'static)>::hello` introduced here + --> $DIR/static-impl-obligation.rs:4:5 + | +LL | impl dyn Foo { + | ^^^^^^^^^^^^ lifetime requirement introduced here +LL | fn hello(&self) {} + | error[E0521]: borrowed data escapes outside of function --> $DIR/static-impl-obligation.rs:20:9 @@ -183,9 +191,10 @@ LL | y.hello(); | argument requires that `'a` must outlive `'static` | note: `'static` lifetime requirement from `<(dyn b::Foo + 'static)>::hello` introduced here - --> $DIR/static-impl-obligation.rs:16:18 + --> $DIR/static-impl-obligation.rs:15:5 | LL | impl dyn Foo { + | ^^^^^^^^^^^^ lifetime requirement introduced here LL | fn hello(&'static self) {} | ^^^^^^^^^^^^^ lifetime requirement introduced here @@ -204,9 +213,10 @@ LL | y.hello(); | argument requires that `'a` must outlive `'static` | note: `'static` lifetime requirement from `<(dyn c::Foo + 'static)>::hello` introduced here - --> $DIR/static-impl-obligation.rs:27:18 + --> $DIR/static-impl-obligation.rs:26:5 | LL | impl dyn Foo { + | ^^^^^^^^^^^^ lifetime requirement introduced here LL | fn hello(&'static self) where Self: 'static {} | ^^^^^^^^^^^^^ ^^^^^^^ lifetime requirement introduced here | | @@ -227,9 +237,10 @@ LL | y.hello(); | argument requires that `'a` must outlive `'static` | note: `'static` lifetime requirement from `<(dyn d::Foo + 'static)>::hello` introduced here - --> $DIR/static-impl-obligation.rs:38:37 + --> $DIR/static-impl-obligation.rs:37:5 | LL | impl dyn Foo { + | ^^^^^^^^^^^^ lifetime requirement introduced here LL | fn hello(&self) where Self: 'static {} | ^^^^^^^ lifetime requirement introduced here @@ -246,6 +257,14 @@ LL | y.hello(); | | | `x` escapes the function body here | argument requires that `'a` must outlive `'static` + | +note: `'static` lifetime requirement from `<(dyn e::Foo + 'static)>::hello` introduced here + --> $DIR/static-impl-obligation.rs:48:5 + | +LL | impl dyn Foo + 'static { + | ^^^^^^^^^^^^^^^^^^^^^^ lifetime requirement introduced here +LL | fn hello(&self) {} + | error[E0521]: borrowed data escapes outside of function --> $DIR/static-impl-obligation.rs:64:9 @@ -262,9 +281,10 @@ LL | y.hello(); | argument requires that `'a` must outlive `'static` | note: `'static` lifetime requirement from `<(dyn f::Foo + 'static)>::hello` introduced here - --> $DIR/static-impl-obligation.rs:60:18 + --> $DIR/static-impl-obligation.rs:59:5 | LL | impl dyn Foo + 'static { + | ^^^^^^^^^^^^^^^^^^^^^^ lifetime requirement introduced here LL | fn hello(&'static self) {} | ^^^^^^^^^^^^^ lifetime requirement introduced here @@ -283,9 +303,10 @@ LL | y.hello(); | argument requires that `'a` must outlive `'static` | note: `'static` lifetime requirement from `<(dyn g::Foo + 'static)>::hello` introduced here - --> $DIR/static-impl-obligation.rs:71:18 + --> $DIR/static-impl-obligation.rs:70:5 | LL | impl dyn Foo + 'static { + | ^^^^^^^^^^^^^^^^^^^^^^ lifetime requirement introduced here LL | fn hello(&'static self) where Self: 'static {} | ^^^^^^^^^^^^^ ^^^^^^^ lifetime requirement introduced here | | @@ -306,9 +327,10 @@ LL | y.hello(); | argument requires that `'a` must outlive `'static` | note: `'static` lifetime requirement from `<(dyn h::Foo + 'static)>::hello` introduced here - --> $DIR/static-impl-obligation.rs:82:37 + --> $DIR/static-impl-obligation.rs:81:5 | LL | impl dyn Foo + 'static { + | ^^^^^^^^^^^^^^^^^^^^^^ lifetime requirement introduced here LL | fn hello(&self) where Self: 'static {} | ^^^^^^^ lifetime requirement introduced here @@ -547,6 +569,14 @@ LL | y.hello(); | | | `x` escapes the function body here | argument requires that `'a` must outlive `'static` + | +note: `'static` lifetime requirement from `<(dyn s::Foo + 'static) as s::Trait>::hello` introduced here + --> $DIR/static-impl-obligation.rs:201:5 + | +LL | impl Trait for dyn Foo { + | ^^^^^^^^^^^^^^^^^^^^^^ lifetime requirement introduced here +LL | fn hello(&self) {} + | error[E0521]: borrowed data escapes outside of function --> $DIR/static-impl-obligation.rs:276:9 diff --git a/tests/ui/regions/issue-78262.base.stderr b/tests/ui/regions/issue-78262.base.stderr index 472d46ef93644..2a7d6181cf9fb 100644 --- a/tests/ui/regions/issue-78262.base.stderr +++ b/tests/ui/regions/issue-78262.base.stderr @@ -8,6 +8,14 @@ LL | let f = |x: &dyn TT| x.func(); | | | argument requires that `'1` must outlive `'static` | | let's call the lifetime of this reference `'1` | `x` is only valid in the closure body + | +note: `'static` lifetime requirement from `<(dyn TT + 'static)>::func` introduced here + --> $DIR/issue-78262.rs:7:1 + | +LL | impl dyn TT { + | ^^^^^^^^^^^ lifetime requirement introduced here +LL | fn func(&self) {} + | error: aborting due to 1 previous error diff --git a/tests/ui/regions/issue-78262.polonius.stderr b/tests/ui/regions/issue-78262.polonius.stderr index 472d46ef93644..2a7d6181cf9fb 100644 --- a/tests/ui/regions/issue-78262.polonius.stderr +++ b/tests/ui/regions/issue-78262.polonius.stderr @@ -8,6 +8,14 @@ LL | let f = |x: &dyn TT| x.func(); | | | argument requires that `'1` must outlive `'static` | | let's call the lifetime of this reference `'1` | `x` is only valid in the closure body + | +note: `'static` lifetime requirement from `<(dyn TT + 'static)>::func` introduced here + --> $DIR/issue-78262.rs:7:1 + | +LL | impl dyn TT { + | ^^^^^^^^^^^ lifetime requirement introduced here +LL | fn func(&self) {} + | error: aborting due to 1 previous error diff --git a/tests/ui/regions/regions-static-bound-on-type-param.stderr b/tests/ui/regions/regions-static-bound-on-type-param.stderr index d30f1fbe62782..64496cb703bee 100644 --- a/tests/ui/regions/regions-static-bound-on-type-param.stderr +++ b/tests/ui/regions/regions-static-bound-on-type-param.stderr @@ -13,6 +13,8 @@ LL | err.is::() | note: `'static` lifetime requirement from `<(dyn std::error::Error + 'static)>::is` introduced here --> $SRC_DIR/core/src/error.rs:LL:COL + | + = note: lifetime requirement introduced here ::: $SRC_DIR/core/src/error.rs:LL:COL | = note: lifetime requirement introduced here diff --git a/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr b/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr index 8ef1b052384c6..9f5e45ecddec4 100644 --- a/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr +++ b/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr @@ -18,6 +18,13 @@ LL | impl MyTrait for dyn ObjectTrait { | ^^^^^^^^^^^^^^ this has an implicit `'static` lifetime requirement LL | fn use_self(&self) -> &() { panic!() } | -------- calling this method introduces the `impl`'s `'static` requirement +note: `'static` lifetime requirement from `<(dyn foo::ObjectTrait + 'static) as foo::MyTrait>::use_self` introduced here + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:15:5 + | +LL | impl MyTrait for dyn ObjectTrait { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime requirement introduced here +LL | fn use_self(&self) -> &() { panic!() } + | help: consider relaxing the implicit `'static` requirement | LL | impl MyTrait for dyn ObjectTrait + '_ { @@ -43,6 +50,13 @@ LL | impl dyn ObjectTrait { | ^^^^^^^^^^^ this has an implicit `'static` lifetime requirement LL | fn use_self(&self) -> &() { panic!() } | -------- calling this method introduces the `impl`'s `'static` requirement +note: `'static` lifetime requirement from `<(dyn bat::ObjectTrait + 'static)>::use_self` introduced here + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:67:5 + | +LL | impl dyn ObjectTrait { + | ^^^^^^^^^^^^^^^^^^^^ lifetime requirement introduced here +LL | fn use_self(&self) -> &() { panic!() } + | help: consider relaxing the implicit `'static` requirement | LL | impl dyn ObjectTrait + '_ { @@ -120,6 +134,13 @@ LL | impl MyTrait for dyn ObjectTrait { | ^^^^^^^^^^^ this has an implicit `'static` lifetime requirement LL | fn use_self(&self) -> &() { panic!() } | -------- calling this method introduces the `impl`'s `'static` requirement +note: `'static` lifetime requirement from `<(dyn bar::ObjectTrait + 'static) as bar::MyTrait>::use_self` introduced here + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:32:5 + | +LL | impl MyTrait for dyn ObjectTrait { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime requirement introduced here +LL | fn use_self(&self) -> &() { panic!() } + | help: consider relaxing the implicit `'static` requirement | LL | impl MyTrait for dyn ObjectTrait + '_ { From 7840dfe4cb81eaa9365938f52aa4c3af4e580ad6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 22 Sep 2026 04:40:15 +0000 Subject: [PATCH 15/23] Use better spans on local `impl dyn Trait` when pointing at `'static` lifetime ``` note: `'static` lifetime requirement from `<(dyn a::Foo + 'static)>::hello` introduced here --> $DIR/static-impl-obligation.rs:4:10 | LL | impl dyn Foo { | ^^^^^^^ `dyn Trait` introduces an implicit `'static` lifetime requirement LL | fn hello(&self) {} | ``` ``` note: `'static` lifetime requirement from `<(dyn e::Foo + 'static)>::hello` introduced here --> $DIR/static-impl-obligation.rs:48:20 | LL | impl dyn Foo + 'static { | ^^^^^^^ lifetime requirement introduced here LL | fn hello(&self) {} | ``` --- .../src/diagnostics/region_errors.rs | 39 +++++++-- .../lifetimes/static-impl-obligation.stderr | 84 +++++++++++-------- tests/ui/regions/issue-78262.base.stderr | 4 +- tests/ui/regions/issue-78262.polonius.stderr | 4 +- ...yn-trait-with-implicit-static-bound.stderr | 12 +-- 5 files changed, 91 insertions(+), 52 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index a085ffa64d409..9d795ff567087 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -1,6 +1,6 @@ //! Error reporting machinery for lifetime errors. -use rustc_data_structures::fx::FxIndexSet; +use rustc_data_structures::fx::{FxHashMap, FxIndexSet}; use rustc_errors::{Applicability, Diag, ErrorGuaranteed, MultiSpan, msg}; use rustc_hir as hir; use rustc_hir::GenericBound::Trait; @@ -457,6 +457,8 @@ impl<'diag, 'tcx> MirBorrowckCtxt<'_, 'diag, 'tcx> { .map(|(_, sp)| sp) .collect::>(); + let mut labels = FxHashMap::default(); + let parent = tcx.parent(def_id); if let Some(rcvr) = tcx.fn_sig(def_id).instantiate_identity().skip_norm_wip().inputs().skip_binder().get(0) @@ -495,12 +497,32 @@ impl<'diag, 'tcx> MirBorrowckCtxt<'_, 'diag, 'tcx> { && *region == tcx.lifetimes.re_static { // We have a call into a method of either `impl dyn Trait {}` or - // `impl dyn Trait + 'static {}`. We point at the whole def `Span` for now. We - // should instead point only at the `dyn Trait` with an explanation of where the - // `'static` obligation comes from, or only the `'static` when it is explicit. - let def_span = tcx.def_span(parent); - if !bounds.iter().any(|sp| sp.overlaps(def_span)) { - bounds.push(def_span); + // `impl dyn Trait + 'static {}`. + if let Some(def_id) = parent.as_local() + && let hir::OwnerNode::Item(item) = tcx.expect_hir_owner_node(def_id) + && let hir::ItemKind::Impl(impl_) = item.kind + && let hir::TyKind::TraitObject(_, tagged_ref) = impl_.self_ty.kind + { + if tagged_ref.is_static() { + // impl dyn Trait + 'static { + // ^^^^^^^ lifetime requirement introduced here + bounds.push(tagged_ref.pointer().ident.span); + } else if tagged_ref.is_implicit() { + // impl dyn Trait { + // ^^^^^^^^^ `dyn Trait` introduces an... + bounds.push(impl_.self_ty.span); + labels.insert( + impl_.self_ty.span, + "`dyn Trait` introduces an implicit `'static` lifetime requirement", + ); + } + } else { + // Non-local `impl`, we don't have a way to differentiate between `+ 'static` + // and bare `dyn Trait`. We point at the whole def `Span` for now. + let def_span = tcx.def_span(parent); + if !bounds.iter().any(|sp| sp.overlaps(def_span)) { + bounds.push(def_span); + } } } } @@ -508,7 +530,8 @@ impl<'diag, 'tcx> MirBorrowckCtxt<'_, 'diag, 'tcx> { if !bounds.is_empty() { let mut multispan: MultiSpan = bounds.clone().into(); for span in bounds { - multispan.push_span_label(span, "lifetime requirement introduced here"); + let label = labels.get(&span).unwrap_or(&"lifetime requirement introduced here"); + multispan.push_span_label(span, *label); } multispan.push_span_context(tcx.def_span(def_id).shrink_to_lo()); if let DefKind::Impl { .. } | DefKind::Trait = tcx.def_kind(parent) { diff --git a/tests/ui/lifetimes/static-impl-obligation.stderr b/tests/ui/lifetimes/static-impl-obligation.stderr index 25da231557094..27751557ab51d 100644 --- a/tests/ui/lifetimes/static-impl-obligation.stderr +++ b/tests/ui/lifetimes/static-impl-obligation.stderr @@ -169,10 +169,10 @@ LL | y.hello(); | argument requires that `'a` must outlive `'static` | note: `'static` lifetime requirement from `<(dyn a::Foo + 'static)>::hello` introduced here - --> $DIR/static-impl-obligation.rs:4:5 + --> $DIR/static-impl-obligation.rs:4:10 | LL | impl dyn Foo { - | ^^^^^^^^^^^^ lifetime requirement introduced here + | ^^^^^^^ `dyn Trait` introduces an implicit `'static` lifetime requirement LL | fn hello(&self) {} | @@ -191,10 +191,10 @@ LL | y.hello(); | argument requires that `'a` must outlive `'static` | note: `'static` lifetime requirement from `<(dyn b::Foo + 'static)>::hello` introduced here - --> $DIR/static-impl-obligation.rs:15:5 + --> $DIR/static-impl-obligation.rs:15:10 | LL | impl dyn Foo { - | ^^^^^^^^^^^^ lifetime requirement introduced here + | ^^^^^^^ `dyn Trait` introduces an implicit `'static` lifetime requirement LL | fn hello(&'static self) {} | ^^^^^^^^^^^^^ lifetime requirement introduced here @@ -213,10 +213,10 @@ LL | y.hello(); | argument requires that `'a` must outlive `'static` | note: `'static` lifetime requirement from `<(dyn c::Foo + 'static)>::hello` introduced here - --> $DIR/static-impl-obligation.rs:26:5 + --> $DIR/static-impl-obligation.rs:26:10 | LL | impl dyn Foo { - | ^^^^^^^^^^^^ lifetime requirement introduced here + | ^^^^^^^ `dyn Trait` introduces an implicit `'static` lifetime requirement LL | fn hello(&'static self) where Self: 'static {} | ^^^^^^^^^^^^^ ^^^^^^^ lifetime requirement introduced here | | @@ -237,10 +237,10 @@ LL | y.hello(); | argument requires that `'a` must outlive `'static` | note: `'static` lifetime requirement from `<(dyn d::Foo + 'static)>::hello` introduced here - --> $DIR/static-impl-obligation.rs:37:5 + --> $DIR/static-impl-obligation.rs:37:10 | LL | impl dyn Foo { - | ^^^^^^^^^^^^ lifetime requirement introduced here + | ^^^^^^^ `dyn Trait` introduces an implicit `'static` lifetime requirement LL | fn hello(&self) where Self: 'static {} | ^^^^^^^ lifetime requirement introduced here @@ -259,10 +259,10 @@ LL | y.hello(); | argument requires that `'a` must outlive `'static` | note: `'static` lifetime requirement from `<(dyn e::Foo + 'static)>::hello` introduced here - --> $DIR/static-impl-obligation.rs:48:5 + --> $DIR/static-impl-obligation.rs:48:20 | LL | impl dyn Foo + 'static { - | ^^^^^^^^^^^^^^^^^^^^^^ lifetime requirement introduced here + | ^^^^^^^ lifetime requirement introduced here LL | fn hello(&self) {} | @@ -281,10 +281,10 @@ LL | y.hello(); | argument requires that `'a` must outlive `'static` | note: `'static` lifetime requirement from `<(dyn f::Foo + 'static)>::hello` introduced here - --> $DIR/static-impl-obligation.rs:59:5 + --> $DIR/static-impl-obligation.rs:59:20 | LL | impl dyn Foo + 'static { - | ^^^^^^^^^^^^^^^^^^^^^^ lifetime requirement introduced here + | ^^^^^^^ lifetime requirement introduced here LL | fn hello(&'static self) {} | ^^^^^^^^^^^^^ lifetime requirement introduced here @@ -303,10 +303,10 @@ LL | y.hello(); | argument requires that `'a` must outlive `'static` | note: `'static` lifetime requirement from `<(dyn g::Foo + 'static)>::hello` introduced here - --> $DIR/static-impl-obligation.rs:70:5 + --> $DIR/static-impl-obligation.rs:70:20 | LL | impl dyn Foo + 'static { - | ^^^^^^^^^^^^^^^^^^^^^^ lifetime requirement introduced here + | ^^^^^^^ lifetime requirement introduced here LL | fn hello(&'static self) where Self: 'static {} | ^^^^^^^^^^^^^ ^^^^^^^ lifetime requirement introduced here | | @@ -327,10 +327,10 @@ LL | y.hello(); | argument requires that `'a` must outlive `'static` | note: `'static` lifetime requirement from `<(dyn h::Foo + 'static)>::hello` introduced here - --> $DIR/static-impl-obligation.rs:81:5 + --> $DIR/static-impl-obligation.rs:81:20 | LL | impl dyn Foo + 'static { - | ^^^^^^^^^^^^^^^^^^^^^^ lifetime requirement introduced here + | ^^^^^^^ lifetime requirement introduced here LL | fn hello(&self) where Self: 'static {} | ^^^^^^^ lifetime requirement introduced here @@ -349,10 +349,12 @@ LL | y.hello(); | argument requires that `'a` must outlive `'static` | note: `'static` lifetime requirement from `<(dyn i::Foo + 'static)>::hello` introduced here - --> $DIR/static-impl-obligation.rs:92:30 + --> $DIR/static-impl-obligation.rs:92:10 | LL | impl dyn Foo where Self: 'static { - | ^^^^^^^ lifetime requirement introduced here + | ^^^^^^^ ^^^^^^^ lifetime requirement introduced here + | | + | `dyn Trait` introduces an implicit `'static` lifetime requirement LL | fn hello(&self) {} | @@ -371,10 +373,12 @@ LL | y.hello(); | argument requires that `'a` must outlive `'static` | note: `'static` lifetime requirement from `<(dyn j::Foo + 'static)>::hello` introduced here - --> $DIR/static-impl-obligation.rs:103:30 + --> $DIR/static-impl-obligation.rs:103:10 | LL | impl dyn Foo where Self: 'static { - | ^^^^^^^ lifetime requirement introduced here + | ^^^^^^^ ^^^^^^^ lifetime requirement introduced here + | | + | `dyn Trait` introduces an implicit `'static` lifetime requirement LL | fn hello(&'static self) {} | ^^^^^^^^^^^^^ lifetime requirement introduced here @@ -393,10 +397,12 @@ LL | y.hello(); | argument requires that `'a` must outlive `'static` | note: `'static` lifetime requirement from `<(dyn k::Foo + 'static)>::hello` introduced here - --> $DIR/static-impl-obligation.rs:114:30 + --> $DIR/static-impl-obligation.rs:114:10 | LL | impl dyn Foo where Self: 'static { - | ^^^^^^^ lifetime requirement introduced here + | ^^^^^^^ ^^^^^^^ lifetime requirement introduced here + | | + | `dyn Trait` introduces an implicit `'static` lifetime requirement LL | fn hello(&'static self) where Self: 'static {} | ^^^^^^^^^^^^^ ^^^^^^^ lifetime requirement introduced here | | @@ -417,10 +423,12 @@ LL | y.hello(); | argument requires that `'a` must outlive `'static` | note: `'static` lifetime requirement from `<(dyn l::Foo + 'static)>::hello` introduced here - --> $DIR/static-impl-obligation.rs:125:30 + --> $DIR/static-impl-obligation.rs:125:10 | LL | impl dyn Foo where Self: 'static { - | ^^^^^^^ lifetime requirement introduced here + | ^^^^^^^ ^^^^^^^ lifetime requirement introduced here + | | + | `dyn Trait` introduces an implicit `'static` lifetime requirement LL | fn hello(&self) where Self: 'static {} | ^^^^^^^ lifetime requirement introduced here @@ -439,10 +447,12 @@ LL | y.hello(); | argument requires that `'a` must outlive `'static` | note: `'static` lifetime requirement from `<(dyn m::Foo + 'static)>::hello` introduced here - --> $DIR/static-impl-obligation.rs:136:40 + --> $DIR/static-impl-obligation.rs:136:20 | LL | impl dyn Foo + 'static where Self: 'static { - | ^^^^^^^ lifetime requirement introduced here + | ^^^^^^^ ^^^^^^^ lifetime requirement introduced here + | | + | lifetime requirement introduced here LL | fn hello(&self) {} | @@ -461,10 +471,12 @@ LL | y.hello(); | argument requires that `'a` must outlive `'static` | note: `'static` lifetime requirement from `<(dyn n::Foo + 'static)>::hello` introduced here - --> $DIR/static-impl-obligation.rs:147:40 + --> $DIR/static-impl-obligation.rs:147:20 | LL | impl dyn Foo + 'static where Self: 'static { - | ^^^^^^^ lifetime requirement introduced here + | ^^^^^^^ ^^^^^^^ lifetime requirement introduced here + | | + | lifetime requirement introduced here LL | fn hello(&'static self) {} | ^^^^^^^^^^^^^ lifetime requirement introduced here @@ -483,10 +495,12 @@ LL | y.hello(); | argument requires that `'a` must outlive `'static` | note: `'static` lifetime requirement from `<(dyn o::Foo + 'static)>::hello` introduced here - --> $DIR/static-impl-obligation.rs:158:40 + --> $DIR/static-impl-obligation.rs:158:20 | LL | impl dyn Foo + 'static where Self: 'static { - | ^^^^^^^ lifetime requirement introduced here + | ^^^^^^^ ^^^^^^^ lifetime requirement introduced here + | | + | lifetime requirement introduced here LL | fn hello(&'static self) where Self: 'static {} | ^^^^^^^^^^^^^ ^^^^^^^ lifetime requirement introduced here | | @@ -507,10 +521,12 @@ LL | y.hello(); | argument requires that `'a` must outlive `'static` | note: `'static` lifetime requirement from `<(dyn p::Foo + 'static)>::hello` introduced here - --> $DIR/static-impl-obligation.rs:169:40 + --> $DIR/static-impl-obligation.rs:169:20 | LL | impl dyn Foo + 'static where Self: 'static { - | ^^^^^^^ lifetime requirement introduced here + | ^^^^^^^ ^^^^^^^ lifetime requirement introduced here + | | + | lifetime requirement introduced here LL | fn hello(&self) where Self: 'static {} | ^^^^^^^ lifetime requirement introduced here @@ -571,10 +587,10 @@ LL | y.hello(); | argument requires that `'a` must outlive `'static` | note: `'static` lifetime requirement from `<(dyn s::Foo + 'static) as s::Trait>::hello` introduced here - --> $DIR/static-impl-obligation.rs:201:5 + --> $DIR/static-impl-obligation.rs:201:20 | LL | impl Trait for dyn Foo { - | ^^^^^^^^^^^^^^^^^^^^^^ lifetime requirement introduced here + | ^^^^^^^ `dyn Trait` introduces an implicit `'static` lifetime requirement LL | fn hello(&self) {} | diff --git a/tests/ui/regions/issue-78262.base.stderr b/tests/ui/regions/issue-78262.base.stderr index 2a7d6181cf9fb..54a2393c913ed 100644 --- a/tests/ui/regions/issue-78262.base.stderr +++ b/tests/ui/regions/issue-78262.base.stderr @@ -10,10 +10,10 @@ LL | let f = |x: &dyn TT| x.func(); | `x` is only valid in the closure body | note: `'static` lifetime requirement from `<(dyn TT + 'static)>::func` introduced here - --> $DIR/issue-78262.rs:7:1 + --> $DIR/issue-78262.rs:7:6 | LL | impl dyn TT { - | ^^^^^^^^^^^ lifetime requirement introduced here + | ^^^^^^ `dyn Trait` introduces an implicit `'static` lifetime requirement LL | fn func(&self) {} | diff --git a/tests/ui/regions/issue-78262.polonius.stderr b/tests/ui/regions/issue-78262.polonius.stderr index 2a7d6181cf9fb..54a2393c913ed 100644 --- a/tests/ui/regions/issue-78262.polonius.stderr +++ b/tests/ui/regions/issue-78262.polonius.stderr @@ -10,10 +10,10 @@ LL | let f = |x: &dyn TT| x.func(); | `x` is only valid in the closure body | note: `'static` lifetime requirement from `<(dyn TT + 'static)>::func` introduced here - --> $DIR/issue-78262.rs:7:1 + --> $DIR/issue-78262.rs:7:6 | LL | impl dyn TT { - | ^^^^^^^^^^^ lifetime requirement introduced here + | ^^^^^^ `dyn Trait` introduces an implicit `'static` lifetime requirement LL | fn func(&self) {} | diff --git a/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr b/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr index 9f5e45ecddec4..9793b7fb8dc7a 100644 --- a/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr +++ b/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr @@ -19,10 +19,10 @@ LL | impl MyTrait for dyn ObjectTrait { LL | fn use_self(&self) -> &() { panic!() } | -------- calling this method introduces the `impl`'s `'static` requirement note: `'static` lifetime requirement from `<(dyn foo::ObjectTrait + 'static) as foo::MyTrait>::use_self` introduced here - --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:15:5 + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:15:28 | LL | impl MyTrait for dyn ObjectTrait { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime requirement introduced here + | ^^^^^^^^^^^^^^^^^^ `dyn Trait` introduces an implicit `'static` lifetime requirement LL | fn use_self(&self) -> &() { panic!() } | help: consider relaxing the implicit `'static` requirement @@ -51,10 +51,10 @@ LL | impl dyn ObjectTrait { LL | fn use_self(&self) -> &() { panic!() } | -------- calling this method introduces the `impl`'s `'static` requirement note: `'static` lifetime requirement from `<(dyn bat::ObjectTrait + 'static)>::use_self` introduced here - --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:67:5 + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:67:10 | LL | impl dyn ObjectTrait { - | ^^^^^^^^^^^^^^^^^^^^ lifetime requirement introduced here + | ^^^^^^^^^^^^^^^ `dyn Trait` introduces an implicit `'static` lifetime requirement LL | fn use_self(&self) -> &() { panic!() } | help: consider relaxing the implicit `'static` requirement @@ -135,10 +135,10 @@ LL | impl MyTrait for dyn ObjectTrait { LL | fn use_self(&self) -> &() { panic!() } | -------- calling this method introduces the `impl`'s `'static` requirement note: `'static` lifetime requirement from `<(dyn bar::ObjectTrait + 'static) as bar::MyTrait>::use_self` introduced here - --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:32:5 + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:32:22 | LL | impl MyTrait for dyn ObjectTrait { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime requirement introduced here + | ^^^^^^^^^^^^^^^ `dyn Trait` introduces an implicit `'static` lifetime requirement LL | fn use_self(&self) -> &() { panic!() } | help: consider relaxing the implicit `'static` requirement From 94dc6dd98ad000c78b950acb1bb34e2ccdf9e990 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 22 Sep 2026 15:59:30 +0000 Subject: [PATCH 16/23] Fix test --- src/tools/clippy/tests/ui/crashes/ice-6256.stderr | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/tools/clippy/tests/ui/crashes/ice-6256.stderr b/src/tools/clippy/tests/ui/crashes/ice-6256.stderr index 4cb83e24e7a05..b0cd8abed048b 100644 --- a/src/tools/clippy/tests/ui/crashes/ice-6256.stderr +++ b/src/tools/clippy/tests/ui/crashes/ice-6256.stderr @@ -8,6 +8,14 @@ LL | let f = |x: &dyn TT| x.func(); | | | argument requires that `'1` must outlive `'static` | | let's call the lifetime of this reference `'1` | `x` is only valid in the closure body + | +note: `'static` lifetime requirement from `<(dyn TT + 'static)>::func` introduced here + --> tests/ui/crashes/ice-6256.rs:7:6 + | +LL | impl dyn TT { + | ^^^^^^ `dyn Trait` introduces an implicit `'static` lifetime requirement +LL | fn func(&self) {} + | error: aborting due to 1 previous error From fc83fc885ddfef7c695c49e1be3af90655f4af44 Mon Sep 17 00:00:00 2001 From: Takayuki Maeda Date: Wed, 9 Sep 2026 05:02:14 +0900 Subject: [PATCH 17/23] avoid ICEs when recovering malformed function parameters --- .../rustc_parse/src/parser/diagnostics.rs | 36 +++++++++++++------ .../recover-invalid-fn-trait-bound-pattern.rs | 5 +++ ...over-invalid-fn-trait-bound-pattern.stderr | 20 +++++++++++ ...over-invalid-function-parameter-pattern.rs | 6 ++++ ...-invalid-function-parameter-pattern.stderr | 28 +++++++++++++++ 5 files changed, 85 insertions(+), 10 deletions(-) create mode 100644 tests/ui/parser/recover-invalid-fn-trait-bound-pattern.rs create mode 100644 tests/ui/parser/recover-invalid-fn-trait-bound-pattern.stderr create mode 100644 tests/ui/parser/recover-invalid-function-parameter-pattern.rs create mode 100644 tests/ui/parser/recover-invalid-function-parameter-pattern.stderr diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index db6af6ab17aca..928518c88fec6 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -2140,16 +2140,32 @@ impl<'a> Parser<'a> { let pat = self.parse_pat_no_top_alt(Some(Expected::ArgumentName), None)?; self.expect(exp!(Colon))?; let ty = self.parse_ty()?; - self.dcx().emit_err(PatternMethodParamWithoutBody { - span: pat.span, - target: match context { - FnContext::Trait => "methods without bodies", - FnContext::FunctionPtrType => "function pointer types", - FnContext::ParenthesizedArgumentList => "parenthesized argument list", - FnContext::Free => unreachable!("This method is not called in free functions, as patterns are always allowed there"), - FnContext::Impl => unreachable!("This method is not called in impls, as patterns are always allowed there"), - }, - }); + match context { + FnContext::Trait + | FnContext::FunctionPtrType + | FnContext::ParenthesizedArgumentList => { + self.dcx().emit_err(PatternMethodParamWithoutBody { + span: pat.span, + target: if context == FnContext::Trait { + "methods without bodies" + } else if context == FnContext::FunctionPtrType { + "function pointer types" + } else { + "parenthesized argument list" + }, + }); + } + FnContext::Free | FnContext::Impl => { + self.dcx().span_delayed_bug( + pat.span, + if context == FnContext::Free { + "This method is not called in free functions, as patterns are always allowed there" + } else { + "This method is not called in impls, as patterns are always allowed there" + }, + ); + } + } // Pretend the pattern is `_`, to avoid duplicate errors from AST validation. let pat = Box::new(Pat { kind: PatKind::Wild, span: pat.span, id: ast::DUMMY_NODE_ID }); diff --git a/tests/ui/parser/recover-invalid-fn-trait-bound-pattern.rs b/tests/ui/parser/recover-invalid-fn-trait-bound-pattern.rs new file mode 100644 index 0000000000000..abbff103bb2be --- /dev/null +++ b/tests/ui/parser/recover-invalid-fn-trait-bound-pattern.rs @@ -0,0 +1,5 @@ +// Regression test for https://github.com/rust-lang/rust/issues/160337. + +struct Baz where U : fn(() : bool) +//~^ ERROR expected identifier, found keyword `fn` +//~| ERROR expected `{` after struct name, found `` diff --git a/tests/ui/parser/recover-invalid-fn-trait-bound-pattern.stderr b/tests/ui/parser/recover-invalid-fn-trait-bound-pattern.stderr new file mode 100644 index 0000000000000..02ec950b3a365 --- /dev/null +++ b/tests/ui/parser/recover-invalid-fn-trait-bound-pattern.stderr @@ -0,0 +1,20 @@ +error: expected identifier, found keyword `fn` + --> $DIR/recover-invalid-fn-trait-bound-pattern.rs:3:22 + | +LL | struct Baz where U : fn(() : bool) + | ^^ + | +help: use `Fn` to refer to the trait (notice the capitalization) + | +LL - struct Baz where U : fn(() : bool) +LL + struct Baz where U : Fn(() : bool) + | + +error: expected `{` after struct name, found `` + --> $DIR/recover-invalid-fn-trait-bound-pattern.rs:3:34 + | +LL | struct Baz where U : fn(() : bool) + | ^ expected `{` after struct name + +error: aborting due to 2 previous errors + diff --git a/tests/ui/parser/recover-invalid-function-parameter-pattern.rs b/tests/ui/parser/recover-invalid-function-parameter-pattern.rs new file mode 100644 index 0000000000000..a9e6a5578486f --- /dev/null +++ b/tests/ui/parser/recover-invalid-function-parameter-pattern.rs @@ -0,0 +1,6 @@ +// Regression test for https://github.com/rust-lang/rust/issues/160337. + +fn main(... : ...) +//~^ ERROR unexpected `...` +//~| ERROR unexpected `...` +//~| ERROR expected one of `->`, `where`, or `{`, found `` diff --git a/tests/ui/parser/recover-invalid-function-parameter-pattern.stderr b/tests/ui/parser/recover-invalid-function-parameter-pattern.stderr new file mode 100644 index 0000000000000..d4b78db29dba9 --- /dev/null +++ b/tests/ui/parser/recover-invalid-function-parameter-pattern.stderr @@ -0,0 +1,28 @@ +error: unexpected `...` + --> $DIR/recover-invalid-function-parameter-pattern.rs:3:9 + | +LL | fn main(... : ...) + | ^^^ not a valid pattern + | +help: for a rest pattern, use `..` instead of `...` + | +LL - fn main(... : ...) +LL + fn main(.. : ...) + | + +error: unexpected `...` + --> $DIR/recover-invalid-function-parameter-pattern.rs:3:15 + | +LL | fn main(... : ...) + | ^^^ + | + = note: only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list + +error: expected one of `->`, `where`, or `{`, found `` + --> $DIR/recover-invalid-function-parameter-pattern.rs:3:18 + | +LL | fn main(... : ...) + | ^ expected one of `->`, `where`, or `{` + +error: aborting due to 3 previous errors + From a91d256934cc9d62cd65972323246d243e8d7730 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 22 Sep 2026 18:47:35 +0000 Subject: [PATCH 18/23] Update comment --- .../src/diagnostics/region_errors.rs | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index 9d795ff567087..6ded70f4c5100 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -399,7 +399,7 @@ impl<'diag, 'tcx> MirBorrowckCtxt<'_, 'diag, 'tcx> { /// --> $DIR/static-impl-obligation.rs:163:9 /// | /// LL | fn bar<'a>(x: &'a &'a u32) { - /// | -- - `x` is a reference that is only valid in the function body + /// | -- - `x` is only valid in the function body /// | | /// | lifetime `'a` defined here /// LL | let y: &dyn Foo = x; @@ -409,13 +409,17 @@ impl<'diag, 'tcx> MirBorrowckCtxt<'_, 'diag, 'tcx> { /// | `x` escapes the function body here /// | argument requires that `'a` must outlive `'static` /// | - /// note: `'static` requirement for `<(dyn o::Foo + 'static)>::hello` introduced here - /// --> $DIR/static-impl-obligation.rs:158:40 + /// note: `'static` lifetime requirement from `<(dyn o::Foo + 'static)>::hello` introduced here + /// --> $DIR/static-impl-obligation.rs:158:20 /// | /// LL | impl dyn Foo + 'static where Self: 'static { - /// | ^^^^^^^ `'static` requirement introduced here + /// | ^^^^^^^ ^^^^^^^ lifetime requirement introduced here + /// | | + /// | lifetime requirement introduced here /// LL | fn hello(&'static self) where Self: 'static {} - /// | ^^^^^^^ `'static` requirement introduced here + /// | ^^^^^^^^^^^^^ ^^^^^^^ lifetime requirement introduced here + /// | | + /// | lifetime requirement introduced here /// ``` fn explain_impl_static_obligation( &self, From 693bf504c707e17f7fc7450277be10c193a1465d Mon Sep 17 00:00:00 2001 From: mejrs <59372212+mejrs@users.noreply.github.com> Date: Wed, 23 Sep 2026 14:27:49 +0200 Subject: [PATCH 19/23] Update deprecated rustc_hir imports --- Cargo.lock | 10 ++++++- compiler/rustc_const_eval/Cargo.toml | 1 + .../src/check_consts/check.rs | 20 ++++++------- .../rustc_const_eval/src/check_consts/mod.rs | 3 +- .../rustc_const_eval/src/check_consts/ops.rs | 2 +- .../src/check_consts/post_drop_elaboration.rs | 2 +- .../src/check_consts/qualifs.rs | 2 +- .../src/const_eval/fn_queries.rs | 3 +- .../src/const_eval/machine.rs | 7 +++-- .../src/const_eval/type_info.rs | 2 +- .../rustc_const_eval/src/interpret/call.rs | 2 +- .../src/util/caller_location.rs | 2 +- compiler/rustc_hir/src/lib.rs | 11 +++----- compiler/rustc_hir_analysis/Cargo.toml | 1 + .../src/check/always_applicable.rs | 3 +- .../rustc_hir_analysis/src/check/check.rs | 4 +-- .../src/check/compare_eii.rs | 4 +-- .../rustc_hir_analysis/src/check/entry.rs | 3 +- .../rustc_hir_analysis/src/check/intrinsic.rs | 2 +- compiler/rustc_hir_analysis/src/check/mod.rs | 2 +- .../rustc_hir_analysis/src/check/wfcheck.rs | 6 ++-- .../src/coherence/builtin.rs | 2 +- .../src/coherence/builtin/coerce_shared.rs | 2 +- .../src/coherence/inherent_impls.rs | 2 +- .../rustc_hir_analysis/src/coherence/mod.rs | 2 +- .../src/coherence/unsafety.rs | 2 +- compiler/rustc_hir_analysis/src/collect.rs | 3 +- .../src/collect/clauses_of.rs | 2 +- .../src/hir_ty_lowering/bounds.rs | 5 ++-- .../src/hir_ty_lowering/dyn_trait.rs | 2 +- .../src/hir_ty_lowering/mod.rs | 2 +- .../rustc_hir_analysis/src/outlives/dump.rs | 2 +- .../rustc_hir_analysis/src/variance/dump.rs | 2 +- compiler/rustc_incremental/Cargo.toml | 1 + .../rustc_incremental/src/assert_dep_graph.rs | 3 +- .../rustc_incremental/src/persist/clean.rs | 7 ++--- compiler/rustc_lint/Cargo.toml | 1 + compiler/rustc_lint/src/autorefs.rs | 3 +- compiler/rustc_lint/src/builtin.rs | 28 +++++++++---------- compiler/rustc_lint/src/c_void_returns.rs | 2 +- compiler/rustc_lint/src/context.rs | 5 +++- compiler/rustc_lint/src/dangling.rs | 5 ++-- .../src/deref_into_dyn_supertrait.rs | 2 +- .../rustc_lint/src/disallowed_pass_by_ref.rs | 3 +- .../src/for_loops_over_fallibles.rs | 2 +- compiler/rustc_lint/src/foreign_modules.rs | 2 +- compiler/rustc_lint/src/gpukernel_abi.rs | 3 +- .../rustc_lint/src/interior_mutable_consts.rs | 3 +- compiler/rustc_lint/src/internal.rs | 3 +- .../src/multiple_supertrait_upcastable.rs | 2 +- compiler/rustc_lint/src/non_fmt_panic.rs | 2 +- compiler/rustc_lint/src/non_local_def.rs | 3 +- compiler/rustc_lint/src/nonstandard_style.rs | 4 +-- compiler/rustc_lint/src/passes.rs | 6 ++-- compiler/rustc_lint/src/ptr_nulls.rs | 3 +- compiler/rustc_lint/src/runtime_symbols.rs | 2 +- compiler/rustc_lint/src/shadowed_into_iter.rs | 2 +- compiler/rustc_lint/src/traits.rs | 2 +- compiler/rustc_lint/src/types.rs | 5 ++-- compiler/rustc_lint/src/unused/must_use.rs | 5 ++-- compiler/rustc_metadata/Cargo.toml | 1 + compiler/rustc_metadata/src/creader.rs | 3 +- compiler/rustc_metadata/src/eii.rs | 3 +- compiler/rustc_metadata/src/native_libs.rs | 3 +- compiler/rustc_metadata/src/rmeta/decoder.rs | 6 ++-- .../src/rmeta/decoder/cstore_impl.rs | 2 +- compiler/rustc_metadata/src/rmeta/encoder.rs | 11 ++++---- compiler/rustc_metadata/src/rmeta/mod.rs | 18 ++++++------ .../rustc_metadata/src/rmeta/parameterized.rs | 18 ++++++------ compiler/rustc_mir_dataflow/Cargo.toml | 2 +- .../src/framework/graphviz.rs | 3 +- compiler/rustc_mir_dataflow/src/rustc_peek.rs | 3 +- compiler/rustc_monomorphize/Cargo.toml | 1 + compiler/rustc_monomorphize/src/collector.rs | 4 +-- compiler/rustc_monomorphize/src/lib.rs | 2 +- .../rustc_monomorphize/src/partitioning.rs | 4 +-- compiler/rustc_passes/src/check_export.rs | 2 +- compiler/rustc_passes/src/dead.rs | 3 +- compiler/rustc_passes/src/entry.rs | 3 +- compiler/rustc_passes/src/input_stats.rs | 2 +- compiler/rustc_privacy/Cargo.toml | 1 + compiler/rustc_privacy/src/lib.rs | 3 +- .../rustc_resolve/src/build_reduced_graph.rs | 3 +- .../rustc_resolve/src/diagnostics/impls.rs | 8 ++++-- .../rustc_resolve/src/late/diagnostics.rs | 8 +++--- compiler/rustc_resolve/src/lib.rs | 4 +-- compiler/rustc_resolve/src/macros.rs | 5 ++-- compiler/rustc_trait_selection/Cargo.toml | 1 + .../src/error_reporting/infer/mod.rs | 5 ++-- .../error_reporting/infer/note_and_explain.rs | 5 ++-- .../src/error_reporting/traits/ambiguity.rs | 2 +- .../src/error_reporting/traits/call_kind.rs | 2 +- .../traits/fulfillment_errors.rs | 7 +++-- .../src/error_reporting/traits/mod.rs | 2 +- .../traits/on_unimplemented.rs | 4 +-- .../src/error_reporting/traits/suggestions.rs | 2 +- compiler/rustc_trait_selection/src/infer.rs | 2 +- .../src/solve/delegate.rs | 2 +- .../src/solve/fulfill/derive_errors.rs | 2 +- .../src/traits/dyn_compatibility.rs | 2 +- .../src/traits/effects.rs | 2 +- .../rustc_trait_selection/src/traits/misc.rs | 5 ++-- .../src/traits/project.rs | 2 +- .../src/traits/select/candidate_assembly.rs | 2 +- .../src/traits/select/confirmation.rs | 2 +- .../src/traits/select/mod.rs | 2 +- .../rustc_trait_selection/src/traits/util.rs | 2 +- .../rustc_trait_selection/src/traits/wf.rs | 2 +- compiler/rustc_ty_utils/src/abi.rs | 3 +- compiler/rustc_ty_utils/src/layout.rs | 5 ++-- compiler/rustc_ty_utils/src/needs_drop.rs | 2 +- 111 files changed, 225 insertions(+), 197 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a1a43f47965c0..5f35ce252b78e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3872,6 +3872,7 @@ dependencies = [ "rustc_abi", "rustc_apfloat", "rustc_ast", + "rustc_attr_ir", "rustc_data_structures", "rustc_errors", "rustc_hir", @@ -4129,6 +4130,7 @@ dependencies = [ "rustc_abi", "rustc_arena", "rustc_ast", + "rustc_attr_ir", "rustc_data_structures", "rustc_errors", "rustc_feature", @@ -4204,6 +4206,7 @@ name = "rustc_incremental" version = "0.0.0" dependencies = [ "rand 0.9.3", + "rustc_attr_ir", "rustc_data_structures", "rustc_errors", "rustc_fs_util", @@ -4325,6 +4328,7 @@ dependencies = [ "rustc_apfloat", "rustc_ast", "rustc_ast_pretty", + "rustc_attr_ir", "rustc_attr_parsing", "rustc_data_structures", "rustc_errors", @@ -4403,6 +4407,7 @@ dependencies = [ "odht", "rustc_abi", "rustc_ast", + "rustc_attr_ir", "rustc_attr_parsing", "rustc_crate_store", "rustc_data_structures", @@ -4493,10 +4498,10 @@ dependencies = [ "polonius-engine", "regex", "rustc_abi", + "rustc_attr_ir", "rustc_data_structures", "rustc_errors", "rustc_graphviz", - "rustc_hir", "rustc_index", "rustc_macros", "rustc_middle", @@ -4539,6 +4544,7 @@ version = "0.0.0" dependencies = [ "rustc_abi", "rustc_ast", + "rustc_attr_ir", "rustc_data_structures", "rustc_errors", "rustc_hir", @@ -4656,6 +4662,7 @@ name = "rustc_privacy" version = "0.0.0" dependencies = [ "rustc_ast", + "rustc_attr_ir", "rustc_data_structures", "rustc_errors", "rustc_hir", @@ -4913,6 +4920,7 @@ dependencies = [ "itertools", "rustc_abi", "rustc_ast", + "rustc_attr_ir", "rustc_crate_store", "rustc_data_structures", "rustc_errors", diff --git a/compiler/rustc_const_eval/Cargo.toml b/compiler/rustc_const_eval/Cargo.toml index 296368c42034b..8d14d86581a66 100644 --- a/compiler/rustc_const_eval/Cargo.toml +++ b/compiler/rustc_const_eval/Cargo.toml @@ -9,6 +9,7 @@ either = "1" rustc_abi = { path = "../rustc_abi" } rustc_apfloat = "0.2.0" rustc_ast = { path = "../rustc_ast" } +rustc_attr_ir = { path = "../rustc_attr_ir" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } rustc_hir = { path = "../rustc_hir" } diff --git a/compiler/rustc_const_eval/src/check_consts/check.rs b/compiler/rustc_const_eval/src/check_consts/check.rs index c9217856252d8..192bb8556a75d 100644 --- a/compiler/rustc_const_eval/src/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/check_consts/check.rs @@ -5,11 +5,12 @@ use std::num::NonZero; use std::ops::Deref; use std::{assert_matches, mem}; +use rustc_attr_ir::lang_items::LangItem; +use rustc_attr_ir::{ConstStability, StabilityLevel, find_attr}; use rustc_errors::{Diag, ErrorGuaranteed}; -use rustc_hir::attrs::lang_items::LangItem; +use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::def_id::DefId; -use rustc_hir::{self as hir, find_attr}; use rustc_index::bit_set::DenseBitSet; use rustc_infer::infer::TyCtxtInferExt; use rustc_middle::mir::visit::Visitor; @@ -427,7 +428,7 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> { /// Check the const stability of the given item (fn or trait). fn check_callee_stability(&mut self, def_id: DefId) { match self.tcx.lookup_const_stability(def_id) { - Some(hir::ConstStability { level: hir::StabilityLevel::Stable { .. }, .. }) => { + Some(ConstStability { level: StabilityLevel::Stable { .. }, .. }) => { // All good. } None => { @@ -443,8 +444,8 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> { }); } } - Some(hir::ConstStability { - level: hir::StabilityLevel::Unstable { implied_by: implied_feature, issue, .. }, + Some(ConstStability { + level: StabilityLevel::Unstable { implied_by: implied_feature, issue, .. }, feature, .. }) => { @@ -858,8 +859,8 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { }); } } - Some(hir::ConstStability { - level: hir::StabilityLevel::Unstable { .. }, + Some(ConstStability { + level: StabilityLevel::Unstable { .. }, feature, .. }) => { @@ -878,10 +879,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { const_stable_indirect, }); } - Some(hir::ConstStability { - level: hir::StabilityLevel::Stable { .. }, - .. - }) => { + Some(ConstStability { level: StabilityLevel::Stable { .. }, .. }) => { // All good. Note that a `#[rustc_const_stable]` intrinsic (meaning it // can be *directly* invoked from stable const code) does not always // have the `#[rustc_intrinsic_const_stable_indirect]` attribute (which controls diff --git a/compiler/rustc_const_eval/src/check_consts/mod.rs b/compiler/rustc_const_eval/src/check_consts/mod.rs index df7d0a2182428..99b6062a23ac4 100644 --- a/compiler/rustc_const_eval/src/check_consts/mod.rs +++ b/compiler/rustc_const_eval/src/check_consts/mod.rs @@ -4,9 +4,10 @@ //! has interior mutability or needs to be dropped, as well as the visitor that emits errors when //! it finds operations that are invalid in a certain context. +use rustc_attr_ir::find_attr; use rustc_errors::DiagCtxtHandle; +use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; -use rustc_hir::{self as hir, find_attr}; use rustc_middle::mir; use rustc_middle::ty::{self, PolyFnSig, TyCtxt}; use rustc_span::{Symbol, bug}; diff --git a/compiler/rustc_const_eval/src/check_consts/ops.rs b/compiler/rustc_const_eval/src/check_consts/ops.rs index 1d1a99d2c6095..ace12201abf02 100644 --- a/compiler/rustc_const_eval/src/check_consts/ops.rs +++ b/compiler/rustc_const_eval/src/check_consts/ops.rs @@ -1,10 +1,10 @@ //! Concrete error types for all operations which may be invalid in a certain const context. use hir::ConstContext; +use rustc_attr_ir::lang_items::LangItem; use rustc_errors::codes::*; use rustc_errors::{Applicability, Diag, MultiSpan, msg}; use rustc_hir as hir; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::def_id::DefId; use rustc_infer::infer::TyCtxtInferExt; use rustc_infer::traits::{ImplSource, Obligation, ObligationCause}; diff --git a/compiler/rustc_const_eval/src/check_consts/post_drop_elaboration.rs b/compiler/rustc_const_eval/src/check_consts/post_drop_elaboration.rs index 34d4ce9f9f2c2..e8ddff445133e 100644 --- a/compiler/rustc_const_eval/src/check_consts/post_drop_elaboration.rs +++ b/compiler/rustc_const_eval/src/check_consts/post_drop_elaboration.rs @@ -1,4 +1,4 @@ -use rustc_hir::find_attr; +use rustc_attr_ir::find_attr; use rustc_middle::mir::visit::Visitor; use rustc_middle::mir::{self, BasicBlock, Location}; use rustc_middle::ty::TyCtxt; diff --git a/compiler/rustc_const_eval/src/check_consts/qualifs.rs b/compiler/rustc_const_eval/src/check_consts/qualifs.rs index 9331c50b84b37..4d1a72808972b 100644 --- a/compiler/rustc_const_eval/src/check_consts/qualifs.rs +++ b/compiler/rustc_const_eval/src/check_consts/qualifs.rs @@ -5,8 +5,8 @@ // FIXME(const_trait_impl): This API should be really reworked. It's dangerously general for // having basically only two use-cases that act in different ways. +use rustc_attr_ir::lang_items::LangItem; use rustc_errors::ErrorGuaranteed; -use rustc_hir::attrs::lang_items::LangItem; use rustc_infer::infer::TyCtxtInferExt; use rustc_middle::mir; use rustc_middle::mir::*; diff --git a/compiler/rustc_const_eval/src/const_eval/fn_queries.rs b/compiler/rustc_const_eval/src/const_eval/fn_queries.rs index 8267cb66e9e15..4da9d79a8434a 100644 --- a/compiler/rustc_const_eval/src/const_eval/fn_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/fn_queries.rs @@ -1,7 +1,8 @@ +use rustc_attr_ir::find_attr; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::{ Constness, ExprKind, ForeignItemKind, ImplItem, ImplItemImplKind, ImplItemKind, Item, ItemKind, - Node, TraitItem, TraitItemKind, VariantData, find_attr, + Node, TraitItem, TraitItemKind, VariantData, }; use rustc_middle::query::Providers; use rustc_middle::ty::TyCtxt; diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index c0617c19263e7..843cd7cb4930d 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -4,10 +4,11 @@ use std::{fmt, mem}; use rustc_abi::{Align, FIRST_VARIANT, FieldIdx, Size, VariantIdx}; use rustc_ast::Mutability; +use rustc_attr_ir::find_attr; +use rustc_attr_ir::lang_items::LangItem; use rustc_data_structures::fx::{FxHashMap, FxIndexMap, IndexEntry}; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::def_id::{DefId, LocalDefId}; -use rustc_hir::{self as hir, CRATE_HIR_ID, find_attr}; +use rustc_hir::{CRATE_HIR_ID, HirId}; use rustc_lint_defs::builtin::LONG_RUNNING_CONST_EVAL; use rustc_middle::mir; use rustc_middle::mir::AssertMessage; @@ -394,7 +395,7 @@ impl<'tcx> CompileTimeMachine<'tcx> { #[inline(always)] /// Find the first stack frame that is within the current crate, if any. /// Otherwise, return the crate's HirId - pub fn best_lint_scope(&self, tcx: TyCtxt<'tcx>) -> hir::HirId { + pub fn best_lint_scope(&self, tcx: TyCtxt<'tcx>) -> HirId { self.stack.iter().find_map(|frame| frame.lint_root(tcx)).unwrap_or(CRATE_HIR_ID) } } diff --git a/compiler/rustc_const_eval/src/const_eval/type_info.rs b/compiler/rustc_const_eval/src/const_eval/type_info.rs index f0875952a5039..0bece36c64ed0 100644 --- a/compiler/rustc_const_eval/src/const_eval/type_info.rs +++ b/compiler/rustc_const_eval/src/const_eval/type_info.rs @@ -3,7 +3,7 @@ mod adt; use std::borrow::Cow; use rustc_abi::{ExternAbi, FieldIdx}; -use rustc_hir::attrs::lang_items::LangItem; +use rustc_attr_ir::lang_items::LangItem; use rustc_middle::ty::layout::TyAndLayout; use rustc_middle::ty::{self, FnHeader, FnSigKind, FnSigTys, ScalarInt, Ty, TyCtxt}; use rustc_span::{Symbol, span_bug, sym}; diff --git a/compiler/rustc_const_eval/src/interpret/call.rs b/compiler/rustc_const_eval/src/interpret/call.rs index 3bf020009beed..c7615a216312e 100644 --- a/compiler/rustc_const_eval/src/interpret/call.rs +++ b/compiler/rustc_const_eval/src/interpret/call.rs @@ -6,8 +6,8 @@ use std::borrow::Cow; use either::{Left, Right}; use rustc_abi::{self as abi, ExternAbi, FieldIdx, Integer, VariantIdx}; +use rustc_attr_ir::find_attr; use rustc_hir::def_id::DefId; -use rustc_hir::find_attr; use rustc_middle::mir; use rustc_middle::ty::layout::{IntegerExt, TyAndLayout}; use rustc_middle::ty::{self, AdtDef, FieldDef, Instance, Ty, VariantDef}; diff --git a/compiler/rustc_const_eval/src/util/caller_location.rs b/compiler/rustc_const_eval/src/util/caller_location.rs index 99220a23de4fc..c76da6c6a36c8 100644 --- a/compiler/rustc_const_eval/src/util/caller_location.rs +++ b/compiler/rustc_const_eval/src/util/caller_location.rs @@ -1,5 +1,5 @@ use rustc_abi::FieldIdx; -use rustc_hir::attrs::lang_items::LangItem; +use rustc_attr_ir::lang_items::LangItem; use rustc_middle::mir; use rustc_middle::ty::{self, TyCtxt}; use rustc_span::{Symbol, bug}; diff --git a/compiler/rustc_hir/src/lib.rs b/compiler/rustc_hir/src/lib.rs index 5855c1126a971..5a23d23e4f622 100644 --- a/compiler/rustc_hir/src/lib.rs +++ b/compiler/rustc_hir/src/lib.rs @@ -24,17 +24,14 @@ pub mod pat_util; mod stable_hash_impls; mod target_impls; -// FIXME: Remove this use tree, replace by `rustc_attr_ir` imports -#[doc(hidden)] -pub use attrs::{ - Attribute, ConstStability, DefaultBodyStability, Stability, StabilityLevel, StableSince, - UnstableReason, target::Target, -}; #[doc(no_inline)] pub use hir::*; // FIXME: Remove this use tree, replace by `rustc_attr_ir` imports #[doc(hidden)] -pub use rustc_attr_ir::{self as attrs, find_attr}; +pub use rustc_attr_ir::{ + self as attrs, Attribute, ConstStability, DefaultBodyStability, Stability, StabilityLevel, + StableSince, find_attr, target::Target, +}; pub use rustc_hir_id::*; pub use rustc_span::def_id; diff --git a/compiler/rustc_hir_analysis/Cargo.toml b/compiler/rustc_hir_analysis/Cargo.toml index 06092f53272ce..a250ed77bb8c2 100644 --- a/compiler/rustc_hir_analysis/Cargo.toml +++ b/compiler/rustc_hir_analysis/Cargo.toml @@ -13,6 +13,7 @@ itertools = "0.15" rustc_abi = { path = "../rustc_abi" } rustc_arena = { path = "../rustc_arena" } rustc_ast = { path = "../rustc_ast" } +rustc_attr_ir = { path = "../rustc_attr_ir" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } rustc_feature = { path = "../rustc_feature" } diff --git a/compiler/rustc_hir_analysis/src/check/always_applicable.rs b/compiler/rustc_hir_analysis/src/check/always_applicable.rs index b098a6c186457..e805ccb4a1d89 100644 --- a/compiler/rustc_hir_analysis/src/check/always_applicable.rs +++ b/compiler/rustc_hir_analysis/src/check/always_applicable.rs @@ -4,6 +4,7 @@ //! //! This is necessary for `Drop` and negative impls to be well-formed. +use rustc_attr_ir::find_attr; use rustc_data_structures::fx::FxHashSet; use rustc_errors::codes::*; use rustc_errors::{ErrorGuaranteed, struct_span_code_err}; @@ -442,7 +443,7 @@ fn check_drop_xor_pin_drop<'tcx>( } (Some(span), None) => { if tcx.adt_def(adt_def_id).is_pin_project() { - let pin_v2_span = rustc_hir::find_attr!(tcx, adt_def_id, PinV2(attr) => *attr); + let pin_v2_span = find_attr!(tcx, adt_def_id, PinV2(attr) => *attr); let adt_name = tcx.item_name(adt_def_id); return Err(tcx.dcx().emit_err(crate::diagnostics::PinV2WithoutPinDrop { span, diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 924041c399ef1..f35b901633fcb 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -2,12 +2,12 @@ use std::cell::LazyCell; use std::ops::ControlFlow; use rustc_abi::{ExternAbi, FieldIdx, MAX_SIMD_LANES, ScalableElt}; +use rustc_attr_ir::ReprAttr::ReprPacked; +use rustc_attr_ir::lang_items::LangItem; use rustc_data_structures::unord::{UnordMap, UnordSet}; use rustc_errors::codes::*; use rustc_errors::{Diag, DiagCtxtHandle, Diagnostic, Level, MultiSpan}; use rustc_hir as hir; -use rustc_hir::attrs::ReprAttr::ReprPacked; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::def::{CtorKind, DefKind}; use rustc_hir::{Node, find_attr, intravisit}; use rustc_infer::infer::{RegionVariableOrigin, TyCtxtInferExt}; diff --git a/compiler/rustc_hir_analysis/src/check/compare_eii.rs b/compiler/rustc_hir_analysis/src/check/compare_eii.rs index c9fd3da24fe07..6e22ce3d84b76 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_eii.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_eii.rs @@ -6,12 +6,12 @@ use std::borrow::Cow; use std::iter; +use rustc_attr_ir::{EiiImplResolution, find_attr}; use rustc_data_structures::fx::FxIndexSet; use rustc_errors::{Applicability, E0806, struct_span_code_err}; -use rustc_hir::attrs::EiiImplResolution; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; -use rustc_hir::{self as hir, FnSig, HirId, ItemKind, find_attr}; +use rustc_hir::{self as hir, FnSig, HirId, ItemKind}; use rustc_infer::infer::{self, InferCtxt, TyCtxtInferExt}; use rustc_infer::traits::{ObligationCause, ObligationCauseCode, TraitErrors}; use rustc_middle::ty::error::{ExpectedFound, TypeError}; diff --git a/compiler/rustc_hir_analysis/src/check/entry.rs b/compiler/rustc_hir_analysis/src/check/entry.rs index a115ccba9ad08..17123376159de 100644 --- a/compiler/rustc_hir_analysis/src/check/entry.rs +++ b/compiler/rustc_hir_analysis/src/check/entry.rs @@ -1,7 +1,8 @@ use std::ops::Not; +use rustc_attr_ir::find_attr; use rustc_hir as hir; -use rustc_hir::{Node, find_attr}; +use rustc_hir::Node; use rustc_infer::infer::TyCtxtInferExt; use rustc_infer::traits::TraitErrors; use rustc_middle::ty::{self, TyCtxt, TypingMode, Unnormalized}; diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs index b566f6b04bf41..bcab1457e0655 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs @@ -1,8 +1,8 @@ //! Type-checking for the `#[rustc_intrinsic]` intrinsics that the compiler exposes. +use rustc_attr_ir::lang_items::LangItem; use rustc_errors::DiagMessage; use rustc_hir as hir; -use rustc_hir::attrs::lang_items::LangItem; use rustc_middle::traits::{ObligationCause, ObligationCauseCode}; use rustc_middle::ty::consts::ConstExt; use rustc_middle::ty::{self, Const, Ty, TyCtxt}; diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs index fa2b3e9f25342..00700713afc88 100644 --- a/compiler/rustc_hir_analysis/src/check/mod.rs +++ b/compiler/rustc_hir_analysis/src/check/mod.rs @@ -76,9 +76,9 @@ use std::num::NonZero; pub use check::check_abi; use rustc_abi::VariantIdx; +use rustc_attr_ir::lang_items::LangItem; use rustc_data_structures::fx::{FxHashSet, FxIndexMap}; use rustc_errors::{ErrorGuaranteed, pluralize, struct_span_code_err}; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::intravisit::Visitor; use rustc_index::bit_set::DenseBitSet; diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index bde17c39e2bc4..0a1787a23c893 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -4,16 +4,16 @@ use std::ops::{ControlFlow, Deref}; use hir::intravisit::{self, Visitor}; use rustc_abi::{ExternAbi, ScalableElt}; use rustc_ast as ast; +use rustc_attr_ir::lang_items::LangItem; +use rustc_attr_ir::{EiiDecl, EiiImpl, EiiImplResolution, find_attr}; use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; use rustc_data_structures::transitive_relation::TransitiveRelationBuilder; use rustc_errors::codes::*; use rustc_errors::{Applicability, ErrorGuaranteed, msg, pluralize, struct_span_code_err}; use rustc_hir as hir; -use rustc_hir::attrs::lang_items::LangItem; -use rustc_hir::attrs::{EiiDecl, EiiImpl, EiiImplResolution}; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{DefId, LocalDefId}; -use rustc_hir::{AmbigArg, ItemKind, find_attr}; +use rustc_hir::{AmbigArg, ItemKind}; use rustc_infer::infer::outlives::env::OutlivesEnvironment; use rustc_infer::infer::{BoundRegionConversionTime, SolverRegionConstraint, TyCtxtInferExt}; use rustc_infer::traits::{PredicateObligations, TraitErrors}; diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs index e9adabc7ca4bb..efed5994f63fe 100644 --- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs +++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs @@ -3,11 +3,11 @@ use std::collections::BTreeMap; +use rustc_attr_ir::lang_items::LangItem; use rustc_data_structures::fx::FxHashSet; use rustc_errors::{ErrorGuaranteed, MultiSpan}; use rustc_hir as hir; use rustc_hir::ItemKind; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_infer::infer::{self, InferCtxt, RegionResolutionError, SubregionOrigin, TyCtxtInferExt}; use rustc_infer::traits::{Obligation, TraitErrors}; diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin/coerce_shared.rs b/compiler/rustc_hir_analysis/src/coherence/builtin/coerce_shared.rs index 77330e4fa3b34..e405e149c8eef 100644 --- a/compiler/rustc_hir_analysis/src/coherence/builtin/coerce_shared.rs +++ b/compiler/rustc_hir_analysis/src/coherence/builtin/coerce_shared.rs @@ -1,7 +1,7 @@ +use rustc_attr_ir::lang_items::LangItem; use rustc_errors::ErrorGuaranteed; use rustc_hir as hir; use rustc_hir::ItemKind; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, TyCtxtInferExt}; use rustc_infer::traits::{Obligation, TraitErrors}; diff --git a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs index 94234cd185a02..591ff35becf81 100644 --- a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs +++ b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs @@ -7,10 +7,10 @@ //! `tcx.inherent_impls(def_id)`). That value, however, //! is computed by selecting an idea from this table. +use rustc_attr_ir::find_attr; use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; -use rustc_hir::find_attr; use rustc_middle::ty::fast_reject::{SimplifiedType, TreatParams, simplify_type}; use rustc_middle::ty::{self, CrateInherentImpls, Ty, TyCtxt}; use rustc_span::{ErrorGuaranteed, bug}; diff --git a/compiler/rustc_hir_analysis/src/coherence/mod.rs b/compiler/rustc_hir_analysis/src/coherence/mod.rs index e3f4f8d0507d3..c1ca62d333e64 100644 --- a/compiler/rustc_hir_analysis/src/coherence/mod.rs +++ b/compiler/rustc_hir_analysis/src/coherence/mod.rs @@ -5,9 +5,9 @@ // done by the orphan and overlap modules. Then we build up various // mappings. That mapping code resides here. +use rustc_attr_ir::lang_items::LangItem; use rustc_errors::codes::*; use rustc_errors::struct_span_code_err; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_middle::query::Providers; use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt, elaborate}; diff --git a/compiler/rustc_hir_analysis/src/coherence/unsafety.rs b/compiler/rustc_hir_analysis/src/coherence/unsafety.rs index 18ba46ff08913..cfca879abe8f1 100644 --- a/compiler/rustc_hir_analysis/src/coherence/unsafety.rs +++ b/compiler/rustc_hir_analysis/src/coherence/unsafety.rs @@ -1,10 +1,10 @@ //! Unsafety checker: every impl either implements a trait defined in this //! crate or pertains to a type defined in this crate. +use rustc_attr_ir::lang_items::LangItem; use rustc_errors::codes::*; use rustc_errors::struct_span_code_err; use rustc_hir::Safety; -use rustc_hir::attrs::lang_items::LangItem; use rustc_middle::ty::ImplPolarity::*; use rustc_middle::ty::print::PrintTraitRefExt as _; use rustc_middle::ty::{ImplTraitHeader, TraitDef, TyCtxt}; diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 02a7fa6f98791..8f693221b0fd2 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -19,6 +19,7 @@ use std::{assert_matches, debug_assert_matches, iter}; use rustc_abi::{ExternAbi, Size}; use rustc_ast::Recovered; +use rustc_attr_ir::find_attr; use rustc_data_structures::fx::{FxHashSet, FxIndexMap}; use rustc_data_structures::thin_vec::{ThinVec, thin_vec}; use rustc_errors::{ @@ -27,7 +28,7 @@ use rustc_errors::{ use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::intravisit::{InferKind, Visitor}; -use rustc_hir::{self as hir, GenericParamKind, HirId, Node, PreciseCapturingArgKind, find_attr}; +use rustc_hir::{self as hir, GenericParamKind, HirId, Node, PreciseCapturingArgKind}; use rustc_infer::infer::{InferCtxt, SolverRegionConstraint, TyCtxtInferExt}; use rustc_infer::traits::{DynCompatibilityViolation, ObligationCause}; use rustc_lint_defs::builtin::REPR_C_ENUMS_LARGER_THAN_INT; diff --git a/compiler/rustc_hir_analysis/src/collect/clauses_of.rs b/compiler/rustc_hir_analysis/src/collect/clauses_of.rs index 78884bab033bf..ae384a67ee6aa 100644 --- a/compiler/rustc_hir_analysis/src/collect/clauses_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/clauses_of.rs @@ -1,11 +1,11 @@ use std::assert_matches; use hir::Node; +use rustc_attr_ir::find_attr; use rustc_data_structures::fx::FxIndexSet; use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; -use rustc_hir::find_attr; use rustc_middle::ty::{ self, GenericClauses, ImplTraitInTraitData, Ty, TyCtxt, TypeVisitable, TypeVisitor, Upcast, }; diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs index 011ca64b7f32a..4bfe93f5949f7 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs @@ -1,13 +1,14 @@ use std::ops::ControlFlow; +use rustc_attr_ir::find_attr; +use rustc_attr_ir::lang_items::LangItem; use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; use rustc_errors::codes::*; use rustc_errors::struct_span_code_err; use rustc_hir as hir; -use rustc_hir::attrs::lang_items::LangItem; +use rustc_hir::PolyTraitRef; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::DefId; -use rustc_hir::{PolyTraitRef, find_attr}; use rustc_middle::ty::{ self as ty, IsSuggestable, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, Upcast, diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs index cab8fcf556edb..a3cba8ce15fda 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs @@ -1,11 +1,11 @@ use rustc_ast::TraitObjectSyntax; +use rustc_attr_ir::lang_items::LangItem; use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; use rustc_errors::codes::*; use rustc_errors::{ Applicability, Diag, DiagCtxtHandle, Diagnostic, Level, StashKey, Suggestions, struct_span_code_err, }; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::DefId; use rustc_hir::{self as hir, HirId}; 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 e7ecde09ce27b..be608ced39a48 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -25,6 +25,7 @@ use std::{assert_matches, slice}; use rustc_abi::FIRST_VARIANT; use rustc_ast::LitKind; +use rustc_attr_ir::lang_items::LangItem; use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; use rustc_data_structures::sso::SsoHashSet; use rustc_data_structures::thin_vec::ThinVec; @@ -33,7 +34,6 @@ use rustc_errors::{ Applicability, Diag, DiagCtxtHandle, ErrorGuaranteed, FatalError, StashKey, struct_span_code_err, }; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res}; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::{self as hir, AnonConst, GenericArg, GenericArgs, HirId}; diff --git a/compiler/rustc_hir_analysis/src/outlives/dump.rs b/compiler/rustc_hir_analysis/src/outlives/dump.rs index c0314c378fbdd..6cb585c6c97c5 100644 --- a/compiler/rustc_hir_analysis/src/outlives/dump.rs +++ b/compiler/rustc_hir_analysis/src/outlives/dump.rs @@ -1,4 +1,4 @@ -use rustc_hir::find_attr; +use rustc_attr_ir::find_attr; use rustc_middle::ty::{self, TyCtxt}; use rustc_span::{bug, sym}; diff --git a/compiler/rustc_hir_analysis/src/variance/dump.rs b/compiler/rustc_hir_analysis/src/variance/dump.rs index 7963f5da0e870..aa05e512dc2af 100644 --- a/compiler/rustc_hir_analysis/src/variance/dump.rs +++ b/compiler/rustc_hir_analysis/src/variance/dump.rs @@ -1,8 +1,8 @@ use std::fmt::Write; +use rustc_attr_ir::find_attr; use rustc_hir::def::DefKind; use rustc_hir::def_id::LocalDefId; -use rustc_hir::find_attr; use rustc_middle::ty::{GenericArgs, TyCtxt}; fn format_variances(tcx: TyCtxt<'_>, def_id: LocalDefId) -> String { diff --git a/compiler/rustc_incremental/Cargo.toml b/compiler/rustc_incremental/Cargo.toml index ac4d7d8e1cbc0..bf331f41b0e09 100644 --- a/compiler/rustc_incremental/Cargo.toml +++ b/compiler/rustc_incremental/Cargo.toml @@ -6,6 +6,7 @@ edition = "2024" [dependencies] # tidy-alphabetical-start rand = "0.9.0" +rustc_attr_ir = { path = "../rustc_attr_ir" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } rustc_fs_util = { path = "../rustc_fs_util" } diff --git a/compiler/rustc_incremental/src/assert_dep_graph.rs b/compiler/rustc_incremental/src/assert_dep_graph.rs index be23c3466f184..8147e3c3ae550 100644 --- a/compiler/rustc_incremental/src/assert_dep_graph.rs +++ b/compiler/rustc_incremental/src/assert_dep_graph.rs @@ -37,12 +37,11 @@ use std::env; use std::fs::{self, File}; use std::io::Write; +use rustc_attr_ir::{Attribute, AttributeKind}; use rustc_data_structures::fx::FxIndexSet; use rustc_data_structures::graph::linked_graph::{Direction, INCOMING, NodeIndex, OUTGOING}; use rustc_graphviz as dot; use rustc_hir as hir; -use rustc_hir::Attribute; -use rustc_hir::attrs::AttributeKind; use rustc_hir::def_id::{CRATE_DEF_ID, DefId, LocalDefId}; use rustc_hir::intravisit::{self, Visitor}; use rustc_middle::dep_graph::{DepKind, DepNode, DepNodeFilter, EdgeFilter, RetainedDepGraph}; diff --git a/compiler/rustc_incremental/src/persist/clean.rs b/compiler/rustc_incremental/src/persist/clean.rs index a311832e62d96..b6402181fba12 100644 --- a/compiler/rustc_incremental/src/persist/clean.rs +++ b/compiler/rustc_incremental/src/persist/clean.rs @@ -19,14 +19,11 @@ //! Errors are reported if we are in the suitable configuration but //! the required condition is not met. +use rustc_attr_ir::{Attribute, AttributeKind, RustcCleanAttribute, find_attr}; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::unord::UnordSet; -use rustc_hir::attrs::{AttributeKind, RustcCleanAttribute}; use rustc_hir::def_id::LocalDefId; -use rustc_hir::{ - Attribute, ImplItemKind, ItemKind as HirItem, Node as HirNode, TraitItemKind, find_attr, - intravisit, -}; +use rustc_hir::{ImplItemKind, ItemKind as HirItem, Node as HirNode, TraitItemKind, intravisit}; use rustc_middle::dep_graph::{DepKind, DepNode, dep_kind_from_label}; use rustc_middle::hir::nested_filter; use rustc_middle::ty::TyCtxt; diff --git a/compiler/rustc_lint/Cargo.toml b/compiler/rustc_lint/Cargo.toml index a672f242449e4..0024d8b26f1fb 100644 --- a/compiler/rustc_lint/Cargo.toml +++ b/compiler/rustc_lint/Cargo.toml @@ -10,6 +10,7 @@ rustc_abi = { path = "../rustc_abi" } rustc_apfloat = "0.2.0" rustc_ast = { path = "../rustc_ast" } rustc_ast_pretty = { path = "../rustc_ast_pretty" } +rustc_attr_ir = { path = "../rustc_attr_ir" } rustc_attr_parsing = { path = "../rustc_attr_parsing" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } diff --git a/compiler/rustc_lint/src/autorefs.rs b/compiler/rustc_lint/src/autorefs.rs index 728937b762110..0064e8c6b3a23 100644 --- a/compiler/rustc_lint/src/autorefs.rs +++ b/compiler/rustc_lint/src/autorefs.rs @@ -1,5 +1,6 @@ use rustc_ast::{BorrowKind, UnOp}; -use rustc_hir::{Expr, ExprKind, Mutability, find_attr}; +use rustc_attr_ir::find_attr; +use rustc_hir::{Expr, ExprKind, Mutability}; use rustc_lint_defs::{declare_lint, declare_lint_pass}; use rustc_middle::ty::adjustment::{ Adjust, Adjustment, AutoBorrow, DerefAdjustKind, OverloadedDeref, diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 7ccbef12af4c6..bba993ee3f052 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -21,15 +21,15 @@ use rustc_ast::tokenstream::{TokenStream, TokenTree}; use rustc_ast::visit::{FnCtxt, FnKind}; use rustc_ast::{self as ast, *}; use rustc_ast_pretty::pprust::expr_to_string; +use rustc_attr_ir::lang_items::LangItem; +use rustc_attr_ir::{AttributeKind, DocAttribute, find_attr}; use rustc_attr_parsing::AttributeParser; use rustc_errors::{Applicability, Diagnostic, msg}; use rustc_feature::GateIssue; -use rustc_hir::attrs::lang_items::LangItem; -use rustc_hir::attrs::{AttributeKind, DocAttribute}; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{CRATE_DEF_ID, DefId, LocalDefId}; use rustc_hir::intravisit::FnKind as HirFnKind; -use rustc_hir::{self as hir, Body, FnDecl, ImplItemImplKind, PatKind, PredicateOrigin, find_attr}; +use rustc_hir::{self as hir, Body, FnDecl, ImplItemImplKind, PatKind, PredicateOrigin}; // Lints from rustc_lint_defs pub use rustc_lint_defs::builtin::*; use rustc_lint_defs::{declare_lint, declare_lint_pass, fcw, impl_lint_pass}; @@ -239,13 +239,13 @@ impl EarlyLintPass for UnsafeCode { } ast::ItemKind::MacroDef(..) => { - if let Some(hir::Attribute::Parsed(AttributeKind::AllowInternalUnsafe(span))) = - AttributeParser::parse_limited_sym( - cx.builder.sess(), - &it.attrs, - &[sym::allow_internal_unsafe], - ) - { + if let Some(rustc_attr_ir::Attribute::Parsed(AttributeKind::AllowInternalUnsafe( + span, + ))) = AttributeParser::parse_limited_sym( + cx.builder.sess(), + &it.attrs, + &[sym::allow_internal_unsafe], + ) { self.report_unsafe(cx, span, BuiltinUnsafe::AllowInternalUnsafe); } } @@ -307,12 +307,12 @@ pub struct MissingDoc; impl_lint_pass!(MissingDoc => [MISSING_DOCS]); -fn has_doc(attr: &hir::Attribute) -> bool { - if matches!(attr, hir::Attribute::Parsed(AttributeKind::DocComment { .. })) { +fn has_doc(attr: &rustc_attr_ir::Attribute) -> bool { + if matches!(attr, rustc_attr_ir::Attribute::Parsed(AttributeKind::DocComment { .. })) { return true; } - if let hir::Attribute::Parsed(AttributeKind::Doc(d)) = attr + if let rustc_attr_ir::Attribute::Parsed(AttributeKind::Doc(d)) = attr && matches!(d.as_ref(), DocAttribute { hidden: Some(..), .. }) { return true; @@ -1030,7 +1030,7 @@ declare_lint_pass!( ); impl<'tcx> LateLintPass<'tcx> for UnstableFeatures { - fn check_attributes(&mut self, cx: &LateContext<'_>, attrs: &[hir::Attribute]) { + fn check_attributes(&mut self, cx: &LateContext<'_>, attrs: &[rustc_attr_ir::Attribute]) { if let Some(features) = find_attr!(attrs, Feature(features, _) => features) { for feature in features { cx.emit_span_lint(UNSTABLE_FEATURES, feature.span, BuiltinUnstableFeatures); diff --git a/compiler/rustc_lint/src/c_void_returns.rs b/compiler/rustc_lint/src/c_void_returns.rs index 1358dcea262e8..da2c52d019923 100644 --- a/compiler/rustc_lint/src/c_void_returns.rs +++ b/compiler/rustc_lint/src/c_void_returns.rs @@ -1,6 +1,6 @@ use rustc_abi::ExternAbi; +use rustc_attr_ir::lang_items::LangItem; use rustc_hir as hir; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::def::Res; use rustc_hir::def_id::LocalDefId; use rustc_hir::intravisit::FnKind; diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index 68b2e2a3b6e7b..a7ded8a82b5dc 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -842,7 +842,10 @@ impl<'tcx> LateContext<'tcx> { /// be used for pretty-printing HIR by rustc_hir_pretty. pub fn precedence(&self, expr: &hir::Expr<'_>) -> ExprPrecedence { let has_attr = |id: hir::HirId| -> bool { - self.tcx.hir_attrs(id).iter().any(hir::Attribute::is_prefix_attr_for_suggestions) + self.tcx + .hir_attrs(id) + .iter() + .any(rustc_attr_ir::Attribute::is_prefix_attr_for_suggestions) }; expr.precedence(&has_attr) } diff --git a/compiler/rustc_lint/src/dangling.rs b/compiler/rustc_lint/src/dangling.rs index c272dd4496984..d06292d62730f 100644 --- a/compiler/rustc_lint/src/dangling.rs +++ b/compiler/rustc_lint/src/dangling.rs @@ -1,9 +1,10 @@ use rustc_ast::visit::{visit_opt, walk_list}; -use rustc_hir::attrs::lang_items::LangItem; +use rustc_attr_ir::find_attr; +use rustc_attr_ir::lang_items::LangItem; use rustc_hir::def::Res; use rustc_hir::def_id::LocalDefId; use rustc_hir::intravisit::{FnKind, Visitor, walk_expr}; -use rustc_hir::{Block, Body, Expr, ExprKind, FnDecl, FnRetTy, TyKind, find_attr}; +use rustc_hir::{Block, Body, Expr, ExprKind, FnDecl, FnRetTy, TyKind}; use rustc_lint_defs::{declare_lint, impl_lint_pass}; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_span::{Span, sym}; diff --git a/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs b/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs index 165c8f58a09f9..506ab027d8771 100644 --- a/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs +++ b/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs @@ -1,5 +1,5 @@ +use rustc_attr_ir::lang_items::LangItem; use rustc_hir as hir; -use rustc_hir::attrs::lang_items::LangItem; use rustc_lint_defs::{declare_lint, declare_lint_pass}; use rustc_middle::ty; use rustc_span::{Ident, sym}; diff --git a/compiler/rustc_lint/src/disallowed_pass_by_ref.rs b/compiler/rustc_lint/src/disallowed_pass_by_ref.rs index 92350ecf60a21..5ecc4d4b07548 100644 --- a/compiler/rustc_lint/src/disallowed_pass_by_ref.rs +++ b/compiler/rustc_lint/src/disallowed_pass_by_ref.rs @@ -1,5 +1,6 @@ +use rustc_attr_ir::find_attr; use rustc_hir::def::Res; -use rustc_hir::{self as hir, AmbigArg, GenericArg, PathSegment, QPath, TyKind, find_attr}; +use rustc_hir::{self as hir, AmbigArg, GenericArg, PathSegment, QPath, TyKind}; use rustc_lint_defs::{declare_lint_pass, declare_tool_lint}; use rustc_middle::ty; diff --git a/compiler/rustc_lint/src/for_loops_over_fallibles.rs b/compiler/rustc_lint/src/for_loops_over_fallibles.rs index df0455470feb7..bb0f2a2793ab8 100644 --- a/compiler/rustc_lint/src/for_loops_over_fallibles.rs +++ b/compiler/rustc_lint/src/for_loops_over_fallibles.rs @@ -1,6 +1,6 @@ use hir::{Expr, Pat}; +use rustc_attr_ir::lang_items::LangItem; use rustc_hir as hir; -use rustc_hir::attrs::lang_items::LangItem; use rustc_infer::infer::TyCtxtInferExt; use rustc_infer::traits::ObligationCause; use rustc_lint_defs::{declare_lint, declare_lint_pass}; diff --git a/compiler/rustc_lint/src/foreign_modules.rs b/compiler/rustc_lint/src/foreign_modules.rs index 7dae504804752..e6092a1497a0f 100644 --- a/compiler/rustc_lint/src/foreign_modules.rs +++ b/compiler/rustc_lint/src/foreign_modules.rs @@ -1,8 +1,8 @@ use rustc_abi::FIRST_VARIANT; +use rustc_attr_ir::find_attr; use rustc_data_structures::unord::{UnordMap, UnordSet}; use rustc_hir as hir; use rustc_hir::def::DefKind; -use rustc_hir::find_attr; use rustc_lint_defs::declare_lint; use rustc_middle::query::Providers; use rustc_middle::ty::{self, AdtDef, Instance, Ty, TyCtxt}; diff --git a/compiler/rustc_lint/src/gpukernel_abi.rs b/compiler/rustc_lint/src/gpukernel_abi.rs index 64f0744dffed4..05f41cd6fdf48 100644 --- a/compiler/rustc_lint/src/gpukernel_abi.rs +++ b/compiler/rustc_lint/src/gpukernel_abi.rs @@ -1,7 +1,8 @@ use std::iter; use rustc_abi::ExternAbi; -use rustc_hir::{self as hir, find_attr}; +use rustc_attr_ir::find_attr; +use rustc_hir as hir; use rustc_lint_defs::{declare_lint, declare_lint_pass}; use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable}; use rustc_span::Span; diff --git a/compiler/rustc_lint/src/interior_mutable_consts.rs b/compiler/rustc_lint/src/interior_mutable_consts.rs index ff48749a2e6a9..4d0557d5e9b54 100644 --- a/compiler/rustc_lint/src/interior_mutable_consts.rs +++ b/compiler/rustc_lint/src/interior_mutable_consts.rs @@ -1,5 +1,6 @@ +use rustc_attr_ir::find_attr; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::{Expr, ExprKind, ItemKind, Node, find_attr}; +use rustc_hir::{Expr, ExprKind, ItemKind, Node}; use rustc_lint_defs::{declare_lint, declare_lint_pass}; use rustc_middle::ty::adjustment::Adjust; diff --git a/compiler/rustc_lint/src/internal.rs b/compiler/rustc_lint/src/internal.rs index 9746b52dda41e..2646131bb59cd 100644 --- a/compiler/rustc_lint/src/internal.rs +++ b/compiler/rustc_lint/src/internal.rs @@ -3,10 +3,11 @@ use rustc_ast as ast; use rustc_ast::{Pat, PatKind, Path}; +use rustc_attr_ir::find_attr; use rustc_hir as hir; use rustc_hir::def::Res; use rustc_hir::def_id::DefId; -use rustc_hir::{Expr, ExprKind, HirId, find_attr}; +use rustc_hir::{Expr, ExprKind, HirId}; use rustc_lint_defs::{declare_lint_pass, declare_tool_lint}; use rustc_middle::ty::{self, ClausePolarity, GenericArgsRef}; use rustc_span::hygiene::{ExpnKind, MacroKind}; diff --git a/compiler/rustc_lint/src/multiple_supertrait_upcastable.rs b/compiler/rustc_lint/src/multiple_supertrait_upcastable.rs index ae07295db512f..75552ab759fd5 100644 --- a/compiler/rustc_lint/src/multiple_supertrait_upcastable.rs +++ b/compiler/rustc_lint/src/multiple_supertrait_upcastable.rs @@ -1,5 +1,5 @@ +use rustc_attr_ir::lang_items::LangItem; use rustc_hir as hir; -use rustc_hir::attrs::lang_items::LangItem; use rustc_lint_defs::{declare_lint, declare_lint_pass}; use rustc_middle::ty::Unnormalized; diff --git a/compiler/rustc_lint/src/non_fmt_panic.rs b/compiler/rustc_lint/src/non_fmt_panic.rs index cb811421be5c6..fbe8eb837f852 100644 --- a/compiler/rustc_lint/src/non_fmt_panic.rs +++ b/compiler/rustc_lint/src/non_fmt_panic.rs @@ -1,7 +1,7 @@ use rustc_ast as ast; +use rustc_attr_ir::lang_items::LangItem; use rustc_errors::{Applicability, Diag, DiagCtxtHandle, Diagnostic, Level, msg}; use rustc_hir as hir; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::def_id::DefId; use rustc_infer::infer::TyCtxtInferExt; use rustc_lint_defs::{declare_lint, declare_lint_pass, fcw}; diff --git a/compiler/rustc_lint/src/non_local_def.rs b/compiler/rustc_lint/src/non_local_def.rs index 01ddc172f274d..e4f082d49cba7 100644 --- a/compiler/rustc_lint/src/non_local_def.rs +++ b/compiler/rustc_lint/src/non_local_def.rs @@ -1,7 +1,8 @@ +use rustc_attr_ir::find_attr; use rustc_errors::{MultiSpan, msg}; use rustc_hir::def::{DefKind, Res}; use rustc_hir::intravisit::{self, Visitor}; -use rustc_hir::{Body, HirId, Item, ItemKind, Node, Path, TyKind, find_attr}; +use rustc_hir::{Body, HirId, Item, ItemKind, Node, Path, TyKind}; use rustc_lint_defs::{declare_lint, impl_lint_pass}; use rustc_middle::ty::TyCtxt; use rustc_span::def_id::{DefId, LOCAL_CRATE}; diff --git a/compiler/rustc_lint/src/nonstandard_style.rs b/compiler/rustc_lint/src/nonstandard_style.rs index b7bb7865ea080..551843947b758 100644 --- a/compiler/rustc_lint/src/nonstandard_style.rs +++ b/compiler/rustc_lint/src/nonstandard_style.rs @@ -1,13 +1,13 @@ use rustc_abi::ExternAbi; use rustc_ast as ast; +use rustc_attr_ir::{AttributeKind, ReprAttr, find_attr}; use rustc_attr_parsing::AttributeParser; use rustc_errors::{Applicability, Diag, DiagCtxtHandle, Diagnostic, Level}; use rustc_hir as hir; -use rustc_hir::attrs::{AttributeKind, ReprAttr}; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::DefId; use rustc_hir::intravisit::{FnKind, Visitor}; -use rustc_hir::{Attribute, GenericParamKind, PatExprKind, PatKind, find_attr}; +use rustc_hir::{Attribute, GenericParamKind, PatExprKind, PatKind}; use rustc_lint_defs::{declare_lint, declare_lint_pass}; use rustc_middle::hir::nested_filter::All; use rustc_middle::ty::AssocContainer; diff --git a/compiler/rustc_lint/src/passes.rs b/compiler/rustc_lint/src/passes.rs index 6b7955db483f1..98ab44c37e26a 100644 --- a/compiler/rustc_lint/src/passes.rs +++ b/compiler/rustc_lint/src/passes.rs @@ -40,9 +40,9 @@ macro_rules! late_lint_methods { fn check_field_def(a: &'tcx rustc_hir::FieldDef<'tcx>); fn check_variant(a: &'tcx rustc_hir::Variant<'tcx>); fn check_path(a: &rustc_hir::Path<'tcx>, b: rustc_hir::HirId); - fn check_attribute(a: &'tcx rustc_hir::Attribute); - fn check_attributes(a: &'tcx [rustc_hir::Attribute]); - fn check_attributes_post(a: &'tcx [rustc_hir::Attribute]); + fn check_attribute(a: &'tcx rustc_attr_ir::Attribute); + fn check_attributes(a: &'tcx [rustc_attr_ir::Attribute]); + fn check_attributes_post(a: &'tcx [rustc_attr_ir::Attribute]); ]); ) } diff --git a/compiler/rustc_lint/src/ptr_nulls.rs b/compiler/rustc_lint/src/ptr_nulls.rs index 19c1a8a1b665c..0c4dba0893fc4 100644 --- a/compiler/rustc_lint/src/ptr_nulls.rs +++ b/compiler/rustc_lint/src/ptr_nulls.rs @@ -1,5 +1,6 @@ use rustc_ast::LitKind; -use rustc_hir::{BinOpKind, Expr, ExprKind, TyKind, find_attr}; +use rustc_attr_ir::find_attr; +use rustc_hir::{BinOpKind, Expr, ExprKind, TyKind}; use rustc_lint_defs::{declare_lint, declare_lint_pass}; use rustc_middle::ty::RawPtr; use rustc_span::{Span, sym}; diff --git a/compiler/rustc_lint/src/runtime_symbols.rs b/compiler/rustc_lint/src/runtime_symbols.rs index df52150799522..f0e186c34ca0f 100644 --- a/compiler/rustc_lint/src/runtime_symbols.rs +++ b/compiler/rustc_lint/src/runtime_symbols.rs @@ -1,4 +1,4 @@ -use rustc_hir::attrs::CanonicalSymbol; +use rustc_attr_ir::CanonicalSymbol; use rustc_hir::def_id::LocalDefId; use rustc_hir::{self as hir, FnSig, ForeignItemKind}; use rustc_infer::infer::DefineOpaqueTypes; diff --git a/compiler/rustc_lint/src/shadowed_into_iter.rs b/compiler/rustc_lint/src/shadowed_into_iter.rs index 0468142a987ca..021499f6b712c 100644 --- a/compiler/rustc_lint/src/shadowed_into_iter.rs +++ b/compiler/rustc_lint/src/shadowed_into_iter.rs @@ -1,5 +1,5 @@ +use rustc_attr_ir::lang_items::LangItem; use rustc_hir as hir; -use rustc_hir::attrs::lang_items::LangItem; use rustc_lint_defs::{declare_lint, fcw, impl_lint_pass}; use rustc_middle::ty::{self, Ty}; diff --git a/compiler/rustc_lint/src/traits.rs b/compiler/rustc_lint/src/traits.rs index 2d6d83d4e0776..1e2c012ee337a 100644 --- a/compiler/rustc_lint/src/traits.rs +++ b/compiler/rustc_lint/src/traits.rs @@ -1,4 +1,4 @@ -use rustc_hir::attrs::lang_items::LangItem; +use rustc_attr_ir::lang_items::LangItem; use rustc_hir::{self as hir, AmbigArg}; use rustc_lint_defs::{declare_lint, declare_lint_pass}; use rustc_span::sym; diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index d62fca02cf4cf..eab950f4d66a8 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -2,9 +2,10 @@ use std::iter; use rustc_abi::{BackendRepr, TagEncoding, Variants, WrappingRange}; use rustc_ast as ast; +use rustc_attr_ir::find_attr; +use rustc_attr_ir::lang_items::LangItem; use rustc_hir as hir; -use rustc_hir::attrs::lang_items::LangItem; -use rustc_hir::{Expr, ExprKind, HirId, find_attr}; +use rustc_hir::{Expr, ExprKind, HirId}; use rustc_lint_defs::{declare_lint, declare_lint_pass, impl_lint_pass}; use rustc_middle::ty::consts::ConstExt; use rustc_middle::ty::layout::{LayoutOf, SizeSkeleton}; diff --git a/compiler/rustc_lint/src/unused/must_use.rs b/compiler/rustc_lint/src/unused/must_use.rs index a637e8cf3b0f4..dab842a688ae1 100644 --- a/compiler/rustc_lint/src/unused/must_use.rs +++ b/compiler/rustc_lint/src/unused/must_use.rs @@ -1,10 +1,11 @@ use std::iter; +use rustc_attr_ir::find_attr; +use rustc_attr_ir::lang_items::LangItem; use rustc_errors::pluralize; -use rustc_hir::attrs::lang_items::LangItem; +use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::DefId; -use rustc_hir::{self as hir, find_attr}; use rustc_infer::traits::util::elaborate; use rustc_lint_defs::{declare_lint, declare_lint_pass}; use rustc_middle::ty::consts::ConstExt; diff --git a/compiler/rustc_metadata/Cargo.toml b/compiler/rustc_metadata/Cargo.toml index a2ef8454ed6a6..e036c2d7e23c9 100644 --- a/compiler/rustc_metadata/Cargo.toml +++ b/compiler/rustc_metadata/Cargo.toml @@ -10,6 +10,7 @@ libloading = "0.9.0" odht = { version = "0.3.1", features = ["nightly"] } rustc_abi = { path = "../rustc_abi" } rustc_ast = { path = "../rustc_ast" } +rustc_attr_ir = { path = "../rustc_attr_ir" } rustc_attr_parsing = { path = "../rustc_attr_parsing" } rustc_crate_store = { path = "../rustc_crate_store" } rustc_data_structures = { path = "../rustc_data_structures" } diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index c828ba13b8af6..ad8264078348b 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -14,7 +14,6 @@ use rustc_data_structures::svh::Svh; use rustc_data_structures::sync::{self, FreezeReadGuard, FreezeWriteGuard}; use rustc_data_structures::unord::UnordMap; use rustc_expand::base::SyntaxExtension; -use rustc_hir as hir; use rustc_hir::def_id::{CrateNum, LOCAL_CRATE, LocalDefId, StableCrateId}; use rustc_hir::definitions::Definitions; use rustc_index::IndexVec; @@ -89,7 +88,7 @@ pub enum LoadedMacro { MacroDef { def: MacroDef, ident: Ident, - attrs: Vec, + attrs: Vec, span: Span, edition: Edition, }, diff --git a/compiler/rustc_metadata/src/eii.rs b/compiler/rustc_metadata/src/eii.rs index 47e982a315395..d7942e2085522 100644 --- a/compiler/rustc_metadata/src/eii.rs +++ b/compiler/rustc_metadata/src/eii.rs @@ -1,7 +1,6 @@ +use rustc_attr_ir::{EiiDecl, EiiImpl, EiiImplResolution, find_attr}; use rustc_data_structures::fx::FxIndexMap; -use rustc_hir::attrs::{EiiDecl, EiiImpl, EiiImplResolution}; use rustc_hir::def_id::DefId; -use rustc_hir::find_attr; use rustc_middle::query::LocalCrate; use rustc_middle::ty::TyCtxt; use rustc_span::bug; diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs index 1c7d865e41234..6cb6ad0015f92 100644 --- a/compiler/rustc_metadata/src/native_libs.rs +++ b/compiler/rustc_metadata/src/native_libs.rs @@ -1,12 +1,11 @@ use rustc_abi::ExternAbi; +use rustc_attr_ir::{PeImportNameType, find_attr}; use rustc_attr_parsing::eval_config_entry; use rustc_crate_store::{ DllCallingConvention, DllImport, DllImportSymbolType, ForeignModule, NativeLib, }; use rustc_data_structures::fx::FxHashSet; -use rustc_hir::attrs::PeImportNameType; use rustc_hir::def::DefKind; -use rustc_hir::find_attr; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::query::LocalCrate; use rustc_middle::ty::{self, List, Ty, TyCtxt}; diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index a73e94dd076e7..2f41ca1a77511 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -7,6 +7,8 @@ use std::{io, mem}; pub(super) use cstore_impl::provide; use rustc_ast as ast; +use rustc_attr_ir::CanonicalSymbols; +use rustc_attr_ir::diagnostic_items::DiagnosticItems; use rustc_crate_store::{CrateSource, ExternCrate}; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::FxIndexMap; @@ -16,8 +18,6 @@ use rustc_data_structures::unhash::UnhashMap; use rustc_expand::base::{SyntaxExtension, SyntaxExtensionKind}; use rustc_expand::proc_macro::{AttrProcMacro, BangProcMacro, DeriveProcMacro}; use rustc_hir::Safety; -use rustc_hir::attrs::CanonicalSymbols; -use rustc_hir::attrs::diagnostic_items::DiagnosticItems; use rustc_hir::def::Res; use rustc_hir::def_id::{CRATE_DEF_INDEX, LOCAL_CRATE}; use rustc_hir::definitions::{DefPath, DefPathData}; @@ -1424,7 +1424,7 @@ impl CrateMetadata { &self, tcx: TyCtxt<'_>, id: DefIndex, - ) -> impl Iterator { + ) -> impl Iterator { self.root .tables .attributes diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index f1a4ed09b3516..79bfb15eefac1 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -2,9 +2,9 @@ use std::any::Any; use std::mem; use std::sync::Arc; +use rustc_attr_ir::Deprecation; use rustc_crate_store::{CrateStore, ExternCrate}; use rustc_data_structures::fx::FxHashMap; -use rustc_hir::attrs::Deprecation; use rustc_hir::def::{CtorKind, DefKind}; use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LOCAL_CRATE}; use rustc_hir::definitions::{DefKey, DefPath, DefPathHash}; diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 8481db9d3c523..1031af39f272b 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -7,16 +7,15 @@ use std::path::{Path, PathBuf}; use std::rc::Rc; use std::sync::Arc; +use rustc_attr_ir::{AttributeKind, EncodeCrossCrate, find_attr}; use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; use rustc_data_structures::memmap::{Mmap, MmapMut}; use rustc_data_structures::sync::{par_for_each_in, par_join}; use rustc_data_structures::temp_dir::MaybeTempDir; use rustc_data_structures::thousands::usize_with_underscores; use rustc_hir as hir; -use rustc_hir::attrs::{AttributeKind, EncodeCrossCrate}; use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE, LocalDefId, LocalDefIdSet}; use rustc_hir::definitions::DefPathData; -use rustc_hir::find_attr; use rustc_hir_pretty::id_to_string; use rustc_middle::dep_graph::{WorkProduct, WorkProductId}; use rustc_middle::middle::dependency_format::Linkage; @@ -872,9 +871,9 @@ struct AnalyzeAttrState { /// visibility: this is a piece of data that can be computed once per defid, and not once per /// attribute. Some attributes would only be usable downstream if they are public. #[inline] -fn analyze_attr(attr: &hir::Attribute, state: &mut AnalyzeAttrState) -> bool { +fn analyze_attr(attr: &rustc_attr_ir::Attribute, state: &mut AnalyzeAttrState) -> bool { let mut should_encode = false; - if let hir::Attribute::Parsed(p) = attr + if let rustc_attr_ir::Attribute::Parsed(p) = attr && p.encode_cross_crate() == EncodeCrossCrate::No { // Attributes not marked encode-cross-crate don't need to be encoded for downstream crates. @@ -883,14 +882,14 @@ fn analyze_attr(attr: &hir::Attribute, state: &mut AnalyzeAttrState) -> bool { { // Lint attributes don't need to be encoded for downstream crates. // FIXME remove this when #152369 is re-merged - } else if let hir::Attribute::Parsed(AttributeKind::DocComment { .. }) = attr { + } else if let rustc_attr_ir::Attribute::Parsed(AttributeKind::DocComment { .. }) = attr { // We keep all doc comments reachable to rustdoc because they might be "imported" into // downstream crates if they use `#[doc(inline)]` to copy an item's documentation into // their own. if state.is_exported { should_encode = true; } - } else if let hir::Attribute::Parsed(AttributeKind::Doc(d)) = attr { + } else if let rustc_attr_ir::Attribute::Parsed(AttributeKind::Doc(d)) = attr { should_encode = true; if d.hidden.is_some() { state.is_doc_hidden = true; diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index f89be5368da9a..99429647bd26c 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -9,16 +9,16 @@ pub use encoder::{EncodedMetadata, encode_metadata, rendered_const}; pub(crate) use parameterized::ParameterizedOverTcx; use rustc_abi::{FieldIdx, ReprOptions, VariantIdx}; use rustc_ast as ast; +use rustc_attr_ir::lang_items::LangItem; +use rustc_attr_ir::{Stability, StrippedCfgItem}; use rustc_crate_store::{CrateDepKind, ForeignModule, LinkagePreference, NativeLib}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::svh::Svh; use rustc_hir as hir; -use rustc_hir::attrs::StrippedCfgItem; -use rustc_hir::attrs::lang_items::LangItem; +use rustc_hir::PreciseCapturingArgKind; use rustc_hir::def::{CtorKind, DefKind, MacroKinds}; use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, DefIndex, DefPathHash, StableCrateId}; use rustc_hir::definitions::DefKey; -use rustc_hir::{PreciseCapturingArgKind, attrs}; use rustc_index::IndexVec; use rustc_index::bit_set::DenseBitSet; use rustc_macros::{ @@ -192,7 +192,7 @@ type ExpnHashTable = LazyTable>>; #[derive(MetadataEncodable, LazyDecodable)] pub(crate) struct ProcMacroData { proc_macro_decls_static: DefIndex, - stability: Option, + stability: Option, macros: LazyArray<(DefIndex, LazyValue)>, } @@ -417,7 +417,7 @@ define_tables! { impl_is_fully_generic_for_reflection: Table, - optional: - attributes: Table>, + attributes: Table>, // For non-reexported names in a module every name is associated with a separate `DefId`, // so we can take their names, visibilities etc from other encoded tables. module_children_non_reexports: Table>, @@ -426,10 +426,10 @@ define_tables! { visibility: Table>>, def_span: Table>, def_ident_span: Table>, - lookup_stability: Table>, - lookup_const_stability: Table>, - lookup_default_body_stability: Table>, - lookup_deprecation_entry: Table>, + lookup_stability: Table>, + lookup_const_stability: Table>, + lookup_default_body_stability: Table>, + lookup_deprecation_entry: Table>, explicit_clauses_of: Table>>, generics_of: Table>, type_of: Table>>>, diff --git a/compiler/rustc_metadata/src/rmeta/parameterized.rs b/compiler/rustc_metadata/src/rmeta/parameterized.rs index 4eb922446b71b..a6a937a56ed50 100644 --- a/compiler/rustc_metadata/src/rmeta/parameterized.rs +++ b/compiler/rustc_metadata/src/rmeta/parameterized.rs @@ -85,24 +85,24 @@ trivially_parameterized_over_tcx! { crate::rmeta::VariantData, rustc_abi::ReprOptions, rustc_ast::DelimArgs, + rustc_attr_ir::Attribute, + rustc_attr_ir::ConstStability, + rustc_attr_ir::DefaultBodyStability, + rustc_attr_ir::Deprecation, + rustc_attr_ir::EiiDecl, + rustc_attr_ir::EiiImpl, + rustc_attr_ir::Stability, + rustc_attr_ir::StrippedCfgItem, + rustc_attr_ir::lang_items::LangItem, rustc_crate_store::ForeignModule, rustc_crate_store::LinkagePreference, rustc_crate_store::NativeLib, - rustc_hir::Attribute, - rustc_hir::ConstStability, rustc_hir::Constness, rustc_hir::CoroutineKind, - rustc_hir::DefaultBodyStability, rustc_hir::Defaultness, rustc_hir::OpaqueTyOrigin, rustc_hir::PreciseCapturingArgKind, rustc_hir::Safety, - rustc_hir::Stability, - rustc_hir::attrs::Deprecation, - rustc_hir::attrs::EiiDecl, - rustc_hir::attrs::EiiImpl, - rustc_hir::attrs::StrippedCfgItem, - rustc_hir::attrs::lang_items::LangItem, rustc_hir::def::DefKind, rustc_hir::def_id::DefId, rustc_hir::def_id::DefIndex, diff --git a/compiler/rustc_mir_dataflow/Cargo.toml b/compiler/rustc_mir_dataflow/Cargo.toml index 156caa7030a03..c1ef4d96f385b 100644 --- a/compiler/rustc_mir_dataflow/Cargo.toml +++ b/compiler/rustc_mir_dataflow/Cargo.toml @@ -8,10 +8,10 @@ edition = "2024" polonius-engine = "0.13.0" regex = "1" rustc_abi = { path = "../rustc_abi" } +rustc_attr_ir = { path = "../rustc_attr_ir" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } rustc_graphviz = { path = "../rustc_graphviz" } -rustc_hir = { path = "../rustc_hir" } rustc_index = { path = "../rustc_index" } rustc_macros = { path = "../rustc_macros" } rustc_middle = { path = "../rustc_middle" } diff --git a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs index af185e868fe9c..b1e4bbe98b86b 100644 --- a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs +++ b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs @@ -7,9 +7,8 @@ use std::sync::LazyLock; use std::{io, ops, str}; use regex::Regex; +use rustc_attr_ir::{BorrowckGraphvizFormatKind, RustcMirKind, find_attr}; use rustc_graphviz as dot; -use rustc_hir::attrs::{BorrowckGraphvizFormatKind, RustcMirKind}; -use rustc_hir::find_attr; use rustc_index::bit_set::DenseBitSet; use rustc_middle::mir::{ self, BasicBlock, Body, Location, MirDumper, TerminatorEdges, graphviz_safe_def_name, traversal, diff --git a/compiler/rustc_mir_dataflow/src/rustc_peek.rs b/compiler/rustc_mir_dataflow/src/rustc_peek.rs index 35c601f09acd4..0e14d1f830492 100644 --- a/compiler/rustc_mir_dataflow/src/rustc_peek.rs +++ b/compiler/rustc_mir_dataflow/src/rustc_peek.rs @@ -1,5 +1,4 @@ -use rustc_hir::attrs::RustcMirKind; -use rustc_hir::find_attr; +use rustc_attr_ir::{RustcMirKind, find_attr}; use rustc_middle::mir::{self, Body, Local, Location}; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_span::{Span, sym}; diff --git a/compiler/rustc_monomorphize/Cargo.toml b/compiler/rustc_monomorphize/Cargo.toml index ce5b90e2593a8..b2edfed1f5ce2 100644 --- a/compiler/rustc_monomorphize/Cargo.toml +++ b/compiler/rustc_monomorphize/Cargo.toml @@ -7,6 +7,7 @@ edition = "2024" # tidy-alphabetical-start rustc_abi = { path = "../rustc_abi" } rustc_ast = { path = "../rustc_ast" } +rustc_attr_ir = { path = "../rustc_attr_ir" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } rustc_hir = { path = "../rustc_hir" } diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 3e16760ba3c00..bfe3ba91bb6bc 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -208,12 +208,12 @@ use std::cell::OnceCell; use std::ops::ControlFlow; +use rustc_attr_ir::InlineAttr; +use rustc_attr_ir::lang_items::LangItem; use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::sync::{Lock, par_for_each_in}; use rustc_data_structures::unord::{UnordMap, UnordSet}; use rustc_hir as hir; -use rustc_hir::attrs::InlineAttr; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId}; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; diff --git a/compiler/rustc_monomorphize/src/lib.rs b/compiler/rustc_monomorphize/src/lib.rs index 16a4a04e8eb39..ec52a837e1a51 100644 --- a/compiler/rustc_monomorphize/src/lib.rs +++ b/compiler/rustc_monomorphize/src/lib.rs @@ -4,7 +4,7 @@ #![feature(once_cell_get_mut)] // tidy-alphabetical-end -use rustc_hir::attrs::lang_items::LangItem; +use rustc_attr_ir::lang_items::LangItem; use rustc_middle::query::TyCtxtAt; use rustc_middle::traits; use rustc_middle::ty::adjustment::CustomCoerceUnsized; diff --git a/compiler/rustc_monomorphize/src/partitioning.rs b/compiler/rustc_monomorphize/src/partitioning.rs index 32de7a3d5f7ab..43ce9634cc203 100644 --- a/compiler/rustc_monomorphize/src/partitioning.rs +++ b/compiler/rustc_monomorphize/src/partitioning.rs @@ -98,12 +98,12 @@ use std::fs::{self, File}; use std::io::Write; use std::path::{Path, PathBuf}; +use rustc_attr_ir::lang_items::LangItem; +use rustc_attr_ir::{InlineAttr, Linkage}; use rustc_data_structures::either::Either; use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; use rustc_data_structures::sync::par_join; use rustc_data_structures::unord::{UnordMap, UnordSet}; -use rustc_hir::attrs::lang_items::LangItem; -use rustc_hir::attrs::{InlineAttr, Linkage}; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, DefIdSet, LOCAL_CRATE}; use rustc_hir::definitions::DefPathDataName; diff --git a/compiler/rustc_passes/src/check_export.rs b/compiler/rustc_passes/src/check_export.rs index bd2cf272faa35..15a1084686718 100644 --- a/compiler/rustc_passes/src/check_export.rs +++ b/compiler/rustc_passes/src/check_export.rs @@ -2,11 +2,11 @@ use std::iter; use std::ops::ControlFlow; use rustc_abi::ExternAbi; +use rustc_attr_ir::find_attr; use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; -use rustc_hir::find_attr; use rustc_hir::intravisit::{self, Visitor}; use rustc_middle::hir::nested_filter; use rustc_middle::middle::privacy::{EffectiveVisibility, Level}; diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index 1800d4fc6c25e..bd1bdf7cc0646 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -9,12 +9,13 @@ use std::sync::atomic::Ordering; use hir::def_id::{LocalDefIdMap, LocalDefIdSet}; use rustc_abi::FieldIdx; +use rustc_attr_ir::find_attr; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet}; use rustc_errors::{ErrorGuaranteed, MultiSpan}; use rustc_hir::def::{CtorOf, DefKind, Res}; use rustc_hir::def_id::{DefId, LocalDefId, LocalModId}; use rustc_hir::intravisit::{self, Visitor}; -use rustc_hir::{self as hir, ForeignItemId, ItemId, Node, PatKind, QPath, find_attr}; +use rustc_hir::{self as hir, ForeignItemId, ItemId, Node, PatKind, QPath}; use rustc_lint_defs::builtin::{DEAD_CODE, DEAD_CODE_PUB_IN_BINARY}; use rustc_lint_defs::{self as lint, Lint, StableLintExpectationId}; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; diff --git a/compiler/rustc_passes/src/entry.rs b/compiler/rustc_passes/src/entry.rs index 3b0ee311efc22..8f933bb7a3b6d 100644 --- a/compiler/rustc_passes/src/entry.rs +++ b/compiler/rustc_passes/src/entry.rs @@ -1,7 +1,8 @@ use rustc_ast::entry::EntryPointType; +use rustc_attr_ir::find_attr; use rustc_errors::codes::*; use rustc_hir::def_id::{CRATE_DEF_ID, DefId, LOCAL_CRATE, LocalDefId}; -use rustc_hir::{ItemId, Node, find_attr}; +use rustc_hir::{ItemId, Node}; use rustc_middle::query::Providers; use rustc_middle::ty::TyCtxt; use rustc_session::config::{EntryFnType, sigpipe}; diff --git a/compiler/rustc_passes/src/input_stats.rs b/compiler/rustc_passes/src/input_stats.rs index 961e6e63a81da..f8ee98e28685d 100644 --- a/compiler/rustc_passes/src/input_stats.rs +++ b/compiler/rustc_passes/src/input_stats.rs @@ -547,7 +547,7 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> { hir_visit::walk_assoc_item_constraint(self, constraint) } - fn visit_attribute(&mut self, attr: &'v hir::Attribute) { + fn visit_attribute(&mut self, attr: &'v rustc_attr_ir::Attribute) { self.record("Attribute", None, attr); } diff --git a/compiler/rustc_privacy/Cargo.toml b/compiler/rustc_privacy/Cargo.toml index e5fdcc6e0749e..6cd997cce27c5 100644 --- a/compiler/rustc_privacy/Cargo.toml +++ b/compiler/rustc_privacy/Cargo.toml @@ -6,6 +6,7 @@ edition = "2024" [dependencies] # tidy-alphabetical-start rustc_ast = { path = "../rustc_ast" } +rustc_attr_ir = { path = "../rustc_attr_ir" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } rustc_hir = { path = "../rustc_hir" } diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 97475c8fdccf0..9406f23155399 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -16,6 +16,7 @@ use diagnostics::{ UnnamedItemIsPrivate, }; use rustc_ast::visit::{VisitorResult, try_visit}; +use rustc_attr_ir::find_attr; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::indexmap::IndexSet; use rustc_data_structures::intern::Interned; @@ -23,7 +24,7 @@ use rustc_errors::{MultiSpan, listify}; use rustc_hir::def::{CtorOf, DefKind, Res}; use rustc_hir::def_id::{DefId, LocalDefId, LocalModId}; use rustc_hir::intravisit::{self, InferKind, Visitor}; -use rustc_hir::{self as hir, AmbigArg, ForeignItemId, ItemId, OwnerId, PatKind, find_attr}; +use rustc_hir::{self as hir, AmbigArg, ForeignItemId, ItemId, OwnerId, PatKind}; use rustc_lint_defs::builtin::{ EXPORTED_PRIVATE_DEPENDENCIES, PRIVATE_BOUNDS, PRIVATE_INTERFACES, UNNAMEABLE_TYPES, }; diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 24f9f56c0a3a6..7ddf916bc7b6b 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -13,12 +13,11 @@ use rustc_ast::{ DelegationSource, Fn, ForeignItem, ForeignItemKind, Inline, Item, ItemKind, NodeId, StaticItem, StmtKind, TraitAlias, TyAlias, }; +use rustc_attr_ir::{Attribute, AttributeKind, MacroUseArgs}; use rustc_attr_parsing::AttributeParser; use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::sync::WriteGuard; use rustc_expand::base::{ResolverExpand, SyntaxExtension, SyntaxExtensionKind}; -use rustc_hir::Attribute; -use rustc_hir::attrs::{AttributeKind, MacroUseArgs}; use rustc_hir::def::{self, *}; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_index::bit_set::DenseBitSet; diff --git a/compiler/rustc_resolve/src/diagnostics/impls.rs b/compiler/rustc_resolve/src/diagnostics/impls.rs index 8357372c40839..331c948c66403 100644 --- a/compiler/rustc_resolve/src/diagnostics/impls.rs +++ b/compiler/rustc_resolve/src/diagnostics/impls.rs @@ -9,6 +9,10 @@ use rustc_ast::{ join_path_idents, }; use rustc_ast_pretty::pprust; +use rustc_attr_ir::diagnostic::{CustomDiagnostic, Directive, FormatArgs}; +use rustc_attr_ir::{ + Attribute, AttributeKind, CfgEntry, Stability, StabilityLevel, StrippedCfgItem, find_attr, +}; use rustc_attr_parsing::AttributeParser; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::unord::{UnordMap, UnordSet}; @@ -18,12 +22,10 @@ use rustc_errors::{ pluralize, struct_span_code_err, }; use rustc_feature::BUILTIN_ATTRIBUTES; -use rustc_hir::attrs::diagnostic::{CustomDiagnostic, Directive, FormatArgs}; -use rustc_hir::attrs::{AttributeKind, CfgEntry, StrippedCfgItem}; +use rustc_hir::PrimTy; use rustc_hir::def::Namespace::{self, *}; use rustc_hir::def::{CtorKind, CtorOf, DefKind, MacroKinds, NonMacroAttrKind, PerNS}; use rustc_hir::def_id::{CRATE_DEF_ID, DefId}; -use rustc_hir::{Attribute, PrimTy, Stability, StabilityLevel, find_attr}; use rustc_lint_defs::builtin::{ ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE, AMBIGUOUS_GLOB_IMPORTS, AMBIGUOUS_IMPORT_VISIBILITIES, AMBIGUOUS_PANIC_IMPORTS, MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS, diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index d7a527f365c02..3dbb1b7fff662 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -11,6 +11,8 @@ use rustc_ast::{ PathSegment, Ty, TyKind, }; use rustc_ast_pretty::pprust::{path_to_string, where_bound_predicate_to_string}; +use rustc_attr_ir::diagnostic::{CustomDiagnostic, FormatArgs}; +use rustc_attr_ir::find_attr; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet}; use rustc_data_structures::unord::UnordItems; use rustc_errors::codes::*; @@ -18,12 +20,10 @@ use rustc_errors::{ Applicability, Diag, Diagnostic, ErrorGuaranteed, MultiSpan, SuggestionStyle, pluralize, struct_span_code_err, }; -use rustc_hir as hir; -use rustc_hir::attrs::diagnostic::{CustomDiagnostic, FormatArgs}; use rustc_hir::def::Namespace::{self, *}; use rustc_hir::def::{CtorKind, CtorOf, DefKind, MacroKinds}; use rustc_hir::def_id::{CRATE_DEF_ID, DefId}; -use rustc_hir::{MissingLifetimeKind, PrimTy, find_attr}; +use rustc_hir::{MissingLifetimeKind, PrimTy}; use rustc_lint_defs::builtin::{SINGLE_USE_LIFETIMES, UNUSED_LIFETIMES}; use rustc_middle::ty; use rustc_session::Session; @@ -1287,7 +1287,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { // confused by them. continue; } - if let Some(d) = hir::find_attr!(r.tcx, did, Doc(d) => d) + if let Some(d) = find_attr!(r.tcx, did, Doc(d) => d) && d.aliases.contains_key(&item_name) { return Some(did); diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index ecbcb0d609a3c..7c80a892fa131 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -43,6 +43,7 @@ use rustc_ast::{ self as ast, AngleBracketedArg, CRATE_NODE_ID, Crate, DUMMY_NODE_ID, Expr, ExprKind, GenericArg, GenericArgs, Generics, NodeId, Path, attr, }; +use rustc_attr_ir::{StrippedCfgItem, find_attr}; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet, default}; use rustc_data_structures::intern::Interned; use rustc_data_structures::steal::Steal; @@ -51,12 +52,11 @@ use rustc_data_structures::unord::{UnordItems, UnordMap, UnordSet}; use rustc_errors::{Applicability, Diag, ErrCode, ErrorGuaranteed, LintBuffer}; use rustc_expand::base::{DeriveResolution, SyntaxExtension, SyntaxExtensionKind}; use rustc_feature::{BUILTIN_ATTRIBUTES, Features}; -use rustc_hir::attrs::StrippedCfgItem; use rustc_hir::def::Namespace::{self, *}; use rustc_hir::def::{self, CtorOf, DefKind, MacroKinds, NonMacroAttrKind, PerNS}; use rustc_hir::def_id::{CRATE_DEF_ID, CrateNum, DefId, LOCAL_CRATE, LocalDefId, LocalDefIdMap}; use rustc_hir::definitions::{PerParentDisambiguatorState, PerParentDisambiguatorsMap}; -use rustc_hir::{PrimTy, TraitCandidate, find_attr}; +use rustc_hir::{PrimTy, TraitCandidate}; use rustc_index::bit_set::DenseBitSet; use rustc_lint_defs::builtin::PRIVATE_MACRO_USE; use rustc_metadata::creader::CStore; diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index 24a52d4143493..3442d946b4f30 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -6,6 +6,7 @@ use std::sync::Arc; use rustc_ast::{self as ast, Crate, DelegationSuffixes, NodeId}; use rustc_ast_pretty::pprust; +use rustc_attr_ir::{Attribute, AttributeKind, CfgEntry, StabilityLevel, StrippedCfgItem}; use rustc_attr_parsing::AttributeParser; use rustc_data_structures::sync::RwLock; use rustc_errors::{Applicability, StashKey}; @@ -17,10 +18,8 @@ use rustc_expand::compile_declarative_macro; use rustc_expand::expand::{ AstFragment, AstFragmentKind, Invocation, InvocationKind, SupportsMacroExpansion, }; -use rustc_hir::attrs::{AttributeKind, CfgEntry, StrippedCfgItem}; use rustc_hir::def::{DefKind, MacroKinds, Namespace, NonMacroAttrKind}; use rustc_hir::def_id::{CrateNum, DefId, LocalDefId}; -use rustc_hir::{Attribute, StabilityLevel}; use rustc_lint_defs::builtin::{ LEGACY_DERIVE_HELPERS, OUT_OF_SCOPE_MACRO_CALLS, UNUSED_MACRO_RULES, UNUSED_MACROS, }; @@ -1213,7 +1212,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { &self, macro_def: &ast::MacroDef, ident: Ident, - attrs: &[rustc_hir::Attribute], + attrs: &[rustc_attr_ir::Attribute], span: Span, node_id: NodeId, edition: Edition, diff --git a/compiler/rustc_trait_selection/Cargo.toml b/compiler/rustc_trait_selection/Cargo.toml index 8eecfda24e557..92ff046af8241 100644 --- a/compiler/rustc_trait_selection/Cargo.toml +++ b/compiler/rustc_trait_selection/Cargo.toml @@ -8,6 +8,7 @@ edition = "2024" itertools = "0.15" rustc_abi = { path = "../rustc_abi" } rustc_ast = { path = "../rustc_ast" } +rustc_attr_ir = { path = "../rustc_attr_ir" } rustc_crate_store = { path = "../rustc_crate_store" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs index f554620c57208..d83df2dfdf291 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs @@ -51,12 +51,13 @@ use std::path::PathBuf; use std::{cmp, fmt, iter}; use rustc_abi::ExternAbi; +use rustc_attr_ir::diagnostic::{CustomDiagnostic, Directive, FormatArgs}; +use rustc_attr_ir::find_attr; use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; use rustc_errors::{Applicability, Diag, DiagStyledString, IntoDiagArg, StringPart, pluralize}; -use rustc_hir::attrs::diagnostic::{CustomDiagnostic, Directive, FormatArgs}; +use rustc_hir as hir; use rustc_hir::def_id::{CRATE_DEF_ID, DefId}; use rustc_hir::intravisit::Visitor; -use rustc_hir::{self as hir, find_attr}; use rustc_infer::infer::DefineOpaqueTypes; use rustc_macros::extension; use rustc_middle::traits::PatternOriginExpr; diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs index de829a5c6ae1a..7b5bd350fe8f9 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs @@ -1,8 +1,9 @@ +use rustc_attr_ir::find_attr; +use rustc_attr_ir::lang_items::LangItem; use rustc_errors::Applicability::{MachineApplicable, MaybeIncorrect}; use rustc_errors::{Diag, MultiSpan, pluralize}; -use rustc_hir::attrs::lang_items::LangItem; +use rustc_hir as hir; use rustc_hir::def::DefKind; -use rustc_hir::{self as hir, find_attr}; use rustc_middle::traits::{ObligationCause, ObligationCauseCode}; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::fast_reject::DeepRejectCtxt; diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs index 261dc5594bd24..05e1cb6210b50 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs @@ -1,8 +1,8 @@ use std::ops::ControlFlow; +use rustc_attr_ir::lang_items::LangItem; use rustc_errors::{Applicability, Diag, E0283, E0284, E0790, MultiSpan, struct_span_code_err}; use rustc_hir as hir; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{CRATE_DEF_ID, DefId}; use rustc_hir::intravisit::Visitor as _; diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/call_kind.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/call_kind.rs index 3b1feeaa1424a..4142febc7844f 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/call_kind.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/call_kind.rs @@ -2,7 +2,7 @@ //! as well as errors when attempting to call a non-const function in a const //! context. -use rustc_hir::attrs::lang_items::{self, LangItem}; +use rustc_attr_ir::lang_items::{self, LangItem}; use rustc_hir::def::DefKind; use rustc_hir::def_id::DefId; use rustc_middle::ty::{ diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index bc5bf38ec9266..4cb5465b5bbee 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -6,6 +6,9 @@ use std::path::PathBuf; use rustc_ast::ast::LitKind; use rustc_ast::{LitIntType, TraitObjectSyntax}; +use rustc_attr_ir::diagnostic::CustomDiagnostic; +use rustc_attr_ir::find_attr; +use rustc_attr_ir::lang_items::LangItem; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::unord::UnordSet; use rustc_errors::codes::*; @@ -13,11 +16,9 @@ use rustc_errors::{ Applicability, Diag, ErrorGuaranteed, MultiSpan, StashKey, StringPart, Sublevel, Suggestions, msg, pluralize, struct_span_code_err, }; -use rustc_hir::attrs::diagnostic::CustomDiagnostic; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId}; use rustc_hir::intravisit::Visitor; -use rustc_hir::{self as hir, Node, expr_needs_parens, find_attr}; +use rustc_hir::{self as hir, Node, expr_needs_parens}; use rustc_infer::infer::{InferOk, TypeTrace}; use rustc_infer::traits::solve::Goal; use rustc_infer::traits::{ImplSource, TraitErrors}; diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs index c120df4e2c3ef..a7a907e8f4d94 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs @@ -7,11 +7,11 @@ pub mod suggestions; use std::{fmt, iter}; +use rustc_attr_ir::lang_items::LangItem; use rustc_crate_store::{ExternCrate, ExternCrateSource}; use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; use rustc_data_structures::unord::UnordSet; use rustc_errors::{Applicability, Diag, E0038, E0276, MultiSpan, struct_span_code_err}; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId}; use rustc_hir::intravisit::Visitor; use rustc_hir::{self as hir, AmbigArg}; diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs index 2967dfb64e710..cc5375cb334c1 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs @@ -1,9 +1,9 @@ use std::path::PathBuf; +use rustc_attr_ir::diagnostic::{CustomDiagnostic, FilterOptions, FormatArgs}; +use rustc_attr_ir::find_attr; use rustc_hir as hir; -use rustc_hir::attrs::diagnostic::{CustomDiagnostic, FilterOptions, FormatArgs}; use rustc_hir::def_id::LocalDefId; -use rustc_hir::find_attr; use rustc_middle::ty::consts::ConstExt; use rustc_middle::ty::print::PrintTraitRefExt; use rustc_middle::ty::{self, GenericParamDef, GenericParamDefKind}; 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 47652c22a7ebc..32237e9f60ca3 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -6,12 +6,12 @@ use std::{debug_assert_matches, iter}; use itertools::{EitherOrBoth, Itertools}; use rustc_abi::ExternAbi; +use rustc_attr_ir::lang_items::{self, LangItem}; use rustc_data_structures::fx::FxHashSet; use rustc_errors::codes::*; use rustc_errors::{ Applicability, Diag, MultiSpan, Style, SuggestionStyle, pluralize, struct_span_code_err, }; -use rustc_hir::attrs::lang_items::{self, LangItem}; use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res}; use rustc_hir::def_id::DefId; use rustc_hir::intravisit::Visitor; diff --git a/compiler/rustc_trait_selection/src/infer.rs b/compiler/rustc_trait_selection/src/infer.rs index 802393a22b7e5..7e1ad3234440e 100644 --- a/compiler/rustc_trait_selection/src/infer.rs +++ b/compiler/rustc_trait_selection/src/infer.rs @@ -1,6 +1,6 @@ use std::fmt::Debug; -use rustc_hir::attrs::lang_items::LangItem; +use rustc_attr_ir::lang_items::LangItem; use rustc_hir::def_id::DefId; pub use rustc_infer::infer::*; use rustc_infer::traits::TraitErrors; diff --git a/compiler/rustc_trait_selection/src/solve/delegate.rs b/compiler/rustc_trait_selection/src/solve/delegate.rs index c67a4bdd329b0..e1043d53fa6fc 100644 --- a/compiler/rustc_trait_selection/src/solve/delegate.rs +++ b/compiler/rustc_trait_selection/src/solve/delegate.rs @@ -3,9 +3,9 @@ use std::fmt::Debug; use std::mem; use std::ops::{ControlFlow, Deref}; +use rustc_attr_ir::lang_items::LangItem; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_hir::CRATE_HIR_ID; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::def::Namespace; use rustc_hir::def_id::{CRATE_DEF_ID, DefId, LOCAL_CRATE}; use rustc_infer::infer::canonical::query_response::make_query_region_constraints; diff --git a/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs b/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs index 7f704d41ab6c5..d30421a762ea9 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs @@ -1,6 +1,6 @@ use std::ops::ControlFlow; -use rustc_hir::attrs::lang_items::LangItem; +use rustc_attr_ir::lang_items::LangItem; use rustc_infer::infer::InferCtxt; use rustc_infer::traits::solve::{CandidateSource, GoalSource, MaybeCause}; use rustc_infer::traits::{ diff --git a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs index e964c09420b0e..59f3ebfcce33e 100644 --- a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs +++ b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs @@ -6,9 +6,9 @@ use std::ops::ControlFlow; +use rustc_attr_ir::lang_items::LangItem; use rustc_errors::FatalError; use rustc_hir as hir; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::def_id::DefId; use rustc_middle::query::Providers; use rustc_middle::ty::{ diff --git a/compiler/rustc_trait_selection/src/traits/effects.rs b/compiler/rustc_trait_selection/src/traits/effects.rs index dda72a45d5764..5892e376126eb 100644 --- a/compiler/rustc_trait_selection/src/traits/effects.rs +++ b/compiler/rustc_trait_selection/src/traits/effects.rs @@ -1,5 +1,5 @@ +use rustc_attr_ir::lang_items::LangItem; use rustc_hir as hir; -use rustc_hir::attrs::lang_items::LangItem; use rustc_infer::infer::{BoundRegionConversionTime, DefineOpaqueTypes}; use rustc_infer::traits::{ ImplDerivedHostCause, ImplSource, Obligation, ObligationCause, ObligationCauseCode, diff --git a/compiler/rustc_trait_selection/src/traits/misc.rs b/compiler/rustc_trait_selection/src/traits/misc.rs index 658248144b529..69fc873c4aae9 100644 --- a/compiler/rustc_trait_selection/src/traits/misc.rs +++ b/compiler/rustc_trait_selection/src/traits/misc.rs @@ -1,8 +1,9 @@ //! Miscellaneous type-system utilities that are too small to deserve their own modules. use rustc_ast::Mutability; +use rustc_attr_ir::find_attr; +use rustc_attr_ir::lang_items::LangItem; use rustc_hir as hir; -use rustc_hir::attrs::lang_items::LangItem; use rustc_infer::infer::{RegionResolutionError, TyCtxtInferExt}; use rustc_infer::traits::TraitErrors; use rustc_middle::ty::{self, AdtDef, Ty, TyCtxt, TypeVisitableExt, TypingMode}; @@ -122,7 +123,7 @@ pub fn type_allowed_to_implement_const_param_ty<'tcx>( if !tcx.features().adt_const_params() { for variant in adt.variants() { if variant.is_field_list_non_exhaustive() { - let attr_span = match hir::find_attr!(tcx, variant.def_id, hir::attrs::AttributeKind::NonExhaustive(span) => *span) + let attr_span = match find_attr!(tcx, variant.def_id, NonExhaustive(span) => *span) { Some(sp) => sp, None => bug!("non_exhaustive variant missing NonExhaustive attribute"), diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index c1f4e74119744..6f7c46089632f 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -2,9 +2,9 @@ use std::ops::ControlFlow; +use rustc_attr_ir::lang_items::LangItem; use rustc_data_structures::sso::SsoHashSet; use rustc_errors::ErrorGuaranteed; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::def_id::DefId; use rustc_infer::infer::DefineOpaqueTypes; use rustc_infer::traits::{ObligationCauseCode, PredicateObligations}; diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index 120f83c14b5c7..9ebfb4d5ecda0 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -9,8 +9,8 @@ use std::ops::ControlFlow; use hir::def_id::DefId; +use rustc_attr_ir::lang_items::LangItem; use rustc_data_structures::fx::{FxHashSet, FxIndexSet}; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::{self as hir, CoroutineDesugaring, CoroutineKind}; use rustc_infer::traits::{Obligation, PolyTraitObligation, PredicateObligation, SelectionError}; use rustc_middle::ty::fast_reject::DeepRejectCtxt; diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index b410070123da7..81517955181ee 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -9,7 +9,7 @@ use std::ops::ControlFlow; -use rustc_hir::attrs::lang_items::LangItem; +use rustc_attr_ir::lang_items::LangItem; use rustc_infer::infer::{BoundRegionConversionTime, DefineOpaqueTypes, InferOk}; use rustc_infer::traits::ObligationCauseCode; use rustc_middle::traits::{BuiltinImplSource, SignatureMismatchData}; diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index f8619fcd120a2..7ee6eec3e1c44 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -8,10 +8,10 @@ use std::fmt::{self, Display}; use std::ops::ControlFlow; use hir::def::DefKind; +use rustc_attr_ir::lang_items::LangItem; use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; use rustc_errors::Diag; use rustc_hir as hir; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::def_id::DefId; use rustc_infer::infer::BoundRegionConversionTime::{self, HigherRankedType}; use rustc_infer::infer::DefineOpaqueTypes; diff --git a/compiler/rustc_trait_selection/src/traits/util.rs b/compiler/rustc_trait_selection/src/traits/util.rs index 5685bd8ef55f8..c60ebc4758ead 100644 --- a/compiler/rustc_trait_selection/src/traits/util.rs +++ b/compiler/rustc_trait_selection/src/traits/util.rs @@ -1,7 +1,7 @@ use std::collections::VecDeque; +use rustc_attr_ir::lang_items::LangItem; use rustc_data_structures::fx::FxHashSet; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::def_id::DefId; use rustc_infer::infer::InferCtxt; use rustc_infer::traits::PolyTraitObligation; diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index 175183ce633ab..ba33270c2adba 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -5,8 +5,8 @@ use std::iter; +use rustc_attr_ir::lang_items::LangItem; use rustc_hir as hir; -use rustc_hir::attrs::lang_items::LangItem; use rustc_infer::traits::{ObligationCauseCode, PredicateObligation, PredicateObligations}; use rustc_middle::ty::{ self, DelayedSet, GenericArgsRef, PredicateProxy, Term, TermKind, Ty, TyCtxt, diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs index bcba5839926db..011c6fde740ac 100644 --- a/compiler/rustc_ty_utils/src/abi.rs +++ b/compiler/rustc_ty_utils/src/abi.rs @@ -2,8 +2,9 @@ use std::{assert_matches, iter}; use rustc_abi::Primitive::Pointer; use rustc_abi::{Align, BackendRepr, ExternAbi, PointerKind, Scalar, Size}; +use rustc_attr_ir::find_attr; use rustc_attr_ir::lang_items::LangItem; -use rustc_hir::{self as hir, find_attr}; +use rustc_hir as hir; use rustc_middle::middle::deduced_param_attrs::DeducedParamAttrs; use rustc_middle::query::Providers; use rustc_middle::ty::layout::{ diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index 43af74d10aba7..ef1241266cac6 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -1,6 +1,5 @@ use std::range::{RangeFrom, RangeToInclusive}; -use hir::def_id::DefId; use rustc_abi as abi; use rustc_abi::Integer::{I8, I32}; use rustc_abi::Primitive::{self, Float, Int, Pointer}; @@ -9,10 +8,10 @@ use rustc_abi::{ LayoutCalculatorError, LayoutData, Niche, ReprOptions, Scalar, Size, StructKind, TagEncoding, VariantIdx, Variants, WrappingRange, }; +use rustc_attr_ir::find_attr; use rustc_attr_ir::lang_items::LangItem; use rustc_hashes::Hash64; -use rustc_hir as hir; -use rustc_hir::find_attr; +use rustc_hir::def_id::DefId; use rustc_index::{Idx as _, IndexVec}; use rustc_middle::query::Providers; use rustc_middle::traits::ObligationCause; diff --git a/compiler/rustc_ty_utils/src/needs_drop.rs b/compiler/rustc_ty_utils/src/needs_drop.rs index 529abd1d41415..094cf5aec0bd1 100644 --- a/compiler/rustc_ty_utils/src/needs_drop.rs +++ b/compiler/rustc_ty_utils/src/needs_drop.rs @@ -1,8 +1,8 @@ //! Check whether a type has (potentially) non-trivial drop glue. +use rustc_attr_ir::find_attr; use rustc_data_structures::fx::FxHashSet; use rustc_hir::def_id::DefId; -use rustc_hir::find_attr; use rustc_middle::query::Providers; use rustc_middle::ty::util::{AlwaysRequiresDrop, needs_drop_components}; use rustc_middle::ty::{self, EarlyBinder, GenericArgsRef, Ty, TyCtxt, Unnormalized}; From 6cc4e7e2788cb8f7c71454efb074e2f114b84898 Mon Sep 17 00:00:00 2001 From: Shun Sakai Date: Wed, 23 Sep 2026 22:52:15 +0900 Subject: [PATCH 20/23] Add `inline` attribute to `NonZero::from_str` --- library/core/src/num/nonzero.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index d0ae6c31267f3..595f3d2248190 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -1449,6 +1449,7 @@ macro_rules! nonzero_integer { /// #[doc = concat!("assert!(NonZero::<", stringify!($Int), ">::from_str(\"1 \").is_err());")] /// ``` + #[inline] fn from_str(src: &str) -> Result { Self::from_str_radix(src, 10) } From 9f208cb493f605226853d6015c2df8d4f6a983af Mon Sep 17 00:00:00 2001 From: David Carlier Date: Fri, 2 Feb 2024 20:55:44 +0000 Subject: [PATCH 21/23] std::thread::available_parallelism merging linux/android/freebsd version FreeBSD 13.1 had introduced a sched cpu affinity compatibility layer with Linux. 13.0 and even 13.1 being EOL, we can simplify here. --- library/std/src/sys/thread/unix.rs | 40 +++++++++--------------------- 1 file changed, 12 insertions(+), 28 deletions(-) diff --git a/library/std/src/sys/thread/unix.rs b/library/std/src/sys/thread/unix.rs index b7908dea2b5de..11fe569f8e0a9 100644 --- a/library/std/src/sys/thread/unix.rs +++ b/library/std/src/sys/thread/unix.rs @@ -162,6 +162,7 @@ pub fn available_parallelism() -> io::Result> { target_os = "hurd", target_os = "linux", target_os = "aix", + target_os = "freebsd", target_vendor = "apple", target_os = "cygwin", target_os = "redox", @@ -174,9 +175,17 @@ pub fn available_parallelism() -> io::Result> { #[cfg(any(target_os = "android", target_os = "linux"))] { quota = cgroups::quota().max(1); - let mut set: libc::cpu_set_t = unsafe { mem::zeroed() }; + } + + #[cfg(any(target_os = "android", target_os = "linux", target_os = "freebsd"))] + { + #[cfg(not(target_os = "freebsd"))] + type Cpuset = libc::cpu_set_t; + #[cfg(target_os = "freebsd")] + type Cpuset = libc::cpuset_t; + let mut set: Cpuset = unsafe { mem::zeroed() }; unsafe { - if libc::sched_getaffinity(0, size_of::(), &mut set) == 0 { + if libc::sched_getaffinity(0, size_of::(), &mut set) == 0 { let count = libc::CPU_COUNT(&set) as usize; let count = count.min(quota); @@ -201,34 +210,9 @@ pub fn available_parallelism() -> io::Result> { } } } - any( - target_os = "freebsd", - target_os = "dragonfly", - target_os = "openbsd", - target_os = "netbsd", - ) => { + any(target_os = "dragonfly", target_os = "openbsd", target_os = "netbsd") => { use crate::ptr; - #[cfg(target_os = "freebsd")] - { - let mut set: libc::cpuset_t = unsafe { mem::zeroed() }; - unsafe { - if libc::cpuset_getaffinity( - libc::CPU_LEVEL_WHICH, - libc::CPU_WHICH_PID, - -1, - size_of::(), - &mut set, - ) == 0 - { - let count = libc::CPU_COUNT(&set) as usize; - if count > 0 { - return Ok(NonZero::new_unchecked(count)); - } - } - } - } - #[cfg(target_os = "netbsd")] { unsafe { From e2160bd1cd7a99e0fc2d33b1c0f5229a5ec80ca1 Mon Sep 17 00:00:00 2001 From: Takayuki Maeda Date: Thu, 24 Sep 2026 00:14:06 +0900 Subject: [PATCH 22/23] convert the malformed function parameter crash test to a UI test --- tests/crashes/160490.rs | 2 - ...r-invalid-function-parameter-pattern-1.rs} | 0 ...valid-function-parameter-pattern-1.stderr} | 6 +-- ...er-invalid-function-parameter-pattern-2.rs | 8 ++++ ...nvalid-function-parameter-pattern-2.stderr | 43 +++++++++++++++++++ 5 files changed, 54 insertions(+), 5 deletions(-) delete mode 100644 tests/crashes/160490.rs rename tests/ui/parser/{recover-invalid-function-parameter-pattern.rs => recover-invalid-function-parameter-pattern-1.rs} (100%) rename tests/ui/parser/{recover-invalid-function-parameter-pattern.stderr => recover-invalid-function-parameter-pattern-1.stderr} (75%) create mode 100644 tests/ui/parser/recover-invalid-function-parameter-pattern-2.rs create mode 100644 tests/ui/parser/recover-invalid-function-parameter-pattern-2.stderr diff --git a/tests/crashes/160490.rs b/tests/crashes/160490.rs deleted file mode 100644 index 5f713ed268042..0000000000000 --- a/tests/crashes/160490.rs +++ /dev/null @@ -1,2 +0,0 @@ -//@ known-bug: #160490 -fn f(...: u8) {} diff --git a/tests/ui/parser/recover-invalid-function-parameter-pattern.rs b/tests/ui/parser/recover-invalid-function-parameter-pattern-1.rs similarity index 100% rename from tests/ui/parser/recover-invalid-function-parameter-pattern.rs rename to tests/ui/parser/recover-invalid-function-parameter-pattern-1.rs diff --git a/tests/ui/parser/recover-invalid-function-parameter-pattern.stderr b/tests/ui/parser/recover-invalid-function-parameter-pattern-1.stderr similarity index 75% rename from tests/ui/parser/recover-invalid-function-parameter-pattern.stderr rename to tests/ui/parser/recover-invalid-function-parameter-pattern-1.stderr index d4b78db29dba9..0bf724d0db8eb 100644 --- a/tests/ui/parser/recover-invalid-function-parameter-pattern.stderr +++ b/tests/ui/parser/recover-invalid-function-parameter-pattern-1.stderr @@ -1,5 +1,5 @@ error: unexpected `...` - --> $DIR/recover-invalid-function-parameter-pattern.rs:3:9 + --> $DIR/recover-invalid-function-parameter-pattern-1.rs:3:9 | LL | fn main(... : ...) | ^^^ not a valid pattern @@ -11,7 +11,7 @@ LL + fn main(.. : ...) | error: unexpected `...` - --> $DIR/recover-invalid-function-parameter-pattern.rs:3:15 + --> $DIR/recover-invalid-function-parameter-pattern-1.rs:3:15 | LL | fn main(... : ...) | ^^^ @@ -19,7 +19,7 @@ LL | fn main(... : ...) = note: only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list error: expected one of `->`, `where`, or `{`, found `` - --> $DIR/recover-invalid-function-parameter-pattern.rs:3:18 + --> $DIR/recover-invalid-function-parameter-pattern-1.rs:3:18 | LL | fn main(... : ...) | ^ expected one of `->`, `where`, or `{` diff --git a/tests/ui/parser/recover-invalid-function-parameter-pattern-2.rs b/tests/ui/parser/recover-invalid-function-parameter-pattern-2.rs new file mode 100644 index 0000000000000..ea0233f433099 --- /dev/null +++ b/tests/ui/parser/recover-invalid-function-parameter-pattern-2.rs @@ -0,0 +1,8 @@ +// Regression test for https://github.com/rust-lang/rust/issues/160490. + +fn f(...: u8) {} +//~^ ERROR unexpected `...` +//~| ERROR missing pattern for `...` argument +//~| WARN this was previously accepted by the compiler + +fn main() {} diff --git a/tests/ui/parser/recover-invalid-function-parameter-pattern-2.stderr b/tests/ui/parser/recover-invalid-function-parameter-pattern-2.stderr new file mode 100644 index 0000000000000..7a9ea16a9d5d5 --- /dev/null +++ b/tests/ui/parser/recover-invalid-function-parameter-pattern-2.stderr @@ -0,0 +1,43 @@ +error: unexpected `...` + --> $DIR/recover-invalid-function-parameter-pattern-2.rs:3:6 + | +LL | fn f(...: u8) {} + | ^^^ not a valid pattern + | +help: for a rest pattern, use `..` instead of `...` + | +LL - fn f(...: u8) {} +LL + fn f(..: u8) {} + | + +error: missing pattern for `...` argument + --> $DIR/recover-invalid-function-parameter-pattern-2.rs:3:6 + | +LL | fn f(...: u8) {} + | ^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #145544 + = note: `#[deny(varargs_without_pattern)]` (part of `#[deny(future_incompatible)]`) on by default +help: name the argument, or use `_` to continue ignoring it + | +LL | fn f(_: ...: u8) {} + | ++ + +error: aborting due to 2 previous errors + +Future incompatibility report: Future breakage diagnostic: +error: missing pattern for `...` argument + --> $DIR/recover-invalid-function-parameter-pattern-2.rs:3:6 + | +LL | fn f(...: u8) {} + | ^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #145544 + = note: `#[deny(varargs_without_pattern)]` (part of `#[deny(future_incompatible)]`) on by default +help: name the argument, or use `_` to continue ignoring it + | +LL | fn f(_: ...: u8) {} + | ++ + From 5e2db49550ee899e9c9227436b3b77863a043abd Mon Sep 17 00:00:00 2001 From: sjwang05 <63834813+sjwang05@users.noreply.github.com> Date: Tue, 22 Sep 2026 14:59:51 -0700 Subject: [PATCH 23/23] revert "don't calculate dtors if the self ty has impossible bounds" This reverts commit 644839ab44dbc1507ebe1bb055d9b01e308e7067, reversing changes made to 73cf3019a83292f82c49dd12c81a9ce39635563e. --- .../src/check/always_applicable.rs | 41 +------------------ compiler/rustc_hir_analysis/src/check/mod.rs | 12 +----- compiler/rustc_middle/src/ty/util.rs | 12 ------ .../150387.rs} | 6 +-- .../153947.rs} | 7 +--- 5 files changed, 5 insertions(+), 73 deletions(-) rename tests/{ui/dropck/overlapping_impossible_drop_min_specialization.rs => crashes/150387.rs} (84%) rename tests/{ui/dropck/overlapping_impossible_drop.rs => crashes/153947.rs} (83%) diff --git a/compiler/rustc_hir_analysis/src/check/always_applicable.rs b/compiler/rustc_hir_analysis/src/check/always_applicable.rs index b098a6c186457..fd46e94fd9cb7 100644 --- a/compiler/rustc_hir_analysis/src/check/always_applicable.rs +++ b/compiler/rustc_hir_analysis/src/check/always_applicable.rs @@ -8,7 +8,7 @@ use rustc_data_structures::fx::FxHashSet; use rustc_errors::codes::*; use rustc_errors::{ErrorGuaranteed, struct_span_code_err}; use rustc_infer::infer::{RegionResolutionError, TyCtxtInferExt}; -use rustc_infer::traits::{Obligation, ObligationCause, ObligationCauseCode}; +use rustc_infer::traits::{ObligationCause, ObligationCauseCode}; use rustc_middle::ty::util::CheckRegions; use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt, TypeVisitableExt, TypingMode}; use rustc_span::{span_bug, sym}; @@ -133,45 +133,6 @@ pub(crate) fn check_negative_auto_trait_impl<'tcx>( } } -/// Checks if the self ty's where-clauses are able to be proven. For instance, if we have multiple -/// overlapping drop impls, and we have `[T]: Sized` on both the impls and the self ty, we shouldn't -/// error or ICE, since neither the ADT nor the impls are nameable in practice. -/// -/// We already emit errors for the case where the impossible bound exists only on the self ty, or -/// only on the impl(s). -pub(crate) fn is_impossible_self_ty(tcx: TyCtxt<'_>, adt_did: LocalDefId) -> bool { - let clauses = tcx.clauses_of(adt_did).clauses; - if clauses.is_empty() { - return false; - } - - // Be conservative in cases where we have `W` and a method like `Self: Sized`, - // since that method *may* have some substitutions where the predicates hold. - // - // This replicates the logic we use in coherence. - let infcx = tcx - .infer_ctxt() - .ignoring_regions() - .with_next_trait_solver(true) - .enable_next_solver_overflow_fcw(false) - .build(TypingMode::Coherence); - let param_env = ty::ParamEnv::empty(); - let args = infcx.fresh_args_for_item(tcx.def_span(adt_did), adt_did.to_def_id()); - - let obligations = clauses.iter().map(|(clause, span)| { - Obligation::new( - tcx, - ObligationCause::dummy_with_span(*span), - param_env, - ty::EarlyBinder::bind(tcx, *clause).instantiate(tcx, args).skip_norm_wip(), - ) - }); - - let ocx = ObligationCtxt::new(&infcx); - ocx.register_obligations(obligations); - ocx.try_evaluate_obligations().has_errors() -} - fn ensure_impl_params_and_item_params_correspond<'tcx>( tcx: TyCtxt<'tcx>, impl_def_id: LocalDefId, diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs index fa2b3e9f25342..9eaaecaa02227 100644 --- a/compiler/rustc_hir_analysis/src/check/mod.rs +++ b/compiler/rustc_hir_analysis/src/check/mod.rs @@ -125,11 +125,7 @@ pub(super) fn provide(providers: &mut Providers) { } fn adt_destructor(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option { - let dtor = tcx.calculate_dtor( - def_id, - always_applicable::check_drop_impl, - always_applicable::is_impossible_self_ty, - ); + let dtor = tcx.calculate_dtor(def_id, always_applicable::check_drop_impl); if dtor.is_none() && tcx.features().async_drop() { if let Some(async_dtor) = adt_async_destructor(tcx, def_id) { // When type has AsyncDrop impl, but doesn't have Drop impl, generate error @@ -141,11 +137,7 @@ fn adt_destructor(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option } fn adt_async_destructor(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option { - let result = tcx.calculate_async_dtor( - def_id, - always_applicable::check_drop_impl, - always_applicable::is_impossible_self_ty, - ); + let result = tcx.calculate_async_dtor(def_id, always_applicable::check_drop_impl); // Async drop in libstd/libcore would become insta-stable — catch that mistake. if result.is_some() && tcx.features().staged_api() { span_bug!(tcx.def_span(def_id), "don't use async drop in libstd, it becomes insta-stable"); diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index db983038e1af9..31b7b719fa9cf 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -377,7 +377,6 @@ impl<'tcx> TyCtxt<'tcx> { self, adt_did: LocalDefId, validate: impl Fn(Self, LocalDefId) -> Result<(), ErrorGuaranteed>, - impossible_self_ty: impl Fn(Self, LocalDefId) -> bool, ) -> Option { let drop_trait = self.lang_items().drop_trait()?; self.ensure_result().coherent_trait(drop_trait).ok()?; @@ -395,11 +394,6 @@ impl<'tcx> TyCtxt<'tcx> { continue; } - if impossible_self_ty(self, adt_did) { - // The self ty is unnameable, so it can't be constructed in the first place. - continue; - } - let Some(&item_id) = self.associated_item_def_ids(impl_did).first() else { self.dcx() .span_delayed_bug(self.def_span(impl_did), "Drop impl without drop function"); @@ -430,7 +424,6 @@ impl<'tcx> TyCtxt<'tcx> { self, adt_did: LocalDefId, validate: impl Fn(Self, LocalDefId) -> Result<(), ErrorGuaranteed>, - impossible_self_ty: impl Fn(Self, LocalDefId) -> bool, ) -> Option { let async_drop_trait = self.lang_items().async_drop_trait()?; self.ensure_result().coherent_trait(async_drop_trait).ok()?; @@ -448,11 +441,6 @@ impl<'tcx> TyCtxt<'tcx> { continue; } - if impossible_self_ty(self, adt_did) { - // The self ty is unnameable, so it can't be constructed in the first place. - continue; - } - if let Some(old_impl_did) = dtor_candidate { self.dcx() .struct_span_err(self.def_span(impl_did), "multiple async drop impls found") diff --git a/tests/ui/dropck/overlapping_impossible_drop_min_specialization.rs b/tests/crashes/150387.rs similarity index 84% rename from tests/ui/dropck/overlapping_impossible_drop_min_specialization.rs rename to tests/crashes/150387.rs index e201c75f4f4b3..b29ce143fb4ea 100644 --- a/tests/ui/dropck/overlapping_impossible_drop_min_specialization.rs +++ b/tests/crashes/150387.rs @@ -1,7 +1,4 @@ -//@ check-pass - -// Regression test for #150387 - +//@ known-bug: #150387 #![feature(min_specialization)] #![allow(dead_code)] @@ -13,5 +10,4 @@ impl Drop for Thing where [T]: Sized { impl Drop for Thing where [T]: Sized { fn drop(&mut self) {} } - fn main() {} diff --git a/tests/ui/dropck/overlapping_impossible_drop.rs b/tests/crashes/153947.rs similarity index 83% rename from tests/ui/dropck/overlapping_impossible_drop.rs rename to tests/crashes/153947.rs index 6200572b9b72e..39bc8c074cfc0 100644 --- a/tests/ui/dropck/overlapping_impossible_drop.rs +++ b/tests/crashes/153947.rs @@ -1,9 +1,5 @@ -//@ check-pass - -// Regression test for #153947 - +//@ known-bug: #153947 #![expect(drop_bounds)] - pub struct Thing(T) where [T]: Sized, Self: Drop; impl Drop for Thing where [T]: Sized, Self: Drop { fn drop(&mut self) {} @@ -11,5 +7,4 @@ impl Drop for Thing where [T]: Sized, Self: Drop { impl Drop for Thing where [T]: Sized, Self: Drop { fn drop(&mut self) {} } - fn main() {}