Skip to content

Commit b353723

Browse files
authored
Merge pull request #59902 from xedin/rdar-96469597
[CSApply] A couple of locator adjustments to support updated Double<->CGFloat conversion
2 parents 380e370 + b8cba10 commit b353723

File tree

3 files changed

+79
-13
lines changed

3 files changed

+79
-13
lines changed

lib/Sema/CSApply.cpp

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3541,9 +3541,11 @@ namespace {
35413541

35423542
auto elementType = expr->getElementType();
35433543

3544-
for (auto &element : expr->getElements()) {
3545-
element = coerceToType(element, elementType,
3546-
cs.getConstraintLocator(element));
3544+
for (unsigned i = 0, n = expr->getNumElements(); i != n; ++i) {
3545+
expr->setElement(
3546+
i, coerceToType(expr->getElement(i), elementType,
3547+
cs.getConstraintLocator(
3548+
expr, {LocatorPathElt::TupleElement(i)})));
35473549
}
35483550

35493551
return expr;
@@ -3586,9 +3588,12 @@ namespace {
35863588
expr->setInitializer(witness);
35873589

35883590
auto elementType = expr->getElementType();
3589-
for (auto &element : expr->getElements()) {
3590-
element = coerceToType(element, elementType,
3591-
cs.getConstraintLocator(element));
3591+
3592+
for (unsigned i = 0, n = expr->getNumElements(); i != n; ++i) {
3593+
expr->setElement(
3594+
i, coerceToType(expr->getElement(i), elementType,
3595+
cs.getConstraintLocator(
3596+
expr, {LocatorPathElt::TupleElement(i)})));
35923597
}
35933598

35943599
return expr;
@@ -3790,10 +3795,12 @@ namespace {
37903795
expr->setCondExpr(cond);
37913796

37923797
// Coerce the then/else branches to the common type.
3793-
expr->setThenExpr(coerceToType(expr->getThenExpr(), resultTy,
3794-
cs.getConstraintLocator(expr->getThenExpr())));
3795-
expr->setElseExpr(coerceToType(expr->getElseExpr(), resultTy,
3796-
cs.getConstraintLocator(expr->getElseExpr())));
3798+
expr->setThenExpr(coerceToType(
3799+
expr->getThenExpr(), resultTy,
3800+
cs.getConstraintLocator(expr, LocatorPathElt::TernaryBranch(true))));
3801+
expr->setElseExpr(coerceToType(
3802+
expr->getElseExpr(), resultTy,
3803+
cs.getConstraintLocator(expr, LocatorPathElt::TernaryBranch(false))));
37973804

37983805
return expr;
37993806
}
@@ -4365,9 +4372,12 @@ namespace {
43654372
Expr *visitAssignExpr(AssignExpr *expr) {
43664373
// Convert the source to the simplified destination type.
43674374
auto destTy = simplifyType(cs.getType(expr->getDest()));
4368-
auto locator =
4369-
ConstraintLocatorBuilder(cs.getConstraintLocator(expr->getSrc()));
4370-
Expr *src = coerceToType(expr->getSrc(), destTy->getRValueType(), locator);
4375+
// Conversion is recorded as anchored on an assignment itself by
4376+
// constraint generator and that has to be preserved here in case
4377+
// anything depends on the locator (i.e. Double<->CGFloat implicit
4378+
// conversion).
4379+
Expr *src = coerceToType(expr->getSrc(), destTy->getRValueType(),
4380+
cs.getConstraintLocator(expr));
43714381
if (!src)
43724382
return nullptr;
43734383

@@ -6821,6 +6831,11 @@ Expr *ExprRewriter::coerceToType(Expr *expr, Type toType,
68216831
auto *argExpr = locator.trySimplifyToExpr();
68226832
assert(argExpr);
68236833

6834+
// Source requires implicit conversion to match destination
6835+
// type but the conversion itself is recorded on assignment.
6836+
if (auto *assignment = dyn_cast<AssignExpr>(argExpr))
6837+
argExpr = assignment->getSrc();
6838+
68246839
// Load the value for conversion.
68256840
argExpr = cs.coerceToRValue(argExpr);
68266841

lib/Sema/ConstraintSystem.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -429,6 +429,11 @@ ConstraintLocator *ConstraintSystem::getImplicitValueConversionLocator(
429429
SmallVector<LocatorPathElt, 4> path;
430430
auto anchor = root.getLocatorParts(path);
431431
{
432+
if (isExpr<DictionaryExpr>(anchor) && path.size() > 1) {
433+
// Drop everything except for first `tuple element #`.
434+
path.pop_back_n(path.size() - 1);
435+
}
436+
432437
// Drop any value-to-optional conversions that were applied along the
433438
// way to reach this one.
434439
while (!path.empty()) {

test/Constraints/implicit_double_cgfloat_conversion.swift

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,3 +216,49 @@ func test_multi_argument_conversion_with_optional(d: Double, cgf: CGFloat) {
216216

217217
test(cgf, d) // Ok (CGFloat -> Double and Double? -> CGFloat?)
218218
}
219+
220+
extension CGFloat: Hashable {
221+
public func hash(into hasher: inout Hasher) { fatalError() }
222+
}
223+
224+
func test_collection_literals_as_call_arguments() {
225+
enum E {
226+
case test_arr([CGFloat])
227+
case test_dict_key([CGFloat: String])
228+
case test_dict_value([String: CGFloat])
229+
case test_arr_nested([String: [[CGFloat]: String]])
230+
case test_dict_nested([String: [String: CGFloat]])
231+
}
232+
233+
struct Container {
234+
var prop: E
235+
}
236+
237+
struct Point {
238+
var x: Double
239+
var y: Double
240+
}
241+
242+
func test(cont: inout Container, point: Point) {
243+
cont.prop = .test_arr([point.x]) // Ok
244+
cont.prop = .test_dict_key([point.y: ""]) // Ok
245+
cont.prop = .test_dict_value(["": point.y]) // Ok
246+
cont.prop = .test_arr_nested(["": [[point.x]: ""]]) // Ok
247+
cont.prop = .test_dict_nested(["": ["": point.x]]) // Ok
248+
}
249+
}
250+
251+
func assignments_with_and_without_optionals() {
252+
class C {
253+
var prop: CGFloat = 0
254+
}
255+
256+
func test(c: C?, v: Double, cgf: CGFloat) {
257+
c?.prop = v / 2.0 // Ok
258+
c?.prop = (false ? cgf : v)
259+
260+
let copy = c!
261+
copy.prop = Optional(v) ?? 0 // Ok
262+
copy.prop = (true ? cgf : (false ? v : cgf))
263+
}
264+
}

0 commit comments

Comments
 (0)