Skip to content

Commit c946c80

Browse files
authored
Merge pull request #34036 from xedin/replace-error-types-with-holes
[CSGen] Avoid failing on invalid declarations
2 parents 9e68f9d + bf58b0c commit c946c80

File tree

9 files changed

+66
-26
lines changed

9 files changed

+66
-26
lines changed

include/swift/AST/Types.h

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5740,19 +5740,19 @@ DEFINE_EMPTY_CAN_TYPE_WRAPPER(TypeVariableType, Type)
57405740
/// because the expression is ambiguous. This type is only used by the
57415741
/// constraint solver and transformed into UnresolvedType to be used in AST.
57425742
class HoleType : public TypeBase {
5743-
using OriginatorType =
5744-
llvm::PointerUnion<TypeVariableType *, DependentMemberType *>;
5743+
using Originator = llvm::PointerUnion<TypeVariableType *,
5744+
DependentMemberType *, VarDecl *>;
57455745

5746-
OriginatorType Originator;
5746+
Originator O;
57475747

5748-
HoleType(ASTContext &C, OriginatorType originator,
5748+
HoleType(ASTContext &C, Originator originator,
57495749
RecursiveTypeProperties properties)
5750-
: TypeBase(TypeKind::Hole, &C, properties), Originator(originator) {}
5750+
: TypeBase(TypeKind::Hole, &C, properties), O(originator) {}
57515751

57525752
public:
5753-
static Type get(ASTContext &ctx, OriginatorType originatorType);
5753+
static Type get(ASTContext &ctx, Originator originator);
57545754

5755-
OriginatorType getOriginatorType() const { return Originator; }
5755+
Originator getOriginator() const { return O; }
57565756

57575757
static bool classof(const TypeBase *T) {
57585758
return T->getKind() == TypeKind::Hole;

lib/AST/ASTContext.cpp

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2400,13 +2400,9 @@ Type ErrorType::get(Type originalType) {
24002400
return entry = new (mem) ErrorType(ctx, originalType, properties);
24012401
}
24022402

2403-
Type HoleType::get(ASTContext &ctx, OriginatorType originator) {
2403+
Type HoleType::get(ASTContext &ctx, Originator originator) {
24042404
assert(originator);
2405-
auto properties = reinterpret_cast<TypeBase *>(originator.getOpaqueValue())
2406-
->getRecursiveProperties();
2407-
properties |= RecursiveTypeProperties::HasTypeHole;
2408-
2409-
auto arena = getArena(properties);
2405+
auto arena = getArena(RecursiveTypeProperties::HasTypeHole);
24102406
return new (ctx, arena)
24112407
HoleType(ctx, originator, RecursiveTypeProperties::HasTypeHole);
24122408
}

lib/AST/ASTDumper.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3512,12 +3512,14 @@ namespace {
35123512

35133513
void visitHoleType(HoleType *T, StringRef label) {
35143514
printCommon(label, "hole_type");
3515-
auto originatorTy = T->getOriginatorType();
3516-
if (auto *typeVar = originatorTy.dyn_cast<TypeVariableType *>()) {
3515+
auto originator = T->getOriginator();
3516+
if (auto *typeVar = originator.dyn_cast<TypeVariableType *>()) {
35173517
printRec("type_variable", typeVar);
3518+
} else if (auto *VD = originator.dyn_cast<VarDecl *>()) {
3519+
VD->dumpRef(PrintWithColorRAII(OS, DeclColor).getOS());
35183520
} else {
35193521
printRec("dependent_member_type",
3520-
originatorTy.get<DependentMemberType *>());
3522+
originator.get<DependentMemberType *>());
35213523
}
35223524
PrintWithColorRAII(OS, ParenthesisColor) << ')';
35233525
}

lib/AST/ASTPrinter.cpp

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3822,8 +3822,15 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
38223822
void visitHoleType(HoleType *T) {
38233823
if (Options.PrintTypesForDebugging) {
38243824
Printer << "<<hole for ";
3825-
auto originatorTy = T->getOriginatorType();
3826-
visit(Type(reinterpret_cast<TypeBase *>(originatorTy.getOpaqueValue())));
3825+
auto originator = T->getOriginator();
3826+
if (auto *typeVar = originator.dyn_cast<TypeVariableType *>()) {
3827+
visit(typeVar);
3828+
} else if (auto *VD = originator.dyn_cast<VarDecl *>()) {
3829+
Printer << "decl = ";
3830+
Printer << VD->getName();
3831+
} else {
3832+
visit(originator.get<DependentMemberType *>());
3833+
}
38273834
Printer << ">>";
38283835
} else {
38293836
Printer << "<<hole>>";

lib/Sema/CSGen.cpp

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1241,19 +1241,20 @@ namespace {
12411241
if (auto *VD = dyn_cast<VarDecl>(E->getDecl())) {
12421242
knownType = CS.getTypeIfAvailable(VD);
12431243
if (!knownType)
1244-
knownType = VD->getType();
1244+
knownType = CS.getVarType(VD);
12451245

12461246
if (knownType) {
1247-
assert(!knownType->isHole());
12481247
// If the known type has an error, bail out.
12491248
if (knownType->hasError()) {
12501249
if (!CS.hasType(E))
12511250
CS.setType(E, knownType);
12521251
return nullptr;
12531252
}
12541253

1255-
// Set the favored type for this expression to the known type.
1256-
CS.setFavoredType(E, knownType.getPointer());
1254+
if (!knownType->hasHole()) {
1255+
// Set the favored type for this expression to the known type.
1256+
CS.setFavoredType(E, knownType.getPointer());
1257+
}
12571258
}
12581259

12591260
// This can only happen when failure diagnostics is trying
@@ -2016,7 +2017,7 @@ namespace {
20162017

20172018
Type externalType;
20182019
if (param->getTypeRepr()) {
2019-
auto declaredTy = param->getType();
2020+
auto declaredTy = CS.getVarType(param);
20202021
externalType = CS.openUnboundGenericTypes(declaredTy, paramLoc);
20212022
} else {
20222023
// Let's allow parameters which haven't been explicitly typed
@@ -3884,7 +3885,7 @@ bool ConstraintSystem::generateConstraints(
38843885
getConstraintLocator(typeRepr));
38853886
setType(typeRepr, backingType);
38863887

3887-
auto propertyType = wrappedVar->getType();
3888+
auto propertyType = getVarType(wrappedVar);
38883889
if (propertyType->hasError())
38893890
return true;
38903891

lib/Sema/CSSimplify.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7014,7 +7014,7 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyMemberConstraint(
70147014
// type but a hole.
70157015
auto shouldRecordFixForHole = [&](HoleType *baseType) {
70167016
auto *originator =
7017-
baseType->getOriginatorType().dyn_cast<TypeVariableType *>();
7017+
baseType->getOriginator().dyn_cast<TypeVariableType *>();
70187018

70197019
if (!originator)
70207020
return false;

lib/Sema/ConstraintSystem.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5209,3 +5209,21 @@ void ConstraintSystem::recordFixedRequirement(ConstraintLocator *reqLocator,
52095209
std::make_tuple(GP, reqKind, requirementTy.getPointer()));
52105210
}
52115211
}
5212+
5213+
// Replace any error types encountered with holes.
5214+
Type ConstraintSystem::getVarType(const VarDecl *var) {
5215+
auto type = var->getType();
5216+
5217+
// If this declaration is used as part of a code completion
5218+
// expression, solver needs to glance over the fact that
5219+
// it might be invalid to avoid failing constraint generation
5220+
// and produce completion results.
5221+
if (!isForCodeCompletion())
5222+
return type;
5223+
5224+
return type.transform([&](Type type) {
5225+
if (!type->is<ErrorType>())
5226+
return type;
5227+
return HoleType::get(Context, const_cast<VarDecl *>(var));
5228+
});
5229+
}

lib/Sema/ConstraintSystem.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1293,6 +1293,11 @@ enum class ConstraintSystemFlags {
12931293
/// Don't try to type check closure bodies, and leave them unchecked. This is
12941294
/// used for source tooling functionalities.
12951295
LeaveClosureBodyUnchecked = 0x20,
1296+
1297+
/// If set, we are solving specifically to determine the type of a
1298+
/// CodeCompletionExpr, and should continue in the presence of errors wherever
1299+
/// possible.
1300+
ForCodeCompletion = 0x40,
12961301
};
12971302

12981303
/// Options that affect the constraint system as a whole.
@@ -2834,6 +2839,11 @@ class ConstraintSystem {
28342839
return known->second;
28352840
}
28362841

2842+
/// Retrieve type type of the given declaration to be used in
2843+
/// constraint system, this is better than calling `getType()`
2844+
/// directly because it accounts of constraint system flags.
2845+
Type getVarType(const VarDecl *var);
2846+
28372847
/// Cache the type of the expression argument and return that same
28382848
/// argument.
28392849
template <typename T>
@@ -3057,6 +3067,12 @@ class ConstraintSystem {
30573067
return Options.contains(ConstraintSystemFlags::ReusePrecheckedType);
30583068
}
30593069

3070+
/// Whether we are solving to determine the possible types of a
3071+
/// \c CodeCompletionExpr.
3072+
bool isForCodeCompletion() const {
3073+
return Options.contains(ConstraintSystemFlags::ForCodeCompletion);
3074+
}
3075+
30603076
/// Log and record the application of the fix. Return true iff any
30613077
/// subsequent solution would be worse than the best known solution.
30623078
bool recordFix(ConstraintFix *fix, unsigned impact = 1);

lib/Sema/TypeCheckCodeCompletion.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1012,7 +1012,7 @@ sawSolution(const constraints::Solution &S) {
10121012
return S.simplifyType(completionTy.transform([&](Type type) {
10131013
if (auto *hole = type->getAs<HoleType>()) {
10141014
if (auto *typeVar =
1015-
hole->getOriginatorType().dyn_cast<TypeVariableType *>()) {
1015+
hole->getOriginator().dyn_cast<TypeVariableType *>()) {
10161016
if (auto *GP = typeVar->getImpl().getGenericParameter()) {
10171017
// Code completion depends on generic parameter type being
10181018
// represented in terms of `ArchetypeType` since it's easy

0 commit comments

Comments
 (0)