mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
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
172 lines
6.3 KiB
Swift
172 lines
6.3 KiB
Swift
// RUN: %swift -parse %s -verify
|
|
|
|
infix operator %%% {}
|
|
infix operator %%%% {}
|
|
|
|
func %%%() {} // expected-error {{operators must have one or two arguments}}
|
|
func %%%%(a: Int, b: Int, c: Int) {} // expected-error {{operators must have one or two arguments}}
|
|
|
|
struct X {}
|
|
struct Y {}
|
|
|
|
func +(lhs: X, rhs: X) -> X {} // okay
|
|
|
|
func +++(lhs: X, rhs: X) -> X {} // expected-error {{operator implementation without matching operator declaration}}
|
|
|
|
infix operator ++++ {
|
|
precedence 195
|
|
associativity left
|
|
}
|
|
|
|
infix func fn_binary(lhs: Int, rhs: Int) {} // expected-error {{'infix' requires a function with an operator identifier}}
|
|
|
|
|
|
func ++++(lhs: X, rhs: X) -> X {}
|
|
func ++++(lhs: Y, rhs: Y) -> Y {} // okay
|
|
|
|
func useInt(x: Int) {}
|
|
func test() {
|
|
var x : Int
|
|
var y : Int = 42
|
|
// Produce a diagnostic for using the result of an assignment as a value.
|
|
// rdar://12961094
|
|
useInt(x = y) // expected-error{{cannot invoke 'useInt' with an argument list of type '()'}} expected-note{{expected an argument list of type 'Int'}}
|
|
}
|
|
|
|
prefix operator ~~ {}
|
|
postfix operator ~~ {}
|
|
infix operator ~~ {}
|
|
|
|
postfix func foo(x: Int) {} // expected-error {{'postfix' requires a function with an operator identifier}}
|
|
postfix func ~~(x: Int) -> Float { return Float(x) }
|
|
postfix func ~~(x: Int, y: Int) {} // expected-error {{'postfix' requires a function with one argument}}
|
|
prefix func ~~(x: Float) {}
|
|
func test_postfix(x: Int) {
|
|
~~x~~
|
|
}
|
|
|
|
prefix operator ~~~ {} // expected-note 2{{prefix operator found here}}
|
|
|
|
// Unary operators require a prefix or postfix attribute
|
|
func ~~~(x: Float) {} // expected-error{{prefix unary operator missing 'prefix' modifier}}{{1-1=prefix }}
|
|
|
|
protocol P {
|
|
func ~~~(x: Self) // expected-error{{prefix unary operator missing 'prefix' modifier}}{{3-3=prefix }}
|
|
}
|
|
|
|
prefix func +// this should be a comment, not an operator
|
|
(arg: Int) -> Int { return arg }
|
|
|
|
prefix func -/* this also should be a comment, not an operator */
|
|
(arg: Int) -> Int { return arg }
|
|
|
|
func +*/ () {} // expected-error {{expected identifier in function declaration}} expected-error {{unexpected end of block comment}} expected-error {{braced block of statements is an unused closure}} expected-error{{begin with a closure}} expected-note{{discard the result}} expected-error{{type of expression is ambiguous without more context}}
|
|
func errors() {
|
|
*/ // expected-error {{unexpected end of block comment}}
|
|
|
|
// rdar://12962712 - reject */ in an operator as it should end a block comment.
|
|
*/+ // expected-error {{unexpected end of block comment}}
|
|
}
|
|
|
|
prefix operator ... {}
|
|
|
|
prefix func ... (arg: Int) -> Int { return arg }
|
|
func resyncParser() {}
|
|
|
|
// Operator decl refs (<op>)
|
|
|
|
infix operator +-+ {}
|
|
prefix operator +-+ {}
|
|
|
|
prefix operator -+- {}
|
|
postfix operator -+- {}
|
|
|
|
infix operator +-+= {}
|
|
|
|
infix func +-+ (x: Int, y: Int) -> Int {} // expected-error {{'infix' modifier is not required or allowed on func declarations}}
|
|
prefix func +-+ (x: Int) -> Int {}
|
|
|
|
prefix func -+- (inout y: Int) -> Int {} // expected-note 2{{found this candidate}}
|
|
postfix func -+- (inout x: Int) -> Int {} // expected-note 2{{found this candidate}}
|
|
|
|
infix func +-+= (inout x: Int, y: Int) -> Int {} // expected-error {{'infix' modifier is not required or allowed on func declarations}}
|
|
|
|
var n = 0
|
|
|
|
// Infix by context
|
|
(+-+)(1, 2)
|
|
// Prefix by context
|
|
(+-+)(1)
|
|
|
|
// Ambiguous -- could be prefix or postfix
|
|
(-+-)(&n) // expected-error{{ambiguous use of operator '-+-'}}
|
|
|
|
// Assignment operator refs become inout functions
|
|
(+-+=)(&n, 12)
|
|
(+-+=)(n, 12) // expected-error {{passing value of type 'Int' to an inout parameter requires explicit '&'}}
|
|
|
|
var f1 : (Int, Int) -> Int = (+-+)
|
|
var f2 : (Int) -> Int = (+-+)
|
|
var f3 : (inout Int) -> Int = (-+-) // expected-error{{ambiguous use of operator '-+-'}}
|
|
var f4 : (inout Int, Int) -> Int = (+-+=)
|
|
var r5 : (a : (Int, Int) -> Int, b : (Int, Int) -> Int) = (+, -)
|
|
var r6 : (a : (Int, Int) -> Int, b : (Int, Int) -> Int) = (b : +, a : -)
|
|
|
|
struct f6_S {
|
|
subscript(op : (Int, Int) -> Int) -> Int {
|
|
return 42
|
|
}
|
|
}
|
|
var f6_s : f6_S
|
|
var junk = f6_s[+]
|
|
|
|
// Unicode operator names
|
|
infix operator ☃ {}
|
|
infix operator ☃⃠ {} // Operators can contain (but not start with) combining characters
|
|
|
|
func ☃(x: Int, y: Int) -> Bool { return x == y }
|
|
func ☃⃠(x: Int, y: Int) -> Bool { return x != y }
|
|
|
|
var x, y : Int
|
|
x☃y
|
|
x☃⃠y
|
|
|
|
// rdar://14705150 - crash on invalid
|
|
func test_14705150() {
|
|
var a = 4
|
|
var b! = a // expected-error {{consecutive statements on a line must be separated by ';'}} \
|
|
// expected-error {{expected expression}} \
|
|
// expected-error {{type annotation missing in pattern}}
|
|
}
|
|
|
|
prefix postfix func ++(x: Int) {} // expected-error {{attribute 'prefix' cannot be combined with this attribute}}
|
|
postfix prefix func ++(x: Int) {} // expected-error {{attribute 'postfix' cannot be combined with this attribute}}
|
|
|
|
// Don't allow one to define a postfix '!'; it's built into the
|
|
// language.
|
|
postfix operator! {} // expected-error {{cannot declare a custom postfix '!' operator}}
|
|
prefix operator & {} // expected-error {{cannot declare a custom prefix '&' operator}}
|
|
|
|
// <rdar://problem/14607026> Restrict use of '<' and '>' as prefix/postfix operator names
|
|
postfix operator > {} // expected-error {{cannot declare a custom postfix '>' operator}}
|
|
prefix operator < {} // expected-error {{cannot declare a custom prefix '<' operator}}
|
|
|
|
postfix func !(x: Int) { } // expected-error{{cannot declare a custom postfix '!' operator}}
|
|
postfix func!(x: Int8) { } // expected-error{{cannot declare a custom postfix '!' operator}}
|
|
prefix func & (x: Int) {} // expected-error {{cannot declare a custom prefix '&' operator}}
|
|
|
|
// Only allow operators at global scope:
|
|
func operator_in_func_bad () {
|
|
prefix func + (input: String) -> String { return "+" + input } // expected-error {{operators are only allowed at global scope}} expected-error{{type of expression is ambiguous without more context}} \
|
|
// expected-error {{braced block of statements is an unused closure}}
|
|
}
|
|
|
|
infix operator ? {} // expected-error {{expected operator name in operator declaration}} expected-error {{braced block of statements is an unused closure}} expected-error{{begin with a closure}} expected-note{{discard the result}} expected-error{{type of expression is ambiguous without more context}}
|
|
|
|
infix operator ??= {}
|
|
|
|
func ??= <T>(inout result : T?, rhs : Int) { // ok
|
|
}
|
|
|
|
|