about summary refs log tree commit diff
path: root/compiler/rustc_trait_selection/src
diff options
context:
space:
mode:
authorMatthew Jasper <mjjasper1@gmail.com>2023-05-05 15:52:53 +0100
committerMatthew Jasper <mjjasper1@gmail.com>2023-05-05 22:19:56 +0100
commitf46eabb9e56fab132ec8171d0e0239f42c986e52 (patch)
tree4650dd85c8015bef2e3dd4db160fdb1de24cfb6a /compiler/rustc_trait_selection/src
parentfafe9e71d5c949c41a5a562e44cc40d72c5f7244 (diff)
downloadrust-f46eabb9e56fab132ec8171d0e0239f42c986e52.tar.gz
rust-f46eabb9e56fab132ec8171d0e0239f42c986e52.zip
Report nicer lifetime errors for specialization
Add an obligation cause for these error so that the error points to the
implementations that caused the error.
Diffstat (limited to 'compiler/rustc_trait_selection/src')
-rw-r--r--compiler/rustc_trait_selection/src/traits/coherence.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/mod.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/specialize/mod.rs34
-rw-r--r--compiler/rustc_trait_selection/src/traits/util.rs4
4 files changed, 39 insertions, 7 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs
index b7690f79933..9f405aaf1a8 100644
--- a/compiler/rustc_trait_selection/src/traits/coherence.rs
+++ b/compiler/rustc_trait_selection/src/traits/coherence.rs
@@ -322,7 +322,9 @@ fn negative_impl(tcx: TyCtxt<'_>, impl1_def_id: DefId, impl2_def_id: DefId) -> b
     let selcx = &mut SelectionContext::new(&infcx);
     let impl2_substs = infcx.fresh_substs_for_item(DUMMY_SP, impl2_def_id);
     let (subject2, obligations) =
-        impl_subject_and_oblig(selcx, impl_env, impl2_def_id, impl2_substs);
+        impl_subject_and_oblig(selcx, impl_env, impl2_def_id, impl2_substs, |_, _| {
+            ObligationCause::dummy()
+        });
 
     !equate(&infcx, impl_env, subject1, subject2, obligations, impl1_def_id)
 }
diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs
index 8b8c50f6b83..138b0fb7432 100644
--- a/compiler/rustc_trait_selection/src/traits/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/mod.rs
@@ -54,7 +54,9 @@ pub use self::select::{EvaluationCache, SelectionCache, SelectionContext};
 pub use self::select::{EvaluationResult, IntercrateAmbiguityCause, OverflowError};
 pub use self::specialize::specialization_graph::FutureCompatOverlapError;
 pub use self::specialize::specialization_graph::FutureCompatOverlapErrorKind;
-pub use self::specialize::{specialization_graph, translate_substs, OverlapError};
+pub use self::specialize::{
+    specialization_graph, translate_substs, translate_substs_with_cause, OverlapError,
+};
 pub use self::structural_match::{
     search_for_adt_const_param_violation, search_for_structural_match_violation,
 };
diff --git a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
index 8bbebadb22a..9a4b72013b8 100644
--- a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
@@ -83,6 +83,30 @@ pub fn translate_substs<'tcx>(
     source_substs: SubstsRef<'tcx>,
     target_node: specialization_graph::Node,
 ) -> SubstsRef<'tcx> {
+    translate_substs_with_cause(
+        infcx,
+        param_env,
+        source_impl,
+        source_substs,
+        target_node,
+        |_, _| ObligationCause::dummy(),
+    )
+}
+
+/// Like [translate_substs], but obligations from the parent implementation
+/// are registered with the provided `ObligationCause`.
+///
+/// This is for reporting *region* errors from those bounds. Type errors should
+/// not happen because the specialization graph already checks for those, and
+/// will result in an ICE.
+pub fn translate_substs_with_cause<'tcx>(
+    infcx: &InferCtxt<'tcx>,
+    param_env: ty::ParamEnv<'tcx>,
+    source_impl: DefId,
+    source_substs: SubstsRef<'tcx>,
+    target_node: specialization_graph::Node,
+    cause: impl Fn(usize, Span) -> ObligationCause<'tcx>,
+) -> SubstsRef<'tcx> {
     debug!(
         "translate_substs({:?}, {:?}, {:?}, {:?})",
         param_env, source_impl, source_substs, target_node
@@ -99,7 +123,7 @@ pub fn translate_substs<'tcx>(
                 return source_substs;
             }
 
-            fulfill_implication(infcx, param_env, source_trait_ref, source_impl, target_impl)
+            fulfill_implication(infcx, param_env, source_trait_ref, source_impl, target_impl, cause)
                 .unwrap_or_else(|()| {
                     bug!(
                         "When translating substitutions from {source_impl:?} to {target_impl:?}, \
@@ -154,7 +178,10 @@ pub(super) fn specializes(tcx: TyCtxt<'_>, (impl1_def_id, impl2_def_id): (DefId,
     let infcx = tcx.infer_ctxt().build();
 
     // Attempt to prove that impl2 applies, given all of the above.
-    fulfill_implication(&infcx, penv, impl1_trait_ref, impl1_def_id, impl2_def_id).is_ok()
+    fulfill_implication(&infcx, penv, impl1_trait_ref, impl1_def_id, impl2_def_id, |_, _| {
+        ObligationCause::dummy()
+    })
+    .is_ok()
 }
 
 /// Attempt to fulfill all obligations of `target_impl` after unification with
@@ -168,6 +195,7 @@ fn fulfill_implication<'tcx>(
     source_trait_ref: ty::TraitRef<'tcx>,
     source_impl: DefId,
     target_impl: DefId,
+    error_cause: impl Fn(usize, Span) -> ObligationCause<'tcx>,
 ) -> Result<SubstsRef<'tcx>, ()> {
     debug!(
         "fulfill_implication({:?}, trait_ref={:?} |- {:?} applies)",
@@ -195,7 +223,7 @@ fn fulfill_implication<'tcx>(
     let selcx = &mut SelectionContext::new(&infcx);
     let target_substs = infcx.fresh_substs_for_item(DUMMY_SP, target_impl);
     let (target_trait, obligations) =
-        util::impl_subject_and_oblig(selcx, param_env, target_impl, target_substs);
+        util::impl_subject_and_oblig(selcx, param_env, target_impl, target_substs, error_cause);
 
     // do the impls unify? If not, no specialization.
     let Ok(InferOk { obligations: more_obligations, .. }) =
diff --git a/compiler/rustc_trait_selection/src/traits/util.rs b/compiler/rustc_trait_selection/src/traits/util.rs
index 7b7e297c64b..82f3df40198 100644
--- a/compiler/rustc_trait_selection/src/traits/util.rs
+++ b/compiler/rustc_trait_selection/src/traits/util.rs
@@ -197,6 +197,7 @@ pub fn impl_subject_and_oblig<'a, 'tcx>(
     param_env: ty::ParamEnv<'tcx>,
     impl_def_id: DefId,
     impl_substs: SubstsRef<'tcx>,
+    cause: impl Fn(usize, Span) -> ObligationCause<'tcx>,
 ) -> (ImplSubject<'tcx>, impl Iterator<Item = PredicateObligation<'tcx>>) {
     let subject = selcx.tcx().impl_subject(impl_def_id);
     let subject = subject.subst(selcx.tcx(), impl_substs);
@@ -208,8 +209,7 @@ pub fn impl_subject_and_oblig<'a, 'tcx>(
     let predicates = predicates.instantiate(selcx.tcx(), impl_substs);
     let InferOk { value: predicates, obligations: normalization_obligations2 } =
         selcx.infcx.at(&ObligationCause::dummy(), param_env).normalize(predicates);
-    let impl_obligations =
-        super::predicates_for_generics(|_, _| ObligationCause::dummy(), param_env, predicates);
+    let impl_obligations = super::predicates_for_generics(cause, param_env, predicates);
 
     let impl_obligations = impl_obligations
         .chain(normalization_obligations1.into_iter())