Skip to content

Commit 7e05b53

Browse files
authored
Merge pull request #9954 from slavapestov/fix-inout-crash
Start cleaning up "must be materializable" type variables
2 parents e73e11b + 39d0385 commit 7e05b53

File tree

8 files changed

+146
-83
lines changed

8 files changed

+146
-83
lines changed

lib/Sema/CSDiag.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5551,7 +5551,9 @@ namespace {
55515551
cs.getConstraintLocator(expr, ConstraintLocator::FunctionResult);
55525552

55535553
auto tv = cs.createTypeVariable(inputLocator,
5554-
TVO_CanBindToLValue|TVO_PrefersSubtypeBinding);
5554+
TVO_CanBindToLValue |
5555+
TVO_CanBindToInOut |
5556+
TVO_PrefersSubtypeBinding);
55555557

55565558
// In order to make this work, we pick the most general function type and
55575559
// use a conversion constraint. This gives us:
@@ -7224,7 +7226,7 @@ bool FailureDiagnosis::visitKeyPathExpr(KeyPathExpr *KPE) {
72247226

72257227
bool builtConstraints(ConstraintSystem &cs, Expr *expr) override {
72267228
auto *locator = cs.getConstraintLocator(expr);
7227-
auto valueType = cs.createTypeVariable(locator, /* options */ 0);
7229+
auto valueType = cs.createTypeVariable(locator, TVO_CanBindToInOut);
72287230

72297231
auto keyPathType =
72307232
BoundGenericClassType::get(Decl, ParentType, {RootType, valueType});

lib/Sema/CSGen.cpp

Lines changed: 84 additions & 47 deletions
Large diffs are not rendered by default.

lib/Sema/CSSimplify.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2407,7 +2407,9 @@ ConstraintSystem::simplifyConstructionConstraint(
24072407
auto fnLocator = getConstraintLocator(locator,
24082408
ConstraintLocator::ApplyFunction);
24092409
auto tv = createTypeVariable(applyLocator,
2410-
TVO_CanBindToLValue|TVO_PrefersSubtypeBinding);
2410+
TVO_CanBindToLValue |
2411+
TVO_CanBindToInOut |
2412+
TVO_PrefersSubtypeBinding);
24112413

24122414
// The constructor will have function type T -> T2, for a fresh type
24132415
// variable T. T2 is the result type provided via the construction
@@ -4535,7 +4537,9 @@ ConstraintSystem::simplifyRestrictedConstraintImpl(
45354537
return SolutionKind::Error;
45364538

45374539
auto constraintLocator = getConstraintLocator(locator);
4538-
auto tv = createTypeVariable(constraintLocator, TVO_PrefersSubtypeBinding);
4540+
auto tv = createTypeVariable(constraintLocator,
4541+
TVO_PrefersSubtypeBinding |
4542+
TVO_CanBindToInOut);
45394543

45404544
addConstraint(ConstraintKind::ConformsTo, tv,
45414545
hashableProtocol->getDeclaredType(), constraintLocator);

lib/Sema/CSSolver.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1991,7 +1991,8 @@ ConstraintSystem::solve(Expr *&expr,
19911991
if (allowFreeTypeVariables == FreeTypeVariableBinding::UnresolvedType) {
19921992
convertType = convertType.transform([&](Type type) -> Type {
19931993
if (type->is<UnresolvedType>())
1994-
return createTypeVariable(getConstraintLocator(expr), 0);
1994+
return createTypeVariable(getConstraintLocator(expr),
1995+
TVO_CanBindToInOut);
19951996
return type;
19961997
});
19971998
}

lib/Sema/ConstraintSystem.cpp

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -871,7 +871,8 @@ ConstraintSystem::getTypeOfReference(ValueDecl *value,
871871
if (param->isLet() && valueType->is<TypeVariableType>()) {
872872
Type paramType = valueType;
873873
valueType = createTypeVariable(getConstraintLocator(locator),
874-
TVO_CanBindToLValue);
874+
TVO_CanBindToLValue |
875+
TVO_CanBindToInOut);
875876
addConstraint(ConstraintKind::BindParam, paramType, valueType,
876877
getConstraintLocator(locator));
877878
}
@@ -973,8 +974,7 @@ void ConstraintSystem::openGeneric(
973974
locator.withPathElement(LocatorPathElt(archetype)));
974975

975976
auto typeVar = createTypeVariable(locatorPtr,
976-
TVO_PrefersSubtypeBinding |
977-
TVO_MustBeMaterializable);
977+
TVO_PrefersSubtypeBinding);
978978
auto result = replacements.insert(
979979
std::make_pair(cast<GenericTypeParamType>(gp->getCanonicalType()),
980980
typeVar));
@@ -1353,9 +1353,11 @@ resolveOverloadForDeclWithSpecialTypeCheckingSemantics(ConstraintSystem &CS,
13531353
// existentials (as seen from the current abstraction level), which can't
13541354
// be expressed in the type system currently.
13551355
auto input = CS.createTypeVariable(
1356-
CS.getConstraintLocator(locator, ConstraintLocator::FunctionArgument), 0);
1356+
CS.getConstraintLocator(locator, ConstraintLocator::FunctionArgument),
1357+
TVO_CanBindToInOut);
13571358
auto output = CS.createTypeVariable(
1358-
CS.getConstraintLocator(locator, ConstraintLocator::FunctionResult), 0);
1359+
CS.getConstraintLocator(locator, ConstraintLocator::FunctionResult),
1360+
TVO_CanBindToInOut);
13591361

13601362
auto inputArg = TupleTypeElt(input, CS.getASTContext().getIdentifier("of"));
13611363
auto inputTuple = TupleType::get(inputArg, CS.getASTContext());
@@ -1371,14 +1373,17 @@ resolveOverloadForDeclWithSpecialTypeCheckingSemantics(ConstraintSystem &CS,
13711373
// receives a copy of the argument closure that is temporarily made
13721374
// @escaping.
13731375
auto noescapeClosure = CS.createTypeVariable(
1374-
CS.getConstraintLocator(locator, ConstraintLocator::FunctionArgument), 0);
1376+
CS.getConstraintLocator(locator, ConstraintLocator::FunctionArgument),
1377+
TVO_CanBindToInOut);
13751378
auto escapeClosure = CS.createTypeVariable(
1376-
CS.getConstraintLocator(locator, ConstraintLocator::FunctionArgument), 0);
1379+
CS.getConstraintLocator(locator, ConstraintLocator::FunctionArgument),
1380+
TVO_CanBindToInOut);
13771381
CS.addConstraint(ConstraintKind::EscapableFunctionOf,
13781382
escapeClosure, noescapeClosure,
13791383
CS.getConstraintLocator(locator, ConstraintLocator::RvalueAdjustment));
13801384
auto result = CS.createTypeVariable(
1381-
CS.getConstraintLocator(locator, ConstraintLocator::FunctionResult), 0);
1385+
CS.getConstraintLocator(locator, ConstraintLocator::FunctionResult),
1386+
TVO_CanBindToInOut);
13821387
auto bodyClosure = FunctionType::get(
13831388
ParenType::get(CS.getASTContext(), escapeClosure), result,
13841389
FunctionType::ExtInfo(FunctionType::Representation::Swift,
@@ -1403,14 +1408,17 @@ resolveOverloadForDeclWithSpecialTypeCheckingSemantics(ConstraintSystem &CS,
14031408
// The body closure receives a freshly-opened archetype constrained by the
14041409
// existential type as its input.
14051410
auto openedTy = CS.createTypeVariable(
1406-
CS.getConstraintLocator(locator, ConstraintLocator::FunctionArgument), 0);
1411+
CS.getConstraintLocator(locator, ConstraintLocator::FunctionArgument),
1412+
TVO_CanBindToInOut);
14071413
auto existentialTy = CS.createTypeVariable(
1408-
CS.getConstraintLocator(locator, ConstraintLocator::FunctionArgument), 0);
1414+
CS.getConstraintLocator(locator, ConstraintLocator::FunctionArgument),
1415+
TVO_CanBindToInOut);
14091416
CS.addConstraint(ConstraintKind::OpenedExistentialOf,
14101417
openedTy, existentialTy,
14111418
CS.getConstraintLocator(locator, ConstraintLocator::RvalueAdjustment));
14121419
auto result = CS.createTypeVariable(
1413-
CS.getConstraintLocator(locator, ConstraintLocator::FunctionResult), 0);
1420+
CS.getConstraintLocator(locator, ConstraintLocator::FunctionResult),
1421+
TVO_CanBindToInOut);
14141422
auto bodyClosure = FunctionType::get(
14151423
ParenType::get(CS.getASTContext(), openedTy), result,
14161424
FunctionType::ExtInfo(FunctionType::Representation::Swift,
@@ -1543,12 +1551,15 @@ void ConstraintSystem::resolveOverload(ConstraintLocator *locator,
15431551
// The element type is T or @lvalue T based on the key path subtype and
15441552
// the mutability of the base.
15451553
auto keyPathIndexTy = createTypeVariable(
1546-
getConstraintLocator(locator, ConstraintLocator::FunctionArgument), 0);
1554+
getConstraintLocator(locator, ConstraintLocator::FunctionArgument),
1555+
TVO_CanBindToInOut);
15471556
auto elementTy = createTypeVariable(
15481557
getConstraintLocator(locator, ConstraintLocator::FunctionArgument),
1549-
TVO_CanBindToLValue);
1558+
TVO_CanBindToLValue |
1559+
TVO_CanBindToInOut);
15501560
auto elementObjTy = createTypeVariable(
1551-
getConstraintLocator(locator, ConstraintLocator::FunctionArgument), 0);
1561+
getConstraintLocator(locator, ConstraintLocator::FunctionArgument),
1562+
TVO_CanBindToInOut);
15521563
addConstraint(ConstraintKind::Equal, elementTy, elementObjTy, locator);
15531564

15541565
// The element result is an lvalue or rvalue based on the key path class.

lib/Sema/ConstraintSystem.h

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -122,12 +122,12 @@ enum TypeVariableOptions {
122122
/// Whether the type variable can be bound to an lvalue type or not.
123123
TVO_CanBindToLValue = 0x01,
124124

125+
/// Whether the type variable can be bound to an inout type or not.
126+
TVO_CanBindToInOut = 0x02,
127+
125128
/// Whether a more specific deduction for this type variable implies a
126129
/// better solution to the constraint system.
127-
TVO_PrefersSubtypeBinding = 0x02,
128-
129-
/// Whether the variable must be bound to a materializable type.
130-
TVO_MustBeMaterializable = 0x04
130+
TVO_PrefersSubtypeBinding = 0x04
131131
};
132132

133133
/// \brief The implementation object for a type variable used within the
@@ -170,14 +170,17 @@ class TypeVariableType::Implementation {
170170
/// Whether this type variable can bind to an lvalue type.
171171
bool canBindToLValue() const { return Options & TVO_CanBindToLValue; }
172172

173+
/// Whether this type variable can bind to an inout type.
174+
bool canBindToInOut() const { return Options & TVO_CanBindToInOut; }
175+
173176
/// Whether this type variable prefers a subtype binding over a supertype
174177
/// binding.
175178
bool prefersSubtypeBinding() const {
176179
return Options & TVO_PrefersSubtypeBinding;
177180
}
178181

179182
bool mustBeMaterializable() const {
180-
return Options & TVO_MustBeMaterializable;
183+
return !(Options & TVO_CanBindToInOut) && !(Options & TVO_CanBindToLValue);
181184
}
182185

183186
/// \brief Retrieve the type variable associated with this implementation.
@@ -297,7 +300,8 @@ class TypeVariableType::Implementation {
297300
if (!mustBeMaterializable() && otherRep->getImpl().mustBeMaterializable()) {
298301
if (record)
299302
recordBinding(*record);
300-
Options |= TVO_MustBeMaterializable;
303+
Options &= ~TVO_CanBindToLValue;
304+
Options &= ~TVO_CanBindToInOut;
301305
}
302306
}
303307

@@ -338,7 +342,8 @@ class TypeVariableType::Implementation {
338342
if (!rep->getImpl().mustBeMaterializable()) {
339343
if (record)
340344
rep->getImpl().recordBinding(*record);
341-
rep->getImpl().Options |= TVO_MustBeMaterializable;
345+
rep->getImpl().Options &= ~TVO_CanBindToLValue;
346+
rep->getImpl().Options &= ~TVO_CanBindToInOut;
342347
}
343348
}
344349

lib/Sema/TypeCheckConstraints.cpp

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2037,7 +2037,9 @@ bool TypeChecker::typeCheckCompletionSequence(Expr *&expr, DeclContext *DC) {
20372037

20382038
// Add type variable for the code-completion expression.
20392039
auto tvRHS =
2040-
CS.createTypeVariable(CS.getConstraintLocator(CCE), TVO_CanBindToLValue);
2040+
CS.createTypeVariable(CS.getConstraintLocator(CCE),
2041+
TVO_CanBindToLValue |
2042+
TVO_CanBindToInOut);
20412043
CCE->setType(tvRHS);
20422044

20432045
if (auto generated = CS.generateConstraints(expr)) {
@@ -2333,7 +2335,7 @@ bool TypeChecker::typeCheckForEachBinding(DeclContext *dc, ForEachStmt *stmt) {
23332335
}
23342336

23352337
SequenceType =
2336-
cs.createTypeVariable(Locator, /*options=*/TVO_MustBeMaterializable);
2338+
cs.createTypeVariable(Locator, /*options=*/0);
23372339
cs.addConstraint(ConstraintKind::Conversion, cs.getType(expr),
23382340
SequenceType, Locator);
23392341
cs.addConstraint(ConstraintKind::ConformsTo, SequenceType,
@@ -2406,8 +2408,7 @@ bool TypeChecker::typeCheckForEachBinding(DeclContext *dc, ForEachStmt *stmt) {
24062408
}
24072409

24082410
if (elementType.isNull()) {
2409-
elementType = cs.createTypeVariable(elementLocator,
2410-
TVO_MustBeMaterializable);
2411+
elementType = cs.createTypeVariable(elementLocator, /*options=*/0);
24112412
}
24122413

24132414
// Add a conversion constraint between the element type of the sequence
@@ -2492,7 +2493,7 @@ Type ConstraintSystem::computeAssignDestType(Expr *dest, SourceLoc equalLoc) {
24922493
// Newly allocated type should be explicitly materializable,
24932494
// it's invalid to use non-materializable types as assignment destination.
24942495
auto objectTv = createTypeVariable(getConstraintLocator(dest),
2495-
TVO_MustBeMaterializable);
2496+
/*options=*/0);
24962497
auto refTv = LValueType::get(objectTv);
24972498
addConstraint(ConstraintKind::Bind, typeVar, refTv,
24982499
getConstraintLocator(dest));
@@ -2712,7 +2713,8 @@ static Type replaceArchetypesWithTypeVariables(ConstraintSystem &cs,
27122713
return Type();
27132714

27142715
auto locator = cs.getConstraintLocator(nullptr);
2715-
auto replacement = cs.createTypeVariable(locator, 0);
2716+
auto replacement = cs.createTypeVariable(locator,
2717+
TVO_CanBindToInOut);
27162718

27172719
if (auto superclass = archetypeType->getSuperclass()) {
27182720
cs.addConstraint(ConstraintKind::Subtype, replacement,
@@ -2729,7 +2731,8 @@ static Type replaceArchetypesWithTypeVariables(ConstraintSystem &cs,
27292731
// FIXME: Remove this case
27302732
assert(cast<GenericTypeParamType>(origType));
27312733
auto locator = cs.getConstraintLocator(nullptr);
2732-
auto replacement = cs.createTypeVariable(locator, 0);
2734+
auto replacement = cs.createTypeVariable(locator,
2735+
TVO_CanBindToInOut);
27332736
types[origType] = replacement;
27342737
return replacement;
27352738
},
@@ -3109,8 +3112,8 @@ void ConstraintSystem::print(raw_ostream &out) {
31093112
tv->getImpl().print(out);
31103113
if (tv->getImpl().canBindToLValue())
31113114
out << " [lvalue allowed]";
3112-
if (tv->getImpl().mustBeMaterializable())
3113-
out << " [must be materializable]";
3115+
if (tv->getImpl().canBindToInOut())
3116+
out << " [inout allowed]";
31143117
auto rep = getRepresentative(tv);
31153118
if (rep == tv) {
31163119
if (auto fixed = getFixedType(tv)) {
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,6 @@
55
// See https://swift.org/LICENSE.txt for license information
66
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
77

8-
// RUN: not --crash %target-swift-frontend %s -emit-ir
8+
// RUN: not %target-swift-frontend %s -emit-ir
99
// REQUIRES: asserts
1010
&[_=(&_

0 commit comments

Comments
 (0)