Fix Rustdoc ICE when checking blanket impls
Fixes #55001, #54744 Previously, SelectionContext would unconditionally cache the selection result for an obligation. This worked fine for most users of SelectionContext, but it caused an issue when used by Rustdoc's blanket impl finder. The issue occured when SelectionContext chose a ParamCandidate which contained inference variables. Since inference variables can change between calls to select(), it's not safe to cache the selection result - the chosen candidate might not be applicable for future results, leading to an ICE when we try to run confirmation. This commit prevents SelectionContext from caching any ParamCandidate that contains inference variables. This should always be completely safe, as trait selection should never depend on a particular result being cached. I've also added some extra debug!() statements, which I found helpful in tracking down this bug.
This commit is contained in:
parent
ca2639e82e
commit
4f2624cac9
5 changed files with 87 additions and 3 deletions
|
@ -50,6 +50,7 @@ impl<'a, 'tcx, 'rcx, 'cstore> BlanketImplFinder <'a, 'tcx, 'rcx, 'cstore> {
|
|||
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
|
||||
|
@ -78,6 +79,8 @@ impl<'a, 'tcx, 'rcx, 'cstore> BlanketImplFinder <'a, 'tcx, 'rcx, 'cstore> {
|
|||
}
|
||||
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");
|
||||
|
@ -104,8 +107,8 @@ impl<'a, 'tcx, 'rcx, 'cstore> BlanketImplFinder <'a, 'tcx, 'rcx, 'cstore> {
|
|||
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(
|
||||
|
@ -117,6 +120,10 @@ impl<'a, 'tcx, 'rcx, 'cstore> BlanketImplFinder <'a, 'tcx, 'rcx, 'cstore> {
|
|||
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
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue