@@ -24,7 +24,7 @@ using namespace swift::constraints;
24
24
bool ArgumentTypeCheckCompletionCallback::addPossibleParams (
25
25
const ArgumentTypeCheckCompletionCallback::Result &Res,
26
26
SmallVectorImpl<PossibleParamInfo> &Params, SmallVectorImpl<Type> &Types) {
27
- if (!Res.ParamIdx ) {
27
+ if (!Res.ParamIdx || !Res. FuncTy ) {
28
28
// We don't really know much here. Suggest global results without a specific
29
29
// expected type.
30
30
return true ;
@@ -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,10 +149,25 @@ 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
117
160
auto Info = getSelectedOverloadInfo (S, CalleeLocator);
161
+ if (Info.Value && Info.Value ->shouldHideFromEditor ()) {
162
+ return ;
163
+ }
164
+ // Disallow invalid initializer references
165
+ for (auto Fix : S.Fixes ) {
166
+ if (Fix->getLocator () == CalleeLocator &&
167
+ Fix->getKind () == FixKind::AllowInvalidInitRef) {
168
+ return ;
169
+ }
170
+ }
118
171
119
172
// Find the parameter the completion was bound to (if any), as well as which
120
173
// parameters are already bound (so we don't suggest them even when the args
@@ -179,10 +232,39 @@ void ArgumentTypeCheckCompletionCallback::sawSolutionImpl(const Solution &S) {
179
232
if (Info.ValueTy ) {
180
233
FuncTy = Info.ValueTy ->lookThroughAllOptionalTypes ()->getAs <AnyFunctionType>();
181
234
}
182
- Results.push_back ({ExpectedTy, isa<SubscriptExpr>(ParentCall), Info.Value ,
183
- FuncTy, ArgIdx, ParamIdx, std::move (ClaimedParams),
184
- IsNoninitialVariadic, Info.BaseTy , HasLabel, IsAsync,
185
- 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});
239
+ }
240
+
241
+ void ArgumentTypeCheckCompletionCallback::computeShadowedDecls (
242
+ SmallPtrSetImpl<ValueDecl *> &ShadowedDecls) {
243
+ for (size_t i = 0 ; i < Results.size (); ++i) {
244
+ auto &ResultA = Results[i];
245
+ for (size_t j = i + 1 ; j < Results.size (); ++j) {
246
+ auto &ResultB = Results[j];
247
+ if (!ResultA.FuncD || !ResultB.FuncD || !ResultA.FuncTy || !ResultB.FuncTy ) {
248
+ continue ;
249
+ }
250
+ if (ResultA.FuncD ->getName () != ResultB.FuncD ->getName ()) {
251
+ continue ;
252
+ }
253
+ if (!ResultA.FuncTy ->isEqual (ResultB.FuncTy )) {
254
+ continue ;
255
+ }
256
+ ProtocolDecl *inProtocolExtensionA =
257
+ ResultA.FuncD ->getDeclContext ()->getExtendedProtocolDecl ();
258
+ ProtocolDecl *inProtocolExtensionB =
259
+ ResultB.FuncD ->getDeclContext ()->getExtendedProtocolDecl ();
260
+
261
+ if (inProtocolExtensionA && !inProtocolExtensionB) {
262
+ ShadowedDecls.insert (ResultA.FuncD );
263
+ } else if (!inProtocolExtensionA && inProtocolExtensionB) {
264
+ ShadowedDecls.insert (ResultB.FuncD );
265
+ }
266
+ }
267
+ }
186
268
}
187
269
188
270
void ArgumentTypeCheckCompletionCallback::deliverResults (
@@ -193,12 +275,23 @@ void ArgumentTypeCheckCompletionCallback::deliverResults(
193
275
CompletionLookup Lookup (CompletionCtx.getResultSink (), Ctx, DC,
194
276
&CompletionCtx);
195
277
278
+ SmallPtrSet<ValueDecl *, 4 > ShadowedDecls;
279
+ computeShadowedDecls (ShadowedDecls);
280
+
196
281
// Perform global completion as a fallback if we don't have any results.
197
282
bool shouldPerformGlobalCompletion = Results.empty ();
283
+ SmallVector<Type, 4 > ExpectedCallTypes;
284
+ for (auto &Result : Results) {
285
+ ExpectedCallTypes.push_back (Result.ExpectedCallType );
286
+ }
287
+
198
288
SmallVector<Type, 8 > ExpectedTypes;
199
289
200
290
if (IncludeSignature && !Results.empty ()) {
201
291
Lookup.setHaveLParen (true );
292
+ Lookup.setExpectedTypes (ExpectedCallTypes,
293
+ /* isImplicitSingleExpressionReturn=*/ false );
294
+
202
295
for (auto &Result : Results) {
203
296
auto SemanticContext = SemanticContextKind::None;
204
297
NominalTypeDecl *BaseNominal = nullptr ;
@@ -229,13 +322,17 @@ void ArgumentTypeCheckCompletionCallback::deliverResults(
229
322
}
230
323
if (Result.FuncTy ) {
231
324
if (auto FuncTy = Result.FuncTy ) {
232
- if (Result.IsSubscript ) {
233
- assert (SemanticContext != SemanticContextKind::None);
234
- auto *SD = dyn_cast_or_null<SubscriptDecl>(Result.FuncD );
235
- Lookup.addSubscriptCallPattern (FuncTy, SD, SemanticContext);
236
- } else {
237
- auto *FD = dyn_cast_or_null<AbstractFunctionDecl>(Result.FuncD );
238
- Lookup.addFunctionCallPattern (FuncTy, FD, SemanticContext);
325
+ if (ShadowedDecls.count (Result.FuncD ) == 0 ) {
326
+ // Don't show call pattern completions if the function is
327
+ // overridden.
328
+ if (Result.IsSubscript ) {
329
+ assert (SemanticContext != SemanticContextKind::None);
330
+ auto *SD = dyn_cast_or_null<SubscriptDecl>(Result.FuncD );
331
+ Lookup.addSubscriptCallPattern (FuncTy, SD, SemanticContext);
332
+ } else {
333
+ auto *FD = dyn_cast_or_null<AbstractFunctionDecl>(Result.FuncD );
334
+ Lookup.addFunctionCallPattern (FuncTy, FD, SemanticContext);
335
+ }
239
336
}
240
337
}
241
338
}
0 commit comments