1
Fork 0

Filter out Negative impls on intercrate mode's ambiguous reasoning

This commit is contained in:
Santiago Pastorino 2021-10-15 16:09:04 -03:00
parent 85c8fd9c94
commit 89a419cf7d
No known key found for this signature in database
GPG key ID: 8131A24E0C79EFAF

View file

@ -866,34 +866,39 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
// precise still. // precise still.
let unbound_input_types = let unbound_input_types =
stack.fresh_trait_ref.value.skip_binder().substs.types().any(|ty| ty.is_fresh()); stack.fresh_trait_ref.value.skip_binder().substs.types().any(|ty| ty.is_fresh());
// This check was an imperfect workaround for a bug in the old
// intercrate mode; it should be removed when that goes away. if stack.obligation.predicate.skip_binder().polarity != ty::ImplPolarity::Negative {
if unbound_input_types && self.intercrate { // This check was an imperfect workaround for a bug in the old
debug!("evaluate_stack --> unbound argument, intercrate --> ambiguous",); // intercrate mode; it should be removed when that goes away.
// Heuristics: show the diagnostics when there are no candidates in crate. if unbound_input_types && self.intercrate {
if self.intercrate_ambiguity_causes.is_some() { debug!("evaluate_stack --> unbound argument, intercrate --> ambiguous",);
debug!("evaluate_stack: intercrate_ambiguity_causes is some"); // Heuristics: show the diagnostics when there are no candidates in crate.
if let Ok(candidate_set) = self.assemble_candidates(stack) { if self.intercrate_ambiguity_causes.is_some() {
if !candidate_set.ambiguous && candidate_set.vec.is_empty() { debug!("evaluate_stack: intercrate_ambiguity_causes is some");
let trait_ref = stack.obligation.predicate.skip_binder().trait_ref; if let Ok(candidate_set) = self.assemble_candidates(stack) {
let self_ty = trait_ref.self_ty(); if !candidate_set.ambiguous && candidate_set.vec.is_empty() {
let cause = let trait_ref = stack.obligation.predicate.skip_binder().trait_ref;
with_no_trimmed_paths(|| IntercrateAmbiguityCause::DownstreamCrate { let self_ty = trait_ref.self_ty();
trait_desc: trait_ref.print_only_trait_path().to_string(), let cause = with_no_trimmed_paths(|| {
self_desc: if self_ty.has_concrete_skeleton() { IntercrateAmbiguityCause::DownstreamCrate {
Some(self_ty.to_string()) trait_desc: trait_ref.print_only_trait_path().to_string(),
} else { self_desc: if self_ty.has_concrete_skeleton() {
None Some(self_ty.to_string())
}, } else {
None
},
}
}); });
debug!(?cause, "evaluate_stack: pushing cause"); debug!(?cause, "evaluate_stack: pushing cause");
self.intercrate_ambiguity_causes.as_mut().unwrap().push(cause); self.intercrate_ambiguity_causes.as_mut().unwrap().push(cause);
}
} }
} }
return Ok(EvaluatedToAmbig);
} }
return Ok(EvaluatedToAmbig);
} }
if unbound_input_types if unbound_input_types
&& stack.iter().skip(1).any(|prev| { && stack.iter().skip(1).any(|prev| {
stack.obligation.param_env == prev.obligation.param_env stack.obligation.param_env == prev.obligation.param_env
@ -1178,7 +1183,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
fn is_knowable<'o>(&mut self, stack: &TraitObligationStack<'o, 'tcx>) -> Option<Conflict> { fn is_knowable<'o>(&mut self, stack: &TraitObligationStack<'o, 'tcx>) -> Option<Conflict> {
debug!("is_knowable(intercrate={:?})", self.intercrate); debug!("is_knowable(intercrate={:?})", self.intercrate);
if !self.intercrate { if !self.intercrate
|| stack.obligation.predicate.skip_binder().polarity == ty::ImplPolarity::Negative
{
return None; return None;
} }