Skip to content

Use a special DeclBaseName for init #15201

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Mar 16, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions include/swift/AST/Identifier.h
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,7 @@ class DeclBaseName {
enum class Kind: uint8_t {
Normal,
Subscript,
Constructor,
Destructor
};

Expand All @@ -224,6 +225,8 @@ class DeclBaseName {
/// This is an implementation detail that should never leak outside of
/// DeclName.
static void *SubscriptIdentifierData;
/// As above, for special constructor DeclNames.
static void *ConstructorIdentifierData;
/// As above, for special destructor DeclNames.
static void *DestructorIdentifierData;

Expand All @@ -238,13 +241,19 @@ class DeclBaseName {
return DeclBaseName(Identifier((const char *)SubscriptIdentifierData));
}

static DeclBaseName createConstructor() {
return DeclBaseName(Identifier((const char *)ConstructorIdentifierData));
}

static DeclBaseName createDestructor() {
return DeclBaseName(Identifier((const char *)DestructorIdentifierData));
}

Kind getKind() const {
if (Ident.get() == SubscriptIdentifierData) {
return Kind::Subscript;
} else if (Ident.get() == ConstructorIdentifierData) {
return Kind::Constructor;
} else if (Ident.get() == DestructorIdentifierData) {
return Kind::Destructor;
} else {
Expand Down Expand Up @@ -282,6 +291,8 @@ class DeclBaseName {
return getIdentifier().str();
case Kind::Subscript:
return "subscript";
case Kind::Constructor:
return "init";
case Kind::Destructor:
return "deinit";
}
Expand Down
1 change: 0 additions & 1 deletion include/swift/AST/KnownIdentifiers.def
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,6 @@ IDENTIFIER(forKey)
IDENTIFIER(from)
IDENTIFIER(fromRaw)
IDENTIFIER(hashValue)
IDENTIFIER(init)
IDENTIFIER(initialize)
IDENTIFIER(initStorage)
IDENTIFIER(initialValue)
Expand Down
3 changes: 2 additions & 1 deletion include/swift/Parse/Parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -1427,7 +1427,8 @@ ParsedDeclName parseDeclName(StringRef name) LLVM_READONLY;
DeclName formDeclName(ASTContext &ctx,
StringRef baseName,
ArrayRef<StringRef> argumentLabels,
bool isFunctionName);
bool isFunctionName,
bool isInitializer);

/// Parse a stringified Swift declaration name, e.g. "init(frame:)".
DeclName parseDeclName(ASTContext &ctx, StringRef name);
Expand Down
5 changes: 4 additions & 1 deletion include/swift/Serialization/ModuleFormat.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ const uint16_t VERSION_MAJOR = 0;
/// describe what change you made. The content of this comment isn't important;
/// it just ensures a conflict if two people change the module format.
/// Don't worry about adhering to the 80-column limit for this line.
const uint16_t VERSION_MINOR = 402; // Last change: effects(releasenone)
const uint16_t VERSION_MINOR = 403; // Last change: `init` special name

using DeclIDField = BCFixed<31>;

Expand Down Expand Up @@ -380,6 +380,7 @@ using OptionalTypeKindField = BCFixed<2>;
enum class DeclNameKind: uint8_t {
Normal,
Subscript,
Constructor,
Destructor
};

Expand All @@ -394,6 +395,8 @@ enum SpecialIdentifierID : uint8_t {
OBJC_HEADER_MODULE_ID,
/// Special value for the special subscript name
SUBSCRIPT_ID,
/// Special value for the special constructor name
CONSTRUCTOR_ID,
/// Special value for the special destructor name
DESTRUCTOR_ID,

Expand Down
11 changes: 6 additions & 5 deletions lib/AST/Decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2773,7 +2773,7 @@ void ClassDecl::addImplicitDestructor() {

bool ClassDecl::hasMissingDesignatedInitializers() const {
auto *mutableThis = const_cast<ClassDecl *>(this);
(void)mutableThis->lookupDirect(getASTContext().Id_init,
(void)mutableThis->lookupDirect(DeclBaseName::createConstructor(),
/*ignoreNewExtensions*/true);
return Bits.ClassDecl.HasMissingDesignatedInitializers;
}
Expand Down Expand Up @@ -2821,11 +2821,10 @@ bool ClassDecl::inheritsSuperclassInitializers(LazyResolver *resolver) {

// Look at all of the initializers of the subclass to gather the initializers
// they override from the superclass.
auto &ctx = getASTContext();
llvm::SmallPtrSet<ConstructorDecl *, 4> overriddenInits;
if (resolver)
resolver->resolveImplicitConstructors(this);
for (auto member : lookupDirect(ctx.Id_init)) {
for (auto member : lookupDirect(DeclBaseName::createConstructor())) {
auto ctor = dyn_cast<ConstructorDecl>(member);
if (!ctor)
continue;
Expand Down Expand Up @@ -2855,7 +2854,7 @@ bool ClassDecl::inheritsSuperclassInitializers(LazyResolver *resolver) {
// Note: This should be treated as a lookup for intra-module dependency
// purposes, but a subclass already depends on its superclasses and any
// extensions for many other reasons.
for (auto member : superclassDecl->lookupDirect(ctx.Id_init)) {
for (auto member : superclassDecl->lookupDirect(DeclBaseName::createConstructor())) {
if (AvailableAttr::isUnavailable(member))
continue;

Expand Down Expand Up @@ -5195,6 +5194,8 @@ ConstructorDecl::ConstructorDecl(DeclName Name, SourceLoc ConstructorLoc,
Bits.ConstructorDecl.HasStubImplementation = 0;
Bits.ConstructorDecl.InitKind = static_cast<unsigned>(CtorInitializerKind::Designated);
Bits.ConstructorDecl.Failability = static_cast<unsigned>(Failability);

assert(Name.getBaseName() == DeclBaseName::createConstructor());
}

void ConstructorDecl::setParameterLists(ParamDecl *selfDecl,
Expand Down Expand Up @@ -5441,7 +5442,7 @@ ConstructorDecl::getDelegatingOrChainedInitKind(DiagnosticEngine *diags,
} else if (auto *CRE = dyn_cast<ConstructorRefCallExpr>(Callee)) {
arg = CRE->getArg();
} else if (auto *dotExpr = dyn_cast<UnresolvedDotExpr>(Callee)) {
if (dotExpr->getName().getBaseName() != "init")
if (dotExpr->getName().getBaseName() != DeclBaseName::createConstructor())
return { true, E };

arg = dotExpr->getBase();
Expand Down
2 changes: 2 additions & 0 deletions lib/AST/Identifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ using namespace swift;

void *DeclBaseName::SubscriptIdentifierData =
&DeclBaseName::SubscriptIdentifierData;
void *DeclBaseName::ConstructorIdentifierData =
&DeclBaseName::ConstructorIdentifierData;
void *DeclBaseName::DestructorIdentifierData =
&DeclBaseName::DestructorIdentifierData;

Expand Down
9 changes: 4 additions & 5 deletions lib/AST/NameLookup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,6 @@ bool swift::removeOverriddenDecls(SmallVectorImpl<ValueDecl*> &decls) {
if (decls.empty())
return false;

ASTContext &ctx = decls.front()->getASTContext();
llvm::SmallPtrSet<ValueDecl*, 8> overridden;
for (auto decl : decls) {
while (auto overrides = decl->getOverriddenDecl()) {
Expand All @@ -95,7 +94,7 @@ bool swift::removeOverriddenDecls(SmallVectorImpl<ValueDecl*> &decls) {
// C.init overrides B.init overrides A.init, but only C.init and
// A.init are in the chain. Make sure we still remove A.init from the
// set in this case.
if (decl->getFullName().getBaseName() == ctx.Id_init) {
if (decl->getFullName().getBaseName() == DeclBaseName::createConstructor()) {
/// FIXME: Avoid the possibility of an infinite loop by fixing the root
/// cause instead (incomplete circularity detection).
assert(decl != overrides && "Circular class inheritance?");
Expand Down Expand Up @@ -1367,7 +1366,7 @@ TinyPtrVector<ValueDecl *> NominalTypeDecl::lookupDirect(
// that appears to special-case initializers (clang-imported initializer
// sorting, implicit initializer synthesis), so for the time being we have to
// turn it off for them entirely.
if (name.getBaseName() == ctx.Id_init)
if (name.getBaseName() == DeclBaseName::createConstructor())
useNamedLazyMemberLoading = false;

DEBUG(llvm::dbgs() << getNameStr() << ".lookupDirect(" << name << ")"
Expand Down Expand Up @@ -1753,7 +1752,7 @@ bool DeclContext::lookupQualified(Type type,

// Make sure we've resolved implicit members, if we need them.
if (typeResolver) {
if (member.getBaseName() == ctx.Id_init)
if (member.getBaseName() == DeclBaseName::createConstructor())
typeResolver->resolveImplicitConstructors(current);

typeResolver->resolveImplicitMember(current, member);
Expand Down Expand Up @@ -1782,7 +1781,7 @@ bool DeclContext::lookupQualified(Type type,
// current class permits inheritance. Even then, only find complete
// object initializers.
bool visitSuperclass = true;
if (member.getBaseName() == ctx.Id_init) {
if (member.getBaseName() == DeclBaseName::createConstructor()) {
if (classDecl->inheritsSuperclassInitializers(typeResolver))
onlyCompleteObjectInits = true;
else
Expand Down
43 changes: 27 additions & 16 deletions lib/ClangImporter/IAMInference.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,8 @@ class IAMInference {
IAMResult importAsTypeID(const clang::QualType typeIDTy,
EffectiveClangContext effectiveDC) {
++SuccessImportAsTypeID;
return {formDeclName("typeID"), IAMAccessorKind::Getter, effectiveDC};
return {formDeclName("typeID", /*isInitializer=*/false),
IAMAccessorKind::Getter, effectiveDC};
}

// Init
Expand Down Expand Up @@ -245,7 +246,7 @@ class IAMInference {

assert(didDrop != 0 && "specifier not present?");
}
return {formDeclName("init", params, prefix), effectiveDC};
return {formDeclName("init", true, params, prefix), effectiveDC};
}

// Instance computed property
Expand All @@ -259,7 +260,8 @@ class IAMInference {
propSpec == "Get" ? IAMAccessorKind::Getter : IAMAccessorKind::Setter;
assert(kind == IAMAccessorKind::Getter || pairedAccessor && "no set-only");

return {formDeclName(name), kind, selfIdx, effectiveDC};
return {formDeclName(name, /*isInitializer=*/false),
kind, selfIdx, effectiveDC};
}

// Instance method
Expand All @@ -268,14 +270,15 @@ class IAMInference {
ArrayRef<const clang::ParmVarDecl *> nonSelfParams,
EffectiveClangContext effectiveDC) {
++SuccessImportAsInstanceMethod;
return {formDeclName(name, nonSelfParams), selfIdx, effectiveDC};
return {formDeclName(name, /*isInitializer=*/false, nonSelfParams),
selfIdx, effectiveDC};
}

// Static stored property
IAMResult importAsStaticProperty(StringRef name,
EffectiveClangContext effectiveDC) {
++SuccessImportAsStaticProperty;
return {formDeclName(name), effectiveDC};
return {formDeclName(name, /*isInitializer=*/false), effectiveDC};
}

// Static computed property
Expand All @@ -289,7 +292,8 @@ class IAMInference {
propSpec == "Get" ? IAMAccessorKind::Getter : IAMAccessorKind::Setter;
assert(kind == IAMAccessorKind::Getter || pairedAccessor && "no set-only");

return {formDeclName(name), kind, effectiveDC};
return {formDeclName(name, /*isInitializer=*/false),
kind, effectiveDC};
}

// Static method
Expand All @@ -298,7 +302,8 @@ class IAMInference {
ArrayRef<const clang::ParmVarDecl *> nonSelfParams,
EffectiveClangContext effectiveDC) {
++SuccessImportAsStaticMethod;
return {formDeclName(name, nonSelfParams), effectiveDC};
return {formDeclName(name, /*isInitializer=*/false, nonSelfParams),
effectiveDC};
}

Identifier getIdentifier(StringRef str) {
Expand Down Expand Up @@ -379,18 +384,20 @@ class IAMInference {
return clangLookupFunction(pairName);
}

Identifier getHumbleIdentifier(StringRef name) {
DeclBaseName getHumbleBaseName(StringRef name, bool isInitializer) {
// Lower-camel-case the incoming name
NameBuffer buf;
formHumbleCamelName(name, buf);
if (isInitializer && buf == "init")
return DeclBaseName::createConstructor();
return getIdentifier(buf);
}

DeclName formDeclName(StringRef baseName) {
return {getHumbleIdentifier(baseName)};
DeclName formDeclName(StringRef baseName, bool isInitializer) {
return {getHumbleBaseName(baseName, isInitializer)};
}

DeclName formDeclName(StringRef baseName,
DeclName formDeclName(StringRef baseName, bool isInitializer,
ArrayRef<const clang::ParmVarDecl *> params,
StringRef firstPrefix = "") {

Expand All @@ -402,7 +409,7 @@ class IAMInference {
// We need to form an argument label, despite there being no argument
NameBuffer paramName;
formHumbleCamelName(firstPrefix, paramName);
return {context, getHumbleIdentifier(baseName),
return {context, getHumbleBaseName(baseName, isInitializer),
getIdentifier(paramName)};
}

Expand All @@ -426,7 +433,9 @@ class IAMInference {
SmallVector<Identifier, 8> argLabels;
for (auto str : argStrs)
argLabels.push_back(getIdentifier(str));
DEBUG((beforeOmit = {context, getHumbleIdentifier(baseName), argLabels}));
DEBUG((beforeOmit = {context,
getHumbleBaseName(baseName, isInitializer),
argLabels}));
}

SmallVector<OmissionTypeName, 8> paramTypeNames;
Expand All @@ -435,16 +444,18 @@ class IAMInference {
clangSema.getASTContext(), param->getType()));
}

auto humbleBaseName = getHumbleIdentifier(baseName);
baseName = humbleBaseName.str();
auto humbleBaseName = getHumbleBaseName(baseName, isInitializer);
baseName = humbleBaseName.userFacingName();
bool didOmit =
omitNeedlessWords(baseName, argStrs, "", "", "", paramTypeNames, false,
false, nullptr, scratch);
SmallVector<Identifier, 8> argLabels;
for (auto str : argStrs)
argLabels.push_back(getIdentifier(str));

DeclName ret = {context, getHumbleIdentifier(baseName), argLabels};
DeclName ret(context,
getHumbleBaseName(baseName, isInitializer),
argLabels);

if (didOmit) {
++OmitNumTimes;
Expand Down
12 changes: 6 additions & 6 deletions lib/ClangImporter/ImportDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -444,7 +444,7 @@ makeEnumRawValueConstructor(ClangImporter::Implementation &Impl,

auto paramPL = ParameterList::createWithoutLoc(param);

DeclName name(C, C.Id_init, paramPL);
DeclName name(C, DeclBaseName::createConstructor(), paramPL);
auto *ctorDecl =
new (C) ConstructorDecl(name, enumDecl->getLoc(),
OTK_Optional, /*FailabilityLoc=*/SourceLoc(),
Expand Down Expand Up @@ -1167,7 +1167,7 @@ createDefaultConstructor(ClangImporter::Implementation &Impl,
auto emptyPL = ParameterList::createEmpty(context);

// Create the constructor.
DeclName name(context, context.Id_init, emptyPL);
DeclName name(context, DeclBaseName::createConstructor(), emptyPL);
auto constructor = new (context) ConstructorDecl(
name, structDecl->getLoc(), OTK_None, /*FailabilityLoc=*/SourceLoc(),
/*Throws=*/false, /*ThrowsLoc=*/SourceLoc(), selfDecl, emptyPL,
Expand Down Expand Up @@ -1282,7 +1282,7 @@ createValueConstructor(ClangImporter::Implementation &Impl,
ParameterList::create(context, valueParameters)};

// Create the constructor
DeclName name(context, context.Id_init, paramLists[1]);
DeclName name(context, DeclBaseName::createConstructor(), paramLists[1]);
auto constructor = new (context) ConstructorDecl(
name, structDecl->getLoc(), OTK_None, /*FailabilityLoc=*/SourceLoc(),
/*Throws=*/false, /*ThrowsLoc=*/SourceLoc(), selfDecl, paramLists[1],
Expand Down Expand Up @@ -2264,7 +2264,7 @@ namespace {

bool isFactoryInit(ImportedName &name) {
return name &&
name.getDeclName().getBaseName() == Impl.SwiftContext.Id_init &&
name.getDeclName().getBaseName() == DeclBaseName::createConstructor() &&
(name.getInitKind() == CtorInitializerKind::Factory ||
name.getInitKind() == CtorInitializerKind::ConvenienceFactory);
}
Expand Down Expand Up @@ -3521,7 +3521,7 @@ namespace {
DeclName name = accessorInfo ? DeclName() : importedName.getDeclName();
if (importedName.importAsMember()) {
// Handle initializers.
if (name.getBaseName() == Impl.SwiftContext.Id_init) {
if (name.getBaseName() == DeclBaseName::createConstructor()) {
assert(!accessorInfo);
return importGlobalAsInitializer(decl, name, dc,
importedName.getInitKind(),
Expand Down Expand Up @@ -7234,7 +7234,7 @@ void SwiftDeclConverter::importInheritedConstructors(
// If we have a superclass, import from it.
if (auto superclassClangDecl = superclass->getClangDecl()) {
if (isa<clang::ObjCInterfaceDecl>(superclassClangDecl)) {
inheritConstructors(superclass->lookupDirect(Impl.SwiftContext.Id_init),
inheritConstructors(superclass->lookupDirect(DeclBaseName::createConstructor()),
kind);
}
}
Expand Down
3 changes: 2 additions & 1 deletion lib/ClangImporter/ImportName.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1712,7 +1712,8 @@ ImportedName NameImporter::importNameImpl(const clang::NamedDecl *D,
}
}

result.declName = formDeclName(swiftCtx, baseName, argumentNames, isFunction);
result.declName = formDeclName(swiftCtx, baseName, argumentNames, isFunction,
isInitializer);
return result;
}

Expand Down
Loading