diff options
Diffstat (limited to 'compiler/rustc_borrowck')
| -rw-r--r-- | compiler/rustc_borrowck/src/handle_placeholders.rs | 10 | ||||
| -rw-r--r-- | compiler/rustc_borrowck/src/region_infer/mod.rs | 20 | ||||
| -rw-r--r-- | compiler/rustc_borrowck/src/type_check/canonical.rs | 16 |
3 files changed, 28 insertions, 18 deletions
diff --git a/compiler/rustc_borrowck/src/handle_placeholders.rs b/compiler/rustc_borrowck/src/handle_placeholders.rs index 94379cdebf7..6be90994015 100644 --- a/compiler/rustc_borrowck/src/handle_placeholders.rs +++ b/compiler/rustc_borrowck/src/handle_placeholders.rs @@ -166,13 +166,9 @@ impl RegionTracker { } } - /// Determine if the tracked universes of the two SCCs are compatible. - pub(crate) fn universe_compatible_with(&self, other: Self) -> bool { - // HACK: We first check whether we can name the highest existential universe - // of `other`. This only exists to avoid errors in case that scc already - // depends on a placeholder it cannot name itself. - self.max_nameable_universe().can_name(other.max_nameable_universe()) - || other.reachable_placeholders.can_be_named_by(self.max_nameable_universe()) + /// Determine if we can name all the placeholders in `other`. + pub(crate) fn can_name_all_placeholders(&self, other: Self) -> bool { + other.reachable_placeholders.can_be_named_by(self.max_nameable_universe.0) } /// If this SCC reaches a placeholder it can't name, return it. diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index f57456949bb..5f4bfd9df48 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -571,11 +571,15 @@ impl<'tcx> RegionInferenceContext<'tcx> { } } - /// Returns `true` if all the elements in the value of `scc_b` are nameable + /// Returns `true` if all the placeholders in the value of `scc_b` are nameable /// in `scc_a`. Used during constraint propagation, and only once /// the value of `scc_b` has been computed. - fn universe_compatible(&self, scc_b: ConstraintSccIndex, scc_a: ConstraintSccIndex) -> bool { - self.scc_annotations[scc_a].universe_compatible_with(self.scc_annotations[scc_b]) + fn can_name_all_placeholders( + &self, + scc_a: ConstraintSccIndex, + scc_b: ConstraintSccIndex, + ) -> bool { + self.scc_annotations[scc_a].can_name_all_placeholders(self.scc_annotations[scc_b]) } /// Once regions have been propagated, this method is used to see @@ -964,16 +968,22 @@ impl<'tcx> RegionInferenceContext<'tcx> { return true; } + let fr_static = self.universal_regions().fr_static; + // If we are checking that `'sup: 'sub`, and `'sub` contains // some placeholder that `'sup` cannot name, then this is only // true if `'sup` outlives static. - if !self.universe_compatible(sub_region_scc, sup_region_scc) { + // + // Avoid infinite recursion if `sub_region` is already `'static` + if sub_region != fr_static + && !self.can_name_all_placeholders(sup_region_scc, sub_region_scc) + { debug!( "sub universe `{sub_region_scc:?}` is not nameable \ by super `{sup_region_scc:?}`, promoting to static", ); - return self.eval_outlives(sup_region, self.universal_regions().fr_static); + return self.eval_outlives(sup_region, fr_static); } // Both the `sub_region` and `sup_region` consist of the union diff --git a/compiler/rustc_borrowck/src/type_check/canonical.rs b/compiler/rustc_borrowck/src/type_check/canonical.rs index 2627ed899a9..aece0bda346 100644 --- a/compiler/rustc_borrowck/src/type_check/canonical.rs +++ b/compiler/rustc_borrowck/src/type_check/canonical.rs @@ -230,8 +230,14 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { location: impl NormalizeLocation, ) -> Ty<'tcx> { let tcx = self.tcx(); + let body = self.body; + + let cause = ObligationCause::misc( + location.to_locations().span(body), + body.source.def_id().expect_local(), + ); + if self.infcx.next_trait_solver() { - let body = self.body; let param_env = self.infcx.param_env; // FIXME: Make this into a real type op? self.fully_perform_op( @@ -241,10 +247,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { |ocx| { let structurally_normalize = |ty| { ocx.structurally_normalize_ty( - &ObligationCause::misc( - location.to_locations().span(body), - body.source.def_id().expect_local(), - ), + &cause, param_env, ty, ) @@ -253,6 +256,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { let tail = tcx.struct_tail_raw( ty, + &cause, structurally_normalize, || {}, ); @@ -265,7 +269,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { .unwrap_or_else(|guar| Ty::new_error(tcx, guar)) } else { let mut normalize = |ty| self.normalize(ty, location); - let tail = tcx.struct_tail_raw(ty, &mut normalize, || {}); + let tail = tcx.struct_tail_raw(ty, &cause, &mut normalize, || {}); normalize(tail) } } |
