News for hackers. Stuff that matters.
Re:Understanding contravariance by munificent on Friday June 22, 2018 @01:22PM (#17375695)
Counter-opinion.

I work on a language, Dart, where all generics are covariant. In Dart 1, invalid uses of covariance were not checked at runtime and were silently ignored. When that leads to wrong behavior down the road, it's profoundly confusing. Not checking this and sacrificing safety, also ties your hands when it comes to compile time optimization because you can longer take any of your type annotations seriously.

In Dart 2, we've moved to a sound type system, which involves checking these misuses at runtime. I have personally gone through and fixed hundreds of these runtime failures. Others at Google have done the same. It's grueling, difficult work. Figuring out where an object was constructed before it eventually wound up somewhere in a covariant position is not easy.

I would much rather have static control over variance even with the additional complexity if causes, and I've heard similar requests from many users.

Re:Understanding contravariance by mraleph on Monday June 25, 2018 @02:57AM (#17390434)
> I have personally gone through and fixed hundreds of these runtime failures.

An interesting question here would be how many of those hundreds of failures were actual bugs and how many were just were just side effect of changing "dynamic is both top and bottom" rule.

So far I have not encountered a single actual issue when migrating users' code to Dart 2 - I encountered "unsoundly" typed code, but it actually worked and did not contain bugs.

Re:Understanding contravariance by munificent on Monday June 25, 2018 @02:25PM (#17394499)
Some, but not many actual bugs, but note that the corpus in question:

1. Is developed at a company with a stronger-than-average culture around quality and tests.

2. Already has copious tests.

3. Is mostly in applications that have been shipped in production.

So most of the bugs were already flushed out before we got to the point where we started tightening things. The more interesting question, which we don't have data for, is how much time it took to flush those bugs out the first time and how much the stricter runtime checking affects that. Hopefully it helps users find these kinds of issues faster.

Re:Understanding contravariance by wisam on Friday June 22, 2018 @08:29PM (#17378680)
I thought soundness (when it comes to statically-typed languages) means that the static type checker won't pass a program that would raise runtime type errors. Your comment (and Dart's website) was the first time I've read a claim of soundness by combining static type checker and runtime checks. Doesn't your definition mean that most type systems (even those of weakly and dynamically-typed languages) are sound. Even JS and PHP will eventually give up and give you a type error. Can't think languages other than C (which might give you segfaults or whathaveyou) that won't fit that definition of soundness.

Sincere question, what am I getting wrong?

Re:Understanding contravariance by munificent on Monday June 25, 2018 @02:33PM (#17394579)
"Sound" is one of those words whose definition varies more than you think. Some people use it to mean only statically proven to be free of type errors.

But, I think in practice, most languages that we call "sound" do indeed rely on some amount of runtime checking in order to guarantee that. Java and C# are both widely considered sound — and need to be to preserve memory safety! — and they both use runtime checking to ensure that (on cast operators and covariant array usage). I think even Haskell defaults to runtime checking of non-exhaustive pattern matching, which could be considered a form of "type errors".

> Doesn't your definition mean that most type systems (even those of weakly and dynamically-typed languages) are sound.

Dynamically-typed languages detect the type error right at the point where you try to perform an invalid operation for that type. They are safe in that that doesn't generally lead you into a hard crash or scary undefined behavior.

C# and Java are similar with respect to array usage — you get the type error right when you attempt to do a covariant store. Dart is similar for covariant generics.

But in most other cases, Dart detects the error earlier, at the point that you attempt to cast a value to the wrong type, not when you later use it as that wrong type.

Re:Understanding contravariance by jblow on Friday June 22, 2018 @01:50PM (#17375895)
You don’t have a debug allocator that just tells you what file and line made the allocation? Ouch.
Re:Understanding contravariance by munificent on Friday June 22, 2018 @04:54PM (#17377256)
We have a lot of different execution environments (compiled to JS with debug compiler, compiled to JS with optimizing compiler, JIT VM, AoT VM, bytecode interpreter, Android, iOS, etc.) so that makes it a little more complex.

We do have allocation tracking in some of those, but that doesn't always get you as much as you'd expect. Discovering that, say, "oh, this list was deserialized by the JSON API" still means it could have come from dozens of different regions of the program.

Re:Understanding contravariance by archgoon on Friday June 22, 2018 @02:43PM (#17376309)
I would expect the debug allocator would need to be a full stack trace, file and line on their own would probably not be helpful. This is probably doable if they cache the allocation paths. But it would be interesting to hear about what tooling they've added to track these issues.