Skip to content

Commit fa5c712

Browse files
committed
[ConstraintSystem] Ignore value-to-optional conversions to correctly detect conformance failures
If there is a conformance failure related to existential conversion let's ignore that fact that there could be an implicit value-to-optional conversion involved, because it's not the main issue in cases like that. Resolves: rdar://problem/70814576
1 parent 15d566d commit fa5c712

File tree

2 files changed

+26
-7
lines changed

2 files changed

+26
-7
lines changed

lib/Sema/CSSimplify.cpp

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2616,11 +2616,22 @@ ConstraintSystem::matchExistentialTypes(Type type1, Type type2,
26162616
if (!shouldAttemptFixes())
26172617
return getTypeMatchFailure(locator);
26182618

2619+
SmallVector<LocatorPathElt, 4> path;
2620+
auto anchor = locator.getLocatorParts(path);
2621+
2622+
// If the path ends at `optional payload` it means that this
2623+
// check is part of an implicit value-to-optional conversion,
2624+
// and it could be safely dropped.
2625+
if (!path.empty() && path.back().is<LocatorPathElt::OptionalPayload>())
2626+
path.pop_back();
2627+
26192628
// Determine whether this conformance mismatch is
2620-
// associate with argument to a call, and if so
2629+
// associated with argument to a call, and if so
26212630
// produce a tailored fix.
2622-
if (auto last = locator.last()) {
2623-
if (last->is<LocatorPathElt::ApplyArgToParam>()) {
2631+
if (!path.empty()) {
2632+
auto last = path.back();
2633+
2634+
if (last.is<LocatorPathElt::ApplyArgToParam>()) {
26242635
auto *fix = AllowArgumentMismatch::create(
26252636
*this, type1, proto, getConstraintLocator(locator));
26262637

@@ -2643,21 +2654,19 @@ ConstraintSystem::matchExistentialTypes(Type type1, Type type2,
26432654
//
26442655
// Once either reacher locators or better diagnostic presentation for
26452656
// nested type failures is available this check could be removed.
2646-
if (last->is<LocatorPathElt::FunctionResult>())
2657+
if (last.is<LocatorPathElt::FunctionResult>())
26472658
return getTypeMatchFailure(locator);
26482659

26492660
// If instance types didn't line up correctly, let's produce a
26502661
// diagnostic which mentions them together with their metatypes.
2651-
if (last->is<LocatorPathElt::InstanceType>())
2662+
if (last.is<LocatorPathElt::InstanceType>())
26522663
return getTypeMatchFailure(locator);
26532664

26542665
} else { // There are no elements in the path
2655-
auto anchor = locator.getAnchor();
26562666
if (!(isExpr<AssignExpr>(anchor) || isExpr<CoerceExpr>(anchor)))
26572667
return getTypeMatchFailure(locator);
26582668
}
26592669

2660-
auto anchor = locator.getAnchor();
26612670
if (isExpr<CoerceExpr>(anchor)) {
26622671
auto *fix = ContextualMismatch::create(
26632672
*this, type1, type2, getConstraintLocator(locator));

test/Constraints/protocols.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -422,3 +422,13 @@ func test_sr_11609() {
422422
let _: String = foo()
423423
// expected-error@-1 {{local function 'foo' requires that 'String' conform to 'Initable'}}
424424
}
425+
426+
// rdar://70814576 -- failed to produce a diagnostic when implicit value-to-optional conversion is involved.
427+
func rdar70814576() {
428+
struct S {}
429+
430+
func test(_: Fooable?) {
431+
}
432+
433+
test(S()) // expected-error {{argument type 'S' does not conform to expected type 'Fooable'}}
434+
}

0 commit comments

Comments
 (0)