diff --git a/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs b/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs index c17925471d983..f0eb75237c73a 100644 --- a/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs +++ b/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs @@ -59,6 +59,17 @@ pub(super) fn infer_predicates( } } + DefKind::TyAlias if tcx.type_alias_is_lazy(item_did) => { + 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, + ); + } + _ => {} }; @@ -212,6 +223,21 @@ fn insert_required_predicates_to_be_wf<'tcx>( ); } + ty::Alias(ty::Weak, alias) => { + // This corresponds to a type like `Type<'a, T>`. + // Contrary to a GAT like `<() as Trait>::Type<'a, T>`, + // we do use the own explicit predicates. + debug!("Weak"); + check_explicit_predicates( + tcx, + alias.def_id, + alias.args, + required_predicates, + explicit_map, + None, + ); + } + // FIXME(inherent_associated_types): Handle this case properly. ty::Alias(ty::Inherent, _) => {} diff --git a/compiler/rustc_hir_analysis/src/outlives/mod.rs b/compiler/rustc_hir_analysis/src/outlives/mod.rs index 72511bfa01f14..6b69265c53932 100644 --- a/compiler/rustc_hir_analysis/src/outlives/mod.rs +++ b/compiler/rustc_hir_analysis/src/outlives/mod.rs @@ -21,6 +21,10 @@ fn inferred_outlives_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[(ty::Clau 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::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() { diff --git a/tests/ui/lazy-type-alias/dont-imply-implied-outlives-bounds.rs b/tests/ui/lazy-type-alias/dont-imply-implied-outlives-bounds.rs new file mode 100644 index 0000000000000..49ac161a20807 --- /dev/null +++ b/tests/ui/lazy-type-alias/dont-imply-implied-outlives-bounds.rs @@ -0,0 +1,12 @@ +// Ensure that we don't imply the *implied* outlives-bounds of weak aliases. +// For context, we only imply the explicit bounds. +#![feature(lazy_type_alias)] +#![allow(incomplete_features)] + +type Alias<'a, T> = &'a T; // implied bound `T: 'a` + +struct Outer0<'a, T>(Alias<'a, T>); //~ ERROR the parameter type `T` may not live long enough + +type Outer1<'a, T> = Alias<'a, T>; //~ ERROR the parameter type `T` may not live long enough + +fn main() {} diff --git a/tests/ui/lazy-type-alias/dont-imply-implied-outlives-bounds.stderr b/tests/ui/lazy-type-alias/dont-imply-implied-outlives-bounds.stderr new file mode 100644 index 0000000000000..b3b216c33c7eb --- /dev/null +++ b/tests/ui/lazy-type-alias/dont-imply-implied-outlives-bounds.stderr @@ -0,0 +1,29 @@ +error[E0309]: the parameter type `T` may not live long enough + --> $DIR/dont-imply-implied-outlives-bounds.rs:8:22 + | +LL | struct Outer0<'a, T>(Alias<'a, T>); + | -- ^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds + | | + | the parameter type `T` must be valid for the lifetime `'a` as defined here... + | +help: consider adding an explicit lifetime bound + | +LL | struct Outer0<'a, T: 'a>(Alias<'a, T>); + | ++++ + +error[E0309]: the parameter type `T` may not live long enough + --> $DIR/dont-imply-implied-outlives-bounds.rs:10:22 + | +LL | type Outer1<'a, T> = Alias<'a, T>; + | -- ^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds + | | + | the parameter type `T` must be valid for the lifetime `'a` as defined here... + | +help: consider adding an explicit lifetime bound + | +LL | type Outer1<'a, T: 'a> = Alias<'a, T>; + | ++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0309`. diff --git a/tests/ui/lazy-type-alias/implied-outlives-bounds.neg.stderr b/tests/ui/lazy-type-alias/implied-outlives-bounds.neg.stderr new file mode 100644 index 0000000000000..63e9788a6966f --- /dev/null +++ b/tests/ui/lazy-type-alias/implied-outlives-bounds.neg.stderr @@ -0,0 +1,26 @@ +error: lifetime may not live long enough + --> $DIR/implied-outlives-bounds.rs:18:12 + | +LL | fn env0<'any>() { + | ---- lifetime `'any` defined here +LL | let _: TypeOutlives<'static, &'any ()>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'any` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/implied-outlives-bounds.rs:23:12 + | +LL | fn env1<'any>() { + | ---- lifetime `'any` defined here +LL | let _: RegionOutlives<'static, 'any>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'any` must outlive `'static` + +error: lifetime may not live long enough + --> $DIR/implied-outlives-bounds.rs:28:12 + | +LL | fn env2<'any>() { + | ---- lifetime `'any` defined here +LL | let _: Outer0<'static, &'any ()>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'any` must outlive `'static` + +error: aborting due to 3 previous errors + diff --git a/tests/ui/lazy-type-alias/implied-outlives-bounds.rs b/tests/ui/lazy-type-alias/implied-outlives-bounds.rs new file mode 100644 index 0000000000000..980335b3063e1 --- /dev/null +++ b/tests/ui/lazy-type-alias/implied-outlives-bounds.rs @@ -0,0 +1,31 @@ +// Check that we imply outlives-bounds on lazy type aliases. + +// revisions: pos neg +//[pos] check-pass + +#![feature(lazy_type_alias)] +#![allow(incomplete_features)] + +type TypeOutlives<'a, T> = &'a T; +type RegionOutlives<'a, 'b> = &'a &'b (); + +// Ensure that we imply `T: 'a` from the explicit predicates of the weak alias `Alias`. +struct Outer0<'a, T>(Alias<'a, T>); +type Alias<'a, T: 'a> = &'a T; + +#[cfg(neg)] +fn env0<'any>() { + let _: TypeOutlives<'static, &'any ()>; //[neg]~ ERROR lifetime may not live long enough +} + +#[cfg(neg)] +fn env1<'any>() { + let _: RegionOutlives<'static, 'any>; //[neg]~ ERROR lifetime may not live long enough +} + +#[cfg(neg)] +fn env2<'any>() { + let _: Outer0<'static, &'any ()>; //[neg]~ ERROR lifetime may not live long enough +} + +fn main() {}