@@ -2286,8 +2286,30 @@ namespace {
2286
2286
case PatternKind::Named: {
2287
2287
auto var = cast<NamedPattern>(pattern)->getDecl ();
2288
2288
2289
- Type varType = CS.createTypeVariable (
2290
- CS.getConstraintLocator (locator), TVO_CanBindToNoEscape);
2289
+ Type varType;
2290
+
2291
+ // If we have a type from an initializer expression, and that
2292
+ // expression does not produce an InOut type, use it. This
2293
+ // will avoid exponential typecheck behavior in the case of
2294
+ // tuples, nested arrays, and dictionary literals.
2295
+ //
2296
+ // FIXME: This should be handled in the solver, not here.
2297
+ //
2298
+ // Otherwise, create a new type variable.
2299
+ bool assumedInitializerType = false ;
2300
+ if (!var->hasNonPatternBindingInit () &&
2301
+ !var->hasAttachedPropertyWrapper ()) {
2302
+ if (auto boundExpr = locator.trySimplifyToExpr ()) {
2303
+ if (!boundExpr->isSemanticallyInOutExpr ()) {
2304
+ varType = CS.getType (boundExpr)->getRValueType ();
2305
+ assumedInitializerType = true ;
2306
+ }
2307
+ }
2308
+ }
2309
+
2310
+ if (!assumedInitializerType)
2311
+ varType = CS.createTypeVariable (CS.getConstraintLocator (locator),
2312
+ TVO_CanBindToNoEscape);
2291
2313
2292
2314
// When we are supposed to bind pattern variables, create a fresh
2293
2315
// type variable and a one-way constraint to assign it to either the
@@ -2308,7 +2330,19 @@ namespace {
2308
2330
ROK = OA->get ();
2309
2331
switch (optionalityOf (ROK)) {
2310
2332
case ReferenceOwnershipOptionality::Required:
2333
+ if (assumedInitializerType) {
2334
+ // Already Optional<T>
2335
+ if (varType->getOptionalObjectType ())
2336
+ break ;
2337
+
2338
+ // Create a fresh type variable to handle overloaded expressions.
2339
+ if (varType->is <TypeVariableType>())
2340
+ varType = CS.createTypeVariable (CS.getConstraintLocator (locator),
2341
+ TVO_CanBindToNoEscape);
2342
+ }
2343
+
2311
2344
varType = TypeChecker::getOptionalType (var->getLoc (), varType);
2345
+
2312
2346
if (oneWayVarType) {
2313
2347
oneWayVarType =
2314
2348
TypeChecker::getOptionalType (var->getLoc (), oneWayVarType);
@@ -2342,15 +2376,17 @@ namespace {
2342
2376
2343
2377
Type openedType = CS.openUnboundGenericType (type, locator);
2344
2378
2379
+ auto *subPattern = cast<TypedPattern>(pattern)->getSubPattern ();
2345
2380
// Determine the subpattern type. It will be convertible to the
2346
2381
// ascribed type.
2347
- Type subPatternType =
2348
- getTypeForPattern (
2349
- cast<TypedPattern>(pattern)->getSubPattern (), locator,
2350
- Type (), bindPatternVarsOneWay);
2382
+ Type subPatternType = getTypeForPattern (
2383
+ subPattern,
2384
+ locator.withPathElement (LocatorPathElt::PatternMatch (subPattern)),
2385
+ Type (), bindPatternVarsOneWay);
2386
+
2351
2387
CS.addConstraint (
2352
2388
ConstraintKind::Conversion, subPatternType, openedType,
2353
- locator.withPathElement (LocatorPathElt::PatternMatch (pattern)));
2389
+ locator.withPathElement (LocatorPathElt::PatternMatch (pattern)));
2354
2390
return setType (openedType);
2355
2391
}
2356
2392
@@ -2385,11 +2421,11 @@ namespace {
2385
2421
if (!externalEltTypes.empty ())
2386
2422
externalEltType = externalEltTypes[i].getPlainType ();
2387
2423
2424
+ auto *eltPattern = tupleElt.getPattern ();
2388
2425
Type eltTy = getTypeForPattern (
2389
- tupleElt.getPattern (),
2390
- locator,
2391
- externalEltType,
2392
- bindPatternVarsOneWay);
2426
+ eltPattern,
2427
+ locator.withPathElement (LocatorPathElt::PatternMatch (eltPattern)),
2428
+ externalEltType, bindPatternVarsOneWay);
2393
2429
tupleTypeElts.push_back (TupleTypeElt (eltTy, tupleElt.getLabel ()));
2394
2430
}
2395
2431
@@ -2410,9 +2446,11 @@ namespace {
2410
2446
externalPatternType = objVar;
2411
2447
}
2412
2448
2449
+ auto *subPattern = cast<OptionalSomePattern>(pattern)->getSubPattern ();
2413
2450
// The subpattern must have optional type.
2414
2451
Type subPatternType = getTypeForPattern (
2415
- cast<OptionalSomePattern>(pattern)->getSubPattern (), locator,
2452
+ subPattern,
2453
+ locator.withPathElement (LocatorPathElt::PatternMatch (subPattern)),
2416
2454
externalPatternType, bindPatternVarsOneWay);
2417
2455
2418
2456
return setType (OptionalType::get (subPatternType));
0 commit comments