dir: RelationDir)
-> RelateResult<'tcx, Generalization<'tcx>>
{
+ debug!("generalize(ty={:?}, for_vid={:?}, dir={:?}", ty, for_vid, dir);
// Determine the ambient variance within which `ty` appears.
// The surrounding equation is:
//
root_ty: ty,
};
- let ty = generalize.relate(&ty, &ty)?;
+ let ty = match generalize.relate(&ty, &ty) {
+ Ok(ty) => ty,
+ Err(e) => {
+ debug!("generalize: failure {:?}", e);
+ return Err(e);
+ }
+ };
let needs_wf = generalize.needs_wf;
+ debug!("generalize: success {{ {:?}, {:?} }}", ty, needs_wf);
Ok(Generalization { ty, needs_wf })
}
}
let infcx = self.fields.infcx;
let a = infcx.type_variables.borrow_mut().replace_if_possible(a);
let b = infcx.type_variables.borrow_mut().replace_if_possible(b);
+
+ debug!("{}.tys: replacements ({:?}, {:?})", self.tag(), a, b);
+
match (&a.sty, &b.sty) {
(&ty::Infer(TyVar(a_id)), &ty::Infer(TyVar(b_id))) => {
infcx.type_variables.borrow_mut().equate(a_id, b_id);
.map(|v| v.get(tcx))
}
+ /// Determines whether can we safely cache the result
+ /// of selecting an obligation. This is almost always 'true',
+ /// except when dealing with certain ParamCandidates.
+ ///
+ /// Ordinarily, a ParamCandidate will contain no inference variables,
+ /// since it was usually produced directly from a DefId. However,
+ /// certain cases (currently only librustdoc's blanket impl finder),
+ /// a ParamEnv may be explicitly constructed with inference types.
+ /// When this is the case, we do *not* want to cache the resulting selection
+ /// candidate. This is due to the fact that it might not always be possible
+ /// to equate the obligation's trait ref and the candidate's trait ref,
+ /// if more constraints end up getting added to an inference variable.
+ ///
+ /// Because of this, we always want to re-run the full selection
+ /// process for our obligation the next time we see it, since
+ /// we might end up picking a different SelectionCandidate (or none at all)
+ fn can_cache_candidate(&self,
+ result: &SelectionResult<'tcx, SelectionCandidate<'tcx>>
+ ) -> bool {
+ match result {
+ Ok(Some(SelectionCandidate::ParamCandidate(trait_ref))) => {
+ !trait_ref.skip_binder().input_types().any(|t| t.walk().any(|t_| t_.is_ty_infer()))
+ },
+ _ => true
+ }
+ }
+
fn insert_candidate_cache(
&mut self,
param_env: ty::ParamEnv<'tcx>,
) {
let tcx = self.tcx();
let trait_ref = cache_fresh_trait_pred.skip_binder().trait_ref;
+
+ if !self.can_cache_candidate(&candidate) {
+ debug!("insert_candidate_cache(trait_ref={:?}, candidate={:?} -\
+ candidate is not cacheable", trait_ref, candidate);
+ return;
+
+ }
+
if self.can_use_global_caches(param_env) {
if let Err(Overflow) = candidate {
// Don't cache overflow globally; we only produce this
name: Option<String>,
) -> Vec<Item>
where F: Fn(DefId) -> Def {
+ debug!("get_blanket_impls(def_id={:?}, ...)", def_id);
let mut impls = Vec::new();
if self.cx
.tcx
}
self.cx.tcx.for_each_relevant_impl(trait_def_id, ty, |impl_def_id| {
self.cx.tcx.infer_ctxt().enter(|infcx| {
+ debug!("get_blanet_impls: Considering impl for trait '{:?}' {:?}",
+ trait_def_id, impl_def_id);
let t_generics = infcx.tcx.generics_of(impl_def_id);
let trait_ref = infcx.tcx.impl_trait_ref(impl_def_id)
.expect("Cannot get impl trait");
drop(obligations);
debug!(
- "invoking predicate_may_hold: {:?}",
- trait_ref,
+ "invoking predicate_may_hold: param_env={:?}, trait_ref={:?}, ty={:?}",
+ param_env, trait_ref, ty
);
let may_apply = match infcx.evaluate_obligation(
&traits::Obligation::new(
Ok(eval_result) => eval_result.may_apply(),
Err(traits::OverflowError) => true, // overflow doesn't mean yes *or* no
};
+ debug!("get_blanket_impls: found applicable impl: {}\
+ for trait_ref={:?}, ty={:?}",
+ may_apply, trait_ref, ty);
+
if !may_apply {
return
}
--- /dev/null
+// Regression test for issue #55001. Previously, we would incorrectly
+// cache certain trait selection results when checking for blanket impls,
+// resulting in an ICE when we tried to confirm the cached ParamCandidate
+// against an obligation.
+
+pub struct DefaultAllocator;
+pub struct Standard;
+pub struct Inner;
+
+pub trait Rand {}
+
+pub trait Distribution<T> {}
+pub trait Allocator<N> {}
+
+impl<T> Rand for T where Standard: Distribution<T> {}
+
+impl<A> Distribution<Point<A>> for Standard
+where
+DefaultAllocator: Allocator<A>,
+Standard: Distribution<A> {}
+
+impl Distribution<Inner> for Standard {}
+
+
+pub struct Point<N>
+where DefaultAllocator: Allocator<N>
+{
+ field: N
+}
+
+fn main() {}