Skip to content

Commit 386d93e

Browse files
authored
Merge pull request swiftlang#6753 from xedin/if-expr-recheck
[Diagnostics] Improve diagnostics for expressions involving ternary operators
2 parents 2b98e46 + f142568 commit 386d93e

File tree

2 files changed

+41
-0
lines changed

2 files changed

+41
-0
lines changed

lib/Sema/CSGen.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2753,6 +2753,32 @@ namespace {
27532753
public:
27542754
SanitizeExpr(TypeChecker &tc) : TC(tc) { }
27552755

2756+
std::pair<bool, Expr *> walkToExprPre(Expr *expr) override {
2757+
// Let's check if condition of the IfExpr looks properly
2758+
// type-checked, and roll it back to the original state,
2759+
// because otherwise, since condition is implicitly Int1,
2760+
// we'll have to handle multiple ways of type-checking
2761+
// IfExprs in both ConstraintGenerator and ExprRewriter,
2762+
// so it's less error prone to do it once here.
2763+
if (auto IE = dyn_cast<IfExpr>(expr)) {
2764+
auto condition = IE->getCondExpr();
2765+
if (!condition)
2766+
return {true, expr};
2767+
2768+
if (auto call = dyn_cast<CallExpr>(condition)) {
2769+
if (!call->isImplicit())
2770+
return {true, expr};
2771+
2772+
if (auto DSCE = dyn_cast<DotSyntaxCallExpr>(call->getFn())) {
2773+
if (DSCE->isImplicit())
2774+
IE->setCondExpr(DSCE->getBase());
2775+
}
2776+
}
2777+
}
2778+
2779+
return {true, expr};
2780+
}
2781+
27562782
Expr *walkToExprPost(Expr *expr) override {
27572783
if (auto implicit = dyn_cast<ImplicitConversionExpr>(expr)) {
27582784
// Skip implicit conversions completely.

test/Constraints/diagnostics.swift

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -910,3 +910,18 @@ let _ = SR_2164<Int, Bool>(a: 0) // Ok
910910
let _ = SR_2164<Int, Bool>(b: true) // Ok
911911
SR_2164<Int, Bool, Float>(a: 0) // expected-error {{generic type 'SR_2164' specialized with too many type parameters (got 3, but expected 2)}}
912912
SR_2164<Int, Bool, Float>(b: 0) // expected-error {{generic type 'SR_2164' specialized with too many type parameters (got 3, but expected 2)}}
913+
914+
// <rdar://problem/29850459> Swift compiler misreports type error in ternary expression
915+
916+
let r29850459_flag = true
917+
let r29850459_a: Int = 0
918+
let r29850459_b: Int = 1
919+
func r29850459() -> Bool { return false }
920+
let _ = (r29850459_flag ? r29850459_a : r29850459_b) + 42.0 // expected-error {{binary operator '+' cannot be applied to operands of type 'Int' and 'Double'}}
921+
// expected-note@-1 {{overloads for '+' exist with these partially matching parameter lists: (Int, Int), (Double, Double), (Int, UnsafeMutablePointer<Pointee>), (Int, UnsafePointer<Pointee>)}}
922+
let _ = ({ true }() ? r29850459_a : r29850459_b) + 42.0 // expected-error {{binary operator '+' cannot be applied to operands of type 'Int' and 'Double'}}
923+
// expected-note@-1 {{overloads for '+' exist with these partially matching parameter lists: (Int, Int), (Double, Double), (Int, UnsafeMutablePointer<Pointee>), (Int, UnsafePointer<Pointee>)}}
924+
let _ = (r29850459() ? r29850459_a : r29850459_b) + 42.0 // expected-error {{binary operator '+' cannot be applied to operands of type 'Int' and 'Double'}}
925+
// expected-note@-1 {{overloads for '+' exist with these partially matching parameter lists: (Int, Int), (Double, Double), (Int, UnsafeMutablePointer<Pointee>), (Int, UnsafePointer<Pointee>)}}
926+
let _ = ((r29850459_flag || r29850459()) ? r29850459_a : r29850459_b) + 42.0 // expected-error {{binary operator '+' cannot be applied to operands of type 'Int' and 'Double'}}
927+
// expected-note@-1 {{overloads for '+' exist with these partially matching parameter lists: (Int, Int), (Double, Double), (Int, UnsafeMutablePointer<Pointee>), (Int, UnsafePointer<Pointee>)}}

0 commit comments

Comments
 (0)