Skip to content

Commit ffd21b1

Browse files
committed
add in a "paranoid" trait bound
1 parent 80447c3 commit ffd21b1

File tree

1 file changed

+34
-0
lines changed

1 file changed

+34
-0
lines changed

src/librustc/traits/project.rs

+34
Original file line numberDiff line numberDiff line change
@@ -488,6 +488,13 @@ fn opt_normalize_projection_type<'a, 'b, 'gcx, 'tcx>(
488488
ty.obligations = vec![];
489489
}
490490

491+
push_paranoid_cache_value_obligation(infcx,
492+
param_env,
493+
projection_ty,
494+
cause,
495+
depth,
496+
&mut ty);
497+
491498
return Some(ty);
492499
}
493500
Err(ProjectionCacheEntry::Error) => {
@@ -612,6 +619,33 @@ fn prune_cache_value_obligations<'a, 'gcx, 'tcx>(infcx: &'a InferCtxt<'a, 'gcx,
612619
NormalizedTy { value: result.value, obligations }
613620
}
614621

622+
/// Whenever we give back a cache result for a projection like `<T as
623+
/// Trait>::Item ==> X`, we *always* include the obligation to prove
624+
/// that `T: Trait` (we may also include some other obligations). This
625+
/// may or may not be necessary -- in principle, all the obligations
626+
/// that must be proven to show that `T: Trait` were also returned
627+
/// when the cache was first populated. But there is a vague concern
628+
/// that perhaps someone would not have proven those, but also not
629+
/// have used a snapshot, in which case the cache could remain
630+
/// populated even though `T: Trait` has not been shown. Returning
631+
/// this "paranoid" obligation ensures that, no matter what has come
632+
/// before, if you prove the subobligations, we at least know that `T:
633+
/// Trait` is implemented.
634+
fn push_paranoid_cache_value_obligation<'a, 'gcx, 'tcx>(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
635+
param_env: ty::ParamEnv<'tcx>,
636+
projection_ty: ty::ProjectionTy<'tcx>,
637+
cause: ObligationCause<'tcx>,
638+
depth: usize,
639+
result: &mut NormalizedTy<'tcx>)
640+
{
641+
let trait_ref = projection_ty.trait_ref(infcx.tcx).to_poly_trait_ref();
642+
let trait_obligation = Obligation { cause,
643+
recursion_depth: depth,
644+
param_env,
645+
predicate: trait_ref.to_predicate() };
646+
result.obligations.push(trait_obligation);
647+
}
648+
615649
/// If we are projecting `<T as Trait>::Item`, but `T: Trait` does not
616650
/// hold. In various error cases, we cannot generate a valid
617651
/// normalized projection. Therefore, we create an inference variable

0 commit comments

Comments
 (0)