@@ -1282,25 +1282,19 @@ static void diagSyntacticUseRestrictions(const Expr *E, const DeclContext *DC,
1282
1282
1283
1283
}
1284
1284
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 implicit type='Int?'
1289
- // / (declref_expr implicit decl=Optional.none)
1290
- // / (type_expr type=Int?))
1291
- // /
1292
- // / Or like this if it is any other ExpressibleByNilLiteral type:
1293
- // /
1294
- // / (nil_literal_expr)
1295
- // /
1296
- bool isTypeCheckedOptionalNil (Expr *E) {
1285
+ // / Returns true if this is a 'nil' literal
1286
+ bool isNilLiteral (Expr *E) {
1297
1287
if (dyn_cast<NilLiteralExpr>(E)) return true ;
1298
-
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) {
1299
1294
auto CE = dyn_cast<ApplyExpr>(E->getSemanticsProvidingExpr ());
1300
- if (!CE || !CE-> isImplicit () )
1295
+ if (!CE)
1301
1296
return false ;
1302
1297
1303
- // First case -- Optional.none
1304
1298
if (auto DRE = dyn_cast<DeclRefExpr>(CE->getSemanticFn ()))
1305
1299
return DRE->getDecl () == Ctx.getOptionalNoneDecl ();
1306
1300
@@ -1345,9 +1339,12 @@ static void diagSyntacticUseRestrictions(const Expr *E, const DeclContext *DC,
1345
1339
1346
1340
if (calleeName == " ==" || calleeName == " !=" ||
1347
1341
calleeName == " ===" || calleeName == " !==" ) {
1342
+ bool isTrue = calleeName == " !=" || calleeName == " !==" ;
1343
+
1344
+ // Diagnose a redundant comparison of a non-optional to a `nil` literal
1348
1345
if (((subExpr = isImplicitPromotionToOptional (lhs)) &&
1349
- isTypeCheckedOptionalNil (rhs)) ||
1350
- (isTypeCheckedOptionalNil (lhs) &&
1346
+ isNilLiteral (rhs)) ||
1347
+ (isNilLiteral (lhs) &&
1351
1348
(subExpr = isImplicitPromotionToOptional (rhs)))) {
1352
1349
bool isTrue = calleeName == " !=" || calleeName == " !==" ;
1353
1350
@@ -1357,6 +1354,19 @@ static void diagSyntacticUseRestrictions(const Expr *E, const DeclContext *DC,
1357
1354
.highlight (rhs->getSourceRange ());
1358
1355
return ;
1359
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)
1366
+ .highlight (lhs->getSourceRange ())
1367
+ .highlight (rhs->getSourceRange ());
1368
+ return ;
1369
+ }
1360
1370
}
1361
1371
}
1362
1372
};
0 commit comments