mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
@@ -4007,7 +4007,10 @@ WARNING(use_of_qq_on_non_optional_value,none,
|
||||
"left side of nil coalescing operator '?""?' has non-optional type %0, "
|
||||
"so the right side is never used", (Type))
|
||||
WARNING(nonoptional_compare_to_nil,none,
|
||||
"comparing non-optional value of type %0 to 'nil' or 'Optional.none' always returns"
|
||||
"comparing non-optional value of type %0 to 'nil' always returns"
|
||||
" %select{false|true}1", (Type, bool))
|
||||
WARNING(nonoptional_compare_to_optional_none_case,none,
|
||||
"comparing non-optional value of type %0 to 'Optional.none' always returns"
|
||||
" %select{false|true}1", (Type, bool))
|
||||
WARNING(optional_check_nonoptional,none,
|
||||
"non-optional expression of type %0 used in a check for optionals",
|
||||
|
||||
@@ -1282,28 +1282,19 @@ static void diagSyntacticUseRestrictions(const Expr *E, const DeclContext *DC,
|
||||
|
||||
}
|
||||
|
||||
/// Return true if this is a 'nil' literal. This looks
|
||||
/// like this if the type is Optional<T>:
|
||||
///
|
||||
/// (dot_syntax_call_expr type='String?'
|
||||
/// (declref_expr type='(Optional<String>.Type) -> Optional<String>'
|
||||
/// decl=Swift.(file).Optional.none function_ref=unapplied)
|
||||
/// (argument_list implicit
|
||||
/// (argument
|
||||
/// (type_expr implicit type='String?.Type' typerepr='String?'))))
|
||||
///
|
||||
/// Or like this if it is any other ExpressibleByNilLiteral type:
|
||||
///
|
||||
/// (nil_literal_expr)
|
||||
///
|
||||
bool isTypeCheckedOptionalNil(Expr *E) {
|
||||
/// Returns true if this is a 'nil' literal
|
||||
bool isNilLiteral(Expr *E) {
|
||||
if (dyn_cast<NilLiteralExpr>(E)) return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Returns true if this is a expression is a reference to
|
||||
/// the `Optional.none` case specifically (e.g. not `nil`).
|
||||
bool isOptionalNoneCase(Expr *E) {
|
||||
auto CE = dyn_cast<ApplyExpr>(E->getSemanticsProvidingExpr());
|
||||
if (!CE)
|
||||
return false;
|
||||
|
||||
// First case -- Optional.none
|
||||
if (auto DRE = dyn_cast<DeclRefExpr>(CE->getSemanticFn()))
|
||||
return DRE->getDecl() == Ctx.getOptionalNoneDecl();
|
||||
|
||||
@@ -1348,9 +1339,12 @@ static void diagSyntacticUseRestrictions(const Expr *E, const DeclContext *DC,
|
||||
|
||||
if (calleeName == "==" || calleeName == "!=" ||
|
||||
calleeName == "===" || calleeName == "!==") {
|
||||
bool isTrue = calleeName == "!=" || calleeName == "!==";
|
||||
|
||||
// Diagnose a redundant comparison of a non-optional to a `nil` literal
|
||||
if (((subExpr = isImplicitPromotionToOptional(lhs)) &&
|
||||
isTypeCheckedOptionalNil(rhs)) ||
|
||||
(isTypeCheckedOptionalNil(lhs) &&
|
||||
isNilLiteral(rhs)) ||
|
||||
(isNilLiteral(lhs) &&
|
||||
(subExpr = isImplicitPromotionToOptional(rhs)))) {
|
||||
bool isTrue = calleeName == "!=" || calleeName == "!==";
|
||||
|
||||
@@ -1360,6 +1354,19 @@ static void diagSyntacticUseRestrictions(const Expr *E, const DeclContext *DC,
|
||||
.highlight(rhs->getSourceRange());
|
||||
return;
|
||||
}
|
||||
|
||||
// Diagnose a redundant comparison of a non-optional to the `Optional.none` case
|
||||
if (((subExpr = isImplicitPromotionToOptional(lhs)) &&
|
||||
isOptionalNoneCase(rhs)) ||
|
||||
(isOptionalNoneCase(lhs) &&
|
||||
(subExpr = isImplicitPromotionToOptional(rhs)))) {
|
||||
|
||||
Ctx.Diags.diagnose(DRE->getLoc(), diag::nonoptional_compare_to_optional_none_case,
|
||||
subExpr->getType(), isTrue)
|
||||
.highlight(lhs->getSourceRange())
|
||||
.highlight(rhs->getSourceRange());
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -5,12 +5,12 @@ import CoreCooling
|
||||
func testSomeClass(_ sc: SomeClass, osc: SomeClass?) {
|
||||
let ao1: Any = sc.methodA(osc)
|
||||
_ = ao1
|
||||
if sc.methodA(osc) == nil { } // expected-warning {{comparing non-optional value of type 'Any' to 'nil' or 'Optional.none' always returns false}}
|
||||
if sc.methodA(osc) == Optional.none { } // expected-warning {{comparing non-optional value of type 'Any' to 'nil' or 'Optional.none' always returns false}}
|
||||
if sc.methodA(osc) == nil { } // expected-warning {{comparing non-optional value of type 'Any' to 'nil' always returns false}}
|
||||
if sc.methodA(osc) == Optional.none { } // expected-warning {{comparing non-optional value of type 'Any' to 'Optional.none' always returns false}}
|
||||
|
||||
let ao2: Any = sc.methodB(nil)
|
||||
_ = ao2
|
||||
if sc.methodA(osc) == nil { }// expected-warning {{comparing non-optional value of type 'Any' to 'nil' or 'Optional.none' always returns false}}
|
||||
if sc.methodA(osc) == nil { }// expected-warning {{comparing non-optional value of type 'Any' to 'nil' always returns false}}
|
||||
|
||||
let ao3: Any? = sc.property.flatMap { .some($0) }
|
||||
_ = ao3
|
||||
@@ -19,7 +19,7 @@ func testSomeClass(_ sc: SomeClass, osc: SomeClass?) {
|
||||
|
||||
let ao4: Any = sc.methodD()
|
||||
_ = ao4
|
||||
if sc.methodD() == nil { } // expected-warning {{comparing non-optional value of type 'Any' to 'nil' or 'Optional.none' always returns false}}
|
||||
if sc.methodD() == nil { } // expected-warning {{comparing non-optional value of type 'Any' to 'nil' always returns false}}
|
||||
|
||||
sc.methodE(sc)
|
||||
sc.methodE(osc) // expected-error{{value of optional type 'SomeClass?' must be unwrapped}}
|
||||
@@ -44,7 +44,7 @@ func testSomeClass(_ sc: SomeClass, osc: SomeClass?) {
|
||||
let sc2 = SomeClass(int: ci)
|
||||
let sc2a: SomeClass = sc2
|
||||
_ = sc2a
|
||||
if sc2 == nil { } // expected-warning {{comparing non-optional value of type 'SomeClass' to 'nil' or 'Optional.none' always returns false}}
|
||||
if sc2 == nil { } // expected-warning {{comparing non-optional value of type 'SomeClass' to 'nil' always returns false}}
|
||||
|
||||
let sc3 = SomeClass(double: 1.5)
|
||||
if sc3 == nil { } // okay
|
||||
@@ -56,7 +56,7 @@ func testSomeClass(_ sc: SomeClass, osc: SomeClass?) {
|
||||
let sc4 = sc.returnMe()
|
||||
let sc4a: SomeClass = sc4
|
||||
_ = sc4a
|
||||
if sc4 == nil { } // expected-warning {{comparing non-optional value of type 'SomeClass' to 'nil' or 'Optional.none' always returns false}}
|
||||
if sc4 == nil { } // expected-warning {{comparing non-optional value of type 'SomeClass' to 'nil' always returns false}}
|
||||
}
|
||||
|
||||
// Nullability with CF types.
|
||||
|
||||
@@ -222,7 +222,7 @@ class r20201968C {
|
||||
// <rdar://problem/21459429> QoI: Poor compilation error calling assert
|
||||
func r21459429(_ a : Int) {
|
||||
assert(a != nil, "ASSERT COMPILATION ERROR")
|
||||
// expected-warning @-1 {{comparing non-optional value of type 'Int' to 'nil' or 'Optional.none' always returns true}}
|
||||
// expected-warning @-1 {{comparing non-optional value of type 'Int' to 'nil' always returns true}}
|
||||
}
|
||||
|
||||
|
||||
@@ -537,7 +537,7 @@ func r21684487() {
|
||||
func r18397777(_ d : r21447318?) {
|
||||
let c = r21447318()
|
||||
|
||||
if c != nil { // expected-warning {{comparing non-optional value of type 'r21447318' to 'nil' or 'Optional.none' always returns true}}
|
||||
if c != nil { // expected-warning {{comparing non-optional value of type 'r21447318' to 'nil' always returns true}}
|
||||
}
|
||||
|
||||
if d { // expected-error {{optional type 'r21447318?' cannot be used as a boolean; test for '!= nil' instead}} {{6-6=(}} {{7-7= != nil)}}
|
||||
@@ -745,27 +745,27 @@ class C_44203 {
|
||||
func f(bytes : UnsafeMutablePointer<Int>, _ i : Int?) {
|
||||
_ = (i === nil) // expected-error {{value of type 'Int?' cannot be compared by reference; did you mean to compare by value?}} {{12-15===}}
|
||||
_ = (bytes === nil) // expected-error {{type 'UnsafeMutablePointer<Int>' is not optional, value can never be nil}}
|
||||
_ = (self === nil) // expected-warning {{comparing non-optional value of type 'AnyObject' to 'nil' or 'Optional.none' always returns false}}
|
||||
_ = (self === .none) // expected-warning {{comparing non-optional value of type 'AnyObject' to 'nil' or 'Optional.none' always returns false}}
|
||||
_ = (self === Optional.none) // expected-warning {{comparing non-optional value of type 'AnyObject' to 'nil' or 'Optional.none' always returns false}}
|
||||
_ = (self === nil) // expected-warning {{comparing non-optional value of type 'AnyObject' to 'nil' always returns false}}
|
||||
_ = (self === .none) // expected-warning {{comparing non-optional value of type 'AnyObject' to 'Optional.none' always returns false}}
|
||||
_ = (self === Optional.none) // expected-warning {{comparing non-optional value of type 'AnyObject' to 'Optional.none' always returns false}}
|
||||
_ = (i !== nil) // expected-error {{value of type 'Int?' cannot be compared by reference; did you mean to compare by value?}} {{12-15=!=}}
|
||||
_ = (bytes !== nil) // expected-error {{type 'UnsafeMutablePointer<Int>' is not optional, value can never be nil}}
|
||||
_ = (self !== nil) // expected-warning {{comparing non-optional value of type 'AnyObject' to 'nil' or 'Optional.none' always returns true}}
|
||||
_ = (self !== .none) // expected-warning {{comparing non-optional value of type 'AnyObject' to 'nil' or 'Optional.none' always returns true}}
|
||||
_ = (self !== Optional.none) // expected-warning {{comparing non-optional value of type 'AnyObject' to 'nil' or 'Optional.none' always returns true}}
|
||||
_ = (self !== nil) // expected-warning {{comparing non-optional value of type 'AnyObject' to 'nil' always returns true}}
|
||||
_ = (self !== .none) // expected-warning {{comparing non-optional value of type 'AnyObject' to 'Optional.none' always returns true}}
|
||||
_ = (self !== Optional.none) // expected-warning {{comparing non-optional value of type 'AnyObject' to 'Optional.none' always returns true}}
|
||||
}
|
||||
}
|
||||
|
||||
func nilComparison(i: Int, o: AnyObject) {
|
||||
_ = i == nil // expected-warning {{comparing non-optional value of type 'Int' to 'nil' or 'Optional.none' always returns false}}
|
||||
_ = nil == i // expected-warning {{comparing non-optional value of type 'Int' to 'nil' or 'Optional.none' always returns false}}
|
||||
_ = i != nil // expected-warning {{comparing non-optional value of type 'Int' to 'nil' or 'Optional.none' always returns true}}
|
||||
_ = nil != i // expected-warning {{comparing non-optional value of type 'Int' to 'nil' or 'Optional.none' always returns true}}
|
||||
_ = i == nil // expected-warning {{comparing non-optional value of type 'Int' to 'nil' always returns false}}
|
||||
_ = nil == i // expected-warning {{comparing non-optional value of type 'Int' to 'nil' always returns false}}
|
||||
_ = i != nil // expected-warning {{comparing non-optional value of type 'Int' to 'nil' always returns true}}
|
||||
_ = nil != i // expected-warning {{comparing non-optional value of type 'Int' to 'nil' always returns true}}
|
||||
|
||||
_ = i == Optional.none // expected-warning {{comparing non-optional value of type 'Int' to 'nil' or 'Optional.none' always returns false}}
|
||||
_ = Optional.none == i // expected-warning {{comparing non-optional value of type 'Int' to 'nil' or 'Optional.none' always returns false}}
|
||||
_ = i != Optional.none // expected-warning {{comparing non-optional value of type 'Int' to 'nil' or 'Optional.none' always returns true}}
|
||||
_ = Optional.none != i // expected-warning {{comparing non-optional value of type 'Int' to 'nil' or 'Optional.none' always returns true}}
|
||||
_ = i == Optional.none // expected-warning {{comparing non-optional value of type 'Int' to 'Optional.none' always returns false}}
|
||||
_ = Optional.none == i // expected-warning {{comparing non-optional value of type 'Int' to 'Optional.none' always returns false}}
|
||||
_ = i != Optional.none // expected-warning {{comparing non-optional value of type 'Int' to 'Optional.none' always returns true}}
|
||||
_ = Optional.none != i // expected-warning {{comparing non-optional value of type 'Int' to 'Optional.none' always returns true}}
|
||||
|
||||
// FIXME(integers): uncomment these tests once the < is no longer ambiguous
|
||||
// _ = i < nil // _xpected-error {{type 'Int' is not optional, value can never be nil}}
|
||||
@@ -777,8 +777,8 @@ func nilComparison(i: Int, o: AnyObject) {
|
||||
// _ = i >= nil // _xpected-error {{type 'Int' is not optional, value can never be nil}}
|
||||
// _ = nil >= i // _xpected-error {{type 'Int' is not optional, value can never be nil}}
|
||||
|
||||
_ = o === nil // expected-warning {{comparing non-optional value of type 'AnyObject' to 'nil' or 'Optional.none' always returns false}}
|
||||
_ = o !== nil // expected-warning {{comparing non-optional value of type 'AnyObject' to 'nil' or 'Optional.none' always returns true}}
|
||||
_ = o === nil // expected-warning {{comparing non-optional value of type 'AnyObject' to 'nil' always returns false}}
|
||||
_ = o !== nil // expected-warning {{comparing non-optional value of type 'AnyObject' to 'nil' always returns true}}
|
||||
}
|
||||
|
||||
// <rdar://problem/23709100> QoI: incorrect ambiguity error due to implicit conversion
|
||||
|
||||
@@ -5,10 +5,10 @@ var f = false
|
||||
|
||||
func markUsed<T>(_ t: T) {}
|
||||
|
||||
markUsed(t != nil) // expected-warning {{comparing non-optional value of type 'Bool' to 'nil' or 'Optional.none' always returns true}}
|
||||
markUsed(f != nil) // expected-warning {{comparing non-optional value of type 'Bool' to 'nil' or 'Optional.none' always returns true}}
|
||||
markUsed(t != Optional.none) // expected-warning {{comparing non-optional value of type 'Bool' to 'nil' or 'Optional.none' always returns true}}
|
||||
markUsed(f != Optional.none) // expected-warning {{comparing non-optional value of type 'Bool' to 'nil' or 'Optional.none' always returns true}}
|
||||
markUsed(t != nil) // expected-warning {{comparing non-optional value of type 'Bool' to 'nil' always returns true}}
|
||||
markUsed(f != nil) // expected-warning {{comparing non-optional value of type 'Bool' to 'nil' always returns true}}
|
||||
markUsed(t != Optional.none) // expected-warning {{comparing non-optional value of type 'Bool' to 'Optional.none' always returns true}}
|
||||
markUsed(f != Optional.none) // expected-warning {{comparing non-optional value of type 'Bool' to 'Optional.none' always returns true}}
|
||||
|
||||
class C : Equatable {}
|
||||
|
||||
@@ -17,10 +17,10 @@ func == (lhs: C, rhs: C) -> Bool {
|
||||
}
|
||||
|
||||
func test(_ c: C) {
|
||||
if c == nil {} // expected-warning {{comparing non-optional value of type 'C' to 'nil' or 'Optional.none' always returns false}}
|
||||
if c == .none {} // expected-warning {{comparing non-optional value of type 'C' to 'nil' or 'Optional.none' always returns false}}
|
||||
if c == Optional.none {} // expected-warning {{comparing non-optional value of type 'C' to 'nil' or 'Optional.none' always returns false}}
|
||||
if c == C?.none {} // expected-warning {{comparing non-optional value of type 'C' to 'nil' or 'Optional.none' always returns false}}
|
||||
if c == nil {} // expected-warning {{comparing non-optional value of type 'C' to 'nil' always returns false}}
|
||||
if c == .none {} // expected-warning {{comparing non-optional value of type 'C' to 'Optional.none' always returns false}}
|
||||
if c == Optional.none {} // expected-warning {{comparing non-optional value of type 'C' to 'Optional.none' always returns false}}
|
||||
if c == C?.none {} // expected-warning {{comparing non-optional value of type 'C' to 'Optional.none' always returns false}}
|
||||
}
|
||||
|
||||
class D {}
|
||||
@@ -44,4 +44,4 @@ func test(_ e: E) {
|
||||
_ = e == E.none
|
||||
_ = e == Optional.none // expected-warning {{comparing non-optional value of type 'E' to 'nil' or 'Optional.none' always returns false}}
|
||||
_ = e == E?.none // expected-warning {{comparing non-optional value of type 'E' to 'nil' or 'Optional.none' always returns false}}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -762,15 +762,15 @@ func invalidDictionaryLiteral() {
|
||||
//===----------------------------------------------------------------------===//
|
||||
// nil/metatype comparisons
|
||||
//===----------------------------------------------------------------------===//
|
||||
_ = Int.self == nil // expected-warning {{comparing non-optional value of type 'any Any.Type' to 'nil' or 'Optional.none' always returns false}}
|
||||
_ = nil == Int.self // expected-warning {{comparing non-optional value of type 'any Any.Type' to 'nil' or 'Optional.none' always returns false}}
|
||||
_ = Int.self != nil // expected-warning {{comparing non-optional value of type 'any Any.Type' to 'nil' or 'Optional.none' always returns true}}
|
||||
_ = nil != Int.self // expected-warning {{comparing non-optional value of type 'any Any.Type' to 'nil' or 'Optional.none' always returns true}}
|
||||
_ = Int.self == nil // expected-warning {{comparing non-optional value of type 'any Any.Type' to 'nil' always returns false}}
|
||||
_ = nil == Int.self // expected-warning {{comparing non-optional value of type 'any Any.Type' to 'nil' always returns false}}
|
||||
_ = Int.self != nil // expected-warning {{comparing non-optional value of type 'any Any.Type' to 'nil' always returns true}}
|
||||
_ = nil != Int.self // expected-warning {{comparing non-optional value of type 'any Any.Type' to 'nil' always returns true}}
|
||||
|
||||
_ = Int.self == .none // expected-warning {{comparing non-optional value of type 'any Any.Type' to 'nil' or 'Optional.none' always returns false}}
|
||||
_ = .none == Int.self // expected-warning {{comparing non-optional value of type 'any Any.Type' to 'nil' or 'Optional.none' always returns false}}
|
||||
_ = Int.self != .none // expected-warning {{comparing non-optional value of type 'any Any.Type' to 'nil' or 'Optional.none' always returns true}}
|
||||
_ = .none != Int.self // expected-warning {{comparing non-optional value of type 'any Any.Type' to 'nil' or 'Optional.none' always returns true}}
|
||||
_ = Int.self == .none // expected-warning {{comparing non-optional value of type 'any Any.Type' to 'Optional.none' always returns false}}
|
||||
_ = .none == Int.self // expected-warning {{comparing non-optional value of type 'any Any.Type' to 'Optional.none' always returns false}}
|
||||
_ = Int.self != .none // expected-warning {{comparing non-optional value of type 'any Any.Type' to 'Optional.none' always returns true}}
|
||||
_ = .none != Int.self // expected-warning {{comparing non-optional value of type 'any Any.Type' to 'Optional.none' always returns true}}
|
||||
|
||||
// <rdar://problem/19032294> Disallow postfix ? when not chaining
|
||||
func testOptionalChaining(_ a : Int?, b : Int!, c : Int??) {
|
||||
|
||||
Reference in New Issue
Block a user