diff --git a/compiler/rustc_borrowck/src/handle_placeholders.rs b/compiler/rustc_borrowck/src/handle_placeholders.rs index aaaf2f45c869d..8893ba662ae67 100644 --- a/compiler/rustc_borrowck/src/handle_placeholders.rs +++ b/compiler/rustc_borrowck/src/handle_placeholders.rs @@ -103,6 +103,10 @@ impl RegionTracker { self.max_nameable_universe } + pub(crate) fn max_placeholder_universe_reached(self) -> UniverseIndex { + self.max_placeholder_universe_reached + } + fn merge_min_max_seen(&mut self, other: &Self) { self.max_placeholder_universe_reached = std::cmp::max( self.max_placeholder_universe_reached, diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index 5f1b655c6b60d..2f1c1d7cd6109 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -713,7 +713,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { // If the member region lives in a higher universe, we currently choose // the most conservative option by leaving it unchanged. - if !self.max_nameable_universe(scc).is_root() { + if !self.max_placeholder_universe_reached(scc).is_root() { return; } @@ -1376,6 +1376,13 @@ impl<'tcx> RegionInferenceContext<'tcx> { self.scc_annotations[scc].max_nameable_universe() } + pub(crate) fn max_placeholder_universe_reached( + &self, + scc: ConstraintSccIndex, + ) -> UniverseIndex { + self.scc_annotations[scc].max_placeholder_universe_reached() + } + /// Checks the final value for the free region `fr` to see if it /// grew too large. In particular, examine what `end(X)` points /// wound up in `fr`'s final value; for each `end(X)` where `X != diff --git a/compiler/rustc_borrowck/src/type_check/relate_tys.rs b/compiler/rustc_borrowck/src/type_check/relate_tys.rs index 02a41469c97f4..cb584b25dbd42 100644 --- a/compiler/rustc_borrowck/src/type_check/relate_tys.rs +++ b/compiler/rustc_borrowck/src/type_check/relate_tys.rs @@ -124,8 +124,13 @@ impl<'a, 'b, 'tcx> NllTypeRelating<'a, 'b, 'tcx> { // by using `ty_vid rel B` and then finally and end by equating `ty_vid` to // the opaque. let mut enable_subtyping = |ty, opaque_is_expected| { - let ty_vid = infcx.next_ty_var_id_in_universe(self.span(), ty::UniverseIndex::ROOT); - + // We create the fresh inference variable in the highest universe. + // In theory we could limit it to the highest universe in the args of + // the opaque but that isn't really worth the effort. + // + // We'll make sure that the opaque type can actually name everything + // in its hidden type later on. + let ty_vid = infcx.next_ty_vid(self.span()); let variance = if opaque_is_expected { self.ambient_variance } else { diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 96e03e3bea564..5b7f60a51b287 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -743,22 +743,30 @@ impl<'tcx> InferCtxt<'tcx> { self.inner.borrow_mut().type_variables().num_vars() } - pub fn next_ty_var(&self, span: Span) -> Ty<'tcx> { - self.next_ty_var_with_origin(TypeVariableOrigin { span, param_def_id: None }) + pub fn next_ty_vid(&self, span: Span) -> TyVid { + self.next_ty_vid_with_origin(TypeVariableOrigin { span, param_def_id: None }) } - pub fn next_ty_var_with_origin(&self, origin: TypeVariableOrigin) -> Ty<'tcx> { - let vid = self.inner.borrow_mut().type_variables().new_var(self.universe(), origin); - Ty::new_var(self.tcx, vid) + pub fn next_ty_vid_with_origin(&self, origin: TypeVariableOrigin) -> TyVid { + self.inner.borrow_mut().type_variables().new_var(self.universe(), origin) } - pub fn next_ty_var_id_in_universe(&self, span: Span, universe: ty::UniverseIndex) -> TyVid { + pub fn next_ty_vid_in_universe(&self, span: Span, universe: ty::UniverseIndex) -> TyVid { let origin = TypeVariableOrigin { span, param_def_id: None }; self.inner.borrow_mut().type_variables().new_var(universe, origin) } + pub fn next_ty_var(&self, span: Span) -> Ty<'tcx> { + self.next_ty_var_with_origin(TypeVariableOrigin { span, param_def_id: None }) + } + + pub fn next_ty_var_with_origin(&self, origin: TypeVariableOrigin) -> Ty<'tcx> { + let vid = self.next_ty_vid_with_origin(origin); + Ty::new_var(self.tcx, vid) + } + pub fn next_ty_var_in_universe(&self, span: Span, universe: ty::UniverseIndex) -> Ty<'tcx> { - let vid = self.next_ty_var_id_in_universe(span, universe); + let vid = self.next_ty_vid_in_universe(span, universe); Ty::new_var(self.tcx, vid) } diff --git a/tests/ui/nll/member-constraints/non-root-universe-existential-1.rs b/tests/ui/nll/member-constraints/non-root-universe-existential-1.rs new file mode 100644 index 0000000000000..39dbfebce10aa --- /dev/null +++ b/tests/ui/nll/member-constraints/non-root-universe-existential-1.rs @@ -0,0 +1,29 @@ +//@ check-pass +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver + +trait Proj<'a> { + type Assoc; +} + +impl<'a, 'b, F: FnOnce() -> &'b ()> Proj<'a> for F { + type Assoc = (); +} + +fn is_proj Proj<'a>>(f: F) {} + +fn define<'a>() -> impl Sized + use<'a> { + // This defines the RPIT to `&'unconstrained_b ()`, an inference + // variable which is in a higher universe as gets created inside + // of the binder of `F: for<'a> Proj<'a>`. This previously caused + // us to not apply member constraints. + // + // This was unnecessary. It is totally acceptable for member regions + // to be able to name placeholders from higher universes, as long as + // they don't actually do so. + is_proj(define::<'a>); + &() +} + +fn main() {} diff --git a/tests/ui/nll/member-constraints/non-root-universe-existential-2.rs b/tests/ui/nll/member-constraints/non-root-universe-existential-2.rs new file mode 100644 index 0000000000000..8d637abad7d3b --- /dev/null +++ b/tests/ui/nll/member-constraints/non-root-universe-existential-2.rs @@ -0,0 +1,31 @@ +//@ check-pass + +// Unlike `non-root-universe-existential-1.rs` this previously +// compiled as it simnply didn't define the hidden type of +// `impl Iterator` when projecting through it. We will do so +// with the new solver. Further minimizing this is challenging. + +struct Type(Vec); +enum TypeTreeValueIter<'a, T> { + Once(T), + Ref(&'a ()), +} + +impl<'a, T> Iterator for TypeTreeValueIter<'a, T> { + type Item = T; + + fn next(&mut self) -> Option { + loop {} + } +} + +fn item>(x: I) -> ::Item { + loop {} +} + +fn get_type_tree_values<'a>(ty: &'a Type) -> impl Iterator { + let _: &'a Type = item(std::iter::once(ty).map(get_type_tree_values)); + TypeTreeValueIter::<'a, &'a Type>::Once(ty) +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/higher_kinded_params3.rs b/tests/ui/type-alias-impl-trait/higher_kinded_params3.rs index 4fb2e60b5c5a3..04208fadddecf 100644 --- a/tests/ui/type-alias-impl-trait/higher_kinded_params3.rs +++ b/tests/ui/type-alias-impl-trait/higher_kinded_params3.rs @@ -24,8 +24,7 @@ type Successors<'a> = impl std::fmt::Debug + 'a; impl Terminator { #[define_opaque(Successors, Tait)] fn successors(&self, mut f: for<'x> fn(&'x ()) -> <&'x A as B>::C) -> Successors<'_> { - f = g; - //~^ ERROR mismatched types + f = g; //~ ERROR expected generic lifetime parameter, found `'x` } } diff --git a/tests/ui/type-alias-impl-trait/higher_kinded_params3.stderr b/tests/ui/type-alias-impl-trait/higher_kinded_params3.stderr index 558792987f31c..8e6778bdd0b53 100644 --- a/tests/ui/type-alias-impl-trait/higher_kinded_params3.stderr +++ b/tests/ui/type-alias-impl-trait/higher_kinded_params3.stderr @@ -1,15 +1,12 @@ -error[E0308]: mismatched types +error[E0792]: expected generic lifetime parameter, found `'x` --> $DIR/higher_kinded_params3.rs:27:9 | LL | type Tait<'a> = impl std::fmt::Debug + 'a; - | ------------------------- the expected opaque type + | -- this generic parameter must be used with a generic lifetime parameter ... LL | f = g; - | ^^^^^ one type is more general than the other - | - = note: expected fn pointer `for<'x> fn(&'x ()) -> Tait<'x>` - found fn pointer `for<'a> fn(&'a ()) -> &'a ()` + | ^^^^^ error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0308`. +For more information about this error, try `rustc --explain E0792`. diff --git a/tests/ui/type-alias-impl-trait/hkl_forbidden3.rs b/tests/ui/type-alias-impl-trait/hkl_forbidden3.rs index c7f04dc07bb12..ba75b114a1188 100644 --- a/tests/ui/type-alias-impl-trait/hkl_forbidden3.rs +++ b/tests/ui/type-alias-impl-trait/hkl_forbidden3.rs @@ -8,7 +8,7 @@ fn foo<'a>(x: &'a ()) -> &'a () { #[define_opaque(Opaque)] fn test() -> for<'a> fn(&'a ()) -> Opaque<'a> { - foo //~ ERROR: mismatched types + foo //~ ERROR: expected generic lifetime parameter, found `'a` } fn main() {} diff --git a/tests/ui/type-alias-impl-trait/hkl_forbidden3.stderr b/tests/ui/type-alias-impl-trait/hkl_forbidden3.stderr index b8c04185a7d14..d699059e3972c 100644 --- a/tests/ui/type-alias-impl-trait/hkl_forbidden3.stderr +++ b/tests/ui/type-alias-impl-trait/hkl_forbidden3.stderr @@ -1,15 +1,12 @@ -error[E0308]: mismatched types +error[E0792]: expected generic lifetime parameter, found `'a` --> $DIR/hkl_forbidden3.rs:11:5 | LL | type Opaque<'a> = impl Sized + 'a; - | --------------- the expected opaque type + | -- this generic parameter must be used with a generic lifetime parameter ... LL | foo - | ^^^ one type is more general than the other - | - = note: expected fn pointer `for<'a> fn(&'a ()) -> Opaque<'a>` - found fn pointer `for<'a> fn(&'a ()) -> &'a ()` + | ^^^ error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0308`. +For more information about this error, try `rustc --explain E0792`.