From e7772f20881282ede329ed2c19eb479fded4aecd Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 19 May 2024 14:58:48 +0200 Subject: [PATCH 01/15] use posix_memalign on most Unix targets --- library/std/src/sys/pal/unix/alloc.rs | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/library/std/src/sys/pal/unix/alloc.rs b/library/std/src/sys/pal/unix/alloc.rs index 2f908e3d0e956..242a054199f42 100644 --- a/library/std/src/sys/pal/unix/alloc.rs +++ b/library/std/src/sys/pal/unix/alloc.rs @@ -59,10 +59,9 @@ unsafe impl GlobalAlloc for System { } cfg_if::cfg_if! { - // We use posix_memalign wherever possible, but not all targets have that function. + // We use posix_memalign wherever possible, but some targets have very incomplete POSIX coverage + // so we need a fallback for those. if #[cfg(any( - target_os = "redox", - target_os = "espidf", target_os = "horizon", target_os = "vita", ))] { @@ -74,12 +73,11 @@ cfg_if::cfg_if! { #[inline] unsafe fn aligned_malloc(layout: &Layout) -> *mut u8 { let mut out = ptr::null_mut(); - // We prefer posix_memalign over aligned_malloc since with aligned_malloc, - // implementations are making almost arbitrary choices for which alignments are - // "supported", making it hard to use. For instance, some implementations require the - // size to be a multiple of the alignment (wasi emmalloc), while others require the - // alignment to be at least the pointer size (Illumos, macOS) -- which may or may not be - // standards-compliant, but that does not help us. + // We prefer posix_memalign over aligned_malloc since it is more widely available, and + // since with aligned_malloc, implementations are making almost arbitrary choices for + // which alignments are "supported", making it hard to use. For instance, some + // implementations require the size to be a multiple of the alignment (wasi emmalloc), + // while others require the alignment to be at least the pointer size (Illumos, macOS). // posix_memalign only has one, clear requirement: that the alignment be a multiple of // `sizeof(void*)`. Since these are all powers of 2, we can just use max. let align = layout.align().max(crate::mem::size_of::()); From 3c2d9c2dbe0fd764b4af473a75fb4f44616f6b4c Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 19 May 2024 20:40:46 +0200 Subject: [PATCH 02/15] fix typo Co-authored-by: Jubilee <46493976+workingjubilee@users.noreply.github.com> --- library/std/src/sys/pal/unix/alloc.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/std/src/sys/pal/unix/alloc.rs b/library/std/src/sys/pal/unix/alloc.rs index 242a054199f42..eb3a57c212b4a 100644 --- a/library/std/src/sys/pal/unix/alloc.rs +++ b/library/std/src/sys/pal/unix/alloc.rs @@ -73,8 +73,8 @@ cfg_if::cfg_if! { #[inline] unsafe fn aligned_malloc(layout: &Layout) -> *mut u8 { let mut out = ptr::null_mut(); - // We prefer posix_memalign over aligned_malloc since it is more widely available, and - // since with aligned_malloc, implementations are making almost arbitrary choices for + // We prefer posix_memalign over aligned_alloc since it is more widely available, and + // since with aligned_alloc, implementations are making almost arbitrary choices for // which alignments are "supported", making it hard to use. For instance, some // implementations require the size to be a multiple of the alignment (wasi emmalloc), // while others require the alignment to be at least the pointer size (Illumos, macOS). From dc8d1bc3733bf922a11197649b9a41360a3aacd3 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 23 May 2024 15:46:56 +0000 Subject: [PATCH 03/15] Add more tests --- tests/ui/impl-trait/unsize_adt.rs | 14 ++++++++ tests/ui/impl-trait/unsize_adt.stderr | 17 ++++++++++ tests/ui/impl-trait/unsize_slice.rs | 12 +++++++ tests/ui/impl-trait/unsize_slice.stderr | 17 ++++++++++ tests/ui/impl-trait/unsize_tuple.rs | 14 ++++++++ tests/ui/impl-trait/unsize_tuple.stderr | 17 ++++++++++ .../illegal-upcast-to-impl-opaque.rs | 28 ++++++++++++++++ .../trait-upcasting/type-checking-test-4.rs | 4 +++ .../type-checking-test-4.stderr | 12 +++---- .../type-checking-test-opaques.rs | 21 ++++++++++++ .../type-checking-test-opaques.stderr | 9 ++++++ .../constrain_in_projection.current.stderr | 11 +++++++ .../constrain_in_projection.rs | 28 ++++++++++++++++ .../constrain_in_projection2.current.stderr | 13 ++++++++ .../constrain_in_projection2.next.stderr | 19 +++++++++++ .../constrain_in_projection2.rs | 32 +++++++++++++++++++ 16 files changed, 262 insertions(+), 6 deletions(-) create mode 100644 tests/ui/impl-trait/unsize_adt.rs create mode 100644 tests/ui/impl-trait/unsize_adt.stderr create mode 100644 tests/ui/impl-trait/unsize_slice.rs create mode 100644 tests/ui/impl-trait/unsize_slice.stderr create mode 100644 tests/ui/impl-trait/unsize_tuple.rs create mode 100644 tests/ui/impl-trait/unsize_tuple.stderr create mode 100644 tests/ui/traits/trait-upcasting/illegal-upcast-to-impl-opaque.rs create mode 100644 tests/ui/traits/trait-upcasting/type-checking-test-opaques.rs create mode 100644 tests/ui/traits/trait-upcasting/type-checking-test-opaques.stderr create mode 100644 tests/ui/type-alias-impl-trait/constrain_in_projection.current.stderr create mode 100644 tests/ui/type-alias-impl-trait/constrain_in_projection.rs create mode 100644 tests/ui/type-alias-impl-trait/constrain_in_projection2.current.stderr create mode 100644 tests/ui/type-alias-impl-trait/constrain_in_projection2.next.stderr create mode 100644 tests/ui/type-alias-impl-trait/constrain_in_projection2.rs diff --git a/tests/ui/impl-trait/unsize_adt.rs b/tests/ui/impl-trait/unsize_adt.rs new file mode 100644 index 0000000000000..fce5094bd404c --- /dev/null +++ b/tests/ui/impl-trait/unsize_adt.rs @@ -0,0 +1,14 @@ +//! Test that we do not allow unsizing `Foo<[Opaque; N]>` to `Foo<[Concrete]>`. + +struct Foo(T); + +fn hello() -> Foo<[impl Sized; 2]> { + if false { + let x = hello(); + let _: &Foo<[i32]> = &x; + //~^ ERROR: mismatched types + } + todo!() +} + +fn main() {} diff --git a/tests/ui/impl-trait/unsize_adt.stderr b/tests/ui/impl-trait/unsize_adt.stderr new file mode 100644 index 0000000000000..2b93b4a571b1b --- /dev/null +++ b/tests/ui/impl-trait/unsize_adt.stderr @@ -0,0 +1,17 @@ +error[E0308]: mismatched types + --> $DIR/unsize_adt.rs:8:30 + | +LL | fn hello() -> Foo<[impl Sized; 2]> { + | ---------- the found opaque type +... +LL | let _: &Foo<[i32]> = &x; + | ----------- ^^ expected `&Foo<[i32]>`, found `&Foo<[impl Sized; 2]>` + | | + | expected due to this + | + = note: expected reference `&Foo<[i32]>` + found reference `&Foo<[impl Sized; 2]>` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/impl-trait/unsize_slice.rs b/tests/ui/impl-trait/unsize_slice.rs new file mode 100644 index 0000000000000..ec0f162656400 --- /dev/null +++ b/tests/ui/impl-trait/unsize_slice.rs @@ -0,0 +1,12 @@ +//! Test that we do not allow unsizing `[Opaque; N]` to `[Concrete]`. + +fn hello() -> [impl Sized; 2] { + if false { + let x = hello(); + let _: &[i32] = &x; + //~^ ERROR: mismatched types + } + todo!() +} + +fn main() {} diff --git a/tests/ui/impl-trait/unsize_slice.stderr b/tests/ui/impl-trait/unsize_slice.stderr new file mode 100644 index 0000000000000..6a7fdb46163b9 --- /dev/null +++ b/tests/ui/impl-trait/unsize_slice.stderr @@ -0,0 +1,17 @@ +error[E0308]: mismatched types + --> $DIR/unsize_slice.rs:6:25 + | +LL | fn hello() -> [impl Sized; 2] { + | ---------- the found opaque type +... +LL | let _: &[i32] = &x; + | ------ ^^ expected `&[i32]`, found `&[impl Sized; 2]` + | | + | expected due to this + | + = note: expected reference `&[i32]` + found reference `&[impl Sized; 2]` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/impl-trait/unsize_tuple.rs b/tests/ui/impl-trait/unsize_tuple.rs new file mode 100644 index 0000000000000..630b8fd430f1a --- /dev/null +++ b/tests/ui/impl-trait/unsize_tuple.rs @@ -0,0 +1,14 @@ +//! Test that we do not allow unsizing `([Opaque; N],)` to `([Concrete],)`. + +#![feature(unsized_tuple_coercion)] + +fn hello() -> ([impl Sized; 2],) { + if false { + let x = hello(); + let _: &([i32],) = &x; + //~^ ERROR: mismatched types + } + todo!() +} + +fn main() {} diff --git a/tests/ui/impl-trait/unsize_tuple.stderr b/tests/ui/impl-trait/unsize_tuple.stderr new file mode 100644 index 0000000000000..8d3cf15887c08 --- /dev/null +++ b/tests/ui/impl-trait/unsize_tuple.stderr @@ -0,0 +1,17 @@ +error[E0308]: mismatched types + --> $DIR/unsize_tuple.rs:8:28 + | +LL | fn hello() -> ([impl Sized; 2],) { + | ---------- the found opaque type +... +LL | let _: &([i32],) = &x; + | --------- ^^ expected `&([i32],)`, found `&([impl Sized; 2],)` + | | + | expected due to this + | + = note: expected reference `&([i32],)` + found reference `&([impl Sized; 2],)` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/traits/trait-upcasting/illegal-upcast-to-impl-opaque.rs b/tests/ui/traits/trait-upcasting/illegal-upcast-to-impl-opaque.rs new file mode 100644 index 0000000000000..5820e49a4e52d --- /dev/null +++ b/tests/ui/traits/trait-upcasting/illegal-upcast-to-impl-opaque.rs @@ -0,0 +1,28 @@ +//@ revisions: current next +//@[next] compile-flags: -Znext-solver +//@[next] failure-status: 101 +//@[next] known-bug: unknown +//@[next] normalize-stderr-test "note: .*\n\n" -> "" +//@[next] normalize-stderr-test "thread 'rustc' panicked.*\n.*\n" -> "" +//@[next] normalize-stderr-test "(error: internal compiler error: [^:]+):\d+:\d+: " -> "$1:LL:CC: " +//@[next] normalize-stderr-test "delayed at .*" -> "" +//@[next] rustc-env:RUST_BACKTRACE=0 +//@ check-pass + +#![feature(trait_upcasting)] + +trait Super { + type Assoc; +} + +trait Sub: Super {} + +impl Super for T { + type Assoc = i32; +} + +fn illegal(x: &dyn Sub) -> &dyn Super { + x +} + +fn main() {} diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-4.rs b/tests/ui/traits/trait-upcasting/type-checking-test-4.rs index f40c48f0d125f..01759ec7a93c6 100644 --- a/tests/ui/traits/trait-upcasting/type-checking-test-4.rs +++ b/tests/ui/traits/trait-upcasting/type-checking-test-4.rs @@ -11,6 +11,10 @@ fn test_correct(x: &dyn Foo<'static>) { let _ = x as &dyn Bar<'static, 'static>; } +fn test_correct2<'a>(x: &dyn Foo<'a>) { + let _ = x as &dyn Bar<'_, '_>; +} + fn test_wrong1<'a>(x: &dyn Foo<'static>, y: &'a u32) { let _ = x as &dyn Bar<'static, 'a>; // Error //~^ ERROR lifetime may not live long enough diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-4.stderr b/tests/ui/traits/trait-upcasting/type-checking-test-4.stderr index 8d506e5807ece..ccced5875778d 100644 --- a/tests/ui/traits/trait-upcasting/type-checking-test-4.stderr +++ b/tests/ui/traits/trait-upcasting/type-checking-test-4.stderr @@ -1,5 +1,5 @@ error: lifetime may not live long enough - --> $DIR/type-checking-test-4.rs:15:13 + --> $DIR/type-checking-test-4.rs:19:13 | LL | fn test_wrong1<'a>(x: &dyn Foo<'static>, y: &'a u32) { | -- lifetime `'a` defined here @@ -7,7 +7,7 @@ LL | let _ = x as &dyn Bar<'static, 'a>; // Error | ^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static` error: lifetime may not live long enough - --> $DIR/type-checking-test-4.rs:20:13 + --> $DIR/type-checking-test-4.rs:24:13 | LL | fn test_wrong2<'a>(x: &dyn Foo<'static>, y: &'a u32) { | -- lifetime `'a` defined here @@ -15,7 +15,7 @@ LL | let _ = x as &dyn Bar<'a, 'static>; // Error | ^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static` error: lifetime may not live long enough - --> $DIR/type-checking-test-4.rs:26:5 + --> $DIR/type-checking-test-4.rs:30:5 | LL | fn test_wrong3<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> { | -- lifetime `'a` defined here @@ -24,7 +24,7 @@ LL | y.get_b() // ERROR | ^^^^^^^^^ returning this value requires that `'a` must outlive `'static` error: lifetime may not live long enough - --> $DIR/type-checking-test-4.rs:31:5 + --> $DIR/type-checking-test-4.rs:35:5 | LL | fn test_wrong4<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> { | -- lifetime `'a` defined here @@ -32,7 +32,7 @@ LL | <_ as Bar>::get_b(x) // ERROR | ^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static` error: lifetime may not live long enough - --> $DIR/type-checking-test-4.rs:36:5 + --> $DIR/type-checking-test-4.rs:40:5 | LL | fn test_wrong5<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> { | -- lifetime `'a` defined here @@ -40,7 +40,7 @@ LL | <_ as Bar<'_, '_>>::get_b(x) // ERROR | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static` error: lifetime may not live long enough - --> $DIR/type-checking-test-4.rs:44:5 + --> $DIR/type-checking-test-4.rs:48:5 | LL | fn test_wrong6<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> { | -- lifetime `'a` defined here diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-opaques.rs b/tests/ui/traits/trait-upcasting/type-checking-test-opaques.rs new file mode 100644 index 0000000000000..edad62fa4dbcf --- /dev/null +++ b/tests/ui/traits/trait-upcasting/type-checking-test-opaques.rs @@ -0,0 +1,21 @@ +#![feature(trait_upcasting, type_alias_impl_trait)] + +type Tait = impl Sized; + +trait Foo<'a>: Bar<'a, 'a, Tait> {} +trait Bar<'a, 'b, T> {} + +fn test_correct(x: &dyn Foo<'static>) { + let _ = x as &dyn Bar<'static, 'static, Tait>; +} + +fn test_correct2<'a>(x: &dyn Foo<'a>) { + let _ = x as &dyn Bar<'_, '_, Tait>; +} + +fn test_correct3<'a>(x: &dyn Foo<'a>, _: Tait) { + let _ = x as &dyn Bar<'_, '_, ()>; + //~^ ERROR: non-primitive cast +} + +fn main() {} diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-opaques.stderr b/tests/ui/traits/trait-upcasting/type-checking-test-opaques.stderr new file mode 100644 index 0000000000000..b2982f581ea04 --- /dev/null +++ b/tests/ui/traits/trait-upcasting/type-checking-test-opaques.stderr @@ -0,0 +1,9 @@ +error[E0605]: non-primitive cast: `&dyn Foo<'a>` as `&dyn Bar<'_, '_, ()>` + --> $DIR/type-checking-test-opaques.rs:17:13 + | +LL | let _ = x as &dyn Bar<'_, '_, ()>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0605`. diff --git a/tests/ui/type-alias-impl-trait/constrain_in_projection.current.stderr b/tests/ui/type-alias-impl-trait/constrain_in_projection.current.stderr new file mode 100644 index 0000000000000..c215d197db436 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/constrain_in_projection.current.stderr @@ -0,0 +1,11 @@ +error[E0277]: the trait bound `Foo: Trait` is not satisfied + --> $DIR/constrain_in_projection.rs:24:14 + | +LL | let x = >::Assoc::default(); + | ^^^ the trait `Trait` is not implemented for `Foo` + | + = help: the trait `Trait<()>` is implemented for `Foo` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/constrain_in_projection.rs b/tests/ui/type-alias-impl-trait/constrain_in_projection.rs new file mode 100644 index 0000000000000..7d7d16361ae6d --- /dev/null +++ b/tests/ui/type-alias-impl-trait/constrain_in_projection.rs @@ -0,0 +1,28 @@ +//! Check that projections will constrain opaque types while looking for +//! matching impls. + +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver +//@[next]check-pass + +#![feature(type_alias_impl_trait)] + +struct Foo; + +type Bar = impl Sized; + +trait Trait { + type Assoc: Default; +} + +impl Trait<()> for Foo { + type Assoc = u32; +} + +fn bop(_: Bar) { + let x = >::Assoc::default(); + //[current]~^ `Foo: Trait` is not satisfied +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/constrain_in_projection2.current.stderr b/tests/ui/type-alias-impl-trait/constrain_in_projection2.current.stderr new file mode 100644 index 0000000000000..69df5c77f9de9 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/constrain_in_projection2.current.stderr @@ -0,0 +1,13 @@ +error[E0277]: the trait bound `Foo: Trait` is not satisfied + --> $DIR/constrain_in_projection2.rs:27:14 + | +LL | let x = >::Assoc::default(); + | ^^^ the trait `Trait` is not implemented for `Foo` + | + = help: the following other types implement trait `Trait`: + > + > + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/constrain_in_projection2.next.stderr b/tests/ui/type-alias-impl-trait/constrain_in_projection2.next.stderr new file mode 100644 index 0000000000000..0d6eac4216bae --- /dev/null +++ b/tests/ui/type-alias-impl-trait/constrain_in_projection2.next.stderr @@ -0,0 +1,19 @@ +error[E0283]: type annotations needed: cannot satisfy `Foo: Trait` + --> $DIR/constrain_in_projection2.rs:27:14 + | +LL | let x = >::Assoc::default(); + | ^^^ help: use the fully qualified path to an implementation: `::Assoc` + | +note: multiple `impl`s satisfying `Foo: Trait` found + --> $DIR/constrain_in_projection2.rs:18:1 + | +LL | impl Trait<()> for Foo { + | ^^^^^^^^^^^^^^^^^^^^^^ +... +LL | impl Trait for Foo { + | ^^^^^^^^^^^^^^^^^^^^^^^ + = note: associated types cannot be accessed directly on a `trait`, they can only be accessed through a specific `impl` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/type-alias-impl-trait/constrain_in_projection2.rs b/tests/ui/type-alias-impl-trait/constrain_in_projection2.rs new file mode 100644 index 0000000000000..af222f6c15347 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/constrain_in_projection2.rs @@ -0,0 +1,32 @@ +//! Check that projections will constrain opaque types while looking for +//! matching impls and error if ambiguous. + +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver + +#![feature(type_alias_impl_trait)] + +struct Foo; + +type Bar = impl Sized; + +trait Trait { + type Assoc: Default; +} + +impl Trait<()> for Foo { + type Assoc = u32; +} + +impl Trait for Foo { + type Assoc = u32; +} + +fn bop(_: Bar) { + let x = >::Assoc::default(); + //[next]~^ ERROR: cannot satisfy `Foo: Trait` + //[current]~^^ ERROR: `Foo: Trait` is not satisfied +} + +fn main() {} From 29a630eb72ffb94c3708947afae1e948ad3cb189 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 17 Apr 2024 09:29:13 +0000 Subject: [PATCH 04/15] When checking whether an impl applies, constrain hidden types of opaque types. We already handle this case this way on the coherence side, and it matches the new solver's behaviour. While there is some breakage around type-alias-impl-trait (see new "type annotations needed" in tests/ui/type-alias-impl-trait/issue-84660-unsoundness.rs), no stable code breaks, and no new stable code is accepted. --- .../src/traits/select/mod.rs | 2 +- tests/ui/impl-trait/equality.rs | 13 +++++++---- tests/ui/impl-trait/equality.stderr | 15 ++++-------- tests/ui/impl-trait/nested_impl_trait.stderr | 16 ++++++++----- ...rsive-type-alias-impl-trait-declaration.rs | 2 +- ...e-type-alias-impl-trait-declaration.stderr | 12 +++------- .../constrain_in_projection.current.stderr | 11 --------- .../constrain_in_projection.rs | 3 +-- .../constrain_in_projection2.current.stderr | 18 ++++++++++----- .../constrain_in_projection2.rs | 3 +-- ...=> issue-84660-unsoundness.current.stderr} | 2 +- .../issue-84660-unsoundness.next.stderr | 23 +++++++++++++++++++ .../issue-84660-unsoundness.rs | 8 ++++++- .../nested-tait-inference.rs | 13 +++++++---- .../nested-tait-inference2.current.stderr | 17 ++++++++++++++ .../nested-tait-inference2.next.stderr | 9 ++++++++ .../nested-tait-inference2.rs | 7 +++++- .../nested-tait-inference2.stderr | 16 ------------- .../normalize-hidden-types.current.stderr | 21 +++++++---------- .../self-referential-2.current.stderr | 14 ----------- .../self-referential-2.rs | 4 ++-- .../self-referential-3.rs | 2 +- .../self-referential-3.stderr | 12 ++++------ 23 files changed, 127 insertions(+), 116 deletions(-) delete mode 100644 tests/ui/type-alias-impl-trait/constrain_in_projection.current.stderr rename tests/ui/type-alias-impl-trait/{issue-84660-unsoundness.stderr => issue-84660-unsoundness.current.stderr} (90%) create mode 100644 tests/ui/type-alias-impl-trait/issue-84660-unsoundness.next.stderr create mode 100644 tests/ui/type-alias-impl-trait/nested-tait-inference2.current.stderr create mode 100644 tests/ui/type-alias-impl-trait/nested-tait-inference2.next.stderr delete mode 100644 tests/ui/type-alias-impl-trait/nested-tait-inference2.stderr delete mode 100644 tests/ui/type-alias-impl-trait/self-referential-2.current.stderr diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 4a94643d908bf..86a5d464b7bb1 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -2539,7 +2539,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { let InferOk { obligations, .. } = self .infcx .at(&cause, obligation.param_env) - .eq(DefineOpaqueTypes::No, placeholder_obligation_trait_ref, impl_trait_ref) + .eq(DefineOpaqueTypes::Yes, placeholder_obligation_trait_ref, impl_trait_ref) .map_err(|e| { debug!("match_impl: failed eq_trait_refs due to `{}`", e.to_string(self.tcx())) })?; diff --git a/tests/ui/impl-trait/equality.rs b/tests/ui/impl-trait/equality.rs index 828b5aac896be..952f81f19784c 100644 --- a/tests/ui/impl-trait/equality.rs +++ b/tests/ui/impl-trait/equality.rs @@ -22,7 +22,7 @@ fn sum_to(n: u32) -> impl Foo { 0 } else { n + sum_to(n - 1) - //~^ ERROR cannot add `impl Foo` to `u32` + //~^ ERROR cannot satisfy `>::Output == i32` } } @@ -32,12 +32,15 @@ trait Leak: Sized { } impl Leak for T { default type T = (); - default fn leak(self) -> Self::T { panic!() } + default fn leak(self) -> Self::T { + panic!() + } } impl Leak for i32 { type T = i32; - fn leak(self) -> i32 { self } + fn leak(self) -> i32 { + self + } } -fn main() { -} +fn main() {} diff --git a/tests/ui/impl-trait/equality.stderr b/tests/ui/impl-trait/equality.stderr index 69f4cbbbf4294..c9ba1a5ba32d1 100644 --- a/tests/ui/impl-trait/equality.stderr +++ b/tests/ui/impl-trait/equality.stderr @@ -22,20 +22,13 @@ help: change the type of the numeric literal from `u32` to `i32` LL | 0_i32 | ~~~ -error[E0277]: cannot add `impl Foo` to `u32` +error[E0284]: type annotations needed: cannot satisfy `>::Output == i32` --> $DIR/equality.rs:24:11 | LL | n + sum_to(n - 1) - | ^ no implementation for `u32 + impl Foo` - | - = help: the trait `Add` is not implemented for `u32` - = help: the following other types implement trait `Add`: - <&'a u32 as Add> - <&u32 as Add<&u32>> - > - + | ^ cannot satisfy `>::Output == i32` error: aborting due to 2 previous errors; 1 warning emitted -Some errors have detailed explanations: E0277, E0308. -For more information about an error, try `rustc --explain E0277`. +Some errors have detailed explanations: E0284, E0308. +For more information about an error, try `rustc --explain E0284`. diff --git a/tests/ui/impl-trait/nested_impl_trait.stderr b/tests/ui/impl-trait/nested_impl_trait.stderr index 1f9a2a5e9d600..f7c708a1dfae8 100644 --- a/tests/ui/impl-trait/nested_impl_trait.stderr +++ b/tests/ui/impl-trait/nested_impl_trait.stderr @@ -46,19 +46,23 @@ error[E0277]: the trait bound `impl Into: Into` is not satisfie --> $DIR/nested_impl_trait.rs:6:46 | LL | fn bad_in_ret_position(x: impl Into) -> impl Into { x } - | ^^^^^^^^^^^^^^^^^^^^^ the trait `From>` is not implemented for `impl Into`, which is required by `impl Into: Into` + | ^^^^^^^^^^^^^^^^^^^^^ the trait `Debug` is not implemented for `impl Into` | - = help: the trait `Into` is implemented for `T` - = note: required for `impl Into` to implement `Into` +help: consider further restricting this bound + | +LL | fn bad_in_ret_position(x: impl Into + std::fmt::Debug) -> impl Into { x } + | +++++++++++++++++ error[E0277]: the trait bound `impl Into: Into` is not satisfied --> $DIR/nested_impl_trait.rs:19:34 | LL | fn bad(x: impl Into) -> impl Into { x } - | ^^^^^^^^^^^^^^^^^^^^^ the trait `From>` is not implemented for `impl Into`, which is required by `impl Into: Into` + | ^^^^^^^^^^^^^^^^^^^^^ the trait `Debug` is not implemented for `impl Into` + | +help: consider further restricting this bound | - = help: the trait `Into` is implemented for `T` - = note: required for `impl Into` to implement `Into` +LL | fn bad(x: impl Into + std::fmt::Debug) -> impl Into { x } + | +++++++++++++++++ error: aborting due to 7 previous errors diff --git a/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration.rs b/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration.rs index aab10be2de27a..7874a21f3aec5 100644 --- a/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration.rs +++ b/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration.rs @@ -11,7 +11,7 @@ impl PartialEq<(Bar, i32)> for Bar { } fn foo() -> Foo { - //~^ ERROR can't compare `Bar` with `(Foo, i32)` + //~^ ERROR overflow evaluating the requirement `Bar: PartialEq<(Foo, i32)>` Bar } diff --git a/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration.stderr b/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration.stderr index bc810c0f88f3d..2d4707f8a2799 100644 --- a/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration.stderr +++ b/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration.stderr @@ -1,15 +1,9 @@ -error[E0277]: can't compare `Bar` with `(Foo, i32)` +error[E0275]: overflow evaluating the requirement `Bar: PartialEq<(Foo, i32)>` --> $DIR/recursive-type-alias-impl-trait-declaration.rs:13:13 | LL | fn foo() -> Foo { - | ^^^ no implementation for `Bar == (Foo, i32)` -LL | -LL | Bar - | --- return type was inferred to be `Bar` here - | - = help: the trait `PartialEq<(Foo, i32)>` is not implemented for `Bar` - = help: the trait `PartialEq<(Bar, i32)>` is implemented for `Bar` + | ^^^ error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/type-alias-impl-trait/constrain_in_projection.current.stderr b/tests/ui/type-alias-impl-trait/constrain_in_projection.current.stderr deleted file mode 100644 index c215d197db436..0000000000000 --- a/tests/ui/type-alias-impl-trait/constrain_in_projection.current.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[E0277]: the trait bound `Foo: Trait` is not satisfied - --> $DIR/constrain_in_projection.rs:24:14 - | -LL | let x = >::Assoc::default(); - | ^^^ the trait `Trait` is not implemented for `Foo` - | - = help: the trait `Trait<()>` is implemented for `Foo` - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/constrain_in_projection.rs b/tests/ui/type-alias-impl-trait/constrain_in_projection.rs index 7d7d16361ae6d..2a246900106cb 100644 --- a/tests/ui/type-alias-impl-trait/constrain_in_projection.rs +++ b/tests/ui/type-alias-impl-trait/constrain_in_projection.rs @@ -4,7 +4,7 @@ //@ revisions: current next //@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver -//@[next]check-pass +//@check-pass #![feature(type_alias_impl_trait)] @@ -22,7 +22,6 @@ impl Trait<()> for Foo { fn bop(_: Bar) { let x = >::Assoc::default(); - //[current]~^ `Foo: Trait` is not satisfied } fn main() {} diff --git a/tests/ui/type-alias-impl-trait/constrain_in_projection2.current.stderr b/tests/ui/type-alias-impl-trait/constrain_in_projection2.current.stderr index 69df5c77f9de9..0d6eac4216bae 100644 --- a/tests/ui/type-alias-impl-trait/constrain_in_projection2.current.stderr +++ b/tests/ui/type-alias-impl-trait/constrain_in_projection2.current.stderr @@ -1,13 +1,19 @@ -error[E0277]: the trait bound `Foo: Trait` is not satisfied +error[E0283]: type annotations needed: cannot satisfy `Foo: Trait` --> $DIR/constrain_in_projection2.rs:27:14 | LL | let x = >::Assoc::default(); - | ^^^ the trait `Trait` is not implemented for `Foo` + | ^^^ help: use the fully qualified path to an implementation: `::Assoc` | - = help: the following other types implement trait `Trait`: - > - > +note: multiple `impl`s satisfying `Foo: Trait` found + --> $DIR/constrain_in_projection2.rs:18:1 + | +LL | impl Trait<()> for Foo { + | ^^^^^^^^^^^^^^^^^^^^^^ +... +LL | impl Trait for Foo { + | ^^^^^^^^^^^^^^^^^^^^^^^ + = note: associated types cannot be accessed directly on a `trait`, they can only be accessed through a specific `impl` error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/type-alias-impl-trait/constrain_in_projection2.rs b/tests/ui/type-alias-impl-trait/constrain_in_projection2.rs index af222f6c15347..0066131f0155f 100644 --- a/tests/ui/type-alias-impl-trait/constrain_in_projection2.rs +++ b/tests/ui/type-alias-impl-trait/constrain_in_projection2.rs @@ -25,8 +25,7 @@ impl Trait for Foo { fn bop(_: Bar) { let x = >::Assoc::default(); - //[next]~^ ERROR: cannot satisfy `Foo: Trait` - //[current]~^^ ERROR: `Foo: Trait` is not satisfied + //~^ ERROR: cannot satisfy `Foo: Trait` } fn main() {} diff --git a/tests/ui/type-alias-impl-trait/issue-84660-unsoundness.stderr b/tests/ui/type-alias-impl-trait/issue-84660-unsoundness.current.stderr similarity index 90% rename from tests/ui/type-alias-impl-trait/issue-84660-unsoundness.stderr rename to tests/ui/type-alias-impl-trait/issue-84660-unsoundness.current.stderr index 461da20f37b67..a7ff097e8bf38 100644 --- a/tests/ui/type-alias-impl-trait/issue-84660-unsoundness.stderr +++ b/tests/ui/type-alias-impl-trait/issue-84660-unsoundness.current.stderr @@ -1,5 +1,5 @@ error[E0119]: conflicting implementations of trait `Trait` - --> $DIR/issue-84660-unsoundness.rs:23:1 + --> $DIR/issue-84660-unsoundness.rs:28:1 | LL | impl Trait for Out { | ------------------------------------ first implementation here diff --git a/tests/ui/type-alias-impl-trait/issue-84660-unsoundness.next.stderr b/tests/ui/type-alias-impl-trait/issue-84660-unsoundness.next.stderr new file mode 100644 index 0000000000000..607f0b062abd7 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/issue-84660-unsoundness.next.stderr @@ -0,0 +1,23 @@ +error[E0284]: type annotations needed: cannot satisfy `>::Out == ()` + --> $DIR/issue-84660-unsoundness.rs:22:37 + | +LL | fn convert(_i: In) -> Self::Out { + | _____________________________________^ +LL | | +LL | | unreachable!(); +LL | | } + | |_____^ cannot satisfy `>::Out == ()` + +error[E0119]: conflicting implementations of trait `Trait` + --> $DIR/issue-84660-unsoundness.rs:28:1 + | +LL | impl Trait for Out { + | ------------------------------------ first implementation here +... +LL | impl Trait<(), In> for Out { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0119, E0284. +For more information about an error, try `rustc --explain E0119`. diff --git a/tests/ui/type-alias-impl-trait/issue-84660-unsoundness.rs b/tests/ui/type-alias-impl-trait/issue-84660-unsoundness.rs index 48d4b0c96ff0a..99a5d36066b08 100644 --- a/tests/ui/type-alias-impl-trait/issue-84660-unsoundness.rs +++ b/tests/ui/type-alias-impl-trait/issue-84660-unsoundness.rs @@ -1,6 +1,10 @@ // Another example from issue #84660, this time weaponized as a safe transmute: an opaque type in an // impl header being accepted was used to create unsoundness. +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver + #![feature(type_alias_impl_trait)] trait Foo {} @@ -16,11 +20,13 @@ trait Trait { impl Trait for Out { type Out = Out; fn convert(_i: In) -> Self::Out { + //[next]~^ ERROR: type annotations needed unreachable!(); } } -impl Trait<(), In> for Out { //~ ERROR conflicting implementations of trait `Trait` +impl Trait<(), In> for Out { + //~^ ERROR conflicting implementations of trait `Trait` type Out = In; fn convert(i: In) -> Self::Out { i diff --git a/tests/ui/type-alias-impl-trait/nested-tait-inference.rs b/tests/ui/type-alias-impl-trait/nested-tait-inference.rs index 82248971692ce..70495c44706a7 100644 --- a/tests/ui/type-alias-impl-trait/nested-tait-inference.rs +++ b/tests/ui/type-alias-impl-trait/nested-tait-inference.rs @@ -1,18 +1,21 @@ #![feature(type_alias_impl_trait)] #![allow(dead_code)] +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver +//@check-pass + use std::fmt::Debug; type FooX = impl Debug; -trait Foo { } +trait Foo {} -impl Foo<()> for () { } +impl Foo<()> for () {} fn foo() -> impl Foo { - //~^ ERROR: the trait bound `(): Foo` is not satisfied - // FIXME(type-alias-impl-trait): We could probably make this work. () } -fn main() { } +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/nested-tait-inference2.current.stderr b/tests/ui/type-alias-impl-trait/nested-tait-inference2.current.stderr new file mode 100644 index 0000000000000..c7b7af152ab32 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/nested-tait-inference2.current.stderr @@ -0,0 +1,17 @@ +error[E0283]: type annotations needed: cannot satisfy `(): Foo` + --> $DIR/nested-tait-inference2.rs:17:13 + | +LL | fn foo() -> impl Foo { + | ^^^^^^^^^^^^^^ + | +note: multiple `impl`s satisfying `(): Foo` found + --> $DIR/nested-tait-inference2.rs:14:1 + | +LL | impl Foo<()> for () {} + | ^^^^^^^^^^^^^^^^^^^ +LL | impl Foo for () {} + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/type-alias-impl-trait/nested-tait-inference2.next.stderr b/tests/ui/type-alias-impl-trait/nested-tait-inference2.next.stderr new file mode 100644 index 0000000000000..9647d9e376eb4 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/nested-tait-inference2.next.stderr @@ -0,0 +1,9 @@ +error[E0284]: type annotations needed: cannot satisfy `impl Foo == ()` + --> $DIR/nested-tait-inference2.rs:19:5 + | +LL | () + | ^^ cannot satisfy `impl Foo == ()` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0284`. diff --git a/tests/ui/type-alias-impl-trait/nested-tait-inference2.rs b/tests/ui/type-alias-impl-trait/nested-tait-inference2.rs index 0d7f5bad25f11..fe2f76e552ad7 100644 --- a/tests/ui/type-alias-impl-trait/nested-tait-inference2.rs +++ b/tests/ui/type-alias-impl-trait/nested-tait-inference2.rs @@ -1,6 +1,10 @@ #![feature(type_alias_impl_trait)] #![allow(dead_code)] +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver + use std::fmt::Debug; type FooX = impl Debug; @@ -11,8 +15,9 @@ impl Foo<()> for () {} impl Foo for () {} fn foo() -> impl Foo { - //~^ ERROR: the trait bound `(): Foo` is not satisfied + //[current]~^ ERROR: cannot satisfy `(): Foo` () + //[next]~^ ERROR: cannot satisfy `impl Foo == ()` } fn main() {} diff --git a/tests/ui/type-alias-impl-trait/nested-tait-inference2.stderr b/tests/ui/type-alias-impl-trait/nested-tait-inference2.stderr deleted file mode 100644 index 241342b05096b..0000000000000 --- a/tests/ui/type-alias-impl-trait/nested-tait-inference2.stderr +++ /dev/null @@ -1,16 +0,0 @@ -error[E0277]: the trait bound `(): Foo` is not satisfied - --> $DIR/nested-tait-inference2.rs:13:13 - | -LL | fn foo() -> impl Foo { - | ^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `()` -LL | -LL | () - | -- return type was inferred to be `()` here - | - = help: the following other types implement trait `Foo`: - <() as Foo<()>> - <() as Foo> - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/normalize-hidden-types.current.stderr b/tests/ui/type-alias-impl-trait/normalize-hidden-types.current.stderr index a40dac06a01c3..eff29303bf18e 100644 --- a/tests/ui/type-alias-impl-trait/normalize-hidden-types.current.stderr +++ b/tests/ui/type-alias-impl-trait/normalize-hidden-types.current.stderr @@ -22,21 +22,17 @@ note: previous use here LL | fn define_1() -> Opaque { dyn_hoops::<_>(0) } | ^^^^^^^^^^^^^^^^^ -error[E0308]: mismatched types +error: concrete type differs from previous defining opaque type use --> $DIR/normalize-hidden-types.rs:43:25 | -LL | type Opaque = impl Sized; - | ---------- the expected opaque type -... LL | let _: Opaque = dyn_hoops::(0); - | ------ ^^^^^^^^^^^^^^^^^^ expected opaque type, found `*const dyn FnOnce(())` - | | - | expected due to this - | - = note: expected opaque type `typeck::Opaque` - found raw pointer `*const (dyn FnOnce(()) + 'static)` - = help: consider constraining the associated type `::Gat<'_>` to `()` or calling a method that returns `::Gat<'_>` - = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html + | ^^^^^^^^^^^^^^^^^^ expected `*const (dyn FnOnce(()) + 'static)`, got `*const dyn for<'a> FnOnce(::Gat<'a>)` + | +note: previous use here + --> $DIR/normalize-hidden-types.rs:44:9 + | +LL | None + | ^^^^ error: concrete type differs from previous defining opaque type use --> $DIR/normalize-hidden-types.rs:52:25 @@ -52,4 +48,3 @@ LL | None error: aborting due to 4 previous errors -For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/type-alias-impl-trait/self-referential-2.current.stderr b/tests/ui/type-alias-impl-trait/self-referential-2.current.stderr deleted file mode 100644 index 3ae3590ca7fe3..0000000000000 --- a/tests/ui/type-alias-impl-trait/self-referential-2.current.stderr +++ /dev/null @@ -1,14 +0,0 @@ -error[E0277]: can't compare `i32` with `Foo` - --> $DIR/self-referential-2.rs:10:13 - | -LL | fn bar() -> Bar { - | ^^^ no implementation for `i32 == Foo` -LL | 42_i32 - | ------ return type was inferred to be `i32` here - | - = help: the trait `PartialEq` is not implemented for `i32` - = help: the trait `PartialEq` is implemented for `i32` - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/self-referential-2.rs b/tests/ui/type-alias-impl-trait/self-referential-2.rs index f96364ccfcddf..f4102f2e2cb71 100644 --- a/tests/ui/type-alias-impl-trait/self-referential-2.rs +++ b/tests/ui/type-alias-impl-trait/self-referential-2.rs @@ -1,14 +1,14 @@ //@ revisions: current next //@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver -//@[next] check-pass +//@ check-pass #![feature(type_alias_impl_trait)] type Foo = impl std::fmt::Debug; type Bar = impl PartialEq; fn bar() -> Bar { - 42_i32 //[current]~^ ERROR can't compare `i32` with `Foo` + 42_i32 } fn main() {} diff --git a/tests/ui/type-alias-impl-trait/self-referential-3.rs b/tests/ui/type-alias-impl-trait/self-referential-3.rs index b33051da2d779..3b015ab322aca 100644 --- a/tests/ui/type-alias-impl-trait/self-referential-3.rs +++ b/tests/ui/type-alias-impl-trait/self-referential-3.rs @@ -5,7 +5,7 @@ type Bar<'a, 'b> = impl PartialEq> + std::fmt::Debug; fn bar<'a, 'b>(i: &'a i32) -> Bar<'a, 'b> { - //~^ ERROR can't compare `&i32` with `Bar<'a, 'b>` + //~^ ERROR overflow normalizing the type alias `Bar<'a, 'b>` i } diff --git a/tests/ui/type-alias-impl-trait/self-referential-3.stderr b/tests/ui/type-alias-impl-trait/self-referential-3.stderr index 32eac622e5181..caa9f9691dda5 100644 --- a/tests/ui/type-alias-impl-trait/self-referential-3.stderr +++ b/tests/ui/type-alias-impl-trait/self-referential-3.stderr @@ -1,15 +1,11 @@ -error[E0277]: can't compare `&i32` with `Bar<'a, 'b>` +error[E0275]: overflow normalizing the type alias `Bar<'a, 'b>` --> $DIR/self-referential-3.rs:7:31 | LL | fn bar<'a, 'b>(i: &'a i32) -> Bar<'a, 'b> { - | ^^^^^^^^^^^ no implementation for `&i32 == Bar<'a, 'b>` -LL | -LL | i - | - return type was inferred to be `&i32` here + | ^^^^^^^^^^^ | - = help: the trait `PartialEq>` is not implemented for `&i32` - = help: the trait `PartialEq` is implemented for `i32` + = note: in case this is a recursive type alias, consider using a struct, enum, or union instead error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0275`. From 7f292f41a0c6c5ebbc915d487dd49741f9982684 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 17 Apr 2024 10:01:34 +0000 Subject: [PATCH 05/15] Allow defining opaque types during trait object upcasting. No stable code is affected, as this requires the `trait_upcasting` feature gate. --- .../src/traits/select/mod.rs | 2 +- .../upcast-defining-opaque.current.stderr | 17 ----------------- .../trait-upcasting/upcast-defining-opaque.rs | 4 ++-- 3 files changed, 3 insertions(+), 20 deletions(-) delete mode 100644 tests/ui/traits/trait-upcasting/upcast-defining-opaque.current.stderr diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 86a5d464b7bb1..ee4b81b046f4f 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -2631,7 +2631,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { nested.extend( self.infcx .at(&obligation.cause, obligation.param_env) - .eq(DefineOpaqueTypes::No, source_projection, target_projection) + .eq(DefineOpaqueTypes::Yes, source_projection, target_projection) .map_err(|_| SelectionError::Unimplemented)? .into_obligations(), ); diff --git a/tests/ui/traits/trait-upcasting/upcast-defining-opaque.current.stderr b/tests/ui/traits/trait-upcasting/upcast-defining-opaque.current.stderr deleted file mode 100644 index a259abb28ae3e..0000000000000 --- a/tests/ui/traits/trait-upcasting/upcast-defining-opaque.current.stderr +++ /dev/null @@ -1,17 +0,0 @@ -error[E0308]: mismatched types - --> $DIR/upcast-defining-opaque.rs:21:5 - | -LL | type Foo = impl Sized; - | ---------- the found opaque type -LL | -LL | fn upcast(x: &dyn Sub) -> &dyn Super { - | ----------------------- expected `&dyn Super` because of return type -LL | x - | ^ expected trait `Super`, found trait `Sub` - | - = note: expected reference `&dyn Super` - found reference `&dyn Sub` - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/traits/trait-upcasting/upcast-defining-opaque.rs b/tests/ui/traits/trait-upcasting/upcast-defining-opaque.rs index cb1501a94a2ae..07f1549e177fb 100644 --- a/tests/ui/traits/trait-upcasting/upcast-defining-opaque.rs +++ b/tests/ui/traits/trait-upcasting/upcast-defining-opaque.rs @@ -1,7 +1,7 @@ //@ revisions: current next //@[next] compile-flags: -Znext-solver //@ ignore-compare-mode-next-solver (explicit revisions) -//@[next] check-pass +//@check-pass #![feature(trait_upcasting, type_alias_impl_trait)] @@ -18,7 +18,7 @@ impl Super for T { type Foo = impl Sized; fn upcast(x: &dyn Sub) -> &dyn Super { - x //[current]~ mismatched types + x } fn main() {} From 4387eea7f76e82d6f6050df99196c15d53b4914a Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 17 Apr 2024 10:48:20 +0000 Subject: [PATCH 06/15] Support constraining opaque types while trait upcasting with binders --- compiler/rustc_trait_selection/src/traits/select/mod.rs | 2 +- .../traits/trait-upcasting/type-checking-test-opaques.rs | 3 ++- .../trait-upcasting/type-checking-test-opaques.stderr | 9 --------- 3 files changed, 3 insertions(+), 11 deletions(-) delete mode 100644 tests/ui/traits/trait-upcasting/type-checking-test-opaques.stderr diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index ee4b81b046f4f..696b1c1511531 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -2594,7 +2594,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { self.infcx .at(&obligation.cause, obligation.param_env) .eq( - DefineOpaqueTypes::No, + DefineOpaqueTypes::Yes, upcast_principal.map_bound(|trait_ref| { ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref) }), diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-opaques.rs b/tests/ui/traits/trait-upcasting/type-checking-test-opaques.rs index edad62fa4dbcf..a3a1ce29465b1 100644 --- a/tests/ui/traits/trait-upcasting/type-checking-test-opaques.rs +++ b/tests/ui/traits/trait-upcasting/type-checking-test-opaques.rs @@ -1,5 +1,7 @@ #![feature(trait_upcasting, type_alias_impl_trait)] +//@ check-pass + type Tait = impl Sized; trait Foo<'a>: Bar<'a, 'a, Tait> {} @@ -15,7 +17,6 @@ fn test_correct2<'a>(x: &dyn Foo<'a>) { fn test_correct3<'a>(x: &dyn Foo<'a>, _: Tait) { let _ = x as &dyn Bar<'_, '_, ()>; - //~^ ERROR: non-primitive cast } fn main() {} diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-opaques.stderr b/tests/ui/traits/trait-upcasting/type-checking-test-opaques.stderr deleted file mode 100644 index b2982f581ea04..0000000000000 --- a/tests/ui/traits/trait-upcasting/type-checking-test-opaques.stderr +++ /dev/null @@ -1,9 +0,0 @@ -error[E0605]: non-primitive cast: `&dyn Foo<'a>` as `&dyn Bar<'_, '_, ()>` - --> $DIR/type-checking-test-opaques.rs:17:13 - | -LL | let _ = x as &dyn Bar<'_, '_, ()>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0605`. From 09c8e39adb5b19d4ff412e8f77ea42c569a8e02d Mon Sep 17 00:00:00 2001 From: surechen Date: Wed, 22 May 2024 18:25:26 +0800 Subject: [PATCH 07/15] A small diagnostic improvement for dropping_copy_types fixes #125189 --- compiler/rustc_lint/messages.ftl | 1 + .../rustc_lint/src/drop_forget_useless.rs | 21 +++++++++-- compiler/rustc_lint/src/lints.rs | 16 +++++++- .../defaults-unsound-62211-1.next.stderr | 6 ++- .../defaults-unsound-62211-2.next.stderr | 6 ++- ...g_copy_types-issue-125189-can-not-fixed.rs | 14 +++++++ ...py_types-issue-125189-can-not-fixed.stderr | 37 +++++++++++++++++++ .../dropping_copy_types-issue-125189.fixed | 10 +++++ .../lint/dropping_copy_types-issue-125189.rs | 10 +++++ .../dropping_copy_types-issue-125189.stderr | 35 ++++++++++++++++++ tests/ui/lint/dropping_copy_types.stderr | 24 ++++++++++-- 11 files changed, 169 insertions(+), 11 deletions(-) create mode 100644 tests/ui/lint/dropping_copy_types-issue-125189-can-not-fixed.rs create mode 100644 tests/ui/lint/dropping_copy_types-issue-125189-can-not-fixed.stderr create mode 100644 tests/ui/lint/dropping_copy_types-issue-125189.fixed create mode 100644 tests/ui/lint/dropping_copy_types-issue-125189.rs create mode 100644 tests/ui/lint/dropping_copy_types-issue-125189.stderr diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 82b90e1660a95..289005e000540 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -197,6 +197,7 @@ lint_drop_trait_constraints = lint_dropping_copy_types = calls to `std::mem::drop` with a value that implements `Copy` does nothing .label = argument has type `{$arg_ty}` .note = use `let _ = ...` to ignore the expression or result + .suggestion = use `let _ = ...` to ignore the expression or result lint_dropping_references = calls to `std::mem::drop` with a reference instead of an owned value does nothing .label = argument has type `{$arg_ty}` diff --git a/compiler/rustc_lint/src/drop_forget_useless.rs b/compiler/rustc_lint/src/drop_forget_useless.rs index 78ac7f9b2354d..5033d194a21ef 100644 --- a/compiler/rustc_lint/src/drop_forget_useless.rs +++ b/compiler/rustc_lint/src/drop_forget_useless.rs @@ -1,11 +1,11 @@ -use rustc_hir::{Arm, Expr, ExprKind, Node}; +use rustc_hir::{Arm, Expr, ExprKind, Node, StmtKind}; use rustc_middle::ty; use rustc_span::sym; use crate::{ lints::{ - DropCopyDiag, DropRefDiag, ForgetCopyDiag, ForgetRefDiag, UndroppedManuallyDropsDiag, - UndroppedManuallyDropsSuggestion, + DropCopyDiag, DropCopySuggestion, DropRefDiag, ForgetCopyDiag, ForgetRefDiag, + UndroppedManuallyDropsDiag, UndroppedManuallyDropsSuggestion, }, LateContext, LateLintPass, LintContext, }; @@ -163,10 +163,23 @@ impl<'tcx> LateLintPass<'tcx> for DropForgetUseless { ); } sym::mem_drop if is_copy && !drop_is_single_call_in_arm => { + let sugg = if let Some((_, node)) = cx.tcx.hir().parent_iter(expr.hir_id).nth(0) + && let Node::Stmt(stmt) = node + && let StmtKind::Semi(e) = stmt.kind + && e.hir_id == expr.hir_id + { + DropCopySuggestion::Suggestion { + start_span: expr.span.shrink_to_lo().until(arg.span), + end_span: arg.span.shrink_to_hi().until(expr.span.shrink_to_hi()), + } + } else { + DropCopySuggestion::Note + }; + cx.emit_span_lint( DROPPING_COPY_TYPES, expr.span, - DropCopyDiag { arg_ty, label: arg.span }, + DropCopyDiag { arg_ty, label: arg.span, sugg }, ); } sym::mem_forget if is_copy => { diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index a034bebc85ec0..084e818a2758f 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -669,11 +669,25 @@ pub struct DropRefDiag<'a> { #[derive(LintDiagnostic)] #[diag(lint_dropping_copy_types)] -#[note] pub struct DropCopyDiag<'a> { pub arg_ty: Ty<'a>, #[label] pub label: Span, + #[subdiagnostic] + pub sugg: DropCopySuggestion, +} + +#[derive(Subdiagnostic)] +pub enum DropCopySuggestion { + #[note(lint_note)] + Note, + #[multipart_suggestion(lint_suggestion, style = "verbose", applicability = "maybe-incorrect")] + Suggestion { + #[suggestion_part(code = "let _ = ")] + start_span: Span, + #[suggestion_part(code = "")] + end_span: Span, + }, } #[derive(LintDiagnostic)] diff --git a/tests/ui/associated-types/defaults-unsound-62211-1.next.stderr b/tests/ui/associated-types/defaults-unsound-62211-1.next.stderr index 834ae00a8d85b..ffb02eccc77dc 100644 --- a/tests/ui/associated-types/defaults-unsound-62211-1.next.stderr +++ b/tests/ui/associated-types/defaults-unsound-62211-1.next.stderr @@ -6,8 +6,12 @@ LL | drop(origin); | | | argument has type `::Output` | - = note: use `let _ = ...` to ignore the expression or result = note: `#[warn(dropping_copy_types)]` on by default +help: use `let _ = ...` to ignore the expression or result + | +LL - drop(origin); +LL + let _ = origin; + | warning: 1 warning emitted diff --git a/tests/ui/associated-types/defaults-unsound-62211-2.next.stderr b/tests/ui/associated-types/defaults-unsound-62211-2.next.stderr index 0f944a18ed58b..e6ae8183e77dc 100644 --- a/tests/ui/associated-types/defaults-unsound-62211-2.next.stderr +++ b/tests/ui/associated-types/defaults-unsound-62211-2.next.stderr @@ -6,8 +6,12 @@ LL | drop(origin); | | | argument has type `::Output` | - = note: use `let _ = ...` to ignore the expression or result = note: `#[warn(dropping_copy_types)]` on by default +help: use `let _ = ...` to ignore the expression or result + | +LL - drop(origin); +LL + let _ = origin; + | warning: 1 warning emitted diff --git a/tests/ui/lint/dropping_copy_types-issue-125189-can-not-fixed.rs b/tests/ui/lint/dropping_copy_types-issue-125189-can-not-fixed.rs new file mode 100644 index 0000000000000..12c984c932acf --- /dev/null +++ b/tests/ui/lint/dropping_copy_types-issue-125189-can-not-fixed.rs @@ -0,0 +1,14 @@ +//@ check-fail + +#![deny(dropping_copy_types)] + +fn main() { + let y = 1; + let z = 2; + match y { + 0 => drop(y), //~ ERROR calls to `std::mem::drop` + 1 => drop(z), //~ ERROR calls to `std::mem::drop` + 2 => drop(3), //~ ERROR calls to `std::mem::drop` + _ => {}, + } +} diff --git a/tests/ui/lint/dropping_copy_types-issue-125189-can-not-fixed.stderr b/tests/ui/lint/dropping_copy_types-issue-125189-can-not-fixed.stderr new file mode 100644 index 0000000000000..6c73e5ea90b47 --- /dev/null +++ b/tests/ui/lint/dropping_copy_types-issue-125189-can-not-fixed.stderr @@ -0,0 +1,37 @@ +error: calls to `std::mem::drop` with a value that implements `Copy` does nothing + --> $DIR/dropping_copy_types-issue-125189-can-not-fixed.rs:9:14 + | +LL | 0 => drop(y), + | ^^^^^-^ + | | + | argument has type `i32` + | + = note: use `let _ = ...` to ignore the expression or result +note: the lint level is defined here + --> $DIR/dropping_copy_types-issue-125189-can-not-fixed.rs:3:9 + | +LL | #![deny(dropping_copy_types)] + | ^^^^^^^^^^^^^^^^^^^ + +error: calls to `std::mem::drop` with a value that implements `Copy` does nothing + --> $DIR/dropping_copy_types-issue-125189-can-not-fixed.rs:10:14 + | +LL | 1 => drop(z), + | ^^^^^-^ + | | + | argument has type `i32` + | + = note: use `let _ = ...` to ignore the expression or result + +error: calls to `std::mem::drop` with a value that implements `Copy` does nothing + --> $DIR/dropping_copy_types-issue-125189-can-not-fixed.rs:11:14 + | +LL | 2 => drop(3), + | ^^^^^-^ + | | + | argument has type `i32` + | + = note: use `let _ = ...` to ignore the expression or result + +error: aborting due to 3 previous errors + diff --git a/tests/ui/lint/dropping_copy_types-issue-125189.fixed b/tests/ui/lint/dropping_copy_types-issue-125189.fixed new file mode 100644 index 0000000000000..2dfd68d4cc16a --- /dev/null +++ b/tests/ui/lint/dropping_copy_types-issue-125189.fixed @@ -0,0 +1,10 @@ +//@ check-fail +//@ run-rustfix + +#![deny(dropping_copy_types)] + +fn main() { + let y = 1; + let _ = 3.2; //~ ERROR calls to `std::mem::drop` + let _ = y; //~ ERROR calls to `std::mem::drop` +} diff --git a/tests/ui/lint/dropping_copy_types-issue-125189.rs b/tests/ui/lint/dropping_copy_types-issue-125189.rs new file mode 100644 index 0000000000000..1f42efabba9ff --- /dev/null +++ b/tests/ui/lint/dropping_copy_types-issue-125189.rs @@ -0,0 +1,10 @@ +//@ check-fail +//@ run-rustfix + +#![deny(dropping_copy_types)] + +fn main() { + let y = 1; + drop(3.2); //~ ERROR calls to `std::mem::drop` + drop(y); //~ ERROR calls to `std::mem::drop` +} diff --git a/tests/ui/lint/dropping_copy_types-issue-125189.stderr b/tests/ui/lint/dropping_copy_types-issue-125189.stderr new file mode 100644 index 0000000000000..ba3e36f5b6ec4 --- /dev/null +++ b/tests/ui/lint/dropping_copy_types-issue-125189.stderr @@ -0,0 +1,35 @@ +error: calls to `std::mem::drop` with a value that implements `Copy` does nothing + --> $DIR/dropping_copy_types-issue-125189.rs:8:5 + | +LL | drop(3.2); + | ^^^^^---^ + | | + | argument has type `f64` + | +note: the lint level is defined here + --> $DIR/dropping_copy_types-issue-125189.rs:4:9 + | +LL | #![deny(dropping_copy_types)] + | ^^^^^^^^^^^^^^^^^^^ +help: use `let _ = ...` to ignore the expression or result + | +LL - drop(3.2); +LL + let _ = 3.2; + | + +error: calls to `std::mem::drop` with a value that implements `Copy` does nothing + --> $DIR/dropping_copy_types-issue-125189.rs:9:5 + | +LL | drop(y); + | ^^^^^-^ + | | + | argument has type `i32` + | +help: use `let _ = ...` to ignore the expression or result + | +LL - drop(y); +LL + let _ = y; + | + +error: aborting due to 2 previous errors + diff --git a/tests/ui/lint/dropping_copy_types.stderr b/tests/ui/lint/dropping_copy_types.stderr index b6291aa5ed634..bdeb0c290fe93 100644 --- a/tests/ui/lint/dropping_copy_types.stderr +++ b/tests/ui/lint/dropping_copy_types.stderr @@ -6,12 +6,16 @@ LL | drop(s1); | | | argument has type `SomeStruct` | - = note: use `let _ = ...` to ignore the expression or result note: the lint level is defined here --> $DIR/dropping_copy_types.rs:3:9 | LL | #![warn(dropping_copy_types)] | ^^^^^^^^^^^^^^^^^^^ +help: use `let _ = ...` to ignore the expression or result + | +LL - drop(s1); +LL + let _ = s1; + | warning: calls to `std::mem::drop` with a value that implements `Copy` does nothing --> $DIR/dropping_copy_types.rs:35:5 @@ -21,7 +25,11 @@ LL | drop(s2); | | | argument has type `SomeStruct` | - = note: use `let _ = ...` to ignore the expression or result +help: use `let _ = ...` to ignore the expression or result + | +LL - drop(s2); +LL + let _ = s2; + | warning: calls to `std::mem::drop` with a reference instead of an owned value does nothing --> $DIR/dropping_copy_types.rs:36:5 @@ -42,7 +50,11 @@ LL | drop(s4); | | | argument has type `SomeStruct` | - = note: use `let _ = ...` to ignore the expression or result +help: use `let _ = ...` to ignore the expression or result + | +LL - drop(s4); +LL + let _ = s4; + | warning: calls to `std::mem::drop` with a reference instead of an owned value does nothing --> $DIR/dropping_copy_types.rs:38:5 @@ -82,7 +94,11 @@ LL | drop(println_and(13)); | | | argument has type `i32` | - = note: use `let _ = ...` to ignore the expression or result +help: use `let _ = ...` to ignore the expression or result + | +LL - drop(println_and(13)); +LL + let _ = println_and(13); + | warning: calls to `std::mem::drop` with a value that implements `Copy` does nothing --> $DIR/dropping_copy_types.rs:74:14 From 3fe3157858ca1cb038ec5f9eb627ade385a5461a Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Fri, 24 May 2024 17:35:58 +0200 Subject: [PATCH 08/15] Stop using the avx512er and avx512pf x86 target features They are no longer supported by LLVM 19. Fixes #125492 --- compiler/rustc_target/src/target_features.rs | 2 -- library/std/tests/run-time-detect.rs | 2 -- tests/ui/check-cfg/mix.stderr | 2 +- tests/ui/check-cfg/well-known-values.stderr | 2 +- 4 files changed, 2 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs index 1b507bb2a155e..d9812540e497d 100644 --- a/compiler/rustc_target/src/target_features.rs +++ b/compiler/rustc_target/src/target_features.rs @@ -199,11 +199,9 @@ const X86_ALLOWED_FEATURES: &[(&str, Stability)] = &[ ("avx512bw", Unstable(sym::avx512_target_feature)), ("avx512cd", Unstable(sym::avx512_target_feature)), ("avx512dq", Unstable(sym::avx512_target_feature)), - ("avx512er", Unstable(sym::avx512_target_feature)), ("avx512f", Unstable(sym::avx512_target_feature)), ("avx512fp16", Unstable(sym::avx512_target_feature)), ("avx512ifma", Unstable(sym::avx512_target_feature)), - ("avx512pf", Unstable(sym::avx512_target_feature)), ("avx512vbmi", Unstable(sym::avx512_target_feature)), ("avx512vbmi2", Unstable(sym::avx512_target_feature)), ("avx512vl", Unstable(sym::avx512_target_feature)), diff --git a/library/std/tests/run-time-detect.rs b/library/std/tests/run-time-detect.rs index c9b9c54e3d49c..6948670565662 100644 --- a/library/std/tests/run-time-detect.rs +++ b/library/std/tests/run-time-detect.rs @@ -121,10 +121,8 @@ fn x86_all() { println!("avx512bw: {:?}", is_x86_feature_detected!("avx512bw")); println!("avx512cd: {:?}", is_x86_feature_detected!("avx512cd")); println!("avx512dq: {:?}", is_x86_feature_detected!("avx512dq")); - println!("avx512er: {:?}", is_x86_feature_detected!("avx512er")); println!("avx512f: {:?}", is_x86_feature_detected!("avx512f")); println!("avx512ifma: {:?}", is_x86_feature_detected!("avx512ifma")); - println!("avx512pf: {:?}", is_x86_feature_detected!("avx512pf")); println!("avx512vbmi2: {:?}", is_x86_feature_detected!("avx512vbmi2")); println!("avx512vbmi: {:?}", is_x86_feature_detected!("avx512vbmi")); println!("avx512vl: {:?}", is_x86_feature_detected!("avx512vl")); diff --git a/tests/ui/check-cfg/mix.stderr b/tests/ui/check-cfg/mix.stderr index 8c1bf5a11607d..b3d0046fc1788 100644 --- a/tests/ui/check-cfg/mix.stderr +++ b/tests/ui/check-cfg/mix.stderr @@ -251,7 +251,7 @@ warning: unexpected `cfg` condition value: `zebra` LL | cfg!(target_feature = "zebra"); | ^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512er`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512pf`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, `avx512vpopcntdq`, `bf16`, `bmi1`, and `bmi2` and 188 more + = note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, `avx512vpopcntdq`, `bf16`, `bmi1`, `bmi2`, `bti`, and `bulk-memory` and 186 more = note: see for more information about checking conditional configuration warning: 27 warnings emitted diff --git a/tests/ui/check-cfg/well-known-values.stderr b/tests/ui/check-cfg/well-known-values.stderr index c13446bb9f89b..0c50ec1abba99 100644 --- a/tests/ui/check-cfg/well-known-values.stderr +++ b/tests/ui/check-cfg/well-known-values.stderr @@ -165,7 +165,7 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` LL | target_feature = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512er`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512pf`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, `avx512vpopcntdq`, `bf16`, `bmi1`, `bmi2`, `bti`, `bulk-memory`, `c`, `cache`, `cmpxchg16b`, `crc`, `crt-static`, `d`, `d32`, `dit`, `doloop`, `dotprod`, `dpb`, `dpb2`, `dsp`, `dsp1e2`, `dspe60`, `e`, `e1`, `e2`, `edsp`, `elrw`, `ermsb`, `exception-handling`, `extended-const`, `f`, `f16c`, `f32mm`, `f64mm`, `fcma`, `fdivdu`, `fhm`, `flagm`, `float1e2`, `float1e3`, `float3e4`, `float7e60`, `floate1`, `fma`, `fp-armv8`, `fp16`, `fp64`, `fpuv2_df`, `fpuv2_sf`, `fpuv3_df`, `fpuv3_hf`, `fpuv3_hi`, `fpuv3_sf`, `frecipe`, `frintts`, `fxsr`, `gfni`, `hard-float`, `hard-float-abi`, `hard-tp`, `high-registers`, `hvx`, `hvx-length128b`, `hwdiv`, `i8mm`, `jsconv`, `lahfsahf`, `lasx`, `lbt`, `lor`, `lse`, `lsx`, `lvz`, `lzcnt`, `m`, `mclass`, `movbe`, `mp`, `mp1e2`, `msa`, `mte`, `multivalue`, `mutable-globals`, `neon`, `nontrapping-fptoint`, `nvic`, `paca`, `pacg`, `pan`, `pclmulqdq`, `pmuv3`, `popcnt`, `power10-vector`, `power8-altivec`, `power8-vector`, `power9-altivec`, `power9-vector`, `prfchw`, `rand`, `ras`, `rclass`, `rcpc`, `rcpc2`, `rdm`, `rdrand`, `rdseed`, `reference-types`, `relax`, `relaxed-simd`, `rtm`, `sb`, `sha`, `sha2`, `sha3`, `sign-ext`, `simd128`, `sm4`, `spe`, `ssbs`, `sse`, `sse2`, `sse3`, `sse4.1`, `sse4.2`, `sse4a`, `ssse3`, `sve`, `sve2`, `sve2-aes`, `sve2-bitperm`, `sve2-sha3`, `sve2-sm4`, `tbm`, `thumb-mode`, `thumb2`, `tme`, `trust`, `trustzone`, `ual`, `unaligned-scalar-mem`, `v`, `v5te`, `v6`, `v6k`, `v6t2`, `v7`, `v8`, `v8.1a`, `v8.2a`, `v8.3a`, `v8.4a`, `v8.5a`, `v8.6a`, `v8.7a`, `vaes`, `vdsp2e60f`, `vdspv1`, `vdspv2`, `vfp2`, `vfp3`, `vfp4`, `vh`, `virt`, `virtualization`, `vpclmulqdq`, `vsx`, `xsave`, `xsavec`, `xsaveopt`, `xsaves`, `zba`, `zbb`, `zbc`, `zbkb`, `zbkc`, `zbkx`, `zbs`, `zdinx`, `zfh`, `zfhmin`, `zfinx`, `zhinx`, `zhinxmin`, `zk`, `zkn`, `zknd`, `zkne`, `zknh`, `zkr`, `zks`, `zksed`, `zksh`, and `zkt` + = note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, `avx512vpopcntdq`, `bf16`, `bmi1`, `bmi2`, `bti`, `bulk-memory`, `c`, `cache`, `cmpxchg16b`, `crc`, `crt-static`, `d`, `d32`, `dit`, `doloop`, `dotprod`, `dpb`, `dpb2`, `dsp`, `dsp1e2`, `dspe60`, `e`, `e1`, `e2`, `edsp`, `elrw`, `ermsb`, `exception-handling`, `extended-const`, `f`, `f16c`, `f32mm`, `f64mm`, `fcma`, `fdivdu`, `fhm`, `flagm`, `float1e2`, `float1e3`, `float3e4`, `float7e60`, `floate1`, `fma`, `fp-armv8`, `fp16`, `fp64`, `fpuv2_df`, `fpuv2_sf`, `fpuv3_df`, `fpuv3_hf`, `fpuv3_hi`, `fpuv3_sf`, `frecipe`, `frintts`, `fxsr`, `gfni`, `hard-float`, `hard-float-abi`, `hard-tp`, `high-registers`, `hvx`, `hvx-length128b`, `hwdiv`, `i8mm`, `jsconv`, `lahfsahf`, `lasx`, `lbt`, `lor`, `lse`, `lsx`, `lvz`, `lzcnt`, `m`, `mclass`, `movbe`, `mp`, `mp1e2`, `msa`, `mte`, `multivalue`, `mutable-globals`, `neon`, `nontrapping-fptoint`, `nvic`, `paca`, `pacg`, `pan`, `pclmulqdq`, `pmuv3`, `popcnt`, `power10-vector`, `power8-altivec`, `power8-vector`, `power9-altivec`, `power9-vector`, `prfchw`, `rand`, `ras`, `rclass`, `rcpc`, `rcpc2`, `rdm`, `rdrand`, `rdseed`, `reference-types`, `relax`, `relaxed-simd`, `rtm`, `sb`, `sha`, `sha2`, `sha3`, `sign-ext`, `simd128`, `sm4`, `spe`, `ssbs`, `sse`, `sse2`, `sse3`, `sse4.1`, `sse4.2`, `sse4a`, `ssse3`, `sve`, `sve2`, `sve2-aes`, `sve2-bitperm`, `sve2-sha3`, `sve2-sm4`, `tbm`, `thumb-mode`, `thumb2`, `tme`, `trust`, `trustzone`, `ual`, `unaligned-scalar-mem`, `v`, `v5te`, `v6`, `v6k`, `v6t2`, `v7`, `v8`, `v8.1a`, `v8.2a`, `v8.3a`, `v8.4a`, `v8.5a`, `v8.6a`, `v8.7a`, `vaes`, `vdsp2e60f`, `vdspv1`, `vdspv2`, `vfp2`, `vfp3`, `vfp4`, `vh`, `virt`, `virtualization`, `vpclmulqdq`, `vsx`, `xsave`, `xsavec`, `xsaveopt`, `xsaves`, `zba`, `zbb`, `zbc`, `zbkb`, `zbkc`, `zbkx`, `zbs`, `zdinx`, `zfh`, `zfhmin`, `zfinx`, `zhinx`, `zhinxmin`, `zk`, `zkn`, `zknd`, `zkne`, `zknh`, `zkr`, `zks`, `zksed`, `zksh`, and `zkt` = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` From ebd9f355e2b34e36bd5b326c24a5c0eb0b40a371 Mon Sep 17 00:00:00 2001 From: lcnr Date: Fri, 24 May 2024 18:23:24 +0000 Subject: [PATCH 09/15] remove proof tree formatter, make em shallow --- compiler/rustc_interface/src/tests.rs | 5 +- compiler/rustc_middle/src/arena.rs | 5 +- .../rustc_middle/src/traits/solve/cache.rs | 6 +- compiler/rustc_middle/src/ty/context.rs | 3 +- compiler/rustc_session/src/config.rs | 10 - compiler/rustc_session/src/options.rs | 26 +- .../src/solve/eval_ctxt/mod.rs | 27 +-- .../src/solve/fulfill.rs | 6 +- .../src/solve/inspect/analyse.rs | 13 +- .../src/solve/inspect/build.rs | 226 ++++++------------ .../src/solve/search_graph.rs | 20 +- .../src/traits/error_reporting/mod.rs | 17 -- .../error_reporting/type_err_ctxt_ext.rs | 18 +- compiler/rustc_type_ir/src/interner.rs | 8 +- compiler/rustc_type_ir/src/solve/inspect.rs | 77 ++---- .../rustc_type_ir/src/solve/inspect/format.rs | 173 -------------- 16 files changed, 135 insertions(+), 505 deletions(-) delete mode 100644 compiler/rustc_type_ir/src/solve/inspect/format.rs diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 36f9dda7250ca..c6cf7cf4f3f7d 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -799,10 +799,7 @@ fn test_unstable_options_tracking_hash() { tracked!(mir_opt_level, Some(4)); tracked!(move_size_limit, Some(4096)); tracked!(mutable_noalias, false); - tracked!( - next_solver, - Some(NextSolverConfig { coherence: true, globally: false, dump_tree: Default::default() }) - ); + tracked!(next_solver, Some(NextSolverConfig { coherence: true, globally: false })); tracked!(no_generate_arange_section, true); tracked!(no_jump_tables, true); tracked!(no_link, true); diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs index 7392eb6c2bb4d..b0e72eaf5a4cd 100644 --- a/compiler/rustc_middle/src/arena.rs +++ b/compiler/rustc_middle/src/arena.rs @@ -61,7 +61,10 @@ macro_rules! arena_types { [] dtorck_constraint: rustc_middle::traits::query::DropckConstraint<'tcx>, [] candidate_step: rustc_middle::traits::query::CandidateStep<'tcx>, [] autoderef_bad_ty: rustc_middle::traits::query::MethodAutoderefBadTy<'tcx>, - [] canonical_goal_evaluation: rustc_next_trait_solver::solve::inspect::GoalEvaluationStep>, + [] canonical_goal_evaluation: + rustc_next_trait_solver::solve::inspect::CanonicalGoalEvaluationStep< + rustc_middle::ty::TyCtxt<'tcx> + >, [] query_region_constraints: rustc_middle::infer::canonical::QueryRegionConstraints<'tcx>, [] type_op_subtype: rustc_middle::infer::canonical::Canonical<'tcx, diff --git a/compiler/rustc_middle/src/traits/solve/cache.rs b/compiler/rustc_middle/src/traits/solve/cache.rs index 2ff4ade21d087..dc31114b2c459 100644 --- a/compiler/rustc_middle/src/traits/solve/cache.rs +++ b/compiler/rustc_middle/src/traits/solve/cache.rs @@ -17,7 +17,7 @@ pub struct EvaluationCache<'tcx> { #[derive(Debug, PartialEq, Eq)] pub struct CacheData<'tcx> { pub result: QueryResult<'tcx>, - pub proof_tree: Option<&'tcx [inspect::GoalEvaluationStep>]>, + pub proof_tree: Option<&'tcx inspect::CanonicalGoalEvaluationStep>>, pub additional_depth: usize, pub encountered_overflow: bool, } @@ -28,7 +28,7 @@ impl<'tcx> EvaluationCache<'tcx> { &self, tcx: TyCtxt<'tcx>, key: CanonicalInput<'tcx>, - proof_tree: Option<&'tcx [inspect::GoalEvaluationStep>]>, + proof_tree: Option<&'tcx inspect::CanonicalGoalEvaluationStep>>, additional_depth: usize, encountered_overflow: bool, cycle_participants: FxHashSet>, @@ -107,7 +107,7 @@ struct Success<'tcx> { #[derive(Clone, Copy)] pub struct QueryData<'tcx> { pub result: QueryResult<'tcx>, - pub proof_tree: Option<&'tcx [inspect::GoalEvaluationStep>]>, + pub proof_tree: Option<&'tcx inspect::CanonicalGoalEvaluationStep>>, } /// The cache entry for a goal `CanonicalInput`. diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 6e53b5bb52067..d138cd9ceb9d4 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -103,7 +103,8 @@ impl<'tcx> Interner for TyCtxt<'tcx> { type PredefinedOpaques = solve::PredefinedOpaques<'tcx>; type DefiningOpaqueTypes = &'tcx ty::List; type ExternalConstraints = ExternalConstraints<'tcx>; - type GoalEvaluationSteps = &'tcx [solve::inspect::GoalEvaluationStep>]; + type CanonicalGoalEvaluationStepRef = + &'tcx solve::inspect::CanonicalGoalEvaluationStep>; type Ty = Ty<'tcx>; type Tys = &'tcx List>; diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 5ac4d194e8721..c90da966e7081 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -796,16 +796,6 @@ pub struct NextSolverConfig { /// Whether the new trait solver should be enabled everywhere. /// This is only `true` if `coherence` is also enabled. pub globally: bool, - /// Whether to dump proof trees after computing a proof tree. - pub dump_tree: DumpSolverProofTree, -} - -#[derive(Default, Debug, Copy, Clone, Hash, PartialEq, Eq)] -pub enum DumpSolverProofTree { - Always, - OnError, - #[default] - Never, } #[derive(Clone)] diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 65660286dd73a..6309fcdd2db3c 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -399,7 +399,8 @@ mod desc { pub const parse_instrument_xray: &str = "either a boolean (`yes`, `no`, `on`, `off`, etc), or a comma separated list of settings: `always` or `never` (mutually exclusive), `ignore-loops`, `instruction-threshold=N`, `skip-entry`, `skip-exit`"; pub const parse_unpretty: &str = "`string` or `string=string`"; pub const parse_treat_err_as_bug: &str = "either no value or a non-negative number"; - pub const parse_next_solver_config: &str = "a comma separated list of solver configurations: `globally` (default), `coherence`, `dump-tree`, `dump-tree-on-error"; + pub const parse_next_solver_config: &str = + "a comma separated list of solver configurations: `globally` (default), and `coherence`"; pub const parse_lto: &str = "either a boolean (`yes`, `no`, `on`, `off`, etc), `thin`, `fat`, or omitted"; pub const parse_linker_plugin_lto: &str = @@ -1058,7 +1059,6 @@ mod parse { if let Some(config) = v { let mut coherence = false; let mut globally = true; - let mut dump_tree = None; for c in config.split(',') { match c { "globally" => globally = true, @@ -1066,31 +1066,13 @@ mod parse { globally = false; coherence = true; } - "dump-tree" => { - if dump_tree.replace(DumpSolverProofTree::Always).is_some() { - return false; - } - } - "dump-tree-on-error" => { - if dump_tree.replace(DumpSolverProofTree::OnError).is_some() { - return false; - } - } _ => return false, } } - *slot = Some(NextSolverConfig { - coherence: coherence || globally, - globally, - dump_tree: dump_tree.unwrap_or_default(), - }); + *slot = Some(NextSolverConfig { coherence: coherence || globally, globally }); } else { - *slot = Some(NextSolverConfig { - coherence: true, - globally: true, - dump_tree: Default::default(), - }); + *slot = Some(NextSolverConfig { coherence: true, globally: true }); } true diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs index 7e1d7d73e0b3f..ce408ddea3780 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs @@ -1,6 +1,3 @@ -use std::io::Write; -use std::ops::ControlFlow; - use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_hir::def_id::DefId; use rustc_infer::infer::at::ToTrace; @@ -20,10 +17,10 @@ use rustc_middle::ty::{ self, InferCtxtLike, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, }; -use rustc_session::config::DumpSolverProofTree; use rustc_span::DUMMY_SP; use rustc_type_ir::{self as ir, CanonicalVarValues, Interner}; use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic}; +use std::ops::ControlFlow; use crate::traits::coherence; use crate::traits::vtable::{count_own_vtable_entries, prepare_vtable_segments, VtblSegment}; @@ -135,8 +132,7 @@ impl NestedGoals { #[derive(PartialEq, Eq, Debug, Hash, HashStable, Clone, Copy)] pub enum GenerateProofTree { Yes, - IfEnabled, - Never, + No, } #[extension(pub trait InferCtxtEvalExt<'tcx>)] @@ -182,7 +178,7 @@ impl<'a, 'tcx> EvalCtxt<'a, InferCtxt<'tcx>> { infcx, search_graph: &mut search_graph, nested_goals: NestedGoals::new(), - inspect: ProofTreeBuilder::new_maybe_root(infcx.tcx, generate_proof_tree), + inspect: ProofTreeBuilder::new_maybe_root(generate_proof_tree), // Only relevant when canonicalizing the response, // which we don't do within this evaluation context. @@ -197,23 +193,14 @@ impl<'a, 'tcx> EvalCtxt<'a, InferCtxt<'tcx>> { }; let result = f(&mut ecx); - let tree = ecx.inspect.finalize(); - if let (Some(tree), DumpSolverProofTree::Always) = ( - &tree, - infcx.tcx.sess.opts.unstable_opts.next_solver.map(|c| c.dump_tree).unwrap_or_default(), - ) { - let mut lock = std::io::stdout().lock(); - let _ = lock.write_fmt(format_args!("{tree:?}\n")); - let _ = lock.flush(); - } - + let proof_tree = ecx.inspect.finalize(); assert!( ecx.nested_goals.is_empty(), "root `EvalCtxt` should not have any goals added to it" ); assert!(search_graph.is_empty()); - (result, tree) + (result, proof_tree) } /// Creates a nested evaluation context that shares the same search graph as the @@ -483,7 +470,6 @@ impl<'a, 'tcx> EvalCtxt<'a, InferCtxt<'tcx>> { // the certainty of all the goals. #[instrument(level = "trace", skip(self))] pub(super) fn try_evaluate_added_goals(&mut self) -> Result { - self.inspect.start_evaluate_added_goals(); let mut response = Ok(Certainty::overflow(false)); for _ in 0..FIXPOINT_STEP_LIMIT { // FIXME: This match is a bit ugly, it might be nice to change the inspect @@ -501,8 +487,6 @@ impl<'a, 'tcx> EvalCtxt<'a, InferCtxt<'tcx>> { } } - self.inspect.evaluate_added_goals_result(response); - if response.is_err() { self.tainted = Err(NoSolution); } @@ -515,7 +499,6 @@ impl<'a, 'tcx> EvalCtxt<'a, InferCtxt<'tcx>> { /// Goals for the next step get directly added to the nested goals of the `EvalCtxt`. fn evaluate_added_goals_step(&mut self) -> Result, NoSolution> { let tcx = self.tcx(); - self.inspect.start_evaluate_added_goals_step(); let mut goals = core::mem::take(&mut self.nested_goals); // If this loop did not result in any progress, what's our final certainty. diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs index 7291eb00e7271..d28cf834032de 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs @@ -79,7 +79,7 @@ impl<'tcx> ObligationStorage<'tcx> { // change. self.overflowed.extend(self.pending.extract_if(|o| { let goal = o.clone().into(); - let result = infcx.evaluate_root_goal(goal, GenerateProofTree::Never).0; + let result = infcx.evaluate_root_goal(goal, GenerateProofTree::No).0; match result { Ok((has_changed, _)) => has_changed, _ => false, @@ -159,7 +159,7 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> { let mut has_changed = false; for obligation in self.obligations.unstalled_for_select() { let goal = obligation.clone().into(); - let result = infcx.evaluate_root_goal(goal, GenerateProofTree::IfEnabled).0; + let result = infcx.evaluate_root_goal(goal, GenerateProofTree::No).0; self.inspect_evaluated_obligation(infcx, &obligation, &result); let (changed, certainty) = match result { Ok(result) => result, @@ -246,7 +246,7 @@ fn fulfillment_error_for_stalled<'tcx>( root_obligation: PredicateObligation<'tcx>, ) -> FulfillmentError<'tcx> { let (code, refine_obligation) = infcx.probe(|_| { - match infcx.evaluate_root_goal(root_obligation.clone().into(), GenerateProofTree::Never).0 { + match infcx.evaluate_root_goal(root_obligation.clone().into(), GenerateProofTree::No).0 { Ok((_, Certainty::Maybe(MaybeCause::Ambiguity))) => { (FulfillmentErrorCode::Ambiguity { overflow: None }, true) } diff --git a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs index 737d03f73f00b..447357f8b3f64 100644 --- a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs +++ b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs @@ -317,7 +317,6 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> { inspect::ProbeStep::RecordImplArgs { impl_args: i } => { assert_eq!(impl_args.replace(i), None); } - inspect::ProbeStep::EvaluateGoals(_) => (), } } @@ -359,13 +358,7 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> { warn!("unexpected root evaluation: {:?}", self.evaluation_kind); return vec![]; } - inspect::CanonicalGoalEvaluationKind::Evaluation { revisions } => { - if let Some(last) = revisions.last() { - last - } else { - return vec![]; - } - } + inspect::CanonicalGoalEvaluationKind::Evaluation { final_revision } => final_revision, }; let mut nested_goals = vec![]; @@ -392,9 +385,7 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> { normalizes_to_term_hack: Option>, source: GoalSource, ) -> Self { - let inspect::GoalEvaluation { uncanonicalized_goal, kind, evaluation } = root; - let inspect::GoalEvaluationKind::Root { orig_values } = kind else { unreachable!() }; - + let inspect::GoalEvaluation { uncanonicalized_goal, orig_values, evaluation } = root; let result = evaluation.result.and_then(|ok| { if let Some(term_hack) = normalizes_to_term_hack { infcx diff --git a/compiler/rustc_trait_selection/src/solve/inspect/build.rs b/compiler/rustc_trait_selection/src/solve/inspect/build.rs index 803300c5196ca..3c63336264831 100644 --- a/compiler/rustc_trait_selection/src/solve/inspect/build.rs +++ b/compiler/rustc_trait_selection/src/solve/inspect/build.rs @@ -5,20 +5,17 @@ //! see the comment on [ProofTreeBuilder]. use std::mem; +use crate::solve::eval_ctxt::canonical; +use crate::solve::{self, inspect, GenerateProofTree}; use rustc_infer::infer::InferCtxt; use rustc_middle::bug; use rustc_middle::infer::canonical::CanonicalVarValues; -use rustc_middle::traits::query::NoSolution; use rustc_middle::ty::{self, TyCtxt}; use rustc_next_trait_solver::solve::{ CanonicalInput, Certainty, Goal, GoalSource, QueryInput, QueryResult, }; -use rustc_session::config::DumpSolverProofTree; use rustc_type_ir::Interner; -use crate::solve::eval_ctxt::canonical; -use crate::solve::{self, inspect, GenerateProofTree}; - /// The core data structure when building proof trees. /// /// In case the current evaluation does not generate a proof @@ -53,7 +50,7 @@ enum DebugSolver { Root, GoalEvaluation(WipGoalEvaluation), CanonicalGoalEvaluation(WipCanonicalGoalEvaluation), - GoalEvaluationStep(WipGoalEvaluationStep), + CanonicalGoalEvaluationStep(WipCanonicalGoalEvaluationStep), } impl From> for DebugSolver { @@ -68,9 +65,9 @@ impl From> for DebugSolver { } } -impl From> for DebugSolver { - fn from(g: WipGoalEvaluationStep) -> DebugSolver { - DebugSolver::GoalEvaluationStep(g) +impl From> for DebugSolver { + fn from(g: WipCanonicalGoalEvaluationStep) -> DebugSolver { + DebugSolver::CanonicalGoalEvaluationStep(g) } } @@ -78,7 +75,7 @@ impl From> for DebugSolver { #[derivative(PartialEq(bound = ""), Eq(bound = ""), Debug(bound = ""))] struct WipGoalEvaluation { pub uncanonicalized_goal: Goal, - pub kind: WipGoalEvaluationKind, + pub orig_values: Vec, pub evaluation: Option>, } @@ -86,31 +83,19 @@ impl WipGoalEvaluation { fn finalize(self) -> inspect::GoalEvaluation { inspect::GoalEvaluation { uncanonicalized_goal: self.uncanonicalized_goal, - kind: match self.kind { - WipGoalEvaluationKind::Root { orig_values } => { - inspect::GoalEvaluationKind::Root { orig_values } - } - WipGoalEvaluationKind::Nested => inspect::GoalEvaluationKind::Nested, - }, + orig_values: self.orig_values, evaluation: self.evaluation.unwrap().finalize(), } } } -#[derive(derivative::Derivative)] -#[derivative(PartialEq(bound = ""), Eq(bound = ""), Debug(bound = ""))] -pub(in crate::solve) enum WipGoalEvaluationKind { - Root { orig_values: Vec }, - Nested, -} - #[derive(derivative::Derivative)] #[derivative(PartialEq(bound = ""), Eq(bound = ""))] pub(in crate::solve) enum WipCanonicalGoalEvaluationKind { Overflow, CycleInStack, ProvisionalCacheHit, - Interned { revisions: I::GoalEvaluationSteps }, + Interned { final_revision: I::CanonicalGoalEvaluationStepRef }, } impl std::fmt::Debug for WipCanonicalGoalEvaluationKind { @@ -119,7 +104,9 @@ impl std::fmt::Debug for WipCanonicalGoalEvaluationKind { Self::Overflow => write!(f, "Overflow"), Self::CycleInStack => write!(f, "CycleInStack"), Self::ProvisionalCacheHit => write!(f, "ProvisionalCacheHit"), - Self::Interned { revisions: _ } => f.debug_struct("Interned").finish_non_exhaustive(), + Self::Interned { final_revision: _ } => { + f.debug_struct("Interned").finish_non_exhaustive() + } } } } @@ -131,13 +118,15 @@ struct WipCanonicalGoalEvaluation { kind: Option>, /// Only used for uncached goals. After we finished evaluating /// the goal, this is interned and moved into `kind`. - revisions: Vec>, + final_revision: Option>, result: Option>, } impl WipCanonicalGoalEvaluation { fn finalize(self) -> inspect::CanonicalGoalEvaluation { - assert!(self.revisions.is_empty()); + // We've already interned the final revision in + // `fn finalize_canonical_goal_evaluation`. + assert!(self.final_revision.is_none()); let kind = match self.kind.unwrap() { WipCanonicalGoalEvaluationKind::Overflow => { inspect::CanonicalGoalEvaluationKind::Overflow @@ -148,8 +137,8 @@ impl WipCanonicalGoalEvaluation { WipCanonicalGoalEvaluationKind::ProvisionalCacheHit => { inspect::CanonicalGoalEvaluationKind::ProvisionalCacheHit } - WipCanonicalGoalEvaluationKind::Interned { revisions } => { - inspect::CanonicalGoalEvaluationKind::Evaluation { revisions } + WipCanonicalGoalEvaluationKind::Interned { final_revision } => { + inspect::CanonicalGoalEvaluationKind::Evaluation { final_revision } } }; @@ -159,29 +148,7 @@ impl WipCanonicalGoalEvaluation { #[derive(derivative::Derivative)] #[derivative(PartialEq(bound = ""), Eq(bound = ""), Debug(bound = ""))] -struct WipAddedGoalsEvaluation { - evaluations: Vec>>, - result: Option>, -} - -impl WipAddedGoalsEvaluation { - fn finalize(self) -> inspect::AddedGoalsEvaluation { - inspect::AddedGoalsEvaluation { - evaluations: self - .evaluations - .into_iter() - .map(|evaluations| { - evaluations.into_iter().map(WipGoalEvaluation::finalize).collect() - }) - .collect(), - result: self.result.unwrap(), - } - } -} - -#[derive(derivative::Derivative)] -#[derivative(PartialEq(bound = ""), Eq(bound = ""), Debug(bound = ""))] -struct WipGoalEvaluationStep { +struct WipCanonicalGoalEvaluationStep { /// Unlike `EvalCtxt::var_values`, we append a new /// generic arg here whenever we create a new inference /// variable. @@ -194,7 +161,7 @@ struct WipGoalEvaluationStep { evaluation: WipProbe, } -impl WipGoalEvaluationStep { +impl WipCanonicalGoalEvaluationStep { fn current_evaluation_scope(&mut self) -> &mut WipProbe { let mut current = &mut self.evaluation; for _ in 0..self.probe_depth { @@ -206,24 +173,16 @@ impl WipGoalEvaluationStep { current } - fn added_goals_evaluation(&mut self) -> &mut WipAddedGoalsEvaluation { - let mut current = &mut self.evaluation; - loop { - match current.steps.last_mut() { - Some(WipProbeStep::NestedProbe(p)) => current = p, - Some(WipProbeStep::EvaluateGoals(evaluation)) => return evaluation, - _ => bug!(), - } - } - } - - fn finalize(self) -> inspect::GoalEvaluationStep { + fn finalize(self) -> inspect::CanonicalGoalEvaluationStep { let evaluation = self.evaluation.finalize(); match evaluation.kind { inspect::ProbeKind::Root { .. } => (), _ => unreachable!("unexpected root evaluation: {evaluation:?}"), } - inspect::GoalEvaluationStep { instantiated_goal: self.instantiated_goal, evaluation } + inspect::CanonicalGoalEvaluationStep { + instantiated_goal: self.instantiated_goal, + evaluation, + } } } @@ -250,7 +209,6 @@ impl WipProbe { #[derivative(PartialEq(bound = ""), Eq(bound = ""), Debug(bound = ""))] enum WipProbeStep { AddGoal(GoalSource, inspect::CanonicalState>), - EvaluateGoals(WipAddedGoalsEvaluation), NestedProbe(WipProbe), MakeCanonicalResponse { shallow_certainty: Certainty }, RecordImplArgs { impl_args: inspect::CanonicalState }, @@ -260,7 +218,6 @@ impl WipProbeStep { fn finalize(self) -> inspect::ProbeStep { match self { WipProbeStep::AddGoal(source, goal) => inspect::ProbeStep::AddGoal(source, goal), - WipProbeStep::EvaluateGoals(eval) => inspect::ProbeStep::EvaluateGoals(eval.finalize()), WipProbeStep::NestedProbe(probe) => inspect::ProbeStep::NestedProbe(probe.finalize()), WipProbeStep::RecordImplArgs { impl_args } => { inspect::ProbeStep::RecordImplArgs { impl_args } @@ -278,6 +235,15 @@ impl<'tcx> ProofTreeBuilder> { ProofTreeBuilder { state: Some(Box::new(state.into())) } } + fn opt_nested>>>( + &self, + state: impl FnOnce() -> Option, + ) -> Self { + ProofTreeBuilder { + state: self.state.as_ref().and_then(|_| Some(state()?.into())).map(Box::new), + } + } + fn nested>>>(&self, state: impl FnOnce() -> T) -> Self { ProofTreeBuilder { state: self.state.as_ref().map(|_| Box::new(state().into())) } } @@ -302,22 +268,10 @@ impl<'tcx> ProofTreeBuilder> { } pub fn new_maybe_root( - tcx: TyCtxt<'tcx>, generate_proof_tree: GenerateProofTree, ) -> ProofTreeBuilder> { match generate_proof_tree { - GenerateProofTree::Never => ProofTreeBuilder::new_noop(), - GenerateProofTree::IfEnabled => { - let opts = &tcx.sess.opts.unstable_opts; - match opts.next_solver.map(|c| c.dump_tree).unwrap_or_default() { - DumpSolverProofTree::Always => ProofTreeBuilder::new_root(), - // `OnError` is handled by reevaluating goals in error - // reporting with `GenerateProofTree::Yes`. - DumpSolverProofTree::OnError | DumpSolverProofTree::Never => { - ProofTreeBuilder::new_noop() - } - } - } + GenerateProofTree::No => ProofTreeBuilder::new_noop(), GenerateProofTree::Yes => ProofTreeBuilder::new_root(), } } @@ -340,15 +294,13 @@ impl<'tcx> ProofTreeBuilder> { orig_values: &[ty::GenericArg<'tcx>], kind: solve::GoalEvaluationKind, ) -> ProofTreeBuilder> { - self.nested(|| WipGoalEvaluation { - uncanonicalized_goal: goal, - kind: match kind { - solve::GoalEvaluationKind::Root => { - WipGoalEvaluationKind::Root { orig_values: orig_values.to_vec() } - } - solve::GoalEvaluationKind::Nested => WipGoalEvaluationKind::Nested, - }, - evaluation: None, + self.opt_nested(|| match kind { + solve::GoalEvaluationKind::Root => Some(WipGoalEvaluation { + uncanonicalized_goal: goal, + orig_values: orig_values.to_vec(), + evaluation: None, + }), + solve::GoalEvaluationKind::Nested => None, }) } @@ -359,24 +311,22 @@ impl<'tcx> ProofTreeBuilder> { self.nested(|| WipCanonicalGoalEvaluation { goal, kind: None, - revisions: vec![], + final_revision: None, result: None, }) } - pub fn finalize_evaluation( + pub fn finalize_canonical_goal_evaluation( &mut self, tcx: TyCtxt<'tcx>, - ) -> Option<&'tcx [inspect::GoalEvaluationStep>]> { + ) -> Option<&'tcx inspect::CanonicalGoalEvaluationStep>> { self.as_mut().map(|this| match this { DebugSolver::CanonicalGoalEvaluation(evaluation) => { - let revisions = mem::take(&mut evaluation.revisions) - .into_iter() - .map(WipGoalEvaluationStep::finalize); - let revisions = &*tcx.arena.alloc_from_iter(revisions); - let kind = WipCanonicalGoalEvaluationKind::Interned { revisions }; + let final_revision = mem::take(&mut evaluation.final_revision).unwrap(); + let final_revision = &*tcx.arena.alloc(final_revision.finalize()); + let kind = WipCanonicalGoalEvaluationKind::Interned { final_revision }; assert_eq!(evaluation.kind.replace(kind), None); - revisions + final_revision } _ => unreachable!(), }) @@ -400,7 +350,10 @@ impl<'tcx> ProofTreeBuilder> { } } - pub fn goal_evaluation_kind(&mut self, kind: WipCanonicalGoalEvaluationKind>) { + pub fn canonical_goal_evaluation_kind( + &mut self, + kind: WipCanonicalGoalEvaluationKind>, + ) { if let Some(this) = self.as_mut() { match this { DebugSolver::CanonicalGoalEvaluation(canonical_goal_evaluation) => { @@ -413,17 +366,11 @@ impl<'tcx> ProofTreeBuilder> { pub fn goal_evaluation(&mut self, goal_evaluation: ProofTreeBuilder>) { if let Some(this) = self.as_mut() { - match (this, *goal_evaluation.state.unwrap()) { - ( - DebugSolver::GoalEvaluationStep(state), - DebugSolver::GoalEvaluation(goal_evaluation), - ) => state - .added_goals_evaluation() - .evaluations - .last_mut() - .unwrap() - .push(goal_evaluation), - (this @ DebugSolver::Root, goal_evaluation) => *this = goal_evaluation, + match this { + DebugSolver::Root => *this = *goal_evaluation.state.unwrap(), + DebugSolver::CanonicalGoalEvaluationStep(_) => { + assert!(goal_evaluation.state.is_none()) + } _ => unreachable!(), } } @@ -434,7 +381,7 @@ impl<'tcx> ProofTreeBuilder> { var_values: CanonicalVarValues<'tcx>, instantiated_goal: QueryInput, ty::Predicate<'tcx>>, ) -> ProofTreeBuilder> { - self.nested(|| WipGoalEvaluationStep { + self.nested(|| WipCanonicalGoalEvaluationStep { var_values: var_values.var_values.to_vec(), instantiated_goal, evaluation: WipProbe { @@ -452,9 +399,9 @@ impl<'tcx> ProofTreeBuilder> { match (this, *goal_evaluation_step.state.unwrap()) { ( DebugSolver::CanonicalGoalEvaluation(canonical_goal_evaluations), - DebugSolver::GoalEvaluationStep(goal_evaluation_step), + DebugSolver::CanonicalGoalEvaluationStep(goal_evaluation_step), ) => { - canonical_goal_evaluations.revisions.push(goal_evaluation_step); + canonical_goal_evaluations.final_revision = Some(goal_evaluation_step); } _ => unreachable!(), } @@ -464,7 +411,7 @@ impl<'tcx> ProofTreeBuilder> { pub fn add_var_value>>(&mut self, arg: T) { match self.as_mut() { None => {} - Some(DebugSolver::GoalEvaluationStep(state)) => { + Some(DebugSolver::CanonicalGoalEvaluationStep(state)) => { state.var_values.push(arg.into()); } Some(s) => bug!("tried to add var values to {s:?}"), @@ -474,7 +421,7 @@ impl<'tcx> ProofTreeBuilder> { pub fn enter_probe(&mut self) { match self.as_mut() { None => {} - Some(DebugSolver::GoalEvaluationStep(state)) => { + Some(DebugSolver::CanonicalGoalEvaluationStep(state)) => { let initial_num_var_values = state.var_values.len(); state.current_evaluation_scope().steps.push(WipProbeStep::NestedProbe(WipProbe { initial_num_var_values, @@ -491,7 +438,7 @@ impl<'tcx> ProofTreeBuilder> { pub fn probe_kind(&mut self, probe_kind: inspect::ProbeKind>) { match self.as_mut() { None => {} - Some(DebugSolver::GoalEvaluationStep(state)) => { + Some(DebugSolver::CanonicalGoalEvaluationStep(state)) => { let prev = state.current_evaluation_scope().kind.replace(probe_kind); assert_eq!(prev, None); } @@ -506,7 +453,7 @@ impl<'tcx> ProofTreeBuilder> { ) { match self.as_mut() { None => {} - Some(DebugSolver::GoalEvaluationStep(state)) => { + Some(DebugSolver::CanonicalGoalEvaluationStep(state)) => { let final_state = canonical::make_canonical_state( infcx, &state.var_values, @@ -543,7 +490,7 @@ impl<'tcx> ProofTreeBuilder> { ) { match self.as_mut() { None => {} - Some(DebugSolver::GoalEvaluationStep(state)) => { + Some(DebugSolver::CanonicalGoalEvaluationStep(state)) => { let goal = canonical::make_canonical_state( infcx, &state.var_values, @@ -563,7 +510,7 @@ impl<'tcx> ProofTreeBuilder> { impl_args: ty::GenericArgsRef<'tcx>, ) { match self.as_mut() { - Some(DebugSolver::GoalEvaluationStep(state)) => { + Some(DebugSolver::CanonicalGoalEvaluationStep(state)) => { let impl_args = canonical::make_canonical_state( infcx, &state.var_values, @@ -582,7 +529,7 @@ impl<'tcx> ProofTreeBuilder> { pub fn make_canonical_response(&mut self, shallow_certainty: Certainty) { match self.as_mut() { - Some(DebugSolver::GoalEvaluationStep(state)) => { + Some(DebugSolver::CanonicalGoalEvaluationStep(state)) => { state .current_evaluation_scope() .steps @@ -596,7 +543,7 @@ impl<'tcx> ProofTreeBuilder> { pub fn finish_probe(mut self) -> ProofTreeBuilder> { match self.as_mut() { None => {} - Some(DebugSolver::GoalEvaluationStep(state)) => { + Some(DebugSolver::CanonicalGoalEvaluationStep(state)) => { assert_ne!(state.probe_depth, 0); let num_var_values = state.current_evaluation_scope().initial_num_var_values; state.var_values.truncate(num_var_values); @@ -608,46 +555,13 @@ impl<'tcx> ProofTreeBuilder> { self } - pub fn start_evaluate_added_goals(&mut self) { - match self.as_mut() { - None => {} - Some(DebugSolver::GoalEvaluationStep(state)) => { - state.current_evaluation_scope().steps.push(WipProbeStep::EvaluateGoals( - WipAddedGoalsEvaluation { evaluations: vec![], result: None }, - )); - } - _ => bug!(), - } - } - - pub fn start_evaluate_added_goals_step(&mut self) { - match self.as_mut() { - None => {} - Some(DebugSolver::GoalEvaluationStep(state)) => { - state.added_goals_evaluation().evaluations.push(vec![]); - } - _ => bug!(), - } - } - - pub fn evaluate_added_goals_result(&mut self, result: Result) { - match self.as_mut() { - None => {} - Some(DebugSolver::GoalEvaluationStep(state)) => { - let prev = state.added_goals_evaluation().result.replace(result); - assert_eq!(prev, None); - } - _ => bug!(), - } - } - pub fn query_result(&mut self, result: QueryResult>) { if let Some(this) = self.as_mut() { match this { DebugSolver::CanonicalGoalEvaluation(canonical_goal_evaluation) => { assert_eq!(canonical_goal_evaluation.result.replace(result), None); } - DebugSolver::GoalEvaluationStep(evaluation_step) => { + DebugSolver::CanonicalGoalEvaluationStep(evaluation_step) => { assert_eq!( evaluation_step .evaluation diff --git a/compiler/rustc_trait_selection/src/solve/search_graph.rs b/compiler/rustc_trait_selection/src/solve/search_graph.rs index bcd210f789bfe..6be623b6044f0 100644 --- a/compiler/rustc_trait_selection/src/solve/search_graph.rs +++ b/compiler/rustc_trait_selection/src/solve/search_graph.rs @@ -274,7 +274,8 @@ impl<'tcx> SearchGraph> { last.encountered_overflow = true; } - inspect.goal_evaluation_kind(inspect::WipCanonicalGoalEvaluationKind::Overflow); + inspect + .canonical_goal_evaluation_kind(inspect::WipCanonicalGoalEvaluationKind::Overflow); return Self::response_no_constraints(tcx, input, Certainty::overflow(true)); }; @@ -302,8 +303,9 @@ impl<'tcx> SearchGraph> { // We have a nested goal which is already in the provisional cache, use // its result. We do not provide any usage kind as that should have been // already set correctly while computing the cache entry. - inspect - .goal_evaluation_kind(inspect::WipCanonicalGoalEvaluationKind::ProvisionalCacheHit); + inspect.canonical_goal_evaluation_kind( + inspect::WipCanonicalGoalEvaluationKind::ProvisionalCacheHit, + ); Self::tag_cycle_participants(&mut self.stack, HasBeenUsed::empty(), entry.head); return entry.result; } else if let Some(stack_depth) = cache_entry.stack_depth { @@ -314,7 +316,9 @@ impl<'tcx> SearchGraph> { // // Finally we can return either the provisional response or the initial response // in case we're in the first fixpoint iteration for this goal. - inspect.goal_evaluation_kind(inspect::WipCanonicalGoalEvaluationKind::CycleInStack); + inspect.canonical_goal_evaluation_kind( + inspect::WipCanonicalGoalEvaluationKind::CycleInStack, + ); let is_coinductive_cycle = Self::stack_coinductive_from(tcx, &self.stack, stack_depth); let usage_kind = if is_coinductive_cycle { HasBeenUsed::COINDUCTIVE_CYCLE @@ -371,7 +375,7 @@ impl<'tcx> SearchGraph> { (current_entry, result) }); - let proof_tree = inspect.finalize_evaluation(tcx); + let proof_tree = inspect.finalize_canonical_goal_evaluation(tcx); // We're now done with this goal. In case this goal is involved in a larger cycle // do not remove it from the provisional cache and update its provisional result. @@ -433,9 +437,9 @@ impl<'tcx> SearchGraph> { // the goal. We simply overwrite the existing entry once we're done, // caching the proof tree. if !inspect.is_noop() { - if let Some(revisions) = proof_tree { - let kind = inspect::WipCanonicalGoalEvaluationKind::Interned { revisions }; - inspect.goal_evaluation_kind(kind); + if let Some(final_revision) = proof_tree { + let kind = inspect::WipCanonicalGoalEvaluationKind::Interned { final_revision }; + inspect.canonical_goal_evaluation_kind(kind); } else { return None; } diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index e50edfdc656ce..633d488f7be5f 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -7,15 +7,11 @@ pub mod suggestions; mod type_err_ctxt_ext; use super::{Obligation, ObligationCause, ObligationCauseCode, PredicateObligation}; -use crate::infer::InferCtxt; -use crate::solve::{GenerateProofTree, InferCtxtEvalExt}; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir::intravisit::Visitor; -use rustc_middle::traits::solve::Goal; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_span::Span; -use std::io::Write; use std::ops::ControlFlow; pub use self::infer_ctxt_ext::*; @@ -184,16 +180,3 @@ pub enum DefIdOrName { DefId(DefId), Name(&'static str), } - -pub fn dump_proof_tree<'tcx>(o: &Obligation<'tcx, ty::Predicate<'tcx>>, infcx: &InferCtxt<'tcx>) { - infcx.probe(|_| { - let goal = Goal { predicate: o.predicate, param_env: o.param_env }; - let tree = infcx - .evaluate_root_goal(goal, GenerateProofTree::Yes) - .1 - .expect("proof tree should have been generated"); - let mut lock = std::io::stdout().lock(); - let _ = lock.write_fmt(format_args!("{tree:?}\n")); - let _ = lock.flush(); - }); -} diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs index 494fca0336cc0..46953a61296ac 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs @@ -46,7 +46,6 @@ use rustc_middle::ty::{ TypeVisitableExt, Upcast, }; use rustc_middle::{bug, span_bug}; -use rustc_session::config::DumpSolverProofTree; use rustc_session::Limit; use rustc_span::def_id::LOCAL_CRATE; use rustc_span::symbol::sym; @@ -56,8 +55,8 @@ use std::fmt; use std::iter; use super::{ - dump_proof_tree, ArgKind, CandidateSimilarity, FindExprBySpan, FindTypeParam, - GetSafeTransmuteErrorAndReason, HasNumericInferVisitor, ImplCandidate, UnsatisfiedConst, + ArgKind, CandidateSimilarity, FindExprBySpan, FindTypeParam, GetSafeTransmuteErrorAndReason, + HasNumericInferVisitor, ImplCandidate, UnsatisfiedConst, }; pub use rustc_infer::traits::error_reporting::*; @@ -369,13 +368,6 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { error: &SelectionError<'tcx>, ) -> ErrorGuaranteed { let tcx = self.tcx; - - if tcx.sess.opts.unstable_opts.next_solver.map(|c| c.dump_tree).unwrap_or_default() - == DumpSolverProofTree::OnError - { - dump_proof_tree(root_obligation, self.infcx); - } - let mut span = obligation.cause.span; let mut err = match *error { @@ -1529,12 +1521,6 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { #[instrument(skip(self), level = "debug")] fn report_fulfillment_error(&self, error: &FulfillmentError<'tcx>) -> ErrorGuaranteed { - if self.tcx.sess.opts.unstable_opts.next_solver.map(|c| c.dump_tree).unwrap_or_default() - == DumpSolverProofTree::OnError - { - dump_proof_tree(&error.root_obligation, self.infcx); - } - match error.code { FulfillmentErrorCode::Select(ref selection_error) => self.report_selection_error( error.obligation.clone(), diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs index 9b8bb210ff424..c77414afc52c7 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -5,7 +5,7 @@ use std::ops::Deref; use crate::inherent::*; use crate::ir_print::IrPrint; -use crate::solve::inspect::GoalEvaluationStep; +use crate::solve::inspect::CanonicalGoalEvaluationStep; use crate::visit::{Flags, TypeSuperVisitable, TypeVisitable}; use crate::{ AliasTerm, AliasTermKind, AliasTy, AliasTyKind, CanonicalVarInfo, CoercePredicate, @@ -55,7 +55,11 @@ pub trait Interner: type PredefinedOpaques: Copy + Debug + Hash + Eq; type DefiningOpaqueTypes: Copy + Debug + Hash + Default + Eq + TypeVisitable; type ExternalConstraints: Copy + Debug + Hash + Eq; - type GoalEvaluationSteps: Copy + Debug + Hash + Eq + Deref]>; + type CanonicalGoalEvaluationStepRef: Copy + + Debug + + Hash + + Eq + + Deref>; // Kinds of tys type Ty: Ty; diff --git a/compiler/rustc_type_ir/src/solve/inspect.rs b/compiler/rustc_type_ir/src/solve/inspect.rs index c4f6ee2669bef..0733c730064b0 100644 --- a/compiler/rustc_type_ir/src/solve/inspect.rs +++ b/compiler/rustc_type_ir/src/solve/inspect.rs @@ -1,36 +1,29 @@ //! Data structure used to inspect trait solver behavior. //! //! During trait solving we optionally build "proof trees", the root of -//! which is a [GoalEvaluation] with [GoalEvaluationKind::Root]. These -//! trees are used to improve the debug experience and are also used by -//! the compiler itself to provide necessary context for error messages. +//! which is a [GoalEvaluation]. These trees are used by the compiler +//! to inspect the behavior of the trait solver and to access its internal +//! state, e.g. for diagnostics and when selecting impls during codegen. //! //! Because each nested goal in the solver gets [canonicalized] separately //! and we discard inference progress via "probes", we cannot mechanically //! use proof trees without somehow "lifting up" data local to the current -//! `InferCtxt`. Any data used mechanically is therefore canonicalized and -//! stored as [CanonicalState]. As printing canonicalized data worsens the -//! debugging dumps, we do not simply canonicalize everything. +//! `InferCtxt`. To use the data from evaluation we therefore canonicalize +//! it and store it as a [CanonicalState]. //! -//! This means proof trees contain inference variables and placeholders -//! local to a different `InferCtxt` which must not be used with the -//! current one. +//! Proof trees are only shallow, we do not compute the proof tree for nested +//! goals. Visiting proof trees instead recomputes nested goals in the parents +//! inference context when necessary. //! //! [canonicalized]: https://rustc-dev-guide.rust-lang.org/solve/canonicalization.html -mod format; - -use std::fmt::{Debug, Write}; -use std::hash::Hash; - -use rustc_type_ir_macros::{TypeFoldable_Generic, TypeVisitable_Generic}; - -use self::format::ProofTreeFormatter; use crate::solve::{ - CandidateSource, CanonicalInput, Certainty, Goal, GoalSource, NoSolution, QueryInput, - QueryResult, + CandidateSource, CanonicalInput, Certainty, Goal, GoalSource, QueryInput, QueryResult, }; use crate::{Canonical, CanonicalVarValues, Interner}; +use rustc_type_ir_macros::{TypeFoldable_Generic, TypeVisitable_Generic}; +use std::fmt::Debug; +use std::hash::Hash; /// Some `data` together with information about how they relate to the input /// of the canonical query. @@ -55,23 +48,15 @@ pub struct State { pub type CanonicalState = Canonical>; -/// When evaluating the root goals we also store the -/// original values for the `CanonicalVarValues` of the -/// canonicalized goal. We use this to map any [CanonicalState] -/// from the local `InferCtxt` of the solver query to -/// the `InferCtxt` of the caller. -#[derive(derivative::Derivative)] -#[derivative(PartialEq(bound = ""), Eq(bound = ""), Hash(bound = ""), Debug(bound = ""))] -pub enum GoalEvaluationKind { - Root { orig_values: Vec }, - Nested, -} - +/// When evaluating a goal we also store the original values +/// for the `CanonicalVarValues` of the canonicalized goal. +/// We use this to map any [CanonicalState] from the local `InferCtxt` +/// of the solver query to the `InferCtxt` of the caller. #[derive(derivative::Derivative)] #[derivative(PartialEq(bound = ""), Eq(bound = ""), Hash(bound = ""))] pub struct GoalEvaluation { pub uncanonicalized_goal: Goal, - pub kind: GoalEvaluationKind, + pub orig_values: Vec, pub evaluation: CanonicalGoalEvaluation, } @@ -89,24 +74,12 @@ pub enum CanonicalGoalEvaluationKind { Overflow, CycleInStack, ProvisionalCacheHit, - Evaluation { revisions: I::GoalEvaluationSteps }, -} -impl Debug for GoalEvaluation { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - ProofTreeFormatter::new(f).format_goal_evaluation(self) - } + Evaluation { final_revision: I::CanonicalGoalEvaluationStepRef }, } #[derive(derivative::Derivative)] #[derivative(PartialEq(bound = ""), Eq(bound = ""), Hash(bound = ""), Debug(bound = ""))] -pub struct AddedGoalsEvaluation { - pub evaluations: Vec>>, - pub result: Result, -} - -#[derive(derivative::Derivative)] -#[derivative(PartialEq(bound = ""), Eq(bound = ""), Hash(bound = ""), Debug(bound = ""))] -pub struct GoalEvaluationStep { +pub struct CanonicalGoalEvaluationStep { pub instantiated_goal: QueryInput, /// The actual evaluation of the goal, always `ProbeKind::Root`. @@ -117,7 +90,7 @@ pub struct GoalEvaluationStep { /// corresponds to a `EvalCtxt::probe(_X)` call or the root evaluation /// of a goal. #[derive(derivative::Derivative)] -#[derivative(PartialEq(bound = ""), Eq(bound = ""), Hash(bound = ""))] +#[derivative(Debug(bound = ""), PartialEq(bound = ""), Eq(bound = ""), Hash(bound = ""))] pub struct Probe { /// What happened inside of this probe in chronological order. pub steps: Vec>, @@ -125,23 +98,15 @@ pub struct Probe { pub final_state: CanonicalState, } -impl Debug for Probe { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - ProofTreeFormatter::new(f).format_probe(self) - } -} - #[derive(derivative::Derivative)] #[derivative(PartialEq(bound = ""), Eq(bound = ""), Hash(bound = ""), Debug(bound = ""))] pub enum ProbeStep { /// We added a goal to the `EvalCtxt` which will get proven /// the next time `EvalCtxt::try_evaluate_added_goals` is called. AddGoal(GoalSource, CanonicalState>), - /// The inside of a `EvalCtxt::try_evaluate_added_goals` call. - EvaluateGoals(AddedGoalsEvaluation), /// A call to `probe` while proving the current goal. This is /// used whenever there are multiple candidates to prove the - /// current goalby . + /// current goal. NestedProbe(Probe), /// A trait goal was satisfied by an impl candidate. RecordImplArgs { impl_args: CanonicalState }, diff --git a/compiler/rustc_type_ir/src/solve/inspect/format.rs b/compiler/rustc_type_ir/src/solve/inspect/format.rs deleted file mode 100644 index 44ade04cf98ca..0000000000000 --- a/compiler/rustc_type_ir/src/solve/inspect/format.rs +++ /dev/null @@ -1,173 +0,0 @@ -use std::marker::PhantomData; - -use super::*; - -pub(super) struct ProofTreeFormatter<'a, 'b, I> { - f: &'a mut (dyn Write + 'b), - _interner: PhantomData, -} - -enum IndentorState { - StartWithNewline, - OnNewline, - Inline, -} - -/// A formatter which adds 4 spaces of indentation to its input before -/// passing it on to its nested formatter. -/// -/// We can use this for arbitrary levels of indentation by nesting it. -struct Indentor<'a, 'b> { - f: &'a mut (dyn Write + 'b), - state: IndentorState, -} - -impl Write for Indentor<'_, '_> { - fn write_str(&mut self, s: &str) -> std::fmt::Result { - for line in s.split_inclusive('\n') { - match self.state { - IndentorState::StartWithNewline => self.f.write_str("\n ")?, - IndentorState::OnNewline => self.f.write_str(" ")?, - IndentorState::Inline => {} - } - self.state = - if line.ends_with('\n') { IndentorState::OnNewline } else { IndentorState::Inline }; - self.f.write_str(line)?; - } - - Ok(()) - } -} - -impl<'a, 'b, I: Interner> ProofTreeFormatter<'a, 'b, I> { - pub(super) fn new(f: &'a mut (dyn Write + 'b)) -> Self { - ProofTreeFormatter { f, _interner: PhantomData } - } - - fn nested(&mut self, func: F) -> std::fmt::Result - where - F: FnOnce(&mut ProofTreeFormatter<'_, '_, I>) -> std::fmt::Result, - { - write!(self.f, " {{")?; - func(&mut ProofTreeFormatter { - f: &mut Indentor { f: self.f, state: IndentorState::StartWithNewline }, - _interner: PhantomData, - })?; - writeln!(self.f, "}}") - } - - pub(super) fn format_goal_evaluation(&mut self, eval: &GoalEvaluation) -> std::fmt::Result { - let goal_text = match eval.kind { - GoalEvaluationKind::Root { orig_values: _ } => "ROOT GOAL", - GoalEvaluationKind::Nested => "GOAL", - }; - write!(self.f, "{}: {:?}", goal_text, eval.uncanonicalized_goal)?; - self.nested(|this| this.format_canonical_goal_evaluation(&eval.evaluation)) - } - - pub(super) fn format_canonical_goal_evaluation( - &mut self, - eval: &CanonicalGoalEvaluation, - ) -> std::fmt::Result { - writeln!(self.f, "GOAL: {:?}", eval.goal)?; - - match &eval.kind { - CanonicalGoalEvaluationKind::Overflow => { - writeln!(self.f, "OVERFLOW: {:?}", eval.result) - } - CanonicalGoalEvaluationKind::CycleInStack => { - writeln!(self.f, "CYCLE IN STACK: {:?}", eval.result) - } - CanonicalGoalEvaluationKind::ProvisionalCacheHit => { - writeln!(self.f, "PROVISIONAL CACHE HIT: {:?}", eval.result) - } - CanonicalGoalEvaluationKind::Evaluation { revisions } => { - for (n, step) in revisions.iter().enumerate() { - write!(self.f, "REVISION {n}")?; - self.nested(|this| this.format_evaluation_step(step))?; - } - writeln!(self.f, "RESULT: {:?}", eval.result) - } - } - } - - pub(super) fn format_evaluation_step( - &mut self, - evaluation_step: &GoalEvaluationStep, - ) -> std::fmt::Result { - writeln!(self.f, "INSTANTIATED: {:?}", evaluation_step.instantiated_goal)?; - self.format_probe(&evaluation_step.evaluation) - } - - pub(super) fn format_probe(&mut self, probe: &Probe) -> std::fmt::Result { - match &probe.kind { - ProbeKind::Root { result } => { - write!(self.f, "ROOT RESULT: {result:?}") - } - ProbeKind::TryNormalizeNonRigid { result } => { - write!(self.f, "TRY NORMALIZE NON-RIGID: {result:?}") - } - ProbeKind::NormalizedSelfTyAssembly => { - write!(self.f, "NORMALIZING SELF TY FOR ASSEMBLY:") - } - ProbeKind::UnsizeAssembly => { - write!(self.f, "ASSEMBLING CANDIDATES FOR UNSIZING:") - } - ProbeKind::UpcastProjectionCompatibility => { - write!(self.f, "PROBING FOR PROJECTION COMPATIBILITY FOR UPCASTING:") - } - ProbeKind::OpaqueTypeStorageLookup { result } => { - write!(self.f, "PROBING FOR AN EXISTING OPAQUE: {result:?}") - } - ProbeKind::TraitCandidate { source, result } => { - write!(self.f, "CANDIDATE {source:?}: {result:?}") - } - ProbeKind::ShadowedEnvProbing => { - write!(self.f, "PROBING FOR IMPLS SHADOWED BY PARAM-ENV CANDIDATE:") - } - }?; - - self.nested(|this| { - for step in &probe.steps { - match step { - ProbeStep::AddGoal(source, goal) => { - let source = match source { - GoalSource::Misc => "misc", - GoalSource::ImplWhereBound => "impl where-bound", - GoalSource::InstantiateHigherRanked => "higher-ranked goal", - }; - writeln!(this.f, "ADDED GOAL ({source}): {goal:?}")? - } - ProbeStep::EvaluateGoals(eval) => this.format_added_goals_evaluation(eval)?, - ProbeStep::NestedProbe(probe) => this.format_probe(probe)?, - ProbeStep::MakeCanonicalResponse { shallow_certainty } => { - writeln!(this.f, "EVALUATE GOALS AND MAKE RESPONSE: {shallow_certainty:?}")? - } - ProbeStep::RecordImplArgs { impl_args } => { - writeln!(this.f, "RECORDED IMPL ARGS: {impl_args:?}")? - } - } - } - Ok(()) - }) - } - - pub(super) fn format_added_goals_evaluation( - &mut self, - added_goals_evaluation: &AddedGoalsEvaluation, - ) -> std::fmt::Result { - writeln!(self.f, "TRY_EVALUATE_ADDED_GOALS: {:?}", added_goals_evaluation.result)?; - - for (n, iterations) in added_goals_evaluation.evaluations.iter().enumerate() { - write!(self.f, "ITERATION {n}")?; - self.nested(|this| { - for goal_evaluation in iterations { - this.format_goal_evaluation(goal_evaluation)?; - } - Ok(()) - })?; - } - - Ok(()) - } -} From 1af490de424ac07fbeb3b1a0a1268cad43fdf49d Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 24 May 2024 15:47:50 -0400 Subject: [PATCH 10/15] Better ICE message for unresolved upvars --- .../rustc_mir_build/src/build/expr/as_place.rs | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_mir_build/src/build/expr/as_place.rs b/compiler/rustc_mir_build/src/build/expr/as_place.rs index 93d0d4e59ba99..4b62afa61bbd5 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_place.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_place.rs @@ -4,7 +4,6 @@ use crate::build::expr::category::Category; use crate::build::ForGuard::{OutsideGuard, RefWithinGuard}; use crate::build::{BlockAnd, BlockAndExtension, Builder, Capture, CaptureMap}; use rustc_hir::def_id::LocalDefId; -use rustc_middle::bug; use rustc_middle::hir::place::Projection as HirProjection; use rustc_middle::hir::place::ProjectionKind as HirProjectionKind; use rustc_middle::middle::region; @@ -13,6 +12,7 @@ use rustc_middle::mir::*; use rustc_middle::thir::*; use rustc_middle::ty::AdtDef; use rustc_middle::ty::{self, CanonicalUserTypeAnnotation, Ty, Variance}; +use rustc_middle::{bug, span_bug}; use rustc_span::Span; use rustc_target::abi::{FieldIdx, VariantIdx, FIRST_VARIANT}; use tracing::{debug, instrument, trace}; @@ -252,7 +252,18 @@ fn strip_prefix<'a, 'tcx>( impl<'tcx> PlaceBuilder<'tcx> { pub(in crate::build) fn to_place(&self, cx: &Builder<'_, 'tcx>) -> Place<'tcx> { - self.try_to_place(cx).unwrap() + self.try_to_place(cx).unwrap_or_else(|| match self.base { + PlaceBase::Local(local) => span_bug!( + cx.local_decls[local].source_info.span, + "could not resolve local: {local:#?} + {:?}", + self.projection + ), + PlaceBase::Upvar { var_hir_id, closure_def_id: _ } => span_bug!( + cx.tcx.hir().span(var_hir_id.0), + "could not resolve upvar: {var_hir_id:?} + {:?}", + self.projection + ), + }) } /// Creates a `Place` or returns `None` if an upvar cannot be resolved From 9185ddb019259883db1d5c2625f4ecb42d3aa77b Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Fri, 24 May 2024 15:20:20 -0400 Subject: [PATCH 11/15] bootstrap: support target specific config overrides --- src/bootstrap/src/core/config/config.rs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index 19119a073c5fa..7eb42ad32f539 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -644,7 +644,20 @@ impl Merge for TomlConfig { do_merge(&mut self.llvm, llvm, replace); do_merge(&mut self.rust, rust, replace); do_merge(&mut self.dist, dist, replace); - assert!(target.is_none(), "merging target-specific config is not currently supported"); + + match (self.target.as_mut(), target) { + (_, None) => {} + (None, Some(target)) => self.target = Some(target), + (Some(original_target), Some(new_target)) => { + for (triple, new) in new_target { + if let Some(original) = original_target.get_mut(&triple) { + original.merge(new, replace); + } else { + original_target.insert(triple, new); + } + } + } + } } } From d1f0bc7562043f2d34c77aadc5263cee89d0ee80 Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Fri, 24 May 2024 15:25:44 -0400 Subject: [PATCH 12/15] bootstrap: test target specific config overrides Debug, PartialEq, and Eq are derived for testing purposes. --- src/bootstrap/src/core/config/config.rs | 8 ++--- src/bootstrap/src/core/config/tests.rs | 41 +++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 4 deletions(-) diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index 7eb42ad32f539..d13dc9d1d177a 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -360,7 +360,7 @@ pub enum RustfmtState { LazyEvaluated, } -#[derive(Debug, Default, Clone, Copy, PartialEq)] +#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)] pub enum LlvmLibunwind { #[default] No, @@ -381,7 +381,7 @@ impl FromStr for LlvmLibunwind { } } -#[derive(Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub enum SplitDebuginfo { Packed, Unpacked, @@ -542,7 +542,7 @@ impl PartialEq<&str> for TargetSelection { } /// Per-target configuration stored in the global configuration structure. -#[derive(Default, Clone)] +#[derive(Debug, Default, Clone, PartialEq, Eq)] pub struct Target { /// Some(path to llvm-config) if using an external LLVM. pub llvm_config: Option, @@ -912,7 +912,7 @@ define_config! { } } -#[derive(Clone, Debug, Deserialize)] +#[derive(Clone, Debug, Deserialize, PartialEq, Eq)] #[serde(untagged)] pub enum StringOrBool { String(String), diff --git a/src/bootstrap/src/core/config/tests.rs b/src/bootstrap/src/core/config/tests.rs index 59e16b6542728..c4073910623a4 100644 --- a/src/bootstrap/src/core/config/tests.rs +++ b/src/bootstrap/src/core/config/tests.rs @@ -1,5 +1,7 @@ use super::{flags::Flags, ChangeIdWrapper, Config}; use crate::core::build_steps::clippy::get_clippy_rules_in_order; +use crate::core::config::Target; +use crate::core::config::TargetSelection; use crate::core::config::{LldMode, TomlConfig}; use clap::CommandFactory; @@ -124,6 +126,10 @@ fn override_toml() { "--set=build.gdb=\"bar\"".to_owned(), "--set=build.tools=[\"cargo\"]".to_owned(), "--set=llvm.build-config={\"foo\" = \"bar\"}".to_owned(), + "--set=target.x86_64-unknown-linux-gnu.runner=bar".to_owned(), + "--set=target.x86_64-unknown-linux-gnu.rpath=false".to_owned(), + "--set=target.aarch64-unknown-linux-gnu.sanitizers=false".to_owned(), + "--set=target.aarch64-apple-darwin.runner=apple".to_owned(), ], |&_| { toml::from_str( @@ -140,6 +146,17 @@ tools = [] [llvm] download-ci-llvm = false build-config = {} + +[target.aarch64-unknown-linux-gnu] +sanitizers = true +rpath = true +runner = "aarch64-runner" + +[target.x86_64-unknown-linux-gnu] +sanitizers = true +rpath = true +runner = "x86_64-runner" + "#, ) .unwrap() @@ -163,6 +180,30 @@ build-config = {} [("foo".to_string(), "bar".to_string())].into_iter().collect(), "setting dictionary value" ); + + let x86_64 = TargetSelection::from_user("x86_64-unknown-linux-gnu"); + let x86_64_values = Target { + sanitizers: Some(true), + rpath: Some(false), + runner: Some("bar".into()), + ..Default::default() + }; + let aarch64 = TargetSelection::from_user("aarch64-unknown-linux-gnu"); + let aarch64_values = Target { + sanitizers: Some(false), + rpath: Some(true), + runner: Some("aarch64-runner".into()), + ..Default::default() + }; + let darwin = TargetSelection::from_user("aarch64-apple-darwin"); + let darwin_values = Target { runner: Some("apple".into()), ..Default::default() }; + assert_eq!( + config.target_config, + [(x86_64, x86_64_values), (aarch64, aarch64_values), (darwin, darwin_values)] + .into_iter() + .collect(), + "setting dictionary value" + ); } #[test] From 61aac551b81573d160f19bafbf6deb83f8f0b2be Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 24 May 2024 15:49:17 -0400 Subject: [PATCH 13/15] Structurally resolve before builtin_index in EUV --- compiler/rustc_hir_typeck/src/expr_use_visitor.rs | 6 +++++- .../next-solver/typeck/index-of-projection.rs | 13 +++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 tests/ui/traits/next-solver/typeck/index-of-projection.rs diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs index 89f62577506fd..0ba4bd090f5e2 100644 --- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs +++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs @@ -1741,7 +1741,11 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx } PatKind::Slice(before, ref slice, after) => { - let Some(element_ty) = place_with_id.place.ty().builtin_index() else { + let Some(element_ty) = self + .cx + .try_structurally_resolve_type(pat.span, place_with_id.place.ty()) + .builtin_index() + else { debug!("explicit index of non-indexable type {:?}", place_with_id); return Err(self .cx diff --git a/tests/ui/traits/next-solver/typeck/index-of-projection.rs b/tests/ui/traits/next-solver/typeck/index-of-projection.rs new file mode 100644 index 0000000000000..5023be0bb1482 --- /dev/null +++ b/tests/ui/traits/next-solver/typeck/index-of-projection.rs @@ -0,0 +1,13 @@ +//@ compile-flags: -Znext-solver +//@ check-pass + +// Fixes a regression in `rustc_attr` where we weren't normalizing the +// output type of a index operator performing a `Ty::builtin_index` call, +// leading to an ICE. + +fn main() { + let mut vec = [1, 2, 3]; + let x = || { + let [..] = &vec[..]; + }; +} From f4b9ac68f306f630b5167959d5ee90626a9d7d84 Mon Sep 17 00:00:00 2001 From: Jacob Lifshay Date: Fri, 24 May 2024 16:17:19 -0700 Subject: [PATCH 14/15] Add manual Sync impl for ReentrantLockGuard Fixes: #125526 --- library/std/src/sync/reentrant_lock.rs | 3 +++ tests/ui/sync/reentrantlockguard-sync.rs | 15 +++++++++++++++ tests/ui/sync/reentrantlockguard-sync.stderr | 20 ++++++++++++++++++++ 3 files changed, 38 insertions(+) create mode 100644 tests/ui/sync/reentrantlockguard-sync.rs create mode 100644 tests/ui/sync/reentrantlockguard-sync.stderr diff --git a/library/std/src/sync/reentrant_lock.rs b/library/std/src/sync/reentrant_lock.rs index 80b9e0cf15214..f7fe8eb1c7fd5 100644 --- a/library/std/src/sync/reentrant_lock.rs +++ b/library/std/src/sync/reentrant_lock.rs @@ -116,6 +116,9 @@ pub struct ReentrantLockGuard<'a, T: ?Sized + 'a> { #[unstable(feature = "reentrant_lock", issue = "121440")] impl !Send for ReentrantLockGuard<'_, T> {} +#[unstable(feature = "reentrant_lock", issue = "121440")] +unsafe impl Sync for ReentrantLockGuard<'_, T> {} + #[unstable(feature = "reentrant_lock", issue = "121440")] impl ReentrantLock { /// Creates a new re-entrant lock in an unlocked state ready for use. diff --git a/tests/ui/sync/reentrantlockguard-sync.rs b/tests/ui/sync/reentrantlockguard-sync.rs new file mode 100644 index 0000000000000..84d5b1834a882 --- /dev/null +++ b/tests/ui/sync/reentrantlockguard-sync.rs @@ -0,0 +1,15 @@ +#![feature(reentrant_lock)] +use std::sync::ReentrantLock; +use std::cell::Cell; + +// ReentrantLockGuard> must not be Sync, that would be unsound. + +fn test_sync(_t: T) {} + +fn main() +{ + let m = ReentrantLock::new(Cell::new(0i32)); + let guard = m.lock(); + test_sync(guard); + //~^ ERROR `Cell` cannot be shared between threads safely [E0277] +} diff --git a/tests/ui/sync/reentrantlockguard-sync.stderr b/tests/ui/sync/reentrantlockguard-sync.stderr new file mode 100644 index 0000000000000..ed2e3e2f1124a --- /dev/null +++ b/tests/ui/sync/reentrantlockguard-sync.stderr @@ -0,0 +1,20 @@ +error[E0277]: `Cell` cannot be shared between threads safely + --> $DIR/reentrantlockguard-sync.rs:13:15 + | +LL | test_sync(guard); + | --------- ^^^^^ `Cell` cannot be shared between threads safely + | | + | required by a bound introduced by this call + | + = help: the trait `Sync` is not implemented for `Cell`, which is required by `ReentrantLockGuard<'_, Cell>: Sync` + = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` or `std::sync::atomic::AtomicI32` instead + = note: required for `ReentrantLockGuard<'_, Cell>` to implement `Sync` +note: required by a bound in `test_sync` + --> $DIR/reentrantlockguard-sync.rs:7:17 + | +LL | fn test_sync(_t: T) {} + | ^^^^ required by this bound in `test_sync` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. From 045f448e26257c7b19bf6d68c8e5e9d09ab4df79 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 24 May 2024 15:17:34 -0400 Subject: [PATCH 15/15] Don't eagerly monomorphize drop for types that are impossible to instantiate --- compiler/rustc_monomorphize/src/collector.rs | 9 +++++++++ tests/ui/codegen/mono-impossible-drop.rs | 18 ++++++++++++++++++ 2 files changed, 27 insertions(+) create mode 100644 tests/ui/codegen/mono-impossible-drop.rs diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 76972ff2263d8..9487692662bb7 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -1434,6 +1434,15 @@ impl<'v> RootCollector<'_, 'v> { { debug!("RootCollector: ADT drop-glue for `{id:?}`",); + // This type is impossible to instantiate, so we should not try to + // generate a `drop_in_place` instance for it. + if self.tcx.instantiate_and_check_impossible_predicates(( + id.owner_id.to_def_id(), + ty::List::empty(), + )) { + return; + } + let ty = self.tcx.type_of(id.owner_id.to_def_id()).no_bound_vars().unwrap(); visit_drop_use(self.tcx, ty, true, DUMMY_SP, self.output); } diff --git a/tests/ui/codegen/mono-impossible-drop.rs b/tests/ui/codegen/mono-impossible-drop.rs new file mode 100644 index 0000000000000..dec013cfe54b3 --- /dev/null +++ b/tests/ui/codegen/mono-impossible-drop.rs @@ -0,0 +1,18 @@ +//@ compile-flags: -Clink-dead-code=on --crate-type=lib +//@ build-pass + +#![feature(trivial_bounds)] +#![allow(trivial_bounds)] + +// Make sure we don't monomorphize the drop impl for `Baz`, since it has predicates +// that don't hold under a reveal-all param env. + +trait Foo { + type Assoc; +} + +struct Bar; + +struct Baz(::Assoc) +where + Bar: Foo;