@@ -235,6 +235,143 @@ class BuilderClosureVisitor
235
235
return nullptr ; \
236
236
}
237
237
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
+
337
+ void visitPatternBindingDecl (PatternBindingDecl *patternBinding) {
338
+ // If any of the entries lacks an initializer, don't handle this node.
339
+ if (!llvm::all_of (range (patternBinding->getNumPatternEntries ()),
340
+ [&](unsigned index) {
341
+ return patternBinding->isExplicitlyInitialized (index);
342
+ })) {
343
+ if (!unhandledNode)
344
+ unhandledNode = patternBinding;
345
+ return ;
346
+ }
347
+
348
+ // If we aren't generating constraints, there's nothing to do.
349
+ if (!cs)
350
+ return ;
351
+
352
+ // / Generate constraints for each pattern binding entry
353
+ for (unsigned index : range (patternBinding->getNumPatternEntries ())) {
354
+ // Type check the pattern.
355
+ auto pattern = patternBinding->getPattern (index);
356
+ auto contextualPattern = ContextualPattern::forRawPattern (pattern, dc);
357
+ Type patternType = TypeChecker::typeCheckPattern (contextualPattern);
358
+
359
+ // Generate constraints for the initialization.
360
+ auto target = SolutionApplicationTarget::forInitialization (
361
+ patternBinding->getInit (index), dc, patternType, pattern);
362
+ if (cs->generateConstraints (target, FreeTypeVariableBinding::Disallow))
363
+ continue ;
364
+
365
+ // Keep track of this binding entry.
366
+ applied.patternBindingEntries .insert ({{patternBinding, index}, target});
367
+
368
+ // Bind the variables that occur in the pattern to the corresponding
369
+ // type entry for the pattern itself.
370
+ bindVariablesInPattern (pattern, cs->getType (pattern),
371
+ cs->getConstraintLocator (target.getAsExpr ()));
372
+ }
373
+ }
374
+
238
375
VarDecl *visitBraceStmt (BraceStmt *braceStmt) {
239
376
SmallVector<Expr *, 4 > expressions;
240
377
auto addChild = [&](VarDecl *childVar) {
@@ -270,6 +407,18 @@ class BuilderClosureVisitor
270
407
continue ;
271
408
}
272
409
410
+ // Pattern bindings are okay so long as all of the entries are
411
+ // initialized.
412
+ if (auto patternBinding = dyn_cast<PatternBindingDecl>(decl)) {
413
+ visitPatternBindingDecl (patternBinding);
414
+ continue ;
415
+ }
416
+
417
+ // Ignore variable declarations, because they're always handled within
418
+ // their enclosing pattern bindings.
419
+ if (isa<VarDecl>(decl))
420
+ continue ;
421
+
273
422
if (!unhandledNode)
274
423
unhandledNode = decl;
275
424
@@ -744,6 +893,26 @@ class BuilderClosureRewriter
744
893
elements.push_back (pbd);
745
894
}
746
895
896
+ // / Produce a final type-checked pattern binding.
897
+ void finishPatternBindingDecl (PatternBindingDecl *patternBinding) {
898
+ for (unsigned index : range (patternBinding->getNumPatternEntries ())) {
899
+ // Find the solution application target for this.
900
+ auto knownTarget =
901
+ builderTransform.patternBindingEntries .find ({patternBinding, index});
902
+ assert (knownTarget != builderTransform.patternBindingEntries .end ());
903
+
904
+ // Rewrite the target.
905
+ auto resultTarget = rewriteTarget (knownTarget->second );
906
+ if (!resultTarget)
907
+ continue ;
908
+
909
+ patternBinding->setPattern (
910
+ index, resultTarget->getInitializationPattern (),
911
+ resultTarget->getDeclContext ());
912
+ patternBinding->setInit (index, resultTarget->getAsExpr ());
913
+ }
914
+ }
915
+
747
916
public:
748
917
BuilderClosureRewriter (
749
918
const Solution &solution,
@@ -811,12 +980,29 @@ class BuilderClosureRewriter
811
980
auto decl = node.get <Decl *>();
812
981
813
982
// Skip #if declarations.
814
- if (isa<IfConfigDecl>(decl))
983
+ if (isa<IfConfigDecl>(decl)) {
984
+ newElements.push_back (decl);
815
985
continue ;
986
+ }
816
987
817
988
// Diagnose #warning / #error during application.
818
989
if (auto poundDiag = dyn_cast<PoundDiagnosticDecl>(decl)) {
819
990
TypeChecker::typeCheckDecl (poundDiag);
991
+ newElements.push_back (decl);
992
+ continue ;
993
+ }
994
+
995
+ // Skip variable declarations; they're always part of a pattern
996
+ // binding.
997
+ if (isa<VarDecl>(decl)) {
998
+ newElements.push_back (decl);
999
+ continue ;
1000
+ }
1001
+
1002
+ // Handle pattern bindings.
1003
+ if (auto patternBinding = dyn_cast<PatternBindingDecl>(decl)) {
1004
+ finishPatternBindingDecl (patternBinding);
1005
+ newElements.push_back (decl);
820
1006
continue ;
821
1007
}
822
1008
0 commit comments