diff --git a/compiler/rustc_middle/src/ty/context/impl_interner.rs b/compiler/rustc_middle/src/ty/context/impl_interner.rs index e9eef9336e8ba..58f07b38691f6 100644 --- a/compiler/rustc_middle/src/ty/context/impl_interner.rs +++ b/compiler/rustc_middle/src/ty/context/impl_interner.rs @@ -160,6 +160,10 @@ impl<'tcx> Interner for TyCtxt<'tcx> { // See trait-system-refactor-initiative#234. } + fn expand_free_alias_tys>>(self, t: T) -> T { + self.expand_free_alias_tys(t) + } + fn expand_abstract_consts>>(self, t: T) -> T { self.expand_abstract_consts(t) } diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 9f6d1170a85f1..3e9c8d12f0ec6 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -879,7 +879,7 @@ impl<'tcx> TyCtxt<'tcx> { value.fold_with(&mut FreeAliasTypeExpander { tcx: self, depth: 0 }) } - /// Peel off all [free alias types] in this type until there are none left. + /// Peel off all [free alias types][free] in this type until there are none left. /// /// This only expands free alias types in “head” / outermost positions. It can /// be used over [expand_free_alias_tys] as an optimization in situations where diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs index 1e5ad0b00e7ef..215459c65d439 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -217,6 +217,7 @@ pub trait Interner: /// (in theory) only happen when concurrent. fn assert_evaluation_is_concurrent(&self); + fn expand_free_alias_tys>(self, t: T) -> T; fn expand_abstract_consts>(self, t: T) -> T; type GenericsOf: GenericsOf; diff --git a/compiler/rustc_type_ir/src/outlives.rs b/compiler/rustc_type_ir/src/outlives.rs index 2a1cbc3575d85..743e58bca8c97 100644 --- a/compiler/rustc_type_ir/src/outlives.rs +++ b/compiler/rustc_type_ir/src/outlives.rs @@ -58,6 +58,7 @@ pub fn push_outlives_components( ty: I::Ty, out: &mut SmallVec<[Component; 4]>, ) { + let ty = cx.expand_free_alias_tys(ty); ty.visit_with(&mut OutlivesCollector { cx, out, visited: Default::default() }); } @@ -140,6 +141,11 @@ impl TypeVisitor for OutlivesCollector<'_, I> { self.out.push(Component::Placeholder(p)); } + // All free alias types should've been expanded beforehand. + ty::Alias(ty::AliasTy { kind: ty::Free { .. }, .. }) => { + panic!("unexpected free alias type") + } + // For projections, we prefer to generate an obligation like // `>::Foo: 'a`, because this gives the // regionck more ways to prove that it holds. However, diff --git a/tests/ui/lazy-type-alias/implied-outlives-bounds-1.print.stderr b/tests/ui/lazy-type-alias/implied-outlives-bounds-1.print.stderr new file mode 100644 index 0000000000000..2787283a3b233 --- /dev/null +++ b/tests/ui/lazy-type-alias/implied-outlives-bounds-1.print.stderr @@ -0,0 +1,11 @@ +error: rustc_dump_inferred_outlives + --> $DIR/implied-outlives-bounds-1.rs:13:1 + | +LL | struct Type<'a, K, V>(&'a mut Alias); + | ^^^^^^^^^^^^^^^^^^^^^ + | + = note: K: 'a + = note: V: 'a + +error: aborting due to 1 previous error + diff --git a/tests/ui/lazy-type-alias/implied-outlives-bounds-1.rs b/tests/ui/lazy-type-alias/implied-outlives-bounds-1.rs new file mode 100644 index 0000000000000..7d98bd6a6d7d5 --- /dev/null +++ b/tests/ui/lazy-type-alias/implied-outlives-bounds-1.rs @@ -0,0 +1,17 @@ +// Check that we infer the outlives-predicates `K: 'a`, `V: 'a` for `Type` +// from the free alias `Alias`. +// FIXME(fmease): Proper explainer. + +//@ revisions: default print +//@[default] check-pass + +#![feature(lazy_type_alias)] +#![cfg_attr(print, feature(rustc_attrs))] +#![allow(incomplete_features)] + +#[cfg_attr(print, rustc_dump_inferred_outlives)] +struct Type<'a, K, V>(&'a mut Alias); //[print]~ ERROR rustc_dump_inferred_outlives + +type Alias = (K, V); + +fn main() {}