Repository navigation
Open
Labels
B-RFC-approvedBlocker: Approved by a merged RFC but not yet implemented.Blocker: Approved by a merged RFC but not yet implemented.C-tracking-issueCategory: An issue tracking the progress of sth. like the implementation of an RFCCategory: An issue tracking the progress of sth. like the implementation of an RFCF-unsized_fn_params`#![feature(unsized_fn_params)]``#![feature(unsized_fn_params)]`F-unsized_locals`#![feature(unsized_locals)]``#![feature(unsized_locals)]`S-tracking-design-concernsStatus: There are blocking design concerns.Status: There are blocking design concerns.S-tracking-needs-summaryStatus: It's hard to tell what's been done and what hasn't! Someone should do some investigation.Status: It's hard to tell what's been done and what hasn't! Someone should do some investigation.T-langRelevant to the language teamRelevant to the language team
Description
This is a tracking issue for the RFC "Unsized Rvalues " (rust-lang/rfcs#1909).
Steps:
- Implement the RFC (cc @rust-lang/compiler -- can anyone write up mentoring instructions?)
- Adjust documentation (see instructions on forge)
- Stabilization PR (see instructions on forge)
Blocking bugs for unsized_fn_params:
- unsized_fn_params allows some unsized locals #111175
- unsized_fn_params should not accept types that don't have a dynamically fixed size (such as
externtypes) #115709 (bad interaction with extern_type: we either need to be okay with post-mono checks or need a trait for "dynamically sized" types) - Reject unsized arguments for functions with non-Rust ABI
Related bugs:
- ICE when combining unsized locals and async #61335 -- ICE when combined with async-await
- Box<dyn FnOnce> doesn't respect self alignment #68304 --
Box<dyn FnOnce>doesn't respect self alignment
Unresolved questions:
- What are the MIR semantics for unsized locals? We currently do not have operational semantics for them, and the way they currently work, there are no good operational semantics. This needs a complete from-scratch re-design.
- Can we carve out a path of "guaranteed no alloca" optimization? (See Box<dyn FnOnce> doesn't respect self alignment #68304 for some related discussion)
- Given that LLVM doesn't seem to support alloca with alignment, how do we expect to respect alignment limitations? (See Box<dyn FnOnce> doesn't respect self alignment #68304 for one specific instance)
- How can we mitigate the risk of unintended unsized or large allocas? Note that the problem already exists today with large structs/arrays. A MIR lint against large/variable stack sizes would probably help users avoid these stack overflows. Do we want it in Clippy? rustc?
- How do we handle truely-unsized DSTs when we get them? They can theoretically be passed to functions, but they can never be put in temporaries.
- Decide on a concrete syntax for VLAs.
- What about the interactions between async-await/generators and unsized locals?
- We currently allow
extern typearguments withunsized_fn_params, but that does not make much sense and leads to ICEs: unsized_fn_params should not accept types that don't have a dynamically fixed size (such asexterntypes) #115709
Reacted by Stanislav Tkach, Alex Kreidler, David Husička, Egor Malyutin, cdecompilador, oilaba, Hudson Ayers, Andrew Hlynskyi, Michael Debertol, Andréy Lesnikóv and 39 more
Reacted by cdecompilador, Cherry and Finn Bear
Reacted by est31, tinaun, Jonathan Goodman, Wesley Norris, Pyry Kontio, g, Lance Roy, Eduard-Mihai Burtescu, runiq and 50 more
Reacted by est31, Wesley Norris, g, Eduard-Mihai Burtescu, runiq, Dan Kolsoi, Jakub Hlusička, Sunjay Varma, carado and 34 more
Reacted by Felipe S. S. Schneider, PSeitz, Ben Hansen, MarkTanashchuk, Cherry and Taylor Cramer
Reacted by Ryo Onodera, Blin4ik, Changsheng Wu, Taylor Cramer, xuyue and teor
Metadata
Metadata
Assignees
Labels
B-RFC-approvedBlocker: Approved by a merged RFC but not yet implemented.Blocker: Approved by a merged RFC but not yet implemented.C-tracking-issueCategory: An issue tracking the progress of sth. like the implementation of an RFCCategory: An issue tracking the progress of sth. like the implementation of an RFCF-unsized_fn_params`#![feature(unsized_fn_params)]``#![feature(unsized_fn_params)]`F-unsized_locals`#![feature(unsized_locals)]``#![feature(unsized_locals)]`S-tracking-design-concernsStatus: There are blocking design concerns.Status: There are blocking design concerns.S-tracking-needs-summaryStatus: It's hard to tell what's been done and what hasn't! Someone should do some investigation.Status: It's hard to tell what's been done and what hasn't! Someone should do some investigation.T-langRelevant to the language teamRelevant to the language team
Activity
Aaron1011 commentedon Feb 20, 2018
@aturon: Are you referring to
extern type?aturon commentedon Feb 20, 2018
@Aaron1011 that was copied straight from the RFC. But yes, I presume that's what it's referring to.
ldr709 commentedon Feb 28, 2018
Why would unsized temporaries ever be necessary? The only way it would make sense to pass them as arguments would be by fat pointer, and I cannot think of a situation that would require the memory to be copied/moved. They cannot be assigned or returned from functions under the RFC. Unsized local variables could also be treated as pointers.
In other words, is there any reason why unsized temporary elision shouldn't be always guaranteed?
F001 commentedon May 11, 2018
Is there any progress on this issue?
I'm trying to implement VLA in the compiler. For the AST and HIR part, I added a new enum member for
syntax::ast::ExprKind::Repeatandhir::Expr_::ExprRepeatto save the count expression as below:But for the MIR part, I have no idea how to construct a correct MIR. Should I update the structure of
mir::RValue::Repeatand correspondingtrans_rvaluefunction? What should they look like? What is the expected LLVM-IR?Thanks in advance if someone would like to write a simple mentoring instruction.
qnighy commentedon May 26, 2018
I'm trying to remove the
Sizedbounds and translate MIRs accordingly.mikeyhew commentedon Jul 14, 2018
An alternative that would solve both of the unresolved questions would be explicit
&movereferences. We could have an explicitalloca!expression that returns&move T, and truly unsized types work with&move Tbecause it is just a pointer.If I remember correctly, the main reason for this RFC was to get
dyn FnOnce()to be callable. SinceFnOnce()is not implementable in stable Rust, would it be a backward-compatible change to makeFnOnce::call_oncetake&move Selfinstead? If that was the case, then we could make&move FnOnce()be callable, as well asBox<FnOnce()>(viaDerefMove).cc @arielb1 (RFC author) @qnighy (currently implementing this RFC in #51131) @eddyb (knows a lot about this stuff)
eddyb commentedon Jul 14, 2018
@mikeyhew There's not really much of a problem with making by-value
selfwork and IMO it's more ergonomic anyway. We might eventually even haveDerefMovewithout&moveat all.mikeyhew commentedon Jul 20, 2018
@eddyb
I guess I can see why people think it's more ergonomic: in order to opt into it, you just have to add
?Sizedto your function signature, or in the case of trait methods, do nothing. And maybe it will help new users of the language, since&movewouldn't be show up in documentation everywhere.If we're going to go ahead with this implicit syntax, then there are a few details that would be good to nail down:
If this is syntactic sugar for
&movereferences, what does it desugar too? For function arguments, this could be pretty straightforward: the lifetime of the reference would be limited to the function call, and if you want to extend it past that, you'd have to use explicit&movereferences. Sodesugars too
and you can call the function directly on its argument, so
foo(|x| x + 1)desugars tofoo(&move (|x| x + 1)).And to do something fancier, you'd have to resort to the explicit version:
Given the above semantics,
DerefMovecould be expressed using unsized rvalues, as you said:EDIT: This is kind of sketchy though. What happens if the implementation is wrong, and doesn't call
f?I should probably write an RFC for this.
When do there need to be implicit allocas? I can't actually think of a case where an implicit alloca would be needed. Any function arguments would last as long as the function does, and wouldn't need to be alloca'd. Maybe something involving stack-allocated dynamic arrays, if they are returned from a block, but I'm pretty sure that's explicitly disallowed by the RFC.
mikeyhew commentedon Jul 20, 2018
@eddyb have you seen @alercah's RFC for DerefMove? rust-lang/rfcs#2439
Auto merge of #51131 - qnighy:unsized-locals, r=eddyb
qnighy commentedon Aug 20, 2018
As a next step, I'll be working on trait object safety.
alexreg commentedon Aug 22, 2018
@mikeyhew Sadly @alercah just postponed their
DerefMoveRFC, but I think a separate RFC for&movethat complements that (when it does get revived) would be very much desirable. I would be glad to assist with that even, if you're interested.56 remaining items
Jules-Bertholet commentedon May 5, 2023
@rustbot label F-unsized_fn_params
ices/61335.rs: fixed with errors
ices/68543.rs: fixed with errors
ices/88212.rs: fixed with errors
[-]Tracking issue for RFC #1909: Unsized Rvalues [/-][+]Tracking issue for RFC #1909: Unsized Rvalues (unsized_locals, unsized_fn_params)[/+]RalfJung commentedon Nov 1, 2023
We should probably reject unsized arguments for non-Rust ABIs... it makes little sense to do this with an
extern "C"function since the C ABI does not support unsized arguments.RalfJung commentedon Dec 3, 2023
With #111374, unsized locals are no longer blatantly unsound. However, they still lack an actual operational semantics in MIR -- and the way they are represented in MIR doesn't lend itself to a sensible semantics; they need a from-scratch re-design I think. We are getting more and more MIR optimizations and without a semantics, the interactions of unsized locals with those optimizations are basically unpredictable.
The issue with their MIR form is that and assignment
let x = y;gets compiled to MIR likeHowever, when
xis unsized, we cannot allocate the memory for x in the first step, since we don't know how big x is. The IR just fundamentally doesn't make any sense, with the way we now understandStorageLiveto work.If they were suggested for addition to rustc today, we'd not accept a PR adding them to MIR without giving them semantics. Unsized locals are the only part of MIR that doesn't even have a proposed semantics that could be implemented in Miri. (We used to have a hack, but I removed it because it was hideous and affected the entire interpreter.) I'm not comfortable having even an unstable feature be in such a bad state, with no sign of improvement for many years. So I still feel that unsized locals should be either re-implemented in a well-designed way, or removed -- the current status is very unsatisfying and prone to bugs. Unstable features are what we use to experiment, and sometimes the result of an experiment is that whatever we do doesn't work and we need to try something else.
(Unsized argument do not have that issue: function arguments get marked as "live" when the stack frame is pushed, and at that moment we know the values for all the arguments. Allocating the local and initializing it are done together as part of argument passing. That means we can use the size information we get from the value that the caller chose to allocate the right amount of memory in the callee.)
SpriteOvO commentedon Dec 3, 2023
NobodyXu commentedon Dec 3, 2023
RalfJung commentedon Dec 3, 2023
SpriteOvO commentedon Dec 3, 2023
Auto merge of #148302 - folkertdev:non-rustic-unsized, r=bjorn3
Auto merge of #148302 - folkertdev:non-rustic-unsized, r=bjorn3