Skip to content

Commit 06196e0

Browse files
authored
Merge pull request swiftlang#30496 from DougGregor/contextual-pattern-binding-decl
[Constraint system] Use the PatternBindingDecl context when possible.
2 parents faec586 + f2e581c commit 06196e0

File tree

7 files changed

+108
-24
lines changed

7 files changed

+108
-24
lines changed

lib/Sema/CSApply.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7788,7 +7788,9 @@ static Optional<SolutionApplicationTarget> applySolutionToInitialization(
77887788
TypeResolutionOptions options =
77897789
isa<EditorPlaceholderExpr>(initializer->getSemanticsProvidingExpr())
77907790
? TypeResolverContext::EditorPlaceholderExpr
7791-
: TypeResolverContext::InExpression;
7791+
: target.getInitializationPatternBindingDecl()
7792+
? TypeResolverContext::PatternBindingDecl
7793+
: TypeResolverContext::InExpression;
77927794
options |= TypeResolutionFlags::OverrideType;
77937795

77947796
// Determine the type of the pattern.
@@ -7804,9 +7806,7 @@ static Optional<SolutionApplicationTarget> applySolutionToInitialization(
78047806
finalPatternType = finalPatternType->reconstituteSugar(/*recursive =*/false);
78057807

78067808
// Apply the solution to the pattern as well.
7807-
auto contextualPattern =
7808-
ContextualPattern::forRawPattern(target.getInitializationPattern(),
7809-
target.getDeclContext());
7809+
auto contextualPattern = target.getInitializationContextualPattern();
78107810
if (auto coercedPattern = TypeChecker::coercePatternToType(
78117811
contextualPattern, finalPatternType, options)) {
78127812
resultTarget.setPattern(coercedPattern);

lib/Sema/CSGen.cpp

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2225,9 +2225,12 @@ namespace {
22252225
/// for the types of each variable declared within the pattern, along
22262226
/// with a one-way constraint binding that to the type to which the
22272227
/// variable will be ascribed or inferred.
2228-
Type getTypeForPattern(Pattern *pattern, ConstraintLocatorBuilder locator,
2229-
Type externalPatternType,
2230-
bool bindPatternVarsOneWay) {
2228+
Type getTypeForPattern(
2229+
Pattern *pattern, ConstraintLocatorBuilder locator,
2230+
Type externalPatternType,
2231+
bool bindPatternVarsOneWay,
2232+
PatternBindingDecl *patternBinding = nullptr,
2233+
unsigned patternBindingIndex = 0) {
22312234
// If there's no pattern, then we have an unknown subpattern. Create a
22322235
// type variable.
22332236
if (!pattern) {
@@ -2319,9 +2322,16 @@ namespace {
23192322
case PatternKind::Typed: {
23202323
// FIXME: Need a better locator for a pattern as a base.
23212324
// Compute the type ascribed to the pattern.
2322-
auto contextualPattern =
2323-
ContextualPattern::forRawPattern(pattern, CurDC);
2325+
auto contextualPattern = patternBinding
2326+
? ContextualPattern::forPatternBindingDecl(
2327+
patternBinding, patternBindingIndex)
2328+
: ContextualPattern::forRawPattern(pattern, CurDC);
2329+
23242330
Type type = TypeChecker::typeCheckPattern(contextualPattern);
2331+
2332+
// Look through reference storage types.
2333+
type = type->getReferenceStorageReferent();
2334+
23252335
Type openedType = CS.openUnboundGenericType(type, locator);
23262336

23272337
// Determine the subpattern type. It will be convertible to the
@@ -4097,7 +4107,9 @@ static bool generateInitPatternConstraints(
40974107
auto locator =
40984108
cs.getConstraintLocator(initializer, LocatorPathElt::ContextualType());
40994109
Type patternType = cs.generateConstraints(
4100-
pattern, locator, target.shouldBindPatternVarsOneWay());
4110+
pattern, locator, target.shouldBindPatternVarsOneWay(),
4111+
target.getInitializationPatternBindingDecl(),
4112+
target.getInitializationPatternBindingIndex());
41014113
assert(patternType && "All patterns have a type");
41024114

41034115
if (auto wrappedVar = target.getInitializationWrappedVar()) {
@@ -4199,11 +4211,13 @@ Expr *ConstraintSystem::generateConstraints(Expr *expr, DeclContext *dc) {
41994211
return generateConstraintsFor(*this, expr, dc);
42004212
}
42014213

4202-
Type ConstraintSystem::generateConstraints(Pattern *pattern,
4203-
ConstraintLocatorBuilder locator,
4204-
bool bindPatternVarsOneWay) {
4214+
Type ConstraintSystem::generateConstraints(
4215+
Pattern *pattern, ConstraintLocatorBuilder locator,
4216+
bool bindPatternVarsOneWay, PatternBindingDecl *patternBinding,
4217+
unsigned patternIndex) {
42054218
ConstraintGenerator cg(*this, nullptr);
4206-
return cg.getTypeForPattern(pattern, locator, Type(), bindPatternVarsOneWay);
4219+
return cg.getTypeForPattern(pattern, locator, Type(), bindPatternVarsOneWay,
4220+
patternBinding, patternIndex);
42074221
}
42084222

42094223
bool ConstraintSystem::generateConstraints(StmtCondition condition,
@@ -4276,7 +4290,8 @@ bool ConstraintSystem::generateConstraints(
42764290
// any variables that show up in this pattern, because those variables
42774291
// can be referenced in the guard expressions and the body.
42784292
Type patternType = generateConstraints(
4279-
pattern, locator, /* bindPatternVarsOneWay=*/true);
4293+
pattern, locator, /* bindPatternVarsOneWay=*/true,
4294+
/*patternBinding=*/nullptr, /*patternBindingIndex=*/0);
42804295

42814296
// Convert the subject type to the pattern, which establishes the
42824297
// bindings.

lib/Sema/ConstraintSystem.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4160,6 +4160,8 @@ SolutionApplicationTarget::SolutionApplicationTarget(
41604160
expression.wrappedVar = nullptr;
41614161
expression.isDiscarded = isDiscarded;
41624162
expression.bindPatternVarsOneWay = false;
4163+
expression.patternBinding = nullptr;
4164+
expression.patternBindingIndex = 0;
41634165
}
41644166

41654167
void SolutionApplicationTarget::maybeApplyPropertyWrapper() {
@@ -4242,6 +4244,30 @@ SolutionApplicationTarget SolutionApplicationTarget::forInitialization(
42424244
return target;
42434245
}
42444246

4247+
SolutionApplicationTarget SolutionApplicationTarget::forInitialization(
4248+
Expr *initializer, DeclContext *dc, Type patternType,
4249+
PatternBindingDecl *patternBinding, unsigned patternBindingIndex,
4250+
bool bindPatternVarsOneWay) {
4251+
auto result = forInitialization(
4252+
initializer, dc, patternType,
4253+
patternBinding->getPattern(patternBindingIndex), bindPatternVarsOneWay);
4254+
result.expression.patternBinding = patternBinding;
4255+
result.expression.patternBindingIndex = patternBindingIndex;
4256+
return result;
4257+
}
4258+
4259+
ContextualPattern
4260+
SolutionApplicationTarget::getInitializationContextualPattern() const {
4261+
assert(kind == Kind::expression);
4262+
assert(expression.contextualPurpose == CTP_Initialization);
4263+
if (expression.patternBinding) {
4264+
return ContextualPattern::forPatternBindingDecl(
4265+
expression.patternBinding, expression.patternBindingIndex);
4266+
}
4267+
4268+
return ContextualPattern::forRawPattern(expression.pattern, expression.dc);
4269+
}
4270+
42454271
bool SolutionApplicationTarget::infersOpaqueReturnType() const {
42464272
assert(kind == Kind::expression);
42474273
switch (expression.contextualPurpose) {

lib/Sema/ConstraintSystem.h

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1206,6 +1206,12 @@ class SolutionApplicationTarget {
12061206
/// Whether to bind the variables encountered within the pattern to
12071207
/// fresh type variables via one-way constraints.
12081208
bool bindPatternVarsOneWay;
1209+
1210+
/// The pattern binding declaration for an initialization, if any.
1211+
PatternBindingDecl *patternBinding;
1212+
1213+
/// The index into the pattern binding declaration, if any.
1214+
unsigned patternBindingIndex;
12091215
} expression;
12101216

12111217
struct {
@@ -1267,6 +1273,13 @@ class SolutionApplicationTarget {
12671273
Expr *initializer, DeclContext *dc, Type patternType, Pattern *pattern,
12681274
bool bindPatternVarsOneWay);
12691275

1276+
/// Form a target for the initialization of a pattern binding entry from
1277+
/// an expression.
1278+
static SolutionApplicationTarget forInitialization(
1279+
Expr *initializer, DeclContext *dc, Type patternType,
1280+
PatternBindingDecl *patternBinding, unsigned patternBindingIndex,
1281+
bool bindPatternVarsOneWay);
1282+
12701283
Expr *getAsExpr() const {
12711284
switch (kind) {
12721285
case Kind::expression:
@@ -1351,6 +1364,9 @@ class SolutionApplicationTarget {
13511364
return expression.pattern;
13521365
}
13531366

1367+
/// For a pattern initialization target, retrieve the contextual pattern.
1368+
ContextualPattern getInitializationContextualPattern() const;
1369+
13541370
/// Whether this is an initialization for an Optional.Some pattern.
13551371
bool isOptionalSomePatternInit() const {
13561372
return kind == Kind::expression &&
@@ -1374,6 +1390,18 @@ class SolutionApplicationTarget {
13741390
return expression.wrappedVar;
13751391
}
13761392

1393+
PatternBindingDecl *getInitializationPatternBindingDecl() const {
1394+
assert(kind == Kind::expression);
1395+
assert(expression.contextualPurpose == CTP_Initialization);
1396+
return expression.patternBinding;
1397+
}
1398+
1399+
unsigned getInitializationPatternBindingIndex() const {
1400+
assert(kind == Kind::expression);
1401+
assert(expression.contextualPurpose == CTP_Initialization);
1402+
return expression.patternBindingIndex;
1403+
}
1404+
13771405
/// Whether this context infers an opaque return type.
13781406
bool infersOpaqueReturnType() const;
13791407

@@ -3398,7 +3426,9 @@ class ConstraintSystem {
33983426
///
33993427
/// \returns a possibly-sanitized initializer, or null if an error occurred.
34003428
Type generateConstraints(Pattern *P, ConstraintLocatorBuilder locator,
3401-
bool bindPatternVarsOneWay);
3429+
bool bindPatternVarsOneWay,
3430+
PatternBindingDecl *patternBinding,
3431+
unsigned patternIndex);
34023432

34033433
/// Generate constraints for a statement condition.
34043434
///

lib/Sema/TypeCheckConstraints.cpp

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2352,11 +2352,16 @@ TypeChecker::getTypeOfCompletionOperator(DeclContext *DC, Expr *LHS,
23522352
}
23532353
}
23542354

2355-
bool TypeChecker::typeCheckBinding(Pattern *&pattern, Expr *&initializer,
2356-
DeclContext *DC,
2357-
Type patternType) {
2358-
auto target = SolutionApplicationTarget::forInitialization(
2359-
initializer, DC, patternType, pattern, /*bindPatternVarsOneWay=*/false);
2355+
bool TypeChecker::typeCheckBinding(
2356+
Pattern *&pattern, Expr *&initializer, DeclContext *DC,
2357+
Type patternType, PatternBindingDecl *PBD, unsigned patternNumber) {
2358+
SolutionApplicationTarget target =
2359+
PBD ? SolutionApplicationTarget::forInitialization(
2360+
initializer, DC, patternType, PBD, patternNumber,
2361+
/*bindPatternVarsOneWay=*/false)
2362+
: SolutionApplicationTarget::forInitialization(
2363+
initializer, DC, patternType, pattern,
2364+
/*bindPatternVarsOneWay=*/false);
23602365

23612366
// Type-check the initializer.
23622367
bool unresolvedTypeExprs = false;
@@ -2425,7 +2430,8 @@ bool TypeChecker::typeCheckPatternBinding(PatternBindingDecl *PBD,
24252430
}
24262431
}
24272432

2428-
bool hadError = TypeChecker::typeCheckBinding(pattern, init, DC, patternType);
2433+
bool hadError = TypeChecker::typeCheckBinding(
2434+
pattern, init, DC, patternType, PBD, patternNumber);
24292435
if (!init) {
24302436
PBD->setInvalid();
24312437
return true;
@@ -2550,7 +2556,8 @@ bool TypeChecker::typeCheckForEachBinding(DeclContext *dc, ForEachStmt *stmt) {
25502556
// Collect constraints from the element pattern.
25512557
auto pattern = Stmt->getPattern();
25522558
InitType = cs.generateConstraints(
2553-
pattern, elementLocator, /*bindPatternVarsOneWay=*/false);
2559+
pattern, elementLocator, /*bindPatternVarsOneWay=*/false,
2560+
/*patternBinding=*/nullptr, /*patternBindingIndex=*/0);
25542561
if (!InitType)
25552562
return true;
25562563

lib/Sema/TypeChecker.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -916,7 +916,9 @@ void coerceParameterListToType(ParameterList *P, ClosureExpr *CE,
916916

917917
/// Type-check an initialized variable pattern declaration.
918918
bool typeCheckBinding(Pattern *&P, Expr *&Init, DeclContext *DC,
919-
Type patternType);
919+
Type patternType,
920+
PatternBindingDecl *PBD = nullptr,
921+
unsigned patternNumber = 0);
920922
bool typeCheckPatternBinding(PatternBindingDecl *PBD, unsigned patternNumber,
921923
Type patternType = Type());
922924

test/Constraints/iuo.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,3 +225,7 @@ var y: Int = 2
225225

226226
let r = sr6988(x: x, y: y)
227227
let _: Int = r
228+
229+
// SR-11998 / rdar://problem/58455441
230+
class C<T> {}
231+
var sub: C! = C<Int>()

0 commit comments

Comments
 (0)