Skip to content

Commit 2aa5ef1

Browse files
authored
Rollup merge of #153615 - enthropy7:fix-ice-generics-of-crate-node, r=fee1-dead
fixed generics of crate node ICE when `note_and_explain_type_err` is called during dyn-compatibility checking, the `body_owner_def_id` can be `CRATE_DEF_ID` because `ObligationCause::dummy()` uses it as a placeholder when there is no real body owner. calling `generics_of `on `CRATE_DEF_ID `caused an ICE because the crate root is a module and modules don't have generics. the fix guards all `generics_of` call sites by checking whether `body_owner_def_id` is `CRATE_DEF_ID` before attempting to look up generics, and skips the type parameter span labeling in that case. i also added regression test with original ice reproduce fixes #152335
2 parents 892d08c + f1a4ae0 commit 2aa5ef1

4 files changed

Lines changed: 324 additions & 40 deletions

File tree

compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
5555
use rustc_errors::{Applicability, Diag, DiagStyledString, IntoDiagArg, StringPart, pluralize};
5656
use rustc_hir as hir;
5757
use rustc_hir::def::DefKind;
58-
use rustc_hir::def_id::DefId;
58+
use rustc_hir::def_id::{CRATE_DEF_ID, DefId};
5959
use rustc_hir::intravisit::Visitor;
6060
use rustc_hir::lang_items::LangItem;
6161
use rustc_infer::infer::DefineOpaqueTypes;
@@ -1797,12 +1797,13 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
17971797
}
17981798
}
17991799

1800-
self.note_and_explain_type_err(diag, terr, cause, span, cause.body_id.to_def_id());
1800+
let body_owner_def_id = (cause.body_id != CRATE_DEF_ID).then(|| cause.body_id.to_def_id());
1801+
self.note_and_explain_type_err(diag, terr, cause, span, body_owner_def_id);
18011802
if let Some(exp_found) = exp_found
18021803
&& let exp_found = TypeError::Sorts(exp_found)
18031804
&& exp_found != terr
18041805
{
1805-
self.note_and_explain_type_err(diag, exp_found, cause, span, cause.body_id.to_def_id());
1806+
self.note_and_explain_type_err(diag, exp_found, cause, span, body_owner_def_id);
18061807
}
18071808

18081809
if let Some(ValuePairs::TraitRefs(exp_found)) = values

compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs

Lines changed: 44 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,14 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
2222
err: TypeError<'tcx>,
2323
cause: &ObligationCause<'tcx>,
2424
sp: Span,
25-
body_owner_def_id: DefId,
25+
body_owner_def_id: Option<DefId>,
2626
) {
2727
debug!("note_and_explain_type_err err={:?} cause={:?}", err, cause);
2828

2929
let tcx = self.tcx;
3030

31+
let body_generics = body_owner_def_id.map(|def_id| tcx.generics_of(def_id));
32+
3133
match err {
3234
TypeError::ArgumentSorts(values, _) | TypeError::Sorts(values) => {
3335
match (*values.expected.kind(), *values.found.kind()) {
@@ -64,14 +66,15 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
6466
}
6567
}
6668
(ty::Param(expected), ty::Param(found)) => {
67-
let generics = tcx.generics_of(body_owner_def_id);
68-
let e_span = tcx.def_span(generics.type_param(expected, tcx).def_id);
69-
if !sp.contains(e_span) {
70-
diag.span_label(e_span, "expected type parameter");
71-
}
72-
let f_span = tcx.def_span(generics.type_param(found, tcx).def_id);
73-
if !sp.contains(f_span) {
74-
diag.span_label(f_span, "found type parameter");
69+
if let Some(generics) = body_generics {
70+
let e_span = tcx.def_span(generics.type_param(expected, tcx).def_id);
71+
if !sp.contains(e_span) {
72+
diag.span_label(e_span, "expected type parameter");
73+
}
74+
let f_span = tcx.def_span(generics.type_param(found, tcx).def_id);
75+
if !sp.contains(f_span) {
76+
diag.span_label(f_span, "found type parameter");
77+
}
7578
}
7679
diag.note(
7780
"a type parameter was expected, but a different one was found; \
@@ -92,9 +95,10 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
9295
// FIXME(inherent_associated_types): Extend this to support `ty::Inherent`, too.
9396
(ty::Param(p), ty::Alias(ty::Projection, proj))
9497
| (ty::Alias(ty::Projection, proj), ty::Param(p))
95-
if !tcx.is_impl_trait_in_trait(proj.def_id) =>
98+
if !tcx.is_impl_trait_in_trait(proj.def_id)
99+
&& let Some(generics) = body_generics =>
96100
{
97-
let param = tcx.generics_of(body_owner_def_id).type_param(p, tcx);
101+
let param = generics.type_param(p, tcx);
98102
let p_def_id = param.def_id;
99103
let p_span = tcx.def_span(p_def_id);
100104
let expected = match (values.expected.kind(), values.found.kind()) {
@@ -106,9 +110,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
106110
diag.span_label(p_span, format!("{expected}this type parameter"));
107111
}
108112
let param_def_id = match *proj.self_ty().kind() {
109-
ty::Param(param) => {
110-
tcx.generics_of(body_owner_def_id).type_param(param, tcx).def_id
111-
}
113+
ty::Param(param) => generics.type_param(param, tcx).def_id,
112114
_ => p_def_id,
113115
};
114116
let parent = param_def_id.as_local().and_then(|id| {
@@ -188,15 +190,16 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
188190
}
189191
(ty::Param(p), ty::Dynamic(..) | ty::Alias(ty::Opaque, ..))
190192
| (ty::Dynamic(..) | ty::Alias(ty::Opaque, ..), ty::Param(p)) => {
191-
let generics = tcx.generics_of(body_owner_def_id);
192-
let p_span = tcx.def_span(generics.type_param(p, tcx).def_id);
193-
let expected = match (values.expected.kind(), values.found.kind()) {
194-
(ty::Param(_), _) => "expected ",
195-
(_, ty::Param(_)) => "found ",
196-
_ => "",
197-
};
198-
if !sp.contains(p_span) {
199-
diag.span_label(p_span, format!("{expected}this type parameter"));
193+
if let Some(generics) = body_generics {
194+
let p_span = tcx.def_span(generics.type_param(p, tcx).def_id);
195+
let expected = match (values.expected.kind(), values.found.kind()) {
196+
(ty::Param(_), _) => "expected ",
197+
(_, ty::Param(_)) => "found ",
198+
_ => "",
199+
};
200+
if !sp.contains(p_span) {
201+
diag.span_label(p_span, format!("{expected}this type parameter"));
202+
}
200203
}
201204
diag.help("type parameters must be constrained to match other types");
202205
if diag.code.is_some_and(|code| tcx.sess.teach(code)) {
@@ -236,18 +239,18 @@ impl<T> Trait<T> for X {
236239
ty::Param(p),
237240
ty::Closure(..) | ty::CoroutineClosure(..) | ty::Coroutine(..),
238241
) => {
239-
let generics = tcx.generics_of(body_owner_def_id);
240-
let p_span = tcx.def_span(generics.type_param(p, tcx).def_id);
241-
if !sp.contains(p_span) {
242-
diag.span_label(p_span, "expected this type parameter");
242+
if let Some(generics) = body_generics {
243+
let p_span = tcx.def_span(generics.type_param(p, tcx).def_id);
244+
if !sp.contains(p_span) {
245+
diag.span_label(p_span, "expected this type parameter");
246+
}
243247
}
244248
diag.help(format!(
245249
"every closure has a distinct type and so could not always match the \
246250
caller-chosen type of parameter `{p}`"
247251
));
248252
}
249-
(ty::Param(p), _) | (_, ty::Param(p)) => {
250-
let generics = tcx.generics_of(body_owner_def_id);
253+
(ty::Param(p), _) | (_, ty::Param(p)) if let Some(generics) = body_generics => {
251254
let p_span = tcx.def_span(generics.type_param(p, tcx).def_id);
252255
let expected = match (values.expected.kind(), values.found.kind()) {
253256
(ty::Param(_), _) => "expected ",
@@ -366,7 +369,8 @@ impl<T> Trait<T> for X {
366369
}
367370
(_, ty::Alias(ty::Opaque, opaque_ty))
368371
| (ty::Alias(ty::Opaque, opaque_ty), _) => {
369-
if opaque_ty.def_id.is_local()
372+
if let Some(body_owner_def_id) = body_owner_def_id
373+
&& opaque_ty.def_id.is_local()
370374
&& matches!(
371375
tcx.def_kind(body_owner_def_id),
372376
DefKind::Fn
@@ -560,11 +564,14 @@ impl<T> Trait<T> for X {
560564
&self,
561565
diag: &mut Diag<'_>,
562566
msg: impl Fn() -> String,
563-
body_owner_def_id: DefId,
567+
body_owner_def_id: Option<DefId>,
564568
proj_ty: ty::AliasTy<'tcx>,
565569
ty: Ty<'tcx>,
566570
) -> bool {
567571
let tcx = self.tcx;
572+
let Some(body_owner_def_id) = body_owner_def_id else {
573+
return false;
574+
};
568575
let assoc = tcx.associated_item(proj_ty.def_id);
569576
let (trait_ref, assoc_args) = proj_ty.trait_ref_and_own_args(tcx);
570577
let Some(item) = tcx.hir_get_if_local(body_owner_def_id) else {
@@ -611,7 +618,7 @@ impl<T> Trait<T> for X {
611618
_ => return false,
612619
};
613620
let parent = tcx.hir_get_parent_item(hir_id).def_id;
614-
self.suggest_constraint(diag, msg, parent.into(), proj_ty, ty)
621+
self.suggest_constraint(diag, msg, Some(parent.into()), proj_ty, ty)
615622
}
616623

617624
/// An associated type was expected and a different type was found.
@@ -632,7 +639,7 @@ impl<T> Trait<T> for X {
632639
diag: &mut Diag<'_>,
633640
proj_ty: ty::AliasTy<'tcx>,
634641
values: ExpectedFound<Ty<'tcx>>,
635-
body_owner_def_id: DefId,
642+
body_owner_def_id: Option<DefId>,
636643
cause_code: &ObligationCauseCode<'_>,
637644
) {
638645
let tcx = self.tcx;
@@ -653,7 +660,7 @@ impl<T> Trait<T> for X {
653660
)
654661
};
655662

656-
let body_owner = tcx.hir_get_if_local(body_owner_def_id);
663+
let body_owner = body_owner_def_id.and_then(|id| tcx.hir_get_if_local(id));
657664
let current_method_ident = body_owner.and_then(|n| n.ident()).map(|i| i.name);
658665

659666
// We don't want to suggest calling an assoc fn in a scope where that isn't feasible.
@@ -835,12 +842,12 @@ fn foo(&self) -> Self::T { String::new() }
835842
fn point_at_associated_type(
836843
&self,
837844
diag: &mut Diag<'_>,
838-
body_owner_def_id: DefId,
845+
body_owner_def_id: Option<DefId>,
839846
found: Ty<'tcx>,
840847
) -> bool {
841848
let tcx = self.tcx;
842849

843-
let Some(def_id) = body_owner_def_id.as_local() else {
850+
let Some(def_id) = body_owner_def_id.and_then(|id| id.as_local()) else {
844851
return false;
845852
};
846853

@@ -852,7 +859,7 @@ fn foo(&self) -> Self::T { String::new() }
852859

853860
debug!("expected_projection parent item {:?}", item);
854861

855-
let param_env = tcx.param_env(body_owner_def_id);
862+
let param_env = tcx.param_env(def_id);
856863

857864
if let DefKind::Trait | DefKind::Impl { .. } = tcx.def_kind(parent_id) {
858865
let assoc_items = tcx.associated_items(parent_id);
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// Regression test for #152335.
2+
// The compiler used to ICE in `generics_of` when `note_and_explain_type_err`
3+
// was called with `CRATE_DEF_ID` as the body owner during dyn-compatibility
4+
// checking. This happened because `ObligationCause::dummy()` sets `body_id`
5+
// to `CRATE_DEF_ID`, and error reporting tried to look up generics on it.
6+
7+
struct ActuallySuper;
8+
9+
trait Super<B = Self> {
10+
type Assoc;
11+
}
12+
13+
trait Dyn {}
14+
impl<T, U> Dyn for dyn Foo<T, U> + '_ {}
15+
//~^ ERROR the trait `Foo` is not dyn compatible
16+
17+
trait Foo<T, U>: Super<ActuallySuper, Assoc = T>
18+
//~^ ERROR type mismatch resolving
19+
//~| ERROR the size for values of type `Self` cannot be known
20+
where
21+
<Self as Mirror>::Assoc: Super,
22+
//~^ ERROR type mismatch resolving
23+
//~| ERROR the size for values of type `Self` cannot be known
24+
//~| ERROR type mismatch resolving
25+
//~| ERROR the size for values of type `Self` cannot be known
26+
{
27+
fn transmute(&self, t: T) -> <Self as B>::Assoc;
28+
//~^ ERROR cannot find trait `B` in this scope
29+
//~| ERROR type mismatch resolving
30+
//~| ERROR the size for values of type `Self` cannot be known
31+
//~| ERROR type mismatch resolving
32+
//~| ERROR the size for values of type `Self` cannot be known
33+
}
34+
35+
trait Mirror {
36+
type Assoc: ?Sized;
37+
}
38+
impl<T: Super<ActuallySuper, Assoc = T>> Mirror for T {}
39+
//~^ ERROR not all trait items implemented
40+
//~| ERROR `main` function not found

0 commit comments

Comments
 (0)