Add arg splat experiment initial tuple impl#153697
Add arg splat experiment initial tuple impl#153697teor2345 wants to merge 8 commits intorust-lang:mainfrom
Conversation
|
r? @JohnTitor rustbot has assigned @JohnTitor. Use Why was this reviewer chosen?The reviewer was selected based on:
|
This comment has been minimized.
This comment has been minimized.
|
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? |
|
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 |
89102bf to
c784a57
Compare
c784a57 to
2d9e563
Compare
This comment was marked as outdated.
This comment was marked as outdated.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
Add arg splat experiment initial tuple impl
This comment has been minimized.
This comment has been minimized.
|
Finished benchmarking commit (a8930df): comparison URL. Overall result: ❌ regressions - please read:Benchmarking means the PR may be perf-sensitive. It's automatically marked not fit for rolling up. Overriding is possible but disadvised: it risks changing compiler perf. Next, please: If you can, justify the regressions found in this try perf run in writing along with @bors rollup=never Instruction countOur most reliable metric. Used to determine the overall result above. However, even this metric can be noisy.
Max RSS (memory usage)Results (primary -0.7%, secondary -2.3%)A less reliable metric. May be of interest, but not used to determine the overall result above.
CyclesResults (secondary -4.1%)A less reliable metric. May be of interest, but not used to determine the overall result above.
Binary sizeResults (primary 0.1%, secondary 0.2%)A less reliable metric. May be of interest, but not used to determine the overall result above.
Bootstrap: 490.512s -> 491.535s (0.21%) |
This comment was marked as resolved.
This comment was marked as resolved.
7e8fef2 to
d83e6d9
Compare
This comment has been minimized.
This comment has been minimized.
d83e6d9 to
d4229d6
Compare
This comment has been minimized.
This comment has been minimized.
d4229d6 to
482f842
Compare
|
The perf issues above are resolved by a minor refactor, but I'd like to merge them as separate PRs/commits, just in case we need to go back to the original code for testing (or further refactors). See the perf analysis here, overall this PR plus the refactor in #155852 results in an 0.24% primary benchmark improvement, with no primary regressions: |
482f842 to
84cab65
Compare
|
I've done a rough split of the code into separate commits, and dropped the unrelated changes. |
| // FIXME(splat): only allow MacroCall if the macro creates an argument | ||
| Allow(Target::MacroCall), |
There was a problem hiding this comment.
could also just not allow this for now, or add a test that excercises this code path
|
|
||
| // Multiple splatted arguments are invalid: we can't know which arguments go in each splat. | ||
| if splatted_arg_indexes.len() > 1 { | ||
| self.dcx().emit_err(errors::DuplicateSplattedArgs { spans: splatted_spans.clone() }); |
There was a problem hiding this comment.
I'm somewhat worried that due to these errors being non-blocking for the rest of the compiler, that it's possible to cause weird ICEs, but that's nothing new wrt most of the ast validation checks.
| // Function parameter count, including C variadic `...` if present. | ||
| fn param_count(&self, def_id: DefId) -> (usize, bool /*c_variadic*/) { | ||
| // Function parameter count, including C variadic `...` and `#[splat]` if present. | ||
| fn param_count(&self, def_id: DefId) -> (usize, bool /*c_variadic*/, Option<u16> /*splatted*/) { |
There was a problem hiding this comment.
This return type should be a struct I think 😆 it's getting a little out of hand, and usually is just passed along to another function anyway, so we could just keep passing these modifiers along together. Also the function name doesn't really represent the return value anymore... maybe param_info?
| /// Which function argument is splatted into multiple arguments in callers, if any? | ||
| /// Splatting functions with `u16::MAX` arguments is not supported, see `FnSigKind` for | ||
| /// details. | ||
| splatted: u16, |
There was a problem hiding this comment.
far future possibility: make newtype_index allow for types other than u32 to be used for the storage. Then we could just encode a new ArgIdx type that inherently forbids u16::MAX (and maybe a few others at the upper limit to allow for more niche opts)
There was a problem hiding this comment.
also 😭 why do we allow more than 250 arguments on functions
| /// Create a new FnDeclKind with no implicit self, no lifetime elision, and no C-style variadic argument. | ||
| /// Marker index for "no splatted argument". | ||
| /// Must have the same value as `FnSigKind::NO_SPLATTED_ARG_INDEX` and `rustc_ast::FnDecl::NO_SPLATTED_ARG_INDEX`. | ||
| const NO_SPLATTED_ARG_INDEX: u16 = u16::MAX; |
There was a problem hiding this comment.
can these all be linked somehow by depending on them in the argument? Or are there two of them who don't have the others' crate in their dependency list?
| }; | ||
|
|
||
| // If the arguments should be wrapped in a tuple (ex: closures, splats), unwrap them here | ||
| if let Some(first_tupled_arg_index) = first_tupled_arg_index { |
There was a problem hiding this comment.
Pull this condition's body out into a separate function
|
|
||
| let type_errors = ocx.try_evaluate_obligations(); | ||
| if type_errors.is_empty() { | ||
| assert_matches!(new_tupled_type.kind(), ty::Tuple(_)); |
There was a problem hiding this comment.
This assert seems odd since you just created the tuple with this kind a few lines above, did you mean to check calee_tuple_type?
|
|
||
| // Keep the type variable if the argument is splatted, so we can force it to be a tuple later. | ||
| let tuple_type = if fn_sig_kind.splatted().is_some() { | ||
| let calee_tuple_type = self.try_structurally_resolve_type( |
There was a problem hiding this comment.
typo calee is missing an l
| let ocx_error = | ||
| ocx.eq(&origin, self.param_env, calee_tuple_type, new_tupled_type); | ||
| if let Err(ocx_error) = ocx_error { | ||
| struct_span_code_err!( |
There was a problem hiding this comment.
is this error reachable? if so, please add a test specifically for it
| sym::variadic => { | ||
| self.write_scalar(Scalar::from_bool(fn_sig_kind.c_variadic()), &field_place)?; | ||
| } | ||
| sym::splat => { |
There was a problem hiding this comment.
Also add it to libcore in the same commit
|
☔ The latest upstream changes (presumably #155329) made this pull request unmergeable. Please resolve the merge conflicts. |
| }; | ||
|
|
||
| // Split the rust-call tupled arguments off. | ||
| // FIXME(splat): un-tuple splatted arguments in codegen, for performance |
There was a problem hiding this comment.
Why "for performance"? If this follows the RustCall approach, the ABI requires untupling for correctness. I am confused by this comment.
There was a problem hiding this comment.
Oh I see, I think I got confused by "splatted MIR lowering and tupling". This doesn't actually do anything on the ABI level yet, it passes things as structs.
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:
splatincomplete feature gate#[splat]attribute on function arguments#[splat]function parameter check at THIR levelOnce this PR merges, we can add further functionality, then test it out in interop tools.
Further Work
Out of Scope for this PR