Skip to content

Commit 19fce32

Browse files
committed
[Diagnostics] For array element conversion failures, emit an error message
for each element whose type variable was merged in addJoinConstraint
1 parent 989a432 commit 19fce32

File tree

5 files changed

+33
-4
lines changed

5 files changed

+33
-4
lines changed

lib/Sema/CSDiagnostics.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4942,6 +4942,9 @@ bool CollectionElementContextualFailure::diagnoseAsError() {
49424942

49434943
Optional<InFlightDiagnostic> diagnostic;
49444944
if (isExpr<ArrayExpr>(anchor)) {
4945+
if (diagnoseMergedLiteralElements())
4946+
return true;
4947+
49454948
diagnostic.emplace(emitDiagnostic(diag::cannot_convert_array_element,
49464949
eltType, contextualType));
49474950
}
@@ -4992,6 +4995,30 @@ bool CollectionElementContextualFailure::diagnoseAsError() {
49924995
return true;
49934996
}
49944997

4998+
bool CollectionElementContextualFailure::diagnoseMergedLiteralElements() {
4999+
auto elementAnchor = simplifyLocatorToAnchor(getLocator());
5000+
if (!elementAnchor)
5001+
return false;
5002+
5003+
auto *typeVar = getRawType(elementAnchor)->getAs<TypeVariableType>();
5004+
if (!typeVar || !typeVar->getImpl().getAtomicLiteralKind())
5005+
return false;
5006+
5007+
// This element is a literal whose type variable could have been merged with others,
5008+
// but the conversion constraint to the array element type was only placed on one
5009+
// of them. So, we want to emit the error for each element whose type variable is in
5010+
// this equivalence class.
5011+
auto &cs = getConstraintSystem();
5012+
auto node = cs.getRepresentative(typeVar)->getImpl().getGraphNode();
5013+
for (const auto *typeVar : node->getEquivalenceClass()) {
5014+
auto anchor = typeVar->getImpl().getLocator()->getAnchor();
5015+
emitDiagnosticAt(constraints::getLoc(anchor), diag::cannot_convert_array_element,
5016+
getFromType(), getToType());
5017+
}
5018+
5019+
return true;
5020+
}
5021+
49955022
bool MissingContextualConformanceFailure::diagnoseAsError() {
49965023
auto anchor = getAnchor();
49975024
auto path = getLocator()->getPath();

lib/Sema/CSDiagnostics.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1637,6 +1637,8 @@ class CollectionElementContextualFailure final : public ContextualFailure {
16371637
: ContextualFailure(solution, eltType, contextualType, locator) {}
16381638

16391639
bool diagnoseAsError() override;
1640+
1641+
bool diagnoseMergedLiteralElements();
16401642
};
16411643

16421644
class MissingContextualConformanceFailure final : public ContextualFailure {

test/Constraints/diagnostics.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -338,7 +338,7 @@ variadic(arrayWithOtherEltType) // expected-error {{cannot convert value of type
338338
variadic(1, arrayWithOtherEltType) // expected-error {{cannot convert value of type '[String]' to expected argument type 'Int'}}
339339

340340
// FIXME: SR-11104
341-
variadic(["hello", "world"]) // expected-error {{cannot convert value of type 'String' to expected element type 'Int'}}
341+
variadic(["hello", "world"]) // expected-error 2 {{cannot convert value of type 'String' to expected element type 'Int'}}
342342
// expected-error@-1 {{cannot pass array of type '[Int]' as variadic arguments of type 'Int'}}
343343
// expected-note@-2 {{remove brackets to pass array elements directly}}
344344

test/Parse/pointer_conversion.swift.gyb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ func constPointerArguments(_ p: UnsafeMutablePointer<Int>,
164164
takesConstPointer([0, 1, 2])
165165
// <rdar://problem/22308330> QoI: CSDiags doesn't handle array -> pointer impl conversions well
166166
takesConstPointer([0.0, 1.0, 2.0])
167-
// expected-error@-1 {{cannot convert value of type 'Double' to expected element type 'Int'}}
167+
// expected-error@-1 3 {{cannot convert value of type 'Double' to expected element type 'Int'}}
168168

169169
// We don't allow these conversions outside of function arguments.
170170
var x: UnsafePointer<Int> = &i // expected-error {{use of extraneous '&'}}

test/expr/cast/as_coerce.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,13 +84,13 @@ c3 as C4 // expected-error {{'C3' is not convertible to 'C4'; did you mean to us
8484
Double(1) as Double as String // expected-error{{cannot convert value of type 'Double' to type 'String' in coercion}}
8585
["awd"] as [Int] // expected-error{{cannot convert value of type 'String' to expected element type 'Int'}}
8686
([1, 2, 1.0], 1) as ([String], Int)
87-
// expected-error@-1 {{cannot convert value of type 'Int' to expected element type 'String'}}
87+
// expected-error@-1 2 {{cannot convert value of type 'Int' to expected element type 'String'}}
8888
// expected-error@-2 {{cannot convert value of type 'Double' to expected element type 'String'}}
8989
[[1]] as [[String]] // expected-error{{cannot convert value of type 'Int' to expected element type 'String'}}
9090
(1, 1.0) as (Int, Int) // expected-error{{cannot convert value of type '(Int, Double)' to type '(Int, Int)' in coercion}}
9191
(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}}
9292
(1, 1.0, "a", [1, 23]) as (Int, Double, String, [String])
93-
// expected-error@-1 {{cannot convert value of type 'Int' to expected element type 'String'}}
93+
// expected-error@-1 2 {{cannot convert value of type 'Int' to expected element type 'String'}}
9494

9595
_ = [1] as! [String] // OK
9696
_ = [(1, (1, 1))] as! [(Int, (String, Int))] // OK

0 commit comments

Comments
 (0)