SR-13706 Fix-it for missing let/var in pattern when identifier is unbound
Issue Description:
Consider this incorrect code:
enum List {
indirect case Cons(Int, List)
case Nil
}
func hd(_ lst : List) -> Int? {
switch lst {
case .Cons(hd, _): return hd
case .Nil: return nil
}
}
let lst = List.Cons(1, List.Nil)
if let h = hd(lst) {
print(h)
}
The programmer (me) thought they were introducing a new binding, `hd` in the Cons case pattern. But, that requires a let/var in the pattern, so the compiler interprets it as an expression pattern. Not to be confused with SR-13706, here `hd` is bound as the name of the function itself, so we get the following type error:
missing_let_int.swift:9:20: error: expression pattern of type '(List) -> Int?' cannot match values of type 'Int'
case .Cons(hd, _): return hd
^~
missing_let_int.swift:9:35: error: cannot convert return expression of type '(List) -> Int?' to return type 'Int?'
case .Cons(hd, _): return hd
^~
In this case, a fix-it may be warranted to suggest that they add a let/var in the pattern. The errors can get quite nasty and confusing when making this mistake for a more complex enum type, such as in this code:
enum List<T> {
indirect case Cons(T, List<T>)
case Nil
}
func hd<T>(_ lst : List<T>) -> T? {
switch lst {
case .Cons(hd, _): return hd
case .Nil: return nil
}
}
let lst = List.Cons(1, List.Nil)
if let h = hd(lst) {
print(h)
}
Which gives all of these errors:
missing_let.swift:9:20: error: expression pattern of type '(List<T>) -> T?' cannot match values of type 'T'
case .Cons(hd, _): return hd
^~
missing_let.swift:9:20: error: generic parameter 'T' could not be inferred
case .Cons(hd, _): return hd
^
missing_let.swift:7:6: note: in call to function 'hd'
func hd<T>(_ lst : List<T>) -> T? {
^
missing_let.swift:9:35: error: cannot convert return expression of type '(List<T>) -> T?' to return type 'T?'
case .Cons(hd, _): return hd
^~
as! T
missing_let.swift:9:35: error: generic parameter 'T' could not be inferred
case .Cons(hd, _): return hd
^
missing_let.swift:7:6: note: in call to function 'hd'
func hd<T>(_ lst : List<T>) -> T? {
^
theindigamer (JIRA User) agrees that a fix-it may be good here.
Additional Detail from JIRA
| | | |------------------|-----------------| |Votes | 0 | |Component/s | Compiler | |Labels | Improvement, DiagnosticsQoI, TypeChecker | |Assignee | None | |Priority | Medium | md5: 56d9c5d34022ff4984c7e5bdb640d5e2relates to:
Issue Description:
Consider this incorrect code:
The programmer (me) thought they were introducing a new binding, `hd` in the Cons case pattern. But, that requires a let/var in the pattern, so the compiler interprets it as an expression pattern. Not to be confused with SR-13706, here `hd` is bound as the name of the function itself, so we get the following type error:
In this case, a fix-it may be warranted to suggest that they add a let/var in the pattern. The errors can get quite nasty and confusing when making this mistake for a more complex enum type, such as in this code:
Which gives all of these errors:
theindigamer (JIRA User) agrees that a fix-it may be good here.