@@ -483,49 +483,60 @@ static void checkInheritanceClause(
483
483
}
484
484
485
485
// Check for static properties that produce empty option sets
486
+ // using a rawValue initializer with a value of '0'
486
487
static void checkForEmptyOptionSet (const VarDecl *VD, TypeChecker &tc) {
488
+ // Check if property is a 'static let'
487
489
if (!VD->isStatic () || !VD->isLet ())
488
490
return ;
489
491
490
492
auto DC = VD->getDeclContext ();
491
493
494
+ // Make sure property is of same type as the type it is declared in
492
495
if (!VD->getType ()->isEqual (DC->getSelfTypeInContext ()))
493
496
return ;
494
497
498
+ // Make sure this type conforms to OptionSet
495
499
auto *optionSetProto = tc.Context .getProtocol (KnownProtocolKind::OptionSet);
496
- auto protocolConformance = ! tc.containsProtocol (
500
+ bool conformsToOptionSet = tc.containsProtocol (
497
501
DC->getSelfTypeInContext (),
498
502
optionSetProto,
499
503
DC,
500
- /* Flags*/ None);
504
+ /* Flags*/ None). hasValue () ;
501
505
502
- if (!protocolConformance )
506
+ if (!conformsToOptionSet )
503
507
return ;
504
508
505
509
auto PBD = VD->getParentPatternBinding ();
506
510
if (!PBD)
507
511
return ;
508
512
509
- for (auto entry : PBD->getPatternList ()) {
510
- if (entry.getPattern ()->getSingleVar () != VD) continue ;
511
-
512
- auto ctor = dyn_cast<CallExpr>(entry.getInit ());
513
- if (!ctor) continue ;
514
- if (!isa<ConstructorDecl>(ctor->getCalledValue ())) continue ;
515
-
516
- if (ctor->getNumArguments () != 1 ) continue ;
517
- if (ctor->getArgumentLabels ().front () != tc.Context .Id_rawValue ) continue ;
518
-
519
- auto *args = cast<TupleExpr>(ctor->getArg ());
520
- auto intArg = dyn_cast<IntegerLiteralExpr>(args->getElement (0 ));
521
- if (!intArg) continue ;
522
- if (intArg->getValue () != 0 ) continue ;
523
-
524
- auto loc = VD->getLoc ();
525
- tc.diagnose (loc, diag::option_set_zero_constant, VD->getName ());
526
- tc.diagnose (loc, diag::option_set_empty_set_init)
527
- .fixItReplace (args->getSourceRange (), " ([])" );
528
- }
513
+ auto entry = PBD->getPatternEntryForVarDecl (VD);
514
+
515
+ // Make sure property is being set with a constructor
516
+ auto ctor = dyn_cast<CallExpr>(entry.getInit ());
517
+ if (!ctor)
518
+ return ;
519
+ if (!isa<ConstructorDecl>(ctor->getCalledValue ()))
520
+ return ;
521
+
522
+ // Make sure it is calling the rawValue constructor
523
+ if (ctor->getNumArguments () != 1 )
524
+ return ;
525
+ if (ctor->getArgumentLabels ().front () != tc.Context .Id_rawValue )
526
+ return ;
527
+
528
+ // Make sure the rawValue parameter is a '0' integer literal
529
+ auto *args = cast<TupleExpr>(ctor->getArg ());
530
+ auto intArg = dyn_cast<IntegerLiteralExpr>(args->getElement (0 ));
531
+ if (!intArg)
532
+ return ;
533
+ if (intArg->getValue () != 0 )
534
+ return ;
535
+
536
+ auto loc = VD->getLoc ();
537
+ tc.diagnose (loc, diag::option_set_zero_constant, VD->getName ());
538
+ tc.diagnose (loc, diag::option_set_empty_set_init)
539
+ .fixItReplace (args->getSourceRange (), " ([])" );
529
540
}
530
541
531
542
0 commit comments