about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2025-07-05 17:47:28 +0000
committerMichael Goulet <michael@errs.io>2025-07-05 17:47:28 +0000
commit995eeeb54cda2f3c7884e14a82bbe1f279143388 (patch)
tree5dd45d4587c011aa85c62eb3fe2d41b24e99cf04
parent6dec76f1c2809fded082dd44d3752d3f6220d767 (diff)
downloadrust-995eeeb54cda2f3c7884e14a82bbe1f279143388.tar.gz
rust-995eeeb54cda2f3c7884e14a82bbe1f279143388.zip
Don't call predicates_of on a dummy obligation cause's body id
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs33
-rw-r--r--tests/ui/traits/error-reporting/ambiguity-in-dropck-err-reporting.rs18
-rw-r--r--tests/ui/traits/error-reporting/ambiguity-in-dropck-err-reporting.stderr19
3 files changed, 57 insertions, 13 deletions
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs
index 39f115ce0cd..a8ba1baf6b9 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs
@@ -4,7 +4,7 @@ use rustc_errors::{Applicability, Diag, E0283, E0284, E0790, MultiSpan, struct_s
 use rustc_hir as hir;
 use rustc_hir::LangItem;
 use rustc_hir::def::{DefKind, Res};
-use rustc_hir::def_id::DefId;
+use rustc_hir::def_id::{CRATE_DEF_ID, DefId};
 use rustc_hir::intravisit::Visitor as _;
 use rustc_infer::infer::{BoundRegionConversionTime, InferCtxt};
 use rustc_infer::traits::util::elaborate;
@@ -128,19 +128,26 @@ pub fn compute_applicable_impls_for_diagnostics<'tcx>(
         },
     );
 
-    let predicates =
-        tcx.predicates_of(obligation.cause.body_id.to_def_id()).instantiate_identity(tcx);
-    for (pred, span) in elaborate(tcx, predicates.into_iter()) {
-        let kind = pred.kind();
-        if let ty::ClauseKind::Trait(trait_pred) = kind.skip_binder()
-            && param_env_candidate_may_apply(kind.rebind(trait_pred))
-        {
-            if kind.rebind(trait_pred.trait_ref)
-                == ty::Binder::dummy(ty::TraitRef::identity(tcx, trait_pred.def_id()))
+    // If our `body_id` has been set (and isn't just from a dummy obligation cause),
+    // then try to look for a param-env clause that would apply. The way we compute
+    // this is somewhat manual, since we need the spans, so we elaborate this directly
+    // from `predicates_of` rather than actually looking at the param-env which
+    // otherwise would be more appropriate.
+    let body_id = obligation.cause.body_id;
+    if body_id != CRATE_DEF_ID {
+        let predicates = tcx.predicates_of(body_id.to_def_id()).instantiate_identity(tcx);
+        for (pred, span) in elaborate(tcx, predicates.into_iter()) {
+            let kind = pred.kind();
+            if let ty::ClauseKind::Trait(trait_pred) = kind.skip_binder()
+                && param_env_candidate_may_apply(kind.rebind(trait_pred))
             {
-                ambiguities.push(CandidateSource::ParamEnv(tcx.def_span(trait_pred.def_id())))
-            } else {
-                ambiguities.push(CandidateSource::ParamEnv(span))
+                if kind.rebind(trait_pred.trait_ref)
+                    == ty::Binder::dummy(ty::TraitRef::identity(tcx, trait_pred.def_id()))
+                {
+                    ambiguities.push(CandidateSource::ParamEnv(tcx.def_span(trait_pred.def_id())))
+                } else {
+                    ambiguities.push(CandidateSource::ParamEnv(span))
+                }
             }
         }
     }
diff --git a/tests/ui/traits/error-reporting/ambiguity-in-dropck-err-reporting.rs b/tests/ui/traits/error-reporting/ambiguity-in-dropck-err-reporting.rs
new file mode 100644
index 00000000000..ad313823fe4
--- /dev/null
+++ b/tests/ui/traits/error-reporting/ambiguity-in-dropck-err-reporting.rs
@@ -0,0 +1,18 @@
+// Regression test for #143481, where we were calling `predicates_of` on
+// a Crate HIR node because we were using a dummy obligation cause's body id
+// without checking that it was meaningful first.
+
+trait Role {
+    type Inner;
+}
+struct HandshakeCallback<C>(C);
+impl<C: Clone> Role for HandshakeCallback {
+    //~^ ERROR missing generics
+    type Inner = usize;
+}
+struct Handshake<R: Role>(R::Inner);
+fn accept() -> Handshake<HandshakeCallback<()>> {
+    todo!()
+}
+
+fn main() {}
diff --git a/tests/ui/traits/error-reporting/ambiguity-in-dropck-err-reporting.stderr b/tests/ui/traits/error-reporting/ambiguity-in-dropck-err-reporting.stderr
new file mode 100644
index 00000000000..17ace03e891
--- /dev/null
+++ b/tests/ui/traits/error-reporting/ambiguity-in-dropck-err-reporting.stderr
@@ -0,0 +1,19 @@
+error[E0107]: missing generics for struct `HandshakeCallback`
+  --> $DIR/ambiguity-in-dropck-err-reporting.rs:9:25
+   |
+LL | impl<C: Clone> Role for HandshakeCallback {
+   |                         ^^^^^^^^^^^^^^^^^ expected 1 generic argument
+   |
+note: struct defined here, with 1 generic parameter: `C`
+  --> $DIR/ambiguity-in-dropck-err-reporting.rs:8:8
+   |
+LL | struct HandshakeCallback<C>(C);
+   |        ^^^^^^^^^^^^^^^^^ -
+help: add missing generic argument
+   |
+LL | impl<C: Clone> Role for HandshakeCallback<C> {
+   |                                          +++
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0107`.