about summary refs log tree commit diff
diff options
context:
space:
mode:
authorSantiago Pastorino <spastorino@gmail.com>2022-03-20 00:12:03 -0300
committerSantiago Pastorino <spastorino@gmail.com>2022-03-20 00:12:18 -0300
commit0cd03c917cd728844048edb41a3d30d414214ad8 (patch)
tree6b693f6e98878f73e01df5ad8b8ae7cfc0784579
parent91b52148ebc16f41632930344bdbe4e093f1970e (diff)
downloadrust-0cd03c917cd728844048edb41a3d30d414214ad8.tar.gz
rust-0cd03c917cd728844048edb41a3d30d414214ad8.zip
Extract ImplSubject information
-rw-r--r--compiler/rustc_middle/src/hir/mod.rs10
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs6
-rw-r--r--compiler/rustc_trait_selection/src/traits/coherence.rs75
3 files changed, 52 insertions, 39 deletions
diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs
index 1053f0cefbe..4bc0d3a4d86 100644
--- a/compiler/rustc_middle/src/hir/mod.rs
+++ b/compiler/rustc_middle/src/hir/mod.rs
@@ -7,10 +7,10 @@ pub mod nested_filter;
 pub mod place;
 
 use crate::ty::query::Providers;
-use crate::ty::TyCtxt;
+use crate::ty::{ImplSubject, TyCtxt};
 use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
-use rustc_hir::def_id::LocalDefId;
+use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::*;
 use rustc_query_system::ich::StableHashingContext;
 use rustc_span::DUMMY_SP;
@@ -54,6 +54,12 @@ impl<'tcx> TyCtxt<'tcx> {
     pub fn parent_module(self, id: HirId) -> LocalDefId {
         self.parent_module_from_def_id(id.owner)
     }
+
+    pub fn impl_header(self, def_id: DefId) -> ImplSubject<'tcx> {
+        self.impl_trait_ref(def_id)
+            .map(ImplSubject::Trait)
+            .unwrap_or_else(|| ImplSubject::Inherent(self.type_of(def_id)))
+    }
 }
 
 pub fn provide(providers: &mut Providers) {
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 83ab761aa55..91d2d64c52e 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -172,6 +172,12 @@ pub struct ImplHeader<'tcx> {
     pub predicates: Vec<Predicate<'tcx>>,
 }
 
+#[derive(Debug)]
+pub enum ImplSubject<'tcx> {
+    Trait(TraitRef<'tcx>),
+    Inherent(Ty<'tcx>),
+}
+
 #[derive(
     Copy,
     Clone,
diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs
index 8698384800c..a0fbf94c01d 100644
--- a/compiler/rustc_trait_selection/src/traits/coherence.rs
+++ b/compiler/rustc_trait_selection/src/traits/coherence.rs
@@ -24,7 +24,7 @@ use rustc_middle::traits::specialization_graph::OverlapMode;
 use rustc_middle::ty::fast_reject::{self, TreatParams};
 use rustc_middle::ty::fold::TypeFoldable;
 use rustc_middle::ty::subst::Subst;
-use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_middle::ty::{self, ImplSubject, Ty, TyCtxt};
 use rustc_span::symbol::sym;
 use rustc_span::DUMMY_SP;
 use std::fmt::Debug;
@@ -307,46 +307,47 @@ fn negative_impl<'cx, 'tcx>(
         // create a parameter environment corresponding to a (placeholder) instantiation of impl1
         let impl1_env = tcx.param_env(impl1_def_id);
 
-        if let Some(impl1_trait_ref) = tcx.impl_trait_ref(impl1_def_id) {
-            // Normalize the trait reference. The WF rules ought to ensure
-            // that this always succeeds.
-            let impl1_trait_ref = match traits::fully_normalize(
-                &infcx,
-                FulfillmentContext::new(),
-                ObligationCause::dummy(),
-                impl1_env,
-                impl1_trait_ref,
-            ) {
-                Ok(impl1_trait_ref) => impl1_trait_ref,
-                Err(err) => {
-                    bug!("failed to fully normalize {:?}: {:?}", impl1_trait_ref, err);
-                }
-            };
-
-            // Attempt to prove that impl2 applies, given all of the above.
-            let selcx = &mut SelectionContext::new(&infcx);
-            let impl2_substs = infcx.fresh_substs_for_item(DUMMY_SP, impl2_def_id);
-            let (impl2_trait_ref, obligations) =
-                impl_trait_ref_and_oblig(selcx, impl1_env, impl2_def_id, impl2_substs);
-
-            !obligations_satisfiable(
-                &infcx,
-                impl1_env,
-                impl1_def_id,
-                impl1_trait_ref,
-                impl2_trait_ref,
-                obligations,
-            )
-        } else {
-            let ty1 = tcx.type_of(impl1_def_id);
-            let ty2 = tcx.type_of(impl2_def_id);
-
-            !obligations_satisfiable(&infcx, impl1_env, impl1_def_id, ty1, ty2, iter::empty())
+        match tcx.impl_header(impl1_def_id) {
+            ImplSubject::Trait(impl1_trait_ref) => {
+                // Normalize the trait reference. The WF rules ought to ensure
+                // that this always succeeds.
+                let impl1_trait_ref = match traits::fully_normalize(
+                    &infcx,
+                    FulfillmentContext::new(),
+                    ObligationCause::dummy(),
+                    impl1_env,
+                    impl1_trait_ref,
+                ) {
+                    Ok(impl1_trait_ref) => impl1_trait_ref,
+                    Err(err) => {
+                        bug!("failed to fully normalize {:?}: {:?}", impl1_trait_ref, err);
+                    }
+                };
+
+                // Attempt to prove that impl2 applies, given all of the above.
+                let selcx = &mut SelectionContext::new(&infcx);
+                let impl2_substs = infcx.fresh_substs_for_item(DUMMY_SP, impl2_def_id);
+                let (impl2_trait_ref, obligations) =
+                    impl_trait_ref_and_oblig(selcx, impl1_env, impl2_def_id, impl2_substs);
+
+                !equate(
+                    &infcx,
+                    impl1_env,
+                    impl1_def_id,
+                    impl1_trait_ref,
+                    impl2_trait_ref,
+                    obligations,
+                )
+            }
+            ImplSubject::Inherent(ty1) => {
+                let ty2 = tcx.type_of(impl2_def_id);
+                !equate(&infcx, impl1_env, impl1_def_id, ty1, ty2, iter::empty())
+            }
         }
     })
 }
 
-fn obligations_satisfiable<'cx, 'tcx, T: Debug + ToTrace<'tcx>>(
+fn equate<'cx, 'tcx, T: Debug + ToTrace<'tcx>>(
     infcx: &InferCtxt<'cx, 'tcx>,
     impl1_env: ty::ParamEnv<'tcx>,
     impl1_def_id: DefId,