Skip to content

Commit 2ac8d7e

Browse files
committed
[ConstraintSystem] Add support for type checking an out-of-line
initialized wrapped property via SolutionApplicationTarget.
1 parent ebf01c9 commit 2ac8d7e

File tree

4 files changed

+118
-9
lines changed

4 files changed

+118
-9
lines changed

lib/Sema/CSApply.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8139,6 +8139,17 @@ ExprWalker::rewriteTarget(SolutionApplicationTarget target) {
81398139
patternBinding->setInit(index, resultTarget->getAsExpr());
81408140
}
81418141

8142+
return target;
8143+
} else if (auto *wrappedVar = target.getAsUninitializedWrappedVar()) {
8144+
// Get the outermost wrapper type from the solution
8145+
auto outermostWrapper = wrappedVar->getAttachedPropertyWrappers().front();
8146+
auto backingType = solution.simplifyType(
8147+
solution.getType(outermostWrapper->getTypeRepr()));
8148+
8149+
auto &ctx = solution.getConstraintSystem().getASTContext();
8150+
ctx.setSideCachedPropertyWrapperBackingPropertyType(
8151+
wrappedVar, backingType->mapTypeOutOfContext());
8152+
81428153
return target;
81438154
} else {
81448155
auto fn = *target.getAsFunction();
@@ -8419,6 +8430,9 @@ SolutionApplicationTarget SolutionApplicationTarget::walk(ASTWalker &walker) {
84198430

84208431
case Kind::patternBinding:
84218432
return *this;
8433+
8434+
case Kind::uninitializedWrappedVar:
8435+
return *this;
84228436
}
84238437

84248438
llvm_unreachable("invalid target kind");

lib/Sema/CSGen.cpp

Lines changed: 30 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3874,35 +3874,36 @@ static Expr *generateConstraintsFor(ConstraintSystem &cs, Expr *expr,
38743874
/// \param wrappedVar The property that has a property wrapper.
38753875
/// \returns the type of the property.
38763876
static Type generateWrappedPropertyTypeConstraints(
3877-
ConstraintSystem &cs, Type initializerType,
3878-
VarDecl *wrappedVar, ConstraintLocator *locator) {
3877+
ConstraintSystem &cs, Type initializerType, VarDecl *wrappedVar) {
38793878
auto dc = wrappedVar->getInnermostDeclContext();
38803879

38813880
Type wrapperType = LValueType::get(initializerType);
38823881
Type wrappedValueType;
38833882

3884-
for (unsigned i : indices(wrappedVar->getAttachedPropertyWrappers())) {
3883+
auto wrapperAttributes = wrappedVar->getAttachedPropertyWrappers();
3884+
for (unsigned i : indices(wrapperAttributes)) {
38853885
Type rawWrapperType = wrappedVar->getAttachedPropertyWrapperType(i);
3886-
if (!rawWrapperType || rawWrapperType->hasError())
3886+
auto wrapperInfo = wrappedVar->getAttachedPropertyWrapperTypeInfo(i);
3887+
if (rawWrapperType->hasError() || !wrapperInfo)
38873888
return Type();
38883889

38893890
// The former wrappedValue type must be equal to the current wrapper type
38903891
if (wrappedValueType) {
3892+
auto *typeRepr = wrapperAttributes[i]->getTypeRepr();
3893+
auto *locator =
3894+
cs.getConstraintLocator(typeRepr, LocatorPathElt::ContextualType());
38913895
wrapperType = cs.openUnboundGenericTypes(rawWrapperType, locator);
38923896
cs.addConstraint(ConstraintKind::Equal, wrappedValueType, wrapperType,
38933897
locator);
38943898
}
38953899

3896-
auto wrapperInfo = wrappedVar->getAttachedPropertyWrapperTypeInfo(i);
3897-
if (!wrapperInfo)
3898-
return Type();
3899-
39003900
wrappedValueType = wrapperType->getTypeOfMember(
39013901
dc->getParentModule(), wrapperInfo.valueVar);
39023902
}
39033903

39043904
// Set up an equality constraint to drop the lvalue-ness of the value
39053905
// type we produced.
3906+
auto locator = cs.getConstraintLocator(wrappedVar);
39063907
Type propertyType = cs.createTypeVariable(locator, 0);
39073908
cs.addConstraint(ConstraintKind::Equal, propertyType, wrappedValueType, locator);
39083909
return propertyType;
@@ -3922,7 +3923,7 @@ static bool generateInitPatternConstraints(
39223923

39233924
if (auto wrappedVar = target.getInitializationWrappedVar()) {
39243925
Type propertyType = generateWrappedPropertyTypeConstraints(
3925-
cs, cs.getType(target.getAsExpr()), wrappedVar, locator);
3926+
cs, cs.getType(target.getAsExpr()), wrappedVar);
39263927
if (!propertyType)
39273928
return true;
39283929

@@ -4165,6 +4166,26 @@ bool ConstraintSystem::generateConstraints(
41654166

41664167
return hadError;
41674168
}
4169+
4170+
case SolutionApplicationTarget::Kind::uninitializedWrappedVar: {
4171+
auto *wrappedVar = target.getAsUninitializedWrappedVar();
4172+
Type propertyType = wrappedVar->getType();
4173+
if (propertyType->hasError())
4174+
return true;
4175+
4176+
auto *outermostWrapper = wrappedVar->getAttachedPropertyWrappers().front();
4177+
auto *typeRepr = outermostWrapper->getTypeRepr();
4178+
auto backingType = openUnboundGenericTypes(outermostWrapper->getType(),
4179+
getConstraintLocator(typeRepr));
4180+
setType(typeRepr, backingType);
4181+
4182+
auto wrappedValueType =
4183+
generateWrappedPropertyTypeConstraints(*this, backingType, wrappedVar);
4184+
4185+
addConstraint(ConstraintKind::Equal, propertyType, wrappedValueType,
4186+
getConstraintLocator(wrappedVar, LocatorPathElt::ContextualType()));
4187+
return false;
4188+
}
41684189
}
41694190
}
41704191

lib/Sema/ConstraintSystem.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4674,6 +4674,11 @@ SolutionApplicationTarget SolutionApplicationTarget::forForEachStmt(
46744674
return target;
46754675
}
46764676

4677+
SolutionApplicationTarget
4678+
SolutionApplicationTarget::forUninitializedWrappedVar(VarDecl *wrappedVar) {
4679+
return SolutionApplicationTarget(wrappedVar);
4680+
}
4681+
46774682
ContextualPattern
46784683
SolutionApplicationTarget::getContextualPattern() const {
46794684
assert(kind == Kind::expression);
@@ -4781,6 +4786,18 @@ void ConstraintSystem::diagnoseFailureFor(SolutionApplicationTarget target) {
47814786
// diagnostic various cases that come up.
47824787
DE.diagnose(expr->getLoc(), diag::type_of_expression_is_ambiguous)
47834788
.highlight(expr->getSourceRange());
4789+
} else if (auto *wrappedVar = target.getAsUninitializedWrappedVar()) {
4790+
auto *wrapper = wrappedVar->getAttachedPropertyWrappers().back();
4791+
Type propertyType = wrappedVar->getInterfaceType();
4792+
Type wrapperType = wrapper->getType();
4793+
4794+
// Emit the property wrapper fallback diagnostic
4795+
wrappedVar->diagnose(diag::property_wrapper_incompatible_property,
4796+
propertyType, wrapperType);
4797+
if (auto nominal = wrapperType->getAnyNominal()) {
4798+
nominal->diagnose(diag::property_wrapper_declared_here,
4799+
nominal->getName());
4800+
}
47844801
} else {
47854802
// Emit a poor fallback message.
47864803
DE.diagnose(target.getAsFunction()->getLoc(),

lib/Sema/ConstraintSystem.h

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -856,6 +856,7 @@ class SolutionApplicationTargetsKey {
856856
stmtCondElement,
857857
stmt,
858858
patternBindingEntry,
859+
varDecl,
859860
};
860861

861862
private:
@@ -870,6 +871,8 @@ class SolutionApplicationTargetsKey {
870871
const PatternBindingDecl *patternBinding;
871872
unsigned index;
872873
} patternBindingEntry;
874+
875+
const VarDecl *varDecl;
873876
} storage;
874877

875878
public:
@@ -895,6 +898,11 @@ class SolutionApplicationTargetsKey {
895898
storage.patternBindingEntry.index = index;
896899
}
897900

901+
SolutionApplicationTargetsKey(const VarDecl *varDecl) {
902+
kind = Kind::varDecl;
903+
storage.varDecl = varDecl;
904+
}
905+
898906
friend bool operator==(
899907
SolutionApplicationTargetsKey lhs, SolutionApplicationTargetsKey rhs) {
900908
if (lhs.kind != rhs.kind)
@@ -916,6 +924,9 @@ class SolutionApplicationTargetsKey {
916924
== rhs.storage.patternBindingEntry.patternBinding) &&
917925
(lhs.storage.patternBindingEntry.index
918926
== rhs.storage.patternBindingEntry.index);
927+
928+
case Kind::varDecl:
929+
return lhs.storage.varDecl == rhs.storage.varDecl;
919930
}
920931
llvm_unreachable("invalid SolutionApplicationTargetsKey kind");
921932
}
@@ -951,6 +962,11 @@ class SolutionApplicationTargetsKey {
951962
storage.patternBindingEntry.patternBinding),
952963
DenseMapInfo<unsigned>::getHashValue(
953964
storage.patternBindingEntry.index));
965+
966+
case Kind::varDecl:
967+
return hash_combine(
968+
DenseMapInfo<unsigned>::getHashValue(static_cast<unsigned>(kind)),
969+
DenseMapInfo<void *>::getHashValue(storage.varDecl));
954970
}
955971
llvm_unreachable("invalid statement kind");
956972
}
@@ -1343,6 +1359,7 @@ class SolutionApplicationTarget {
13431359
stmtCondition,
13441360
caseLabelItem,
13451361
patternBinding,
1362+
uninitializedWrappedVar,
13461363
} kind;
13471364

13481365
private:
@@ -1409,6 +1426,8 @@ class SolutionApplicationTarget {
14091426
} caseLabelItem;
14101427

14111428
PatternBindingDecl *patternBinding;
1429+
1430+
VarDecl *uninitializedWrappedVar;
14121431
};
14131432

14141433
// If the pattern contains a single variable that has an attached
@@ -1454,6 +1473,11 @@ class SolutionApplicationTarget {
14541473
this->patternBinding = patternBinding;
14551474
}
14561475

1476+
SolutionApplicationTarget(VarDecl *wrappedVar) {
1477+
kind = Kind::uninitializedWrappedVar;
1478+
this->uninitializedWrappedVar= wrappedVar;
1479+
}
1480+
14571481
/// Form a target for the initialization of a pattern from an expression.
14581482
static SolutionApplicationTarget forInitialization(
14591483
Expr *initializer, DeclContext *dc, Type patternType, Pattern *pattern,
@@ -1471,6 +1495,11 @@ class SolutionApplicationTarget {
14711495
ForEachStmt *stmt, ProtocolDecl *sequenceProto, DeclContext *dc,
14721496
bool bindPatternVarsOneWay);
14731497

1498+
/// Form a target for a property with an attached property wrapper that is
1499+
/// initialized out-of-line.
1500+
static SolutionApplicationTarget forUninitializedWrappedVar(
1501+
VarDecl *wrappedVar);
1502+
14741503
Expr *getAsExpr() const {
14751504
switch (kind) {
14761505
case Kind::expression:
@@ -1480,6 +1509,7 @@ class SolutionApplicationTarget {
14801509
case Kind::stmtCondition:
14811510
case Kind::caseLabelItem:
14821511
case Kind::patternBinding:
1512+
case Kind::uninitializedWrappedVar:
14831513
return nullptr;
14841514
}
14851515
llvm_unreachable("invalid expression type");
@@ -1501,6 +1531,9 @@ class SolutionApplicationTarget {
15011531

15021532
case Kind::patternBinding:
15031533
return patternBinding->getDeclContext();
1534+
1535+
case Kind::uninitializedWrappedVar:
1536+
return uninitializedWrappedVar->getDeclContext();
15041537
}
15051538
llvm_unreachable("invalid decl context type");
15061539
}
@@ -1653,6 +1686,7 @@ class SolutionApplicationTarget {
16531686
case Kind::stmtCondition:
16541687
case Kind::caseLabelItem:
16551688
case Kind::patternBinding:
1689+
case Kind::uninitializedWrappedVar:
16561690
return None;
16571691

16581692
case Kind::function:
@@ -1667,6 +1701,7 @@ class SolutionApplicationTarget {
16671701
case Kind::function:
16681702
case Kind::caseLabelItem:
16691703
case Kind::patternBinding:
1704+
case Kind::uninitializedWrappedVar:
16701705
return None;
16711706

16721707
case Kind::stmtCondition:
@@ -1681,6 +1716,7 @@ class SolutionApplicationTarget {
16811716
case Kind::function:
16821717
case Kind::stmtCondition:
16831718
case Kind::patternBinding:
1719+
case Kind::uninitializedWrappedVar:
16841720
return None;
16851721

16861722
case Kind::caseLabelItem:
@@ -1695,13 +1731,28 @@ class SolutionApplicationTarget {
16951731
case Kind::function:
16961732
case Kind::stmtCondition:
16971733
case Kind::caseLabelItem:
1734+
case Kind::uninitializedWrappedVar:
16981735
return nullptr;
16991736

17001737
case Kind::patternBinding:
17011738
return patternBinding;
17021739
}
17031740
}
17041741

1742+
VarDecl *getAsUninitializedWrappedVar() const {
1743+
switch (kind) {
1744+
case Kind::expression:
1745+
case Kind::function:
1746+
case Kind::stmtCondition:
1747+
case Kind::caseLabelItem:
1748+
case Kind::patternBinding:
1749+
return nullptr;
1750+
1751+
case Kind::uninitializedWrappedVar:
1752+
return uninitializedWrappedVar;
1753+
}
1754+
}
1755+
17051756
BraceStmt *getFunctionBody() const {
17061757
assert(kind == Kind::function);
17071758
return function.body;
@@ -1730,6 +1781,9 @@ class SolutionApplicationTarget {
17301781

17311782
case Kind::patternBinding:
17321783
return patternBinding->getSourceRange();
1784+
1785+
case Kind::uninitializedWrappedVar:
1786+
return uninitializedWrappedVar->getSourceRange();
17331787
}
17341788
llvm_unreachable("invalid target type");
17351789
}
@@ -1751,6 +1805,9 @@ class SolutionApplicationTarget {
17511805

17521806
case Kind::patternBinding:
17531807
return patternBinding->getLoc();
1808+
1809+
case Kind::uninitializedWrappedVar:
1810+
return uninitializedWrappedVar->getLoc();
17541811
}
17551812
llvm_unreachable("invalid target type");
17561813
}

0 commit comments

Comments
 (0)