Skip to content

Commit 1c3ac86

Browse files
committed
AST: Banish OptionalTypeKind to ClangImporter.h
The only place this was used in Decl.h was the failability kind of a constructor. I decided to replace this with a boolean isFailable() bit. Now that we have isImplicitlyUnwrappedOptional(), it seems to make more sense to not have ConstructorDecl represent redundant information which might not be internally consistent. Most callers of getFailability() actually only care if the result is failable or not; the few callers that care about it being IUO can check isImplicitlyUnwrappedOptional() as well.
1 parent 19d283d commit 1c3ac86

30 files changed

+125
-189
lines changed

include/swift/AST/Decl.h

Lines changed: 7 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -456,16 +456,16 @@ class alignas(1 << DeclAlignInBits) Decl {
456456
IsTransparentComputed : 1
457457
);
458458

459-
SWIFT_INLINE_BITFIELD(ConstructorDecl, AbstractFunctionDecl, 3+2+1,
459+
SWIFT_INLINE_BITFIELD(ConstructorDecl, AbstractFunctionDecl, 3+1+1,
460460
/// The body initialization kind (+1), or zero if not yet computed.
461461
///
462462
/// This value is cached but is not serialized, because it is a property
463463
/// of the definition of the constructor that is useful only to semantic
464464
/// analysis and SIL generation.
465465
ComputedBodyInitKind : 3,
466466

467-
/// The failability of this initializer, which is an OptionalTypeKind.
468-
Failability : 2,
467+
/// Whether this constructor can fail, by building an Optional type.
468+
Failable : 1,
469469

470470
/// Whether this initializer is a stub placed into a subclass to
471471
/// catch invalid delegations to a designated initializer not
@@ -3220,19 +3220,6 @@ class AssociatedTypeDecl : public AbstractTypeParamDecl {
32203220

32213221
class MemberLookupTable;
32223222
class ConformanceLookupTable;
3223-
3224-
/// Kinds of optional types.
3225-
enum OptionalTypeKind : unsigned {
3226-
/// The type is not an optional type.
3227-
OTK_None = 0,
3228-
3229-
/// The type is Optional<T>.
3230-
OTK_Optional,
3231-
3232-
/// The type is ImplicitlyUnwrappedOptional<T>.
3233-
OTK_ImplicitlyUnwrappedOptional
3234-
};
3235-
enum { NumOptionalTypeKinds = 2 };
32363223

32373224
// Kinds of pointer types.
32383225
enum PointerTypeKind : unsigned {
@@ -6517,7 +6504,7 @@ class ConstructorDecl : public AbstractFunctionDecl {
65176504

65186505
public:
65196506
ConstructorDecl(DeclName Name, SourceLoc ConstructorLoc,
6520-
OptionalTypeKind Failability, SourceLoc FailabilityLoc,
6507+
bool Failable, SourceLoc FailabilityLoc,
65216508
bool Throws, SourceLoc ThrowsLoc,
65226509
ParameterList *BodyParams,
65236510
GenericParamList *GenericParams,
@@ -6617,9 +6604,9 @@ class ConstructorDecl : public AbstractFunctionDecl {
66176604
llvm_unreachable("bad CtorInitializerKind");
66186605
}
66196606

6620-
/// Determine the failability of the initializer.
6621-
OptionalTypeKind getFailability() const {
6622-
return static_cast<OptionalTypeKind>(Bits.ConstructorDecl.Failability);
6607+
/// Determine if this is a failable initializer.
6608+
bool isFailable() const {
6609+
return Bits.ConstructorDecl.Failable;
66236610
}
66246611

66256612
/// Retrieve the location of the '!' or '?' in a failable initializer.

include/swift/ClangImporter/ClangImporter.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,19 @@ class TypeDecl;
6060
class VisibleDeclConsumer;
6161
enum class SelectorSplitKind;
6262

63+
/// Kinds of optional types.
64+
enum OptionalTypeKind : unsigned {
65+
/// The type is not an optional type.
66+
OTK_None = 0,
67+
68+
/// The type is Optional<T>.
69+
OTK_Optional,
70+
71+
/// The type is ImplicitlyUnwrappedOptional<T>.
72+
OTK_ImplicitlyUnwrappedOptional
73+
};
74+
enum { NumOptionalTypeKinds = 2 };
75+
6376
/// This interface is implemented by LLDB to serve as a fallback when Clang
6477
/// modules can't be imported from source in the debugger.
6578
///

include/swift/Serialization/ModuleFormat.h

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ const uint16_t SWIFTMODULE_VERSION_MAJOR = 0;
5252
/// describe what change you made. The content of this comment isn't important;
5353
/// it just ensures a conflict if two people change the module format.
5454
/// Don't worry about adhering to the 80-column limit for this line.
55-
const uint16_t SWIFTMODULE_VERSION_MINOR = 510; // serialize isIUO bit on ValueDecls
55+
const uint16_t SWIFTMODULE_VERSION_MINOR = 511; // ctor failability change
5656

5757
using DeclIDField = BCFixed<31>;
5858

@@ -409,15 +409,6 @@ enum class AccessLevel : uint8_t {
409409
};
410410
using AccessLevelField = BCFixed<3>;
411411

412-
// These IDs must \em not be renumbered or reordered without incrementing
413-
// the module version.
414-
enum class OptionalTypeKind : uint8_t {
415-
None,
416-
Optional,
417-
ImplicitlyUnwrappedOptional
418-
};
419-
using OptionalTypeKindField = BCFixed<2>;
420-
421412
// These IDs must \em not be renumbered or reordered without incrementing
422413
// the module version.
423414
enum class DeclNameKind: uint8_t {
@@ -1019,7 +1010,8 @@ namespace decls_block {
10191010
using ConstructorLayout = BCRecordLayout<
10201011
CONSTRUCTOR_DECL,
10211012
DeclContextIDField, // context decl
1022-
OptionalTypeKindField, // failability
1013+
BCFixed<1>, // failable?
1014+
BCFixed<1>, // IUO result?
10231015
BCFixed<1>, // implicit?
10241016
BCFixed<1>, // objc?
10251017
BCFixed<1>, // stub implementation?

lib/AST/ASTDumper.cpp

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -370,15 +370,6 @@ static StringRef getCtorInitializerKindString(CtorInitializerKind value) {
370370

371371
llvm_unreachable("Unhandled CtorInitializerKind in switch.");
372372
}
373-
static StringRef getOptionalTypeKindString(OptionalTypeKind value) {
374-
switch (value) {
375-
case OTK_None: return "none";
376-
case OTK_Optional: return "Optional";
377-
case OTK_ImplicitlyUnwrappedOptional: return "ImplicitlyUnwrappedOptional";
378-
}
379-
380-
llvm_unreachable("Unhandled OptionalTypeKind in switch.");
381-
}
382373
static StringRef getAssociativityString(Associativity value) {
383374
switch (value) {
384375
case Associativity::None: return "none";
@@ -1100,9 +1091,11 @@ namespace {
11001091
PrintWithColorRAII(OS, DeclModifierColor) << " required";
11011092
PrintWithColorRAII(OS, DeclModifierColor) << " "
11021093
<< getCtorInitializerKindString(CD->getInitKind());
1103-
if (CD->getFailability() != OTK_None)
1094+
if (CD->isFailable())
11041095
PrintWithColorRAII(OS, DeclModifierColor) << " failable="
1105-
<< getOptionalTypeKindString(CD->getFailability());
1096+
<< (CD->isImplicitlyUnwrappedOptional()
1097+
? "ImplicitlyUnwrappedOptional"
1098+
: "Optional");
11061099
printAbstractFunctionDecl(CD);
11071100
PrintWithColorRAII(OS, ParenthesisColor) << ')';
11081101
}

lib/AST/ASTPrinter.cpp

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3012,17 +3012,11 @@ void PrintAST::visitConstructorDecl(ConstructorDecl *decl) {
30123012
[&]{
30133013
Printer << "init";
30143014
}, [&] { // Signature
3015-
switch (decl->getFailability()) {
3016-
case OTK_None:
3017-
break;
3018-
3019-
case OTK_Optional:
3020-
Printer << "?";
3021-
break;
3022-
3023-
case OTK_ImplicitlyUnwrappedOptional:
3024-
Printer << "!";
3025-
break;
3015+
if (decl->isFailable()) {
3016+
if (decl->isImplicitlyUnwrappedOptional())
3017+
Printer << "!";
3018+
else
3019+
Printer << "?";
30263020
}
30273021

30283022
printGenericDeclGenericParams(decl);

lib/AST/ASTVerifier.cpp

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1061,7 +1061,7 @@ class Verifier : public ASTWalker {
10611061
abort();
10621062
}
10631063

1064-
if (ctor->getFailability() == OTK_None && !ctor->isInvalid()) {
1064+
if (!ctor->isFailable() && !ctor->isInvalid()) {
10651065
Out << "non-failable initializer contains a 'fail' statement\n";
10661066
ctor->dump(Out);
10671067
abort();
@@ -2950,8 +2950,9 @@ class Verifier : public ASTWalker {
29502950
if (!CD->isInvalid() &&
29512951
CD->getDeclContext()->getDeclaredInterfaceType()->getAnyNominal() !=
29522952
Ctx.getOptionalDecl()) {
2953-
bool resultIsOptional = (bool) CD->getResultInterfaceType()->getOptionalObjectType();
2954-
auto declIsOptional = CD->getFailability() != OTK_None;
2953+
bool resultIsOptional = (bool) CD->getResultInterfaceType()
2954+
->getOptionalObjectType();
2955+
auto declIsOptional = CD->isFailable();
29552956

29562957
if (resultIsOptional != declIsOptional) {
29572958
Out << "Initializer has result optionality/failability mismatch\n";
@@ -2974,26 +2975,17 @@ class Verifier : public ASTWalker {
29742975
}
29752976
}
29762977

2977-
if (CD->isImplicitlyUnwrappedOptional()) {
2978-
if (CD->getFailability() != OTK_ImplicitlyUnwrappedOptional) {
2979-
Out << "Expected IUO failability for constructor with IUO decl "
2980-
"attribute!\n";
2981-
CD->dump(llvm::errs());
2982-
abort();
2983-
}
2984-
2978+
if (CD->isFailable()) {
29852979
auto resultTy = CD->getResultInterfaceType();
2986-
29872980
if (!resultTy->getOptionalObjectType()) {
29882981
Out << "implicitly unwrapped optional attribute should only be set "
29892982
"on constructors with optional return types\n";
29902983
CD->dump(llvm::errs());
29912984
abort();
29922985
}
29932986
} else {
2994-
if (CD->getFailability() == OTK_ImplicitlyUnwrappedOptional) {
2995-
Out << "Expected IUO decl attribute for constructor with IUO "
2996-
"failability!\n";
2987+
if (CD->isImplicitlyUnwrappedOptional()) {
2988+
Out << "Expected failable constructor if result is IUO\n";
29972989
CD->dump(llvm::errs());
29982990
abort();
29992991
}

lib/AST/Decl.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6727,7 +6727,7 @@ void AbstractFunctionDecl::computeType(AnyFunctionType::ExtInfo info) {
67276727
}
67286728

67296729
// Adjust result type for failability.
6730-
if (ctor->getFailability() != OTK_None)
6730+
if (ctor->isFailable())
67316731
resultTy = OptionalType::get(resultTy);
67326732
} else {
67336733
assert(isa<DestructorDecl>(this));
@@ -7001,8 +7001,7 @@ SelfAccessKind FuncDecl::getSelfAccessKind() const {
70017001
}
70027002

70037003
ConstructorDecl::ConstructorDecl(DeclName Name, SourceLoc ConstructorLoc,
7004-
OptionalTypeKind Failability,
7005-
SourceLoc FailabilityLoc,
7004+
bool Failable, SourceLoc FailabilityLoc,
70067005
bool Throws,
70077006
SourceLoc ThrowsLoc,
70087007
ParameterList *BodyParams,
@@ -7019,7 +7018,7 @@ ConstructorDecl::ConstructorDecl(DeclName Name, SourceLoc ConstructorLoc,
70197018

70207019
Bits.ConstructorDecl.ComputedBodyInitKind = 0;
70217020
Bits.ConstructorDecl.HasStubImplementation = 0;
7022-
Bits.ConstructorDecl.Failability = static_cast<unsigned>(Failability);
7021+
Bits.ConstructorDecl.Failable = Failable;
70237022

70247023
assert(Name.getBaseName() == DeclBaseName::createConstructor());
70257024
}

lib/ClangImporter/ClangAdapter.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ class TypedefNameDecl;
4646
// TODO: pull more off of the ImportImpl
4747

4848
namespace swift {
49+
enum OptionalTypeKind : unsigned;
50+
4951
namespace importer {
5052
struct PlatformAvailability;
5153

lib/ClangImporter/ImportDecl.cpp

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -534,7 +534,7 @@ makeEnumRawValueConstructor(ClangImporter::Implementation &Impl,
534534
DeclName name(C, DeclBaseName::createConstructor(), paramPL);
535535
auto *ctorDecl =
536536
new (C) ConstructorDecl(name, enumDecl->getLoc(),
537-
OTK_Optional, /*FailabilityLoc=*/SourceLoc(),
537+
/*Failable=*/true, /*FailabilityLoc=*/SourceLoc(),
538538
/*Throws=*/false, /*ThrowsLoc=*/SourceLoc(),
539539
paramPL,
540540
/*GenericParams=*/nullptr, enumDecl);
@@ -1312,7 +1312,8 @@ createDefaultConstructor(ClangImporter::Implementation &Impl,
13121312
// Create the constructor.
13131313
DeclName name(context, DeclBaseName::createConstructor(), emptyPL);
13141314
auto constructor = new (context) ConstructorDecl(
1315-
name, structDecl->getLoc(), OTK_None, /*FailabilityLoc=*/SourceLoc(),
1315+
name, structDecl->getLoc(),
1316+
/*Failable=*/false, /*FailabilityLoc=*/SourceLoc(),
13161317
/*Throws=*/false, /*ThrowsLoc=*/SourceLoc(), emptyPL,
13171318
/*GenericParams=*/nullptr, structDecl);
13181319

@@ -1441,7 +1442,8 @@ createValueConstructor(ClangImporter::Implementation &Impl,
14411442
// Create the constructor
14421443
DeclName name(context, DeclBaseName::createConstructor(), paramList);
14431444
auto constructor = new (context) ConstructorDecl(
1444-
name, structDecl->getLoc(), OTK_None, /*FailabilityLoc=*/SourceLoc(),
1445+
name, structDecl->getLoc(),
1446+
/*Failable=*/false, /*FailabilityLoc=*/SourceLoc(),
14451447
/*Throws=*/false, /*ThrowsLoc=*/SourceLoc(), paramList,
14461448
/*GenericParams=*/nullptr, structDecl);
14471449

@@ -5745,19 +5747,21 @@ Decl *SwiftDeclConverter::importGlobalAsInitializer(
57455747
Impl.importFunctionReturnType(dc, decl, allowNSUIntegerAsInt);
57465748

57475749
// Update the failability appropriately based on the imported method type.
5748-
OptionalTypeKind initOptionality = OTK_None;
5750+
bool failable = false, isIUO = false;
57495751
if (importedType.isImplicitlyUnwrapped()) {
57505752
assert(importedType.getType()->getOptionalObjectType());
5751-
initOptionality = OTK_ImplicitlyUnwrappedOptional;
5753+
failable = true;
5754+
isIUO = true;
57525755
} else if (importedType.getType()->getOptionalObjectType()) {
5753-
initOptionality = OTK_Optional;
5756+
failable = true;
57545757
}
57555758

57565759
auto result = Impl.createDeclWithClangNode<ConstructorDecl>(
57575760
decl, AccessLevel::Public, name, /*NameLoc=*/SourceLoc(),
5758-
initOptionality, /*FailabilityLoc=*/SourceLoc(),
5761+
failable, /*FailabilityLoc=*/SourceLoc(),
57595762
/*Throws=*/false, /*ThrowsLoc=*/SourceLoc(), parameterList,
57605763
/*GenericParams=*/nullptr, dc);
5764+
result->setImplicitlyUnwrappedOptional(isIUO);
57615765
result->getASTContext().evaluator.cacheOutput(InitKindRequest{result},
57625766
std::move(initKind));
57635767
result->setImportAsStaticMember();

lib/IDE/CodeCompletion.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2697,7 +2697,8 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
26972697
if (init->shouldHideFromEditor())
26982698
continue;
26992699
if (IsUnresolvedMember &&
2700-
cast<ConstructorDecl>(init)->getFailability() == OTK_Optional) {
2700+
cast<ConstructorDecl>(init)->isFailable() &&
2701+
!cast<ConstructorDecl>(init)->isImplicitlyUnwrappedOptional()) {
27012702
continue;
27022703
}
27032704
addConstructorCall(cast<ConstructorDecl>(init), Reason,

lib/IDE/ExprContextAnalysis.cpp

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -912,13 +912,7 @@ bool swift::ide::isReferenceableByImplicitMemberExpr(
912912

913913
// Only non-failable constructors are implicitly referenceable.
914914
if (auto CD = dyn_cast<ConstructorDecl>(VD)) {
915-
switch (CD->getFailability()) {
916-
case OTK_None:
917-
case OTK_ImplicitlyUnwrappedOptional:
918-
return true;
919-
case OTK_Optional:
920-
return false;
921-
}
915+
return (!CD->isFailable() || CD->isImplicitlyUnwrappedOptional());
922916
}
923917

924918
// Otherwise, check the result type matches the contextual type.

lib/Parse/ParseDecl.cpp

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5622,7 +5622,7 @@ void Parser::parseAbstractFunctionBody(AbstractFunctionDecl *AFD) {
56225622
AFD->setHasSingleExpressionBody();
56235623
AFD->setSingleExpressionBody(E);
56245624
} else if (auto *F = dyn_cast<ConstructorDecl>(AFD)) {
5625-
if (F->getFailability() != OTK_None && isa<NilLiteralExpr>(E)) {
5625+
if (F->isFailable() && isa<NilLiteralExpr>(E)) {
56265626
// If it's a nil literal, just insert return. This is the only
56275627
// legal thing to return.
56285628
auto RS = new (Context) ReturnStmt(E->getStartLoc(), E);
@@ -6442,7 +6442,7 @@ ParserResult<ConstructorDecl>
64426442
Parser::parseDeclInit(ParseDeclOptions Flags, DeclAttributes &Attributes) {
64436443
assert(Tok.is(tok::kw_init));
64446444
SourceLoc ConstructorLoc = consumeToken();
6445-
OptionalTypeKind Failability = OTK_None;
6445+
bool Failable = false, IUO = false;
64466446
SourceLoc FailabilityLoc;
64476447

64486448
const bool ConstructorsNotAllowed = !(Flags & PD_HasContainerType);
@@ -6455,10 +6455,11 @@ Parser::parseDeclInit(ParseDeclOptions Flags, DeclAttributes &Attributes) {
64556455
// Parse the '!' or '?' for a failable initializer.
64566456
if (Tok.isAny(tok::exclaim_postfix, tok::sil_exclamation) ||
64576457
(Tok.isAnyOperator() && Tok.getText() == "!")) {
6458-
Failability = OTK_ImplicitlyUnwrappedOptional;
6458+
Failable = true;
6459+
IUO = true;
64596460
FailabilityLoc = consumeToken();
64606461
} else if (Tok.isAny(tok::question_postfix, tok::question_infix)) {
6461-
Failability = OTK_Optional;
6462+
Failable = true;
64626463
FailabilityLoc = consumeToken();
64636464
}
64646465

@@ -6509,10 +6510,11 @@ Parser::parseDeclInit(ParseDeclOptions Flags, DeclAttributes &Attributes) {
65096510

65106511
DeclName FullName(Context, DeclBaseName::createConstructor(), namePieces);
65116512
auto *CD = new (Context) ConstructorDecl(FullName, ConstructorLoc,
6512-
Failability, FailabilityLoc,
6513+
Failable, FailabilityLoc,
65136514
throwsLoc.isValid(), throwsLoc,
65146515
Params.get(), nullptr,
65156516
CurDeclContext);
6517+
CD->setImplicitlyUnwrappedOptional(IUO);
65166518
CD->getAttrs() = Attributes;
65176519

65186520
// Parse a 'where' clause if present, adding it to our GenericParamList.

lib/PrintAsObjC/PrintAsObjC.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -575,7 +575,14 @@ class ObjCPrinter : private DeclVisitor<ObjCPrinter>,
575575
if (errorConvention && errorConvention->stripsResultOptionality()) {
576576
printNullability(OTK_Optional, NullabilityPrintKind::ContextSensitive);
577577
} else if (auto ctor = dyn_cast<ConstructorDecl>(AFD)) {
578-
printNullability(ctor->getFailability(),
578+
OptionalTypeKind kind = OTK_None;
579+
if (ctor->isFailable()) {
580+
if (ctor->isImplicitlyUnwrappedOptional())
581+
kind = OTK_ImplicitlyUnwrappedOptional;
582+
else
583+
kind = OTK_Optional;
584+
}
585+
printNullability(kind,
579586
NullabilityPrintKind::ContextSensitive);
580587
} else {
581588
auto func = cast<FuncDecl>(AFD);

0 commit comments

Comments
 (0)