Skip to content

Commit 1db0947

Browse files
authored
Merge pull request #65837 from ahoppen/ahoppen/fix-asan-failure
2 parents f651afe + 9dd87e9 commit 1db0947

File tree

2 files changed

+51
-43
lines changed

2 files changed

+51
-43
lines changed

Diff for: include/swift/IDE/ArgumentCompletion.h

+9-5
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@ class ArgumentTypeCheckCompletionCallback : public TypeCheckCompletionCallback {
2929
Type ExpectedCallType;
3030
/// True if this is a subscript rather than a function call.
3131
bool IsSubscript;
32-
/// The reference to the FuncDecl or SubscriptDecl associated with the call.
33-
ConcreteDeclRef FuncDeclRef;
32+
/// The FuncDecl or SubscriptDecl associated with the call.
33+
ValueDecl *FuncD;
3434
/// The type of the function being called.
3535
AnyFunctionType *FuncTy;
3636
/// The index of the argument containing the completion location
@@ -50,14 +50,18 @@ class ArgumentTypeCheckCompletionCallback : public TypeCheckCompletionCallback {
5050
/// Whether the surrounding context is async and thus calling async
5151
/// functions is supported.
5252
bool IsInAsyncContext;
53+
/// A bitfield to mark whether the parameter at a given index is optional.
54+
/// Parameters can be optional if they have a default argument or belong to
55+
/// a parameter pack.
56+
/// Indices are based on the parameters in \c FuncTy. Note that the number
57+
/// of parameters in \c FuncTy and \c FuncD is different when a parameter
58+
/// pack has been exploded.
59+
llvm::BitVector DeclParamIsOptional;
5360

5461
/// Types of variables that were determined in the solution that produced
5562
/// this result. This in particular includes parameters of closures that
5663
/// were type-checked with the code completion expression.
5764
llvm::SmallDenseMap<const VarDecl *, Type> SolutionSpecificVarTypes;
58-
59-
/// Return the \c FuncDecl or \c SubscriptDecl associated with this call.
60-
ValueDecl *getFuncD() const { return FuncDeclRef.getDecl(); }
6165
};
6266

6367
CodeCompletionExpr *CompletionExpr;

Diff for: lib/IDE/ArgumentCompletion.cpp

+42-38
Original file line numberDiff line numberDiff line change
@@ -47,25 +47,8 @@ bool ArgumentTypeCheckCompletionCallback::addPossibleParams(
4747
break;
4848
}
4949

50-
// We work with the parameter from the function type and the declaration
51-
// because they contain different information that we need.
52-
//
53-
// Since not all function types are backed by declarations (e.g. closure
54-
// paramters), `DeclParam` might be `nullptr`.
5550
const AnyFunctionType::Param *TypeParam = &ParamsToPass[Idx];
56-
const ParamDecl *DeclParam = nullptr;
57-
if (Res.FuncDeclRef) {
58-
DeclParam = getParameterAt(Res.FuncDeclRef, Idx);
59-
}
60-
61-
bool Required = true;
62-
if (DeclParam && DeclParam->isDefaultArgument()) {
63-
Required = false;
64-
} else if (DeclParam && DeclParam->getType()->is<PackExpansionType>()) {
65-
Required = false;
66-
} else if (TypeParam->isVariadic()) {
67-
Required = false;
68-
}
51+
bool Required = !Res.DeclParamIsOptional[Idx];
6952

7053
if (TypeParam->hasLabel() && !(IsCompletion && Res.IsNoninitialVariadic)) {
7154
// Suggest parameter label if parameter has label, we are completing in it
@@ -225,7 +208,7 @@ void ArgumentTypeCheckCompletionCallback::sawSolutionImpl(const Solution &S) {
225208

226209
// If this is a duplicate of any other result, ignore this solution.
227210
if (llvm::any_of(Results, [&](const Result &R) {
228-
return R.FuncDeclRef == Info.ValueRef &&
211+
return R.FuncD == Info.getValue() &&
229212
nullableTypesEqual(R.FuncTy, Info.ValueTy) &&
230213
nullableTypesEqual(R.BaseType, Info.BaseTy) &&
231214
R.ParamIdx == ParamIdx &&
@@ -241,11 +224,34 @@ void ArgumentTypeCheckCompletionCallback::sawSolutionImpl(const Solution &S) {
241224
if (Info.ValueTy) {
242225
FuncTy = Info.ValueTy->lookThroughAllOptionalTypes()->getAs<AnyFunctionType>();
243226
}
227+
228+
// Determine which parameters are optional. We need to do this in
229+
// `sawSolutionImpl` because it accesses the substitution map in
230+
// `Info.ValueRef`. This substitution map might contain type variables that
231+
// are allocated in the constraint system's arena and are freed once we reach
232+
// `deliverResults`.
233+
llvm::BitVector 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+
244250
Results.push_back({ExpectedTy, ExpectedCallType,
245-
isa<SubscriptExpr>(ParentCall), Info.ValueRef, FuncTy,
251+
isa<SubscriptExpr>(ParentCall), Info.getValue(), FuncTy,
246252
ArgIdx, ParamIdx, std::move(ClaimedParams),
247253
IsNoninitialVariadic, Info.BaseTy, HasLabel, IsAsync,
248-
SolutionSpecificVarTypes});
254+
DeclParamIsOptional, SolutionSpecificVarTypes});
249255
}
250256

251257
void ArgumentTypeCheckCompletionCallback::computeShadowedDecls(
@@ -254,25 +260,25 @@ void ArgumentTypeCheckCompletionCallback::computeShadowedDecls(
254260
auto &ResultA = Results[i];
255261
for (size_t j = i + 1; j < Results.size(); ++j) {
256262
auto &ResultB = Results[j];
257-
if (!ResultA.getFuncD() || !ResultB.getFuncD() || !ResultA.FuncTy ||
263+
if (!ResultA.FuncD || !ResultB.FuncD || !ResultA.FuncTy ||
258264
!ResultB.FuncTy) {
259265
continue;
260266
}
261-
if (ResultA.getFuncD()->getName() != ResultB.getFuncD()->getName()) {
267+
if (ResultA.FuncD->getName() != ResultB.FuncD->getName()) {
262268
continue;
263269
}
264270
if (!ResultA.FuncTy->isEqual(ResultB.FuncTy)) {
265271
continue;
266272
}
267273
ProtocolDecl *inProtocolExtensionA =
268-
ResultA.getFuncD()->getDeclContext()->getExtendedProtocolDecl();
274+
ResultA.FuncD->getDeclContext()->getExtendedProtocolDecl();
269275
ProtocolDecl *inProtocolExtensionB =
270-
ResultB.getFuncD()->getDeclContext()->getExtendedProtocolDecl();
276+
ResultB.FuncD->getDeclContext()->getExtendedProtocolDecl();
271277

272278
if (inProtocolExtensionA && !inProtocolExtensionB) {
273-
ShadowedDecls.insert(ResultA.getFuncD());
279+
ShadowedDecls.insert(ResultA.FuncD);
274280
} else if (!inProtocolExtensionA && inProtocolExtensionB) {
275-
ShadowedDecls.insert(ResultB.getFuncD());
281+
ShadowedDecls.insert(ResultB.FuncD);
276282
}
277283
}
278284
}
@@ -313,37 +319,35 @@ void ArgumentTypeCheckCompletionCallback::deliverResults(
313319
}
314320
if ((BaseNominal = BaseTy->getAnyNominal())) {
315321
SemanticContext = SemanticContextKind::CurrentNominal;
316-
if (Result.getFuncD() &&
317-
Result.getFuncD()->getDeclContext()->getSelfNominalTypeDecl() !=
322+
if (Result.FuncD &&
323+
Result.FuncD->getDeclContext()->getSelfNominalTypeDecl() !=
318324
BaseNominal) {
319325
SemanticContext = SemanticContextKind::Super;
320326
}
321327
} else if (BaseTy->is<TupleType>() || BaseTy->is<SubstitutableType>()) {
322328
SemanticContext = SemanticContextKind::CurrentNominal;
323329
}
324330
}
325-
if (SemanticContext == SemanticContextKind::None && Result.getFuncD()) {
326-
if (Result.getFuncD()->getDeclContext()->isTypeContext()) {
331+
if (SemanticContext == SemanticContextKind::None && Result.FuncD) {
332+
if (Result.FuncD->getDeclContext()->isTypeContext()) {
327333
SemanticContext = SemanticContextKind::CurrentNominal;
328-
} else if (Result.getFuncD()->getDeclContext()->isLocalContext()) {
334+
} else if (Result.FuncD->getDeclContext()->isLocalContext()) {
329335
SemanticContext = SemanticContextKind::Local;
330-
} else if (Result.getFuncD()->getModuleContext() ==
331-
DC->getParentModule()) {
336+
} else if (Result.FuncD->getModuleContext() == DC->getParentModule()) {
332337
SemanticContext = SemanticContextKind::CurrentModule;
333338
}
334339
}
335340
if (Result.FuncTy) {
336341
if (auto FuncTy = Result.FuncTy) {
337-
if (ShadowedDecls.count(Result.getFuncD()) == 0) {
342+
if (ShadowedDecls.count(Result.FuncD) == 0) {
338343
// Don't show call pattern completions if the function is
339344
// overridden.
340345
if (Result.IsSubscript) {
341346
assert(SemanticContext != SemanticContextKind::None);
342-
auto *SD = dyn_cast_or_null<SubscriptDecl>(Result.getFuncD());
347+
auto *SD = dyn_cast_or_null<SubscriptDecl>(Result.FuncD);
343348
Lookup.addSubscriptCallPattern(FuncTy, SD, SemanticContext);
344349
} else {
345-
auto *FD =
346-
dyn_cast_or_null<AbstractFunctionDecl>(Result.getFuncD());
350+
auto *FD = dyn_cast_or_null<AbstractFunctionDecl>(Result.FuncD);
347351
Lookup.addFunctionCallPattern(FuncTy, FD, SemanticContext);
348352
}
349353
}

0 commit comments

Comments
 (0)