Skip to content

Commit a339e28

Browse files
committed
Merge remote-tracking branch 'origin/main' into rebranch
2 parents cb6888d + 9a0a831 commit a339e28

17 files changed

+97
-83
lines changed

include/swift/AST/Types.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -720,6 +720,12 @@ class alignas(1 << TypeAlignInBits) TypeBase
720720
return getRecursiveProperties().hasTypeVariable();
721721
}
722722

723+
// Convenience for checking whether the given type either has a type
724+
// variable or placeholder.
725+
bool hasTypeVariableOrPlaceholder() const {
726+
return hasTypeVariable() || hasPlaceholder();
727+
}
728+
723729
/// Determine where this type is a type variable or a dependent
724730
/// member root in a type variable.
725731
bool isTypeVariableOrMember();

include/swift/Sema/ConstraintSystem.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -102,9 +102,7 @@ enum class FreeTypeVariableBinding {
102102
/// Disallow any binding of such free type variables.
103103
Disallow,
104104
/// Allow the free type variables to persist in the solution.
105-
Allow,
106-
/// Bind the type variables to UnresolvedType to represent the ambiguity.
107-
UnresolvedType
105+
Allow
108106
};
109107

110108
/// Describes whether or not a result builder method is supported.

lib/AST/ASTContext.cpp

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3577,7 +3577,13 @@ void LocatableType::Profile(llvm::FoldingSetNodeID &id, SourceLoc loc,
35773577
Type ErrorType::get(const ASTContext &C) { return C.TheErrorType; }
35783578

35793579
Type ErrorType::get(Type originalType) {
3580-
assert(originalType);
3580+
ASSERT(originalType);
3581+
// We don't currently support solver-allocated error types, if we want
3582+
// this in the future we'll need to adjust `Solution::simplifyType` to fold
3583+
// them into regular ErrorTypes. Additionally, any clients of
3584+
// `typesSatisfyConstraint` will need to be taught not to pass such types.
3585+
ASSERT(!originalType->getRecursiveProperties().isSolverAllocated() &&
3586+
"Solver-allocated error types not supported");
35813587

35823588
auto originalProperties = originalType->getRecursiveProperties();
35833589
auto arena = getArena(originalProperties);
@@ -3588,14 +3594,8 @@ Type ErrorType::get(Type originalType) {
35883594

35893595
void *mem = ctx.Allocate(sizeof(ErrorType) + sizeof(Type),
35903596
alignof(ErrorType), arena);
3591-
RecursiveTypeProperties properties = RecursiveTypeProperties::HasError;
3592-
3593-
// We need to preserve the solver allocated bit, to ensure any wrapping
3594-
// types are solver allocated too.
3595-
if (originalProperties.isSolverAllocated())
3596-
properties |= RecursiveTypeProperties::SolverAllocated;
3597-
3598-
return entry = new (mem) ErrorType(ctx, originalType, properties);
3597+
return entry = new (mem) ErrorType(ctx, originalType,
3598+
RecursiveTypeProperties::HasError);
35993599
}
36003600

36013601
void ErrorUnionType::Profile(llvm::FoldingSetNodeID &id, ArrayRef<Type> terms) {

lib/AST/TypeSubstitution.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -446,8 +446,13 @@ Type TypeSubstituter::transformDependentMemberType(DependentMemberType *dependen
446446

447447
auto result = conformance.getTypeWitness(assocType, IFS.getOptions());
448448
if (result->is<ErrorType>()) {
449+
// Substitute the base type for the original ErrorType for type printing.
450+
// Avoid doing this if the substitutions introduce type variables or
451+
// placeholders since ErrorTypes can't be solver-allocated currently (and
452+
// type variables aren't helpful when printing anyway).
449453
auto substBase = origBase.subst(IFS);
450-
return DependentMemberType::get(ErrorType::get(substBase), assocType);
454+
if (!substBase->hasTypeVariableOrPlaceholder())
455+
return DependentMemberType::get(ErrorType::get(substBase), assocType);
451456
}
452457
return result;
453458
}
@@ -1242,4 +1247,4 @@ ProtocolConformanceRef ReplaceExistentialArchetypesWithConcreteTypes::operator()
12421247

12431248
return subs.lookupConformance(
12441249
getInterfaceType(existentialArchetype)->getCanonicalType(), proto);
1245-
}
1250+
}

lib/Sema/CSFix.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -185,9 +185,12 @@ CoerceToCheckedCast *CoerceToCheckedCast::attempt(ConstraintSystem &cs,
185185
Type fromType, Type toType,
186186
bool useConditionalCast,
187187
ConstraintLocator *locator) {
188-
// If any of the types has a type variable, don't add the fix.
189-
if (fromType->hasTypeVariable() || toType->hasTypeVariable())
188+
// If any of the types have type variables or placeholders, don't add the fix.
189+
// `typeCheckCheckedCast` doesn't support checking such types.
190+
if (fromType->hasTypeVariableOrPlaceholder() ||
191+
toType->hasTypeVariableOrPlaceholder()) {
190192
return nullptr;
193+
}
191194

192195
auto anchor = locator->getAnchor();
193196
if (auto *assignExpr = getAsExpr<AssignExpr>(anchor))

lib/Sema/CSGen.cpp

Lines changed: 10 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -4872,29 +4872,16 @@ bool ConstraintSystem::generateConstraints(
48724872
return convertTypeLocator;
48734873
};
48744874

4875-
// Substitute type variables in for placeholder types (and unresolved
4876-
// types, if allowed).
4877-
if (allowFreeTypeVariables == FreeTypeVariableBinding::UnresolvedType) {
4878-
convertType = convertType.transformRec([&](Type type) -> std::optional<Type> {
4879-
if (type->is<UnresolvedType>() || type->is<PlaceholderType>()) {
4880-
return Type(createTypeVariable(getLocator(type),
4881-
TVO_CanBindToNoEscape |
4882-
TVO_PrefersSubtypeBinding |
4883-
TVO_CanBindToHole));
4884-
}
4885-
return std::nullopt;
4886-
});
4887-
} else {
4888-
convertType = convertType.transformRec([&](Type type) -> std::optional<Type> {
4889-
if (type->is<PlaceholderType>()) {
4890-
return Type(createTypeVariable(getLocator(type),
4891-
TVO_CanBindToNoEscape |
4892-
TVO_PrefersSubtypeBinding |
4893-
TVO_CanBindToHole));
4894-
}
4895-
return std::nullopt;
4896-
});
4897-
}
4875+
// Substitute type variables in for placeholder types.
4876+
convertType = convertType.transformRec([&](Type type) -> std::optional<Type> {
4877+
if (type->is<PlaceholderType>()) {
4878+
return Type(createTypeVariable(getLocator(type),
4879+
TVO_CanBindToNoEscape |
4880+
TVO_PrefersSubtypeBinding |
4881+
TVO_CanBindToHole));
4882+
}
4883+
return std::nullopt;
4884+
});
48984885

48994886
addContextualConversionConstraint(expr, convertType, ctp,
49004887
convertTypeLocator);

lib/Sema/CSRanking.cpp

Lines changed: 7 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1413,26 +1413,10 @@ SolutionCompareResult ConstraintSystem::compareSolutions(
14131413
auto type1 = types.Type1;
14141414
auto type2 = types.Type2;
14151415

1416-
// If either of the types still contains type variables, we can't
1417-
// compare them.
1418-
// FIXME: This is really unfortunate. More type variable sharing
1419-
// (when it's sound) would help us do much better here.
1420-
if (type1->hasTypeVariable() || type2->hasTypeVariable()) {
1421-
identical = false;
1422-
continue;
1423-
}
1424-
1425-
// With introduction of holes it's currently possible to form solutions
1426-
// with UnresolvedType bindings, we need to account for that in
1427-
// ranking. If one solution has a hole for a given type variable
1428-
// it's always worse than any non-hole type other solution might have.
1429-
if (type1->is<UnresolvedType>() || type2->is<UnresolvedType>()) {
1430-
if (type1->is<UnresolvedType>()) {
1431-
++score2;
1432-
} else {
1433-
++score1;
1434-
}
1435-
1416+
// If either of the types have holes or unresolved type variables, we can't
1417+
// compare them. `isSubtypeOf` cannot be used with solver-allocated types.
1418+
if (type1->hasTypeVariableOrPlaceholder() ||
1419+
type2->hasTypeVariableOrPlaceholder()) {
14361420
identical = false;
14371421
continue;
14381422
}
@@ -1469,15 +1453,12 @@ SolutionCompareResult ConstraintSystem::compareSolutions(
14691453
// The systems are not considered equivalent.
14701454
identical = false;
14711455

1472-
// Archetypes are worse than concrete types (i.e. non-placeholder and
1473-
// non-archetype)
1456+
// Archetypes are worse than concrete types
14741457
// FIXME: Total hack.
1475-
if (type1->is<ArchetypeType>() && !type2->is<ArchetypeType>() &&
1476-
!type2->is<PlaceholderType>()) {
1458+
if (type1->is<ArchetypeType>() && !type2->is<ArchetypeType>()) {
14771459
++score2;
14781460
continue;
1479-
} else if (type2->is<ArchetypeType>() && !type1->is<ArchetypeType>() &&
1480-
!type1->is<PlaceholderType>()) {
1461+
} else if (type2->is<ArchetypeType>() && !type1->is<ArchetypeType>()) {
14811462
++score1;
14821463
continue;
14831464
}

lib/Sema/CSSimplify.cpp

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4909,8 +4909,12 @@ static bool
49094909
repairViaBridgingCast(ConstraintSystem &cs, Type fromType, Type toType,
49104910
SmallVectorImpl<RestrictionOrFix> &conversionsOrFixes,
49114911
ConstraintLocatorBuilder locator) {
4912-
if (fromType->hasTypeVariable() || toType->hasTypeVariable())
4912+
// Don't check if any of the types have type variables or placeholders,
4913+
// `typeCheckCheckedCast` doesn't support checking solver-allocated types.
4914+
if (fromType->hasTypeVariableOrPlaceholder() ||
4915+
toType->hasTypeVariableOrPlaceholder()) {
49134916
return false;
4917+
}
49144918

49154919
auto objectType1 = fromType->getOptionalObjectType();
49164920
auto objectType2 = toType->getOptionalObjectType();
@@ -9375,10 +9379,12 @@ static ConstraintFix *maybeWarnAboutExtraneousCast(
93759379
if (locator.endsWith<LocatorPathElt::GenericArgument>())
93769380
return nullptr;
93779381

9378-
// Both types have to be fixed.
9379-
if (fromType->hasTypeVariable() || toType->hasTypeVariable() ||
9380-
fromType->hasPlaceholder() || toType->hasPlaceholder())
9382+
// Both types have to be resolved, `typeCheckCheckedCast` doesn't support
9383+
// checking solver-allocated types.
9384+
if (fromType->hasTypeVariableOrPlaceholder() ||
9385+
toType->hasTypeVariableOrPlaceholder()) {
93819386
return nullptr;
9387+
}
93829388

93839389
SmallVector<LocatorPathElt, 4> path;
93849390
auto anchor = locator.getLocatorParts(path);

lib/Sema/CSSolver.cpp

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -91,10 +91,6 @@ Solution ConstraintSystem::finalize() {
9191

9292
case FreeTypeVariableBinding::Allow:
9393
break;
94-
95-
case FreeTypeVariableBinding::UnresolvedType:
96-
assignFixedType(tv, ctx.TheUnresolvedType);
97-
break;
9894
}
9995
}
10096

lib/Sema/TypeCheckConstraints.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1080,8 +1080,14 @@ bool TypeChecker::typesSatisfyConstraint(Type type1, Type type2,
10801080
bool openArchetypes,
10811081
ConstraintKind kind, DeclContext *dc,
10821082
bool *unwrappedIUO) {
1083-
assert(!type1->hasTypeVariable() && !type2->hasTypeVariable() &&
1084-
"Unexpected type variable in constraint satisfaction testing");
1083+
// Don't allow any type variables to leak into the nested ConstraintSystem
1084+
// (including as originator types for placeholders). This also ensure that we
1085+
// avoid lifetime issues for e.g cases where we lazily populate the
1086+
// `ContextSubMap` on `NominalOrBoundGenericNominalType` in the nested arena,
1087+
// since it will be destroyed on leaving.
1088+
ASSERT(!type1->getRecursiveProperties().isSolverAllocated() &&
1089+
!type2->getRecursiveProperties().isSolverAllocated() &&
1090+
"Cannot escape solver-allocated types into a nested ConstraintSystem");
10851091

10861092
ConstraintSystem cs(dc, ConstraintSystemOptions());
10871093
if (openArchetypes) {

0 commit comments

Comments
 (0)