Skip to content

Commit 7af5238

Browse files
committed
AST: Add SubstFlags::DesugarMemberTypes
For code completion to use Type::subst() without undoing previously-added heuristics, we need a form of member lookup that strips the outermost typealias type. For example, if we have protocol P { associatedtype Fruit } struct Apple {} typealias Pear = Apple class Bowl : P { typealias Fruit = Pear } With DesugarMemberTypes OFF, the substitution 'T := Bowl' applied to 'T.Fruit' yields 'Bowl.Fruit'. With DesugarMemberTypes ON, the same substitution instead produces 'Pear' (note: not 'Apple'; we only desugar one level here, to match the current code completion behavior). Also, add another tweak that will become important shortly; if a type witness cannot be derived, set the type witness to an alias type pointing to an error type, instead of directly storing an error type in there.
1 parent e053b3a commit 7af5238

File tree

3 files changed

+19
-4
lines changed

3 files changed

+19
-4
lines changed

include/swift/AST/Type.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ enum class SubstFlags {
6262
/// is just changing between contextual and interface type
6363
/// representations, using Type::subst() is allowed.
6464
AllowLoweredTypes = 0x02,
65+
/// Map member types to their desugared witness type.
66+
DesugarMemberTypes = 0x04,
6567
};
6668

6769
/// Options for performing substitutions into a type.

lib/AST/Type.cpp

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2876,8 +2876,17 @@ static Type getMemberForBaseType(ConformanceSource conformances,
28762876
!conformance->getConcrete()->hasTypeWitness(assocType, nullptr))
28772877
return Type();
28782878

2879-
return conformance->getConcrete()->getTypeWitness(assocType, resolver)
2880-
.getReplacement();
2879+
auto witness = conformance->getConcrete()
2880+
->getTypeWitness(assocType, resolver).getReplacement();
2881+
2882+
// This is a hacky feature allowing code completion to migrate to
2883+
// using Type::subst() without changing output.
2884+
if (options & SubstFlags::DesugarMemberTypes)
2885+
if (auto *aliasType = dyn_cast<NameAliasType>(witness.getPointer()))
2886+
if (!aliasType->is<ErrorType>())
2887+
witness = aliasType->getSinglyDesugaredType();
2888+
2889+
return witness;
28812890
}
28822891

28832892
// FIXME: This is a fallback. We want the above, conformance-based

lib/Sema/TypeCheckProtocol.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1976,9 +1976,13 @@ void ConformanceChecker::recordTypeWitness(AssociatedTypeDecl *assocType,
19761976
DC);
19771977
aliasDecl->computeType();
19781978
aliasDecl->setImplicit();
1979-
if (type->is<ErrorType>())
1979+
if (type->is<ErrorType>()) {
19801980
aliasDecl->setInvalid();
1981-
if (type->hasArchetype()) {
1981+
1982+
// If we're recording a failed type witness, keep the sugar around for
1983+
// code completion.
1984+
type = aliasDecl->getDeclaredType();
1985+
} else if (type->hasArchetype()) {
19821986
Type metaType = MetatypeType::get(type);
19831987
aliasDecl->setInterfaceType(
19841988
ArchetypeBuilder::mapTypeOutOfContext(DC, metaType));

0 commit comments

Comments
 (0)