Skip to content

[BUG] Cannot return object of type by value #400

Closed

Description

@realgdman

Cpp1 error when trying to return object (by value?) from local variable

Code example
S : type = {
public x: int = 42;
}

baz: () -> _ = {
return S(); //ok cpp1: return S();
}
foo: () -> _ = {
//foo: () -> move _ = { //same behavior
s: S = ();
return s; //cpp1 error: see below
}

main: () = {
std::cout << baz().x;
std::cout << foo().x;
}

Actual result - cpp1 error

error: call to deleted constructor of 'typename std::remove_reference<S &>::type' (aka 'S')
return std::move(s);
note: 'S' has been explicitly marked deleted here
public: S(S const&) = delete;

Additional info
it is possible to return just constructed object like in baz()
Probably this is desired, but I dont see much difference why local cannot be returned here, and constructed object can.

Another note, it is working if type declared with @struct meta

Activity

  1. changed the title [-][BUG] Cannot return type by value[/-] [+][BUG] Cannot return object of type by value[/+] on May 1, 2023
  2. JohelEGP commented on May 1, 2023

    @JohelEGP
    Contributor

    The error is clear.
    See 10241cd:

    If the user didn't write a 'that' constructor, suppress Cpp1's compiler-generated copying and assignment

    So a @struct works because it is copyable.

  3. JohelEGP commented on May 1, 2023

    @JohelEGP
    Contributor

    See also https://wg21.link/P2573.
    Right now, public: S(S const&) = delete; appears in the error message,
    so a short comment can be appended as a stand-in for a proper error message.
    Recently, Clang or GCC started trimming source lines too long in error messages,
    so the comment should be short yet helpful.
    I suggest public: S(S const&) = delete; // No `that` constructor, suppressing.

  4. realgdman commented on May 1, 2023

    @realgdman
    Author

    Should baz() still work?

  5. JohelEGP commented on May 1, 2023

    @JohelEGP
    Contributor

    Yes. That looks OK.

  6. realgdman commented on May 1, 2023

    @realgdman
    Author

    Well I still not fully understand. Isn't foo() supposed to not copy, but move by cpp2 default? Error rises inside std::remove_reference which for me looks like some inner workings, not what I am expressing in cpp2.

  7. JohelEGP commented on May 1, 2023

    @JohelEGP
    Contributor

    Copy and move are an overload set.
    S doesn't implement a move constructor,
    so the deleted copy constructor is used.

  8. realgdman commented on May 1, 2023

    @realgdman
    Author

    I think baz() works in cpp1 because of guaranteed copy elision in cpp++17? It's still returning S which is not copyable.

    On other hand, in foo() cpp2 wraps return in std::move() behind scenes.
    Does that mean that I forced to write move constructor? Even if I don't want to change S type definition?
    Is there or should be a way to suppress move? I have tried declaring
    foo: () -> copy _ = {...} which gives

    error: only 'forward' and 'move' return passing style are allowed from functions (at 'copy')

    Also I tried return copy s or return (copy s) which is syntax error too.

  9. JohelEGP commented on May 1, 2023

    @JohelEGP
    Contributor

    I think baz() works in cpp1 because of guaranteed copy elision in cpp++17? It's still returning S which is not copyable.

    That's right. Returning a prvalue doesn't require copy/move.

    Does that mean that I forced to write move constructor?

    Or an in that operator= (copy constructor).

    Is there or should be a way to suppress move?

    That's subject of #231.
    Using x&* rather than x works: https://cpp2.godbolt.org/z/aY13c3GG6.
    Also using a function call like as-lvalue.
    See also #396.

  10. hsutter commented on May 5, 2023

    @hsutter
    Owner

    Thanks for the usability report, and I like the error message suggestion. Applied!

  11. added a commit that references this issue on Dec 5, 2023
    4fe8b3d
  12. added a commit that references this issue on Feb 4, 2024
    4d034f3
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

    bugSomething isn't working

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions