File tree Expand file tree Collapse file tree 5 files changed +57
-3
lines changed Expand file tree Collapse file tree 5 files changed +57
-3
lines changed Original file line number Diff line number Diff line change @@ -486,6 +486,10 @@ class TypeVariableType::Implementation {
486486 // / Determine whether this type variable represents a subscript result type.
487487 bool isSubscriptResultType () const ;
488488
489+ // / Determine whether this type variable represents a result type of an
490+ // / application i.e. a call, an operator, or a subscript.
491+ bool isApplicationResultType () const ;
492+
489493 // / Determine whether this type variable represents an opened
490494 // / type parameter pack.
491495 bool isParameterPack () const ;
Original file line number Diff line number Diff line change @@ -1293,9 +1293,16 @@ bool BindingSet::favoredOverDisjunction(Constraint *disjunction) const {
12931293
12941294 return !hasConversions (binding.BindingType );
12951295 })) {
1296- // Result type of subscript could be l-value so we can't bind it early.
1297- if (!TypeVar->getImpl ().isSubscriptResultType () &&
1298- llvm::none_of (Info.DelayedBy , [](const Constraint *constraint) {
1296+ bool isApplicationResultType = TypeVar->getImpl ().isApplicationResultType ();
1297+ if (llvm::none_of (Info.DelayedBy , [&isApplicationResultType](
1298+ const Constraint *constraint) {
1299+ // Let's not attempt to bind result type before application
1300+ // happens. For example because it could be discardable or
1301+ // l-value (subscript applications).
1302+ if (isApplicationResultType &&
1303+ constraint->getKind () == ConstraintKind::ApplicableFunction)
1304+ return true ;
1305+
12991306 return constraint->getKind () == ConstraintKind::Disjunction ||
13001307 constraint->getKind () == ConstraintKind::ValueMember;
13011308 }))
Original file line number Diff line number Diff line change @@ -175,6 +175,16 @@ bool TypeVariableType::Implementation::isSubscriptResultType() const {
175175 KeyPathExpr::Component::Kind::UnresolvedSubscript;
176176}
177177
178+ bool TypeVariableType::Implementation::isApplicationResultType () const {
179+ if (!(locator && locator->getAnchor ()))
180+ return false ;
181+
182+ if (!locator->isLastElement <LocatorPathElt::FunctionResult>())
183+ return false ;
184+
185+ return isExpr<ApplyExpr>(locator->getAnchor ()) || isSubscriptResultType ();
186+ }
187+
178188bool TypeVariableType::Implementation::isParameterPack () const {
179189 return locator
180190 && locator->isForGenericParameter ()
Original file line number Diff line number Diff line change @@ -180,3 +180,20 @@ struct OverloadInImplicitAsyncClosure {
180180
181181 init ( int: Int ) throws { }
182182}
183+
184+ @available ( SwiftStdlib 5 . 5 , * )
185+ func test( _: Int ) async throws { }
186+
187+ @discardableResult
188+ @available ( SwiftStdlib 5 . 5 , * )
189+ func test( _: Int ) -> String { " " }
190+
191+ @available ( SwiftStdlib 5 . 5 , * )
192+ func compute( _: @escaping ( ) -> Void ) { }
193+
194+ @available ( SwiftStdlib 5 . 5 , * )
195+ func test_sync_in_closure_context( ) {
196+ compute {
197+ test ( 42 ) // Ok (select sync overloads and discards the result)
198+ }
199+ }
Original file line number Diff line number Diff line change @@ -1267,3 +1267,19 @@ do {
12671267
12681268// Currently legal.
12691269let _: ( ) -> Int = { return fatalError ( ) }
1270+
1271+ // Make sure that `Void` assigned to closure result doesn't get eagerly propagated into the body
1272+ do {
1273+ class C {
1274+ func f( _: Any ) -> Int ! { fatalError ( ) }
1275+ static func f( _: Any ) -> Int ! { fatalError ( ) }
1276+ }
1277+
1278+ class G < T> {
1279+ func g< U> ( _ u: U , _: ( U , T ) -> ( ) ) { }
1280+
1281+ func g< U: C > ( _ u: U ) {
1282+ g ( u) { $0. f ( $1) } // expected-warning {{result of call to 'f' is unused}}
1283+ }
1284+ }
1285+ }
You can’t perform that action at this time.
0 commit comments