@@ -78,6 +78,44 @@ bool ArgumentTypeCheckCompletionCallback::addPossibleParams(
78
78
return ShowGlobalCompletions;
79
79
}
80
80
81
+ // / Applies heuristic to determine whether the result type of \p E is
82
+ // / unconstrained, that is if the constraint system is satisfiable for any
83
+ // / result type of \p E.
84
+ static bool isExpressionResultTypeUnconstrained (const Solution &S, Expr *E) {
85
+ ConstraintSystem &CS = S.getConstraintSystem ();
86
+ if (auto ParentExpr = CS.getParentExpr (E)) {
87
+ if (auto Assign = dyn_cast<AssignExpr>(ParentExpr)) {
88
+ if (isa<DiscardAssignmentExpr>(Assign->getDest ())) {
89
+ // _ = <expr> is unconstrained
90
+ return true ;
91
+ }
92
+ } else if (isa<RebindSelfInConstructorExpr>(ParentExpr)) {
93
+ // super.init() is unconstrained (it always produces the correct result
94
+ // by definition)
95
+ return true ;
96
+ }
97
+ }
98
+ auto targetIt = S.solutionApplicationTargets .find (E);
99
+ if (targetIt == S.solutionApplicationTargets .end ()) {
100
+ return false ;
101
+ }
102
+ auto target = targetIt->second ;
103
+ assert (target.kind == SolutionApplicationTarget::Kind::expression);
104
+ switch (target.getExprContextualTypePurpose ()) {
105
+ case CTP_Unused:
106
+ // If we aren't using the contextual type, its unconstrained by definition.
107
+ return true ;
108
+ case CTP_Initialization: {
109
+ // let x = <expr> is unconstrained
110
+ auto contextualType = target.getExprContextualType ();
111
+ return !contextualType || contextualType->is <UnresolvedType>();
112
+ }
113
+ default :
114
+ // Assume that it's constrained by default.
115
+ return false ;
116
+ }
117
+ }
118
+
81
119
void ArgumentTypeCheckCompletionCallback::sawSolutionImpl (const Solution &S) {
82
120
Type ExpectedTy = getTypeForCompletion (S, CompletionExpr);
83
121
@@ -111,6 +149,11 @@ void ArgumentTypeCheckCompletionCallback::sawSolutionImpl(const Solution &S) {
111
149
}
112
150
auto ArgIdx = ArgInfo->completionIdx ;
113
151
152
+ Type ExpectedCallType;
153
+ if (!isExpressionResultTypeUnconstrained (S, ParentCall)) {
154
+ ExpectedCallType = getTypeForCompletion (S, ParentCall);
155
+ }
156
+
114
157
auto *CallLocator = CS.getConstraintLocator (ParentCall);
115
158
auto *CalleeLocator = S.getCalleeLocator (CallLocator);
116
159
@@ -189,10 +232,10 @@ void ArgumentTypeCheckCompletionCallback::sawSolutionImpl(const Solution &S) {
189
232
if (Info.ValueTy ) {
190
233
FuncTy = Info.ValueTy ->lookThroughAllOptionalTypes ()->getAs <AnyFunctionType>();
191
234
}
192
- Results.push_back ({ExpectedTy, isa<SubscriptExpr>(ParentCall), Info. Value ,
193
- FuncTy, ArgIdx, ParamIdx, std::move (ClaimedParams) ,
194
- IsNoninitialVariadic, Info. BaseTy , HasLabel, IsAsync ,
195
- SolutionSpecificVarTypes});
235
+ Results.push_back ({ExpectedTy, ExpectedCallType ,
236
+ isa<SubscriptExpr>(ParentCall), Info. Value , FuncTy, ArgIdx ,
237
+ ParamIdx, std::move (ClaimedParams), IsNoninitialVariadic ,
238
+ Info. BaseTy , HasLabel, IsAsync, SolutionSpecificVarTypes});
196
239
}
197
240
198
241
void ArgumentTypeCheckCompletionCallback::deliverResults (
@@ -205,10 +248,18 @@ void ArgumentTypeCheckCompletionCallback::deliverResults(
205
248
206
249
// Perform global completion as a fallback if we don't have any results.
207
250
bool shouldPerformGlobalCompletion = Results.empty ();
251
+ SmallVector<Type, 4 > ExpectedCallTypes;
252
+ for (auto &Result : Results) {
253
+ ExpectedCallTypes.push_back (Result.ExpectedCallType );
254
+ }
255
+
208
256
SmallVector<Type, 8 > ExpectedTypes;
209
257
210
258
if (IncludeSignature && !Results.empty ()) {
211
259
Lookup.setHaveLParen (true );
260
+ Lookup.setExpectedTypes (ExpectedCallTypes,
261
+ /* isImplicitSingleExpressionReturn=*/ false );
262
+
212
263
for (auto &Result : Results) {
213
264
auto SemanticContext = SemanticContextKind::None;
214
265
NominalTypeDecl *BaseNominal = nullptr ;
0 commit comments