Skip to content

Commit 995eeeb

Browse files
Don't call predicates_of on a dummy obligation cause's body id
1 parent 6dec76f commit 995eeeb

File tree

3 files changed

+57
-13
lines changed

3 files changed

+57
-13
lines changed

compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use rustc_errors::{Applicability, Diag, E0283, E0284, E0790, MultiSpan, struct_s
44
use rustc_hir as hir;
55
use rustc_hir::LangItem;
66
use rustc_hir::def::{DefKind, Res};
7-
use rustc_hir::def_id::DefId;
7+
use rustc_hir::def_id::{CRATE_DEF_ID, DefId};
88
use rustc_hir::intravisit::Visitor as _;
99
use rustc_infer::infer::{BoundRegionConversionTime, InferCtxt};
1010
use rustc_infer::traits::util::elaborate;
@@ -128,19 +128,26 @@ pub fn compute_applicable_impls_for_diagnostics<'tcx>(
128128
},
129129
);
130130

131-
let predicates =
132-
tcx.predicates_of(obligation.cause.body_id.to_def_id()).instantiate_identity(tcx);
133-
for (pred, span) in elaborate(tcx, predicates.into_iter()) {
134-
let kind = pred.kind();
135-
if let ty::ClauseKind::Trait(trait_pred) = kind.skip_binder()
136-
&& param_env_candidate_may_apply(kind.rebind(trait_pred))
137-
{
138-
if kind.rebind(trait_pred.trait_ref)
139-
== ty::Binder::dummy(ty::TraitRef::identity(tcx, trait_pred.def_id()))
131+
// If our `body_id` has been set (and isn't just from a dummy obligation cause),
132+
// then try to look for a param-env clause that would apply. The way we compute
133+
// this is somewhat manual, since we need the spans, so we elaborate this directly
134+
// from `predicates_of` rather than actually looking at the param-env which
135+
// otherwise would be more appropriate.
136+
let body_id = obligation.cause.body_id;
137+
if body_id != CRATE_DEF_ID {
138+
let predicates = tcx.predicates_of(body_id.to_def_id()).instantiate_identity(tcx);
139+
for (pred, span) in elaborate(tcx, predicates.into_iter()) {
140+
let kind = pred.kind();
141+
if let ty::ClauseKind::Trait(trait_pred) = kind.skip_binder()
142+
&& param_env_candidate_may_apply(kind.rebind(trait_pred))
140143
{
141-
ambiguities.push(CandidateSource::ParamEnv(tcx.def_span(trait_pred.def_id())))
142-
} else {
143-
ambiguities.push(CandidateSource::ParamEnv(span))
144+
if kind.rebind(trait_pred.trait_ref)
145+
== ty::Binder::dummy(ty::TraitRef::identity(tcx, trait_pred.def_id()))
146+
{
147+
ambiguities.push(CandidateSource::ParamEnv(tcx.def_span(trait_pred.def_id())))
148+
} else {
149+
ambiguities.push(CandidateSource::ParamEnv(span))
150+
}
144151
}
145152
}
146153
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Regression test for #143481, where we were calling `predicates_of` on
2+
// a Crate HIR node because we were using a dummy obligation cause's body id
3+
// without checking that it was meaningful first.
4+
5+
trait Role {
6+
type Inner;
7+
}
8+
struct HandshakeCallback<C>(C);
9+
impl<C: Clone> Role for HandshakeCallback {
10+
//~^ ERROR missing generics
11+
type Inner = usize;
12+
}
13+
struct Handshake<R: Role>(R::Inner);
14+
fn accept() -> Handshake<HandshakeCallback<()>> {
15+
todo!()
16+
}
17+
18+
fn main() {}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
error[E0107]: missing generics for struct `HandshakeCallback`
2+
--> $DIR/ambiguity-in-dropck-err-reporting.rs:9:25
3+
|
4+
LL | impl<C: Clone> Role for HandshakeCallback {
5+
| ^^^^^^^^^^^^^^^^^ expected 1 generic argument
6+
|
7+
note: struct defined here, with 1 generic parameter: `C`
8+
--> $DIR/ambiguity-in-dropck-err-reporting.rs:8:8
9+
|
10+
LL | struct HandshakeCallback<C>(C);
11+
| ^^^^^^^^^^^^^^^^^ -
12+
help: add missing generic argument
13+
|
14+
LL | impl<C: Clone> Role for HandshakeCallback<C> {
15+
| +++
16+
17+
error: aborting due to 1 previous error
18+
19+
For more information about this error, try `rustc --explain E0107`.

0 commit comments

Comments
 (0)