@@ -157,27 +157,165 @@ static ConstructorComparison compareConstructors(ConstructorDecl *ctor1,
157
157
return ConstructorComparison::Same;
158
158
}
159
159
160
- bool swift::removeShadowedDecls (SmallVectorImpl<ValueDecl*> &decls,
161
- const ModuleDecl *curModule) {
162
- auto typeResolver = curModule->getASTContext ().getLazyResolver ();
163
-
164
- // Category declarations by their signatures.
165
- llvm::SmallDenseMap<std::pair<CanType, DeclBaseName>,
166
- llvm::TinyPtrVector<ValueDecl *>>
167
- CollidingDeclGroups;
168
-
169
- // / Objective-C initializers are tracked by their context type and
170
- // / full name.
171
- llvm::SmallDenseMap<std::pair<CanType, DeclName>,
172
- llvm::TinyPtrVector<ConstructorDecl *>>
173
- ObjCCollidingConstructors;
174
- bool anyCollisions = false ;
160
+ // / Given a set of declarations whose names and signatures have matched,
161
+ // / figure out which of these declarations have been shadowed by others.
162
+ static void recordShadowedDeclsAfterSignatureMatch (
163
+ ArrayRef<ValueDecl *> decls,
164
+ const ModuleDecl *curModule,
165
+ llvm::SmallPtrSetImpl<ValueDecl *> &shadowed) {
166
+ assert (decls.size () > 1 && " Nothing collided" );
167
+
168
+ // Compare each declaration to every other declaration. This is
169
+ // unavoidably O(n^2) in the number of declarations, but because they
170
+ // all have the same signature, we expect n to remain small.
171
+ ASTContext &ctx = curModule->getASTContext ();
172
+ for (unsigned firstIdx : indices (decls)) {
173
+ auto firstDecl = decls[firstIdx];
174
+ auto firstModule = firstDecl->getModuleContext ();
175
+ for (unsigned secondIdx : range (firstIdx + 1 , decls.size ())) {
176
+ // Determine whether one module takes precedence over another.
177
+ auto secondDecl = decls[secondIdx];
178
+ auto secondModule = secondDecl->getModuleContext ();
179
+
180
+ // If one declaration is in a protocol or extension thereof and the
181
+ // other is not, prefer the one that is not.
182
+ if ((bool )firstDecl->getDeclContext ()
183
+ ->getAsProtocolOrProtocolExtensionContext ()
184
+ != (bool )secondDecl->getDeclContext ()
185
+ ->getAsProtocolOrProtocolExtensionContext ()) {
186
+ if (firstDecl->getDeclContext ()
187
+ ->getAsProtocolOrProtocolExtensionContext ()) {
188
+ shadowed.insert (firstDecl);
189
+ break ;
190
+ } else {
191
+ shadowed.insert (secondDecl);
192
+ continue ;
193
+ }
194
+ }
195
+
196
+ // If one declaration is available and the other is not, prefer the
197
+ // available one.
198
+ if (firstDecl->getAttrs ().isUnavailable (ctx) !=
199
+ secondDecl->getAttrs ().isUnavailable (ctx)) {
200
+ if (firstDecl->getAttrs ().isUnavailable (ctx)) {
201
+ shadowed.insert (firstDecl);
202
+ break ;
203
+ } else {
204
+ shadowed.insert (secondDecl);
205
+ continue ;
206
+ }
207
+ }
208
+
209
+ // Don't apply module-shadowing rules to members of protocol types.
210
+ if (isa<ProtocolDecl>(firstDecl->getDeclContext ()) ||
211
+ isa<ProtocolDecl>(secondDecl->getDeclContext ()))
212
+ continue ;
213
+
214
+ // Prefer declarations in the current module over those in another
215
+ // module.
216
+ // FIXME: This is a hack. We should query a (lazily-built, cached)
217
+ // module graph to determine shadowing.
218
+ if ((firstModule == curModule) != (secondModule == curModule)) {
219
+ // If the first module is the current module, the second declaration
220
+ // is shadowed by the first.
221
+ if (firstModule == curModule) {
222
+ shadowed.insert (secondDecl);
223
+ continue ;
224
+ }
225
+
226
+ // Otherwise, the first declaration is shadowed by the second. There is
227
+ // no point in continuing to compare the first declaration to others.
228
+ shadowed.insert (firstDecl);
229
+ break ;
230
+ }
231
+
232
+ // Prefer declarations in an overlay to similar declarations in
233
+ // the Clang module it customizes.
234
+ if (firstDecl->hasClangNode () != secondDecl->hasClangNode ()) {
235
+ auto clangLoader = ctx.getClangModuleLoader ();
236
+ if (!clangLoader) continue ;
237
+
238
+ if (clangLoader->isInOverlayModuleForImportedModule (
239
+ firstDecl->getDeclContext (),
240
+ secondDecl->getDeclContext ())) {
241
+ shadowed.insert (secondDecl);
242
+ continue ;
243
+ }
244
+
245
+ if (clangLoader->isInOverlayModuleForImportedModule (
246
+ secondDecl->getDeclContext (),
247
+ firstDecl->getDeclContext ())) {
248
+ shadowed.insert (firstDecl);
249
+ break ;
250
+ }
251
+ }
252
+ }
253
+ }
254
+ }
255
+
256
+ // / Look through the given set of declarations (that all have the same name),
257
+ // / recording those that are shadowed by another declaration in the
258
+ // / \c shadowed set.
259
+ static void recordShadowDeclsAfterObjCInitMatch (
260
+ ArrayRef<ConstructorDecl *> ctors,
261
+ llvm::SmallPtrSetImpl<ValueDecl *> &shadowed) {
262
+ assert (ctors.size () > 1 && " No collisions" );
263
+
264
+ ASTContext &ctx = ctors.front ()->getASTContext ();
265
+
266
+ // Find the "best" constructor with this signature.
267
+ ConstructorDecl *bestCtor = ctors[0 ];
268
+ for (auto ctor : ctors.slice (1 )) {
269
+ auto comparison = compareConstructors (ctor, bestCtor, ctx);
270
+ if (comparison == ConstructorComparison::Better)
271
+ bestCtor = ctor;
272
+ }
273
+
274
+ // Shadow any initializers that are worse.
275
+ for (auto ctor : ctors) {
276
+ auto comparison = compareConstructors (ctor, bestCtor, ctx);
277
+ if (comparison == ConstructorComparison::Worse)
278
+ shadowed.insert (ctor);
279
+ }
280
+ }
281
+
282
+ // / Look through the given set of declarations (that all have the same name),
283
+ // / recording those that are shadowed by another declaration in the
284
+ // / \c shadowed set.
285
+ static void recordShadowedDecls (ArrayRef<ValueDecl *> decls,
286
+ const ModuleDecl *curModule,
287
+ llvm::SmallPtrSetImpl<ValueDecl *> &shadowed) {
288
+ if (decls.size () < 2 )
289
+ return ;
290
+
291
+ auto typeResolver = decls[0 ]->getASTContext ().getLazyResolver ();
292
+
293
+ // Categorize all of the declarations based on their overload signatures.
294
+ llvm::SmallDenseMap<CanType, llvm::TinyPtrVector<ValueDecl *>> collisions;
295
+ llvm::SmallVector<CanType, 2 > collisionTypes;
296
+ llvm::SmallDenseMap<NominalTypeDecl *, llvm::TinyPtrVector<ConstructorDecl *>>
297
+ objCInitializerCollisions;
298
+ llvm::TinyPtrVector<NominalTypeDecl *> objCInitializerCollisionNominals;
299
+
175
300
for (auto decl : decls) {
176
- // FIXME: Egregious hack to avoid failing when there are no declared types.
177
- // FIXME: Pass this down instead of getting it from the ASTContext.
301
+ // Specifically keep track of Objective-C initializers, which can come from
302
+ // either init methods or factory methods.
303
+ if (decl->hasClangNode ()) {
304
+ if (auto ctor = dyn_cast<ConstructorDecl>(decl)) {
305
+ auto nominal = ctor->getDeclContext ()
306
+ ->getAsNominalTypeOrNominalTypeExtensionContext ();
307
+ auto &knownInits = objCInitializerCollisions[nominal];
308
+ if (knownInits.size () == 1 ) {
309
+ objCInitializerCollisionNominals.push_back (nominal);
310
+ }
311
+ knownInits.push_back (ctor);
312
+ }
313
+ }
314
+
315
+ // We need an interface type here.
178
316
if (typeResolver)
179
317
typeResolver->resolveDeclSignature (decl);
180
-
318
+
181
319
// If the decl is currently being validated, this is likely a recursive
182
320
// reference and we'll want to skip ahead so as to avoid having its type
183
321
// attempt to desugar itself.
@@ -195,154 +333,60 @@ bool swift::removeShadowedDecls(SmallVectorImpl<ValueDecl*> &decls,
195
333
if (auto asd = dyn_cast<AbstractStorageDecl>(decl))
196
334
signature = asd->getOverloadSignatureType ();
197
335
198
- // If we've seen a declaration with this signature before, note it.
199
- auto &knownDecls =
200
- CollidingDeclGroups[std::make_pair (signature, decl->getBaseName ())];
336
+ // Record this declaration based on its signature.
337
+ auto &known = collisions[signature];
338
+ if (known.size () == 1 ) {
339
+ collisionTypes.push_back (signature);
340
+ }
341
+ known.push_back (decl);
342
+ }
343
+
344
+ // Check whether we have shadowing for signature collisions.
345
+ for (auto signature : collisionTypes) {
346
+ recordShadowedDeclsAfterSignatureMatch (collisions[signature], curModule,
347
+ shadowed);
348
+ }
349
+
350
+ // Check whether we have shadowing for Objective-C initializer collisions.
351
+ for (auto nominal : objCInitializerCollisionNominals) {
352
+ recordShadowDeclsAfterObjCInitMatch (objCInitializerCollisions[nominal],
353
+ shadowed);
354
+ }
355
+ }
356
+
357
+ bool swift::removeShadowedDecls (SmallVectorImpl<ValueDecl*> &decls,
358
+ const ModuleDecl *curModule) {
359
+ // Collect declarations with the same (full) name.
360
+ llvm::SmallDenseMap<DeclName, llvm::TinyPtrVector<ValueDecl *>>
361
+ collidingDeclGroups;
362
+ bool anyCollisions = false ;
363
+ for (auto decl : decls) {
364
+ // Record this declaration based on its full name.
365
+ auto &knownDecls = collidingDeclGroups[decl->getFullName ()];
201
366
if (!knownDecls.empty ())
202
367
anyCollisions = true ;
203
368
204
369
knownDecls.push_back (decl);
205
-
206
- // Specifically keep track of Objective-C initializers, which can come from
207
- // either init methods or factory methods.
208
- if (decl->hasClangNode ()) {
209
- if (auto ctor = dyn_cast<ConstructorDecl>(decl)) {
210
- auto ctorSignature
211
- = std::make_pair (ctor->getDeclContext ()->getDeclaredInterfaceType ()
212
- ->getCanonicalType (),
213
- decl->getFullName ());
214
- auto &knownCtors = ObjCCollidingConstructors[ctorSignature];
215
- if (!knownCtors.empty ())
216
- anyCollisions = true ;
217
- knownCtors.push_back (ctor);
218
- }
219
- }
220
370
}
221
371
222
- // If there were no signature collisions, there is nothing to do .
372
+ // If nothing collided, we're done .
223
373
if (!anyCollisions)
224
374
return false ;
225
375
226
- // Determine the set of declarations that are shadowed by other declarations .
376
+ // Walk through the declarations again, marking any declarations that shadow .
227
377
llvm::SmallPtrSet<ValueDecl *, 4 > shadowed;
228
- ASTContext &ctx = decls[0 ]->getASTContext ();
229
- for (auto &collidingDecls : CollidingDeclGroups) {
230
- // If only one declaration has this signature, it isn't shadowed by
231
- // anything.
232
- if (collidingDecls.second .size () == 1 )
233
- continue ;
234
-
235
- // Compare each declaration to every other declaration. This is
236
- // unavoidably O(n^2) in the number of declarations, but because they
237
- // all have the same signature, we expect n to remain small.
238
- for (unsigned firstIdx = 0 , n = collidingDecls.second .size ();
239
- firstIdx != n; ++firstIdx) {
240
- auto firstDecl = collidingDecls.second [firstIdx];
241
- auto firstModule = firstDecl->getModuleContext ();
242
- for (unsigned secondIdx = firstIdx + 1 ; secondIdx != n; ++secondIdx) {
243
- // Determine whether one module takes precedence over another.
244
- auto secondDecl = collidingDecls.second [secondIdx];
245
- auto secondModule = secondDecl->getModuleContext ();
246
-
247
- // If one declaration is in a protocol or extension thereof and the
248
- // other is not, prefer the one that is not.
249
- if ((bool )firstDecl->getDeclContext ()
250
- ->getAsProtocolOrProtocolExtensionContext ()
251
- != (bool )secondDecl->getDeclContext ()
252
- ->getAsProtocolOrProtocolExtensionContext ()) {
253
- if (firstDecl->getDeclContext ()
254
- ->getAsProtocolOrProtocolExtensionContext ()) {
255
- shadowed.insert (firstDecl);
256
- break ;
257
- } else {
258
- shadowed.insert (secondDecl);
259
- continue ;
260
- }
261
- }
262
-
263
- // If one declaration is available and the other is not, prefer the
264
- // available one.
265
- if (firstDecl->getAttrs ().isUnavailable (ctx) !=
266
- secondDecl->getAttrs ().isUnavailable (ctx)) {
267
- if (firstDecl->getAttrs ().isUnavailable (ctx)) {
268
- shadowed.insert (firstDecl);
269
- break ;
270
- } else {
271
- shadowed.insert (secondDecl);
272
- continue ;
273
- }
274
- }
275
-
276
- // Don't apply module-shadowing rules to members of protocol types.
277
- if (isa<ProtocolDecl>(firstDecl->getDeclContext ()) ||
278
- isa<ProtocolDecl>(secondDecl->getDeclContext ()))
279
- continue ;
280
-
281
- // Prefer declarations in the current module over those in another
282
- // module.
283
- // FIXME: This is a hack. We should query a (lazily-built, cached)
284
- // module graph to determine shadowing.
285
- if ((firstModule == curModule) != (secondModule == curModule)) {
286
- // If the first module is the current module, the second declaration
287
- // is shadowed by the first.
288
- if (firstModule == curModule) {
289
- shadowed.insert (secondDecl);
290
- continue ;
291
- }
292
-
293
- // Otherwise, the first declaration is shadowed by the second. There is
294
- // no point in continuing to compare the first declaration to others.
295
- shadowed.insert (firstDecl);
296
- break ;
297
- }
298
-
299
- // Prefer declarations in an overlay to similar declarations in
300
- // the Clang module it customizes.
301
- if (firstDecl->hasClangNode () != secondDecl->hasClangNode ()) {
302
- auto clangLoader = ctx.getClangModuleLoader ();
303
- if (!clangLoader) continue ;
304
-
305
- if (clangLoader->isInOverlayModuleForImportedModule (
306
- firstDecl->getDeclContext (),
307
- secondDecl->getDeclContext ())) {
308
- shadowed.insert (secondDecl);
309
- continue ;
310
- }
311
-
312
- if (clangLoader->isInOverlayModuleForImportedModule (
313
- secondDecl->getDeclContext (),
314
- firstDecl->getDeclContext ())) {
315
- shadowed.insert (firstDecl);
316
- break ;
317
- }
318
- }
319
- }
320
- }
321
- }
322
-
323
- // Check for collisions among Objective-C initializers. When such collisions
324
- // exist, we pick the
325
- for (const auto &colliding : ObjCCollidingConstructors) {
326
- if (colliding.second .size () == 1 )
378
+ for (auto decl : decls) {
379
+ auto known = collidingDeclGroups.find (decl->getFullName ());
380
+ if (known == collidingDeclGroups.end ()) {
381
+ // We already handled this group.
327
382
continue ;
328
-
329
- // Find the "best" constructor with this signature.
330
- ConstructorDecl *bestCtor = colliding.second [0 ];
331
- for (auto ctor : colliding.second ) {
332
- auto comparison = compareConstructors (ctor, bestCtor, ctx);
333
- if (comparison == ConstructorComparison::Better)
334
- bestCtor = ctor;
335
383
}
336
384
337
- // Shadow any initializers that are worse.
338
- for (auto ctor : colliding.second ) {
339
- auto comparison = compareConstructors (ctor, bestCtor, ctx);
340
- if (comparison == ConstructorComparison::Worse)
341
- shadowed.insert (ctor);
342
- }
385
+ recordShadowedDecls (known->second , curModule, shadowed);
386
+ collidingDeclGroups.erase (known);
343
387
}
344
388
345
- // If none of the declarations were shadowed, we're done.
389
+ // If no declarations were shadowed, we're done.
346
390
if (shadowed.empty ())
347
391
return false ;
348
392
@@ -2277,8 +2321,7 @@ directReferencesForTypeRepr(Evaluator &evaluator,
2277
2321
}
2278
2322
}
2279
2323
2280
- static DirectlyReferencedTypeDecls
2281
- directReferencesForType (Type type) {
2324
+ static DirectlyReferencedTypeDecls directReferencesForType (Type type) {
2282
2325
// If it's a typealias, return that.
2283
2326
if (auto aliasType = dyn_cast<NameAliasType>(type.getPointer ()))
2284
2327
return { 1 , aliasType->getDecl () };
0 commit comments