-
-
Save nikomatsakis/389081d10444601bca9d8b33883b087f to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs | |
index 512cfee12b..dcb9507fc0 100644 | |
--- a/src/librustc/traits/project.rs | |
+++ b/src/librustc/traits/project.rs | |
@@ -416,7 +416,8 @@ fn opt_normalize_projection_type<'a, 'b, 'gcx, 'tcx>( | |
// bounds. It might be the case that we want two distinct caches, | |
// or else another kind of cache entry. | |
- match infcx.projection_cache.borrow_mut().try_start(cache_key) { | |
+ let cache_result = infcx.projection_cache.borrow_mut().try_start(cache_key); | |
+ match cache_result { | |
Ok(()) => { } | |
Err(ProjectionCacheEntry::Ambiguous) => { | |
// If we found ambiguity the last time, that generally | |
@@ -466,7 +467,7 @@ fn opt_normalize_projection_type<'a, 'b, 'gcx, 'tcx>( | |
projection_ty); | |
selcx.infcx().report_overflow_error(&obligation, false); | |
} | |
- Err(ProjectionCacheEntry::NormalizedTy(ty)) => { | |
+ Err(ProjectionCacheEntry::NormalizedTy(mut ty)) => { | |
// If we find the value in the cache, then return it along | |
// with the obligations that went along with it. Note | |
// that, when using a fulfillment context, these | |
@@ -479,6 +480,15 @@ fn opt_normalize_projection_type<'a, 'b, 'gcx, 'tcx>( | |
debug!("opt_normalize_projection_type: \ | |
found normalized ty `{:?}`", | |
ty); | |
+ ty.value = infcx.resolve_type_vars_if_possible(&ty.value); | |
+ | |
+ // Once we have inferred everything we need to know, we | |
+ // can ignore the `obligations` from that point on. | |
+ if !ty.value.has_infer_types() { | |
+ infcx.projection_cache.borrow_mut().complete(cache_key); | |
+ ty.obligations = vec![]; | |
+ } | |
+ | |
return Some(ty); | |
} | |
Err(ProjectionCacheEntry::Error) => { | |
@@ -504,7 +514,7 @@ fn opt_normalize_projection_type<'a, 'b, 'gcx, 'tcx>( | |
depth, | |
obligations); | |
- let result = if projected_ty.has_projection_types() { | |
+ let mut result = if projected_ty.has_projection_types() { | |
let mut normalizer = AssociatedTypeNormalizer::new(selcx, | |
param_env, | |
cause, | |
@@ -527,7 +537,27 @@ fn opt_normalize_projection_type<'a, 'b, 'gcx, 'tcx>( | |
obligations, | |
} | |
}; | |
- infcx.projection_cache.borrow_mut().insert_ty(cache_key, &result); | |
+ result.value = infcx.resolve_type_vars_if_possible(&result.value); | |
+ | |
+ if !result.value.has_infer_types() { | |
+ // If there are no unresolved type variables in the | |
+ // output, then there is no need to cache the | |
+ // subobligations (though we do return them here, so | |
+ // that they can be registered and verified). In | |
+ // particular, the only thing that can happen with | |
+ // those subobligations is that one of them will fail | |
+ // to be verified, yielding a compilation error. | |
+ infcx.projection_cache.borrow_mut().insert_ty(cache_key, &Normalized { | |
+ value: result.value, | |
+ obligations: vec![] | |
+ }); | |
+ } else { | |
+ // If there *are* unresolved type variables, then we | |
+ // need the subobligations, at least until those type | |
+ // variables are fully resolved. | |
+ infcx.projection_cache.borrow_mut().insert_ty(cache_key, &result); | |
+ } | |
+ | |
Some(result) | |
} | |
Ok(ProjectedTy::NoProgress(projected_ty)) => { |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment