diff --git a/include/swift/Sema/ConstraintSystem.h b/include/swift/Sema/ConstraintSystem.h index 1615f3a103244..c0a305f1b8f5a 100644 --- a/include/swift/Sema/ConstraintSystem.h +++ b/include/swift/Sema/ConstraintSystem.h @@ -486,10 +486,6 @@ class TypeVariableType::Implementation { /// Determine whether this type variable represents a subscript result type. bool isSubscriptResultType() const; - /// Determine whether this type variable represents a result type of an - /// application i.e. a call, an operator, or a subscript. - bool isApplicationResultType() const; - /// Determine whether this type variable represents an opened /// type parameter pack. bool isParameterPack() const; diff --git a/lib/Sema/CSBindings.cpp b/lib/Sema/CSBindings.cpp index 30f3d7b346570..7e6a1942faa6b 100644 --- a/lib/Sema/CSBindings.cpp +++ b/lib/Sema/CSBindings.cpp @@ -1208,19 +1208,7 @@ bool BindingSet::isViable(PotentialBinding &binding, bool isTransitive) { if (!existingNTD || NTD != existingNTD) continue; - // What is going on here needs to be thoroughly re-evaluated, - // but at least for now, let's not filter bindings of different - // kinds so if we have a situation like: `Array<$T0> conv $T1` - // and `$T1 conv Array<(String, Int)>` we can't lose `Array<$T0>` - // as a binding because `$T0` could be inferred to - // `(key: String, value: Int)` and binding `$T1` to `Array<(String, Int)>` - // eagerly would be incorrect. - if (existing->Kind != binding.Kind) { - // Array, Set and Dictionary allow conversions, everything else - // requires their generic arguments to match exactly. - if (existingType->isKnownStdlibCollectionType()) - continue; - } + // FIXME: What is going on here needs to be thoroughly re-evaluated. // If new type has a type variable it shouldn't // be considered viable. @@ -1276,8 +1264,7 @@ static bool hasConversions(Type type) { } return !(type->is() || type->is() || - type->is() || type->is() || - type->isVoid()); + type->is() || type->is()); } bool BindingSet::favoredOverDisjunction(Constraint *disjunction) const { @@ -1293,16 +1280,9 @@ bool BindingSet::favoredOverDisjunction(Constraint *disjunction) const { return !hasConversions(binding.BindingType); })) { - bool isApplicationResultType = TypeVar->getImpl().isApplicationResultType(); - if (llvm::none_of(Info.DelayedBy, [&isApplicationResultType]( - const Constraint *constraint) { - // Let's not attempt to bind result type before application - // happens. For example because it could be discardable or - // l-value (subscript applications). - if (isApplicationResultType && - constraint->getKind() == ConstraintKind::ApplicableFunction) - return true; - + // Result type of subscript could be l-value so we can't bind it early. + if (!TypeVar->getImpl().isSubscriptResultType() && + llvm::none_of(Info.DelayedBy, [](const Constraint *constraint) { return constraint->getKind() == ConstraintKind::Disjunction || constraint->getKind() == ConstraintKind::ValueMember; })) diff --git a/lib/Sema/TypeCheckConstraints.cpp b/lib/Sema/TypeCheckConstraints.cpp index d39452130d23f..828ef6b005449 100644 --- a/lib/Sema/TypeCheckConstraints.cpp +++ b/lib/Sema/TypeCheckConstraints.cpp @@ -175,16 +175,6 @@ bool TypeVariableType::Implementation::isSubscriptResultType() const { KeyPathExpr::Component::Kind::UnresolvedSubscript; } -bool TypeVariableType::Implementation::isApplicationResultType() const { - if (!(locator && locator->getAnchor())) - return false; - - if (!locator->isLastElement()) - return false; - - return isExpr(locator->getAnchor()) || isSubscriptResultType(); -} - bool TypeVariableType::Implementation::isParameterPack() const { return locator && locator->isForGenericParameter() diff --git a/test/Constraints/rdar139812024.swift b/test/Constraints/rdar139812024.swift new file mode 100644 index 0000000000000..9f5ab0a0d8862 --- /dev/null +++ b/test/Constraints/rdar139812024.swift @@ -0,0 +1,37 @@ +// RUN: %target-typecheck-verify-swift %clang-importer-sdk + +// REQUIRES: objc_interop + +// rdar://139812024 - error: cannot convert return expression of type 'NSObject' to return type 'NSImage' + +import Foundation + +@objc +final class Image: NSObject { +} + +@available(*, unavailable) +extension Image: Sendable {} // expected-note {{explicitly marked unavailable here}} + +class Lock { + func withLock(_: @Sendable (inout State) -> R) -> R { + fatalError() + } +} + +extension Lock where State == Void { + func withLock(_: @Sendable () -> R) -> R { + fatalError() + } +} + +class Test { + var images: [Int: Image] = [:] + + func fetchImage(lock: Lock, id: Int) -> Image? { + if let existingImage = lock.withLock({ return images[id] }) { // expected-warning {{unavailable}} + return existingImage + } + return nil + } +}