Skip to content

Introduce special DeclNames for subscripts #6848

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

Closed

Conversation

ahoppen
Copy link
Member

@ahoppen ahoppen commented Jan 16, 2017

This is a preparation to use special DeclNames that don't carry identifiers e.g. for subscripts, initializers, and destructors which shall at some point fix SR-2575 as outlined in #5537 and #6305.

@ahoppen ahoppen requested a review from jrose-apple January 16, 2017 19:43
@ahoppen ahoppen changed the title Sr 2575 3 identifier to decl name WIP: Use DeclName instead of Identifier in various locations again Jan 16, 2017
@ahoppen
Copy link
Member Author

ahoppen commented Jan 16, 2017

@jrose-apple: I've taken a more conservative approach now. Could you maybe have a quick look if this is going in the right direction? It's still kind of WIP and I haven't created the matching PR to the LLDB repo yet, so no need for running the test or doing an in-depth review. Thanks!

@ahoppen
Copy link
Member Author

ahoppen commented Jan 23, 2017

I'm making fairly good progress on this PR now and just have a few issues to fix. For that, I've got a quick question:

Subscripts are currently represented in SIL as <Type>.subscript!(getter|setter) which is the same spelling as for an instance variable named subscript. I.e. the accessor path for the following two is the same:

class Foo {
  subscript() -> String {
    return ""
  }
  
  var `subscript`: String
}

namely #Foo.subscript!getter.1

Until now this wasn't an issue since both of them were represented by the identifier Id_subscript so name lookup found either. Furthermore, the above code doesn't compile right now and complains about a redeclaration of subscript. However, with the introduction of special DeclNames, the above code is actually valid. So we would need a way to disambiguate the two in SIL to get the same expressive power there. My proposal is to rename the actual subscript reference in SIL to something like <Type>.[]!getter, [] being a constant string (nothing is meant to go in between the brackets), but I'm open to other solutions as well. The only requirement for the representation is that it isn't a valid identifier on the surface language.

Do you think this syntax would fit in the current spirit of SIL (which I really don't know a lot about) or is there another syntax coming to your mind that would be better? Thanks!

@ahoppen ahoppen force-pushed the SR-2575-3-Identifier-toDeclName branch 2 times, most recently from 34ed74c to 4229f92 Compare January 24, 2017 11:15
@jrose-apple
Copy link
Contributor

Sorry for continuing to ignore this series, even after Branch Day—lots of 3.1 bugs to keep our hands full!

I'm no SIL expert, but I think expanding the set of allowed characters seems a bit iffy. Don't we have the same problem with init and deinit stepping on regular declarations? Maybe we should just add a leading '!' or something, i.e. !init and !subscript!getter. @jckarter, @swiftix, any thoughts on this particular issue?

@jckarter
Copy link
Contributor

Or `subscript`!1 ?

@ahoppen
Copy link
Member Author

ahoppen commented Jan 28, 2017

Subscript in backticks sounds good. While implementing it, I found two issues that prevents generated SIL files from being parsed again. I just wanted to point to them (workarounds would be fine for me right now) since they make further development nearly impossible: SR-3773, SR-3774

@ahoppen ahoppen force-pushed the SR-2575-3-Identifier-toDeclName branch 3 times, most recently from 8049fbc to 4f6855b Compare February 4, 2017 19:12
@ahoppen
Copy link
Member Author

ahoppen commented Feb 4, 2017

Please test with following pull request:
apple/swift-lldb#106

@swift-ci Please test

@swift-ci
Copy link
Contributor

swift-ci commented Feb 4, 2017

Build failed
Jenkins build - Swift Test OS X Platform
Git Commit - 12ce139b4fc5facf2d5b513368beea677db751e1
Test requested by - @ahoppen

@swift-ci
Copy link
Contributor

swift-ci commented Feb 4, 2017

Build failed
Jenkins build - Swift Test Linux Platform
Git Commit - 12ce139b4fc5facf2d5b513368beea677db751e1
Test requested by - @ahoppen

@ahoppen ahoppen force-pushed the SR-2575-3-Identifier-toDeclName branch from 4f6855b to 87bfcd8 Compare February 5, 2017 10:48
@ahoppen
Copy link
Member Author

ahoppen commented Feb 5, 2017

Please test with following pull request:
apple/swift-lldb#106

@swift-ci Please test

@swift-ci
Copy link
Contributor

swift-ci commented Feb 5, 2017

Build failed
Jenkins build - Swift Test OS X Platform
Git Commit - 4f6855bd02d54c9c39c4e4f1a450ed604ea5e6ad
Test requested by - @ahoppen

@swift-ci
Copy link
Contributor

swift-ci commented Feb 5, 2017

Build failed
Jenkins build - Swift Test Linux Platform
Git Commit - 4f6855bd02d54c9c39c4e4f1a450ed604ea5e6ad
Test requested by - @ahoppen

@ahoppen
Copy link
Member Author

ahoppen commented Feb 5, 2017

Hitting this failure: https://lists.swift.org/pipermail/swift-dev/Week-of-Mon-20170130/003954.html
Hoping a rerun solves the issue.

Please test with following pull request:
apple/swift-lldb#106

@swift-ci Please test

@ahoppen ahoppen changed the title WIP: Use DeclName instead of Identifier in various locations again Introduce special DeclNames for subscripts Feb 5, 2017
@ahoppen
Copy link
Member Author

ahoppen commented Feb 5, 2017

@jrose-apple: The PR is done so far from my side, could you (or someone else) review the changes?

Copy link
Contributor

@jrose-apple jrose-apple left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for continuing to push this forward, Alex. I find I'm still really uncomfortable with this change because it erases the distinction between operations that take compound names and those that only take base names (whether normal or special). I'm going to go back to saying that we need to change Identifier, not DeclName. @DougGregor?

@@ -4698,6 +4700,8 @@ class AbstractFunctionDecl : public ValueDecl, public DeclContext {
GenericEnvironment *getLazyGenericEnvironmentSlow() const;

public:
Identifier getName() const { return getFullName().getBaseName(); }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This one I'd be happy to drop in favor of getBaseName(), but that can be a follow-up patch.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, I wanted to keep the code change as small as possible and not litter the PR with renames from getName to getBaseName.

StringRef str() const {
switch (getKind()) {
case DeclNameKind::Normal:
return getBaseName().str();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think it's okay to drop the argument labels here. Either this should be called getBaseNameStr() (or something), or it should assert that this is not a compound name (and probably still have a less simple name than str()).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Renaming sounds like the way to go since IIRC this behaviour is needed in quite a few places.

@@ -1733,7 +1734,7 @@ void ASTMangler::appendProtocolConformance(const ProtocolConformance *conformanc
appendIdentifier(
fileUnit->getDiscriminatorForPrivateValue(behaviorStorage).str());
appendProtocolName(conformance->getProtocol());
appendIdentifier(behaviorStorage->getName().str());
appendIdentifier(behaviorStorage->getBaseName().getBaseName().str());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Extra getBaseName here?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This basically asserts that the base name is not special because then the second getBaseName() will crash. Maybe an assert would indeed be cleaner.

lib/AST/Decl.cpp Outdated
@@ -190,7 +190,7 @@ DescriptiveDeclKind Decl::getDescriptiveKind() const {
return DescriptiveDeclKind::MaterializeForSet;
}

if (!func->getName().empty() && func->getName().isOperator())
if (!func->getName().empty() && func->isOperator())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does func->isOperator() already check for an empty name? In that case you could just use that.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't right now but it seems like a reasonable thing to add there.

lib/AST/Decl.cpp Outdated
ArrayRef<Identifier>());

if (afd->getFullName().getKind() == DeclNameKind::Subscript) {
return DeclName::createSubscript(ctx, ArrayRef<Identifier>());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't correct; you need the index labels too. Isn't it okay to just continue returning afd->getFullName() though?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know why I changed this in the first place. I'll change it back to how it was

@@ -1168,7 +1166,7 @@ namespace {
CS.addBindOverloadConstraint(fnTy, choice, subscriptMemberLocator,
CurDC);
} else {
CS.addValueMemberConstraint(baseTy, Context.Id_subscript,
CS.addValueMemberConstraint(baseTy, DeclName::createSubscript(),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this correctly distinguish between subscript and subscript()?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think so. I don't understand your specific concern though…

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's the difference between a reference to "any subscript" and "a subscript with zero arguments", or between a base DeclName and a compound DeclName. Just wanted to make sure this was producing a base DeclName and not a compound one.

@@ -2795,8 +2795,16 @@ performMemberLookup(ConstraintKind constraintKind, DeclName memberName,
// anything else, because the cost of the general search is so
// high.
if (baseObjTy->isAnyObject() && argumentLabels) {
memberName = DeclName(TC.Context, memberName.getBaseName(),
argumentLabels->Labels);
switch (memberName.getKind()) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe there should be a general withArgumentLabels operation on DeclName?

}
} else {
if (lhs.getKind() == rhs.getKind()) {
score = 0;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about argument labels?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aren't they handled further down (line 5205 - 5210)?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, whoops. I thought this was an early return for some reason.

@@ -297,22 +298,36 @@ namespace {
/// Used to deserialize entries in the on-disk decl hash table.
class ModuleFile::DeclTableInfo {
public:
using internal_key_type = StringRef;
using external_key_type = Identifier;
using internal_key_type = std::pair<DeclNameKind, StringRef>;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is good, use something like this for the ClangImporter lookup tables, please.

// Subscript
return DeclName::createSubscript();
} else {
// Serialized prior to special DeclNames. Just read the normal identifier
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At this point the module format isn't stable, so we can just make a breaking change here. It seems more important to look forward than backward; in a forward world, we've introduced a new special kind that this compiler treats as a normal name. We could either import it as a normal name or fail.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, I didn't want to be the first one to increase the major version though ;-) But with your OK, I'll go ahead ;-)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We're treating the minor version as a breaking version for now, please continue doing that.

@ahoppen
Copy link
Member Author

ahoppen commented Feb 9, 2017

Thanks for the review. It explained a few things I didn't quite understand before. 😄
I'll wait with any further changes until we've reached a decision whether this is the way forward or not. If we decide to go a more Identifier centric approach, there is still my initial idea of using $subscript similar to $match in switch statements, which we could revive again.

@ahoppen
Copy link
Member Author

ahoppen commented Mar 2, 2017

Just a friendly ping that it would be great if you could discuss internally if we want to continue with the DeclName based approach or try to model the special names using Identifier. I really don't feel like I'm able to judge what's best in the overall picture.

@rjmccall
Copy link
Contributor

rjmccall commented Mar 2, 2017

It sounds to me like the base name of a DeclName should use a new DeclBaseName type that's either an identifier or one of these special names. We shouldn't contaminate the entire Identifier type with the possibility of special names, but we also shouldn't pretend that special names only make sense at the DeclName level.

@ahoppen
Copy link
Member Author

ahoppen commented Mar 2, 2017

Sounds very reasonable to me.
And I guess then change some of the places where we currently (prior to this PR) use Identifiers to use the new DeclBaseName if it could be a special name.

@rjmccall
Copy link
Contributor

rjmccall commented Mar 2, 2017

Yeah. That might not be a very fun project, but it's probably the right thing to do. I'd wait for @jrose-apple's blessing before getting started, though.

@jrose-apple
Copy link
Contributor

I'm sad to have three types, because I'm not sure Identifier will be pulling its weight after this, but it's always easier to collapse back down to two if we change our minds later, and right now we really have identified three different kinds of entities.

@jrose-apple
Copy link
Contributor

Thanks for weighing in, @rjmccall.

@ahoppen
Copy link
Member Author

ahoppen commented Mar 3, 2017

Cool, I'll try and tackle this one more time then ;-)

@ahoppen ahoppen force-pushed the SR-2575-3-Identifier-toDeclName branch 2 times, most recently from 8a08dab to 2a3e8ad Compare March 5, 2017 19:43
ahoppen added 5 commits March 5, 2017 19:51
The new DeclBaseName type will later abstract over normal Identifiers as
they exist now and special names that don't have an identifier in the
surface language like subscripts
Special names will in the future represent names that don't have a
surface language identifier like subscript.

For this, change the backing type of DeclName to a new type DeclBaseName
that will later be able to represent special names.

ValueDecls may therefore no longer have an identifier name. Thus we move
the getName method from ValueDecl to the subtypes that are guaranteed
to have identifier names
Special DeclNames represent names that do not have an identifier in the
surface language. This implies serializing the information about whether
a name is special together with its identifier (if it is not special)
in both the module file and the swift lookup table.

ValueDecls are not guaranteed to have a name anymore and thus getNameStr
is moved from ValueDecl to subclasses that guarantee to be backed by
identifiers. Other calls need to handle special names if the context
doesn't guarantee that the declaration's name is non-special.
@ahoppen
Copy link
Member Author

ahoppen commented Mar 5, 2017

Please test with following pull request:
apple/swift-lldb#165

@swift-ci Please test

@swift-ci
Copy link
Contributor

swift-ci commented Mar 5, 2017

Build failed
Jenkins build - Swift Test OS X Platform
Git Commit - 87bfcd8cf560b45c61888a529417c08b8615bfc6
Test requested by - @ahoppen

@swift-ci
Copy link
Contributor

swift-ci commented Mar 5, 2017

Build failed
Jenkins build - Swift Test Linux Platform
Git Commit - 87bfcd8cf560b45c61888a529417c08b8615bfc6
Test requested by - @ahoppen

@ahoppen
Copy link
Member Author

ahoppen commented Mar 6, 2017

OK, so I've implemented the changes with a new type DeclBaseName now. I personally feel like this could be a good solution, the impact of the changes seems to be far lower than with the other approaches. So, a review would be very welcome.

I've got one more open point which is that subscripts are currently mangled as something like _TFC4main3Foog9subscriptFT_Si. I feel like we shouldn't include the string 'subscript' in the mangled name anymore, but that's something to be tackled in a subsequent PR, I'd say.

Copy link
Contributor

@jrose-apple jrose-apple left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This does look a lot better. It seems obvious now that we really do have three different kinds of things. Thanks, Alex!

The patch is still pretty big; it would be nice to factor out some of the changes that don't depend on DeclBaseName already existing, so we can review those separately and/or get those in first. I scanned through the entire thing today but that doesn't mean I didn't miss something.

return userFacingStr().compare(other.userFacingStr());
}

bool operator==(StringRef Str) const {
Copy link
Contributor

@jrose-apple jrose-apple Mar 8, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These seem too easy to misuse. Maybe we should go the Clang route: bool isStr(StringRef str).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What kind of misuse do you have in mind? I quite liked the brevity of == in ifs. But I can, of course, change it

Copy link
Contributor

@jrose-apple jrose-apple Mar 9, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess I was worried about == "subscript" (and whatever else we add), and maybe that's being too cautious.


raw_ostream &operator<<(raw_ostream &OS, swift::DeclBaseName D);

// Identifiers hash just like pointers.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick: comment.

// Identifiers hash just like pointers.
template<> struct DenseMapInfo<swift::DeclBaseName> {
static swift::DeclBaseName getEmptyKey() {
return swift::DeclBaseName::getEmptyKey();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick: Why the extra level of indirection? It's not like getEmptyKey is going to be used anywhere else.

(I see that Identifier did this too, but it's weird there too.)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was just copying what Identifier did ;-). I'll change it.

@@ -154,6 +154,8 @@ class Mangler {
void mangleProtocolList(ArrayRef<Type> protocols);
void mangleIdentifier(Identifier ident,
OperatorFixity fixity = OperatorFixity::NotOperator);
void mangleIdentifier(DeclBaseName ident,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do we want to do about things like this? Is continuing to say mangleIdentifier the right way forward? I think it's fine for this patch (minimizes an already large changeset), but what do you think for follow-up?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would imagine that we will at some point change the mangling name of subscripts to something that doesn't contain the string "subscript" (I'd use a new special character in the mangling scheme). Then the special names would be handled on the call side of this function and we could remove it again.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, right, we could do it based on the DeclKind. Okay, that seems reasonable.

// have an identifier. As above, these IDs must \em not be renumbered or
// reordered without incrementing VERSION_MAJOR.
enum SpecialNameID : uint8_t {
SUBSCRIPT_ID = NUM_SPECIAL_MODULES,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems dangerous. How do people know whether to check NUM_SPECIAL_MODULES or NUM_SPECIAL_IDS? I think we should either fold the two lists together or allow the same value to represent multiple things (builtin module OR subscript, current module OR init, etc).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I think folding the two enums together would be the right way to go. Didn't really feel too comfortable with it but wanted an opinion on whether using the same enum for both special module names and other special names would be alright.

@@ -0,0 +1,16 @@
// RUN: %target-run-simple-swift | %FileCheck %s
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick: execution tests don't belong in test/Sema/. Can you move this to test/Interpreter/ instead?

}
}

SR2575().subscript() // expected-error{{type 'SR2575' has no member 'subscript'}}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should probably make a note / bug to come back and improve this specific case later.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you wan to change here? Offer a fixit to change the call to subscript to a proper subscript?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Something like that. Maybe something that makes it clear it's looking for functions named subscript rather than actual subscripts.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, I'll open a follow-up JIRA once the PR has been landed.

@@ -116,7 +116,7 @@ func testParseErrors3(_ c1: C1) {

func testParseErrors4() {
// Subscripts
_ = #selector(C1.subscript) // expected-error{{type 'C1.Type' has no subscript members}}
_ = #selector(C1.subscript) // expected-error{{type 'C1' has no member 'subscript'}}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we are going to want to support syntax like this for getting the selector of a subscript getter or setter some day: #selector(getter:C1.subscript). It doesn't currently work but that doesn't mean it shouldn't work.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd say that C1.subscript will always be invalid unless you declare a func `subscript`() {}. Otherwise we would get into ambiguity issues if you declare both a subscript and a function named subscript.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's what the getter: is for. Or whatever the no-argument function disambiguation syntax turns out to be.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, but then I don't get why we want to support syntax like this. #selector(getter:…) would then need to implement some special lookup logic to handle the subscript case, I'd say.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

…and I don't quite understand your objection. How do you want to spell "the selector of the getter for this subscript"?

I suppose we haven't had a huge need for it yet, but it's not an unreasonable thing to ask for.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think my point is that, from my point of view, whether or not we want to support selectors for subscripts is nothing to worry about for now and that we will only need to worry about how to implement it when the time comes.
Or maybe let's ask the other way round: What would you want to be changed here?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm concerned about the diagnostic. It implies that the compiler is interpreting this syntax as a reference to a member named 'subscript', which would lead to a user thinking they've done something wrong, rather than this simply being a feature that's not implemented yet.

It's not a deal-breaker, but I consider us not supporting subscript selectors to just be a bug, and therefore the compiler shouldn't tell the user they've done something wrong.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, OK, now I see. For now I'd suggest changing the error message to type 'C1' has no member named 'subscript' (adding the word 'named'). I guess then it's correct since C1 doesn't have a member named subscript but only a subscript-member.

In a subsequent PR we could then maybe improve the diagnostics by looking if the type would have a subscript-member (which was probably meant) and point out that selectors for subscripts are not yet supported. Once we do support them, this would turn into a fixit for the getter or setter syntax.

case DeclBaseName::Kind::Subscript:
return "subscript";
case DeclBaseName::Kind::Normal:
return llvm::StringSwitch<StringRef>(name.getIdentifier().str())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rather than a StringSwitch, we should just escape anything that's a keyword.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't want to escape all keywords here. A function named default should still be output unescaped. I'm basically escaping a new class of keywords here, namely those that represent special names (in which "subscript" is currently the only member)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think that makes sense. You wouldn't want to see func func in the output of this tool. @nkcsgexi, what do you think? (Sorry to pull you in mid-discusson.)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think for swift-api-digester per se, being consistent is more important than being precise. So this change is fine as long as we always keep subscript escaped; however, this may not help the tool itself much.

@@ -1,4 +1,4 @@
// RUN: not --crash %target-swift-frontend %s -typecheck
// RUN: not %target-swift-frontend %s -typecheck
// REQUIRES: asserts
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please drop the "REQUIRES: asserts" as well. (We're not good about this and often clean them up in large batches, but it's good to get in the habit.)

@ahoppen
Copy link
Member Author

ahoppen commented Mar 9, 2017

Thanks for the review.

I guess the only way I could split this in some sensible way would be across my different commits. This would mean, we could split it in up to 5 pull requests:

  • Change calls of getName().isOperator() to isOperator()
    • Really small patch
  • Change the backing base name type of DeclName to DeclBaseName
    • Introduce DeclBaseName as an implementation detail of DeclName but don't expose it yet
    • Basically only affects Identifier.h
  • Preparations for special names
    • Expose DeclBaseName to the project but without special names for the moment
    • This basically adds a bunch of todos in places where special names will be handled later
  • Introduce special decl names
    • Actually introduce special names and remove the todos added in the previous commit
    • This and the above commit are both still fairly big (~500 lines) but I can't think of any sensible way to break them apart so that it still compiles in between
  • Add test cases for special subscript name
    • Should probably be merged together with the previous commit

@jrose-apple
Copy link
Contributor

That seems like a reasonable way to split it up. If (3) and (4) don't split nicely at least we'd have gotten (1) and (2) out of the way first, so they're not intermingled with everything else.

@ahoppen
Copy link
Member Author

ahoppen commented Mar 10, 2017

I'll create PRs one by one now, splitting (3) and (4) since the commits are already separate. We can always merge them again if we want to.

Part 1 -> #8015

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants