@@ -1431,55 +1431,57 @@ static LiteralExpr *getAutomaticRawValueExpr(TypeChecker &TC,
1431
1431
llvm_unreachable (" Unhandled AutomaticEnumValueKind in switch." );
1432
1432
}
1433
1433
1434
- static void checkEnumRawValues (TypeChecker &TC, EnumDecl *ED) {
1434
+ static Optional<AutomaticEnumValueKind>
1435
+ computeAutomaticEnumValueKind (TypeChecker &TC, EnumDecl *ED) {
1435
1436
Type rawTy = ED->getRawType ();
1436
- if (!rawTy) {
1437
- return ;
1438
- }
1439
-
1437
+ assert (rawTy && " Cannot compute value kind without raw type!" );
1438
+
1440
1439
if (ED->getGenericEnvironmentOfContext () != nullptr )
1441
1440
rawTy = ED->mapTypeIntoContext (rawTy);
1442
- if (rawTy->hasError ())
1443
- return ;
1444
-
1445
- AutomaticEnumValueKind valueKind;
1441
+
1446
1442
// Swift enums require that the raw type is convertible from one of the
1447
1443
// primitive literal protocols.
1448
1444
auto conformsToProtocol = [&](KnownProtocolKind protoKind) {
1449
- ProtocolDecl *proto = TC.getProtocol (ED->getLoc (), protoKind);
1450
- return TypeChecker::conformsToProtocol (rawTy, proto,
1451
- ED->getDeclContext (), None);
1445
+ ProtocolDecl *proto = TC.getProtocol (ED->getLoc (), protoKind);
1446
+ return TypeChecker::conformsToProtocol (rawTy, proto,
1447
+ ED->getDeclContext (), None);
1452
1448
};
1453
-
1449
+
1454
1450
static auto otherLiteralProtocolKinds = {
1455
1451
KnownProtocolKind::ExpressibleByFloatLiteral,
1456
1452
KnownProtocolKind::ExpressibleByUnicodeScalarLiteral,
1457
1453
KnownProtocolKind::ExpressibleByExtendedGraphemeClusterLiteral,
1458
1454
};
1459
-
1455
+
1460
1456
if (conformsToProtocol (KnownProtocolKind::ExpressibleByIntegerLiteral)) {
1461
- valueKind = AutomaticEnumValueKind::Integer;
1457
+ return AutomaticEnumValueKind::Integer;
1462
1458
} else if (conformsToProtocol (KnownProtocolKind::ExpressibleByStringLiteral)){
1463
- valueKind = AutomaticEnumValueKind::String;
1459
+ return AutomaticEnumValueKind::String;
1464
1460
} else if (std::any_of (otherLiteralProtocolKinds.begin (),
1465
1461
otherLiteralProtocolKinds.end (),
1466
1462
conformsToProtocol)) {
1467
- valueKind = AutomaticEnumValueKind::None;
1463
+ return AutomaticEnumValueKind::None;
1468
1464
} else {
1469
- TC.diagnose (ED->getInherited ().front ().getSourceRange ().Start ,
1470
- diag::raw_type_not_literal_convertible,
1471
- rawTy);
1472
- ED->getInherited ().front ().setInvalidType (TC.Context );
1473
- return ;
1465
+ return None;
1474
1466
}
1467
+ }
1475
1468
1476
- // We need at least one case to have a raw value.
1477
- if (ED->getAllElements ().empty ()) {
1478
- TC.diagnose (ED->getInherited ().front ().getSourceRange ().Start ,
1479
- diag::empty_enum_raw_type);
1469
+ static void checkEnumRawValues (TypeChecker &TC, EnumDecl *ED) {
1470
+ Type rawTy = ED->getRawType ();
1471
+ if (!rawTy) {
1480
1472
return ;
1481
1473
}
1482
1474
1475
+ if (ED->getGenericEnvironmentOfContext () != nullptr )
1476
+ rawTy = ED->mapTypeIntoContext (rawTy);
1477
+ if (rawTy->hasError ())
1478
+ return ;
1479
+
1480
+ // If we don't have a value kind, the decl checker will provide a diagnostic.
1481
+ auto valueKind = computeAutomaticEnumValueKind (TC, ED);
1482
+ if (!valueKind.hasValue ())
1483
+ return ;
1484
+
1483
1485
// Check the raw values of the cases.
1484
1486
LiteralExpr *prevValue = nullptr ;
1485
1487
EnumElementDecl *lastExplicitValueElt = nullptr ;
@@ -1499,24 +1501,14 @@ static void checkEnumRawValues(TypeChecker &TC, EnumDecl *ED) {
1499
1501
(void )elt->getInterfaceType ();
1500
1502
if (elt->isInvalid ())
1501
1503
continue ;
1502
-
1503
- // We don't yet support raw values on payload cases.
1504
- if (elt->hasAssociatedValues ()) {
1505
- TC.diagnose (elt->getLoc (),
1506
- diag::enum_with_raw_type_case_with_argument);
1507
- TC.diagnose (ED->getInherited ().front ().getSourceRange ().Start ,
1508
- diag::enum_raw_type_here, rawTy);
1509
- elt->setInvalid ();
1510
- continue ;
1511
- }
1512
1504
1513
1505
if (elt->hasRawValueExpr ()) {
1514
1506
lastExplicitValueElt = elt;
1515
1507
} else {
1516
1508
// If the enum element has no explicit raw value, try to
1517
1509
// autoincrement from the previous value, or start from zero if this
1518
1510
// is the first element.
1519
- auto nextValue = getAutomaticRawValueExpr (TC, valueKind, elt, prevValue);
1511
+ auto nextValue = getAutomaticRawValueExpr (TC, * valueKind, elt, prevValue);
1520
1512
if (!nextValue) {
1521
1513
elt->setInvalid ();
1522
1514
break ;
@@ -2611,11 +2603,26 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
2611
2603
checkAccessControl (TC, ED);
2612
2604
2613
2605
TC.checkPatternBindingCaptures (ED);
2614
-
2615
- if (ED->hasRawType () && !ED->isObjC ()) {
2606
+
2607
+ if (auto rawTy = ED->getRawType ()) {
2608
+ // The raw type must be one of the blessed literal convertible types.
2609
+ if (!computeAutomaticEnumValueKind (TC, ED)) {
2610
+ TC.diagnose (ED->getInherited ().front ().getSourceRange ().Start ,
2611
+ diag::raw_type_not_literal_convertible,
2612
+ rawTy);
2613
+ ED->getInherited ().front ().setInvalidType (TC.Context );
2614
+ }
2615
+
2616
+ // We need at least one case to have a raw value.
2617
+ if (ED->getAllElements ().empty ()) {
2618
+ TC.diagnose (ED->getInherited ().front ().getSourceRange ().Start ,
2619
+ diag::empty_enum_raw_type);
2620
+ }
2621
+
2616
2622
// ObjC enums have already had their raw values checked, but pure Swift
2617
2623
// enums haven't.
2618
- checkEnumRawValues (TC, ED);
2624
+ if (!ED->isObjC ())
2625
+ checkEnumRawValues (TC, ED);
2619
2626
}
2620
2627
2621
2628
checkExplicitAvailability (ED);
@@ -3089,6 +3096,7 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
3089
3096
3090
3097
void visitEnumElementDecl (EnumElementDecl *EED) {
3091
3098
(void )EED->getInterfaceType ();
3099
+ auto *ED = EED->getParentEnum ();
3092
3100
3093
3101
TC.checkDeclAttributes (EED);
3094
3102
@@ -3097,8 +3105,19 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
3097
3105
checkDefaultArguments (TC, PL, EED);
3098
3106
}
3099
3107
3108
+ // We don't yet support raw values on payload cases.
3109
+ if (EED->hasAssociatedValues ()) {
3110
+ if (auto rawTy = ED->getRawType ()) {
3111
+ TC.diagnose (EED->getLoc (),
3112
+ diag::enum_with_raw_type_case_with_argument);
3113
+ TC.diagnose (ED->getInherited ().front ().getSourceRange ().Start ,
3114
+ diag::enum_raw_type_here, rawTy);
3115
+ EED->setInvalid ();
3116
+ }
3117
+ }
3118
+
3100
3119
// Yell if our parent doesn't have a raw type but we have a raw value.
3101
- if (! EED->getParentEnum ()-> hasRawType () && EED-> hasRawValueExpr ()) {
3120
+ if (EED->hasRawValueExpr () && !ED-> hasRawType ()) {
3102
3121
TC.diagnose (EED->getRawValueExpr ()->getLoc (),
3103
3122
diag::enum_raw_value_without_raw_type);
3104
3123
EED->setInvalid ();
0 commit comments