@@ -38,12 +38,6 @@ bool ArgumentTypeCheckCompletionCallback::addPossibleParams(
38
38
39
39
ArrayRef<AnyFunctionType::Param> ParamsToPass = Res.FuncTy ->getParams ();
40
40
41
- ParameterList *PL = nullptr ;
42
- if (Res.FuncD ) {
43
- PL = swift::getParameterList (Res.FuncD );
44
- }
45
- assert (!PL || PL->size () == ParamsToPass.size ());
46
-
47
41
bool ShowGlobalCompletions = false ;
48
42
for (auto Idx : range (*Res.ParamIdx , ParamsToPass.size ())) {
49
43
bool IsCompletion = (Idx == Res.ParamIdx );
@@ -53,22 +47,21 @@ bool ArgumentTypeCheckCompletionCallback::addPossibleParams(
53
47
break ;
54
48
}
55
49
56
- const AnyFunctionType::Param *P = &ParamsToPass[Idx];
57
- bool Required =
58
- !(PL && PL->get (Idx)->isDefaultArgument ()) && !P->isVariadic ();
50
+ const AnyFunctionType::Param *TypeParam = &ParamsToPass[Idx];
51
+ bool Required = !Res.DeclParamIsOptional [Idx];
59
52
60
- if (P ->hasLabel () && !(IsCompletion && Res.IsNoninitialVariadic )) {
53
+ if (TypeParam ->hasLabel () && !(IsCompletion && Res.IsNoninitialVariadic )) {
61
54
// Suggest parameter label if parameter has label, we are completing in it
62
55
// and it is not a variadic parameter that already has arguments
63
- PossibleParamInfo PP (P , Required);
56
+ PossibleParamInfo PP (TypeParam , Required);
64
57
if (!llvm::is_contained (Params, PP)) {
65
58
Params.push_back (std::move (PP));
66
59
}
67
60
} else {
68
61
// We have a parameter that doesn't require a label. Suggest global
69
62
// results for that type.
70
63
ShowGlobalCompletions = true ;
71
- Types.push_back (P ->getPlainType ());
64
+ Types.push_back (TypeParam ->getPlainType ());
72
65
}
73
66
if (Required) {
74
67
// The user should only be suggested the first required param. Stop.
@@ -157,7 +150,7 @@ void ArgumentTypeCheckCompletionCallback::sawSolutionImpl(const Solution &S) {
157
150
auto *CalleeLocator = S.getCalleeLocator (CallLocator);
158
151
159
152
auto Info = getSelectedOverloadInfo (S, CalleeLocator);
160
- if (Info.Value && Info.Value ->shouldHideFromEditor ()) {
153
+ if (Info.getValue () && Info.getValue () ->shouldHideFromEditor ()) {
161
154
return ;
162
155
}
163
156
// Disallow invalid initializer references
@@ -215,7 +208,7 @@ void ArgumentTypeCheckCompletionCallback::sawSolutionImpl(const Solution &S) {
215
208
216
209
// If this is a duplicate of any other result, ignore this solution.
217
210
if (llvm::any_of (Results, [&](const Result &R) {
218
- return R.FuncD == Info.Value &&
211
+ return R.FuncD == Info.getValue () &&
219
212
nullableTypesEqual (R.FuncTy , Info.ValueTy ) &&
220
213
nullableTypesEqual (R.BaseType , Info.BaseTy ) &&
221
214
R.ParamIdx == ParamIdx &&
@@ -231,10 +224,34 @@ void ArgumentTypeCheckCompletionCallback::sawSolutionImpl(const Solution &S) {
231
224
if (Info.ValueTy ) {
232
225
FuncTy = Info.ValueTy ->lookThroughAllOptionalTypes ()->getAs <AnyFunctionType>();
233
226
}
227
+
228
+ // Determine which parameters is optional. We need to do this in
229
+ // `sawSolutionImpl` because it accesses the substitution map in
230
+ // `Info.ValueRef`. This substitution map might contain tyep variables that
231
+ // are allocated in the constraint system's arena and are freed once we reach
232
+ // `deliverResults`.
233
+ std::vector<bool > DeclParamIsOptional;
234
+ if (FuncTy) {
235
+ ArrayRef<AnyFunctionType::Param> ParamsToPass = FuncTy->getParams ();
236
+ for (auto Idx : range (0 , ParamsToPass.size ())) {
237
+ bool Optional = false ;
238
+ if (Info.ValueRef ) {
239
+ if (const ParamDecl *DeclParam = getParameterAt (Info.ValueRef , Idx)) {
240
+ Optional |= DeclParam->isDefaultArgument ();
241
+ Optional |= DeclParam->getType ()->is <PackExpansionType>();
242
+ }
243
+ }
244
+ const AnyFunctionType::Param *TypeParam = &ParamsToPass[Idx];
245
+ Optional |= TypeParam->isVariadic ();
246
+ DeclParamIsOptional.push_back (Optional);
247
+ }
248
+ }
249
+
234
250
Results.push_back ({ExpectedTy, ExpectedCallType,
235
- isa<SubscriptExpr>(ParentCall), Info.Value , FuncTy, ArgIdx,
236
- ParamIdx, std::move (ClaimedParams), IsNoninitialVariadic,
237
- Info.BaseTy , HasLabel, IsAsync, SolutionSpecificVarTypes});
251
+ isa<SubscriptExpr>(ParentCall), Info.getValue (), FuncTy,
252
+ ArgIdx, ParamIdx, std::move (ClaimedParams),
253
+ IsNoninitialVariadic, Info.BaseTy , HasLabel, IsAsync,
254
+ DeclParamIsOptional, SolutionSpecificVarTypes});
238
255
}
239
256
240
257
void ArgumentTypeCheckCompletionCallback::computeShadowedDecls (
@@ -243,7 +260,8 @@ void ArgumentTypeCheckCompletionCallback::computeShadowedDecls(
243
260
auto &ResultA = Results[i];
244
261
for (size_t j = i + 1 ; j < Results.size (); ++j) {
245
262
auto &ResultB = Results[j];
246
- if (!ResultA.FuncD || !ResultB.FuncD || !ResultA.FuncTy || !ResultB.FuncTy ) {
263
+ if (!ResultA.FuncD || !ResultB.FuncD || !ResultA.FuncTy ||
264
+ !ResultB.FuncTy ) {
247
265
continue ;
248
266
}
249
267
if (ResultA.FuncD ->getName () != ResultB.FuncD ->getName ()) {
0 commit comments