Skip to content

[CodeCompletion] Wrap base expression with CodeCompletionExpr #32184

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 10, 2020

Conversation

rintaro
Copy link
Member

@rintaro rintaro commented Jun 4, 2020

For example, for:

funcName(base.<HERE>)

Wrap base with CodeCompletionExpr so that type checker can check base independently without affecting the overload choice of funcName.

This increases the chance of successful type checking.

rdar://problem/63965160

@rintaro
Copy link
Member Author

rintaro commented Jun 4, 2020

@swift-ci Please smoke test

@rintaro rintaro force-pushed the ide-completion-rdar63965160 branch from c510db9 to f67c1b5 Compare June 4, 2020 17:47
@rintaro rintaro requested a review from xedin June 4, 2020 17:47
@rintaro
Copy link
Member Author

rintaro commented Jun 4, 2020

@swift-ci Please smoke test

Comment on lines 1184 to 1194
// Defaults to the type of the base expression.
if (auto base = E->getBase()) {
CS.addConstraint(ConstraintKind::Defaultable, ty, CS.getType(base),
locator);
}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure this is desirable. But this is needed to preserve the current behavior in several test cases.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Am I reading this correctly that we are saying that in

foo(something.<complete>)

the type of something.completed_expr must be defaultable to the type of something? What kinds of tests changes do you see without this?

Copy link
Member Author

@rintaro rintaro Jun 4, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ConstraintKind::Defaultable means "the first type can be defaulted to the second", not "must be defaultable", IIUC. It's something like "fallback" type.

The failing test case was:

let val = Something.<HERE>

In this case val is type checked to the type of Something so each result has type relation (e.g. Invalid for Void result). Without Defaultable, since val cannot be resolved, there's no expected type here. (I'm not saying that val as Something is the right thing)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see. That seems like an unfortunate way to say "non-Void". What happens if there is an expected type and it really is Void?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems like what we really want here is for code completion expression to be marked as a hole by default, just like we do in some other cases, that would solve a case where there is absolutely no contextual information available (let _ = foo.<#complete#> just like Rintaro mentioned).

I'm still thinking about this but it might be possible to generate constraints here in a way which would match what we do for DefineMemberBasedOnUse fix if member couldn't be found, that would guarantee that there is either a type or a hole inferred for a member reference.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the least disruptive change would be to default code completion to UnresolvedType regardless of whether it's a member lookup or not, we also currently use UnresolvedType to indicate holes so it's fitting.

@rintaro rintaro requested a review from benlangmuir June 4, 2020 18:21
Copy link
Contributor

@benlangmuir benlangmuir left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Conceptually seems reasonable to me, but the CSGen change doesn't make sense to me.

Comment on lines 1184 to 1194
// Defaults to the type of the base expression.
if (auto base = E->getBase()) {
CS.addConstraint(ConstraintKind::Defaultable, ty, CS.getType(base),
locator);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Am I reading this correctly that we are saying that in

foo(something.<complete>)

the type of something.completed_expr must be defaultable to the type of something? What kinds of tests changes do you see without this?

@rintaro rintaro force-pushed the ide-completion-rdar63965160 branch from f67c1b5 to 0ed063d Compare June 5, 2020 16:06
@rintaro
Copy link
Member Author

rintaro commented Jun 5, 2020

@swift-ci Please smoke test

@@ -10,7 +10,8 @@

// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=TOP_LEVEL_VAR_INIT_1 > %t.toplevel.txt
// RUN: %FileCheck %s -check-prefix=TOP_LEVEL_VAR_INIT_1 < %t.toplevel.txt
// RUN: %FileCheck %s -check-prefix=TOP_LEVEL_VAR_INIT_1_NEGATIVE < %t.toplevel.txt
// FIXME: rdar://problem/56755598
// RUN: not %FileCheck %s -check-prefix=TOP_LEVEL_VAR_INIT_1_NEGATIVE < %t.toplevel.txt
Copy link
Member Author

@rintaro rintaro Jun 5, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test case is

var topLevelVar1 = #^TOP_LEVEL_VAR_INIT_1^#
// Check that the variable itself does not show up.
// TOP_LEVEL_VAR_INIT_1_NEGATIVE-NOT: topLevelVar1

This used to work only because typechecking this decl was failed. Now that it's typechecked to UnresolvedType so it revealed the existing issue(rdar://problem/56755598).

@rintaro rintaro force-pushed the ide-completion-rdar63965160 branch from 0ed063d to 12493c6 Compare June 5, 2020 16:38
Comment on lines 525 to 529
// NOTE: [Convertible] to AnyHashable.
// FIXME: '/TypeRelation[Convertible]' to AnyHashable.
// IN_FOR_EACH_4-NOT: Decl[LocalVar]
// IN_FOR_EACH_4: Decl[LocalVar]/Local/TypeRelation[Convertible]: local[#Int#];
// IN_FOR_EACH_4: Decl[LocalVar]/Local: local[#Int#];
// IN_FOR_EACH_4-NOT: after
// IN_FOR_EACH_4: Decl[LocalVar]/Local/TypeRelation[Convertible]: arg[#Int#];
// IN_FOR_EACH_4: Decl[LocalVar]/Local: arg[#Int#];
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a regression. For example:

let _ = [<HERE>: 1]

Previously this used to be type checked to [AnyHashable : Int], but now it's [<<unresolved type>> : Int]. It's unfortunate, but in practice, I don't think this causes a big difference.

@rintaro
Copy link
Member Author

rintaro commented Jun 5, 2020

@swift-ci Please smoke test

For example for:

  funcName(base.<HERE>)

Wrap 'base' with 'CodeCompletionExpr' so that type checker can check
'base' independently without preventing the overload choice of 'funcName'.

This increases the chance of successful type checking.

rdar://problem/63965160
@rintaro rintaro force-pushed the ide-completion-rdar63965160 branch from 12493c6 to 3ec250f Compare June 5, 2020 23:00
@rintaro
Copy link
Member Author

rintaro commented Jun 5, 2020

@swift-ci Please smoke test

@rintaro
Copy link
Member Author

rintaro commented Jun 5, 2020

Decided not to default it to UnresolvedType for now.

Copy link
Contributor

@xedin xedin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! We'll iterate on how to make code completion expressions proper "holes".

@rintaro rintaro merged commit 4205e46 into swiftlang:master Jun 10, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants