Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions include/swift/AST/Types.h
Original file line number Diff line number Diff line change
Expand Up @@ -5736,19 +5736,19 @@ DEFINE_EMPTY_CAN_TYPE_WRAPPER(TypeVariableType, Type)
/// because the expression is ambiguous. This type is only used by the
/// constraint solver and transformed into UnresolvedType to be used in AST.
class HoleType : public TypeBase {
using OriginatorType =
llvm::PointerUnion<TypeVariableType *, DependentMemberType *>;
using Originator = llvm::PointerUnion<TypeVariableType *,
DependentMemberType *, VarDecl *>;

OriginatorType Originator;
Originator O;

HoleType(ASTContext &C, OriginatorType originator,
HoleType(ASTContext &C, Originator originator,
RecursiveTypeProperties properties)
: TypeBase(TypeKind::Hole, &C, properties), Originator(originator) {}
: TypeBase(TypeKind::Hole, &C, properties), O(originator) {}

public:
static Type get(ASTContext &ctx, OriginatorType originatorType);
static Type get(ASTContext &ctx, Originator originator);

OriginatorType getOriginatorType() const { return Originator; }
Originator getOriginator() const { return O; }

static bool classof(const TypeBase *T) {
return T->getKind() == TypeKind::Hole;
Expand Down
8 changes: 2 additions & 6 deletions lib/AST/ASTContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2400,13 +2400,9 @@ Type ErrorType::get(Type originalType) {
return entry = new (mem) ErrorType(ctx, originalType, properties);
}

Type HoleType::get(ASTContext &ctx, OriginatorType originator) {
Type HoleType::get(ASTContext &ctx, Originator originator) {
assert(originator);
auto properties = reinterpret_cast<TypeBase *>(originator.getOpaqueValue())
->getRecursiveProperties();
properties |= RecursiveTypeProperties::HasTypeHole;

auto arena = getArena(properties);
auto arena = getArena(RecursiveTypeProperties::HasTypeHole);
return new (ctx, arena)
HoleType(ctx, originator, RecursiveTypeProperties::HasTypeHole);
}
Expand Down
8 changes: 5 additions & 3 deletions lib/AST/ASTDumper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3512,12 +3512,14 @@ namespace {

void visitHoleType(HoleType *T, StringRef label) {
printCommon(label, "hole_type");
auto originatorTy = T->getOriginatorType();
if (auto *typeVar = originatorTy.dyn_cast<TypeVariableType *>()) {
auto originator = T->getOriginator();
if (auto *typeVar = originator.dyn_cast<TypeVariableType *>()) {
printRec("type_variable", typeVar);
} else if (auto *VD = originator.dyn_cast<VarDecl *>()) {
VD->dumpRef(PrintWithColorRAII(OS, DeclColor).getOS());
} else {
printRec("dependent_member_type",
originatorTy.get<DependentMemberType *>());
originator.get<DependentMemberType *>());
}
PrintWithColorRAII(OS, ParenthesisColor) << ')';
}
Expand Down
11 changes: 9 additions & 2 deletions lib/AST/ASTPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3822,8 +3822,15 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
void visitHoleType(HoleType *T) {
if (Options.PrintTypesForDebugging) {
Printer << "<<hole for ";
auto originatorTy = T->getOriginatorType();
visit(Type(reinterpret_cast<TypeBase *>(originatorTy.getOpaqueValue())));
auto originator = T->getOriginator();
if (auto *typeVar = originator.dyn_cast<TypeVariableType *>()) {
visit(typeVar);
} else if (auto *VD = originator.dyn_cast<VarDecl *>()) {
Printer << "decl = ";
Printer << VD->getName();
} else {
visit(originator.get<DependentMemberType *>());
}
Printer << ">>";
} else {
Printer << "<<hole>>";
Expand Down
13 changes: 7 additions & 6 deletions lib/Sema/CSGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1241,19 +1241,20 @@ namespace {
if (auto *VD = dyn_cast<VarDecl>(E->getDecl())) {
knownType = CS.getTypeIfAvailable(VD);
if (!knownType)
knownType = VD->getType();
knownType = CS.getVarType(VD);

if (knownType) {
assert(!knownType->isHole());
// If the known type has an error, bail out.
if (knownType->hasError()) {
if (!CS.hasType(E))
CS.setType(E, knownType);
return nullptr;
}

// Set the favored type for this expression to the known type.
CS.setFavoredType(E, knownType.getPointer());
if (!knownType->hasHole()) {
// Set the favored type for this expression to the known type.
CS.setFavoredType(E, knownType.getPointer());
}
}

// This can only happen when failure diagnostics is trying
Expand Down Expand Up @@ -2016,7 +2017,7 @@ namespace {

Type externalType;
if (param->getTypeRepr()) {
auto declaredTy = param->getType();
auto declaredTy = CS.getVarType(param);
externalType = CS.openUnboundGenericTypes(declaredTy, paramLoc);
} else {
// Let's allow parameters which haven't been explicitly typed
Expand Down Expand Up @@ -3884,7 +3885,7 @@ bool ConstraintSystem::generateConstraints(
getConstraintLocator(typeRepr));
setType(typeRepr, backingType);

auto propertyType = wrappedVar->getType();
auto propertyType = getVarType(wrappedVar);
if (propertyType->hasError())
return true;

Expand Down
2 changes: 1 addition & 1 deletion lib/Sema/CSSimplify.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7016,7 +7016,7 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyMemberConstraint(
// type but a hole.
auto shouldRecordFixForHole = [&](HoleType *baseType) {
auto *originator =
baseType->getOriginatorType().dyn_cast<TypeVariableType *>();
baseType->getOriginator().dyn_cast<TypeVariableType *>();

if (!originator)
return false;
Expand Down
18 changes: 18 additions & 0 deletions lib/Sema/ConstraintSystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5213,3 +5213,21 @@ void ConstraintSystem::recordFixedRequirement(ConstraintLocator *reqLocator,
std::make_tuple(GP, reqKind, requirementTy.getPointer()));
}
}

// Replace any error types encountered with holes.
Type ConstraintSystem::getVarType(const VarDecl *var) {
auto type = var->getType();

// If this declaration is used as part of a code completion
// expression, solver needs to glance over the fact that
// it might be invalid to avoid failing constraint generation
// and produce completion results.
if (!isForCodeCompletion())
return type;

return type.transform([&](Type type) {
if (!type->is<ErrorType>())
return type;
return HoleType::get(Context, const_cast<VarDecl *>(var));
});
}
16 changes: 16 additions & 0 deletions lib/Sema/ConstraintSystem.h
Original file line number Diff line number Diff line change
Expand Up @@ -1293,6 +1293,11 @@ enum class ConstraintSystemFlags {
/// Don't try to type check closure bodies, and leave them unchecked. This is
/// used for source tooling functionalities.
LeaveClosureBodyUnchecked = 0x20,

/// If set, we are solving specifically to determine the type of a
/// CodeCompletionExpr, and should continue in the presence of errors wherever
/// possible.
ForCodeCompletion = 0x40,
};

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

/// Retrieve type type of the given declaration to be used in
/// constraint system, this is better than calling `getType()`
/// directly because it accounts of constraint system flags.
Type getVarType(const VarDecl *var);

/// Cache the type of the expression argument and return that same
/// argument.
template <typename T>
Expand Down Expand Up @@ -3057,6 +3067,12 @@ class ConstraintSystem {
return Options.contains(ConstraintSystemFlags::ReusePrecheckedType);
}

/// Whether we are solving to determine the possible types of a
/// \c CodeCompletionExpr.
bool isForCodeCompletion() const {
return Options.contains(ConstraintSystemFlags::ForCodeCompletion);
}

/// Log and record the application of the fix. Return true iff any
/// subsequent solution would be worse than the best known solution.
bool recordFix(ConstraintFix *fix, unsigned impact = 1);
Expand Down
2 changes: 1 addition & 1 deletion lib/Sema/TypeCheckCodeCompletion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1012,7 +1012,7 @@ sawSolution(const constraints::Solution &S) {
return S.simplifyType(completionTy.transform([&](Type type) {
if (auto *hole = type->getAs<HoleType>()) {
if (auto *typeVar =
hole->getOriginatorType().dyn_cast<TypeVariableType *>()) {
hole->getOriginator().dyn_cast<TypeVariableType *>()) {
if (auto *GP = typeVar->getImpl().getGenericParameter()) {
// Code completion depends on generic parameter type being
// represented in terms of `ArchetypeType` since it's easy
Expand Down