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() {
2350
2350
}
2351
2351
2352
2352
Constraint *ConstraintSystem::selectConjunction () {
2353
+ SmallVector<Constraint *, 4 > conjunctions;
2353
2354
for (auto &constraint : InactiveConstraints) {
2354
2355
if (constraint.isDisabled ())
2355
2356
continue ;
2356
2357
2357
2358
if (constraint.getKind () == ConstraintKind::Conjunction)
2358
- return &constraint;
2359
+ conjunctions. push_back ( &constraint) ;
2359
2360
}
2360
2361
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 ();
2362
2386
}
2363
2387
2364
2388
bool DisjunctionChoice::attempt (ConstraintSystem &cs) const {
Original file line number Diff line number Diff line change 1
-
2
1
// RUN: %target-typecheck-verify-swift -swift-version 5 -enable-experimental-static-assert
3
2
4
3
func isInt< T> ( _ value: T ) -> Bool {
@@ -626,3 +625,28 @@ do {
626
625
}
627
626
}
628
627
}
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 {
22
22
return arr. compactMap { i in
23
23
var flag = false
24
24
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
26
26
guard let a = try ? u. foo ( ) else { return nil }
27
27
return a. value!
28
28
} . contains {
You can’t perform that action at this time.
0 commit comments