Skip to content

Commit 5eea0ae

Browse files
authored
Merge pull request #30803 from xedin/rdar-60961087
[CSGen] Bring back performance hack for named patterns with an initializer expression
2 parents bdb2aee + 4bc049b commit 5eea0ae

File tree

2 files changed

+68
-12
lines changed

2 files changed

+68
-12
lines changed

lib/Sema/CSGen.cpp

Lines changed: 50 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2286,8 +2286,30 @@ namespace {
22862286
case PatternKind::Named: {
22872287
auto var = cast<NamedPattern>(pattern)->getDecl();
22882288

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);
22912313

22922314
// When we are supposed to bind pattern variables, create a fresh
22932315
// type variable and a one-way constraint to assign it to either the
@@ -2308,7 +2330,19 @@ namespace {
23082330
ROK = OA->get();
23092331
switch (optionalityOf(ROK)) {
23102332
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+
23112344
varType = TypeChecker::getOptionalType(var->getLoc(), varType);
2345+
23122346
if (oneWayVarType) {
23132347
oneWayVarType =
23142348
TypeChecker::getOptionalType(var->getLoc(), oneWayVarType);
@@ -2342,15 +2376,17 @@ namespace {
23422376

23432377
Type openedType = CS.openUnboundGenericType(type, locator);
23442378

2379+
auto *subPattern = cast<TypedPattern>(pattern)->getSubPattern();
23452380
// Determine the subpattern type. It will be convertible to the
23462381
// 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+
23512387
CS.addConstraint(
23522388
ConstraintKind::Conversion, subPatternType, openedType,
2353-
locator.withPathElement(LocatorPathElt::PatternMatch(pattern)));
2389+
locator.withPathElement(LocatorPathElt::PatternMatch(pattern)));
23542390
return setType(openedType);
23552391
}
23562392

@@ -2385,11 +2421,11 @@ namespace {
23852421
if (!externalEltTypes.empty())
23862422
externalEltType = externalEltTypes[i].getPlainType();
23872423

2424+
auto *eltPattern = tupleElt.getPattern();
23882425
Type eltTy = getTypeForPattern(
2389-
tupleElt.getPattern(),
2390-
locator,
2391-
externalEltType,
2392-
bindPatternVarsOneWay);
2426+
eltPattern,
2427+
locator.withPathElement(LocatorPathElt::PatternMatch(eltPattern)),
2428+
externalEltType, bindPatternVarsOneWay);
23932429
tupleTypeElts.push_back(TupleTypeElt(eltTy, tupleElt.getLabel()));
23942430
}
23952431

@@ -2410,9 +2446,11 @@ namespace {
24102446
externalPatternType = objVar;
24112447
}
24122448

2449+
auto *subPattern = cast<OptionalSomePattern>(pattern)->getSubPattern();
24132450
// The subpattern must have optional type.
24142451
Type subPatternType = getTypeForPattern(
2415-
cast<OptionalSomePattern>(pattern)->getSubPattern(), locator,
2452+
subPattern,
2453+
locator.withPathElement(LocatorPathElt::PatternMatch(subPattern)),
24162454
externalPatternType, bindPatternVarsOneWay);
24172455

24182456
return setType(OptionalType::get(subPatternType));
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// RUN: %scale-test --begin 1 --end 10 --step 1 --select NumLeafScopes %s
2+
// REQUIRES: asserts,no_asan
3+
4+
func test(_ array: [UInt8]) {
5+
var bytes = array.makeIterator()
6+
7+
while let firstByte = bytes.next() {
8+
let secondByte = bytes.next() ?? 0
9+
10+
let encoded = (
11+
(firstByte & 0xF8) >> 3,
12+
%for i in range(0, N):
13+
((firstByte & 0x07) << 2) | ((secondByte & 0xC0) >> 6),
14+
%end
15+
(firstByte & 0xF8) >> 3
16+
)
17+
}
18+
}

0 commit comments

Comments
 (0)