This is really great, as Swift’s error messages aren’t great when working with anything moderately complex. SwiftUI in particular seemed to stretch the abilities of the type system to the breaking point, and I’m glad to see that work is being done to improve error messages there instead of failing with mystifying reasons when people make reasonable mistakes.
The article gives several examples of areas in which these changes have particularly made big improvements to common error messages one might see while working with SwiftUI
"Please don't comment on whether someone read an article. "Did you even read the article? It mentions that" can be shortened to "The article mentions that.""
I’ve noticed that when editing the ContentView in SwiftUI, errors will sometimes be attached to a totally unrelated line (OTOH, forgetting to unwrap an optional returned by NumberFormatter.string() showed
type of expression is ambiguous without more context
on a straightforward Text() expression halfway up the file). The only way to find the actual source of the error is to undo every change until the error disappears, and coupled with sluggish compilation times this becomes a real pain. I hope they address this issue as part of their improvements.
I'm really happy to see this effort! I participate in the rustc project dedicating myself mainly to diagnostics and ergonomics and I believe that the industry hasn't scratched the surface of what can be done through error messages. In Rust, my own personal rule of thumb is that the compiler should be your first tutor and act as a pair programmer. Rust has one advantage for doing so that was arrived to "by accident": the fewer things are valid code, the bigger the distance between valid and invalid code. In the boundary of these two areas there is code that can be reasonably imagined to be valid by somebody who knows a fraction of the rules of the language. I call this the "negative space" of the language. You can think of a case (again, in Rust because it is what I am familiar with, but the ideas can be applied to any language) like
fn main() {
let x = "a" + "b";
}
which is invalid Rust due to reasons, but the compiler emits the following output[1]:
error[E0369]: binary operation `+` cannot be applied to type `&str`
--> src/main.rs:2:17
|
2 | let x = "a" + "b";
| --- ^ --- &str
| | |
| | `+` cannot be used to concatenate two `&str` strings
| &str
help: `to_owned()` can be used to create an owned `String` from a string reference. String concatenation appends the string on the right to the string on the left and may require reallocation. This requires ownership of the string on the left
|
2 | let x = "a".to_owned() + "b";
| ^^^^^^^^^^^^^^
Is it perfect? No, it is verbose and you could make the case that the language should be extended to accept the code as is. Because we have design constraints that don't let us accept the code, we've extended the compiler to support the construct in order to provide the fixed code, while simultaneously allowing the language to conform to its constraints. The hard part of this is that now your compiler is as complex as it would have to be to support the superset language. Also, the less negative space there's in the language, namely, the more expressive it is, the less you can apply this strategy
I am reminded of a recent tweet: "We spent decades trying to invent a sufficiently smart compiler when we should have been inventing a sufficiently empathetic one"[2]
Edit: if you have to Google to understand what the compiler is saying, I consider that a bug. File tickets for confusing diagnostics!
The diagnostic improvements are great. Unfortunately many of these examples show how serious of a mistake it was to require explicit numeric conversions all over the place.
17 comments
[ 1.7 ms ] story [ 48.2 ms ] threadPast the breaking point. SwiftUI brought several new language features just to make it possible.
https://news.ycombinator.com/newsguidelines.html
I guess SwiftUI exacerbates the problem since expressions are necessarily very deeply nested.
It seems to be a problematic diagnostic they have particularly focused on resolving.
I am reminded of a recent tweet: "We spent decades trying to invent a sufficiently smart compiler when we should have been inventing a sufficiently empathetic one"[2]
Edit: if you have to Google to understand what the compiler is saying, I consider that a bug. File tickets for confusing diagnostics!
[1]: https://play.rust-lang.org/?version=nightly&mode=debug&editi...
[2]: https://twitter.com/mostlysafe/status/1176170363266449410
I this it's a great idea and with new diagnostic architecture described in the blog post it would be relatively easy to archive.
error: binary operator '+' cannot be applied to operands of type 'String' and 'Int'
_ = "a" + 1
note: overloads for '+' exist with these partially matching parameter lists: (Int, Int), (String, String)_ = "a" + 1
note: candidate expects value of type 'String' for parameter #2 note: candidate expects value of type 'Int' for parameter #1The article describes the mental model needed to understand the operation of the swift type error diagnostic system with a high level of clarity.
Thinking through how this system works provides a super valuable learning experience for a wide audience of readers.