diff --git a/include/swift/AST/Type.h b/include/swift/AST/Type.h index 8d6a849fb301..a1315299807e 100644 --- a/include/swift/AST/Type.h +++ b/include/swift/AST/Type.h @@ -595,17 +595,6 @@ template <> struct CanTypeWrapperTraits { \ BEGIN_CAN_TYPE_WRAPPER(TYPE, BASE) \ END_CAN_TYPE_WRAPPER(TYPE, BASE) -// Disallow direct uses of isa/cast/dyn_cast on Type to eliminate a -// certain class of bugs. -template inline bool -isa(const Type&) = delete; // Use TypeBase::is instead. -template inline typename llvm::cast_retty::ret_type -cast(const Type&) = delete; // Use TypeBase::castTo instead. -template inline typename llvm::cast_retty::ret_type -dyn_cast(const Type&) = delete; // Use TypeBase::getAs instead. -template inline typename llvm::cast_retty::ret_type -dyn_cast_or_null(const Type&) = delete; - // Permit direct uses of isa/cast/dyn_cast on CanType and preserve // canonicality. template inline bool isa(CanType type) { @@ -656,16 +645,6 @@ namespace llvm { return OS; } - // A Type casts like a TypeBase*. - template<> struct simplify_type { - typedef ::swift::TypeBase *SimpleType; - static SimpleType getSimplifiedValue(const ::swift::Type &Val) { - return Val.getPointer(); - } - }; - template<> struct simplify_type< ::swift::Type> - : public simplify_type {}; - // Type hashes just like pointers. template<> struct DenseMapInfo { static swift::Type getEmptyKey() { @@ -716,4 +695,37 @@ namespace llvm { }; } // end namespace llvm +/// Disallow uses of `isa`/`cast`/`dyn_cast` directly on `Type` to eliminate a +/// certain class of bugs. +namespace llvm { + +template +struct CastInfo { + // FIXME: Without this 'false' indirection, clang from 5.9 toolchain + // triggers the static assert directly on the template. Try removing once + // Linux CI is updated to 6.0. + static constexpr bool False() { return false; } + static_assert( + False(), "don't use isa/cast/dyn_cast directly on a 'Type' value; " + "instead, use 'isa/cast/dyn_cast(type.getPointer())' to " + "cast the exact type, or use 'type->is/getAs/castTo()' " + "to cast the desugared type, which is usually the right choice"); +}; +template +struct CastInfo : public CastInfo {}; + +/// These specializations exist to avoid unhelpful instantiation errors in +/// addition to the above static assertion. +template <> +struct simplify_type { + typedef ::swift::TypeBase *SimpleType; + static SimpleType getSimplifiedValue(const swift::Type &Val) { + return Val.getPointer(); + } +}; +template <> +struct simplify_type : public simplify_type {}; + +} // namespace llvm + #endif diff --git a/lib/AST/ASTPrinter.cpp b/lib/AST/ASTPrinter.cpp index f9d99543705c..909df265d15b 100644 --- a/lib/AST/ASTPrinter.cpp +++ b/lib/AST/ASTPrinter.cpp @@ -4397,8 +4397,8 @@ void PrintAST::visitFuncDecl(FuncDecl *decl) { if (decl->hasSendingResult()) { Printer << "sending "; - } else if (auto *ft = llvm::dyn_cast_if_present( - decl->getInterfaceType())) { + } else if (auto *ft = + decl->getInterfaceType()->getAs()) { if (ft->hasExtInfo() && ft->hasSendingResult()) { Printer << "sending "; } diff --git a/lib/AST/TypeSubstitution.cpp b/lib/AST/TypeSubstitution.cpp index 2e467ab839b6..2f0e8854f62e 100644 --- a/lib/AST/TypeSubstitution.cpp +++ b/lib/AST/TypeSubstitution.cpp @@ -1123,7 +1123,7 @@ ProtocolConformanceRef swift::substOpaqueTypesWithUnderlyingTypes( ProtocolConformanceRef ReplaceOpaqueTypesWithUnderlyingTypes:: operator()(InFlightSubstitution &IFS, Type maybeOpaqueType, ProtocolDecl *protocol) const { - auto archetype = dyn_cast(maybeOpaqueType); + auto *archetype = maybeOpaqueType->getAs(); if (!archetype) return ProtocolConformanceRef::forAbstract(maybeOpaqueType, protocol); @@ -1194,7 +1194,7 @@ Type ReplaceExistentialArchetypesWithConcreteTypes::operator()( ProtocolConformanceRef ReplaceExistentialArchetypesWithConcreteTypes::operator()( InFlightSubstitution &IFS, Type origType, ProtocolDecl *proto) const { - auto existentialArchetype = dyn_cast(origType); + auto *existentialArchetype = origType->getAs(); if (!existentialArchetype || existentialArchetype->getGenericEnvironment() != env) return ProtocolConformanceRef::forAbstract(origType.subst(IFS), proto); diff --git a/lib/ConstExtract/ConstExtract.cpp b/lib/ConstExtract/ConstExtract.cpp index b6863915c54a..e2eb0865b87e 100644 --- a/lib/ConstExtract/ConstExtract.cpp +++ b/lib/ConstExtract/ConstExtract.cpp @@ -1392,7 +1392,7 @@ void writeAssociatedTypeAliases(llvm::json::OStream &JSON, toFullyQualifiedTypeNameString(type)); JSON.attribute("substitutedMangledTypeName", toMangledTypeNameString(type)); - if (auto OpaqueTy = dyn_cast(type)) { + if (auto *OpaqueTy = type->getAs()) { writeSubstitutedOpaqueTypeAliasDetails(JSON, *OpaqueTy); } }); diff --git a/lib/IRGen/GenDecl.cpp b/lib/IRGen/GenDecl.cpp index 7188bc566a55..81f1e9eaae08 100644 --- a/lib/IRGen/GenDecl.cpp +++ b/lib/IRGen/GenDecl.cpp @@ -3601,7 +3601,7 @@ bool swift::irgen::hasValidSignatureForEmbedded(SILFunction *f) { auto s = f->getLoweredFunctionType()->getInvocationGenericSignature(); for (auto genParam : s.getGenericParams()) { auto mappedParam = f->getGenericEnvironment()->mapTypeIntoEnvironment(genParam); - if (auto archeTy = dyn_cast(mappedParam)) { + if (auto *archeTy = mappedParam->getAs()) { if (archeTy->requiresClass()) continue; } diff --git a/lib/IRGen/IRGenDebugInfo.cpp b/lib/IRGen/IRGenDebugInfo.cpp index 7737d464569d..69c7fce7aad7 100644 --- a/lib/IRGen/IRGenDebugInfo.cpp +++ b/lib/IRGen/IRGenDebugInfo.cpp @@ -1599,7 +1599,7 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo { std::vector GenericArgs; Type CurrentType = BGT; while (CurrentType && CurrentType->getAnyNominal()) { - if (auto *BGT = llvm::dyn_cast(CurrentType)) + if (auto *BGT = CurrentType->getAs()) GenericArgs.insert(GenericArgs.end(), BGT->getGenericArgs().begin(), BGT->getGenericArgs().end()); CurrentType = CurrentType->getNominalParent(); @@ -2460,9 +2460,10 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo { return TypeWalker::Action::Stop; DeclContext *D = nullptr; - if (auto *TAT = llvm::dyn_cast(T)) + if (auto *TAT = llvm::dyn_cast(T.getPointer())) D = TAT->getDecl()->getDeclContext(); - else if (auto *NT = llvm::dyn_cast(T)) + else if (auto *NT = llvm::dyn_cast( + T.getPointer())) D = NT->getDecl()->getDeclContext(); // A type inside a function uses that function's signature as part of diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp index 21797bc5454b..18acc629256b 100644 --- a/lib/Sema/CSSimplify.cpp +++ b/lib/Sema/CSSimplify.cpp @@ -9977,7 +9977,7 @@ ConstraintSystem::matchPackElementType(Type elementType, Type patternType, return tryFix([&]() { auto envShape = genericEnv->mapTypeIntoEnvironment( genericEnv->getOpenedElementShapeClass()); - if (auto *pack = dyn_cast(envShape)) + if (auto *pack = dyn_cast(envShape.getPointer())) envShape = pack->unwrapSingletonPackExpansion()->getPatternType(); return SkipSameShapeRequirement::create( diff --git a/lib/Sema/IDETypeCheckingRequests.cpp b/lib/Sema/IDETypeCheckingRequests.cpp index facb89de0216..378c924f9c44 100644 --- a/lib/Sema/IDETypeCheckingRequests.cpp +++ b/lib/Sema/IDETypeCheckingRequests.cpp @@ -151,7 +151,7 @@ static bool isExtensionAppliedInternal(const DeclContext *DC, Type BaseTy, return true; ProtocolDecl *BaseTypeProtocolDecl = nullptr; - if (auto opaqueType = dyn_cast(BaseTy)) { + if (auto *opaqueType = BaseTy->getAs()) { if (opaqueType->getConformsTo().size() == 1) { BaseTypeProtocolDecl = opaqueType->getConformsTo().front(); } diff --git a/lib/Sema/TypeCheckAvailability.cpp b/lib/Sema/TypeCheckAvailability.cpp index 87067348c93e..c41dc9ed14a3 100644 --- a/lib/Sema/TypeCheckAvailability.cpp +++ b/lib/Sema/TypeCheckAvailability.cpp @@ -2627,7 +2627,7 @@ class ExprAvailabilityWalker : public BaseDiagnosticWalker { if (ty->isKnownImmutableKeyPathType()) return StorageAccessKind::Get; - if (auto existential = dyn_cast(ty)) { + if (auto *existential = ty->getAs()) { if (auto superclass = existential->getExistentialLayout().getSuperclass()) { if (superclass->isKnownImmutableKeyPathType()) diff --git a/lib/Sema/TypeCheckType.cpp b/lib/Sema/TypeCheckType.cpp index df987877e12c..ea67ea340e14 100644 --- a/lib/Sema/TypeCheckType.cpp +++ b/lib/Sema/TypeCheckType.cpp @@ -5412,7 +5412,7 @@ TypeResolver::resolveIsolatedTypeRepr(IsolatedTypeRepr *repr, unwrappedType = wrappedOptionalType; } - if (auto dynamicSelfType = dyn_cast(unwrappedType)) { + if (auto *dynamicSelfType = unwrappedType->getAs()) { unwrappedType = dynamicSelfType->getSelfType(); } diff --git a/lib/Serialization/Serialization.cpp b/lib/Serialization/Serialization.cpp index 9c0d9eb8834f..fb7a94dd5658 100644 --- a/lib/Serialization/Serialization.cpp +++ b/lib/Serialization/Serialization.cpp @@ -5626,7 +5626,7 @@ struct ImplementationOnlyWalker : TypeWalker { const ModuleDecl *currentModule; ImplementationOnlyWalker(const ModuleDecl *M) : currentModule(M) {} Action walkToTypePre(Type ty) override { - if (auto *typeAlias = dyn_cast(ty)) { + if (auto *typeAlias = dyn_cast(ty.getPointer())) { if (importedImplementationOnly(typeAlias->getDecl())) return Action::Stop; } else if (auto *nominal = ty->getAs()) {