Skip to content

Commit 2487277

Browse files
committed
Now that enough yaks are cleanly shaven, completely reimplement how
we process contextual constraints when producing diagnostic. Formerly, we would aggressively drop contextual type information on the floor under the idea that it would reduce constraints on the system and make it more likely to be solvable. However, this also has the downside of introducing ambiguity into the system, and some expr nodes (notably closures) cannot usually be solved without that contextual information. In the new model, expr diagnostics are expected to handle the fact that contextual information may be present, and bail out without diagnosing an error if that is the case. This gets us more information into closures, allowing more specific return type information, e.g. in the case in test/expr/closure/closures.swift. This approach also produces more correct diagnostics in a bunch of other cases as well, e.g.: - var c = [:] // expected-error {{type '[_ : _]' does not conform to protocol 'DictionaryLiteralConvertible'}} + var c = [:] // expected-error {{expression type '[_ : _]' is ambiguous without more context}} and the examples in test/stmt/foreach.swift, test/expr/cast/as_coerce.swift, test/expr/cast/array_iteration.swift, etc. That said, this another two steps forward, one back thing. Because we don't handle propagating sametype constraints from results of calls to their arguments, we regress a couple of (admittedly weird) cases. This is now tracked by: <rdar://problem/22333090> QoI: Propagate contextual information in a call to operands There is also the one-off narrow case tracked by: <rdar://problem/22333281> QoI: improve diagnostic when contextual type of closure disagrees with arguments Swift SVN r31319
1 parent 0c288e0 commit 2487277

16 files changed

+219
-368
lines changed

lib/Sema/CSDiag.cpp

Lines changed: 182 additions & 341 deletions
Large diffs are not rendered by default.

test/Constraints/array_literal.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,8 @@ useDoubleList([1.0,2,3])
5050
useDoubleList([1.0,2.0,3.0])
5151

5252
useIntDict(["Niners" => 31, "Ravens" => 34])
53-
useIntDict(["Niners" => 31, "Ravens" => 34.0]) // expected-error{{cannot convert value of type '(String, Double)' to expected element type '(String, Int)'}}
53+
// FIXME: rdar://22333090 improve diagnostic.
54+
useIntDict(["Niners" => 31, "Ravens" => 34.0]) // expected-error{{binary operator '=>' cannot be applied to operands of type 'String' and 'Double'}}
5455
useDoubleDict(["Niners" => 31, "Ravens" => 34.0])
5556
useDoubleDict(["Niners" => 31.0, "Ravens" => 34])
5657
useDoubleDict(["Niners" => 31.0, "Ravens" => 34.0])

test/Constraints/bridging.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,6 @@ func rdar20029786(ns: NSString?) {
269269
// <rdar://problem/19813772> QoI: Using as! instead of as in this case produces really bad diagnostic
270270
func rdar19813772(nsma: NSMutableArray) {
271271
var a1 = nsma as! Array // expected-error{{argument for generic parameter 'Element' could not be inferred}}
272-
// expected-warning @-1 {{cast from 'NSMutableArray' to unrelated type 'Array<_>' always fails}}
273272
var a2 = nsma as! Array<AnyObject> // expected-warning{{forced cast from 'NSMutableArray' to 'Array<AnyObject>' always succeeds; did you mean to use 'as'?}} {{17-20=as}}
274273
var a3 = nsma as Array<AnyObject>
275274
}

test/Constraints/lvalues.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ var ir2 = ((&i)) // expected-error{{type 'inout Int' of variable is not material
169169
func takeArrayRef(inout x:Array<String>) { }
170170

171171
// FIXME rdar://22308291 Poor diagnostic.
172-
takeArrayRef(["asdf", "1234"]) // expected-error{{type 'inout Array<String>' does not conform to protocol 'ArrayLiteralConvertible'}}
172+
takeArrayRef(["asdf", "1234"]) // expected-error{{cannot convert value of type '[String]' to expected argument type 'inout Array<String>'}}
173173

174174
// <rdar://problem/19835413> Reference to value from array changed
175175
func rdar19835413() {

test/Constraints/protocols.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,8 +88,8 @@ let _: () -> Any = { // expected-error {{function signature '() -> Int' is not
8888
return 0
8989
}
9090

91-
let _: () -> Int = { // expected-error {{cannot convert value of type '() -> String' to specified type '() -> Int'}}
92-
() -> String in
91+
let _: () -> Int = {
92+
() -> String in // expected-error {{declared closure result 'String' is incompatible with contextual type 'Int'}}
9393
return ""
9494
}
9595

test/Generics/deduction.swift

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,10 @@ func testReturnTuple(x: Int, y: Float) {
8888

8989
var _ : (Int, Float) = returnTuple(x)
9090
var _ : (Float, Float) = returnTuple(y)
91-
var _ : (Int, Float) = returnTuple(y) // expected-error{{cannot convert value of type '(Float, _)' to specified type '(Int, Float)'}}
91+
92+
// FIXME rdar://22333090: Improve diagnostic
93+
var _ : (Int, Float) = returnTuple(y) // expected-error{{cannot invoke 'returnTuple' with an argument list of type '(Float)'}}
94+
// expected-note @-1 {{expected an argument list of type '(T)'}}
9295
}
9396

9497

test/Parse/pointer_conversion.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ func constPointerArguments(p: UnsafeMutablePointer<Int>,
9595
takesConstPointer(ff) // expected-error{{cannot convert value of type '[Float]' to expected argument type 'UnsafePointer<Int>'}}
9696
takesConstPointer([0, 1, 2])
9797
// FIXME: improve QoI: rdar://22308330
98-
takesConstPointer([0.0, 1.0, 2.0]) // expected-error{{type 'UnsafePointer<Int>' does not conform to protocol 'ArrayLiteralConvertible'}}
98+
takesConstPointer([0.0, 1.0, 2.0]) // expected-error{{cannot convert value of type '[Double]' to expected argument type 'UnsafePointer<Int>'}}
9999

100100
// We don't allow these conversions outside of function arguments.
101101
var x: UnsafePointer<Int> = &i // expected-error{{cannot convert value of type 'inout Int' to specified type 'UnsafePointer<Int>'}}

test/decl/func/default-values.swift

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,11 @@ func identity<T>(t: T) -> T { return t }
9595
func defaultArgTuplesNotMaterializable(x: Int, y: Int = 0) {}
9696

9797
defaultArgTuplesNotMaterializable(identity(5))
98+
99+
// FIXME: 22333090 - Improve diagnostic
98100
defaultArgTuplesNotMaterializable(identity((5, y: 10)))
99-
// expected-error@-1 {{cannot convert value of type '(Int, y: Int)' to expected argument type 'Int'}}
101+
// expected-error@-1 {{cannot invoke 'identity' with an argument list of type '(Int, y: Int)'}}
102+
// expected-note@-2 {{expected an argument list of type '(T)'}}
100103

101104

102105
// rdar://problem/21799331

test/expr/cast/array_iteration.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ for view in rootView.subviews as! [View] {
1616
doFoo()
1717
}
1818

19-
for view:View in rootView.subviews { // expected-error{{'Array<AnyObject>!' is not convertible to 'View'}}
19+
for view:View in rootView.subviews { // expected-error{{'AnyObject' is not convertible to 'View'}}
2020
doFoo()
2121
}
2222

test/expr/cast/as_coerce.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,10 +81,10 @@ c3 as C4 // expected-error {{'C3' is not convertible to 'C4'; did you mean to us
8181
1 as Double as Float // expected-error{{cannot convert value of type 'Double' to type 'Float' in coercion}}
8282
1 as Int as String // expected-error{{cannot convert value of type 'Int' to type 'String' in coercion}}
8383
Double(1) as Double as String // expected-error{{cannot convert value of type 'Double' to type 'String' in coercion}}
84-
["awd"] as [Int] // expected-error{{'[Int]' is not convertible to 'Int'}}
84+
["awd"] as [Int] // expected-error{{cannot convert value of type '[String]' to type '[Int]' in coercion}}
8585
([1, 2, 1.0], 1) as ([String], Int) // expected-error{{cannot convert value of type '([Double], Int)' (aka '(Array<Double>, Int)') to type '([String], Int)' (aka '(Array<String>, Int)') in coercion}}
8686
// FIXME: below diagnostic should say [[Int]], not [Array<Int>]
87-
[[1]] as [[String]] // expected-error{{'[[String]]' is not convertible to '[String]'}}
87+
[[1]] as [[String]] // expected-error{{cannot convert value of type '[Array<Int>]' to type '[[String]]' in coercion}}
8888
(1, 1.0) as (Int, Int) // expected-error{{cannot convert value of type '(Int, Double)' to type '(Int, Int)' in coercion}}
8989
(1.0, 1, "asd") as (String, Int, Float) // expected-error{{cannot convert value of type '(Double, Int, String)' to type '(String, Int, Float)' in coercion}}
9090
(1, 1.0, "a", [1, 23]) as (Int, Double, String, [String]) // expected-error{{cannot convert value of type '(Int, Double, String, [Int])' (aka '(Int, Double, String, Array<Int>)') to type '(Int, Double, String, [String])' (aka '(Int, Double, String, Array<String>)') in coercion}}

test/expr/closure/basic.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ func variadic() {
2626
f(1, 2)
2727
f(1, 3)
2828

29-
let D = { (Ss ...) in 1 } // expected-error{{'...' cannot be applied to a subpattern which is not explicitly typed}}, expected-error{{unable to infer closure type in the current context}}
29+
let D = { (Ss ...) in 1 } // expected-error{{'...' cannot be applied to a subpattern which is not explicitly typed}}, expected-error{{unable to infer closure return type in current context}}
3030
}
3131

3232
// Closures with attributes in the parameter list.

test/expr/closure/closures.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@ var closure2 : (Int,Int) -> Int = { 4 } // FIXME: expected-error{{tuple types '(
1313
var closure3a : ()->()->(Int,Int) = {{ (4, 2) }} // multi-level closing.
1414
var closure3b : (Int,Int)->(Int)->(Int,Int) = {{ (4, 2) }} // expected-error{{tuple types '(Int, Int)' and '()' have a different number of elements (2 vs. 0)}}
1515
var closure4 : (Int,Int) -> Int = { $0 + $1 }
16-
var closure5 : (Double) -> Int =
17-
{ // expected-error {{cannot convert value of type '(Double) -> Double' to specified type '(Double) -> Int'}}
18-
$0 + 1.0 }
16+
var closure5 : (Double) -> Int = {
17+
$0 + 1.0 // expected-error {{cannot convert value of type 'Double' to closure result type 'Int'}}
18+
}
1919

2020
var closure6 = $0 // expected-error {{anonymous closure argument not contained in a closure}}
2121

test/expr/closure/default_args.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22

33
func simple_default_args() {
44
let _ : (Int) -> Int = {(x : Int = 1) in x+1} // expected-error{{default argument is only permitted for a non-curried function parameter}} {{36-39=}}
5-
let _ : () -> Int = {(x : Int = 1) in x+1} // expected-error{{cannot convert value of type '(Int) -> Int' to specified type '() -> Int'}} expected-error {{default argument is only permitted for a non-curried function parameter}} {{33-36=}}
6-
let _ : () -> Int = {(x : Int) in x+1} // expected-error{{cannot convert value of type '(Int) -> Int' to specified type '() -> Int'}}
5+
let _ : () -> Int = {(x : Int = 1) in x+1} // expected-error{{cannot convert value of type 'Int -> Int' to specified type '() -> Int'}} expected-error {{default argument is only permitted for a non-curried function parameter}} {{33-36=}}
6+
let _ : () -> Int = {(x : Int) in x+1} // expected-error{{cannot convert value of type 'Int -> Int' to specified type '() -> Int'}}
77
}
88

99
func func_default_args() {

test/expr/expressions.swift

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,13 @@ func basictest() {
4747
x8 = x8 + 1
4848
x8 + 1
4949
0 + x8
50-
1.0 + x8 // expected-error{{binary operator '+' cannot be applied to operands of type 'Double' and 'Int8'}} expected-note {{overloads for '+' exist with these partially matching parameter lists:}}
51-
var x9 : Int16 = x8 + 1 // expected-error{{cannot convert value of type 'Int8' to specified type 'Int16'}}
50+
1.0 + x8 // expected-error{{binary operator '+' cannot be applied to operands of type 'Double' and 'Int8'}}
51+
// expected-note @-1 {{overloads for '+' exist with these partially matching parameter lists:}}
52+
53+
54+
// FIXME rdar://22333090 - Improve diagnostic.
55+
var x9 : Int16 = x8 + 1 // expected-error{{binary operator '+' cannot be applied to operands of type 'Int8' and 'Int'}}
56+
// expected-note @-1 {{overloads for '+' exist with these partially matching parameter lists:}}
5257

5358
// Various tuple types.
5459
var tuple1 : ()
@@ -139,8 +144,8 @@ acceptsInt(unknown_var) // expected-error {{use of unresolved identifier 'unknow
139144
// and support the '=' operator.
140145

141146

142-
// FIXME: Bogus error
143-
var test1a: (Int) -> (Int) -> Int = { { $0 } } // expected-error{{type of expression is ambiguous without more context}}
147+
// FIXME rdar://22333281: Poor error message.
148+
var test1a: (Int) -> (Int) -> Int = { { $0 } } // expected-error{{tuple pattern cannot match values of the non-tuple type 'Int'}}
144149
var test1b = { 42 }
145150
var test1c = { { 42 } }
146151
var test1d = { { { 42 } } }
@@ -629,13 +634,13 @@ func unusedExpressionResults() {
629634
func arrayLiterals() {
630635
var a = [1,2,3]
631636
var b : [Int] = []
632-
var c = [] // expected-error {{type '[_]' does not conform to protocol 'ArrayLiteralConvertible'}}
637+
var c = [] // expected-error {{expression type '[_]' is ambiguous without more context}}
633638
}
634639
635640
func dictionaryLiterals() {
636641
var a = [1 : "foo",2 : "bar",3 : "baz"]
637642
var b : Dictionary<Int, String> = [:]
638-
var c = [:] // expected-error {{type '[_ : _]' does not conform to protocol 'DictionaryLiteralConvertible'}}
643+
var c = [:] // expected-error {{expression type '[_ : _]' is ambiguous without more context}}
639644
}
640645
641646
func invalidDictionaryLiteral() {

test/stmt/errors.swift

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
// RUN: %target-swift-frontend -parse -verify %s
2-
32
enum MSV : ErrorType {
43
case Foo, Bar, Baz
54

@@ -159,7 +158,7 @@ func ==(a: Thirteen, b: Thirteen) -> Bool { return true }
159158

160159
func thirteen_helper(fn: (Thirteen) -> ()) {}
161160
func thirteen() {
162-
thirteen_helper { (a) in // expected-error {{invalid conversion from throwing function of type '(_) throws -> ()' to non-throwing function type '(Thirteen) -> ()'}}
161+
thirteen_helper { (a) in // expected-error {{invalid conversion from throwing function of type '_ throws -> ()' to non-throwing function type '(Thirteen) -> ()'}}
163162
do {
164163
try thrower()
165164
} catch a {

test/stmt/foreach.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ func patterns(gir: GoodRange<Int>, gtr: GoodTupleGeneratorType) {
6060
var sumf : Float
6161
for i : Int in gir { sum = sum + i }
6262
for i in gir { sum = sum + i }
63-
for f : Float in gir { sum = sum + f } // expected-error{{'GoodRange<Int>' is not convertible to 'Float'}}
63+
for f : Float in gir { sum = sum + f } // expected-error{{'Int' is not convertible to 'Float'}}
6464

6565
for (i, f) : (Int, Float) in gtr { sum = sum + i }
6666

@@ -72,7 +72,7 @@ func patterns(gir: GoodRange<Int>, gtr: GoodTupleGeneratorType) {
7272

7373
for (i, _) : (Int, Float) in gtr { sum = sum + i }
7474

75-
for (i, _) : (Int, Int) in gtr { sum = sum + i } // expected-error{{'GoodTupleGeneratorType' is not convertible to '(Int, Int)'}}
75+
for (i, _) : (Int, Int) in gtr { sum = sum + i } // expected-error{{'Element' (aka '(Int, Float)') is not convertible to '(Int, Int)'}}
7676

7777
for (i, f) in gtr {}
7878
}

0 commit comments

Comments
 (0)