Skip to content

Swap two conditions to get dynamically looked-up optional requirement… #15856

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
Apr 11, 2018
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
52 changes: 25 additions & 27 deletions lib/Sema/ConstraintSystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1675,31 +1675,6 @@ void ConstraintSystem::resolveOverload(ConstraintLocator *locator,
choice.getFunctionRefKind(), locator);
}

if (!isRequirementOrWitness(locator) &&
choice.getDecl()->getAttrs().hasAttribute<OptionalAttr>() &&
!isa<SubscriptDecl>(choice.getDecl())) {
// For a non-subscript declaration that is an optional
// requirement in a protocol, strip off the lvalue-ness (FIXME:
// one cannot assign to such declarations for now) and make a
// reference to that declaration be optional.
//
// Subscript declarations are handled within
// getTypeOfMemberReference(); their result types are optional.

// Deal with values declared as implicitly unwrapped, or
// functions with return types that are implicitly unwrapped.
if (choice.isImplicitlyUnwrappedValueOrReturnValue()) {
// Build the disjunction to attempt binding both T? and T (or
// function returning T? and function returning T).
Type ty = createTypeVariable(locator);
buildDisjunctionForImplicitlyUnwrappedOptional(ty, refType,
locator);
addConstraint(ConstraintKind::Bind, boundType,
OptionalType::get(ty->getRValueType()), locator);
bindConstraintCreated = true;
}
refType = OptionalType::get(refType->getRValueType());
}
// For a non-subscript declaration found via dynamic lookup, strip
// off the lvalue-ness (FIXME: as a temporary hack. We eventually
// want this to work) and make a reference to that declaration be
Expand All @@ -1708,7 +1683,7 @@ void ConstraintSystem::resolveOverload(ConstraintLocator *locator,
// Subscript declarations are handled within
// getTypeOfMemberReference(); their result types are unchecked
// optional.
else if (isDynamicResult) {
if (isDynamicResult) {
if (isa<SubscriptDecl>(choice.getDecl())) {
// We always expect function type for subscripts.
auto fnTy = refType->castTo<AnyFunctionType>();
Expand Down Expand Up @@ -1773,8 +1748,31 @@ void ConstraintSystem::resolveOverload(ConstraintLocator *locator,
}

bindConstraintCreated = true;
}
} else if (!isRequirementOrWitness(locator) &&
choice.getDecl()->getAttrs().hasAttribute<OptionalAttr>() &&
!isa<SubscriptDecl>(choice.getDecl())) {
// For a non-subscript declaration that is an optional
// requirement in a protocol, strip off the lvalue-ness (FIXME:
// one cannot assign to such declarations for now) and make a
// reference to that declaration be optional.
//
// Subscript declarations are handled within
// getTypeOfMemberReference(); their result types are optional.

// Deal with values declared as implicitly unwrapped, or
// functions with return types that are implicitly unwrapped.
if (choice.isImplicitlyUnwrappedValueOrReturnValue()) {
// Build the disjunction to attempt binding both T? and T (or
// function returning T? and function returning T).
Type ty = createTypeVariable(locator);
buildDisjunctionForImplicitlyUnwrappedOptional(ty, refType, locator);
addConstraint(ConstraintKind::Bind, boundType,
OptionalType::get(ty->getRValueType()), locator);
bindConstraintCreated = true;
}

refType = OptionalType::get(refType->getRValueType());
}
// If the declaration is unavailable, note that in the score.
if (choice.getDecl()->getAttrs().isUnavailable(getASTContext())) {
increaseScore(SK_Unavailable);
Expand Down
13 changes: 13 additions & 0 deletions test/Constraints/sr7098.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -typecheck %s
// REQUIRES: objc_interop

import Foundation

class C : NSObject, NSWobbling {
func wobble() {}
func returnMyself() -> Self { return self }
}

func testDynamicOptionalRequirement(_ a: AnyObject) {
a.optionalRequirement?()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where is optionalRequirement defined?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

test/Inputs/clang-importer-sdk/usr/include/Foundation.h line 870.

}