Skip to content

Add arg splat experiment initial tuple impl#153697

Open
teor2345 wants to merge 17 commits into
rust-lang:mainfrom
teor2345:fn-arg-splat-experiment
Open

Add arg splat experiment initial tuple impl#153697
teor2345 wants to merge 17 commits into
rust-lang:mainfrom
teor2345:fn-arg-splat-experiment

Conversation

@teor2345
Copy link
Copy Markdown
Contributor

@teor2345 teor2345 commented Mar 11, 2026

View all comments

This PR is part of the argument splatting lang experiment, and FFI overloading / C++ interop project goals:

Example code using existing unstable features:

Discussion of implementation strategy:

The PR is the initial implementation of the feature:

  • splat incomplete feature gate
  • #[splat] attribute on function arguments
  • Splatted function argument TypeInfo
  • #[splat] function parameter check at THIR level
  • splatted MIR lowering (as tupled arguments)
  • feature gate and UI tests for item type filtering, non-splattable arguments, splattable tuples, generics, and the "overloading at home" example
    • about half the diff (1100 lines) is tests and test output

Once this PR merges, we can add further functionality, then test it out in interop tools.

Further Work

Out of Scope for this PR

  • Change codegen to de-tuple caller and callee
  • Better diagnostics
  • Full support for splatted function pointer arguments

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-libs Relevant to the library team, which will review and decide on the PR/issue. labels Mar 11, 2026
@rustbot
Copy link
Copy Markdown
Collaborator

rustbot commented Mar 11, 2026

r? @JohnTitor

rustbot has assigned @JohnTitor.
They will have a look at your PR within the next two weeks and either review your PR or reassign to another reviewer.

Use r? to explicitly pick a reviewer

Why was this reviewer chosen?

The reviewer was selected based on:

  • Owners of files modified in this PR: compiler
  • compiler expanded to 69 candidates
  • Random selection from 16 candidates

@rust-log-analyzer

This comment has been minimized.

Comment thread compiler/rustc_builtin_macros/src/splat.rs Outdated
@JohnTitor
Copy link
Copy Markdown
Member

It should be better for someone on https://rust-lang.zulipchat.com/#narrow/channel/213817-t-lang/topic/On.20overloading/with/573924937 to review this, @oli-obk could you take over?

@oli-obk oli-obk assigned oli-obk and unassigned JohnTitor Mar 11, 2026
@oli-obk oli-obk added the S-blocked Status: Blocked on something else such as an RFC or other implementation work. label Mar 12, 2026
@oli-obk
Copy link
Copy Markdown
Contributor

oli-obk commented Mar 12, 2026

Let's wait for the ongoing discussion on Zulip to figure out whether we need to have a proc macro, an AST manipulating attribute (like define_opaque), or just a normal attribute

@teor2345 teor2345 marked this pull request as draft March 13, 2026 06:49
@rustbot rustbot added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Mar 13, 2026
@teor2345 teor2345 force-pushed the fn-arg-splat-experiment branch from 89102bf to c784a57 Compare March 16, 2026 07:35
@rustbot rustbot added the A-attributes Area: Attributes (`#[…]`, `#![…]`) label Mar 16, 2026
Comment thread compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs Outdated
Comment thread compiler/rustc_hir/src/target.rs
Comment thread tests/ui/splat/splat-non-function.rs Outdated
@teor2345 teor2345 force-pushed the fn-arg-splat-experiment branch from c784a57 to 2d9e563 Compare March 20, 2026 01:37
@rustbot rustbot added A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. A-query-system Area: The rustc query system (https://rustc-dev-guide.rust-lang.org/query.html) labels Mar 20, 2026
@teor2345

This comment was marked as outdated.

@rust-log-analyzer

This comment has been minimized.

teor2345

This comment was marked as resolved.

@rust-log-analyzer

This comment has been minimized.

@rustbot rustbot added the T-clippy Relevant to the Clippy team. label Mar 20, 2026
@rustbot

This comment has been minimized.

@rust-bors

This comment has been minimized.

@rustbot

This comment has been minimized.

@rustbot
Copy link
Copy Markdown
Collaborator

rustbot commented Jun 5, 2026

This PR was rebased onto a different main commit. Here's a range-diff highlighting what actually changed.

Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers.

@teor2345
Copy link
Copy Markdown
Contributor Author

teor2345 commented Jun 5, 2026

@rustbot ready

I've rebased and cherry-picked @Ajay-singh1's bug fix and extra tests from #157434.

@rust-log-analyzer

This comment has been minimized.

Comment on lines +346 to +353
// FIXME(splat): should these fields be private, or merged into an Option<u16>?
/// Is any function argument splatted?
pub is_splatted: bool,

/// The index of the splatted function argument in `inputs`, only valid if `is_splatted` is true.
/// e.g. in `fn overload(a: u8, #[splat] b: (f32, usize))` the index is 1, and it can be called
/// as `overload(a, 1.0, 2)`.
pub splatted_index: u16,
Copy link
Copy Markdown
Member

@RalfJung RalfJung Jun 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you immediately need reflection support for this? If not, seems better to leave this for later and make the PR a bit smaller.

View changes since the review

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think so, happy to split the PR.

Would it be easier as 3 PRs?

  • feature gate only
  • splat attribute, typecheck, and MIR
  • reflection

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't the feature gate just a single line?

But reflection is sufficiently new that it might be worth separating. OTOH you have @oli-obk as reviewer who is intimately familiar with reflection so for him it's probably fine. I should have checked the reviewer before commenting, sorry.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't the feature gate just a single line?

About 200 lines when you add attribute parsing and tests. But I get your point.

But reflection is sufficiently new that it might be worth separating. OTOH you have @oli-obk as reviewer who is intimately familiar with reflection so for him it's probably fine.

I'll split it on Monday if I don't hear back from Oli, then other people might be able to review the other parts. Maybe there's more splits that make sense, I'll have a think about it.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

About 200 lines when you add attribute parsing and tests. But I get your point.

Ah that's more than just the feature gate then. :)

Separating the syntactic parts out also can make sense yeah, I've seen this for other new features in the past.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reflection is sufficiently simple that doing it together with adding the field to function signature makes sense

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alright, I'll split it into two PRs:

  • attribute parsing and syntax
  • type checking, lowering, and reflection

It seems like most conflicting PRs either touch one or the other, so hopefully that will reduce the rebases.

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer
Copy link
Copy Markdown
Collaborator

The job aarch64-gnu-llvm-21-1 failed! Check out the build log: (web) (plain enhanced) (plain)

Click to see the possible cause of the failure (guessed by this bot)
test [ui] tests/ui/specialization/specialization-translate-projections-with-params.rs ... ok
test [ui] tests/ui/specialization/trait-specialization-default-methods-55380.rs ... ok
test [ui] tests/ui/specialization/specialization-translate-projections.rs ... ok
test [ui] tests/ui/specialization/transmute-specialization.rs ... ok
test [ui] tests/ui/splat/splat-assoc-fn-tuple-simple.rs ... ok
test [ui] tests/ui/splat/splat-cannot-resolve.rs ... ok
test [ui] tests/ui/splat/splat-fn-ptr-tuple.rs ... ok
test [ui] tests/ui/splat/splat-fn-tuple-generic-fail.rs ... ok
test [ui] tests/ui/splat/splat-fn-tuple-generic.rs ... ok
test [ui] tests/ui/splat/splat-fn-tuple-simple.rs ... ok
test [ui] tests/ui/splat/splat-generics-inside-tuple.rs ... ok
test [ui] tests/ui/splat/splat-invalid-trait-impl.rs ... ok
test [ui] tests/ui/splat/splat-generics-everywhere.rs ... ok
test [ui] tests/ui/splat/splat-maybe-tuple.rs ... ok
test [ui] tests/ui/splat/splat-invalid.rs ... ok
test [ui] tests/ui/splat/splat-non-fn-arg.rs ... ok
test [ui] tests/ui/splat/splat-non-tuple.rs ... ok
test [ui] tests/ui/splat/splat-method-tuple-simple.rs ... ok
test [ui] tests/ui/stability-attribute/accidental-stable-in-unstable.rs ... ok
test [ui] tests/ui/splat/splat-overload-at-home-fail.rs ... FAILED
test [ui] tests/ui/splat/splat-trait-tuple.rs ... ok
test [ui] tests/ui/splat/splat-overload-at-home.rs ... ok
test [ui] tests/ui/stability-attribute/check-stability-issue-138319.rs ... ok
test [ui] tests/ui/stability-attribute/const-stability-attribute-implies-missing.rs ... ok
test [ui] tests/ui/stability-attribute/allowed-through-unstable.rs ... ok
test [ui] tests/ui/stability-attribute/const-stability-attribute-implies-using-stable.rs ... ok
test [ui] tests/ui/stability-attribute/allow-unstable-reexport.rs ... ok
---
test [ui] tests/ui/zero-sized/zero-sized-btreemap-insert.rs ... ok

failures:

---- [ui] tests/ui/splat/splat-overload-at-home-fail.rs stdout ----

error: Error: expected failure status (Some(1)) but received status Some(101).
status: exit status: 101
command: env -u RUSTC_LOG_COLOR RUSTC_ICE="0" RUST_BACKTRACE="short" "/checkout/obj/build/aarch64-unknown-linux-gnu/stage2/bin/rustc" "/checkout/tests/ui/splat/splat-overload-at-home-fail.rs" "-Zthreads=1" "-Zsimulate-remapped-rust-src-base=/rustc/FAKE_PREFIX" "-Ztranslate-remapped-path-to-local-path=no" "-Z" "ignore-directory-in-diagnostics-source-blocks=/cargo" "-Z" "ignore-directory-in-diagnostics-source-blocks=/checkout/vendor" "--sysroot" "/checkout/obj/build/aarch64-unknown-linux-gnu/stage2" "--target=aarch64-unknown-linux-gnu" "--check-cfg" "cfg(test,FALSE)" "--error-format" "json" "--json" "future-incompat" "-Ccodegen-units=1" "-Zui-testing" "-Zdeduplicate-diagnostics=no" "-Zwrite-long-types-to-disk=no" "-Cstrip=debuginfo" "--emit" "metadata" "-C" "prefer-dynamic" "--out-dir" "/checkout/obj/build/aarch64-unknown-linux-gnu/test/ui/splat/splat-overload-at-home-fail" "-A" "unused" "-W" "unused_attributes" "-A" "internal_features" "-A" "incomplete_features" "-A" "unused_parens" "-A" "unused_braces" "-Crpath" "-Cdebuginfo=0" "-Lnative=/checkout/obj/build/aarch64-unknown-linux-gnu/native/rust-test-helpers"
stdout: none
--- stderr -------------------------------
error[E0308]: mismatched types
##[error]  --> /checkout/tests/ui/splat/splat-overload-at-home-fail.rs:35:16
   |
LL |     foo.method(42f32);
   |         ------ ^^^^^ expected `i32`, found `f32`
   |         |
   |         arguments to this method are incorrect
   |
note: method defined here
  --> /checkout/tests/ui/splat/splat-overload-at-home-fail.rs:26:8
   |
LL |     fn method<T: MethodArgs>(&self, #[splat] args: T) {
   |        ^^^^^^                       ----------------
help: change the type of the numeric literal from `f32` to `i32`
   |
LL -     foo.method(42f32);
LL +     foo.method(42i32);
   |


thread 'rustc' (154883) panicked at compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs:1704:17:
assertion `left == right` failed
  left: 1
 right: 2
stack backtrace:
   0: __rustc::rust_begin_unwind
   1: core::panicking::panic_fmt
   2: core::panicking::assert_failed_inner
   3: core::panicking::assert_failed::<usize, usize>
   4: <rustc_hir_typeck::fn_ctxt::FnCtxt>::label_fn_like
   5: <rustc_hir_typeck::fn_ctxt::checks::FnCallDiagCtxt>::check_single_incompatible
   6: <rustc_hir_typeck::fn_ctxt::FnCtxt>::check_argument_types
   7: <rustc_hir_typeck::fn_ctxt::FnCtxt>::check_expr_kind
   8: <rustc_hir_typeck::fn_ctxt::FnCtxt>::check_expr_with_expectation_and_args
   9: <rustc_hir_typeck::fn_ctxt::FnCtxt>::check_expr_with_expectation
  10: <rustc_hir_typeck::fn_ctxt::FnCtxt>::check_expr_block
  11: <rustc_hir_typeck::fn_ctxt::FnCtxt>::check_expr_kind
  12: <rustc_hir_typeck::fn_ctxt::FnCtxt>::check_expr_with_expectation_and_args
  13: <rustc_hir_typeck::fn_ctxt::FnCtxt>::check_expr_with_expectation
  14: <rustc_hir_typeck::fn_ctxt::FnCtxt>::check_return_or_body_tail
  15: rustc_hir_typeck::check::check_fn
  16: rustc_hir_typeck::typeck_with_inspect
      [... omitted 2 frames ...]
  17: <rustc_middle::query::plumbing::TyCtxtEnsureOk>::typeck::<rustc_span::def_id::LocalDefId>
  18: <rustc_middle::ty::context::TyCtxt>::par_hir_body_owners::<rustc_hir_analysis::check_crate::{closure#1}>::{closure#0}
  19: std::panicking::catch_unwind::<(), core::panic::unwind_safe::AssertUnwindSafe<rustc_data_structures::sync::parallel::par_for_each_in<&rustc_span::def_id::LocalDefId, &[rustc_span::def_id::LocalDefId], <rustc_middle::ty::context::TyCtxt>::par_hir_body_owners<rustc_hir_analysis::check_crate::{closure#1}>::{closure#0}>::{closure#0}::{closure#1}::{closure#0}>>
  20: rustc_data_structures::sync::parallel::par_for_each_in::<&rustc_span::def_id::LocalDefId, &[rustc_span::def_id::LocalDefId], <rustc_middle::ty::context::TyCtxt>::par_hir_body_owners<rustc_hir_analysis::check_crate::{closure#1}>::{closure#0}>
  21: rustc_hir_analysis::check_crate
  22: rustc_interface::passes::analysis
      [... omitted 2 frames ...]
  23: std::panicking::catch_unwind::<core::option::Option<rustc_interface::queries::Linker>, core::panic::unwind_safe::AssertUnwindSafe<rustc_interface::passes::create_and_enter_global_ctxt<core::option::Option<rustc_interface::queries::Linker>, rustc_driver_impl::run_compiler::{closure#0}::{closure#2}>::{closure#2}::{closure#0}>>
  24: <std::thread::local::LocalKey<core::cell::Cell<*const ()>>>::with::<rustc_middle::ty::context::tls::enter_context<<rustc_middle::ty::context::GlobalCtxt>::enter<rustc_interface::passes::create_and_enter_global_ctxt<core::option::Option<rustc_interface::queries::Linker>, rustc_driver_impl::run_compiler::{closure#0}::{closure#2}>::{closure#2}, core::option::Option<rustc_interface::queries::Linker>>::{closure#1}, core::option::Option<rustc_interface::queries::Linker>>::{closure#0}, core::option::Option<rustc_interface::queries::Linker>>
  25: <rustc_middle::ty::context::TyCtxt>::create_global_ctxt::<core::option::Option<rustc_interface::queries::Linker>, rustc_interface::passes::create_and_enter_global_ctxt<core::option::Option<rustc_interface::queries::Linker>, rustc_driver_impl::run_compiler::{closure#0}::{closure#2}>::{closure#2}>
  26: rustc_interface::passes::create_and_enter_global_ctxt::<core::option::Option<rustc_interface::queries::Linker>, rustc_driver_impl::run_compiler::{closure#0}::{closure#2}>
  27: std::panicking::catch_unwind::<(), core::panic::unwind_safe::AssertUnwindSafe<rustc_interface::interface::run_compiler<(), rustc_driver_impl::run_compiler::{closure#0}>::{closure#1}::{closure#0}>>
  28: rustc_interface::interface::run_compiler::<(), rustc_driver_impl::run_compiler::{closure#0}>::{closure#1}
  29: <scoped_tls::ScopedKey<rustc_span::SessionGlobals>>::set::<rustc_interface::util::run_in_thread_with_globals<rustc_interface::util::run_in_thread_pool_with_globals<rustc_interface::interface::run_compiler<(), rustc_driver_impl::run_compiler::{closure#0}>::{closure#1}, ()>::{closure#0}, ()>::{closure#0}::{closure#0}::{closure#0}, ()>
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
---
note: please make sure that you have updated to the latest nightly

note: rustc 1.98.0-nightly (7c18df87f 2026-06-05) running on aarch64-unknown-linux-gnu

note: compiler flags: -Z threads=1 -Z simulate-remapped-rust-src-base=/rustc/FAKE_PREFIX -Z translate-remapped-path-to-local-path=no -Z ignore-directory-in-diagnostics-source-blocks=/cargo -Z ignore-directory-in-diagnostics-source-blocks=/checkout/vendor -C codegen-units=1 -Z ui-testing -Z deduplicate-diagnostics=no -Z write-long-types-to-disk=no -C strip=debuginfo -C prefer-dynamic -C rpath -C debuginfo=0

query stack during panic:
#0 [typeck_root] type-checking `main`
#1 [analysis] running analysis passes on crate `splat_overload_at_home_fail`
end of query stack
error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0308`.
------------------------------------------

---- [ui] tests/ui/splat/splat-overload-at-home-fail.rs stdout end ----

failures:
    [ui] tests/ui/splat/splat-overload-at-home-fail.rs

test result: FAILED. 20882 passed; 1 failed; 392 ignored; 0 measured; 20 filtered out; finished in 616.60s

Some tests failed in compiletest suite=ui mode=ui host=aarch64-unknown-linux-gnu target=aarch64-unknown-linux-gnu
Bootstrap failed while executing `--stage 2 test --skip tidy --skip compiler --skip src`

@rust-bors
Copy link
Copy Markdown
Contributor

rust-bors Bot commented Jun 5, 2026

☔ The latest upstream changes (presumably #157504) made this pull request unmergeable. Please resolve the merge conflicts.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-attributes Area: Attributes (`#[…]`, `#![…]`) A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. A-query-system Area: The rustc query system (https://rustc-dev-guide.rust-lang.org/query.html) perf-regression Performance regression. S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-clippy Relevant to the Clippy team. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-libs Relevant to the library team, which will review and decide on the PR/issue. T-rust-analyzer Relevant to the rust-analyzer team, which will review and decide on the PR/issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.