Skip to content

Commit 68ba9cf

Browse files
authored
Merge pull request swiftlang#32034 from slavapestov/optimize-remove-shadowed-decls
AST: Optimize removeShadowedDecls()
2 parents 94ff157 + 6ca148d commit 68ba9cf

File tree

2 files changed

+86
-37
lines changed

2 files changed

+86
-37
lines changed

lib/AST/Decl.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2810,7 +2810,7 @@ CanType ValueDecl::getOverloadSignatureType() const {
28102810
// implementation of the swift::conflicting overload that deals with
28112811
// overload types, in order to account for cases where the overload types
28122812
// don't match, but the decls differ and therefore always conflict.
2813-
2813+
assert(isa<TypeDecl>(this));
28142814
return CanType();
28152815
}
28162816

lib/AST/NameLookup.cpp

Lines changed: 85 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -244,12 +244,13 @@ static ConstructorComparison compareConstructors(ConstructorDecl *ctor1,
244244
return ConstructorComparison::Same;
245245
}
246246

247-
/// Given a set of declarations whose names and signatures have matched,
247+
/// Given a set of declarations whose names and interface types have matched,
248248
/// figure out which of these declarations have been shadowed by others.
249249
template <typename T>
250-
static void
251-
recordShadowedDeclsAfterSignatureMatch(ArrayRef<T> decls, const DeclContext *dc,
252-
llvm::SmallPtrSetImpl<T> &shadowed) {
250+
static void recordShadowedDeclsAfterTypeMatch(
251+
ArrayRef<T> decls,
252+
const DeclContext *dc,
253+
llvm::SmallPtrSetImpl<T> &shadowed) {
253254
assert(decls.size() > 1 && "Nothing collided");
254255

255256
// Compare each declaration to every other declaration. This is
@@ -491,6 +492,48 @@ recordShadowedDeclsAfterSignatureMatch(ArrayRef<T> decls, const DeclContext *dc,
491492
}
492493
}
493494

495+
/// Given a set of declarations whose names and generic signatures have matched,
496+
/// figure out which of these declarations have been shadowed by others.
497+
static void recordShadowedDeclsAfterSignatureMatch(
498+
ArrayRef<ValueDecl *> decls,
499+
const DeclContext *dc,
500+
llvm::SmallPtrSetImpl<ValueDecl *> &shadowed) {
501+
assert(decls.size() > 1 && "Nothing collided");
502+
503+
// Categorize all of the declarations based on their overload types.
504+
llvm::SmallDenseMap<CanType, llvm::TinyPtrVector<ValueDecl *>> collisions;
505+
llvm::SmallVector<CanType, 2> collisionTypes;
506+
507+
for (auto decl : decls) {
508+
assert(!isa<TypeDecl>(decl));
509+
510+
CanType type;
511+
512+
// FIXME: The type of a variable or subscript doesn't include
513+
// enough context to distinguish entities from different
514+
// constrained extensions, so use the overload signature's
515+
// type. This is layering a partial fix upon a total hack.
516+
if (auto asd = dyn_cast<AbstractStorageDecl>(decl))
517+
type = asd->getOverloadSignatureType();
518+
else
519+
type = decl->getInterfaceType()->getCanonicalType();
520+
521+
// Record this declaration based on its signature.
522+
auto &known = collisions[type];
523+
if (known.size() == 1) {
524+
collisionTypes.push_back(type);
525+
}
526+
known.push_back(decl);
527+
}
528+
529+
// Check whether we have shadowing for signature collisions.
530+
for (auto type : collisionTypes) {
531+
ArrayRef<ValueDecl *> collidingDecls = collisions[type];
532+
recordShadowedDeclsAfterTypeMatch(collidingDecls, dc,
533+
shadowed);
534+
}
535+
}
536+
494537
/// Look through the given set of declarations (that all have the same name),
495538
/// recording those that are shadowed by another declaration in the
496539
/// \c shadowed set.
@@ -526,14 +569,23 @@ static void recordShadowedDecls(ArrayRef<ValueDecl *> decls,
526569
if (decls.size() < 2)
527570
return;
528571

572+
llvm::TinyPtrVector<ValueDecl *> typeDecls;
573+
529574
// Categorize all of the declarations based on their overload signatures.
530-
llvm::SmallDenseMap<CanType, llvm::TinyPtrVector<ValueDecl *>> collisions;
531-
llvm::SmallVector<CanType, 2> collisionTypes;
532-
llvm::SmallDenseMap<NominalTypeDecl *, llvm::TinyPtrVector<ConstructorDecl *>>
575+
llvm::SmallDenseMap<const GenericSignatureImpl *,
576+
llvm::TinyPtrVector<ValueDecl *>> collisions;
577+
llvm::SmallVector<const GenericSignatureImpl *, 2> collisionSignatures;
578+
llvm::SmallDenseMap<NominalTypeDecl *,
579+
llvm::TinyPtrVector<ConstructorDecl *>>
533580
importedInitializerCollisions;
534-
llvm::TinyPtrVector<NominalTypeDecl *> importedInitializerCollectionTypes;
581+
llvm::TinyPtrVector<NominalTypeDecl *> importedInitializerCollisionTypes;
535582

536583
for (auto decl : decls) {
584+
if (auto *typeDecl = dyn_cast<TypeDecl>(decl)) {
585+
typeDecls.push_back(typeDecl);
586+
continue;
587+
}
588+
537589
// Specifically keep track of imported initializers, which can come from
538590
// Objective-C init methods, Objective-C factory methods, renamed C
539591
// functions, or be synthesized by the importer.
@@ -544,50 +596,47 @@ static void recordShadowedDecls(ArrayRef<ValueDecl *> decls,
544596
auto nominal = ctor->getDeclContext()->getSelfNominalTypeDecl();
545597
auto &knownInits = importedInitializerCollisions[nominal];
546598
if (knownInits.size() == 1) {
547-
importedInitializerCollectionTypes.push_back(nominal);
599+
importedInitializerCollisionTypes.push_back(nominal);
548600
}
549601
knownInits.push_back(ctor);
550602
}
551603
}
552604

553-
CanType signature;
605+
// If the decl is currently being validated, this is likely a recursive
606+
// reference and we'll want to skip ahead so as to avoid having its type
607+
// attempt to desugar itself.
608+
if (decl->isRecursiveValidation())
609+
continue;
554610

555-
if (!isa<TypeDecl>(decl)) {
556-
// If the decl is currently being validated, this is likely a recursive
557-
// reference and we'll want to skip ahead so as to avoid having its type
558-
// attempt to desugar itself.
559-
if (decl->isRecursiveValidation())
560-
continue;
561-
auto ifaceType = decl->getInterfaceType();
562-
563-
// FIXME: the canonical type makes a poor signature, because we don't
564-
// canonicalize away default arguments.
565-
signature = ifaceType->getCanonicalType();
566-
567-
// FIXME: The type of a variable or subscript doesn't include
568-
// enough context to distinguish entities from different
569-
// constrained extensions, so use the overload signature's
570-
// type. This is layering a partial fix upon a total hack.
571-
if (auto asd = dyn_cast<AbstractStorageDecl>(decl))
572-
signature = asd->getOverloadSignatureType();
573-
}
611+
CanGenericSignature signature;
612+
613+
auto *dc = decl->getInnermostDeclContext();
614+
if (auto genericSig = dc->getGenericSignatureOfContext())
615+
signature = genericSig->getCanonicalSignature();
574616

575617
// Record this declaration based on its signature.
576-
auto &known = collisions[signature];
618+
auto &known = collisions[signature.getPointer()];
577619
if (known.size() == 1) {
578-
collisionTypes.push_back(signature);
620+
collisionSignatures.push_back(signature.getPointer());
579621
}
622+
580623
known.push_back(decl);
581624
}
582625

626+
// Check whether we have shadowing for type declarations.
627+
if (typeDecls.size() > 1) {
628+
ArrayRef<ValueDecl *> collidingDecls = typeDecls;
629+
recordShadowedDeclsAfterTypeMatch(collidingDecls, dc, shadowed);
630+
}
631+
583632
// Check whether we have shadowing for signature collisions.
584-
for (auto signature : collisionTypes) {
633+
for (auto signature : collisionSignatures) {
585634
ArrayRef<ValueDecl *> collidingDecls = collisions[signature];
586635
recordShadowedDeclsAfterSignatureMatch(collidingDecls, dc, shadowed);
587636
}
588637

589638
// Check whether we have shadowing for imported initializer collisions.
590-
for (auto nominal : importedInitializerCollectionTypes) {
639+
for (auto nominal : importedInitializerCollisionTypes) {
591640
recordShadowedDeclsForImportedInits(importedInitializerCollisions[nominal],
592641
shadowed);
593642
}
@@ -597,15 +646,15 @@ static void
597646
recordShadowedDecls(ArrayRef<OperatorDecl *> decls, const DeclContext *dc,
598647
llvm::SmallPtrSetImpl<OperatorDecl *> &shadowed) {
599648
// Always considered to have the same signature.
600-
recordShadowedDeclsAfterSignatureMatch(decls, dc, shadowed);
649+
recordShadowedDeclsAfterTypeMatch(decls, dc, shadowed);
601650
}
602651

603652
static void
604653
recordShadowedDecls(ArrayRef<PrecedenceGroupDecl *> decls,
605654
const DeclContext *dc,
606655
llvm::SmallPtrSetImpl<PrecedenceGroupDecl *> &shadowed) {
607-
// Always considered to have the same signature.
608-
recordShadowedDeclsAfterSignatureMatch(decls, dc, shadowed);
656+
// Always considered to have the same type.
657+
recordShadowedDeclsAfterTypeMatch(decls, dc, shadowed);
609658
}
610659

611660
template <typename T, typename Container>

0 commit comments

Comments
 (0)