Skip to content

Commit c2890ed

Browse files
committed
Add overlap mode
1 parent b2a45f0 commit c2890ed

File tree

1 file changed

+27
-9
lines changed

1 file changed

+27
-9
lines changed

compiler/rustc_trait_selection/src/traits/coherence.rs

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,25 @@ fn with_fresh_ty_vars<'cx, 'tcx>(
135135
header
136136
}
137137

138+
enum OverlapMode {
139+
Stable,
140+
Strict,
141+
}
142+
143+
fn overlap_mode<'tcx>(tcx: TyCtxt<'tcx>, impl1_def_id: DefId, impl2_def_id: DefId) -> OverlapMode {
144+
if tcx.has_attr(impl1_def_id, sym::rustc_strict_coherence)
145+
!= tcx.has_attr(impl2_def_id, sym::rustc_strict_coherence)
146+
{
147+
bug!("Use strict coherence on both impls",);
148+
}
149+
150+
if tcx.has_attr(impl1_def_id, sym::rustc_strict_coherence) {
151+
OverlapMode::Strict
152+
} else {
153+
OverlapMode::Stable
154+
}
155+
}
156+
138157
/// Can both impl `a` and impl `b` be satisfied by a common type (including
139158
/// where-clauses)? If so, returns an `ImplHeader` that unifies the two impls.
140159
fn overlap<'cx, 'tcx>(
@@ -169,10 +188,8 @@ fn overlap_within_probe<'cx, 'tcx>(
169188
let impl1_header = with_fresh_ty_vars(selcx, param_env, impl1_def_id);
170189
let impl2_header = with_fresh_ty_vars(selcx, param_env, impl2_def_id);
171190

172-
let strict_coherence = tcx.has_attr(impl1_def_id, sym::rustc_strict_coherence)
173-
&& tcx.has_attr(impl2_def_id, sym::rustc_strict_coherence);
174-
175-
if stable_disjoint(selcx, param_env, &impl1_header, impl2_header, strict_coherence) {
191+
let overlap_mode = overlap_mode(tcx, impl1_def_id, impl2_def_id);
192+
if stable_disjoint(selcx, param_env, &impl1_header, impl2_header, overlap_mode) {
176193
return None;
177194
}
178195

@@ -200,7 +217,7 @@ fn stable_disjoint<'cx, 'tcx>(
200217
param_env: ty::ParamEnv<'tcx>,
201218
impl1_header: &ty::ImplHeader<'tcx>,
202219
impl2_header: ty::ImplHeader<'tcx>,
203-
strict_coherence: bool,
220+
overlap_mode: OverlapMode,
204221
) -> bool {
205222
debug!("overlap: impl1_header={:?}", impl1_header);
206223
debug!("overlap: impl2_header={:?}", impl2_header);
@@ -258,10 +275,11 @@ fn stable_disjoint<'cx, 'tcx>(
258275
.find(|o| {
259276
// if both impl headers are set to strict coherence it means that this will be accepted
260277
// only if it's stated that T: !Trait. So only prove that the negated obligation holds.
261-
if strict_coherence {
262-
strict_check(selcx, o)
263-
} else {
264-
loose_check(selcx, o) || tcx.features().negative_impls && strict_check(selcx, o)
278+
match overlap_mode {
279+
OverlapMode::Stable => {
280+
loose_check(selcx, o) || tcx.features().negative_impls && strict_check(selcx, o)
281+
}
282+
OverlapMode::Strict => strict_check(selcx, o),
265283
}
266284
});
267285
// FIXME: the call to `selcx.predicate_may_hold_fatal` above should be ported

0 commit comments

Comments
 (0)