@@ -2198,18 +2198,38 @@ namespace {
2198
2198
// /
2199
2199
// / \param pattern The pattern.
2200
2200
Type getTypeForPattern (Pattern *pattern, ConstraintLocatorBuilder locator) {
2201
+ // If there's no pattern, then we have an unknown subpattern. Create a
2202
+ // type variable.
2203
+ if (!pattern) {
2204
+ return CS.createTypeVariable (CS.getConstraintLocator (locator),
2205
+ TVO_CanBindToNoEscape);
2206
+ }
2207
+
2208
+ // Local function that must be called for each "return" throughout this
2209
+ // function, to set the type of the pattern.
2210
+ auto setType = [&](Type type) {
2211
+ CS.setType (pattern, type);
2212
+ return type;
2213
+ };
2214
+
2201
2215
switch (pattern->getKind ()) {
2202
2216
case PatternKind::Paren:
2203
- // Parentheses don't affect the type.
2204
- return getTypeForPattern (cast<ParenPattern>(pattern)->getSubPattern (),
2205
- locator);
2217
+ // Parentheses don't affect the canonical type, but record them as
2218
+ // type sugar.
2219
+ return setType (
2220
+ ParenType::get (
2221
+ CS.getASTContext (),
2222
+ getTypeForPattern (
2223
+ cast<ParenPattern>(pattern)->getSubPattern (), locator)));
2206
2224
case PatternKind::Var:
2207
2225
// Var doesn't affect the type.
2208
- return getTypeForPattern (cast<VarPattern>(pattern)->getSubPattern (),
2209
- locator);
2226
+ return setType (
2227
+ getTypeForPattern (
2228
+ cast<VarPattern>(pattern)->getSubPattern (), locator));
2210
2229
case PatternKind::Any: {
2211
- return CS.createTypeVariable (CS.getConstraintLocator (locator),
2212
- TVO_CanBindToNoEscape);
2230
+ return setType (
2231
+ CS.createTypeVariable (CS.getConstraintLocator (locator),
2232
+ TVO_CanBindToNoEscape));
2213
2233
}
2214
2234
2215
2235
case PatternKind::Named: {
@@ -2223,23 +2243,29 @@ namespace {
2223
2243
ROK = OA->get ();
2224
2244
switch (optionalityOf (ROK)) {
2225
2245
case ReferenceOwnershipOptionality::Required:
2226
- return TypeChecker::getOptionalType (var->getLoc (), varType);
2246
+ return setType ( TypeChecker::getOptionalType (var->getLoc (), varType) );
2227
2247
case ReferenceOwnershipOptionality::Allowed:
2228
2248
case ReferenceOwnershipOptionality::Disallowed:
2229
- return varType;
2249
+ return setType ( varType) ;
2230
2250
}
2231
2251
}
2232
2252
2233
2253
case PatternKind::Typed: {
2234
2254
// FIXME: Need a better locator for a pattern as a base.
2255
+ // Compute the type ascribed to the pattern.
2235
2256
auto contextualPattern =
2236
2257
ContextualPattern::forRawPattern (pattern, CurDC);
2237
2258
Type type = TypeChecker::typeCheckPattern (contextualPattern);
2238
2259
Type openedType = CS.openUnboundGenericType (type, locator);
2239
2260
2240
- // For a typed pattern, simply return the opened type of the pattern.
2241
- // FIXME: Error recovery if the type is an error type?
2242
- return openedType;
2261
+ // Determine the subpattern type. It will be convertible to the
2262
+ // ascribed type.
2263
+ Type subPatternType =
2264
+ getTypeForPattern (
2265
+ cast<TypedPattern>(pattern)->getSubPattern (), locator);
2266
+ CS.addConstraint (
2267
+ ConstraintKind::Conversion, subPatternType, openedType, locator);
2268
+ return setType (openedType);
2243
2269
}
2244
2270
2245
2271
case PatternKind::Tuple: {
@@ -2253,19 +2279,119 @@ namespace {
2253
2279
LocatorPathElt::TupleElement (i)));
2254
2280
tupleTypeElts.push_back (TupleTypeElt (eltTy, tupleElt.getLabel ()));
2255
2281
}
2256
- return TupleType::get (tupleTypeElts, CS.getASTContext ());
2282
+ return setType ( TupleType::get (tupleTypeElts, CS.getASTContext () ));
2257
2283
}
2258
-
2284
+
2285
+ case PatternKind::OptionalSome: {
2286
+ // The subpattern must have optional type.
2287
+ Type subPatternType = getTypeForPattern (
2288
+ cast<OptionalSomePattern>(pattern)->getSubPattern (), locator);
2289
+
2290
+ return setType (OptionalType::get (subPatternType));
2291
+ }
2292
+
2293
+ case PatternKind::Is: {
2294
+ auto isPattern = cast<IsPattern>(pattern);
2295
+ Type subPatternType =
2296
+ getTypeForPattern (isPattern->getSubPattern (), locator);
2297
+
2298
+ // Make sure we can cast from the subpattern type to the type we're
2299
+ // checking; if it's impossible, fail.
2300
+ if (Type castType =
2301
+ resolveTypeReferenceInExpression (isPattern->getCastTypeLoc ())) {
2302
+ castType = CS.openUnboundGenericType (castType, locator);
2303
+ CS.addConstraint (
2304
+ ConstraintKind::CheckedCast, subPatternType, castType, locator);
2305
+ }
2306
+
2307
+ return setType (subPatternType);
2308
+ }
2309
+
2310
+ case PatternKind::Bool:
2311
+ return setType (CS.getASTContext ().getBoolDecl ()->getDeclaredType ());
2312
+
2313
+ case PatternKind::EnumElement: {
2314
+ auto enumPattern = cast<EnumElementPattern>(pattern);
2315
+
2316
+ // Create a type variable to represent the pattern.
2317
+ Type patternType =
2318
+ CS.createTypeVariable (CS.getConstraintLocator (locator),
2319
+ TVO_CanBindToNoEscape);
2320
+
2321
+ // Form the member constraint for a reference to a member of this
2322
+ // type.
2323
+ Type baseType;
2324
+ Type memberType = CS.createTypeVariable (
2325
+ CS.getConstraintLocator (locator),
2326
+ TVO_CanBindToLValue | TVO_CanBindToNoEscape);
2327
+ FunctionRefKind functionRefKind = FunctionRefKind::Compound;
2328
+ if (!enumPattern->getParentType ().isNull ()) {
2329
+ // Resolve the parent type.
2330
+ Type parentType =
2331
+ resolveTypeReferenceInExpression (enumPattern->getParentType ());
2332
+ parentType = CS.openUnboundGenericType (parentType, locator);
2333
+
2334
+ // Perform member lookup into the parent's metatype.
2335
+ Type parentMetaType = MetatypeType::get (parentType);
2336
+ CS.addValueMemberConstraint (
2337
+ parentMetaType, enumPattern->getName (), memberType, CurDC,
2338
+ functionRefKind, { },
2339
+ locator.withPathElement (LocatorPathElt::PatternMatch (pattern)));
2340
+
2341
+ // Parent type needs to be convertible to the pattern type; this
2342
+ // accounts for cases where the pattern type is existential.
2343
+ CS.addConstraint (ConstraintKind::Conversion, parentType, patternType,
2344
+ locator);
2345
+
2346
+ baseType = parentType;
2347
+ } else {
2348
+ // Use the pattern type for member lookup.
2349
+ CS.addUnresolvedValueMemberConstraint (
2350
+ MetatypeType::get (patternType), enumPattern->getName (),
2351
+ memberType, CurDC, functionRefKind,
2352
+ locator.withPathElement (LocatorPathElt::PatternMatch (pattern)));
2353
+
2354
+ baseType = patternType;
2355
+ }
2356
+
2357
+ if (auto subPattern = enumPattern->getSubPattern ()) {
2358
+ // When there is a subpattern, the member will have function type,
2359
+ // and we're matching the type of that subpattern to the parameter
2360
+ // types.
2361
+ Type subPatternType = getTypeForPattern (subPattern, locator);
2362
+ SmallVector<AnyFunctionType::Param, 8 > params;
2363
+ AnyFunctionType::decomposeInput (subPatternType, params);
2364
+
2365
+ // Remove parameter labels; they aren't used when matching cases,
2366
+ // but outright conflicts will be checked during coercion.
2367
+ for (auto ¶m : params) {
2368
+ param = param.getWithoutLabel ();
2369
+ }
2370
+
2371
+ Type outputType = CS.createTypeVariable (
2372
+ CS.getConstraintLocator (locator),
2373
+ TVO_CanBindToNoEscape);
2374
+ Type functionType = FunctionType::get (params, outputType);
2375
+ CS.addConstraint (
2376
+ ConstraintKind::Equal, functionType, memberType,
2377
+ locator.withPathElement (LocatorPathElt::PatternMatch (pattern)));
2378
+
2379
+ CS.addConstraint (ConstraintKind::Conversion, outputType, baseType,
2380
+ locator);
2381
+ }
2382
+
2383
+ return setType (patternType);
2384
+ }
2385
+
2259
2386
// Refutable patterns occur when checking the PatternBindingDecls in an
2260
2387
// if/let or while/let condition. They always require an initial value,
2261
2388
// so they always allow unspecified types.
2262
- #define PATTERN (Id, Parent )
2263
- #define REFUTABLE_PATTERN (Id, Parent ) case PatternKind::Id:
2264
- #include " swift/AST/PatternNodes.def"
2389
+ case PatternKind::Expr:
2265
2390
// TODO: we could try harder here, e.g. for enum elements to provide the
2266
2391
// enum type.
2267
- return CS.createTypeVariable (CS.getConstraintLocator (locator),
2268
- TVO_CanBindToNoEscape);
2392
+ return setType (
2393
+ CS.createTypeVariable (
2394
+ CS.getConstraintLocator (locator), TVO_CanBindToNoEscape));
2269
2395
}
2270
2396
2271
2397
llvm_unreachable (" Unhandled pattern kind" );
@@ -3845,11 +3971,7 @@ static bool generateInitPatternConstraints(
3845
3971
auto locator =
3846
3972
cs.getConstraintLocator (initializer, LocatorPathElt::ContextualType ());
3847
3973
Type patternType = cs.generateConstraints (pattern, locator);
3848
- if (!patternType)
3849
- return true ;
3850
-
3851
- // Record the type of this pattern.
3852
- cs.setType (pattern, patternType);
3974
+ assert (patternType && " All patterns have a type" );
3853
3975
3854
3976
if (auto wrappedVar = target.getInitializationWrappedVar ()) {
3855
3977
// Add an equal constraint between the pattern type and the
@@ -4035,7 +4157,7 @@ void ConstraintSystem::bindVariablesInPattern(
4035
4157
case PatternKind::Named: {
4036
4158
auto var = cast<NamedPattern>(pattern)->getDecl ();
4037
4159
4038
- // / Create a fresh type variable to describe the type of the
4160
+ // / Create a fresh type variable to describe the type of the bound variable.
4039
4161
Type varType = createTypeVariable (locator, TVO_CanBindToNoEscape);
4040
4162
4041
4163
auto ROK = ReferenceOwnership::Strong;
0 commit comments