Skip to content

Commit 69510b3

Browse files
committed
[CS] Clean up some property wrapper logic
These methods can be simplified a bunch since the returned decl is always the input decl and we can refactor the lambdas to just return the auxiliary variable and have the type computation in the caller.
1 parent 074480e commit 69510b3

File tree

4 files changed

+68
-84
lines changed

4 files changed

+68
-84
lines changed

include/swift/Sema/ConstraintSystem.h

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3969,21 +3969,18 @@ class ConstraintSystem {
39693969
isRepresentativeFor(TypeVariableType *typeVar,
39703970
ConstraintLocator::PathElementKind kind) const;
39713971

3972-
/// Gets the VarDecl associated with resolvedOverload, and the type of the
3973-
/// projection if the decl has an associated property wrapper with a projectedValue.
3974-
std::optional<std::pair<VarDecl *, Type>>
3975-
getPropertyWrapperProjectionInfo(SelectedOverload resolvedOverload);
3972+
/// Gets the the type of the projection if the decl has an associated property
3973+
/// wrapper with a projectedValue.
3974+
Type getPropertyWrapperProjectionType(SelectedOverload resolvedOverload);
39763975

3977-
/// Gets the VarDecl associated with resolvedOverload, and the type of the
3978-
/// backing storage if the decl has an associated property wrapper.
3979-
std::optional<std::pair<VarDecl *, Type>>
3980-
getPropertyWrapperInformation(SelectedOverload resolvedOverload);
3976+
/// Gets the type of the backing storage if the decl has an associated
3977+
/// property wrapper.
3978+
Type getPropertyWrapperBackingType(SelectedOverload resolvedOverload);
39813979

39823980
/// Gets the VarDecl, and the type of the type property that it wraps if
39833981
/// resolved overload has a decl which is the backing storage for a
39843982
/// property wrapper.
3985-
std::optional<std::pair<VarDecl *, Type>>
3986-
getWrappedPropertyInformation(SelectedOverload resolvedOverload);
3983+
Type getWrappedPropertyType(SelectedOverload resolvedOverload);
39873984

39883985
/// Merge the equivalence sets of the two type variables.
39893986
///

lib/Sema/CSSimplify.cpp

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4825,14 +4825,19 @@ static ConstraintFix *fixPropertyWrapperFailure(
48254825
if (!resolvedOverload)
48264826
return nullptr;
48274827

4828+
auto *decl = resolvedOverload->choice.getDeclOrNull();
4829+
auto *VD = dyn_cast_or_null<VarDecl>(decl);
4830+
if (!VD)
4831+
return nullptr;
4832+
48284833
enum class Fix : uint8_t {
48294834
ProjectedValue,
48304835
PropertyWrapper,
48314836
WrappedValue,
48324837
};
48334838

4834-
auto applyFix = [&](Fix fix, VarDecl *decl, Type type) -> ConstraintFix * {
4835-
if (!decl->hasInterfaceType() || !type)
4839+
auto applyFix = [&](Fix fix, Type type) -> ConstraintFix * {
4840+
if (!VD->hasInterfaceType() || !type)
48364841
return nullptr;
48374842

48384843
if (baseTy->isEqual(type))
@@ -4841,40 +4846,34 @@ static ConstraintFix *fixPropertyWrapperFailure(
48414846
if (baseTy->is<TypeVariableType>() || type->is<TypeVariableType>())
48424847
return nullptr;
48434848

4844-
if (!attemptFix(*resolvedOverload, decl, type))
4849+
if (!attemptFix(*resolvedOverload, VD, type))
48454850
return nullptr;
48464851

48474852
switch (fix) {
48484853
case Fix::ProjectedValue:
48494854
case Fix::PropertyWrapper:
4850-
return UsePropertyWrapper::create(cs, decl, fix == Fix::ProjectedValue,
4851-
baseTy, toType.value_or(type),
4852-
locator);
4855+
return UsePropertyWrapper::create(cs, VD, fix == Fix::ProjectedValue,
4856+
baseTy, toType.value_or(type), locator);
48534857

48544858
case Fix::WrappedValue:
4855-
return UseWrappedValue::create(cs, decl, baseTy, toType.value_or(type),
4859+
return UseWrappedValue::create(cs, VD, baseTy, toType.value_or(type),
48564860
locator);
48574861
}
48584862
llvm_unreachable("Unhandled Fix type in switch");
48594863
};
48604864

4861-
if (auto projection =
4862-
cs.getPropertyWrapperProjectionInfo(*resolvedOverload)) {
4863-
if (auto *fix = applyFix(Fix::ProjectedValue, projection->first,
4864-
projection->second))
4865+
if (auto projectTy = cs.getPropertyWrapperProjectionType(*resolvedOverload)) {
4866+
if (auto *fix = applyFix(Fix::ProjectedValue, projectTy))
48654867
return fix;
48664868
}
48674869

4868-
if (auto wrapper = cs.getPropertyWrapperInformation(*resolvedOverload)) {
4869-
if (auto *fix =
4870-
applyFix(Fix::PropertyWrapper, wrapper->first, wrapper->second))
4870+
if (auto backingTy = cs.getPropertyWrapperBackingType(*resolvedOverload)) {
4871+
if (auto *fix = applyFix(Fix::PropertyWrapper, backingTy))
48714872
return fix;
48724873
}
48734874

4874-
if (auto wrappedProperty =
4875-
cs.getWrappedPropertyInformation(*resolvedOverload)) {
4876-
if (auto *fix = applyFix(Fix::WrappedValue, wrappedProperty->first,
4877-
wrappedProperty->second))
4875+
if (auto wrappedTy = cs.getWrappedPropertyType(*resolvedOverload)) {
4876+
if (auto *fix = applyFix(Fix::WrappedValue, wrappedTy))
48784877
return fix;
48794878
}
48804879

lib/Sema/ConstraintSystem.cpp

Lines changed: 35 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1244,72 +1244,51 @@ TypeVariableType *ConstraintSystem::isRepresentativeFor(
12441244
return *member;
12451245
}
12461246

1247-
static std::optional<std::pair<VarDecl *, Type>>
1248-
getPropertyWrapperInformationFromOverload(
1249-
SelectedOverload resolvedOverload, DeclContext *DC,
1250-
llvm::function_ref<std::optional<std::pair<VarDecl *, Type>>(VarDecl *)>
1251-
getInformation) {
1252-
if (auto *decl =
1253-
dyn_cast_or_null<VarDecl>(resolvedOverload.choice.getDeclOrNull())) {
1254-
if (auto declInformation = getInformation(decl)) {
1255-
Type type;
1256-
VarDecl *memberDecl;
1257-
std::tie(memberDecl, type) = *declInformation;
1258-
if (Type baseType = resolvedOverload.choice.getBaseType()) {
1259-
type = baseType->getRValueType()->getTypeOfMember(memberDecl, type);
1260-
}
1261-
return std::make_pair(decl, type);
1262-
}
1263-
}
1264-
return std::nullopt;
1265-
}
1247+
static Type getPropertyWrapperTypeFromOverload(
1248+
ConstraintSystem &cs, SelectedOverload resolvedOverload,
1249+
llvm::function_ref<VarDecl *(VarDecl *)> getWrapperVar) {
1250+
auto *D = dyn_cast_or_null<VarDecl>(resolvedOverload.choice.getDeclOrNull());
1251+
if (!D)
1252+
return Type();
12661253

1267-
std::optional<std::pair<VarDecl *, Type>>
1268-
ConstraintSystem::getPropertyWrapperProjectionInfo(
1269-
SelectedOverload resolvedOverload) {
1270-
return getPropertyWrapperInformationFromOverload(
1271-
resolvedOverload, DC,
1272-
[](VarDecl *decl) -> std::optional<std::pair<VarDecl *, Type>> {
1273-
if (!decl->hasAttachedPropertyWrapper())
1274-
return std::nullopt;
1254+
auto *wrapperVar = getWrapperVar(D);
1255+
if (!wrapperVar)
1256+
return Type();
12751257

1276-
auto projectionVar = decl->getPropertyWrapperProjectionVar();
1277-
if (!projectionVar)
1278-
return std::nullopt;
1258+
// For the backing property we need to query the request to ensure it kicks
1259+
// type-checking if necessary. Otherwise we can query the interface type.
1260+
auto ty = wrapperVar == D->getPropertyWrapperBackingProperty()
1261+
? D->getPropertyWrapperBackingPropertyType()
1262+
: wrapperVar->getInterfaceType();
1263+
if (!ty)
1264+
return Type();
12791265

1280-
return std::make_pair(projectionVar,
1281-
projectionVar->getInterfaceType());
1282-
});
1266+
// If this is a for a property, substitute the base type.
1267+
if (auto baseType = resolvedOverload.choice.getBaseType())
1268+
ty = baseType->getRValueType()->getTypeOfMember(wrapperVar, ty);
1269+
1270+
return ty;
12831271
}
12841272

1285-
std::optional<std::pair<VarDecl *, Type>>
1286-
ConstraintSystem::getPropertyWrapperInformation(
1273+
Type ConstraintSystem::getPropertyWrapperProjectionType(
12871274
SelectedOverload resolvedOverload) {
1288-
return getPropertyWrapperInformationFromOverload(
1289-
resolvedOverload, DC,
1290-
[](VarDecl *decl) -> std::optional<std::pair<VarDecl *, Type>> {
1291-
if (!decl->hasAttachedPropertyWrapper())
1292-
return std::nullopt;
1293-
1294-
auto backingTy = decl->getPropertyWrapperBackingPropertyType();
1295-
if (!backingTy)
1296-
return std::nullopt;
1297-
1298-
return std::make_pair(decl, backingTy);
1299-
});
1275+
return getPropertyWrapperTypeFromOverload(
1276+
*this, resolvedOverload,
1277+
[&](VarDecl *decl) { return decl->getPropertyWrapperProjectionVar(); });
13001278
}
13011279

1302-
std::optional<std::pair<VarDecl *, Type>>
1303-
ConstraintSystem::getWrappedPropertyInformation(
1280+
Type ConstraintSystem::getPropertyWrapperBackingType(
13041281
SelectedOverload resolvedOverload) {
1305-
return getPropertyWrapperInformationFromOverload(
1306-
resolvedOverload, DC,
1307-
[](VarDecl *decl) -> std::optional<std::pair<VarDecl *, Type>> {
1308-
if (auto wrapped = decl->getOriginalWrappedProperty())
1309-
return std::make_pair(decl, wrapped->getInterfaceType());
1282+
return getPropertyWrapperTypeFromOverload(
1283+
*this, resolvedOverload,
1284+
[](VarDecl *decl) { return decl->getPropertyWrapperBackingProperty(); });
1285+
}
13101286

1311-
return std::nullopt;
1312-
});
1287+
Type ConstraintSystem::getWrappedPropertyType(
1288+
SelectedOverload resolvedOverload) {
1289+
return getPropertyWrapperTypeFromOverload(
1290+
*this, resolvedOverload,
1291+
[](VarDecl *decl) { return decl->getOriginalWrappedProperty(); });
13131292
}
13141293

13151294
void ConstraintSystem::addOverloadSet(Type boundType,

test/decl/var/property_wrappers.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1346,6 +1346,15 @@ struct MissingPropertyWrapperUnwrap {
13461346
}
13471347
}
13481348

1349+
_ = {
1350+
struct S {
1351+
@WrapperWithInitialValue var x = 0
1352+
init() {}
1353+
}
1354+
func a<T>(_: WrapperWithInitialValue<T>) {}
1355+
a(S().x) // expected-error {{cannot convert value 'x' of type 'Int' to expected type 'WrapperWithInitialValue<Int>', use wrapper instead}} {{9-9=_}}
1356+
}
1357+
13491358
struct InvalidPropertyDelegateUse {
13501359
// TODO(diagnostics): We need to a tailored diagnostic for extraneous arguments in property delegate initialization
13511360
@Foo var x: Int = 42 // expected-error@:21 {{extra argument 'wrappedValue' in call}}

0 commit comments

Comments
 (0)