@@ -1282,19 +1282,28 @@ static void diagSyntacticUseRestrictions(const Expr *E, const DeclContext *DC,
1282
1282
1283
1283
}
1284
1284
1285
- // / Returns true if this is a 'nil' literal
1286
- bool isNilLiteral (Expr *E) {
1285
+ // / Return true if this is a 'nil' literal. This looks
1286
+ // / like this if the type is Optional<T>:
1287
+ // /
1288
+ // / (dot_syntax_call_expr type='String?'
1289
+ // / (declref_expr type='(Optional<String>.Type) -> Optional<String>'
1290
+ // / decl=Swift.(file).Optional.none function_ref=unapplied)
1291
+ // / (argument_list implicit
1292
+ // / (argument
1293
+ // / (type_expr implicit type='String?.Type' typerepr='String?'))))
1294
+ // /
1295
+ // / Or like this if it is any other ExpressibleByNilLiteral type:
1296
+ // /
1297
+ // / (nil_literal_expr)
1298
+ // /
1299
+ bool isTypeCheckedOptionalNil (Expr *E) {
1287
1300
if (dyn_cast<NilLiteralExpr>(E)) return true ;
1288
- return false ;
1289
- }
1290
-
1291
- // / Returns true if this is a expression is a reference to
1292
- // / the `Optional.none` case specifically (e.g. not `nil`).
1293
- bool isOptionalNoneCase (Expr *E) {
1301
+
1294
1302
auto CE = dyn_cast<ApplyExpr>(E->getSemanticsProvidingExpr ());
1295
1303
if (!CE)
1296
1304
return false ;
1297
1305
1306
+ // First case -- Optional.none
1298
1307
if (auto DRE = dyn_cast<DeclRefExpr>(CE->getSemanticFn ()))
1299
1308
return DRE->getDecl () == Ctx.getOptionalNoneDecl ();
1300
1309
@@ -1339,30 +1348,15 @@ static void diagSyntacticUseRestrictions(const Expr *E, const DeclContext *DC,
1339
1348
1340
1349
if (calleeName == " ==" || calleeName == " !=" ||
1341
1350
calleeName == " ===" || calleeName == " !==" ) {
1342
- bool isTrue = calleeName == " !=" || calleeName == " !==" ;
1343
-
1344
- // Diagnose a redundant comparison of a non-optional to a `nil` literal
1345
1351
if (((subExpr = isImplicitPromotionToOptional (lhs)) &&
1346
- isNilLiteral (rhs)) ||
1347
- (isNilLiteral (lhs) &&
1352
+ isTypeCheckedOptionalNil (rhs)) ||
1353
+ (isTypeCheckedOptionalNil (lhs) &&
1348
1354
(subExpr = isImplicitPromotionToOptional (rhs)))) {
1349
1355
bool isTrue = calleeName == " !=" || calleeName == " !==" ;
1356
+ bool isNilLiteral = dyn_cast<NilLiteralExpr>(lhs) || dyn_cast<NilLiteralExpr>(rhs);
1350
1357
1351
1358
Ctx.Diags .diagnose (DRE->getLoc (), diag::nonoptional_compare_to_nil,
1352
- subExpr->getType (), isTrue)
1353
- .highlight (lhs->getSourceRange ())
1354
- .highlight (rhs->getSourceRange ());
1355
- return ;
1356
- }
1357
-
1358
- // Diagnose a redundant comparison of a non-optional to the `Optional.none` case
1359
- if (((subExpr = isImplicitPromotionToOptional (lhs)) &&
1360
- isOptionalNoneCase (rhs)) ||
1361
- (isOptionalNoneCase (lhs) &&
1362
- (subExpr = isImplicitPromotionToOptional (rhs)))) {
1363
-
1364
- Ctx.Diags .diagnose (DRE->getLoc (), diag::nonoptional_compare_to_optional_none_case,
1365
- subExpr->getType (), isTrue)
1359
+ subExpr->getType (), isNilLiteral, isTrue)
1366
1360
.highlight (lhs->getSourceRange ())
1367
1361
.highlight (rhs->getSourceRange ());
1368
1362
return ;
0 commit comments