From 06fb36c92ea0d92d93361badde0cae5aab763d43 Mon Sep 17 00:00:00 2001 From: "Kurt Heiritz (pseudo)" Date: Fri, 27 Jun 2025 16:26:53 +0530 Subject: [PATCH 01/20] Update poison.rs to fix the typo (sys->sync) --- library/std/src/sync/poison.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/sync/poison.rs b/library/std/src/sync/poison.rs index cc1d0b30152a1..571f0d14248e1 100644 --- a/library/std/src/sync/poison.rs +++ b/library/std/src/sync/poison.rs @@ -13,7 +13,7 @@ //! depend on the primitive. See [#Overview] bellow. //! //! For the alternative implementations that do not employ poisoning, -//! see `std::sys::nonpoisoning`. +//! see `std::sync::nonpoisoning`. //! //! # Overview //! From 6ca9b43ea9f50d5e77dc0f8d4d62283017b3f1b0 Mon Sep 17 00:00:00 2001 From: Kivooeo Date: Sun, 29 Jun 2025 21:04:41 +0500 Subject: [PATCH 02/20] moved test files --- .../nested-cfg-attr-conditional-compilation.rs} | 0 .../nested-cfg-attr-conditional-compilation.stderr} | 0 tests/ui/{myriad-closures.rs => closures/many-closures.rs} | 0 .../mutable-function-parameters.rs} | 0 .../generic-params-nested-fn-scope-error.rs} | 0 .../generic-params-nested-fn-scope-error.stderr} | 0 .../{nested-block-comment.rs => parser/nested-block-comments.rs} | 0 tests/ui/{nested-class.rs => resolve/resolve-same-name-struct.rs} | 0 .../mutually-recursive-types.rs} | 0 9 files changed, 0 insertions(+), 0 deletions(-) rename tests/ui/{nested-cfg-attrs.rs => cfg/nested-cfg-attr-conditional-compilation.rs} (100%) rename tests/ui/{nested-cfg-attrs.stderr => cfg/nested-cfg-attr-conditional-compilation.stderr} (100%) rename tests/ui/{myriad-closures.rs => closures/many-closures.rs} (100%) rename tests/ui/{mut-function-arguments.rs => fn/mutable-function-parameters.rs} (100%) rename tests/ui/{nested-ty-params.rs => generics/generic-params-nested-fn-scope-error.rs} (100%) rename tests/ui/{nested-ty-params.stderr => generics/generic-params-nested-fn-scope-error.stderr} (100%) rename tests/ui/{nested-block-comment.rs => parser/nested-block-comments.rs} (100%) rename tests/ui/{nested-class.rs => resolve/resolve-same-name-struct.rs} (100%) rename tests/ui/{mutual-recursion-group.rs => type/mutually-recursive-types.rs} (100%) diff --git a/tests/ui/nested-cfg-attrs.rs b/tests/ui/cfg/nested-cfg-attr-conditional-compilation.rs similarity index 100% rename from tests/ui/nested-cfg-attrs.rs rename to tests/ui/cfg/nested-cfg-attr-conditional-compilation.rs diff --git a/tests/ui/nested-cfg-attrs.stderr b/tests/ui/cfg/nested-cfg-attr-conditional-compilation.stderr similarity index 100% rename from tests/ui/nested-cfg-attrs.stderr rename to tests/ui/cfg/nested-cfg-attr-conditional-compilation.stderr diff --git a/tests/ui/myriad-closures.rs b/tests/ui/closures/many-closures.rs similarity index 100% rename from tests/ui/myriad-closures.rs rename to tests/ui/closures/many-closures.rs diff --git a/tests/ui/mut-function-arguments.rs b/tests/ui/fn/mutable-function-parameters.rs similarity index 100% rename from tests/ui/mut-function-arguments.rs rename to tests/ui/fn/mutable-function-parameters.rs diff --git a/tests/ui/nested-ty-params.rs b/tests/ui/generics/generic-params-nested-fn-scope-error.rs similarity index 100% rename from tests/ui/nested-ty-params.rs rename to tests/ui/generics/generic-params-nested-fn-scope-error.rs diff --git a/tests/ui/nested-ty-params.stderr b/tests/ui/generics/generic-params-nested-fn-scope-error.stderr similarity index 100% rename from tests/ui/nested-ty-params.stderr rename to tests/ui/generics/generic-params-nested-fn-scope-error.stderr diff --git a/tests/ui/nested-block-comment.rs b/tests/ui/parser/nested-block-comments.rs similarity index 100% rename from tests/ui/nested-block-comment.rs rename to tests/ui/parser/nested-block-comments.rs diff --git a/tests/ui/nested-class.rs b/tests/ui/resolve/resolve-same-name-struct.rs similarity index 100% rename from tests/ui/nested-class.rs rename to tests/ui/resolve/resolve-same-name-struct.rs diff --git a/tests/ui/mutual-recursion-group.rs b/tests/ui/type/mutually-recursive-types.rs similarity index 100% rename from tests/ui/mutual-recursion-group.rs rename to tests/ui/type/mutually-recursive-types.rs From f12120d2bd237ffbf03c8de027513a8d0bc63616 Mon Sep 17 00:00:00 2001 From: Kivooeo Date: Sun, 29 Jun 2025 21:05:19 +0500 Subject: [PATCH 03/20] cleaned up some tests --- ...nested-cfg-attr-conditional-compilation.rs | 16 ++++++- ...ed-cfg-attr-conditional-compilation.stderr | 6 +-- tests/ui/closures/many-closures.rs | 38 +++++++++------ tests/ui/fn/mutable-function-parameters.rs | 9 +++- .../generic-params-nested-fn-scope-error.rs | 15 ++++-- ...eneric-params-nested-fn-scope-error.stderr | 16 +++---- tests/ui/parser/nested-block-comments.rs | 27 ++++++++++- tests/ui/resolve/resolve-same-name-struct.rs | 40 ++++++++-------- tests/ui/type/mutually-recursive-types.rs | 46 ++++++++++++++++--- 9 files changed, 152 insertions(+), 61 deletions(-) diff --git a/tests/ui/cfg/nested-cfg-attr-conditional-compilation.rs b/tests/ui/cfg/nested-cfg-attr-conditional-compilation.rs index 941807a84310e..7618e83a64290 100644 --- a/tests/ui/cfg/nested-cfg-attr-conditional-compilation.rs +++ b/tests/ui/cfg/nested-cfg-attr-conditional-compilation.rs @@ -1,4 +1,18 @@ +//! Test that nested `cfg_attr` attributes work correctly for conditional compilation. +//! This checks that `cfg_attr` can be arbitrarily deeply nested and that the +//! expansion works from outside to inside, eventually applying the innermost +//! conditional compilation directive. +//! +//! In this test, `cfg_attr(all(), cfg_attr(all(), cfg(false)))` should expand to: +//! 1. `cfg_attr(all(), cfg(false))` (outer cfg_attr applied) +//! 2. `cfg(false)` (inner cfg_attr applied) +//! 3. Function `f` is excluded from compilation +//! +//! Added in . + #[cfg_attr(all(), cfg_attr(all(), cfg(false)))] fn f() {} -fn main() { f() } //~ ERROR cannot find function `f` in this scope +fn main() { + f() //~ ERROR cannot find function `f` in this scope +} diff --git a/tests/ui/cfg/nested-cfg-attr-conditional-compilation.stderr b/tests/ui/cfg/nested-cfg-attr-conditional-compilation.stderr index 16c2930714353..ddb8ea1e13ae5 100644 --- a/tests/ui/cfg/nested-cfg-attr-conditional-compilation.stderr +++ b/tests/ui/cfg/nested-cfg-attr-conditional-compilation.stderr @@ -1,8 +1,8 @@ error[E0425]: cannot find function `f` in this scope - --> $DIR/nested-cfg-attrs.rs:4:13 + --> $DIR/nested-cfg-attr-conditional-compilation.rs:17:5 | -LL | fn main() { f() } - | ^ not found in this scope +LL | f() + | ^ not found in this scope error: aborting due to 1 previous error diff --git a/tests/ui/closures/many-closures.rs b/tests/ui/closures/many-closures.rs index 541d27d5de407..c96ef5544c22e 100644 --- a/tests/ui/closures/many-closures.rs +++ b/tests/ui/closures/many-closures.rs @@ -1,13 +1,17 @@ +//! Test that the compiler can handle code bases with a high number of closures. +//! This is particularly important for the MinGW toolchain which has a limit of +//! 2^15 weak symbols per binary. This test creates 2^12 closures (256 functions +//! with 16 closures each) to check the compiler handles this correctly. +//! +//! Regression test for . +//! See also . + //@ run-pass -// This test case tests whether we can handle code bases that contain a high -// number of closures, something that needs special handling in the MingGW -// toolchain. -// See https://github.com/rust-lang/rust/issues/34793 for more information. // Make sure we don't optimize anything away: //@ compile-flags: -C no-prepopulate-passes -Cpasses=name-anon-globals -// Expand something exponentially +/// Macro for exponential expansion - creates 2^n copies of the given macro call macro_rules! go_bacterial { ($mac:ident) => ($mac!()); ($mac:ident 1 $($t:tt)*) => ( @@ -16,24 +20,28 @@ macro_rules! go_bacterial { ) } -macro_rules! mk_closure { - () => ((move || {})()) +/// Creates and immediately calls a closure +macro_rules! create_closure { + () => { + (move || {})() + }; } -macro_rules! mk_fn { +/// Creates a function containing 16 closures (2^4) +macro_rules! create_function_with_closures { () => { { - fn function() { - // Make 16 closures - go_bacterial!(mk_closure 1 1 1 1); + fn function_with_closures() { + // Create 16 closures using exponential expansion: 2^4 = 16 + go_bacterial!(create_closure 1 1 1 1); } - let _ = function(); + let _ = function_with_closures(); } } } fn main() { - // Make 2^8 functions, each containing 16 closures, - // resulting in 2^12 closures overall. - go_bacterial!(mk_fn 1 1 1 1 1 1 1 1); + // Create 2^8 = 256 functions, each containing 16 closures, + // resulting in 2^12 = 4096 closures total. + go_bacterial!(create_function_with_closures 1 1 1 1 1 1 1 1); } diff --git a/tests/ui/fn/mutable-function-parameters.rs b/tests/ui/fn/mutable-function-parameters.rs index 01c264fce0389..5045a783f0492 100644 --- a/tests/ui/fn/mutable-function-parameters.rs +++ b/tests/ui/fn/mutable-function-parameters.rs @@ -1,3 +1,6 @@ +//! Test that function and closure parameters marked as `mut` can be mutated +//! within the function body. + //@ run-pass fn f(mut y: Box) { @@ -6,10 +9,12 @@ fn f(mut y: Box) { } fn g() { - let frob = |mut q: Box| { *q = 2; assert_eq!(*q, 2); }; + let frob = |mut q: Box| { + *q = 2; + assert_eq!(*q, 2); + }; let w = Box::new(37); frob(w); - } pub fn main() { diff --git a/tests/ui/generics/generic-params-nested-fn-scope-error.rs b/tests/ui/generics/generic-params-nested-fn-scope-error.rs index c00c3bc337230..eaf514da33763 100644 --- a/tests/ui/generics/generic-params-nested-fn-scope-error.rs +++ b/tests/ui/generics/generic-params-nested-fn-scope-error.rs @@ -1,9 +1,14 @@ -fn hd(v: Vec ) -> U { - fn hd1(w: [U]) -> U { return w[0]; } - //~^ ERROR can't use generic parameters from outer item - //~| ERROR can't use generic parameters from outer item +//! Test that generic parameters from an outer function are not accessible +//! in nested functions. - return hd1(v); +fn foo(v: Vec) -> U { + fn bar(w: [U]) -> U { + //~^ ERROR can't use generic parameters from outer item + //~| ERROR can't use generic parameters from outer item + return w[0]; + } + + return bar(v); } fn main() {} diff --git a/tests/ui/generics/generic-params-nested-fn-scope-error.stderr b/tests/ui/generics/generic-params-nested-fn-scope-error.stderr index 7ca65b421b25f..7fd1069c651fa 100644 --- a/tests/ui/generics/generic-params-nested-fn-scope-error.stderr +++ b/tests/ui/generics/generic-params-nested-fn-scope-error.stderr @@ -1,19 +1,19 @@ error[E0401]: can't use generic parameters from outer item - --> $DIR/nested-ty-params.rs:2:16 + --> $DIR/generic-params-nested-fn-scope-error.rs:5:16 | -LL | fn hd(v: Vec ) -> U { - | - type parameter from outer item -LL | fn hd1(w: [U]) -> U { return w[0]; } +LL | fn foo(v: Vec) -> U { + | - type parameter from outer item +LL | fn bar(w: [U]) -> U { | - ^ use of generic parameter from outer item | | | help: try introducing a local generic parameter here: `` error[E0401]: can't use generic parameters from outer item - --> $DIR/nested-ty-params.rs:2:23 + --> $DIR/generic-params-nested-fn-scope-error.rs:5:23 | -LL | fn hd(v: Vec ) -> U { - | - type parameter from outer item -LL | fn hd1(w: [U]) -> U { return w[0]; } +LL | fn foo(v: Vec) -> U { + | - type parameter from outer item +LL | fn bar(w: [U]) -> U { | - ^ use of generic parameter from outer item | | | help: try introducing a local generic parameter here: `` diff --git a/tests/ui/parser/nested-block-comments.rs b/tests/ui/parser/nested-block-comments.rs index 008df27e0e2a2..8fe778963619c 100644 --- a/tests/ui/parser/nested-block-comments.rs +++ b/tests/ui/parser/nested-block-comments.rs @@ -1,11 +1,34 @@ +//! Test that nested block comments are properly supported by the parser. +//! +//! See . + //@ run-pass /* This test checks that nested comments are supported - /* - This should not panic + /* This is a nested comment + /* And this is even more deeply nested */ + Back to the first level of nesting */ + + /* Another nested comment at the same level */ +*/ + +/* Additional test cases for nested comments */ + +#[rustfmt::skip] +/* + /* Level 1 + /* Level 2 + /* Level 3 */ + */ + */ */ pub fn main() { + // Check that code after nested comments works correctly + let _x = 42; + + /* Even inline /* nested */ comments work */ + let _y = /* nested /* comment */ test */ 100; } diff --git a/tests/ui/resolve/resolve-same-name-struct.rs b/tests/ui/resolve/resolve-same-name-struct.rs index f84ab40dd1d41..1bea0938e3da0 100644 --- a/tests/ui/resolve/resolve-same-name-struct.rs +++ b/tests/ui/resolve/resolve-same-name-struct.rs @@ -1,25 +1,29 @@ -//@ run-pass - -#![allow(non_camel_case_types)] +//! Test that name resolution works correctly when a struct and its constructor +//! function have the same name within a nested scope. This checks that the +//! compiler can distinguish between type names and value names in the same +//! namespace. -pub fn main() { - struct b { - i: isize, - } +//@ run-pass - impl b { - fn do_stuff(&self) -> isize { return 37; } - } +struct Point { + i: isize, +} - fn b(i:isize) -> b { - b { - i: i - } +impl Point { + fn get_value(&self) -> isize { + return 37; } +} - // fn b(x:isize) -> isize { panic!(); } +// Constructor function with the same name as the struct +#[allow(non_snake_case)] +fn Point(i: isize) -> Point { + Point { i } +} - let z = b(42); - assert_eq!(z.i, 42); - assert_eq!(z.do_stuff(), 37); +pub fn main() { + // Test that we can use the constructor function + let point = Point(42); + assert_eq!(point.i, 42); + assert_eq!(point.get_value(), 37); } diff --git a/tests/ui/type/mutually-recursive-types.rs b/tests/ui/type/mutually-recursive-types.rs index f83150af7dc85..5472e1582218e 100644 --- a/tests/ui/type/mutually-recursive-types.rs +++ b/tests/ui/type/mutually-recursive-types.rs @@ -1,15 +1,47 @@ +//! Test that mutually recursive type definitions are properly handled by the compiler. +//! This checks that types can reference each other in their definitions through +//! `Box` indirection, creating cycles in the type dependency graph. + //@ run-pass -#![allow(non_camel_case_types)] -#![allow(dead_code)] +#[derive(Debug, PartialEq)] +enum Colour { + Red, + Green, + Blue, +} + +#[derive(Debug, PartialEq)] +enum Tree { + Children(Box), + Leaf(Colour), +} + +#[derive(Debug, PartialEq)] +enum List { + Cons(Box, Box), + Nil, +} + +#[derive(Debug, PartialEq)] +enum SmallList { + Kons(isize, Box), + Neel, +} + +pub fn main() { + // Construct and test all variants of Colour + let _ = Tree::Leaf(Colour::Red); + let _ = Tree::Leaf(Colour::Green); -enum colour { red, green, blue, } + let _ = Tree::Leaf(Colour::Blue); -enum tree { children(Box), leaf(colour), } + let _ = List::Nil; -enum list { cons(Box, Box), nil, } + let _ = Tree::Children(Box::new(List::Nil)); -enum small_list { kons(isize, Box), neel, } + let _ = List::Cons(Box::new(Tree::Leaf(Colour::Blue)), Box::new(List::Nil)); -pub fn main() { } + let _ = SmallList::Kons(42, Box::new(SmallList::Neel)); +} From 3b57db4d87ea589ec05e2c7543fb6ad2df41795f Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Tue, 1 Jul 2025 06:59:49 +0000 Subject: [PATCH 04/20] Give some UI tests more apropriate names Prepare for rework done by the rest of RUST-142440. Co-authored-by: Kivooeo --- src/tools/tidy/src/issues.txt | 4 ---- .../impl-future-escaping-bound-vars-ice.rs} | 0 .../impl-future-escaping-bound-vars-ice.stderr} | 0 .../closure-capture-after-clone.rs} | 0 .../closure-last-use-move.rs} | 0 .../closure-upvar-last-use-analysis.rs} | 0 .../auxiliary/cross-crate-refcell-match.rs} | 0 tests/ui/{ => cross-crate}/auxiliary/kinds_in_metadata.rs | 0 .../cross-crate-refcell-match.rs} | 0 .../metadata-trait-serialization.rs} | 0 .../higher-ranked-encoding.rs} | 0 .../{item-name-overload.rs => modules/mod-same-item-names.rs} | 0 .../inherent-impl-primitive-types-error.rs} | 0 .../inherent-impl-primitive-types-error.stderr} | 0 14 files changed, 4 deletions(-) rename tests/ui/{issues-71798.rs => async-await/impl-future-escaping-bound-vars-ice.rs} (100%) rename tests/ui/{issues-71798.stderr => async-await/impl-future-escaping-bound-vars-ice.stderr} (100%) rename tests/ui/{last-use-is-capture.rs => closures/closure-capture-after-clone.rs} (100%) rename tests/ui/{last-use-in-block.rs => closures/closure-last-use-move.rs} (100%) rename tests/ui/{last-use-in-cap-clause.rs => closures/closure-upvar-last-use-analysis.rs} (100%) rename tests/ui/{auxiliary/issue-16822.rs => cross-crate/auxiliary/cross-crate-refcell-match.rs} (100%) rename tests/ui/{ => cross-crate}/auxiliary/kinds_in_metadata.rs (100%) rename tests/ui/{issue-16822.rs => cross-crate/cross-crate-refcell-match.rs} (100%) rename tests/ui/{kinds-in-metadata.rs => cross-crate/metadata-trait-serialization.rs} (100%) rename tests/ui/{issue-15924.rs => higher-ranked/higher-ranked-encoding.rs} (100%) rename tests/ui/{item-name-overload.rs => modules/mod-same-item-names.rs} (100%) rename tests/ui/{kinds-of-primitive-impl.rs => type/inherent-impl-primitive-types-error.rs} (100%) rename tests/ui/{kinds-of-primitive-impl.stderr => type/inherent-impl-primitive-types-error.stderr} (100%) diff --git a/src/tools/tidy/src/issues.txt b/src/tools/tidy/src/issues.txt index 18da874dbef2e..0966c3d79356d 100644 --- a/src/tools/tidy/src/issues.txt +++ b/src/tools/tidy/src/issues.txt @@ -276,7 +276,6 @@ ui/auto-traits/issue-23080-2.rs ui/auto-traits/issue-23080.rs ui/auto-traits/issue-83857-ub.rs ui/auto-traits/issue-84075.rs -ui/auxiliary/issue-16822.rs ui/bench/issue-32062.rs ui/binding/issue-40402-1.rs ui/binding/issue-40402-2.rs @@ -1368,9 +1367,6 @@ ui/infinite/issue-41731-infinite-macro-println.rs ui/intrinsics/issue-28575.rs ui/intrinsics/issue-84297-reifying-copy.rs ui/invalid/issue-114435-layout-type-err.rs -ui/issue-15924.rs -ui/issue-16822.rs -ui/issues-71798.rs ui/issues/auxiliary/issue-11224.rs ui/issues/auxiliary/issue-11508.rs ui/issues/auxiliary/issue-11529.rs diff --git a/tests/ui/issues-71798.rs b/tests/ui/async-await/impl-future-escaping-bound-vars-ice.rs similarity index 100% rename from tests/ui/issues-71798.rs rename to tests/ui/async-await/impl-future-escaping-bound-vars-ice.rs diff --git a/tests/ui/issues-71798.stderr b/tests/ui/async-await/impl-future-escaping-bound-vars-ice.stderr similarity index 100% rename from tests/ui/issues-71798.stderr rename to tests/ui/async-await/impl-future-escaping-bound-vars-ice.stderr diff --git a/tests/ui/last-use-is-capture.rs b/tests/ui/closures/closure-capture-after-clone.rs similarity index 100% rename from tests/ui/last-use-is-capture.rs rename to tests/ui/closures/closure-capture-after-clone.rs diff --git a/tests/ui/last-use-in-block.rs b/tests/ui/closures/closure-last-use-move.rs similarity index 100% rename from tests/ui/last-use-in-block.rs rename to tests/ui/closures/closure-last-use-move.rs diff --git a/tests/ui/last-use-in-cap-clause.rs b/tests/ui/closures/closure-upvar-last-use-analysis.rs similarity index 100% rename from tests/ui/last-use-in-cap-clause.rs rename to tests/ui/closures/closure-upvar-last-use-analysis.rs diff --git a/tests/ui/auxiliary/issue-16822.rs b/tests/ui/cross-crate/auxiliary/cross-crate-refcell-match.rs similarity index 100% rename from tests/ui/auxiliary/issue-16822.rs rename to tests/ui/cross-crate/auxiliary/cross-crate-refcell-match.rs diff --git a/tests/ui/auxiliary/kinds_in_metadata.rs b/tests/ui/cross-crate/auxiliary/kinds_in_metadata.rs similarity index 100% rename from tests/ui/auxiliary/kinds_in_metadata.rs rename to tests/ui/cross-crate/auxiliary/kinds_in_metadata.rs diff --git a/tests/ui/issue-16822.rs b/tests/ui/cross-crate/cross-crate-refcell-match.rs similarity index 100% rename from tests/ui/issue-16822.rs rename to tests/ui/cross-crate/cross-crate-refcell-match.rs diff --git a/tests/ui/kinds-in-metadata.rs b/tests/ui/cross-crate/metadata-trait-serialization.rs similarity index 100% rename from tests/ui/kinds-in-metadata.rs rename to tests/ui/cross-crate/metadata-trait-serialization.rs diff --git a/tests/ui/issue-15924.rs b/tests/ui/higher-ranked/higher-ranked-encoding.rs similarity index 100% rename from tests/ui/issue-15924.rs rename to tests/ui/higher-ranked/higher-ranked-encoding.rs diff --git a/tests/ui/item-name-overload.rs b/tests/ui/modules/mod-same-item-names.rs similarity index 100% rename from tests/ui/item-name-overload.rs rename to tests/ui/modules/mod-same-item-names.rs diff --git a/tests/ui/kinds-of-primitive-impl.rs b/tests/ui/type/inherent-impl-primitive-types-error.rs similarity index 100% rename from tests/ui/kinds-of-primitive-impl.rs rename to tests/ui/type/inherent-impl-primitive-types-error.rs diff --git a/tests/ui/kinds-of-primitive-impl.stderr b/tests/ui/type/inherent-impl-primitive-types-error.stderr similarity index 100% rename from tests/ui/kinds-of-primitive-impl.stderr rename to tests/ui/type/inherent-impl-primitive-types-error.stderr From 1daba456361d0bbac3d0bd9e0f11b7784d20ebe5 Mon Sep 17 00:00:00 2001 From: Kivooeo Date: Fri, 13 Jun 2025 02:30:47 +0500 Subject: [PATCH 05/20] cleaned up some tests --- .../impl-future-escaping-bound-vars-ice.rs | 4 ++ ...impl-future-escaping-bound-vars-ice.stderr | 4 +- .../closures/closure-capture-after-clone.rs | 40 ++++++++++++++---- tests/ui/closures/closure-last-use-move.rs | 42 ++++++++++++------- .../closure-upvar-last-use-analysis.rs | 27 +++++++++--- .../cross-crate/cross-crate-refcell-match.rs | 22 ++++++++-- .../metadata-trait-serialization.rs | 5 +-- .../higher-ranked/higher-ranked-encoding.rs | 15 ++++--- tests/ui/modules/mod-same-item-names.rs | 11 +++-- .../inherent-impl-primitive-types-error.rs | 10 +++-- ...inherent-impl-primitive-types-error.stderr | 10 ++--- 11 files changed, 130 insertions(+), 60 deletions(-) diff --git a/tests/ui/async-await/impl-future-escaping-bound-vars-ice.rs b/tests/ui/async-await/impl-future-escaping-bound-vars-ice.rs index 14b6c0f35812f..ea30e8c839f77 100644 --- a/tests/ui/async-await/impl-future-escaping-bound-vars-ice.rs +++ b/tests/ui/async-await/impl-future-escaping-bound-vars-ice.rs @@ -1,3 +1,7 @@ +//! Regression test for issue https://github.com/rust-lang/rust/issues/71798 +// ICE with escaping bound variables when impl Future + '_ +// returns non-Future type combined with syntax errors + fn test_ref(x: &u32) -> impl std::future::Future + '_ { //~^ ERROR `u32` is not a future *x diff --git a/tests/ui/async-await/impl-future-escaping-bound-vars-ice.stderr b/tests/ui/async-await/impl-future-escaping-bound-vars-ice.stderr index 52dd14ccb0a14..5beca58e13c77 100644 --- a/tests/ui/async-await/impl-future-escaping-bound-vars-ice.stderr +++ b/tests/ui/async-await/impl-future-escaping-bound-vars-ice.stderr @@ -1,11 +1,11 @@ error[E0425]: cannot find value `u` in this scope - --> $DIR/issues-71798.rs:7:24 + --> $DIR/impl-future-escaping-bound-vars-ice.rs:11:24 | LL | let _ = test_ref & u; | ^ not found in this scope error[E0277]: `u32` is not a future - --> $DIR/issues-71798.rs:1:25 + --> $DIR/impl-future-escaping-bound-vars-ice.rs:5:25 | LL | fn test_ref(x: &u32) -> impl std::future::Future + '_ { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `u32` is not a future diff --git a/tests/ui/closures/closure-capture-after-clone.rs b/tests/ui/closures/closure-capture-after-clone.rs index 6e07895f1d301..29fba147909b4 100644 --- a/tests/ui/closures/closure-capture-after-clone.rs +++ b/tests/ui/closures/closure-capture-after-clone.rs @@ -1,13 +1,39 @@ -//@ run-pass +//! Regression test for issue #1399 +//! +//! This tests that when a variable is used (via clone) and then later +//! captured by a closure, the last-use analysis doesn't incorrectly optimize +//! the earlier use as a "last use" and perform an invalid move. +//! +//! The sequence being tested: +//! 1. Create variable `k` +//! 2. Use `k.clone()` for some purpose +//! 3. Later capture `k` in a closure +//! +//! The analysis must not treat step 2 as the "last use" since step 3 needs `k`. +//! +//! See: https://github.com/rust-lang/rust/issues/1399 -#![allow(dead_code)] -// Make sure #1399 stays fixed +//@ run-pass -struct A { a: Box } +struct A { + _a: Box, +} pub fn main() { - fn invoke(f: F) where F: FnOnce() { f(); } + fn invoke(f: F) + where + F: FnOnce(), + { + f(); + } + let k: Box<_> = 22.into(); - let _u = A {a: k.clone()}; - invoke(|| println!("{}", k.clone()) ) + + // This clone should NOT be treated as "last use" of k + // even though k is not used again until the closure + let _u = A { _a: k.clone() }; + + // Here k is actually captured by the closure + // The last-use analyzer must have accounted for this when processing the clone above + invoke(|| println!("{}", k.clone())); } diff --git a/tests/ui/closures/closure-last-use-move.rs b/tests/ui/closures/closure-last-use-move.rs index 4a166b97bda4b..f5b99d87f0918 100644 --- a/tests/ui/closures/closure-last-use-move.rs +++ b/tests/ui/closures/closure-last-use-move.rs @@ -1,21 +1,33 @@ -//@ run-pass - -#![allow(dead_code)] -#![allow(unused_parens)] -// Issue #1818 +//! Regression test for issue #1818 +//! last-use analysis in closures should allow moves instead of requiring copies. +//! +//! The original issue was that the compiler incorrectly flagged certain return values +//! in anonymous functions/closures as requiring copies of non-copyable values, when +//! they should have been treated as moves (since they were the last use of the value). +//! +//! See: https://github.com/rust-lang/rust/issues/1818 +//@ run-pass -fn lp(s: String, mut f: F) -> T where F: FnMut(String) -> T { - while false { - let r = f(s); - return (r); +fn apply(s: String, mut f: F) -> T +where + F: FnMut(String) -> T +{ + fn g(s: String, mut f: F) -> T + where + F: FnMut(String) -> T + { + f(s) } - panic!(); -} -fn apply(s: String, mut f: F) -> T where F: FnMut(String) -> T { - fn g(s: String, mut f: F) -> T where F: FnMut(String) -> T {f(s)} - g(s, |v| { let r = f(v); r }) + g(s, |v| { + let r = f(v); + r // This should be a move, not requiring copy + }) } -pub fn main() {} +pub fn main() { + // Actually test the functionality + let result = apply(String::from("test"), |s| s.len()); + assert_eq!(result, 4); +} diff --git a/tests/ui/closures/closure-upvar-last-use-analysis.rs b/tests/ui/closures/closure-upvar-last-use-analysis.rs index 23c263c98058f..2c3e349437dc1 100644 --- a/tests/ui/closures/closure-upvar-last-use-analysis.rs +++ b/tests/ui/closures/closure-upvar-last-use-analysis.rs @@ -1,14 +1,29 @@ -//@ run-pass +//! Regression test for issue #1399 +//! +//! This tests that the compiler's last-use analysis correctly handles variables +//! that are captured by closures (upvars). The original issue was that the analysis +//! would incorrectly optimize variable usage as "last use" and perform moves, even when +//! the variable was later needed by a closure that captured it. +//! +//! See: https://github.com/rust-lang/rust/issues/1399 -#![allow(dead_code)] -// Make sure #1399 stays fixed +//@ run-pass -struct A { a: Box } +struct A { + _a: Box, +} fn foo() -> Box isize + 'static> { let k: Box<_> = Box::new(22); - let _u = A {a: k.clone()}; - let result = || 22; + + // This use of k.clone() should not be treated as a "last use" + // even though the closure below doesn't actually capture k + let _u = A { _a: k.clone() }; + + // The closure doesn't actually use k, but the analyzer needs to handle + // the potential capture scenario correctly + let result = || 22; + Box::new(result) } diff --git a/tests/ui/cross-crate/cross-crate-refcell-match.rs b/tests/ui/cross-crate/cross-crate-refcell-match.rs index 94d89f88f4705..7e46425612f33 100644 --- a/tests/ui/cross-crate/cross-crate-refcell-match.rs +++ b/tests/ui/cross-crate/cross-crate-refcell-match.rs @@ -1,12 +1,24 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/16822 +// +//! ICE when using RefCell::borrow_mut() +//! inside match statement with cross-crate generics. +//! +//! The bug occurred when: +//! - A library defines a generic struct with RefCell and uses borrow_mut() in match +//! - Main crate implements the library trait for its own type +//! - Cross-crate generic constraint causes type inference issues +//! +//! The problematic match statement is in the auxiliary file, this file triggers it. + //@ run-pass -//@ aux-build:issue-16822.rs +//@ aux-build:cross-crate-refcell-match.rs -extern crate issue_16822 as lib; +extern crate cross_crate_refcell_match as lib; use std::cell::RefCell; struct App { - i: isize + i: isize, } impl lib::Update for App { @@ -15,8 +27,10 @@ impl lib::Update for App { } } -fn main(){ +fn main() { let app = App { i: 5 }; let window = lib::Window { data: RefCell::new(app) }; + // This specific pattern (RefCell::borrow_mut in match with cross-crate generics) + // caused the ICE in the original issue window.update(1); } diff --git a/tests/ui/cross-crate/metadata-trait-serialization.rs b/tests/ui/cross-crate/metadata-trait-serialization.rs index 58dffba861d57..a6645018da4ae 100644 --- a/tests/ui/cross-crate/metadata-trait-serialization.rs +++ b/tests/ui/cross-crate/metadata-trait-serialization.rs @@ -1,12 +1,11 @@ +//! Test that trait information (like Copy) is correctly serialized in crate metadata + //@ run-pass //@ aux-build:kinds_in_metadata.rs - /* Any copyright is dedicated to the Public Domain. * http://creativecommons.org/publicdomain/zero/1.0/ */ -// Tests that metadata serialization works for the `Copy` kind. - extern crate kinds_in_metadata; use kinds_in_metadata::f; diff --git a/tests/ui/higher-ranked/higher-ranked-encoding.rs b/tests/ui/higher-ranked/higher-ranked-encoding.rs index eb2aef9cee12b..463e0f50e5379 100644 --- a/tests/ui/higher-ranked/higher-ranked-encoding.rs +++ b/tests/ui/higher-ranked/higher-ranked-encoding.rs @@ -1,9 +1,7 @@ -//@ run-pass +//! Regression test for https://github.com/rust-lang/rust/issues/15924 -#![allow(unused_imports)] -#![allow(unused_must_use)] +//@ run-pass -use std::fmt; use std::marker::PhantomData; trait Encoder { @@ -26,9 +24,8 @@ impl Encoder for JsonEncoder<'_> { type Error = (); } -fn encode_json Encodable>>( - object: &T, -) -> Result { +// This function uses higher-ranked trait bounds, which previously caused ICE +fn encode_json Encodable>>(object: &T) -> Result { let s = String::new(); { let mut encoder = JsonEncoder(PhantomData); @@ -37,13 +34,15 @@ fn encode_json Encodable>>( Ok(s) } +// Structure with HRTB constraint that was problematic struct Foo Encodable>> { v: T, } +// Drop implementation that exercises the HRTB bounds impl Encodable>> Drop for Foo { fn drop(&mut self) { - encode_json(&self.v); + let _ = encode_json(&self.v); } } diff --git a/tests/ui/modules/mod-same-item-names.rs b/tests/ui/modules/mod-same-item-names.rs index dd2925aa53fe4..1e9a9caa5fc5d 100644 --- a/tests/ui/modules/mod-same-item-names.rs +++ b/tests/ui/modules/mod-same-item-names.rs @@ -1,16 +1,15 @@ +//! Test that items with identical names can coexist in different modules + //@ run-pass #![allow(dead_code)] - - - mod foo { - pub fn baz() { } + pub fn baz() {} } mod bar { - pub fn baz() { } + pub fn baz() {} } -pub fn main() { } +pub fn main() {} diff --git a/tests/ui/type/inherent-impl-primitive-types-error.rs b/tests/ui/type/inherent-impl-primitive-types-error.rs index f1c2ee8e5506e..88b8b9da56b8e 100644 --- a/tests/ui/type/inherent-impl-primitive-types-error.rs +++ b/tests/ui/type/inherent-impl-primitive-types-error.rs @@ -1,16 +1,18 @@ +//! Test that inherent impl blocks cannot be defined for primitive types + impl u8 { -//~^ error: cannot define inherent `impl` for primitive types + //~^ ERROR: cannot define inherent `impl` for primitive types pub const B: u8 = 0; } impl str { -//~^ error: cannot define inherent `impl` for primitive types + //~^ ERROR: cannot define inherent `impl` for primitive types fn foo() {} fn bar(self) {} //~ ERROR: size for values of type `str` cannot be known } impl char { -//~^ error: cannot define inherent `impl` for primitive types + //~^ ERROR: cannot define inherent `impl` for primitive types pub const B: u8 = 0; pub const C: u8 = 0; fn foo() {} @@ -19,7 +21,7 @@ impl char { struct MyType; impl &MyType { -//~^ error: cannot define inherent `impl` for primitive types + //~^ ERROR: cannot define inherent `impl` for primitive types pub fn for_ref(self) {} } diff --git a/tests/ui/type/inherent-impl-primitive-types-error.stderr b/tests/ui/type/inherent-impl-primitive-types-error.stderr index 1c8c417e88c1f..5b79521a35e77 100644 --- a/tests/ui/type/inherent-impl-primitive-types-error.stderr +++ b/tests/ui/type/inherent-impl-primitive-types-error.stderr @@ -1,5 +1,5 @@ error[E0390]: cannot define inherent `impl` for primitive types - --> $DIR/kinds-of-primitive-impl.rs:1:1 + --> $DIR/inherent-impl-primitive-types-error.rs:3:1 | LL | impl u8 { | ^^^^^^^ @@ -7,7 +7,7 @@ LL | impl u8 { = help: consider using an extension trait instead error[E0390]: cannot define inherent `impl` for primitive types - --> $DIR/kinds-of-primitive-impl.rs:6:1 + --> $DIR/inherent-impl-primitive-types-error.rs:8:1 | LL | impl str { | ^^^^^^^^ @@ -15,7 +15,7 @@ LL | impl str { = help: consider using an extension trait instead error[E0390]: cannot define inherent `impl` for primitive types - --> $DIR/kinds-of-primitive-impl.rs:12:1 + --> $DIR/inherent-impl-primitive-types-error.rs:14:1 | LL | impl char { | ^^^^^^^^^ @@ -23,7 +23,7 @@ LL | impl char { = help: consider using an extension trait instead error[E0390]: cannot define inherent `impl` for primitive types - --> $DIR/kinds-of-primitive-impl.rs:21:1 + --> $DIR/inherent-impl-primitive-types-error.rs:23:1 | LL | impl &MyType { | ^^^^^^^^^^^^ @@ -32,7 +32,7 @@ LL | impl &MyType { = note: you could also try moving the reference to uses of `MyType` (such as `self`) within the implementation error[E0277]: the size for values of type `str` cannot be known at compilation time - --> $DIR/kinds-of-primitive-impl.rs:9:12 + --> $DIR/inherent-impl-primitive-types-error.rs:11:12 | LL | fn bar(self) {} | ^^^^ doesn't have a size known at compile-time From 986f1c9b692665d4e7388062b8d8536acb0c99fd Mon Sep 17 00:00:00 2001 From: Kivooeo Date: Tue, 1 Jul 2025 18:21:05 +0500 Subject: [PATCH 06/20] moved tests --- .../allocator-reallocate-overflow.rs} | 0 .../auto-trait-phantom-data-bounds.rs} | 0 .../auto-trait-phantom-data-bounds.stderr} | 0 .../binop-evaluation-order-primitive.rs} | 0 .../basic-ptr-coercions.rs} | 0 .../ptr-mutability-errors.rs} | 0 .../ptr-mutability-errors.stderr} | 0 .../stdout-stderr-separation.rs} | 0 .../closure-parameter-type-inference-mismatch.rs} | 0 ...losure-parameter-type-inference-mismatch.stderr} | 0 .../type-error-diagnostic-in-complex-return.rs} | 0 .../type-error-diagnostic-in-complex-return.stderr} | 0 .../doc-comment-in-generic.rs} | 0 .../raw/raw-string-literals.rs} | Bin .../pattern-ref-bindings-reassignment.rs} | 0 .../pattern-ref-bindings-reassignment.stderr} | 0 .../print-calling-conventions.rs | 0 .../print-calling-conventions.stdout | 0 .../fs-nul-byte-paths.rs} | 0 .../nested-generic-traits-performance.rs} | 0 20 files changed, 0 insertions(+), 0 deletions(-) rename tests/ui/{realloc-16687.rs => allocator/allocator-reallocate-overflow.rs} (100%) rename tests/ui/{phantom-auto-trait.rs => auto-traits/auto-trait-phantom-data-bounds.rs} (100%) rename tests/ui/{phantom-auto-trait.stderr => auto-traits/auto-trait-phantom-data-bounds.stderr} (100%) rename tests/ui/{primitive-binop-lhs-mut.rs => binop/binop-evaluation-order-primitive.rs} (100%) rename tests/ui/{ptr-coercion-rpass.rs => coercion/basic-ptr-coercions.rs} (100%) rename tests/ui/{ptr-coercion.rs => coercion/ptr-mutability-errors.rs} (100%) rename tests/ui/{ptr-coercion.stderr => coercion/ptr-mutability-errors.stderr} (100%) rename tests/ui/{print-stdout-eprint-stderr.rs => io-checks/stdout-stderr-separation.rs} (100%) rename tests/ui/{pptypedef.rs => mismatched_types/closure-parameter-type-inference-mismatch.rs} (100%) rename tests/ui/{pptypedef.stderr => mismatched_types/closure-parameter-type-inference-mismatch.stderr} (100%) rename tests/ui/{point-to-type-err-cause-on-impl-trait-return-2.rs => mismatched_types/type-error-diagnostic-in-complex-return.rs} (100%) rename tests/ui/{point-to-type-err-cause-on-impl-trait-return-2.stderr => mismatched_types/type-error-diagnostic-in-complex-return.stderr} (100%) rename tests/ui/{query-visibility.rs => parser/doc-comment-in-generic.rs} (100%) rename tests/ui/{raw-str.rs => parser/raw/raw-string-literals.rs} (100%) rename tests/ui/{reassign-ref-mut.rs => pattern/move-ref-patterns/pattern-ref-bindings-reassignment.rs} (100%) rename tests/ui/{reassign-ref-mut.stderr => pattern/move-ref-patterns/pattern-ref-bindings-reassignment.stderr} (100%) rename tests/ui/{ => print-request}/print-calling-conventions.rs (100%) rename tests/ui/{ => print-request}/print-calling-conventions.stdout (100%) rename tests/ui/{paths-containing-nul.rs => std/fs-nul-byte-paths.rs} (100%) rename tests/ui/{project-cache-issue-31849.rs => typeck/nested-generic-traits-performance.rs} (100%) diff --git a/tests/ui/realloc-16687.rs b/tests/ui/allocator/allocator-reallocate-overflow.rs similarity index 100% rename from tests/ui/realloc-16687.rs rename to tests/ui/allocator/allocator-reallocate-overflow.rs diff --git a/tests/ui/phantom-auto-trait.rs b/tests/ui/auto-traits/auto-trait-phantom-data-bounds.rs similarity index 100% rename from tests/ui/phantom-auto-trait.rs rename to tests/ui/auto-traits/auto-trait-phantom-data-bounds.rs diff --git a/tests/ui/phantom-auto-trait.stderr b/tests/ui/auto-traits/auto-trait-phantom-data-bounds.stderr similarity index 100% rename from tests/ui/phantom-auto-trait.stderr rename to tests/ui/auto-traits/auto-trait-phantom-data-bounds.stderr diff --git a/tests/ui/primitive-binop-lhs-mut.rs b/tests/ui/binop/binop-evaluation-order-primitive.rs similarity index 100% rename from tests/ui/primitive-binop-lhs-mut.rs rename to tests/ui/binop/binop-evaluation-order-primitive.rs diff --git a/tests/ui/ptr-coercion-rpass.rs b/tests/ui/coercion/basic-ptr-coercions.rs similarity index 100% rename from tests/ui/ptr-coercion-rpass.rs rename to tests/ui/coercion/basic-ptr-coercions.rs diff --git a/tests/ui/ptr-coercion.rs b/tests/ui/coercion/ptr-mutability-errors.rs similarity index 100% rename from tests/ui/ptr-coercion.rs rename to tests/ui/coercion/ptr-mutability-errors.rs diff --git a/tests/ui/ptr-coercion.stderr b/tests/ui/coercion/ptr-mutability-errors.stderr similarity index 100% rename from tests/ui/ptr-coercion.stderr rename to tests/ui/coercion/ptr-mutability-errors.stderr diff --git a/tests/ui/print-stdout-eprint-stderr.rs b/tests/ui/io-checks/stdout-stderr-separation.rs similarity index 100% rename from tests/ui/print-stdout-eprint-stderr.rs rename to tests/ui/io-checks/stdout-stderr-separation.rs diff --git a/tests/ui/pptypedef.rs b/tests/ui/mismatched_types/closure-parameter-type-inference-mismatch.rs similarity index 100% rename from tests/ui/pptypedef.rs rename to tests/ui/mismatched_types/closure-parameter-type-inference-mismatch.rs diff --git a/tests/ui/pptypedef.stderr b/tests/ui/mismatched_types/closure-parameter-type-inference-mismatch.stderr similarity index 100% rename from tests/ui/pptypedef.stderr rename to tests/ui/mismatched_types/closure-parameter-type-inference-mismatch.stderr diff --git a/tests/ui/point-to-type-err-cause-on-impl-trait-return-2.rs b/tests/ui/mismatched_types/type-error-diagnostic-in-complex-return.rs similarity index 100% rename from tests/ui/point-to-type-err-cause-on-impl-trait-return-2.rs rename to tests/ui/mismatched_types/type-error-diagnostic-in-complex-return.rs diff --git a/tests/ui/point-to-type-err-cause-on-impl-trait-return-2.stderr b/tests/ui/mismatched_types/type-error-diagnostic-in-complex-return.stderr similarity index 100% rename from tests/ui/point-to-type-err-cause-on-impl-trait-return-2.stderr rename to tests/ui/mismatched_types/type-error-diagnostic-in-complex-return.stderr diff --git a/tests/ui/query-visibility.rs b/tests/ui/parser/doc-comment-in-generic.rs similarity index 100% rename from tests/ui/query-visibility.rs rename to tests/ui/parser/doc-comment-in-generic.rs diff --git a/tests/ui/raw-str.rs b/tests/ui/parser/raw/raw-string-literals.rs similarity index 100% rename from tests/ui/raw-str.rs rename to tests/ui/parser/raw/raw-string-literals.rs diff --git a/tests/ui/reassign-ref-mut.rs b/tests/ui/pattern/move-ref-patterns/pattern-ref-bindings-reassignment.rs similarity index 100% rename from tests/ui/reassign-ref-mut.rs rename to tests/ui/pattern/move-ref-patterns/pattern-ref-bindings-reassignment.rs diff --git a/tests/ui/reassign-ref-mut.stderr b/tests/ui/pattern/move-ref-patterns/pattern-ref-bindings-reassignment.stderr similarity index 100% rename from tests/ui/reassign-ref-mut.stderr rename to tests/ui/pattern/move-ref-patterns/pattern-ref-bindings-reassignment.stderr diff --git a/tests/ui/print-calling-conventions.rs b/tests/ui/print-request/print-calling-conventions.rs similarity index 100% rename from tests/ui/print-calling-conventions.rs rename to tests/ui/print-request/print-calling-conventions.rs diff --git a/tests/ui/print-calling-conventions.stdout b/tests/ui/print-request/print-calling-conventions.stdout similarity index 100% rename from tests/ui/print-calling-conventions.stdout rename to tests/ui/print-request/print-calling-conventions.stdout diff --git a/tests/ui/paths-containing-nul.rs b/tests/ui/std/fs-nul-byte-paths.rs similarity index 100% rename from tests/ui/paths-containing-nul.rs rename to tests/ui/std/fs-nul-byte-paths.rs diff --git a/tests/ui/project-cache-issue-31849.rs b/tests/ui/typeck/nested-generic-traits-performance.rs similarity index 100% rename from tests/ui/project-cache-issue-31849.rs rename to tests/ui/typeck/nested-generic-traits-performance.rs From 1549585f26881927ea8305e0724d2d1f1dc45ade Mon Sep 17 00:00:00 2001 From: Kivooeo Date: Tue, 1 Jul 2025 19:28:14 +0500 Subject: [PATCH 07/20] moved tests --- .../reexport-test-harness-entry-point.rs} | 0 .../{stable-addr-of.rs => const-ptr/pointer-address-stability.rs} | 0 .../error-format-short.rs} | 0 .../error-format-short.stderr} | 0 .../{resource-assign-is-not-copy.rs => drop/drop-once-on-move.rs} | 0 tests/ui/{resource-destruct.rs => drop/drop-scope-exit.rs} | 0 .../ui/{seq-args.rs => generics/trait-incorrect-generic-args.rs} | 0 .../trait-incorrect-generic-args.stderr} | 0 .../io-stdout-blocking-writes.rs} | 0 tests/ui/{shadow-bool.rs => shadowed/primitive-type-shadowing.rs} | 0 .../use-shadows-reexport.rs} | 0 .../recursive-type-infinite-size.rs} | 0 .../recursive-type-infinite-size.stderr} | 0 .../sized-box-unsized-content.rs} | 0 .../sized-reference-to-unsized.rs} | 0 .../atomic-types-not-copyable.rs} | 0 .../atomic-types-not-copyable.stderr} | 0 tests/ui/{sse2.rs => target-feature/target-feature-detection.rs} | 0 .../error-trait-object-from-string.rs} | 0 19 files changed, 0 insertions(+), 0 deletions(-) rename tests/ui/{reexport-test-harness-main.rs => attributes/reexport-test-harness-entry-point.rs} (100%) rename tests/ui/{stable-addr-of.rs => const-ptr/pointer-address-stability.rs} (100%) rename tests/ui/{short-error-format.rs => diagnostic-flags/error-format-short.rs} (100%) rename tests/ui/{short-error-format.stderr => diagnostic-flags/error-format-short.stderr} (100%) rename tests/ui/{resource-assign-is-not-copy.rs => drop/drop-once-on-move.rs} (100%) rename tests/ui/{resource-destruct.rs => drop/drop-scope-exit.rs} (100%) rename tests/ui/{seq-args.rs => generics/trait-incorrect-generic-args.rs} (100%) rename tests/ui/{seq-args.stderr => generics/trait-incorrect-generic-args.stderr} (100%) rename tests/ui/{stdio-is-blocking.rs => io-checks/io-stdout-blocking-writes.rs} (100%) rename tests/ui/{shadow-bool.rs => shadowed/primitive-type-shadowing.rs} (100%) rename tests/ui/{shadowed-use-visibility.rs => shadowed/use-shadows-reexport.rs} (100%) rename tests/ui/{sized-cycle-note.rs => sized/recursive-type-infinite-size.rs} (100%) rename tests/ui/{sized-cycle-note.stderr => sized/recursive-type-infinite-size.stderr} (100%) rename tests/ui/{sized-owned-pointer.rs => sized/sized-box-unsized-content.rs} (100%) rename tests/ui/{sized-borrowed-pointer.rs => sized/sized-reference-to-unsized.rs} (100%) rename tests/ui/{std-uncopyable-atomics.rs => sync/atomic-types-not-copyable.rs} (100%) rename tests/ui/{std-uncopyable-atomics.stderr => sync/atomic-types-not-copyable.stderr} (100%) rename tests/ui/{sse2.rs => target-feature/target-feature-detection.rs} (100%) rename tests/ui/{string-box-error.rs => traits/error-trait-object-from-string.rs} (100%) diff --git a/tests/ui/reexport-test-harness-main.rs b/tests/ui/attributes/reexport-test-harness-entry-point.rs similarity index 100% rename from tests/ui/reexport-test-harness-main.rs rename to tests/ui/attributes/reexport-test-harness-entry-point.rs diff --git a/tests/ui/stable-addr-of.rs b/tests/ui/const-ptr/pointer-address-stability.rs similarity index 100% rename from tests/ui/stable-addr-of.rs rename to tests/ui/const-ptr/pointer-address-stability.rs diff --git a/tests/ui/short-error-format.rs b/tests/ui/diagnostic-flags/error-format-short.rs similarity index 100% rename from tests/ui/short-error-format.rs rename to tests/ui/diagnostic-flags/error-format-short.rs diff --git a/tests/ui/short-error-format.stderr b/tests/ui/diagnostic-flags/error-format-short.stderr similarity index 100% rename from tests/ui/short-error-format.stderr rename to tests/ui/diagnostic-flags/error-format-short.stderr diff --git a/tests/ui/resource-assign-is-not-copy.rs b/tests/ui/drop/drop-once-on-move.rs similarity index 100% rename from tests/ui/resource-assign-is-not-copy.rs rename to tests/ui/drop/drop-once-on-move.rs diff --git a/tests/ui/resource-destruct.rs b/tests/ui/drop/drop-scope-exit.rs similarity index 100% rename from tests/ui/resource-destruct.rs rename to tests/ui/drop/drop-scope-exit.rs diff --git a/tests/ui/seq-args.rs b/tests/ui/generics/trait-incorrect-generic-args.rs similarity index 100% rename from tests/ui/seq-args.rs rename to tests/ui/generics/trait-incorrect-generic-args.rs diff --git a/tests/ui/seq-args.stderr b/tests/ui/generics/trait-incorrect-generic-args.stderr similarity index 100% rename from tests/ui/seq-args.stderr rename to tests/ui/generics/trait-incorrect-generic-args.stderr diff --git a/tests/ui/stdio-is-blocking.rs b/tests/ui/io-checks/io-stdout-blocking-writes.rs similarity index 100% rename from tests/ui/stdio-is-blocking.rs rename to tests/ui/io-checks/io-stdout-blocking-writes.rs diff --git a/tests/ui/shadow-bool.rs b/tests/ui/shadowed/primitive-type-shadowing.rs similarity index 100% rename from tests/ui/shadow-bool.rs rename to tests/ui/shadowed/primitive-type-shadowing.rs diff --git a/tests/ui/shadowed-use-visibility.rs b/tests/ui/shadowed/use-shadows-reexport.rs similarity index 100% rename from tests/ui/shadowed-use-visibility.rs rename to tests/ui/shadowed/use-shadows-reexport.rs diff --git a/tests/ui/sized-cycle-note.rs b/tests/ui/sized/recursive-type-infinite-size.rs similarity index 100% rename from tests/ui/sized-cycle-note.rs rename to tests/ui/sized/recursive-type-infinite-size.rs diff --git a/tests/ui/sized-cycle-note.stderr b/tests/ui/sized/recursive-type-infinite-size.stderr similarity index 100% rename from tests/ui/sized-cycle-note.stderr rename to tests/ui/sized/recursive-type-infinite-size.stderr diff --git a/tests/ui/sized-owned-pointer.rs b/tests/ui/sized/sized-box-unsized-content.rs similarity index 100% rename from tests/ui/sized-owned-pointer.rs rename to tests/ui/sized/sized-box-unsized-content.rs diff --git a/tests/ui/sized-borrowed-pointer.rs b/tests/ui/sized/sized-reference-to-unsized.rs similarity index 100% rename from tests/ui/sized-borrowed-pointer.rs rename to tests/ui/sized/sized-reference-to-unsized.rs diff --git a/tests/ui/std-uncopyable-atomics.rs b/tests/ui/sync/atomic-types-not-copyable.rs similarity index 100% rename from tests/ui/std-uncopyable-atomics.rs rename to tests/ui/sync/atomic-types-not-copyable.rs diff --git a/tests/ui/std-uncopyable-atomics.stderr b/tests/ui/sync/atomic-types-not-copyable.stderr similarity index 100% rename from tests/ui/std-uncopyable-atomics.stderr rename to tests/ui/sync/atomic-types-not-copyable.stderr diff --git a/tests/ui/sse2.rs b/tests/ui/target-feature/target-feature-detection.rs similarity index 100% rename from tests/ui/sse2.rs rename to tests/ui/target-feature/target-feature-detection.rs diff --git a/tests/ui/string-box-error.rs b/tests/ui/traits/error-trait-object-from-string.rs similarity index 100% rename from tests/ui/string-box-error.rs rename to tests/ui/traits/error-trait-object-from-string.rs From 5292554337171308eff06605cd825d0fcc68874c Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Thu, 3 Jul 2025 22:23:15 -0700 Subject: [PATCH 08/20] Block SIMD in transmute_immediate; delete `OperandValueKind` See conversation in . --- compiler/rustc_codegen_ssa/src/mir/operand.rs | 11 +- compiler/rustc_codegen_ssa/src/mir/rvalue.rs | 218 ++++++------------ tests/codegen/intrinsics/transmute-x64.rs | 11 +- .../simd-intrinsic-transmute-array.rs | 6 +- tests/codegen/transmute-scalar.rs | 14 +- tests/codegen/vec-in-place.rs | 31 +-- 6 files changed, 101 insertions(+), 190 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/mir/operand.rs b/compiler/rustc_codegen_ssa/src/mir/operand.rs index da615cc9a003d..2c4fca71e2a02 100644 --- a/compiler/rustc_codegen_ssa/src/mir/operand.rs +++ b/compiler/rustc_codegen_ssa/src/mir/operand.rs @@ -346,6 +346,13 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> { let val = if field.is_zst() { OperandValue::ZeroSized + } else if let BackendRepr::SimdVector { .. } = self.layout.backend_repr { + // codegen_transmute_operand doesn't support SIMD, but since the previous + // check handled ZSTs, the only possible field access into something SIMD + // is to the `non_1zst_field` that's the same SIMD. (Other things, even + // just padding, would change the wrapper's representation type.) + assert_eq!(field.size, self.layout.size); + self.val } else if field.size == self.layout.size { assert_eq!(offset.bytes(), 0); fx.codegen_transmute_operand(bx, *self, field).unwrap_or_else(|| { @@ -606,10 +613,8 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, Result> { }; let mut update = |tgt: &mut Result, src, from_scalar| { - let from_bty = bx.cx().type_from_scalar(from_scalar); let to_scalar = tgt.unwrap_err(); - let to_bty = bx.cx().type_from_scalar(to_scalar); - let imm = transmute_immediate(bx, src, from_scalar, from_bty, to_scalar, to_bty); + let imm = transmute_immediate(bx, src, from_scalar, to_scalar); *tgt = Ok(imm); }; diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs index 60cf4e28b5a09..10954c5a98b8b 100644 --- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs +++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs @@ -1,10 +1,8 @@ -use std::assert_matches::assert_matches; - use rustc_abi::{self as abi, FIRST_VARIANT}; use rustc_middle::ty::adjustment::PointerCoercion; use rustc_middle::ty::layout::{HasTyCtxt, HasTypingEnv, LayoutOf, TyAndLayout}; use rustc_middle::ty::{self, Instance, Ty, TyCtxt}; -use rustc_middle::{bug, mir, span_bug}; +use rustc_middle::{bug, mir}; use rustc_session::config::OptLevel; use rustc_span::{DUMMY_SP, Span}; use tracing::{debug, instrument}; @@ -12,7 +10,7 @@ use tracing::{debug, instrument}; use super::operand::{OperandRef, OperandValue}; use super::place::PlaceRef; use super::{FunctionCx, LocalRef}; -use crate::common::IntPredicate; +use crate::common::{IntPredicate, TypeKind}; use crate::traits::*; use crate::{MemFlags, base}; @@ -200,31 +198,25 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { assert!(src.layout.is_sized()); assert!(dst.layout.is_sized()); - if let Some(val) = self.codegen_transmute_operand(bx, src, dst.layout) { - val.store(bx, dst); - return; - } - - match src.val { - OperandValue::Ref(..) | OperandValue::ZeroSized => { - span_bug!( - self.mir.span, - "Operand path should have handled transmute \ - from {src:?} to place {dst:?}" - ); - } - OperandValue::Immediate(..) | OperandValue::Pair(..) => { - // When we have immediate(s), the alignment of the source is irrelevant, - // so we can store them using the destination's alignment. - src.val.store(bx, dst.val.with_type(src.layout)); - } + if src.layout.size == dst.layout.size { + // Since in this path we have a place anyway, we can store or copy to it, + // making sure we use the destination place's alignment even if the + // source would normally have a higher one. + src.val.store(bx, dst.val.with_type(src.layout)); + } else if src.layout.is_uninhabited() { + bx.unreachable() + } else { + // Since this is known statically and the input could have existed + // without already having hit UB, might as well trap for it, even + // though it's UB so we *could* also unreachable it. + bx.abort(); } } /// Attempts to transmute an `OperandValue` to another `OperandValue`. /// /// Returns `None` for cases that can't work in that framework, such as for - /// `Immediate`->`Ref` that needs an `alloc` to get the location. + /// `Immediate`->`Ref` that needs an `alloca` to get the location. pub(crate) fn codegen_transmute_operand( &mut self, bx: &mut Bx, @@ -247,69 +239,34 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { return Some(OperandValue::poison(bx, cast)); } - let operand_kind = self.value_kind(operand.layout); - let cast_kind = self.value_kind(cast); - - match operand.val { - OperandValue::Ref(source_place_val) => { + Some(match (operand.val, operand.layout.backend_repr, cast.backend_repr) { + _ if cast.is_zst() => OperandValue::ZeroSized, + (OperandValue::ZeroSized, _, _) => bug!(), + ( + OperandValue::Ref(source_place_val), + abi::BackendRepr::Memory { .. }, + abi::BackendRepr::Scalar(_) | abi::BackendRepr::ScalarPair(_, _), + ) => { assert_eq!(source_place_val.llextra, None); - assert_matches!(operand_kind, OperandValueKind::Ref); // The existing alignment is part of `source_place_val`, // so that alignment will be used, not `cast`'s. - Some(bx.load_operand(source_place_val.with_type(cast)).val) + bx.load_operand(source_place_val.with_type(cast)).val } - OperandValue::ZeroSized => { - let OperandValueKind::ZeroSized = operand_kind else { - bug!("Found {operand_kind:?} for operand {operand:?}"); - }; - if let OperandValueKind::ZeroSized = cast_kind { - Some(OperandValue::ZeroSized) - } else { - None - } - } - OperandValue::Immediate(imm) => { - let OperandValueKind::Immediate(from_scalar) = operand_kind else { - bug!("Found {operand_kind:?} for operand {operand:?}"); - }; - if let OperandValueKind::Immediate(to_scalar) = cast_kind - && from_scalar.size(self.cx) == to_scalar.size(self.cx) - { - let from_backend_ty = bx.backend_type(operand.layout); - let to_backend_ty = bx.backend_type(cast); - Some(OperandValue::Immediate(transmute_immediate( - bx, - imm, - from_scalar, - from_backend_ty, - to_scalar, - to_backend_ty, - ))) - } else { - None - } - } - OperandValue::Pair(imm_a, imm_b) => { - let OperandValueKind::Pair(in_a, in_b) = operand_kind else { - bug!("Found {operand_kind:?} for operand {operand:?}"); - }; - if let OperandValueKind::Pair(out_a, out_b) = cast_kind - && in_a.size(self.cx) == out_a.size(self.cx) - && in_b.size(self.cx) == out_b.size(self.cx) - { - let in_a_ibty = bx.scalar_pair_element_backend_type(operand.layout, 0, false); - let in_b_ibty = bx.scalar_pair_element_backend_type(operand.layout, 1, false); - let out_a_ibty = bx.scalar_pair_element_backend_type(cast, 0, false); - let out_b_ibty = bx.scalar_pair_element_backend_type(cast, 1, false); - Some(OperandValue::Pair( - transmute_immediate(bx, imm_a, in_a, in_a_ibty, out_a, out_a_ibty), - transmute_immediate(bx, imm_b, in_b, in_b_ibty, out_b, out_b_ibty), - )) - } else { - None - } - } - } + ( + OperandValue::Immediate(imm), + abi::BackendRepr::Scalar(from_scalar), + abi::BackendRepr::Scalar(to_scalar), + ) => OperandValue::Immediate(transmute_immediate(bx, imm, from_scalar, to_scalar)), + ( + OperandValue::Pair(imm_a, imm_b), + abi::BackendRepr::ScalarPair(in_a, in_b), + abi::BackendRepr::ScalarPair(out_a, out_b), + ) => OperandValue::Pair( + transmute_immediate(bx, imm_a, in_a, out_a), + transmute_immediate(bx, imm_b, in_b, out_b), + ), + _ => return None, + }) } /// Cast one of the immediates from an [`OperandValue::Immediate`] @@ -479,9 +436,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // path as the other integer-to-X casts. | mir::CastKind::PointerWithExposedProvenance => { let imm = operand.immediate(); - let operand_kind = self.value_kind(operand.layout); - let OperandValueKind::Immediate(from_scalar) = operand_kind else { - bug!("Found {operand_kind:?} for operand {operand:?}"); + let abi::BackendRepr::Scalar(from_scalar) = operand.layout.backend_repr else { + bug!("Found non-scalar for operand {operand:?}"); }; let from_backend_ty = bx.cx().immediate_backend_type(operand.layout); @@ -491,9 +447,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let val = OperandValue::Immediate(bx.cx().const_poison(to_backend_ty)); return OperandRef { val, layout: cast }; } - let cast_kind = self.value_kind(cast); - let OperandValueKind::Immediate(to_scalar) = cast_kind else { - bug!("Found {cast_kind:?} for operand {cast:?}"); + let abi::BackendRepr::Scalar(to_scalar) = cast.layout.backend_repr else { + bug!("Found non-scalar for cast {cast:?}"); }; self.cast_immediate(bx, imm, from_scalar, from_backend_ty, to_scalar, to_backend_ty) @@ -993,31 +948,29 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let operand_ty = operand.ty(self.mir, self.cx.tcx()); let cast_layout = self.cx.layout_of(self.monomorphize(cast_ty)); let operand_layout = self.cx.layout_of(self.monomorphize(operand_ty)); - - match (self.value_kind(operand_layout), self.value_kind(cast_layout)) { - // Can always load from a pointer as needed - (OperandValueKind::Ref, _) => true, - - // ZST-to-ZST is the easiest thing ever - (OperandValueKind::ZeroSized, OperandValueKind::ZeroSized) => true, - - // But if only one of them is a ZST the sizes can't match - (OperandValueKind::ZeroSized, _) | (_, OperandValueKind::ZeroSized) => false, - - // Need to generate an `alloc` to get a pointer from an immediate - (OperandValueKind::Immediate(..) | OperandValueKind::Pair(..), OperandValueKind::Ref) => false, + match (operand_layout.backend_repr, cast_layout.backend_repr) { + // If the input is in a place we can load immediates from there. + (abi::BackendRepr::Memory { .. }, abi::BackendRepr::Scalar(_) | abi::BackendRepr::ScalarPair(_, _)) => true, // When we have scalar immediates, we can only convert things // where the sizes match, to avoid endianness questions. - (OperandValueKind::Immediate(a), OperandValueKind::Immediate(b)) => + (abi::BackendRepr::Scalar(a), abi::BackendRepr::Scalar(b)) => a.size(self.cx) == b.size(self.cx), - (OperandValueKind::Pair(a0, a1), OperandValueKind::Pair(b0, b1)) => + (abi::BackendRepr::ScalarPair(a0, a1), abi::BackendRepr::ScalarPair(b0, b1)) => a0.size(self.cx) == b0.size(self.cx) && a1.size(self.cx) == b1.size(self.cx), - // Send mixings between scalars and pairs through the memory route - // FIXME: Maybe this could use insertvalue/extractvalue instead? - (OperandValueKind::Immediate(..), OperandValueKind::Pair(..)) | - (OperandValueKind::Pair(..), OperandValueKind::Immediate(..)) => false, + // SIMD vectors don't work like normal immediates, + // so always send them through memory. + (abi::BackendRepr::SimdVector { .. }, _) | (_, abi::BackendRepr::SimdVector { .. }) => false, + + // When the output will be in memory anyway, just use its place + // (instead of the operand path) unless it's the trivial ZST case. + (_, abi::BackendRepr::Memory { .. }) => cast_layout.is_zst(), + + // Mixing Scalars and ScalarPairs can get quite complicated when + // padding and undef get involved, so leave that to the memory path. + (abi::BackendRepr::Scalar(_), abi::BackendRepr::ScalarPair(_, _)) | + (abi::BackendRepr::ScalarPair(_, _), abi::BackendRepr::Scalar(_)) => false, } } mir::Rvalue::Ref(..) | @@ -1062,41 +1015,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // (*) this is only true if the type is suitable } - - /// Gets which variant of [`OperandValue`] is expected for a particular type. - fn value_kind(&self, layout: TyAndLayout<'tcx>) -> OperandValueKind { - if layout.is_zst() { - OperandValueKind::ZeroSized - } else if self.cx.is_backend_immediate(layout) { - assert!(!self.cx.is_backend_scalar_pair(layout)); - OperandValueKind::Immediate(match layout.backend_repr { - abi::BackendRepr::Scalar(s) => s, - abi::BackendRepr::SimdVector { element, .. } => element, - x => span_bug!(self.mir.span, "Couldn't translate {x:?} as backend immediate"), - }) - } else if self.cx.is_backend_scalar_pair(layout) { - let abi::BackendRepr::ScalarPair(s1, s2) = layout.backend_repr else { - span_bug!( - self.mir.span, - "Couldn't translate {:?} as backend scalar pair", - layout.backend_repr, - ); - }; - OperandValueKind::Pair(s1, s2) - } else { - OperandValueKind::Ref - } - } -} - -/// The variants of this match [`OperandValue`], giving details about the -/// backend values that will be held in that other type. -#[derive(Debug, Copy, Clone)] -enum OperandValueKind { - Ref, - Immediate(abi::Scalar), - Pair(abi::Scalar, abi::Scalar), - ZeroSized, } /// Transmutes one of the immediates from an [`OperandValue::Immediate`] @@ -1108,22 +1026,30 @@ pub(super) fn transmute_immediate<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( bx: &mut Bx, mut imm: Bx::Value, from_scalar: abi::Scalar, - from_backend_ty: Bx::Type, to_scalar: abi::Scalar, - to_backend_ty: Bx::Type, ) -> Bx::Value { assert_eq!(from_scalar.size(bx.cx()), to_scalar.size(bx.cx())); + let imm_ty = bx.cx().val_ty(imm); + assert_ne!( + bx.cx().type_kind(imm_ty), + TypeKind::Vector, + "Vector type {imm_ty:?} not allowed in transmute_immediate {from_scalar:?} -> {to_scalar:?}" + ); // While optimizations will remove no-op transmutes, they might still be // there in debug or things that aren't no-op in MIR because they change // the Rust type but not the underlying layout/niche. - if from_scalar == to_scalar && from_backend_ty == to_backend_ty { + if from_scalar == to_scalar { return imm; } use abi::Primitive::*; imm = bx.from_immediate(imm); + let from_backend_ty = bx.cx().type_from_scalar(from_scalar); + debug_assert_eq!(bx.cx().val_ty(imm), from_backend_ty); + let to_backend_ty = bx.cx().type_from_scalar(to_scalar); + // If we have a scalar, we must already know its range. Either // // 1) It's a parameter with `range` parameter metadata, @@ -1154,6 +1080,8 @@ pub(super) fn transmute_immediate<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( } }; + debug_assert_eq!(bx.cx().val_ty(imm), to_backend_ty); + // This `assume` remains important for cases like (a conceptual) // transmute::(x) == 0 // since it's never passed to something with parameter metadata (especially diff --git a/tests/codegen/intrinsics/transmute-x64.rs b/tests/codegen/intrinsics/transmute-x64.rs index be45e4db90fd9..8c9480ab0915e 100644 --- a/tests/codegen/intrinsics/transmute-x64.rs +++ b/tests/codegen/intrinsics/transmute-x64.rs @@ -9,17 +9,20 @@ use std::mem::transmute; // CHECK-LABEL: @check_sse_pair_to_avx( #[no_mangle] pub unsafe fn check_sse_pair_to_avx(x: (__m128i, __m128i)) -> __m256i { + // CHECK: start: // CHECK-NOT: alloca - // CHECK: %0 = load <4 x i64>, ptr %x, align 16 - // CHECK: store <4 x i64> %0, ptr %_0, align 32 + // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 32 %_0, ptr align 16 %x, i64 32, i1 false) + // CHECK-NEXT: ret void transmute(x) } // CHECK-LABEL: @check_sse_pair_from_avx( #[no_mangle] pub unsafe fn check_sse_pair_from_avx(x: __m256i) -> (__m128i, __m128i) { + // CHECK: start: // CHECK-NOT: alloca - // CHECK: %0 = load <4 x i64>, ptr %x, align 32 - // CHECK: store <4 x i64> %0, ptr %_0, align 16 + // CHECK-NEXT: %[[TEMP:.+]] = load <4 x i64>, ptr %x, align 32 + // CHECK-NEXT: store <4 x i64> %[[TEMP]], ptr %_0, align 16 + // CHECK-NEXT: ret void transmute(x) } diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-transmute-array.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-transmute-array.rs index 977bf3379b7dd..301f06c2d74ae 100644 --- a/tests/codegen/simd-intrinsic/simd-intrinsic-transmute-array.rs +++ b/tests/codegen/simd-intrinsic/simd-intrinsic-transmute-array.rs @@ -40,8 +40,7 @@ pub fn build_array_s(x: [f32; 4]) -> S<4> { // CHECK-LABEL: @build_array_transmute_s #[no_mangle] pub fn build_array_transmute_s(x: [f32; 4]) -> S<4> { - // CHECK: %[[VAL:.+]] = load <4 x float>, ptr %x, align [[ARRAY_ALIGN]] - // CHECK: store <4 x float> %[[VAL:.+]], ptr %_0, align [[VECTOR_ALIGN]] + // CHECK: call void @llvm.memcpy.{{.+}}({{.*}} align [[VECTOR_ALIGN]] {{.*}} align [[ARRAY_ALIGN]] {{.*}}, [[USIZE]] 16, i1 false) unsafe { std::mem::transmute(x) } } @@ -55,7 +54,6 @@ pub fn build_array_t(x: [f32; 4]) -> T { // CHECK-LABEL: @build_array_transmute_t #[no_mangle] pub fn build_array_transmute_t(x: [f32; 4]) -> T { - // CHECK: %[[VAL:.+]] = load <4 x float>, ptr %x, align [[ARRAY_ALIGN]] - // CHECK: store <4 x float> %[[VAL:.+]], ptr %_0, align [[VECTOR_ALIGN]] + // CHECK: call void @llvm.memcpy.{{.+}}({{.*}} align [[VECTOR_ALIGN]] {{.*}} align [[ARRAY_ALIGN]] {{.*}}, [[USIZE]] 16, i1 false) unsafe { std::mem::transmute(x) } } diff --git a/tests/codegen/transmute-scalar.rs b/tests/codegen/transmute-scalar.rs index 3ac6ba3beb1ee..ce1b0558b2eec 100644 --- a/tests/codegen/transmute-scalar.rs +++ b/tests/codegen/transmute-scalar.rs @@ -111,8 +111,11 @@ pub fn fake_bool_unsigned_to_bool(b: FakeBoolUnsigned) -> bool { struct S([i64; 1]); // CHECK-LABEL: define{{.*}}i64 @single_element_simd_to_scalar(<1 x i64> %b) -// CHECK: bitcast <1 x i64> %b to i64 -// CHECK: ret i64 +// CHECK-NEXT: start: +// CHECK-NEXT: %[[RET:.+]] = alloca [8 x i8] +// CHECK-NEXT: store <1 x i64> %b, ptr %[[RET]] +// CHECK-NEXT: %[[TEMP:.+]] = load i64, ptr %[[RET]] +// CHECK-NEXT: ret i64 %[[TEMP]] #[no_mangle] #[cfg_attr(target_family = "wasm", target_feature(enable = "simd128"))] #[cfg_attr(target_arch = "arm", target_feature(enable = "neon"))] @@ -124,8 +127,11 @@ pub extern "C" fn single_element_simd_to_scalar(b: S) -> i64 { } // CHECK-LABEL: define{{.*}}<1 x i64> @scalar_to_single_element_simd(i64 %b) -// CHECK: bitcast i64 %b to <1 x i64> -// CHECK: ret <1 x i64> +// CHECK-NEXT: start: +// CHECK-NEXT: %[[RET:.+]] = alloca [8 x i8] +// CHECK-NEXT: store i64 %b, ptr %[[RET]] +// CHECK-NEXT: %[[TEMP:.+]] = load <1 x i64>, ptr %[[RET]] +// CHECK-NEXT: ret <1 x i64> %[[TEMP]] #[no_mangle] #[cfg_attr(target_family = "wasm", target_feature(enable = "simd128"))] #[cfg_attr(target_arch = "arm", target_feature(enable = "neon"))] diff --git a/tests/codegen/vec-in-place.rs b/tests/codegen/vec-in-place.rs index 1f6836f6dfabb..a5ef8653b997e 100644 --- a/tests/codegen/vec-in-place.rs +++ b/tests/codegen/vec-in-place.rs @@ -41,9 +41,6 @@ pub fn vec_iterator_cast_primitive(vec: Vec) -> Vec { // CHECK: call{{.+}}void @llvm.assume(i1 %{{.+}}) // CHECK-NOT: loop // CHECK-NOT: call - // CHECK: call{{.+}}void @llvm.assume(i1 %{{.+}}) - // CHECK-NOT: loop - // CHECK-NOT: call vec.into_iter().map(|e| e as u8).collect() } @@ -55,9 +52,6 @@ pub fn vec_iterator_cast_wrapper(vec: Vec) -> Vec> { // CHECK: call{{.+}}void @llvm.assume(i1 %{{.+}}) // CHECK-NOT: loop // CHECK-NOT: call - // CHECK: call{{.+}}void @llvm.assume(i1 %{{.+}}) - // CHECK-NOT: loop - // CHECK-NOT: call vec.into_iter().map(|e| Wrapper(e)).collect() } @@ -86,9 +80,6 @@ pub fn vec_iterator_cast_unwrap(vec: Vec>) -> Vec { // CHECK: call{{.+}}void @llvm.assume(i1 %{{.+}}) // CHECK-NOT: loop // CHECK-NOT: call - // CHECK: call{{.+}}void @llvm.assume(i1 %{{.+}}) - // CHECK-NOT: loop - // CHECK-NOT: call vec.into_iter().map(|e| e.0).collect() } @@ -100,9 +91,6 @@ pub fn vec_iterator_cast_aggregate(vec: Vec<[u64; 4]>) -> Vec { // CHECK: call{{.+}}void @llvm.assume(i1 %{{.+}}) // CHECK-NOT: loop // CHECK-NOT: call - // CHECK: call{{.+}}void @llvm.assume(i1 %{{.+}}) - // CHECK-NOT: loop - // CHECK-NOT: call vec.into_iter().map(|e| unsafe { std::mem::transmute(e) }).collect() } @@ -114,9 +102,6 @@ pub fn vec_iterator_cast_deaggregate_tra(vec: Vec) -> Vec<[u64; 4]> { // CHECK: call{{.+}}void @llvm.assume(i1 %{{.+}}) // CHECK-NOT: loop // CHECK-NOT: call - // CHECK: call{{.+}}void @llvm.assume(i1 %{{.+}}) - // CHECK-NOT: loop - // CHECK-NOT: call // Safety: For the purpose of this test we assume that Bar layout matches [u64; 4]. // This currently is not guaranteed for repr(Rust) types, but it happens to work here and @@ -133,9 +118,6 @@ pub fn vec_iterator_cast_deaggregate_fold(vec: Vec) -> Vec<[u64; 4]> { // CHECK: call{{.+}}void @llvm.assume(i1 %{{.+}}) // CHECK-NOT: loop // CHECK-NOT: call - // CHECK: call{{.+}}void @llvm.assume(i1 %{{.+}}) - // CHECK-NOT: loop - // CHECK-NOT: call // Safety: For the purpose of this test we assume that Bar layout matches [u64; 4]. // This currently is not guaranteed for repr(Rust) types, but it happens to work here and @@ -156,12 +138,7 @@ pub fn vec_iterator_cast_unwrap_drop(vec: Vec>) -> Vec { // CHECK-NOT: call // CHECK-NOT: %{{.*}} = mul // CHECK-NOT: %{{.*}} = udiv - // CHECK: call - // CHECK-SAME: void @llvm.assume(i1 %{{.+}}) - // CHECK-NOT: br i1 %{{.*}}, label %{{.*}}, label %{{.*}} - // CHECK-NOT: call - // CHECK-NOT: %{{.*}} = mul - // CHECK-NOT: %{{.*}} = udiv + // CHECK: ret void vec.into_iter().map(|Wrapper(e)| e).collect() } @@ -178,12 +155,6 @@ pub fn vec_iterator_cast_wrap_drop(vec: Vec) -> Vec> { // CHECK-NOT: call // CHECK-NOT: %{{.*}} = mul // CHECK-NOT: %{{.*}} = udiv - // CHECK: call - // CHECK-SAME: void @llvm.assume(i1 %{{.+}}) - // CHECK-NOT: br i1 %{{.*}}, label %{{.*}}, label %{{.*}} - // CHECK-NOT: call - // CHECK-NOT: %{{.*}} = mul - // CHECK-NOT: %{{.*}} = udiv // CHECK: ret void vec.into_iter().map(Wrapper).collect() From a3277a1bbb82423416a716b13c483a13e00aef59 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Thu, 3 Jul 2025 20:39:32 +0200 Subject: [PATCH 09/20] test rust calling a C C-variadic function --- .../c-link-to-rust-va-list-fn/checkrust.rs | 62 +++++++++++++++---- .../run-make/c-link-to-rust-va-list-fn/test.c | 53 ++++++++++++++++ 2 files changed, 104 insertions(+), 11 deletions(-) diff --git a/tests/run-make/c-link-to-rust-va-list-fn/checkrust.rs b/tests/run-make/c-link-to-rust-va-list-fn/checkrust.rs index 36c9db106ec45..63d8d713d6226 100644 --- a/tests/run-make/c-link-to-rust-va-list-fn/checkrust.rs +++ b/tests/run-make/c-link-to-rust-va-list-fn/checkrust.rs @@ -1,7 +1,8 @@ #![crate_type = "staticlib"] #![feature(c_variadic)] +#![feature(cfg_select)] -use std::ffi::{CStr, CString, VaList, c_char, c_double, c_int, c_long, c_longlong}; +use std::ffi::{CStr, CString, VaList, VaListImpl, c_char, c_double, c_int, c_long, c_longlong}; macro_rules! continue_if { ($cond:expr) => { @@ -19,7 +20,7 @@ unsafe fn compare_c_str(ptr: *const c_char, val: &str) -> bool { } } -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn check_list_0(mut ap: VaList) -> usize { continue_if!(ap.arg::() == 1); continue_if!(ap.arg::() == 2); @@ -27,7 +28,7 @@ pub unsafe extern "C" fn check_list_0(mut ap: VaList) -> usize { 0 } -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn check_list_1(mut ap: VaList) -> usize { continue_if!(ap.arg::() == -1); continue_if!(ap.arg::() == 'A' as c_int); @@ -39,7 +40,7 @@ pub unsafe extern "C" fn check_list_1(mut ap: VaList) -> usize { 0 } -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn check_list_2(mut ap: VaList) -> usize { continue_if!(ap.arg::().floor() == 3.14f64.floor()); continue_if!(ap.arg::() == 12); @@ -51,7 +52,7 @@ pub unsafe extern "C" fn check_list_2(mut ap: VaList) -> usize { 0 } -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn check_list_copy_0(mut ap: VaList) -> usize { continue_if!(ap.arg::().floor() == 6.28f64.floor()); continue_if!(ap.arg::() == 16); @@ -64,14 +65,14 @@ pub unsafe extern "C" fn check_list_copy_0(mut ap: VaList) -> usize { ) } -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn check_varargs_0(_: c_int, mut ap: ...) -> usize { continue_if!(ap.arg::() == 42); continue_if!(compare_c_str(ap.arg::<*const c_char>(), "Hello, World!")); 0 } -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn check_varargs_1(_: c_int, mut ap: ...) -> usize { continue_if!(ap.arg::().floor() == 3.14f64.floor()); continue_if!(ap.arg::() == 12); @@ -80,12 +81,12 @@ pub unsafe extern "C" fn check_varargs_1(_: c_int, mut ap: ...) -> usize { 0 } -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn check_varargs_2(_: c_int, _ap: ...) -> usize { 0 } -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn check_varargs_3(_: c_int, mut ap: ...) -> usize { continue_if!(ap.arg::() == 1); continue_if!(ap.arg::() == 2); @@ -100,7 +101,7 @@ pub unsafe extern "C" fn check_varargs_3(_: c_int, mut ap: ...) -> usize { 0 } -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn check_varargs_4(_: c_double, mut ap: ...) -> usize { continue_if!(ap.arg::() == 1.0); continue_if!(ap.arg::() == 2.0); @@ -118,7 +119,7 @@ pub unsafe extern "C" fn check_varargs_4(_: c_double, mut ap: ...) -> usize { 0 } -#[no_mangle] +#[unsafe(no_mangle)] pub unsafe extern "C" fn check_varargs_5(_: c_int, mut ap: ...) -> usize { continue_if!(ap.arg::() == 1.0); continue_if!(ap.arg::() == 1); @@ -148,3 +149,42 @@ pub unsafe extern "C" fn check_varargs_5(_: c_int, mut ap: ...) -> usize { continue_if!(ap.arg::() == 13.0); 0 } + +unsafe extern "C" { + fn test_variadic(_: c_int, ...) -> usize; + fn test_va_list_by_value(_: VaList) -> usize; + fn test_va_list_by_pointer(_: *mut VaListImpl) -> usize; + fn test_va_list_by_pointer_pointer(_: *mut *mut VaListImpl) -> usize; +} + +#[unsafe(no_mangle)] +extern "C" fn run_test_variadic() -> usize { + return unsafe { test_variadic(0, 1 as c_longlong, 2 as c_int, 3 as c_longlong) }; +} + +#[unsafe(no_mangle)] +extern "C" fn run_test_va_list_by_value() -> usize { + unsafe extern "C" fn helper(mut ap: ...) -> usize { + unsafe { test_va_list_by_value(ap.as_va_list()) } + } + + unsafe { helper(1 as c_longlong, 2 as c_int, 3 as c_longlong) } +} + +#[unsafe(no_mangle)] +extern "C" fn run_test_va_list_by_pointer() -> usize { + unsafe extern "C" fn helper(mut ap: ...) -> usize { + unsafe { test_va_list_by_pointer(&mut ap) } + } + + unsafe { helper(1 as c_longlong, 2 as c_int, 3 as c_longlong) } +} + +#[unsafe(no_mangle)] +extern "C" fn run_test_va_list_by_pointer_pointer() -> usize { + unsafe extern "C" fn helper(mut ap: ...) -> usize { + unsafe { test_va_list_by_pointer_pointer(&mut (&mut ap as *mut _)) } + } + + unsafe { helper(1 as c_longlong, 2 as c_int, 3 as c_longlong) } +} diff --git a/tests/run-make/c-link-to-rust-va-list-fn/test.c b/tests/run-make/c-link-to-rust-va-list-fn/test.c index b47a9357880f1..2bb93c0b5d0ef 100644 --- a/tests/run-make/c-link-to-rust-va-list-fn/test.c +++ b/tests/run-make/c-link-to-rust-va-list-fn/test.c @@ -15,6 +15,11 @@ extern size_t check_varargs_3(int fixed, ...); extern size_t check_varargs_4(double fixed, ...); extern size_t check_varargs_5(int fixed, ...); +extern size_t run_test_variadic(); +extern size_t run_test_va_list_by_value(); +extern size_t run_test_va_list_by_pointer(); +extern size_t run_test_va_list_by_pointer_pointer(); + int test_rust(size_t (*fn)(va_list), ...) { size_t ret = 0; va_list ap; @@ -47,5 +52,53 @@ int main(int argc, char* argv[]) { assert(check_varargs_5(0, 1.0, 1, 2.0, 2, 3.0, 3, 4.0, 4, 5, 5.0, 6, 6.0, 7, 7.0, 8, 8.0, 9, 9.0, 10, 10.0, 11, 11.0, 12, 12.0, 13, 13.0) == 0); + assert(run_test_variadic() == 0); + assert(run_test_va_list_by_value() == 0); + assert(run_test_va_list_by_pointer() == 0); + assert(run_test_va_list_by_pointer_pointer() == 0); + + return 0; +} + +#define continue_if_else_end(cond) \ + do { if (!(cond)) { va_end(ap); return 0xff; } } while (0) + +size_t test_variadic(int unused, ...) { + va_list ap; + va_start(ap, unused); + + continue_if_else_end(va_arg(ap, long long) == 1); + continue_if_else_end(va_arg(ap, int) == 2); + continue_if_else_end(va_arg(ap, long long) == 3); + + va_end(ap); + + return 0; +} + +#define continue_if(cond) \ + do { if (!(cond)) { return 0xff; } } while (0) + +size_t test_va_list_by_value(va_list ap) { + continue_if(va_arg(ap, long long) == 1); + continue_if(va_arg(ap, int) == 2); + continue_if(va_arg(ap, long long) == 3); + + return 0; +} + +size_t test_va_list_by_pointer(va_list *ap) { + continue_if(va_arg(*ap, long long) == 1); + continue_if(va_arg(*ap, int) == 2); + continue_if(va_arg(*ap, long long) == 3); + + return 0; +} + +size_t test_va_list_by_pointer_pointer(va_list **ap) { + continue_if(va_arg(**ap, long long) == 1); + continue_if(va_arg(**ap, int) == 2); + continue_if(va_arg(**ap, long long) == 3); + return 0; } From e0c54c3a9bc92b480570d26251c98ce497109988 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Fri, 4 Jul 2025 10:35:51 -0700 Subject: [PATCH 10/20] =?UTF-8?q?Rename=20`transmute=5Fimmediate`=20?= =?UTF-8?q?=E2=86=92=20`transmute=5Fscalar`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- compiler/rustc_codegen_ssa/src/mir/operand.rs | 4 ++-- compiler/rustc_codegen_ssa/src/mir/rvalue.rs | 20 ++++++++++--------- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/mir/operand.rs b/compiler/rustc_codegen_ssa/src/mir/operand.rs index 2c4fca71e2a02..4b1c689a01069 100644 --- a/compiler/rustc_codegen_ssa/src/mir/operand.rs +++ b/compiler/rustc_codegen_ssa/src/mir/operand.rs @@ -13,7 +13,7 @@ use rustc_session::config::OptLevel; use tracing::{debug, instrument}; use super::place::{PlaceRef, PlaceValue}; -use super::rvalue::transmute_immediate; +use super::rvalue::transmute_scalar; use super::{FunctionCx, LocalRef}; use crate::common::IntPredicate; use crate::traits::*; @@ -614,7 +614,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, Result> { let mut update = |tgt: &mut Result, src, from_scalar| { let to_scalar = tgt.unwrap_err(); - let imm = transmute_immediate(bx, src, from_scalar, to_scalar); + let imm = transmute_scalar(bx, src, from_scalar, to_scalar); *tgt = Ok(imm); }; diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs index 10954c5a98b8b..589405e885fbd 100644 --- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs +++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs @@ -256,14 +256,14 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { OperandValue::Immediate(imm), abi::BackendRepr::Scalar(from_scalar), abi::BackendRepr::Scalar(to_scalar), - ) => OperandValue::Immediate(transmute_immediate(bx, imm, from_scalar, to_scalar)), + ) => OperandValue::Immediate(transmute_scalar(bx, imm, from_scalar, to_scalar)), ( OperandValue::Pair(imm_a, imm_b), abi::BackendRepr::ScalarPair(in_a, in_b), abi::BackendRepr::ScalarPair(out_a, out_b), ) => OperandValue::Pair( - transmute_immediate(bx, imm_a, in_a, out_a), - transmute_immediate(bx, imm_b, in_b, out_b), + transmute_scalar(bx, imm_a, in_a, out_a), + transmute_scalar(bx, imm_b, in_b, out_b), ), _ => return None, }) @@ -1017,12 +1017,14 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } } -/// Transmutes one of the immediates from an [`OperandValue::Immediate`] -/// or an [`OperandValue::Pair`] to an immediate of the target type. +/// Transmutes a single scalar value `imm` from `from_scalar` to `to_scalar`. /// -/// `to_backend_ty` must be the *non*-immediate backend type (so it will be -/// `i8`, not `i1`, for `bool`-like types.) -pub(super) fn transmute_immediate<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( +/// This is expected to be in *immediate* form, as seen in [`OperandValue::Immediate`] +/// or [`OperandValue::Pair`] (so `i1` for bools, not `i8`, for example). +/// +/// ICEs if the passed-in `imm` is not a value of the expected type for +/// `from_scalar`, such as if it's a vector or a pair. +pub(super) fn transmute_scalar<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( bx: &mut Bx, mut imm: Bx::Value, from_scalar: abi::Scalar, @@ -1033,7 +1035,7 @@ pub(super) fn transmute_immediate<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( assert_ne!( bx.cx().type_kind(imm_ty), TypeKind::Vector, - "Vector type {imm_ty:?} not allowed in transmute_immediate {from_scalar:?} -> {to_scalar:?}" + "Vector type {imm_ty:?} not allowed in transmute_scalar {from_scalar:?} -> {to_scalar:?}" ); // While optimizations will remove no-op transmutes, they might still be From 4e615272bf5fc1331b5389c35893c1744dfc46f0 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Fri, 4 Jul 2025 12:12:07 -0700 Subject: [PATCH 11/20] Address PR feedback --- compiler/rustc_codegen_ssa/src/mir/operand.rs | 7 +- compiler/rustc_codegen_ssa/src/mir/rvalue.rs | 86 +++++++++++-------- tests/codegen/intrinsics/transmute.rs | 14 +-- 3 files changed, 59 insertions(+), 48 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/mir/operand.rs b/compiler/rustc_codegen_ssa/src/mir/operand.rs index 4b1c689a01069..568c54c657063 100644 --- a/compiler/rustc_codegen_ssa/src/mir/operand.rs +++ b/compiler/rustc_codegen_ssa/src/mir/operand.rs @@ -355,12 +355,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> { self.val } else if field.size == self.layout.size { assert_eq!(offset.bytes(), 0); - fx.codegen_transmute_operand(bx, *self, field).unwrap_or_else(|| { - bug!( - "Expected `codegen_transmute_operand` to handle equal-size \ - field {i:?} projection from {self:?} to {field:?}" - ) - }) + fx.codegen_transmute_operand(bx, *self, field) } else { let (in_scalar, imm) = match (self.val, self.layout.backend_repr) { // Extract a scalar component from a pair. diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs index 589405e885fbd..f7e8d5dcab267 100644 --- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs +++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs @@ -188,6 +188,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } } + /// Transmutes the `src` value to the destination type by writing it to `dst`. + /// + /// See also [`Self::codegen_transmute_operand`] for cases that can be done + /// without needing a pre-allocated place for the destination. fn codegen_transmute( &mut self, bx: &mut Bx, @@ -198,31 +202,36 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { assert!(src.layout.is_sized()); assert!(dst.layout.is_sized()); - if src.layout.size == dst.layout.size { + if src.layout.size != dst.layout.size + || src.layout.is_uninhabited() + || dst.layout.is_uninhabited() + { + // These cases are all UB to actually hit, so don't emit code for them. + // (The size mismatches are reachable via `transmute_unchecked`.) + // We can't use unreachable because that's a terminator, and we + // need something that can be in the middle of a basic block. + bx.assume(bx.cx().const_bool(false)) + } else { // Since in this path we have a place anyway, we can store or copy to it, // making sure we use the destination place's alignment even if the // source would normally have a higher one. src.val.store(bx, dst.val.with_type(src.layout)); - } else if src.layout.is_uninhabited() { - bx.unreachable() - } else { - // Since this is known statically and the input could have existed - // without already having hit UB, might as well trap for it, even - // though it's UB so we *could* also unreachable it. - bx.abort(); } } - /// Attempts to transmute an `OperandValue` to another `OperandValue`. + /// Transmutes an `OperandValue` to another `OperandValue`. /// - /// Returns `None` for cases that can't work in that framework, such as for - /// `Immediate`->`Ref` that needs an `alloca` to get the location. + /// This is supported only for cases where [`Self::rvalue_creates_operand`] + /// returns `true`, and will ICE otherwise. (In particular, anything that + /// would need to `alloca` in order to return a `PlaceValue` will ICE, + /// expecting those to go via [`Self::codegen_transmute`] instead where + /// the destination place is already allocated.) pub(crate) fn codegen_transmute_operand( &mut self, bx: &mut Bx, operand: OperandRef<'tcx, Bx::Value>, cast: TyAndLayout<'tcx>, - ) -> Option> { + ) -> OperandValue { // Check for transmutes that are always UB. if operand.layout.size != cast.size || operand.layout.is_uninhabited() @@ -236,17 +245,15 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // Because this transmute is UB, return something easy to generate, // since it's fine that later uses of the value are probably UB. - return Some(OperandValue::poison(bx, cast)); + return OperandValue::poison(bx, cast); } - Some(match (operand.val, operand.layout.backend_repr, cast.backend_repr) { + match (operand.val, operand.layout.backend_repr, cast.backend_repr) { _ if cast.is_zst() => OperandValue::ZeroSized, - (OperandValue::ZeroSized, _, _) => bug!(), - ( - OperandValue::Ref(source_place_val), - abi::BackendRepr::Memory { .. }, - abi::BackendRepr::Scalar(_) | abi::BackendRepr::ScalarPair(_, _), - ) => { + (_, _, abi::BackendRepr::Memory { .. }) => { + bug!("Cannot `codegen_transmute_operand` to non-ZST memory-ABI output {cast:?}"); + } + (OperandValue::Ref(source_place_val), abi::BackendRepr::Memory { .. }, _) => { assert_eq!(source_place_val.llextra, None); // The existing alignment is part of `source_place_val`, // so that alignment will be used, not `cast`'s. @@ -265,8 +272,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { transmute_scalar(bx, imm_a, in_a, out_a), transmute_scalar(bx, imm_b, in_b, out_b), ), - _ => return None, - }) + _ => bug!("Cannot `codegen_transmute_operand` {operand:?} to {cast:?}"), + } } /// Cast one of the immediates from an [`OperandValue::Immediate`] @@ -458,9 +465,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { }) } mir::CastKind::Transmute => { - self.codegen_transmute_operand(bx, operand, cast).unwrap_or_else(|| { - bug!("Unsupported transmute-as-operand of {operand:?} to {cast:?}"); - }) + self.codegen_transmute_operand(bx, operand, cast) } }; OperandRef { val, layout: cast } @@ -942,6 +947,15 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { OperandValue::Pair(val, of) } + /// Returns `true` if the `rvalue` can be computed into an [`OperandRef`], + /// rather than needing a full `PlaceRef` for the assignment destination. + /// + /// This is used by the [`super::analyze`] code to decide which MIR locals + /// can stay as SSA values (as opposed to generating `alloca` slots for them). + /// As such, some paths here return `true` even where the specific rvalue + /// will not actually take the operand path because the result type is such + /// that it always gets an `alloca`, but where it's not worth re-checking the + /// layout in this code when the right thing will happen anyway. pub(crate) fn rvalue_creates_operand(&self, rvalue: &mir::Rvalue<'tcx>, span: Span) -> bool { match *rvalue { mir::Rvalue::Cast(mir::CastKind::Transmute, ref operand, cast_ty) => { @@ -949,8 +963,13 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let cast_layout = self.cx.layout_of(self.monomorphize(cast_ty)); let operand_layout = self.cx.layout_of(self.monomorphize(operand_ty)); match (operand_layout.backend_repr, cast_layout.backend_repr) { - // If the input is in a place we can load immediates from there. - (abi::BackendRepr::Memory { .. }, abi::BackendRepr::Scalar(_) | abi::BackendRepr::ScalarPair(_, _)) => true, + // When the output will be in memory anyway, just use its place + // (instead of the operand path) unless it's the trivial ZST case. + (_, abi::BackendRepr::Memory { .. }) => cast_layout.is_zst(), + + // Otherwise (for a non-memory output) if the input is memory + // then we can just read the value from the place. + (abi::BackendRepr::Memory { .. }, _) => true, // When we have scalar immediates, we can only convert things // where the sizes match, to avoid endianness questions. @@ -959,18 +978,15 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { (abi::BackendRepr::ScalarPair(a0, a1), abi::BackendRepr::ScalarPair(b0, b1)) => a0.size(self.cx) == b0.size(self.cx) && a1.size(self.cx) == b1.size(self.cx), - // SIMD vectors don't work like normal immediates, - // so always send them through memory. - (abi::BackendRepr::SimdVector { .. }, _) | (_, abi::BackendRepr::SimdVector { .. }) => false, - - // When the output will be in memory anyway, just use its place - // (instead of the operand path) unless it's the trivial ZST case. - (_, abi::BackendRepr::Memory { .. }) => cast_layout.is_zst(), - // Mixing Scalars and ScalarPairs can get quite complicated when // padding and undef get involved, so leave that to the memory path. (abi::BackendRepr::Scalar(_), abi::BackendRepr::ScalarPair(_, _)) | (abi::BackendRepr::ScalarPair(_, _), abi::BackendRepr::Scalar(_)) => false, + + // SIMD vectors aren't worth the trouble of dealing with complex + // cases like from vectors of f32 to vectors of pointers or + // from fat pointers to vectors of u16. (See #143194 #110021 ...) + (abi::BackendRepr::SimdVector { .. }, _) | (_, abi::BackendRepr::SimdVector { .. }) => false, } } mir::Rvalue::Ref(..) | diff --git a/tests/codegen/intrinsics/transmute.rs b/tests/codegen/intrinsics/transmute.rs index 560ebcccdd021..e375724bc1bbd 100644 --- a/tests/codegen/intrinsics/transmute.rs +++ b/tests/codegen/intrinsics/transmute.rs @@ -29,28 +29,28 @@ pub struct Aggregate8(u8); // CHECK-LABEL: @check_bigger_size( #[no_mangle] pub unsafe fn check_bigger_size(x: u16) -> u32 { - // CHECK: call void @llvm.trap + // CHECK: call void @llvm.assume(i1 false) transmute_unchecked(x) } // CHECK-LABEL: @check_smaller_size( #[no_mangle] pub unsafe fn check_smaller_size(x: u32) -> u16 { - // CHECK: call void @llvm.trap + // CHECK: call void @llvm.assume(i1 false) transmute_unchecked(x) } // CHECK-LABEL: @check_smaller_array( #[no_mangle] pub unsafe fn check_smaller_array(x: [u32; 7]) -> [u32; 3] { - // CHECK: call void @llvm.trap + // CHECK: call void @llvm.assume(i1 false) transmute_unchecked(x) } // CHECK-LABEL: @check_bigger_array( #[no_mangle] pub unsafe fn check_bigger_array(x: [u32; 3]) -> [u32; 7] { - // CHECK: call void @llvm.trap + // CHECK: call void @llvm.assume(i1 false) transmute_unchecked(x) } @@ -73,9 +73,9 @@ pub unsafe fn check_to_empty_array(x: [u32; 5]) -> [u32; 0] { #[no_mangle] #[custom_mir(dialect = "runtime", phase = "optimized")] pub unsafe fn check_from_empty_array(x: [u32; 0]) -> [u32; 5] { - // CHECK-NOT: trap - // CHECK: call void @llvm.trap - // CHECK-NOT: trap + // CHECK-NOT: call + // CHECK: call void @llvm.assume(i1 false) + // CHECK-NOT: call mir! { { RET = CastTransmute(x); From 9ad98f78d4485f6f7f9615c1961bb75b281bfceb Mon Sep 17 00:00:00 2001 From: Kivooeo Date: Tue, 1 Jul 2025 00:41:51 +0500 Subject: [PATCH 12/20] moved tests --- .../{not-copy-closure.rs => closures/closure-no-copy-mut-env.rs} | 0 .../closure-no-copy-mut-env.stderr} | 0 tests/ui/{ => fn}/auxiliary/delegate_macro.rs | 0 .../fn-arg-count-mismatch-diagnostics.rs} | 0 .../fn-arg-count-mismatch-diagnostics.stderr} | 0 .../null-pointer-optimization.rs} | 0 .../null-pointer-size-optimization.rs} | 0 tests/ui/{nul-characters.rs => str/nul-char-equivalence.rs} | 0 .../trait-object-method-receiver-rules.rs} | 0 .../trait-object-method-receiver-rules.stderr} | 0 .../trait-object-mut-to-shared-coercion.rs} | 0 11 files changed, 0 insertions(+), 0 deletions(-) rename tests/ui/{not-copy-closure.rs => closures/closure-no-copy-mut-env.rs} (100%) rename tests/ui/{not-copy-closure.stderr => closures/closure-no-copy-mut-env.stderr} (100%) rename tests/ui/{ => fn}/auxiliary/delegate_macro.rs (100%) rename tests/ui/{not-enough-arguments.rs => fn/fn-arg-count-mismatch-diagnostics.rs} (100%) rename tests/ui/{not-enough-arguments.stderr => fn/fn-arg-count-mismatch-diagnostics.stderr} (100%) rename tests/ui/{nullable-pointer-iotareduction.rs => layout/null-pointer-optimization.rs} (100%) rename tests/ui/{nullable-pointer-size.rs => layout/null-pointer-size-optimization.rs} (100%) rename tests/ui/{nul-characters.rs => str/nul-char-equivalence.rs} (100%) rename tests/ui/{object-pointer-types.rs => traits/trait-object-method-receiver-rules.rs} (100%) rename tests/ui/{object-pointer-types.stderr => traits/trait-object-method-receiver-rules.stderr} (100%) rename tests/ui/{objects-coerce-freeze-borrored.rs => traits/trait-object-mut-to-shared-coercion.rs} (100%) diff --git a/tests/ui/not-copy-closure.rs b/tests/ui/closures/closure-no-copy-mut-env.rs similarity index 100% rename from tests/ui/not-copy-closure.rs rename to tests/ui/closures/closure-no-copy-mut-env.rs diff --git a/tests/ui/not-copy-closure.stderr b/tests/ui/closures/closure-no-copy-mut-env.stderr similarity index 100% rename from tests/ui/not-copy-closure.stderr rename to tests/ui/closures/closure-no-copy-mut-env.stderr diff --git a/tests/ui/auxiliary/delegate_macro.rs b/tests/ui/fn/auxiliary/delegate_macro.rs similarity index 100% rename from tests/ui/auxiliary/delegate_macro.rs rename to tests/ui/fn/auxiliary/delegate_macro.rs diff --git a/tests/ui/not-enough-arguments.rs b/tests/ui/fn/fn-arg-count-mismatch-diagnostics.rs similarity index 100% rename from tests/ui/not-enough-arguments.rs rename to tests/ui/fn/fn-arg-count-mismatch-diagnostics.rs diff --git a/tests/ui/not-enough-arguments.stderr b/tests/ui/fn/fn-arg-count-mismatch-diagnostics.stderr similarity index 100% rename from tests/ui/not-enough-arguments.stderr rename to tests/ui/fn/fn-arg-count-mismatch-diagnostics.stderr diff --git a/tests/ui/nullable-pointer-iotareduction.rs b/tests/ui/layout/null-pointer-optimization.rs similarity index 100% rename from tests/ui/nullable-pointer-iotareduction.rs rename to tests/ui/layout/null-pointer-optimization.rs diff --git a/tests/ui/nullable-pointer-size.rs b/tests/ui/layout/null-pointer-size-optimization.rs similarity index 100% rename from tests/ui/nullable-pointer-size.rs rename to tests/ui/layout/null-pointer-size-optimization.rs diff --git a/tests/ui/nul-characters.rs b/tests/ui/str/nul-char-equivalence.rs similarity index 100% rename from tests/ui/nul-characters.rs rename to tests/ui/str/nul-char-equivalence.rs diff --git a/tests/ui/object-pointer-types.rs b/tests/ui/traits/trait-object-method-receiver-rules.rs similarity index 100% rename from tests/ui/object-pointer-types.rs rename to tests/ui/traits/trait-object-method-receiver-rules.rs diff --git a/tests/ui/object-pointer-types.stderr b/tests/ui/traits/trait-object-method-receiver-rules.stderr similarity index 100% rename from tests/ui/object-pointer-types.stderr rename to tests/ui/traits/trait-object-method-receiver-rules.stderr diff --git a/tests/ui/objects-coerce-freeze-borrored.rs b/tests/ui/traits/trait-object-mut-to-shared-coercion.rs similarity index 100% rename from tests/ui/objects-coerce-freeze-borrored.rs rename to tests/ui/traits/trait-object-mut-to-shared-coercion.rs From b28806da237176468ab2afae42b51fe43ad416e6 Mon Sep 17 00:00:00 2001 From: Kivooeo Date: Tue, 1 Jul 2025 18:24:12 +0500 Subject: [PATCH 13/20] cleaned up some tests --- ...e-overflow.rs => alloc-shrink-oob-read.rs} | 10 +-- .../auto-trait-phantom-data-bounds.rs | 6 +- .../auto-trait-phantom-data-bounds.stderr | 18 ++--- .../binop/binop-evaluation-order-primitive.rs | 11 ++- tests/ui/coercion/basic-ptr-coercions.rs | 25 +++---- tests/ui/coercion/ptr-mutability-errors.rs | 3 +- .../ui/coercion/ptr-mutability-errors.stderr | 6 +- .../ui/io-checks/stdout-stderr-separation.rs | 3 + ...osure-parameter-type-inference-mismatch.rs | 26 +++++-- ...e-parameter-type-inference-mismatch.stderr | 28 +++---- ...type-error-diagnostic-in-complex-return.rs | 6 +- ...-error-diagnostic-in-complex-return.stderr | 2 +- tests/ui/parser/doc-comment-in-generic.rs | 10 ++- tests/ui/parser/raw/raw-string-literals.rs | Bin 848 -> 998 bytes .../pattern-ref-bindings-reassignment.rs | 26 ++++--- .../pattern-ref-bindings-reassignment.stderr | 5 +- .../print-calling-conventions.rs | 2 + tests/ui/std/fs-nul-byte-paths.rs | 20 +++-- .../nested-generic-traits-performance.rs | 69 +++++++++++------- 19 files changed, 168 insertions(+), 108 deletions(-) rename tests/ui/allocator/{allocator-reallocate-overflow.rs => alloc-shrink-oob-read.rs} (96%) diff --git a/tests/ui/allocator/allocator-reallocate-overflow.rs b/tests/ui/allocator/alloc-shrink-oob-read.rs similarity index 96% rename from tests/ui/allocator/allocator-reallocate-overflow.rs rename to tests/ui/allocator/alloc-shrink-oob-read.rs index 43810a469dfec..b9edfca3b7b51 100644 --- a/tests/ui/allocator/allocator-reallocate-overflow.rs +++ b/tests/ui/allocator/alloc-shrink-oob-read.rs @@ -1,13 +1,13 @@ +//! Sanity check for out-of-bounds read caused by copying the entire original buffer on shrink. +//! +//! Regression test for: + //@ run-pass -// alloc::heap::reallocate test. -// -// Ideally this would be revised to use no_std, but for now it serves -// well enough to reproduce (and illustrate) the bug from #16687. #![feature(allocator_api)] #![feature(slice_ptr_get)] -use std::alloc::{handle_alloc_error, Allocator, Global, Layout}; +use std::alloc::{Allocator, Global, Layout, handle_alloc_error}; use std::ptr::{self, NonNull}; fn main() { diff --git a/tests/ui/auto-traits/auto-trait-phantom-data-bounds.rs b/tests/ui/auto-traits/auto-trait-phantom-data-bounds.rs index 0172ca335c32a..6d1c4c87fad47 100644 --- a/tests/ui/auto-traits/auto-trait-phantom-data-bounds.rs +++ b/tests/ui/auto-traits/auto-trait-phantom-data-bounds.rs @@ -1,9 +1,9 @@ -// Ensure that auto trait checks `T` when it encounters a `PhantomData` field, instead of -// checking the `PhantomData` type itself (which almost always implements an auto trait). +//! Ensure that auto trait checks `T` when it encounters a `PhantomData` field, instead of +//! checking the `PhantomData` type itself (which almost always implements an auto trait). #![feature(auto_traits)] -use std::marker::{PhantomData}; +use std::marker::PhantomData; unsafe auto trait Zen {} diff --git a/tests/ui/auto-traits/auto-trait-phantom-data-bounds.stderr b/tests/ui/auto-traits/auto-trait-phantom-data-bounds.stderr index ffd4c3a0e1ad0..56c2e8ff257b7 100644 --- a/tests/ui/auto-traits/auto-trait-phantom-data-bounds.stderr +++ b/tests/ui/auto-traits/auto-trait-phantom-data-bounds.stderr @@ -1,5 +1,5 @@ error[E0277]: `T` cannot be shared between threads safely - --> $DIR/phantom-auto-trait.rs:21:12 + --> $DIR/auto-trait-phantom-data-bounds.rs:21:12 | LL | is_zen(x) | ------ ^ `T` cannot be shared between threads safely @@ -7,19 +7,19 @@ LL | is_zen(x) | required by a bound introduced by this call | note: required for `&T` to implement `Zen` - --> $DIR/phantom-auto-trait.rs:10:24 + --> $DIR/auto-trait-phantom-data-bounds.rs:10:24 | LL | unsafe impl<'a, T: 'a> Zen for &'a T where T: Sync {} | ^^^ ^^^^^ ---- unsatisfied trait bound introduced here note: required because it appears within the type `PhantomData<&T>` --> $SRC_DIR/core/src/marker.rs:LL:COL note: required because it appears within the type `Guard<'_, T>` - --> $DIR/phantom-auto-trait.rs:12:8 + --> $DIR/auto-trait-phantom-data-bounds.rs:12:8 | LL | struct Guard<'a, T: 'a> { | ^^^^^ note: required by a bound in `is_zen` - --> $DIR/phantom-auto-trait.rs:18:14 + --> $DIR/auto-trait-phantom-data-bounds.rs:18:14 | LL | fn is_zen(_: T) {} | ^^^ required by this bound in `is_zen` @@ -29,7 +29,7 @@ LL | fn not_sync(x: Guard) { | +++++++++++++++++++ error[E0277]: `T` cannot be shared between threads safely - --> $DIR/phantom-auto-trait.rs:26:12 + --> $DIR/auto-trait-phantom-data-bounds.rs:26:12 | LL | is_zen(x) | ------ ^ `T` cannot be shared between threads safely @@ -37,24 +37,24 @@ LL | is_zen(x) | required by a bound introduced by this call | note: required for `&T` to implement `Zen` - --> $DIR/phantom-auto-trait.rs:10:24 + --> $DIR/auto-trait-phantom-data-bounds.rs:10:24 | LL | unsafe impl<'a, T: 'a> Zen for &'a T where T: Sync {} | ^^^ ^^^^^ ---- unsatisfied trait bound introduced here note: required because it appears within the type `PhantomData<&T>` --> $SRC_DIR/core/src/marker.rs:LL:COL note: required because it appears within the type `Guard<'_, T>` - --> $DIR/phantom-auto-trait.rs:12:8 + --> $DIR/auto-trait-phantom-data-bounds.rs:12:8 | LL | struct Guard<'a, T: 'a> { | ^^^^^ note: required because it appears within the type `Nested>` - --> $DIR/phantom-auto-trait.rs:16:8 + --> $DIR/auto-trait-phantom-data-bounds.rs:16:8 | LL | struct Nested(T); | ^^^^^^ note: required by a bound in `is_zen` - --> $DIR/phantom-auto-trait.rs:18:14 + --> $DIR/auto-trait-phantom-data-bounds.rs:18:14 | LL | fn is_zen(_: T) {} | ^^^ required by this bound in `is_zen` diff --git a/tests/ui/binop/binop-evaluation-order-primitive.rs b/tests/ui/binop/binop-evaluation-order-primitive.rs index d988e2ed14fc4..33266d1c0478a 100644 --- a/tests/ui/binop/binop-evaluation-order-primitive.rs +++ b/tests/ui/binop/binop-evaluation-order-primitive.rs @@ -1,6 +1,15 @@ +//! Test evaluation order in binary operations with primitive types. + //@ run-pass fn main() { let x = Box::new(0); - assert_eq!(0, *x + { drop(x); let _ = Box::new(main); 0 }); + assert_eq!( + 0, + *x + { + drop(x); + let _ = Box::new(main); + 0 + } + ); } diff --git a/tests/ui/coercion/basic-ptr-coercions.rs b/tests/ui/coercion/basic-ptr-coercions.rs index 8cc4120328e45..4229d1fb2745f 100644 --- a/tests/ui/coercion/basic-ptr-coercions.rs +++ b/tests/ui/coercion/basic-ptr-coercions.rs @@ -1,29 +1,24 @@ -//@ run-pass - -#![allow(unused_variables)] -// Test coercions between pointers which don't do anything fancy like unsizing. +//! Tests basic pointer coercions +//@ run-pass pub fn main() { // &mut -> & let x: &mut isize = &mut 42; - let x: &isize = x; - - let x: &isize = &mut 42; + let _x: &isize = x; + let _x: &isize = &mut 42; // & -> *const let x: &isize = &42; - let x: *const isize = x; - - let x: *const isize = &42; + let _x: *const isize = x; + let _x: *const isize = &42; // &mut -> *const let x: &mut isize = &mut 42; - let x: *const isize = x; - - let x: *const isize = &mut 42; + let _x: *const isize = x; + let _x: *const isize = &mut 42; // *mut -> *const - let x: *mut isize = &mut 42; - let x: *const isize = x; + let _x: *mut isize = &mut 42; + let _x: *const isize = x; } diff --git a/tests/ui/coercion/ptr-mutability-errors.rs b/tests/ui/coercion/ptr-mutability-errors.rs index 2549bd6f134d7..391eaf0b91343 100644 --- a/tests/ui/coercion/ptr-mutability-errors.rs +++ b/tests/ui/coercion/ptr-mutability-errors.rs @@ -1,5 +1,4 @@ -// Test coercions between pointers which don't do anything fancy like unsizing. -// These are testing that we don't lose mutability when converting to raw pointers. +//! Tests that pointer coercions preserving mutability are enforced: //@ dont-require-annotations: NOTE diff --git a/tests/ui/coercion/ptr-mutability-errors.stderr b/tests/ui/coercion/ptr-mutability-errors.stderr index 8de41d2c38276..b4ded821c79cd 100644 --- a/tests/ui/coercion/ptr-mutability-errors.stderr +++ b/tests/ui/coercion/ptr-mutability-errors.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/ptr-coercion.rs:9:25 + --> $DIR/ptr-mutability-errors.rs:8:25 | LL | let x: *mut isize = x; | ---------- ^ types differ in mutability @@ -10,7 +10,7 @@ LL | let x: *mut isize = x; found raw pointer `*const isize` error[E0308]: mismatched types - --> $DIR/ptr-coercion.rs:15:25 + --> $DIR/ptr-mutability-errors.rs:14:25 | LL | let x: *mut isize = &42; | ---------- ^^^ types differ in mutability @@ -21,7 +21,7 @@ LL | let x: *mut isize = &42; found reference `&isize` error[E0308]: mismatched types - --> $DIR/ptr-coercion.rs:21:25 + --> $DIR/ptr-mutability-errors.rs:20:25 | LL | let x: *mut isize = x; | ---------- ^ types differ in mutability diff --git a/tests/ui/io-checks/stdout-stderr-separation.rs b/tests/ui/io-checks/stdout-stderr-separation.rs index 4b356e2fe6172..1bb3f16d3a1fb 100644 --- a/tests/ui/io-checks/stdout-stderr-separation.rs +++ b/tests/ui/io-checks/stdout-stderr-separation.rs @@ -1,3 +1,6 @@ +//! Test that print!/println! output to stdout and eprint!/eprintln! +//! output to stderr correctly. + //@ run-pass //@ needs-subprocess diff --git a/tests/ui/mismatched_types/closure-parameter-type-inference-mismatch.rs b/tests/ui/mismatched_types/closure-parameter-type-inference-mismatch.rs index d5f43df9d85c5..1cd41114bbdd5 100644 --- a/tests/ui/mismatched_types/closure-parameter-type-inference-mismatch.rs +++ b/tests/ui/mismatched_types/closure-parameter-type-inference-mismatch.rs @@ -1,13 +1,25 @@ +//! Test closure parameter type inference and type mismatch errors. +//! +//! Related to . + //@ dont-require-annotations: NOTE -fn let_in(x: T, f: F) where F: FnOnce(T) {} +fn let_in(x: T, f: F) +where + F: FnOnce(T), +{ +} fn main() { - let_in(3u32, |i| { assert!(i == 3i32); }); - //~^ ERROR mismatched types - //~| NOTE expected `u32`, found `i32` + let_in(3u32, |i| { + assert!(i == 3i32); + //~^ ERROR mismatched types + //~| NOTE expected `u32`, found `i32` + }); - let_in(3i32, |i| { assert!(i == 3u32); }); - //~^ ERROR mismatched types - //~| NOTE expected `i32`, found `u32` + let_in(3i32, |i| { + assert!(i == 3u32); + //~^ ERROR mismatched types + //~| NOTE expected `i32`, found `u32` + }); } diff --git a/tests/ui/mismatched_types/closure-parameter-type-inference-mismatch.stderr b/tests/ui/mismatched_types/closure-parameter-type-inference-mismatch.stderr index a6d673e61c698..c75e90ce4ef11 100644 --- a/tests/ui/mismatched_types/closure-parameter-type-inference-mismatch.stderr +++ b/tests/ui/mismatched_types/closure-parameter-type-inference-mismatch.stderr @@ -1,29 +1,29 @@ error[E0308]: mismatched types - --> $DIR/pptypedef.rs:6:37 + --> $DIR/closure-parameter-type-inference-mismatch.rs:15:22 | -LL | let_in(3u32, |i| { assert!(i == 3i32); }); - | - ^^^^ expected `u32`, found `i32` - | | - | expected because this is `u32` +LL | assert!(i == 3i32); + | - ^^^^ expected `u32`, found `i32` + | | + | expected because this is `u32` | help: change the type of the numeric literal from `i32` to `u32` | -LL - let_in(3u32, |i| { assert!(i == 3i32); }); -LL + let_in(3u32, |i| { assert!(i == 3u32); }); +LL - assert!(i == 3i32); +LL + assert!(i == 3u32); | error[E0308]: mismatched types - --> $DIR/pptypedef.rs:10:37 + --> $DIR/closure-parameter-type-inference-mismatch.rs:21:22 | -LL | let_in(3i32, |i| { assert!(i == 3u32); }); - | - ^^^^ expected `i32`, found `u32` - | | - | expected because this is `i32` +LL | assert!(i == 3u32); + | - ^^^^ expected `i32`, found `u32` + | | + | expected because this is `i32` | help: change the type of the numeric literal from `u32` to `i32` | -LL - let_in(3i32, |i| { assert!(i == 3u32); }); -LL + let_in(3i32, |i| { assert!(i == 3i32); }); +LL - assert!(i == 3u32); +LL + assert!(i == 3i32); | error: aborting due to 2 previous errors diff --git a/tests/ui/mismatched_types/type-error-diagnostic-in-complex-return.rs b/tests/ui/mismatched_types/type-error-diagnostic-in-complex-return.rs index 50f1fe873cb5f..6711d303eb3db 100644 --- a/tests/ui/mismatched_types/type-error-diagnostic-in-complex-return.rs +++ b/tests/ui/mismatched_types/type-error-diagnostic-in-complex-return.rs @@ -1,4 +1,8 @@ -fn unrelated() -> Result<(), std::string::ParseError> { // #57664 +//! Regression test for . +//! Checks that compiler doesn't get confused by `?` operator and complex +//! return types when reporting type mismatches. + +fn unrelated() -> Result<(), std::string::ParseError> { let x = 0; match x { diff --git a/tests/ui/mismatched_types/type-error-diagnostic-in-complex-return.stderr b/tests/ui/mismatched_types/type-error-diagnostic-in-complex-return.stderr index 34aaea5b70bbe..38392fe99d663 100644 --- a/tests/ui/mismatched_types/type-error-diagnostic-in-complex-return.stderr +++ b/tests/ui/mismatched_types/type-error-diagnostic-in-complex-return.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/point-to-type-err-cause-on-impl-trait-return-2.rs:9:41 + --> $DIR/type-error-diagnostic-in-complex-return.rs:13:41 | LL | let value: &bool = unsafe { &42 }; | ^^^ expected `&bool`, found `&{integer}` diff --git a/tests/ui/parser/doc-comment-in-generic.rs b/tests/ui/parser/doc-comment-in-generic.rs index 84abe875910cc..2596496763bac 100644 --- a/tests/ui/parser/doc-comment-in-generic.rs +++ b/tests/ui/parser/doc-comment-in-generic.rs @@ -1,9 +1,13 @@ +//! Tests correct parsing of doc comments on generic parameters in traits. +//! Checks that compiler doesn't panic when processing this. + //@ check-pass -// Check that it doesn't panic when `Input` gets its visibility checked. #![crate_type = "lib"] pub trait Layer< - /// Hello. + /// Documentation for generic parameter. Input, -> {} +> +{ +} diff --git a/tests/ui/parser/raw/raw-string-literals.rs b/tests/ui/parser/raw/raw-string-literals.rs index 230184032952effa5fe5fc30f3aef8bd5570a652..2272f268b3675960d76334943606ee19261a548e 100644 GIT binary patch delta 234 zcmYk0%?ZLl5QT}L;@;E-o+pVAayDKpz?0a(YF1fDcH_?YlY>};qyTHM0c-GV0oLIX zRGizqH{ZPXXuaC!I38f3hzWb?wA~Tb*5w4dhLZ;nJ8d?|G%F`F5+aVLa61zflIjh5 zW2{pV>$HqmE)&du7$H@eUV4&MR$^rhOKsq<$p5Ly%di(Fm|34uNcJJ-8|iCcuX9l8 msUz5Typ2aeN8mHnD!5ji#=Ti9RX6DWdC$gH)Ot7(C-DZY+etqF delta 88 zcmaFHeu2$WU*AEYs5DQvAhEcZOJ83hGd(ZAC{?#4Go@0uBryqHC?_*7H77MMy(DAf eE-l8%ZyD!LZe=<;c@m?@ $DIR/reassign-ref-mut.rs:12:5 + --> $DIR/pattern-ref-bindings-reassignment.rs:18:5 | LL | let &mut (ref a, ref mut b) = &mut one_two; | ----- first assignment to `a` +... LL | a = &three_four.0; | ^^^^^^^^^^^^^^^^^ cannot assign twice to immutable variable error[E0384]: cannot assign twice to immutable variable `b` - --> $DIR/reassign-ref-mut.rs:14:5 + --> $DIR/pattern-ref-bindings-reassignment.rs:22:5 | LL | let &mut (ref a, ref mut b) = &mut one_two; | --------- first assignment to `b` diff --git a/tests/ui/print-request/print-calling-conventions.rs b/tests/ui/print-request/print-calling-conventions.rs index 302ed088142d8..cefaa0d9b6fc0 100644 --- a/tests/ui/print-request/print-calling-conventions.rs +++ b/tests/ui/print-request/print-calling-conventions.rs @@ -1,2 +1,4 @@ +//! Test that `--print calling-conventions` outputs all supported calling conventions. + //@ compile-flags: --print calling-conventions //@ build-pass diff --git a/tests/ui/std/fs-nul-byte-paths.rs b/tests/ui/std/fs-nul-byte-paths.rs index 5c37980127db1..790123623474d 100644 --- a/tests/ui/std/fs-nul-byte-paths.rs +++ b/tests/ui/std/fs-nul-byte-paths.rs @@ -1,18 +1,22 @@ -//@ run-pass +//! Test that `std::fs` functions properly reject paths containing NUL bytes. +//@ run-pass #![allow(deprecated)] //@ ignore-wasm32 no cwd //@ ignore-sgx no files -use std::fs; -use std::io; +use std::{fs, io}; fn assert_invalid_input(on: &str, result: io::Result) { fn inner(on: &str, result: io::Result<()>) { match result { Ok(()) => panic!("{} didn't return an error on a path with NUL", on), - Err(e) => assert!(e.kind() == io::ErrorKind::InvalidInput, - "{} returned a strange {:?} on a path with NUL", on, e.kind()), + Err(e) => assert!( + e.kind() == io::ErrorKind::InvalidInput, + "{} returned a strange {:?} on a path with NUL", + on, + e.kind() + ), } } inner(on, result.map(drop)) @@ -43,6 +47,8 @@ fn main() { assert_invalid_input("remove_dir", fs::remove_dir("\0")); assert_invalid_input("remove_dir_all", fs::remove_dir_all("\0")); assert_invalid_input("read_dir", fs::read_dir("\0")); - assert_invalid_input("set_permissions", - fs::set_permissions("\0", fs::metadata(".").unwrap().permissions())); + assert_invalid_input( + "set_permissions", + fs::set_permissions("\0", fs::metadata(".").unwrap().permissions()), + ); } diff --git a/tests/ui/typeck/nested-generic-traits-performance.rs b/tests/ui/typeck/nested-generic-traits-performance.rs index 29c278171a61b..e029228c1b2ef 100644 --- a/tests/ui/typeck/nested-generic-traits-performance.rs +++ b/tests/ui/typeck/nested-generic-traits-performance.rs @@ -1,65 +1,82 @@ +//! Test that deeply nested generic traits with complex bounds +//! don't cause excessive memory usage during type checking. +//! +//! Regression test for . + //@ run-pass -// Regression test for #31849: the problem here was actually a performance -// cliff, but I'm adding the test for reference. pub trait Upcast { fn upcast(self) -> T; } -impl Upcast<(T1, T2)> for (S1,S2) - where S1: Upcast, - S2: Upcast, +impl Upcast<(T1, T2)> for (S1, S2) +where + S1: Upcast, + S2: Upcast, { - fn upcast(self) -> (T1, T2) { (self.0.upcast(), self.1.upcast()) } + fn upcast(self) -> (T1, T2) { + (self.0.upcast(), self.1.upcast()) + } } -impl Upcast<()> for () -{ - fn upcast(self) -> () { () } +impl Upcast<()> for () { + fn upcast(self) -> () { + () + } } pub trait ToStatic { type Static: 'static; - fn to_static(self) -> Self::Static where Self: Sized; + fn to_static(self) -> Self::Static + where + Self: Sized; } impl ToStatic for (T, U) - where T: ToStatic, - U: ToStatic +where + T: ToStatic, + U: ToStatic, { type Static = (T::Static, U::Static); - fn to_static(self) -> Self::Static { (self.0.to_static(), self.1.to_static()) } + fn to_static(self) -> Self::Static { + (self.0.to_static(), self.1.to_static()) + } } -impl ToStatic for () -{ +impl ToStatic for () { type Static = (); - fn to_static(self) -> () { () } + fn to_static(self) -> () { + () + } } - trait Factory { type Output; fn build(&self) -> Self::Output; } -impl Factory for (S, T) - where S: Factory, - T: Factory, - S::Output: ToStatic, - ::Static: Upcast, +impl Factory for (S, T) +where + S: Factory, + T: Factory, + S::Output: ToStatic, + ::Static: Upcast, { type Output = (S::Output, T::Output); - fn build(&self) -> Self::Output { (self.0.build().to_static().upcast(), self.1.build()) } + fn build(&self) -> Self::Output { + (self.0.build().to_static().upcast(), self.1.build()) + } } impl Factory for () { type Output = (); - fn build(&self) -> Self::Output { () } + fn build(&self) -> Self::Output { + () + } } fn main() { - // More parens, more time. - let it = ((((((((((),()),()),()),()),()),()),()),()),()); + // Deeply nested tuple to trigger the original performance issue + let it = ((((((((((), ()), ()), ()), ()), ()), ()), ()), ()), ()); it.build(); } From 7f2e37fc5cdca01d4e140921f59fad398862606d Mon Sep 17 00:00:00 2001 From: Kivooeo Date: Tue, 1 Jul 2025 02:07:53 +0500 Subject: [PATCH 14/20] moved & deleted tests opeq.rs was removed as duplicating test logic in other tests --- .../compound-assign-by-ref.rs} | 0 .../fnonce-call-twice-error.rs} | 0 .../fnonce-call-twice-error.stderr} | 0 tests/ui/opeq.rs | 17 ----------------- .../oom-panic-unwind.rs} | 0 .../copy-requires-all-fields-copy.rs} | 0 .../copy-requires-all-fields-copy.stderr} | 0 .../direct-self-reference-occurs-check.rs} | 0 .../direct-self-reference-occurs-check.stderr} | 0 .../enum-self-reference-occurs-check.rs} | 0 .../enum-self-reference-occurs-check.stderr} | 0 .../infinite-type-occurs-check.rs} | 0 .../infinite-type-occurs-check.stderr} | 0 13 files changed, 17 deletions(-) rename tests/ui/{op-assign-builtins-by-ref.rs => binop/compound-assign-by-ref.rs} (100%) rename tests/ui/{once-cant-call-twice-on-heap.rs => closures/fnonce-call-twice-error.rs} (100%) rename tests/ui/{once-cant-call-twice-on-heap.stderr => closures/fnonce-call-twice-error.stderr} (100%) delete mode 100644 tests/ui/opeq.rs rename tests/ui/{oom_unwind.rs => panics/oom-panic-unwind.rs} (100%) rename tests/ui/{opt-in-copy.rs => traits/copy-requires-all-fields-copy.rs} (100%) rename tests/ui/{opt-in-copy.stderr => traits/copy-requires-all-fields-copy.stderr} (100%) rename tests/ui/{occurs-check.rs => type-inference/direct-self-reference-occurs-check.rs} (100%) rename tests/ui/{occurs-check.stderr => type-inference/direct-self-reference-occurs-check.stderr} (100%) rename tests/ui/{occurs-check-3.rs => type-inference/enum-self-reference-occurs-check.rs} (100%) rename tests/ui/{occurs-check-3.stderr => type-inference/enum-self-reference-occurs-check.stderr} (100%) rename tests/ui/{occurs-check-2.rs => type-inference/infinite-type-occurs-check.rs} (100%) rename tests/ui/{occurs-check-2.stderr => type-inference/infinite-type-occurs-check.stderr} (100%) diff --git a/tests/ui/op-assign-builtins-by-ref.rs b/tests/ui/binop/compound-assign-by-ref.rs similarity index 100% rename from tests/ui/op-assign-builtins-by-ref.rs rename to tests/ui/binop/compound-assign-by-ref.rs diff --git a/tests/ui/once-cant-call-twice-on-heap.rs b/tests/ui/closures/fnonce-call-twice-error.rs similarity index 100% rename from tests/ui/once-cant-call-twice-on-heap.rs rename to tests/ui/closures/fnonce-call-twice-error.rs diff --git a/tests/ui/once-cant-call-twice-on-heap.stderr b/tests/ui/closures/fnonce-call-twice-error.stderr similarity index 100% rename from tests/ui/once-cant-call-twice-on-heap.stderr rename to tests/ui/closures/fnonce-call-twice-error.stderr diff --git a/tests/ui/opeq.rs b/tests/ui/opeq.rs deleted file mode 100644 index 956ea0684fa70..0000000000000 --- a/tests/ui/opeq.rs +++ /dev/null @@ -1,17 +0,0 @@ -//@ run-pass - -pub fn main() { - let mut x: isize = 1; - x *= 2; - println!("{}", x); - assert_eq!(x, 2); - x += 3; - println!("{}", x); - assert_eq!(x, 5); - x *= x; - println!("{}", x); - assert_eq!(x, 25); - x /= 5; - println!("{}", x); - assert_eq!(x, 5); -} diff --git a/tests/ui/oom_unwind.rs b/tests/ui/panics/oom-panic-unwind.rs similarity index 100% rename from tests/ui/oom_unwind.rs rename to tests/ui/panics/oom-panic-unwind.rs diff --git a/tests/ui/opt-in-copy.rs b/tests/ui/traits/copy-requires-all-fields-copy.rs similarity index 100% rename from tests/ui/opt-in-copy.rs rename to tests/ui/traits/copy-requires-all-fields-copy.rs diff --git a/tests/ui/opt-in-copy.stderr b/tests/ui/traits/copy-requires-all-fields-copy.stderr similarity index 100% rename from tests/ui/opt-in-copy.stderr rename to tests/ui/traits/copy-requires-all-fields-copy.stderr diff --git a/tests/ui/occurs-check.rs b/tests/ui/type-inference/direct-self-reference-occurs-check.rs similarity index 100% rename from tests/ui/occurs-check.rs rename to tests/ui/type-inference/direct-self-reference-occurs-check.rs diff --git a/tests/ui/occurs-check.stderr b/tests/ui/type-inference/direct-self-reference-occurs-check.stderr similarity index 100% rename from tests/ui/occurs-check.stderr rename to tests/ui/type-inference/direct-self-reference-occurs-check.stderr diff --git a/tests/ui/occurs-check-3.rs b/tests/ui/type-inference/enum-self-reference-occurs-check.rs similarity index 100% rename from tests/ui/occurs-check-3.rs rename to tests/ui/type-inference/enum-self-reference-occurs-check.rs diff --git a/tests/ui/occurs-check-3.stderr b/tests/ui/type-inference/enum-self-reference-occurs-check.stderr similarity index 100% rename from tests/ui/occurs-check-3.stderr rename to tests/ui/type-inference/enum-self-reference-occurs-check.stderr diff --git a/tests/ui/occurs-check-2.rs b/tests/ui/type-inference/infinite-type-occurs-check.rs similarity index 100% rename from tests/ui/occurs-check-2.rs rename to tests/ui/type-inference/infinite-type-occurs-check.rs diff --git a/tests/ui/occurs-check-2.stderr b/tests/ui/type-inference/infinite-type-occurs-check.stderr similarity index 100% rename from tests/ui/occurs-check-2.stderr rename to tests/ui/type-inference/infinite-type-occurs-check.stderr From 0f7a86bb2ac5b2ca57e5524127f9cbeb88f89a74 Mon Sep 17 00:00:00 2001 From: Kivooeo Date: Tue, 1 Jul 2025 02:09:12 +0500 Subject: [PATCH 15/20] cleaned up some tests --- tests/ui/binop/compound-assign-by-ref.rs | 5 ++--- tests/ui/closures/fnonce-call-twice-error.rs | 7 +++---- tests/ui/closures/fnonce-call-twice-error.stderr | 12 ++++++------ tests/ui/panics/oom-panic-unwind.rs | 2 ++ tests/ui/traits/copy-requires-all-fields-copy.rs | 2 ++ tests/ui/traits/copy-requires-all-fields-copy.stderr | 4 ++-- .../direct-self-reference-occurs-check.rs | 4 ++++ .../direct-self-reference-occurs-check.stderr | 2 +- .../enum-self-reference-occurs-check.rs | 11 ++++++++--- .../enum-self-reference-occurs-check.stderr | 2 +- .../ui/type-inference/infinite-type-occurs-check.rs | 5 ++++- .../type-inference/infinite-type-occurs-check.stderr | 2 +- 12 files changed, 36 insertions(+), 22 deletions(-) diff --git a/tests/ui/binop/compound-assign-by-ref.rs b/tests/ui/binop/compound-assign-by-ref.rs index 73788da92321c..e1f519a137fc9 100644 --- a/tests/ui/binop/compound-assign-by-ref.rs +++ b/tests/ui/binop/compound-assign-by-ref.rs @@ -1,9 +1,8 @@ +//! Test compound assignment operators with reference right-hand side. + //@ run-pass fn main() { - // test compound assignment operators with ref as right-hand side, - // for each operator, with various types as operands. - // test AddAssign { let mut x = 3i8; diff --git a/tests/ui/closures/fnonce-call-twice-error.rs b/tests/ui/closures/fnonce-call-twice-error.rs index 3fd8c5cadca98..1662b7bddaaee 100644 --- a/tests/ui/closures/fnonce-call-twice-error.rs +++ b/tests/ui/closures/fnonce-call-twice-error.rs @@ -1,16 +1,15 @@ -// Testing guarantees provided by once functions. -// This program would segfault if it were legal. +//! Test that `FnOnce` closures cannot be called twice. use std::sync::Arc; -fn foo(blk: F) { +fn foo(blk: F) { blk(); blk(); //~ ERROR use of moved value } fn main() { let x = Arc::new(true); - foo(move|| { + foo(move || { assert!(*x); drop(x); }); diff --git a/tests/ui/closures/fnonce-call-twice-error.stderr b/tests/ui/closures/fnonce-call-twice-error.stderr index 42697374115ca..51d8a33dcd796 100644 --- a/tests/ui/closures/fnonce-call-twice-error.stderr +++ b/tests/ui/closures/fnonce-call-twice-error.stderr @@ -1,18 +1,18 @@ error[E0382]: use of moved value: `blk` - --> $DIR/once-cant-call-twice-on-heap.rs:8:5 + --> $DIR/fnonce-call-twice-error.rs:7:5 | -LL | fn foo(blk: F) { - | --- move occurs because `blk` has type `F`, which does not implement the `Copy` trait +LL | fn foo(blk: F) { + | --- move occurs because `blk` has type `F`, which does not implement the `Copy` trait LL | blk(); | ----- `blk` moved due to this call LL | blk(); | ^^^ value used here after move | note: `FnOnce` closures can only be called once - --> $DIR/once-cant-call-twice-on-heap.rs:6:10 + --> $DIR/fnonce-call-twice-error.rs:5:11 | -LL | fn foo(blk: F) { - | ^^^^^^^^ `F` is made to be an `FnOnce` closure here +LL | fn foo(blk: F) { + | ^^^^^^^^ `F` is made to be an `FnOnce` closure here LL | blk(); | ----- this value implements `FnOnce`, which causes it to be moved when called diff --git a/tests/ui/panics/oom-panic-unwind.rs b/tests/ui/panics/oom-panic-unwind.rs index be5e63d430b70..5974ad91406f3 100644 --- a/tests/ui/panics/oom-panic-unwind.rs +++ b/tests/ui/panics/oom-panic-unwind.rs @@ -1,3 +1,5 @@ +//! Test that out-of-memory conditions trigger catchable panics with `-Z oom=panic`. + //@ compile-flags: -Z oom=panic //@ run-pass //@ no-prefer-dynamic diff --git a/tests/ui/traits/copy-requires-all-fields-copy.rs b/tests/ui/traits/copy-requires-all-fields-copy.rs index d0257b5745d8b..8c829a7382b3e 100644 --- a/tests/ui/traits/copy-requires-all-fields-copy.rs +++ b/tests/ui/traits/copy-requires-all-fields-copy.rs @@ -1,3 +1,5 @@ +//! Test that `Copy` cannot be implemented if any field doesn't implement `Copy`. + struct CantCopyThis; struct IWantToCopyThis { diff --git a/tests/ui/traits/copy-requires-all-fields-copy.stderr b/tests/ui/traits/copy-requires-all-fields-copy.stderr index 258ff16e6e485..1a9e1ada36637 100644 --- a/tests/ui/traits/copy-requires-all-fields-copy.stderr +++ b/tests/ui/traits/copy-requires-all-fields-copy.stderr @@ -1,5 +1,5 @@ error[E0204]: the trait `Copy` cannot be implemented for this type - --> $DIR/opt-in-copy.rs:7:15 + --> $DIR/copy-requires-all-fields-copy.rs:9:15 | LL | but_i_cant: CantCopyThis, | ------------------------ this field does not implement `Copy` @@ -8,7 +8,7 @@ LL | impl Copy for IWantToCopyThis {} | ^^^^^^^^^^^^^^^ error[E0204]: the trait `Copy` cannot be implemented for this type - --> $DIR/opt-in-copy.rs:19:15 + --> $DIR/copy-requires-all-fields-copy.rs:21:15 | LL | ButICant(CantCopyThisEither), | ------------------ this field does not implement `Copy` diff --git a/tests/ui/type-inference/direct-self-reference-occurs-check.rs b/tests/ui/type-inference/direct-self-reference-occurs-check.rs index 638b9b6d7e4c2..6e3d8251fc4f8 100644 --- a/tests/ui/type-inference/direct-self-reference-occurs-check.rs +++ b/tests/ui/type-inference/direct-self-reference-occurs-check.rs @@ -1,3 +1,7 @@ +//! Test that occurs check prevents direct self-reference in variable assignment. +//! +//! Regression test for . + fn main() { let f; f = Box::new(f); diff --git a/tests/ui/type-inference/direct-self-reference-occurs-check.stderr b/tests/ui/type-inference/direct-self-reference-occurs-check.stderr index ea7c541abc135..6c522ffac1f7a 100644 --- a/tests/ui/type-inference/direct-self-reference-occurs-check.stderr +++ b/tests/ui/type-inference/direct-self-reference-occurs-check.stderr @@ -1,5 +1,5 @@ error[E0275]: overflow assigning `Box<_>` to `_` - --> $DIR/occurs-check.rs:3:18 + --> $DIR/direct-self-reference-occurs-check.rs:7:18 | LL | f = Box::new(f); | ^ diff --git a/tests/ui/type-inference/enum-self-reference-occurs-check.rs b/tests/ui/type-inference/enum-self-reference-occurs-check.rs index 377a043daf3f6..2905868b8bfa9 100644 --- a/tests/ui/type-inference/enum-self-reference-occurs-check.rs +++ b/tests/ui/type-inference/enum-self-reference-occurs-check.rs @@ -1,11 +1,16 @@ -// From Issue #778 +//! Test that occurs check prevents infinite types with enum self-references. +//! +//! Regression test for . + +enum Clam { + A(T), +} -enum Clam { A(T) } fn main() { let c; c = Clam::A(c); //~^ ERROR overflow assigning `Clam<_>` to `_` match c { - Clam::A::(_) => { } + Clam::A::(_) => {} } } diff --git a/tests/ui/type-inference/enum-self-reference-occurs-check.stderr b/tests/ui/type-inference/enum-self-reference-occurs-check.stderr index eb05c94957c98..3239be51a1766 100644 --- a/tests/ui/type-inference/enum-self-reference-occurs-check.stderr +++ b/tests/ui/type-inference/enum-self-reference-occurs-check.stderr @@ -1,5 +1,5 @@ error[E0275]: overflow assigning `Clam<_>` to `_` - --> $DIR/occurs-check-3.rs:6:17 + --> $DIR/enum-self-reference-occurs-check.rs:11:17 | LL | c = Clam::A(c); | ^ diff --git a/tests/ui/type-inference/infinite-type-occurs-check.rs b/tests/ui/type-inference/infinite-type-occurs-check.rs index 9289a8e870a18..b353824e931d4 100644 --- a/tests/ui/type-inference/infinite-type-occurs-check.rs +++ b/tests/ui/type-inference/infinite-type-occurs-check.rs @@ -1,5 +1,8 @@ -fn main() { +//! Test that occurs check prevents infinite types during type inference. +//! +//! Regression test for . +fn main() { let f; let g; diff --git a/tests/ui/type-inference/infinite-type-occurs-check.stderr b/tests/ui/type-inference/infinite-type-occurs-check.stderr index 5f296967f30d8..9cb8bb917962e 100644 --- a/tests/ui/type-inference/infinite-type-occurs-check.stderr +++ b/tests/ui/type-inference/infinite-type-occurs-check.stderr @@ -1,5 +1,5 @@ error[E0275]: overflow assigning `Box<_>` to `_` - --> $DIR/occurs-check-2.rs:6:9 + --> $DIR/infinite-type-occurs-check.rs:9:9 | LL | g = f; | ^ From 46ce66ff5c1627230d43a5b5d41592186f79ebc5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Fri, 4 Jul 2025 21:24:42 +0200 Subject: [PATCH 16/20] Unify completion list between `x test tidy` and `x run generate-completions` --- src/bootstrap/src/core/build_steps/run.rs | 45 +++++++++++----------- src/bootstrap/src/core/build_steps/test.rs | 13 +++---- src/bootstrap/src/core/config/flags.rs | 10 ++++- 3 files changed, 36 insertions(+), 32 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/run.rs b/src/bootstrap/src/core/build_steps/run.rs index b3104ae05e884..b2293fdd9b523 100644 --- a/src/bootstrap/src/core/build_steps/run.rs +++ b/src/bootstrap/src/core/build_steps/run.rs @@ -5,6 +5,8 @@ use std::path::PathBuf; +use clap_complete::{Generator, shells}; + use crate::core::build_steps::dist::distdir; use crate::core::build_steps::test; use crate::core::build_steps::tool::{self, SourceType, Tool}; @@ -285,36 +287,35 @@ impl Step for GenerateWindowsSys { } } +/// Return tuples of (shell, file containing completions). +pub fn get_completion_paths(builder: &Builder<'_>) -> Vec<(&'static dyn Generator, PathBuf)> { + vec![ + (&shells::Bash as &'static dyn Generator, builder.src.join("src/etc/completions/x.py.sh")), + (&shells::Zsh, builder.src.join("src/etc/completions/x.py.zsh")), + (&shells::Fish, builder.src.join("src/etc/completions/x.py.fish")), + (&shells::PowerShell, builder.src.join("src/etc/completions/x.py.ps1")), + (&shells::Bash, builder.src.join("src/etc/completions/x.sh")), + (&shells::Zsh, builder.src.join("src/etc/completions/x.zsh")), + (&shells::Fish, builder.src.join("src/etc/completions/x.fish")), + (&shells::PowerShell, builder.src.join("src/etc/completions/x.ps1")), + ] +} + #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct GenerateCompletions; -macro_rules! generate_completions { - ( $( ( $shell:ident, $filename:expr ) ),* ) => { - $( - if let Some(comp) = get_completion($shell, &$filename) { - std::fs::write(&$filename, comp).expect(&format!("writing {} completion", stringify!($shell))); - } - )* - }; -} - impl Step for GenerateCompletions { type Output = (); /// Uses `clap_complete` to generate shell completions. fn run(self, builder: &Builder<'_>) { - use clap_complete::shells::{Bash, Fish, PowerShell, Zsh}; - - generate_completions!( - (Bash, builder.src.join("src/etc/completions/x.py.sh")), - (Zsh, builder.src.join("src/etc/completions/x.py.zsh")), - (Fish, builder.src.join("src/etc/completions/x.py.fish")), - (PowerShell, builder.src.join("src/etc/completions/x.py.ps1")), - (Bash, builder.src.join("src/etc/completions/x.sh")), - (Zsh, builder.src.join("src/etc/completions/x.zsh")), - (Fish, builder.src.join("src/etc/completions/x.fish")), - (PowerShell, builder.src.join("src/etc/completions/x.ps1")) - ); + for (shell, path) in get_completion_paths(builder) { + if let Some(comp) = get_completion(shell, &path) { + std::fs::write(&path, comp).unwrap_or_else(|e| { + panic!("writing completion into {} failed: {e:?}", path.display()) + }); + } + } } fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index 2d4d9e535981c..a5b7b22aba85f 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -8,12 +8,11 @@ use std::ffi::{OsStr, OsString}; use std::path::{Path, PathBuf}; use std::{env, fs, iter}; -use clap_complete::shells; - use crate::core::build_steps::compile::{Std, run_cargo}; use crate::core::build_steps::doc::DocumentationFormat; use crate::core::build_steps::gcc::{Gcc, add_cg_gcc_cargo_flags}; use crate::core::build_steps::llvm::get_llvm_version; +use crate::core::build_steps::run::get_completion_paths; use crate::core::build_steps::synthetic_targets::MirOptPanicAbortSyntheticTarget; use crate::core::build_steps::tool::{self, COMPILETEST_ALLOW_FEATURES, SourceType, Tool}; use crate::core::build_steps::toolstate::ToolState; @@ -1153,14 +1152,12 @@ HELP: to skip test's attempt to check tidiness, pass `--skip src/tools/tidy` to cmd.delay_failure().run(builder); builder.info("x.py completions check"); - let [bash, zsh, fish, powershell] = ["x.py.sh", "x.py.zsh", "x.py.fish", "x.py.ps1"] - .map(|filename| builder.src.join("src/etc/completions").join(filename)); + let completion_paths = get_completion_paths(builder); if builder.config.cmd.bless() { builder.ensure(crate::core::build_steps::run::GenerateCompletions); - } else if get_completion(shells::Bash, &bash).is_some() - || get_completion(shells::Fish, &fish).is_some() - || get_completion(shells::PowerShell, &powershell).is_some() - || crate::flags::get_completion(shells::Zsh, &zsh).is_some() + } else if completion_paths + .into_iter() + .any(|(shell, path)| get_completion(shell, &path).is_some()) { eprintln!( "x.py completions were changed; run `x.py run generate-completions` to update them" diff --git a/src/bootstrap/src/core/config/flags.rs b/src/bootstrap/src/core/config/flags.rs index 79275db648631..bfc06f90d4f26 100644 --- a/src/bootstrap/src/core/config/flags.rs +++ b/src/bootstrap/src/core/config/flags.rs @@ -6,6 +6,7 @@ use std::path::{Path, PathBuf}; use clap::{CommandFactory, Parser, ValueEnum}; +use clap_complete::Generator; #[cfg(feature = "tracing")] use tracing::instrument; @@ -644,7 +645,7 @@ impl Subcommand { /// Returns the shell completion for a given shell, if the result differs from the current /// content of `path`. If `path` does not exist, always returns `Some`. -pub fn get_completion(shell: G, path: &Path) -> Option { +pub fn get_completion(shell: &dyn Generator, path: &Path) -> Option { let mut cmd = Flags::command(); let current = if !path.exists() { String::new() @@ -662,7 +663,12 @@ pub fn get_completion(shell: G, path: &Path) -> Opt .expect("file name should be UTF-8") .rsplit_once('.') .expect("file name should have an extension"); - clap_complete::generate(shell, &mut cmd, bin_name, &mut buf); + + // We sort of replicate `clap_complete::generate` here, because we want to call it with + // `&dyn Generator`, but that function requires `G: Generator` instead. + cmd.set_bin_name(bin_name); + cmd.build(); + shell.generate(&cmd, &mut buf); if buf == current.as_bytes() { return None; } From 1a1f56174b10c877aa408700fd4dacb5d40df46d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Fri, 4 Jul 2025 21:26:21 +0200 Subject: [PATCH 17/20] Update completions --- src/etc/completions/x.fish | 2 +- src/etc/completions/x.ps1 | 2 +- src/etc/completions/x.zsh | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/etc/completions/x.fish b/src/etc/completions/x.fish index 46d18ac7dbcbc..69bd525a31221 100644 --- a/src/etc/completions/x.fish +++ b/src/etc/completions/x.fish @@ -293,7 +293,7 @@ complete -c x -n "__fish_x_using_subcommand doc" -l skip-std-check-if-no-downloa complete -c x -n "__fish_x_using_subcommand doc" -s h -l help -d 'Print help (see more with \'--help\')' complete -c x -n "__fish_x_using_subcommand test" -l test-args -d 'extra arguments to be passed for the test tool being used (e.g. libtest, compiletest or rustdoc)' -r complete -c x -n "__fish_x_using_subcommand test" -l compiletest-rustc-args -d 'extra options to pass the compiler when running compiletest tests' -r -complete -c x -n "__fish_x_using_subcommand test" -l extra-checks -d 'comma-separated list of other files types to check (accepts py, py:lint, py:fmt, shell)' -r +complete -c x -n "__fish_x_using_subcommand test" -l extra-checks -d 'comma-separated list of other files types to check (accepts py, py:lint, py:fmt, shell, shell:lint, cpp, cpp:fmt, spellcheck, spellcheck:fix)' -r complete -c x -n "__fish_x_using_subcommand test" -l compare-mode -d 'mode describing what file the actual ui output will be compared to' -r complete -c x -n "__fish_x_using_subcommand test" -l pass -d 'force {check,build,run}-pass tests to this mode' -r complete -c x -n "__fish_x_using_subcommand test" -l run -d 'whether to execute run-* tests' -r diff --git a/src/etc/completions/x.ps1 b/src/etc/completions/x.ps1 index 1ca00bb67dfed..7b142ba97ce51 100644 --- a/src/etc/completions/x.ps1 +++ b/src/etc/completions/x.ps1 @@ -339,7 +339,7 @@ Register-ArgumentCompleter -Native -CommandName 'x' -ScriptBlock { 'x;test' { [CompletionResult]::new('--test-args', '--test-args', [CompletionResultType]::ParameterName, 'extra arguments to be passed for the test tool being used (e.g. libtest, compiletest or rustdoc)') [CompletionResult]::new('--compiletest-rustc-args', '--compiletest-rustc-args', [CompletionResultType]::ParameterName, 'extra options to pass the compiler when running compiletest tests') - [CompletionResult]::new('--extra-checks', '--extra-checks', [CompletionResultType]::ParameterName, 'comma-separated list of other files types to check (accepts py, py:lint, py:fmt, shell)') + [CompletionResult]::new('--extra-checks', '--extra-checks', [CompletionResultType]::ParameterName, 'comma-separated list of other files types to check (accepts py, py:lint, py:fmt, shell, shell:lint, cpp, cpp:fmt, spellcheck, spellcheck:fix)') [CompletionResult]::new('--compare-mode', '--compare-mode', [CompletionResultType]::ParameterName, 'mode describing what file the actual ui output will be compared to') [CompletionResult]::new('--pass', '--pass', [CompletionResultType]::ParameterName, 'force {check,build,run}-pass tests to this mode') [CompletionResult]::new('--run', '--run', [CompletionResultType]::ParameterName, 'whether to execute run-* tests') diff --git a/src/etc/completions/x.zsh b/src/etc/completions/x.zsh index 00fb7d8e2ecbd..c495e8318ba46 100644 --- a/src/etc/completions/x.zsh +++ b/src/etc/completions/x.zsh @@ -338,7 +338,7 @@ _arguments "${_arguments_options[@]}" : \ _arguments "${_arguments_options[@]}" : \ '*--test-args=[extra arguments to be passed for the test tool being used (e.g. libtest, compiletest or rustdoc)]:ARGS:_default' \ '*--compiletest-rustc-args=[extra options to pass the compiler when running compiletest tests]:ARGS:_default' \ -'--extra-checks=[comma-separated list of other files types to check (accepts py, py\:lint, py\:fmt, shell)]:EXTRA_CHECKS:_default' \ +'--extra-checks=[comma-separated list of other files types to check (accepts py, py\:lint, py\:fmt, shell, shell\:lint, cpp, cpp\:fmt, spellcheck, spellcheck\:fix)]:EXTRA_CHECKS:_default' \ '--compare-mode=[mode describing what file the actual ui output will be compared to]:COMPARE MODE:_default' \ '--pass=[force {check,build,run}-pass tests to this mode]:check | build | run:_default' \ '--run=[whether to execute run-* tests]:auto | always | never:_default' \ From 62ada473281d86e9a7e19d2fe375171874f83cab Mon Sep 17 00:00:00 2001 From: Kivooeo Date: Tue, 1 Jul 2025 00:43:31 +0500 Subject: [PATCH 18/20] cleaned up some tests --- tests/ui/closures/closure-no-copy-mut-env.rs | 2 +- .../closures/closure-no-copy-mut-env.stderr | 4 +- .../fn/fn-arg-count-mismatch-diagnostics.rs | 9 ++-- .../fn-arg-count-mismatch-diagnostics.stderr | 20 ++++----- ....rs => null-pointer-optimization-sizes.rs} | 18 ++++++-- tests/ui/layout/null-pointer-optimization.rs | 44 ++++++++++--------- tests/ui/str/nul-char-equivalence.rs | 13 +++--- .../trait-object-method-receiver-rules.rs | 5 ++- .../trait-object-method-receiver-rules.stderr | 6 +-- .../trait-object-mut-to-shared-coercion.rs | 4 +- 10 files changed, 70 insertions(+), 55 deletions(-) rename tests/ui/layout/{null-pointer-size-optimization.rs => null-pointer-optimization-sizes.rs} (65%) diff --git a/tests/ui/closures/closure-no-copy-mut-env.rs b/tests/ui/closures/closure-no-copy-mut-env.rs index f6530f9a410aa..890e99c1ac79c 100644 --- a/tests/ui/closures/closure-no-copy-mut-env.rs +++ b/tests/ui/closures/closure-no-copy-mut-env.rs @@ -1,4 +1,4 @@ -// Check that closures do not implement `Copy` if their environment is not `Copy`. +//! Checks that closures do not implement `Copy` when they capture mutable references. fn main() { let mut a = 5; diff --git a/tests/ui/closures/closure-no-copy-mut-env.stderr b/tests/ui/closures/closure-no-copy-mut-env.stderr index 60cb135231306..1443366a47700 100644 --- a/tests/ui/closures/closure-no-copy-mut-env.stderr +++ b/tests/ui/closures/closure-no-copy-mut-env.stderr @@ -1,5 +1,5 @@ error[E0382]: use of moved value: `hello` - --> $DIR/not-copy-closure.rs:10:13 + --> $DIR/closure-no-copy-mut-env.rs:10:13 | LL | let b = hello; | ----- value moved here @@ -7,7 +7,7 @@ LL | let c = hello; | ^^^^^ value used here after move | note: closure cannot be moved more than once as it is not `Copy` due to moving the variable `a` out of its environment - --> $DIR/not-copy-closure.rs:6:9 + --> $DIR/closure-no-copy-mut-env.rs:6:9 | LL | a += 1; | ^ diff --git a/tests/ui/fn/fn-arg-count-mismatch-diagnostics.rs b/tests/ui/fn/fn-arg-count-mismatch-diagnostics.rs index ec660a1de81be..b2f80ba1bf62f 100644 --- a/tests/ui/fn/fn-arg-count-mismatch-diagnostics.rs +++ b/tests/ui/fn/fn-arg-count-mismatch-diagnostics.rs @@ -1,15 +1,15 @@ +//! Checks clean diagnostics for argument count mismatches without unrelated errors. +//! +//! `delegate!` part related: + //@ aux-build: delegate_macro.rs extern crate delegate_macro; use delegate_macro::delegate; -// Check that the only error msg we report is the -// mismatch between the # of params, and not other -// unrelated errors. fn foo(a: isize, b: isize, c: isize, d: isize) { panic!(); } -// Check that all arguments are shown in the error message, even if they're across multiple lines. fn bar(a: i32, b: i32, c: i32, d: i32, e: i32, f: i32) { println!("{}", a); println!("{}", b); @@ -37,6 +37,7 @@ struct Bar; impl Bar { fn foo(a: u8, b: u8) {} + fn bar() { delegate_local!(foo); delegate!(foo); diff --git a/tests/ui/fn/fn-arg-count-mismatch-diagnostics.stderr b/tests/ui/fn/fn-arg-count-mismatch-diagnostics.stderr index 908d0273bbecd..6af7671af03bf 100644 --- a/tests/ui/fn/fn-arg-count-mismatch-diagnostics.stderr +++ b/tests/ui/fn/fn-arg-count-mismatch-diagnostics.stderr @@ -1,5 +1,5 @@ error[E0061]: this function takes 2 arguments but 1 argument was supplied - --> $DIR/not-enough-arguments.rs:24:9 + --> $DIR/fn-arg-count-mismatch-diagnostics.rs:24:9 | LL | ::$method(8) | ^^^^^^^^^^^^^^^--- argument #2 of type `u8` is missing @@ -8,7 +8,7 @@ LL | delegate_local!(foo); | -------------------- in this macro invocation | note: associated function defined here - --> $DIR/not-enough-arguments.rs:39:8 + --> $DIR/fn-arg-count-mismatch-diagnostics.rs:39:8 | LL | fn foo(a: u8, b: u8) {} | ^^^ ----- @@ -19,20 +19,20 @@ LL | ::$method(8, /* u8 */) | ++++++++++ error[E0061]: this function takes 2 arguments but 1 argument was supplied - --> $DIR/not-enough-arguments.rs:42:9 + --> $DIR/fn-arg-count-mismatch-diagnostics.rs:43:9 | LL | delegate!(foo); | ^^^^^^^^^^^^^^ argument #2 of type `u8` is missing | note: associated function defined here - --> $DIR/not-enough-arguments.rs:39:8 + --> $DIR/fn-arg-count-mismatch-diagnostics.rs:39:8 | LL | fn foo(a: u8, b: u8) {} | ^^^ ----- = note: this error originates in the macro `delegate` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0061]: this function takes 2 arguments but 1 argument was supplied - --> $DIR/not-enough-arguments.rs:31:9 + --> $DIR/fn-arg-count-mismatch-diagnostics.rs:31:9 | LL | <$from>::$method(8) | ^^^^^^^^^^^^^^^^--- argument #2 of type `u8` is missing @@ -41,7 +41,7 @@ LL | delegate_from!(Bar, foo); | ------------------------ in this macro invocation | note: associated function defined here - --> $DIR/not-enough-arguments.rs:39:8 + --> $DIR/fn-arg-count-mismatch-diagnostics.rs:39:8 | LL | fn foo(a: u8, b: u8) {} | ^^^ ----- @@ -52,13 +52,13 @@ LL | <$from>::$method(8, /* u8 */) | ++++++++++ error[E0061]: this function takes 4 arguments but 3 arguments were supplied - --> $DIR/not-enough-arguments.rs:49:5 + --> $DIR/fn-arg-count-mismatch-diagnostics.rs:50:5 | LL | foo(1, 2, 3); | ^^^--------- argument #4 of type `isize` is missing | note: function defined here - --> $DIR/not-enough-arguments.rs:8:4 + --> $DIR/fn-arg-count-mismatch-diagnostics.rs:9:4 | LL | fn foo(a: isize, b: isize, c: isize, d: isize) { | ^^^ -------- @@ -68,13 +68,13 @@ LL | foo(1, 2, 3, /* isize */); | +++++++++++++ error[E0061]: this function takes 6 arguments but 3 arguments were supplied - --> $DIR/not-enough-arguments.rs:51:5 + --> $DIR/fn-arg-count-mismatch-diagnostics.rs:52:5 | LL | bar(1, 2, 3); | ^^^--------- three arguments of type `i32`, `i32`, and `i32` are missing | note: function defined here - --> $DIR/not-enough-arguments.rs:13:4 + --> $DIR/fn-arg-count-mismatch-diagnostics.rs:13:4 | LL | fn bar(a: i32, b: i32, c: i32, d: i32, e: i32, f: i32) { | ^^^ ------ ------ ------ diff --git a/tests/ui/layout/null-pointer-size-optimization.rs b/tests/ui/layout/null-pointer-optimization-sizes.rs similarity index 65% rename from tests/ui/layout/null-pointer-size-optimization.rs rename to tests/ui/layout/null-pointer-optimization-sizes.rs index aabdfa140dff6..95310b32e25f3 100644 --- a/tests/ui/layout/null-pointer-size-optimization.rs +++ b/tests/ui/layout/null-pointer-optimization-sizes.rs @@ -1,10 +1,20 @@ +//! null pointer optimization preserves type sizes. +//! +//! Verifies that Option has the same size as T for non-null pointer types, +//! and for custom enums that have a niche. + //@ run-pass +// Needs for Nothing variat in Enum #![allow(dead_code)] use std::mem; -enum E { Thing(isize, T), Nothing((), ((), ()), [i8; 0]) } +enum E { + Thing(isize, T), + Nothing((), ((), ()), [i8; 0]), +} + struct S(isize, T); // These are macros so we get useful assert messages. @@ -12,20 +22,20 @@ struct S(isize, T); macro_rules! check_option { ($T:ty) => { assert_eq!(mem::size_of::>(), mem::size_of::<$T>()); - } + }; } macro_rules! check_fancy { ($T:ty) => { assert_eq!(mem::size_of::>(), mem::size_of::>()); - } + }; } macro_rules! check_type { ($T:ty) => {{ check_option!($T); check_fancy!($T); - }} + }}; } pub fn main() { diff --git a/tests/ui/layout/null-pointer-optimization.rs b/tests/ui/layout/null-pointer-optimization.rs index 1b73164c9fc74..5e77c8d22ab22 100644 --- a/tests/ui/layout/null-pointer-optimization.rs +++ b/tests/ui/layout/null-pointer-optimization.rs @@ -1,27 +1,34 @@ -//@ run-pass +//! null pointer optimization with iota-reduction for enums. +//! +//! Iota-reduction is a rule from the Calculus of (Co-)Inductive Constructions: +//! "a destructor applied to an object built from a constructor behaves as expected". +//! See . +//! +//! This test verifies that null pointer optimization works correctly for both +//! Option and custom enums, accounting for pointers and regions. -// Iota-reduction is a rule in the Calculus of (Co-)Inductive Constructions, -// which "says that a destructor applied to an object built from a constructor -// behaves as expected". -- https://coq.inria.fr/doc/language/core/conversion.html#iota-reduction -// -// It's a little more complicated here, because of pointers and regions and -// trying to get assert failure messages that at least identify which case -// failed. +//@ run-pass #![allow(unpredictable_function_pointer_comparisons)] -enum E { Thing(isize, T), #[allow(dead_code)] Nothing((), ((), ()), [i8; 0]) } +enum E { + Thing(isize, T), + #[allow(dead_code)] + Nothing((), ((), ()), [i8; 0]), +} + impl E { fn is_none(&self) -> bool { match *self { E::Thing(..) => false, - E::Nothing(..) => true + E::Nothing(..) => true, } } + fn get_ref(&self) -> (isize, &T) { match *self { - E::Nothing(..) => panic!("E::get_ref(Nothing::<{}>)", stringify!(T)), - E::Thing(x, ref y) => (x, y) + E::Nothing(..) => panic!("E::get_ref(Nothing::<{}>)", stringify!(T)), + E::Thing(x, ref y) => (x, y), } } } @@ -36,7 +43,7 @@ macro_rules! check_option { let s_ = Some::<$T>(e); let $v = s_.as_ref().unwrap(); $chk - }} + }}; } macro_rules! check_fancy { @@ -48,11 +55,10 @@ macro_rules! check_fancy { let e = $e; let t_ = E::Thing::<$T>(23, e); match t_.get_ref() { - (23, $v) => { $chk } - _ => panic!("Thing::<{}>(23, {}).get_ref() != (23, _)", - stringify!($T), stringify!($e)) + (23, $v) => $chk, + _ => panic!("Thing::<{}>(23, {}).get_ref() != (23, _)", stringify!($T), stringify!($e)), } - }} + }}; } macro_rules! check_type { @@ -67,7 +73,5 @@ pub fn main() { check_type!(Box::new(18), Box); check_type!("foo".to_string(), String); check_type!(vec![20, 22], Vec); - check_type!(main, fn(), |pthing| { - assert_eq!(main as fn(), *pthing as fn()) - }); + check_type!(main, fn(), |pthing| assert_eq!(main as fn(), *pthing as fn())); } diff --git a/tests/ui/str/nul-char-equivalence.rs b/tests/ui/str/nul-char-equivalence.rs index eb83f440d3e03..2d4110de6812b 100644 --- a/tests/ui/str/nul-char-equivalence.rs +++ b/tests/ui/str/nul-char-equivalence.rs @@ -1,7 +1,8 @@ +//! Checks that different NUL character representations are equivalent in strings and chars. + //@ run-pass -pub fn main() -{ +pub fn main() { let all_nuls1 = "\0\x00\u{0}\u{0}"; let all_nuls2 = "\u{0}\u{0}\x00\0"; let all_nuls3 = "\u{0}\u{0}\x00\0"; @@ -17,11 +18,9 @@ pub fn main() assert_eq!(all_nuls3, all_nuls4); // all extracted characters in all_nuls are equivalent to each other - for c1 in all_nuls1.chars() - { - for c2 in all_nuls1.chars() - { - assert_eq!(c1,c2); + for c1 in all_nuls1.chars() { + for c2 in all_nuls1.chars() { + assert_eq!(c1, c2); } } diff --git a/tests/ui/traits/trait-object-method-receiver-rules.rs b/tests/ui/traits/trait-object-method-receiver-rules.rs index 760a50e5b7972..383e59c131a14 100644 --- a/tests/ui/traits/trait-object-method-receiver-rules.rs +++ b/tests/ui/traits/trait-object-method-receiver-rules.rs @@ -1,7 +1,8 @@ +//! Checks that method availability rules for trait objects depend on receiver type. + trait Foo { fn borrowed(&self); fn borrowed_mut(&mut self); - fn owned(self: Box); } @@ -20,7 +21,7 @@ fn borrowed_mut_receiver(x: &mut dyn Foo) { fn owned_receiver(x: Box) { x.borrowed(); x.borrowed_mut(); // See [1] - x.managed(); //~ ERROR no method named `managed` found + x.managed(); //~ ERROR no method named `managed` found x.owned(); } diff --git a/tests/ui/traits/trait-object-method-receiver-rules.stderr b/tests/ui/traits/trait-object-method-receiver-rules.stderr index 72b290f2ad9f8..83b61a2e6b52e 100644 --- a/tests/ui/traits/trait-object-method-receiver-rules.stderr +++ b/tests/ui/traits/trait-object-method-receiver-rules.stderr @@ -1,5 +1,5 @@ error[E0599]: no method named `owned` found for reference `&dyn Foo` in the current scope - --> $DIR/object-pointer-types.rs:11:7 + --> $DIR/trait-object-method-receiver-rules.rs:12:7 | LL | fn owned(self: Box); | --------- the method might not be found because of this arbitrary self type @@ -13,7 +13,7 @@ LL | x.to_owned(); | +++ error[E0599]: no method named `owned` found for mutable reference `&mut dyn Foo` in the current scope - --> $DIR/object-pointer-types.rs:17:7 + --> $DIR/trait-object-method-receiver-rules.rs:18:7 | LL | fn owned(self: Box); | --------- the method might not be found because of this arbitrary self type @@ -22,7 +22,7 @@ LL | x.owned(); | ^^^^^ method not found in `&mut dyn Foo` error[E0599]: no method named `managed` found for struct `Box<(dyn Foo + 'static)>` in the current scope - --> $DIR/object-pointer-types.rs:23:7 + --> $DIR/trait-object-method-receiver-rules.rs:24:7 | LL | x.managed(); | ^^^^^^^ method not found in `Box<(dyn Foo + 'static)>` diff --git a/tests/ui/traits/trait-object-mut-to-shared-coercion.rs b/tests/ui/traits/trait-object-mut-to-shared-coercion.rs index e122bb9938061..26b5cc6d2dfcb 100644 --- a/tests/ui/traits/trait-object-mut-to-shared-coercion.rs +++ b/tests/ui/traits/trait-object-mut-to-shared-coercion.rs @@ -1,6 +1,6 @@ -//@ run-pass -// Test that we can coerce an `@Object` to an `&Object` +//! Tests that coercion from `&mut dyn Trait` to `&dyn Trait` works correctly. +//@ run-pass trait Foo { fn foo(&self) -> usize; From 066a281f60fd5071a50cf15a28ed40f15bef7563 Mon Sep 17 00:00:00 2001 From: Kivooeo Date: Tue, 1 Jul 2025 19:28:38 +0500 Subject: [PATCH 19/20] cleaned up some tests --- .../reexport-test-harness-entry-point.rs | 3 +++ .../ui/const-ptr/pointer-address-stability.rs | 7 ++++-- .../ui/diagnostic-flags/error-format-short.rs | 3 +++ .../error-format-short.stderr | 4 ++-- tests/ui/drop/drop-once-on-move.rs | 8 ++++--- tests/ui/drop/drop-scope-exit.rs | 20 ++++++++++------ .../generics/trait-incorrect-generic-args.rs | 4 +++- .../trait-incorrect-generic-args.stderr | 12 +++++----- .../ui/io-checks/io-stdout-blocking-writes.rs | 24 +++++++++++-------- tests/ui/shadowed/primitive-type-shadowing.rs | 3 +++ tests/ui/shadowed/use-shadows-reexport.rs | 2 ++ .../ui/sized/recursive-type-infinite-size.rs | 17 +++++++++---- .../sized/recursive-type-infinite-size.stderr | 22 ++++++++++------- tests/ui/sized/sized-box-unsized-content.rs | 13 +++++----- tests/ui/sized/sized-reference-to-unsized.rs | 12 ++++++---- tests/ui/sync/atomic-types-not-copyable.rs | 8 ++++--- .../ui/sync/atomic-types-not-copyable.stderr | 8 +++---- .../target-feature-detection.rs | 19 +++++++++++---- .../traits/error-trait-object-from-string.rs | 5 ++-- 19 files changed, 126 insertions(+), 68 deletions(-) diff --git a/tests/ui/attributes/reexport-test-harness-entry-point.rs b/tests/ui/attributes/reexport-test-harness-entry-point.rs index f79828fc7d666..95765a719ed58 100644 --- a/tests/ui/attributes/reexport-test-harness-entry-point.rs +++ b/tests/ui/attributes/reexport-test-harness-entry-point.rs @@ -1,3 +1,6 @@ +//! Check that `#[reexport_test_harness_main]` correctly reexports the test harness entry point +//! and allows it to be called from within the code. + //@ run-pass //@ compile-flags:--test diff --git a/tests/ui/const-ptr/pointer-address-stability.rs b/tests/ui/const-ptr/pointer-address-stability.rs index e330a4853ce03..84a36e1ddf511 100644 --- a/tests/ui/const-ptr/pointer-address-stability.rs +++ b/tests/ui/const-ptr/pointer-address-stability.rs @@ -1,6 +1,9 @@ -//@ run-pass -// Issue #2040 +//! Check that taking the address of a stack variable with `&` +//! yields a stable and comparable pointer. +//! +//! Regression test for . +//@ run-pass pub fn main() { let foo: isize = 1; diff --git a/tests/ui/diagnostic-flags/error-format-short.rs b/tests/ui/diagnostic-flags/error-format-short.rs index 719870a04fb9b..4c793cd1b189b 100644 --- a/tests/ui/diagnostic-flags/error-format-short.rs +++ b/tests/ui/diagnostic-flags/error-format-short.rs @@ -1,3 +1,6 @@ +//! Check that compile errors are formatted in the "short" style +//! when `--error-format=short` is used. + //@ compile-flags: --error-format=short fn foo(_: u32) {} diff --git a/tests/ui/diagnostic-flags/error-format-short.stderr b/tests/ui/diagnostic-flags/error-format-short.stderr index 1a4a6d4df88e7..0a097e2f623c9 100644 --- a/tests/ui/diagnostic-flags/error-format-short.stderr +++ b/tests/ui/diagnostic-flags/error-format-short.stderr @@ -1,3 +1,3 @@ -$DIR/short-error-format.rs:6:9: error[E0308]: mismatched types: expected `u32`, found `String` -$DIR/short-error-format.rs:8:7: error[E0599]: no method named `salut` found for type `u32` in the current scope: method not found in `u32` +$DIR/error-format-short.rs:9:9: error[E0308]: mismatched types: expected `u32`, found `String` +$DIR/error-format-short.rs:11:7: error[E0599]: no method named `salut` found for type `u32` in the current scope: method not found in `u32` error: aborting due to 2 previous errors diff --git a/tests/ui/drop/drop-once-on-move.rs b/tests/ui/drop/drop-once-on-move.rs index ab42601690131..da01805807697 100644 --- a/tests/ui/drop/drop-once-on-move.rs +++ b/tests/ui/drop/drop-once-on-move.rs @@ -1,3 +1,7 @@ +//! Check that types not implementing `Copy` are moved, not copied, during assignment +//! operations, and their `Drop` implementation is called exactly once when the +//! value goes out of scope. + //@ run-pass #![allow(non_camel_case_types)] @@ -15,9 +19,7 @@ impl<'a> Drop for r<'a> { } fn r(i: &Cell) -> r<'_> { - r { - i: i - } + r { i } } pub fn main() { diff --git a/tests/ui/drop/drop-scope-exit.rs b/tests/ui/drop/drop-scope-exit.rs index 480cbe091a7a2..4d003fec7125e 100644 --- a/tests/ui/drop/drop-scope-exit.rs +++ b/tests/ui/drop/drop-scope-exit.rs @@ -1,31 +1,37 @@ +//! Check that the `Drop` implementation is called when a value goes out of scope. + //@ run-pass #![allow(non_camel_case_types)] use std::cell::Cell; struct shrinky_pointer<'a> { - i: &'a Cell, + i: &'a Cell, } impl<'a> Drop for shrinky_pointer<'a> { fn drop(&mut self) { - println!("Hello!"); self.i.set(self.i.get() - 1); + println!("Hello!"); + self.i.set(self.i.get() - 1); } } impl<'a> shrinky_pointer<'a> { - pub fn look_at(&self) -> isize { return self.i.get(); } + pub fn look_at(&self) -> isize { + return self.i.get(); + } } fn shrinky_pointer(i: &Cell) -> shrinky_pointer<'_> { - shrinky_pointer { - i: i - } + shrinky_pointer { i } } pub fn main() { let my_total = &Cell::new(10); - { let pt = shrinky_pointer(my_total); assert_eq!(pt.look_at(), 10); } + { + let pt = shrinky_pointer(my_total); + assert_eq!(pt.look_at(), 10); + } println!("my_total = {}", my_total.get()); assert_eq!(my_total.get(), 9); } diff --git a/tests/ui/generics/trait-incorrect-generic-args.rs b/tests/ui/generics/trait-incorrect-generic-args.rs index 627dfcc31986a..9715100b19cc7 100644 --- a/tests/ui/generics/trait-incorrect-generic-args.rs +++ b/tests/ui/generics/trait-incorrect-generic-args.rs @@ -1,5 +1,7 @@ +//! Check for compilation errors when a trait is used with an incorrect number of generic arguments. + fn main() { - trait Seq { } + trait Seq {} impl Seq for Vec { //~^ ERROR trait takes 0 generic arguments but 1 generic argument diff --git a/tests/ui/generics/trait-incorrect-generic-args.stderr b/tests/ui/generics/trait-incorrect-generic-args.stderr index 6e0d484d013d3..afc4ff03d949d 100644 --- a/tests/ui/generics/trait-incorrect-generic-args.stderr +++ b/tests/ui/generics/trait-incorrect-generic-args.stderr @@ -1,5 +1,5 @@ error[E0107]: trait takes 0 generic arguments but 1 generic argument was supplied - --> $DIR/seq-args.rs:4:13 + --> $DIR/trait-incorrect-generic-args.rs:6:13 | LL | impl Seq for Vec { | ^^^--- help: remove the unnecessary generics @@ -7,13 +7,13 @@ LL | impl Seq for Vec { | expected 0 generic arguments | note: trait defined here, with 0 generic parameters - --> $DIR/seq-args.rs:2:11 + --> $DIR/trait-incorrect-generic-args.rs:4:11 | -LL | trait Seq { } +LL | trait Seq {} | ^^^ error[E0107]: trait takes 0 generic arguments but 1 generic argument was supplied - --> $DIR/seq-args.rs:9:10 + --> $DIR/trait-incorrect-generic-args.rs:11:10 | LL | impl Seq for u32 { | ^^^------ help: remove the unnecessary generics @@ -21,9 +21,9 @@ LL | impl Seq for u32 { | expected 0 generic arguments | note: trait defined here, with 0 generic parameters - --> $DIR/seq-args.rs:2:11 + --> $DIR/trait-incorrect-generic-args.rs:4:11 | -LL | trait Seq { } +LL | trait Seq {} | ^^^ error: aborting due to 2 previous errors diff --git a/tests/ui/io-checks/io-stdout-blocking-writes.rs b/tests/ui/io-checks/io-stdout-blocking-writes.rs index 615530dcd47e4..1197b7f43be8d 100644 --- a/tests/ui/io-checks/io-stdout-blocking-writes.rs +++ b/tests/ui/io-checks/io-stdout-blocking-writes.rs @@ -1,10 +1,12 @@ +//! Check that writes to standard output are blocking, avoiding interleaving +//! even with concurrent writes from multiple threads. + //@ run-pass //@ needs-subprocess -use std::env; use std::io::prelude::*; use std::process::Command; -use std::thread; +use std::{env, thread}; const THREADS: usize = 20; const WRITES: usize = 100; @@ -33,14 +35,16 @@ fn parent() { } fn child() { - let threads = (0..THREADS).map(|_| { - thread::spawn(|| { - let buf = [b'a'; WRITE_SIZE]; - for _ in 0..WRITES { - write_all(&buf); - } + let threads = (0..THREADS) + .map(|_| { + thread::spawn(|| { + let buf = [b'a'; WRITE_SIZE]; + for _ in 0..WRITES { + write_all(&buf); + } + }) }) - }).collect::>(); + .collect::>(); for thread in threads { thread.join().unwrap(); @@ -63,8 +67,8 @@ fn write_all(buf: &[u8]) { fn write_all(buf: &[u8]) { use std::fs::File; use std::mem; - use std::os::windows::raw::*; use std::os::windows::prelude::*; + use std::os::windows::raw::*; const STD_OUTPUT_HANDLE: u32 = (-11i32) as u32; diff --git a/tests/ui/shadowed/primitive-type-shadowing.rs b/tests/ui/shadowed/primitive-type-shadowing.rs index 8cba2c1710b44..fdcb4246a82fc 100644 --- a/tests/ui/shadowed/primitive-type-shadowing.rs +++ b/tests/ui/shadowed/primitive-type-shadowing.rs @@ -1,3 +1,6 @@ +//! Check that a primitive type can be shadowed by a user-defined type, and the primitive type +//! can still be referenced using its fully qualified path (e.g., `core::primitive::bool`). + //@ check-pass mod bar { diff --git a/tests/ui/shadowed/use-shadows-reexport.rs b/tests/ui/shadowed/use-shadows-reexport.rs index 5ce4103b55970..d220e4b406be8 100644 --- a/tests/ui/shadowed/use-shadows-reexport.rs +++ b/tests/ui/shadowed/use-shadows-reexport.rs @@ -1,3 +1,5 @@ +//! Check that a local `use` declaration can shadow a re-exported item within the same module. + //@ run-pass #![allow(unused_imports)] diff --git a/tests/ui/sized/recursive-type-infinite-size.rs b/tests/ui/sized/recursive-type-infinite-size.rs index 766a5fa0de3dc..5cd8e89557393 100644 --- a/tests/ui/sized/recursive-type-infinite-size.rs +++ b/tests/ui/sized/recursive-type-infinite-size.rs @@ -1,7 +1,16 @@ -struct Baz { q: Option } -//~^ ERROR recursive types `Baz` and `Foo` have infinite size -struct Foo { q: Option } +//! Check for compilation errors when recursive types are defined in a way +//! that leads to an infinite size. -impl Foo { fn bar(&self) {} } +struct Baz { + //~^ ERROR recursive types `Baz` and `Foo` have infinite size + q: Option, +} +struct Foo { + q: Option, +} + +impl Foo { + fn bar(&self) {} +} fn main() {} diff --git a/tests/ui/sized/recursive-type-infinite-size.stderr b/tests/ui/sized/recursive-type-infinite-size.stderr index 21e54c12fedad..98ac36c4bb6bb 100644 --- a/tests/ui/sized/recursive-type-infinite-size.stderr +++ b/tests/ui/sized/recursive-type-infinite-size.stderr @@ -1,17 +1,23 @@ error[E0072]: recursive types `Baz` and `Foo` have infinite size - --> $DIR/sized-cycle-note.rs:1:1 + --> $DIR/recursive-type-infinite-size.rs:4:1 | -LL | struct Baz { q: Option } - | ^^^^^^^^^^ --- recursive without indirection +LL | struct Baz { + | ^^^^^^^^^^ LL | -LL | struct Foo { q: Option } - | ^^^^^^^^^^ --- recursive without indirection +LL | q: Option, + | --- recursive without indirection +LL | } +LL | struct Foo { + | ^^^^^^^^^^ +LL | q: Option, + | --- recursive without indirection | help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle | -LL ~ struct Baz { q: Option> } -LL | -LL ~ struct Foo { q: Option> } +LL ~ q: Option>, +LL | } +LL | struct Foo { +LL ~ q: Option>, | error: aborting due to 1 previous error diff --git a/tests/ui/sized/sized-box-unsized-content.rs b/tests/ui/sized/sized-box-unsized-content.rs index b35c0f91abd2c..9cc202a1582fd 100644 --- a/tests/ui/sized/sized-box-unsized-content.rs +++ b/tests/ui/sized/sized-box-unsized-content.rs @@ -1,10 +1,11 @@ +//! Check that `Box` is `Sized`, even when `T` is a dynamically sized type. + //@ run-pass #![allow(dead_code)] -// Possibly-dynamic size of typaram should be cleared at pointer boundary. - - -fn bar() { } -fn foo() { bar::>() } -pub fn main() { } +fn bar() {} +fn foo() { + bar::>() +} +pub fn main() {} diff --git a/tests/ui/sized/sized-reference-to-unsized.rs b/tests/ui/sized/sized-reference-to-unsized.rs index bd213c067db5d..ac2934d8fe646 100644 --- a/tests/ui/sized/sized-reference-to-unsized.rs +++ b/tests/ui/sized/sized-reference-to-unsized.rs @@ -1,9 +1,11 @@ +//! Check that a reference to a potentially unsized type (`&T`) is itself considered `Sized`. + //@ run-pass #![allow(dead_code)] -// Possibly-dynamic size of typaram should be cleared at pointer boundary. - -fn bar() { } -fn foo() { bar::<&T>() } -pub fn main() { } +fn bar() {} +fn foo() { + bar::<&T>() +} +pub fn main() {} diff --git a/tests/ui/sync/atomic-types-not-copyable.rs b/tests/ui/sync/atomic-types-not-copyable.rs index d85864ecac285..d96414676ee66 100644 --- a/tests/ui/sync/atomic-types-not-copyable.rs +++ b/tests/ui/sync/atomic-types-not-copyable.rs @@ -1,8 +1,10 @@ -// Issue #8380 +//! Check that atomic types from `std::sync::atomic` are not `Copy` +//! and cannot be moved out of a shared reference. +//! +//! Regression test for . - -use std::sync::atomic::*; use std::ptr; +use std::sync::atomic::*; fn main() { let x = AtomicBool::new(false); diff --git a/tests/ui/sync/atomic-types-not-copyable.stderr b/tests/ui/sync/atomic-types-not-copyable.stderr index 8c5d0b9609627..05103f5d8f265 100644 --- a/tests/ui/sync/atomic-types-not-copyable.stderr +++ b/tests/ui/sync/atomic-types-not-copyable.stderr @@ -1,5 +1,5 @@ error[E0507]: cannot move out of a shared reference - --> $DIR/std-uncopyable-atomics.rs:9:13 + --> $DIR/atomic-types-not-copyable.rs:11:13 | LL | let x = *&x; | ^^^ move occurs because value has type `std::sync::atomic::AtomicBool`, which does not implement the `Copy` trait @@ -11,7 +11,7 @@ LL + let x = &x; | error[E0507]: cannot move out of a shared reference - --> $DIR/std-uncopyable-atomics.rs:11:13 + --> $DIR/atomic-types-not-copyable.rs:13:13 | LL | let x = *&x; | ^^^ move occurs because value has type `std::sync::atomic::AtomicIsize`, which does not implement the `Copy` trait @@ -23,7 +23,7 @@ LL + let x = &x; | error[E0507]: cannot move out of a shared reference - --> $DIR/std-uncopyable-atomics.rs:13:13 + --> $DIR/atomic-types-not-copyable.rs:15:13 | LL | let x = *&x; | ^^^ move occurs because value has type `std::sync::atomic::AtomicUsize`, which does not implement the `Copy` trait @@ -35,7 +35,7 @@ LL + let x = &x; | error[E0507]: cannot move out of a shared reference - --> $DIR/std-uncopyable-atomics.rs:15:13 + --> $DIR/atomic-types-not-copyable.rs:17:13 | LL | let x = *&x; | ^^^ move occurs because value has type `std::sync::atomic::AtomicPtr`, which does not implement the `Copy` trait diff --git a/tests/ui/target-feature/target-feature-detection.rs b/tests/ui/target-feature/target-feature-detection.rs index a1894cc03dbc5..3404bfbe782ac 100644 --- a/tests/ui/target-feature/target-feature-detection.rs +++ b/tests/ui/target-feature/target-feature-detection.rs @@ -1,3 +1,6 @@ +//! Check that `cfg!(target_feature = "...")` correctly detects available CPU features, +//! specifically `sse2` on x86/x86_64 platforms, and correctly reports absent features. + //@ run-pass #![allow(stable_features)] @@ -10,17 +13,23 @@ fn main() { Ok(s) => { // Skip this tests on i586-unknown-linux-gnu where sse2 is disabled if s.contains("i586") { - return + return; } } Err(_) => return, } if cfg!(any(target_arch = "x86", target_arch = "x86_64")) { - assert!(cfg!(target_feature = "sse2"), - "SSE2 was not detected as available on an x86 platform"); + assert!( + cfg!(target_feature = "sse2"), + "SSE2 was not detected as available on an x86 platform" + ); } // check a negative case too -- certainly not enabled by default #[expect(unexpected_cfgs)] - { assert!(cfg!(not(target_feature = "ferris_wheel")), - "🎡 shouldn't be detected as available by default on any platform") }; + { + assert!( + cfg!(not(target_feature = "ferris_wheel")), + "🎡 shouldn't be detected as available by default on any platform" + ) + }; } diff --git a/tests/ui/traits/error-trait-object-from-string.rs b/tests/ui/traits/error-trait-object-from-string.rs index 9a7cd81ee0453..896f164a04d46 100644 --- a/tests/ui/traits/error-trait-object-from-string.rs +++ b/tests/ui/traits/error-trait-object-from-string.rs @@ -1,6 +1,7 @@ +//! Check that `String` and `&str` can be converted into `Box` and +//! `Box` trait objects + //@ run-pass -// Ensure that both `Box` and `Box` can be -// obtained from `String`. use std::error::Error; From 2d1aa582254e87b06c0805e6c3dcc4559bc7924c Mon Sep 17 00:00:00 2001 From: "Kurt Heiritz (pseudo)" Date: Thu, 26 Jun 2025 10:41:27 +0530 Subject: [PATCH 20/20] Make Rem const for floats --- library/core/src/ops/arith.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/ops/arith.rs b/library/core/src/ops/arith.rs index 7ffde233da342..e53c128efe069 100644 --- a/library/core/src/ops/arith.rs +++ b/library/core/src/ops/arith.rs @@ -627,7 +627,7 @@ macro_rules! rem_impl_float { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_ops", issue = "90080")] - impl Rem for $t { + impl const Rem for $t { type Output = $t; #[inline]