Skip to content

Commit

Permalink
add in a "paranoid" trait bound
Browse files Browse the repository at this point in the history
  • Loading branch information
nikomatsakis committed Sep 6, 2017
1 parent 80447c3 commit ffd21b1
Showing 1 changed file with 34 additions and 0 deletions.
34 changes: 34 additions & 0 deletions src/librustc/traits/project.rs
Original file line number Diff line number Diff line change
Expand Up @@ -488,6 +488,13 @@ fn opt_normalize_projection_type<'a, 'b, 'gcx, 'tcx>(
ty.obligations = vec![];
}

push_paranoid_cache_value_obligation(infcx,
param_env,
projection_ty,
cause,
depth,
&mut ty);

return Some(ty);
}
Err(ProjectionCacheEntry::Error) => {
Expand Down Expand Up @@ -612,6 +619,33 @@ fn prune_cache_value_obligations<'a, 'gcx, 'tcx>(infcx: &'a InferCtxt<'a, 'gcx,
NormalizedTy { value: result.value, obligations }
}

/// Whenever we give back a cache result for a projection like `<T as
/// Trait>::Item ==> X`, we *always* include the obligation to prove
/// that `T: Trait` (we may also include some other obligations). This
/// may or may not be necessary -- in principle, all the obligations
/// that must be proven to show that `T: Trait` were also returned
/// when the cache was first populated. But there is a vague concern
/// that perhaps someone would not have proven those, but also not
/// have used a snapshot, in which case the cache could remain
/// populated even though `T: Trait` has not been shown. Returning
/// this "paranoid" obligation ensures that, no matter what has come
/// before, if you prove the subobligations, we at least know that `T:
/// Trait` is implemented.
fn push_paranoid_cache_value_obligation<'a, 'gcx, 'tcx>(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
param_env: ty::ParamEnv<'tcx>,
projection_ty: ty::ProjectionTy<'tcx>,
cause: ObligationCause<'tcx>,
depth: usize,
result: &mut NormalizedTy<'tcx>)
{
let trait_ref = projection_ty.trait_ref(infcx.tcx).to_poly_trait_ref();
let trait_obligation = Obligation { cause,
recursion_depth: depth,
param_env,
predicate: trait_ref.to_predicate() };
result.obligations.push(trait_obligation);
}

/// If we are projecting `<T as Trait>::Item`, but `T: Trait` does not
/// hold. In various error cases, we cannot generate a valid
/// normalized projection. Therefore, we create an inference variable
Expand Down

0 comments on commit ffd21b1

Please sign in to comment.