Skip to content

Commit d23ab39

Browse files
authored
Merge pull request #28589 from DougGregor/wrapper-type-default-init-crash
[Property wrappers] Fix crash due to wrapped type/wrapper type confusion
2 parents fb2346d + 36f67b2 commit d23ab39

File tree

9 files changed

+50
-32
lines changed

9 files changed

+50
-32
lines changed

include/swift/AST/Decl.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5102,16 +5102,16 @@ class VarDecl : public AbstractStorageDecl {
51025102
/// Retrieve the backing storage property for a lazy property.
51035103
VarDecl *getLazyStorageProperty() const;
51045104

5105-
/// Whether this is a property with a property wrapper that was initialized
5106-
/// via a value of the original type, e.g.,
5105+
/// Whether the memberwise initializer parameter for a property with a
5106+
/// property wrapper type uses the wrapped type. This will occur, for example,
5107+
/// when there is an explicitly-specified initializer like:
51075108
///
51085109
/// \code
51095110
/// @Lazy var i = 17
51105111
/// \end
5111-
bool isPropertyWrapperInitializedWithInitialValue() const;
5112-
5113-
/// Whether the memberwise initializer parameter for a property with a property wrapper type
5114-
/// uses the wrapped type.
5112+
///
5113+
/// Or when there is no initializer but each composed property wrapper has
5114+
/// a suitable `init(initialValue:)`.
51155115
bool isPropertyMemberwiseInitializedWithWrappedType() const;
51165116

51175117
/// If this property is the backing storage for a property with an attached

lib/AST/Decl.cpp

Lines changed: 6 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5807,13 +5807,12 @@ VarDecl *VarDecl::getLazyStorageProperty() const {
58075807
{});
58085808
}
58095809

5810-
static bool propertyWrapperInitializedViaInitialValue(
5811-
const VarDecl *var, bool checkDefaultInit) {
5812-
auto customAttrs = var->getAttachedPropertyWrappers();
5810+
bool VarDecl::isPropertyMemberwiseInitializedWithWrappedType() const {
5811+
auto customAttrs = getAttachedPropertyWrappers();
58135812
if (customAttrs.empty())
58145813
return false;
58155814

5816-
auto *PBD = var->getParentPatternBinding();
5815+
auto *PBD = getParentPatternBinding();
58175816
if (!PBD)
58185817
return false;
58195818

@@ -5828,23 +5827,12 @@ static bool propertyWrapperInitializedViaInitialValue(
58285827
return false;
58295828

58305829
// Default initialization does not use a value.
5831-
if (checkDefaultInit &&
5832-
var->getAttachedPropertyWrapperTypeInfo(0).defaultInit)
5830+
if (getAttachedPropertyWrapperTypeInfo(0).defaultInit)
58335831
return false;
58345832

5835-
// If all property wrappers have an initialValue initializer, the property
5833+
// If all property wrappers have a wrappedValue initializer, the property
58365834
// wrapper will be initialized that way.
5837-
return var->allAttachedPropertyWrappersHaveInitialValueInit();
5838-
}
5839-
5840-
bool VarDecl::isPropertyWrapperInitializedWithInitialValue() const {
5841-
return propertyWrapperInitializedViaInitialValue(
5842-
this, /*checkDefaultInit=*/true);
5843-
}
5844-
5845-
bool VarDecl::isPropertyMemberwiseInitializedWithWrappedType() const {
5846-
return propertyWrapperInitializedViaInitialValue(
5847-
this, /*checkDefaultInit=*/false);
5835+
return allAttachedPropertyWrappersHaveInitialValueInit();
58485836
}
58495837

58505838
Identifier VarDecl::getObjCPropertyName() const {

lib/SIL/TypeLowering.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1887,7 +1887,7 @@ static CanAnyFunctionType getStoredPropertyInitializerInterfaceType(
18871887
// wrapper that was initialized with '=', the stored property initializer
18881888
// will be in terms of the original property's type.
18891889
if (auto originalProperty = VD->getOriginalWrappedProperty()) {
1890-
if (originalProperty->isPropertyWrapperInitializedWithInitialValue())
1890+
if (originalProperty->isPropertyMemberwiseInitializedWithWrappedType())
18911891
resultTy = originalProperty->getValueInterfaceType()->getCanonicalType();
18921892
}
18931893

lib/SILGen/SILGen.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1115,8 +1115,8 @@ emitStoredPropertyInitialization(PatternBindingDecl *pbd, unsigned i) {
11151115
->isPropertyMemberwiseInitializedWithWrappedType()) {
11161116
auto wrapperInfo =
11171117
originalProperty->getPropertyWrapperBackingPropertyInfo();
1118-
if (wrapperInfo.originalInitialValue)
1119-
init = wrapperInfo.originalInitialValue;
1118+
assert(wrapperInfo.originalInitialValue);
1119+
init = wrapperInfo.originalInitialValue;
11201120
}
11211121
}
11221122

lib/SILGen/SILGenConstructor.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -899,7 +899,7 @@ static Type getInitializationTypeInContext(
899899
// initialization type is the original property type.
900900
if (auto singleVar = pattern->getSingleVar()) {
901901
if (auto originalProperty = singleVar->getOriginalWrappedProperty()) {
902-
if (originalProperty->isPropertyWrapperInitializedWithInitialValue())
902+
if (originalProperty->isPropertyMemberwiseInitializedWithWrappedType())
903903
interfaceType = originalProperty->getValueInterfaceType();
904904
}
905905
}
@@ -968,7 +968,7 @@ void SILGenFunction::emitMemberInitializers(DeclContext *dc,
968968
if (auto singleVar = pbd->getSingleVar()) {
969969
auto originalVar = singleVar->getOriginalWrappedProperty();
970970
if (originalVar &&
971-
originalVar->isPropertyWrapperInitializedWithInitialValue()) {
971+
originalVar->isPropertyMemberwiseInitializedWithWrappedType()) {
972972
result = maybeEmitPropertyWrapperInitFromValue(
973973
*this, init, singleVar, std::move(result));
974974
}

lib/SILGen/SILGenFunction.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -812,7 +812,7 @@ void SILGenFunction::emitGeneratorFunction(SILDeclRef function, VarDecl *var) {
812812
// wrapper that was initialized with '=', the stored property initializer
813813
// will be in terms of the original property's type.
814814
if (auto originalProperty = var->getOriginalWrappedProperty()) {
815-
if (originalProperty->isPropertyWrapperInitializedWithInitialValue()) {
815+
if (originalProperty->isPropertyMemberwiseInitializedWithWrappedType()) {
816816
interfaceType = originalProperty->getValueInterfaceType();
817817
varType = originalProperty->getType();
818818
}

lib/Sema/CodeSynthesis.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,8 @@ static void maybeAddMemberwiseDefaultArg(ParamDecl *arg, VarDecl *var,
145145
var->getAttrs().hasAttribute<LazyAttr>() ||
146146
(!isExplicitlyInitialized && isDefaultInitializable &&
147147
var->getValueInterfaceType()->getAnyNominal() == ctx.getOptionalDecl() &&
148-
!var->getAttachedPropertyWrapperTypeInfo(0).defaultInit);
148+
(var->getAttachedPropertyWrappers().empty() ||
149+
var->isPropertyMemberwiseInitializedWithWrappedType()));
149150
if (isNilInitialized) {
150151
arg->setDefaultArgumentKind(DefaultArgumentKind::NilLiteral);
151152
return;

test/IDE/print_property_wrappers.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ struct HasWrappers {
4747
var z: String
4848

4949
// Memberwise initializer.
50-
// CHECK: init(x: Wrapper<Int> = Wrapper(closure: foo), y: Bool = true, z: String = Wrapper())
50+
// CHECK: init(x: Wrapper<Int> = Wrapper(closure: foo), y: Bool = true, z: Wrapper<String> = Wrapper())
5151
}
5252

5353
func trigger() {

test/SILGen/property_wrappers.swift

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -541,6 +541,35 @@ struct SR_11603 {
541541
}
542542
}
543543

544+
// rdar://problem/57545381 - crash due to inconsistent decision about whether
545+
// to initialize a wrapper property with an instance of the wrapper type vs.
546+
// the wrapped type.
547+
@propertyWrapper
548+
class WrappedInt {
549+
var intValue: Int?
550+
551+
var wrappedValue: Int? {
552+
get {
553+
return intValue
554+
}
555+
set {
556+
intValue = newValue
557+
}
558+
}
559+
560+
init() { }
561+
562+
init(wrappedValue: Int?) {
563+
self.wrappedValue = wrappedValue
564+
}
565+
}
566+
567+
struct WrappedIntContainer {
568+
// CHECK: sil hidden [ossa] @$s17property_wrappers19WrappedIntContainerV3intAcA0cD0C_tcfcfA_ : $@convention(thin) () -> @owned WrappedInt
569+
@WrappedInt var int: Int?
570+
}
571+
572+
544573
// CHECK-LABEL: sil_vtable ClassUsingWrapper {
545574
// CHECK-NEXT: #ClassUsingWrapper.x!getter.1: (ClassUsingWrapper) -> () -> Int : @$s17property_wrappers17ClassUsingWrapperC1xSivg // ClassUsingWrapper.x.getter
546575
// CHECK-NEXT: #ClassUsingWrapper.x!setter.1: (ClassUsingWrapper) -> (Int) -> () : @$s17property_wrappers17ClassUsingWrapperC1xSivs // ClassUsingWrapper.x.setter

0 commit comments

Comments
 (0)