From f1fd6a2b0b8b3eeee1754fab11b1aeceab639f39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Wed, 11 Jun 2025 13:25:21 +0200 Subject: [PATCH] GCI: Imply outlives-bounds on free (generic) const items --- .../rustc_hir_analysis/src/collect/type_of.rs | 6 +- .../src/outlives/implicit_infer.rs | 28 +++-- .../rustc_hir_analysis/src/outlives/mod.rs | 34 +++--- .../src/traits/implied-bounds.md | 8 +- .../return-via-stack.stderr | 36 +++--- ...uct-or-union-add-generic-impl-trait.stderr | 22 ++-- .../assoc-const-missing-type.rs | 20 ---- .../assoc-const-missing-type.stderr | 36 ------ .../implied-outlives-bounds-0.neg.stderr | 18 +++ .../implied-outlives-bounds-0.rs | 28 +++++ .../implied-outlives-bounds-1.rs | 26 +++++ .../missing-or-inferred-type.rs | 39 +++++++ .../missing-or-inferred-type.stderr | 53 +++++++++ .../reference-outlives-referent.rs | 13 ++- .../reference-outlives-referent.stderr | 47 ++++++-- tests/ui/suggestions/issue-61963.stderr | 20 ++-- .../typeck_type_placeholder_item.stderr | 108 +++++++++--------- 17 files changed, 349 insertions(+), 193 deletions(-) delete mode 100644 tests/ui/generic-const-items/assoc-const-missing-type.rs delete mode 100644 tests/ui/generic-const-items/assoc-const-missing-type.stderr create mode 100644 tests/ui/generic-const-items/implied-outlives-bounds-0.neg.stderr create mode 100644 tests/ui/generic-const-items/implied-outlives-bounds-0.rs create mode 100644 tests/ui/generic-const-items/implied-outlives-bounds-1.rs create mode 100644 tests/ui/generic-const-items/missing-or-inferred-type.rs create mode 100644 tests/ui/generic-const-items/missing-or-inferred-type.stderr diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index 23df419d06a70..e4cf5741f970f 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -137,8 +137,10 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_ } } } - ItemKind::Const(ident, _, ty, rhs) => { - if ty.is_suggestable_infer_ty() { + ItemKind::Const(ident, generics, ty, rhs) => { + // We can't infer the type of parameterized const items without causing a query + // cycle (typeck -..> inferred_outlives_of -..> type_of -> typeck), so let's not. + if generics.params.is_empty() && ty.is_suggestable_infer_ty() { infer_placeholder_type( icx.lowerer(), def_id, diff --git a/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs b/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs index 4f35b87be3016..3b527af8f5338 100644 --- a/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs +++ b/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs @@ -8,18 +8,13 @@ use tracing::debug; use super::explicit::ExplicitPredicatesMap; use super::utils::*; -/// Infer predicates for the items in the crate. -/// -/// `global_inferred_outlives`: this is initially the empty map that -/// was generated by walking the items in the crate. This will -/// now be filled with inferred predicates. +/// Infer outlives-predicates for the items in the local crate. pub(super) fn infer_predicates( tcx: TyCtxt<'_>, ) -> FxIndexMap>> { debug!("infer_predicates"); let mut explicit_map = ExplicitPredicatesMap::new(); - let mut global_inferred_outlives = FxIndexMap::default(); // If new predicates were added then we need to re-calculate @@ -58,7 +53,6 @@ pub(super) fn infer_predicates( ); } } - DefKind::TyAlias if tcx.type_alias_is_lazy(item_did) => { insert_required_predicates_to_be_wf( tcx, @@ -69,7 +63,23 @@ pub(super) fn infer_predicates( &mut explicit_map, ); } - + // HACK(generic_const_items): We have to explicitly disqualify const items that do + // not have any parameters to break certain query cycles that would otherwise occur + // when `typeck`'ing const items which we would only do if its type signature was + // ill-formed due to it missing or containing inferred types `_`. + // + // This is correct as we only ever imply outlives-predicates where the outlived + // region is early-bound ... for which the item must have generic parameters. + DefKind::Const { .. } if !tcx.generics_of(item_did).is_empty() => { + insert_required_predicates_to_be_wf( + tcx, + tcx.type_of(item_did).instantiate_identity(), + tcx.def_span(item_did), + &global_inferred_outlives, + &mut item_required_predicates, + &mut explicit_map, + ); + } _ => {} }; @@ -312,7 +322,7 @@ fn check_explicit_predicates<'tcx>( } } -/// Check the inferred predicates declared on the type. +/// Check the inferred predicates of the type. /// /// ### Example /// diff --git a/compiler/rustc_hir_analysis/src/outlives/mod.rs b/compiler/rustc_hir_analysis/src/outlives/mod.rs index d155f4f98ad79..22fcd08bf4071 100644 --- a/compiler/rustc_hir_analysis/src/outlives/mod.rs +++ b/compiler/rustc_hir_analysis/src/outlives/mod.rs @@ -13,17 +13,11 @@ pub(super) fn inferred_outlives_of( item_def_id: LocalDefId, ) -> &[(ty::Clause<'_>, Span)] { match tcx.def_kind(item_def_id) { - DefKind::Struct | DefKind::Enum | DefKind::Union => { - let crate_map = tcx.inferred_outlives_crate(()); - crate_map.predicates.get(&item_def_id.to_def_id()).copied().unwrap_or(&[]) - } - DefKind::TyAlias if tcx.type_alias_is_lazy(item_def_id) => { - let crate_map = tcx.inferred_outlives_crate(()); - crate_map.predicates.get(&item_def_id.to_def_id()).copied().unwrap_or(&[]) - } + DefKind::Struct | DefKind::Enum | DefKind::Union | DefKind::Const { .. } => {} + DefKind::TyAlias if tcx.type_alias_is_lazy(item_def_id) => {} DefKind::AnonConst if tcx.features().generic_const_exprs() => { let id = tcx.local_def_id_to_hir_id(item_def_id); - if tcx.hir_opt_const_param_default_param_def_id(id).is_some() { + return if tcx.hir_opt_const_param_default_param_def_id(id).is_some() { // In `generics_of` we set the generics' parent to be our parent's parent which means that // we lose out on the predicates of our actual parent if we dont return those predicates here. // (See comment in `generics_of` for more information on why the parent shenanigans is necessary) @@ -40,21 +34,23 @@ pub(super) fn inferred_outlives_of( tcx.inferred_outlives_of(item_def_id) } else { &[] - } + }; } - _ => &[], + _ => return &[], + } + + if tcx.generics_of(item_def_id).is_empty() { + // Fast path. + return &[]; } + + let crate_map = tcx.inferred_outlives_crate(()); + crate_map.predicates.get(&item_def_id.to_def_id()).copied().unwrap_or(&[]) } +/// Compute a map from each applicable item in the local crate to its +/// inferred / implied outlives-predicates. pub(super) fn inferred_outlives_crate(tcx: TyCtxt<'_>, (): ()) -> CratePredicatesMap<'_> { - // Compute a map from each ADT (struct/enum/union) and lazy type alias to - // the **explicit** outlives predicates (`T: 'a`, `'a: 'b`) that the user wrote. - // Typically there won't be many of these, except in older code where - // they were mandatory. Nonetheless, we have to ensure that every such - // predicate is satisfied, so they form a kind of base set of requirements - // for the type. - - // Compute the inferred predicates let global_inferred_outlives = implicit_infer::infer_predicates(tcx); // Convert the inferred predicates into the "collected" form the diff --git a/src/doc/rustc-dev-guide/src/traits/implied-bounds.md b/src/doc/rustc-dev-guide/src/traits/implied-bounds.md index cdcb90d3e2edf..4b8be3663f99e 100644 --- a/src/doc/rustc-dev-guide/src/traits/implied-bounds.md +++ b/src/doc/rustc-dev-guide/src/traits/implied-bounds.md @@ -9,9 +9,9 @@ handled... well... implicitly. ## explicit implied bounds -The explicit implied bounds are computed in [`fn inferred_outlives_of`]. Only ADTs and -lazy type aliases have explicit implied bounds which are computed via a fixpoint algorithm -in the [`fn inferred_outlives_crate`] query. +The explicit implied bounds are computed in [`fn inferred_outlives_of`]. Only ADTs, +[lazy type aliases][lta] and [free (generic) const items][gci] have explicit implied bounds +which are computed via a fixpoint algorithm in the [`fn inferred_outlives_crate`] query. We use [`fn insert_required_predicates_to_be_wf`] on all fields of all ADTs in the crate. This function computes the outlives bounds for each component of the field using a @@ -31,6 +31,8 @@ if the outlived region is a region parameter. [It does not add `'static` require [`fn check_explicit_predicates`]: https://github.com/rust-lang/rust/blob/5b8bc568d28b2e922290c9a966b3231d0ce9398b/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs#L238 [`fn insert_outlives_predicate`]: https://github.com/rust-lang/rust/blob/5b8bc568d28b2e922290c9a966b3231d0ce9398b/compiler/rustc_hir_analysis/src/outlives/utils.rs#L15 [nostatic]: https://github.com/rust-lang/rust/blob/5b8bc568d28b2e922290c9a966b3231d0ce9398b/compiler/rustc_hir_analysis/src/outlives/utils.rs#L159-L165 + [lta]: https://github.com/rust-lang/rust/issues/112792 + [gci]: https://github.com/rust-lang/rust/issues/113521 ## implicit implied bounds diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/return-via-stack.stderr b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/return-via-stack.stderr index 6b7446abc8eb8..a41fc4f89efd2 100644 --- a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/return-via-stack.stderr +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/return-via-stack.stderr @@ -1,21 +1,3 @@ -error[E0798]: return value of `"cmse-nonsecure-call"` function too large to pass via registers - --> $DIR/return-via-stack.rs:41:48 - | -LL | u128: extern "cmse-nonsecure-call" fn() -> u128, - | ^^^^ this type doesn't fit in the available registers - | - = note: functions with the `"cmse-nonsecure-call"` ABI must pass their result via the available return registers - = note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size - -error[E0798]: return value of `"cmse-nonsecure-call"` function too large to pass via registers - --> $DIR/return-via-stack.rs:42:48 - | -LL | i128: extern "cmse-nonsecure-call" fn() -> i128, - | ^^^^ this type doesn't fit in the available registers - | - = note: functions with the `"cmse-nonsecure-call"` ABI must pass their result via the available return registers - = note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size - error[E0798]: return value of `"cmse-nonsecure-call"` function too large to pass via registers --> $DIR/return-via-stack.rs:30:46 | @@ -70,6 +52,24 @@ LL | f6: extern "cmse-nonsecure-call" fn() -> [u8; 5], = note: functions with the `"cmse-nonsecure-call"` ABI must pass their result via the available return registers = note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size +error[E0798]: return value of `"cmse-nonsecure-call"` function too large to pass via registers + --> $DIR/return-via-stack.rs:41:48 + | +LL | u128: extern "cmse-nonsecure-call" fn() -> u128, + | ^^^^ this type doesn't fit in the available registers + | + = note: functions with the `"cmse-nonsecure-call"` ABI must pass their result via the available return registers + = note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size + +error[E0798]: return value of `"cmse-nonsecure-call"` function too large to pass via registers + --> $DIR/return-via-stack.rs:42:48 + | +LL | i128: extern "cmse-nonsecure-call" fn() -> i128, + | ^^^^ this type doesn't fit in the available registers + | + = note: functions with the `"cmse-nonsecure-call"` ABI must pass their result via the available return registers + = note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size + error[E0798]: return value of `"cmse-nonsecure-call"` function too large to pass via registers --> $DIR/return-via-stack.rs:57:46 | diff --git a/tests/ui/dyn-keyword/suggest-struct-or-union-add-generic-impl-trait.stderr b/tests/ui/dyn-keyword/suggest-struct-or-union-add-generic-impl-trait.stderr index 9584147bbc77f..0e03f571c937a 100644 --- a/tests/ui/dyn-keyword/suggest-struct-or-union-add-generic-impl-trait.stderr +++ b/tests/ui/dyn-keyword/suggest-struct-or-union-add-generic-impl-trait.stderr @@ -46,6 +46,17 @@ LL | A(u32), LL ~ B(T), | +error[E0782]: expected a type, found a trait + --> $DIR/suggest-struct-or-union-add-generic-impl-trait.rs:31:5 + | +LL | Trait:, {} + | ^^^^^ + | +help: you can add the `dyn` keyword if you want a trait object + | +LL | dyn Trait:, {} + | +++ + error[E0782]: expected a type, found a trait --> $DIR/suggest-struct-or-union-add-generic-impl-trait.rs:35:8 | @@ -58,17 +69,6 @@ LL ~ struct HasGenerics { LL ~ f: U, | -error[E0782]: expected a type, found a trait - --> $DIR/suggest-struct-or-union-add-generic-impl-trait.rs:31:5 - | -LL | Trait:, {} - | ^^^^^ - | -help: you can add the `dyn` keyword if you want a trait object - | -LL | dyn Trait:, {} - | +++ - error: aborting due to 6 previous errors For more information about this error, try `rustc --explain E0782`. diff --git a/tests/ui/generic-const-items/assoc-const-missing-type.rs b/tests/ui/generic-const-items/assoc-const-missing-type.rs deleted file mode 100644 index 2b7167ad067e2..0000000000000 --- a/tests/ui/generic-const-items/assoc-const-missing-type.rs +++ /dev/null @@ -1,20 +0,0 @@ -// Ensure that we properly deal with missing/placeholder types inside GACs. -// issue: rust-lang/rust#124833 -#![feature(generic_const_items)] -#![allow(incomplete_features)] - -trait Trait { - const K: T; - const Q<'a>: &'a str; -} - -impl Trait for () { - const K = (); - //~^ ERROR missing type for `const` item - //~| ERROR mismatched types - const Q = ""; - //~^ ERROR missing type for `const` item - //~| ERROR lifetime parameters or bounds on associated constant `Q` do not match the trait declaration -} - -fn main() {} diff --git a/tests/ui/generic-const-items/assoc-const-missing-type.stderr b/tests/ui/generic-const-items/assoc-const-missing-type.stderr deleted file mode 100644 index 7c79133d64ec3..0000000000000 --- a/tests/ui/generic-const-items/assoc-const-missing-type.stderr +++ /dev/null @@ -1,36 +0,0 @@ -error[E0308]: mismatched types - --> $DIR/assoc-const-missing-type.rs:12:18 - | -LL | const K = (); - | - ^^ expected type parameter `T`, found `()` - | | - | expected this type parameter - | - = note: expected type parameter `T` - found unit type `()` - -error: missing type for `const` item - --> $DIR/assoc-const-missing-type.rs:12:15 - | -LL | const K = (); - | ^ help: provide a type for the associated constant: `()` - -error[E0195]: lifetime parameters or bounds on associated constant `Q` do not match the trait declaration - --> $DIR/assoc-const-missing-type.rs:15:12 - | -LL | const Q<'a>: &'a str; - | ---- lifetimes in impl do not match this associated constant in trait -... -LL | const Q = ""; - | ^ lifetimes do not match associated constant in trait - -error: missing type for `const` item - --> $DIR/assoc-const-missing-type.rs:15:12 - | -LL | const Q = ""; - | ^ help: provide a type for the associated constant: `: &str` - -error: aborting due to 4 previous errors - -Some errors have detailed explanations: E0195, E0308. -For more information about an error, try `rustc --explain E0195`. diff --git a/tests/ui/generic-const-items/implied-outlives-bounds-0.neg.stderr b/tests/ui/generic-const-items/implied-outlives-bounds-0.neg.stderr new file mode 100644 index 0000000000000..6f128ae92066c --- /dev/null +++ b/tests/ui/generic-const-items/implied-outlives-bounds-0.neg.stderr @@ -0,0 +1,18 @@ +error: lifetime may not live long enough + --> $DIR/implied-outlives-bounds-0.rs:20:9 + | +LL | fn env0<'any>() { + | ---- lifetime `'any` defined here +LL | _ = TYPE_OUTLIVES_0::<'static, &'any ()>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'any` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/implied-outlives-bounds-0.rs:25:9 + | +LL | fn env1<'any>() { + | ---- lifetime `'any` defined here +LL | _ = REGION_OUTLIVES_0::<'static, 'any>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'any` must outlive `'static` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/generic-const-items/implied-outlives-bounds-0.rs b/tests/ui/generic-const-items/implied-outlives-bounds-0.rs new file mode 100644 index 0000000000000..de953a6caa1e6 --- /dev/null +++ b/tests/ui/generic-const-items/implied-outlives-bounds-0.rs @@ -0,0 +1,28 @@ +// Check that we imply outlives-bounds on (generic) free const items. +//@ revisions: pos neg +//@[pos] check-pass +#![feature(generic_const_items)] +#![feature(freeze)] // only used in the test case `TYPE_OUTLIVES_1` +#![expect(incomplete_features)] + +const REGION_OUTLIVES_0<'a, 'b>: Option<&'a &'b ()> = None; // we imply `'a: 'b` +const REGION_OUTLIVES_1<'a, 'b>: &'a &'b () = &&(); // we imply `'a: 'b` + +const TYPE_OUTLIVES_0<'a, T>: Option<&'a T> = None; // we imply `T: 'a` + +const TYPE_OUTLIVES_1<'a, T: Def>: &'a T = &T::DEF; // we imply `T: 'a` +trait Def: std::marker::Freeze { const DEF: Self; } + +// Ensure that we actually enforce these implied bounds at usage sites: + +#[cfg(neg)] +fn env0<'any>() { + _ = TYPE_OUTLIVES_0::<'static, &'any ()>; //[neg]~ ERROR lifetime may not live long enough +} + +#[cfg(neg)] +fn env1<'any>() { + _ = REGION_OUTLIVES_0::<'static, 'any>; //[neg]~ ERROR lifetime may not live long enough +} + +fn main() {} diff --git a/tests/ui/generic-const-items/implied-outlives-bounds-1.rs b/tests/ui/generic-const-items/implied-outlives-bounds-1.rs new file mode 100644 index 0000000000000..ee593b90f2aae --- /dev/null +++ b/tests/ui/generic-const-items/implied-outlives-bounds-1.rs @@ -0,0 +1,26 @@ +// FIXME(fmease): This still needs to be implemented +//@ ignore-test +// Check that paths referring to (generic) free const items induce implied bounds. +//@ revisions: pos neg +//@[pos] check-pass +#![feature(generic_const_items, min_generic_const_args)] +#![expect(incomplete_items)] + +// References of `EXP::<'r, 'q>` should induce implied bound `'q: 'r` in the enclosing def. +type const EXP<'a, 'b: 'a>: usize = 0; + +struct Ty<'a, 'b>([(); EXP::<'a, 'b>]); // we imply `'a: 'b` +const CT<'a, 'b>: [(); EXP::<'a, 'b>] = { + let _: &'a &'b (); // OK since `EXP::<'a, 'b>` implies `'a: 'b` + [] +}; + +#[cfg(neg)] +fn env0<'any>() { + let _: Ty<'static, 'any>; //[neg]~ ERROR lifetime may not live long enough +} + +#[cfg(neg)] +fn env1<'any>() { + _ = CT::<'static, 'any>; //[neg]~ ERROR lifetime may not live long enough +} diff --git a/tests/ui/generic-const-items/missing-or-inferred-type.rs b/tests/ui/generic-const-items/missing-or-inferred-type.rs new file mode 100644 index 0000000000000..09d98324a2cf1 --- /dev/null +++ b/tests/ui/generic-const-items/missing-or-inferred-type.rs @@ -0,0 +1,39 @@ +// Ensure that we properly deal with missing signatures and inferred types `_` in the signature. +#![feature(generic_const_items)] +#![expect(incomplete_features)] + +// For implicit & explicit inferred types in the item signature we generally try to infer the +// type of the body which we can then suggest to the user. + +// However, in the type of trait impl assoc items specifically we first try to suggest the type of +// the corresponding definition in the trait. While doing so, we once didn't use to instantiate GACs +// correctly & couldn't handle mismatches in parameter list lengths very well (impl v trait). +// issue: + +trait Trait { + const K: T; + const Q<'a>: &'a str; +} + +impl Trait for () { + const K = (); + //~^ ERROR missing type for `const` item + //~| ERROR mismatched types + //~| SUGGESTION () + const Q = ""; + //~^ ERROR missing type for `const` item + //~| ERROR lifetime parameters or bounds on associated constant `Q` do not match the trait declaration + //~| SUGGESTION : &str +} + +// For parametrized free const items however, we can't typeck the body without causing a query cycle +// so we don't and thus fall back to a generic suggestion that has a placeholder. + +const _ = loop {}; +//~^ ERROR missing type for `const` item +//~| SUGGESTION + +const _: _ = 0; +//~^ ERROR the placeholder `_` is not allowed + +fn main() {} diff --git a/tests/ui/generic-const-items/missing-or-inferred-type.stderr b/tests/ui/generic-const-items/missing-or-inferred-type.stderr new file mode 100644 index 0000000000000..ebc9e33e3aa09 --- /dev/null +++ b/tests/ui/generic-const-items/missing-or-inferred-type.stderr @@ -0,0 +1,53 @@ +error[E0308]: mismatched types + --> $DIR/missing-or-inferred-type.rs:19:18 + | +LL | const K = (); + | - ^^ expected type parameter `T`, found `()` + | | + | expected this type parameter + | + = note: expected type parameter `T` + found unit type `()` + +error: missing type for `const` item + --> $DIR/missing-or-inferred-type.rs:19:15 + | +LL | const K = (); + | ^ help: provide a type for the associated constant: `()` + +error[E0195]: lifetime parameters or bounds on associated constant `Q` do not match the trait declaration + --> $DIR/missing-or-inferred-type.rs:23:13 + | +LL | const Q<'a>: &'a str; + | ---- lifetimes in impl do not match this associated constant in trait +... +LL | const Q = ""; + | ^ lifetimes do not match associated constant in trait + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants + --> $DIR/missing-or-inferred-type.rs:36:13 + | +LL | const _: _ = 0; + | ^ not allowed in type signatures + +error: missing type for `const` item + --> $DIR/missing-or-inferred-type.rs:23:13 + | +LL | const Q = ""; + | ^ help: provide a type for the associated constant: `: &str` + +error: missing type for `const` item + --> $DIR/missing-or-inferred-type.rs:32:11 + | +LL | const _ = loop {}; + | ^ + | +help: provide a type for the item + | +LL | const _: = loop {}; + | ++++++++ + +error: aborting due to 6 previous errors + +Some errors have detailed explanations: E0121, E0195, E0308. +For more information about an error, try `rustc --explain E0121`. diff --git a/tests/ui/generic-const-items/reference-outlives-referent.rs b/tests/ui/generic-const-items/reference-outlives-referent.rs index 13e4eaac39f88..ba9bae688584c 100644 --- a/tests/ui/generic-const-items/reference-outlives-referent.rs +++ b/tests/ui/generic-const-items/reference-outlives-referent.rs @@ -2,8 +2,17 @@ // successfully emit a diagnostic. Regression test for issue #114714. #![feature(generic_const_items)] -#![allow(incomplete_features)] +#![expect(incomplete_features)] -const Q<'a, 'b>: &'a &'b () = &&(); //~ ERROR reference has a longer lifetime than the data it references +struct S<'a>(&'a ()); + +impl<'a> S<'a> { + const C<'b, 'c>: &'c &'b () = &&(); //~ ERROR reference has a longer lifetime than the data it references + const K<'b>: &'a &'b () = &&(); //~ ERROR reference has a longer lifetime than the data it references +} + +const Q<'a, 'b>: () = { + let _: &'a &'b () = &&(); //~ ERROR lifetime may not live long enough +}; fn main() {} diff --git a/tests/ui/generic-const-items/reference-outlives-referent.stderr b/tests/ui/generic-const-items/reference-outlives-referent.stderr index 34553c51654bb..427bd4a832564 100644 --- a/tests/ui/generic-const-items/reference-outlives-referent.stderr +++ b/tests/ui/generic-const-items/reference-outlives-referent.stderr @@ -1,20 +1,49 @@ +error[E0491]: in type `&'c &'b ()`, reference has a longer lifetime than the data it references + --> $DIR/reference-outlives-referent.rs:10:5 + | +LL | const C<'b, 'c>: &'c &'b () = &&(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the pointer is valid for the lifetime `'c` as defined here + --> $DIR/reference-outlives-referent.rs:10:17 + | +LL | const C<'b, 'c>: &'c &'b () = &&(); + | ^^ +note: but the referenced data is only valid for the lifetime `'b` as defined here + --> $DIR/reference-outlives-referent.rs:10:13 + | +LL | const C<'b, 'c>: &'c &'b () = &&(); + | ^^ + error[E0491]: in type `&'a &'b ()`, reference has a longer lifetime than the data it references - --> $DIR/reference-outlives-referent.rs:7:18 + --> $DIR/reference-outlives-referent.rs:11:5 | -LL | const Q<'a, 'b>: &'a &'b () = &&(); - | ^^^^^^^^^^ +LL | const K<'b>: &'a &'b () = &&(); + | ^^^^^^^^^^^^^^^^^^^^^^^ | note: the pointer is valid for the lifetime `'a` as defined here - --> $DIR/reference-outlives-referent.rs:7:9 + --> $DIR/reference-outlives-referent.rs:9:6 | -LL | const Q<'a, 'b>: &'a &'b () = &&(); - | ^^ +LL | impl<'a> S<'a> { + | ^^ note: but the referenced data is only valid for the lifetime `'b` as defined here - --> $DIR/reference-outlives-referent.rs:7:13 + --> $DIR/reference-outlives-referent.rs:11:13 | -LL | const Q<'a, 'b>: &'a &'b () = &&(); +LL | const K<'b>: &'a &'b () = &&(); | ^^ -error: aborting due to 1 previous error +error: lifetime may not live long enough + --> $DIR/reference-outlives-referent.rs:15:12 + | +LL | const Q<'a, 'b>: () = { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | let _: &'a &'b () = &&(); + | ^^^^^^^^^^ requires that `'b` must outlive `'a` + | + = help: consider adding the following bound: `'b: 'a` + +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0491`. diff --git a/tests/ui/suggestions/issue-61963.stderr b/tests/ui/suggestions/issue-61963.stderr index f9146a619ec45..621a3129260c1 100644 --- a/tests/ui/suggestions/issue-61963.stderr +++ b/tests/ui/suggestions/issue-61963.stderr @@ -1,8 +1,8 @@ error: trait objects without an explicit `dyn` are deprecated - --> $DIR/issue-61963.rs:24:14 + --> $DIR/issue-61963.rs:20:1 | -LL | bar: Box, - | ^^^ +LL | pub struct Foo { + | ^^^ | = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see @@ -13,21 +13,21 @@ LL | #![deny(bare_trait_objects)] | ^^^^^^^^^^^^^^^^^^ help: if this is a dyn-compatible trait, use `dyn` | -LL | bar: Box, - | +++ +LL | dyn pub struct Foo { + | +++ error: trait objects without an explicit `dyn` are deprecated - --> $DIR/issue-61963.rs:20:1 + --> $DIR/issue-61963.rs:24:14 | -LL | pub struct Foo { - | ^^^ +LL | bar: Box, + | ^^^ | = 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 | dyn pub struct Foo { - | +++ +LL | bar: Box, + | +++ error: aborting due to 2 previous errors diff --git a/tests/ui/typeck/typeck_type_placeholder_item.stderr b/tests/ui/typeck/typeck_type_placeholder_item.stderr index 2772d55f953a8..7d963ee7ba07e 100644 --- a/tests/ui/typeck/typeck_type_placeholder_item.stderr +++ b/tests/ui/typeck/typeck_type_placeholder_item.stderr @@ -138,60 +138,6 @@ error[E0121]: the placeholder `_` is not allowed within types on item signatures LL | fn test8(_f: fn() -> _) { } | ^ not allowed in type signatures -error[E0121]: the placeholder `_` is not allowed within types on item signatures for structs - --> $DIR/typeck_type_placeholder_item.rs:66:8 - | -LL | a: _, - | ^ not allowed in type signatures - -error[E0121]: the placeholder `_` is not allowed within types on item signatures for structs - --> $DIR/typeck_type_placeholder_item.rs:68:9 - | -LL | b: (_, _), - | ^ not allowed in type signatures - -error[E0121]: the placeholder `_` is not allowed within types on item signatures for structs - --> $DIR/typeck_type_placeholder_item.rs:68:12 - | -LL | b: (_, _), - | ^ not allowed in type signatures - -error[E0121]: the placeholder `_` is not allowed within types on item signatures for structs - --> $DIR/typeck_type_placeholder_item.rs:123:12 - | -LL | a: _, - | ^ not allowed in type signatures - -error[E0121]: the placeholder `_` is not allowed within types on item signatures for structs - --> $DIR/typeck_type_placeholder_item.rs:125:13 - | -LL | b: (_, _), - | ^ not allowed in type signatures - -error[E0121]: the placeholder `_` is not allowed within types on item signatures for structs - --> $DIR/typeck_type_placeholder_item.rs:125:16 - | -LL | b: (_, _), - | ^ not allowed in type signatures - -error[E0121]: the placeholder `_` is not allowed within types on item signatures for structs - --> $DIR/typeck_type_placeholder_item.rs:158:21 - | -LL | struct BadStruct<_>(_); - | ^ not allowed in type signatures - -error[E0121]: the placeholder `_` is not allowed within types on item signatures for structs - --> $DIR/typeck_type_placeholder_item.rs:173:25 - | -LL | struct BadStruct1<_, _>(_); - | ^ not allowed in type signatures - -error[E0121]: the placeholder `_` is not allowed within types on item signatures for structs - --> $DIR/typeck_type_placeholder_item.rs:178:25 - | -LL | struct BadStruct2<_, T>(_, T); - | ^ not allowed in type signatures - error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types --> $DIR/typeck_type_placeholder_item.rs:47:26 | @@ -240,6 +186,24 @@ LL - fn clone_from(&mut self, other: _) { *self = Test9; } LL + fn clone_from(&mut self, other: &Test9) { *self = Test9; } | +error[E0121]: the placeholder `_` is not allowed within types on item signatures for structs + --> $DIR/typeck_type_placeholder_item.rs:66:8 + | +LL | a: _, + | ^ not allowed in type signatures + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for structs + --> $DIR/typeck_type_placeholder_item.rs:68:9 + | +LL | b: (_, _), + | ^ not allowed in type signatures + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for structs + --> $DIR/typeck_type_placeholder_item.rs:68:12 + | +LL | b: (_, _), + | ^ not allowed in type signatures + error: missing type for `static` item --> $DIR/typeck_type_placeholder_item.rs:74:13 | @@ -376,6 +340,24 @@ LL - fn clone_from(&mut self, other: _) { *self = FnTest9; } LL + fn clone_from(&mut self, other: &FnTest9) { *self = FnTest9; } | +error[E0121]: the placeholder `_` is not allowed within types on item signatures for structs + --> $DIR/typeck_type_placeholder_item.rs:123:12 + | +LL | a: _, + | ^ not allowed in type signatures + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for structs + --> $DIR/typeck_type_placeholder_item.rs:125:13 + | +LL | b: (_, _), + | ^ not allowed in type signatures + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for structs + --> $DIR/typeck_type_placeholder_item.rs:125:16 + | +LL | b: (_, _), + | ^ not allowed in type signatures + error[E0282]: type annotations needed --> $DIR/typeck_type_placeholder_item.rs:130:21 | @@ -416,6 +398,24 @@ LL - fn fn_test13(x: _) -> (i32, _) { (x, x) } LL + fn fn_test13(x: _) -> (i32, i32) { (x, x) } | +error[E0121]: the placeholder `_` is not allowed within types on item signatures for structs + --> $DIR/typeck_type_placeholder_item.rs:158:21 + | +LL | struct BadStruct<_>(_); + | ^ not allowed in type signatures + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for structs + --> $DIR/typeck_type_placeholder_item.rs:173:25 + | +LL | struct BadStruct1<_, _>(_); + | ^ not allowed in type signatures + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for structs + --> $DIR/typeck_type_placeholder_item.rs:178:25 + | +LL | struct BadStruct2<_, T>(_, T); + | ^ not allowed in type signatures + error[E0121]: the placeholder `_` is not allowed within types on item signatures for methods --> $DIR/typeck_type_placeholder_item.rs:142:31 |