Allow more characters (like whitespaces and punctuations) for escaped identifiers

That's great!

One thing that occurred to me after my post above was that the identifiers I wanted to use (//path/to/package:target_name) contain operator characters (and indeed, start with one). If we want to allow backticks to escape non-identifier characters in identifiers, we need to give consideration to how operator characters are handled. Some open questions and thoughts which are partly motivated by my own needs/use case:

  • Should operator characters be allowed in backticked identifiers? I think so; not only for my import use case, but it might be nice to write func `test +`() { ... } if I'm testing the + operator of a custom type.

  • Should backticks turn sequences entirely composed of operator characters into regular non-operator identifiers? For example, should `..<` or `+` be treated as separate non-operator identifiers to ..< and +? I think the answer should be no; that could lead to confusion, and there has also been some interest in using backticks around operators to reference them as type members, and I think these two features would tie nicely together.

  • What about backticked identifiers that contain mixed operator and non-operator characters? Any difference depending on whether the identifier starts with an operator character vs. just containing one? I think it should be fine to mix them, and I don't think it should the behavior should differ whether the identifier starts with an operator character or not; in both cases, it should be a regular identifier. (Selfishly, these are both important to my module use case.)

So, to summarize, IMO a backticked identifier may contain operator characters, but a backticked sequence that contains only operator characters is still an operator, not a regular identifier. In other words:

static func + (lhs: Foo, rhs: Foo) -> Foo {}  // an operator, of course
static func `+` (lhs: Foo, rhs: Foo) -> Foo {}  // equivalent, still an operator
let `-` = 5  // still not allowed, `-` is the same as -, an operator

func `test +`() {}  // a regular identifier

Now, strict application of my proposed rule could allow some weird situations:

func `+ -`() {}  // a regular identifier, because SPACE is not an operator character

We could try to add more rules, like "an identifier may not consist only of operator characters and whitespace, even when surrounded by backticks," but I don't know if adding more rules to address that would actually help or if it would just make things more complicated. I think it goes back to trusting users to not do silly things, just as we do with Unicode support today, and enforcing additional rules through style guides, linters, and code reviews. After all, we can put all the mechanical rules that we can dream of but nothing would stop a user from naming an identifier jidjfosijfsiodno, so figuring out where to draw the line is important, but also challenging.

2 Likes