Skip to content

Commit 57ae9de

Browse files
authored
Merge pull request #84030 from hamishknight/hole-in-one
[CS] Avoid unnecessary type variables when opening ErrorTypes
2 parents 090bc16 + ef7d696 commit 57ae9de

File tree

6 files changed

+36
-36
lines changed

6 files changed

+36
-36
lines changed

include/swift/AST/Types.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7734,8 +7734,8 @@ class PlaceholderType : public TypeBase {
77347734
// NOTE: If you add a new Type-based originator, you'll need to update the
77357735
// recursive property logic in PlaceholderType::get.
77367736
using Originator =
7737-
llvm::PointerUnion<TypeVariableType *, DependentMemberType *, VarDecl *,
7738-
ErrorExpr *, TypeRepr *>;
7737+
llvm::PointerUnion<TypeVariableType *, DependentMemberType *, ErrorType *,
7738+
VarDecl *, ErrorExpr *, TypeRepr *>;
77397739

77407740
Originator O;
77417741

lib/AST/ASTContext.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3675,6 +3675,9 @@ Type PlaceholderType::get(ASTContext &ctx, Originator originator) {
36753675
if (auto *depTy = originator.dyn_cast<DependentMemberType *>())
36763676
return depTy->getRecursiveProperties();
36773677

3678+
if (auto *errTy = originator.dyn_cast<ErrorType *>())
3679+
return errTy->getRecursiveProperties();
3680+
36783681
return RecursiveTypeProperties();
36793682
}();
36803683
auto arena = getArena(originatorProps);

lib/AST/ASTDumper.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6077,6 +6077,8 @@ namespace {
60776077
Label::optional("originating_var"), DeclColor);
60786078
} else if (isa<ErrorExpr *>(originator)) {
60796079
printFlag("error_expr");
6080+
} else if (auto *errTy = originator.dyn_cast<ErrorType *>()) {
6081+
printRec(errTy, Label::always("error_type"));
60806082
} else if (auto *DMT = originator.dyn_cast<DependentMemberType *>()) {
60816083
printRec(DMT, Label::always("dependent_member_type"));
60826084
} else if (isa<TypeRepr *>(originator)) {

lib/AST/ASTPrinter.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6146,6 +6146,8 @@ class TypePrinter : public TypeVisitor<TypePrinter, void, NonRecursivePrintOptio
61466146
Printer << VD->getName();
61476147
} else if (isa<ErrorExpr *>(originator)) {
61486148
Printer << "error_expr";
6149+
} else if (auto *errTy = originator.dyn_cast<ErrorType *>()) {
6150+
visit(errTy);
61496151
} else if (auto *DMT = originator.dyn_cast<DependentMemberType *>()) {
61506152
visit(DMT);
61516153
} else if (isa<TypeRepr *>(originator)) {

lib/Sema/CSGen.cpp

Lines changed: 25 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1712,17 +1712,12 @@ namespace {
17121712
const auto result = TypeResolution::resolveContextualType(
17131713
repr, CS.DC, options, genericOpener, placeholderHandler,
17141714
packElementOpener, requirementOpener);
1715+
// If we have an error, record a fix and produce a hole for the type.
17151716
if (result->hasError()) {
17161717
CS.recordFix(
17171718
IgnoreInvalidASTNode::create(CS, CS.getConstraintLocator(locator)));
17181719

1719-
// Immediately bind the result to a hole since we know it's invalid and
1720-
// want it to propagate rather than allowing other type variables to
1721-
// become holes.
1722-
auto *tv = CS.createTypeVariable(CS.getConstraintLocator(repr),
1723-
TVO_CanBindToHole);
1724-
CS.recordTypeVariablesAsHoles(tv);
1725-
return tv;
1720+
return PlaceholderType::get(CS.getASTContext(), repr);
17261721
}
17271722
// Diagnose top-level usages of placeholder types.
17281723
if (auto *ty = dyn_cast<PlaceholderTypeRepr>(repr->getWithoutParens())) {
@@ -4901,18 +4896,6 @@ bool ConstraintSystem::generateConstraints(
49014896
getConstraintLocator(expr, LocatorPathElt::ContextualType(ctp));
49024897
}
49034898

4904-
auto getLocator = [&](Type ty) -> ConstraintLocator * {
4905-
// If we have a placeholder originating from a PlaceholderTypeRepr,
4906-
// tack that on to the locator.
4907-
if (auto *placeholderTy = ty->getAs<PlaceholderType>())
4908-
if (auto *typeRepr = placeholderTy->getOriginator()
4909-
.dyn_cast<TypeRepr *>())
4910-
return getConstraintLocator(
4911-
convertTypeLocator,
4912-
LocatorPathElt::PlaceholderType(typeRepr));
4913-
return convertTypeLocator;
4914-
};
4915-
49164899
// If the contextual type has an error, we can't apply the solution.
49174900
// Record a fix for an invalid AST node.
49184901
if (convertType->hasError())
@@ -4921,18 +4904,30 @@ bool ConstraintSystem::generateConstraints(
49214904
// Substitute type variables in for placeholder and error types.
49224905
convertType =
49234906
convertType.transformRec([&](Type type) -> std::optional<Type> {
4924-
if (!isa<PlaceholderType, ErrorType>(type.getPointer()))
4925-
return std::nullopt;
4926-
4927-
auto flags = TVO_CanBindToNoEscape | TVO_PrefersSubtypeBinding |
4928-
TVO_CanBindToHole;
4929-
auto tv = Type(createTypeVariable(getLocator(type), flags));
4930-
// For ErrorTypes we want to eagerly bind to a hole since we
4931-
// know this is where the issue is.
4932-
if (isa<ErrorType>(type.getPointer())) {
4933-
recordTypeVariablesAsHoles(tv);
4907+
auto *tyPtr = type.getPointer();
4908+
// Open a type variable for a placeholder type repr. Note we don't
4909+
// do this for arbitrary placeholders since they may be existing
4910+
// holes when e.g generating the constraints for a ReturnStmt in a
4911+
// closure.
4912+
if (auto *placeholderTy = dyn_cast<PlaceholderType>(tyPtr)) {
4913+
auto originator = placeholderTy->getOriginator();
4914+
auto *typeRepr = originator.dyn_cast<TypeRepr *>();
4915+
if (!isa_and_nonnull<PlaceholderTypeRepr>(typeRepr))
4916+
return std::nullopt;
4917+
4918+
auto *loc = getConstraintLocator(
4919+
convertTypeLocator,
4920+
LocatorPathElt::PlaceholderType(typeRepr));
4921+
return createTypeVariable(loc, TVO_CanBindToNoEscape |
4922+
TVO_PrefersSubtypeBinding |
4923+
TVO_CanBindToHole);
49344924
}
4935-
return tv;
4925+
// For ErrorTypes we want to eagerly produce a hole since we know
4926+
// this is where the issue is.
4927+
if (auto *errTy = dyn_cast<ErrorType>(tyPtr)) {
4928+
return PlaceholderType::get(getASTContext(), errTy);
4929+
}
4930+
return std::nullopt;
49364931
});
49374932

49384933
addContextualConversionConstraint(expr, convertType, ctp,

lib/Sema/TypeOfReference.cpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -274,11 +274,9 @@ class InferableTypeOpener final {
274274
}
275275

276276
Type transformErrorType(ErrorType *errTy) {
277-
// For ErrorTypes we want to eagerly bind to a hole since we know this is
277+
// For ErrorTypes we want to eagerly produce a hole since we know this is
278278
// where the issue is.
279-
auto *tv = createTypeVariable(cs.getConstraintLocator(locator));
280-
cs.recordTypeVariablesAsHoles(tv);
281-
return tv;
279+
return PlaceholderType::get(cs.getASTContext(), errTy);
282280
}
283281

284282
Type transform(Type type) {

0 commit comments

Comments
 (0)