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:
Chris Lattner
2015-03-12 00:39:43 +00:00
parent 83541dd362
commit 5549775677
8 changed files with 59 additions and 27 deletions

View File

@@ -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 {

View File

@@ -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
}
}

View File

@@ -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

View File

@@ -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)

View File

@@ -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

View File

@@ -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

View File

@@ -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"

View File

@@ -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
}
}