diff options
| author | Ryan Levick <me@ryanlevick.com> | 2021-02-12 14:04:09 +0100 |
|---|---|---|
| committer | Ryan Levick <me@ryanlevick.com> | 2021-02-12 14:04:09 +0100 |
| commit | 8ea0973725f18ea3d392b7558165c0fecc589eb8 (patch) | |
| tree | 0c66430749921ae0328b3ab57a53025d88cffb89 | |
| parent | cdfc52fbd638ee3b7b1debad0aef84e730543e8a (diff) | |
| download | rust-8ea0973725f18ea3d392b7558165c0fecc589eb8.tar.gz rust-8ea0973725f18ea3d392b7558165c0fecc589eb8.zip | |
Short circuit full corherence check when dealing with types with different reference mutability
| -rw-r--r-- | compiler/rustc_middle/src/ty/sty.rs | 9 | ||||
| -rw-r--r-- | compiler/rustc_trait_selection/src/traits/coherence.rs | 11 |
2 files changed, 15 insertions, 5 deletions
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 6b4f08d9f93..6b67d509da0 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -1837,6 +1837,15 @@ impl<'tcx> TyS<'tcx> { ) } + /// Get the mutability of the reference or `None` when not a reference + #[inline] + pub fn ref_mutability(&self) -> Option<hir::Mutability> { + match self.kind() { + Ref(_, _, mutability) => Some(*mutability), + _ => None, + } + } + #[inline] pub fn is_unsafe_ptr(&self) -> bool { matches!(self.kind(), RawPtr(_)) diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index 87f2ea16f8a..afe86b2a231 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -75,18 +75,19 @@ where let impl1_ref = tcx.impl_trait_ref(impl1_def_id); let impl2_ref = tcx.impl_trait_ref(impl2_def_id); - // Check if any of the input types definitely mismatch. + // Check if any of the input types definitely do not unify. if impl1_ref .iter() .flat_map(|tref| tref.substs.types()) .zip(impl2_ref.iter().flat_map(|tref| tref.substs.types())) .chain(iter::once((impl1_self, impl2_self))) .any(|(ty1, ty2)| { - let ty1 = fast_reject::simplify_type(tcx, ty1, false); - let ty2 = fast_reject::simplify_type(tcx, ty2, false); - if let (Some(ty1), Some(ty2)) = (ty1, ty2) { + let t1 = fast_reject::simplify_type(tcx, ty1, false); + let t2 = fast_reject::simplify_type(tcx, ty2, false); + if let (Some(t1), Some(t2)) = (t1, t2) { // Simplified successfully - ty1 != ty2 + // Types cannot unify if they differ in their reference mutability or simplify to different types + ty1.ref_mutability() != ty2.ref_mutability() || t1 != t2 } else { // Types might unify false |
