@@ -3558,18 +3558,79 @@ Type Solution::simplifyTypeForCodeCompletion(Type Ty) const {
3558
3558
3559
3559
// Replace all type variables (which must come from placeholders) by their
3560
3560
// generic parameters. Because we call into simplifyTypeImpl
3561
- Ty = CS.simplifyTypeImpl (Ty, [](TypeVariableType *typeVar) -> Type {
3562
- if (auto *GP = typeVar->getImpl ().getGenericParameter ()) {
3563
- // Code completion depends on generic parameter type being
3564
- // represented in terms of `ArchetypeType` since it's easy
3565
- // to extract protocol requirements from it.
3566
- if (auto *GPD = GP->getDecl ()) {
3567
- return GPD->getInnermostDeclContext ()->mapTypeIntoContext (GP);
3561
+ Ty = CS.simplifyTypeImpl (Ty, [&CS](TypeVariableType *typeVar) -> Type {
3562
+ // Code completion depends on generic parameter type being represented in
3563
+ // terms of `ArchetypeType` since it's easy to extract protocol requirements
3564
+ // from it.
3565
+ auto getTypeVarAsArchetype = [](TypeVariableType *typeVar) -> Type {
3566
+ if (auto *GP = typeVar->getImpl ().getGenericParameter ()) {
3567
+ if (auto *GPD = GP->getDecl ()) {
3568
+ return GPD->getInnermostDeclContext ()->mapTypeIntoContext (GP);
3569
+ }
3570
+ }
3571
+ return Type ();
3572
+ };
3573
+
3574
+ if (auto archetype = getTypeVarAsArchetype (typeVar)) {
3575
+ return archetype;
3576
+ }
3577
+
3578
+ // When applying the logic below to get contextual types inside result
3579
+ // builders, the code completion type variable is connected by a one-way
3580
+ // constraint to a type variable in the buildBlock call, but that is not the
3581
+ // type variable that represents the argument type. We need to find the type
3582
+ // variable representing the argument to retrieve protocol requirements from
3583
+ // it. Look for a ArgumentConversion constraint that allows us to retrieve
3584
+ // the argument type var.
3585
+ for (auto argConstraint :
3586
+ CS.getConstraintGraph ()[typeVar].getConstraints ()) {
3587
+ if (argConstraint->getKind () == ConstraintKind::ArgumentConversion &&
3588
+ argConstraint->getFirstType ()->getRValueType ()->isEqual (typeVar)) {
3589
+ if (auto argTV =
3590
+ argConstraint->getSecondType ()->getAs <TypeVariableType>()) {
3591
+ if (auto archetype = getTypeVarAsArchetype (argTV)) {
3592
+ return archetype;
3593
+ }
3594
+ }
3568
3595
}
3569
3596
}
3597
+
3570
3598
return typeVar;
3571
3599
});
3572
3600
3601
+ // Logic to determine the contextual type inside buildBlock result builders:
3602
+ //
3603
+ // When completing inside a result builder, the result builder
3604
+ // @ViewBuilder var body: some View {
3605
+ // Text("Foo")
3606
+ // #^COMPLETE^#
3607
+ // }
3608
+ // gets rewritten to
3609
+ // @ViewBuilder var body: some View {
3610
+ // let $__builder2: Text
3611
+ // let $__builder0 = Text("Foo")
3612
+ // let $__builder1 = #^COMPLETE^#
3613
+ // $__builder2 = ViewBuilder.buildBlock($__builder0, $__builder1)
3614
+ // return $__builder2
3615
+ // }
3616
+ // Inside the constraint system
3617
+ // let $__builder1 = #^COMPLETE^#
3618
+ // gets type checked without context, so we can't know the contexutal type for
3619
+ // the code completion token. But we know that $__builder1 (and thus the type
3620
+ // of #^COMPLETE^#) is used as the second argument to ViewBuilder.buildBlock,
3621
+ // so we can extract the contextual type from that call. To do this, figure
3622
+ // out the type variable that is used for $__builder1 in the buildBlock call.
3623
+ // This type variable is connected to the type variable of $__builder1's
3624
+ // definition by a one-way constraint.
3625
+ if (auto TV = Ty->getAs <TypeVariableType>()) {
3626
+ for (auto constraint : CS.getConstraintGraph ()[TV].getConstraints ()) {
3627
+ if (constraint->getKind () == ConstraintKind::OneWayEqual &&
3628
+ constraint->getSecondType ()->isEqual (TV)) {
3629
+ return simplifyTypeForCodeCompletion (constraint->getFirstType ());
3630
+ }
3631
+ }
3632
+ }
3633
+
3573
3634
// Remove any remaining type variables and placeholders
3574
3635
Ty = simplifyType (Ty);
3575
3636
0 commit comments