Skip to content

Commit 493bed0

Browse files
committed
[Property wrappers] Fix crash due to wrapped type/wrapper type confusion.
We had two predicates that were used to determine whether the default argument for a wrapped property in the memberwise initializer would be of the wrapper type (e.g., Lazy<Int>) vs. the wrapped type (Int). Those two predicates could disagree, causing a SILGen assertion and crash. Collapse the two predicates into one correct one, fixing rdar://problem/57545381.
1 parent e5ea69c commit 493bed0

File tree

6 files changed

+44
-27
lines changed

6 files changed

+44
-27
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: 5 additions & 17 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

58355833
// If all property wrappers have an initialValue 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/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
}

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)