Auto merge of #139996 - matthiaskrgr:rollup-0nka2hw, r=matthiaskrgr

Rollup of 7 pull requests

Successful merges:

 - #138528 (deref patterns: implement implicit deref patterns)
 - #139393 (rustdoc-json: Output target feature information)
 - #139553 (sync::mpsc: prevent double free on `Drop`)
 - #139615 (Remove `name_or_empty`)
 - #139853 (Disable combining LLD with external llvm-config)
 - #139913 (rustdoc/clean: Fix lowering of fn params (fixes correctness & HIR vs. middle parity regressions))
 - #139942 (Ignore aix for tests/ui/erros/pic-linker.rs)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2025-04-18 13:49:17 +00:00
commit 191df20fca
114 changed files with 1839 additions and 642 deletions

View file

@ -0,0 +1,14 @@
//@ only-aarch64-apple-darwin
//@ is "$.target.triple" \"aarch64-apple-darwin\"
//@ is "$.target.target_features[?(@.name=='vh')].globally_enabled" true
//@ is "$.target.target_features[?(@.name=='sve')].globally_enabled" false
//@ has "$.target.target_features[?(@.name=='sve2')].implies_features" '["sve"]'
//@ is "$.target.target_features[?(@.name=='sve2')].unstable_feature_gate" null
// If this breaks due to stabilization, check rustc_target::target_features for a replacement
//@ is "$.target.target_features[?(@.name=='cssc')].unstable_feature_gate" '"aarch64_unstable_target_feature"'
//@ is "$.target.target_features[?(@.name=='v9a')].unstable_feature_gate" '"aarch64_ver_target_feature"'
// Ensure we don't look like x86-64
//@ !has "$.target.target_features[?(@.name=='avx2')]"

View file

@ -0,0 +1,10 @@
//@ only-aarch64
// If we enable SVE Bit Permute, we should see that it is enabled
//@ compile-flags: -Ctarget-feature=+sve2-bitperm
//@ is "$.target.target_features[?(@.name=='sve2-bitperm')].globally_enabled" true
// As well as its dependency chain
//@ is "$.target.target_features[?(@.name=='sve2')].globally_enabled" true
//@ is "$.target.target_features[?(@.name=='sve')].globally_enabled" true
//@ is "$.target.target_features[?(@.name=='neon')].globally_enabled" true

View file

@ -0,0 +1,14 @@
//@ only-aarch64-unknown-linux-gnu
//@ is "$.target.triple" \"aarch64-unknown-linux-gnu\"
//@ is "$.target.target_features[?(@.name=='neon')].globally_enabled" true
//@ is "$.target.target_features[?(@.name=='sve')].globally_enabled" false
//@ has "$.target.target_features[?(@.name=='sve2')].implies_features" '["sve"]'
//@ is "$.target.target_features[?(@.name=='sve2')].unstable_feature_gate" null
// If this breaks due to stabilization, check rustc_target::target_features for a replacement
//@ is "$.target.target_features[?(@.name=='cssc')].unstable_feature_gate" '"aarch64_unstable_target_feature"'
//@ is "$.target.target_features[?(@.name=='v9a')].unstable_feature_gate" '"aarch64_ver_target_feature"'
// Ensure we don't look like x86-64
//@ !has "$.target.target_features[?(@.name=='avx2')]"

View file

@ -0,0 +1,14 @@
//@ only-i686-pc-windows-msvc
//@ is "$.target.triple" \"i686-pc-windows-msvc\"
//@ is "$.target.target_features[?(@.name=='sse2')].globally_enabled" true
//@ is "$.target.target_features[?(@.name=='avx2')].globally_enabled" false
//@ has "$.target.target_features[?(@.name=='avx2')].implies_features" '["avx"]'
//@ is "$.target.target_features[?(@.name=='avx2')].unstable_feature_gate" null
// If this breaks due to stabilization, check rustc_target::target_features for a replacement
//@ is "$.target.target_features[?(@.name=='amx-tile')].unstable_feature_gate" '"x86_amx_intrinsics"'
//@ is "$.target.target_features[?(@.name=='x87')].unstable_feature_gate" '"x87_target_feature"'
// Ensure we don't look like aarch64
//@ !has "$.target.target_features[?(@.name=='sve2')]"

View file

@ -0,0 +1,14 @@
//@ only-i686-unknown-linux-gnu
//@ is "$.target.triple" \"i686-unknown-linux-gnu\"
//@ is "$.target.target_features[?(@.name=='sse2')].globally_enabled" true
//@ is "$.target.target_features[?(@.name=='avx2')].globally_enabled" false
//@ has "$.target.target_features[?(@.name=='avx2')].implies_features" '["avx"]'
//@ is "$.target.target_features[?(@.name=='avx2')].unstable_feature_gate" null
// If this breaks due to stabilization, check rustc_target::target_features for a replacement
//@ is "$.target.target_features[?(@.name=='amx-tile')].unstable_feature_gate" '"x86_amx_intrinsics"'
//@ is "$.target.target_features[?(@.name=='x87')].unstable_feature_gate" '"x87_target_feature"'
// Ensure we don't look like aarch64
//@ !has "$.target.target_features[?(@.name=='sve2')]"

View file

@ -0,0 +1,14 @@
//@ only-x86_64-apple-darwin
//@ is "$.target.triple" \"x86_64-apple-darwin\"
//@ is "$.target.target_features[?(@.name=='sse2')].globally_enabled" true
//@ is "$.target.target_features[?(@.name=='avx2')].globally_enabled" false
//@ has "$.target.target_features[?(@.name=='avx2')].implies_features" '["avx"]'
//@ is "$.target.target_features[?(@.name=='avx2')].unstable_feature_gate" null
// If this breaks due to stabilization, check rustc_target::target_features for a replacement
//@ is "$.target.target_features[?(@.name=='amx-tile')].unstable_feature_gate" '"x86_amx_intrinsics"'
//@ is "$.target.target_features[?(@.name=='x87')].unstable_feature_gate" '"x87_target_feature"'
// Ensure we don't look like aarch64
//@ !has "$.target.target_features[?(@.name=='sve2')]"

View file

@ -0,0 +1,14 @@
//@ only-x86_64-pc-windows-gnu
//@ is "$.target.triple" \"x86_64-pc-windows-gnu\"
//@ is "$.target.target_features[?(@.name=='sse2')].globally_enabled" true
//@ is "$.target.target_features[?(@.name=='avx2')].globally_enabled" false
//@ has "$.target.target_features[?(@.name=='avx2')].implies_features" '["avx"]'
//@ is "$.target.target_features[?(@.name=='avx2')].unstable_feature_gate" null
// If this breaks due to stabilization, check rustc_target::target_features for a replacement
//@ is "$.target.target_features[?(@.name=='amx-tile')].unstable_feature_gate" '"x86_amx_intrinsics"'
//@ is "$.target.target_features[?(@.name=='x87')].unstable_feature_gate" '"x87_target_feature"'
// Ensure we don't look like aarch64
//@ !has "$.target.target_features[?(@.name=='sve2')]"

View file

@ -0,0 +1,14 @@
//@ only-x86_64-pc-windows-msvc
//@ is "$.target.triple" \"x86_64-pc-windows-msvc\"
//@ is "$.target.target_features[?(@.name=='sse2')].globally_enabled" true
//@ is "$.target.target_features[?(@.name=='avx2')].globally_enabled" false
//@ has "$.target.target_features[?(@.name=='avx2')].implies_features" '["avx"]'
//@ is "$.target.target_features[?(@.name=='avx2')].unstable_feature_gate" null
// If this breaks due to stabilization, check rustc_target::target_features for a replacement
//@ is "$.target.target_features[?(@.name=='amx-tile')].unstable_feature_gate" '"x86_amx_intrinsics"'
//@ is "$.target.target_features[?(@.name=='x87')].unstable_feature_gate" '"x87_target_feature"'
// Ensure we don't look like aarch64
//@ !has "$.target.target_features[?(@.name=='sve2')]"

View file

@ -0,0 +1,10 @@
//@ only-x86_64
// If we enable AVX2, we should see that it is enabled
//@ compile-flags: -Ctarget-feature=+avx2
//@ is "$.target.target_features[?(@.name=='avx2')].globally_enabled" true
// As well as its dependency chain
//@ is "$.target.target_features[?(@.name=='avx')].globally_enabled" true
//@ is "$.target.target_features[?(@.name=='sse4.2')].globally_enabled" true
//@ is "$.target.target_features[?(@.name=='sse4.1')].globally_enabled" true

View file

@ -0,0 +1,14 @@
//@ only-x86_64-unknown-linux-gnu
//@ is "$.target.triple" \"x86_64-unknown-linux-gnu\"
//@ is "$.target.target_features[?(@.name=='sse2')].globally_enabled" true
//@ is "$.target.target_features[?(@.name=='avx2')].globally_enabled" false
//@ has "$.target.target_features[?(@.name=='avx2')].implies_features" '["avx"]'
//@ is "$.target.target_features[?(@.name=='avx2')].unstable_feature_gate" null
// If this breaks due to stabilization, check rustc_target::target_features for a replacement
//@ is "$.target.target_features[?(@.name=='amx-tile')].unstable_feature_gate" '"x86_amx_intrinsics"'
//@ is "$.target.target_features[?(@.name=='x87')].unstable_feature_gate" '"x87_target_feature"'
// Ensure we don't look like aarch64
//@ !has "$.target.target_features[?(@.name=='sve2')]"

View file

@ -0,0 +1,25 @@
// Test that we render the deprecated anonymous trait function parameters from Rust 2015 as
// underscores in order not to perpetuate it and for legibility.
//@ edition: 2015
#![expect(anonymous_parameters)]
// Check the "local case" (HIR cleaning) //
//@ has anon_fn_params/trait.Trait.html
pub trait Trait {
//@ has - '//*[@id="tymethod.required"]' 'fn required(_: Option<i32>, _: impl Fn(&str) -> bool)'
fn required(Option<i32>, impl Fn(&str) -> bool);
//@ has - '//*[@id="method.provided"]' 'fn provided(_: [i32; 2])'
fn provided([i32; 2]) {}
}
// Check the "extern case" (middle cleaning) //
//@ aux-build: ext-anon-fn-params.rs
extern crate ext_anon_fn_params;
//@ has anon_fn_params/trait.ExtTrait.html
//@ has - '//*[@id="tymethod.required"]' 'fn required(_: Option<i32>, _: impl Fn(&str) -> bool)'
//@ has - '//*[@id="method.provided"]' 'fn provided(_: [i32; 2])'
pub use ext_anon_fn_params::Trait as ExtTrait;

View file

@ -0,0 +1,13 @@
// Basic testing for associated functions (in traits, trait impls & inherent impls).
//@ has assoc_fns/trait.Trait.html
pub trait Trait {
//@ has - '//*[@id="tymethod.required"]' 'fn required(first: i32, second: &str)'
fn required(first: i32, second: &str);
//@ has - '//*[@id="method.provided"]' 'fn provided(only: ())'
fn provided(only: ()) {}
//@ has - '//*[@id="tymethod.params_are_unnamed"]' 'fn params_are_unnamed(_: i32, _: u32)'
fn params_are_unnamed(_: i32, _: u32);
}

View file

@ -0,0 +1,7 @@
//@ edition: 2015
#![expect(anonymous_parameters)]
pub trait Trait {
fn required(Option<i32>, impl Fn(&str) -> bool);
fn provided([i32; 2]) {}
}

View file

@ -9,4 +9,8 @@ pub use lib::foreigner;
extern "C" {
//@ has ffi/fn.another.html //pre 'pub unsafe extern "C" fn another(cold_as_ice: u32)'
pub fn another(cold_as_ice: u32);
//@ has ffi/fn.params_are_unnamed.html //pre \
// 'pub unsafe extern "C" fn params_are_unnamed(_: i32, _: u32)'
pub fn params_are_unnamed(_: i32, _: u32);
}

View file

@ -53,17 +53,17 @@ pub use default_generic_args::R2;
//@ has user/type.H0.html
// Check that we handle higher-ranked regions correctly:
//@ has - '//*[@class="rust item-decl"]//code' "fn(_: for<'a> fn(_: Re<'a>))"
//@ has - '//*[@class="rust item-decl"]//code' "fn(for<'a> fn(Re<'a>))"
pub use default_generic_args::H0;
//@ has user/type.H1.html
// Check that we don't conflate distinct universially quantified regions (#1):
//@ has - '//*[@class="rust item-decl"]//code' "for<'b> fn(_: for<'a> fn(_: Re<'a, &'b ()>))"
//@ has - '//*[@class="rust item-decl"]//code' "for<'b> fn(for<'a> fn(Re<'a, &'b ()>))"
pub use default_generic_args::H1;
//@ has user/type.H2.html
// Check that we don't conflate distinct universially quantified regions (#2):
//@ has - '//*[@class="rust item-decl"]//code' "for<'a> fn(_: for<'b> fn(_: Re<'a, &'b ()>))"
//@ has - '//*[@class="rust item-decl"]//code' "for<'a> fn(for<'b> fn(Re<'a, &'b ()>))"
pub use default_generic_args::H2;
//@ has user/type.P0.html
@ -86,7 +86,7 @@ pub use default_generic_args::A0;
// Demonstrates that we currently don't elide generic arguments that are alpha-equivalent to their
// respective generic parameter (after instantiation) for perf reasons (it would require us to
// create an inference context).
//@ has - '//*[@class="rust item-decl"]//code' "Alpha<for<'arbitrary> fn(_: &'arbitrary ())>"
//@ has - '//*[@class="rust item-decl"]//code' "Alpha<for<'arbitrary> fn(&'arbitrary ())>"
pub use default_generic_args::A1;
//@ has user/type.M0.html

View file

@ -2,11 +2,11 @@
// They should be rendered exactly as the user wrote it, i.e., in source order and with unused
// parameters present, not stripped.
//@ aux-crate:fn_type=fn-type.rs
//@ aux-crate:fn_ptr_ty=fn-ptr-ty.rs
//@ edition: 2021
#![crate_name = "user"]
//@ has user/type.F.html
//@ has - '//*[@class="rust item-decl"]//code' \
// "for<'z, 'a, '_unused> fn(_: &'z for<'b> fn(_: &'b str), _: &'a ()) -> &'a ();"
pub use fn_type::F;
// "for<'z, 'a, '_unused> fn(&'z for<'b> fn(&'b str), &'a ()) -> &'a ();"
pub use fn_ptr_ty::F;

View file

@ -29,7 +29,7 @@ pub use impl_trait_aux::func4;
//@ has impl_trait/fn.func5.html
//@ has - '//pre[@class="rust item-decl"]' "func5("
//@ has - '//pre[@class="rust item-decl"]' "_f: impl for<'any> Fn(&'any str, &'any str) -> bool + for<'r> Other<T<'r> = ()>,"
//@ has - '//pre[@class="rust item-decl"]' "_a: impl for<'beta, 'alpha, '_gamma> Auxiliary<'alpha, Item<'beta> = fn(_: &'beta ())>"
//@ has - '//pre[@class="rust item-decl"]' "_a: impl for<'beta, 'alpha, '_gamma> Auxiliary<'alpha, Item<'beta> = fn(&'beta ())>"
//@ !has - '//pre[@class="rust item-decl"]' 'where'
pub use impl_trait_aux::func5;

View file

@ -52,3 +52,6 @@ type TestAbiNeSign = (fn(i32), fn(u32)); //~ ERROR: ABIs are not compatible
#[rustc_abi(assert_eq)]
type TestAbiEqNonsense = (fn((str, str)), fn((str, str))); //~ ERROR: cannot be known at compilation time
#[rustc_abi("assert_eq")] //~ ERROR unrecognized argument
type Bad = u32;

View file

@ -906,6 +906,12 @@ LL | type TestAbiEqNonsense = (fn((str, str)), fn((str, str)));
= help: the trait `Sized` is not implemented for `str`
= note: only the last element of a tuple may have a dynamically sized type
error: unrecognized argument
--> $DIR/debug.rs:56:13
|
LL | #[rustc_abi("assert_eq")]
| ^^^^^^^^^^^
error: `#[rustc_abi]` can only be applied to function items, type aliases, and associated functions
--> $DIR/debug.rs:29:5
|
@ -1004,6 +1010,6 @@ error: fn_abi_of(assoc_test) = FnAbi {
LL | fn assoc_test(&self) { }
| ^^^^^^^^^^^^^^^^^^^^
error: aborting due to 11 previous errors
error: aborting due to 12 previous errors
For more information about this error, try `rustc --explain E0277`.

View file

@ -39,13 +39,17 @@
// Notably, `should_panic` is a `AttributeType::Normal` attribute that is checked separately.
#![deny(unused_attributes)]
struct Foo {
#[should_panic::skip]
//~^ ERROR failed to resolve
//~| ERROR `#[should_panic::skip]` only has an effect on functions
pub field: u8,
#[should_panic::a::b::c]
//~^ ERROR failed to resolve
//~| ERROR `#[should_panic::a::b::c]` only has an effect on functions
pub field2: u8,
}

View file

@ -1,21 +1,39 @@
error[E0433]: failed to resolve: use of unresolved module or unlinked crate `should_panic`
--> $DIR/check-builtin-attr-ice.rs:43:7
--> $DIR/check-builtin-attr-ice.rs:45:7
|
LL | #[should_panic::skip]
| ^^^^^^^^^^^^ use of unresolved module or unlinked crate `should_panic`
error[E0433]: failed to resolve: use of unresolved module or unlinked crate `should_panic`
--> $DIR/check-builtin-attr-ice.rs:47:7
--> $DIR/check-builtin-attr-ice.rs:50:7
|
LL | #[should_panic::a::b::c]
| ^^^^^^^^^^^^ use of unresolved module or unlinked crate `should_panic`
error[E0433]: failed to resolve: use of unresolved module or unlinked crate `deny`
--> $DIR/check-builtin-attr-ice.rs:55:7
--> $DIR/check-builtin-attr-ice.rs:59:7
|
LL | #[deny::skip]
| ^^^^ use of unresolved module or unlinked crate `deny`
error: aborting due to 3 previous errors
error: `#[should_panic::skip]` only has an effect on functions
--> $DIR/check-builtin-attr-ice.rs:45:5
|
LL | #[should_panic::skip]
| ^^^^^^^^^^^^^^^^^^^^^
|
note: the lint level is defined here
--> $DIR/check-builtin-attr-ice.rs:42:9
|
LL | #![deny(unused_attributes)]
| ^^^^^^^^^^^^^^^^^
error: `#[should_panic::a::b::c]` only has an effect on functions
--> $DIR/check-builtin-attr-ice.rs:50:5
|
LL | #[should_panic::a::b::c]
| ^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 5 previous errors
For more information about this error, try `rustc --explain E0433`.

View file

@ -10,11 +10,17 @@ note: the lint level is defined here
LL | #![cfg_attr(deny, deny(invalid_macro_export_arguments))]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: `not_local_inner_macros` isn't a valid `#[macro_export]` argument
error: invalid `#[macro_export]` argument
--> $DIR/invalid_macro_export_argument.rs:13:16
|
LL | #[macro_export(not_local_inner_macros)]
| ^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 2 previous errors
error: invalid `#[macro_export]` argument
--> $DIR/invalid_macro_export_argument.rs:33:16
|
LL | #[macro_export("blah")]
| ^^^^^^
error: aborting due to 3 previous errors

View file

@ -11,7 +11,7 @@ macro_rules! a {
}
#[macro_export(not_local_inner_macros)]
//[deny]~^ ERROR `not_local_inner_macros` isn't a valid `#[macro_export]` argument
//[deny]~^ ERROR invalid `#[macro_export]` argument
macro_rules! b {
() => ()
}
@ -30,4 +30,10 @@ macro_rules! e {
() => ()
}
#[macro_export("blah")]
//[deny]~^ ERROR invalid `#[macro_export]` argument
macro_rules! f {
() => ()
}
fn main() {}

View file

@ -38,3 +38,8 @@ fn valid() {}
#[no_sanitize(address)]
static VALID : i32 = 0;
#[no_sanitize("address")]
//~^ ERROR `#[no_sanitize(...)]` should be applied to a function
//~| ERROR invalid argument for `no_sanitize`
static VALID2 : i32 = 0;

View file

@ -59,5 +59,22 @@ LL | #[no_sanitize(address, memory)]
LL | static INVALID : i32 = 0;
| ------------------------- not a function
error: aborting due to 7 previous errors
error: `#[no_sanitize(...)]` should be applied to a function
--> $DIR/no-sanitize.rs:42:15
|
LL | #[no_sanitize("address")]
| ^^^^^^^^^
...
LL | static VALID2 : i32 = 0;
| ------------------------ not a function
error: invalid argument for `no_sanitize`
--> $DIR/no-sanitize.rs:42:15
|
LL | #[no_sanitize("address")]
| ^^^^^^^^^
|
= note: expected one of: `address`, `cfi`, `hwaddress`, `kcfi`, `memory`, `memtag`, `shadow-call-stack`, or `thread`
error: aborting due to 9 previous errors

View file

@ -5,6 +5,7 @@
//@ ignore-windows
//@ ignore-macos
//@ ignore-cross-compile
//@ ignore-aix
//@ compile-flags: -Clink-args=-Wl,-z,text
//@ run-pass

View file

@ -1,7 +1,9 @@
//@ revisions: explicit implicit
//@ run-pass
#![feature(deref_patterns)]
#![allow(incomplete_features)]
#[cfg(explicit)]
fn simple_vec(vec: Vec<u32>) -> u32 {
match vec {
deref!([]) => 100,
@ -13,6 +15,19 @@ fn simple_vec(vec: Vec<u32>) -> u32 {
}
}
#[cfg(implicit)]
fn simple_vec(vec: Vec<u32>) -> u32 {
match vec {
[] => 100,
[x] if x == 4 => x + 4,
[x] => x,
[1, x] => x + 200,
deref!(ref slice) => slice.iter().sum(),
_ => 2000,
}
}
#[cfg(explicit)]
fn nested_vec(vecvec: Vec<Vec<u32>>) -> u32 {
match vecvec {
deref!([]) => 0,
@ -24,6 +39,19 @@ fn nested_vec(vecvec: Vec<Vec<u32>>) -> u32 {
}
}
#[cfg(implicit)]
fn nested_vec(vecvec: Vec<Vec<u32>>) -> u32 {
match vecvec {
[] => 0,
[[x]] => x,
[[0, x] | [1, x]] => x,
[ref x] => x.iter().sum(),
[[], [1, x, y]] => y - x,
_ => 2000,
}
}
#[cfg(explicit)]
fn ref_mut(val: u32) -> u32 {
let mut b = Box::new(0u32);
match &mut b {
@ -37,6 +65,21 @@ fn ref_mut(val: u32) -> u32 {
*x
}
#[cfg(implicit)]
fn ref_mut(val: u32) -> u32 {
let mut b = Box::new((0u32,));
match &mut b {
(_x,) if false => unreachable!(),
(x,) => {
*x = val;
}
_ => unreachable!(),
}
let (x,) = &b else { unreachable!() };
*x
}
#[cfg(explicit)]
#[rustfmt::skip]
fn or_and_guard(tuple: (u32, u32)) -> u32 {
let mut sum = 0;
@ -48,6 +91,18 @@ fn or_and_guard(tuple: (u32, u32)) -> u32 {
sum
}
#[cfg(implicit)]
#[rustfmt::skip]
fn or_and_guard(tuple: (u32, u32)) -> u32 {
let mut sum = 0;
let b = Box::new(tuple);
match b {
(x, _) | (_, x) if { sum += x; false } => {},
_ => {},
}
sum
}
fn main() {
assert_eq!(simple_vec(vec![1]), 1);
assert_eq!(simple_vec(vec![1, 2]), 202);

View file

@ -1,8 +1,10 @@
//@ revisions: explicit implicit
//@ run-pass
// Test the execution of deref patterns.
#![feature(deref_patterns)]
#![allow(incomplete_features)]
#[cfg(explicit)]
fn branch(vec: Vec<u32>) -> u32 {
match vec {
deref!([]) => 0,
@ -12,6 +14,17 @@ fn branch(vec: Vec<u32>) -> u32 {
}
}
#[cfg(implicit)]
fn branch(vec: Vec<u32>) -> u32 {
match vec {
[] => 0,
[1, _, 3] => 1,
[2, ..] => 2,
_ => 1000,
}
}
#[cfg(explicit)]
fn nested(vec: Vec<Vec<u32>>) -> u32 {
match vec {
deref!([deref!([]), ..]) => 1,
@ -20,6 +33,15 @@ fn nested(vec: Vec<Vec<u32>>) -> u32 {
}
}
#[cfg(implicit)]
fn nested(vec: Vec<Vec<u32>>) -> u32 {
match vec {
[[], ..] => 1,
[[0, ..], [1, ..]] => 2,
_ => 1000,
}
}
fn main() {
assert!(matches!(Vec::<u32>::new(), deref!([])));
assert!(matches!(vec![1], deref!([1])));

View file

@ -21,4 +21,22 @@ fn cant_move_out_rc(rc: Rc<Struct>) -> Struct {
}
}
struct Container(Struct);
fn cant_move_out_box_implicit(b: Box<Container>) -> Struct {
match b {
//~^ ERROR: cannot move out of a shared reference
Container(x) => x,
_ => unreachable!(),
}
}
fn cant_move_out_rc_implicit(rc: Rc<Container>) -> Struct {
match rc {
//~^ ERROR: cannot move out of a shared reference
Container(x) => x,
_ => unreachable!(),
}
}
fn main() {}

View file

@ -32,6 +32,40 @@ help: consider borrowing the pattern binding
LL | deref!(ref x) => x,
| +++
error: aborting due to 2 previous errors
error[E0507]: cannot move out of a shared reference
--> $DIR/cant_move_out_of_pattern.rs:27:11
|
LL | match b {
| ^
LL |
LL | Container(x) => x,
| -
| |
| data moved here
| move occurs because `x` has type `Struct`, which does not implement the `Copy` trait
|
help: consider borrowing the pattern binding
|
LL | Container(ref x) => x,
| +++
error[E0507]: cannot move out of a shared reference
--> $DIR/cant_move_out_of_pattern.rs:35:11
|
LL | match rc {
| ^^
LL |
LL | Container(x) => x,
| -
| |
| data moved here
| move occurs because `x` has type `Struct`, which does not implement the `Copy` trait
|
help: consider borrowing the pattern binding
|
LL | Container(ref x) => x,
| +++
error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0507`.

View file

@ -11,6 +11,15 @@ fn main() {
assert_eq!(b.len(), 3);
f();
let v = vec![1, 2, 3];
let f = || {
// this should count as a borrow of `v` as a whole
let [.., x] = v else { unreachable!() };
assert_eq!(x, 3);
};
assert_eq!(v, [1, 2, 3]);
f();
let mut b = Box::new("aaa".to_string());
let mut f = || {
let deref!(ref mut s) = b else { unreachable!() };
@ -18,4 +27,22 @@ fn main() {
};
f();
assert_eq!(b.len(), 5);
let mut v = vec![1, 2, 3];
let mut f = || {
// this should count as a mutable borrow of `v` as a whole
let [.., ref mut x] = v else { unreachable!() };
*x = 4;
};
f();
assert_eq!(v, [1, 2, 4]);
let mut v = vec![1, 2, 3];
let mut f = || {
// here, `[.., x]` is adjusted by both an overloaded deref and a builtin deref
let [.., x] = &mut v else { unreachable!() };
*x = 4;
};
f();
assert_eq!(v, [1, 2, 4]);
}

View file

@ -11,4 +11,11 @@ fn main() {
deref!(false) => {}
_ => {},
}
match b {
true => {}
_ if { *b = true; false } => {}
//~^ ERROR cannot assign `*b` in match guard
false => {}
_ => {},
}
}

View file

@ -7,6 +7,15 @@ LL | deref!(true) => {}
LL | _ if { *b = true; false } => {}
| ^^^^^^^^^ cannot assign
error: aborting due to 1 previous error
error[E0510]: cannot assign `*b` in match guard
--> $DIR/fake_borrows.rs:16:16
|
LL | match b {
| - value is immutable in match guard
LL | true => {}
LL | _ if { *b = true; false } => {}
| ^^^^^^^^^ cannot assign
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0510`.

View file

@ -0,0 +1,19 @@
//! Test that we get an error about structural equality rather than a type error when attempting to
//! use const patterns of library pointer types. Currently there aren't any smart pointers that can
//! be used in constant patterns, but we still need to make sure we don't implicitly dereference the
//! scrutinee and end up with a type error; this would prevent us from reporting that only constants
//! supporting structural equality can be used as patterns.
#![feature(deref_patterns)]
#![allow(incomplete_features)]
const EMPTY: Vec<()> = Vec::new();
fn main() {
// FIXME(inline_const_pat): if `inline_const_pat` is reinstated, there should be a case here for
// inline const block patterns as well; they're checked differently than named constants.
match vec![()] {
EMPTY => {}
//~^ ERROR: constant of non-structural type `Vec<()>` in a pattern
_ => {}
}
}

View file

@ -0,0 +1,16 @@
error: constant of non-structural type `Vec<()>` in a pattern
--> $DIR/implicit-const-deref.rs:15:9
|
LL | const EMPTY: Vec<()> = Vec::new();
| -------------------- constant defined here
...
LL | EMPTY => {}
| ^^^^^ constant of non-structural type
--> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
|
= note: `Vec<()>` must be annotated with `#[derive(PartialEq)]` to be usable in patterns
|
= note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
error: aborting due to 1 previous error

View file

@ -0,0 +1,45 @@
//@ run-pass
//! Test that implicit deref patterns interact as expected with `Cow` constructor patterns.
#![feature(deref_patterns)]
#![allow(incomplete_features)]
use std::borrow::Cow;
fn main() {
let cow: Cow<'static, [u8]> = Cow::Borrowed(&[1, 2, 3]);
match cow {
[..] => {}
_ => unreachable!(),
}
match cow {
Cow::Borrowed(_) => {}
Cow::Owned(_) => unreachable!(),
}
match Box::new(&cow) {
Cow::Borrowed { 0: _ } => {}
Cow::Owned { 0: _ } => unreachable!(),
_ => unreachable!(),
}
let cow_of_cow: Cow<'_, Cow<'static, [u8]>> = Cow::Owned(cow);
match cow_of_cow {
[..] => {}
_ => unreachable!(),
}
// This matches on the outer `Cow` (the owned one).
match cow_of_cow {
Cow::Borrowed(_) => unreachable!(),
Cow::Owned(_) => {}
}
match Box::new(&cow_of_cow) {
Cow::Borrowed { 0: _ } => unreachable!(),
Cow::Owned { 0: _ } => {}
_ => unreachable!(),
}
}

View file

@ -0,0 +1,15 @@
// gate-test-deref_patterns
fn main() {
match Box::new(0) {
deref!(0) => {}
//~^ ERROR: use of unstable library feature `deref_patterns`: placeholder syntax for deref patterns
_ => {}
}
match Box::new(0) {
0 => {}
//~^ ERROR: mismatched types
_ => {}
}
}

View file

@ -0,0 +1,29 @@
error[E0658]: use of unstable library feature `deref_patterns`: placeholder syntax for deref patterns
--> $DIR/needs-gate.rs:5:9
|
LL | deref!(0) => {}
| ^^^^^
|
= note: see issue #87121 <https://github.com/rust-lang/rust/issues/87121> for more information
= help: add `#![feature(deref_patterns)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error[E0308]: mismatched types
--> $DIR/needs-gate.rs:11:9
|
LL | match Box::new(0) {
| ----------- this expression has type `Box<{integer}>`
LL | 0 => {}
| ^ expected `Box<{integer}>`, found integer
|
= note: expected struct `Box<{integer}>`
found type `{integer}`
help: consider dereferencing to access the inner value using the Deref trait
|
LL | match *Box::new(0) {
| +
error: aborting due to 2 previous errors
Some errors have detailed explanations: E0308, E0658.
For more information about an error, try `rustc --explain E0308`.

View file

@ -0,0 +1,23 @@
//! Test that implicit deref patterns respect the recursion limit
#![feature(deref_patterns)]
#![allow(incomplete_features)]
#![recursion_limit = "8"]
use std::ops::Deref;
struct Cyclic;
impl Deref for Cyclic {
type Target = Cyclic;
fn deref(&self) -> &Cyclic {
&Cyclic
}
}
fn main() {
match &Box::new(Cyclic) {
() => {}
//~^ ERROR: reached the recursion limit while auto-dereferencing `Cyclic`
//~| ERROR: the trait bound `Cyclic: DerefPure` is not satisfied
_ => {}
}
}

View file

@ -0,0 +1,18 @@
error[E0055]: reached the recursion limit while auto-dereferencing `Cyclic`
--> $DIR/recursion-limit.rs:18:9
|
LL | () => {}
| ^^ deref recursion limit reached
|
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "16"]` attribute to your crate (`recursion_limit`)
error[E0277]: the trait bound `Cyclic: DerefPure` is not satisfied
--> $DIR/recursion-limit.rs:18:9
|
LL | () => {}
| ^^ the trait `DerefPure` is not implemented for `Cyclic`
error: aborting due to 2 previous errors
Some errors have detailed explanations: E0055, E0277.
For more information about an error, try `rustc --explain E0055`.

View file

@ -8,10 +8,19 @@ fn main() {
deref!(x) => {}
_ => {}
}
match &mut vec![1] {
[x] => {}
_ => {}
}
match &mut Rc::new(1) {
deref!(x) => {}
//~^ ERROR the trait bound `Rc<{integer}>: DerefMut` is not satisfied
_ => {}
}
match &mut Rc::new((1,)) {
(x,) => {}
//~^ ERROR the trait bound `Rc<({integer},)>: DerefMut` is not satisfied
_ => {}
}
}

View file

@ -8,13 +8,19 @@ LL | #![feature(deref_patterns)]
= note: `#[warn(incomplete_features)]` on by default
error[E0277]: the trait bound `Rc<{integer}>: DerefMut` is not satisfied
--> $DIR/ref-mut.rs:13:9
--> $DIR/ref-mut.rs:17:9
|
LL | deref!(x) => {}
| ^^^^^^^^^ the trait `DerefMut` is not implemented for `Rc<{integer}>`
|
= note: this error originates in the macro `deref` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 1 previous error; 1 warning emitted
error[E0277]: the trait bound `Rc<({integer},)>: DerefMut` is not satisfied
--> $DIR/ref-mut.rs:22:9
|
LL | (x,) => {}
| ^^^^ the trait `DerefMut` is not implemented for `Rc<({integer},)>`
error: aborting due to 2 previous errors; 1 warning emitted
For more information about this error, try `rustc --explain E0277`.

View file

@ -10,26 +10,32 @@ fn main() {
let vec: Vec<u32> = Vec::new();
match vec {
deref!([..]) => {}
[..] => {}
_ => {}
}
match Box::new(true) {
deref!(true) => {}
true => {}
_ => {}
}
match &Box::new(true) {
deref!(true) => {}
true => {}
_ => {}
}
match &Rc::new(0) {
deref!(1..) => {}
1.. => {}
_ => {}
}
let _: &Struct = match &Rc::new(Struct) {
deref!(x) => x,
Struct => &Struct,
_ => unreachable!(),
};
let _: &[Struct] = match &Rc::new(vec![Struct]) {
deref!(deref!(x)) => x,
[Struct] => &[Struct],
_ => unreachable!(),
};
}

View file

@ -7,11 +7,22 @@ fn main() {
match "foo".to_string() {
deref!("foo") => {}
//~^ ERROR: mismatched types
"foo" => {}
//~^ ERROR: mismatched types
_ => {}
}
match &"foo".to_string() {
deref!("foo") => {}
//~^ ERROR: mismatched types
"foo" => {}
//~^ ERROR: mismatched types
_ => {}
}
// Make sure we don't try implicitly dereferncing any ADT.
match Some(0) {
Ok(0) => {}
//~^ ERROR: mismatched types
_ => {}
}
}

View file

@ -7,13 +7,45 @@ LL | deref!("foo") => {}
| ^^^^^ expected `str`, found `&str`
error[E0308]: mismatched types
--> $DIR/typeck_fail.rs:13:16
--> $DIR/typeck_fail.rs:10:9
|
LL | match "foo".to_string() {
| ----------------- this expression has type `String`
...
LL | "foo" => {}
| ^^^^^ expected `String`, found `&str`
error[E0308]: mismatched types
--> $DIR/typeck_fail.rs:15:16
|
LL | match &"foo".to_string() {
| ------------------ this expression has type `&String`
LL | deref!("foo") => {}
| ^^^^^ expected `str`, found `&str`
error: aborting due to 2 previous errors
error[E0308]: mismatched types
--> $DIR/typeck_fail.rs:17:9
|
LL | match &"foo".to_string() {
| ------------------ this expression has type `&String`
...
LL | "foo" => {}
| ^^^^^ expected `&String`, found `&str`
|
= note: expected reference `&String`
found reference `&'static str`
error[E0308]: mismatched types
--> $DIR/typeck_fail.rs:24:9
|
LL | match Some(0) {
| ------- this expression has type `Option<{integer}>`
LL | Ok(0) => {}
| ^^^^^ expected `Option<{integer}>`, found `Result<_, _>`
|
= note: expected enum `Option<{integer}>`
found enum `Result<_, _>`
error: aborting due to 5 previous errors
For more information about this error, try `rustc --explain E0308`.

View file

@ -0,0 +1,21 @@
#![feature(deref_patterns)]
#![allow(incomplete_features)]
struct MyPointer;
impl std::ops::Deref for MyPointer {
type Target = ();
fn deref(&self) -> &() {
&()
}
}
fn main() {
// Test that we get a trait error if a user attempts implicit deref pats on their own impls.
// FIXME(deref_patterns): there should be a special diagnostic for missing `DerefPure`.
match MyPointer {
() => {}
//~^ the trait bound `MyPointer: DerefPure` is not satisfied
_ => {}
}
}

View file

@ -0,0 +1,9 @@
error[E0277]: the trait bound `MyPointer: DerefPure` is not satisfied
--> $DIR/unsatisfied-bounds.rs:17:9
|
LL | () => {}
| ^^ the trait `DerefPure` is not implemented for `MyPointer`
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0277`.