Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions tests/ui/splat/run-splat.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
//! Check that splat codegen works for simple cases.
//@ run-pass
//@ check-run-results
#![feature(splat, tuple_trait)]
#![expect(incomplete_features)]

use std::marker::Tuple;

struct Foo;

trait MethodArgs: Tuple {
fn call_method(self, this: &Foo);
}

impl Foo {
fn method(&self, #[splat] args: impl MethodArgs) {
args.call_method(self)
}
}

impl MethodArgs for (i32, String) {
fn call_method(self, _this: &Foo) {
dbg!(self.1, self.0);
}
}

impl MethodArgs for (f64,) {
fn call_method(self, _this: &Foo) {
dbg!(self.0);
}
}

fn main() {
let foo = Foo;
foo.method(42, "hello splat".to_string());
foo.method(3.141);
}
3 changes: 3 additions & 0 deletions tests/ui/splat/run-splat.run.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[$DIR/run-splat.rs:23:9] self.1 = "hello splat"
[$DIR/run-splat.rs:23:9] self.0 = 42
[$DIR/run-splat.rs:29:9] self.0 = 3.141
29 changes: 27 additions & 2 deletions tests/ui/splat/splat-dyn-asref-tuple-fail.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,36 @@
#![feature(splat)]
#![feature(tuple_trait)]

fn dyn_asref_splat<T>(#[splat] _t: &dyn AsRef<T>) where T: std::marker::Tuple {}
//~^ ERROR cannot use splat attribute
// Strip binders and their lifetime numbers from error messages
//@ normalize-stderr: "&.*value: (.*), bound_vars: .*" -> "$1"

// FIXME(splat): Some errors are reported on the callee, but they would be more ergonomic on the
// caller as well
fn dyn_asref_splat<T>(#[splat] _t: &dyn AsRef<T>)
//~^ ERROR cannot use splat attribute; the splatted argument type must be a tuple or unit, not a
//~| ERROR cannot use splat attribute; the splatted argument type must be a tuple or unit, not a
//~| ERROR cannot use splat attribute; the splatted argument type must be a tuple or unit, not a
//~| ERROR cannot use splat attribute; the splatted argument type must be a tuple or unit, not a
where
T: std::marker::Tuple,
{
}

fn main() {
// These error patterns are reported on the function definition, but we can't check for two
// strings in the same error message
let s: String = "hello".to_owned();
dyn_asref_splat::<String>(&s);
//~^ ERROR `String` is not a tuple
//@regex-error-pattern: type must be a tuple or unit, not a .* Trait\(.*AsRef<.*String>\)

dyn_asref_splat(&s);
//@regex-error-pattern: type must be a tuple or unit, not a .* Trait\(.*AsRef<_>\)

let t = (1u8, 2f32);
dyn_asref_splat::<(u8, f32)>(&t);
//@regex-error-pattern: type must be a tuple or unit, not a .* Trait\(.*AsRef<\(u8, f32\)>\)

dyn_asref_splat(&t);
//@regex-error-pattern: type must be a tuple or unit, not a .* Trait\(.*AsRef<_>\)
}
46 changes: 38 additions & 8 deletions tests/ui/splat/splat-dyn-asref-tuple-fail.stderr
Original file line number Diff line number Diff line change
@@ -1,24 +1,54 @@
error[E0277]: cannot use splat attribute; the splatted argument type must be a tuple or unit, not a &'?3 dyn [Binder { value: Trait(std::convert::AsRef<std::string::String>), bound_vars: [] }] + '?3 (&'?3 dyn [Binder { value: Trait(std::convert::AsRef<std::string::String>), bound_vars: [] }] + '?3)
--> $DIR/splat-dyn-asref-tuple-fail.rs:7:36
error[E0277]: cannot use splat attribute; the splatted argument type must be a tuple or unit, not a Trait(std::convert::AsRef<std::string::String>)
--> $DIR/splat-dyn-asref-tuple-fail.rs:12:36
|
LL | fn dyn_asref_splat<T>(#[splat] _t: &dyn AsRef<T>) where T: std::marker::Tuple {}
LL | fn dyn_asref_splat<T>(#[splat] _t: &dyn AsRef<T>)
| ^^^^^^^^^^^^^
...
LL | dyn_asref_splat::<String>(&s);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0277]: `String` is not a tuple
--> $DIR/splat-dyn-asref-tuple-fail.rs:12:23
--> $DIR/splat-dyn-asref-tuple-fail.rs:26:23
|
LL | dyn_asref_splat::<String>(&s);
| ^^^^^^ the nightly-only, unstable trait `std::marker::Tuple` is not implemented for `String`
|
note: required by a bound in `dyn_asref_splat`
--> $DIR/splat-dyn-asref-tuple-fail.rs:7:60
--> $DIR/splat-dyn-asref-tuple-fail.rs:18:8
|
LL | fn dyn_asref_splat<T>(#[splat] _t: &dyn AsRef<T>) where T: std::marker::Tuple {}
| ^^^^^^^^^^^^^^^^^^ required by this bound in `dyn_asref_splat`
LL | fn dyn_asref_splat<T>(#[splat] _t: &dyn AsRef<T>)
| --------------- required by a bound in this function
...
LL | T: std::marker::Tuple,
| ^^^^^^^^^^^^^^^^^^ required by this bound in `dyn_asref_splat`

error[E0277]: cannot use splat attribute; the splatted argument type must be a tuple or unit, not a Trait(std::convert::AsRef<_>)
--> $DIR/splat-dyn-asref-tuple-fail.rs:12:36
|
LL | fn dyn_asref_splat<T>(#[splat] _t: &dyn AsRef<T>)
| ^^^^^^^^^^^^^
...
LL | dyn_asref_splat(&s);
| ^^^^^^^^^^^^^^^^^^^

error[E0277]: cannot use splat attribute; the splatted argument type must be a tuple or unit, not a Trait(std::convert::AsRef<(u8, f32)>)
--> $DIR/splat-dyn-asref-tuple-fail.rs:12:36
|
LL | fn dyn_asref_splat<T>(#[splat] _t: &dyn AsRef<T>)
| ^^^^^^^^^^^^^
...
LL | dyn_asref_splat::<(u8, f32)>(&t);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0277]: cannot use splat attribute; the splatted argument type must be a tuple or unit, not a Trait(std::convert::AsRef<_>)
--> $DIR/splat-dyn-asref-tuple-fail.rs:12:36
|
LL | fn dyn_asref_splat<T>(#[splat] _t: &dyn AsRef<T>)
| ^^^^^^^^^^^^^
...
LL | dyn_asref_splat(&t);
| ^^^^^^^^^^^^^^^^^^^

error: aborting due to 2 previous errors
error: aborting due to 5 previous errors

For more information about this error, try `rustc --explain E0277`.
25 changes: 25 additions & 0 deletions tests/ui/splat/splat-fn-ptr-cast-fail.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
//! Test casting splatted functions to non-splatted function pointers fails.

#![allow(incomplete_features)]
#![feature(splat, tuple_trait)]

use std::marker::Tuple;

fn tuple_args(#[splat] (_a, _b): (u32, i8)) {}

fn splat_non_terminal_arg(#[splat] (_a, _b): (u32, i8), _c: f64) {}

fn f<Args: Tuple>(#[splat] args: Args) {}

fn main() {
// Function pointers
let _fn_ptr: fn((u32, i8)) = tuple_args; //~ ERROR mismatched types
let _fn_ptr: fn((u32, i8), f64) = splat_non_terminal_arg; //~ ERROR mismatched types

let _fn_ptr: fn((u32, i8)) = tuple_args as fn((u32, i8)); //~ ERROR non-primitive cast
let _fn_ptr: fn((u32, i8), f64) = splat_non_terminal_arg as fn((u32, i8), f64); //~ ERROR non-primitive cast

// Bug #158603 regression test variants
const _F2: fn((u8, u32)) = f::<(u8, u32)>; //~ ERROR mismatched types
const _F1: fn(((u8, u32),)) = f::<((u8, u32),)>; //~ ERROR mismatched types
}
60 changes: 60 additions & 0 deletions tests/ui/splat/splat-fn-ptr-cast-fail.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
error[E0308]: mismatched types
--> $DIR/splat-fn-ptr-cast-fail.rs:16:34
|
LL | let _fn_ptr: fn((u32, i8)) = tuple_args;
| ------------- ^^^^^^^^^^ expected fn with no splatted arg, found fn with arg 0 splatted
| |
| expected due to this
|
= note: expected fn pointer `fn((_, _))`
found fn item `fn(#[splat] (_, _)) {tuple_args}`

error[E0308]: mismatched types
--> $DIR/splat-fn-ptr-cast-fail.rs:17:39
|
LL | let _fn_ptr: fn((u32, i8), f64) = splat_non_terminal_arg;
| ------------------ ^^^^^^^^^^^^^^^^^^^^^^ expected fn with no splatted arg, found fn with arg 0 splatted
| |
| expected due to this
|
= note: expected fn pointer `fn((_, _), _)`
found fn item `fn(#[splat] (_, _), _) {splat_non_terminal_arg}`

error[E0605]: non-primitive cast: `fn(, #[splat](u32, i8)) {tuple_args}` as `fn((u32, i8))`
--> $DIR/splat-fn-ptr-cast-fail.rs:19:34
|
LL | let _fn_ptr: fn((u32, i8)) = tuple_args as fn((u32, i8));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid cast

error[E0605]: non-primitive cast: `fn(, #[splat](u32, i8), f64) {splat_non_terminal_arg}` as `fn((u32, i8), f64)`
--> $DIR/splat-fn-ptr-cast-fail.rs:20:39
|
LL | let _fn_ptr: fn((u32, i8), f64) = splat_non_terminal_arg as fn((u32, i8), f64);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid cast

error[E0308]: mismatched types
--> $DIR/splat-fn-ptr-cast-fail.rs:23:32
|
LL | const _F2: fn((u8, u32)) = f::<(u8, u32)>;
| ------------- ^^^^^^^^^^^^^^ expected fn with no splatted arg, found fn with arg 0 splatted
| |
| expected because of the type of the constant
|
= note: expected fn pointer `fn((_, _))`
found fn item `fn(#[splat] (_, _)) {f::<(u8, u32)>}`

error[E0308]: mismatched types
--> $DIR/splat-fn-ptr-cast-fail.rs:24:35
|
LL | const _F1: fn(((u8, u32),)) = f::<((u8, u32),)>;
| ---------------- ^^^^^^^^^^^^^^^^^ expected fn with no splatted arg, found fn with arg 0 splatted
| |
| expected because of the type of the constant
|
= note: expected fn pointer `fn(((_, _),))`
found fn item `fn(#[splat] ((_, _),)) {f::<((u8, u32),)>}`

error: aborting due to 6 previous errors

Some errors have detailed explanations: E0308, E0605.
For more information about an error, try `rustc --explain E0308`.
8 changes: 7 additions & 1 deletion tests/ui/splat/splat-fn-tuple-generic-fail.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@
#![feature(splat)]
#![feature(tuple_trait)]

fn splat_generic_tuple<T: std::marker::Tuple>(#[splat] _t: T) {}
use std::marker::Tuple;

fn splat_generic_tuple<T: Tuple>(#[splat] _t: T) {}

fn f<Args: Tuple>(#[splat] args: Args) {}

fn main() {
// FIXME(splat): should splatted functions be callable with tupled and un-tupled arguments?
Expand All @@ -24,4 +28,6 @@ fn main() {

splat_generic_tuple::<(u32, i8)>((1, 2)); //~ ERROR this splatted function takes 2 arguments, but 1 was provided
splat_generic_tuple::<(u32, i8)>((1u32, 2i8)); //~ ERROR this splatted function takes 2 arguments, but 1 was provided

const F1: fn((u8, u32)) = f::<(u8, u32)>; //~ ERROR mismatched types
}
28 changes: 20 additions & 8 deletions tests/ui/splat/splat-fn-tuple-generic-fail.stderr
Original file line number Diff line number Diff line change
@@ -1,39 +1,51 @@
error[E0057]: this splatted function takes 2 arguments, but 1 was provided
--> $DIR/splat-fn-tuple-generic-fail.rs:19:5
--> $DIR/splat-fn-tuple-generic-fail.rs:23:5
|
LL | splat_generic_tuple::<(((u32, i8)))>((1, 2));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0057]: this splatted function takes 2 arguments, but 1 was provided
--> $DIR/splat-fn-tuple-generic-fail.rs:20:5
--> $DIR/splat-fn-tuple-generic-fail.rs:24:5
|
LL | splat_generic_tuple::<(((u32, i8)))>((1u32, 2i8));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0057]: this splatted function takes 2 arguments, but 1 was provided
--> $DIR/splat-fn-tuple-generic-fail.rs:22:5
--> $DIR/splat-fn-tuple-generic-fail.rs:26:5
|
LL | splat_generic_tuple::<((u32, i8))>((1, 2));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0057]: this splatted function takes 2 arguments, but 1 was provided
--> $DIR/splat-fn-tuple-generic-fail.rs:23:5
--> $DIR/splat-fn-tuple-generic-fail.rs:27:5
|
LL | splat_generic_tuple::<((u32, i8))>((1u32, 2i8));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0057]: this splatted function takes 2 arguments, but 1 was provided
--> $DIR/splat-fn-tuple-generic-fail.rs:25:5
--> $DIR/splat-fn-tuple-generic-fail.rs:29:5
|
LL | splat_generic_tuple::<(u32, i8)>((1, 2));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0057]: this splatted function takes 2 arguments, but 1 was provided
--> $DIR/splat-fn-tuple-generic-fail.rs:26:5
--> $DIR/splat-fn-tuple-generic-fail.rs:30:5
|
LL | splat_generic_tuple::<(u32, i8)>((1u32, 2i8));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: aborting due to 6 previous errors
error[E0308]: mismatched types
--> $DIR/splat-fn-tuple-generic-fail.rs:32:31
|
LL | const F1: fn((u8, u32)) = f::<(u8, u32)>;
| ------------- ^^^^^^^^^^^^^^ expected fn with no splatted arg, found fn with arg 0 splatted
| |
| expected because of the type of the constant
|
= note: expected fn pointer `fn((_, _))`
found fn item `fn(#[splat] (_, _)) {f::<(u8, u32)>}`

error: aborting due to 7 previous errors

For more information about this error, try `rustc --explain E0057`.
Some errors have detailed explanations: E0057, E0308.
For more information about an error, try `rustc --explain E0057`.
21 changes: 21 additions & 0 deletions tests/ui/splat/splat-self.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//@ run-pass
//@ check-run-results
//! Test using `#[splat]` on self arguments of trait methods.

#![feature(splat)]
#![expect(incomplete_features)]

trait Trait {
fn method(#[splat] self: Self);
}

impl Trait for (i32, i64) {
fn method(#[splat] self: Self) {
println!("{self:?}");
}
}

fn main() {
(1_i32, 2_i64).method();
Trait::method(3_i32, 4_i64);
}
2 changes: 2 additions & 0 deletions tests/ui/splat/splat-self.run.stdout
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
(1, 2)
(3, 4)
Loading