mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
The code was favoring overloads where *either* argument matched its parameter type and where both parameter types were the same. This is really overly broad and can result in bugs like the one here, where we only attempt the (Int, Int) -> Bool overload of '!=' despite the fact that it means forcing an optional. We should select the <T>(T?, T?) -> Bool overload instead, and inject the non-optional operand into an optional. Making this require *both* arguments to match mostly disables this optimization, though, since for somethin like "a"+"b"+"c" the second add has a type variable and string literal as arugments. So instead, we'll just disable this in cases where one argument is the optional of the other, to ensure we never try forcing one side. This also means we'll disable the optimization in cases where we would inject one operand into an optional, but that's likely find as we don't have long chains of expressions where that happens. Fixes rdar://problem/37073401.
75 lines
1.8 KiB
Swift
75 lines
1.8 KiB
Swift
// RUN: %target-run-simple-swift | %FileCheck %s
|
|
// REQUIRES: executable_test
|
|
|
|
var x : Int! = .none
|
|
if x != nil {
|
|
print("x is non-empty!")
|
|
} else {
|
|
print("an empty optional is logically false")
|
|
}
|
|
// CHECK: an empty optional is logically false
|
|
|
|
x = .some(0)
|
|
|
|
if x != nil {
|
|
print("a non-empty optional is logically true")
|
|
} else {
|
|
print("x is empty!")
|
|
}
|
|
// CHECK: a non-empty optional is logically true
|
|
|
|
class C {}
|
|
var c : C! = C()
|
|
|
|
if c === nil {
|
|
print("x is nil!")
|
|
} else {
|
|
print("a non-empty class optional should not equal nil")
|
|
}
|
|
// CHECK: a non-empty class optional should not equal nil
|
|
|
|
c = nil
|
|
if c === nil {
|
|
print("an empty class optional should equal nil")
|
|
} else {
|
|
print("x is not nil!")
|
|
}
|
|
// CHECK: an empty class optional should equal nil
|
|
|
|
import StdlibUnittest
|
|
|
|
|
|
import Swift
|
|
|
|
var ImplicitlyUnwrappedOptionalTests = TestSuite("ImplicitlyUnwrappedOptional")
|
|
|
|
ImplicitlyUnwrappedOptionalTests.test("flatMap") {
|
|
// FIXME(19798684): can't call map or flatMap on ImplicitlyUnwrappedOptional
|
|
|
|
// let half: Int32 -> Int16! =
|
|
// { if $0 % 2 == 0 { return Int16($0 / 2) } else { return .none } }
|
|
|
|
// expectOptionalEqual(2 as Int16, half(4))
|
|
// expectNil(half(3))
|
|
|
|
// expectNil((.none as Int!).flatMap(half))
|
|
// expectOptionalEqual(2 as Int16, (4 as Int!).flatMap(half))
|
|
// expectNil((3 as Int!).flatMap(half))
|
|
}
|
|
|
|
infix operator *^* : ComparisonPrecedence
|
|
|
|
func *^*(lhs: Int?, rhs: Int?) -> Bool { return true }
|
|
func *^*(lhs: Int, rhs: Int) -> Bool { return true }
|
|
|
|
ImplicitlyUnwrappedOptionalTests.test("preferOptional") {
|
|
let i: Int! = nil
|
|
let j: Int = 1
|
|
if i != j {} // we should choose != for Optionals rather than forcing i
|
|
if i == j {} // we should choose == for Optionals rather than forcing i
|
|
// FIXME: https://bugs.swift.org/browse/SR-6988
|
|
// if i *^* j {} // we should choose *^* for Optionals rather than forcing i
|
|
}
|
|
|
|
runAllTests()
|