@@ -2197,7 +2197,9 @@ namespace {
2197
2197
// / type information with fresh type variables.
2198
2198
// /
2199
2199
// / \param pattern The pattern.
2200
- Type getTypeForPattern (Pattern *pattern, ConstraintLocatorBuilder locator) {
2200
+ Type getTypeForPattern (Pattern *pattern, ConstraintLocatorBuilder locator,
2201
+ Type externalPatternType,
2202
+ bool bindPatternVarsOneWay) {
2201
2203
// If there's no pattern, then we have an unknown subpattern. Create a
2202
2204
// type variable.
2203
2205
if (!pattern) {
@@ -2213,19 +2215,29 @@ namespace {
2213
2215
};
2214
2216
2215
2217
switch (pattern->getKind ()) {
2216
- case PatternKind::Paren:
2218
+ case PatternKind::Paren: {
2217
2219
// Parentheses don't affect the canonical type, but record them as
2218
2220
// type sugar.
2221
+ if (externalPatternType &&
2222
+ isa<ParenType>(externalPatternType.getPointer ())) {
2223
+ externalPatternType = cast<ParenType>(externalPatternType.getPointer ())
2224
+ ->getUnderlyingType ();
2225
+ }
2226
+
2219
2227
return setType (
2220
2228
ParenType::get (
2221
2229
CS.getASTContext (),
2222
2230
getTypeForPattern (
2223
- cast<ParenPattern>(pattern)->getSubPattern (), locator)));
2231
+ cast<ParenPattern>(pattern)->getSubPattern (), locator,
2232
+ externalPatternType,
2233
+ bindPatternVarsOneWay)));
2234
+ }
2224
2235
case PatternKind::Var:
2225
2236
// Var doesn't affect the type.
2226
2237
return setType (
2227
2238
getTypeForPattern (
2228
- cast<VarPattern>(pattern)->getSubPattern (), locator));
2239
+ cast<VarPattern>(pattern)->getSubPattern (), locator,
2240
+ externalPatternType, bindPatternVarsOneWay));
2229
2241
case PatternKind::Any: {
2230
2242
return setType (
2231
2243
CS.createTypeVariable (CS.getConstraintLocator (locator),
@@ -2238,16 +2250,47 @@ namespace {
2238
2250
Type varType = CS.createTypeVariable (
2239
2251
CS.getConstraintLocator (locator), TVO_CanBindToNoEscape);
2240
2252
2253
+ // When we are supposed to bind pattern variables, create a fresh
2254
+ // type variable and a one-way constraint to assign it to either the
2255
+ // deduced type or the externally-imposed type.
2256
+ Type oneWayVarType;
2257
+ if (bindPatternVarsOneWay) {
2258
+ oneWayVarType = CS.createTypeVariable (
2259
+ CS.getConstraintLocator (locator), TVO_CanBindToNoEscape);
2260
+ if (externalPatternType) {
2261
+ CS.addConstraint (
2262
+ ConstraintKind::OneWayEqual, oneWayVarType,
2263
+ externalPatternType, locator);
2264
+ } else {
2265
+ CS.addConstraint (
2266
+ ConstraintKind::OneWayEqual, oneWayVarType, varType, locator);
2267
+ }
2268
+ }
2269
+
2270
+ // If there is an externally-imposed type.
2271
+
2241
2272
auto ROK = ReferenceOwnership::Strong;
2242
2273
if (auto *OA = var->getAttrs ().getAttribute <ReferenceOwnershipAttr>())
2243
2274
ROK = OA->get ();
2244
2275
switch (optionalityOf (ROK)) {
2245
2276
case ReferenceOwnershipOptionality::Required:
2246
- return setType (TypeChecker::getOptionalType (var->getLoc (), varType));
2277
+ varType = TypeChecker::getOptionalType (var->getLoc (), varType);
2278
+ if (oneWayVarType) {
2279
+ oneWayVarType =
2280
+ TypeChecker::getOptionalType (var->getLoc (), oneWayVarType);
2281
+ }
2282
+ break ;
2283
+
2247
2284
case ReferenceOwnershipOptionality::Allowed:
2248
2285
case ReferenceOwnershipOptionality::Disallowed:
2249
- return setType (varType) ;
2286
+ break ;
2250
2287
}
2288
+
2289
+ // If we have a type to ascribe to the variable, do so now.
2290
+ if (oneWayVarType)
2291
+ CS.setType (var, oneWayVarType);
2292
+
2293
+ return setType (varType);
2251
2294
}
2252
2295
2253
2296
case PatternKind::Typed: {
@@ -2262,47 +2305,93 @@ namespace {
2262
2305
// ascribed type.
2263
2306
Type subPatternType =
2264
2307
getTypeForPattern (
2265
- cast<TypedPattern>(pattern)->getSubPattern (), locator);
2308
+ cast<TypedPattern>(pattern)->getSubPattern (), locator,
2309
+ Type (), bindPatternVarsOneWay);
2266
2310
CS.addConstraint (
2267
2311
ConstraintKind::Conversion, subPatternType, openedType, locator);
2268
2312
return setType (openedType);
2269
2313
}
2270
2314
2271
2315
case PatternKind::Tuple: {
2272
2316
auto tuplePat = cast<TuplePattern>(pattern);
2317
+
2318
+ // If there's an externally-imposed type, decompose it into element
2319
+ // types so long as we have the right number of such types.
2320
+ SmallVector<AnyFunctionType::Param, 4 > externalEltTypes;
2321
+ if (externalPatternType) {
2322
+ AnyFunctionType::decomposeInput (externalPatternType,
2323
+ externalEltTypes);
2324
+
2325
+ // If we have the wrong number of elements, we may not be able to
2326
+ // provide more specific types.
2327
+ if (tuplePat->getNumElements () != externalEltTypes.size ()) {
2328
+ externalEltTypes.clear ();
2329
+
2330
+ // Implicit tupling.
2331
+ if (tuplePat->getNumElements () == 1 ) {
2332
+ externalEltTypes.push_back (
2333
+ AnyFunctionType::Param (externalPatternType));
2334
+ }
2335
+ }
2336
+ }
2337
+
2273
2338
SmallVector<TupleTypeElt, 4 > tupleTypeElts;
2274
2339
tupleTypeElts.reserve (tuplePat->getNumElements ());
2275
2340
for (unsigned i = 0 , e = tuplePat->getNumElements (); i != e; ++i) {
2276
2341
auto &tupleElt = tuplePat->getElement (i);
2277
- Type eltTy = getTypeForPattern (tupleElt.getPattern (),
2278
- locator.withPathElement (
2279
- LocatorPathElt::TupleElement (i)));
2342
+ Type externalEltType;
2343
+ if (!externalEltTypes.empty ())
2344
+ externalEltType = externalEltTypes[i].getPlainType ();
2345
+
2346
+ Type eltTy = getTypeForPattern (
2347
+ tupleElt.getPattern (),
2348
+ locator.withPathElement (LocatorPathElt::TupleElement (i)),
2349
+ externalEltType,
2350
+ bindPatternVarsOneWay);
2280
2351
tupleTypeElts.push_back (TupleTypeElt (eltTy, tupleElt.getLabel ()));
2281
2352
}
2353
+
2282
2354
return setType (TupleType::get (tupleTypeElts, CS.getASTContext ()));
2283
2355
}
2284
2356
2285
2357
case PatternKind::OptionalSome: {
2358
+ // Remove an optional from the object type.
2359
+ if (externalPatternType) {
2360
+ if (Type objType = externalPatternType->getOptionalObjectType ()) {
2361
+ externalPatternType = objType;
2362
+ } else {
2363
+ Type objVar = CS.createTypeVariable (
2364
+ CS.getConstraintLocator (locator), TVO_CanBindToNoEscape);
2365
+ CS.addConstraint (
2366
+ ConstraintKind::Equal, OptionalType::get (objVar),
2367
+ externalPatternType, locator);
2368
+ externalPatternType = objVar;
2369
+ }
2370
+ }
2371
+
2286
2372
// The subpattern must have optional type.
2287
2373
Type subPatternType = getTypeForPattern (
2288
- cast<OptionalSomePattern>(pattern)->getSubPattern (), locator);
2374
+ cast<OptionalSomePattern>(pattern)->getSubPattern (), locator,
2375
+ externalPatternType, bindPatternVarsOneWay);
2289
2376
2290
2377
return setType (OptionalType::get (subPatternType));
2291
2378
}
2292
2379
2293
2380
case PatternKind::Is: {
2294
2381
auto isPattern = cast<IsPattern>(pattern);
2382
+
2383
+ Type castType =
2384
+ resolveTypeReferenceInExpression (isPattern->getCastTypeLoc ());
2385
+ castType = CS.openUnboundGenericType (castType, locator);
2386
+
2295
2387
Type subPatternType =
2296
- getTypeForPattern (isPattern->getSubPattern (), locator);
2388
+ getTypeForPattern (isPattern->getSubPattern (), locator, castType,
2389
+ bindPatternVarsOneWay);
2297
2390
2298
2391
// Make sure we can cast from the subpattern type to the type we're
2299
2392
// 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
- }
2393
+ CS.addConstraint (
2394
+ ConstraintKind::CheckedCast, subPatternType, castType, locator);
2306
2395
2307
2396
return setType (subPatternType);
2308
2397
}
@@ -2358,8 +2447,9 @@ namespace {
2358
2447
// When there is a subpattern, the member will have function type,
2359
2448
// and we're matching the type of that subpattern to the parameter
2360
2449
// types.
2361
- Type subPatternType = getTypeForPattern (subPattern, locator);
2362
- SmallVector<AnyFunctionType::Param, 8 > params;
2450
+ Type subPatternType = getTypeForPattern (
2451
+ subPattern, locator, Type (), bindPatternVarsOneWay);
2452
+ SmallVector<AnyFunctionType::Param, 4 > params;
2363
2453
AnyFunctionType::decomposeInput (subPatternType, params);
2364
2454
2365
2455
// Remove parameter labels; they aren't used when matching cases,
@@ -3970,7 +4060,8 @@ static bool generateInitPatternConstraints(
3970
4060
auto pattern = target.getInitializationPattern ();
3971
4061
auto locator =
3972
4062
cs.getConstraintLocator (initializer, LocatorPathElt::ContextualType ());
3973
- Type patternType = cs.generateConstraints (pattern, locator);
4063
+ Type patternType = cs.generateConstraints (
4064
+ pattern, locator, target.shouldBindPatternVarsOneWay ());
3974
4065
assert (patternType && " All patterns have a type" );
3975
4066
3976
4067
if (auto wrappedVar = target.getInitializationWrappedVar ()) {
@@ -4069,9 +4160,10 @@ Expr *ConstraintSystem::generateConstraints(Expr *expr, DeclContext *dc) {
4069
4160
}
4070
4161
4071
4162
Type ConstraintSystem::generateConstraints (Pattern *pattern,
4072
- ConstraintLocatorBuilder locator) {
4163
+ ConstraintLocatorBuilder locator,
4164
+ bool bindPatternVarsOneWay) {
4073
4165
ConstraintGenerator cg (*this , nullptr );
4074
- return cg.getTypeForPattern (pattern, locator);
4166
+ return cg.getTypeForPattern (pattern, locator, Type (), bindPatternVarsOneWay );
4075
4167
}
4076
4168
4077
4169
bool ConstraintSystem::canGenerateConstraints (StmtCondition condition) {
@@ -4129,100 +4221,6 @@ bool ConstraintSystem::generateConstraints(StmtCondition condition,
4129
4221
return false ;
4130
4222
}
4131
4223
4132
- void ConstraintSystem::bindVariablesInPattern (
4133
- Pattern *pattern, Type patternType, ConstraintLocator *locator) {
4134
- switch (pattern->getKind ()) {
4135
- case PatternKind::Paren: {
4136
- // Parentheses don't affect the type, but unwrap a paren type if we have
4137
- // one.
4138
- Type subPatternType;
4139
- if (auto parenType = dyn_cast<ParenType>(patternType.getPointer ()))
4140
- subPatternType = parenType->getUnderlyingType ();
4141
- else
4142
- subPatternType = patternType;
4143
- return bindVariablesInPattern (
4144
- cast<ParenPattern>(pattern)->getSubPattern (),
4145
- subPatternType, locator);
4146
- }
4147
-
4148
- case PatternKind::Var:
4149
- // Var doesn't affect the type.
4150
- return bindVariablesInPattern (cast<VarPattern>(pattern)->getSubPattern (),
4151
- patternType, locator);
4152
-
4153
- case PatternKind::Any:
4154
- // Nothing to bind.
4155
- return ;
4156
-
4157
- case PatternKind::Named: {
4158
- auto var = cast<NamedPattern>(pattern)->getDecl ();
4159
-
4160
- // / Create a fresh type variable to describe the type of the bound variable.
4161
- Type varType = createTypeVariable (locator, TVO_CanBindToNoEscape);
4162
-
4163
- auto ROK = ReferenceOwnership::Strong;
4164
- if (auto *OA = var->getAttrs ().getAttribute <ReferenceOwnershipAttr>())
4165
- ROK = OA->get ();
4166
- switch (optionalityOf (ROK)) {
4167
- case ReferenceOwnershipOptionality::Required:
4168
- // FIXME: Can we assert this rather than just checking it.
4169
- if (auto optPatternType =
4170
- dyn_cast<OptionalType>(patternType.getPointer ())) {
4171
- // Add a one-way constraint from the type variable to the wrapped
4172
- // type of the optional.
4173
- addConstraint (
4174
- ConstraintKind::OneWayEqual, varType, optPatternType->getBaseType (),
4175
- locator);
4176
-
4177
- // Make the variable type optional.
4178
- varType = TypeChecker::getOptionalType (var->getLoc (), varType);
4179
- break ;
4180
- }
4181
-
4182
- // Fall through to treat this normally.
4183
- LLVM_FALLTHROUGH;
4184
-
4185
- case ReferenceOwnershipOptionality::Allowed:
4186
- case ReferenceOwnershipOptionality::Disallowed:
4187
- // Add the one-way constraint from the variable type to the pattern
4188
- // type.
4189
- addConstraint (ConstraintKind::OneWayEqual, varType, patternType,
4190
- locator);
4191
- break ;
4192
- }
4193
-
4194
- // Bind the type of the variable.
4195
- setType (var, varType);
4196
- return ;
4197
- }
4198
-
4199
- case PatternKind::Typed: {
4200
- // Ignore the type itself; it's part of patternType now.
4201
- return bindVariablesInPattern (
4202
- cast<TypedPattern>(pattern)->getSubPattern (),
4203
- patternType, locator);
4204
- }
4205
-
4206
- case PatternKind::Tuple: {
4207
- auto tuplePat = cast<TuplePattern>(pattern);
4208
- auto tupleType = patternType->castTo <TupleType>();
4209
- for (unsigned i = 0 , e = tuplePat->getNumElements (); i != e; ++i) {
4210
- bindVariablesInPattern (tuplePat->getElement (i).getPattern (),
4211
- tupleType->getElementType (i), locator);
4212
- }
4213
- return ;
4214
- }
4215
-
4216
- // FIXME: Refutable patterns will generate additional constraints.
4217
- #define PATTERN (Id, Parent )
4218
- #define REFUTABLE_PATTERN (Id, Parent ) case PatternKind::Id:
4219
- #include " swift/AST/PatternNodes.def"
4220
- llvm_unreachable (" Refutable patterns are not supported here" );
4221
- }
4222
-
4223
- llvm_unreachable (" Unhandled pattern kind" );
4224
- }
4225
-
4226
4224
void ConstraintSystem::optimizeConstraints (Expr *e) {
4227
4225
if (getASTContext ().TypeCheckerOpts .DisableConstraintSolverPerformanceHacks )
4228
4226
return ;
0 commit comments