review
This commit is contained in:
parent
8167a25e4e
commit
614760f612
@ -214,76 +214,69 @@ fn overlap<'tcx>(
|
|||||||
let mut obligations = equate_impl_headers(selcx.infcx, &impl1_header, &impl2_header)?;
|
let mut obligations = equate_impl_headers(selcx.infcx, &impl1_header, &impl2_header)?;
|
||||||
debug!("overlap: unification check succeeded");
|
debug!("overlap: unification check succeeded");
|
||||||
|
|
||||||
if !overlap_mode.use_implicit_negative() {
|
|
||||||
let impl_header = selcx.infcx.resolve_vars_if_possible(impl1_header);
|
|
||||||
return Some(OverlapResult {
|
|
||||||
impl_header,
|
|
||||||
intercrate_ambiguity_causes: Default::default(),
|
|
||||||
involves_placeholder: false,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
obligations.extend(
|
obligations.extend(
|
||||||
[&impl1_header.predicates, &impl2_header.predicates].into_iter().flatten().map(
|
[&impl1_header.predicates, &impl2_header.predicates].into_iter().flatten().map(
|
||||||
|&predicate| Obligation::new(infcx.tcx, ObligationCause::dummy(), param_env, predicate),
|
|&predicate| Obligation::new(infcx.tcx, ObligationCause::dummy(), param_env, predicate),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
for mode in [TreatInductiveCycleAs::Ambig, TreatInductiveCycleAs::Recur] {
|
if overlap_mode.use_implicit_negative() {
|
||||||
if let Some(failing_obligation) = selcx.with_treat_inductive_cycle_as(mode, |selcx| {
|
for mode in [TreatInductiveCycleAs::Ambig, TreatInductiveCycleAs::Recur] {
|
||||||
impl_intersection_has_impossible_obligation(selcx, &obligations)
|
if let Some(failing_obligation) = selcx.with_treat_inductive_cycle_as(mode, |selcx| {
|
||||||
}) {
|
impl_intersection_has_impossible_obligation(selcx, &obligations)
|
||||||
if matches!(mode, TreatInductiveCycleAs::Recur) {
|
}) {
|
||||||
let first_local_impl = impl1_header
|
if matches!(mode, TreatInductiveCycleAs::Recur) {
|
||||||
.impl_def_id
|
let first_local_impl = impl1_header
|
||||||
.as_local()
|
.impl_def_id
|
||||||
.or(impl2_header.impl_def_id.as_local())
|
.as_local()
|
||||||
.expect("expected one of the impls to be local");
|
.or(impl2_header.impl_def_id.as_local())
|
||||||
infcx.tcx.struct_span_lint_hir(
|
.expect("expected one of the impls to be local");
|
||||||
COINDUCTIVE_OVERLAP_IN_COHERENCE,
|
infcx.tcx.struct_span_lint_hir(
|
||||||
infcx.tcx.local_def_id_to_hir_id(first_local_impl),
|
COINDUCTIVE_OVERLAP_IN_COHERENCE,
|
||||||
infcx.tcx.def_span(first_local_impl),
|
infcx.tcx.local_def_id_to_hir_id(first_local_impl),
|
||||||
format!(
|
infcx.tcx.def_span(first_local_impl),
|
||||||
"implementations {} will conflict in the future",
|
format!(
|
||||||
match impl1_header.trait_ref {
|
"implementations {} will conflict in the future",
|
||||||
Some(trait_ref) => {
|
match impl1_header.trait_ref {
|
||||||
let trait_ref = infcx.resolve_vars_if_possible(trait_ref);
|
Some(trait_ref) => {
|
||||||
format!(
|
let trait_ref = infcx.resolve_vars_if_possible(trait_ref);
|
||||||
"of `{}` for `{}`",
|
format!(
|
||||||
trait_ref.print_only_trait_path(),
|
"of `{}` for `{}`",
|
||||||
trait_ref.self_ty()
|
trait_ref.print_only_trait_path(),
|
||||||
)
|
trait_ref.self_ty()
|
||||||
}
|
)
|
||||||
None => format!(
|
}
|
||||||
"for `{}`",
|
None => format!(
|
||||||
infcx.resolve_vars_if_possible(impl1_header.self_ty)
|
"for `{}`",
|
||||||
),
|
infcx.resolve_vars_if_possible(impl1_header.self_ty)
|
||||||
|
),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
|lint| {
|
||||||
|
lint.note(
|
||||||
|
"impls that are not considered to overlap may be considered to \
|
||||||
|
overlap in the future",
|
||||||
|
)
|
||||||
|
.span_label(
|
||||||
|
infcx.tcx.def_span(impl1_header.impl_def_id),
|
||||||
|
"the first impl is here",
|
||||||
|
)
|
||||||
|
.span_label(
|
||||||
|
infcx.tcx.def_span(impl2_header.impl_def_id),
|
||||||
|
"the second impl is here",
|
||||||
|
);
|
||||||
|
lint.note(format!(
|
||||||
|
"`{}` may be considered to hold in future releases, \
|
||||||
|
causing the impls to overlap",
|
||||||
|
infcx.resolve_vars_if_possible(failing_obligation.predicate)
|
||||||
|
));
|
||||||
|
lint
|
||||||
},
|
},
|
||||||
),
|
);
|
||||||
|lint| {
|
}
|
||||||
lint.note(
|
|
||||||
"impls that are not considered to overlap may be considered to \
|
|
||||||
overlap in the future",
|
|
||||||
)
|
|
||||||
.span_label(
|
|
||||||
infcx.tcx.def_span(impl1_header.impl_def_id),
|
|
||||||
"the first impl is here",
|
|
||||||
)
|
|
||||||
.span_label(
|
|
||||||
infcx.tcx.def_span(impl2_header.impl_def_id),
|
|
||||||
"the second impl is here",
|
|
||||||
);
|
|
||||||
lint.note(format!(
|
|
||||||
"`{}` may be considered to hold in future releases, \
|
|
||||||
causing the impls to overlap",
|
|
||||||
infcx.resolve_vars_if_possible(failing_obligation.predicate)
|
|
||||||
));
|
|
||||||
lint
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return None;
|
return None;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -294,7 +287,9 @@ fn overlap<'tcx>(
|
|||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
let intercrate_ambiguity_causes = if infcx.next_trait_solver() {
|
let intercrate_ambiguity_causes = if !overlap_mode.use_implicit_negative() {
|
||||||
|
Default::default()
|
||||||
|
} else if infcx.next_trait_solver() {
|
||||||
compute_intercrate_ambiguity_causes(&infcx, &obligations)
|
compute_intercrate_ambiguity_causes(&infcx, &obligations)
|
||||||
} else {
|
} else {
|
||||||
selcx.take_intercrate_ambiguity_causes()
|
selcx.take_intercrate_ambiguity_causes()
|
||||||
@ -932,6 +927,8 @@ fn visit_goal(&mut self, goal: &InspectGoal<'_, 'tcx>) -> ControlFlow<Self::Brea
|
|||||||
|
|
||||||
let Goal { param_env, predicate } = goal.goal();
|
let Goal { param_env, predicate } = goal.goal();
|
||||||
|
|
||||||
|
// For bound predicates we simply call `infcx.replace_bound_vars_with_placeholders`
|
||||||
|
// and then prove the resulting predicate as a nested goal.
|
||||||
let trait_ref = match predicate.kind().no_bound_vars() {
|
let trait_ref = match predicate.kind().no_bound_vars() {
|
||||||
Some(ty::PredicateKind::Clause(ty::ClauseKind::Trait(tr))) => tr.trait_ref,
|
Some(ty::PredicateKind::Clause(ty::ClauseKind::Trait(tr))) => tr.trait_ref,
|
||||||
Some(ty::PredicateKind::Clause(ty::ClauseKind::Projection(proj))) => {
|
Some(ty::PredicateKind::Clause(ty::ClauseKind::Projection(proj))) => {
|
||||||
@ -942,21 +939,6 @@ fn visit_goal(&mut self, goal: &InspectGoal<'_, 'tcx>) -> ControlFlow<Self::Brea
|
|||||||
|
|
||||||
let mut ambiguity_cause = None;
|
let mut ambiguity_cause = None;
|
||||||
for cand in goal.candidates() {
|
for cand in goal.candidates() {
|
||||||
match cand.result() {
|
|
||||||
Ok(Certainty::Maybe(_)) => {}
|
|
||||||
// We only add intercrate ambiguity causes if the goal would
|
|
||||||
// otherwise result in an error.
|
|
||||||
//
|
|
||||||
// FIXME: this isn't quite right. Changing a goal from YES with
|
|
||||||
// inference contraints to AMBIGUOUS can also cause a goal to not
|
|
||||||
// fail.
|
|
||||||
Ok(Certainty::Yes) => {
|
|
||||||
ambiguity_cause = None;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
Err(NoSolution) => continue,
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME: boiiii, using string comparisions here sure is scuffed.
|
// FIXME: boiiii, using string comparisions here sure is scuffed.
|
||||||
if let inspect::ProbeKind::MiscCandidate { name: "coherence unknowable", result: _ } =
|
if let inspect::ProbeKind::MiscCandidate { name: "coherence unknowable", result: _ } =
|
||||||
cand.kind()
|
cand.kind()
|
||||||
@ -1011,6 +993,21 @@ fn visit_goal(&mut self, goal: &InspectGoal<'_, 'tcx>) -> ControlFlow<Self::Brea
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
} else {
|
||||||
|
match cand.result() {
|
||||||
|
// We only add an ambiguity cause if the goal would otherwise
|
||||||
|
// result in an error.
|
||||||
|
//
|
||||||
|
// FIXME: While this matches the behavior of the
|
||||||
|
// old solver, it is not the only way in which the unknowable
|
||||||
|
// candidates *weaken* coherence, they can also force otherwise
|
||||||
|
// sucessful normalization to be ambiguous.
|
||||||
|
Ok(Certainty::Maybe(_) | Certainty::Yes) => {
|
||||||
|
ambiguity_cause = None;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Err(NoSolution) => continue,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user