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;
}