Files
swift-mirror/test/decl/enumtest.swift
Joe Pamer 2912159776 Improve diagnostics for expression typecheck errors
These changes make the following improvements to how we generate diagnostics for expression typecheck failure:
- Customizing a diagnostic for a specific expression kind is as easy as adding a new method to the FailureDiagnosis class,
  and does not require intimate knowledge of the constraint solver’s inner workings.
    - As part of this patch, I’ve introduced specialized diagnostics for call, binop, unop, subscript, assignment and inout
      expressions, but we can go pretty far with this.
    - This also opens up the possibility to customize diagnostics not just for the expression kind, but for the specific types
      involved as well.
- For the purpose of presenting accurate type info, partially-specialized subexpressions are individually re-typechecked
  free of any contextual types. This allows us to:
    - Properly surface subexpression errors.
    - Almost completely avoid any type variables in our diagnostics. In cases where they could not be eliminated, we now
      substitute in "_".
    - More accurately indicate the sources of errors.
- We do a much better job of diagnosing disjunction failures. (So no more nonsensical ‘UInt8’ error messages.)
- We now present reasonable error messages for overload resolution failures, informing the user of partially-matching
  parameter lists when possible.

At the very least, these changes address the following bugs:

<rdar://problem/15863738> More information needed in type-checking error messages
<rdar://problem/16306600> QoI: passing a 'let' value as an inout results in an unfriendly diagnostic
<rdar://problem/16449805> Wrong error for struct-to-protocol downcast
<rdar://problem/16699932> improve type checker diagnostic when passing Double to function taking a Float
<rdar://problem/16707914> fatal error: Can't unwrap Optional.None…Optional.swift, line 75 running Master-Detail Swift app built from template
<rdar://problem/16785829> Inout parameter fixit
<rdar://problem/16900438> We shouldn't leak the internal type placeholder
<rdar://problem/16909379> confusing type check diagnostics
<rdar://problem/16951521> Extra arguments to functions result in an unhelpful error
<rdar://problem/16971025> Two Terrible Diagnostics
<rdar://problem/17007804> $T2 in compiler error string
<rdar://problem/17027483> Terrible diagnostic
<rdar://problem/17083239> Mysterious error using find() with Foundation types
<rdar://problem/17149771> Diagnostic for closure with no inferred return value leaks type variables
<rdar://problem/17212371> Swift poorly-worded error message when overload resolution fails on return type
<rdar://problem/17236976> QoI: Swift error for incorrectly typed parameter is confusing/misleading
<rdar://problem/17304200> Wrong error for non-self-conforming protocols
<rdar://problem/17321369> better error message for inout protocols
<rdar://problem/17539380> Swift error seems wrong
<rdar://problem/17559593> Bogus locationless "treating a forced downcast to 'NSData' as optional will never produce 'nil'" warning
<rdar://problem/17567973> 32-bit error message is really far from the mark: error: missing argument for parameter 'withFont' in call
<rdar://problem/17671058> Wrong error message: "Missing argument for parameter 'completion' in call"
<rdar://problem/17704609> Float is not convertible to UInt8
<rdar://problem/17705424> Poor error reporting for passing Doubles to NSColor: extra argument 'red' in call
<rdar://problem/17743603> Swift compiler gives misleading error message in "NSLayoutConstraint.constraintsWithVisualFormat("x", options: 123, metrics: nil, views: views)"
<rdar://problem/17784167> application of operator to generic type results in odd diagnostic
<rdar://problem/17801696> Awful diagnostic trying to construct an Int when .Int is around
<rdar://problem/17863882> cannot convert the expression's type '()' to type 'Seq'
<rdar://problem/17865869> "has different argument names" diagnostic when parameter defaulted-ness differs
<rdar://problem/17937593> Unclear error message for empty array literal without type context
<rdar://problem/17943023> QoI: compiler displays wrong error when a float is provided to a Int16 parameter in init method
<rdar://problem/17951148> Improve error messages for expressions inside if statements by pre-evaluating outside the 'if'
<rdar://problem/18057815> Unhelpful Swift error message
<rdar://problem/18077468> Incorrect argument label for insertSubview(...)
<rdar://problem/18079213> 'T1' is not identical to 'T2' lacks directionality
<rdar://problem/18086470> Confusing Swift error message: error: 'T' is not convertible to 'MirrorDisposition'
<rdar://problem/18098995> QoI: Unhelpful compiler error when leaving off an & on an inout parameter
<rdar://problem/18104379> Terrible error message
<rdar://problem/18121897> unexpected low-level error on assignment to immutable value through array writeback
<rdar://problem/18123596> unexpected error on self. capture inside class method
<rdar://problem/18152074> QoI: Improve diagnostic for type mismatch in dictionary subscripting
<rdar://problem/18242160> There could be a better error message when using [] instead of [:]
<rdar://problem/18242812> 6A1021a : Type variable leaked
<rdar://problem/18331819> Unclear error message when trying to set an element of an array constant (Swift)
<rdar://problem/18414834> Bad diagnostics example
<rdar://problem/18422468> Calculation of constant value yields unexplainable error
<rdar://problem/18427217> Misleading error message makes debugging difficult
<rdar://problem/18439742> Misleading error: "cannot invoke" mentions completely unrelated types as arguments
<rdar://problem/18535804> Wrong compiler error from swift compiler
<rdar://problem/18567914> Xcode 6.1. GM, Swift, assignment from Int64 to NSNumber. Warning shown as problem with UInt8
<rdar://problem/18784027> Negating Int? Yields Float
<rdar://problem/17691565> attempt to modify a 'let' variable with ++ results in typecheck error about @lvalue Float
<rdar://problem/17164001> "++" on let value could give a better error message

Swift SVN r23782
2014-12-08 21:56:47 +00:00

292 lines
7.0 KiB
Swift

// RUN: %swift -parse %s -verify
//===----------------------------------------------------------------------===//
// Tests for various simple enum constructs
//===----------------------------------------------------------------------===//
public enum unionSearchFlags {
case None
case Backwards
case Anchored
init() { self = .None }
}
func test1() -> unionSearchFlags {
var a : unionSearchFlags
var b = unionSearchFlags.None
b = unionSearchFlags.Anchored
return unionSearchFlags.Backwards
}
func test1a() -> unionSearchFlags {
var a : unionSearchFlags
var b : unionSearchFlags = .None
b = .Anchored
// ForwardIndexType use of MaybeInt.
var c = MaybeInt.None
return .Backwards
}
func test1b(b : Bool) {
var x = 123
.description == 1 // expected-error{{could not find member 'description'}}
}
enum MaybeInt {
case None
case Some(Int)
init(_ i: Int) { self = MaybeInt.Some(i) }
}
func test2(a: Int, b: Int, c: MaybeInt) {
var c = MaybeInt.Some(4)
var d = MaybeInt.Some // expected-error{{partial application of enum constructor is not allowed}}
var e = MaybeInt.Some(b)
test2(1, 2, .None)
}
enum ZeroOneTwoThree {
case Zero
case One(Int)
case Two(Int, Int)
case Three(Int,Int,Int)
case Unknown(MaybeInt, MaybeInt, MaybeInt)
init (_ i: Int) { self = .One(i) }
init (_ i: Int, _ j: Int, _ k: Int) { self = .Three(i, j, k) }
init (_ i: MaybeInt, _ j: MaybeInt, _ k: MaybeInt) { self = .Unknown(i, j, k) }
}
func test3(a: ZeroOneTwoThree) {
var e = ZeroOneTwoThree.Three(1,2,3)
var f = ZeroOneTwoThree.Unknown(MaybeInt.None, MaybeInt.Some(4),
MaybeInt.Some(32))
var f1 = ZeroOneTwoThree(MaybeInt.None, MaybeInt(4), MaybeInt(32))
var g : Int =
ZeroOneTwoThree.Zero // expected-error {{'ZeroOneTwoThree' is not convertible to 'Int'}}
test3 ZeroOneTwoThree.Zero // expected-error {{expression resolves to an unused function}} expected-error{{consecutive statements}}
test3 (ZeroOneTwoThree.Zero)
test3(ZeroOneTwoThree.Zero)
test3 // expected-error {{expression resolves to an unused function}}
(ZeroOneTwoThree.Zero)
var h : ZeroOneTwoThree = .One(4)
var inf : (Int,Int) -> ZeroOneTwoThree = .Two // expected-error{{'((Int, Int) -> ZeroOneTwoThree).Type' does not have a member named 'Two'}}
}
func test3a(a: ZeroOneTwoThree) {
var e : ZeroOneTwoThree = (.Three(1, 2, 3))
var f = ZeroOneTwoThree.Unknown(.None, .Some(4), .Some(32))
var g = .None // expected-error {{could not find member 'None'}}
// Overload resolution can resolve this to the right constructor.
var h = ZeroOneTwoThree(1)
test3a; // expected-error {{unused function}}
.Zero // expected-error {{could not find member 'Zero'}}
test3a // expected-error {{unused function}}
(.Zero) // expected-error {{could not find member 'Zero'}}
test3a(.Zero)
}
struct CGPoint { var x : Int, y : Int }
typealias OtherPoint = ( x : Int, y : Int)
func test4() {
var a : CGPoint
// Note: we reject the following because it conflicts with the current
// "init" hack.
var b = CGPoint.CGPoint(1, 2) // expected-error {{'CGPoint.Type' does not have a member named 'CGPoint'}}
var c = CGPoint(x: 2, y : 1) // Using injected name.
var e = CGPoint.x // expected-error {{'CGPoint.Type' does not have a member named 'x'}}
var f = OtherPoint.x // expected-error {{'OtherPoint.Type' does not have a member named 'x'}}
}
struct CGSize { var width : Int, height : Int }
extension CGSize {
func area() -> Int {
return width*self.height
}
func area_wrapper() -> Int {
return area()
}
}
struct CGRect {
var origin : CGPoint,
size : CGSize
func area() -> Int {
return self.size.area()
}
}
func area(r: CGRect) -> Int {
return r.size.area()
}
extension CGRect {
func search(x: Int) -> CGSize {}
func bad_search(Int) -> CGSize {}
}
func test5(myorigin: CGPoint) {
var x1 = CGRect(origin: myorigin, size: CGSize(width: 42, height: 123))
var x2 = x1
4+5
// Dot syntax.
var x3 = x2.origin.x
var x4 = x1.size.area()
var x4a = (r : x1.size).r.area()
var x5 = x1.size.area()
var x5a = (r : x1.size).r.area()
var x5b = x1.area //expected-error{{partial application of struct method is not allowed}}
var x6 = x1.search(42)
var x7 = x1.search(42).width
// TODO: something like this (name binding on the LHS):
// var (CGSize(width, height)) = CGSize(1,2)
// TODO: something like this, how do we get it in scope in the {} block?
//if (var Some(x) = somemaybeint) { ... }
}
struct StructTest1 {
var a : Int, c, b : Int
typealias ElementType = Int
}
enum UnionTest1 {
case x
case y(Int)
func foo() {}
init() { self = .x }
}
extension UnionTest1 {
func food() {}
func bar() {}
// Type method.
static func baz() {}
}
struct EmptyStruct {
func foo() {}
}
func f() {
var a : UnionTest1
a.bar()
UnionTest1.baz() // dot syntax access to a static method.
// Test that we can get the "address of a member".
var member_ptr_static : () -> () = UnionTest1.baz
var member_ptr : (UnionTest1) -> () -> () = UnionTest1.bar
}
func union_error(a: ZeroOneTwoThree) {
var t1 : ZeroOneTwoThree = .Zero(1) // expected-error {{'(IntegerLiteralConvertible) -> _' is not identical to 'ZeroOneTwoThree'}}
var t2 : ZeroOneTwoThree = .One // expected-error {{could not find member 'One'}}
var t3 : ZeroOneTwoThree = .foo // expected-error {{'ZeroOneTwoThree.Type' does not have a member named 'foo'}}
var t4 : ZeroOneTwoThree = .foo() // expected-error {{'ZeroOneTwoThree.Type' does not have a member named 'foo'}}
}
func local_struct() {
struct s { func y() {} }
}
//===----------------------------------------------------------------------===//
// A silly units example showing "user defined literals".
//===----------------------------------------------------------------------===//
struct distance { var v : Int }
func - (lhs: distance, rhs: distance) -> distance {}
extension Int {
func km() -> distance {}
func cm() -> distance {}
}
func units(x: Int) -> distance {
x.km() - 4.cm() - 42.km()
}
var %% : distance -> distance // expected-error {{expected pattern}}
func badTupleElement() {
typealias X = (x : Int, y : Int)
var y = X.y // expected-error{{'X.Type' does not have a member named 'y'}}
var z = X.z // expected-error{{'X.Type' does not have a member named 'z'}}
}
enum Direction {
case North(distance: Int)
case NorthEast(distanceNorth: Int, distanceEast: Int)
}
func testDirection() {
var dir: Direction = .North(distance: 5)
dir = .NorthEast(distanceNorth: 5, distanceEast: 7)
var i: Int
switch dir {
case .North(let x):
i = x.distance
break;
case .NorthEast(let x):
i = x.distanceEast
break;
}
}
enum NestedSingleElementTuple {
case Case(x: (y: Int)) // expected-error{{cannot create a single-element tuple with an element label}}
}
// <rdar://problem/17186190>
class OuterNonGenericClass {
enum Bar {
case Baz
case Zab
}
}
class OuterGenericClass<T> {
enum Bar { // expected-error {{type 'Bar' nested in generic type 'OuterGenericClass' is not allowed}}
case Baz
case Zab
}
}