Skip to content

[BUG] Converting assignment generated from non-converting constructor #468

Closed
@JohelEGP

Description

@JohelEGP

Title: Converting assignment generated from non-converting constructor.

Description:

Relevant extracts from https://github.com/hsutter/cppfront/wiki/Cpp2:-operator=,-this-&-that
always talk about generating converting assignment from a converting constructor,
but cppfront currently generate converting assignment from an explicit constructor.

  • implicit: On a two-parameter operator= function, writing operator=: (implicit out this, /*...*/) defines a conversion function that can be used to perform implicit conversions to this type.

operator= is the generalized name for all value-setting functions, including the six combinations of { copy, move, converting } x { constructors, assignment operators }.

Note: The concept of a converting assignment operator is first-class in Cpp2, and makes this 3x2 matrix of options symmetric. In Cpp1, it's common to write a converting constructor from some other type, but not an assignment operator from that other type, which leads to asymmetries like mytype var = other; working but var = other; not working.

  • (A)ssignment, A1, A2, A3: If you write a copy or move or converting constructor, but not a corresponding copy or move or converting assignment operator, the latter is generated.

Note: Generating inout this (assignment) from out this also generates converting assignment from converting construction, which is a new thing. Today in Cpp1, if you write a converting constructor from another type X, you may or may not write the corresponding assignment from X; in Cpp2 you will get that by default, and it sets the object to the same state as the converting constructor from X does.

Minimal reproducer (https://cpp2.godbolt.org/z/zzK9qc4Gx):

quantity: type = {
  value: int = ();
  operator=: (out this, val: int) = { value = val; }
}

main: () = {
  x := quantity(0);
  x = 1;
}
Commands:
cppfront -clean-cpp1 main.cpp2
clang++17 -std=c++2b -stdlib=libc++ -lc++abi -pedantic-errors -Wall -Wextra -Wconversion -I . main.cpp

Expected result:

An error at:

  x = 1;

Actual result and error:

Cpp2 lowered to Cpp1.
#include "cpp2util.h"

class quantity;
  
class quantity {
  private: int value {}; 
  public: explicit quantity(cpp2::in<int> val);
  public: auto operator=(cpp2::in<int> val) -> quantity& ;

  public: quantity(quantity const&) = delete; /* No 'that' constructor, suppress copy */
  public: auto operator=(quantity const&) -> void = delete;
};

auto main() -> int;
  

  quantity::quantity(cpp2::in<int> val)
                                      : value{ val }
  {}
  auto quantity::operator=(cpp2::in<int> val) -> quantity& {
                                      value = val;
                                      return *this;
  }

auto main() -> int{
  auto x {quantity(0)}; 
  x = 1;
}

Output:

Program returned: 0

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions