mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
API checker: only diagnose adding enum cases to exhaustive enums
Adding new cases to a non-exhaustive enum type isn't source-breaking since it only triggers a warning. rdar://63464929
This commit is contained in:
@@ -132,6 +132,7 @@ KEY_BOOL(HasStorage, hasStorage)
|
||||
KEY_BOOL(ReqNewWitnessTableEntry, reqNewWitnessTableEntry)
|
||||
KEY_BOOL(IsABIPlaceholder, isABIPlaceholder)
|
||||
KEY_BOOL(IsExternal, isExternal)
|
||||
KEY_BOOL(IsEnumExhaustive, isEnumExhaustive)
|
||||
KEY_BOOL(HasMissingDesignatedInitializers, hasMissingDesignatedInitializers)
|
||||
KEY_BOOL(InheritsConvenienceInitializers, inheritsConvenienceInitializers)
|
||||
|
||||
|
||||
@@ -40,6 +40,9 @@ public struct C6 {}
|
||||
@frozen
|
||||
public enum IceKind {}
|
||||
|
||||
@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)
|
||||
public enum FutureKind {}
|
||||
|
||||
public protocol P1 {}
|
||||
|
||||
public protocol P2 {}
|
||||
|
||||
@@ -40,6 +40,11 @@ public struct C6 {}
|
||||
|
||||
public enum IceKind {}
|
||||
|
||||
@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)
|
||||
public enum FutureKind {
|
||||
case FineToAdd
|
||||
}
|
||||
|
||||
public protocol P1 {}
|
||||
|
||||
public protocol P2 {}
|
||||
|
||||
@@ -615,6 +615,7 @@
|
||||
"usr": "s:4cake6NumberO",
|
||||
"moduleName": "cake",
|
||||
"enumRawTypeName": "Int",
|
||||
"isEnumExhaustive": true,
|
||||
"conformances": [
|
||||
{
|
||||
"kind": "Conformance",
|
||||
|
||||
@@ -635,6 +635,7 @@
|
||||
"usr": "s:4cake6NumberO",
|
||||
"moduleName": "cake",
|
||||
"enumRawTypeName": "Int",
|
||||
"isEnumExhaustive": true,
|
||||
"conformances": [
|
||||
{
|
||||
"kind": "Conformance",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// REQUIRES: macosx
|
||||
// REQUIRES: OS=macosx
|
||||
// RUN: %empty-directory(%t.mod)
|
||||
// RUN: %empty-directory(%t.sdk)
|
||||
// RUN: %empty-directory(%t.module-cache)
|
||||
|
||||
@@ -126,7 +126,9 @@ SDKNodeTypeAlias::SDKNodeTypeAlias(SDKNodeInitInfo Info):
|
||||
SDKNodeDeclType::SDKNodeDeclType(SDKNodeInitInfo Info):
|
||||
SDKNodeDecl(Info, SDKNodeKind::DeclType), SuperclassUsr(Info.SuperclassUsr),
|
||||
SuperclassNames(Info.SuperclassNames),
|
||||
EnumRawTypeName(Info.EnumRawTypeName), IsExternal(Info.IsExternal),
|
||||
EnumRawTypeName(Info.EnumRawTypeName),
|
||||
IsExternal(Info.IsExternal),
|
||||
IsEnumExhaustive(Info.IsEnumExhaustive),
|
||||
HasMissingDesignatedInitializers(Info.HasMissingDesignatedInitializers),
|
||||
InheritsConvenienceInitializers(Info.InheritsConvenienceInitializers) {}
|
||||
|
||||
@@ -1426,6 +1428,7 @@ SDKNodeInitInfo::SDKNodeInitInfo(SDKContext &Ctx, ValueDecl *VD)
|
||||
|
||||
// Get enum raw type name if this is an enum.
|
||||
if (auto *ED = dyn_cast<EnumDecl>(VD)) {
|
||||
IsEnumExhaustive = ED->isFormallyExhaustive(nullptr);
|
||||
if (auto RT = ED->getRawType()) {
|
||||
if (auto *D = RT->getNominalOrBoundGenericNominal()) {
|
||||
EnumRawTypeName = D->getName().str();
|
||||
@@ -1981,6 +1984,7 @@ void SDKNodeDeclType::jsonize(json::Output &out) {
|
||||
output(out, KeyKind::KK_superclassUsr, SuperclassUsr);
|
||||
output(out, KeyKind::KK_enumRawTypeName, EnumRawTypeName);
|
||||
output(out, KeyKind::KK_isExternal, IsExternal);
|
||||
output(out, KeyKind::KK_isEnumExhaustive, IsEnumExhaustive);
|
||||
output(out, KeyKind::KK_hasMissingDesignatedInitializers,
|
||||
HasMissingDesignatedInitializers);
|
||||
output(out, KeyKind::KK_inheritsConvenienceInitializers,
|
||||
|
||||
@@ -524,6 +524,7 @@ class SDKNodeDeclType: public SDKNodeDecl {
|
||||
// Check whether the type declaration is pulled from an external module so we
|
||||
// can incorporate extensions in the interested module.
|
||||
bool IsExternal;
|
||||
bool IsEnumExhaustive;
|
||||
bool HasMissingDesignatedInitializers;
|
||||
bool InheritsConvenienceInitializers;
|
||||
public:
|
||||
@@ -550,6 +551,11 @@ public:
|
||||
return EnumRawTypeName;
|
||||
}
|
||||
|
||||
bool isEnumExhaustive() const {
|
||||
assert(isEnum());
|
||||
return IsEnumExhaustive;
|
||||
}
|
||||
|
||||
bool hasMissingDesignatedInitializers() const {
|
||||
return HasMissingDesignatedInitializers;
|
||||
};
|
||||
|
||||
@@ -1216,10 +1216,12 @@ public:
|
||||
if (!Ctx.checkingABI()) {
|
||||
if (auto *Var = dyn_cast<SDKNodeDeclVar>(Right)) {
|
||||
if (Var->getDeclKind() == DeclKind::EnumElement) {
|
||||
if (Var->getParent()->getAs<SDKNodeDeclType>()->isEnumExhaustive()) {
|
||||
Var->emitDiag(Var->getLoc(), diag::enum_case_added);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
case NodeMatchReason::Removed:
|
||||
assert(!Right);
|
||||
|
||||
Reference in New Issue
Block a user