Skip to content

Commit 19f3320

Browse files
committed
Better handling of metatypes and operators in LegalConstExprVerifier.cpp
1 parent c63db8a commit 19f3320

File tree

2 files changed

+36
-50
lines changed

2 files changed

+36
-50
lines changed

lib/Sema/LegalConstExprVerifier.cpp

Lines changed: 28 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -157,12 +157,6 @@ checkSupportedWithSectionAttribute(const Expr *expr,
157157
while (!expressionsToCheck.empty()) {
158158
const Expr *expr = expressionsToCheck.pop_back_val();
159159

160-
// Look through IdentityExpr
161-
if (const IdentityExpr *identityExpr = dyn_cast<IdentityExpr>(expr)) {
162-
expressionsToCheck.push_back(identityExpr->getSubExpr());
163-
continue;
164-
}
165-
166160
// Tuples composed of constant expressions are allowed
167161
if (const TupleExpr *tupleExpr = dyn_cast<TupleExpr>(expr)) {
168162
for (const Expr *element : tupleExpr->getElements())
@@ -173,25 +167,24 @@ checkSupportedWithSectionAttribute(const Expr *expr,
173167
// Array literals of type InlineArray composed of constant expressions are
174168
// allowed
175169
if (const ArrayExpr *arrayExpr = dyn_cast<ArrayExpr>(expr)) {
176-
// Check if this is specifically an InlineArray type
177170
auto arrayType = arrayExpr->getType();
178-
if (arrayType && arrayType->getNominalOrBoundGenericNominal()) {
179-
auto nominal = arrayType->getNominalOrBoundGenericNominal();
180-
if (nominal->getName().str() == "InlineArray") {
181-
for (const Expr *element : arrayExpr->getElements())
182-
expressionsToCheck.push_back(element);
183-
continue;
184-
}
171+
if (arrayType && arrayType->isInlineArray()) {
172+
for (const Expr *element : arrayExpr->getElements())
173+
expressionsToCheck.push_back(element);
174+
continue;
185175
}
186176
// Non-InlineArray arrays are not allowed
187177
return std::make_pair(expr, TypeNotSupported);
188178
}
189179

190180
// Operators are not allowed in @section expressions
191-
if (isa<BinaryExpr>(expr) || isa<PrefixUnaryExpr>(expr)) {
181+
if (isa<BinaryExpr>(expr)) {
192182
return std::make_pair(expr, UnsupportedBinaryOperator);
193183
}
194-
184+
if (isa<PrefixUnaryExpr>(expr) || isa<PostfixUnaryExpr>(expr)) {
185+
return std::make_pair(expr, UnsupportedUnaryOperator);
186+
}
187+
195188
// Optionals are not allowed
196189
if (isa<InjectIntoOptionalExpr>(expr)) {
197190
return std::make_pair(expr, TypeNotSupported);
@@ -215,28 +208,6 @@ checkSupportedWithSectionAttribute(const Expr *expr,
215208
return std::make_pair(expr, TypeNotSupported);
216209
}
217210

218-
// Direct references to non-generic metatypes are allowed
219-
if (const TypeExpr *typeExpr = dyn_cast<TypeExpr>(expr)) {
220-
auto type = typeExpr->getTypeRepr();
221-
if (type) {
222-
// Check if this is a direct type reference (SomeType.self)
223-
if (auto dotSelfExpr = dyn_cast<DotSelfExpr>(expr)) {
224-
auto baseType = dotSelfExpr->getSubExpr()->getType();
225-
if (baseType && baseType->getMetatypeInstanceType()) {
226-
auto instanceType = baseType->getMetatypeInstanceType();
227-
// Check if it's non-generic and non-resilient
228-
if (auto nominal =
229-
instanceType->getNominalOrBoundGenericNominal()) {
230-
if (!nominal->isGeneric() && !nominal->isResilient()) {
231-
continue;
232-
}
233-
}
234-
}
235-
}
236-
}
237-
return std::make_pair(expr, TypeExpression);
238-
}
239-
240211
// Keypath expressions not supported in constant expressions
241212
if (isa<KeyPathExpr>(expr))
242213
return std::make_pair(expr, KeyPath);
@@ -279,29 +250,39 @@ checkSupportedWithSectionAttribute(const Expr *expr,
279250
return std::make_pair(expr, OpaqueDeclRef);
280251
}
281252

282-
// DotSelfExpr for metatype references
253+
// DotSelfExpr for metatype references (but only a direct TypeExpr inside)
283254
if (const DotSelfExpr *dotSelfExpr = dyn_cast<DotSelfExpr>(expr)) {
284-
auto baseType = dotSelfExpr->getSubExpr()->getType();
285-
if (baseType && baseType->is<MetatypeType>()) {
286-
auto instanceType = baseType->getMetatypeInstanceType();
287-
if (auto nominal = instanceType->getNominalOrBoundGenericNominal()) {
288-
// Allow non-generic, non-resilient types
289-
if (!nominal->isGeneric() && !nominal->isResilient()) {
290-
continue;
255+
if (const TypeExpr *typeExpr =
256+
dyn_cast<TypeExpr>(dotSelfExpr->getSubExpr())) {
257+
auto baseType = typeExpr->getType();
258+
if (baseType && baseType->is<MetatypeType>()) {
259+
auto instanceType = baseType->getMetatypeInstanceType();
260+
if (auto nominal = instanceType->getNominalOrBoundGenericNominal()) {
261+
// Allow non-generic, non-resilient types
262+
if (!nominal->isGeneric() && !nominal->isResilient()) {
263+
continue;
264+
}
291265
}
292266
}
293267
}
294268
return std::make_pair(expr, TypeExpression);
295269
}
296270

271+
// Look through IdentityExpr, but only after DotSelfExpr, which is also an
272+
// IdentityExpr.
273+
if (const IdentityExpr *identityExpr = dyn_cast<IdentityExpr>(expr)) {
274+
expressionsToCheck.push_back(identityExpr->getSubExpr());
275+
continue;
276+
}
277+
297278
// Function calls and constructors are not allowed
298279
if (isa<ApplyExpr>(expr))
299280
return std::make_pair(expr, Default);
300281

301282
// Anything else is not allowed
302283
return std::make_pair(expr, Default);
303284
}
304-
285+
305286
return std::nullopt;
306287
}
307288

test/ConstValues/SectionSyntactic.swift

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,13 +63,18 @@ func bar(x: Int) -> String { return "test" }
6363
struct S { }
6464
enum E { case a }
6565

66-
// metatypes - TODO
67-
@section("mysection") let metatype1 = Int.self
68-
// expected-error@-1{{type expressions not supported in a '@const' expression}}
66+
// metatypes
67+
@section("mysection") let metatype1 = Int.self // ok
6968

7069
// invalid metatype references
7170
@section("mysection") let invalidMetatype1 = Int.self.self
7271
// expected-error@-1{{type expressions not supported in a '@const' expression}}
72+
@section("mysection") let invalidMetatype2 = (1 == 1 ? Int.self : Int.self).self
73+
// expected-error@-1{{type expressions not supported in a '@const' expression}}
74+
@section("mysection") let invalidMetatype3 = Array<Int>.self // generic
75+
// expected-error@-1{{type expressions not supported in a '@const' expression}}
76+
@section("mysection") let invalidMetatype4 = Mirror.self // resilient
77+
// expected-error@-1{{type expressions not supported in a '@const' expression}}
7378

7479
// tuples
7580
@section("mysection") let tuple1 = (1, 2, 3, 2.718, true) // ok

0 commit comments

Comments
 (0)