diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs index d9ea2e005789..db3fece734da 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs @@ -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 diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs index 6bfd9c78df5d..8cd773d84224 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs @@ -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, ) { 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, 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>, - body_owner_def_id: DefId, + body_owner_def_id: Option, 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, 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); diff --git a/tests/ui/dyn-compatibility/ice-generics-of-crate-root-152335.rs b/tests/ui/dyn-compatibility/ice-generics-of-crate-root-152335.rs new file mode 100644 index 000000000000..a1d0e540b398 --- /dev/null +++ b/tests/ui/dyn-compatibility/ice-generics-of-crate-root-152335.rs @@ -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 { + type Assoc; +} + +trait Dyn {} +impl Dyn for dyn Foo + '_ {} +//~^ ERROR the trait `Foo` is not dyn compatible + +trait Foo: Super +//~^ ERROR type mismatch resolving +//~| ERROR the size for values of type `Self` cannot be known +where + ::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) -> ::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> Mirror for T {} +//~^ ERROR not all trait items implemented +//~| ERROR `main` function not found diff --git a/tests/ui/dyn-compatibility/ice-generics-of-crate-root-152335.stderr b/tests/ui/dyn-compatibility/ice-generics-of-crate-root-152335.stderr new file mode 100644 index 000000000000..cf00ee45a43e --- /dev/null +++ b/tests/ui/dyn-compatibility/ice-generics-of-crate-root-152335.stderr @@ -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) -> ::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> Mirror for T {} + | ^ consider adding a `main` function to `$DIR/ice-generics-of-crate-root-152335.rs` + +error[E0271]: type mismatch resolving `>::Assoc == Self` + --> $DIR/ice-generics-of-crate-root-152335.rs:27:5 + | +LL | fn transmute(&self, t: T) -> ::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> 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) -> ::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> 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 Dyn for dyn Foo + '_ {} + | ^^^^^^^^^^^^^^^^^^ `Foo` is not dyn compatible + | +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit + --> $DIR/ice-generics-of-crate-root-152335.rs:21:30 + | +LL | trait Foo: Super + | --- this trait is not dyn compatible... +... +LL | ::Assoc: Super, + | ^^^^^ ...because it uses `Self` as a type parameter + +error[E0271]: type mismatch resolving `>::Assoc == Self` + --> $DIR/ice-generics-of-crate-root-152335.rs:17:1 + | +LL | trait Foo: 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> 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: 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> Mirror for T {} + | - ^^^^^^ ^ + | | + | unsatisfied trait bound implicitly introduced here +help: consider further restricting `Self` + | +LL | trait Foo: Super + Sized + | +++++++ + +error[E0271]: type mismatch resolving `>::Assoc == Self` + --> $DIR/ice-generics-of-crate-root-152335.rs:21:30 + | +LL | trait Foo: Super + | ------------------------------------------------ + | | | + | | found type parameter + | expected type parameter +... +LL | ::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> 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 | ::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> Mirror for T {} + | - ^^^^^^ ^ + | | + | unsatisfied trait bound implicitly introduced here +help: consider further restricting `Self` + | +LL | trait Foo: Super + 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> Mirror for T {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `Assoc` in implementation + +error[E0271]: type mismatch resolving `>::Assoc == Self` + --> $DIR/ice-generics-of-crate-root-152335.rs:27:5 + | +LL | trait Foo: Super + | ------------------------------------------------ + | | | + | | found type parameter + | expected type parameter +... +LL | fn transmute(&self, t: T) -> ::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> 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) -> ::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> Mirror for T {} + | - ^^^^^^ ^ + | | + | unsatisfied trait bound implicitly introduced here +help: consider further restricting `Self` + | +LL | fn transmute(&self, t: T) -> ::Assoc where Self: Sized; + | +++++++++++++++++ + +error[E0271]: type mismatch resolving `>::Assoc == Self` + --> $DIR/ice-generics-of-crate-root-152335.rs:21:30 + | +LL | trait Foo: Super + | ------------------------------------------------ + | | | + | | found type parameter + | expected type parameter +... +LL | ::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> 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 | ::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> Mirror for T {} + | - ^^^^^^ ^ + | | + | unsatisfied trait bound implicitly introduced here +help: consider further restricting `Self` + | +LL | fn transmute(&self, t: T) -> ::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`.