Add overlap mode

This commit is contained in:
Santiago Pastorino 2022-01-21 12:22:13 -03:00
parent b2a45f0645
commit c2890ed426
No known key found for this signature in database
GPG key ID: 8131A24E0C79EFAF

View file

@ -135,6 +135,25 @@ fn with_fresh_ty_vars<'cx, 'tcx>(
header header
} }
enum OverlapMode {
Stable,
Strict,
}
fn overlap_mode<'tcx>(tcx: TyCtxt<'tcx>, impl1_def_id: DefId, impl2_def_id: DefId) -> OverlapMode {
if tcx.has_attr(impl1_def_id, sym::rustc_strict_coherence)
!= tcx.has_attr(impl2_def_id, sym::rustc_strict_coherence)
{
bug!("Use strict coherence on both impls",);
}
if tcx.has_attr(impl1_def_id, sym::rustc_strict_coherence) {
OverlapMode::Strict
} else {
OverlapMode::Stable
}
}
/// Can both impl `a` and impl `b` be satisfied by a common type (including /// Can both impl `a` and impl `b` be satisfied by a common type (including
/// where-clauses)? If so, returns an `ImplHeader` that unifies the two impls. /// where-clauses)? If so, returns an `ImplHeader` that unifies the two impls.
fn overlap<'cx, 'tcx>( fn overlap<'cx, 'tcx>(
@ -169,10 +188,8 @@ fn overlap_within_probe<'cx, 'tcx>(
let impl1_header = with_fresh_ty_vars(selcx, param_env, impl1_def_id); let impl1_header = with_fresh_ty_vars(selcx, param_env, impl1_def_id);
let impl2_header = with_fresh_ty_vars(selcx, param_env, impl2_def_id); let impl2_header = with_fresh_ty_vars(selcx, param_env, impl2_def_id);
let strict_coherence = tcx.has_attr(impl1_def_id, sym::rustc_strict_coherence) let overlap_mode = overlap_mode(tcx, impl1_def_id, impl2_def_id);
&& tcx.has_attr(impl2_def_id, sym::rustc_strict_coherence); if stable_disjoint(selcx, param_env, &impl1_header, impl2_header, overlap_mode) {
if stable_disjoint(selcx, param_env, &impl1_header, impl2_header, strict_coherence) {
return None; return None;
} }
@ -200,7 +217,7 @@ fn stable_disjoint<'cx, 'tcx>(
param_env: ty::ParamEnv<'tcx>, param_env: ty::ParamEnv<'tcx>,
impl1_header: &ty::ImplHeader<'tcx>, impl1_header: &ty::ImplHeader<'tcx>,
impl2_header: ty::ImplHeader<'tcx>, impl2_header: ty::ImplHeader<'tcx>,
strict_coherence: bool, overlap_mode: OverlapMode,
) -> bool { ) -> bool {
debug!("overlap: impl1_header={:?}", impl1_header); debug!("overlap: impl1_header={:?}", impl1_header);
debug!("overlap: impl2_header={:?}", impl2_header); debug!("overlap: impl2_header={:?}", impl2_header);
@ -258,10 +275,11 @@ fn stable_disjoint<'cx, 'tcx>(
.find(|o| { .find(|o| {
// if both impl headers are set to strict coherence it means that this will be accepted // if both impl headers are set to strict coherence it means that this will be accepted
// only if it's stated that T: !Trait. So only prove that the negated obligation holds. // only if it's stated that T: !Trait. So only prove that the negated obligation holds.
if strict_coherence { match overlap_mode {
strict_check(selcx, o) OverlapMode::Stable => {
} else { loose_check(selcx, o) || tcx.features().negative_impls && strict_check(selcx, o)
loose_check(selcx, o) || tcx.features().negative_impls && strict_check(selcx, o) }
OverlapMode::Strict => strict_check(selcx, o),
} }
}); });
// FIXME: the call to `selcx.predicate_may_hold_fatal` above should be ported // FIXME: the call to `selcx.predicate_may_hold_fatal` above should be ported