Skip to content

Commit 98614d1

Browse files
author
Nathan Hawes
authored
Merge pull request swiftlang#34238 from nathawes/handle-error-exprs-when-generating-constraints-for-completion
[CodeCompletion][CSGen] Treat ErrorExprs as holes when generating constraints for code completion
2 parents 001e7bb + be23120 commit 98614d1

File tree

8 files changed

+31
-9
lines changed

8 files changed

+31
-9
lines changed

include/swift/AST/Types.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ class ModuleType;
8787
class ProtocolConformance;
8888
enum PointerTypeKind : unsigned;
8989
struct ValueOwnershipKind;
90+
class ErrorExpr;
9091

9192
typedef CanTypeWrapper<SILFunctionType> CanSILFunctionType;
9293

@@ -5738,7 +5739,8 @@ DEFINE_EMPTY_CAN_TYPE_WRAPPER(TypeVariableType, Type)
57385739
/// constraint solver and transformed into UnresolvedType to be used in AST.
57395740
class HoleType : public TypeBase {
57405741
using Originator = llvm::PointerUnion<TypeVariableType *,
5741-
DependentMemberType *, VarDecl *>;
5742+
DependentMemberType *, VarDecl *,
5743+
ErrorExpr *>;
57425744

57435745
Originator O;
57445746

lib/AST/ASTDumper.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3523,6 +3523,8 @@ namespace {
35233523
printRec("type_variable", typeVar);
35243524
} else if (auto *VD = originator.dyn_cast<VarDecl *>()) {
35253525
VD->dumpRef(PrintWithColorRAII(OS, DeclColor).getOS());
3526+
} else if (auto *EE = originator.dyn_cast<ErrorExpr *>()) {
3527+
printFlag("error_expr");
35263528
} else {
35273529
printRec("dependent_member_type",
35283530
originator.get<DependentMemberType *>());

lib/AST/ASTPrinter.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3828,6 +3828,8 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
38283828
} else if (auto *VD = originator.dyn_cast<VarDecl *>()) {
38293829
Printer << "decl = ";
38303830
Printer << VD->getName();
3831+
} else if (auto *EE = originator.dyn_cast<ErrorExpr *>()) {
3832+
Printer << "error_expr";
38313833
} else {
38323834
visit(originator.get<DependentMemberType *>());
38333835
}

lib/Sema/CSGen.cpp

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1003,8 +1003,21 @@ namespace {
10031003
ConstraintSystem &getConstraintSystem() const { return CS; }
10041004

10051005
virtual Type visitErrorExpr(ErrorExpr *E) {
1006-
// FIXME: Can we do anything with error expressions at this point?
1007-
return nullptr;
1006+
if (!CS.isForCodeCompletion())
1007+
return nullptr;
1008+
1009+
// For code completion, treat error expressions that don't contain
1010+
// the completion location itself as holes. If an ErrorExpr contains the
1011+
// code completion location, a fallback typecheck is called on the
1012+
// ErrorExpr's OriginalExpr (valid sub-expression) if it had one,
1013+
// independent of the wider expression containing the ErrorExpr, so
1014+
// there's no point attempting to produce a solution for it.
1015+
SourceRange range = E->getSourceRange();
1016+
if (range.isInvalid() ||
1017+
CS.getASTContext().SourceMgr.rangeContainsCodeCompletionLoc(range))
1018+
return nullptr;
1019+
1020+
return HoleType::get(CS.getASTContext(), E);
10081021
}
10091022

10101023
virtual Type visitCodeCompletionExpr(CodeCompletionExpr *E) {

lib/Sema/TypeCheckCodeCompletion.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -786,6 +786,7 @@ bool TypeChecker::typeCheckForCodeCompletion(
786786
ConstraintSystemOptions options;
787787
options |= ConstraintSystemFlags::AllowFixes;
788788
options |= ConstraintSystemFlags::SuppressDiagnostics;
789+
options |= ConstraintSystemFlags::ForCodeCompletion;
789790

790791
ConstraintSystem cs(DC, options);
791792

test/IDE/complete_ambiguous.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=RELATED | %FileCheck %s --check-prefix=RELATED
55
// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=RELATED_EXTRAARG | %FileCheck %s --check-prefix=RELATED
66
// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=RELATED_INERROREXPR | %FileCheck %s --check-prefix=RELATED
7+
// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=ERROR_IN_BASE | %FileCheck %s --check-prefix=SIMPLE
78
// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=GENERIC | %FileCheck %s --check-prefix=GENERIC
89
// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=GENERIC_MISSINGARG | %FileCheck %s --check-prefix=NORESULTS
910
// RUN: %swift-ide-test -code-completion -source-filename %s -code-completion-token=CLOSURE_MISSINGARG | %FileCheck %s --check-prefix=POINT_MEMBER
@@ -34,6 +35,11 @@ struct HasMembers {
3435

3536
HasMembers().overloadedReturn().#^SIMPLE_MEMBERS^#
3637

38+
func givenErrorExpr(_ a: String) -> A {}
39+
func givenErrorExpr(_ b: Int) -> B {}
40+
41+
givenErrorExpr(undefined).#^ERROR_IN_BASE^#
42+
3743
// SIMPLE: Begin completions, 4 items
3844
// SIMPLE-DAG: Keyword[self]/CurrNominal: self[#A#]{{; name=.+$}}
3945
// SIMPLE-DAG: Decl[InstanceMethod]/CurrNominal: doAThings()[#A#]{{; name=.+$}}

test/IDE/complete_assignment.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,7 @@ func f2() {
202202
// ASSIGN_11-DAG: Decl[InstanceMethod]/CurrNominal: IntOpGen()[#Int?#]
203203
// ASSIGN_11-DAG: Decl[InstanceMethod]/CurrNominal: D1Gen()[#D1#]
204204
// ASSIGN_11-DAG: Decl[InstanceMethod]/CurrNominal: D2Gen()[#D2#]
205-
// ASSIGN_11-DAG: Decl[InstanceMethod]/CurrNominal: VoidGen()[#Void#]
205+
// ASSIGN_11-DAG: Decl[InstanceMethod]/CurrNominal/TypeRelation[Invalid]: VoidGen()[#Void#]
206206
// ASSIGN_11-DAG: Decl[InstanceVar]/CurrNominal: InternalC2[#C2#]
207207

208208
func f12() {

test/IDE/complete_func_body_typechecking.swift

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=TC_VAR_4 | %FileCheck %s -check-prefix=FOO_STRUCT_COMMON
55
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=TC_VAR_5 | %FileCheck %s -check-prefix=FOO_STRUCT_COMMON
66
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=TC_VAR_6 | %FileCheck %s -check-prefix=FOO_STRUCT_COMMON
7-
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=TC_VAR_7 | %FileCheck %s -check-prefix=ERROR_COMMON
7+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=TC_VAR_7 | %FileCheck %s -check-prefix=FOO_STRUCT_COMMON
88

99
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=TC_VAR_IN_CONSTRUCTOR_1 | %FileCheck %s -check-prefix=FOO_STRUCT_COMMON
1010
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=TC_VAR_IN_CONSTRUCTOR_2 | %FileCheck %s -check-prefix=FOO_STRUCT_COMMON
@@ -91,10 +91,6 @@ func testTypecheckVar6() {
9191
}
9292

9393
func testTypecheckVar7() {
94-
// FIXME: We don't display any useful completions here, although we could --
95-
// it is obvious that the expression could only have type 'FooStruct'.
96-
//
97-
// In any case, ensure that we don't crash.
9894
var localInt = 42
9995
FooStruct(localInt).builderFunc2(unknown_var).#^TC_VAR_7^#
10096
}

0 commit comments

Comments
 (0)