@@ -2485,259 +2485,6 @@ IgnoreDefaultExprTypeMismatch::create(ConstraintSystem &cs, Type argType,
2485
2485
IgnoreDefaultExprTypeMismatch (cs, argType, paramType, locator);
2486
2486
}
2487
2487
2488
- bool AddExplicitExistentialCoercion::diagnose (const Solution &solution,
2489
- bool asNote) const {
2490
- MissingExplicitExistentialCoercion failure (solution, ErasedResultType,
2491
- getLocator (), fixBehavior);
2492
- return failure.diagnose (asNote);
2493
- }
2494
-
2495
- bool AddExplicitExistentialCoercion::isRequired (
2496
- ConstraintSystem &cs, Type resultTy,
2497
- llvm::function_ref<llvm::Optional<Type>(TypeVariableType *)>
2498
- findExistentialType,
2499
- ConstraintLocatorBuilder locator) {
2500
- using ExistentialTypeFinder =
2501
- llvm::function_ref<llvm::Optional<Type>(TypeVariableType *)>;
2502
-
2503
- struct CoercionChecker : public TypeWalker {
2504
- bool RequiresCoercion = false ;
2505
-
2506
- ConstraintSystem &cs;
2507
- ExistentialTypeFinder GetExistentialType;
2508
-
2509
- CoercionChecker (ConstraintSystem &cs,
2510
- ExistentialTypeFinder getExistentialType)
2511
- : cs(cs), GetExistentialType(getExistentialType) {}
2512
-
2513
- Action walkToTypePre (Type componentTy) override {
2514
- // In cases where result references a member type, we need to check
2515
- // whether such type would is resolved to concrete or not.
2516
- if (auto *member = componentTy->getAs <DependentMemberType>()) {
2517
- auto memberBaseTy = getBaseTypeOfDependentMemberChain (member);
2518
-
2519
- auto typeVar = memberBaseTy->getAs <TypeVariableType>();
2520
- if (!typeVar)
2521
- return Action::SkipChildren;
2522
-
2523
- // If the base is an opened existential type, let's see whether
2524
- // erase would produce an existential in this case and if so,
2525
- // we need to check whether any requirements are going to be lost
2526
- // in process.
2527
-
2528
- auto existentialType = GetExistentialType (typeVar);
2529
- if (!existentialType)
2530
- return Action::SkipChildren;
2531
-
2532
- auto erasedMemberTy = typeEraseOpenedExistentialReference (
2533
- Type (member), *existentialType, typeVar, TypePosition::Covariant);
2534
-
2535
- // If result is an existential type and the base has `where` clauses
2536
- // associated with its associated types, the call needs a coercion.
2537
- if (erasedMemberTy->isExistentialType () &&
2538
- hasConstrainedAssociatedTypes (member, *existentialType)) {
2539
- RequiresCoercion = true ;
2540
- return Action::Stop;
2541
- }
2542
-
2543
- if (erasedMemberTy->isExistentialType () &&
2544
- erasedMemberTy->hasTypeParameter ()) {
2545
- RequiresCoercion = true ;
2546
- return Action::Stop;
2547
- }
2548
-
2549
- return Action::SkipChildren;
2550
- }
2551
-
2552
- // The case where there is a direct access to opened existential type
2553
- // e.g. `$T` or `[$T]`.
2554
- if (auto *typeVar = componentTy->getAs <TypeVariableType>()) {
2555
- if (auto existentialType = GetExistentialType (typeVar)) {
2556
- RequiresCoercion |= hasAnyConstrainedAssociatedTypes (
2557
- (*existentialType)->getExistentialLayout ());
2558
- return RequiresCoercion ? Action::Stop : Action::SkipChildren;
2559
- }
2560
- }
2561
-
2562
- return Action::Continue;
2563
- }
2564
-
2565
- private:
2566
- // / Check whether the given member type has any of its associated
2567
- // / types constrained by requirements associated with the given
2568
- // / existential type.
2569
- static bool hasConstrainedAssociatedTypes (DependentMemberType *member,
2570
- Type existentialTy) {
2571
- auto layout = existentialTy->getExistentialLayout ();
2572
- for (auto *protocol : layout.getProtocols ()) {
2573
- auto requirementSig = protocol->getRequirementSignature ();
2574
- if (hasConstrainedAssociatedTypes (member,
2575
- requirementSig.getRequirements ()))
2576
- return true ;
2577
- }
2578
- return false ;
2579
- }
2580
-
2581
- // / Check whether the given member type has any of its associated
2582
- // / types constrained by the given requirement set.
2583
- static bool
2584
- hasConstrainedAssociatedTypes (DependentMemberType *member,
2585
- ArrayRef<Requirement> requirements) {
2586
- for (const auto &req : requirements) {
2587
- switch (req.getKind ()) {
2588
- case RequirementKind::SameShape:
2589
- llvm_unreachable (" Same-shape requirement not supported here" );
2590
-
2591
- case RequirementKind::Superclass:
2592
- case RequirementKind::Conformance:
2593
- case RequirementKind::Layout: {
2594
- if (isAnchoredOn (req.getFirstType (), member->getAssocType ()))
2595
- return true ;
2596
- break ;
2597
- }
2598
-
2599
- case RequirementKind::SameType: {
2600
- auto lhsTy = req.getFirstType ();
2601
- auto rhsTy = req.getSecondType ();
2602
-
2603
- if (isAnchoredOn (lhsTy, member->getAssocType ()) ||
2604
- isAnchoredOn (rhsTy, member->getAssocType ()))
2605
- return true ;
2606
-
2607
- break ;
2608
- }
2609
- }
2610
- }
2611
-
2612
- return false ;
2613
- }
2614
-
2615
- // / Check whether any of the protocols mentioned in the given
2616
- // / existential layout have constraints associated with their
2617
- // / associated types via a `where` clause, for example:
2618
- // / `associatedtype A: P where A.B == Int`
2619
- static bool hasAnyConstrainedAssociatedTypes (ExistentialLayout layout) {
2620
- for (auto *protocol : layout.getProtocols ()) {
2621
- auto requirementSig = protocol->getRequirementSignature ();
2622
- for (const auto &req : requirementSig.getRequirements ()) {
2623
- switch (req.getKind ()) {
2624
- case RequirementKind::SameShape:
2625
- llvm_unreachable (" Same-shape requirement not supported here" );
2626
-
2627
- case RequirementKind::Conformance:
2628
- case RequirementKind::Layout:
2629
- case RequirementKind::Superclass: {
2630
- if (getMemberChainDepth (req.getFirstType ()) > 1 )
2631
- return true ;
2632
- break ;
2633
- }
2634
-
2635
- case RequirementKind::SameType:
2636
- auto lhsTy = req.getFirstType ();
2637
- auto rhsTy = req.getSecondType ();
2638
-
2639
- if (getMemberChainDepth (lhsTy) > 1 ||
2640
- getMemberChainDepth (rhsTy) > 1 )
2641
- return true ;
2642
-
2643
- break ;
2644
- }
2645
- }
2646
- }
2647
- return false ;
2648
- }
2649
-
2650
- // / Check whether the given type is a dependent member type and
2651
- // / is anchored on the given associated type e.g. type is `A.B.C`
2652
- // / and associated type is `A.B`.
2653
- static bool isAnchoredOn (Type type, AssociatedTypeDecl *assocTy,
2654
- unsigned depth = 0 ) {
2655
- if (auto *member = type->getAs <DependentMemberType>()) {
2656
- if (member->getAssocType () == assocTy)
2657
- return depth > 0 ;
2658
-
2659
- return isAnchoredOn (member->getBase (), assocTy, depth + 1 );
2660
- }
2661
-
2662
- return false ;
2663
- }
2664
-
2665
- static unsigned getMemberChainDepth (Type type, unsigned currDepth = 0 ) {
2666
- if (auto *memberTy = type->getAs <DependentMemberType>())
2667
- return getMemberChainDepth (memberTy->getBase (), currDepth + 1 );
2668
- return currDepth;
2669
- }
2670
-
2671
- static Type getBaseTypeOfDependentMemberChain (DependentMemberType *member) {
2672
- if (!member->getBase ())
2673
- return member;
2674
-
2675
- auto base = member->getBase ();
2676
-
2677
- if (auto *DMT = base->getAs <DependentMemberType>())
2678
- return getBaseTypeOfDependentMemberChain (DMT);
2679
-
2680
- return base;
2681
- }
2682
- };
2683
-
2684
- // First, let's check whether coercion is already there.
2685
- if (auto *anchor = getAsExpr (locator.getAnchor ())) {
2686
- // If this is erasure related to `Self`, let's look through
2687
- // the call, if any.
2688
- if (auto *UDE = dyn_cast<UnresolvedDotExpr>(anchor)) {
2689
- // If this is an implicit `makeIterator` call, let's skip the check.
2690
- if (UDE->isImplicit () &&
2691
- cs.getContextualTypePurpose (UDE->getBase ()) == CTP_ForEachSequence)
2692
- return false ;
2693
-
2694
- auto parentExpr = cs.getParentExpr (anchor);
2695
- if (parentExpr && isa<CallExpr>(parentExpr))
2696
- anchor = parentExpr;
2697
- }
2698
-
2699
- auto *parent = cs.getParentExpr (anchor);
2700
- // Support both `as` and `as!` coercions.
2701
- if (parent &&
2702
- (isa<CoerceExpr>(parent) || isa<ForcedCheckedCastExpr>(parent)))
2703
- return false ;
2704
- }
2705
-
2706
- CoercionChecker check (cs, findExistentialType);
2707
- resultTy.walk (check);
2708
-
2709
- return check.RequiresCoercion ;
2710
- }
2711
-
2712
- bool AddExplicitExistentialCoercion::isRequired (
2713
- ConstraintSystem &cs, Type resultTy,
2714
- ArrayRef<std::pair<TypeVariableType *, OpenedArchetypeType *>>
2715
- openedExistentials,
2716
- ConstraintLocatorBuilder locator) {
2717
- return isRequired (
2718
- cs, resultTy,
2719
- [&](TypeVariableType *typeVar) -> llvm::Optional<Type> {
2720
- auto opened =
2721
- llvm::find_if (openedExistentials, [&typeVar](const auto &entry) {
2722
- return typeVar == entry.first ;
2723
- });
2724
-
2725
- if (opened == openedExistentials.end ())
2726
- return llvm::None;
2727
-
2728
- return opened->second ->getExistentialType ();
2729
- },
2730
- locator);
2731
- }
2732
-
2733
- AddExplicitExistentialCoercion *
2734
- AddExplicitExistentialCoercion::create (ConstraintSystem &cs, Type resultTy,
2735
- ConstraintLocator *locator) {
2736
- FixBehavior fixBehavior = FixBehavior::Error;
2737
- return new (cs.getAllocator ())
2738
- AddExplicitExistentialCoercion (cs, resultTy, locator, fixBehavior);
2739
- }
2740
-
2741
2488
bool RenameConflictingPatternVariables::diagnose (const Solution &solution,
2742
2489
bool asNote) const {
2743
2490
ConflictingPatternVariables failure (solution, ExpectedType,
0 commit comments