Skip to content

Commit 5e28c7c

Browse files
committed
[Constraint System] Move bindVariablesInPattern into the constraint system.
This general notion of wiring up the types of variables that occur within a pattern to the types in the produced pattern type is useful outside of function builders, too.
1 parent 8c92cfd commit 5e28c7c

File tree

3 files changed

+113
-101
lines changed

3 files changed

+113
-101
lines changed

lib/Sema/BuilderTransform.cpp

Lines changed: 2 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -235,105 +235,6 @@ class BuilderClosureVisitor
235235
return nullptr; \
236236
}
237237

238-
/// Provide a type for each variable that occurs within the given pattern,
239-
/// by matching the pattern structurally with its already-computed pattern
240-
/// type. The variables will either get a concrete type (when present in
241-
/// the pattern type) or a fresh type variable bound to that part of the
242-
/// pattern via a one-way constraint.
243-
void bindVariablesInPattern(Pattern *pattern, Type patternType,
244-
ConstraintLocator *locator) {
245-
switch (pattern->getKind()) {
246-
case PatternKind::Paren: {
247-
// Parentheses don't affect the type, but unwrap a paren type if we have
248-
// one.
249-
Type subPatternType;
250-
if (auto parenType = dyn_cast<ParenType>(patternType.getPointer()))
251-
subPatternType = parenType->getUnderlyingType();
252-
else
253-
subPatternType = patternType;
254-
return bindVariablesInPattern(
255-
cast<ParenPattern>(pattern)->getSubPattern(),
256-
subPatternType, locator);
257-
}
258-
259-
case PatternKind::Var:
260-
// Var doesn't affect the type.
261-
return bindVariablesInPattern(cast<VarPattern>(pattern)->getSubPattern(),
262-
patternType, locator);
263-
264-
case PatternKind::Any:
265-
// Nothing to bind.
266-
return;
267-
268-
case PatternKind::Named: {
269-
auto var = cast<NamedPattern>(pattern)->getDecl();
270-
271-
/// Create a fresh type variable to describe the type of the
272-
Type varType = cs->createTypeVariable(locator, TVO_CanBindToNoEscape);
273-
274-
auto ROK = ReferenceOwnership::Strong;
275-
if (auto *OA = var->getAttrs().getAttribute<ReferenceOwnershipAttr>())
276-
ROK = OA->get();
277-
switch (optionalityOf(ROK)) {
278-
case ReferenceOwnershipOptionality::Required:
279-
// FIXME: Can we assert this rather than just checking it.
280-
if (auto optPatternType =
281-
dyn_cast<OptionalType>(patternType.getPointer())) {
282-
// Add a one-way constraint from the type variable to the wrapped
283-
// type of the optional.
284-
cs->addConstraint(
285-
ConstraintKind::OneWayEqual, varType, optPatternType->getBaseType(),
286-
locator);
287-
288-
// Make the variable type optional.
289-
varType = TypeChecker::getOptionalType(var->getLoc(), varType);
290-
break;
291-
}
292-
293-
// Fall through to treat this normally.
294-
LLVM_FALLTHROUGH;
295-
296-
case ReferenceOwnershipOptionality::Allowed:
297-
case ReferenceOwnershipOptionality::Disallowed:
298-
// Add the one-way constraint from the variable type to the pattern
299-
// type.
300-
cs->addConstraint(ConstraintKind::OneWayEqual, varType, patternType,
301-
locator);
302-
break;
303-
}
304-
305-
// Bind the type of the variable.
306-
cs->setType(var, varType);
307-
return;
308-
}
309-
310-
case PatternKind::Typed: {
311-
// Ignore the type itself; it's part of patternType now.
312-
return bindVariablesInPattern(
313-
cast<TypedPattern>(pattern)->getSubPattern(),
314-
patternType, locator);
315-
}
316-
317-
case PatternKind::Tuple: {
318-
auto tuplePat = cast<TuplePattern>(pattern);
319-
auto tupleType = patternType->castTo<TupleType>();
320-
for (unsigned i = 0, e = tuplePat->getNumElements(); i != e; ++i) {
321-
bindVariablesInPattern(tuplePat->getElement(i).getPattern(),
322-
tupleType->getElementType(i), locator);
323-
}
324-
return;
325-
}
326-
327-
// FIXME: Refutable patterns will generate additional constraints.
328-
#define PATTERN(Id, Parent)
329-
#define REFUTABLE_PATTERN(Id, Parent) case PatternKind::Id:
330-
#include "swift/AST/PatternNodes.def"
331-
llvm_unreachable("Refutable patterns are not supported here");
332-
}
333-
334-
llvm_unreachable("Unhandled pattern kind");
335-
}
336-
337238
void visitPatternBindingDecl(PatternBindingDecl *patternBinding) {
338239
// If any of the entries lacks an initializer, don't handle this node.
339240
if (!llvm::all_of(range(patternBinding->getNumPatternEntries()),
@@ -367,8 +268,8 @@ class BuilderClosureVisitor
367268

368269
// Bind the variables that occur in the pattern to the corresponding
369270
// type entry for the pattern itself.
370-
bindVariablesInPattern(pattern, cs->getType(pattern),
371-
cs->getConstraintLocator(target.getAsExpr()));
271+
cs->bindVariablesInPattern(
272+
pattern, cs->getConstraintLocator(target.getAsExpr()));
372273
}
373274
}
374275

lib/Sema/CSGen.cpp

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4033,6 +4033,100 @@ bool ConstraintSystem::generateConstraints(StmtCondition condition,
40334033
return false;
40344034
}
40354035

4036+
void ConstraintSystem::bindVariablesInPattern(
4037+
Pattern *pattern, Type patternType, ConstraintLocator *locator) {
4038+
switch (pattern->getKind()) {
4039+
case PatternKind::Paren: {
4040+
// Parentheses don't affect the type, but unwrap a paren type if we have
4041+
// one.
4042+
Type subPatternType;
4043+
if (auto parenType = dyn_cast<ParenType>(patternType.getPointer()))
4044+
subPatternType = parenType->getUnderlyingType();
4045+
else
4046+
subPatternType = patternType;
4047+
return bindVariablesInPattern(
4048+
cast<ParenPattern>(pattern)->getSubPattern(),
4049+
subPatternType, locator);
4050+
}
4051+
4052+
case PatternKind::Var:
4053+
// Var doesn't affect the type.
4054+
return bindVariablesInPattern(cast<VarPattern>(pattern)->getSubPattern(),
4055+
patternType, locator);
4056+
4057+
case PatternKind::Any:
4058+
// Nothing to bind.
4059+
return;
4060+
4061+
case PatternKind::Named: {
4062+
auto var = cast<NamedPattern>(pattern)->getDecl();
4063+
4064+
/// Create a fresh type variable to describe the type of the
4065+
Type varType = createTypeVariable(locator, TVO_CanBindToNoEscape);
4066+
4067+
auto ROK = ReferenceOwnership::Strong;
4068+
if (auto *OA = var->getAttrs().getAttribute<ReferenceOwnershipAttr>())
4069+
ROK = OA->get();
4070+
switch (optionalityOf(ROK)) {
4071+
case ReferenceOwnershipOptionality::Required:
4072+
// FIXME: Can we assert this rather than just checking it.
4073+
if (auto optPatternType =
4074+
dyn_cast<OptionalType>(patternType.getPointer())) {
4075+
// Add a one-way constraint from the type variable to the wrapped
4076+
// type of the optional.
4077+
addConstraint(
4078+
ConstraintKind::OneWayEqual, varType, optPatternType->getBaseType(),
4079+
locator);
4080+
4081+
// Make the variable type optional.
4082+
varType = TypeChecker::getOptionalType(var->getLoc(), varType);
4083+
break;
4084+
}
4085+
4086+
// Fall through to treat this normally.
4087+
LLVM_FALLTHROUGH;
4088+
4089+
case ReferenceOwnershipOptionality::Allowed:
4090+
case ReferenceOwnershipOptionality::Disallowed:
4091+
// Add the one-way constraint from the variable type to the pattern
4092+
// type.
4093+
addConstraint(ConstraintKind::OneWayEqual, varType, patternType,
4094+
locator);
4095+
break;
4096+
}
4097+
4098+
// Bind the type of the variable.
4099+
setType(var, varType);
4100+
return;
4101+
}
4102+
4103+
case PatternKind::Typed: {
4104+
// Ignore the type itself; it's part of patternType now.
4105+
return bindVariablesInPattern(
4106+
cast<TypedPattern>(pattern)->getSubPattern(),
4107+
patternType, locator);
4108+
}
4109+
4110+
case PatternKind::Tuple: {
4111+
auto tuplePat = cast<TuplePattern>(pattern);
4112+
auto tupleType = patternType->castTo<TupleType>();
4113+
for (unsigned i = 0, e = tuplePat->getNumElements(); i != e; ++i) {
4114+
bindVariablesInPattern(tuplePat->getElement(i).getPattern(),
4115+
tupleType->getElementType(i), locator);
4116+
}
4117+
return;
4118+
}
4119+
4120+
// FIXME: Refutable patterns will generate additional constraints.
4121+
#define PATTERN(Id, Parent)
4122+
#define REFUTABLE_PATTERN(Id, Parent) case PatternKind::Id:
4123+
#include "swift/AST/PatternNodes.def"
4124+
llvm_unreachable("Refutable patterns are not supported here");
4125+
}
4126+
4127+
llvm_unreachable("Unhandled pattern kind");
4128+
}
4129+
40364130
void ConstraintSystem::optimizeConstraints(Expr *e) {
40374131
if (getASTContext().TypeCheckerOpts.DisableConstraintSolverPerformanceHacks)
40384132
return;

lib/Sema/ConstraintSystem.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3256,6 +3256,23 @@ class ConstraintSystem {
32563256
/// if generation succeeded.
32573257
bool generateConstraints(StmtCondition condition, DeclContext *dc);
32583258

3259+
/// Provide a type for each variable that occurs within the given pattern,
3260+
/// by matching the pattern structurally with its already-computed pattern
3261+
/// type. The variables will either get a concrete type (when present in
3262+
/// the pattern type) or a fresh type variable bound to that part of the
3263+
/// pattern via a one-way constraint.
3264+
void bindVariablesInPattern(Pattern *pattern, Type patternType,
3265+
ConstraintLocator *locator);
3266+
3267+
/// Provide a type for each variable that occurs within the given pattern,
3268+
/// by matching the pattern structurally with its already-computed pattern
3269+
/// type. The variables will either get a concrete type (when present in
3270+
/// the pattern type) or a fresh type variable bound to that part of the
3271+
/// pattern via a one-way constraint.
3272+
void bindVariablesInPattern(Pattern *pattern, ConstraintLocator *locator) {
3273+
bindVariablesInPattern(pattern, getType(pattern), locator);
3274+
}
3275+
32593276
/// Generate constraints for a given set of overload choices.
32603277
///
32613278
/// \param constraints The container of generated constraint choices.

0 commit comments

Comments
 (0)