From 03988b8e376e6c6ffa52a561bc294d7b60ad3e01 Mon Sep 17 00:00:00 2001 From: Peter-Phi-Tran Date: Sun, 5 Jul 2026 11:39:21 -0500 Subject: [PATCH 1/2] Skip virtual dispatches when collecting default impl mono items --- compiler/rustc_monomorphize/src/collector.rs | 7 +++ ...no-item-collector-dyn-self-default-impl.rs | 52 +++++++++++++++++++ 2 files changed, 59 insertions(+) create mode 100644 tests/ui/codegen/mono-item-collector-dyn-self-default-impl.rs diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index ceb044c102f69..f950594c2e03d 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -1792,6 +1792,13 @@ fn create_mono_items_for_default_impls<'tcx>( let args = trait_ref.args.extend_to(tcx, method.def_id, only_region_params); let instance = ty::Instance::expect_resolve(tcx, typing_env, method.def_id, args, DUMMY_SP); + // A provided method of an `impl Trait for dyn Trait` (written via a type alias or + // projection that normalizes to the trait object) resolves to a virtual dispatch, which + // has no MIR body. Skip it rather than ICE in `instance_mir`. See #158411. + if matches!(instance.def, ty::InstanceKind::Virtual(..)) { + continue; + } + let mono_item = create_fn_mono_item(tcx, instance, DUMMY_SP); if mono_item.node.is_instantiable(tcx) && tcx.should_codegen_locally(instance) { output.push(mono_item); diff --git a/tests/ui/codegen/mono-item-collector-dyn-self-default-impl.rs b/tests/ui/codegen/mono-item-collector-dyn-self-default-impl.rs new file mode 100644 index 0000000000000..46e12196b4df1 --- /dev/null +++ b/tests/ui/codegen/mono-item-collector-dyn-self-default-impl.rs @@ -0,0 +1,52 @@ +// Under eager mono item collection (`-Clink-dead-code`), collecting the provided method of a trait +// implemented for (a type that normalizes to) its own trait object type used to resolve the method +// to a virtual dispatch, which has no MIR body, and crashed the collector with "virtual dispatches +// have no instance MIR". Such impls are accepted by coherence, so the program should compile. +// +// Regression test for #158411. + +//@ build-pass +//@ compile-flags: -Clink-dead-code + +#![feature(lazy_type_alias)] +#![allow(incomplete_features)] + +// (1) Self type is a lazy type alias resolving to `dyn Trait` (the original #158411 repro). +pub trait Trait { + fn a(&self) {} +} +pub type Alias = dyn Trait; +impl Trait for Alias {} + +// (2) Self type is an associated type projection resolving to `dyn Bar`. This collects a *provided* +// method through a projection self type (the #141119 test only exercises a required method). +pub trait Bar { + fn b(&self) {} +} +pub trait Mirror { + type Assoc: ?Sized; +} +impl Mirror for T { + type Assoc = T; +} +impl Bar for ::Assoc {} + +// (3) Multiple provided methods with one overridden: `one` is a concrete `Item` and must still be +// collected, while the inherited `two` resolves to a (skipped) virtual dispatch. +pub trait Baz { + fn one(&self) {} + fn two(&self) {} +} +pub type BazAlias = dyn Baz; +impl Baz for BazAlias { + fn one(&self) {} +} + +// (4) Auto-trait component in the trait object type. +pub trait Qux { + fn q(&self) {} +} +pub type QuxAlias = dyn Qux + Send; +impl Qux for QuxAlias {} + +fn main() {} From fbbd735e2588b4bd8a7e8ff1c6bda36810e76658 Mon Sep 17 00:00:00 2001 From: Peter-Phi-Tran Date: Sun, 5 Jul 2026 14:05:18 -0500 Subject: [PATCH 2/2] Remove now-fixed tests/crashes entries and extend the regression test --- tests/crashes/114198-2.rs | 15 --------------- tests/crashes/114198.rs | 13 ------------- .../mono-item-collector-dyn-self-default-impl.rs | 16 +++++++++++++++- 3 files changed, 15 insertions(+), 29 deletions(-) delete mode 100644 tests/crashes/114198-2.rs delete mode 100644 tests/crashes/114198.rs diff --git a/tests/crashes/114198-2.rs b/tests/crashes/114198-2.rs deleted file mode 100644 index 56cb7d76e02d3..0000000000000 --- a/tests/crashes/114198-2.rs +++ /dev/null @@ -1,15 +0,0 @@ -//@ known-bug: #114198 -//@ compile-flags: -Zprint-mono-items -Clink-dead-code - -impl Trait for ::Struct {} -trait Trait { - fn test(&self) {} -} - -enum Ty {} -trait Owner { type Struct: ?Sized; } -impl Owner for Ty { - type Struct = dyn Trait + Send; -} - -fn main() {} diff --git a/tests/crashes/114198.rs b/tests/crashes/114198.rs deleted file mode 100644 index 0f479b3615fb0..0000000000000 --- a/tests/crashes/114198.rs +++ /dev/null @@ -1,13 +0,0 @@ -//@ known-bug: #114198 -//@ compile-flags: -Zprint-mono-items -Clink-dead-code - -#![feature(lazy_type_alias)] - -impl Trait for Struct {} -trait Trait { - fn test(&self) {} -} - -type Struct = dyn Trait + Send; - -fn main() {} diff --git a/tests/ui/codegen/mono-item-collector-dyn-self-default-impl.rs b/tests/ui/codegen/mono-item-collector-dyn-self-default-impl.rs index 46e12196b4df1..3b5df89b51bcb 100644 --- a/tests/ui/codegen/mono-item-collector-dyn-self-default-impl.rs +++ b/tests/ui/codegen/mono-item-collector-dyn-self-default-impl.rs @@ -3,7 +3,7 @@ // to a virtual dispatch, which has no MIR body, and crashed the collector with "virtual dispatches // have no instance MIR". Such impls are accepted by coherence, so the program should compile. // -// Regression test for #158411. +// Regression test for #158411 and #114198 (an earlier report of the same bug). //@ build-pass //@ compile-flags: -Clink-dead-code @@ -49,4 +49,18 @@ pub trait Qux { pub type QuxAlias = dyn Qux + Send; impl Qux for QuxAlias {} +// (5) The self type is an associated type projection on a concrete type, so it looks non-`dyn` +// until normalized (here to `dyn Corge + Send`). This form needs no feature gate. From #114198. +pub trait Corge { + fn c(&self) {} +} +enum Ty {} +trait Owner { + type Struct: ?Sized; +} +impl Owner for Ty { + type Struct = dyn Corge + Send; +} +impl Corge for ::Struct {} + fn main() {}