diff options
| author | Santiago Pastorino <spastorino@gmail.com> | 2022-01-21 12:22:13 -0300 |
|---|---|---|
| committer | Santiago Pastorino <spastorino@gmail.com> | 2022-01-21 18:21:04 -0300 |
| commit | c2890ed426aaef4b680848e793a2a741e517a6cc (patch) | |
| tree | e382d647fea9a634fef0149362d4c70124759a01 | |
| parent | b2a45f064514e06908564153014f8860b8b206d2 (diff) | |
| download | rust-c2890ed426aaef4b680848e793a2a741e517a6cc.tar.gz rust-c2890ed426aaef4b680848e793a2a741e517a6cc.zip | |
Add overlap mode
| -rw-r--r-- | compiler/rustc_trait_selection/src/traits/coherence.rs | 36 |
1 files changed, 27 insertions, 9 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index 84b934c19f9..170740d2cbd 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -135,6 +135,25 @@ fn with_fresh_ty_vars<'cx, 'tcx>( 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 /// where-clauses)? If so, returns an `ImplHeader` that unifies the two impls. 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 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) - && tcx.has_attr(impl2_def_id, sym::rustc_strict_coherence); - - if stable_disjoint(selcx, param_env, &impl1_header, impl2_header, strict_coherence) { + let overlap_mode = overlap_mode(tcx, impl1_def_id, impl2_def_id); + if stable_disjoint(selcx, param_env, &impl1_header, impl2_header, overlap_mode) { return None; } @@ -200,7 +217,7 @@ fn stable_disjoint<'cx, 'tcx>( param_env: ty::ParamEnv<'tcx>, impl1_header: &ty::ImplHeader<'tcx>, impl2_header: ty::ImplHeader<'tcx>, - strict_coherence: bool, + overlap_mode: OverlapMode, ) -> bool { debug!("overlap: impl1_header={:?}", impl1_header); debug!("overlap: impl2_header={:?}", impl2_header); @@ -258,10 +275,11 @@ fn stable_disjoint<'cx, 'tcx>( .find(|o| { // 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. - if strict_coherence { - strict_check(selcx, o) - } else { - loose_check(selcx, o) || tcx.features().negative_impls && strict_check(selcx, o) + match overlap_mode { + OverlapMode::Stable => { + 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 |
