From f8dd4d25af497c9486a46378b5f9562463834d22 Mon Sep 17 00:00:00 2001 From: "Tim (Theemathas Chirananthavat)" Date: Sun, 21 Jun 2026 19:54:00 +0700 Subject: [PATCH 1/2] Add tests for conflicting associated type bounds with different generics. See https://github.com/rust-lang/rust/issues/154662 These tests will be fixed in a subsequent commit. --- ...ng-bounds-different-generics-legitimate.rs | 31 +++ ...icting-bounds-different-generics-simple.rs | 29 +++ ...ng-bounds-different-generics-simple.stderr | 188 ++++++++++++++++++ ...cting-bounds-different-generics-unsound.rs | 56 ++++++ 4 files changed, 304 insertions(+) create mode 100644 tests/ui/associated-type-bounds/conflicting-bounds-different-generics-legitimate.rs create mode 100644 tests/ui/associated-type-bounds/conflicting-bounds-different-generics-simple.rs create mode 100644 tests/ui/associated-type-bounds/conflicting-bounds-different-generics-simple.stderr create mode 100644 tests/ui/associated-type-bounds/conflicting-bounds-different-generics-unsound.rs diff --git a/tests/ui/associated-type-bounds/conflicting-bounds-different-generics-legitimate.rs b/tests/ui/associated-type-bounds/conflicting-bounds-different-generics-legitimate.rs new file mode 100644 index 0000000000000..56dee9bd8d293 --- /dev/null +++ b/tests/ui/associated-type-bounds/conflicting-bounds-different-generics-legitimate.rs @@ -0,0 +1,31 @@ +//@ run-pass + +// This is a legitimate use case, where the `dyn Sub` trait object ends up +// having two different "values" for `Assoc`. This is allowed because we know +// that the two values are for `Super` and `Super`, which can't +// possibly be the same trait. + +trait Super { + type Assoc; +} + +trait Sub: Super + Super { + fn method(&self) {} +} + +fn foo(x: &dyn Sub) { + x.method(); +} + +struct Thing; +impl Super for Thing { + type Assoc = u32; +} +impl Super for Thing { + type Assoc = u64; +} +impl Sub for Thing {} + +fn main() { + foo(&Thing); +} diff --git a/tests/ui/associated-type-bounds/conflicting-bounds-different-generics-simple.rs b/tests/ui/associated-type-bounds/conflicting-bounds-different-generics-simple.rs new file mode 100644 index 0000000000000..953b5480efb1e --- /dev/null +++ b/tests/ui/associated-type-bounds/conflicting-bounds-different-generics-simple.rs @@ -0,0 +1,29 @@ +//@ known-bug: #154662 +//@ failure-status: 101 +//@ compile-flags: --emit link + +// We currently accept conflicting associated type bounds with different generics, +// which results in an ICE, since those generics can be instantiated with the +// same concrete type. +// See https://github.com/rust-lang/rust/issues/154662 + +trait Super { + type Assoc; +} + +trait Sub: Super + Super { + fn method(&self) {} +} + +fn foo(x: Option<&dyn Sub>) { + if false { + x.unwrap().method(); + } +} + +fn main() { + // This ends up proving that `dyn Sub` implements `Super`. + // However, `dyn Sub` has bounds for both `Assoc = u32` and `Assoc = u64`, + // which is nonsense. + foo::(None); +} diff --git a/tests/ui/associated-type-bounds/conflicting-bounds-different-generics-simple.stderr b/tests/ui/associated-type-bounds/conflicting-bounds-different-generics-simple.stderr new file mode 100644 index 0000000000000..6a43e19c3d971 --- /dev/null +++ b/tests/ui/associated-type-bounds/conflicting-bounds-different-generics-simple.stderr @@ -0,0 +1,188 @@ +error: internal compiler error: compiler/rustc_middle/src/ty/instance.rs:616:21: failed to resolve instance for as Sub>::method + --> $DIR/conflicting-bounds-different-generics-simple.rs:20:9 + | +LL | x.unwrap().method(); + | ^^^^^^^^^^^^^^^^^^^ + + +thread 'rustc' ($TID) panicked at compiler/rustc_middle/src/ty/instance.rs:616:21: +Box +stack backtrace: + 0: begin_panic + at /rustc/0417c25868d6dfbd1c291dfeae950504faa6f790/library/std/src/panicking.rs:761:5 + 1: panic_any + at /rustc/0417c25868d6dfbd1c291dfeae950504faa6f790/library/std/src/panic.rs:260:5 + 2: emit_producing_guarantee + at ./compiler/rustc_errors/src/diagnostic.rs:59:9 + 3: emit + at ./compiler/rustc_errors/src/diagnostic.rs:1295:9 + 4: span_bug + at ./compiler/rustc_errors/src/lib.rs:974:48 + 5: {closure#0} + at ./compiler/rustc_middle/src/util/bug.rs:38:54 + 6: {closure#0}, !> + at ./compiler/rustc_middle/src/ty/context/tls.rs:109:23 + 7: with_context_opt, !>, !> + at ./compiler/rustc_middle/src/ty/context/tls.rs:75:18 + 8: with_opt, !> + at ./compiler/rustc_middle/src/ty/context/tls.rs:107:5 + 9: opt_span_bug_fmt + at ./compiler/rustc_middle/src/util/bug.rs:33:5 + 10: span_bug_fmt + at ./compiler/rustc_middle/src/util/bug.rs:24:5 + 11: expect_resolve + at ./compiler/rustc_middle/src/macros.rs:34:9 + 12: visit_mentioned_item + at ./compiler/rustc_monomorphize/src/collector.rs:1393:32 + 13: collect_items_of_instance + at ./compiler/rustc_monomorphize/src/collector.rs:1360:13 + 14: items_of_instance + at ./compiler/rustc_monomorphize/src/collector.rs:1374:41 + [... omitted 16 frames ...] + 15: query_get_at>> + at ./compiler/rustc_middle/src/query/inner.rs:45:17 + 16: items_of_instance + at ./compiler/rustc_middle/src/query/plumbing.rs:564:46 + 17: items_of_instance + at ./compiler/rustc_middle/src/query/plumbing.rs:552:39 + 18: {closure#0} + at ./compiler/rustc_monomorphize/src/collector.rs:475:49 + 19: maybe_grow<(), rustc_monomorphize::collector::collect_items_rec::{closure_env#0}> + at /Users/timc/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/stacker-0.1.21/src/lib.rs:57:9 + 20: ensure_sufficient_stack<(), rustc_monomorphize::collector::collect_items_rec::{closure_env#0}> + at ./compiler/rustc_data_structures/src/stack.rs:21:5 + 21: collect_items_rec + at ./compiler/rustc_monomorphize/src/collector.rs:474:13 + 22: collect_items_rec + at ./compiler/rustc_monomorphize/src/collector.rs:590:13 + 23: collect_items_root + at ./compiler/rustc_monomorphize/src/collector.rs:365:5 + 24: {closure#0} + at ./compiler/rustc_monomorphize/src/collector.rs:1828:13 + 25: {closure#0}, rustc_monomorphize::collector::collect_crate_mono_items::{closure#1}::{closure_env#0}> + at ./compiler/rustc_data_structures/src/sync/parallel.rs:182:30 + 26: call_once<(), rustc_data_structures::sync::parallel::par_for_each_in::{closure#0}::{closure#1}::{closure_env#0}, rustc_monomorphize::collector::collect_crate_mono_items::{closure#1}::{closure_env#0}>> + at /rustc/0417c25868d6dfbd1c291dfeae950504faa6f790/library/core/src/panic/unwind_safe.rs:275:9 + 27: do_call, rustc_monomorphize::collector::collect_crate_mono_items::{closure#1}::{closure_env#0}>>, ()> + at /rustc/0417c25868d6dfbd1c291dfeae950504faa6f790/library/std/src/panicking.rs:581:40 + 28: catch_unwind<(), core::panic::unwind_safe::AssertUnwindSafe, rustc_monomorphize::collector::collect_crate_mono_items::{closure#1}::{closure_env#0}>>> + at /rustc/0417c25868d6dfbd1c291dfeae950504faa6f790/library/std/src/panicking.rs:544:19 + 29: catch_unwind, rustc_monomorphize::collector::collect_crate_mono_items::{closure#1}::{closure_env#0}>>, ()> + at /rustc/0417c25868d6dfbd1c291dfeae950504faa6f790/library/std/src/panic.rs:359:14 + 30: run<(), rustc_data_structures::sync::parallel::par_for_each_in::{closure#0}::{closure#1}::{closure_env#0}, rustc_monomorphize::collector::collect_crate_mono_items::{closure#1}::{closure_env#0}>> + at ./compiler/rustc_data_structures/src/sync/parallel.rs:23:9 + 31: {closure#1}, rustc_monomorphize::collector::collect_crate_mono_items::{closure#1}::{closure_env#0}> + at ./compiler/rustc_data_structures/src/sync/parallel.rs:182:23 + 32: {closure#0}, rustc_monomorphize::collector::collect_crate_mono_items::{closure#1}::{closure_env#0}>> + at /rustc/0417c25868d6dfbd1c291dfeae950504faa6f790/library/core/src/iter/traits/iterator.rs:884:29 + 33: fold, rustc_monomorphize::collector::collect_crate_mono_items::{closure#1}::{closure_env#0}>>> + at /rustc/0417c25868d6dfbd1c291dfeae950504faa6f790/library/alloc/src/vec/into_iter.rs:367:25 + 34: for_each, rustc_data_structures::sync::parallel::par_for_each_in::{closure#0}::{closure_env#1}, rustc_monomorphize::collector::collect_crate_mono_items::{closure#1}::{closure_env#0}>> + at /rustc/0417c25868d6dfbd1c291dfeae950504faa6f790/library/core/src/iter/traits/iterator.rs:887:14 + 35: {closure#0}, rustc_monomorphize::collector::collect_crate_mono_items::{closure#1}::{closure_env#0}> + at ./compiler/rustc_data_structures/src/sync/parallel.rs:181:27 + 36: parallel_guard<(), rustc_data_structures::sync::parallel::par_for_each_in::{closure_env#0}, rustc_monomorphize::collector::collect_crate_mono_items::{closure#1}::{closure_env#0}>> + at ./compiler/rustc_data_structures/src/sync/parallel.rs:39:15 + 37: par_for_each_in, rustc_monomorphize::collector::collect_crate_mono_items::{closure#1}::{closure_env#0}> + at ./compiler/rustc_data_structures/src/sync/parallel.rs:176:5 + 38: {closure#1} + at ./compiler/rustc_monomorphize/src/collector.rs:1827:9 + 39: run<(), rustc_monomorphize::collector::collect_crate_mono_items::{closure_env#1}> + at ./compiler/rustc_data_structures/src/profiling.rs:845:9 + 40: time<(), rustc_monomorphize::collector::collect_crate_mono_items::{closure_env#1}> + at ./compiler/rustc_session/src/utils.rs:17:50 + 41: collect_crate_mono_items + at ./compiler/rustc_monomorphize/src/collector.rs:1826:14 + 42: collect_and_partition_mono_items + at ./compiler/rustc_monomorphize/src/partitioning.rs:1138:30 + [... omitted 16 frames ...] + 43: query_get_at>> + at ./compiler/rustc_middle/src/query/inner.rs:45:17 + 44: collect_and_partition_mono_items + at ./compiler/rustc_middle/src/query/plumbing.rs:564:46 + 45: collect_and_partition_mono_items + at ./compiler/rustc_middle/src/query/plumbing.rs:552:39 + 46: codegen_crate + at ./compiler/rustc_codegen_ssa/src/base.rs:713:56 + 47: codegen_crate + at ./compiler/rustc_codegen_llvm/src/lib.rs:351:18 + 48: {closure#0} + at ./compiler/rustc_interface/src/passes.rs:1305:29 + 49: run, rustc_interface::passes::start_codegen::{closure_env#0}> + at ./compiler/rustc_data_structures/src/profiling.rs:845:9 + 50: time, rustc_interface::passes::start_codegen::{closure_env#0}> + at ./compiler/rustc_session/src/utils.rs:17:50 + 51: start_codegen + at ./compiler/rustc_interface/src/passes.rs:1297:28 + 52: codegen_and_build_linker + at ./compiler/rustc_interface/src/queries.rs:33:55 + 53: {closure#2} + at ./compiler/rustc_driver_impl/src/lib.rs:342:26 + 54: {closure#0}, rustc_driver_impl::run_compiler::{closure#0}::{closure_env#2}> + at ./compiler/rustc_interface/src/passes.rs:1035:80 + 55: call_once, rustc_interface::passes::create_and_enter_global_ctxt::{closure#2}::{closure_env#0}, rustc_driver_impl::run_compiler::{closure#0}::{closure_env#2}>> + at /rustc/0417c25868d6dfbd1c291dfeae950504faa6f790/library/core/src/panic/unwind_safe.rs:275:9 + 56: do_call, rustc_driver_impl::run_compiler::{closure#0}::{closure_env#2}>>, core::option::Option> + at /rustc/0417c25868d6dfbd1c291dfeae950504faa6f790/library/std/src/panicking.rs:581:40 + 57: catch_unwind, core::panic::unwind_safe::AssertUnwindSafe, rustc_driver_impl::run_compiler::{closure#0}::{closure_env#2}>>> + at /rustc/0417c25868d6dfbd1c291dfeae950504faa6f790/library/std/src/panicking.rs:544:19 + 58: catch_unwind, rustc_driver_impl::run_compiler::{closure#0}::{closure_env#2}>>, core::option::Option> + at /rustc/0417c25868d6dfbd1c291dfeae950504faa6f790/library/std/src/panic.rs:359:14 + 59: {closure#2}, rustc_driver_impl::run_compiler::{closure#0}::{closure_env#2}> + at ./compiler/rustc_interface/src/passes.rs:1035:23 + 60: {closure#1}, rustc_driver_impl::run_compiler::{closure#0}::{closure_env#2}>, core::option::Option> + at ./compiler/rustc_middle/src/ty/context.rs:802:37 + 61: {closure#0}, rustc_driver_impl::run_compiler::{closure#0}::{closure_env#2}>, core::option::Option>, core::option::Option> + at ./compiler/rustc_middle/src/ty/context/tls.rs:56:9 + 62: try_with, rustc_middle::ty::context::tls::enter_context::{closure_env#0}, rustc_driver_impl::run_compiler::{closure#0}::{closure_env#2}>, core::option::Option>, core::option::Option>, core::option::Option> + at /rustc/0417c25868d6dfbd1c291dfeae950504faa6f790/library/std/src/thread/local.rs:462:12 + 63: with, rustc_middle::ty::context::tls::enter_context::{closure_env#0}, rustc_driver_impl::run_compiler::{closure#0}::{closure_env#2}>, core::option::Option>, core::option::Option>, core::option::Option> + at /rustc/0417c25868d6dfbd1c291dfeae950504faa6f790/library/std/src/thread/local.rs:426:20 + 64: enter_context, rustc_driver_impl::run_compiler::{closure#0}::{closure_env#2}>, core::option::Option>, core::option::Option> + at ./compiler/rustc_middle/src/ty/context/tls.rs:53:9 + 65: enter, rustc_driver_impl::run_compiler::{closure#0}::{closure_env#2}>, core::option::Option> + at ./compiler/rustc_middle/src/ty/context.rs:802:9 + 66: create_global_ctxt, rustc_interface::passes::create_and_enter_global_ctxt::{closure_env#2}, rustc_driver_impl::run_compiler::{closure#0}::{closure_env#2}>> + at ./compiler/rustc_middle/src/ty/context.rs:996:13 + 67: create_and_enter_global_ctxt, rustc_driver_impl::run_compiler::{closure#0}::{closure_env#2}> + at ./compiler/rustc_interface/src/passes.rs:995:5 + 68: {closure#0} + at ./compiler/rustc_driver_impl/src/lib.rs:299:22 + 69: {closure#0}<(), rustc_driver_impl::run_compiler::{closure_env#0}> + at ./compiler/rustc_interface/src/interface.rs:496:80 + 70: call_once<(), rustc_interface::interface::run_compiler::{closure#1}::{closure_env#0}<(), rustc_driver_impl::run_compiler::{closure_env#0}>> + at /rustc/0417c25868d6dfbd1c291dfeae950504faa6f790/library/core/src/panic/unwind_safe.rs:275:9 + 71: do_call>, ()> + at /rustc/0417c25868d6dfbd1c291dfeae950504faa6f790/library/std/src/panicking.rs:581:40 + 72: catch_unwind<(), core::panic::unwind_safe::AssertUnwindSafe>> + at /rustc/0417c25868d6dfbd1c291dfeae950504faa6f790/library/std/src/panicking.rs:544:19 + 73: catch_unwind>, ()> + at /rustc/0417c25868d6dfbd1c291dfeae950504faa6f790/library/std/src/panic.rs:359:14 + 74: {closure#1}<(), rustc_driver_impl::run_compiler::{closure_env#0}> + at ./compiler/rustc_interface/src/interface.rs:496:23 + 75: {closure#0}, ()> + at ./compiler/rustc_interface/src/util.rs:206:17 + 76: {closure#0}, ()>, ()> + at ./compiler/rustc_interface/src/util.rs:162:24 + 77: set, ()>, ()>, ()> + at /Users/timc/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/scoped-tls-1.0.1/src/lib.rs:137:9 + 78: create_session_globals_then<(), rustc_interface::util::run_in_thread_with_globals::{closure#0}::{closure#0}::{closure_env#0}, ()>, ()>> + at ./compiler/rustc_span/src/lib.rs:155:21 + 79: {closure#0}, ()>, ()> + at ./compiler/rustc_interface/src/util.rs:158:17 +note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace. + +note: we would appreciate a bug report: https://github.com/rust-lang/rust/issues/new?labels=C-bug%2C+I-ICE%2C+T-compiler&template=ice.md + +note: please make sure that you have updated to the latest nightly + +note: rustc 1.99.0-dev running on aarch64-apple-darwin + +note: compiler flags: -Z threads=1 -Z simulate-remapped-rust-src-base=/rustc/FAKE_PREFIX -Z translate-remapped-path-to-local-path=no -Z ignore-directory-in-diagnostics-source-blocks=/Users/timc/.cargo -Z ignore-directory-in-diagnostics-source-blocks=/Users/timc/rust/vendor -C codegen-units=1 -Z ui-testing -Z deduplicate-diagnostics=no -Z write-long-types-to-disk=no -C strip=debuginfo -C prefer-dynamic -C rpath -C debuginfo=0 + +query stack during panic: +#0 [items_of_instance] collecting items used by `foo::` +#1 [collect_and_partition_mono_items] collect_and_partition_mono_items +end of query stack +error: aborting due to 1 previous error + diff --git a/tests/ui/associated-type-bounds/conflicting-bounds-different-generics-unsound.rs b/tests/ui/associated-type-bounds/conflicting-bounds-different-generics-unsound.rs new file mode 100644 index 0000000000000..39a78211d4d05 --- /dev/null +++ b/tests/ui/associated-type-bounds/conflicting-bounds-different-generics-unsound.rs @@ -0,0 +1,56 @@ +//@ build-pass + +// We currently accept conflicting associated type bounds with different generics, +// which results in unsoundness, since those generics can be instantiated with the +// same concrete type. +// See https://github.com/rust-lang/rust/issues/154662 + +type Payload = Box; +type Src<'a> = &'a Payload; +type Dst = &'static Payload; + +trait Super { + type Assoc; +} + +trait Sub<'a, A1, A2>: Super> + Super {} + +trait Callback { + fn callback + Super + ?Sized>( + payload: >::Assoc, + ) -> >::Assoc; +} +struct CallbackStruct; +impl Callback for CallbackStruct { + fn callback + ?Sized>(payload: U::Assoc) -> U::Assoc { + payload + } +} + +fn require_trait< + 'a, + A1, + A2, + U: Super> + Super + ?Sized, + C: Callback, +>( + payload: Src<'a>, +) -> Dst { + C::callback::(payload) +} + +fn use_dyn<'a, A1, A2, C: Callback>(payload: Src<'a>) -> Dst { + require_trait::<'a, A1, A2, dyn Sub<'a, A1, A2>, C>(payload) +} + +fn extend<'a>(payload: Src<'a>) -> Dst { + // `dyn Sub<'a, i16, i16>` has both an `Assoc = Src<'a>` bound and an `Assoc = Dst` bound. + use_dyn::(payload) +} + +fn main() { + let payload: Box = Box::new(Box::new(1)); + let wrong: &'static Payload = extend(&*payload); + drop(payload); + println!("{wrong}"); +} From 256670e715c16bae510f4d7241ea42aaaf79fefc Mon Sep 17 00:00:00 2001 From: "Tim (Theemathas Chirananthavat)" Date: Tue, 7 Jul 2026 21:57:53 +0700 Subject: [PATCH 2/2] Require coherence of supertrait associated item bounds for dyn-compability Fixes https://github.com/rust-lang/rust/issues/154662 In a `dyn` type, if multiple bounds are specified via supertraits for the same associated item, then we previously accepted them if the relevant trait's generics are different, even if the bounds conflict. This was unsound, since those generics could end up being instantiated with identical concrete types, causing the `dyn` type to have two different "values" for the same bound. Thus, if a trait has multiple supertrait bounds for the same associated item, we check whether those bounds are coherent, similarly to how we check for overlap between impulse (i.e., we check if the generics could be instantiated to be the same while the "values" of the bounds are different). If the bounds are incoherent, then we consider the trait to be dyn-incompatible. --- compiler/rustc_middle/src/traits/mod.rs | 28 ++- .../src/traits/dyn_compatibility.rs | 97 +++++++- ...icting-bounds-different-generics-simple.rs | 7 +- ...ng-bounds-different-generics-simple.stderr | 231 ++++-------------- ...cting-bounds-different-generics-unsound.rs | 3 +- ...g-bounds-different-generics-unsound.stderr | 19 ++ .../multiple-supers-should-work.rs | 4 +- .../multiple-supers-should-work.stderr | 37 +++ .../normalize-under-binder/issue-81809.rs | 4 +- .../normalize-under-binder/issue-81809.stderr | 37 +++ .../traits/next-solver/supertrait-alias-4.rs | 3 +- .../next-solver/supertrait-alias-4.stderr | 35 +++ ...n-projection-output-repeated-supertrait.rs | 4 +- ...ojection-output-repeated-supertrait.stderr | 37 +++ 14 files changed, 343 insertions(+), 203 deletions(-) create mode 100644 tests/ui/associated-type-bounds/conflicting-bounds-different-generics-unsound.stderr create mode 100644 tests/ui/dyn-compatibility/multiple-supers-should-work.stderr create mode 100644 tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-81809.stderr create mode 100644 tests/ui/traits/next-solver/supertrait-alias-4.stderr create mode 100644 tests/ui/traits/object/with-self-in-projection-output-repeated-supertrait.stderr diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index 4cd124248e093..48dfc813eb8e0 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -782,6 +782,24 @@ pub enum DynCompatibilityViolation { /// Generic associated type (GAT). GenericAssocTy(Symbol, Span), + + /// We consider a trait dyn-incompatible if it has supertrait bounds that + /// include two associated type/const bounds on the same associated type/const + /// `DefId`, and have generics that could be instantiated into the same concrete + /// types, but the bounds may have unequal terms. + /// + /// Trait objects from such traits could otherwise be instantiated into + /// a concrete type with conflicting associated types, violating coherence, + /// which is unsound. See #154662. + /// + /// Checking this predicate is conceptually like checking for + /// the coherence of the builtin impls for `dyn`, to make sure that the + /// associated type/const don't conflict with each other between the impls. + // + // FIXME: Improve diagnostics for this. + // * Tell the user the exact projections involved that are in conflict + // * Point to where the projection bound was written + IncoherentSupertraitAssocs(Symbol, Span), } impl DynCompatibilityViolation { @@ -851,6 +869,10 @@ impl DynCompatibilityViolation { Self::GenericAssocTy(name, _) => { format!("it contains generic associated type `{name}`").into() } + Self::IncoherentSupertraitAssocs(name, _) => { + format!("it has conflicting associated item bounds for {name} in supertraits") + .into() + } } } @@ -860,7 +882,8 @@ impl DynCompatibilityViolation { | Self::SizedSelf(_) | Self::SupertraitSelf(_) | Self::SupertraitNonLifetimeBinder(..) - | Self::SupertraitConst(_) => DynCompatibilityViolationSolution::None, + | Self::SupertraitConst(_) + | Self::IncoherentSupertraitAssocs(..) => DynCompatibilityViolationSolution::None, Self::Method( name, MethodViolation::StaticMethod(Some((add_self_sugg, make_sized_sugg))), @@ -890,7 +913,8 @@ impl DynCompatibilityViolation { | Self::SupertraitConst(spans) => spans.clone(), Self::Method(_, _, span) | Self::AssocConst(_, _, span) - | Self::GenericAssocTy(_, span) => { + | Self::GenericAssocTy(_, span) + | Self::IncoherentSupertraitAssocs(_, span) => { if *span != DUMMY_SP { smallvec![*span] } else { diff --git a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs index 7b45dfe48a7fe..354170e18cb50 100644 --- a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs +++ b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs @@ -6,14 +6,17 @@ use std::ops::ControlFlow; +use itertools::Itertools; +use rustc_data_structures::fx::FxHashMap; use rustc_errors::FatalError; use rustc_hir::def_id::DefId; use rustc_hir::{self as hir, LangItem}; +use rustc_infer::infer::{BoundRegionConversionTime, DefineOpaqueTypes}; use rustc_middle::query::Providers; use rustc_middle::ty::{ - self, EarlyBinder, GenericArgs, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, - TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, TypingMode, Unnormalized, - Upcast, elaborate, + self, Clause, EarlyBinder, GenericArgs, PolyProjectionPredicate, Ty, TyCtxt, TypeFoldable, + TypeFolder, TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, + TypeVisitor, TypingMode, Unnormalized, Upcast, elaborate, }; use rustc_span::{DUMMY_SP, Span}; use smallvec::SmallVec; @@ -54,7 +57,8 @@ fn dyn_compatibility_violations( debug!("dyn_compatibility_violations: {:?}", trait_def_id); tcx.arena.alloc_from_iter( elaborate::supertrait_def_ids(tcx, trait_def_id) - .flat_map(|def_id| dyn_compatibility_violations_for_trait(tcx, def_id)), + .flat_map(|def_id| dyn_compatibility_violations_for_trait(tcx, def_id)) + .chain(incoherent_supertrait_assocs(tcx, trait_def_id)), ) } @@ -978,6 +982,91 @@ impl<'tcx> TypeVisitor> for IllegalRpititVisitor<'tcx> { } } +/// Computes [`DynCompatibilityViolation::IncoherentSupertraitAssocs`] +#[instrument(level = "debug", skip(tcx))] +fn incoherent_supertrait_assocs( + tcx: TyCtxt<'_>, + trait_def_id: DefId, +) -> impl Iterator { + let predicates = tcx + .predicates_of(trait_def_id) + .instantiate_identity(tcx) + .predicates + .into_iter() + .map(Unnormalized::skip_normalization); + // Map from associated items to projection predicates that apply to them. + let mut preds_for_assoc = FxHashMap::>>::default(); + elaborate(tcx, predicates).filter_map(Clause::as_projection_clause).flat_map(move |proj| { + let prev_projs = preds_for_assoc.entry(proj.item_def_id()).or_default(); + let violations: Vec<_> = prev_projs + .iter() + .copied() + .filter(move |&prev_proj| { + !does_pair_have_coherent_supertrait_assocs(tcx, trait_def_id, prev_proj, proj) + }) + .map(move |_| { + DynCompatibilityViolation::IncoherentSupertraitAssocs( + tcx.item_name(proj.item_def_id()), + tcx.def_ident_span(proj.item_def_id()) + .expect("Associated items should have a def_ident_span"), + ) + }) + .collect(); + prev_projs.push(proj); + violations + }) +} + +#[instrument(level = "debug", skip(tcx), ret)] +fn does_pair_have_coherent_supertrait_assocs<'tcx>( + tcx: TyCtxt<'tcx>, + trait_def_id: DefId, + proj_1: PolyProjectionPredicate<'tcx>, + proj_2: PolyProjectionPredicate<'tcx>, +) -> bool { + // We syntactically compare the two terms. If they're equal, then + // they do not conflict with each other. + // FIXME: This is an overly strict definition of equality. Could this be done better? + if proj_1.term() == proj_2.term() { + return true; + } + + let infcx = tcx + .infer_ctxt() + .with_next_trait_solver(tcx.next_trait_solver_in_coherence()) + .build(TypingMode::Coherence); + // We instantiate type parameters in the two projections with the same + // fresh inference variables. + let trait_args = infcx.fresh_args_for_item(DUMMY_SP, trait_def_id); + let process_proj = |proj: PolyProjectionPredicate<'tcx>| { + let instantiated_proj = EarlyBinder::bind(tcx, proj).instantiate(tcx, trait_args); + infcx.instantiate_binder_with_fresh_vars( + DUMMY_SP, + BoundRegionConversionTime::AssocTypeProjection(proj.item_def_id()), + // FIXME: Normalizing here could maybe make more code compile? + instantiated_proj.skip_normalization(), + ) + }; + let proj_1 = process_proj(proj_1); + let proj_2 = process_proj(proj_2); + assert_eq!( + proj_1.projection_term.kind, proj_2.projection_term.kind, + "should compare the same projection kind" + ); + proj_1.projection_term.args.iter().zip_eq(proj_2.projection_term.args).any(|(arg_1, arg_2)| { + // Note that we discard any obligations we get here. + // We don't care about proving them. + // + // If this call returns an Err, then the two sets of generic args + // can't possibly be instantiated with the same concrete types. + // So, we return true from the function + infcx + .at(&ObligationCause::dummy(), tcx.param_env(trait_def_id)) + .eq(DefineOpaqueTypes::Yes, arg_1, arg_2) + .is_err() + }) +} + pub(crate) fn provide(providers: &mut Providers) { *providers = Providers { dyn_compatibility_violations, diff --git a/tests/ui/associated-type-bounds/conflicting-bounds-different-generics-simple.rs b/tests/ui/associated-type-bounds/conflicting-bounds-different-generics-simple.rs index 953b5480efb1e..e37f0fe363b83 100644 --- a/tests/ui/associated-type-bounds/conflicting-bounds-different-generics-simple.rs +++ b/tests/ui/associated-type-bounds/conflicting-bounds-different-generics-simple.rs @@ -1,7 +1,3 @@ -//@ known-bug: #154662 -//@ failure-status: 101 -//@ compile-flags: --emit link - // We currently accept conflicting associated type bounds with different generics, // which results in an ICE, since those generics can be instantiated with the // same concrete type. @@ -16,8 +12,10 @@ trait Sub: Super + Super { } fn foo(x: Option<&dyn Sub>) { + //~^ ERROR the trait `Sub` is not dyn compatible if false { x.unwrap().method(); + //~^ ERROR the trait `Sub` is not dyn compatible } } @@ -26,4 +24,5 @@ fn main() { // However, `dyn Sub` has bounds for both `Assoc = u32` and `Assoc = u64`, // which is nonsense. foo::(None); + //~^ ERROR the trait `Sub` is not dyn compatible } diff --git a/tests/ui/associated-type-bounds/conflicting-bounds-different-generics-simple.stderr b/tests/ui/associated-type-bounds/conflicting-bounds-different-generics-simple.stderr index 6a43e19c3d971..df2e82b1d9d4f 100644 --- a/tests/ui/associated-type-bounds/conflicting-bounds-different-generics-simple.stderr +++ b/tests/ui/associated-type-bounds/conflicting-bounds-different-generics-simple.stderr @@ -1,188 +1,51 @@ -error: internal compiler error: compiler/rustc_middle/src/ty/instance.rs:616:21: failed to resolve instance for as Sub>::method - --> $DIR/conflicting-bounds-different-generics-simple.rs:20:9 +error[E0038]: the trait `Sub` is not dyn compatible + --> $DIR/conflicting-bounds-different-generics-simple.rs:14:25 + | +LL | fn foo(x: Option<&dyn Sub>) { + | ^^^^^^^^^^^^^ `Sub` is not dyn compatible + | +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit + --> $DIR/conflicting-bounds-different-generics-simple.rs:7:10 + | +LL | type Assoc; + | ^^^^^ ...because it has conflicting associated item bounds for Assoc in supertraits +... +LL | trait Sub: Super + Super { + | --- this trait is not dyn compatible... + +error[E0038]: the trait `Sub` is not dyn compatible + --> $DIR/conflicting-bounds-different-generics-simple.rs:17:9 | LL | x.unwrap().method(); - | ^^^^^^^^^^^^^^^^^^^ - - -thread 'rustc' ($TID) panicked at compiler/rustc_middle/src/ty/instance.rs:616:21: -Box -stack backtrace: - 0: begin_panic - at /rustc/0417c25868d6dfbd1c291dfeae950504faa6f790/library/std/src/panicking.rs:761:5 - 1: panic_any - at /rustc/0417c25868d6dfbd1c291dfeae950504faa6f790/library/std/src/panic.rs:260:5 - 2: emit_producing_guarantee - at ./compiler/rustc_errors/src/diagnostic.rs:59:9 - 3: emit - at ./compiler/rustc_errors/src/diagnostic.rs:1295:9 - 4: span_bug - at ./compiler/rustc_errors/src/lib.rs:974:48 - 5: {closure#0} - at ./compiler/rustc_middle/src/util/bug.rs:38:54 - 6: {closure#0}, !> - at ./compiler/rustc_middle/src/ty/context/tls.rs:109:23 - 7: with_context_opt, !>, !> - at ./compiler/rustc_middle/src/ty/context/tls.rs:75:18 - 8: with_opt, !> - at ./compiler/rustc_middle/src/ty/context/tls.rs:107:5 - 9: opt_span_bug_fmt - at ./compiler/rustc_middle/src/util/bug.rs:33:5 - 10: span_bug_fmt - at ./compiler/rustc_middle/src/util/bug.rs:24:5 - 11: expect_resolve - at ./compiler/rustc_middle/src/macros.rs:34:9 - 12: visit_mentioned_item - at ./compiler/rustc_monomorphize/src/collector.rs:1393:32 - 13: collect_items_of_instance - at ./compiler/rustc_monomorphize/src/collector.rs:1360:13 - 14: items_of_instance - at ./compiler/rustc_monomorphize/src/collector.rs:1374:41 - [... omitted 16 frames ...] - 15: query_get_at>> - at ./compiler/rustc_middle/src/query/inner.rs:45:17 - 16: items_of_instance - at ./compiler/rustc_middle/src/query/plumbing.rs:564:46 - 17: items_of_instance - at ./compiler/rustc_middle/src/query/plumbing.rs:552:39 - 18: {closure#0} - at ./compiler/rustc_monomorphize/src/collector.rs:475:49 - 19: maybe_grow<(), rustc_monomorphize::collector::collect_items_rec::{closure_env#0}> - at /Users/timc/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/stacker-0.1.21/src/lib.rs:57:9 - 20: ensure_sufficient_stack<(), rustc_monomorphize::collector::collect_items_rec::{closure_env#0}> - at ./compiler/rustc_data_structures/src/stack.rs:21:5 - 21: collect_items_rec - at ./compiler/rustc_monomorphize/src/collector.rs:474:13 - 22: collect_items_rec - at ./compiler/rustc_monomorphize/src/collector.rs:590:13 - 23: collect_items_root - at ./compiler/rustc_monomorphize/src/collector.rs:365:5 - 24: {closure#0} - at ./compiler/rustc_monomorphize/src/collector.rs:1828:13 - 25: {closure#0}, rustc_monomorphize::collector::collect_crate_mono_items::{closure#1}::{closure_env#0}> - at ./compiler/rustc_data_structures/src/sync/parallel.rs:182:30 - 26: call_once<(), rustc_data_structures::sync::parallel::par_for_each_in::{closure#0}::{closure#1}::{closure_env#0}, rustc_monomorphize::collector::collect_crate_mono_items::{closure#1}::{closure_env#0}>> - at /rustc/0417c25868d6dfbd1c291dfeae950504faa6f790/library/core/src/panic/unwind_safe.rs:275:9 - 27: do_call, rustc_monomorphize::collector::collect_crate_mono_items::{closure#1}::{closure_env#0}>>, ()> - at /rustc/0417c25868d6dfbd1c291dfeae950504faa6f790/library/std/src/panicking.rs:581:40 - 28: catch_unwind<(), core::panic::unwind_safe::AssertUnwindSafe, rustc_monomorphize::collector::collect_crate_mono_items::{closure#1}::{closure_env#0}>>> - at /rustc/0417c25868d6dfbd1c291dfeae950504faa6f790/library/std/src/panicking.rs:544:19 - 29: catch_unwind, rustc_monomorphize::collector::collect_crate_mono_items::{closure#1}::{closure_env#0}>>, ()> - at /rustc/0417c25868d6dfbd1c291dfeae950504faa6f790/library/std/src/panic.rs:359:14 - 30: run<(), rustc_data_structures::sync::parallel::par_for_each_in::{closure#0}::{closure#1}::{closure_env#0}, rustc_monomorphize::collector::collect_crate_mono_items::{closure#1}::{closure_env#0}>> - at ./compiler/rustc_data_structures/src/sync/parallel.rs:23:9 - 31: {closure#1}, rustc_monomorphize::collector::collect_crate_mono_items::{closure#1}::{closure_env#0}> - at ./compiler/rustc_data_structures/src/sync/parallel.rs:182:23 - 32: {closure#0}, rustc_monomorphize::collector::collect_crate_mono_items::{closure#1}::{closure_env#0}>> - at /rustc/0417c25868d6dfbd1c291dfeae950504faa6f790/library/core/src/iter/traits/iterator.rs:884:29 - 33: fold, rustc_monomorphize::collector::collect_crate_mono_items::{closure#1}::{closure_env#0}>>> - at /rustc/0417c25868d6dfbd1c291dfeae950504faa6f790/library/alloc/src/vec/into_iter.rs:367:25 - 34: for_each, rustc_data_structures::sync::parallel::par_for_each_in::{closure#0}::{closure_env#1}, rustc_monomorphize::collector::collect_crate_mono_items::{closure#1}::{closure_env#0}>> - at /rustc/0417c25868d6dfbd1c291dfeae950504faa6f790/library/core/src/iter/traits/iterator.rs:887:14 - 35: {closure#0}, rustc_monomorphize::collector::collect_crate_mono_items::{closure#1}::{closure_env#0}> - at ./compiler/rustc_data_structures/src/sync/parallel.rs:181:27 - 36: parallel_guard<(), rustc_data_structures::sync::parallel::par_for_each_in::{closure_env#0}, rustc_monomorphize::collector::collect_crate_mono_items::{closure#1}::{closure_env#0}>> - at ./compiler/rustc_data_structures/src/sync/parallel.rs:39:15 - 37: par_for_each_in, rustc_monomorphize::collector::collect_crate_mono_items::{closure#1}::{closure_env#0}> - at ./compiler/rustc_data_structures/src/sync/parallel.rs:176:5 - 38: {closure#1} - at ./compiler/rustc_monomorphize/src/collector.rs:1827:9 - 39: run<(), rustc_monomorphize::collector::collect_crate_mono_items::{closure_env#1}> - at ./compiler/rustc_data_structures/src/profiling.rs:845:9 - 40: time<(), rustc_monomorphize::collector::collect_crate_mono_items::{closure_env#1}> - at ./compiler/rustc_session/src/utils.rs:17:50 - 41: collect_crate_mono_items - at ./compiler/rustc_monomorphize/src/collector.rs:1826:14 - 42: collect_and_partition_mono_items - at ./compiler/rustc_monomorphize/src/partitioning.rs:1138:30 - [... omitted 16 frames ...] - 43: query_get_at>> - at ./compiler/rustc_middle/src/query/inner.rs:45:17 - 44: collect_and_partition_mono_items - at ./compiler/rustc_middle/src/query/plumbing.rs:564:46 - 45: collect_and_partition_mono_items - at ./compiler/rustc_middle/src/query/plumbing.rs:552:39 - 46: codegen_crate - at ./compiler/rustc_codegen_ssa/src/base.rs:713:56 - 47: codegen_crate - at ./compiler/rustc_codegen_llvm/src/lib.rs:351:18 - 48: {closure#0} - at ./compiler/rustc_interface/src/passes.rs:1305:29 - 49: run, rustc_interface::passes::start_codegen::{closure_env#0}> - at ./compiler/rustc_data_structures/src/profiling.rs:845:9 - 50: time, rustc_interface::passes::start_codegen::{closure_env#0}> - at ./compiler/rustc_session/src/utils.rs:17:50 - 51: start_codegen - at ./compiler/rustc_interface/src/passes.rs:1297:28 - 52: codegen_and_build_linker - at ./compiler/rustc_interface/src/queries.rs:33:55 - 53: {closure#2} - at ./compiler/rustc_driver_impl/src/lib.rs:342:26 - 54: {closure#0}, rustc_driver_impl::run_compiler::{closure#0}::{closure_env#2}> - at ./compiler/rustc_interface/src/passes.rs:1035:80 - 55: call_once, rustc_interface::passes::create_and_enter_global_ctxt::{closure#2}::{closure_env#0}, rustc_driver_impl::run_compiler::{closure#0}::{closure_env#2}>> - at /rustc/0417c25868d6dfbd1c291dfeae950504faa6f790/library/core/src/panic/unwind_safe.rs:275:9 - 56: do_call, rustc_driver_impl::run_compiler::{closure#0}::{closure_env#2}>>, core::option::Option> - at /rustc/0417c25868d6dfbd1c291dfeae950504faa6f790/library/std/src/panicking.rs:581:40 - 57: catch_unwind, core::panic::unwind_safe::AssertUnwindSafe, rustc_driver_impl::run_compiler::{closure#0}::{closure_env#2}>>> - at /rustc/0417c25868d6dfbd1c291dfeae950504faa6f790/library/std/src/panicking.rs:544:19 - 58: catch_unwind, rustc_driver_impl::run_compiler::{closure#0}::{closure_env#2}>>, core::option::Option> - at /rustc/0417c25868d6dfbd1c291dfeae950504faa6f790/library/std/src/panic.rs:359:14 - 59: {closure#2}, rustc_driver_impl::run_compiler::{closure#0}::{closure_env#2}> - at ./compiler/rustc_interface/src/passes.rs:1035:23 - 60: {closure#1}, rustc_driver_impl::run_compiler::{closure#0}::{closure_env#2}>, core::option::Option> - at ./compiler/rustc_middle/src/ty/context.rs:802:37 - 61: {closure#0}, rustc_driver_impl::run_compiler::{closure#0}::{closure_env#2}>, core::option::Option>, core::option::Option> - at ./compiler/rustc_middle/src/ty/context/tls.rs:56:9 - 62: try_with, rustc_middle::ty::context::tls::enter_context::{closure_env#0}, rustc_driver_impl::run_compiler::{closure#0}::{closure_env#2}>, core::option::Option>, core::option::Option>, core::option::Option> - at /rustc/0417c25868d6dfbd1c291dfeae950504faa6f790/library/std/src/thread/local.rs:462:12 - 63: with, rustc_middle::ty::context::tls::enter_context::{closure_env#0}, rustc_driver_impl::run_compiler::{closure#0}::{closure_env#2}>, core::option::Option>, core::option::Option>, core::option::Option> - at /rustc/0417c25868d6dfbd1c291dfeae950504faa6f790/library/std/src/thread/local.rs:426:20 - 64: enter_context, rustc_driver_impl::run_compiler::{closure#0}::{closure_env#2}>, core::option::Option>, core::option::Option> - at ./compiler/rustc_middle/src/ty/context/tls.rs:53:9 - 65: enter, rustc_driver_impl::run_compiler::{closure#0}::{closure_env#2}>, core::option::Option> - at ./compiler/rustc_middle/src/ty/context.rs:802:9 - 66: create_global_ctxt, rustc_interface::passes::create_and_enter_global_ctxt::{closure_env#2}, rustc_driver_impl::run_compiler::{closure#0}::{closure_env#2}>> - at ./compiler/rustc_middle/src/ty/context.rs:996:13 - 67: create_and_enter_global_ctxt, rustc_driver_impl::run_compiler::{closure#0}::{closure_env#2}> - at ./compiler/rustc_interface/src/passes.rs:995:5 - 68: {closure#0} - at ./compiler/rustc_driver_impl/src/lib.rs:299:22 - 69: {closure#0}<(), rustc_driver_impl::run_compiler::{closure_env#0}> - at ./compiler/rustc_interface/src/interface.rs:496:80 - 70: call_once<(), rustc_interface::interface::run_compiler::{closure#1}::{closure_env#0}<(), rustc_driver_impl::run_compiler::{closure_env#0}>> - at /rustc/0417c25868d6dfbd1c291dfeae950504faa6f790/library/core/src/panic/unwind_safe.rs:275:9 - 71: do_call>, ()> - at /rustc/0417c25868d6dfbd1c291dfeae950504faa6f790/library/std/src/panicking.rs:581:40 - 72: catch_unwind<(), core::panic::unwind_safe::AssertUnwindSafe>> - at /rustc/0417c25868d6dfbd1c291dfeae950504faa6f790/library/std/src/panicking.rs:544:19 - 73: catch_unwind>, ()> - at /rustc/0417c25868d6dfbd1c291dfeae950504faa6f790/library/std/src/panic.rs:359:14 - 74: {closure#1}<(), rustc_driver_impl::run_compiler::{closure_env#0}> - at ./compiler/rustc_interface/src/interface.rs:496:23 - 75: {closure#0}, ()> - at ./compiler/rustc_interface/src/util.rs:206:17 - 76: {closure#0}, ()>, ()> - at ./compiler/rustc_interface/src/util.rs:162:24 - 77: set, ()>, ()>, ()> - at /Users/timc/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/scoped-tls-1.0.1/src/lib.rs:137:9 - 78: create_session_globals_then<(), rustc_interface::util::run_in_thread_with_globals::{closure#0}::{closure#0}::{closure_env#0}, ()>, ()>> - at ./compiler/rustc_span/src/lib.rs:155:21 - 79: {closure#0}, ()>, ()> - at ./compiler/rustc_interface/src/util.rs:158:17 -note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace. - -note: we would appreciate a bug report: https://github.com/rust-lang/rust/issues/new?labels=C-bug%2C+I-ICE%2C+T-compiler&template=ice.md - -note: please make sure that you have updated to the latest nightly - -note: rustc 1.99.0-dev running on aarch64-apple-darwin - -note: compiler flags: -Z threads=1 -Z simulate-remapped-rust-src-base=/rustc/FAKE_PREFIX -Z translate-remapped-path-to-local-path=no -Z ignore-directory-in-diagnostics-source-blocks=/Users/timc/.cargo -Z ignore-directory-in-diagnostics-source-blocks=/Users/timc/rust/vendor -C codegen-units=1 -Z ui-testing -Z deduplicate-diagnostics=no -Z write-long-types-to-disk=no -C strip=debuginfo -C prefer-dynamic -C rpath -C debuginfo=0 + | ^^^^^^^^^^ `Sub` is not dyn compatible + | +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit + --> $DIR/conflicting-bounds-different-generics-simple.rs:7:10 + | +LL | type Assoc; + | ^^^^^ ...because it has conflicting associated item bounds for Assoc in supertraits +... +LL | trait Sub: Super + Super { + | --- this trait is not dyn compatible... + +error[E0038]: the trait `Sub` is not dyn compatible + --> $DIR/conflicting-bounds-different-generics-simple.rs:26:21 + | +LL | foo::(None); + | ^^^^ `Sub` is not dyn compatible + | +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit + --> $DIR/conflicting-bounds-different-generics-simple.rs:7:10 + | +LL | type Assoc; + | ^^^^^ ...because it has conflicting associated item bounds for Assoc in supertraits +... +LL | trait Sub: Super + Super { + | --- this trait is not dyn compatible... -query stack during panic: -#0 [items_of_instance] collecting items used by `foo::` -#1 [collect_and_partition_mono_items] collect_and_partition_mono_items -end of query stack -error: aborting due to 1 previous error +error: aborting due to 3 previous errors +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/associated-type-bounds/conflicting-bounds-different-generics-unsound.rs b/tests/ui/associated-type-bounds/conflicting-bounds-different-generics-unsound.rs index 39a78211d4d05..9b8e5addbf6a3 100644 --- a/tests/ui/associated-type-bounds/conflicting-bounds-different-generics-unsound.rs +++ b/tests/ui/associated-type-bounds/conflicting-bounds-different-generics-unsound.rs @@ -1,5 +1,3 @@ -//@ build-pass - // We currently accept conflicting associated type bounds with different generics, // which results in unsoundness, since those generics can be instantiated with the // same concrete type. @@ -41,6 +39,7 @@ fn require_trait< fn use_dyn<'a, A1, A2, C: Callback>(payload: Src<'a>) -> Dst { require_trait::<'a, A1, A2, dyn Sub<'a, A1, A2>, C>(payload) + //~^ ERROR the trait `Sub` is not dyn compatible } fn extend<'a>(payload: Src<'a>) -> Dst { diff --git a/tests/ui/associated-type-bounds/conflicting-bounds-different-generics-unsound.stderr b/tests/ui/associated-type-bounds/conflicting-bounds-different-generics-unsound.stderr new file mode 100644 index 0000000000000..918fd2bf795b7 --- /dev/null +++ b/tests/ui/associated-type-bounds/conflicting-bounds-different-generics-unsound.stderr @@ -0,0 +1,19 @@ +error[E0038]: the trait `Sub` is not dyn compatible + --> $DIR/conflicting-bounds-different-generics-unsound.rs:41:37 + | +LL | require_trait::<'a, A1, A2, dyn Sub<'a, A1, A2>, C>(payload) + | ^^^^^^^^^^^^^^^ `Sub` is not dyn compatible + | +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit + --> $DIR/conflicting-bounds-different-generics-unsound.rs:11:10 + | +LL | type Assoc; + | ^^^^^ ...because it has conflicting associated item bounds for Assoc in supertraits +... +LL | trait Sub<'a, A1, A2>: Super> + Super {} + | --- this trait is not dyn compatible... + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/dyn-compatibility/multiple-supers-should-work.rs b/tests/ui/dyn-compatibility/multiple-supers-should-work.rs index 6f381da9a2200..a6d2d0a384ee8 100644 --- a/tests/ui/dyn-compatibility/multiple-supers-should-work.rs +++ b/tests/ui/dyn-compatibility/multiple-supers-should-work.rs @@ -1,5 +1,3 @@ -//@ check-pass - // We previously incorrectly deduplicated the list of projection bounds // of trait objects, causing us to incorrectly reject this code, cc #136458. @@ -17,5 +15,7 @@ impl Trait for () {} fn main() { let x: &dyn Trait<(), _> = &(); + //~^ ERROR the trait `Trait` is not dyn compatible let y: &dyn Trait<_, ()> = x; + //~^ ERROR the trait `Trait` is not dyn compatible } diff --git a/tests/ui/dyn-compatibility/multiple-supers-should-work.stderr b/tests/ui/dyn-compatibility/multiple-supers-should-work.stderr new file mode 100644 index 0000000000000..66de9b5dface0 --- /dev/null +++ b/tests/ui/dyn-compatibility/multiple-supers-should-work.stderr @@ -0,0 +1,37 @@ +error[E0038]: the trait `Trait` is not dyn compatible + --> $DIR/multiple-supers-should-work.rs:17:17 + | +LL | let x: &dyn Trait<(), _> = &(); + | ^^^^^^^^^^^^ `Trait` is not dyn compatible + | +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit + --> $DIR/multiple-supers-should-work.rs:5:10 + | +LL | type Assoc; + | ^^^^^ ...because it has conflicting associated item bounds for Assoc in supertraits +... +LL | trait Trait: Sup + Sup {} + | ----- this trait is not dyn compatible... + = help: only type `()` implements `Trait`; consider using it directly instead. + +error[E0038]: the trait `Trait` is not dyn compatible + --> $DIR/multiple-supers-should-work.rs:19:17 + | +LL | let y: &dyn Trait<_, ()> = x; + | ^^^^^^^^^^^^ `Trait` is not dyn compatible + | +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit + --> $DIR/multiple-supers-should-work.rs:5:10 + | +LL | type Assoc; + | ^^^^^ ...because it has conflicting associated item bounds for Assoc in supertraits +... +LL | trait Trait: Sup + Sup {} + | ----- this trait is not dyn compatible... + = help: only type `()` implements `Trait`; consider using it directly instead. + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-81809.rs b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-81809.rs index ced73a40d5d82..4302a09f024e4 100644 --- a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-81809.rs +++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-81809.rs @@ -1,5 +1,3 @@ -//@ check-pass - pub trait Indexable { type Idx; } @@ -15,7 +13,9 @@ pub trait Indexer: std::ops::Index {} trait StoreIndex: Indexer + Indexer {} fn foo(st: &impl StoreIndex) -> &dyn StoreIndex { + //~^ ERROR the trait `StoreIndex` is not dyn compatible st as &dyn StoreIndex + //~^ ERROR the trait `StoreIndex` is not dyn compatible } fn main() {} diff --git a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-81809.stderr b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-81809.stderr new file mode 100644 index 0000000000000..a2c8b14e9fa98 --- /dev/null +++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-81809.stderr @@ -0,0 +1,37 @@ +error[E0038]: the trait `StoreIndex` is not dyn compatible + --> $DIR/issue-81809.rs:15:34 + | +LL | fn foo(st: &impl StoreIndex) -> &dyn StoreIndex { + | ^^^^^^^^^^^^^^ `StoreIndex` is not dyn compatible + | +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit + --> $SRC_DIR/core/src/ops/index.rs:LL:COL + | + = note: ...because it has conflicting associated item bounds for Output in supertraits + | + ::: $DIR/issue-81809.rs:13:7 + | +LL | trait StoreIndex: Indexer + Indexer {} + | ---------- this trait is not dyn compatible... + +error[E0038]: the trait `StoreIndex` is not dyn compatible + --> $DIR/issue-81809.rs:17:16 + | +LL | st as &dyn StoreIndex + | ^^^^^^^^^^ `StoreIndex` is not dyn compatible + | +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit + --> $SRC_DIR/core/src/ops/index.rs:LL:COL + | + = note: ...because it has conflicting associated item bounds for Output in supertraits + | + ::: $DIR/issue-81809.rs:13:7 + | +LL | trait StoreIndex: Indexer + Indexer {} + | ---------- this trait is not dyn compatible... + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/traits/next-solver/supertrait-alias-4.rs b/tests/ui/traits/next-solver/supertrait-alias-4.rs index 919a768fcf281..3224b32e1e8e1 100644 --- a/tests/ui/traits/next-solver/supertrait-alias-4.rs +++ b/tests/ui/traits/next-solver/supertrait-alias-4.rs @@ -1,5 +1,4 @@ //@ compile-flags: -Znext-solver -//@ check-pass // Exercises the ambiguity that comes from replacing the associated types within the bounds // that are required for a `impl Trait for dyn Trait` built-in object impl to hold. @@ -19,6 +18,8 @@ fn foo(x: &(impl Foo + ?Sized)) {} fn main() { let x: &dyn Foo<_, _, Other = ()> = todo!(); + //~^ ERROR the trait `Foo` is not dyn compatible foo(x); let y: &dyn Foo = x; + //~^ ERROR the trait `Foo` is not dyn compatible } diff --git a/tests/ui/traits/next-solver/supertrait-alias-4.stderr b/tests/ui/traits/next-solver/supertrait-alias-4.stderr new file mode 100644 index 0000000000000..61cbedc41248a --- /dev/null +++ b/tests/ui/traits/next-solver/supertrait-alias-4.stderr @@ -0,0 +1,35 @@ +error[E0038]: the trait `Foo` is not dyn compatible + --> $DIR/supertrait-alias-4.rs:20:17 + | +LL | let x: &dyn Foo<_, _, Other = ()> = todo!(); + | ^^^^^^^^^^^^^^^^^^^^^ `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/supertrait-alias-4.rs:7:10 + | +LL | type Assoc; + | ^^^^^ ...because it has conflicting associated item bounds for Assoc in supertraits +... +LL | trait Foo: Sup + Sup { + | --- this trait is not dyn compatible... + +error[E0038]: the trait `Foo` is not dyn compatible + --> $DIR/supertrait-alias-4.rs:23:17 + | +LL | let y: &dyn Foo = x; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ `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/supertrait-alias-4.rs:7:10 + | +LL | type Assoc; + | ^^^^^ ...because it has conflicting associated item bounds for Assoc in supertraits +... +LL | trait Foo: Sup + Sup { + | --- this trait is not dyn compatible... + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/traits/object/with-self-in-projection-output-repeated-supertrait.rs b/tests/ui/traits/object/with-self-in-projection-output-repeated-supertrait.rs index 2d8230973325d..5d7af696fccad 100644 --- a/tests/ui/traits/object/with-self-in-projection-output-repeated-supertrait.rs +++ b/tests/ui/traits/object/with-self-in-projection-output-repeated-supertrait.rs @@ -1,5 +1,3 @@ -//@ build-pass (FIXME(62277): could be check-pass?) - // FIXME(eddyb) shorten the name so windows doesn't choke on it. #![crate_name = "trait_test"] @@ -47,5 +45,7 @@ fn main() { // Make sure this works both with and without the associated type // being specified. let _x: Box> = Box::new(2u32); + //~^ ERROR the trait `NormalizingHelper` is not dyn compatible let _y: Box> = Box::new(2u32); + //~^ ERROR the trait `NormalizingHelper` is not dyn compatible } diff --git a/tests/ui/traits/object/with-self-in-projection-output-repeated-supertrait.stderr b/tests/ui/traits/object/with-self-in-projection-output-repeated-supertrait.stderr new file mode 100644 index 0000000000000..a8c3fc022f168 --- /dev/null +++ b/tests/ui/traits/object/with-self-in-projection-output-repeated-supertrait.stderr @@ -0,0 +1,37 @@ +error[E0038]: the trait `NormalizingHelper` is not dyn compatible + --> $DIR/with-self-in-projection-output-repeated-supertrait.rs:47:21 + | +LL | let _x: Box> = Box::new(2u32); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `NormalizingHelper` is not dyn compatible + | +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit + --> $DIR/with-self-in-projection-output-repeated-supertrait.rs:27:10 + | +LL | type Output; + | ^^^^^^ ...because it has conflicting associated item bounds for Output in supertraits +... +LL | trait NormalizingHelper: Base::Out> + Base { + | ----------------- this trait is not dyn compatible... + = help: only type `u32` implements `NormalizingHelper`; consider using it directly instead. + +error[E0038]: the trait `NormalizingHelper` is not dyn compatible + --> $DIR/with-self-in-projection-output-repeated-supertrait.rs:49:21 + | +LL | let _y: Box> = Box::new(2u32); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `NormalizingHelper` is not dyn compatible + | +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit + --> $DIR/with-self-in-projection-output-repeated-supertrait.rs:27:10 + | +LL | type Output; + | ^^^^^^ ...because it has conflicting associated item bounds for Output in supertraits +... +LL | trait NormalizingHelper: Base::Out> + Base { + | ----------------- this trait is not dyn compatible... + = help: only type `u32` implements `NormalizingHelper`; consider using it directly instead. + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0038`.