mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Sema: Pull availability checking out of resolveType()
We used to diagnose references to unavailable declarations in two places: - inside Exprs, right after type checking the expression - inside TypeReprs, from resolveType() In broad terms, resolveType() is called with TypeReprs stored inside both Stmts and Decls. To handle the first case, I added a new overload of diagAvailability() that takes a Stmt, to be called from typeCheckStmt(). This doesn't actually walk into any Exprs stored inside the statement; this means it only walks Patterns and such. For the second case, a new DeclAvailabilityChecker is now defined in TypeCheckAccess.cpp. It's structure is analogous to the other three walkers there: - AccessControlChecker - UsableFromInlineChecker - ExportabilityChecker The new implementation of availability checking for types introduces a lot more code than the old online logic it replaces. However, I hope to consolidate some of the code duplication among the four checkers that are defined in TypeCheckAccess.cpp, and do some other cleanups that will make the benefit of the new approach apparent.
This commit is contained in:
@@ -4607,7 +4607,9 @@ void swift::performSyntacticExprDiagnostics(const Expr *E,
|
||||
checkActorIsolation(E, DC);
|
||||
}
|
||||
|
||||
void swift::performStmtDiagnostics(ASTContext &ctx, const Stmt *S) {
|
||||
void swift::performStmtDiagnostics(const Stmt *S, DeclContext *DC) {
|
||||
auto &ctx = DC->getASTContext();
|
||||
|
||||
TypeChecker::checkUnsupportedProtocolType(ctx, const_cast<Stmt *>(S));
|
||||
|
||||
if (auto switchStmt = dyn_cast<SwitchStmt>(S))
|
||||
@@ -4619,6 +4621,9 @@ void swift::performStmtDiagnostics(ASTContext &ctx, const Stmt *S) {
|
||||
if (auto *lcs = dyn_cast<LabeledConditionalStmt>(S))
|
||||
for (const auto &elt : lcs->getCond())
|
||||
checkImplicitPromotionsInCondition(elt, ctx);
|
||||
|
||||
if (!ctx.LangOpts.DisableAvailabilityChecking)
|
||||
diagAvailability(S, const_cast<DeclContext*>(DC));
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
@@ -38,7 +38,7 @@ void performSyntacticExprDiagnostics(const Expr *E, const DeclContext *DC,
|
||||
bool isExprStmt);
|
||||
|
||||
/// Emit diagnostics for a given statement.
|
||||
void performStmtDiagnostics(ASTContext &ctx, const Stmt *S);
|
||||
void performStmtDiagnostics(const Stmt *S, DeclContext *DC);
|
||||
|
||||
void performAbstractFuncDeclDiagnostics(AbstractFunctionDecl *AFD);
|
||||
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "TypeCheckAccess.h"
|
||||
#include "TypeChecker.h"
|
||||
#include "TypeCheckAvailability.h"
|
||||
#include "TypeAccessScopeChecker.h"
|
||||
#include "swift/AST/ASTVisitor.h"
|
||||
#include "swift/AST/ASTWalker.h"
|
||||
@@ -1772,7 +1774,11 @@ public:
|
||||
checkOverride(VD);
|
||||
}
|
||||
|
||||
DeclVisitor<ExportabilityChecker>::visit(D);
|
||||
// Note: references to @_spi and @_implementationOnly declarations from
|
||||
// @inlinable code are diagnosed by DeclAvailabilityChecker below.
|
||||
auto *DC = D->getInnermostDeclContext();
|
||||
if (DC->getFragileFunctionKind().kind == FragileFunctionKind::None)
|
||||
DeclVisitor<ExportabilityChecker>::visit(D);
|
||||
}
|
||||
|
||||
// Force all kinds to be handled at a lower level.
|
||||
@@ -2035,6 +2041,261 @@ public:
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/// Diagnose declarations whose signatures refer to unavailable types.
|
||||
class DeclAvailabilityChecker : public DeclVisitor<DeclAvailabilityChecker> {
|
||||
DeclContext *DC;
|
||||
|
||||
void checkType(Type type, const TypeRepr *typeRepr, const Decl *context,
|
||||
bool allowUnavailableProtocol=false) {
|
||||
// Don't bother checking errors.
|
||||
if (type && type->hasError())
|
||||
return;
|
||||
|
||||
// Check the TypeRepr for references to unavailable declarations.
|
||||
if (typeRepr) {
|
||||
DeclAvailabilityFlags flags = None;
|
||||
|
||||
// We allow a type to conform to a protocol that is less available than
|
||||
// the type itself. This enables a type to retroactively model or directly
|
||||
// conform to a protocol only available on newer OSes and yet still be used on
|
||||
// older OSes.
|
||||
//
|
||||
// To support this, inside inheritance clauses we allow references to
|
||||
// protocols that are unavailable in the current type refinement context.
|
||||
if (allowUnavailableProtocol)
|
||||
flags |= DeclAvailabilityFlag::AllowPotentiallyUnavailableProtocol;
|
||||
|
||||
diagnoseTypeReprAvailability(typeRepr, DC, flags);
|
||||
}
|
||||
|
||||
// Check the type for references to unavailable conformances.
|
||||
if (type)
|
||||
if (!context->getDeclContext()->isLocalContext())
|
||||
diagnoseTypeAvailability(type, context->getLoc(), DC);
|
||||
}
|
||||
|
||||
void checkGenericParams(const GenericContext *ownerCtx,
|
||||
const ValueDecl *ownerDecl) {
|
||||
// FIXME: What if we have a where clause and no generic params?
|
||||
const auto params = ownerCtx->getGenericParams();
|
||||
if (!params)
|
||||
return;
|
||||
|
||||
for (auto param : *params) {
|
||||
if (param->getInherited().empty())
|
||||
continue;
|
||||
assert(param->getInherited().size() == 1);
|
||||
auto inherited = param->getInherited().front();
|
||||
checkType(inherited.getType(), inherited.getTypeRepr(), ownerDecl);
|
||||
}
|
||||
|
||||
forAllRequirementTypes(WhereClauseOwner(
|
||||
const_cast<GenericContext *>(ownerCtx)),
|
||||
[&](Type type, TypeRepr *typeRepr) {
|
||||
checkType(type, typeRepr, ownerDecl);
|
||||
});
|
||||
}
|
||||
|
||||
public:
|
||||
explicit DeclAvailabilityChecker(Decl *D)
|
||||
: DC(D->getInnermostDeclContext()) {}
|
||||
|
||||
void visit(Decl *D) {
|
||||
if (D->isImplicit())
|
||||
return;
|
||||
|
||||
DeclVisitor<DeclAvailabilityChecker>::visit(D);
|
||||
}
|
||||
|
||||
// Force all kinds to be handled at a lower level.
|
||||
void visitDecl(Decl *D) = delete;
|
||||
void visitValueDecl(ValueDecl *D) = delete;
|
||||
|
||||
#define UNREACHABLE(KIND, REASON) \
|
||||
void visit##KIND##Decl(KIND##Decl *D) { \
|
||||
llvm_unreachable(REASON); \
|
||||
}
|
||||
UNREACHABLE(Import, "not applicable")
|
||||
UNREACHABLE(TopLevelCode, "not applicable")
|
||||
UNREACHABLE(Module, "not applicable")
|
||||
|
||||
UNREACHABLE(Param, "handled by the enclosing declaration")
|
||||
UNREACHABLE(GenericTypeParam, "handled by the enclosing declaration")
|
||||
UNREACHABLE(MissingMember, "handled by the enclosing declaration")
|
||||
#undef UNREACHABLE
|
||||
|
||||
#define UNINTERESTING(KIND) \
|
||||
void visit##KIND##Decl(KIND##Decl *D) {}
|
||||
|
||||
UNINTERESTING(PrefixOperator) // Does not reference other decls.
|
||||
UNINTERESTING(PostfixOperator) // Does not reference other decls.
|
||||
UNINTERESTING(InfixOperator) // Does not reference other decls.
|
||||
UNINTERESTING(IfConfig) // Not applicable.
|
||||
UNINTERESTING(PoundDiagnostic) // Not applicable.
|
||||
UNINTERESTING(EnumCase) // Handled at the EnumElement level.
|
||||
UNINTERESTING(Destructor) // Always correct.
|
||||
UNINTERESTING(Accessor) // Handled by the Var or Subscript.
|
||||
UNINTERESTING(OpaqueType) // TODO
|
||||
UNINTERESTING(PrecedenceGroup) // Doesn't reference anything with availability.
|
||||
|
||||
// Handled at the PatternBinding level; if the pattern has a simple
|
||||
// "name: TheType" form, we can get better results by diagnosing the TypeRepr.
|
||||
UNINTERESTING(Var)
|
||||
|
||||
/// \see visitPatternBindingDecl
|
||||
void checkNamedPattern(const NamedPattern *NP,
|
||||
const llvm::DenseSet<const VarDecl *> &seenVars) {
|
||||
const VarDecl *theVar = NP->getDecl();
|
||||
|
||||
// Only check the type of individual variables if we didn't check an
|
||||
// enclosing TypedPattern.
|
||||
if (seenVars.count(theVar))
|
||||
return;
|
||||
|
||||
checkType(theVar->getValueInterfaceType(), /*typeRepr*/nullptr, theVar);
|
||||
}
|
||||
|
||||
/// \see visitPatternBindingDecl
|
||||
void checkTypedPattern(PatternBindingDecl *PBD,
|
||||
const TypedPattern *TP,
|
||||
llvm::DenseSet<const VarDecl *> &seenVars) {
|
||||
// FIXME: We need to figure out if this is a stored or computed property,
|
||||
// so we pull out some random VarDecl in the pattern. They're all going to
|
||||
// be the same, but still, ick.
|
||||
const VarDecl *anyVar = nullptr;
|
||||
TP->forEachVariable([&](VarDecl *V) {
|
||||
seenVars.insert(V);
|
||||
anyVar = V;
|
||||
});
|
||||
|
||||
checkType(TP->hasType() ? TP->getType() : Type(),
|
||||
TP->getTypeRepr(), PBD);
|
||||
|
||||
// Check the property wrapper types.
|
||||
if (anyVar)
|
||||
for (auto attr : anyVar->getAttachedPropertyWrappers())
|
||||
checkType(attr->getType(), attr->getTypeRepr(), anyVar);
|
||||
}
|
||||
|
||||
void visitPatternBindingDecl(PatternBindingDecl *PBD) {
|
||||
llvm::DenseSet<const VarDecl *> seenVars;
|
||||
for (auto idx : range(PBD->getNumPatternEntries())) {
|
||||
PBD->getPattern(idx)->forEachNode([&](const Pattern *P) {
|
||||
if (auto *NP = dyn_cast<NamedPattern>(P)) {
|
||||
checkNamedPattern(NP, seenVars);
|
||||
return;
|
||||
}
|
||||
|
||||
auto *TP = dyn_cast<TypedPattern>(P);
|
||||
if (!TP)
|
||||
return;
|
||||
checkTypedPattern(PBD, TP, seenVars);
|
||||
});
|
||||
seenVars.clear();
|
||||
}
|
||||
}
|
||||
|
||||
void visitTypeAliasDecl(TypeAliasDecl *TAD) {
|
||||
checkGenericParams(TAD, TAD);
|
||||
checkType(TAD->getUnderlyingType(),
|
||||
TAD->getUnderlyingTypeRepr(), TAD);
|
||||
}
|
||||
|
||||
void visitAssociatedTypeDecl(AssociatedTypeDecl *assocType) {
|
||||
llvm::for_each(assocType->getInherited(),
|
||||
[&](TypeLoc requirement) {
|
||||
checkType(requirement.getType(), requirement.getTypeRepr(),
|
||||
assocType);
|
||||
});
|
||||
checkType(assocType->getDefaultDefinitionType(),
|
||||
assocType->getDefaultDefinitionTypeRepr(), assocType);
|
||||
|
||||
if (assocType->getTrailingWhereClause()) {
|
||||
forAllRequirementTypes(assocType,
|
||||
[&](Type type, TypeRepr *typeRepr) {
|
||||
checkType(type, typeRepr, assocType);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void visitNominalTypeDecl(const NominalTypeDecl *nominal) {
|
||||
checkGenericParams(nominal, nominal);
|
||||
|
||||
llvm::for_each(nominal->getInherited(),
|
||||
[&](TypeLoc inherited) {
|
||||
checkType(inherited.getType(), inherited.getTypeRepr(),
|
||||
nominal, /*allowUnavailableProtocol=*/true);
|
||||
});
|
||||
}
|
||||
|
||||
void visitProtocolDecl(ProtocolDecl *proto) {
|
||||
llvm::for_each(proto->getInherited(),
|
||||
[&](TypeLoc requirement) {
|
||||
checkType(requirement.getType(), requirement.getTypeRepr(), proto,
|
||||
/*allowUnavailableProtocol=*/true);
|
||||
});
|
||||
|
||||
if (proto->getTrailingWhereClause()) {
|
||||
forAllRequirementTypes(proto, [&](Type type, TypeRepr *typeRepr) {
|
||||
checkType(type, typeRepr, proto);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void visitSubscriptDecl(SubscriptDecl *SD) {
|
||||
checkGenericParams(SD, SD);
|
||||
|
||||
for (auto &P : *SD->getIndices()) {
|
||||
checkType(P->getInterfaceType(), P->getTypeRepr(), SD);
|
||||
}
|
||||
checkType(SD->getElementInterfaceType(), SD->getElementTypeRepr(), SD);
|
||||
}
|
||||
|
||||
void visitAbstractFunctionDecl(AbstractFunctionDecl *fn) {
|
||||
checkGenericParams(fn, fn);
|
||||
|
||||
for (auto *P : *fn->getParameters())
|
||||
checkType(P->getInterfaceType(), P->getTypeRepr(), fn);
|
||||
}
|
||||
|
||||
void visitFuncDecl(FuncDecl *FD) {
|
||||
visitAbstractFunctionDecl(FD);
|
||||
checkType(FD->getResultInterfaceType(), FD->getResultTypeRepr(), FD);
|
||||
}
|
||||
|
||||
void visitEnumElementDecl(EnumElementDecl *EED) {
|
||||
if (!EED->hasAssociatedValues())
|
||||
return;
|
||||
for (auto &P : *EED->getParameterList())
|
||||
checkType(P->getInterfaceType(), P->getTypeRepr(), EED);
|
||||
}
|
||||
|
||||
void checkConstrainedExtensionRequirements(ExtensionDecl *ED) {
|
||||
if (!ED->getTrailingWhereClause())
|
||||
return;
|
||||
forAllRequirementTypes(ED, [&](Type type, TypeRepr *typeRepr) {
|
||||
checkType(type, typeRepr, ED);
|
||||
});
|
||||
}
|
||||
|
||||
void visitExtensionDecl(ExtensionDecl *ED) {
|
||||
auto extendedType = ED->getExtendedNominal();
|
||||
assert(extendedType && "valid extension with no extended type?");
|
||||
if (!extendedType)
|
||||
return;
|
||||
|
||||
llvm::for_each(ED->getInherited(),
|
||||
[&](TypeLoc inherited) {
|
||||
checkType(inherited.getType(), inherited.getTypeRepr(),
|
||||
ED, /*allowUnavailableProtocol=*/true);
|
||||
});
|
||||
|
||||
checkType(ED->getExtendedType(), ED->getExtendedTypeRepr(), ED);
|
||||
checkConstrainedExtensionRequirements(ED);
|
||||
}
|
||||
};
|
||||
|
||||
} // end anonymous namespace
|
||||
|
||||
static void checkExtensionGenericParamAccess(const ExtensionDecl *ED) {
|
||||
@@ -2086,4 +2347,5 @@ void swift::checkAccessControl(Decl *D) {
|
||||
}
|
||||
|
||||
ExportabilityChecker().visit(D);
|
||||
DeclAvailabilityChecker(D).visit(D);
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "swift/AST/NameLookup.h"
|
||||
#include "swift/AST/Pattern.h"
|
||||
#include "swift/AST/SourceFile.h"
|
||||
#include "swift/AST/TypeDeclFinder.h"
|
||||
#include "swift/AST/TypeRefinementContext.h"
|
||||
#include "swift/Basic/Defer.h"
|
||||
#include "swift/Basic/SourceManager.h"
|
||||
@@ -2468,6 +2469,11 @@ public:
|
||||
return E;
|
||||
}
|
||||
|
||||
bool walkToTypeReprPre(TypeRepr *T) override {
|
||||
diagnoseTypeReprAvailability(T, DC);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool diagAvailability(ConcreteDeclRef declRef, SourceRange R,
|
||||
const ApplyExpr *call = nullptr,
|
||||
DeclAvailabilityFlags flags = None) const;
|
||||
@@ -2871,6 +2877,170 @@ void swift::diagAvailability(const Expr *E, DeclContext *DC) {
|
||||
const_cast<Expr*>(E)->walk(walker);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
class StmtAvailabilityWalker : public ASTWalker {
|
||||
DeclContext *DC;
|
||||
|
||||
public:
|
||||
explicit StmtAvailabilityWalker(DeclContext *DC) : DC(DC) {}
|
||||
|
||||
/// We'll visit the expression from performSyntacticExprDiagnostics().
|
||||
std::pair<bool, Expr *> walkToExprPre(Expr *E) override {
|
||||
return std::make_pair(false, E);
|
||||
}
|
||||
|
||||
bool walkToTypeReprPre(TypeRepr *T) override {
|
||||
diagnoseTypeReprAvailability(T, DC);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
void swift::diagAvailability(const Stmt *S, DeclContext *DC) {
|
||||
// We'll visit the individual statements when we check them.
|
||||
if (isa<BraceStmt>(S))
|
||||
return;
|
||||
|
||||
StmtAvailabilityWalker walker(DC);
|
||||
const_cast<Stmt*>(S)->walk(walker);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
class TypeReprAvailabilityWalker : public ASTWalker {
|
||||
DeclContext *DC;
|
||||
DeclAvailabilityFlags flags;
|
||||
|
||||
bool checkComponentIdentTypeRepr(ComponentIdentTypeRepr *ITR) {
|
||||
if (auto *typeDecl = ITR->getBoundDecl()) {
|
||||
auto range = ITR->getNameLoc().getSourceRange();
|
||||
if (diagnoseDeclAvailability(typeDecl, DC, range, flags))
|
||||
return true;
|
||||
}
|
||||
|
||||
bool foundAnyIssues = false;
|
||||
|
||||
if (auto *GTR = dyn_cast<GenericIdentTypeRepr>(ITR)) {
|
||||
auto genericFlags = flags;
|
||||
genericFlags -= DeclAvailabilityFlag::AllowPotentiallyUnavailableProtocol;
|
||||
|
||||
for (auto *genericArg : GTR->getGenericArgs()) {
|
||||
if (diagnoseTypeReprAvailability(genericArg, DC, genericFlags))
|
||||
foundAnyIssues = true;
|
||||
}
|
||||
}
|
||||
|
||||
return foundAnyIssues;
|
||||
}
|
||||
|
||||
public:
|
||||
bool foundAnyIssues = false;
|
||||
|
||||
TypeReprAvailabilityWalker(DeclContext *DC,
|
||||
DeclAvailabilityFlags flags)
|
||||
: DC(DC), flags(flags) {}
|
||||
|
||||
bool walkToTypeReprPre(TypeRepr *T) override {
|
||||
if (auto *ITR = dyn_cast<IdentTypeRepr>(T)) {
|
||||
if (auto *CTR = dyn_cast<CompoundIdentTypeRepr>(ITR)) {
|
||||
for (auto *comp : CTR->getComponents()) {
|
||||
// If a parent type is unavailable, don't go on to diagnose
|
||||
// the member since that will just produce a redundant
|
||||
// diagnostic.
|
||||
if (checkComponentIdentTypeRepr(comp)) {
|
||||
foundAnyIssues = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (auto *GTR = dyn_cast<GenericIdentTypeRepr>(T)) {
|
||||
if (checkComponentIdentTypeRepr(GTR))
|
||||
foundAnyIssues = true;
|
||||
} else if (auto *STR = dyn_cast<SimpleIdentTypeRepr>(T)) {
|
||||
if (checkComponentIdentTypeRepr(STR))
|
||||
foundAnyIssues = true;
|
||||
}
|
||||
|
||||
// We've already visited all the children above, so we don't
|
||||
// need to recurse.
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
bool swift::diagnoseTypeReprAvailability(const TypeRepr *T, DeclContext *DC,
|
||||
DeclAvailabilityFlags flags) {
|
||||
TypeReprAvailabilityWalker walker(DC, flags);
|
||||
const_cast<TypeRepr*>(T)->walk(walker);
|
||||
return walker.foundAnyIssues;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
class ProblematicTypeFinder : public TypeDeclFinder {
|
||||
DeclContext *DC;
|
||||
FragileFunctionKind FragileKind;
|
||||
SourceLoc Loc;
|
||||
|
||||
public:
|
||||
ProblematicTypeFinder(DeclContext *DC, SourceLoc Loc)
|
||||
: DC(DC), Loc(Loc) {
|
||||
FragileKind = DC->getFragileFunctionKind();
|
||||
}
|
||||
|
||||
Action visitNominalType(NominalType *ty) override {
|
||||
if (FragileKind.kind != FragileFunctionKind::None)
|
||||
TypeChecker::diagnoseGenericTypeExportability(Loc, ty, DC);
|
||||
return Action::Continue;
|
||||
}
|
||||
|
||||
Action visitBoundGenericType(BoundGenericType *ty) override {
|
||||
if (FragileKind.kind != FragileFunctionKind::None)
|
||||
TypeChecker::diagnoseGenericTypeExportability(Loc, ty, DC);
|
||||
return Action::Continue;
|
||||
}
|
||||
|
||||
Action visitTypeAliasType(TypeAliasType *ty) override {
|
||||
if (FragileKind.kind != FragileFunctionKind::None)
|
||||
TypeChecker::diagnoseGenericTypeExportability(Loc, ty, DC);
|
||||
return Action::Continue;
|
||||
}
|
||||
|
||||
// We diagnose unserializable Clang function types in the
|
||||
// post-visitor so that we diagnose any unexportable component
|
||||
// types first.
|
||||
Action walkToTypePost(Type T) override {
|
||||
if (FragileKind.kind != FragileFunctionKind::None) {
|
||||
if (auto fnType = T->getAs<AnyFunctionType>()) {
|
||||
if (auto clangType = fnType->getClangTypeInfo().getType()) {
|
||||
auto &ctx = DC->getASTContext();
|
||||
auto loader = ctx.getClangModuleLoader();
|
||||
// Serialization will serialize the sugared type if it can,
|
||||
// but we need the canonical type to be serializable or else
|
||||
// canonicalization (e.g. in SIL) might break things.
|
||||
if (!loader->isSerializable(clangType, /*check canonical*/ true)) {
|
||||
ctx.Diags.diagnose(Loc, diag::unexportable_clang_function_type,
|
||||
fnType);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return TypeDeclFinder::walkToTypePost(T);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
void swift::diagnoseTypeAvailability(Type T, SourceLoc loc, DeclContext *DC) {
|
||||
T.walk(ProblematicTypeFinder(DC, loc));
|
||||
}
|
||||
|
||||
/// Run the Availability-diagnostics algorithm otherwise used in an expr
|
||||
/// context, but for non-expr contexts such as TypeDecls referenced from
|
||||
/// TypeReprs.
|
||||
|
||||
@@ -28,11 +28,11 @@ namespace swift {
|
||||
class Expr;
|
||||
class InFlightDiagnostic;
|
||||
class Decl;
|
||||
class Stmt;
|
||||
class Type;
|
||||
class TypeRepr;
|
||||
class ValueDecl;
|
||||
|
||||
/// Diagnose uses of unavailable declarations.
|
||||
void diagAvailability(const Expr *E, DeclContext *DC);
|
||||
|
||||
enum class DeclAvailabilityFlag : uint8_t {
|
||||
/// Do not diagnose uses of protocols in versions before they were introduced.
|
||||
/// Used when type-checking protocol conformances, since conforming to a
|
||||
@@ -57,6 +57,20 @@ enum class DeclAvailabilityFlag : uint8_t {
|
||||
};
|
||||
using DeclAvailabilityFlags = OptionSet<DeclAvailabilityFlag>;
|
||||
|
||||
/// Diagnose uses of unavailable declarations in expressions.
|
||||
void diagAvailability(const Expr *E, DeclContext *DC);
|
||||
|
||||
/// Diagnose uses of unavailable declarations in statements (via patterns, etc),
|
||||
/// without walking into expressions.
|
||||
void diagAvailability(const Stmt *S, DeclContext *DC);
|
||||
|
||||
/// Diagnose uses of unavailable declarations in types.
|
||||
bool diagnoseTypeReprAvailability(const TypeRepr *T, DeclContext *DC,
|
||||
DeclAvailabilityFlags flags = None);
|
||||
|
||||
/// Diagnose uses of unavailable conformances in types.
|
||||
void diagnoseTypeAvailability(Type T, SourceLoc loc, DeclContext *DC);
|
||||
|
||||
/// Run the Availability-diagnostics algorithm otherwise used in an expr
|
||||
/// context, but for non-expr contexts such as TypeDecls referenced from
|
||||
/// TypeReprs.
|
||||
|
||||
@@ -254,7 +254,7 @@ public:
|
||||
}
|
||||
|
||||
std::pair<bool, Stmt *> walkToStmtPre(Stmt *stmt) override {
|
||||
performStmtDiagnostics(dcStack.back()->getASTContext(), stmt);
|
||||
performStmtDiagnostics(stmt, dcStack.back());
|
||||
return {true, stmt};
|
||||
}
|
||||
|
||||
|
||||
@@ -677,7 +677,7 @@ public:
|
||||
if (S2 == nullptr)
|
||||
return true;
|
||||
S = S2;
|
||||
performStmtDiagnostics(getASTContext(), S);
|
||||
performStmtDiagnostics(S, DC);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -1598,26 +1598,6 @@ resolveIdentTypeComponent(TypeResolution resolution,
|
||||
comp);
|
||||
}
|
||||
|
||||
static bool diagnoseAvailability(IdentTypeRepr *IdType,
|
||||
DeclContext *DC,
|
||||
bool AllowPotentiallyUnavailableProtocol) {
|
||||
DeclAvailabilityFlags flags =
|
||||
DeclAvailabilityFlag::ContinueOnPotentialUnavailability;
|
||||
if (AllowPotentiallyUnavailableProtocol)
|
||||
flags |= DeclAvailabilityFlag::AllowPotentiallyUnavailableProtocol;
|
||||
auto componentRange = IdType->getComponentRange();
|
||||
for (auto comp : componentRange) {
|
||||
if (auto *typeDecl = comp->getBoundDecl()) {
|
||||
if (diagnoseDeclAvailability(typeDecl, DC,
|
||||
comp->getNameLoc().getSourceRange(), flags)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Hack to apply context-specific @escaping to an AST function type.
|
||||
static Type applyNonEscapingIfNecessary(Type ty,
|
||||
TypeResolutionOptions options) {
|
||||
@@ -3331,24 +3311,6 @@ Type TypeResolver::resolveIdentifierType(IdentTypeRepr *IdType,
|
||||
if (result->is<FunctionType>())
|
||||
result = applyNonEscapingIfNecessary(result, options);
|
||||
|
||||
// Check the availability of the type.
|
||||
|
||||
// We allow a type to conform to a protocol that is less available than
|
||||
// the type itself. This enables a type to retroactively model or directly
|
||||
// conform to a protocol only available on newer OSes and yet still be used on
|
||||
// older OSes.
|
||||
// To support this, inside inheritance clauses we allow references to
|
||||
// protocols that are unavailable in the current type refinement context.
|
||||
|
||||
if (!options.contains(TypeResolutionFlags::SilenceErrors) &&
|
||||
!options.contains(TypeResolutionFlags::AllowUnavailable) &&
|
||||
diagnoseAvailability(
|
||||
IdType, getDeclContext(),
|
||||
options.contains(TypeResolutionFlags::AllowUnavailableProtocol))) {
|
||||
Components.back()->setInvalid();
|
||||
return ErrorType::get(getASTContext());
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ __attribute__((objc_root_class))
|
||||
|
||||
__attribute__((objc_root_class))
|
||||
@interface Base
|
||||
-(nonnull instancetype)init;
|
||||
@end
|
||||
|
||||
@interface B : A
|
||||
|
||||
@@ -107,6 +107,7 @@ func testRenamedTopLevelDiags() {
|
||||
// CHECK-DIAGS-4-NOT: versioned.swift:[[@LINE-1]]:
|
||||
_ = s.value
|
||||
// CHECK-DIAGS-4-NOT: versioned.swift:[[@LINE-1]]:
|
||||
_ = t
|
||||
}
|
||||
|
||||
func testAKA(structValue: ImportantCStruct, aliasValue: ImportantCAlias) {
|
||||
|
||||
@@ -10,91 +10,91 @@ import Foundation
|
||||
// wrapper types with nestest values.
|
||||
@available(macOS 10.11, *)
|
||||
func testNestingRenames() {
|
||||
let _ = SCNGeometrySourceSemantic
|
||||
let _ = SCNGeometrySourceSemantic.self
|
||||
// expected-error@-1{{'SCNGeometrySourceSemantic' has been renamed to 'SCNGeometrySource.Semantic'}}
|
||||
let _ = SCNLightType
|
||||
let _ = SCNLightType.self
|
||||
// expected-error@-1{{'SCNLightType' has been renamed to 'SCNLight.LightType'}}
|
||||
let _ = SCNLightingModel
|
||||
let _ = SCNLightingModel.self
|
||||
// expected-error@-1{{'SCNLightingModel' has been renamed to 'SCNMaterial.LightingModel'}}
|
||||
let _ = SCNParticleProperty
|
||||
let _ = SCNParticleProperty.self
|
||||
// expected-error@-1{{'SCNParticleProperty' has been renamed to 'SCNParticleSystem.ParticleProperty'}}
|
||||
let _ = SCNPhysicsShapeOption
|
||||
let _ = SCNPhysicsShapeOption.self
|
||||
// expected-error@-1{{'SCNPhysicsShapeOption' has been renamed to 'SCNPhysicsShape.Option'}}
|
||||
let _ = SCNPhysicsShapeType
|
||||
let _ = SCNPhysicsShapeType.self
|
||||
// expected-error@-1{{'SCNPhysicsShapeType' has been renamed to 'SCNPhysicsShape.ShapeType'}}
|
||||
let _ = SCNPhysicsTestOption
|
||||
let _ = SCNPhysicsTestOption.self
|
||||
// expected-error@-1{{'SCNPhysicsTestOption' has been renamed to 'SCNPhysicsWorld.TestOption'}}
|
||||
let _ = SCNPhysicsTestSearchMode
|
||||
let _ = SCNPhysicsTestSearchMode.self
|
||||
// expected-error@-1{{'SCNPhysicsTestSearchMode' has been renamed to 'SCNPhysicsWorld.TestSearchMode'}}
|
||||
let _ = SCNSceneAttribute
|
||||
let _ = SCNSceneAttribute.self
|
||||
// expected-error@-1{{'SCNSceneAttribute' has been renamed to 'SCNScene.Attribute'}}
|
||||
let _ = SCNSceneSourceAnimationImportPolicy
|
||||
let _ = SCNSceneSourceAnimationImportPolicy.self
|
||||
// expected-error@-1{{'SCNSceneSourceAnimationImportPolicy' has been renamed to 'SCNSceneSource.AnimationImportPolicy'}}
|
||||
let _ = SCNSceneSourceLoadingOption
|
||||
let _ = SCNSceneSourceLoadingOption.self
|
||||
// expected-error@-1{{'SCNSceneSourceLoadingOption' has been renamed to 'SCNSceneSource.LoadingOption'}}
|
||||
let _ = SCNViewOption
|
||||
let _ = SCNViewOption.self
|
||||
// expected-error@-1{{'SCNViewOption' has been renamed to 'SCNView.Option'}}
|
||||
let _ = SCNHitTestFirstFoundOnlyKey
|
||||
let _ = SCNHitTestFirstFoundOnlyKey.self
|
||||
// expected-error@-1{{'SCNHitTestFirstFoundOnlyKey' has been renamed to 'SCNHitTestOption.firstFoundOnly'}}
|
||||
let _ = SCNHitTestSortResultsKey
|
||||
let _ = SCNHitTestSortResultsKey.self
|
||||
// expected-error@-1{{'SCNHitTestSortResultsKey' has been renamed to 'SCNHitTestOption.sortResults'}}
|
||||
let _ = SCNHitTestClipToZRangeKey
|
||||
let _ = SCNHitTestClipToZRangeKey.self
|
||||
// expected-error@-1{{'SCNHitTestClipToZRangeKey' has been renamed to 'SCNHitTestOption.clipToZRange'}}
|
||||
let _ = SCNHitTestBackFaceCullingKey
|
||||
let _ = SCNHitTestBackFaceCullingKey.self
|
||||
// expected-error@-1{{'SCNHitTestBackFaceCullingKey' has been renamed to 'SCNHitTestOption.backFaceCulling'}}
|
||||
let _ = SCNHitTestBoundingBoxOnlyKey
|
||||
let _ = SCNHitTestBoundingBoxOnlyKey.self
|
||||
// expected-error@-1{{'SCNHitTestBoundingBoxOnlyKey' has been renamed to 'SCNHitTestOption.boundingBoxOnly'}}
|
||||
let _ = SCNHitTestIgnoreChildNodesKey
|
||||
let _ = SCNHitTestIgnoreChildNodesKey.self
|
||||
// expected-error@-1{{'SCNHitTestIgnoreChildNodesKey' has been renamed to 'SCNHitTestOption.ignoreChildNodes'}}
|
||||
let _ = SCNHitTestRootNodeKey
|
||||
let _ = SCNHitTestRootNodeKey.self
|
||||
// expected-error@-1{{'SCNHitTestRootNodeKey' has been renamed to 'SCNHitTestOption.rootNode'}}
|
||||
let _ = SCNHitTestIgnoreHiddenNodesKey
|
||||
let _ = SCNHitTestIgnoreHiddenNodesKey.self
|
||||
// expected-error@-1{{'SCNHitTestIgnoreHiddenNodesKey' has been renamed to 'SCNHitTestOption.ignoreHiddenNodes'}}
|
||||
let _ = SCNPhysicsShapeTypeKey
|
||||
let _ = SCNPhysicsShapeTypeKey.self
|
||||
// expected-error@-1{{'SCNPhysicsShapeTypeKey' has been renamed to 'SCNPhysicsShape.Option.type'}}
|
||||
let _ = SCNPhysicsShapeKeepAsCompoundKey
|
||||
let _ = SCNPhysicsShapeKeepAsCompoundKey.self
|
||||
// expected-error@-1{{'SCNPhysicsShapeKeepAsCompoundKey' has been renamed to 'SCNPhysicsShape.Option.keepAsCompound'}}
|
||||
let _ = SCNPhysicsShapeScaleKey
|
||||
let _ = SCNPhysicsShapeScaleKey.self
|
||||
// expected-error@-1{{'SCNPhysicsShapeScaleKey' has been renamed to 'SCNPhysicsShape.Option.scale'}}
|
||||
let _ = SCNPhysicsTestCollisionBitMaskKey
|
||||
let _ = SCNPhysicsTestCollisionBitMaskKey.self
|
||||
// expected-error@-1{{'SCNPhysicsTestCollisionBitMaskKey' has been renamed to 'SCNPhysicsWorld.TestOption.collisionBitMask'}}
|
||||
let _ = SCNPhysicsTestSearchModeKey
|
||||
let _ = SCNPhysicsTestSearchModeKey.self
|
||||
// expected-error@-1{{'SCNPhysicsTestSearchModeKey' has been renamed to 'SCNPhysicsWorld.TestOption.searchMode'}}
|
||||
let _ = SCNPhysicsTestBackfaceCullingKey
|
||||
let _ = SCNPhysicsTestBackfaceCullingKey.self
|
||||
// expected-error@-1{{'SCNPhysicsTestBackfaceCullingKey' has been renamed to 'SCNPhysicsWorld.TestOption.backfaceCulling'}}
|
||||
let _ = SCNSceneStartTimeAttributeKey
|
||||
let _ = SCNSceneStartTimeAttributeKey.self
|
||||
// expected-error@-1{{'SCNSceneStartTimeAttributeKey' has been renamed to 'SCNScene.Attribute.startTime'}}
|
||||
let _ = SCNSceneEndTimeAttributeKey
|
||||
let _ = SCNSceneEndTimeAttributeKey.self
|
||||
// expected-error@-1{{'SCNSceneEndTimeAttributeKey' has been renamed to 'SCNScene.Attribute.endTime'}}
|
||||
let _ = SCNSceneFrameRateAttributeKey
|
||||
let _ = SCNSceneFrameRateAttributeKey.self
|
||||
// expected-error@-1{{'SCNSceneFrameRateAttributeKey' has been renamed to 'SCNScene.Attribute.frameRate'}}
|
||||
let _ = SCNSceneUpAxisAttributeKey
|
||||
let _ = SCNSceneUpAxisAttributeKey.self
|
||||
// expected-error@-1{{'SCNSceneUpAxisAttributeKey' has been renamed to 'SCNScene.Attribute.upAxis'}}
|
||||
let _ = SCNSceneSourceCreateNormalsIfAbsentKey
|
||||
let _ = SCNSceneSourceCreateNormalsIfAbsentKey.self
|
||||
// expected-error@-1{{'SCNSceneSourceCreateNormalsIfAbsentKey' has been renamed to 'SCNSceneSource.LoadingOption.createNormalsIfAbsent'}}
|
||||
let _ = SCNSceneSourceCheckConsistencyKey
|
||||
let _ = SCNSceneSourceCheckConsistencyKey.self
|
||||
// expected-error@-1{{'SCNSceneSourceCheckConsistencyKey' has been renamed to 'SCNSceneSource.LoadingOption.checkConsistency'}}
|
||||
let _ = SCNSceneSourceFlattenSceneKey
|
||||
let _ = SCNSceneSourceFlattenSceneKey.self
|
||||
// expected-error@-1{{'SCNSceneSourceFlattenSceneKey' has been renamed to 'SCNSceneSource.LoadingOption.flattenScene'}}
|
||||
let _ = SCNSceneSourceUseSafeModeKey
|
||||
let _ = SCNSceneSourceUseSafeModeKey.self
|
||||
// expected-error@-1{{'SCNSceneSourceUseSafeModeKey' has been renamed to 'SCNSceneSource.LoadingOption.useSafeMode'}}
|
||||
let _ = SCNSceneSourceAssetDirectoryURLsKey
|
||||
let _ = SCNSceneSourceAssetDirectoryURLsKey.self
|
||||
// expected-error@-1{{'SCNSceneSourceAssetDirectoryURLsKey' has been renamed to 'SCNSceneSource.LoadingOption.assetDirectoryURLs'}}
|
||||
let _ = SCNSceneSourceOverrideAssetURLsKey
|
||||
let _ = SCNSceneSourceOverrideAssetURLsKey.self
|
||||
// expected-error@-1{{'SCNSceneSourceOverrideAssetURLsKey' has been renamed to 'SCNSceneSource.LoadingOption.overrideAssetURLs'}}
|
||||
let _ = SCNSceneSourceStrictConformanceKey
|
||||
let _ = SCNSceneSourceStrictConformanceKey.self
|
||||
// expected-error@-1{{'SCNSceneSourceStrictConformanceKey' has been renamed to 'SCNSceneSource.LoadingOption.strictConformance'}}
|
||||
let _ = SCNSceneSourceConvertUnitsToMetersKey
|
||||
let _ = SCNSceneSourceConvertUnitsToMetersKey.self
|
||||
// expected-error@-1{{'SCNSceneSourceConvertUnitsToMetersKey' has been renamed to 'SCNSceneSource.LoadingOption.convertUnitsToMeters'}}
|
||||
let _ = SCNSceneSourceConvertToYUpKey
|
||||
let _ = SCNSceneSourceConvertToYUpKey.self
|
||||
// expected-error@-1{{'SCNSceneSourceConvertToYUpKey' has been renamed to 'SCNSceneSource.LoadingOption.convertToYUp'}}
|
||||
let _ = SCNSceneSourceAnimationImportPolicyKey
|
||||
let _ = SCNSceneSourceAnimationImportPolicyKey.self
|
||||
// expected-error@-1{{'SCNSceneSourceAnimationImportPolicyKey' has been renamed to 'SCNSceneSource.LoadingOption.animationImportPolicy'}}
|
||||
let _ = SCNPreferredRenderingAPIKey
|
||||
let _ = SCNPreferredRenderingAPIKey.self
|
||||
// expected-error@-1{{'SCNPreferredRenderingAPIKey' has been renamed to 'SCNView.Option.preferredRenderingAPI'}}
|
||||
let _ = SCNPreferredDeviceKey
|
||||
let _ = SCNPreferredDeviceKey.self
|
||||
// expected-error@-1{{'SCNPreferredDeviceKey' has been renamed to 'SCNView.Option.preferredDevice'}}
|
||||
let _ = SCNPreferLowPowerDeviceKey
|
||||
let _ = SCNPreferLowPowerDeviceKey.self
|
||||
// expected-error@-1{{'SCNPreferLowPowerDeviceKey' has been renamed to 'SCNView.Option.preferLowPowerDevice'}}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ func test() {
|
||||
|
||||
// Enum name remapping.
|
||||
var color: ColorKind = CT_red
|
||||
var color2: ColorType = CT_Red // expected-error{{'ColorType' has been renamed to 'ColorKind'}}{{15-24=ColorKind}}
|
||||
var color2: ColorType = CT_red // expected-error{{'ColorType' has been renamed to 'ColorKind'}}{{15-24=ColorKind}}
|
||||
|
||||
// Enumerator remapping.
|
||||
var excuse: HomeworkExcuse = .dogAteIt
|
||||
|
||||
@@ -103,8 +103,8 @@ func makeSureAnyObject(_: AnyObject) {}
|
||||
|
||||
#if !IRGEN
|
||||
func testUnavailableRefs() {
|
||||
var x: __PrivCFTypeRef // expected-error {{'__PrivCFTypeRef' has been renamed to '__PrivCFType'}}
|
||||
var y: __PrivCFSubRef // expected-error {{'__PrivCFSubRef' has been renamed to '__PrivCFSub'}}
|
||||
var _: __PrivCFTypeRef // expected-error {{'__PrivCFTypeRef' has been renamed to '__PrivCFType'}}
|
||||
var _: __PrivCFSubRef // expected-error {{'__PrivCFSubRef' has been renamed to '__PrivCFSub'}}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -137,6 +137,7 @@ func test_swift_unavailable() {
|
||||
NSSwiftNewUnavailableFunctionPremium() // expected-error {{'NSSwiftNewUnavailableFunctionPremium()' is unavailable in Swift: You didn't want to use it anyway.}}
|
||||
|
||||
let x: NSSwiftUnavailableStruct? = nil // expected-error {{'NSSwiftUnavailableStruct' is unavailable in Swift}}
|
||||
_ = x
|
||||
}
|
||||
|
||||
func test_CFReleaseRetainAutorelease(_ x: CFTypeRef, color: CGColor) {
|
||||
@@ -152,9 +153,9 @@ func testRedeclarations() {
|
||||
unavail2() // expected-error {{is unavailable: middle}}
|
||||
unavail3() // expected-error {{is unavailable: last}}
|
||||
|
||||
UnavailClass1.self // expected-error {{is unavailable: first}}
|
||||
UnavailClass2.self // expected-error {{is unavailable: middle}}
|
||||
UnavailClass3.self // expected-error {{is unavailable: last}}
|
||||
_ = UnavailClass1.self // expected-error {{is unavailable: first}}
|
||||
_ = UnavailClass2.self // expected-error {{is unavailable: middle}}
|
||||
_ = UnavailClass3.self // expected-error {{is unavailable: last}}
|
||||
|
||||
let _: UnavailStruct1 // expected-error {{is unavailable: first}}
|
||||
let _: UnavailStruct2 // expected-error {{is unavailable: first}}
|
||||
@@ -186,7 +187,9 @@ func test_DistributedObjects(_ o: NSObject,
|
||||
i: NSPortCoder) { // expected-error {{'NSPortCoder' is unavailable in Swift: Use NSXPCConnection instead}}
|
||||
|
||||
let ca = NSConnectionDidDieNotification // expected-error {{'NSConnectionDidDieNotification' is unavailable in Swift: Use NSXPCConnection instead}}
|
||||
_ = ca
|
||||
let cc = NSConnectionReplyMode // expected-error {{'NSConnectionReplyMode' is unavailable in Swift: Use NSXPCConnection instead}}
|
||||
_ = cc
|
||||
_ = o.classForPortCoder // expected-error {{'classForPortCoder' is unavailable in Swift: Use NSXPCConnection instead}}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,8 +8,7 @@ import ImportAsMember.A
|
||||
import AppKit
|
||||
|
||||
func testOldTypeNames() {
|
||||
var ps: NSPostingStyle? // expected-error{{'NSPostingStyle' has been renamed to 'NotificationQueue.PostingStyle'}}{{11-25=NotificationQueue.PostingStyle}}
|
||||
|
||||
let _: NSPostingStyle? // expected-error{{'NSPostingStyle' has been renamed to 'NotificationQueue.PostingStyle'}}{{10-24=NotificationQueue.PostingStyle}}
|
||||
|
||||
_ = NSPostingStyle(rawValue: 1) // expected-error{{'NSPostingStyle' has been renamed to 'NotificationQueue.PostingStyle'}}{{7-21=NotificationQueue.PostingStyle}}
|
||||
|
||||
|
||||
@@ -38,8 +38,10 @@ public struct PublicStruct : IOIProtocol, SPIProtocol { // expected-error {{cann
|
||||
public func publicInlinable() {
|
||||
spiFunc() // expected-error {{global function 'spiFunc()' is '@_spi' and cannot be referenced from an '@inlinable' function}}
|
||||
ioiFunc() // expected-error {{global function 'ioiFunc()' cannot be used in an '@inlinable' function because 'Lib' was imported implementation-only}}
|
||||
let s = SPIStruct() // expected-error {{struct 'SPIStruct' is '@_spi' and cannot be referenced from an '@inlinable' function}}
|
||||
let i = IOIStruct() // expected-error {{struct 'IOIStruct' cannot be used in an '@inlinable' function because 'Lib' was imported implementation-only}}
|
||||
let _ = SPIStruct() // expected-error {{struct 'SPIStruct' is '@_spi' and cannot be referenced from an '@inlinable' function}}
|
||||
// expected-error@-1 {{initializer 'init()' is '@_spi' and cannot be referenced from an '@inlinable' function}}
|
||||
let _ = IOIStruct() // expected-error {{struct 'IOIStruct' cannot be used in an '@inlinable' function because 'Lib' was imported implementation-only}}
|
||||
// expected-error@-1 {{initializer 'init()' cannot be used in an '@inlinable' function because 'Lib' was imported implementation-only}}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
// expected-note @-1 3 {{class 'SPIClass' is not '@usableFromInline' or public}}
|
||||
// expected-note @-2 {{class 'SPIClass' is not public}}
|
||||
public init() {}
|
||||
// expected-note@-1 2 {{initializer 'init()' is not '@usableFromInline' or public}}
|
||||
// expected-note@-2 {{initializer 'init()' is not public}}
|
||||
}
|
||||
class InternalClass {} // expected-note 2 {{type declared here}}
|
||||
private class PrivateClass {} // expected-note 2 {{type declared here}}
|
||||
@@ -32,17 +34,25 @@ public func useOfSPITypeInvalid() -> SPIClass { fatalError() } // expected-error
|
||||
func inlinable() -> SPIClass { // expected-error {{class 'SPIClass' is '@_spi' and cannot be referenced from an '@inlinable' function}}
|
||||
spiFunc() // expected-error {{global function 'spiFunc()' is '@_spi' and cannot be referenced from an '@inlinable' function}}
|
||||
_ = SPIClass() // expected-error {{class 'SPIClass' is '@_spi' and cannot be referenced from an '@inlinable' function}}
|
||||
// expected-error@-1 {{initializer 'init()' is '@_spi' and cannot be referenced from an '@inlinable' function}}
|
||||
}
|
||||
|
||||
@_spi(S) public struct SPIStruct { // expected-note 2 {{struct 'SPIStruct' is not '@usableFromInline' or public}}
|
||||
// FIXME: Misleading diagnostic here
|
||||
public init() {}
|
||||
// expected-note@-1 2 {{initializer 'init()' is not '@usableFromInline' or public}}
|
||||
}
|
||||
|
||||
@frozen public struct FrozenStruct {
|
||||
@_spi(S) public var spiInFrozen = SPIStruct() // expected-error {{struct 'SPIStruct' is '@_spi' and cannot be referenced from a property initializer in a '@frozen' type}}
|
||||
// expected-error @-1 {{stored property 'spiInFrozen' cannot be declared '@_spi' in a '@frozen' struct}}
|
||||
// expected-error@-1 {{stored property 'spiInFrozen' cannot be declared '@_spi' in a '@frozen' struct}}
|
||||
// expected-error@-2 {{cannot use struct 'SPIStruct' here; it is SPI}}
|
||||
// expected-error@-3 {{initializer 'init()' is '@_spi' and cannot be referenced from a property initializer in a '@frozen' type}}
|
||||
|
||||
var spiTypeInFrozen = SPIStruct() // expected-error {{struct 'SPIStruct' is '@_spi' and cannot be referenced from a property initializer in a '@frozen' type}}
|
||||
// expected-error@-1 {{cannot use struct 'SPIStruct' here; it is SPI}}
|
||||
// expected-error@-2 {{initializer 'init()' is '@_spi' and cannot be referenced from a property initializer in a '@frozen' type}}
|
||||
|
||||
private var spiTypeInFrozen1: SPIClass // expected-error {{cannot use class 'SPIClass' here; it is SPI}}
|
||||
}
|
||||
|
||||
@@ -98,7 +108,8 @@ public struct NestedParent {
|
||||
}
|
||||
|
||||
public func publicFuncWithDefaultValue(_ p: SPIClass = SPIClass()) {} // expected-error {{cannot use class 'SPIClass' here; it is SPI}}
|
||||
// expected-error @-1 {{class 'SPIClass' is '@_spi' and cannot be referenced from a default argument value}}
|
||||
// expected-error@-1 {{class 'SPIClass' is '@_spi' and cannot be referenced from a default argument value}}
|
||||
// expected-error@-2 {{initializer 'init()' is '@_spi' and cannot be referenced from a default argument value}}
|
||||
|
||||
@_spi(S)
|
||||
public func spiFuncWithDefaultValue(_ p: SPIClass = SPIClass()) {}
|
||||
@@ -107,6 +118,7 @@ public func spiFuncWithDefaultValue(_ p: SPIClass = SPIClass()) {}
|
||||
public func inlinablePublic() {
|
||||
spiFunc() // expected-error {{global function 'spiFunc()' is '@_spi' and cannot be referenced from an '@inlinable' function}}
|
||||
let _ = SPIClass() // expected-error {{class 'SPIClass' is '@_spi' and cannot be referenced from an '@inlinable' function}}
|
||||
// expected-error@-1 {{initializer 'init()' is '@_spi' and cannot be referenced from an '@inlinable' function}}
|
||||
}
|
||||
|
||||
@_spi(S)
|
||||
|
||||
@@ -53,15 +53,16 @@ public func publicUseOfSPI(param: SPIClass) -> SPIClass {} // expected-error 2{{
|
||||
public func publicUseOfSPI2() -> [SPIClass] {} // expected-error {{cannot use class 'SPIClass' here; it is an SPI imported from 'SPIHelper'}}
|
||||
|
||||
@inlinable
|
||||
public func inlinable() -> SPIClass { // expected-error {{class 'SPIClass' is '@_spi' and cannot be referenced from an '@inlinable' function}}
|
||||
public func inlinable1() -> SPIClass { // expected-error {{class 'SPIClass' is '@_spi' and cannot be referenced from an '@inlinable' function}}
|
||||
spiFunc() // expected-error {{global function 'spiFunc()' is '@_spi' and cannot be referenced from an '@inlinable' function}}
|
||||
_ = SPIClass() // expected-error {{class 'SPIClass' is '@_spi' and cannot be referenced from an '@inlinable' function}}
|
||||
// expected-error@-1 {{initializer 'init()' is '@_spi' and cannot be referenced from an '@inlinable' function}}
|
||||
_ = [SPIClass]() // expected-error {{class 'SPIClass' is '@_spi' and cannot be referenced from an '@inlinable' function}}
|
||||
}
|
||||
|
||||
@_spi(S)
|
||||
@inlinable
|
||||
public func inlinable() -> SPIClass {
|
||||
public func inlinable2() -> SPIClass {
|
||||
spiFunc()
|
||||
_ = SPIClass()
|
||||
_ = [SPIClass]()
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
// This file is used by Sema/availability_versions_multi.swift to
|
||||
// This file was used by Sema/availability_versions_multi.swift to
|
||||
// test that we build enough of the type refinement context as needed to
|
||||
// validate declarations when resolving declaration signatures.
|
||||
//
|
||||
// These days, we don't validate availability in secondary files at all,
|
||||
// so the test here is just to make sure we don't crash.
|
||||
//
|
||||
// This file relies on the minimum deployment target for OS X being 10.9.
|
||||
|
||||
@available(OSX, introduced: 99.52)
|
||||
@@ -18,11 +22,9 @@ class OtherIntroduced99_51 {
|
||||
_ = PrivateIntroduced99_52()
|
||||
}
|
||||
|
||||
// This method uses a 99_52 only type in its signature, so validating
|
||||
// the declaration should produce an availability error
|
||||
func returns99_52() -> OtherIntroduced99_52 { // expected-error {{'OtherIntroduced99_52' is only available in macOS 99.52 or newer}}
|
||||
// expected-note@-1 {{add @available attribute to enclosing instance method}}
|
||||
|
||||
// This method uses a 99_52 only type in its signature, but we don't
|
||||
// validate it since it comes from a secondary file.
|
||||
func returns99_52() -> OtherIntroduced99_52 {
|
||||
// Body is not type checked (by design) so no error is expected for unavailable type used in return.
|
||||
return OtherIntroduced99_52()
|
||||
}
|
||||
@@ -86,5 +88,4 @@ extension OtherIntroduced99_51 {
|
||||
class OtherIntroduced99_53 {
|
||||
}
|
||||
|
||||
var globalFromOtherOn99_52 : OtherIntroduced99_52? = nil // expected-error {{'OtherIntroduced99_52' is only available in macOS 99.52 or newer}}
|
||||
// expected-note@-1 {{add @available attribute to enclosing var}}
|
||||
var globalFromOtherOn99_52 : OtherIntroduced99_52? = nil
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
@_exported import indirects
|
||||
|
||||
public struct StructFromDirect {
|
||||
public init() {}
|
||||
public func method() {}
|
||||
public var property: Int {
|
||||
get { return 0 }
|
||||
|
||||
@@ -19,12 +19,16 @@ struct Outer {
|
||||
|
||||
func foo(x : NSUInteger) { // expected-error {{'NSUInteger' is unavailable: use 'Int' instead}}
|
||||
let y : NSUInteger = 42 // expected-error {{'NSUInteger' is unavailable: use 'Int' instead}}
|
||||
// expected-error@-1 {{cannot convert value of type 'Int' to specified type 'NSUInteger'}}
|
||||
|
||||
let z : MyModule.NSUInteger = 42 // expected-error {{'NSUInteger' is unavailable: use 'Int' instead}}
|
||||
// expected-error@-1 {{cannot convert value of type 'Int' to specified type 'NSUInteger'}}
|
||||
|
||||
let z2 : Outer.NSUInteger = 42 // expected-error {{'NSUInteger' is unavailable: use 'UInt' instead}}
|
||||
let z2 : Outer.NSUInteger = 42 // expected-error {{'NSUInteger' is unavailable: use 'UInt' instead}}
|
||||
// expected-error@-1 {{cannot convert value of type 'Int' to specified type 'Outer.NSUInteger'}}
|
||||
|
||||
let z3 : MyModule.Outer.NSUInteger = 42 // expected-error {{'NSUInteger' is unavailable: use 'UInt' instead}}
|
||||
let z3 : MyModule.Outer.NSUInteger = 42 // expected-error {{'NSUInteger' is unavailable: use 'UInt' instead}}
|
||||
// expected-error@-1 {{cannot convert value of type 'Int' to specified type 'Outer.NSUInteger'}}
|
||||
}
|
||||
|
||||
// Test preventing overrides (but allowing shadowing) of unavailable methods.
|
||||
|
||||
@@ -12,7 +12,16 @@ public struct PublicStruct {
|
||||
public typealias ObsoleteAlias = PublicStruct // expected-note * {{marked unavailable here}}
|
||||
|
||||
public let a: ObsoleteAlias.Inner? // expected-error {{'ObsoleteAlias' has been renamed to 'PublicStruct'}}
|
||||
|
||||
public let b: ObsoleteAlias.Obsolete? // expected-error {{'ObsoleteAlias' has been renamed to 'PublicStruct'}}
|
||||
// expected-error@-1 {{constant cannot be declared public because its type uses an internal type}}
|
||||
|
||||
public let c: Pair<ObsoleteAlias.Inner, PublicStruct.Obsolete>? // expected-error {{'ObsoleteAlias' has been renamed to 'PublicStruct'}}
|
||||
// expected-error@-1 {{'Obsolete' is unavailable}}
|
||||
// expected-error@-2 {{constant cannot be declared public because its type uses an internal type}}
|
||||
|
||||
public let c2: Pair<PublicStruct.Obsolete, ObsoleteAlias.Inner>? // expected-error {{'Obsolete' is unavailable}}
|
||||
// expected-error@-1 {{'ObsoleteAlias' has been renamed to 'PublicStruct'}}
|
||||
// expected-error@-2 {{constant cannot be declared public because its type uses an internal type}}
|
||||
|
||||
public let d: ObsoleteAlias? // expected-error {{'ObsoleteAlias' has been renamed to 'PublicStruct'}}
|
||||
|
||||
@@ -70,11 +70,11 @@ func genericFunctionSigilArray<T>(
|
||||
}
|
||||
|
||||
protocol P {
|
||||
associatedtype T // expected-note {{protocol requires nested type 'T'; do you want to add it?}}
|
||||
associatedtype U // expected-note {{protocol requires nested type 'U'; do you want to add it?}}
|
||||
associatedtype T
|
||||
associatedtype U
|
||||
}
|
||||
|
||||
struct S : P { // expected-error {{type 'S' does not conform to protocol 'P'}}
|
||||
struct S : P {
|
||||
typealias T = ImplicitlyUnwrappedOptional<Int> // expected-error {{'ImplicitlyUnwrappedOptional' has been renamed to 'Optional'}}{{17-44=Optional}}
|
||||
typealias U = Optional<ImplicitlyUnwrappedOptional<Int>> // expected-error {{'ImplicitlyUnwrappedOptional' has been renamed to 'Optional'}}{{26-53=Optional}}
|
||||
|
||||
|
||||
@@ -11,16 +11,18 @@
|
||||
@inlinable
|
||||
public func testStructFromIndirect() {
|
||||
_ = StructFromIndirect() // expected-error {{struct 'StructFromIndirect' cannot be used in an '@inlinable' function because 'indirects' was imported implementation-only}}
|
||||
// expected-error@-1 {{initializer 'init()' cannot be used in an '@inlinable' function because 'indirects' was imported implementation-only}}
|
||||
}
|
||||
|
||||
@inlinable
|
||||
public func testAliasFromIndirect() {
|
||||
_ = AliasFromIndirect() // expected-error {{type alias 'AliasFromIndirect' cannot be used in an '@inlinable' function because 'indirects' was imported implementation-only}}
|
||||
// expected-error@-1 {{initializer 'init()' cannot be used in an '@inlinable' function because 'indirects' was imported implementation-only}}
|
||||
}
|
||||
|
||||
@inlinable
|
||||
public func testGenericAliasFromIndirect() {
|
||||
_ = GenericAliasFromIndirect<Int>() // expected-error {{type alias 'GenericAliasFromIndirect' cannot be used in an '@inlinable' function because 'indirects' was imported implementation-only}}
|
||||
_ = GenericAliasFromIndirect<Int>.self // expected-error {{type alias 'GenericAliasFromIndirect' cannot be used in an '@inlinable' function because 'indirects' was imported implementation-only}}
|
||||
}
|
||||
|
||||
// Functions
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
@inlinable
|
||||
public func testStructFromDirect() {
|
||||
_ = StructFromDirect() // expected-error {{struct 'StructFromDirect' cannot be used in an '@inlinable' function because 'directs' was imported implementation-only}}
|
||||
// expected-error@-1 {{initializer 'init()' cannot be used in an '@inlinable' function because 'directs' was imported implementation-only}}
|
||||
}
|
||||
|
||||
@inlinable
|
||||
@@ -22,6 +23,7 @@ public func testStructFromIndirect() {
|
||||
@inlinable
|
||||
public func testAliasFromDirect() {
|
||||
_ = AliasFromDirect() // expected-error {{type alias 'AliasFromDirect' cannot be used in an '@inlinable' function because 'directs' was imported implementation-only}}
|
||||
// expected-error@-1 {{initializer 'init()' cannot be used in an '@inlinable' function because 'directs' was imported implementation-only}}
|
||||
}
|
||||
|
||||
@inlinable
|
||||
@@ -31,7 +33,7 @@ public func testAliasFromIndirect() {
|
||||
|
||||
@inlinable
|
||||
public func testGenericAliasFromDirect() {
|
||||
_ = GenericAliasFromDirect<Int>() // expected-error {{type alias 'GenericAliasFromDirect' cannot be used in an '@inlinable' function because 'directs' was imported implementation-only}}
|
||||
_ = GenericAliasFromDirect<Int>.self // expected-error {{type alias 'GenericAliasFromDirect' cannot be used in an '@inlinable' function because 'directs' was imported implementation-only}}
|
||||
}
|
||||
|
||||
@inlinable
|
||||
|
||||
@@ -12,6 +12,7 @@ import indirects
|
||||
@inlinable
|
||||
public func testStructFromDirect() {
|
||||
_ = StructFromDirect() // expected-error {{struct 'StructFromDirect' cannot be used in an '@inlinable' function because 'directs' was imported implementation-only}}
|
||||
// expected-error@-1 {{initializer 'init()' cannot be used in an '@inlinable' function because 'directs' was imported implementation-only}}
|
||||
}
|
||||
|
||||
@inlinable
|
||||
@@ -22,6 +23,7 @@ public func testStructFromIndirect() {
|
||||
@inlinable
|
||||
public func testAliasFromDirect() {
|
||||
_ = AliasFromDirect() // expected-error {{type alias 'AliasFromDirect' cannot be used in an '@inlinable' function because 'directs' was imported implementation-only}}
|
||||
// expected-error@-1 {{initializer 'init()' cannot be used in an '@inlinable' function because 'directs' was imported implementation-only}}
|
||||
}
|
||||
|
||||
@inlinable
|
||||
@@ -31,7 +33,7 @@ public func testAliasFromIndirect() {
|
||||
|
||||
@inlinable
|
||||
public func testGenericAliasFromDirect() {
|
||||
_ = GenericAliasFromDirect<Int>() // expected-error {{type alias 'GenericAliasFromDirect' cannot be used in an '@inlinable' function because 'directs' was imported implementation-only}}
|
||||
_ = GenericAliasFromDirect<Int>.self // expected-error {{type alias 'GenericAliasFromDirect' cannot be used in an '@inlinable' function because 'directs' was imported implementation-only}}
|
||||
}
|
||||
|
||||
@inlinable
|
||||
|
||||
@@ -54,8 +54,8 @@ typealias YourCollection<Element> = MyCollection<Element> // expected-note {{'Yo
|
||||
|
||||
var x : YourCollection<Int> // expected-error {{'YourCollection' has been renamed to 'MyCollection'}}{{9-23=MyCollection}}
|
||||
|
||||
var x : int // expected-error {{'int' is unavailable: oh no you don't}}
|
||||
var y : float // expected-error {{'float' has been renamed to 'Float'}}{{9-14=Float}}
|
||||
var y : int // expected-error {{'int' is unavailable: oh no you don't}}
|
||||
var z : float // expected-error {{'float' has been renamed to 'Float'}}{{9-14=Float}}
|
||||
|
||||
// Encoded message
|
||||
@available(*, unavailable, message: "This message has a double quote \"")
|
||||
|
||||
@@ -19,8 +19,10 @@ public func publicFunction() {}
|
||||
|
||||
private struct PrivateStruct {}
|
||||
// expected-note@-1 3{{struct 'PrivateStruct' is not '@usableFromInline' or public}}
|
||||
// expected-note@-2 {{initializer 'init()' is not '@usableFromInline' or public}}
|
||||
struct InternalStruct {}
|
||||
// expected-note@-1 3{{struct 'InternalStruct' is not '@usableFromInline' or public}}
|
||||
// expected-note@-2 {{initializer 'init()' is not '@usableFromInline' or public}}
|
||||
@usableFromInline struct VersionedStruct {
|
||||
@usableFromInline init() {}
|
||||
}
|
||||
@@ -75,8 +77,10 @@ public struct Struct {
|
||||
let _ = VersionedStruct()
|
||||
let _ = InternalStruct()
|
||||
// expected-error@-1 {{struct 'InternalStruct' is internal and cannot be referenced from an '@inlinable' function}}
|
||||
// expected-error@-2 {{initializer 'init()' is internal and cannot be referenced from an '@inlinable' function}}
|
||||
let _ = PrivateStruct()
|
||||
// expected-error@-1 {{struct 'PrivateStruct' is private and cannot be referenced from an '@inlinable' function}}
|
||||
// expected-error@-2 {{initializer 'init()' is private and cannot be referenced from an '@inlinable' function}}
|
||||
}
|
||||
|
||||
private func privateMethod() {}
|
||||
@@ -107,7 +111,7 @@ public struct Struct {
|
||||
private func privateInlinableMethod() {
|
||||
// expected-error@-2 {{'@inlinable' attribute can only be applied to public declarations, but 'privateInlinableMethod' is private}}
|
||||
struct Nested {}
|
||||
// OK
|
||||
// expected-error@-1 {{type 'Nested' cannot be nested inside an '@inlinable' function}}
|
||||
}
|
||||
|
||||
@inline(__always)
|
||||
@@ -143,14 +147,18 @@ enum InternalEnum {
|
||||
// expected-note@-1 2{{enum 'InternalEnum' is not '@usableFromInline' or public}}
|
||||
// expected-note@-2 {{type declared here}}
|
||||
case apple
|
||||
// expected-note@-1 {{enum case 'apple' is not '@usableFromInline' or public}}
|
||||
case orange
|
||||
// expected-note@-1 {{enum case 'orange' is not '@usableFromInline' or public}}
|
||||
}
|
||||
|
||||
@inlinable public func usesInternalEnum() {
|
||||
_ = InternalEnum.apple
|
||||
// expected-error@-1 {{enum 'InternalEnum' is internal and cannot be referenced from an '@inlinable' function}}
|
||||
// expected-error@-2 {{enum case 'apple' is internal and cannot be referenced from an '@inlinable' function}}
|
||||
let _: InternalEnum = .orange
|
||||
// expected-error@-1 {{enum 'InternalEnum' is internal and cannot be referenced from an '@inlinable' function}}
|
||||
// expected-error@-2 {{enum case 'orange' is internal and cannot be referenced from an '@inlinable' function}}
|
||||
}
|
||||
|
||||
@usableFromInline enum VersionedEnum {
|
||||
@@ -318,4 +326,4 @@ public struct PrivateInlinableCrash {
|
||||
func innerFunction3(x: () = versionedFunction()) {}
|
||||
|
||||
func innerFunction4(x: () = publicFunction()) {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -276,7 +276,7 @@ extension P10 where A == X<U> { }
|
||||
|
||||
extension P10 where A == X<Self.U> { }
|
||||
|
||||
extension P10 where V == Int { } // expected-warning 2{{'V' is deprecated: just use Int, silly}}
|
||||
extension P10 where V == Int { } // expected-warning {{'V' is deprecated: just use Int, silly}}
|
||||
// expected-warning@-1{{neither type in same-type constraint ('Self.V' (aka 'Int') or 'Int') refers to a generic parameter or associated type}}
|
||||
|
||||
// rdar://problem/36003312
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
// RUN: %target-swift-frontend -typecheck -swift-version 5 %s -verify
|
||||
|
||||
func testPopFirst() {
|
||||
var str = "abc"
|
||||
var charView: String.CharacterView // expected-error{{'CharacterView' is unavailable: Please use String directly}}
|
||||
let str = "abc"
|
||||
let charView: String.CharacterView // expected-error{{'CharacterView' is unavailable: Please use String directly}}
|
||||
_ = str.characters // expected-error{{'characters' is unavailable: Please use String directly}}
|
||||
dump(charView)
|
||||
|
||||
@@ -11,7 +11,7 @@ func testPopFirst() {
|
||||
_ = substr.characters.popFirst() // expected-error{{'characters' is unavailable: Please use Substring directly}}
|
||||
_ = substr.unicodeScalars.popFirst() // ok
|
||||
|
||||
var charSubView: Substring.CharacterView // expected-error{{'CharacterView' is unavailable: Please use Substring directly}}
|
||||
let charSubView: Substring.CharacterView // expected-error{{'CharacterView' is unavailable: Please use Substring directly}}
|
||||
_ = substr.characters // expected-error{{'characters' is unavailable: Please use Substring directly}}
|
||||
dump(charSubView)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user