Closed swift-ci closed 8 years ago
I tried to reproduce the issue and got the following results:
case (#selector(showRescale))?:
works. As does case Optional.some(#selector(showRescale)):
and case .some(#selector(showRescale)):
.
I guess the parenthesis around #selector
should not be necessary and case #selector(showRescale)?:
should work as well. After this change the syntax of optional #selector
aligns with the one of any other optional type and all other versions are expected to be incorrect.
Secondly, applying the fix-its result in invalid code, so they should be fixed to append a question mark at the end of the expression.
I could, however, not reproduce the compiler crash. Could you maybe add more context, in particular method stubs for showRescale
and showUnits
and the class declaration? A small example file or project that crashes the compiler would be best.
As discussed on swift-users, this is not a Swift regression but an SDK change. (That doesn't mean we shouldn't improve things here, just that there's not going to be some particular Swift commit to blame.)
I believe the ?
shorthand only works when doing a pattern-match-style case, not arbitrary expression matching.
I will look into it. My current status is that it is easy to remove the current fix-it which generates malformatted source code. Adding the parenthesis and question mark as a fix-it seems tricky but I will investigate if it is possible.
I think the syntax with the question mark without parenthesis should be supported since you can also use case foo()?
. But maybe I'm missing some crucial fact.
That makes sense. @jckarter?
?
is part of the pattern grammar so it seems like it should work with an expression as a subpattern to me. We definitely shouldn't crash.
I just looked into the grammar and it seems like the pattern is eventually only mapped to expr-unary
which only supports expr-selector
without any postfix symbols, whereas otherwise expr-unary
is mapped to expr-postfix
that handles trailing questions marks. I would suggest to modify the grammar rule that maps expr-unary
to expr-selector
from
expr-unary(Mode): expr-selector
to
expr-unary(Mode): expr-selector '?'?
AFAIK the trailing exclamation mark or multiple question marks do not make any sense, so I would leave them out.
I think a better fix would be to make selector a primary-expression
, so that postfix operations can chain off of it normally.
I have one implementation question so that Swift no longer provides a fix-it after #selector
.
First little background: The case statement is resolved to a pattern matching expression $match ~= toMatch
where the source location of $match
is set to the beginning of #selector
, which AFAIK is sensible so that general errors about this pattern matching expression are reported in the right source line.
If, however, $match
is an Optional and toMatch
isn’t, the generic fix-it is to force unwrap $match
. Because of the implicit source location of $match
this inserts an !
after the first token following case
, which is definitely incorrect. I am currently thinking about the following resolutions to this problem:
Annotate the type variable of $match
as implicit, so that force unwrapping it is not considered in ConstraintSystem::matchTypes
?
using this approach, but I can’t think of any way to get such a fix-it right without doing some special casing in the constraint system that AFAIK can’t tell the difference between an expression with operator ~=
(where the trailing ?
is not allowed) and a pattern matching operation (where a trailing ?
is allowed).Special case the constraint system to provide a fix-it for a trailing ?
Set the source location of $match
to the expression to be switched on
!
to the switch variable may break other case
statements in the same switch and probably isn’t what the user wanted.Provide the same error message (value of optional type 'Int?' not unwrapped; did you mean to use '!' or '?'?
) without a fixit
Which approach do you think is best? And if 1 is the way to go: Can you think of any other AST nodes with implicit types except from DeclRefExpr
that reference an implicit declaration?
Btw the problem with the fix-its ins’t just about case #selector
but occurs with every type, e.g. in this sample:
let myOpt: Int? = 2
let myNonOpt: Int = 5
switch myOpt {
case myNonOpt:
break
}
Environment
MacOS X 10.11.5 (15F34), Xcode Version 8.0 beta (8S128d)Additional Detail from JIRA
| | | |------------------|-----------------| |Votes | 0 | |Component/s | Compiler | |Labels | Bug, CompilerCrash | |Assignee | @ahoppen | |Priority | Medium | md5: 83f099abd7f19440c9f109e51e844166Issue Description:
Here is some macOS code that was working under Xcode7/Swift 2.2:
This does not work under Xcode 8.0 beta (8S128d):
/Developer/SwiftNEC 3/SwiftNEC/NECDocumentVC.swift:78:18: Expected '(' following '#selector'
I have tried several different syntax modifications in an attempt to get it to work:
All of these fail with different errors, either the one reported above, or about a missing ![](, or others. Xcode 8 beta suggests adding the ), so I assume this is the blessed format, but it does not work.This, however, does work:
But shortened versions do not. This version:
causes the compiler to crash. So does this version: