@@ -1892,7 +1892,7 @@ getGenericParamForHoleTypeVar(TypeVariableType *tv, const Solution &S) {
18921892}
18931893
18941894static Type replacePlaceholderType (PlaceholderType *placeholder,
1895- const Solution &S) {
1895+ const Solution &S, bool forCompletion ) {
18961896 auto &ctx = S.getConstraintSystem ().getASTContext ();
18971897 auto origTy = [&]() -> Type {
18981898 auto orig = placeholder->getOriginator ();
@@ -1920,13 +1920,23 @@ static Type replacePlaceholderType(PlaceholderType *placeholder,
19201920 if (isa<TypeVariableType>(replacement.getPointer ()))
19211921 return ErrorType::get (ctx);
19221922
1923+ // For completion, we want to produce an archetype instead of an ErrorType
1924+ // for a top-level generic parameter.
1925+ // FIXME: This is pretty weird, we're producing a contextual type outside of
1926+ // the context it exists in. We ought to see if we can make the completion
1927+ // logic work with ErrorTypes instead.
1928+ if (forCompletion) {
1929+ if (auto *GP = replacement->getAs <GenericTypeParamType>())
1930+ return GP->getDecl ()->getInnermostDeclContext ()->mapTypeIntoContext (GP);
1931+ }
19231932 // Return an ErrorType with the replacement as the original type. Note that
19241933 // if we failed to replace a type variable with a generic parameter in a
19251934 // dependent member, `ErrorType::get` will fold it away.
19261935 return ErrorType::get (replacement);
19271936}
19281937
1929- Type Solution::simplifyType (Type type, bool wantInterfaceType) const {
1938+ Type Solution::simplifyType (Type type, bool wantInterfaceType,
1939+ bool forCompletion) const {
19301940 // If we've been asked for an interface type, start by mapping any archetypes
19311941 // out of context.
19321942 if (wantInterfaceType)
@@ -1966,7 +1976,7 @@ Type Solution::simplifyType(Type type, bool wantInterfaceType) const {
19661976 auto *typePtr = type.getPointer ();
19671977
19681978 if (auto *placeholder = dyn_cast<PlaceholderType>(typePtr))
1969- return replacePlaceholderType (placeholder, *this );
1979+ return replacePlaceholderType (placeholder, *this , forCompletion );
19701980
19711981 if (isa<TypeVariableType>(typePtr))
19721982 return ErrorType::get (ctx);
@@ -1980,136 +1990,8 @@ Type Solution::simplifyType(Type type, bool wantInterfaceType) const {
19801990}
19811991
19821992Type Solution::simplifyTypeForCodeCompletion (Type Ty) const {
1983- auto &CS = getConstraintSystem ();
1984-
1985- // First, instantiate all type variables that we know, but don't replace
1986- // placeholders by unresolved types.
1987- Ty = CS.simplifyTypeImpl (Ty, [this ](TypeVariableType *typeVar) -> Type {
1988- return getFixedType (typeVar);
1989- });
1990-
1991- // Next, replace all placeholders by type variables. We know that all type
1992- // variables now in the type originate from placeholders.
1993- Ty = Ty.transformRec ([](Type type) -> std::optional<Type> {
1994- if (auto *placeholder = type->getAs <PlaceholderType>()) {
1995- if (auto *typeVar =
1996- placeholder->getOriginator ().dyn_cast <TypeVariableType *>()) {
1997- return Type (typeVar);
1998- }
1999- }
2000-
2001- return std::nullopt ;
2002- });
2003-
2004- // Replace all type variables (which must come from placeholders) by their
2005- // generic parameters. Because we call into simplifyTypeImpl
2006- Ty = CS.simplifyTypeImpl (Ty, [&CS, this ](TypeVariableType *typeVar) -> Type {
2007- // Code completion depends on generic parameter type being represented in
2008- // terms of `ArchetypeType` since it's easy to extract protocol requirements
2009- // from it.
2010- auto getTypeVarAsArchetype = [](TypeVariableType *typeVar) -> Type {
2011- if (auto *GP = typeVar->getImpl ().getGenericParameter ()) {
2012- if (auto *GPD = GP->getDecl ()) {
2013- return GPD->getInnermostDeclContext ()->mapTypeIntoContext (GP);
2014- }
2015- }
2016- return Type ();
2017- };
2018-
2019- if (auto archetype = getTypeVarAsArchetype (typeVar)) {
2020- return archetype;
2021- }
2022-
2023- // Sometimes the type variable itself doesn't have have an originator that
2024- // can be replaced by an archetype but one of its equivalent type variable
2025- // does.
2026- // Search thorough all equivalent type variables, looking for one that can
2027- // be replaced by a generic parameter.
2028- std::vector<std::pair<TypeVariableType *, Type>> bindings (
2029- typeBindings.begin (), typeBindings.end ());
2030- // Make sure we iterate the bindings in a deterministic order.
2031- llvm::sort (bindings, [](const std::pair<TypeVariableType *, Type> &lhs,
2032- const std::pair<TypeVariableType *, Type> &rhs) {
2033- return lhs.first ->getID () < rhs.first ->getID ();
2034- });
2035- for (auto binding : bindings) {
2036- if (auto placeholder = binding.second ->getAs <PlaceholderType>()) {
2037- if (placeholder->getOriginator ().dyn_cast <TypeVariableType *>() ==
2038- typeVar) {
2039- if (auto archetype = getTypeVarAsArchetype (binding.first )) {
2040- return archetype;
2041- }
2042- }
2043- }
2044- }
2045-
2046- // When applying the logic below to get contextual types inside result
2047- // builders, the code completion type variable is connected by a one-way
2048- // constraint to a type variable in the buildBlock call, but that is not the
2049- // type variable that represents the argument type. We need to find the type
2050- // variable representing the argument to retrieve protocol requirements from
2051- // it. Look for a ArgumentConversion constraint that allows us to retrieve
2052- // the argument type var.
2053- auto &cg = CS.getConstraintGraph ();
2054-
2055- // FIXME: The type variable is not going to be part of the constraint graph
2056- // at this point unless it was created at the outermost decision level;
2057- // otherwise it has already been rolled back! Work around this by creating
2058- // an empty node if one doesn't exist.
2059- cg.addTypeVariable (typeVar);
2060-
2061- for (auto argConstraint : cg[typeVar].getConstraints ()) {
2062- if (argConstraint->getKind () == ConstraintKind::ArgumentConversion &&
2063- argConstraint->getFirstType ()->getRValueType ()->isEqual (typeVar)) {
2064- if (auto argTV =
2065- argConstraint->getSecondType ()->getAs <TypeVariableType>()) {
2066- if (auto archetype = getTypeVarAsArchetype (argTV)) {
2067- return archetype;
2068- }
2069- }
2070- }
2071- }
2072-
2073- return typeVar;
2074- });
2075-
2076- // Logic to determine the contextual type inside buildBlock result builders:
2077- //
2078- // When completing inside a result builder, the result builder
2079- // @ViewBuilder var body: some View {
2080- // Text("Foo")
2081- // #^COMPLETE^#
2082- // }
2083- // gets rewritten to
2084- // @ViewBuilder var body: some View {
2085- // let $__builder2: Text
2086- // let $__builder0 = Text("Foo")
2087- // let $__builder1 = #^COMPLETE^#
2088- // $__builder2 = ViewBuilder.buildBlock($__builder0, $__builder1)
2089- // return $__builder2
2090- // }
2091- // Inside the constraint system
2092- // let $__builder1 = #^COMPLETE^#
2093- // gets type checked without context, so we can't know the contextual type for
2094- // the code completion token. But we know that $__builder1 (and thus the type
2095- // of #^COMPLETE^#) is used as the second argument to ViewBuilder.buildBlock,
2096- // so we can extract the contextual type from that call. To do this, figure
2097- // out the type variable that is used for $__builder1 in the buildBlock call.
2098- // This type variable is connected to the type variable of $__builder1's
2099- // definition by a one-way constraint.
2100- if (auto TV = Ty->getAs <TypeVariableType>()) {
2101- for (auto constraint : CS.getConstraintGraph ()[TV].getConstraints ()) {
2102- if (constraint->getKind () == ConstraintKind::OneWayEqual &&
2103- constraint->getSecondType ()->isEqual (TV)) {
2104- return simplifyTypeForCodeCompletion (constraint->getFirstType ());
2105- }
2106- }
2107- }
2108-
2109- // Remove any remaining type variables and placeholders
2110- Ty = simplifyType (Ty);
2111-
2112- return Ty->getRValueType ();
1993+ return simplifyType (Ty, /* wantInterfaceType*/ false , /* forCompletion*/ true )
1994+ ->getRValueType ();
21131995}
21141996
21151997template <typename T>
0 commit comments