Skip to content

Commit 02a49f8

Browse files
committed
add in a "paranoid" trait bound
1 parent 596c9a7 commit 02a49f8

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
@@ -487,6 +487,13 @@ fn opt_normalize_projection_type<'a, 'b, 'gcx, 'tcx>(
487487
ty.obligations = vec![];
488488
}
489489

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

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

0 commit comments

Comments
 (0)