dart-sdk/docs
Erik Ernst 57f895c7a4 Bounds of a generic type alias ensure the body is regular-bounded
The analyzer enforces the rule that when a generic type alias F has
formal type parameters X1..Xm with bounds B1..Bm, if we assume that
X1..Xm are types satisfying the corresponding bounds then it must be
the case that every type which occurs in the body of F must be
regular-bounded.

In other words, the bounds on the left hand side of `=` must imply
the bounds applicable to every type on the right hand side.

---------- NEW TEXT ----------

I just discovered that it is _not_ possible to skip the check on
every super-bounded parameterized type based on a generic type
alias: It is certainly possible to have a type which is correctly
super-bounded according to the type parameter bounds on the left
hand side of `=` in the type alias declaration, and still have a
right hand side where some types are not well-bounded. Consider the
following declarations:

  class B<Y1 extends Y2, Y2, Y3 extends num> {}
  typedef F<X extends num> = B<num, Object, X> Function();

According to the declarations to the left of `=`, `F<Object>`
is a correct super-bounded type, because it is not
regular-bounded (`Object <\: num`), and `F<Null>` is regular-bounded
(`Null <: num`).

Also, when the declared bound of `X` is satisfied, we are
guaranteed that each type on the right hand side is regular-bounded
(if parameterized, it receives type arguments that satisfy all
the specified bounds).

But consider the result of applying `F` to `Object`:

  B<num, Object, Object> Function();

That's not a type where all subterms which are types are
well-bounded:

  B<num, Object, Object> is not regular-bounded because
  `Object <\: num` (third type argument).

  B<num, Object, Object> is not super-bounded because
  B<num, Null, Null> is not regular-bounded because
  `num <\: Null` (violating `Y1 extends Y2`).

So there is no way we can prove that this check can be skipped,
because we have a pretty simple counter-example!

I'm currently adjusting the text to re-introduce the check.

---------- OLD TEXT, NOT VALID ----------

This must be specified, because it justifies the _removal_ of a
requirement that we had in the feature specification
super-bounded-types.md: It was required for every application of a
generic type alias F to a list of actual type arguments <T1..Tk>
such that the resulting parameterized type F<T1..Tk> was
super-bounded that both the parameterized type F<T1..Tk> and every
type in the resulting type [T1/X1..Tk/Xk]U (where U is the body of
F and X1..Xk are its formal type parameters) be well-bounded.

But when the bounds of F imply satisfaction of the bounds of all
types that occur in the body of F, it's trivially true that all
types in the resulting type are regular-bounded for the result
of substituting Null for covariant top types and Object for
contravariant Null for every super-bounded F<T1..Tk>. I'm looking
into a proof sketch for the result that this implies that any
well-bounded generic type alias application yields a type that
contains only well-bounded types.

This would be a very welcome simplification (because it was an
inconvenient complication that we had to check both the left hand
side and the right hand side of a type alias whenever we
encountered a super-bounded type expressed via a type alias), and
I believe that it will also make the tools run faster (because they
can now skip all those checks of every type that occurs in the body
for every super-bounded usage of a type alias.

Change-Id: Icd70649ebaed41b193aeb0cb6f08d06aed0ee5bd
Reviewed-on: https://dart-review.googlesource.com/c/79743
Reviewed-by: Leaf Petersen <leafp@google.com>
Reviewed-by: Lasse R.H. Nielsen <lrn@google.com>
2018-10-24 10:32:38 +00:00
..
language Bounds of a generic type alias ensure the body is regular-bounded 2018-10-24 10:32:38 +00:00
newsletter Newsletter 2017-11-24. 2017-11-24 16:27:00 +00:00