Skip to content

[ConstraintSystem] Ignore value-to-optional conversions to correctly … #34568

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 4, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 16 additions & 7 deletions lib/Sema/CSSimplify.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2616,11 +2616,22 @@ ConstraintSystem::matchExistentialTypes(Type type1, Type type2,
if (!shouldAttemptFixes())
return getTypeMatchFailure(locator);

SmallVector<LocatorPathElt, 4> path;
auto anchor = locator.getLocatorParts(path);

// If the path ends at `optional payload` it means that this
// check is part of an implicit value-to-optional conversion,
// and it could be safely dropped.
if (!path.empty() && path.back().is<LocatorPathElt::OptionalPayload>())
path.pop_back();

// Determine whether this conformance mismatch is
// associate with argument to a call, and if so
// associated with argument to a call, and if so
// produce a tailored fix.
if (auto last = locator.last()) {
if (last->is<LocatorPathElt::ApplyArgToParam>()) {
if (!path.empty()) {
auto last = path.back();

if (last.is<LocatorPathElt::ApplyArgToParam>()) {
auto *fix = AllowArgumentMismatch::create(
*this, type1, proto, getConstraintLocator(locator));

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

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

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

auto anchor = locator.getAnchor();
if (isExpr<CoerceExpr>(anchor)) {
auto *fix = ContextualMismatch::create(
*this, type1, type2, getConstraintLocator(locator));
Expand Down
10 changes: 10 additions & 0 deletions test/Constraints/protocols.swift
Original file line number Diff line number Diff line change
Expand Up @@ -422,3 +422,13 @@ func test_sr_11609() {
let _: String = foo()
// expected-error@-1 {{local function 'foo' requires that 'String' conform to 'Initable'}}
}

// rdar://70814576 -- failed to produce a diagnostic when implicit value-to-optional conversion is involved.
func rdar70814576() {
struct S {}

func test(_: Fooable?) {
}

test(S()) // expected-error {{argument type 'S' does not conform to expected type 'Fooable'}}
}