swift-syntax icon indicating copy to clipboard operation
swift-syntax copied to clipboard

Prevent unrelated casts using `as`

Open ahoppen opened this issue 2 years ago • 11 comments

Currently, SyntaxProtocol has an as method that allows casting to any other syntax node type. Because of this, it’s possible to e.g. cast a FunctionDeclSyntax to an IdentifierExprSyntax without any compiler errors or warnings, even though we know that the cast will always fail.

What we should do instead, is to only have a as(_: ExprSyntaxProtocol.Type) function on ExprSyntax (analogous for StmtSyntax and the other base nodes).

The as function on SyntaxProtocol can then be marked as deprecated and produce a warning that the cast will always fail.

is and cast will need to be updated accordingly.

ahoppen avatar Aug 23 '23 16:08 ahoppen

Tracked in Apple’s issue tracker as rdar://114330180

ahoppen avatar Aug 23 '23 16:08 ahoppen

What does the term "as well as as(_: SyntaxProtocol.Type)" mean? Does it suggest that every base node should have this method? Would this be equivalent to having the as method directly on SyntaxProtocol?

Matejkob avatar Aug 23 '23 18:08 Matejkob

Oh, that was an artifact of a sentence I started writing but then didn’t finish. Ignore it – and I removed it from the description

ahoppen avatar Aug 23 '23 20:08 ahoppen

If I have a Syntax, how do I then cast it to something else?

grynspan avatar Aug 28 '23 18:08 grynspan

If I have a Syntax, how do I then cast it to something else?

I believe we should keep this part of the casting API. If you find a while you could review my pull request #2108, which contains a draft proposal on casting constraints?

Matejkob avatar Aug 28 '23 19:08 Matejkob

If I have a Syntax, how do I then cast it to something else?

The proposal here is to remove the as methods on all types that are not base nodes, e.g. FunctionDeclSyntax.as. Syntax.as will continue to exist.

ahoppen avatar Aug 28 '23 20:08 ahoppen

Okay, so a Syntax can still be cast, but an arbitrary some SyntaxProtocol can't be? And if I find myself needing to cast in that case, I can do Syntax(foo).as(...)?

grynspan avatar Aug 29 '23 15:08 grynspan

@Matejkob also noted that in https://github.com/apple/swift-syntax/pull/2108. The only case where you won’t be able to cast is on anything that’s statically known to be a leaf syntax node type. Casting will still be possible on some SyntaxProtocol, some DeclSyntaxProtocol, any SyntaxProtocol etc.

ahoppen avatar Aug 29 '23 18:08 ahoppen

Oh, I get it. Sorry, I misunderstood what was being described here. I'll be quiet. :)

grynspan avatar Aug 29 '23 19:08 grynspan

@ahoppen if I remember correctly, we previously discussed having some follow-up PRs related to the main one (#2108). Should we keep closed the current issue and create new ones, or would you prefer to continue using this issue to track all follow-ups?

Things to do:

  • [x] Address casting for choice nodes (#2184)
  • [ ] Manage casting for syntax traits
  • [ ] Consolidate all casting logic into a single file for consistency and to centralize all implementations.

Matejkob avatar Sep 13 '23 13:09 Matejkob

Oh, sorry. I shouldn’t have closed this issue just yet.

ahoppen avatar Sep 13 '23 14:09 ahoppen