Skip to content

Commit 4130bff

Browse files
authored
Merge pull request #59021 from ahoppen/pr/no-type-relation-for-any
[CodeCompletion] Don’t compute type relations if the contextual type is `Any`
2 parents 997ace4 + ee34db4 commit 4130bff

File tree

3 files changed

+53
-6
lines changed

3 files changed

+53
-6
lines changed

lib/IDE/CodeCompletionResultType.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,12 +305,34 @@ TypeRelation USRBasedTypeContext::ContextualType::typeRelation(
305305

306306
// MARK: - CodeCompletionResultType
307307

308+
/// Returns \c true if \p Ty is the 'Any' type or some type that is sufficiently
309+
/// similar to Any, like the 'Any' metatype or an optional type wrapping 'Any'.
310+
static bool isEssentiallyAnyType(Type Ty) {
311+
while (true) {
312+
if (auto MT = Ty->getAs<AnyMetatypeType>()) {
313+
Ty = MT->getInstanceType();
314+
} else if (auto OT = Ty->getOptionalObjectType()) {
315+
Ty = OT;
316+
} else {
317+
break;
318+
}
319+
}
320+
return Ty->isAny();
321+
}
322+
308323
static TypeRelation calculateTypeRelation(Type Ty, Type ExpectedTy,
309324
const DeclContext &DC) {
310325
if (Ty.isNull() || ExpectedTy.isNull() || Ty->is<ErrorType>() ||
311326
ExpectedTy->is<ErrorType>())
312327
return TypeRelation::Unrelated;
313328

329+
/// Computing type relations to 'Any' is not very enlightning because
330+
/// everything would be convertible to it. If the contextual type is 'Any',
331+
/// just report all type relations as 'Unknown'.
332+
if (isEssentiallyAnyType(ExpectedTy)) {
333+
return TypeRelation::Unknown;
334+
}
335+
314336
// Equality/Conversion of GenericTypeParameterType won't account for
315337
// requirements – ignore them
316338
if (!Ty->hasTypeParameter() && !ExpectedTy->hasTypeParameter()) {

test/IDE/complete_at_top_level.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -328,7 +328,7 @@ var stringInterp = "\(#^STRING_INTERP_3?check=STRING_INTERP^#)"
328328
_ = "" + "\(#^STRING_INTERP_4?check=STRING_INTERP^#)" + ""
329329
// STRING_INTERP: Begin completions
330330
// STRING_INTERP-DAG: Decl[InstanceMethod]/CurrNominal/Flair[ArgLabels]/IsSystem: ['(']{#(value): T#}[')'][#Void#];
331-
// STRING_INTERP-DAG: Decl[Struct]/CurrModule/TypeRelation[Convertible]: FooStruct[#FooStruct#]; name=FooStruct
331+
// STRING_INTERP-DAG: Decl[Struct]/CurrModule: FooStruct[#FooStruct#]; name=FooStruct
332332
// STRING_INTERP-DAG: Decl[FreeFunction]/CurrModule/TypeRelation[Invalid]: fooFunc1()[#Void#];
333333
// STRING_INTERP-DAG: Decl[FreeFunction]/CurrModule: optStr()[#String?#];
334334
// STRING_INTERP-DAG: Decl[GlobalVar]/Local: fooObject[#FooStruct#];

test/IDE/complete_type_any.swift

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
1-
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=ANY_IN_FUNC_PARAM | %FileCheck %s -check-prefix=ANY_IN_FUNC_PARAM
2-
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=ANY_IN_VAR_TYPE | %FileCheck %s -check-prefix=ANY_IN_VAR_TYPE
3-
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=ANY_METATYPE_VARIABLE | %FileCheck %s -check-prefix=ANY_METATYPE_VARIABLE
4-
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=ANY_METATYPE_MEMBER | %FileCheck %s -check-prefix=ANY_METATYPE_MEMBER
5-
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=ANY_IN_TYPEALIAS | %FileCheck %s -check-prefix=ANY_IN_TYPEALIAS
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-swift-ide-test -batch-code-completion -source-filename %s -filecheck %raw-FileCheck -completion-output-dir %t
63

74
func testAnyInParamList(a: #^ANY_IN_FUNC_PARAM^#
85
// ANY_IN_FUNC_PARAM: Begin completions
@@ -31,4 +28,32 @@ typealias A = #^ANY_IN_TYPEALIAS^#
3128
// ANY_IN_TYPEALIAS-DAG: Keyword/None: Any[#Any#]; name=Any
3229
// ANY_IN_TYPEALIAS: End completions
3330

31+
func testRdar64812321() {
32+
func foo<T>(x: T) {}
33+
func foo(x: Any.Type) {}
3434

35+
struct MyStruct {}
36+
let myStruct = MyStruct()
37+
38+
foo(x: #^ANY_RELATIONSHIP^#)
39+
// The MyStruct type should not be preferred over the myStruct instance.
40+
41+
// ANY_RELATIONSHIP: Begin completions
42+
// ANY_RELATIONSHIP-DAG: Decl[LocalVar]/Local: myStruct[#MyStruct#]; name=myStruct
43+
// ANY_RELATIONSHIP-DAG: Decl[Struct]/Local: MyStruct[#MyStruct#]; name=MyStruct
44+
// ANY_RELATIONSHIP: End completions
45+
}
46+
47+
func testRdar84684686() {
48+
func foo(_ x: Any?) {}
49+
50+
struct S {
51+
static func bar(x: Int) -> Int { x }
52+
}
53+
54+
// We should suggest a function call to `bar` here (i.e. `bar(x: <#Int#>)`), not a function reference (i.e. `bar(x:)`)
55+
foo(S.#^ANY_PREFERS_FUNCTION_CALL^#)
56+
// ANY_PREFERS_FUNCTION_CALL: Begin completions
57+
// ANY_PREFERS_FUNCTION_CALL-DAG: Decl[StaticMethod]/CurrNominal: bar({#x: Int#})[#Int#]; name=bar(x:)
58+
// ANY_PREFERS_FUNCTION_CALL: End completions
59+
}

0 commit comments

Comments
 (0)