Skip to content

Tracking issue for RFC #1909: Unsized Rvalues (unsized_locals, unsized_fn_params) #48055

Open

Description

@aturon

This is a tracking issue for the RFC "Unsized Rvalues " (rust-lang/rfcs#1909).

Steps:

Blocking bugs for unsized_fn_params:

Related bugs:

Unresolved questions:

Activity

  1. added
    B-RFC-approvedBlocker: Approved by a merged RFC but not yet implemented.
    T-langRelevant to the language team
    C-tracking-issueCategory: An issue tracking the progress of sth. like the implementation of an RFC
    on Feb 7, 2018
  2. Aaron1011 commented on Feb 20, 2018

    @Aaron1011
    Contributor

    How do we handle truely-unsized DSTs when we get them?

    @aturon: Are you referring to extern type?

  3. aturon commented on Feb 20, 2018

    @aturon
    ContributorAuthor

    @Aaron1011 that was copied straight from the RFC. But yes, I presume that's what it's referring to.

  4. ldr709 commented on Feb 28, 2018

    @ldr709
    Contributor

    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?

  5. F001 commented on May 11, 2018

    @F001
    Contributor

    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::Repeat and hir::Expr_::ExprRepeat to save the count expression as below:

    enum RepeatSyntax { Dyn, None }
    syntax::ast::ExprKind::Repeat(P<Expr>, P<Expr>, RepeatSyntax)
    
    enum RepeatExprCount {
      Const(BodyId),
      Dyn(P<Expr>),
    }
    hir::Expr_::ExprRepeat(P<Expr>, RepeatExprCount)

    But for the MIR part, I have no idea how to construct a correct MIR. Should I update the structure of mir::RValue::Repeat and corresponding trans_rvalue function? What should they look like? What is the expected LLVM-IR?

    Thanks in advance if someone would like to write a simple mentoring instruction.

  6. qnighy commented on May 26, 2018

    @qnighy
    Contributor

    I'm trying to remove the Sized bounds and translate MIRs accordingly.

  7. mikeyhew commented on Jul 14, 2018

    @mikeyhew
    Contributor

    An alternative that would solve both of the unresolved questions would be explicit &move references. We could have an explicit alloca! expression that returns &move T, and truly unsized types work with &move T because it is just a pointer.

    If I remember correctly, the main reason for this RFC was to get dyn FnOnce() to be callable. Since FnOnce() is not implementable in stable Rust, would it be a backward-compatible change to make FnOnce::call_once take &move Self instead? If that was the case, then we could make &move FnOnce() be callable, as well as Box<FnOnce()> (via DerefMove).

    cc @arielb1 (RFC author) @qnighy (currently implementing this RFC in #51131) @eddyb (knows a lot about this stuff)

  8. eddyb commented on Jul 14, 2018

    @eddyb
    Contributor

    @mikeyhew There's not really much of a problem with making by-value self work and IMO it's more ergonomic anyway. We might eventually even have DerefMove without &move at all.

  9. mikeyhew commented on Jul 20, 2018

    @mikeyhew
    Contributor

    @eddyb

    I guess I can see why people think it's more ergonomic: in order to opt into it, you just have to add ?Sized to your function signature, or in the case of trait methods, do nothing. And maybe it will help new users of the language, since &move wouldn'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 &move references, 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 &move references. So

      fn call_once(f: FnOnce(i32))) -> i32

      desugars too

      fn call_once(f: &move FnOnce(i32)) -> i32

      and you can call the function directly on its argument, so foo(|x| x + 1) desugars to foo(&move (|x| x + 1)).

      And to do something fancier, you'd have to resort to the explicit version:

      fn make_owned_pin<'a, T: 'a + ?Sized>(value: &'a move T) -> PinMove<'a, T> { ... }
      
      struct Thunk<'a> {
          f: &'a move FnOnce()
      }

      Given the above semantics, DerefMove could 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?

      // this is the "closure" version of DerefMove. The alternative would be to have an associated type
      // `Cleanup` and return `(Self::Target, Self::Cleanup)`, but that wouldn't work with unsized
      // rvalues because you can't return a DST by value
      fn deref_move<F: FnOnce(Self::Target) -> O, O>(self, f: F) -> O;
      
      // explicit form
      fn deref_move<F: for<'a>FnOnce(&'a move Self::Target) -> O, O>(&'a move self, f: F) -> O;

      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.

  10. mikeyhew commented on Jul 20, 2018

    @mikeyhew
    Contributor

    @eddyb have you seen @alercah's RFC for DerefMove? rust-lang/rfcs#2439

  11. added a commit that references this issue on Aug 19, 2018
  12. qnighy commented on Aug 20, 2018

    @qnighy
    Contributor

    As a next step, I'll be working on trait object safety.

  13. alexreg commented on Aug 22, 2018

    @alexreg
    Contributor

    @mikeyhew Sadly @alercah just postponed their DerefMove RFC, but I think a separate RFC for &move that 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.

  14. 56 remaining items

  15. added
    S-tracking-needs-summaryStatus: It's hard to tell what's been done and what hasn't! Someone should do some investigation.
    on Mar 16, 2022
  16. Jules-Bertholet commented on May 5, 2023

    @Jules-Bertholet
    Contributor

    @rustbot label F-unsized_fn_params

  17. changed the title [-]Tracking issue for RFC #1909: Unsized Rvalues [/-] [+]Tracking issue for RFC #1909: Unsized Rvalues (unsized_locals, unsized_fn_params)[/+] on Nov 1, 2023
  18. RalfJung commented on Nov 1, 2023

    @RalfJung
    Member

    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.

  19. RalfJung commented on Dec 3, 2023

    @RalfJung
    Member

    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 like

    StorageLive(x); // allocates the memory for x
    x = Move(y); // copies the data from y to x
    

    However, when x is 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 understand StorageLive to 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.)

  20. SpriteOvO commented on Dec 3, 2023

    @SpriteOvO
  21. NobodyXu commented on Dec 3, 2023

    @NobodyXu
  22. RalfJung commented on Dec 3, 2023

    @RalfJung
  23. SpriteOvO commented on Dec 3, 2023

    @SpriteOvO
  24. added 2 commits that reference this issue on Nov 5, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    B-RFC-approvedBlocker: Approved by a merged RFC but not yet implemented.C-tracking-issueCategory: An issue tracking the progress of sth. like the implementation of an RFCF-unsized_fn_params`#![feature(unsized_fn_params)]`F-unsized_locals`#![feature(unsized_locals)]`S-tracking-design-concernsStatus: 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.T-langRelevant to the language team

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions