mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
enhance silgen to treat OptionalSomePattern and EnumElementPattern as
"similar", avoiding false positive "not exhaustive" diagnostics on switches
like:
switch ... {
case let x?: break
case .None: break
}
Also, start using x? patterns in the stdlib more (review appreciated!), which
is what shook this issue out.
Swift SVN r26004
This commit is contained in:
@@ -305,9 +305,18 @@ static Pattern *getSimilarSpecializingPattern(Pattern *p, Pattern *first) {
|
||||
// Map down to the semantics-providing pattern.
|
||||
p = p->getSemanticsProvidingPattern();
|
||||
|
||||
// Currently, only patterns with exactly the same kind can be
|
||||
// specialized the same way.
|
||||
return (p->getKind() == first->getKind() ? p : nullptr);
|
||||
// If the patterns are exactly the same kind, they can be treated similarly.
|
||||
if (p->getKind() == first->getKind())
|
||||
return p;
|
||||
|
||||
// If one is an OptionalSomePattern and one is an EnumElementPattern, then
|
||||
// they are the same since the OptionalSomePattern is just sugar for .Some(x).
|
||||
if ((isa<OptionalSomePattern>(p) && isa<EnumElementPattern>(first)) ||
|
||||
(isa<OptionalSomePattern>(first) && isa<EnumElementPattern>(p)))
|
||||
return p;
|
||||
|
||||
// Otherwise, they are different.
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
@@ -151,7 +151,7 @@ public func split<S: Sliceable, R:BooleanType>(
|
||||
}
|
||||
|
||||
switch startIndex {
|
||||
case .Some(var i):
|
||||
case let i?:
|
||||
result.append(elements[i..<elements.endIndex])
|
||||
default:
|
||||
()
|
||||
@@ -408,10 +408,7 @@ public func lexicographicalCompare<
|
||||
}
|
||||
return false
|
||||
}
|
||||
switch e2_ {
|
||||
case .Some(_): return true
|
||||
case .None: return false
|
||||
}
|
||||
return e2_ != nil
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -148,7 +148,7 @@ public struct Character :
|
||||
}
|
||||
|
||||
internal struct _SmallUTF8 : CollectionType {
|
||||
init(var _ u8: UInt64) {
|
||||
init(_ u8: UInt64) {
|
||||
let count = Character._smallSize(u8)
|
||||
_sanityCheck(count <= 8, "Character with more than 8 UTF-8 code units")
|
||||
self.count = UInt16(count)
|
||||
@@ -204,7 +204,7 @@ public struct Character :
|
||||
}
|
||||
|
||||
struct _SmallUTF16 : CollectionType {
|
||||
init(var _ u8: UInt64) {
|
||||
init(_ u8: UInt64) {
|
||||
let count = UTF16.measure(
|
||||
UTF8.self, input: Character._makeSmallUTF8Generator(u8),
|
||||
repairIllFormedSequences: true)!.0
|
||||
|
||||
@@ -65,7 +65,7 @@ extension Optional : DebugPrintable {
|
||||
/// A textual representation of `self`, suitable for debugging.
|
||||
public var debugDescription: String {
|
||||
switch self {
|
||||
case .Some(var value):
|
||||
case .Some(let value):
|
||||
var result = "Optional("
|
||||
debugPrint(value, &result)
|
||||
result += ")"
|
||||
@@ -86,10 +86,10 @@ extension Optional : DebugPrintable {
|
||||
/// Haskell's fmap for Optionals.
|
||||
public func map<T, U>(x: T?, @noescape f: (T)->U) -> U? {
|
||||
switch x {
|
||||
case .Some(var y):
|
||||
return .Some(f(y))
|
||||
case .Some(let y):
|
||||
return .Some(f(y))
|
||||
case .None:
|
||||
return .None
|
||||
return .None
|
||||
}
|
||||
}
|
||||
|
||||
@@ -127,7 +127,7 @@ func _diagnoseUnexpectedNilOptional() {
|
||||
public // COMPILER_INTRINSIC
|
||||
func _getOptionalValue<T>(v: T?) -> T {
|
||||
switch v {
|
||||
case .Some(var x):
|
||||
case let x?:
|
||||
return x
|
||||
case .None:
|
||||
_preconditionFailure(
|
||||
@@ -150,9 +150,9 @@ func _injectNothingIntoOptional<T>() -> T? {
|
||||
// Comparisons
|
||||
public func == <T : Equatable> (lhs: T?, rhs: T?) -> Bool {
|
||||
switch (lhs,rhs) {
|
||||
case (.Some(let l), .Some(let r)):
|
||||
case let (l?, r?):
|
||||
return l == r
|
||||
case (.None, .None):
|
||||
case (nil, nil):
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
@@ -243,7 +243,7 @@ internal struct _OptionalMirror<T> : MirrorType {
|
||||
|
||||
var summary: String {
|
||||
switch _value {
|
||||
case .Some(let contents): return reflect(contents).summary
|
||||
case let contents?: return reflect(contents).summary
|
||||
default: return "nil"
|
||||
}
|
||||
}
|
||||
@@ -256,9 +256,9 @@ internal struct _OptionalMirror<T> : MirrorType {
|
||||
|
||||
public func < <T: _Comparable> (lhs: T?, rhs: T?) -> Bool {
|
||||
switch (lhs,rhs) {
|
||||
case (.Some(let l), .Some(let r)):
|
||||
case let (l?, r?):
|
||||
return l < r
|
||||
case (.None, .Some):
|
||||
case (nil, _?):
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
@@ -267,7 +267,7 @@ public func < <T: _Comparable> (lhs: T?, rhs: T?) -> Bool {
|
||||
|
||||
public func > <T: _Comparable>(lhs: T?, rhs: T?) -> Bool {
|
||||
switch (lhs,rhs) {
|
||||
case (.Some(let l), .Some(let r)):
|
||||
case let (l?, r?):
|
||||
return l > r
|
||||
default:
|
||||
return rhs < lhs
|
||||
@@ -276,7 +276,7 @@ public func > <T: _Comparable>(lhs: T?, rhs: T?) -> Bool {
|
||||
|
||||
public func <= <T: _Comparable>(lhs: T?, rhs: T?) -> Bool {
|
||||
switch (lhs,rhs) {
|
||||
case (.Some(let l), .Some(let r)):
|
||||
case let (l?, r?):
|
||||
return l <= r
|
||||
default:
|
||||
return !(rhs < lhs)
|
||||
@@ -285,7 +285,7 @@ public func <= <T: _Comparable>(lhs: T?, rhs: T?) -> Bool {
|
||||
|
||||
public func >= <T: _Comparable>(lhs: T?, rhs: T?) -> Bool {
|
||||
switch (lhs,rhs) {
|
||||
case (.Some(let l), .Some(let r)):
|
||||
case let (l?, r?):
|
||||
return l >= r
|
||||
default:
|
||||
return !(lhs < rhs)
|
||||
|
||||
@@ -138,12 +138,12 @@ public typealias AnyClass = AnyObject.Type
|
||||
|
||||
public func === (lhs: AnyObject?, rhs: AnyObject?) -> Bool {
|
||||
switch (lhs, rhs) {
|
||||
case (.Some(let l), .Some(let r)):
|
||||
case let (l?, r?):
|
||||
return Bool(Builtin.cmp_eq_RawPointer(
|
||||
Builtin.bridgeToRawPointer(Builtin.castToNativeObject(l)),
|
||||
Builtin.bridgeToRawPointer(Builtin.castToNativeObject(r))
|
||||
))
|
||||
case (.None, .None):
|
||||
case (nil, nil):
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
|
||||
@@ -170,7 +170,7 @@ extension String {
|
||||
if _baseSet {
|
||||
if _ascii {
|
||||
switch self._asciiBase.next() {
|
||||
case let .Some(x):
|
||||
case let x?:
|
||||
result = .Result(UnicodeScalar(x))
|
||||
case .None:
|
||||
result = .EmptyInput
|
||||
|
||||
@@ -16,7 +16,7 @@ import gizmo
|
||||
|
||||
// OPT-LABEL: sil hidden @_TF21objc_nonnull_lie_hack10makeObjectFT_GSqCSo8NSObject_
|
||||
// OPT: [[OPT:%.*]] = unchecked_ref_bit_cast
|
||||
// OPT: switch_enum [[OPT]] : $Optional<NSObject>, case #Optional.None!enumelt: [[NIL:bb[0-9]+]]
|
||||
// OPT: switch_enum [[OPT]] : $Optional<NSObject>{{.*}} case #Optional.None!enumelt: [[NIL:bb[0-9]+]]
|
||||
// OPT: [[NIL]]:
|
||||
// OPT: string_literal utf8 "nil"
|
||||
|
||||
|
||||
@@ -1348,3 +1348,29 @@ func testOptionalPattern(value : Int?) {
|
||||
}
|
||||
|
||||
|
||||
// x? and .None should both be considered "similar" and thus handled in the same
|
||||
// switch on the enum kind. There should be no unreachable generated.
|
||||
// CHECK-LABEL: sil hidden @_TF6switch19testOptionalEnumMixFGSqSi_Si
|
||||
func testOptionalEnumMix(a : Int?) -> Int {
|
||||
// CHECK: debug_value %0 : $Optional<Int> // let a
|
||||
// CHECK-NEXT: switch_enum %0 : $Optional<Int>, case #Optional.Some!enumelt.1: [[SOMEBB:bb[0-9]+]], case #Optional.None!enumelt: [[NILBB:bb[0-9]+]]
|
||||
switch a {
|
||||
case let x?:
|
||||
return 0
|
||||
|
||||
// CHECK: [[SOMEBB]](%3 : $Int):
|
||||
// CHECK-NEXT: debug_value %3 : $Int // let x
|
||||
// CHECK: integer_literal $Builtin.Int2048, 0
|
||||
|
||||
case .None:
|
||||
return 42
|
||||
|
||||
// CHECK: [[NILBB]]:
|
||||
// CHECK: integer_literal $Builtin.Int2048, 42
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user