@@ -3558,18 +3558,79 @@ Type Solution::simplifyTypeForCodeCompletion(Type Ty) const {
35583558
35593559 // Replace all type variables (which must come from placeholders) by their
35603560 // 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+ }
35683595 }
35693596 }
3597+
35703598 return typeVar;
35713599 });
35723600
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+
35733634 // Remove any remaining type variables and placeholders
35743635 Ty = simplifyType (Ty);
35753636
0 commit comments