After ABI Stability: Will Diagnostics and Type Inference Get Some Love?


(Sebastian) #1

I use Swift everyday but haven't (yet) contributed to the language itself. Above all criticism I might have, I'm very grateful for what the Swift community is providing.

Two things I really wish would improve are diagnostics and type inference, in particular when it comes to closures and generics. (I'm beginning to accept the limitations on PATs)

Incidentally, I recently stumbled over this post by Max Howell (Creator of Homebrew and the Swift PromiseKit):
https://promisekit.org/news/2018/02/PromiseKit-6.0-Released/

Therein, he lays out how PromiseKit's type system and elegance have been compromised due to Swift's incomplete type inference and partially useless diagnostics. I have the utmost respect for Max, so I'm a bit worried when someone like him is frustrated with Swift and sounds like he's losing patience:

Swift is great… and terrible, specifically its error diagnostics are so bad in certain conditions that I honestly have started to wonder if recommending the language is still a good idea. [...] Swift lies.

If there is an error inside a closure, Swift, with no improvements since v1 :(, has told you the wrong error.

[...]

While error messages are basically useless as much as half the time Swift will lose mind-share and respect. I see it with new devs, they shake their heads and then tell me they prefer Javascript, they then start reading up about React Native.

I even see experienced developers not know how to proceed here, and this is for the additional reason that getting Xcode to show you the function definition for Swift code is a toss-up, half the time it doesn’t work, so experienced devs have stopped trying to make it work. When you can’t trust your tools you can’t get things done.

So I was wondering:

  1. What would be the process to fix such basic annoyances?
  2. Was the focus on ABI stability the main reason for why these issues still exist?
  3. What will be the Swift evolution focus after ABI stability?

(Slava Pestov) #2

The truth is that for a long time the design for emitting diagnostics from the expression type checker was bogus. The constraint solver would attempt to solver the constraint system, and upon encountering a failure, we would try to reconstruct what went wrong by applying various heuristics, including attempting to walk the syntax tree and type checking sub-expressions independently. The code implementing this had become completely unmaintainable, after non-stop incremental hacking on short deadlines since before Swift 1.

After the release of 4.2 @xedin began leading an effort to roll out a new diagnostics design where instead the constraint solver essentially leaves behind breadcrumbs, making to much easier to figure out what went wrong after the fact. The new code is being staged in incrementally, making it possible to port individual diagnostics over one-by-one (@gregtitus has been helping out as well, which is really great). It will be a while before this vision is completed, but once its all done the old unmaintainable diagnostics code can be ripped out completely.

If you test out a Swift 5.0 development snapshot, you might see some improvements already, but the situations where the new engine is used are still limited.


(Sebastian) #3

Oh alright, sounds like Swift is really in the hands of very few individuals/heroes.

As an outsider to the code and to compilers in general, I would expect the constraint solver itself to return all diagnostic information when it has to give up ...


(Tomáš Znamenáček) #4

I think depends on the design of the solver quite a bit. I have no idea about type inference but generally these algorithms are often of the “either it works or good luck figuring it out” sort. (See Auto Layout for an example. Either the layout works and it’s all rainbows, or there’s an ambiguity or a conflict and then it’s hard to say what’s missing or doesn’t belong.)


(Slava Pestov) #5

I didn't mean to imply that. There are plenty of opportunities to contribute to the type checker -- I just wanted to explain the current design and roadmap, since incremental additions to the old diagnostics code are not likely to produce significantly better results. But if you or anyone else wants to help move the new diagnostics along, @xedin, @rudkx and @gregtitus will be happy to help ;)


(Greg Titus) #6

Please! The nice thing about working on diagnostics is that since the compiler is erroring out, you don't need to get familiar with anything at all in the back half (code generation and optimization).


(Sebastian) #7

Thanks for sharing these insights. I didn't express myself very well, I was just somewhat surprised that there isn't that much process, people and red tape involved in fixing stuff :slight_smile:


(Pavel Yaskevich) #8

Thank you for bringing this up, @flowtoolz! Diagnostics is an area I and others are constantly working to improve. To add to what @Slava_Pestov said, generics and closures were and still are main focus of mine for a while now, but unfortunately these problems weren't easily diagnosable via the current framework @Slava_Pestov described, so I went a different route that makes it much easier to track and diagnose problems precisely.

I've already landed multiple improvements to generics and closures for the upcoming release (PRs have a lot of interesting examples):

@gregtitus helped a lot by adding multiple diagnostics!

Currently I'm adding missing members, name shadowing and porting old diagnostics to new framework.

https://bugs.swift.org/browse/SR-9415 is an interesting case which fits perfectly to be diagnosed via fixes, which is being worked on by external contributor.