diff --git a/lib/Sema/CSApply.cpp b/lib/Sema/CSApply.cpp index b7d81bf2caa5d..766c57bc496f1 100644 --- a/lib/Sema/CSApply.cpp +++ b/lib/Sema/CSApply.cpp @@ -2488,7 +2488,7 @@ namespace { // Make the integer literals for the parameters. auto buildExprFromUnsigned = [&](unsigned value) { LiteralExpr *expr = IntegerLiteralExpr::createFromUnsigned(ctx, value); - cs.setType(expr, TypeChecker::getIntType(ctx)); + cs.setType(expr, ctx.getIntDecl()->getDeclaredInterfaceType()); return handleIntegerLiteralExpr(expr); }; @@ -4698,7 +4698,9 @@ namespace { StringRef(stringCopy, compatStringBuf.size()), SourceRange(), /*implicit*/ true); - cs.setType(stringExpr, TypeChecker::getStringType(cs.getASTContext())); + cs.setType( + stringExpr, + cs.getASTContext().getStringDecl()->getDeclaredInterfaceType()); E->setObjCStringLiteralExpr(stringExpr); } } diff --git a/lib/Sema/CSDiagnostics.cpp b/lib/Sema/CSDiagnostics.cpp index f83ffed73fc32..1e455b9a25dc6 100644 --- a/lib/Sema/CSDiagnostics.cpp +++ b/lib/Sema/CSDiagnostics.cpp @@ -2570,11 +2570,8 @@ bool ContextualFailure::trySequenceSubsequenceFixIts( if (!getASTContext().getStdlibModule()) return false; - auto String = TypeChecker::getStringType(getASTContext()); - auto Substring = TypeChecker::getSubstringType(getASTContext()); - - if (!String || !Substring) - return false; + auto String = getASTContext().getStringDecl()->getDeclaredInterfaceType(); + auto Substring = getASTContext().getSubstringDecl()->getDeclaredInterfaceType(); // Substring -> String conversion // Wrap in String.init diff --git a/lib/Sema/CSGen.cpp b/lib/Sema/CSGen.cpp index 15b1d5ee7a85a..356833955c0df 100644 --- a/lib/Sema/CSGen.cpp +++ b/lib/Sema/CSGen.cpp @@ -1499,7 +1499,7 @@ namespace { options |= TypeResolutionFlags::AllowUnboundGenerics; auto result = TypeResolution::forContextual(CS.DC, options) .resolveType(repr); - if (!result || result->hasError()) { + if (result->hasError()) { return Type(); } return result; @@ -2404,6 +2404,7 @@ namespace { } varType = TypeChecker::getOptionalType(var->getLoc(), varType); + assert(!varType->hasError()); if (oneWayVarType) { oneWayVarType = @@ -2770,7 +2771,7 @@ namespace { Type castType = TypeResolution::forContextual( CS.DC, TypeResolverContext::InExpression) .resolveType(isp->getCastTypeRepr()); - if (!castType) { + if (castType->hasError()) { return false; } @@ -2938,7 +2939,7 @@ namespace { // Try to build the appropriate type for a variadic argument list of // the fresh element type. If that failed, just bail out. auto array = TypeChecker::getArraySliceType(expr->getLoc(), element); - if (!array) return element; + if (array->hasError()) return element; // Require the operand to be convertible to the array type. CS.addConstraint(ConstraintKind::Conversion, @@ -3304,7 +3305,7 @@ namespace { /// worth QoI efforts. Type getOptionalType(SourceLoc optLoc, Type valueTy) { auto optTy = TypeChecker::getOptionalType(optLoc, valueTy); - if (!optTy || + if (optTy->hasError() || TypeChecker::requireOptionalIntrinsics(CS.getASTContext(), optLoc)) return Type(); diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp index 37e2639ccf9a3..50e3b0ef2ed21 100644 --- a/lib/Sema/CSSimplify.cpp +++ b/lib/Sema/CSSimplify.cpp @@ -2426,9 +2426,9 @@ ConstraintSystem::matchExistentialTypes(Type type1, Type type2, static bool isStringCompatiblePointerBaseType(ASTContext &ctx, Type baseType) { // Allow strings to be passed to pointer-to-byte or pointer-to-void types. - if (baseType->isEqual(TypeChecker::getInt8Type(ctx))) + if (baseType->isEqual(ctx.getInt8Decl()->getDeclaredInterfaceType())) return true; - if (baseType->isEqual(TypeChecker::getUInt8Type(ctx))) + if (baseType->isEqual(ctx.getUInt8Decl()->getDeclaredInterfaceType())) return true; if (baseType->isEqual(ctx.TheEmptyTupleType)) return true; @@ -4926,7 +4926,8 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind, // The pointer can be converted from a string, if the element // type is compatible. auto &ctx = getASTContext(); - if (type1->isEqual(TypeChecker::getStringType(ctx))) { + if (type1->isEqual( + ctx.getStringDecl()->getDeclaredInterfaceType())) { auto baseTy = getFixedTypeRecursive(pointeeTy, false); if (baseTy->isTypeVariableOrMember() || @@ -6889,6 +6890,7 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyMemberConstraint( TVO_CanBindToLValue | TVO_CanBindToNoEscape); Type optTy = TypeChecker::getOptionalType(SourceLoc(), innerTV); + assert(!optTy->hasError()); SmallVector optionalities; auto nonoptionalResult = Constraint::createFixed( *this, ConstraintKind::Bind, @@ -9212,11 +9214,11 @@ ConstraintSystem::simplifyRestrictedConstraintImpl( auto &ctx = getASTContext(); auto int8Con = Constraint::create(*this, ConstraintKind::Bind, baseType2, - TypeChecker::getInt8Type(ctx), + ctx.getInt8Decl()->getDeclaredInterfaceType(), getConstraintLocator(locator)); auto uint8Con = Constraint::create(*this, ConstraintKind::Bind, baseType2, - TypeChecker::getUInt8Type(ctx), + ctx.getUInt8Decl()->getDeclaredInterfaceType(), getConstraintLocator(locator)); auto voidCon = Constraint::create(*this, ConstraintKind::Bind, baseType2, ctx.TheEmptyTupleType, diff --git a/lib/Sema/TypeCheckAttr.cpp b/lib/Sema/TypeCheckAttr.cpp index 505232f6748ad..77bdb991f794d 100644 --- a/lib/Sema/TypeCheckAttr.cpp +++ b/lib/Sema/TypeCheckAttr.cpp @@ -2853,7 +2853,7 @@ void AttributeChecker::visitImplementsAttr(ImplementsAttr *attr) { } // Definite error-types were already diagnosed in resolveType. - if (!T || T->hasError()) + if (T->hasError()) return; attr->setProtocolType(T); diff --git a/lib/Sema/TypeCheckConstraints.cpp b/lib/Sema/TypeCheckConstraints.cpp index 7435775298de8..3aec9a838eacb 100644 --- a/lib/Sema/TypeCheckConstraints.cpp +++ b/lib/Sema/TypeCheckConstraints.cpp @@ -1397,7 +1397,7 @@ TypeExpr *PreCheckExpression::simplifyNestedTypeExpr(UnresolvedDotExpr *UDE) { auto resolution = TypeResolution::forContextual(DC, options); auto BaseTy = resolution.resolveType(InnerTypeRepr); - if (BaseTy && BaseTy->mayHaveMembers()) { + if (BaseTy->mayHaveMembers()) { auto lookupOptions = defaultMemberLookupOptions; if (isa(DC) || isa(DC)) diff --git a/lib/Sema/TypeCheckDecl.cpp b/lib/Sema/TypeCheckDecl.cpp index 6a5f8c7ac3b56..333583258b1b6 100644 --- a/lib/Sema/TypeCheckDecl.cpp +++ b/lib/Sema/TypeCheckDecl.cpp @@ -2101,7 +2101,7 @@ static Type validateParameterType(ParamDecl *decl) { if (decl->isVariadic()) { Ty = TypeChecker::getArraySliceType(decl->getStartLoc(), Ty); - if (Ty.isNull()) { + if (Ty->hasError()) { decl->setInvalid(); return ErrorType::get(ctx); } diff --git a/lib/Sema/TypeCheckPattern.cpp b/lib/Sema/TypeCheckPattern.cpp index 3cee1b6d1ce01..f24f3df0c0c0e 100644 --- a/lib/Sema/TypeCheckPattern.cpp +++ b/lib/Sema/TypeCheckPattern.cpp @@ -705,7 +705,7 @@ static Type validateTypedPattern(TypedPattern *TP, TypeResolution resolution) { } auto ty = resolution.resolveType(Repr); - if (!ty || ty->hasError()) { + if (ty->hasError()) { return ErrorType::get(Context); } @@ -1233,7 +1233,7 @@ Pattern *TypeChecker::coercePatternToType(ContextualPattern pattern, TypeResolutionOptions paramOptions(TypeResolverContext::InExpression); auto castType = TypeResolution::forContextual(dc, paramOptions) .resolveType(IP->getCastTypeRepr()); - if (!castType || castType->hasError()) + if (castType->hasError()) return nullptr; IP->setCastType(castType); diff --git a/lib/Sema/TypeCheckType.cpp b/lib/Sema/TypeCheckType.cpp index 3f368011f8aa1..ca1c584062354 100644 --- a/lib/Sema/TypeCheckType.cpp +++ b/lib/Sema/TypeCheckType.cpp @@ -120,7 +120,7 @@ GenericSignature TypeResolution::getGenericSignature() const { return dc->getGenericSignatureOfContext(); case TypeResolutionStage::Structural: - return nullptr; + return GenericSignature(); } llvm_unreachable("unhandled stage"); } @@ -364,68 +364,22 @@ Type TypeChecker::getArraySliceType(SourceLoc loc, Type elementType) { ASTContext &ctx = elementType->getASTContext(); if (!ctx.getArrayDecl()) { ctx.Diags.diagnose(loc, diag::sugar_type_not_found, 0); - return Type(); + return ErrorType::get(ctx); } return ArraySliceType::get(elementType); } -Type TypeChecker::getDictionaryType(SourceLoc loc, Type keyType, - Type valueType) { - ASTContext &ctx = keyType->getASTContext(); - if (!ctx.getDictionaryDecl()) { - ctx.Diags.diagnose(loc, diag::sugar_type_not_found, 3); - return Type(); - } - - return DictionaryType::get(keyType, valueType); -} - Type TypeChecker::getOptionalType(SourceLoc loc, Type elementType) { ASTContext &ctx = elementType->getASTContext(); if (!ctx.getOptionalDecl()) { ctx.Diags.diagnose(loc, diag::sugar_type_not_found, 1); - return Type(); + return ErrorType::get(ctx); } return OptionalType::get(elementType); } -Type TypeChecker::getStringType(ASTContext &Context) { - if (auto typeDecl = Context.getStringDecl()) - return typeDecl->getDeclaredInterfaceType(); - - return Type(); -} - -Type TypeChecker::getSubstringType(ASTContext &Context) { - if (auto typeDecl = Context.getSubstringDecl()) - return typeDecl->getDeclaredInterfaceType(); - - return Type(); -} - -Type TypeChecker::getIntType(ASTContext &Context) { - if (auto typeDecl = Context.getIntDecl()) - return typeDecl->getDeclaredInterfaceType(); - - return Type(); -} - -Type TypeChecker::getInt8Type(ASTContext &Context) { - if (auto typeDecl = Context.getInt8Decl()) - return typeDecl->getDeclaredInterfaceType(); - - return Type(); -} - -Type TypeChecker::getUInt8Type(ASTContext &Context) { - if (auto typeDecl = Context.getUInt8Decl()) - return typeDecl->getDeclaredInterfaceType(); - - return Type(); -} - Type TypeChecker::getDynamicBridgedThroughObjCClass(DeclContext *dc, Type dynamicType, @@ -792,8 +746,9 @@ static Type applyGenericArguments(Type type, TypeResolution resolution, if (nominal->isOptionalDecl()) { // Validate the generic argument. Type objectType = resolution.resolveType(genericArgs[0]); - if (!objectType || objectType->hasError()) - return nullptr; + if (objectType->hasError()) { + return ErrorType::get(ctx); + } return BoundGenericType::get(nominal, /*parent*/ Type(), objectType); } @@ -1692,6 +1647,34 @@ namespace { const auto DefaultParameterConvention = ParameterConvention::Direct_Unowned; const auto DefaultResultConvention = ResultConvention::Unowned; + /// A wrapper that ensures that the returned type from + /// \c TypeResolver::resolveType is never the null \c Type. It otherwise + /// tries to behave like \c Type, so it provides the proper conversion and + /// arrow operators. + class NeverNullType final { + public: + /// Forbid default construction. + NeverNullType() = delete; + /// Forbid construction from \c nullptr. + NeverNullType(std::nullptr_t) = delete; + + public: + /// Construct a never-null Type. If \p Ty is null, a fatal error is thrown. + NeverNullType(Type Ty) : WrappedTy(Ty) { + if (Ty.isNull()) { + llvm::report_fatal_error("Resolved to null type!"); + } + } + + operator Type() const { return WrappedTy; } + Type get() const { return WrappedTy; } + + TypeBase *operator->() const { return WrappedTy.operator->(); } + + private: + Type WrappedTy; + }; + class TypeResolver { ASTContext &Context; TypeResolution resolution; @@ -1705,7 +1688,7 @@ namespace { { } - Type resolveType(TypeRepr *repr, TypeResolutionOptions options); + NeverNullType resolveType(TypeRepr *repr, TypeResolutionOptions options); private: template @@ -1735,12 +1718,9 @@ namespace { = nullptr, DifferentiabilityKind diffKind = DifferentiabilityKind::NonDifferentiable); - bool - resolveASTFunctionTypeParams(TupleTypeRepr *inputRepr, - TypeResolutionOptions options, - bool requiresMappingOut, - DifferentiabilityKind diffKind, - SmallVectorImpl &ps); + SmallVector resolveASTFunctionTypeParams( + TupleTypeRepr *inputRepr, TypeResolutionOptions options, + bool requiresMappingOut, DifferentiabilityKind diffKind); Type resolveSILFunctionType(FunctionTypeRepr *repr, TypeResolutionOptions options, @@ -1843,7 +1823,8 @@ Type ResolveTypeRequest::evaluate(Evaluator &evaluator, return result; } -Type TypeResolver::resolveType(TypeRepr *repr, TypeResolutionOptions options) { +NeverNullType TypeResolver::resolveType(TypeRepr *repr, + TypeResolutionOptions options) { assert(repr && "Cannot validate null TypeReprs!"); // If we know the type representation is invalid, just return an @@ -1939,9 +1920,9 @@ Type TypeResolver::resolveType(TypeRepr *repr, TypeResolutionOptions options) { options |= TypeResolutionFlags::SilenceErrors; auto constraintType = resolveType(opaqueRepr->getConstraint(), options); - - return constraintType && !constraintType->hasError() - ? ErrorType::get(constraintType) : ErrorType::get(Context); + + return !constraintType->hasError() ? ErrorType::get(constraintType) + : ErrorType::get(Context); } case TypeReprKind::Fixed: @@ -2024,7 +2005,7 @@ Type TypeResolver::resolveAttributedType(TypeAttributes &attrs, instanceOptions -= TypeResolutionFlags::SILType; auto instanceTy = resolveType(base, instanceOptions); - if (!instanceTy || instanceTy->hasError()) + if (instanceTy->hasError()) return instanceTy; // Check for @thin. @@ -2463,10 +2444,12 @@ Type TypeResolver::resolveAttributedType(TypeAttributes &attrs, return ty; } -bool TypeResolver::resolveASTFunctionTypeParams( - TupleTypeRepr *inputRepr, TypeResolutionOptions options, - bool requiresMappingOut, DifferentiabilityKind diffKind, - SmallVectorImpl &elements) { +SmallVector +TypeResolver::resolveASTFunctionTypeParams(TupleTypeRepr *inputRepr, + TypeResolutionOptions options, + bool requiresMappingOut, + DifferentiabilityKind diffKind) { + SmallVector elements; elements.reserve(inputRepr->getNumElements()); auto elementOptions = options.withoutContext(true); @@ -2486,9 +2469,7 @@ bool TypeResolver::resolveASTFunctionTypeParams( variadic = true; } - Type ty = resolveType(eltTypeRepr, thisElementOptions); - if (!ty) return true; - + auto ty = resolveType(eltTypeRepr, thisElementOptions); if (ty->hasError()) { elements.emplace_back(ErrorType::get(Context)); continue; @@ -2583,7 +2564,7 @@ bool TypeResolver::resolveASTFunctionTypeParams( } } - return false; + return elements; } Type TypeResolver::resolveOpaqueReturnType(TypeRepr *repr, @@ -2598,7 +2579,7 @@ Type TypeResolver::resolveOpaqueReturnType(TypeRepr *repr, for (auto argRepr : generic->getGenericArgs()) { auto argTy = resolveType(argRepr, options); // If we cannot resolve the generic parameter, propagate the error out. - if (!argTy || argTy->hasError()) { + if (argTy->hasError()) { return ErrorType::get(Context); } TypeArgsBuf.push_back(argTy); @@ -2636,18 +2617,16 @@ Type TypeResolver::resolveASTFunctionType( TypeResolutionOptions options = None; options |= parentOptions.withoutContext().getFlags(); - - SmallVector params; - if (resolveASTFunctionTypeParams(repr->getArgsTypeRepr(), options, - repr->getGenericEnvironment() != nullptr, - diffKind, params)) { - return Type(); - } + auto params = resolveASTFunctionTypeParams( + repr->getArgsTypeRepr(), options, + repr->getGenericEnvironment() != nullptr, diffKind); auto resultOptions = options.withoutContext(); resultOptions.setContext(TypeResolverContext::FunctionResult); - Type outputTy = resolveType(repr->getResultTypeRepr(), resultOptions); - if (!outputTy || outputTy->hasError()) return outputTy; + auto outputTy = resolveType(repr->getResultTypeRepr(), resultOptions); + if (outputTy->hasError()) { + return ErrorType::get(Context); + } // If this is a function type without parens around the parameter list, // diagnose this and produce a fixit to add them. @@ -2867,9 +2846,8 @@ Type TypeResolver::resolveSILFunctionType(FunctionTypeRepr *repr, elementOptions.setContext(TypeResolverContext::FunctionInput); auto param = resolveSILParameter(elt.Type, elementOptions); params.push_back(param); - if (!param.getInterfaceType()) return nullptr; - if (param.getInterfaceType()->hasError()) + if (!param.getInterfaceType() || param.getInterfaceType()->hasError()) hasError = true; } @@ -3216,7 +3194,9 @@ Type TypeResolver::resolveIdentifierType(IdentTypeRepr *IdType, ComponentRange.end()); Type result = resolveIdentTypeComponent(resolution.withOptions(options), Components); - if (!result) return nullptr; + if (!result || result->hasError()) { + return ErrorType::get(Context); + } if (auto moduleTy = result->getAs()) { // Allow module types only if flag is specified. @@ -3304,12 +3284,14 @@ Type TypeResolver::resolveSpecifierTypeRepr(SpecifierTypeRepr *repr, Type TypeResolver::resolveArrayType(ArrayTypeRepr *repr, TypeResolutionOptions options) { - Type baseTy = resolveType(repr->getBase(), options.withoutContext()); - if (!baseTy || baseTy->hasError()) return baseTy; + auto baseTy = resolveType(repr->getBase(), options.withoutContext()); + if (baseTy->hasError()) { + return ErrorType::get(Context); + } auto sliceTy = TypeChecker::getArraySliceType(repr->getBrackets().Start, baseTy); - if (!sliceTy) + if (sliceTy->hasError()) return ErrorType::get(Context); return sliceTy; @@ -3319,29 +3301,31 @@ Type TypeResolver::resolveDictionaryType(DictionaryTypeRepr *repr, TypeResolutionOptions options) { options = adjustOptionsForGenericArgs(options); - Type keyTy = resolveType(repr->getKey(), options.withoutContext()); - if (!keyTy || keyTy->hasError()) return keyTy; + auto keyTy = resolveType(repr->getKey(), options.withoutContext()); + if (keyTy->hasError()) { + return ErrorType::get(Context); + } - Type valueTy = resolveType(repr->getValue(), options.withoutContext()); - if (!valueTy || valueTy->hasError()) return valueTy; + auto valueTy = resolveType(repr->getValue(), options.withoutContext()); + if (valueTy->hasError()) { + return ErrorType::get(Context); + } auto dictDecl = Context.getDictionaryDecl(); - - if (auto dictTy = TypeChecker::getDictionaryType(repr->getBrackets().Start, - keyTy, valueTy)) { - auto unboundTy = dictDecl->getDeclaredType()->castTo(); - - Type args[] = {keyTy, valueTy}; - - if (!TypeChecker::applyUnboundGenericArguments( - unboundTy, dictDecl, repr->getStartLoc(), resolution, args)) { - return nullptr; - } - - return dictTy; + if (!dictDecl) { + Context.Diags.diagnose(repr->getBrackets().Start, + diag::sugar_type_not_found, 3); + return ErrorType::get(Context); } - return ErrorType::get(Context); + auto unboundTy = dictDecl->getDeclaredType()->castTo(); + Type args[] = {keyTy, valueTy}; + if (!TypeChecker::applyUnboundGenericArguments( + unboundTy, dictDecl, repr->getStartLoc(), resolution, args)) { + assert(Context.Diags.hadAnyError()); + return ErrorType::get(Context); + } + return DictionaryType::get(keyTy, valueTy); } Type TypeResolver::resolveOptionalType(OptionalTypeRepr *repr, @@ -3349,14 +3333,16 @@ Type TypeResolver::resolveOptionalType(OptionalTypeRepr *repr, TypeResolutionOptions elementOptions = options.withoutContext(true); elementOptions.setContext(TypeResolverContext::ImmediateOptionalTypeArgument); - // The T in T? is a generic type argument and therefore always an AST type. - // FIXME: diagnose non-materializability of element type! - Type baseTy = resolveType(repr->getBase(), elementOptions); - if (!baseTy || baseTy->hasError()) return baseTy; + auto baseTy = resolveType(repr->getBase(), elementOptions); + if (baseTy->hasError()) { + return ErrorType::get(Context); + } auto optionalTy = TypeChecker::getOptionalType(repr->getQuestionLoc(), baseTy); - if (!optionalTy) return ErrorType::get(Context); + if (optionalTy->hasError()) { + return ErrorType::get(Context); + } return optionalTy; } @@ -3419,17 +3405,16 @@ Type TypeResolver::resolveImplicitlyUnwrappedOptionalType( TypeResolutionOptions elementOptions = options.withoutContext(true); elementOptions.setContext(TypeResolverContext::ImmediateOptionalTypeArgument); - // The T in T! is a generic type argument and therefore always an AST type. - // FIXME: diagnose non-materializability of element type! - Type baseTy = resolveType(repr->getBase(), elementOptions); - if (!baseTy || baseTy->hasError()) return baseTy; - - Type uncheckedOptionalTy; - uncheckedOptionalTy = TypeChecker::getOptionalType(repr->getExclamationLoc(), - baseTy); + auto baseTy = resolveType(repr->getBase(), elementOptions); + if (baseTy->hasError()) { + return ErrorType::get(Context); + } - if (!uncheckedOptionalTy) + auto uncheckedOptionalTy = + TypeChecker::getOptionalType(repr->getExclamationLoc(), baseTy); + if (uncheckedOptionalTy->hasError()) { return ErrorType::get(Context); + } return uncheckedOptionalTy; } @@ -3460,8 +3445,8 @@ Type TypeResolver::resolveTupleType(TupleTypeRepr *repr, for (unsigned i = 0, end = repr->getNumElements(); i != end; ++i) { auto *tyR = repr->getElementType(i); - Type ty = resolveType(tyR, elementOptions); - if (!ty || ty->hasError()) + auto ty = resolveType(tyR, elementOptions); + if (ty->hasError()) hadError = true; auto eltName = repr->getElementName(i); @@ -3529,8 +3514,8 @@ Type TypeResolver::resolveCompositionType(CompositionTypeRepr *repr, }; for (auto tyR : repr->getTypes()) { - Type ty = resolveType(tyR, options.withoutContext()); - if (!ty || ty->hasError()) return ty; + auto ty = resolveType(tyR, options.withoutContext()); + if (ty->hasError()) return ty; auto nominalDecl = ty->getAnyNominal(); if (nominalDecl && isa(nominalDecl)) { @@ -3573,8 +3558,10 @@ Type TypeResolver::resolveCompositionType(CompositionTypeRepr *repr, Type TypeResolver::resolveMetatypeType(MetatypeTypeRepr *repr, TypeResolutionOptions options) { // The instance type of a metatype is always abstract, not SIL-lowered. - Type ty = resolveType(repr->getBase(), options.withoutContext()); - if (!ty || ty->hasError()) return ty; + auto ty = resolveType(repr->getBase(), options.withoutContext()); + if (ty->hasError()) { + return ErrorType::get(Context); + } Optional storedRepr; @@ -3604,8 +3591,10 @@ Type TypeResolver::buildMetatypeType( Type TypeResolver::resolveProtocolType(ProtocolTypeRepr *repr, TypeResolutionOptions options) { // The instance type of a metatype is always abstract, not SIL-lowered. - Type ty = resolveType(repr->getBase(), options.withoutContext()); - if (!ty || ty->hasError()) return ty; + auto ty = resolveType(repr->getBase(), options.withoutContext()); + if (ty->hasError()) { + return ErrorType::get(Context); + } Optional storedRepr; diff --git a/lib/Sema/TypeCheckType.h b/lib/Sema/TypeCheckType.h index b09e418464c2a..e32632d877330 100644 --- a/lib/Sema/TypeCheckType.h +++ b/lib/Sema/TypeCheckType.h @@ -366,7 +366,7 @@ class TypeResolution { /// /// \param TyR The type representation to check. /// - /// \returns a well-formed type or an ErrorType in case of an error. + /// \returns A well-formed type that is never null, or an \c ErrorType in case of an error. Type resolveType(TypeRepr *TyR); /// Whether this type resolution uses archetypes (vs. generic parameters). diff --git a/lib/Sema/TypeChecker.h b/lib/Sema/TypeChecker.h index c3bd2d9384d70..7315910400fff 100644 --- a/lib/Sema/TypeChecker.h +++ b/lib/Sema/TypeChecker.h @@ -345,33 +345,13 @@ enum class CheckedCastContextKind { namespace TypeChecker { Type getArraySliceType(SourceLoc loc, Type elementType); -Type getDictionaryType(SourceLoc loc, Type keyType, Type valueType); Type getOptionalType(SourceLoc loc, Type elementType); -Type getStringType(ASTContext &ctx); -Type getSubstringType(ASTContext &ctx); -Type getIntType(ASTContext &ctx); -Type getInt8Type(ASTContext &ctx); -Type getUInt8Type(ASTContext &ctx); /// Bind an UnresolvedDeclRefExpr by performing name lookup and /// returning the resultant expression. Context is the DeclContext used /// for the lookup. Expr *resolveDeclRefExpr(UnresolvedDeclRefExpr *UDRE, DeclContext *Context); -/// Validate the given type. -/// -/// Type validation performs name lookup, checking of generic arguments, -/// and so on to determine whether the given type is well-formed and can -/// be used as a type. -/// -/// \param Loc The type (with source location information) to validate. -/// If the type has already been validated, returns immediately. -/// -/// \param resolution The type resolution being performed. -/// -/// \returns true if type validation failed, or false otherwise. -bool validateType(TypeLoc &Loc, TypeResolution resolution); - /// Check for unsupported protocol types in the given declaration. void checkUnsupportedProtocolType(Decl *decl); diff --git a/validation-test/compiler_crashers_2_fixed/0163-sr8033.swift b/validation-test/compiler_crashers_2_fixed/0163-sr8033.swift index 3553340caf55c..cd51bdf472be7 100644 --- a/validation-test/compiler_crashers_2_fixed/0163-sr8033.swift +++ b/validation-test/compiler_crashers_2_fixed/0163-sr8033.swift @@ -7,4 +7,4 @@ protocol P1 { } extension Foo: P1 where A : P1 {} // expected-error {{unsupported recursion for reference to associated type 'A' of type 'Foo'}} // expected-error@-1 {{type 'Foo' does not conform to protocol 'P1'}} -// expected-error@-2 {{type 'Foo' in conformance requirement does not refer to a generic parameter or associated type}} +// expected-error@-2 {{type '<>' in conformance requirement does not refer to a generic parameter or associated type}}