Skip to content

Commit b51df73

Browse files
Merge pull request #4410 from swiftwasm/main
[pull] swiftwasm from main
2 parents a8d1f2f + 0ded798 commit b51df73

16 files changed

+201
-99
lines changed

include/swift/IDE/ArgumentCompletion.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,11 @@ class ArgumentTypeCheckCompletionCallback : public TypeCheckCompletionCallback {
4848
/// Whether the surrounding context is async and thus calling async
4949
/// functions is supported.
5050
bool IsInAsyncContext;
51+
52+
/// Types of variables that were determined in the solution that produced
53+
/// this result. This in particular includes parameters of closures that
54+
/// were type-checked with the code completion expression.
55+
llvm::SmallDenseMap<const VarDecl *, Type> SolutionSpecificVarTypes;
5156
};
5257

5358
CodeCompletionExpr *CompletionExpr;

include/swift/IDE/TypeCheckCompletionCallback.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,13 @@ Type getTypeForCompletion(const constraints::Solution &S, ASTNode Node);
7575
/// completion expression \p E.
7676
Type getPatternMatchType(const constraints::Solution &S, Expr *E);
7777

78+
/// Populate \p Result with types of variables that were determined in the
79+
/// solution \p S. This in particular includes parameters of closures that
80+
/// were type-checked with the code completion expression.
81+
void getSolutionSpecificVarTypes(
82+
const constraints::Solution &S,
83+
llvm::SmallDenseMap<const VarDecl *, Type> &Result);
84+
7885
/// Whether the given completion expression is the only expression in its
7986
/// containing closure or function body and its value is implicitly returned.
8087
///

include/swift/Sema/ConstraintSystem.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1288,6 +1288,24 @@ class Solution {
12881288
/// type variables for their fixed types.
12891289
Type simplifyType(Type type) const;
12901290

1291+
// To aid code completion, we need to attempt to convert type placeholders
1292+
// back into underlying generic parameters if possible, since type
1293+
// of the code completion expression is used as "expected" (or contextual)
1294+
// type so it's helpful to know what requirements it has to filter
1295+
// the list of possible member candidates e.g.
1296+
//
1297+
// \code
1298+
// func test<T: P>(_: [T]) {}
1299+
//
1300+
// test(42.#^MEMBERS^#)
1301+
// \code
1302+
//
1303+
// It's impossible to resolve `T` in this case but code completion
1304+
// expression should still have a type of `[T]` instead of `[<<hole>>]`
1305+
// because it helps to produce correct contextual member list based on
1306+
// a conformance requirement associated with generic parameter `T`.
1307+
Type simplifyTypeForCodeCompletion(Type type) const;
1308+
12911309
/// Coerce the given expression to the given type.
12921310
///
12931311
/// This operation cannot fail.

lib/AST/ASTDumper.cpp

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3826,17 +3826,20 @@ namespace {
38263826
void printAnyFunctionTypeCommon(AnyFunctionType *T, StringRef label,
38273827
StringRef name) {
38283828
printCommon(label, name);
3829-
SILFunctionType::Representation representation =
3830-
T->getExtInfo().getSILRepresentation();
38313829

3832-
if (representation != SILFunctionType::Representation::Thick)
3833-
printField("representation",
3834-
getSILFunctionTypeRepresentationString(representation));
3830+
if (T->hasExtInfo()) {
3831+
SILFunctionType::Representation representation =
3832+
T->getExtInfo().getSILRepresentation();
38353833

3836-
printFlag(!T->isNoEscape(), "escaping");
3837-
printFlag(T->isSendable(), "Sendable");
3838-
printFlag(T->isAsync(), "async");
3839-
printFlag(T->isThrowing(), "throws");
3834+
if (representation != SILFunctionType::Representation::Thick) {
3835+
printField("representation",
3836+
getSILFunctionTypeRepresentationString(representation));
3837+
}
3838+
printFlag(!T->isNoEscape(), "escaping");
3839+
printFlag(T->isSendable(), "Sendable");
3840+
printFlag(T->isAsync(), "async");
3841+
printFlag(T->isThrowing(), "throws");
3842+
}
38403843

38413844
if (Type globalActor = T->getGlobalActor()) {
38423845
printField("global_actor", globalActor.getString());

lib/Frontend/CompilerInvocation.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1197,7 +1197,9 @@ static bool ParseClangImporterArgs(ClangImporterOptions &Opts,
11971197

11981198
Opts.DisableOverlayModules |= Args.hasArg(OPT_emit_imported_modules);
11991199

1200-
Opts.EnableClangSPI = !Args.hasArg(OPT_disable_clang_spi);
1200+
if (Args.hasArg(OPT_disable_clang_spi)) {
1201+
Opts.EnableClangSPI = false;
1202+
}
12011203

12021204
Opts.ExtraArgsOnly |= Args.hasArg(OPT_extra_clang_options_only);
12031205

lib/Frontend/ModuleInterfaceLoader.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1493,6 +1493,11 @@ InterfaceSubContextDelegateImpl::InterfaceSubContextDelegateImpl(
14931493
}
14941494
}
14951495

1496+
subClangImporterOpts.EnableClangSPI = clangImporterOpts.EnableClangSPI;
1497+
if (!subClangImporterOpts.EnableClangSPI) {
1498+
GenericArgs.push_back("-disable-clang-spi");
1499+
}
1500+
14961501
// Tell the genericSubInvocation to serialize dependency hashes if asked to do
14971502
// so.
14981503
auto &frontendOpts = genericSubInvocation.getFrontendOptions();

lib/IDE/ArgumentCompletion.cpp

Lines changed: 59 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -104,34 +104,39 @@ void ArgumentTypeCheckCompletionCallback::sawSolutionImpl(const Solution &S) {
104104

105105
auto *CallLocator = CS.getConstraintLocator(ParentCall);
106106
auto *CalleeLocator = S.getCalleeLocator(CallLocator);
107-
auto SelectedOverload = S.getOverloadChoiceIfAvailable(CalleeLocator);
108-
if (!SelectedOverload) {
109-
return;
110-
}
111-
112-
Type CallBaseTy = SelectedOverload->choice.getBaseType();
113-
if (CallBaseTy) {
114-
CallBaseTy = S.simplifyType(CallBaseTy)->getRValueType();
115-
}
107+
ValueDecl *FuncD = nullptr;
108+
Type FuncTy;
109+
Type CallBaseTy;
110+
// If we are calling a closure in-place there is no overload choice, but we
111+
// still have all the other required information (like the argument's
112+
// expected type) to provide useful code completion results.
113+
if (auto SelectedOverload = S.getOverloadChoiceIfAvailable(CalleeLocator)) {
114+
115+
CallBaseTy = SelectedOverload->choice.getBaseType();
116+
if (CallBaseTy) {
117+
CallBaseTy = S.simplifyType(CallBaseTy)->getRValueType();
118+
}
116119

117-
ValueDecl *FuncD = SelectedOverload->choice.getDeclOrNull();
118-
Type FuncTy = S.simplifyType(SelectedOverload->openedType)->getRValueType();
119-
120-
// For completion as the arg in a call to the implicit [keypath: _] subscript
121-
// the solver can't know what kind of keypath is expected without an actual
122-
// argument (e.g. a KeyPath vs WritableKeyPath) so it ends up as a hole.
123-
// Just assume KeyPath so we show the expected keypath's root type to users
124-
// rather than '_'.
125-
if (SelectedOverload->choice.getKind() ==
126-
OverloadChoiceKind::KeyPathApplication) {
127-
auto Params = FuncTy->getAs<AnyFunctionType>()->getParams();
128-
if (Params.size() == 1 && Params[0].getPlainType()->is<UnresolvedType>()) {
129-
auto *KPDecl = CS.getASTContext().getKeyPathDecl();
130-
Type KPTy =
131-
KPDecl->mapTypeIntoContext(KPDecl->getDeclaredInterfaceType());
132-
Type KPValueTy = KPTy->castTo<BoundGenericType>()->getGenericArgs()[1];
133-
KPTy = BoundGenericType::get(KPDecl, Type(), {CallBaseTy, KPValueTy});
134-
FuncTy = FunctionType::get({Params[0].withType(KPTy)}, KPValueTy);
120+
FuncD = SelectedOverload->choice.getDeclOrNull();
121+
FuncTy = S.simplifyTypeForCodeCompletion(SelectedOverload->openedType);
122+
123+
// For completion as the arg in a call to the implicit [keypath: _]
124+
// subscript the solver can't know what kind of keypath is expected without
125+
// an actual argument (e.g. a KeyPath vs WritableKeyPath) so it ends up as a
126+
// hole. Just assume KeyPath so we show the expected keypath's root type to
127+
// users rather than '_'.
128+
if (SelectedOverload->choice.getKind() ==
129+
OverloadChoiceKind::KeyPathApplication) {
130+
auto Params = FuncTy->getAs<AnyFunctionType>()->getParams();
131+
if (Params.size() == 1 &&
132+
Params[0].getPlainType()->is<UnresolvedType>()) {
133+
auto *KPDecl = CS.getASTContext().getKeyPathDecl();
134+
Type KPTy =
135+
KPDecl->mapTypeIntoContext(KPDecl->getDeclaredInterfaceType());
136+
Type KPValueTy = KPTy->castTo<BoundGenericType>()->getGenericArgs()[1];
137+
KPTy = BoundGenericType::get(KPDecl, Type(), {CallBaseTy, KPValueTy});
138+
FuncTy = FunctionType::get({Params[0].withType(KPTy)}, KPValueTy);
139+
}
135140
}
136141
}
137142

@@ -193,9 +198,13 @@ void ArgumentTypeCheckCompletionCallback::sawSolutionImpl(const Solution &S) {
193198
return;
194199
}
195200

201+
llvm::SmallDenseMap<const VarDecl *, Type> SolutionSpecificVarTypes;
202+
getSolutionSpecificVarTypes(S, SolutionSpecificVarTypes);
203+
196204
Results.push_back({ExpectedTy, isa<SubscriptExpr>(ParentCall), FuncD, FuncTy,
197205
ArgIdx, ParamIdx, std::move(ClaimedParams),
198-
IsNoninitialVariadic, CallBaseTy, HasLabel, IsAsync});
206+
IsNoninitialVariadic, CallBaseTy, HasLabel, IsAsync,
207+
SolutionSpecificVarTypes});
199208
}
200209

201210
void ArgumentTypeCheckCompletionCallback::deliverResults(
@@ -231,15 +240,27 @@ void ArgumentTypeCheckCompletionCallback::deliverResults(
231240
SemanticContext = SemanticContextKind::CurrentNominal;
232241
}
233242
}
234-
if (Result.IsSubscript) {
235-
assert(SemanticContext != SemanticContextKind::None);
236-
auto *SD = dyn_cast_or_null<SubscriptDecl>(Result.FuncD);
237-
Lookup.addSubscriptCallPattern(Result.FuncTy->getAs<AnyFunctionType>(),
238-
SD, SemanticContext);
239-
} else {
240-
auto *FD = dyn_cast_or_null<AbstractFunctionDecl>(Result.FuncD);
241-
Lookup.addFunctionCallPattern(Result.FuncTy->getAs<AnyFunctionType>(),
242-
FD, SemanticContext);
243+
if (SemanticContext == SemanticContextKind::None && Result.FuncD) {
244+
if (Result.FuncD->getDeclContext()->isTypeContext()) {
245+
SemanticContext = SemanticContextKind::CurrentNominal;
246+
} else if (Result.FuncD->getDeclContext()->isLocalContext()) {
247+
SemanticContext = SemanticContextKind::Local;
248+
} else if (Result.FuncD->getModuleContext() == DC->getParentModule()) {
249+
SemanticContext = SemanticContextKind::CurrentModule;
250+
}
251+
}
252+
if (Result.FuncTy) {
253+
if (auto FuncTy = Result.FuncTy->lookThroughAllOptionalTypes()
254+
->getAs<AnyFunctionType>()) {
255+
if (Result.IsSubscript) {
256+
assert(SemanticContext != SemanticContextKind::None);
257+
auto *SD = dyn_cast_or_null<SubscriptDecl>(Result.FuncD);
258+
Lookup.addSubscriptCallPattern(FuncTy, SD, SemanticContext);
259+
} else {
260+
auto *FD = dyn_cast_or_null<AbstractFunctionDecl>(Result.FuncD);
261+
Lookup.addFunctionCallPattern(FuncTy, FD, SemanticContext);
262+
}
263+
}
243264
}
244265
}
245266
Lookup.setHaveLParen(false);
@@ -258,6 +279,7 @@ void ArgumentTypeCheckCompletionCallback::deliverResults(
258279
if (shouldPerformGlobalCompletion) {
259280
for (auto &Result : Results) {
260281
ExpectedTypes.push_back(Result.ExpectedType);
282+
Lookup.setSolutionSpecificVarTypes(Result.SolutionSpecificVarTypes);
261283
}
262284
Lookup.setExpectedTypes(ExpectedTypes, false);
263285
bool IsInAsyncContext = llvm::any_of(

lib/IDE/CompletionLookup.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -977,13 +977,14 @@ void CompletionLookup::addEffectsSpecifiers(
977977
assert(AFT != nullptr);
978978

979979
// 'async'.
980-
if (forceAsync || (AFD && AFD->hasAsync()) || AFT->isAsync())
980+
if (forceAsync || (AFD && AFD->hasAsync()) ||
981+
(AFT->hasExtInfo() && AFT->isAsync()))
981982
Builder.addAnnotatedAsync();
982983

983984
// 'throws' or 'rethrows'.
984985
if (AFD && AFD->getAttrs().hasAttribute<RethrowsAttr>())
985986
Builder.addAnnotatedRethrows();
986-
else if (AFT->isThrowing())
987+
else if (AFT->hasExtInfo() && AFT->isThrowing())
987988
Builder.addAnnotatedThrows();
988989
}
989990

@@ -1146,7 +1147,8 @@ void CompletionLookup::addFunctionCallPattern(
11461147
else
11471148
addTypeAnnotation(Builder, AFT->getResult(), genericSig);
11481149

1149-
if (!isForCaching() && AFT->isAsync() && !CanCurrDeclContextHandleAsync) {
1150+
if (!isForCaching() && AFT->hasExtInfo() && AFT->isAsync() &&
1151+
!CanCurrDeclContextHandleAsync) {
11501152
Builder.setContextualNotRecommended(
11511153
ContextualNotRecommendedReason::InvalidAsyncContext);
11521154
}

lib/IDE/ExprCompletion.cpp

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -78,11 +78,7 @@ void ExprTypeCheckCompletionCallback::sawSolutionImpl(
7878
bool IsAsync = isContextAsync(S, DC);
7979

8080
llvm::SmallDenseMap<const VarDecl *, Type> SolutionSpecificVarTypes;
81-
for (auto NT : S.nodeTypes) {
82-
if (auto VD = dyn_cast_or_null<VarDecl>(NT.first.dyn_cast<Decl *>())) {
83-
SolutionSpecificVarTypes[VD] = S.simplifyType(NT.second);
84-
}
85-
}
81+
getSolutionSpecificVarTypes(S, SolutionSpecificVarTypes);
8682

8783
addResult(ImplicitReturn, IsAsync, SolutionSpecificVarTypes);
8884
addExpectedType(ExpectedTy);

lib/IDE/TypeCheckCompletionCallback.cpp

Lines changed: 12 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -51,47 +51,8 @@ Type swift::ide::getTypeForCompletion(const constraints::Solution &S,
5151

5252
Type Result;
5353

54-
// To aid code completion, we need to attempt to convert type placeholders
55-
// back into underlying generic parameters if possible, since type
56-
// of the code completion expression is used as "expected" (or contextual)
57-
// type so it's helpful to know what requirements it has to filter
58-
// the list of possible member candidates e.g.
59-
//
60-
// \code
61-
// func test<T: P>(_: [T]) {}
62-
//
63-
// test(42.#^MEMBERS^#)
64-
// \code
65-
//
66-
// It's impossible to resolve `T` in this case but code completion
67-
// expression should still have a type of `[T]` instead of `[<<hole>>]`
68-
// because it helps to produce correct contextual member list based on
69-
// a conformance requirement associated with generic parameter `T`.
7054
if (isExpr<CodeCompletionExpr>(Node)) {
71-
auto completionTy = S.getType(Node).transform([&](Type type) -> Type {
72-
if (auto *typeVar = type->getAs<TypeVariableType>())
73-
return S.getFixedType(typeVar);
74-
return type;
75-
});
76-
77-
Result = S.simplifyType(completionTy.transform([&](Type type) {
78-
if (auto *placeholder = type->getAs<PlaceholderType>()) {
79-
if (auto *typeVar =
80-
placeholder->getOriginator().dyn_cast<TypeVariableType *>()) {
81-
if (auto *GP = typeVar->getImpl().getGenericParameter()) {
82-
// Code completion depends on generic parameter type being
83-
// represented in terms of `ArchetypeType` since it's easy
84-
// to extract protocol requirements from it.
85-
if (auto *GPD = GP->getDecl())
86-
return GPD->getInnermostDeclContext()->mapTypeIntoContext(GP);
87-
}
88-
}
89-
90-
return Type(CS.getASTContext().TheUnresolvedType);
91-
}
92-
93-
return type;
94-
}));
55+
Result = S.simplifyTypeForCodeCompletion(S.getType(Node));
9556
} else {
9657
Result = S.getResolvedType(Node);
9758
}
@@ -164,6 +125,17 @@ Type swift::ide::getPatternMatchType(const constraints::Solution &S, Expr *E) {
164125
return nullptr;
165126
}
166127

128+
void swift::ide::getSolutionSpecificVarTypes(
129+
const constraints::Solution &S,
130+
llvm::SmallDenseMap<const VarDecl *, Type> &Result) {
131+
assert(Result.empty());
132+
for (auto NT : S.nodeTypes) {
133+
if (auto VD = dyn_cast_or_null<VarDecl>(NT.first.dyn_cast<Decl *>())) {
134+
Result[VD] = S.simplifyType(NT.second);
135+
}
136+
}
137+
}
138+
167139
bool swift::ide::isImplicitSingleExpressionReturn(ConstraintSystem &CS,
168140
Expr *CompletionExpr) {
169141
Expr *ParentExpr = CS.getParentExpr(CompletionExpr);

lib/Sema/CSSimplify.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1275,6 +1275,9 @@ class CompletionArgumentTracker : public ArgumentFailureTracker {
12751275
if (ArgInfo.isBefore(argIdx)) {
12761276
return false;
12771277
}
1278+
if (argIdx == 0 && ArgInfo.completionIdx == 0) {
1279+
return false;
1280+
}
12781281
return ArgumentFailureTracker::extraArgument(argIdx);
12791282
}
12801283

@@ -1825,7 +1828,6 @@ static ConstraintSystem::TypeMatchResult matchCallArguments(
18251828
auto *argExpr = getArgumentExpr(locator.getAnchor(), argIdx);
18261829
if (param.isAutoClosure() && !isSynthesizedArgument(argument)) {
18271830
auto &ctx = cs.getASTContext();
1828-
auto *fnType = paramTy->castTo<FunctionType>();
18291831

18301832
// If this is a call to a function with a closure argument and the
18311833
// parameter is an autoclosure, let's just increment the score here
@@ -1845,7 +1847,9 @@ static ConstraintSystem::TypeMatchResult matchCallArguments(
18451847
if (ctx.isSwiftVersionAtLeast(5) || !isAutoClosureArgument(argExpr)) {
18461848
// In Swift >= 5 mode there is no @autoclosure forwarding,
18471849
// so let's match result types.
1848-
paramTy = fnType->getResult();
1850+
if (auto *fnType = paramTy->getAs<FunctionType>()) {
1851+
paramTy = fnType->getResult();
1852+
}
18491853
} else {
18501854
// Matching @autoclosure argument to @autoclosure parameter
18511855
// directly would mean introducting a function conversion

0 commit comments

Comments
 (0)