mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[CS] Replace UnresolvedType with ErrorType in simplifyType/resolveType
This means we now either produce a bare ErrorType, or an ErrorType with a generic parameter original type for a generic parameter hole. We ought to further consolidate this logic by sinking the generic parameter original type replacement into `simplifyType` itself, but I'm leaving that for a future patch since it affects completion results and I want to try keep this close to NFC.
This commit is contained in:
@@ -983,11 +983,10 @@ static void formatDiagnosticArgument(StringRef Modifier,
|
||||
needsQualification = typeSpellingIsAmbiguous(type, Args, printOptions);
|
||||
}
|
||||
|
||||
// If a type has an unresolved type, print it with syntax sugar removed for
|
||||
// If a type has a bare error type, print it with syntax sugar removed for
|
||||
// clarity. For example, print `Array<_>` instead of `[_]`.
|
||||
if (type->hasUnresolvedType()) {
|
||||
if (type->hasBareError())
|
||||
type = type->getWithoutSyntaxSugar();
|
||||
}
|
||||
|
||||
if (needsQualification &&
|
||||
isa<OpaqueTypeArchetypeType>(type.getPointer()) &&
|
||||
|
||||
@@ -201,7 +201,7 @@ void ArgumentTypeCheckCompletionCallback::sawSolutionImpl(const Solution &S) {
|
||||
}
|
||||
}
|
||||
if (ExpectedCallType &&
|
||||
(ExpectedCallType->hasUnresolvedType() ||
|
||||
(ExpectedCallType->hasError() ||
|
||||
ExpectedCallType->hasUnboundGenericType())) {
|
||||
ExpectedCallType = Type();
|
||||
}
|
||||
|
||||
@@ -693,7 +693,7 @@ Type CompletionLookup::getTypeOfMember(const ValueDecl *VD, Type ExprType) {
|
||||
|
||||
// For a GenericFunctionType, we only want to substitute the
|
||||
// param/result types, as otherwise we might end up with a bad generic
|
||||
// signature if there are UnresolvedTypes present in the base type. Note
|
||||
// signature if there are ErrorTypes present in the base type. Note
|
||||
// we pass in DesugarMemberTypes so that we see the actual concrete type
|
||||
// witnesses instead of type alias types.
|
||||
if (auto *GFT = T->getAs<GenericFunctionType>()) {
|
||||
|
||||
@@ -123,7 +123,7 @@ void ConformingMethodListCallbacks::readyForTypeChecking(SourceFile *SrcFile) {
|
||||
Type T = Res.Ty;
|
||||
WithSolutionSpecificVarTypesRAII VarType(Res.SolutionSpecificVarTypes);
|
||||
|
||||
if (!T || T->is<ErrorType>() || T->is<UnresolvedType>())
|
||||
if (!T || T->is<ErrorType>())
|
||||
return;
|
||||
|
||||
T = T->getRValueType();
|
||||
|
||||
@@ -420,7 +420,7 @@ void PostfixCompletionCallback::collectResults(
|
||||
// tuple. But that doesn’t really make sense so we shouldn't be suggesting
|
||||
// any operators based on `Void`.
|
||||
if (IncludeOperators && !Result.BaseIsStaticMetaType &&
|
||||
!Result.BaseTy->isVoid() &&
|
||||
!Result.BaseTy->isVoid() && !Result.BaseTy->hasError() &&
|
||||
!ProcessedBaseTypes.contains(Result.BaseTy)) {
|
||||
addOperatorResults(Result.BaseTy, Operators, DC, Lookup);
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ swift::ide::getSelectedOverloadInfo(const Solution &S,
|
||||
OverloadChoiceKind::KeyPathApplication) {
|
||||
auto Params = Result.ValueTy->getAs<AnyFunctionType>()->getParams();
|
||||
if (Params.size() == 1 &&
|
||||
Params[0].getPlainType()->is<UnresolvedType>()) {
|
||||
Params[0].getPlainType()->is<ErrorType>()) {
|
||||
auto *KPDecl = CS.getASTContext().getKeyPathDecl();
|
||||
Type KPTy =
|
||||
KPDecl->mapTypeIntoContext(KPDecl->getDeclaredInterfaceType());
|
||||
|
||||
@@ -27,7 +27,7 @@ Type swift::ide::getTypeForCompletion(const constraints::Solution &S,
|
||||
// Use the contextual type, unless it is still unresolved, in which case fall
|
||||
// back to getting the type from the expression.
|
||||
if (auto ContextualType = S.getContextualType(Node)) {
|
||||
if (!ContextualType->hasUnresolvedType() &&
|
||||
if (!ContextualType->hasError() &&
|
||||
!ContextualType->hasUnboundGenericType()) {
|
||||
return ContextualType;
|
||||
}
|
||||
@@ -46,7 +46,7 @@ Type swift::ide::getTypeForCompletion(const constraints::Solution &S,
|
||||
Result = S.getResolvedType(Node);
|
||||
}
|
||||
|
||||
if (Result && Result->is<UnresolvedType>()) {
|
||||
if (Result && Result->is<ErrorType>()) {
|
||||
Result = Type();
|
||||
}
|
||||
return Result;
|
||||
|
||||
@@ -129,7 +129,7 @@ void ContextInfoCallbacks::readyForTypeChecking(SourceFile *SrcFile) {
|
||||
SmallVector<TypeContextInfoItem, 2> results;
|
||||
|
||||
for (auto T : TypeCheckCallback.getTypes()) {
|
||||
if (T->is<ErrorType>() || T->is<UnresolvedType>())
|
||||
if (T->is<ErrorType>())
|
||||
continue;
|
||||
|
||||
T = T->getRValueType();
|
||||
|
||||
@@ -105,15 +105,16 @@ Solution::computeSubstitutions(NullablePtr<ValueDecl> decl,
|
||||
if (openedTypes == OpenedTypes.end())
|
||||
return SubstitutionMap();
|
||||
|
||||
auto &ctx = getConstraintSystem().getASTContext();
|
||||
|
||||
SmallVector<Type, 4> replacementTypes;
|
||||
for (const auto &opened : openedTypes->second) {
|
||||
auto type = getFixedType(opened.second);
|
||||
if (opened.first->isParameterPack()) {
|
||||
if (type->is<PlaceholderType>()) {
|
||||
auto &ctx = type->getASTContext();
|
||||
type =
|
||||
PackType::get(ctx, {PackExpansionType::get(ctx.TheUnresolvedType,
|
||||
ctx.TheUnresolvedType)});
|
||||
type = PackType::get(
|
||||
ctx,
|
||||
{PackExpansionType::get(ErrorType::get(ctx), ErrorType::get(ctx))});
|
||||
} else if (!type->is<PackType>())
|
||||
type = PackType::getSingletonPackExpansion(type);
|
||||
}
|
||||
@@ -126,8 +127,11 @@ Solution::computeSubstitutions(NullablePtr<ValueDecl> decl,
|
||||
auto replacement = original.subst(IFS);
|
||||
assert(!replacement->is<GenericTypeParamType>());
|
||||
|
||||
if (replacement->hasError() ||
|
||||
isOpenedAnyObject(replacement) ||
|
||||
if (replacement->hasError()) {
|
||||
return ProtocolConformanceRef::forAbstract(ErrorType::get(replacement),
|
||||
protoType);
|
||||
}
|
||||
if (isOpenedAnyObject(replacement) ||
|
||||
replacement->is<GenericTypeParamType>()) {
|
||||
return ProtocolConformanceRef::forAbstract(replacement, protoType);
|
||||
}
|
||||
@@ -7218,7 +7222,7 @@ Expr *ConstraintSystem::addImplicitLoadExpr(Expr *expr) {
|
||||
|
||||
Expr *ExprRewriter::coerceToType(Expr *expr, Type toType,
|
||||
ConstraintLocatorBuilder locator) {
|
||||
ASSERT(toType && !toType->hasError() && !toType->hasUnresolvedType() &&
|
||||
ASSERT(toType && !toType->hasError() &&
|
||||
!toType->hasTypeVariableOrPlaceholder());
|
||||
|
||||
// Diagnose conversions to invalid function types that couldn't be performed
|
||||
@@ -10032,8 +10036,7 @@ ConstraintSystem::applySolution(Solution &solution,
|
||||
// unresolved types.
|
||||
{
|
||||
auto isValidType = [&](Type ty) {
|
||||
return !ty->hasUnresolvedType() && !ty->hasError() &&
|
||||
!ty->hasTypeVariableOrPlaceholder();
|
||||
return !ty->hasError() && !ty->hasTypeVariableOrPlaceholder();
|
||||
};
|
||||
for (auto &[_, type] : solution.typeBindings) {
|
||||
ASSERT(isValidType(type) && "type binding has invalid type");
|
||||
|
||||
@@ -100,7 +100,7 @@ Type FailureDiagnostic::resolveType(Type rawType, bool reconstituteSugar,
|
||||
if (auto *typeVar = type->getAs<TypeVariableType>()) {
|
||||
auto resolvedType = S.simplifyType(typeVar);
|
||||
|
||||
if (!resolvedType->hasUnresolvedType())
|
||||
if (!resolvedType->hasError())
|
||||
return resolvedType;
|
||||
|
||||
// If type variable was simplified to an unresolved pack expansion
|
||||
@@ -117,7 +117,7 @@ Type FailureDiagnostic::resolveType(Type rawType, bool reconstituteSugar,
|
||||
}
|
||||
|
||||
Type GP = typeVar->getImpl().getGenericParameter();
|
||||
return resolvedType->is<UnresolvedType>() && GP
|
||||
return resolvedType->is<ErrorType>() && GP
|
||||
? ErrorType::get(GP)
|
||||
: resolvedType;
|
||||
}
|
||||
@@ -128,7 +128,7 @@ Type FailureDiagnostic::resolveType(Type rawType, bool reconstituteSugar,
|
||||
}
|
||||
|
||||
if (type->isPlaceholder())
|
||||
return Type(type->getASTContext().TheUnresolvedType);
|
||||
return ErrorType::get(type->getASTContext());
|
||||
|
||||
return std::nullopt;
|
||||
});
|
||||
@@ -183,7 +183,7 @@ StringRef FailureDiagnostic::getEditorPlaceholder(
|
||||
llvm::SmallVectorImpl<char> &scratch) const {
|
||||
llvm::raw_svector_ostream OS(scratch);
|
||||
OS << "<#";
|
||||
if (!ty || ty->is<UnresolvedType>()) {
|
||||
if (!ty || ty->isBareErrorType()) {
|
||||
OS << description;
|
||||
} else {
|
||||
OS << "T##";
|
||||
@@ -5681,7 +5681,7 @@ bool MissingArgumentsFailure::diagnoseMissingResultBuilderElement() const {
|
||||
auto fixIt = getEditorPlaceholder("result", paramType, scratch);
|
||||
auto fixItLoc = call->getStartLoc();
|
||||
|
||||
if (paramType->is<UnresolvedType>()) {
|
||||
if (paramType->isBareErrorType()) {
|
||||
emitDiagnostic(diag::result_builder_missing_element,
|
||||
resultBuilder->getName())
|
||||
.fixItInsertAfter(fixItLoc, fixIt);
|
||||
@@ -5804,7 +5804,7 @@ bool MissingArgumentsFailure::isMisplacedMissingArgument(
|
||||
auto argType = solution.simplifyType(solution.getType(unaryArg));
|
||||
auto paramType = fnType->getParams()[1].getPlainType();
|
||||
|
||||
if (isExpr<ClosureExpr>(unaryArg) && argType->is<UnresolvedType>()) {
|
||||
if (isExpr<ClosureExpr>(unaryArg) && argType->is<ErrorType>()) {
|
||||
auto unwrappedParamTy = paramType->lookThroughAllOptionalTypes();
|
||||
if (unwrappedParamTy->is<FunctionType>() || unwrappedParamTy->isAny())
|
||||
return true;
|
||||
@@ -5958,7 +5958,7 @@ bool ClosureParamDestructuringFailure::diagnoseAsError() {
|
||||
};
|
||||
|
||||
auto isValidType = [](Type resultType) -> bool {
|
||||
return resultType && !resultType->hasUnresolvedType() &&
|
||||
return resultType && !resultType->hasError() &&
|
||||
!resultType->hasTypeVariable();
|
||||
};
|
||||
|
||||
@@ -6619,7 +6619,7 @@ bool CollectionElementContextualFailure::diagnoseAsError() {
|
||||
// statement it has to be diagnosed as pattern match if there are
|
||||
// holes present in the contextual type.
|
||||
if (purpose == ContextualTypePurpose::CTP_ForEachSequence &&
|
||||
contextualType->hasUnresolvedType()) {
|
||||
contextualType->hasError()) {
|
||||
auto diagnostic = emitDiagnostic(
|
||||
(contextualType->is<TupleType>() && !eltType->is<TupleType>())
|
||||
? diag::cannot_match_expr_tuple_pattern_with_nontuple_value
|
||||
@@ -7490,7 +7490,7 @@ bool ArgumentMismatchFailure::diagnoseAsError() {
|
||||
if (argType->isKeyPath() && !paramType->isKnownKeyPathType()) {
|
||||
auto keyPathTy = argType->castTo<BoundGenericType>();
|
||||
auto rootTy = keyPathTy->getGenericArgs()[0];
|
||||
if (rootTy->is<UnresolvedType>()) {
|
||||
if (rootTy->isBareErrorType()) {
|
||||
emitDiagnostic(diag::cannot_convert_unresolved_key_path_argument_value,
|
||||
paramType);
|
||||
return true;
|
||||
@@ -7627,7 +7627,7 @@ bool ArgumentMismatchFailure::diagnosePatternMatchingMismatch() const {
|
||||
auto rhsType = getType(rhsExpr);
|
||||
|
||||
auto diagnostic =
|
||||
lhsType->is<UnresolvedType>()
|
||||
lhsType->isBareErrorType()
|
||||
? emitDiagnostic(
|
||||
diag::cannot_match_unresolved_expr_pattern_with_value, rhsType)
|
||||
: emitDiagnostic(diag::cannot_match_expr_pattern_with_value, lhsType,
|
||||
@@ -8286,7 +8286,7 @@ bool UnableToInferClosureParameterType::diagnoseAsError() {
|
||||
if (parentExpr) {
|
||||
// Missing or invalid member reference in call.
|
||||
if (auto *AE = dyn_cast<ApplyExpr>(parentExpr)) {
|
||||
if (getType(AE->getFn())->is<UnresolvedType>())
|
||||
if (getType(AE->getFn())->is<ErrorType>())
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -1886,7 +1886,7 @@ Type Solution::simplifyType(Type type, bool wantInterfaceType) const {
|
||||
ASSERT(!(wantInterfaceType && resolvedType->hasPrimaryArchetype()));
|
||||
|
||||
// We may have type variables and placeholders left over. These are solver
|
||||
// allocated so cannot escape this function. Turn them into UnresolvedType.
|
||||
// allocated so cannot escape this function. Turn them into ErrorType.
|
||||
// - Type variables may still be present from unresolved pack expansions where
|
||||
// e.g the count type is a hole, so the pattern may never become a
|
||||
// concrete type.
|
||||
@@ -1900,7 +1900,7 @@ Type Solution::simplifyType(Type type, bool wantInterfaceType) const {
|
||||
|
||||
auto *typePtr = type.getPointer();
|
||||
if (isa<TypeVariableType>(typePtr) || isa<PlaceholderType>(typePtr))
|
||||
return Type(ctx.TheUnresolvedType);
|
||||
return ErrorType::get(ctx);
|
||||
|
||||
return std::nullopt;
|
||||
});
|
||||
@@ -4298,7 +4298,7 @@ Solution::getFunctionArgApplyInfo(ConstraintLocator *locator) const {
|
||||
// If callee couldn't be resolved due to expression
|
||||
// issues e.g. it's a reference to an invalid member
|
||||
// let's just return here.
|
||||
if (simplifyType(rawFnType)->is<UnresolvedType>())
|
||||
if (simplifyType(rawFnType)->is<ErrorType>())
|
||||
return std::nullopt;
|
||||
|
||||
// A tuple construction is spelled in the AST as a function call, but
|
||||
|
||||
Reference in New Issue
Block a user