Skip to content

Commit 35f79e4

Browse files
authored
Merge pull request #79585 from hamishknight/leaps-and-bounds
[Completion] Remove uses of unbounded generic types
2 parents e5cd36e + 8975bf6 commit 35f79e4

17 files changed

+96
-76
lines changed

include/swift/IDE/CompletionLookup.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,11 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
185185
/// \p selfTy must be a \c Self type of the context.
186186
static bool canBeUsedAsRequirementFirstType(Type selfTy, TypeAliasDecl *TAD);
187187

188+
/// Retrieve the type to use as the base for a member completion.
189+
Type getMemberBaseType() const {
190+
return BaseType ? BaseType : ExprType;
191+
}
192+
188193
public:
189194
struct RequestedResultsTy {
190195
const ModuleDecl *TheModule;

lib/IDE/CodeCompletionResultType.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -395,8 +395,7 @@ static TypeRelation calculateTypeRelation(Type Ty, Type ExpectedTy,
395395

396396
// Equality/Conversion of GenericTypeParameterType won't account for
397397
// requirements – ignore them
398-
if (!Ty->hasTypeParameter() && !ExpectedTy->hasTypeParameter() &&
399-
!Ty->hasUnboundGenericType() && !ExpectedTy->hasUnboundGenericType()) {
398+
if (!Ty->hasTypeParameter() && !ExpectedTy->hasTypeParameter()) {
400399
if (Ty->isEqual(ExpectedTy))
401400
return TypeRelation::Convertible;
402401
bool isAny = false;

lib/IDE/CompletionLookup.cpp

Lines changed: 34 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -89,11 +89,11 @@ static Type defaultTypeLiteralKind(CodeCompletionLiteralKind kind,
8989
case CodeCompletionLiteralKind::ArrayLiteral:
9090
if (!Ctx.getArrayDecl())
9191
return Type();
92-
return Ctx.getArrayDecl()->getDeclaredType();
92+
return Ctx.getArrayDecl()->getDeclaredInterfaceType();
9393
case CodeCompletionLiteralKind::DictionaryLiteral:
9494
if (!Ctx.getDictionaryDecl())
9595
return Type();
96-
return Ctx.getDictionaryDecl()->getDeclaredType();
96+
return Ctx.getDictionaryDecl()->getDeclaredInterfaceType();
9797
case CodeCompletionLiteralKind::NilLiteral:
9898
case CodeCompletionLiteralKind::ColorLiteral:
9999
case CodeCompletionLiteralKind::ImageLiteral:
@@ -603,7 +603,7 @@ Type CompletionLookup::getTypeOfMember(const ValueDecl *VD,
603603
DynamicLookupInfo dynamicLookupInfo) {
604604
switch (dynamicLookupInfo.getKind()) {
605605
case DynamicLookupInfo::None:
606-
return getTypeOfMember(VD, this->ExprType);
606+
return getTypeOfMember(VD, getMemberBaseType());
607607
case DynamicLookupInfo::AnyObject:
608608
return getTypeOfMember(VD, Type());
609609
case DynamicLookupInfo::KeyPathDynamicMember: {
@@ -676,7 +676,14 @@ Type CompletionLookup::getTypeOfMember(const ValueDecl *VD,
676676
}
677677

678678
Type CompletionLookup::getTypeOfMember(const ValueDecl *VD, Type ExprType) {
679-
Type T = VD->getInterfaceType();
679+
Type T;
680+
if (auto *TD = dyn_cast<TypeDecl>(VD)) {
681+
// For a type decl we're interested in the declared interface type, i.e
682+
// we don't want a metatype.
683+
T = TD->getDeclaredInterfaceType();
684+
} else {
685+
T = VD->getInterfaceType();
686+
}
680687
assert(!T.isNull());
681688

682689
if (ExprType) {
@@ -763,9 +770,7 @@ Type CompletionLookup::getTypeOfMember(const ValueDecl *VD, Type ExprType) {
763770
}
764771

765772
Type CompletionLookup::getAssociatedTypeType(const AssociatedTypeDecl *ATD) {
766-
Type BaseTy = BaseType;
767-
if (!BaseTy)
768-
BaseTy = ExprType;
773+
Type BaseTy = getMemberBaseType();
769774
if (!BaseTy && CurrDeclContext)
770775
BaseTy =
771776
CurrDeclContext->getInnermostTypeContext()->getDeclaredTypeInContext();
@@ -1709,13 +1714,16 @@ void CompletionLookup::addNominalTypeRef(const NominalTypeDecl *NTD,
17091714
addLeadingDot(Builder);
17101715
Builder.addBaseName(NTD->getName().str());
17111716

1717+
// Substitute the base type for a nested type if needed.
1718+
auto nominalTy = getTypeOfMember(NTD, dynamicLookupInfo);
1719+
17121720
// "Fake" annotation for custom attribute types.
17131721
SmallVector<char, 0> stash;
17141722
StringRef customAttributeAnnotation = getTypeAnnotationString(NTD, stash);
17151723
if (!customAttributeAnnotation.empty()) {
17161724
Builder.addTypeAnnotation(customAttributeAnnotation);
17171725
} else {
1718-
addTypeAnnotation(Builder, NTD->getDeclaredType());
1726+
addTypeAnnotation(Builder, nominalTy);
17191727
}
17201728

17211729
// Override the type relation for NominalTypes. Use the better relation
@@ -1725,8 +1733,7 @@ void CompletionLookup::addNominalTypeRef(const NominalTypeDecl *NTD,
17251733
// func receiveMetatype(_: Int.Type) {}
17261734
//
17271735
// We want to suggest 'Int' as 'Identical' for both arguments.
1728-
Builder.setResultTypes(
1729-
{NTD->getInterfaceType(), NTD->getDeclaredInterfaceType()});
1736+
Builder.setResultTypes({MetatypeType::get(nominalTy), nominalTy});
17301737
Builder.setTypeContext(expectedTypeContext, CurrDeclContext);
17311738
}
17321739

@@ -1739,17 +1746,18 @@ void CompletionLookup::addTypeAliasRef(const TypeAliasDecl *TAD,
17391746
Builder.setAssociatedDecl(TAD);
17401747
addLeadingDot(Builder);
17411748
Builder.addBaseName(TAD->getName().str());
1742-
if (auto underlyingType = TAD->getUnderlyingType()) {
1743-
if (underlyingType->hasError()) {
1744-
addTypeAnnotation(Builder,
1745-
TAD->isGeneric()
1746-
? TAD->getUnboundGenericType()
1747-
: TAD->getDeclaredInterfaceType());
17481749

1749-
} else {
1750-
addTypeAnnotation(Builder, underlyingType);
1751-
}
1750+
// Substitute the base type for a nested typealias if needed.
1751+
auto ty = getTypeOfMember(TAD, dynamicLookupInfo);
1752+
1753+
// If the underlying type has an error, prefer to print the full typealias,
1754+
// otherwise get the underlying type.
1755+
if (auto *TA = dyn_cast<TypeAliasType>(ty.getPointer())) {
1756+
auto underlyingTy = TA->getSinglyDesugaredType();
1757+
if (!underlyingTy->hasError())
1758+
ty = underlyingTy;
17521759
}
1760+
addTypeAnnotation(Builder, ty);
17531761
}
17541762

17551763
void CompletionLookup::addGenericTypeParamRef(
@@ -3010,11 +3018,14 @@ void CompletionLookup::getGenericRequirementCompletions(
30103018
/*includeDerivedRequirements*/ false,
30113019
/*includeProtocolExtensionMembers*/ true);
30123020
// We not only allow referencing nested types/typealiases directly, but also
3013-
// qualified by the current type. Thus also suggest current self type so the
3021+
// qualified by the current type, as long as it's a top-level type (nested
3022+
// types need to be qualified). Thus also suggest current self type so the
30143023
// user can do a memberwise lookup on it.
3015-
if (auto SelfType = typeContext->getSelfNominalTypeDecl()) {
3016-
addNominalTypeRef(SelfType, DeclVisibilityKind::LocalDecl,
3017-
DynamicLookupInfo());
3024+
if (auto *NTD = typeContext->getSelfNominalTypeDecl()) {
3025+
if (!NTD->getDeclContext()->isTypeContext()) {
3026+
addNominalTypeRef(NTD, DeclVisibilityKind::LocalDecl,
3027+
DynamicLookupInfo());
3028+
}
30183029
}
30193030

30203031
// Self is also valid in all cases in which it can be used in function

lib/IDE/TypeCheckCompletionCallback.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,10 @@ Type swift::ide::getTypeForCompletion(const constraints::Solution &S,
5151
// Use the contextual type, unless it is still unresolved, in which case fall
5252
// back to getting the type from the expression.
5353
if (auto ContextualType = S.getContextualType(Node)) {
54-
if (!ContextualType->hasUnresolvedType())
54+
if (!ContextualType->hasUnresolvedType() &&
55+
!ContextualType->hasUnboundGenericType()) {
5556
return ContextualType;
57+
}
5658
}
5759

5860
if (!S.hasType(Node)) {

test/IDE/complete_annotation.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,8 @@ func testGlobal() {
3535
// GLOBAL_EXPR-DAG: Literal[Boolean]/None: <name>false</name>; typename=<typeid.sys>Bool</typeid.sys>;
3636
// GLOBAL_EXPR-DAG: Literal[Nil]/None: <name>nil</name>; typename=;
3737
// GLOBAL_EXPR-DAG: Literal[String]/None: &quot;<callarg><callarg.param>abc</callarg.param></callarg>&quot;; typename=<typeid.sys>String</typeid.sys>;
38-
// GLOBAL_EXPR-DAG: Literal[Array]/None: [<callarg><callarg.param>values</callarg.param></callarg>]; typename=<typeid.sys>Array</typeid.sys>;
39-
// GLOBAL_EXPR-DAG: Literal[Dictionary]/None: [<callarg><callarg.param>key</callarg.param></callarg>: <callarg><callarg.param>value</callarg.param></callarg>]; typename=<typeid.sys>Dictionary</typeid.sys>;
38+
// GLOBAL_EXPR-DAG: Literal[Array]/None: [<callarg><callarg.param>values</callarg.param></callarg>]; typename=<typeid.sys>Array</typeid.sys>&lt;<typeid.sys>Element</typeid.sys>&gt;;
39+
// GLOBAL_EXPR-DAG: Literal[Dictionary]/None: [<callarg><callarg.param>key</callarg.param></callarg>: <callarg><callarg.param>value</callarg.param></callarg>]; typename=<typeid.sys>Dictionary</typeid.sys>&lt;<typeid.sys>Key</typeid.sys>, <typeid.sys>Value</typeid.sys>&gt;;
4040
// GLOBAL_EXPR-DAG: Literal[_Color]/None: <name>#colorLiteral</name>(<callarg><callarg.label>red</callarg.label>: <callarg.type><typeid.sys>Float</typeid.sys></callarg.type></callarg>, <callarg><callarg.label>green</callarg.label>: <callarg.type><typeid.sys>Float</typeid.sys></callarg.type></callarg>, <callarg><callarg.label>blue</callarg.label>: <callarg.type><typeid.sys>Float</typeid.sys></callarg.type></callarg>, <callarg><callarg.label>alpha</callarg.label>: <callarg.type><typeid.sys>Float</typeid.sys></callarg.type></callarg>); typename=;
4141
// GLOBAL_EXPR-DAG: Literal[_Image]/None: <name>#imageLiteral</name>(<callarg><callarg.label>resourceName</callarg.label>: <callarg.type><typeid.sys>String</typeid.sys></callarg.type></callarg>); typename=;
4242
// GLOBAL_EXPR-DAG: Literal[Tuple]/None: (<callarg><callarg.param>values</callarg.param></callarg>); typename=;

test/IDE/complete_at_top_level_library.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,8 @@ protocol MyProtocol {}
7070
// LIBRARY-DAG: Literal[Boolean]/None/Flair[ExprAtFileScope]: false[#Bool#]; name=false
7171
// LIBRARY-DAG: Literal[Nil]/None/Flair[ExprAtFileScope]: nil; name=nil
7272
// LIBRARY-DAG: Literal[String]/None/Flair[ExprAtFileScope]: "{#(abc)#}"[#String#]; name=""
73-
// LIBRARY-DAG: Literal[Array]/None/Flair[ExprAtFileScope]: [{#(values)#}][#Array#]; name=[]
74-
// LIBRARY-DAG: Literal[Dictionary]/None/Flair[ExprAtFileScope]: [{#(key)#}: {#(value)#}][#Dictionary#]; name=[: ]
73+
// LIBRARY-DAG: Literal[Array]/None/Flair[ExprAtFileScope]: [{#(values)#}][#Array<Element>#]; name=[]
74+
// LIBRARY-DAG: Literal[Dictionary]/None/Flair[ExprAtFileScope]: [{#(key)#}: {#(value)#}][#Dictionary<Key, Value>#]; name=[: ]
7575
// LIBRARY-DAG: Literal[Tuple]/None/Flair[ExprAtFileScope]: ({#(values)#}); name=()
7676
// LIBRARY-DAG: Decl[Struct]/CurrModule/Flair[ExprAtFileScope]: MyStruct[#MyStruct#]; name=MyStruct
7777
// LIBRARY-DAG: Decl[Protocol]/CurrModule/Flair[RareType,ExprAtFileScope]: MyProtocol[#MyProtocol#]; name=MyProtocol
@@ -136,8 +136,8 @@ protocol MyProtocol {}
136136
// SCRIPT-DAG: Literal[Boolean]/None: false[#Bool#]; name=false
137137
// SCRIPT-DAG: Literal[Nil]/None: nil; name=nil
138138
// SCRIPT-DAG: Literal[String]/None: "{#(abc)#}"[#String#]; name=""
139-
// SCRIPT-DAG: Literal[Array]/None: [{#(values)#}][#Array#]; name=[]
140-
// SCRIPT-DAG: Literal[Dictionary]/None: [{#(key)#}: {#(value)#}][#Dictionary#]; name=[: ]
139+
// SCRIPT-DAG: Literal[Array]/None: [{#(values)#}][#Array<Element>#]; name=[]
140+
// SCRIPT-DAG: Literal[Dictionary]/None: [{#(key)#}: {#(value)#}][#Dictionary<Key, Value>#]; name=[: ]
141141
// SCRIPT-DAG: Literal[Tuple]/None: ({#(values)#}); name=()
142142
// SCRIPT-DAG: Decl[Struct]/CurrModule: MyStruct[#MyStruct#]; name=MyStruct
143143
// SCRIPT-DAG: Decl[Protocol]/CurrModule/Flair[RareType]: MyProtocol[#MyProtocol#]; name=MyProtocol

test/IDE/complete_constrained.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ func foo(s: MyStruct<Int>) {
7575
// META_MYSTRUCT_INT_DOT: Begin completions, 11 items
7676
// META_MYSTRUCT_INT_DOT-DAG: Keyword[self]/CurrNominal: self[#MyStruct<Int>.Type#]; name=self
7777
// META_MYSTRUCT_INT_DOT-DAG: Keyword/CurrNominal: Type[#MyStruct<Int>.Type#]; name=Type
78-
// META_MYSTRUCT_INT_DOT-DAG: Decl[TypeAlias]/CurrNominal: Assoc[#T#]; name=Assoc
78+
// META_MYSTRUCT_INT_DOT-DAG: Decl[TypeAlias]/CurrNominal: Assoc[#Int#]; name=Assoc
7979
// META_MYSTRUCT_INT_DOT-DAG: Decl[Constructor]/CurrNominal: init({#int: U#})[#MyStruct<Int>#]; name=init(int:)
8080
// META_MYSTRUCT_INT_DOT-DAG: Decl[Constructor]/CurrNominal: init({#withConstrainedGenericParam: SomeProto#})[#MyStruct<Int>#]; name=init(withConstrainedGenericParam:)
8181
// META_MYSTRUCT_INT_DOT-DAG: Decl[InstanceMethod]/CurrNominal: methodWithConstrainedGenericParam({#(self): MyStruct<Int>#})[#(x: SomeProto) -> Int#]; name=methodWithConstrainedGenericParam(:)

test/IDE/complete_constructor.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -311,8 +311,8 @@ class DependentTypeInClosure<Data: DataType> {
311311
func testDependentTypeInClosure() {
312312
let _: DependentTypeInClosure = .#^DEPENDENT_IN_CLOSURE_3^#
313313
// DEPENDENT_IN_CLOSURE_3: Begin completions, 2 items
314-
// DEPENDENT_IN_CLOSURE_3-DAG: Decl[Constructor]/CurrNominal: init({#(arg): DataType#}, {#fn: (DataType.Content) -> Void##(DataType.Content) -> Void#})[#DependentTypeInClosure<DataType>#];
315-
// DEPENDENT_IN_CLOSURE_3-DAG: Decl[Constructor]/CurrNominal: init({#arg: DataType#}, {#fn: () -> DataType.Content##() -> DataType.Content#})[#DependentTypeInClosure<DataType>#];
314+
// DEPENDENT_IN_CLOSURE_3-DAG: Decl[Constructor]/CurrNominal/TypeRelation[Convertible]: init({#(arg): DataType#}, {#fn: (Data.Content) -> Void##(Data.Content) -> Void#})[#DependentTypeInClosure<DataType>#];
315+
// DEPENDENT_IN_CLOSURE_3-DAG: Decl[Constructor]/CurrNominal/TypeRelation[Convertible]: init({#arg: DataType#}, {#fn: () -> Data.Content##() -> Data.Content#})[#DependentTypeInClosure<DataType>#];
316316

317317
let _ = DependentTypeInClosure(#^DEPENDENT_IN_CLOSURE_1^#)
318318
// DEPENDENT_IN_CLOSURE_1-DAG: Decl[Constructor]/CurrNominal/Flair[ArgLabels]: ['(']{#(arg): DataType#}, {#fn: (_) -> Void##(_) -> Void#}[')'][#DependentTypeInClosure<DataType>#];
@@ -348,6 +348,6 @@ func testIgnoreGenericArgsAfterCompletionToken() {
348348
func deserializeRecord() throws -> HostRecord<IPv4> {
349349
var position = 42
350350
return try #^IGNORE_GENERIC_ARGS_AFTER_COMPLETION_TOKEN^#HostRecord<IPv4>(position: &position)
351-
// IGNORE_GENERIC_ARGS_AFTER_COMPLETION_TOKEN-DAG: Decl[Struct]/Local: HostRecord[#HostRecord#];
351+
// IGNORE_GENERIC_ARGS_AFTER_COMPLETION_TOKEN-DAG: Decl[Struct]/Local: HostRecord[#HostRecord<IPType>#];
352352
}
353353
}

test/IDE/complete_embedded_linux.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,6 @@ func test() {
1111
// GLOBAL: Literal[Boolean]/None: false[#Bool#];
1212
// GLOBAL: Literal[Nil]/None: nil;
1313
// GLOBAL: Literal[String]/None: "{#(abc)#}"[#String#];
14-
// GLOBAL: Literal[Array]/None: [{#(values)#}][#Array#];
15-
// GLOBAL: Literal[Dictionary]/None: [{#(key)#}: {#(value)#}][#Dictionary#];
14+
// GLOBAL: Literal[Array]/None: [{#(values)#}][#Array<Element>#];
15+
// GLOBAL: Literal[Dictionary]/None: [{#(key)#}: {#(value)#}][#Dictionary<Key, Value>#];
1616
}

test/IDE/complete_embedded_macos.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,6 @@ func test() {
1111
// GLOBAL: Literal[Boolean]/None: false[#Bool#];
1212
// GLOBAL: Literal[Nil]/None: nil;
1313
// GLOBAL: Literal[String]/None: "{#(abc)#}"[#String#];
14-
// GLOBAL: Literal[Array]/None: [{#(values)#}][#Array#];
15-
// GLOBAL: Literal[Dictionary]/None: [{#(key)#}: {#(value)#}][#Dictionary#];
14+
// GLOBAL: Literal[Array]/None: [{#(values)#}][#Array<Element>#];
15+
// GLOBAL: Literal[Dictionary]/None: [{#(key)#}: {#(value)#}][#Dictionary<Key, Value>#];
1616
}

test/IDE/complete_from_stdlib.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
#^PLAIN_TOP_LEVEL_1?check=PLAIN_TOP_LEVEL;check=NO_STDLIB_PRIVATE^#
77

8-
// PLAIN_TOP_LEVEL-DAG: Decl[Struct]/OtherModule[Swift]/IsSystem: Array[#Array#]{{; name=.+$}}
8+
// PLAIN_TOP_LEVEL-DAG: Decl[Struct]/OtherModule[Swift]/IsSystem: Array[#Array<Element>#]{{; name=.+$}}
99

1010
func privateNominalMembers(_ a: String) {
1111
a.#^PRIVATE_NOMINAL_MEMBERS_1?check=PRIVATE_NOMINAL_MEMBERS_1;check=NO_STDLIB_PRIVATE^#

test/IDE/complete_from_swift_module.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -134,15 +134,15 @@ struct Foo: Swift.Array.#^STDLIB_TYPE_QUALIFIED_NESTED^# {}
134134

135135
struct Bar: Swift.#^STDLIB_TYPE_QUALIFIED^# {}
136136
// STDLIB_TYPE_QUALIFIED-NOT: Decl[Module]
137-
// STDLIB_TYPE_QUALIFIED: Decl[Struct]/OtherModule[Swift]/IsSystem: AnyCollection[#AnyCollection#]; name=AnyCollection
137+
// STDLIB_TYPE_QUALIFIED: Decl[Struct]/OtherModule[Swift]/IsSystem: AnyCollection[#AnyCollection<Element>#]; name=AnyCollection
138138
// STDLIB_TYPE_QUALIFIED-NOT: Decl[Module]
139139

140140
func foo() -> foo_swift_module.#^MODULE_TYPE_QUALIFIED^# {}
141141
// MODULE_TYPE_QUALIFIED: Decl[Protocol]/OtherModule[foo_swift_module]: BarProtocol[#BarProtocol#]; name=BarProtocol
142142
// MODULE_TYPE_QUALIFIED: Decl[Enum]/OtherModule[foo_swift_module]: MyQuickLookObject[#MyQuickLookObject#]; name=MyQuickLookObject
143-
// MODULE_TYPE_QUALIFIED: Decl[Struct]/OtherModule[foo_swift_module]: BarGenericSwiftStruct1[#BarGenericSwiftStruct1#]; name=BarGenericSwiftStruct1
143+
// MODULE_TYPE_QUALIFIED: Decl[Struct]/OtherModule[foo_swift_module]: BarGenericSwiftStruct1[#BarGenericSwiftStruct1<T>#]; name=BarGenericSwiftStruct1
144144
// MODULE_TYPE_QUALIFIED: Decl[Struct]/OtherModule[foo_swift_module]: FooSwiftStruct[#FooSwiftStruct#]; name=FooSwiftStruct
145-
// MODULE_TYPE_QUALIFIED: Decl[Struct]/OtherModule[foo_swift_module]: BarGenericSwiftStruct2[#BarGenericSwiftStruct2#]; name=BarGenericSwiftStruct2
145+
// MODULE_TYPE_QUALIFIED: Decl[Struct]/OtherModule[foo_swift_module]: BarGenericSwiftStruct2[#BarGenericSwiftStruct2<T, U>#]; name=BarGenericSwiftStruct2
146146

147147
// rdar://92048610
148148
func testAmbiguousResultBuilder() {

0 commit comments

Comments
 (0)