[SE-0400] All properties with init accessors become part of the memberwise init

Per the clarification during the review thread, all properties with
init accessors (including those that do not initialize any underlying
storage) are part of the memberwise initializer.
This commit is contained in:
Doug Gregor
2023-06-27 17:28:53 -07:00
parent bd11fceff5
commit fe2dec5ee5
5 changed files with 6 additions and 9 deletions

View File

@@ -7180,7 +7180,7 @@ bool VarDecl::isMemberwiseInitialized(bool preferDeclaredProperties) const {
// other stored properties.
if (hasInitAccessor()) {
if (auto *init = getAccessor(AccessorKind::Init))
return init->getAttrs().hasAttribute<InitializesAttr>();
return true;
}
// If this is a computed property, it's not memberwise initialized unless

View File

@@ -360,6 +360,7 @@ static void emitImplicitValueConstructor(SILGenFunction &SGF,
decl->collectPropertiesInitializableByInitAccessors(initializedViaAccessor);
// Emit the indirect return argument, if any.
bool hasInitAccessors = !decl->getInitAccessorProperties().empty();
SILValue resultSlot;
if (selfTy.isAddress()) {
auto &AC = SGF.getASTContext();
@@ -371,7 +372,7 @@ static void emitImplicitValueConstructor(SILGenFunction &SGF,
VD->setSpecifier(ParamSpecifier::InOut);
VD->setInterfaceType(selfIfaceTy);
resultSlot = SGF.F.begin()->createFunctionArgument(selfTy, VD);
} else if (!initializedViaAccessor.empty()) {
} else if (hasInitAccessors) {
// Allocate "self" on stack which we are going to use to
// reference/init fields and then load to return.
resultSlot = SGF.emitTemporaryAllocation(Loc, selfTy);
@@ -504,7 +505,7 @@ static void emitImplicitValueConstructor(SILGenFunction &SGF,
}
// Load as "take" from our stack allocation and return.
if (!selfTy.isAddress() && !initializedViaAccessor.empty()) {
if (!selfTy.isAddress() && hasInitAccessors) {
auto resultValue = SGF.B.emitLoadValueOperation(
Loc, resultSlot, LoadOwnershipQualifier::Take);

View File

@@ -1300,10 +1300,6 @@ HasMemberwiseInitRequest::evaluate(Evaluator &evaluator,
if (!var->isMemberwiseInitialized(/*preferDeclaredProperties=*/true))
continue;
// If init accessors are not involved, we are done.
if (initializedViaAccessor.empty())
return true;
// Check whether use of init accessors results in access to uninitialized
// properties.

View File

@@ -385,7 +385,7 @@ func test_memberwise_ordering() {
var _c: Int
}
let test3 = Test3(_a: 1, _b: 2, _c: 3)
let test3 = Test3(_a: 1, _b: 2, pair: (1, 2), _c: 3)
print("test-memberwise-ordering-3: \(test3)")
}

View File

@@ -425,7 +425,7 @@ func test_memberwise_ordering() {
var _c: Int
}
_ = Test4(_a: 0, _b: 1, _c: 2) // Ok
_ = Test4(_a: 0, _b: 1, pair: (1, 2), _c: 2) // Ok
struct Test5 {
var _a: Int