Skip to content

Commit 3a0b726

Browse files
authored
Merge pull request swiftlang#63717 from ahoppen/ahoppen/remaining-solver-based
2 parents f3a685a + 597c0dc commit 3a0b726

File tree

74 files changed

+1844
-605
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

74 files changed

+1844
-605
lines changed

include/swift/IDE/CompletionLookup.h

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -519,7 +519,14 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
519519

520520
void getPostfixKeywordCompletions(Type ExprType, Expr *ParsedExpr);
521521

522-
void getValueExprCompletions(Type ExprType, ValueDecl *VD = nullptr);
522+
/// Add code completion results after an expression of type \p ExprType.
523+
/// This includes members as well as call patterns if \p ExprType is a
524+
/// function type.
525+
/// If \p IsDeclUnapplied is \c true, we are completing after a refernce to
526+
/// \p VD that hasn't been called yet. Thus, \p VD has type \p ExprType and we
527+
/// can use \p VD to enrich call pattern completions of \p ExprType.
528+
void getValueExprCompletions(Type ExprType, ValueDecl *VD = nullptr,
529+
bool IsDeclUnapplied = false);
523530

524531
void collectOperators(SmallVectorImpl<OperatorDecl *> &results);
525532

@@ -529,7 +536,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
529536

530537
void tryPostfixOperator(Expr *expr, PostfixOperatorDecl *op);
531538

532-
void addAssignmentOperator(Type RHSType, Type resultType);
539+
void addAssignmentOperator(Type RHSType);
533540

534541
void addInfixOperatorCompletion(OperatorDecl *op, Type resultType,
535542
Type RHSType);

include/swift/IDE/PostfixCompletion.h

Lines changed: 53 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,16 +20,41 @@
2020
namespace swift {
2121
namespace ide {
2222

23-
/// Used to collect and store information needed to perform member completion
24-
/// (\c CompletionKind::DotExpr ) from the solutions formed during expression
25-
/// type-checking.
23+
/// Used to collect and store information needed to perform postfix completion
24+
/// (either <base>.#^COMPLETE^# or <base> #^COMPLETE^#).
2625
class PostfixCompletionCallback : public TypeCheckCompletionCallback {
2726
struct Result {
27+
/// The type that we are completing on. Will never be null.
2828
Type BaseTy;
29+
30+
/// The decl that we are completing on. Is \c nullptr if we are completing
31+
/// on an expression.
2932
ValueDecl *BaseDecl;
33+
34+
/// Whether \c BaseDecl refers to a function that has not been called yet.
35+
/// In such cases, we know that \p BaseTy is the type of \p BaseDecl and we
36+
/// can use \p BaseDecl for more detailed call pattern completions.
37+
bool IsBaseDeclUnapplied;
38+
39+
/// If the expression we are completing on statically refers to a metatype,
40+
/// that is if it's something like 'MyType'. In such cases we want to offer
41+
/// constructor call pattern completions and don't want to suggeste
42+
/// operators that work on metatypes.
43+
bool BaseIsStaticMetaType;
44+
45+
/// The types that the completion is expected to produce.
3046
SmallVector<Type, 4> ExpectedTypes;
47+
48+
/// Whether results that produce 'Void' should be disfavored. This happens
49+
/// if the context is requiring a value. Once a completion produces 'Void',
50+
/// we know that we can't retrieve a value from it anymore.
3151
bool ExpectsNonVoid;
32-
bool BaseIsStaticMetaType;
52+
53+
/// If the code completion expression occurs as a single statement in a
54+
/// single-expression closure. In such cases we don't want to disfavor
55+
/// results that produce 'Void' because the user might intend to make the
56+
/// closure a multi-statment closure, in which case this expression is no
57+
/// longer implicitly returned.
3358
bool IsImplicitSingleExpressionReturn;
3459

3560
/// Whether the surrounding context is async and thus calling async
@@ -40,13 +65,24 @@ class PostfixCompletionCallback : public TypeCheckCompletionCallback {
4065
/// haven't been saved to the AST.
4166
llvm::DenseMap<AbstractClosureExpr *, ClosureActorIsolation>
4267
ClosureActorIsolations;
68+
69+
/// Checks whether this result has the same \c BaseTy and \c BaseDecl as
70+
/// \p Other and if the two can thus be merged to be one value lookup in
71+
/// \c deliverResults.
72+
bool canBeMergedWith(const Result &Other, DeclContext &DC) const;
73+
74+
/// Merge this result with \p Other. Assumes that they can be merged.
75+
void merge(const Result &Other, DeclContext &DC);
4376
};
4477

4578
CodeCompletionExpr *CompletionExpr;
4679
DeclContext *DC;
4780

4881
SmallVector<Result, 4> Results;
49-
llvm::DenseMap<std::pair<Type, Decl *>, size_t> BaseToSolutionIdx;
82+
83+
/// Add a result to \c Results, merging it with an existing result, if
84+
/// possible.
85+
void addResult(const Result &Res);
5086

5187
void sawSolutionImpl(const constraints::Solution &solution) override;
5288

@@ -58,8 +94,18 @@ class PostfixCompletionCallback : public TypeCheckCompletionCallback {
5894
/// \c sawSolution for each solution formed.
5995
void fallbackTypeCheck(DeclContext *DC) override;
6096

61-
void deliverResults(Expr *BaseExpr, DeclContext *DC, SourceLoc DotLoc,
62-
bool IsInSelector, CodeCompletionContext &CompletionCtx,
97+
/// Deliver code completion results that were discoverd by \c sawSolution to
98+
/// \p Consumer.
99+
/// \param DotLoc If we are completing after a dot, the location of the dot,
100+
/// otherwise an invalid SourceLoc.
101+
/// \param IsInSelector Whether we are completing in an Objective-C selector.
102+
/// \param IncludeOperators If operators should be suggested. Assumes that
103+
/// \p DotLoc is invalid
104+
/// \param HasLeadingSpace Whether there is a space separating the exiting
105+
/// expression and the code completion token.
106+
void deliverResults(SourceLoc DotLoc, bool IsInSelector,
107+
bool IncludeOperators, bool HasLeadingSpace,
108+
CodeCompletionContext &CompletionCtx,
63109
CodeCompletionConsumer &Consumer);
64110
};
65111

include/swift/IDE/UnresolvedMemberCompletion.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,14 @@ class UnresolvedMemberTypeCheckCompletionCallback
3232
/// Whether the surrounding context is async and thus calling async
3333
/// functions is supported.
3434
bool IsInAsyncContext;
35+
36+
/// Checks whether this result has the same \c BaseTy and \c BaseDecl as
37+
/// \p Other and if the two can thus be merged to be one value lookup in
38+
/// \c deliverResults.
39+
bool canBeMergedWith(const Result &Other, DeclContext &DC) const;
40+
41+
/// Merge this result with \p Other. Assumes that they can be merged.
42+
void merge(const Result &Other, DeclContext &DC);
3543
};
3644

3745
CodeCompletionExpr *CompletionExpr;
@@ -40,6 +48,10 @@ class UnresolvedMemberTypeCheckCompletionCallback
4048
SmallVector<Result, 4> ExprResults;
4149
SmallVector<Result, 1> EnumPatternTypes;
4250

51+
/// Add a result to \c Results, merging it with an existing result, if
52+
/// possible.
53+
void addExprResult(const Result &Res);
54+
4355
void sawSolutionImpl(const constraints::Solution &solution) override;
4456

4557
public:

include/swift/Parse/IDEInspectionCallbacks.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -147,8 +147,9 @@ class CodeCompletionCallbacks {
147147
/// Complete the \c in keyword in a for-each loop.
148148
virtual void completeForEachInKeyword(){};
149149

150-
/// Complete a given expr-postfix.
151-
virtual void completePostfixExpr(Expr *E, bool hasSpace) {};
150+
/// Complete a expr-postfix. The \c CodeCompletionExpr has the expression it
151+
/// is completing after set as its base.
152+
virtual void completePostfixExpr(CodeCompletionExpr *E, bool hasSpace){};
152153

153154
/// Complete a given expr-postfix, given that there is a following
154155
/// left parenthesis.

include/swift/Sema/ConstraintSystem.h

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -472,6 +472,9 @@ class TypeVariableType::Implementation {
472472
/// Determine whether this type variable represents a closure type.
473473
bool isClosureType() const;
474474

475+
/// Determine whether this type variable represents a type of tap expression.
476+
bool isTapType() const;
477+
475478
/// Determine whether this type variable represents one of the
476479
/// parameter types associated with a closure.
477480
bool isClosureParameterType() const;
@@ -935,6 +938,9 @@ enum ScoreKind: unsigned int {
935938
/// A reference to an @unavailable declaration.
936939
SK_Unavailable,
937940
/// A reference to an async function in a synchronous context.
941+
///
942+
/// \note Any score kind after this is considered a conversion that doesn't
943+
/// require fixing the source and will be ignored during code completion.
938944
SK_AsyncInSyncMismatch,
939945
/// Synchronous function in an asynchronous context or a conversion of
940946
/// a synchronous function to an asynchronous one.
@@ -3951,6 +3957,20 @@ class ConstraintSystem {
39513957
/// \returns `true` if pack expansion has been resolved, `false` otherwise.
39523958
bool resolvePackExpansion(TypeVariableType *typeVar, Type contextualType);
39533959

3960+
/// Bind tap expression to the given contextual type and generate
3961+
/// constraints for its body.
3962+
///
3963+
/// \param typeVar The type variable representing the tap expression.
3964+
/// \param contextualType The contextual type this tap expression
3965+
/// would be bound to.
3966+
/// \param locator The locator associated with contextual type.
3967+
///
3968+
/// \returns `true` if it was possible to generate constraints for
3969+
/// the body and assign fixed type to the tap expression, `false`
3970+
/// otherwise.
3971+
bool resolveTapBody(TypeVariableType *typeVar, Type contextualType,
3972+
ConstraintLocatorBuilder locator);
3973+
39543974
/// Assign a fixed type to the given type variable.
39553975
///
39563976
/// \param typeVar The type variable to bind.
@@ -4354,6 +4374,14 @@ class ConstraintSystem {
43544374
FreeTypeVariableBinding allowFreeTypeVariables =
43554375
FreeTypeVariableBinding::Disallow);
43564376

4377+
/// Generate constraints for the body of the given tap expression.
4378+
///
4379+
/// \param tap the tap expression
4380+
///
4381+
/// \returns \c true if constraint generation failed, \c false otherwise
4382+
[[nodiscard]]
4383+
bool generateConstraints(TapExpr *tap);
4384+
43574385
/// Generate constraints for the body of the given function or closure.
43584386
///
43594387
/// \param fn The function or closure expression
@@ -5203,7 +5231,8 @@ class ConstraintSystem {
52035231
public:
52045232
/// Increase the score of the given kind for the current (partial) solution
52055233
/// along the.
5206-
void increaseScore(ScoreKind kind, unsigned value = 1);
5234+
void increaseScore(ScoreKind kind, ConstraintLocatorBuilder Locator,
5235+
unsigned value = 1);
52075236

52085237
/// Determine whether this solution is guaranteed to be worse than the best
52095238
/// solution found so far.
@@ -5285,6 +5314,22 @@ class ConstraintSystem {
52855314
llvm::Optional<SyntacticElementTarget>(SyntacticElementTarget)>
52865315
rewriteTarget);
52875316

5317+
/// Apply the given solution to the given tap expression.
5318+
///
5319+
/// \param solution The solution to apply.
5320+
/// \param tapExpr The tap expression to which the solution is being applied.
5321+
/// \param currentDC The declaration context in which transformations
5322+
/// will be applied.
5323+
/// \param rewriteTarget Function that performs a rewrite of any
5324+
/// solution application target within the context.
5325+
///
5326+
/// \returns true if solution cannot be applied.
5327+
bool applySolutionToBody(Solution &solution, TapExpr *tapExpr,
5328+
DeclContext *&currentDC,
5329+
std::function<llvm::Optional<SyntacticElementTarget>(
5330+
SyntacticElementTarget)>
5331+
rewriteTarget);
5332+
52885333
/// Reorder the disjunctive clauses for a given expression to
52895334
/// increase the likelihood that a favored constraint will be successfully
52905335
/// resolved before any others.

lib/AST/ASTNode.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ SourceRange ASTNode::getSourceRange() const {
4141
if (const auto *I = this->dyn_cast<CaseLabelItem *>()) {
4242
return I->getSourceRange();
4343
}
44+
assert(!isNull() && "Null ASTNode doesn't have a source range");
4445
llvm_unreachable("unsupported AST node");
4546
}
4647

lib/IDE/ArgumentCompletion.cpp

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,18 @@ void ArgumentTypeCheckCompletionCallback::sawSolutionImpl(const Solution &S) {
236236
for (auto Idx : range(0, ParamsToPass.size())) {
237237
bool Optional = false;
238238
if (Info.ValueRef) {
239-
if (const ParamDecl *DeclParam = getParameterAt(Info.ValueRef, Idx)) {
239+
if (Info.ValueRef.getDecl()->isInstanceMember() &&
240+
!doesMemberRefApplyCurriedSelf(Info.BaseTy,
241+
Info.ValueRef.getDecl())) {
242+
// We are completing in an unapplied instance function, eg.
243+
// struct TestStatic {
244+
// func method() -> Void {}
245+
// }
246+
// TestStatic.method(#^STATIC^#)
247+
// The 'self' parameter is never optional, so don't enter the check
248+
// below (which always assumes that self has been applied).
249+
} else if (const ParamDecl *DeclParam =
250+
getParameterAt(Info.ValueRef, Idx)) {
240251
Optional |= DeclParam->isDefaultArgument();
241252
Optional |= DeclParam->getType()->is<PackExpansionType>();
242253
}

0 commit comments

Comments
 (0)