about summary refs log tree commit diff
path: root/src/librustc_trait_selection
diff options
context:
space:
mode:
authormatthewjasper <mjjasper1@gmail.com>2020-06-16 18:27:40 +0100
committerMatthew Jasper <mjjasper1@gmail.com>2020-06-17 19:46:15 +0100
commitba2ef58ae6c126ec0b87b307d45fef2da127be22 (patch)
tree1af52c4955daf2ea82f05795619c56fe60c7ef3c /src/librustc_trait_selection
parent435f97cec1f0d7de95a0b80e95f295ab444b2fce (diff)
Unify region variables when projecting associated types
This is required to avoid cycles when evaluating auto trait
predicates.
Diffstat (limited to 'src/librustc_trait_selection')
-rw-r--r--src/librustc_trait_selection/traits/project.rs12
1 files changed, 11 insertions, 1 deletions
diff --git a/src/librustc_trait_selection/traits/project.rs b/src/librustc_trait_selection/traits/project.rs
index 9492c3c3409..bccd903f57e 100644
--- a/src/librustc_trait_selection/traits/project.rs
+++ b/src/librustc_trait_selection/traits/project.rs
@@ -24,6 +24,7 @@ use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_errors::ErrorReported;
 use rustc_hir::def_id::DefId;
 use rustc_hir::lang_items::{FnOnceTraitLangItem, GeneratorTraitLangItem};
+use rustc_infer::infer::resolve::OpportunisticRegionResolver;
 use rustc_middle::ty::fold::{TypeFoldable, TypeFolder};
 use rustc_middle::ty::subst::Subst;
 use rustc_middle::ty::util::IntTypeExt;
@@ -1146,7 +1147,7 @@ fn confirm_candidate<'cx, 'tcx>(
 ) -> Progress<'tcx> {
     debug!("confirm_candidate(candidate={:?}, obligation={:?})", candidate, obligation);
 
-    match candidate {
+    let mut progress = match candidate {
         ProjectionTyCandidate::ParamEnv(poly_projection)
         | ProjectionTyCandidate::TraitDef(poly_projection) => {
             confirm_param_env_candidate(selcx, obligation, poly_projection)
@@ -1155,7 +1156,16 @@ fn confirm_candidate<'cx, 'tcx>(
         ProjectionTyCandidate::Select(impl_source) => {
             confirm_select_candidate(selcx, obligation, obligation_trait_ref, impl_source)
         }
+    };
+    // When checking for cycle during evaluation, we compare predicates with
+    // "syntactic" equality. Since normalization generally introduces a type
+    // with new region variables, we need to resolve them to existing variables
+    // when possible for this to work. See `auto-trait-projection-recursion.rs`
+    // for a case where this matters.
+    if progress.ty.has_infer_regions() {
+        progress.ty = OpportunisticRegionResolver::new(selcx.infcx()).fold_ty(progress.ty);
     }
+    progress
 }
 
 fn confirm_select_candidate<'cx, 'tcx>(