Skip to content

Commit 06e6389

Browse files
committed
ModuleInterface: consume _const keyword at var and parameter decls and keep them in textual/binary modules
This is to ensure users can start adding these annotations. Type checker supports will come in later commits. Related to pitch: https://forums.swift.org/t/pitch-compile-time-constant-values/53606 rdar://85268028
1 parent 17f1cf9 commit 06e6389

23 files changed

+184
-33
lines changed

include/swift/AST/Attr.def

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -694,6 +694,11 @@ SIMPLE_DECL_ATTR(_predatesConcurrency, PredatesConcurrency,
694694
ABIBreakingToAdd | ABIBreakingToRemove | APIBreakingToAdd | APIBreakingToRemove,
695695
125)
696696

697+
CONTEXTUAL_SIMPLE_DECL_ATTR(_const, CompileTimeConst,
698+
DeclModifier | OnParam | OnVar |
699+
ABIStableToAdd | ABIStableToRemove | APIBreakingToAdd | APIStableToRemove,
700+
126)
701+
697702
// If you're adding a new underscored attribute here, please document it in
698703
// docs/ReferenceGuides/UnderscoredAttributes.md.
699704

include/swift/AST/Decl.h

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5356,7 +5356,7 @@ class ParamDecl : public VarDecl {
53565356

53575357
TypeRepr *TyRepr = nullptr;
53585358

5359-
struct alignas(1 << DeclAlignInBits) StoredDefaultArgument {
5359+
struct alignas(1 << StoredDefaultArgumentAlignInBits) StoredDefaultArgument {
53605360
PointerUnion<Expr *, VarDecl *> DefaultArg;
53615361

53625362
/// Stores the context for the default argument as well as a bit to
@@ -5380,10 +5380,13 @@ class ParamDecl : public VarDecl {
53805380

53815381
/// Whether or not this parameter is 'isolated'.
53825382
IsIsolated = 1 << 2,
5383+
5384+
/// Whether or not this parameter is '_const'.
5385+
IsCompileTimeConst = 1 << 3,
53835386
};
53845387

53855388
/// The default value, if any, along with flags.
5386-
llvm::PointerIntPair<StoredDefaultArgument *, 3, OptionSet<Flags>>
5389+
llvm::PointerIntPair<StoredDefaultArgument *, 4, OptionSet<Flags>>
53875390
DefaultValueAndFlags;
53885391

53895392
friend class ParamSpecifierRequest;
@@ -5552,6 +5555,17 @@ class ParamDecl : public VarDecl {
55525555
: flags - Flags::IsIsolated);
55535556
}
55545557

5558+
/// Whether or not this parameter is marked with '_const'.
5559+
bool isCompileTimeConst() const {
5560+
return DefaultValueAndFlags.getInt().contains(Flags::IsCompileTimeConst);
5561+
}
5562+
5563+
void setCompileTimeConst(bool value = true) {
5564+
auto flags = DefaultValueAndFlags.getInt();
5565+
DefaultValueAndFlags.setInt(value ? flags | Flags::IsCompileTimeConst
5566+
: flags - Flags::IsCompileTimeConst);
5567+
}
5568+
55555569
/// Does this parameter reject temporary pointer conversions?
55565570
bool isNonEphemeral() const;
55575571

include/swift/AST/TypeAlignments.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ namespace swift {
7575
constexpr size_t SILFunctionAlignInBits = 2;
7676
constexpr size_t ASTContextAlignInBits = 2;
7777
constexpr size_t TypeVariableAlignInBits = 4;
78+
constexpr size_t StoredDefaultArgumentAlignInBits = 4;
7879

7980
// Well, this is the *minimum* pointer alignment; it's going to be 3 on
8081
// 64-bit targets, but that doesn't matter.

include/swift/AST/TypeRepr.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1018,6 +1018,21 @@ class IsolatedTypeRepr : public SpecifierTypeRepr {
10181018
static bool classof(const IsolatedTypeRepr *T) { return true; }
10191019
};
10201020

1021+
/// An '_const' type.
1022+
/// \code
1023+
/// x : _const Int
1024+
/// \endcode
1025+
class CompileTimeConstTypeRepr : public SpecifierTypeRepr {
1026+
public:
1027+
CompileTimeConstTypeRepr(TypeRepr *Base, SourceLoc InOutLoc)
1028+
: SpecifierTypeRepr(TypeReprKind::CompileTimeConst, Base, InOutLoc) {}
1029+
1030+
static bool classof(const TypeRepr *T) {
1031+
return T->getKind() == TypeReprKind::CompileTimeConst;
1032+
}
1033+
static bool classof(const CompileTimeConstTypeRepr *T) { return true; }
1034+
};
1035+
10211036
/// A TypeRepr for a known, fixed type.
10221037
///
10231038
/// Fixed type representations should be used sparingly, in places
@@ -1287,6 +1302,7 @@ inline bool TypeRepr::isSimple() const {
12871302
case TypeReprKind::Owned:
12881303
case TypeReprKind::Isolated:
12891304
case TypeReprKind::Placeholder:
1305+
case TypeReprKind::CompileTimeConst:
12901306
return true;
12911307
}
12921308
llvm_unreachable("bad TypeRepr kind");

include/swift/AST/TypeReprNodes.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ ABSTRACT_TYPEREPR(Specifier, TypeRepr)
6161
TYPEREPR(Shared, SpecifierTypeRepr)
6262
TYPEREPR(Owned, SpecifierTypeRepr)
6363
TYPEREPR(Isolated, SpecifierTypeRepr)
64+
TYPEREPR(CompileTimeConst, SpecifierTypeRepr)
6465
TYPEREPR(Fixed, TypeRepr)
6566
TYPEREPR(SILBox, TypeRepr)
6667
LAST_TYPEREPR(SILBox)

include/swift/AST/Types.h

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1917,7 +1917,7 @@ class TypeAliasType final
19171917
/// Provide parameter type relevant flags, i.e. variadic, autoclosure, and
19181918
/// escaping.
19191919
class ParameterTypeFlags {
1920-
enum ParameterFlags : uint8_t {
1920+
enum ParameterFlags : uint16_t {
19211921
None = 0,
19221922
Variadic = 1 << 0,
19231923
AutoClosure = 1 << 1,
@@ -1926,32 +1926,36 @@ class ParameterTypeFlags {
19261926
Ownership = 7 << OwnershipShift,
19271927
NoDerivative = 1 << 6,
19281928
Isolated = 1 << 7,
1929-
NumBits = 8
1929+
CompileTimeConst = 1 << 8,
1930+
NumBits = 9
19301931
};
19311932
OptionSet<ParameterFlags> value;
19321933
static_assert(NumBits <= 8*sizeof(OptionSet<ParameterFlags>), "overflowed");
19331934

1934-
ParameterTypeFlags(OptionSet<ParameterFlags, uint8_t> val) : value(val) {}
1935+
ParameterTypeFlags(OptionSet<ParameterFlags, uint16_t> val) : value(val) {}
19351936

19361937
public:
19371938
ParameterTypeFlags() = default;
1938-
static ParameterTypeFlags fromRaw(uint8_t raw) {
1939+
static ParameterTypeFlags fromRaw(uint16_t raw) {
19391940
return ParameterTypeFlags(OptionSet<ParameterFlags>(raw));
19401941
}
19411942

19421943
ParameterTypeFlags(bool variadic, bool autoclosure, bool nonEphemeral,
1943-
ValueOwnership ownership, bool isolated, bool noDerivative)
1944+
ValueOwnership ownership, bool isolated, bool noDerivative,
1945+
bool compileTimeConst)
19441946
: value((variadic ? Variadic : 0) | (autoclosure ? AutoClosure : 0) |
19451947
(nonEphemeral ? NonEphemeral : 0) |
19461948
uint8_t(ownership) << OwnershipShift |
19471949
(isolated ? Isolated : 0) |
1948-
(noDerivative ? NoDerivative : 0)) {}
1950+
(noDerivative ? NoDerivative : 0) |
1951+
(compileTimeConst ? CompileTimeConst : 0)){}
19491952

19501953
/// Create one from what's present in the parameter type
19511954
inline static ParameterTypeFlags
19521955
fromParameterType(Type paramTy, bool isVariadic, bool isAutoClosure,
19531956
bool isNonEphemeral, ValueOwnership ownership,
1954-
bool isolated, bool isNoDerivative);
1957+
bool isolated, bool isNoDerivative,
1958+
bool compileTimeConst);
19551959

19561960
bool isNone() const { return !value; }
19571961
bool isVariadic() const { return value.contains(Variadic); }
@@ -1961,6 +1965,7 @@ class ParameterTypeFlags {
19611965
bool isShared() const { return getValueOwnership() == ValueOwnership::Shared;}
19621966
bool isOwned() const { return getValueOwnership() == ValueOwnership::Owned; }
19631967
bool isIsolated() const { return value.contains(Isolated); }
1968+
bool isCompileTimeConst() const { return value.contains(CompileTimeConst); }
19641969
bool isNoDerivative() const { return value.contains(NoDerivative); }
19651970

19661971
ValueOwnership getValueOwnership() const {
@@ -2083,7 +2088,8 @@ class YieldTypeFlags {
20832088
return ParameterTypeFlags(/*variadic*/ false,
20842089
/*autoclosure*/ false,
20852090
/*nonEphemeral*/ false, getValueOwnership(),
2086-
/*isolated*/ false, /*noDerivative*/ false);
2091+
/*isolated*/ false, /*noDerivative*/ false,
2092+
/*compileTimeConst*/false);
20872093
}
20882094

20892095
bool operator ==(const YieldTypeFlags &other) const {
@@ -2882,6 +2888,9 @@ class AnyFunctionType : public TypeBase {
28822888
/// Whether the parameter is 'isolated'.
28832889
bool isIsolated() const { return Flags.isIsolated(); }
28842890

2891+
/// Whether the parameter is 'isCompileTimeConst'.
2892+
bool isCompileTimeConst() const { return Flags.isCompileTimeConst(); }
2893+
28852894
/// Whether the parameter is marked '@noDerivative'.
28862895
bool isNoDerivative() const { return Flags.isNoDerivative(); }
28872896

@@ -6325,7 +6334,8 @@ inline TupleTypeElt TupleTypeElt::getWithType(Type T) const {
63256334
/// Create one from what's present in the parameter decl and type
63266335
inline ParameterTypeFlags ParameterTypeFlags::fromParameterType(
63276336
Type paramTy, bool isVariadic, bool isAutoClosure, bool isNonEphemeral,
6328-
ValueOwnership ownership, bool isolated, bool isNoDerivative) {
6337+
ValueOwnership ownership, bool isolated, bool isNoDerivative,
6338+
bool compileTimeConst) {
63296339
// FIXME(Remove InOut): The last caller that needs this is argument
63306340
// decomposition. Start by enabling the assertion there and fixing up those
63316341
// callers, then remove this, then remove
@@ -6336,7 +6346,7 @@ inline ParameterTypeFlags ParameterTypeFlags::fromParameterType(
63366346
ownership = ValueOwnership::InOut;
63376347
}
63386348
return {isVariadic, isAutoClosure, isNonEphemeral, ownership, isolated,
6339-
isNoDerivative};
6349+
isNoDerivative, compileTimeConst};
63406350
}
63416351

63426352
inline const Type *BoundGenericType::getTrailingObjectsPointer() const {

include/swift/Parse/Parser.h

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1109,20 +1109,23 @@ class Parser {
11091109
ParserStatus parseTypeAttributeList(ParamDecl::Specifier &Specifier,
11101110
SourceLoc &SpecifierLoc,
11111111
SourceLoc &IsolatedLoc,
1112+
SourceLoc &ConstLoc,
11121113
TypeAttributes &Attributes) {
11131114
if (Tok.isAny(tok::at_sign, tok::kw_inout) ||
11141115
(Tok.is(tok::identifier) &&
11151116
(Tok.getRawText().equals("__shared") ||
11161117
Tok.getRawText().equals("__owned") ||
1117-
Tok.isContextualKeyword("isolated"))))
1118+
Tok.isContextualKeyword("isolated") ||
1119+
Tok.isContextualKeyword("_const"))))
11181120
return parseTypeAttributeListPresent(
1119-
Specifier, SpecifierLoc, IsolatedLoc, Attributes);
1121+
Specifier, SpecifierLoc, IsolatedLoc, ConstLoc, Attributes);
11201122
return makeParserSuccess();
11211123
}
11221124

11231125
ParserStatus parseTypeAttributeListPresent(ParamDecl::Specifier &Specifier,
11241126
SourceLoc &SpecifierLoc,
11251127
SourceLoc &IsolatedLoc,
1128+
SourceLoc &ConstLoc,
11261129
TypeAttributes &Attributes);
11271130

11281131
bool parseConventionAttributeInternal(bool justChecking,
@@ -1300,7 +1303,8 @@ class Parser {
13001303
TypeRepr *applyAttributeToType(TypeRepr *Ty, const TypeAttributes &Attr,
13011304
ParamDecl::Specifier Specifier,
13021305
SourceLoc SpecifierLoc,
1303-
SourceLoc IsolatedLoc);
1306+
SourceLoc IsolatedLoc,
1307+
SourceLoc ConstLoc);
13041308

13051309
//===--------------------------------------------------------------------===//
13061310
// Pattern Parsing
@@ -1362,6 +1366,9 @@ class Parser {
13621366
/// The location of the 'isolated' keyword, if present.
13631367
SourceLoc IsolatedLoc;
13641368

1369+
/// The location of the '_const' keyword, if present.
1370+
SourceLoc CompileConstLoc;
1371+
13651372
/// The type following the ':'.
13661373
TypeRepr *Type = nullptr;
13671374

lib/AST/ASTDumper.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3059,6 +3059,12 @@ class PrintTypeRepr : public TypeReprVisitor<PrintTypeRepr> {
30593059
PrintWithColorRAII(OS, ParenthesisColor) << ')';
30603060
}
30613061

3062+
void visitCompileTimeConstTypeRepr(CompileTimeConstTypeRepr *T) {
3063+
printCommon("_const") << '\n';
3064+
printRec(T->getBase());
3065+
PrintWithColorRAII(OS, ParenthesisColor) << ')';
3066+
}
3067+
30623068
void visitOptionalTypeRepr(OptionalTypeRepr *T) {
30633069
printCommon("type_optional") << '\n';
30643070
printRec(T->getBase());

lib/AST/ASTPrinter.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3309,6 +3309,9 @@ static void printParameterFlags(ASTPrinter &printer,
33093309

33103310
if (!options.excludeAttrKind(TAK_escaping) && escaping)
33113311
printer.printKeyword("@escaping", options, " ");
3312+
3313+
if (flags.isCompileTimeConst())
3314+
printer.printKeyword("_const", options, " ");
33123315
}
33133316

33143317
void PrintAST::visitVarDecl(VarDecl *decl) {

lib/AST/ASTWalker.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1842,6 +1842,10 @@ bool Traversal::visitIsolatedTypeRepr(IsolatedTypeRepr *T) {
18421842
return doIt(T->getBase());
18431843
}
18441844

1845+
bool Traversal::visitCompileTimeConstTypeRepr(CompileTimeConstTypeRepr *T) {
1846+
return doIt(T->getBase());
1847+
}
1848+
18451849
bool Traversal::visitOpaqueReturnTypeRepr(OpaqueReturnTypeRepr *T) {
18461850
return doIt(T->getConstraint());
18471851
}

0 commit comments

Comments
 (0)