fix ice generics of crate node

This commit is contained in:
enthropy7
2026-03-09 18:50:42 +03:00
parent f908263775
commit f1a4ae02ed
4 changed files with 324 additions and 40 deletions
@@ -55,7 +55,7 @@
use rustc_errors::{Applicability, Diag, DiagStyledString, IntoDiagArg, StringPart, pluralize};
use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::DefId;
use rustc_hir::def_id::{CRATE_DEF_ID, DefId};
use rustc_hir::intravisit::Visitor;
use rustc_hir::lang_items::LangItem;
use rustc_infer::infer::DefineOpaqueTypes;
@@ -1793,12 +1793,13 @@ enum Similar<'tcx> {
}
}
self.note_and_explain_type_err(diag, terr, cause, span, cause.body_id.to_def_id());
let body_owner_def_id = (cause.body_id != CRATE_DEF_ID).then(|| cause.body_id.to_def_id());
self.note_and_explain_type_err(diag, terr, cause, span, body_owner_def_id);
if let Some(exp_found) = exp_found
&& let exp_found = TypeError::Sorts(exp_found)
&& exp_found != terr
{
self.note_and_explain_type_err(diag, exp_found, cause, span, cause.body_id.to_def_id());
self.note_and_explain_type_err(diag, exp_found, cause, span, body_owner_def_id);
}
if let Some(ValuePairs::TraitRefs(exp_found)) = values
@@ -22,12 +22,14 @@ pub fn note_and_explain_type_err(
err: TypeError<'tcx>,
cause: &ObligationCause<'tcx>,
sp: Span,
body_owner_def_id: DefId,
body_owner_def_id: Option<DefId>,
) {
debug!("note_and_explain_type_err err={:?} cause={:?}", err, cause);
let tcx = self.tcx;
let body_generics = body_owner_def_id.map(|def_id| tcx.generics_of(def_id));
match err {
TypeError::ArgumentSorts(values, _) | TypeError::Sorts(values) => {
match (*values.expected.kind(), *values.found.kind()) {
@@ -64,14 +66,15 @@ pub fn note_and_explain_type_err(
}
}
(ty::Param(expected), ty::Param(found)) => {
let generics = tcx.generics_of(body_owner_def_id);
let e_span = tcx.def_span(generics.type_param(expected, tcx).def_id);
if !sp.contains(e_span) {
diag.span_label(e_span, "expected type parameter");
}
let f_span = tcx.def_span(generics.type_param(found, tcx).def_id);
if !sp.contains(f_span) {
diag.span_label(f_span, "found type parameter");
if let Some(generics) = body_generics {
let e_span = tcx.def_span(generics.type_param(expected, tcx).def_id);
if !sp.contains(e_span) {
diag.span_label(e_span, "expected type parameter");
}
let f_span = tcx.def_span(generics.type_param(found, tcx).def_id);
if !sp.contains(f_span) {
diag.span_label(f_span, "found type parameter");
}
}
diag.note(
"a type parameter was expected, but a different one was found; \
@@ -92,9 +95,10 @@ pub fn note_and_explain_type_err(
// FIXME(inherent_associated_types): Extend this to support `ty::Inherent`, too.
(ty::Param(p), ty::Alias(ty::Projection, proj))
| (ty::Alias(ty::Projection, proj), ty::Param(p))
if !tcx.is_impl_trait_in_trait(proj.def_id) =>
if !tcx.is_impl_trait_in_trait(proj.def_id)
&& let Some(generics) = body_generics =>
{
let param = tcx.generics_of(body_owner_def_id).type_param(p, tcx);
let param = generics.type_param(p, tcx);
let p_def_id = param.def_id;
let p_span = tcx.def_span(p_def_id);
let expected = match (values.expected.kind(), values.found.kind()) {
@@ -106,9 +110,7 @@ pub fn note_and_explain_type_err(
diag.span_label(p_span, format!("{expected}this type parameter"));
}
let param_def_id = match *proj.self_ty().kind() {
ty::Param(param) => {
tcx.generics_of(body_owner_def_id).type_param(param, tcx).def_id
}
ty::Param(param) => generics.type_param(param, tcx).def_id,
_ => p_def_id,
};
let parent = param_def_id.as_local().and_then(|id| {
@@ -188,15 +190,16 @@ pub fn note_and_explain_type_err(
}
(ty::Param(p), ty::Dynamic(..) | ty::Alias(ty::Opaque, ..))
| (ty::Dynamic(..) | ty::Alias(ty::Opaque, ..), ty::Param(p)) => {
let generics = tcx.generics_of(body_owner_def_id);
let p_span = tcx.def_span(generics.type_param(p, tcx).def_id);
let expected = match (values.expected.kind(), values.found.kind()) {
(ty::Param(_), _) => "expected ",
(_, ty::Param(_)) => "found ",
_ => "",
};
if !sp.contains(p_span) {
diag.span_label(p_span, format!("{expected}this type parameter"));
if let Some(generics) = body_generics {
let p_span = tcx.def_span(generics.type_param(p, tcx).def_id);
let expected = match (values.expected.kind(), values.found.kind()) {
(ty::Param(_), _) => "expected ",
(_, ty::Param(_)) => "found ",
_ => "",
};
if !sp.contains(p_span) {
diag.span_label(p_span, format!("{expected}this type parameter"));
}
}
diag.help("type parameters must be constrained to match other types");
if diag.code.is_some_and(|code| tcx.sess.teach(code)) {
@@ -236,18 +239,18 @@ fn foo(&self, x: T) -> T { x }
ty::Param(p),
ty::Closure(..) | ty::CoroutineClosure(..) | ty::Coroutine(..),
) => {
let generics = tcx.generics_of(body_owner_def_id);
let p_span = tcx.def_span(generics.type_param(p, tcx).def_id);
if !sp.contains(p_span) {
diag.span_label(p_span, "expected this type parameter");
if let Some(generics) = body_generics {
let p_span = tcx.def_span(generics.type_param(p, tcx).def_id);
if !sp.contains(p_span) {
diag.span_label(p_span, "expected this type parameter");
}
}
diag.help(format!(
"every closure has a distinct type and so could not always match the \
caller-chosen type of parameter `{p}`"
));
}
(ty::Param(p), _) | (_, ty::Param(p)) => {
let generics = tcx.generics_of(body_owner_def_id);
(ty::Param(p), _) | (_, ty::Param(p)) if let Some(generics) = body_generics => {
let p_span = tcx.def_span(generics.type_param(p, tcx).def_id);
let expected = match (values.expected.kind(), values.found.kind()) {
(ty::Param(_), _) => "expected ",
@@ -366,7 +369,8 @@ fn foo(&self, x: T) -> T { x }
}
(_, ty::Alias(ty::Opaque, opaque_ty))
| (ty::Alias(ty::Opaque, opaque_ty), _) => {
if opaque_ty.def_id.is_local()
if let Some(body_owner_def_id) = body_owner_def_id
&& opaque_ty.def_id.is_local()
&& matches!(
tcx.def_kind(body_owner_def_id),
DefKind::Fn
@@ -560,11 +564,14 @@ fn suggest_constraint(
&self,
diag: &mut Diag<'_>,
msg: impl Fn() -> String,
body_owner_def_id: DefId,
body_owner_def_id: Option<DefId>,
proj_ty: ty::AliasTy<'tcx>,
ty: Ty<'tcx>,
) -> bool {
let tcx = self.tcx;
let Some(body_owner_def_id) = body_owner_def_id else {
return false;
};
let assoc = tcx.associated_item(proj_ty.def_id);
let (trait_ref, assoc_args) = proj_ty.trait_ref_and_own_args(tcx);
let Some(item) = tcx.hir_get_if_local(body_owner_def_id) else {
@@ -611,7 +618,7 @@ fn suggest_constraint(
_ => return false,
};
let parent = tcx.hir_get_parent_item(hir_id).def_id;
self.suggest_constraint(diag, msg, parent.into(), proj_ty, ty)
self.suggest_constraint(diag, msg, Some(parent.into()), proj_ty, ty)
}
/// An associated type was expected and a different type was found.
@@ -632,7 +639,7 @@ fn expected_projection(
diag: &mut Diag<'_>,
proj_ty: ty::AliasTy<'tcx>,
values: ExpectedFound<Ty<'tcx>>,
body_owner_def_id: DefId,
body_owner_def_id: Option<DefId>,
cause_code: &ObligationCauseCode<'_>,
) {
let tcx = self.tcx;
@@ -653,7 +660,7 @@ fn expected_projection(
)
};
let body_owner = tcx.hir_get_if_local(body_owner_def_id);
let body_owner = body_owner_def_id.and_then(|id| tcx.hir_get_if_local(id));
let current_method_ident = body_owner.and_then(|n| n.ident()).map(|i| i.name);
// We don't want to suggest calling an assoc fn in a scope where that isn't feasible.
@@ -835,12 +842,12 @@ fn point_at_methods_that_satisfy_associated_type(
fn point_at_associated_type(
&self,
diag: &mut Diag<'_>,
body_owner_def_id: DefId,
body_owner_def_id: Option<DefId>,
found: Ty<'tcx>,
) -> bool {
let tcx = self.tcx;
let Some(def_id) = body_owner_def_id.as_local() else {
let Some(def_id) = body_owner_def_id.and_then(|id| id.as_local()) else {
return false;
};
@@ -852,7 +859,7 @@ fn point_at_associated_type(
debug!("expected_projection parent item {:?}", item);
let param_env = tcx.param_env(body_owner_def_id);
let param_env = tcx.param_env(def_id);
if let DefKind::Trait | DefKind::Impl { .. } = tcx.def_kind(parent_id) {
let assoc_items = tcx.associated_items(parent_id);
@@ -0,0 +1,40 @@
// Regression test for #152335.
// The compiler used to ICE in `generics_of` when `note_and_explain_type_err`
// was called with `CRATE_DEF_ID` as the body owner during dyn-compatibility
// checking. This happened because `ObligationCause::dummy()` sets `body_id`
// to `CRATE_DEF_ID`, and error reporting tried to look up generics on it.
struct ActuallySuper;
trait Super<B = Self> {
type Assoc;
}
trait Dyn {}
impl<T, U> Dyn for dyn Foo<T, U> + '_ {}
//~^ ERROR the trait `Foo` is not dyn compatible
trait Foo<T, U>: Super<ActuallySuper, Assoc = T>
//~^ ERROR type mismatch resolving
//~| ERROR the size for values of type `Self` cannot be known
where
<Self as Mirror>::Assoc: Super,
//~^ ERROR type mismatch resolving
//~| ERROR the size for values of type `Self` cannot be known
//~| ERROR type mismatch resolving
//~| ERROR the size for values of type `Self` cannot be known
{
fn transmute(&self, t: T) -> <Self as B>::Assoc;
//~^ ERROR cannot find trait `B` in this scope
//~| ERROR type mismatch resolving
//~| ERROR the size for values of type `Self` cannot be known
//~| ERROR type mismatch resolving
//~| ERROR the size for values of type `Self` cannot be known
}
trait Mirror {
type Assoc: ?Sized;
}
impl<T: Super<ActuallySuper, Assoc = T>> Mirror for T {}
//~^ ERROR not all trait items implemented
//~| ERROR `main` function not found
@@ -0,0 +1,236 @@
error[E0405]: cannot find trait `B` in this scope
--> $DIR/ice-generics-of-crate-root-152335.rs:27:43
|
LL | fn transmute(&self, t: T) -> <Self as B>::Assoc;
| ^ not found in this scope
error[E0601]: `main` function not found in crate `ice_generics_of_crate_root_152335`
--> $DIR/ice-generics-of-crate-root-152335.rs:38:57
|
LL | impl<T: Super<ActuallySuper, Assoc = T>> Mirror for T {}
| ^ consider adding a `main` function to `$DIR/ice-generics-of-crate-root-152335.rs`
error[E0271]: type mismatch resolving `<Self as Super<ActuallySuper>>::Assoc == Self`
--> $DIR/ice-generics-of-crate-root-152335.rs:27:5
|
LL | fn transmute(&self, t: T) -> <Self as B>::Assoc;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected type parameter `Self`, found type parameter `T`
|
= note: expected type parameter `Self`
found type parameter `T`
= note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound
= note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters
note: required for `Self` to implement `Mirror`
--> $DIR/ice-generics-of-crate-root-152335.rs:38:42
|
LL | impl<T: Super<ActuallySuper, Assoc = T>> Mirror for T {}
| --------- ^^^^^^ ^
| |
| unsatisfied trait bound introduced here
error[E0277]: the size for values of type `Self` cannot be known at compilation time
--> $DIR/ice-generics-of-crate-root-152335.rs:27:5
|
LL | fn transmute(&self, t: T) -> <Self as B>::Assoc;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
note: required for `Self` to implement `Mirror`
--> $DIR/ice-generics-of-crate-root-152335.rs:38:42
|
LL | impl<T: Super<ActuallySuper, Assoc = T>> Mirror for T {}
| - ^^^^^^ ^
| |
| unsatisfied trait bound implicitly introduced here
error[E0038]: the trait `Foo` is not dyn compatible
--> $DIR/ice-generics-of-crate-root-152335.rs:14:20
|
LL | impl<T, U> Dyn for dyn Foo<T, U> + '_ {}
| ^^^^^^^^^^^^^^^^^^ `Foo` is not dyn compatible
|
note: for a trait to be dyn compatible it needs to allow building a vtable
for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
--> $DIR/ice-generics-of-crate-root-152335.rs:21:30
|
LL | trait Foo<T, U>: Super<ActuallySuper, Assoc = T>
| --- this trait is not dyn compatible...
...
LL | <Self as Mirror>::Assoc: Super,
| ^^^^^ ...because it uses `Self` as a type parameter
error[E0271]: type mismatch resolving `<Self as Super<ActuallySuper>>::Assoc == Self`
--> $DIR/ice-generics-of-crate-root-152335.rs:17:1
|
LL | trait Foo<T, U>: Super<ActuallySuper, Assoc = T>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected type parameter `Self`, found type parameter `T`
|
= note: expected type parameter `Self`
found type parameter `T`
= note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound
= note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters
note: required for `Self` to implement `Mirror`
--> $DIR/ice-generics-of-crate-root-152335.rs:38:42
|
LL | impl<T: Super<ActuallySuper, Assoc = T>> Mirror for T {}
| --------- ^^^^^^ ^
| |
| unsatisfied trait bound introduced here
error[E0277]: the size for values of type `Self` cannot be known at compilation time
--> $DIR/ice-generics-of-crate-root-152335.rs:17:1
|
LL | trait Foo<T, U>: Super<ActuallySuper, Assoc = T>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
note: required for `Self` to implement `Mirror`
--> $DIR/ice-generics-of-crate-root-152335.rs:38:42
|
LL | impl<T: Super<ActuallySuper, Assoc = T>> Mirror for T {}
| - ^^^^^^ ^
| |
| unsatisfied trait bound implicitly introduced here
help: consider further restricting `Self`
|
LL | trait Foo<T, U>: Super<ActuallySuper, Assoc = T> + Sized
| +++++++
error[E0271]: type mismatch resolving `<Self as Super<ActuallySuper>>::Assoc == Self`
--> $DIR/ice-generics-of-crate-root-152335.rs:21:30
|
LL | trait Foo<T, U>: Super<ActuallySuper, Assoc = T>
| ------------------------------------------------
| | |
| | found type parameter
| expected type parameter
...
LL | <Self as Mirror>::Assoc: Super,
| ^^^^^ expected type parameter `Self`, found type parameter `T`
|
= note: expected type parameter `Self`
found type parameter `T`
= note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound
= note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters
note: required for `Self` to implement `Mirror`
--> $DIR/ice-generics-of-crate-root-152335.rs:38:42
|
LL | impl<T: Super<ActuallySuper, Assoc = T>> Mirror for T {}
| --------- ^^^^^^ ^
| |
| unsatisfied trait bound introduced here
error[E0277]: the size for values of type `Self` cannot be known at compilation time
--> $DIR/ice-generics-of-crate-root-152335.rs:21:30
|
LL | <Self as Mirror>::Assoc: Super,
| ^^^^^ doesn't have a size known at compile-time
|
note: required for `Self` to implement `Mirror`
--> $DIR/ice-generics-of-crate-root-152335.rs:38:42
|
LL | impl<T: Super<ActuallySuper, Assoc = T>> Mirror for T {}
| - ^^^^^^ ^
| |
| unsatisfied trait bound implicitly introduced here
help: consider further restricting `Self`
|
LL | trait Foo<T, U>: Super<ActuallySuper, Assoc = T> + Sized
| +++++++
error[E0046]: not all trait items implemented, missing: `Assoc`
--> $DIR/ice-generics-of-crate-root-152335.rs:38:1
|
LL | type Assoc: ?Sized;
| ------------------ `Assoc` from trait
LL | }
LL | impl<T: Super<ActuallySuper, Assoc = T>> Mirror for T {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `Assoc` in implementation
error[E0271]: type mismatch resolving `<Self as Super<ActuallySuper>>::Assoc == Self`
--> $DIR/ice-generics-of-crate-root-152335.rs:27:5
|
LL | trait Foo<T, U>: Super<ActuallySuper, Assoc = T>
| ------------------------------------------------
| | |
| | found type parameter
| expected type parameter
...
LL | fn transmute(&self, t: T) -> <Self as B>::Assoc;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected type parameter `Self`, found type parameter `T`
|
= note: expected type parameter `Self`
found type parameter `T`
= note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound
= note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters
note: required for `Self` to implement `Mirror`
--> $DIR/ice-generics-of-crate-root-152335.rs:38:42
|
LL | impl<T: Super<ActuallySuper, Assoc = T>> Mirror for T {}
| --------- ^^^^^^ ^
| |
| unsatisfied trait bound introduced here
error[E0277]: the size for values of type `Self` cannot be known at compilation time
--> $DIR/ice-generics-of-crate-root-152335.rs:27:5
|
LL | fn transmute(&self, t: T) -> <Self as B>::Assoc;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
note: required for `Self` to implement `Mirror`
--> $DIR/ice-generics-of-crate-root-152335.rs:38:42
|
LL | impl<T: Super<ActuallySuper, Assoc = T>> Mirror for T {}
| - ^^^^^^ ^
| |
| unsatisfied trait bound implicitly introduced here
help: consider further restricting `Self`
|
LL | fn transmute(&self, t: T) -> <Self as B>::Assoc where Self: Sized;
| +++++++++++++++++
error[E0271]: type mismatch resolving `<Self as Super<ActuallySuper>>::Assoc == Self`
--> $DIR/ice-generics-of-crate-root-152335.rs:21:30
|
LL | trait Foo<T, U>: Super<ActuallySuper, Assoc = T>
| ------------------------------------------------
| | |
| | found type parameter
| expected type parameter
...
LL | <Self as Mirror>::Assoc: Super,
| ^^^^^ expected type parameter `Self`, found type parameter `T`
|
= note: expected type parameter `Self`
found type parameter `T`
= note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound
= note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters
note: required for `Self` to implement `Mirror`
--> $DIR/ice-generics-of-crate-root-152335.rs:38:42
|
LL | impl<T: Super<ActuallySuper, Assoc = T>> Mirror for T {}
| --------- ^^^^^^ ^
| |
| unsatisfied trait bound introduced here
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error[E0277]: the size for values of type `Self` cannot be known at compilation time
--> $DIR/ice-generics-of-crate-root-152335.rs:21:30
|
LL | <Self as Mirror>::Assoc: Super,
| ^^^^^ doesn't have a size known at compile-time
|
note: required for `Self` to implement `Mirror`
--> $DIR/ice-generics-of-crate-root-152335.rs:38:42
|
LL | impl<T: Super<ActuallySuper, Assoc = T>> Mirror for T {}
| - ^^^^^^ ^
| |
| unsatisfied trait bound implicitly introduced here
help: consider further restricting `Self`
|
LL | fn transmute(&self, t: T) -> <Self as B>::Assoc where Self: Sized;
| +++++++++++++++++
error: aborting due to 14 previous errors
Some errors have detailed explanations: E0038, E0046, E0271, E0277, E0405, E0601.
For more information about an error, try `rustc --explain E0038`.