File tree Expand file tree Collapse file tree 3 files changed +52
-4
lines changed
validation-test/compiler_crashers_2_fixed Expand file tree Collapse file tree 3 files changed +52
-4
lines changed Original file line number Diff line number Diff line change @@ -2350,15 +2350,39 @@ Constraint *ConstraintSystem::selectDisjunction() {
23502350}
23512351
23522352Constraint *ConstraintSystem::selectConjunction () {
2353+ SmallVector<Constraint *, 4 > conjunctions;
23532354 for (auto &constraint : InactiveConstraints) {
23542355 if (constraint.isDisabled ())
23552356 continue ;
23562357
23572358 if (constraint.getKind () == ConstraintKind::Conjunction)
2358- return &constraint;
2359+ conjunctions. push_back ( &constraint) ;
23592360 }
23602361
2361- return nullptr ;
2362+ if (conjunctions.empty ())
2363+ return nullptr ;
2364+
2365+ auto &SM = getASTContext ().SourceMgr ;
2366+
2367+ // All of the multi-statement closures should be solved in order of their
2368+ // apperance in the source.
2369+ llvm::sort (
2370+ conjunctions, [&](Constraint *conjunctionA, Constraint *conjunctionB) {
2371+ auto *locA = conjunctionA->getLocator ();
2372+ auto *locB = conjunctionB->getLocator ();
2373+
2374+ if (!(locA && locB))
2375+ return false ;
2376+
2377+ auto *closureA = getAsExpr<ClosureExpr>(locA->getAnchor ());
2378+ auto *closureB = getAsExpr<ClosureExpr>(locB->getAnchor ());
2379+
2380+ return closureA && closureB
2381+ ? SM.isBeforeInBuffer (closureA->getLoc (), closureB->getLoc ())
2382+ : false ;
2383+ });
2384+
2385+ return conjunctions.front ();
23622386}
23632387
23642388bool DisjunctionChoice::attempt (ConstraintSystem &cs) const {
Original file line number Diff line number Diff line change 1-
21// RUN: %target-typecheck-verify-swift -swift-version 5 -enable-experimental-static-assert
32
43func isInt< T> ( _ value: T ) -> Bool {
@@ -626,3 +625,28 @@ do {
626625 }
627626 }
628627}
628+
629+ // Test to make sure that type-checker doesn't attempt the closure passed to
630+ // `.filter` before the one from `.init`, otherwise it would mean that generic
631+ // parameter of `.filter` wouldn't be inferred since it depends on result of
632+ // `.init` closure.
633+ func test_that_closures_are_attempted_in_order( ) {
634+ struct Test < T> {
635+ init ( _: ( [ Int ] ) -> T ) { }
636+ init ( _: String ) { }
637+ init ( _: Int , _: String = " " ) { }
638+
639+ func filter( _: ( T ) -> Bool ) { }
640+ }
641+
642+ Test {
643+ _ = 42
644+ return $0. map { Optional ( Float ( $0) ) }
645+ }
646+ . filter {
647+ if $0. isEmpty { // Ok
648+ return true
649+ }
650+ return false
651+ }
652+ }
Original file line number Diff line number Diff line change @@ -22,7 +22,7 @@ func foo(arr: [E], other: P) -> Bool {
2222 return arr. compactMap { i in
2323 var flag = false
2424 return try ? i. getB ( & flag)
25- } . compactMap { u -> P ? in // expected-error {{unable to infer type of a closure parameter 'u' in the current context}}
25+ } . compactMap { u -> P ? in // Ok
2626 guard let a = try ? u. foo ( ) else { return nil }
2727 return a. value!
2828 } . contains {
You can’t perform that action at this time.
0 commit comments