Add an optional bound to type parameter references

This allows us to represent type parameters with promoted bounds which
are different from the bound at the declaration.  A missing promoted
bound indicates that the type parameter has the original bound at the
declaration.

This is a representation-only change, the optional bound is always
`null`.  Closes #29529.

BUG=https://github.com/dart-lang/sdk/issues/29529
R=paulberry@google.com

Review-Url: https://codereview.chromium.org/2866593003 .
diff --git a/pkg/kernel/binary.md b/pkg/kernel/binary.md
index f9f415f..a8fa140 100644
--- a/pkg/kernel/binary.md
+++ b/pkg/kernel/binary.md
@@ -949,6 +949,8 @@
   // the class type parameters in a constructor refer to those declared on the
   // class.
   UInt index;
+  
+  Option<DartType> bound;
 }
 
 type VectorType extends DartType {
diff --git a/pkg/kernel/lib/ast.dart b/pkg/kernel/lib/ast.dart
index fa2d180..72ab24d 100644
--- a/pkg/kernel/lib/ast.dart
+++ b/pkg/kernel/lib/ast.dart
@@ -4103,10 +4103,21 @@
 final Map<TypeParameter, int> _temporaryHashCodeTable = <TypeParameter, int>{};
 
 /// Reference to a type variable.
+///
+/// A type variable has an optional bound because type promotion can change the
+/// bound.  A bound of `null` indicates that the bound has not been promoted and
+/// is the same as the [TypeParameter]'s bound.  This allows one to detect
+/// whether the bound has been promoted.
 class TypeParameterType extends DartType {
   TypeParameter parameter;
 
-  TypeParameterType(this.parameter);
+  /// An optional promoted bound on the type parameter.
+  ///
+  /// 'null' indicates that the type parameter's bound has not been promoted and
+  /// is therefore the same as the bound of [parameter].
+  DartType bound;
+
+  TypeParameterType(this.parameter, [this.bound]);
 
   accept(DartTypeVisitor v) => v.visitTypeParameterType(this);
 
diff --git a/pkg/kernel/lib/binary/ast_from_binary.dart b/pkg/kernel/lib/binary/ast_from_binary.dart
index 86503ff..e5af2a3 100644
--- a/pkg/kernel/lib/binary/ast_from_binary.dart
+++ b/pkg/kernel/lib/binary/ast_from_binary.dart
@@ -1084,7 +1084,8 @@
         return new FunctionType(positional, returnType);
       case Tag.TypeParameterType:
         int index = readUInt();
-        return new TypeParameterType(typeParameterStack[index]);
+        var bound = readDartTypeOption();
+        return new TypeParameterType(typeParameterStack[index], bound);
       default:
         throw fail('Invalid dart type tag: $tag');
     }
diff --git a/pkg/kernel/lib/binary/ast_to_binary.dart b/pkg/kernel/lib/binary/ast_to_binary.dart
index 98582c9..cdc92ea 100644
--- a/pkg/kernel/lib/binary/ast_to_binary.dart
+++ b/pkg/kernel/lib/binary/ast_to_binary.dart
@@ -1013,6 +1013,7 @@
   visitTypeParameterType(TypeParameterType node) {
     writeByte(Tag.TypeParameterType);
     writeUInt30(_typeParameterIndexer[node.parameter]);
+    writeOptionalNode(node.bound);
   }
 
   visitVectorType(VectorType node) {
diff --git a/runtime/vm/kernel_binary.cc b/runtime/vm/kernel_binary.cc
index 80d2939..55cee46 100644
--- a/runtime/vm/kernel_binary.cc
+++ b/runtime/vm/kernel_binary.cc
@@ -1486,6 +1486,8 @@
   TypeParameterType* type = new TypeParameterType();
   type->parameter_ =
       reader->helper()->type_parameters().Lookup(reader->ReadUInt());
+  // There is an optional promoted bound, currently ignored.
+  delete reader->ReadOptional<DartType>();
   return type;
 }