[dart2js] Normalize DartTypes.

Change-Id: I2c3ddbecf9f9bbaac8f940398a7d5949c441fca4
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/134941
Reviewed-by: Sigmund Cherem <sigmund@google.com>
This commit is contained in:
Mayank Patke 2020-02-14 01:59:12 +00:00 committed by commit-bot@chromium.org
parent 573f470615
commit 1591ddcf1e
35 changed files with 947 additions and 651 deletions

View file

@ -41,7 +41,8 @@ main() {
typedefWithFutureOr);
print(
/*TypeLiteral(FutureOr<dynamic>)*/
/*cfe|analyzer.TypeLiteral(FutureOr<dynamic>)*/
/*dart2js.TypeLiteral(dynamic)*/
futureOr);
print(

View file

@ -178,37 +178,38 @@ abstract class CommonElements {
/// [elementType] as its type argument.
///
/// If no type argument is provided, the canonical raw type is returned.
InterfaceType listType([DartType elementType]);
InterfaceType listType(Nullability nullability, [DartType elementType]);
/// Returns an instance of the `Set` type defined in 'dart:core' with
/// [elementType] as its type argument.
///
/// If no type argument is provided, the canonical raw type is returned.
InterfaceType setType([DartType elementType]);
InterfaceType setType(Nullability nullability, [DartType elementType]);
/// Returns an instance of the `Map` type defined in 'dart:core' with
/// [keyType] and [valueType] as its type arguments.
///
/// If no type arguments are provided, the canonical raw type is returned.
InterfaceType mapType([DartType keyType, DartType valueType]);
InterfaceType mapType(Nullability nullability,
[DartType keyType, DartType valueType]);
/// Returns an instance of the `Iterable` type defined in 'dart:core' with
/// [elementType] as its type argument.
///
/// If no type argument is provided, the canonical raw type is returned.
InterfaceType iterableType([DartType elementType]);
InterfaceType iterableType(Nullability nullability, [DartType elementType]);
/// Returns an instance of the `Future` type defined in 'dart:async' with
/// [elementType] as its type argument.
///
/// If no type argument is provided, the canonical raw type is returned.
InterfaceType futureType([DartType elementType]);
InterfaceType futureType(Nullability nullability, [DartType elementType]);
/// Returns an instance of the `Stream` type defined in 'dart:async' with
/// [elementType] as its type argument.
///
/// If no type argument is provided, the canonical raw type is returned.
InterfaceType streamType([DartType elementType]);
InterfaceType streamType(Nullability nullability, [DartType elementType]);
/// Returns `true` if [element] is a superclass of `String` or `num`.
bool isNumberOrStringSupertype(ClassEntity element);
@ -928,23 +929,24 @@ class CommonElementsImpl
InterfaceType get stackTraceType => _getRawType(stackTraceClass);
@override
InterfaceType listType([DartType elementType]) {
InterfaceType listType(Nullability nullability, [DartType elementType]) {
if (elementType == null) {
return _getRawType(listClass);
}
return _createInterfaceType(listClass, [elementType]);
return _createInterfaceType(listClass, [elementType], nullability);
}
@override
InterfaceType setType([DartType elementType]) {
InterfaceType setType(Nullability nullability, [DartType elementType]) {
if (elementType == null) {
return _getRawType(setClass);
}
return _createInterfaceType(setClass, [elementType]);
return _createInterfaceType(setClass, [elementType], nullability);
}
@override
InterfaceType mapType([DartType keyType, DartType valueType]) {
InterfaceType mapType(Nullability nullability,
[DartType keyType, DartType valueType]) {
if (keyType == null && valueType == null) {
return _getRawType(mapClass);
} else if (keyType == null) {
@ -952,31 +954,31 @@ class CommonElementsImpl
} else if (valueType == null) {
valueType = dynamicType;
}
return _createInterfaceType(mapClass, [keyType, valueType]);
return _createInterfaceType(mapClass, [keyType, valueType], nullability);
}
@override
InterfaceType iterableType([DartType elementType]) {
InterfaceType iterableType(Nullability nullability, [DartType elementType]) {
if (elementType == null) {
return _getRawType(iterableClass);
}
return _createInterfaceType(iterableClass, [elementType]);
return _createInterfaceType(iterableClass, [elementType], nullability);
}
@override
InterfaceType futureType([DartType elementType]) {
InterfaceType futureType(Nullability nullability, [DartType elementType]) {
if (elementType == null) {
return _getRawType(futureClass);
}
return _createInterfaceType(futureClass, [elementType]);
return _createInterfaceType(futureClass, [elementType], nullability);
}
@override
InterfaceType streamType([DartType elementType]) {
InterfaceType streamType(Nullability nullability, [DartType elementType]) {
if (elementType == null) {
return _getRawType(streamClass);
}
return _createInterfaceType(streamClass, [elementType]);
return _createInterfaceType(streamClass, [elementType], nullability);
}
@override
@ -1021,17 +1023,19 @@ class CommonElementsImpl
return _env.getRawType(cls);
}
/// Create the instantiation of [cls] with the given [typeArguments].
/// Create the instantiation of [cls] with the given [typeArguments] and
/// [nullability].
InterfaceType _createInterfaceType(
ClassEntity cls, List<DartType> typeArguments) {
return _env.createInterfaceType(cls, typeArguments);
ClassEntity cls, List<DartType> typeArguments, Nullability nullability) {
return _env.createInterfaceType(cls, typeArguments, nullability);
}
@override
InterfaceType getConstantListTypeFor(InterfaceType sourceType) =>
dartTypes.treatAsRawType(sourceType)
? _env.getRawType(jsArrayClass)
: _env.createInterfaceType(jsArrayClass, sourceType.typeArguments);
: _env.createInterfaceType(
jsArrayClass, sourceType.typeArguments, sourceType.nullability);
@override
InterfaceType getConstantMapTypeFor(InterfaceType sourceType,
@ -1039,11 +1043,11 @@ class CommonElementsImpl
ClassEntity classElement = onlyStringKeys
? (hasProtoKey ? constantProtoMapClass : constantStringMapClass)
: generalConstantMapClass;
List<DartType> typeArgument = sourceType.typeArguments;
if (dartTypes.treatAsRawType(sourceType)) {
return _env.getRawType(classElement);
} else {
return _env.createInterfaceType(classElement, typeArgument);
return _env.createInterfaceType(
classElement, sourceType.typeArguments, sourceType.nullability);
}
}
@ -1051,8 +1055,8 @@ class CommonElementsImpl
InterfaceType getConstantSetTypeFor(InterfaceType sourceType) =>
dartTypes.treatAsRawType(sourceType)
? _env.getRawType(constSetLiteralClass)
: _env.createInterfaceType(
constSetLiteralClass, sourceType.typeArguments);
: _env.createInterfaceType(constSetLiteralClass,
sourceType.typeArguments, sourceType.nullability);
@override
FieldEntity get symbolField => symbolImplementationField;
@ -2285,9 +2289,10 @@ abstract class ElementEnvironment {
/// Calls [f] for each supertype of [cls].
void forEachSupertype(ClassEntity cls, void f(InterfaceType supertype));
/// Create the instantiation of [cls] with the given [typeArguments].
/// Create the instantiation of [cls] with the given [typeArguments] and
/// [nullability].
InterfaceType createInterfaceType(
ClassEntity cls, List<DartType> typeArguments);
ClassEntity cls, List<DartType> typeArguments, Nullability nullability);
/// Returns the `dynamic` type.
DartType get dynamicType;

View file

@ -142,8 +142,8 @@ SetConstantValue createSet(CommonElements commonElements,
InterfaceType sourceType, List<ConstantValue> values) {
InterfaceType type = commonElements.getConstantSetTypeFor(sourceType);
DartType elementType = type.typeArguments.first;
InterfaceType mapType =
commonElements.mapType(elementType, commonElements.nullType);
InterfaceType mapType = commonElements.mapType(
Nullability.none, elementType, commonElements.nullType);
List<NullConstantValue> nulls = new List<NullConstantValue>.filled(
values.length, const NullConstantValue());
MapConstantValue entries = createMap(commonElements, mapType, values, nulls);
@ -174,9 +174,10 @@ MapConstantValue createMap(
bool hasProtoKey = (protoValue != null);
InterfaceType keysType;
if (commonElements.dartTypes.treatAsRawType(sourceType)) {
keysType = commonElements.listType();
keysType = commonElements.listType(Nullability.none);
} else {
keysType = commonElements.listType(sourceType.typeArguments.first);
keysType = commonElements.listType(
Nullability.none, sourceType.typeArguments.first);
}
ListConstantValue keysList = createList(commonElements, keysType, keys);
InterfaceType type = commonElements.getConstantMapTypeFor(sourceType,

View file

@ -1049,7 +1049,7 @@ class InstantiationConstantValue extends ConstantValue {
@override
DartType getType(CommonElements types) {
FunctionType type = function.getType(types);
return type.instantiate(typeArguments);
return types.dartTypes.instantiate(type, typeArguments);
}
@override

View file

@ -4,6 +4,7 @@
import '../common/names.dart';
import '../common_elements.dart';
import '../serialization/serialization.dart';
import '../util/util.dart' show equalElements;
import 'entities.dart';
@ -38,17 +39,87 @@ extension NullabilityUtils on Nullability {
int compareTo(Nullability other) => index.compareTo(other.index);
}
abstract class DartType {
final Nullability nullability;
extension on DataSource {
List<DartType> _readDartTypes(
List<FunctionTypeVariable> functionTypeVariables) {
int count = readInt();
List<DartType> types = List<DartType>(count);
for (int index = 0; index < count; index++) {
types[index] = DartType.readFromDataSource(this, functionTypeVariables);
}
return types;
}
}
const DartType(this.nullability);
extension on DataSink {
void _writeDartTypes(
List<DartType> types, List<FunctionTypeVariable> functionTypeVariables) {
writeInt(types.length);
for (DartType type in types) {
type.writeToDataSink(this, functionTypeVariables);
}
}
}
abstract class DartType {
Nullability get nullability;
const DartType();
factory DartType.readFromDataSource(
DataSource source, List<FunctionTypeVariable> functionTypeVariables) {
DartTypeKind kind = source.readEnum(DartTypeKind.values);
switch (kind) {
case DartTypeKind.none:
return null;
case DartTypeKind.neverType:
return NeverType._readFromDataSource(source, functionTypeVariables);
case DartTypeKind.voidType:
return VoidType._readFromDataSource(source, functionTypeVariables);
case DartTypeKind.typeVariable:
return TypeVariableType._readFromDataSource(
source, functionTypeVariables);
case DartTypeKind.functionTypeVariable:
return FunctionTypeVariable._readFromDataSource(
source, functionTypeVariables);
case DartTypeKind.functionType:
return FunctionType._readFromDataSource(source, functionTypeVariables);
case DartTypeKind.interfaceType:
return InterfaceType._readFromDataSource(source, functionTypeVariables);
case DartTypeKind.dynamicType:
return DynamicType._readFromDataSource(source, functionTypeVariables);
case DartTypeKind.erasedType:
return ErasedType._readFromDataSource(source, functionTypeVariables);
case DartTypeKind.anyType:
return AnyType._readFromDataSource(source, functionTypeVariables);
case DartTypeKind.futureOr:
return FutureOrType._readFromDataSource(source, functionTypeVariables);
}
throw UnsupportedError('Unexpected DartTypeKind $kind');
}
void writeToDataSink(
DataSink sink, List<FunctionTypeVariable> functionTypeVariables);
/// Returns a new type formed by replacing the current [nullability] with the
/// specified one.
///
/// Caution: This directly manipulates the type without renormalizing.
DartType _withNullability(Nullability nullability);
DartType _withoutNullability() => _withNullability(Nullability.none);
DartType _withQuestion() => _withNullability(Nullability.question);
/// Returns a new type formed by removing the [nullability] suffix from this
/// type.
DartType get _toNonNullable => _withNullability(Nullability.none);
/// Returns a new type formed by replacing the [nullability] suffix on this
/// type with [Nullability.question].
/// Caution: This directly manipulates the type without renormalizing.
DartType get _toNullable => _withNullability(Nullability.question);
/// Returns a new type formed by replacing the [nullability] suffix on this
/// type with [Nullability.star].
/// Caution: This directly manipulates the type without renormalizing.
DartType get _toLegacy => _withNullability(Nullability.star);
/// Is `true` if this type is a top type.
bool _isTop(bool useNullSafety) => false;
@ -81,22 +152,6 @@ abstract class DartType {
/// type. This excludes function type variables, whether free or bound.
void forEachTypeVariable(f(TypeVariableType variable)) {}
/// Performs the substitution `[arguments[i]/parameters[i]]this`.
///
/// The notation is known from this lambda calculus rule:
///
/// (lambda x.e0)e1 -> [e1/x]e0.
///
/// See [TypeVariableType] for a motivation for this method.
///
/// Invariant: There must be the same number of [arguments] and [parameters].
DartType subst(List<DartType> arguments, List<DartType> parameters) {
assert(arguments.length == parameters.length);
if (parameters.isEmpty) return this;
return SimpleDartTypeSubstitutionVisitor(arguments, parameters)
.substitute(this);
}
/// Calls the visit method on [visitor] corresponding to this type.
R accept<R, A>(DartTypeVisitor<R, A> visitor, A argument);
@ -184,14 +239,32 @@ class _Assumptions {
class InterfaceType extends DartType {
final ClassEntity element;
final List<DartType> typeArguments;
@override
final Nullability nullability;
InterfaceType(this.element, this.typeArguments, Nullability nullability)
: assert(typeArguments.every((e) => e != null)),
super(nullability);
InterfaceType._(this.element, this.typeArguments, this.nullability)
: assert(typeArguments.every((e) => e != null));
factory InterfaceType._readFromDataSource(
DataSource source, List<FunctionTypeVariable> functionTypeVariables) {
ClassEntity element = source.readClass();
List<DartType> typeArguments = source._readDartTypes(functionTypeVariables);
Nullability nullability = source.readEnum(Nullability.values);
return InterfaceType._(element, typeArguments, nullability);
}
@override
void writeToDataSink(
DataSink sink, List<FunctionTypeVariable> functionTypeVariables) {
sink.writeEnum(DartTypeKind.interfaceType);
sink.writeClass(element);
sink._writeDartTypes(typeArguments, functionTypeVariables);
sink.writeEnum(nullability);
}
@override
DartType _withNullability(Nullability nullability) =>
InterfaceType(element, typeArguments, nullability);
InterfaceType._(element, typeArguments, nullability);
@override
bool _isTop(bool useNullSafety) =>
@ -265,13 +338,29 @@ class InterfaceType extends DartType {
class TypeVariableType extends DartType {
final TypeVariableEntity element;
@override
final Nullability nullability;
const TypeVariableType(this.element, Nullability nullability)
: super(nullability);
const TypeVariableType._(this.element, this.nullability);
factory TypeVariableType._readFromDataSource(
DataSource source, List<FunctionTypeVariable> functionTypeVariables) {
TypeVariableEntity element = source.readTypeVariable();
Nullability nullability = source.readEnum(Nullability.values);
return TypeVariableType._(element, nullability);
}
@override
void writeToDataSink(
DataSink sink, List<FunctionTypeVariable> functionTypeVariables) {
sink.writeEnum(DartTypeKind.typeVariable);
sink.writeTypeVariable(element);
sink.writeEnum(nullability);
}
@override
DartType _withNullability(Nullability nullability) =>
TypeVariableType(element, nullability);
TypeVariableType._(element, nullability);
@override
bool get containsTypeVariables => true;
@ -313,15 +402,37 @@ class FunctionTypeVariable extends DartType {
/// type.
final int index;
@override
final Nullability nullability;
/// The bound of this function type variable.
DartType _bound;
FunctionTypeVariable(this.index, Nullability nullability)
: super(nullability);
FunctionTypeVariable._(this.index, this.nullability);
factory FunctionTypeVariable._readFromDataSource(
DataSource source, List<FunctionTypeVariable> functionTypeVariables) {
int index = source.readInt();
assert(0 <= index && index < functionTypeVariables.length);
return functionTypeVariables[index];
}
@override
void writeToDataSink(
DataSink sink, List<FunctionTypeVariable> functionTypeVariables) {
int index = functionTypeVariables.indexOf(this);
if (index == -1) {
// TODO(johnniwinther): Avoid free variables.
const DynamicType._().writeToDataSink(sink, functionTypeVariables);
} else {
sink.writeEnum(DartTypeKind.functionTypeVariable);
sink.writeInt(index);
}
}
@override
DartType _withNullability(Nullability nullability) =>
FunctionTypeVariable(index, nullability)..bound = bound;
FunctionTypeVariable._(index, nullability)..bound = bound;
DartType get bound {
assert(_bound != null, "Bound has not been set.");
@ -348,10 +459,27 @@ class FunctionTypeVariable extends DartType {
}
class NeverType extends DartType {
const NeverType(Nullability nullability) : super(nullability);
@override
final Nullability nullability;
const NeverType._(this.nullability);
factory NeverType._readFromDataSource(
DataSource source, List<FunctionTypeVariable> functionTypeVariables) {
Nullability nullability = source.readEnum(Nullability.values);
return NeverType._(nullability);
}
@override
DartType _withNullability(Nullability nullability) => NeverType(nullability);
void writeToDataSink(
DataSink sink, List<FunctionTypeVariable> functionTypeVariables) {
sink.writeEnum(DartTypeKind.neverType);
sink.writeEnum(nullability);
}
@override
DartType _withNullability(Nullability nullability) =>
NeverType._(nullability);
@override
R accept<R, A>(DartTypeVisitor<R, A> visitor, A argument) =>
@ -370,9 +498,20 @@ class NeverType extends DartType {
}
class VoidType extends DartType {
const VoidType._() : super(Nullability.none);
const VoidType._();
factory VoidType() => const VoidType._();
factory VoidType._readFromDataSource(DataSource source,
List<FunctionTypeVariable> functionTypeVariables) =>
const VoidType._();
@override
void writeToDataSink(
DataSink sink, List<FunctionTypeVariable> functionTypeVariables) {
sink.writeEnum(DartTypeKind.voidType);
}
@override
Nullability get nullability => Nullability.none;
@override
DartType _withNullability(Nullability nullability) => this;
@ -395,9 +534,20 @@ class VoidType extends DartType {
}
class DynamicType extends DartType {
const DynamicType._() : super(Nullability.none);
const DynamicType._();
factory DynamicType() => const DynamicType._();
factory DynamicType._readFromDataSource(DataSource source,
List<FunctionTypeVariable> functionTypeVariables) =>
const DynamicType._();
@override
void writeToDataSink(
DataSink sink, List<FunctionTypeVariable> functionTypeVariables) {
sink.writeEnum(DartTypeKind.dynamicType);
}
@override
Nullability get nullability => Nullability.none;
@override
DartType _withNullability(Nullability nullability) => this;
@ -420,9 +570,20 @@ class DynamicType extends DartType {
}
class ErasedType extends DartType {
const ErasedType._() : super(Nullability.none);
const ErasedType._();
factory ErasedType() => const ErasedType._();
factory ErasedType._readFromDataSource(DataSource source,
List<FunctionTypeVariable> functionTypeVariables) =>
const ErasedType._();
@override
void writeToDataSink(
DataSink sink, List<FunctionTypeVariable> functionTypeVariables) {
sink.writeEnum(DartTypeKind.erasedType);
}
@override
Nullability get nullability => Nullability.none;
@override
DartType _withNullability(Nullability nullability) => this;
@ -456,9 +617,20 @@ class ErasedType extends DartType {
/// * Representing types appearing as generic method bounds which contain type
/// variables. (See issue 33422.)
class AnyType extends DartType {
const AnyType._() : super(Nullability.none);
const AnyType._();
factory AnyType() => const AnyType._();
factory AnyType._readFromDataSource(DataSource source,
List<FunctionTypeVariable> functionTypeVariables) =>
const AnyType._();
@override
void writeToDataSink(
DataSink sink, List<FunctionTypeVariable> functionTypeVariables) {
sink.writeEnum(DartTypeKind.anyType);
}
@override
Nullability get nullability => Nullability.none;
@override
DartType _withNullability(Nullability nullability) => this;
@ -494,15 +666,17 @@ class FunctionType extends DartType {
final List<FunctionTypeVariable> typeVariables;
FunctionType(
@override
final Nullability nullability;
FunctionType._(
this.returnType,
this.parameterTypes,
this.optionalParameterTypes,
this.namedParameters,
this.namedParameterTypes,
this.typeVariables,
Nullability nullability)
: super(nullability) {
this.nullability) {
assert(returnType != null, "Invalid return type in $this.");
assert(!parameterTypes.contains(null), "Invalid parameter types in $this.");
assert(!optionalParameterTypes.contains(null),
@ -514,8 +688,62 @@ class FunctionType extends DartType {
assert(!typeVariables.contains(null), "Invalid type variables in $this.");
}
factory FunctionType._readFromDataSource(
DataSource source, List<FunctionTypeVariable> functionTypeVariables) {
int typeVariableCount = source.readInt();
List<FunctionTypeVariable> typeVariables =
List<FunctionTypeVariable>.generate(typeVariableCount, (int index) {
Nullability nullability = source.readEnum(Nullability.values);
return FunctionTypeVariable._(index, nullability);
});
functionTypeVariables = List<FunctionTypeVariable>.of(functionTypeVariables)
..addAll(typeVariables);
for (int index = 0; index < typeVariableCount; index++) {
typeVariables[index].bound =
DartType.readFromDataSource(source, functionTypeVariables);
}
DartType returnType =
DartType.readFromDataSource(source, functionTypeVariables);
List<DartType> parameterTypes =
source._readDartTypes(functionTypeVariables);
List<DartType> optionalParameterTypes =
source._readDartTypes(functionTypeVariables);
List<DartType> namedParameterTypes =
source._readDartTypes(functionTypeVariables);
List<String> namedParameters = List<String>(namedParameterTypes.length);
for (int i = 0; i < namedParameters.length; i++) {
namedParameters[i] = source.readString();
}
Nullability nullability = source.readEnum(Nullability.values);
return FunctionType._(returnType, parameterTypes, optionalParameterTypes,
namedParameters, namedParameterTypes, typeVariables, nullability);
}
@override
DartType _withNullability(Nullability nullability) => FunctionType(
void writeToDataSink(
DataSink sink, List<FunctionTypeVariable> functionTypeVariables) {
sink.writeEnum(DartTypeKind.functionType);
functionTypeVariables = List<FunctionTypeVariable>.of(functionTypeVariables)
..addAll(typeVariables);
sink.writeInt(typeVariables.length);
for (FunctionTypeVariable variable in typeVariables) {
sink.writeEnum(variable.nullability);
}
for (FunctionTypeVariable variable in typeVariables) {
variable.bound.writeToDataSink(sink, functionTypeVariables);
}
returnType.writeToDataSink(sink, functionTypeVariables);
sink._writeDartTypes(parameterTypes, functionTypeVariables);
sink._writeDartTypes(optionalParameterTypes, functionTypeVariables);
sink._writeDartTypes(namedParameterTypes, functionTypeVariables);
for (String namedParameter in namedParameters) {
sink.writeString(namedParameter);
}
sink.writeEnum(nullability);
}
@override
DartType _withNullability(Nullability nullability) => FunctionType._(
returnType,
parameterTypes,
optionalParameterTypes,
@ -542,10 +770,6 @@ class FunctionType extends DartType {
namedParameterTypes.forEach((type) => type.forEachTypeVariable(f));
}
FunctionType instantiate(List<DartType> arguments) {
return subst(arguments, typeVariables);
}
@override
R accept<R, A>(DartTypeVisitor<R, A> visitor, A argument) =>
visitor.visitFunctionType(this, argument);
@ -612,12 +836,30 @@ class FunctionType extends DartType {
class FutureOrType extends DartType {
final DartType typeArgument;
const FutureOrType(this.typeArgument, Nullability nullability)
: super(nullability);
@override
final Nullability nullability;
const FutureOrType._(this.typeArgument, this.nullability);
factory FutureOrType._readFromDataSource(
DataSource source, List<FunctionTypeVariable> functionTypeVariables) {
DartType typeArgument =
DartType.readFromDataSource(source, functionTypeVariables);
Nullability nullability = source.readEnum(Nullability.values);
return FutureOrType._(typeArgument, nullability);
}
@override
void writeToDataSink(
DataSink sink, List<FunctionTypeVariable> functionTypeVariables) {
sink.writeEnum(DartTypeKind.futureOr);
typeArgument.writeToDataSink(sink, functionTypeVariables);
sink.writeEnum(nullability);
}
@override
DartType _withNullability(Nullability nullability) =>
FutureOrType(typeArgument, nullability);
FutureOrType._(typeArgument, nullability);
@override
bool get containsTypeVariables => typeArgument.containsTypeVariables;
@ -741,6 +983,8 @@ abstract class BaseDartTypeVisitor<R, A> extends DartTypeVisitor<R, A> {
abstract class DartTypeSubstitutionVisitor<A>
extends DartTypeVisitor<DartType, A> {
DartTypes get dartTypes;
// The input type is a DAG and we must preserve the sharing.
Map<DartType, DartType> _map = Map.identity();
@ -813,16 +1057,30 @@ abstract class DartTypeSubstitutionVisitor<A>
return _mapped(type, type);
}
List<FunctionTypeVariable> normalizableVariables = [];
for (int i = 0; i < newTypeVariables.length; i++) {
FunctionTypeVariable t = newTypeVariables[i];
if (identical(t, type.typeVariables[i])) continue;
DartType bound = t.bound;
if (bound.nullability.isNone && bound is NeverType) {
normalizableVariables.add(t);
}
}
return _mapped(
type,
FunctionType(
newReturnType,
newParameterTypes,
newOptionalParameterTypes,
type.namedParameters,
newNamedParameterTypes,
newTypeVariables,
type.nullability));
dartTypes.subst(
List<DartType>.filled(normalizableVariables.length,
dartTypes.neverType(Nullability.none)),
normalizableVariables,
dartTypes.functionType(
newReturnType,
newParameterTypes,
newOptionalParameterTypes,
type.namedParameters,
newNamedParameterTypes,
newTypeVariables,
type.nullability)));
}
List<FunctionTypeVariable> _handleFunctionTypeVariables(
@ -870,8 +1128,8 @@ abstract class DartTypeSubstitutionVisitor<A>
changed = true;
undecided[i] = null;
newVariables ??= variables.toList();
FunctionTypeVariable newVariable =
FunctionTypeVariable(variable.index, variable.nullability);
FunctionTypeVariable newVariable = dartTypes.functionTypeVariable(
variable.index, variable.nullability);
newVariables[i] = newVariable;
_mapped(variable, newVariable);
}
@ -906,7 +1164,9 @@ abstract class DartTypeSubstitutionVisitor<A>
return _mapped(type, type);
}
return _mapped(
type, InterfaceType(type.element, newTypeArguments, type.nullability));
type,
dartTypes.interfaceType(
type.element, newTypeArguments, type.nullability));
}
@override
@ -928,7 +1188,8 @@ abstract class DartTypeSubstitutionVisitor<A>
if (identical(type.typeArgument, newTypeArgument)) {
return _mapped(type, type);
}
return _mapped(type, FutureOrType(newTypeArgument, type.nullability));
return _mapped(
type, dartTypes.futureOrType(newTypeArgument, type.nullability));
}
List<DartType> _substTypes(List<DartType> types, A argument) {
@ -1080,10 +1341,13 @@ class _ContainsFreeTypeVariablesVisitor
class SimpleDartTypeSubstitutionVisitor
extends DartTypeSubstitutionVisitor<Null> {
@override
final DartTypes dartTypes;
final List<DartType> arguments;
final List<DartType> parameters;
SimpleDartTypeSubstitutionVisitor(this.arguments, this.parameters);
SimpleDartTypeSubstitutionVisitor(
this.dartTypes, this.arguments, this.parameters);
DartType substitute(DartType input) => visit(input, null);
@ -1346,6 +1610,126 @@ abstract class DartTypes {
bool get useNullSafety;
bool get useLegacySubtyping;
DartType interfaceType(ClassEntity element, List<DartType> typeArguments,
Nullability nullability) =>
_normalizeNullability(
InterfaceType._(element, typeArguments, Nullability.none),
nullability);
// Since all [TypeVariableType] bounds come from the CFE, we assume that no
// bound will ever be `Never` (or else the CFE would have already normalized
// the type variable to `Never`). Therefore, we can skip normalization.
TypeVariableType typeVariableType(
TypeVariableEntity element, Nullability nullability) =>
TypeVariableType._(element, nullability);
// We normalize when we substitute function types.
DartType functionTypeVariable(int index, Nullability nullability) =>
FunctionTypeVariable._(index, nullability);
DartType neverType(Nullability nullability) => nullability.isQuestion
? commonElements.nullType
: NeverType._(nullability);
VoidType voidType() => const VoidType._();
DynamicType dynamicType() => const DynamicType._();
ErasedType erasedType() => const ErasedType._();
AnyType anyType() => const AnyType._();
FunctionType functionType(
DartType returnType,
List<DartType> parameterTypes,
List<DartType> optionalParameterTypes,
List<String> namedParameters,
List<DartType> namedParameterTypes,
List<FunctionTypeVariable> typeVariables,
Nullability nullability) =>
FunctionType._(returnType, parameterTypes, optionalParameterTypes,
namedParameters, namedParameterTypes, typeVariables, nullability);
DartType futureOrType(DartType typeArgument, Nullability nullability) {
DartType result;
if (isTopType(typeArgument) || typeArgument.isObject) {
result = typeArgument;
} else if (typeArgument is NeverType) {
result = commonElements.futureType(
Nullability.none, neverType(Nullability.none));
} else if (typeArgument.isNull) {
result = commonElements.futureType(
useNullSafety ? Nullability.question : Nullability.none,
commonElements.nullType);
} else {
result = FutureOrType._(typeArgument, nullability);
}
return _normalizeNullability(result, nullability);
}
DartType _normalizeNullability(DartType t, Nullability nullability) {
switch (nullability) {
case Nullability.question:
return _normalizeQuestionOf(t);
case Nullability.star:
return _normalizeStarOf(t);
default:
return t;
}
}
DartType _normalizeQuestionOf(DartType t) {
bool _isNullable(DartType t) =>
// Note that we can assume NNBD is enabled here.
t.isNull ||
t.nullability.isQuestion ||
_isStrongTopType(t) ||
t is FutureOrType && _isNullable(t.typeArgument);
DartType result;
if (t.isNull || t.nullability.isQuestion || _isStrongTopType(t)) {
result = t;
} else if (t is NeverType) {
result = commonElements.nullType;
} else if (t is FutureOrType && _isNullable(t.typeArgument)) {
result = t.nullability.isStar ? t._toNonNullable : t;
} else {
result = t._toNullable;
}
return result;
}
DartType _normalizeStarOf(DartType t) {
DartType result;
if (t.isNull || t.nullability.isPotentiallyNull || isTopType(t)) {
result = t;
} else {
result = t._toLegacy;
}
return result;
}
/// Performs the substitution `[arguments[i]/parameters[i]]t`.
///
/// The notation is known from this lambda calculus rule:
///
/// (lambda x.e0)e1 -> [e1/x]e0.
///
/// See [TypeVariableType] for a motivation for this method.
///
/// Invariant: There must be the same number of [arguments] and [parameters].
DartType subst(
List<DartType> arguments, List<DartType> parameters, DartType t) {
assert(arguments.length == parameters.length);
if (parameters.isEmpty) return t;
return SimpleDartTypeSubstitutionVisitor(this, arguments, parameters)
.substitute(t);
}
DartType instantiate(FunctionType t, List<DartType> arguments) {
return subst(arguments, t.typeVariables, t);
}
// TODO(fishythefish): Clean up all uses of [defaultNullability].
Nullability get defaultNullability =>
useNullSafety ? Nullability.star : Nullability.none;
@ -1442,21 +1826,23 @@ abstract class DartTypes {
return _isSubtype(s.typeArgument, t, env);
}
if (s.nullability.isStar) {
return _isSubtype(s._withoutNullability(), t, env);
return _isSubtype(s._toNonNullable, t, env);
}
return !s.nullability.isQuestion;
}
// Left Legacy:
if (s.nullability.isStar) {
return _isSubtype(s._withoutNullability(), t, env);
return _isSubtype(s._toNonNullable, t, env);
}
// Right Legacy:
if (t.nullability.isStar) {
// Note that to convert `T*` to `T?`, we can't just say `t._toNullable`.
// The resulting type `T?` may be normalizable (e.g. if `T` is `Never`).
return _isSubtype(
s,
useLegacySubtyping ? t._withoutNullability() : t._withQuestion(),
useLegacySubtyping ? t._toNonNullable : _normalizeQuestionOf(t),
env);
}
@ -1464,14 +1850,17 @@ abstract class DartTypes {
if (s is FutureOrType && s.nullability.isNone) {
DartType typeArgument = s.typeArgument;
return _isSubtype(typeArgument, t, env) &&
_isSubtype(commonElements.futureType(typeArgument), t, env);
_isSubtype(
commonElements.futureType(Nullability.none, typeArgument),
t,
env);
}
// Left Nullable:
if (s.nullability.isQuestion) {
return (useLegacySubtyping ||
_isSubtype(commonElements.nullType, t, env)) &&
_isSubtype(s._withoutNullability(), t, env);
_isSubtype(s._toNonNullable, t, env);
}
// Type Variable Reflexivity 1 is subsumed by Reflexivity and therefore
@ -1485,14 +1874,15 @@ abstract class DartTypes {
if (t is FutureOrType && t.nullability.isNone) {
DartType typeArgument = t.typeArgument;
return _isSubtype(s, typeArgument, env) ||
_isSubtype(s, commonElements.futureType(typeArgument), env);
_isSubtype(s,
commonElements.futureType(Nullability.none, typeArgument), env);
}
// Right Nullable:
if (t.nullability.isQuestion) {
return (!useLegacySubtyping &&
_isSubtype(s, commonElements.nullType, env)) ||
_isSubtype(s, t._withoutNullability(), env);
_isSubtype(s, t._toNonNullable, env);
}
// Left Promoted Variable does not apply because we do not represent

View file

@ -48,6 +48,8 @@ class KernelTypeGraphBuilder extends ir.Visitor<TypeInformation> {
final GlobalTypeInferenceElementData _memberData;
final bool _inGenerativeConstructor;
DartTypes get _dartTypes => _closedWorld.dartTypes;
LocalState _stateInternal;
LocalState _stateAfterWhenTrueInternal;
LocalState _stateAfterWhenFalseInternal;
@ -1705,7 +1707,7 @@ class KernelTypeGraphBuilder extends ir.Visitor<TypeInformation> {
TypeInformation mask;
DartType type = node.guard != null
? _elementMap.getDartType(node.guard)
: DynamicType();
: _dartTypes.dynamicType();
if (type is InterfaceType) {
InterfaceType interfaceType = type;
mask = _types.nonNullSubtype(interfaceType.element);
@ -1713,8 +1715,8 @@ class KernelTypeGraphBuilder extends ir.Visitor<TypeInformation> {
mask = _types.dynamicType;
}
Local local = _localsMap.getLocalVariable(exception);
_state.updateLocal(
_inferrer, _capturedAndBoxed, local, mask, node, DynamicType(),
_state.updateLocal(_inferrer, _capturedAndBoxed, local, mask, node,
_dartTypes.dynamicType(),
isNullable: false /* `throw null` produces a NullThrownError */);
}
ir.VariableDeclaration stackTrace = node.stackTrace;
@ -1724,7 +1726,7 @@ class KernelTypeGraphBuilder extends ir.Visitor<TypeInformation> {
// Note: stack trace may be null if users omit a stack in
// `completer.completeError`.
_state.updateLocal(_inferrer, _capturedAndBoxed, local,
_types.dynamicType, node, DynamicType());
_types.dynamicType, node, _dartTypes.dynamicType());
}
visit(node.body);
return null;

View file

@ -43,9 +43,9 @@ abstract class IrToElementMap {
FunctionType getFunctionType(ir.FunctionNode node);
/// Return the [InterfaceType] corresponding to the [cls] with the given
/// [typeArguments].
/// [typeArguments] and [nullability].
InterfaceType createInterfaceType(
ir.Class cls, List<ir.DartType> typeArguments);
ir.Class cls, List<ir.DartType> typeArguments, Nullability nullability);
/// Returns the [CallStructure] corresponding to the [arguments].
CallStructure getCallStructure(ir.Arguments arguments);

View file

@ -68,9 +68,8 @@ class KernelDartTypes extends DartTypes {
for (int index = 0; index < typeArguments.length; index++) {
DartType typeArgument = typeArguments[index];
TypeVariableType typeVariable = typeVariables[index];
DartType bound = elementMap
.getTypeVariableBound(typeVariable.element)
.subst(typeArguments, typeVariables);
DartType bound = subst(typeArguments, typeVariables,
elementMap.getTypeVariableBound(typeVariable.element));
checkTypeVariableBound(context, typeArgument, typeVariable, bound);
}
}

View file

@ -65,7 +65,7 @@ class DartTypeConverter extends ir.DartTypeVisitor<DartType> {
InterfaceType visitSupertype(ir.Supertype node) {
ClassEntity cls = elementMap.getClass(node.classNode);
return new InterfaceType(
return _dartTypes.interfaceType(
cls, visitTypes(node.typeArguments), _dartTypes.defaultNullability);
}
@ -84,9 +84,12 @@ class DartTypeConverter extends ir.DartTypeVisitor<DartType> {
if (node.parameter.parent is ir.Typedef) {
// Typedefs are only used in type literals so we never need their type
// variables.
return DynamicType();
return _dartTypes.dynamicType();
}
return new TypeVariableType(elementMap.getTypeVariable(node.parameter),
// We assume the incoming type is already normalized, so the bound is not
// `Never`. Attempting to check the bound here will overflow the stack.
return _dartTypes.typeVariableType(
elementMap.getTypeVariable(node.parameter),
_dartTypes.defaultNullability);
}
@ -96,7 +99,7 @@ class DartTypeConverter extends ir.DartTypeVisitor<DartType> {
List<FunctionTypeVariable> typeVariables;
for (ir.TypeParameter typeParameter in node.typeParameters) {
FunctionTypeVariable typeVariable =
new FunctionTypeVariable(index, _dartTypes.defaultNullability);
_dartTypes.functionTypeVariable(index, _dartTypes.defaultNullability);
currentFunctionTypeParameters[typeParameter] = typeVariable;
typeVariables ??= <FunctionTypeVariable>[];
typeVariables.add(typeVariable);
@ -109,7 +112,7 @@ class DartTypeConverter extends ir.DartTypeVisitor<DartType> {
}
}
FunctionType type = new FunctionType(
FunctionType type = _dartTypes.functionType(
visitType(node.returnType),
visitTypes(node.positionalParameters
.take(node.requiredParameterCount)
@ -132,28 +135,28 @@ class DartTypeConverter extends ir.DartTypeVisitor<DartType> {
ClassEntity cls = elementMap.getClass(node.classNode);
if (cls.name == 'FutureOr' &&
cls.library == elementMap.commonElements.asyncLibrary) {
return new FutureOrType(
return _dartTypes.futureOrType(
visitTypes(node.typeArguments).single, _dartTypes.defaultNullability);
}
return new InterfaceType(
return _dartTypes.interfaceType(
cls, visitTypes(node.typeArguments), _dartTypes.defaultNullability);
}
@override
DartType visitVoidType(ir.VoidType node) {
return VoidType();
return _dartTypes.voidType();
}
@override
DartType visitDynamicType(ir.DynamicType node) {
return DynamicType();
return _dartTypes.dynamicType();
}
@override
DartType visitInvalidType(ir.InvalidType node) {
// Root uses such a `o is Unresolved` and `o as Unresolved` must be special
// cased in the builder, nested invalid types are treated as `dynamic`.
return DynamicType();
return _dartTypes.dynamicType();
}
@override
@ -205,8 +208,8 @@ class ConstantValuefier extends ir.ComputeOnceConstantVisitor<ConstantValue> {
@override
ConstantValue visitInstanceConstant(ir.InstanceConstant node) {
InterfaceType type =
elementMap.createInterfaceType(node.classNode, node.typeArguments);
InterfaceType type = elementMap.createInterfaceType(
node.classNode, node.typeArguments, Nullability.none);
Map<FieldEntity, ConstantValue> fields = {};
node.fieldValues.forEach((ir.Reference reference, ir.Constant value) {
FieldEntity field = elementMap.getField(reference.asField);
@ -222,7 +225,7 @@ class ConstantValuefier extends ir.ComputeOnceConstantVisitor<ConstantValue> {
elements.add(visitConstant(element));
}
DartType type = elementMap.commonElements
.listType(elementMap.getDartType(node.typeArgument));
.listType(Nullability.none, elementMap.getDartType(node.typeArgument));
return constant_system.createList(
elementMap.commonElements, type, elements);
}
@ -234,7 +237,7 @@ class ConstantValuefier extends ir.ComputeOnceConstantVisitor<ConstantValue> {
elements.add(visitConstant(element));
}
DartType type = elementMap.commonElements
.setType(elementMap.getDartType(node.typeArgument));
.setType(Nullability.none, elementMap.getDartType(node.typeArgument));
return constant_system.createSet(elementMap.commonElements, type, elements);
}
@ -247,6 +250,7 @@ class ConstantValuefier extends ir.ComputeOnceConstantVisitor<ConstantValue> {
values.add(visitConstant(element.value));
}
DartType type = elementMap.commonElements.mapType(
Nullability.none,
elementMap.getDartType(node.keyType),
elementMap.getDartType(node.valueType));
return constant_system.createMap(

View file

@ -447,8 +447,8 @@ class ConstantEmitter extends ModularConstantEmitter {
_constantReferenceGenerator(constant.function)
];
if (_options.useNewRti) {
fields.add(_reifiedTypeNewRti(InterfaceType(cls, constant.typeArguments,
_commonElements.dartTypes.defaultNullability)));
fields.add(_reifiedTypeNewRti(_commonElements.dartTypes
.interfaceType(cls, constant.typeArguments, Nullability.none)));
} else {
fields.add(_reifiedTypeArguments(constant, constant.typeArguments));
}

View file

@ -44,10 +44,10 @@ FunctionType buildJsFunctionType(DartTypes dartTypes) {
// TODO(jacobr): consider using codegenWorldBuilder.isChecks to determine the
// range of positional arguments that need to be supported by JavaScript
// function types.
return new FunctionType(
DynamicType(),
return dartTypes.functionType(
dartTypes.dynamicType(),
const <DartType>[],
new List<DartType>.filled(16, DynamicType()),
new List<DartType>.filled(16, dartTypes.dynamicType()),
const <String>[],
const <DartType>[],
const <FunctionTypeVariable>[],

View file

@ -570,7 +570,8 @@ class TypeVariableTests {
void addImplicitCheck(DartType type) {
if (implicitIsChecks.add(type)) {
if (type is FutureOrType) {
addImplicitCheck(commonElements.futureType(type.typeArgument));
addImplicitCheck(
commonElements.futureType(Nullability.none, type.typeArgument));
addImplicitCheck(type.typeArgument);
}
}
@ -582,7 +583,8 @@ class TypeVariableTests {
world.isChecks.forEach((DartType type) {
if (type is FutureOrType) {
addImplicitCheck(commonElements.futureType(type.typeArgument));
addImplicitCheck(
commonElements.futureType(Nullability.none, type.typeArgument));
addImplicitCheck(type.typeArgument);
}
});

View file

@ -55,6 +55,7 @@ class ParameterStubGenerator {
this._closedWorld,
this._sourceInformationStrategy);
DartTypes get _dartTypes => _closedWorld.dartTypes;
JElementEnvironment get _elementEnvironment =>
_closedWorld.elementEnvironment;
@ -249,8 +250,8 @@ class ParameterStubGenerator {
Set<TypeVariableType> variables = Set();
type.forEachTypeVariable(variables.add);
assert(variables.isNotEmpty);
return type.subst(
List.filled(variables.length, AnyType()), variables.toList());
return _dartTypes.subst(List.filled(variables.length, _dartTypes.anyType()),
variables.toList(), type);
}
// We fill the lists depending on possible/invoked selectors. For example,

View file

@ -108,6 +108,7 @@ class ProgramBuilder {
final Set<TypeVariableType> _lateNamedTypeVariablesNewRti = {};
ClassHierarchy get _classHierarchy => _closedWorld.classHierarchy;
DartTypes get _dartTypes => _closedWorld.dartTypes;
ProgramBuilder(
this._options,
@ -1009,9 +1010,11 @@ class ProgramBuilder {
if (!_rtiNeed.classNeedsTypeArguments(enclosingClass)) {
// Erase type arguments.
List<DartType> typeArguments = enclosingType.typeArguments;
type = type.subst(
List<DartType>.filled(typeArguments.length, ErasedType()),
typeArguments);
type = _dartTypes.subst(
List<DartType>.filled(
typeArguments.length, _dartTypes.erasedType()),
typeArguments,
type);
}
}

View file

@ -47,9 +47,9 @@ abstract class JsToElementMap {
FunctionType getFunctionType(ir.FunctionNode node);
/// Return the [InterfaceType] corresponding to the [cls] with the given
/// [typeArguments].
/// [typeArguments] and [nullability].
InterfaceType createInterfaceType(
ir.Class cls, List<ir.DartType> typeArguments);
ir.Class cls, List<ir.DartType> typeArguments, Nullability nullability);
/// Returns the [CallStructure] corresponding to the [arguments].
CallStructure getCallStructure(ir.Arguments arguments);

View file

@ -618,9 +618,9 @@ class JsKernelToElementMap implements JsToElementMap, IrToElementMap {
@override
InterfaceType createInterfaceType(
ir.Class cls, List<ir.DartType> typeArguments) {
return new InterfaceType(
getClass(cls), getDartTypes(typeArguments), types.defaultNullability);
ir.Class cls, List<ir.DartType> typeArguments, Nullability nullability) {
return types.interfaceType(
getClass(cls), getDartTypes(typeArguments), nullability);
}
@override
@ -642,22 +642,22 @@ class JsKernelToElementMap implements JsToElementMap, IrToElementMap {
if (data is JClassDataImpl && data.thisType == null) {
ir.Class node = data.cls;
if (node.typeParameters.isEmpty) {
data.thisType = data.rawType = new InterfaceType(
data.thisType = data.rawType = types.interfaceType(
cls, const <DartType>[], types.defaultNullability);
} else {
data.thisType = new InterfaceType(
data.thisType = types.interfaceType(
cls,
new List<DartType>.generate(node.typeParameters.length,
(int index) {
return new TypeVariableType(
return types.typeVariableType(
getTypeVariableInternal(node.typeParameters[index]),
types.defaultNullability);
}),
types.defaultNullability);
data.rawType = new InterfaceType(
data.rawType = types.interfaceType(
cls,
new List<DartType>.filled(
node.typeParameters.length, DynamicType()),
node.typeParameters.length, types.dynamicType()),
types.defaultNullability);
}
}
@ -671,9 +671,9 @@ class JsKernelToElementMap implements JsToElementMap, IrToElementMap {
_ensureThisAndRawType(cls, data);
data.jsInteropType = data.thisType;
} else {
data.jsInteropType = InterfaceType(
data.jsInteropType = types.interfaceType(
cls,
List<DartType>.filled(node.typeParameters.length, AnyType()),
List<DartType>.filled(node.typeParameters.length, types.anyType()),
types.defaultNullability);
}
}
@ -868,7 +868,7 @@ class JsKernelToElementMap implements JsToElementMap, IrToElementMap {
if (node.parent is ir.Constructor) {
// The return type on generative constructors is `void`, but we need
// `dynamic` type to match the element model.
returnType = DynamicType();
returnType = types.dynamicType();
} else {
returnType = getDartType(node.returnType);
}
@ -908,10 +908,10 @@ class JsKernelToElementMap implements JsToElementMap, IrToElementMap {
typeVariables = new List<FunctionTypeVariable>.generate(
node.typeParameters.length,
(int index) =>
new FunctionTypeVariable(index, types.defaultNullability));
types.functionTypeVariable(index, types.defaultNullability));
DartType subst(DartType type) {
return type.subst(typeVariables, typeParameters);
return types.subst(typeVariables, typeParameters, type);
}
returnType = subst(returnType);
@ -926,7 +926,7 @@ class JsKernelToElementMap implements JsToElementMap, IrToElementMap {
typeVariables = const <FunctionTypeVariable>[];
}
return new FunctionType(
return types.functionType(
returnType,
parameterTypes,
optionalParameterTypes,
@ -938,8 +938,8 @@ class JsKernelToElementMap implements JsToElementMap, IrToElementMap {
@override
DartType substByContext(DartType type, InterfaceType context) {
return type.subst(
context.typeArguments, getThisType(context.element).typeArguments);
return types.subst(context.typeArguments,
getThisType(context.element).typeArguments, type);
}
/// Returns the type of the `call` method on 'type'.
@ -1756,7 +1756,7 @@ class JsKernelToElementMap implements JsToElementMap, IrToElementMap {
Map<String, IndexedMember> memberMap = <String, IndexedMember>{};
JRecord container = new JRecord(member.library, box.name);
BoxLocal boxLocal = new BoxLocal(container);
InterfaceType thisType = new InterfaceType(
InterfaceType thisType = types.interfaceType(
container, const <DartType>[], types.defaultNullability);
InterfaceType supertype = commonElements.objectType;
JClassData containerData = new RecordClassData(
@ -1820,7 +1820,7 @@ class JsKernelToElementMap implements JsToElementMap, IrToElementMap {
JClass classEntity = new JClosureClass(enclosingLibrary, name);
// Create a classData and set up the interfaces and subclass
// relationships that _ensureSupertypes and _ensureThisAndRawType are doing
InterfaceType thisType = new InterfaceType(
InterfaceType thisType = types.interfaceType(
classEntity, const <DartType>[], types.defaultNullability);
ClosureClassData closureData = new ClosureClassData(
new ClosureClassDefinition(location),
@ -2152,7 +2152,7 @@ class JsElementEnvironment extends ElementEnvironment
JsElementEnvironment(this.elementMap);
@override
DartType get dynamicType => DynamicType();
DartType get dynamicType => elementMap.types.dynamicType();
@override
LibraryEntity get mainLibrary => elementMap._mainLibrary;
@ -2233,9 +2233,8 @@ class JsElementEnvironment extends ElementEnvironment
@override
InterfaceType createInterfaceType(
ClassEntity cls, List<DartType> typeArguments) {
return new InterfaceType(
cls, typeArguments, elementMap.types.defaultNullability);
ClassEntity cls, List<DartType> typeArguments, Nullability nullability) {
return elementMap.types.interfaceType(cls, typeArguments, nullability);
}
@override

View file

@ -54,6 +54,7 @@ class JsClosedWorldBuilder {
ElementEnvironment get _elementEnvironment => _elementMap.elementEnvironment;
CommonElements get _commonElements => _elementMap.commonElements;
DartTypes get _dartTypes => _elementMap.types;
JsClosedWorld convertClosedWorld(
KClosedWorld closedWorld,
@ -427,7 +428,7 @@ class JsClosedWorldBuilder {
boxedVariables,
info,
localsMap,
new InterfaceType(
_dartTypes.interfaceType(
superclass, const [], _elementMap.types.defaultNullability),
createSignatureMethod: createSignatureMethod);
@ -678,7 +679,8 @@ class JsToFrontendMapImpl extends JsToFrontendMap {
DartType toBackendType(DartType type, {bool allowFreeVariables: false}) =>
type == null
? null
: new _TypeConverter(allowFreeVariables: allowFreeVariables)
: new _TypeConverter(_backend.types,
allowFreeVariables: allowFreeVariables)
.visit(type, toBackendEntity);
Entity toBackendEntity(Entity entity) {
@ -733,12 +735,13 @@ class JsToFrontendMapImpl extends JsToFrontendMap {
typedef Entity _EntityConverter(Entity cls);
class _TypeConverter implements DartTypeVisitor<DartType, _EntityConverter> {
final DartTypes _dartTypes;
final bool allowFreeVariables;
Map<FunctionTypeVariable, FunctionTypeVariable> _functionTypeVariables =
<FunctionTypeVariable, FunctionTypeVariable>{};
_TypeConverter({this.allowFreeVariables: false});
_TypeConverter(this._dartTypes, {this.allowFreeVariables: false});
List<DartType> convertTypes(
List<DartType> types, _EntityConverter converter) =>
@ -759,39 +762,39 @@ class _TypeConverter implements DartTypeVisitor<DartType, _EntityConverter> {
@override
DartType visitNeverType(NeverType type, _EntityConverter converter) =>
NeverType(type.nullability);
_dartTypes.neverType(type.nullability);
@override
DartType visitDynamicType(DynamicType type, _EntityConverter converter) {
return DynamicType();
}
DartType visitDynamicType(DynamicType type, _EntityConverter converter) =>
_dartTypes.dynamicType();
@override
DartType visitErasedType(ErasedType type, _EntityConverter converter) =>
ErasedType();
_dartTypes.erasedType();
@override
DartType visitAnyType(AnyType type, _EntityConverter converter) => AnyType();
DartType visitAnyType(AnyType type, _EntityConverter converter) =>
_dartTypes.anyType();
@override
DartType visitInterfaceType(InterfaceType type, _EntityConverter converter) {
return new InterfaceType(converter(type.element),
return _dartTypes.interfaceType(converter(type.element),
visitList(type.typeArguments, converter), type.nullability);
}
@override
DartType visitTypeVariableType(
TypeVariableType type, _EntityConverter converter) {
return new TypeVariableType(converter(type.element), type.nullability);
return _dartTypes.typeVariableType(
converter(type.element), type.nullability);
}
@override
DartType visitFunctionType(FunctionType type, _EntityConverter converter) {
List<FunctionTypeVariable> typeVariables = <FunctionTypeVariable>[];
for (FunctionTypeVariable typeVariable in type.typeVariables) {
typeVariables.add(_functionTypeVariables[typeVariable] =
new FunctionTypeVariable(
typeVariable.index, typeVariable.nullability));
typeVariables.add(_functionTypeVariables[typeVariable] = _dartTypes
.functionTypeVariable(typeVariable.index, typeVariable.nullability));
}
for (FunctionTypeVariable typeVariable in type.typeVariables) {
_functionTypeVariables[typeVariable].bound = typeVariable.bound != null
@ -807,7 +810,7 @@ class _TypeConverter implements DartTypeVisitor<DartType, _EntityConverter> {
for (FunctionTypeVariable typeVariable in type.typeVariables) {
_functionTypeVariables.remove(typeVariable);
}
return new FunctionType(
return _dartTypes.functionType(
returnType,
parameterTypes,
optionalParameterTypes,
@ -830,15 +833,13 @@ class _TypeConverter implements DartTypeVisitor<DartType, _EntityConverter> {
}
@override
DartType visitVoidType(VoidType type, _EntityConverter converter) {
return VoidType();
}
DartType visitVoidType(VoidType type, _EntityConverter converter) =>
_dartTypes.voidType();
@override
DartType visitFutureOrType(FutureOrType type, _EntityConverter converter) {
return new FutureOrType(
visit(type.typeArgument, converter), type.nullability);
}
DartType visitFutureOrType(FutureOrType type, _EntityConverter converter) =>
_dartTypes.futureOrType(
visit(type.typeArgument, converter), type.nullability);
}
class _ConstantConverter implements ConstantValueVisitor<ConstantValue, Null> {
@ -847,7 +848,7 @@ class _ConstantConverter implements ConstantValueVisitor<ConstantValue, Null> {
final _TypeConverter typeConverter;
_ConstantConverter(this._dartTypes, this.toBackendEntity)
: typeConverter = new _TypeConverter();
: typeConverter = new _TypeConverter(_dartTypes);
@override
ConstantValue visitNull(NullConstantValue constant, _) => constant;

View file

@ -319,6 +319,10 @@ class FullTypeEnvironmentRecipe extends TypeEnvironmentRecipe {
}
class TypeRecipeDomainImpl implements TypeRecipeDomain {
final DartTypes _dartTypes;
const TypeRecipeDomainImpl(this._dartTypes);
@override
bool isIdentity(TypeRecipe recipe, TypeEnvironmentStructure structure) {
if (structure is SingletonTypeEnvironmentStructure &&
@ -350,7 +354,7 @@ class TypeRecipeDomainImpl implements TypeRecipeDomain {
if (environmentRecipe is TypeExpressionRecipe) {
List<TypeVariableType> variables = [environmentStructure.variable];
List<DartType> replacements = [environmentRecipe.type];
return _Substitution(null, null, variables, replacements)
return _Substitution(_dartTypes, null, null, variables, replacements)
.substituteRecipe(recipe);
}
failedAt(CURRENT_ELEMENT_SPANNABLE,
@ -362,7 +366,7 @@ class TypeRecipeDomainImpl implements TypeRecipeDomain {
if (environmentStructure.classType != null) {
if (environmentRecipe is TypeExpressionRecipe) {
assert(environmentStructure.bindings.isEmpty);
return _Substitution(environmentStructure.classType,
return _Substitution(_dartTypes, environmentStructure.classType,
environmentRecipe.type, null, null)
.substituteRecipe(recipe);
}
@ -374,6 +378,7 @@ class TypeRecipeDomainImpl implements TypeRecipeDomain {
}
if (environmentRecipe is FullTypeEnvironmentRecipe) {
return _Substitution(
_dartTypes,
environmentStructure.classType,
environmentRecipe.classType,
environmentStructure.bindings,
@ -411,7 +416,7 @@ class TypeRecipeDomainImpl implements TypeRecipeDomain {
List<TypeVariableType> replacedVariables = bindings.sublist(index);
List<TypeVariableType> remainingVariables = bindings.sublist(0, index);
TypeRecipe newRecipe =
_Substitution(null, null, replacedVariables, replacements)
_Substitution(_dartTypes, null, null, replacedVariables, replacements)
.substituteRecipe(recipe);
if (newRecipe == null) return null;
TypeEnvironmentStructure newEnvironmentStructure =
@ -436,8 +441,11 @@ class TypeRecipeDomainImpl implements TypeRecipeDomain {
if (environmentStructure2 is SingletonTypeEnvironmentStructure &&
recipe1 is TypeExpressionRecipe) {
TypeRecipe newRecipe = _Substitution(
null, null, [environmentStructure2.variable], [recipe1.type])
.substituteRecipe(recipe2);
_dartTypes,
null,
null,
[environmentStructure2.variable],
[recipe1.type]).substituteRecipe(recipe2);
if (newRecipe == null) return null;
return TypeRecipeAndEnvironmentStructure(
newRecipe, environmentStructure1);
@ -446,7 +454,7 @@ class TypeRecipeDomainImpl implements TypeRecipeDomain {
if (environmentStructure2 is FullTypeEnvironmentStructure &&
recipe1 is TypeExpressionRecipe) {
assert(environmentStructure2.bindings.isEmpty);
TypeRecipe newRecipe = _Substitution(
TypeRecipe newRecipe = _Substitution(_dartTypes,
environmentStructure2.classType, recipe1.type, null, null)
.substituteRecipe(recipe2);
if (newRecipe == null) return null;
@ -456,8 +464,12 @@ class TypeRecipeDomainImpl implements TypeRecipeDomain {
if (environmentStructure2 is FullTypeEnvironmentStructure &&
recipe1 is FullTypeEnvironmentRecipe) {
TypeRecipe newRecipe = _Substitution(environmentStructure2.classType,
recipe1.classType, environmentStructure2.bindings, recipe1.types)
TypeRecipe newRecipe = _Substitution(
_dartTypes,
environmentStructure2.classType,
recipe1.classType,
environmentStructure2.bindings,
recipe1.types)
.substituteRecipe(recipe2);
if (newRecipe == null) return null;
return TypeRecipeAndEnvironmentStructure(
@ -479,6 +491,8 @@ class TypeRecipeDomainImpl implements TypeRecipeDomain {
/// A [_Substitution] contains the bindings and the state required to perform
/// a single substitution.
class _Substitution extends DartTypeSubstitutionVisitor<Null> {
@override
final DartTypes dartTypes;
final Map<DartType, DartType> _lookupCache = {};
final Map<DartType, int> _counts = {};
bool _failed = false;
@ -488,8 +502,8 @@ class _Substitution extends DartTypeSubstitutionVisitor<Null> {
final List<TypeVariableType> _variables;
final List<DartType> _replacements;
_Substitution(this._classEnvironment, this._classValue, this._variables,
this._replacements)
_Substitution(this.dartTypes, this._classEnvironment, this._classValue,
this._variables, this._replacements)
: assert(_variables?.length == _replacements?.length);
// Returns `null` if declined.

View file

@ -53,9 +53,9 @@ abstract class KernelToElementMap {
FunctionType getFunctionType(ir.FunctionNode node);
/// Return the [InterfaceType] corresponding to the [cls] with the given
/// [typeArguments].
/// [typeArguments] and [nullability].
InterfaceType createInterfaceType(
ir.Class cls, List<ir.DartType> typeArguments);
ir.Class cls, List<ir.DartType> typeArguments, Nullability nullability);
/// Returns the [CallStructure] corresponding to the [arguments].
CallStructure getCallStructure(ir.Arguments arguments);

View file

@ -239,9 +239,9 @@ class KernelToElementMapImpl implements KernelToElementMap, IrToElementMap {
@override
InterfaceType createInterfaceType(
ir.Class cls, List<ir.DartType> typeArguments) {
return new InterfaceType(
getClass(cls), getDartTypes(typeArguments), types.defaultNullability);
ir.Class cls, List<ir.DartType> typeArguments, Nullability nullability) {
return types.interfaceType(
getClass(cls), getDartTypes(typeArguments), nullability);
}
LibraryEntity getLibrary(ir.Library node) => getLibraryInternal(node);
@ -262,22 +262,22 @@ class KernelToElementMapImpl implements KernelToElementMap, IrToElementMap {
if (data is KClassDataImpl && data.thisType == null) {
ir.Class node = data.node;
if (node.typeParameters.isEmpty) {
data.thisType = data.rawType = new InterfaceType(
data.thisType = data.rawType = types.interfaceType(
cls, const <DartType>[], types.defaultNullability);
} else {
data.thisType = new InterfaceType(
data.thisType = types.interfaceType(
cls,
new List<DartType>.generate(node.typeParameters.length,
(int index) {
return new TypeVariableType(
return types.typeVariableType(
getTypeVariableInternal(node.typeParameters[index]),
types.defaultNullability);
}),
types.defaultNullability);
data.rawType = new InterfaceType(
data.rawType = types.interfaceType(
cls,
new List<DartType>.filled(
node.typeParameters.length, DynamicType()),
node.typeParameters.length, types.dynamicType()),
types.defaultNullability);
}
}
@ -291,9 +291,9 @@ class KernelToElementMapImpl implements KernelToElementMap, IrToElementMap {
_ensureThisAndRawType(cls, data);
data.jsInteropType = data.thisType;
} else {
data.jsInteropType = InterfaceType(
data.jsInteropType = types.interfaceType(
cls,
List<DartType>.filled(node.typeParameters.length, AnyType()),
List<DartType>.filled(node.typeParameters.length, types.anyType()),
types.defaultNullability);
}
}
@ -491,7 +491,7 @@ class KernelToElementMapImpl implements KernelToElementMap, IrToElementMap {
if (node.parent is ir.Constructor) {
// The return type on generative constructors is `void`, but we need
// `dynamic` type to match the element model.
returnType = DynamicType();
returnType = types.dynamicType();
} else {
returnType = getDartType(node.returnType);
}
@ -531,10 +531,10 @@ class KernelToElementMapImpl implements KernelToElementMap, IrToElementMap {
typeVariables = new List<FunctionTypeVariable>.generate(
node.typeParameters.length,
(int index) =>
new FunctionTypeVariable(index, types.defaultNullability));
types.functionTypeVariable(index, types.defaultNullability));
DartType subst(DartType type) {
return type.subst(typeVariables, typeParameters);
return types.subst(typeVariables, typeParameters, type);
}
returnType = subst(returnType);
@ -549,7 +549,7 @@ class KernelToElementMapImpl implements KernelToElementMap, IrToElementMap {
typeVariables = const <FunctionTypeVariable>[];
}
return new FunctionType(
return types.functionType(
returnType,
parameterTypes,
optionalParameterTypes,
@ -561,8 +561,8 @@ class KernelToElementMapImpl implements KernelToElementMap, IrToElementMap {
@override
DartType substByContext(DartType type, InterfaceType context) {
return type.subst(
context.typeArguments, getThisType(context.element).typeArguments);
return types.subst(context.typeArguments,
getThisType(context.element).typeArguments, type);
}
/// Returns the type of the `call` method on 'type'.
@ -1625,7 +1625,7 @@ class KernelElementEnvironment extends ElementEnvironment
KernelElementEnvironment(this.elementMap);
@override
DartType get dynamicType => DynamicType();
DartType get dynamicType => elementMap.types.dynamicType();
@override
LibraryEntity get mainLibrary => elementMap._mainLibrary;
@ -1688,9 +1688,8 @@ class KernelElementEnvironment extends ElementEnvironment
@override
InterfaceType createInterfaceType(
ClassEntity cls, List<DartType> typeArguments) {
return new InterfaceType(
cls, typeArguments, elementMap.types.defaultNullability);
ClassEntity cls, List<DartType> typeArguments, Nullability nullability) {
return elementMap.types.interfaceType(cls, typeArguments, nullability);
}
@override

View file

@ -285,7 +285,8 @@ abstract class KernelImpactRegistryMixin implements ImpactRegistry {
void registerListLiteral(ir.DartType elementType,
{bool isConst, bool isEmpty}) {
impactBuilder.registerListLiteral(new ListLiteralUse(
commonElements.listType(elementMap.getDartType(elementType)),
commonElements.listType(
Nullability.none, elementMap.getDartType(elementType)),
isConstant: isConst,
isEmpty: isEmpty));
}
@ -294,7 +295,8 @@ abstract class KernelImpactRegistryMixin implements ImpactRegistry {
void registerSetLiteral(ir.DartType elementType,
{bool isConst, bool isEmpty}) {
impactBuilder.registerSetLiteral(new SetLiteralUse(
commonElements.setType(elementMap.getDartType(elementType)),
commonElements.setType(
Nullability.none, elementMap.getDartType(elementType)),
isConstant: isConst,
isEmpty: isEmpty));
}
@ -303,7 +305,7 @@ abstract class KernelImpactRegistryMixin implements ImpactRegistry {
void registerMapLiteral(ir.DartType keyType, ir.DartType valueType,
{bool isConst, bool isEmpty}) {
impactBuilder.registerMapLiteral(new MapLiteralUse(
commonElements.mapType(
commonElements.mapType(Nullability.none,
elementMap.getDartType(keyType), elementMap.getDartType(valueType)),
isConstant: isConst,
isEmpty: isEmpty));
@ -350,7 +352,8 @@ abstract class KernelImpactRegistryMixin implements ImpactRegistry {
void registerConstInstantiation(ir.Class cls, List<ir.DartType> typeArguments,
ir.LibraryDependency import) {
ImportEntity deferredImport = elementMap.getImport(import);
InterfaceType type = elementMap.createInterfaceType(cls, typeArguments);
InterfaceType type =
elementMap.createInterfaceType(cls, typeArguments, Nullability.none);
impactBuilder
.registerTypeUse(new TypeUse.constInstantiation(type, deferredImport));
}

View file

@ -363,7 +363,7 @@ class NativeBehavior {
/// [nullType] define the types for `Object` and `Null`, respectively. The
/// latter is used for the type strings of the form '' and 'var'.
/// [validTags] can be used to restrict which tags are accepted.
static void processSpecString(
static void processSpecString(DartTypes dartTypes,
DiagnosticReporter reporter, Spannable spannable, String specString,
{Iterable<String> validTags,
void setSideEffects(SideEffects newEffects),
@ -397,7 +397,7 @@ class NativeBehavior {
/// * 'void' - in which case [onVoid] is called,
/// * '' or 'var' - in which case [onVar] is called,
/// * 'T1|...|Tn' - in which case [onType] is called for each resolved Ti.
void resolveTypesString(String typesString,
void resolveTypesString(DartTypes dartTypes, String typesString,
{onVoid(), onVar(), onType(type)}) {
// Various things that are not in fact types.
if (typesString == 'void') {
@ -413,13 +413,13 @@ class NativeBehavior {
return;
}
for (final typeString in typesString.split('|')) {
onType(_parseType(typeString.trim(), lookupType));
onType(_parseType(dartTypes, typeString.trim(), lookupType));
}
}
if (!specString.contains(';') && !specString.contains(':')) {
// Form (1), types or pseudo-types like 'void' and 'var'.
resolveTypesString(specString.trim(), onVar: () {
resolveTypesString(dartTypes, specString.trim(), onVar: () {
typesReturned.add(objectType);
typesReturned.add(nullType);
}, onType: (type) {
@ -478,7 +478,7 @@ class NativeBehavior {
String returns = values['returns'];
if (returns != null) {
resolveTypesString(returns, onVar: () {
resolveTypesString(dartTypes, returns, onVar: () {
typesReturned.add(objectType);
typesReturned.add(nullType);
}, onType: (type) {
@ -488,13 +488,13 @@ class NativeBehavior {
String creates = values['creates'];
if (creates != null) {
resolveTypesString(creates, onVoid: () {
resolveTypesString(dartTypes, creates, onVoid: () {
reportError("Invalid type string 'creates:$creates'");
}, onType: (type) {
typesInstantiated.add(type);
});
} else if (returns != null) {
resolveTypesString(returns, onType: (type) {
resolveTypesString(dartTypes, returns, onType: (type) {
typesInstantiated.add(type);
});
}
@ -634,7 +634,7 @@ class NativeBehavior {
behavior.useGvn = useGvn;
}
processSpecString(reporter, spannable, specString,
processSpecString(commonElements.dartTypes, reporter, spannable, specString,
setSideEffects: setSideEffects,
setThrows: setThrows,
setIsAllocation: setIsAllocation,
@ -669,7 +669,7 @@ class NativeBehavior {
behavior.sideEffects.setTo(newEffects);
}
processSpecString(reporter, spannable, specString,
processSpecString(commonElements.dartTypes, reporter, spannable, specString,
validTags: validTags,
lookupType: lookupType,
setSideEffects: setSideEffects,
@ -711,10 +711,10 @@ class NativeBehavior {
}
static dynamic /*DartType|SpecialType*/ _parseType(
String typeString, TypeLookup lookupType) {
DartTypes dartTypes, String typeString, TypeLookup lookupType) {
if (typeString == '=Object') return SpecialType.JsObject;
if (typeString == 'dynamic') {
return DynamicType();
return dartTypes.dynamicType();
}
int index = typeString.indexOf('<');
var type = lookupType(typeString, required: index == -1);
@ -727,7 +727,7 @@ class NativeBehavior {
return type;
}
}
return DynamicType();
return dartTypes.dynamicType();
}
}
@ -766,7 +766,8 @@ abstract class BehaviorBuilder {
List<dynamic> types = null;
for (String specString in annotations) {
for (final typeString in specString.split('|')) {
var type = NativeBehavior._parseType(typeString, lookupType);
var type = NativeBehavior._parseType(
commonElements.dartTypes, typeString, lookupType);
if (types == null) types = [];
types.add(type);
}

View file

@ -14,9 +14,6 @@ abstract class AbstractDataSink extends DataSinkMixin implements DataSink {
/// and deserialization.
final bool useDataKinds;
/// Visitor used for serializing [DartType]s.
DartTypeWriter _dartTypeWriter;
/// Visitor used for serializing [ir.DartType]s.
DartTypeNodeWriter _dartTypeNodeWriter;
@ -44,7 +41,6 @@ abstract class AbstractDataSink extends DataSinkMixin implements DataSink {
_MemberData _currentMemberData;
AbstractDataSink({this.useDataKinds: false, this.tagFrequencyMap}) {
_dartTypeWriter = new DartTypeWriter(this);
_dartTypeNodeWriter = new DartTypeNodeWriter(this);
_stringIndex = new IndexedSink<String>(this);
_uriIndex = new IndexedSink<Uri>(this);
@ -124,7 +120,7 @@ abstract class AbstractDataSink extends DataSinkMixin implements DataSink {
}
writeEnum(DartTypeKind.none);
} else {
_dartTypeWriter.visit(value, functionTypeVariables);
value.writeToDataSink(this, functionTypeVariables);
}
}

View file

@ -140,16 +140,6 @@ abstract class AbstractDataSource extends DataSourceMixin
return _entityReader.readTypeVariableFromDataSource(this, entityLookup);
}
List<DartType> _readDartTypes(
List<FunctionTypeVariable> functionTypeVariables) {
int count = readInt();
List<DartType> types = new List<DartType>(count);
for (int index = 0; index < count; index++) {
types[index] = _readDartType(functionTypeVariables);
}
return types;
}
List<ir.DartType> _readDartTypeNodes(
List<ir.TypeParameter> functionTypeVariables) {
int count = readInt();
@ -172,82 +162,11 @@ abstract class AbstractDataSource extends DataSourceMixin
@override
DartType readDartType({bool allowNull: false}) {
_checkDataKind(DataKind.dartType);
DartType type = _readDartType([]);
DartType type = DartType.readFromDataSource(this, []);
assert(type != null || allowNull);
return type;
}
DartType _readDartType(List<FunctionTypeVariable> functionTypeVariables) {
DartTypeKind kind = readEnum(DartTypeKind.values);
switch (kind) {
case DartTypeKind.none:
return null;
case DartTypeKind.neverType:
Nullability nullability = readEnum(Nullability.values);
return NeverType(nullability);
case DartTypeKind.voidType:
return VoidType();
case DartTypeKind.typeVariable:
Nullability nullability = readEnum(Nullability.values);
return new TypeVariableType(readTypeVariable(), nullability);
case DartTypeKind.functionTypeVariable:
int index = readInt();
assert(0 <= index && index < functionTypeVariables.length);
return functionTypeVariables[index];
case DartTypeKind.functionType:
int typeVariableCount = readInt();
List<FunctionTypeVariable> typeVariables =
new List<FunctionTypeVariable>.generate(typeVariableCount,
(int index) {
Nullability nullability = readEnum(Nullability.values);
return new FunctionTypeVariable(index, nullability);
});
functionTypeVariables =
new List<FunctionTypeVariable>.from(functionTypeVariables)
..addAll(typeVariables);
for (int index = 0; index < typeVariableCount; index++) {
typeVariables[index].bound = _readDartType(functionTypeVariables);
}
DartType returnType = _readDartType(functionTypeVariables);
List<DartType> parameterTypes = _readDartTypes(functionTypeVariables);
List<DartType> optionalParameterTypes =
_readDartTypes(functionTypeVariables);
List<DartType> namedParameterTypes =
_readDartTypes(functionTypeVariables);
List<String> namedParameters =
new List<String>(namedParameterTypes.length);
for (int i = 0; i < namedParameters.length; i++) {
namedParameters[i] = readString();
}
Nullability nullability = readEnum(Nullability.values);
return new FunctionType(
returnType,
parameterTypes,
optionalParameterTypes,
namedParameters,
namedParameterTypes,
typeVariables,
nullability);
case DartTypeKind.interfaceType:
IndexedClass cls = readClass();
List<DartType> typeArguments = _readDartTypes(functionTypeVariables);
Nullability nullability = readEnum(Nullability.values);
return new InterfaceType(cls, typeArguments, nullability);
case DartTypeKind.dynamicType:
return DynamicType();
case DartTypeKind.erasedType:
return ErasedType();
case DartTypeKind.anyType:
return AnyType();
case DartTypeKind.futureOr:
DartType typeArgument = _readDartType(functionTypeVariables);
Nullability nullability = readEnum(Nullability.values);
return new FutureOrType(typeArgument, nullability);
}
throw new UnsupportedError("Unexpected DartTypeKind $kind");
}
@override
ir.DartType readDartTypeNode({bool allowNull: false}) {
_checkDataKind(DataKind.dartTypeNode);

View file

@ -101,121 +101,6 @@ enum DartTypeKind {
futureOr,
}
/// Visitor that serializes [DartType] object together with [AbstractDataSink].
class DartTypeWriter
implements DartTypeVisitor<void, List<FunctionTypeVariable>> {
final AbstractDataSink _sink;
DartTypeWriter(this._sink);
@override
void visit(covariant DartType type,
List<FunctionTypeVariable> functionTypeVariables) =>
type.accept(this, functionTypeVariables);
void visitTypes(
List<DartType> types, List<FunctionTypeVariable> functionTypeVariables) {
_sink.writeInt(types.length);
for (DartType type in types) {
_sink._writeDartType(type, functionTypeVariables);
}
}
@override
void visitNeverType(covariant NeverType type,
List<FunctionTypeVariable> functionTypeVariables) {
_sink.writeEnum(DartTypeKind.neverType);
_sink.writeEnum(type.nullability);
}
@override
void visitVoidType(covariant VoidType type,
List<FunctionTypeVariable> functionTypeVariables) {
_sink.writeEnum(DartTypeKind.voidType);
}
@override
void visitTypeVariableType(covariant TypeVariableType type,
List<FunctionTypeVariable> functionTypeVariables) {
_sink.writeEnum(DartTypeKind.typeVariable);
IndexedTypeVariable typeVariable = type.element;
_sink.writeEnum(type.nullability);
_sink.writeTypeVariable(typeVariable);
}
@override
void visitFunctionTypeVariable(covariant FunctionTypeVariable type,
List<FunctionTypeVariable> functionTypeVariables) {
int index = functionTypeVariables.indexOf(type);
if (index == -1) {
// TODO(johnniwinther): Avoid free variables.
_sink._writeDartType(DynamicType(), functionTypeVariables);
} else {
_sink.writeEnum(DartTypeKind.functionTypeVariable);
_sink.writeInt(index);
}
}
@override
void visitFunctionType(covariant FunctionType type,
List<FunctionTypeVariable> functionTypeVariables) {
_sink.writeEnum(DartTypeKind.functionType);
functionTypeVariables =
new List<FunctionTypeVariable>.from(functionTypeVariables)
..addAll(type.typeVariables);
_sink.writeInt(type.typeVariables.length);
for (FunctionTypeVariable variable in type.typeVariables) {
_sink.writeEnum(variable.nullability);
}
for (FunctionTypeVariable variable in type.typeVariables) {
_sink._writeDartType(variable.bound, functionTypeVariables);
}
_sink._writeDartType(type.returnType, functionTypeVariables);
visitTypes(type.parameterTypes, functionTypeVariables);
visitTypes(type.optionalParameterTypes, functionTypeVariables);
visitTypes(type.namedParameterTypes, functionTypeVariables);
for (String namedParameter in type.namedParameters) {
_sink.writeString(namedParameter);
}
_sink.writeEnum(type.nullability);
}
@override
void visitInterfaceType(covariant InterfaceType type,
List<FunctionTypeVariable> functionTypeVariables) {
_sink.writeEnum(DartTypeKind.interfaceType);
_sink.writeClass(type.element);
visitTypes(type.typeArguments, functionTypeVariables);
_sink.writeEnum(type.nullability);
}
@override
void visitDynamicType(covariant DynamicType type,
List<FunctionTypeVariable> functionTypeVariables) {
_sink.writeEnum(DartTypeKind.dynamicType);
}
@override
void visitErasedType(covariant ErasedType type,
List<FunctionTypeVariable> functionTypeVariables) {
_sink.writeEnum(DartTypeKind.erasedType);
}
@override
void visitAnyType(covariant AnyType type,
List<FunctionTypeVariable> functionTypeVariables) {
_sink.writeEnum(DartTypeKind.anyType);
}
@override
void visitFutureOrType(covariant FutureOrType type,
List<FunctionTypeVariable> functionTypeVariables) {
_sink.writeEnum(DartTypeKind.futureOr);
_sink._writeDartType(type.typeArgument, functionTypeVariables);
_sink.writeEnum(type.nullability);
}
}
/// Enum used for identifying [ir.DartType] subclasses in serialization.
enum DartTypeNodeKind {
none,

View file

@ -2123,8 +2123,9 @@ class KernelSsaGraphBuilder extends ir.Visitor {
List<HInstruction> arguments = [pop()];
ClassEntity cls = _commonElements.streamIterator;
DartType typeArg = _elementMap.getDartType(node.variable.type);
InterfaceType instanceType = localsHandler.substInContext(new InterfaceType(
cls, [typeArg], closedWorld.dartTypes.defaultNullability));
InterfaceType instanceType = localsHandler.substInContext(
dartTypes.interfaceType(
cls, [typeArg], closedWorld.dartTypes.defaultNullability));
// TODO(johnniwinther): This should be the exact type.
StaticType staticInstanceType =
new StaticType(instanceType, ClassRelation.subtype);
@ -3110,8 +3111,10 @@ class KernelSsaGraphBuilder extends ir.Visitor {
}
if (options.useNewRti) {
// [type] could be `List<T>`, so ensure it is `JSArray<T>`.
InterfaceType arrayType = InterfaceType(_commonElements.jsArrayClass,
type.typeArguments, closedWorld.dartTypes.defaultNullability);
InterfaceType arrayType = dartTypes.interfaceType(
_commonElements.jsArrayClass,
type.typeArguments,
closedWorld.dartTypes.defaultNullability);
HInstruction rti =
_typeBuilder.analyzeTypeArgumentNewRti(arrayType, sourceElement);
@ -3146,7 +3149,8 @@ class KernelSsaGraphBuilder extends ir.Visitor {
SourceInformation sourceInformation =
_sourceInformationBuilder.buildListLiteral(node);
InterfaceType type = localsHandler.substInContext(
_commonElements.listType(_elementMap.getDartType(node.typeArgument)));
_commonElements.listType(
Nullability.none, _elementMap.getDartType(node.typeArgument)));
listInstruction = _setListRuntimeTypeInfoIfNeeded(
listInstruction, type, sourceInformation);
}
@ -3189,8 +3193,8 @@ class KernelSsaGraphBuilder extends ir.Visitor {
assert(
constructor is ConstructorEntity && constructor.isFactoryConstructor);
InterfaceType type = localsHandler.substInContext(
_commonElements.setType(_elementMap.getDartType(node.typeArgument)));
InterfaceType type = localsHandler.substInContext(_commonElements.setType(
Nullability.none, _elementMap.getDartType(node.typeArgument)));
ClassEntity cls = constructor.enclosingClass;
if (_rtiNeed.classNeedsTypeArguments(cls)) {
@ -3271,6 +3275,7 @@ class KernelSsaGraphBuilder extends ir.Visitor {
constructor is ConstructorEntity && constructor.isFactoryConstructor);
InterfaceType type = localsHandler.substInContext(_commonElements.mapType(
Nullability.none,
_elementMap.getDartType(node.keyType),
_elementMap.getDartType(node.valueType)));
ClassEntity cls = constructor.enclosingClass;
@ -3883,7 +3888,9 @@ class KernelSsaGraphBuilder extends ir.Visitor {
}
InterfaceType instanceType = _elementMap.createInterfaceType(
invocation.target.enclosingClass, invocation.arguments.types);
invocation.target.enclosingClass,
invocation.arguments.types,
Nullability.none);
AbstractValue resultType = typeMask;
@ -4008,7 +4015,9 @@ class KernelSsaGraphBuilder extends ir.Visitor {
isGrowableListConstructorCall ||
isJSArrayTypedConstructor)) {
InterfaceType type = _elementMap.createInterfaceType(
invocation.target.enclosingClass, invocation.arguments.types);
invocation.target.enclosingClass,
invocation.arguments.types,
Nullability.none);
stack
.add(_setListRuntimeTypeInfoIfNeeded(pop(), type, sourceInformation));
}
@ -4715,8 +4724,10 @@ class KernelSsaGraphBuilder extends ir.Visitor {
}
// TODO(sra): This should be JSArray<any>, created via
// _elementEnvironment.getJsInteropType(_elementEnvironment.jsArrayClass);
InterfaceType interopType = InterfaceType(_commonElements.jsArrayClass,
[DynamicType()], closedWorld.dartTypes.defaultNullability);
InterfaceType interopType = dartTypes.interfaceType(
_commonElements.jsArrayClass,
[dartTypes.dynamicType()],
closedWorld.dartTypes.defaultNullability);
SourceInformation sourceInformation =
_sourceInformationBuilder.buildCall(invocation, invocation);
HInstruction rti =
@ -5011,8 +5022,8 @@ class KernelSsaGraphBuilder extends ir.Visitor {
// Native behavior effects here are similar to native/behavior.dart.
// The return type is dynamic if we don't trust js-interop type
// declarations.
nativeBehavior.typesReturned
.add(options.trustJSInteropTypeAnnotations ? type : DynamicType());
nativeBehavior.typesReturned.add(
options.trustJSInteropTypeAnnotations ? type : dartTypes.dynamicType());
// The allocation effects include the declared type if it is native (which
// includes js interop types).
@ -5372,7 +5383,7 @@ class KernelSsaGraphBuilder extends ir.Visitor {
ClassEntity cls = constructor.enclosingClass;
AbstractValue typeMask = _abstractValueDomain.createNonNullExact(cls);
InterfaceType instanceType = _elementMap.createInterfaceType(
target.enclosingClass, node.arguments.types);
target.enclosingClass, node.arguments.types, Nullability.none);
instanceType = localsHandler.substInContext(instanceType);
List<HInstruction> arguments = <HInstruction>[];

View file

@ -76,7 +76,8 @@ class SsaOptimizerTask extends CompilerTask {
SsaCodeMotion codeMotion;
SsaLoadElimination loadElimination;
TypeRecipeDomain typeRecipeDomain = TypeRecipeDomainImpl();
TypeRecipeDomain typeRecipeDomain =
TypeRecipeDomainImpl(closedWorld.dartTypes);
OptimizationTestLog log;
if (retainDataForTesting) {
@ -693,7 +694,9 @@ class SsaInstructionSimplifier extends HBaseVisitor
if (_options.useNewRti) {
typeInfo = HLoadType.type(
_closedWorld.elementEnvironment.createInterfaceType(
commonElements.jsArrayClass, [commonElements.stringType]),
commonElements.jsArrayClass,
[commonElements.stringType],
Nullability.none),
_abstractValueDomain.dynamicType);
node.block.addBefore(node, typeInfo);
} else {

View file

@ -66,6 +66,8 @@ main() {
}
"""));
var types = env.types;
testToString(FunctionType type, String expectedToString) {
Expect.equals(expectedToString, type.toString());
}
@ -81,14 +83,14 @@ main() {
testInstantiate(FunctionType type, List<DartType> instantiation,
String expectedToString) {
DartType result = type.instantiate(instantiation);
DartType result = types.instantiate(type, instantiation);
Expect.equals(expectedToString, result.toString(),
"Unexpected instantiation of $type with $instantiation: $result");
}
void testSubst(List<DartType> arguments, List<DartType> parameters,
DartType type1, String expectedToString) {
DartType subst = type1.subst(arguments, parameters);
DartType subst = types.subst(arguments, parameters, type1);
Expect.equals(expectedToString, subst.toString(),
"$type1.subst($arguments,$parameters)");
}
@ -117,10 +119,10 @@ main() {
InterfaceType Object_ = env['Object'];
InterfaceType num_ = env['num'];
InterfaceType int_ = env['int'];
InterfaceType C1 = instantiate(env.getClass('C1'), []);
InterfaceType C2 = instantiate(env.getClass('C2'), []);
InterfaceType C1 = instantiate(types, env.getClass('C1'), []);
InterfaceType C2 = instantiate(types, env.getClass('C2'), []);
ClassEntity C3 = env.getClass('C3');
InterfaceType C4 = instantiate(env.getClass('C4'), []);
InterfaceType C4 = instantiate(types, env.getClass('C4'), []);
FunctionType F1 = env.getFieldType('F1');
FunctionType F2 = env.getFieldType('F2');
FunctionType F3 = env.getFieldType('F3');
@ -203,10 +205,10 @@ main() {
testBounds(F9, [F9.typeVariables.last, Object_]);
testBounds(F10, [F10.typeVariables.last, Object_]);
testBounds(F11, [
instantiate(C3, [F11.typeVariables.last])
instantiate(types, C3, [F11.typeVariables.last])
]);
testBounds(F12, [
instantiate(C3, [F12.typeVariables.last])
instantiate(types, C3, [F12.typeVariables.last])
]);
testBounds(F13, [Object_]);
testBounds(F14, [Object_]);

View file

@ -17,8 +17,9 @@ import 'package:compiler/src/kernel/kernel_strategy.dart';
import 'package:compiler/src/world.dart' show JClosedWorld, KClosedWorld;
import 'memory_compiler.dart' as memory;
DartType instantiate(ClassEntity element, List<DartType> arguments) {
return new InterfaceType(element, arguments, Nullability.none);
DartType instantiate(
DartTypes dartTypes, ClassEntity element, List<DartType> arguments) {
return dartTypes.interfaceType(element, arguments, Nullability.none);
}
class TypeEnvironment {
@ -112,10 +113,10 @@ class TypeEnvironment {
DartType operator [](String name) {
if (name == 'dynamic') {
return DynamicType();
return types.dynamicType();
}
if (name == 'void') {
return VoidType();
return types.voidType();
}
return getElementType(name);
}

View file

@ -8,7 +8,9 @@ import 'package:expect/expect.dart';
import 'package:compiler/src/native/behavior.dart';
import 'package:compiler/src/diagnostics/diagnostic_listener.dart';
import 'package:compiler/src/diagnostics/messages.dart';
import 'package:compiler/src/elements/types.dart';
import 'package:compiler/src/universe/side_effects.dart' show SideEffects;
import '../helpers/type_test_helper.dart';
const OBJECT = 'Object';
const NULL = 'Null';
@ -39,7 +41,7 @@ class Listener extends DiagnosticReporter {
noSuchMethod(_) => null;
}
void test(String specString,
void test(DartTypes dartTypes, String specString,
{List returns,
List creates,
SideEffects expectedSideEffects,
@ -55,7 +57,7 @@ void test(String specString,
bool actualGvn;
Listener listener = new Listener();
try {
NativeBehavior.processSpecString(listener, null, specString,
NativeBehavior.processSpecString(dartTypes, listener, null, specString,
setSideEffects: (effects) => actualSideEffects = effects,
setThrows: (b) => actualThrows = b,
setIsAllocation: (b) => actualNew = b,
@ -84,11 +86,11 @@ void test(String specString,
Expect.equals(expectedGvn, actualGvn);
}
void testWithSideEffects(String specString,
void testWithSideEffects(DartTypes dartTypes, String specString,
{List returns, List creates, bool expectError: false}) {
void sideEffectsTest(String newSpecString, SideEffects expectedSideEffects,
{bool sideEffectsExpectError}) {
test(newSpecString,
test(dartTypes, newSpecString,
returns: returns,
creates: creates,
expectedSideEffects: expectedSideEffects,
@ -194,105 +196,117 @@ void testWithSideEffects(String specString,
sideEffectsExpectError: true);
}
void main() {
test('void', returns: [], creates: []);
test('', returns: [OBJECT, NULL], creates: []);
test('var', returns: [OBJECT, NULL], creates: []);
test('A', returns: ['A'], creates: ['A']);
test('A|B', returns: ['A', 'B'], creates: ['A', 'B']);
test('A|B|C', returns: ['A', 'B', 'C'], creates: ['A', 'B', 'C']);
void main() async {
var env = await TypeEnvironment.create('');
var types = env.types;
test(types, 'void', returns: [], creates: []);
test(types, '', returns: [OBJECT, NULL], creates: []);
test(types, 'var', returns: [OBJECT, NULL], creates: []);
test(types, 'A', returns: ['A'], creates: ['A']);
test(types, 'A|B', returns: ['A', 'B'], creates: ['A', 'B']);
test(types, 'A|B|C', returns: ['A', 'B', 'C'], creates: ['A', 'B', 'C']);
test('returns:void;', returns: [], creates: []);
test('returns:;', returns: [OBJECT, NULL], creates: []);
test('returns:var;', returns: [OBJECT, NULL], creates: []);
test('returns:A;', returns: ['A'], creates: ['A']);
test('returns:A|B;', returns: ['A', 'B'], creates: ['A', 'B']);
test('returns:A|B|C;', returns: ['A', 'B', 'C'], creates: ['A', 'B', 'C']);
test(types, 'returns:void;', returns: [], creates: []);
test(types, 'returns:;', returns: [OBJECT, NULL], creates: []);
test(types, 'returns:var;', returns: [OBJECT, NULL], creates: []);
test(types, 'returns:A;', returns: ['A'], creates: ['A']);
test(types, 'returns:A|B;', returns: ['A', 'B'], creates: ['A', 'B']);
test(types, 'returns:A|B|C;',
returns: ['A', 'B', 'C'], creates: ['A', 'B', 'C']);
test('creates:void;', expectError: true);
test('creates:;', creates: []);
test('creates:var;', creates: []);
test('creates:A;', returns: [], creates: ['A']);
test('creates:A|B;', returns: [], creates: ['A', 'B']);
test('creates:A|B|C;', returns: [], creates: ['A', 'B', 'C']);
test(types, 'creates:void;', expectError: true);
test(types, 'creates:;', creates: []);
test(types, 'creates:var;', creates: []);
test(types, 'creates:A;', returns: [], creates: ['A']);
test(types, 'creates:A|B;', returns: [], creates: ['A', 'B']);
test(types, 'creates:A|B|C;', returns: [], creates: ['A', 'B', 'C']);
test('returns:void;creates:', returns: [], creates: []);
test('returns:;creates:', returns: [OBJECT, NULL], creates: []);
test('returns:var;creates:', returns: [OBJECT, NULL], creates: []);
test('returns:A;creates:', returns: ['A'], creates: []);
test('returns:A|B;creates:;', returns: ['A', 'B'], creates: []);
test('returns:A|B|C;creates:;', returns: ['A', 'B', 'C'], creates: []);
test(types, 'returns:void;creates:', returns: [], creates: []);
test(types, 'returns:;creates:', returns: [OBJECT, NULL], creates: []);
test(types, 'returns:var;creates:', returns: [OBJECT, NULL], creates: []);
test(types, 'returns:A;creates:', returns: ['A'], creates: []);
test(types, 'returns:A|B;creates:;', returns: ['A', 'B'], creates: []);
test(types, 'returns:A|B|C;creates:;', returns: ['A', 'B', 'C'], creates: []);
test('returns:void;creates:A;', returns: [], creates: ['A']);
test('returns:;creates:A|B;', returns: [OBJECT, NULL], creates: ['A', 'B']);
test('returns:var;creates:A|B|C;',
test(types, 'returns:void;creates:A;', returns: [], creates: ['A']);
test(types, 'returns:;creates:A|B;',
returns: [OBJECT, NULL], creates: ['A', 'B']);
test(types, 'returns:var;creates:A|B|C;',
returns: [OBJECT, NULL], creates: ['A', 'B', 'C']);
test('returns:A; creates:A|B|C; ', returns: ['A'], creates: ['A', 'B', 'C']);
test(' returns:A|B; creates:A|C;', returns: ['A', 'B'], creates: ['A', 'C']);
test(' returns:A|B|C; creates:A; ',
test(types, 'returns:A; creates:A|B|C; ',
returns: ['A'], creates: ['A', 'B', 'C']);
test(types, ' returns:A|B; creates:A|C;',
returns: ['A', 'B'], creates: ['A', 'C']);
test(types, ' returns:A|B|C; creates:A; ',
returns: ['A', 'B', 'C'], creates: ['A']);
testWithSideEffects('returns:void;', returns: [], creates: []);
testWithSideEffects('returns:void;', returns: [], creates: []);
testWithSideEffects('returns:;', returns: [OBJECT, NULL], creates: []);
testWithSideEffects('returns:var;', returns: [OBJECT, NULL], creates: []);
testWithSideEffects('returns:A;', returns: ['A'], creates: ['A']);
testWithSideEffects('returns:A|B;', returns: ['A', 'B'], creates: ['A', 'B']);
testWithSideEffects('returns:A|B|C;',
testWithSideEffects(types, 'returns:void;', returns: [], creates: []);
testWithSideEffects(types, 'returns:void;', returns: [], creates: []);
testWithSideEffects(types, 'returns:;', returns: [OBJECT, NULL], creates: []);
testWithSideEffects(types, 'returns:var;',
returns: [OBJECT, NULL], creates: []);
testWithSideEffects(types, 'returns:A;', returns: ['A'], creates: ['A']);
testWithSideEffects(types, 'returns:A|B;',
returns: ['A', 'B'], creates: ['A', 'B']);
testWithSideEffects(types, 'returns:A|B|C;',
returns: ['A', 'B', 'C'], creates: ['A', 'B', 'C']);
testWithSideEffects('returns: A| B |C ;',
testWithSideEffects(types, 'returns: A| B |C ;',
returns: ['A', 'B', 'C'], creates: ['A', 'B', 'C']);
testWithSideEffects('creates:void;', expectError: true);
testWithSideEffects('creates:;', creates: []);
testWithSideEffects('creates:var;', creates: []);
testWithSideEffects('creates:A;', returns: [], creates: ['A']);
testWithSideEffects('creates:A|B;', returns: [], creates: ['A', 'B']);
testWithSideEffects('creates:A|B|C;', returns: [], creates: ['A', 'B', 'C']);
testWithSideEffects(types, 'creates:void;', expectError: true);
testWithSideEffects(types, 'creates:;', creates: []);
testWithSideEffects(types, 'creates:var;', creates: []);
testWithSideEffects(types, 'creates:A;', returns: [], creates: ['A']);
testWithSideEffects(types, 'creates:A|B;', returns: [], creates: ['A', 'B']);
testWithSideEffects(types, 'creates:A|B|C;',
returns: [], creates: ['A', 'B', 'C']);
testWithSideEffects('returns:void;creates:;', returns: [], creates: []);
testWithSideEffects('returns:;creates:;',
testWithSideEffects(types, 'returns:void;creates:;',
returns: [], creates: []);
testWithSideEffects(types, 'returns:;creates:;',
returns: [OBJECT, NULL], creates: []);
testWithSideEffects('returns:var;creates:;',
testWithSideEffects(types, 'returns:var;creates:;',
returns: [OBJECT, NULL], creates: []);
testWithSideEffects('returns:A;creates:;', returns: ['A'], creates: []);
testWithSideEffects('returns:A|B;creates:;',
testWithSideEffects(types, 'returns:A;creates:;',
returns: ['A'], creates: []);
testWithSideEffects(types, 'returns:A|B;creates:;',
returns: ['A', 'B'], creates: []);
testWithSideEffects('returns:A|B|C;creates:;',
testWithSideEffects(types, 'returns:A|B|C;creates:;',
returns: ['A', 'B', 'C'], creates: []);
testWithSideEffects('returns:void;creates:A;', returns: [], creates: ['A']);
testWithSideEffects('returns:;creates:A|B;',
testWithSideEffects(types, 'returns:void;creates:A;',
returns: [], creates: ['A']);
testWithSideEffects(types, 'returns:;creates:A|B;',
returns: [OBJECT, NULL], creates: ['A', 'B']);
testWithSideEffects('returns:var;creates:A|B|C;',
testWithSideEffects(types, 'returns:var;creates:A|B|C;',
returns: [OBJECT, NULL], creates: ['A', 'B', 'C']);
testWithSideEffects('returns:A; creates:A|B|C; ',
testWithSideEffects(types, 'returns:A; creates:A|B|C; ',
returns: ['A'], creates: ['A', 'B', 'C']);
testWithSideEffects(' returns:A|B; creates:A|C;',
testWithSideEffects(types, ' returns:A|B; creates:A|C;',
returns: ['A', 'B'], creates: ['A', 'C']);
testWithSideEffects(' returns:A|B|C; creates:A; ',
testWithSideEffects(types, ' returns:A|B|C; creates:A; ',
returns: ['A', 'B', 'C'], creates: ['A']);
test('throws:may', expectedThrows: NativeThrowBehavior.MAY);
test('throws:never', expectedThrows: NativeThrowBehavior.NEVER);
test('throws:null(1)', expectedThrows: NativeThrowBehavior.NULL_NSM);
test('throws:null(1)+may',
test(types, 'throws:may', expectedThrows: NativeThrowBehavior.MAY);
test(types, 'throws:never', expectedThrows: NativeThrowBehavior.NEVER);
test(types, 'throws:null(1)', expectedThrows: NativeThrowBehavior.NULL_NSM);
test(types, 'throws:null(1)+may',
expectedThrows: NativeThrowBehavior.NULL_NSM_THEN_MAY);
test('new:true', expectedNew: true);
test('new:false', expectedNew: false);
test('returns:A;new:true', returns: ['A'], expectedNew: true);
test(' new : true ; returns:A;', returns: ['A'], expectedNew: true);
test('new:true;returns:A;new:true', expectError: true);
test(types, 'new:true', expectedNew: true);
test(types, 'new:false', expectedNew: false);
test(types, 'returns:A;new:true', returns: ['A'], expectedNew: true);
test(types, ' new : true ; returns:A;', returns: ['A'], expectedNew: true);
test(types, 'new:true;returns:A;new:true', expectError: true);
test('gvn:true', expectedGvn: true);
test('gvn:false', expectedGvn: false);
test('returns:A;gvn:true', returns: ['A'], expectedGvn: true);
test(' gvn : true ; returns:A;', returns: ['A'], expectedGvn: true);
test('gvn:true;returns:A;gvn:true', expectError: true);
test(types, 'gvn:true', expectedGvn: true);
test(types, 'gvn:false', expectedGvn: false);
test(types, 'returns:A;gvn:true', returns: ['A'], expectedGvn: true);
test(types, ' gvn : true ; returns:A;', returns: ['A'], expectedGvn: true);
test(types, 'gvn:true;returns:A;gvn:true', expectError: true);
test('gvn: true; new: true', expectError: true);
test('gvn: true; new: false', expectedGvn: true, expectedNew: false);
test('gvn: false; new: true', expectedGvn: false, expectedNew: true);
test('gvn: false; new: false', expectedGvn: false, expectedNew: false);
test(types, 'gvn: true; new: true', expectError: true);
test(types, 'gvn: true; new: false', expectedGvn: true, expectedNew: false);
test(types, 'gvn: false; new: true', expectedGvn: false, expectedNew: true);
test(types, 'gvn: false; new: false', expectedGvn: false, expectedNew: false);
}

View file

@ -99,8 +99,8 @@ main() {
getReturnType('futureOrFutureOrNum', 'FutureOr<FutureOr<num>>');
DartType futureNull = getReturnType('futureNull', 'Future<Null>');
FutureOrType futureOrNull = getReturnType('futureOrNull', 'FutureOr<Null>');
DartType Null_ = futureOrNull.typeArgument;
InterfaceType futureOrNull = getReturnType('futureOrNull', 'Future<Null>');
DartType Null_ = futureOrNull.typeArguments.single;
ClassEntity C = env.getClass('C');
DartType futureT = getReturnType('futureT', 'Future<C.T>', C);
@ -111,7 +111,7 @@ main() {
DartType returnVoid = getFunctionType('returnVoid', 'void Function()');
DartType returnFutureNull =
getFunctionType('futureOrNull', 'FutureOr<Null> Function()');
getFunctionType('futureOrNull', 'Future<Null> Function()');
List<DartType> all = [
Object_,

View file

@ -106,6 +106,7 @@ testNonTrivialSubstitutions() async {
new F2();
}
""", expectNoWarningsOrErrors: true);
var types = env.types;
DartType _dynamic = env['dynamic'];
DartType _ = env['_'];
@ -178,7 +179,7 @@ testNonTrivialSubstitutions() async {
A: [D1_T],
B: [
D1_T,
instantiate(A, [D1_T])
instantiate(types, A, [D1_T])
]
});
DartType D1_superclass_T = env.elementEnvironment
@ -189,7 +190,7 @@ testNonTrivialSubstitutions() async {
A: [D1_superclass_T],
B: [
D1_superclass_T,
instantiate(A, [D1_superclass_T])
instantiate(types, A, [D1_superclass_T])
]
});
DartType D2_T = env.elementEnvironment.getThisType(D2).typeArguments.first;
@ -197,7 +198,7 @@ testNonTrivialSubstitutions() async {
A: [D2_T],
B: [
D2_T,
instantiate(A, [D2_T])
instantiate(types, A, [D2_T])
]
});
@ -205,21 +206,21 @@ testNonTrivialSubstitutions() async {
A: [_],
B: [
_,
instantiate(A, [_])
instantiate(types, A, [_])
]
});
testSupertypes(env.elementEnvironment.getSuperClass(E1), {
A: [_],
B: [
_,
instantiate(A, [_])
instantiate(types, A, [_])
]
});
testSupertypes(E2, {
A: [_],
B: [
_,
instantiate(A, [_])
instantiate(types, A, [_])
]
});
@ -228,7 +229,7 @@ testNonTrivialSubstitutions() async {
A: [_],
B: [
_,
instantiate(B, [F1_T, _])
instantiate(types, B, [F1_T, _])
]
});
DartType F1_superclass_T = env.elementEnvironment
@ -239,7 +240,7 @@ testNonTrivialSubstitutions() async {
A: [_],
B: [
_,
instantiate(B, [F1_superclass_T, _])
instantiate(types, B, [F1_superclass_T, _])
]
});
DartType F2_T = env.elementEnvironment.getThisType(F2).typeArguments.first;
@ -247,7 +248,7 @@ testNonTrivialSubstitutions() async {
A: [_],
B: [
_,
instantiate(B, [F2_T, _])
instantiate(types, B, [F2_T, _])
]
});
}

View file

@ -63,6 +63,8 @@ Future testInterfaceSubtype() async {
testTypes(env, T, S, expectSubtype);
}
var types = env.types;
ClassEntity A = env.getClass('A');
ClassEntity B = env.getClass('B');
ClassEntity C = env.getClass('C');
@ -124,12 +126,12 @@ Future testInterfaceSubtype() async {
expect(false, dynamic_, Null_);
expect(true, Null_, Null_);
DartType A_Object = instantiate(A, [Object_]);
DartType A_num = instantiate(A, [num_]);
DartType A_int = instantiate(A, [int_]);
DartType A_String = instantiate(A, [String_]);
DartType A_dynamic = instantiate(A, [dynamic_]);
DartType A_Null = instantiate(A, [Null_]);
DartType A_Object = instantiate(types, A, [Object_]);
DartType A_num = instantiate(types, A, [num_]);
DartType A_int = instantiate(types, A, [int_]);
DartType A_String = instantiate(types, A, [String_]);
DartType A_dynamic = instantiate(types, A, [dynamic_]);
DartType A_Null = instantiate(types, A, [Null_]);
expect(true, A_Object, Object_);
expect(false, A_Object, num_);
@ -180,11 +182,11 @@ Future testInterfaceSubtype() async {
expect(false, A_dynamic, A_Null);
expect(true, A_Null, A_Null);
DartType B_Object_Object = instantiate(B, [Object_, Object_]);
DartType B_num_num = instantiate(B, [num_, num_]);
DartType B_int_num = instantiate(B, [int_, num_]);
DartType B_dynamic_dynamic = instantiate(B, [dynamic_, dynamic_]);
DartType B_String_dynamic = instantiate(B, [String_, dynamic_]);
DartType B_Object_Object = instantiate(types, B, [Object_, Object_]);
DartType B_num_num = instantiate(types, B, [num_, num_]);
DartType B_int_num = instantiate(types, B, [int_, num_]);
DartType B_dynamic_dynamic = instantiate(types, B, [dynamic_, dynamic_]);
DartType B_String_dynamic = instantiate(types, B, [String_, dynamic_]);
expect(true, B_Object_Object, Object_);
expect(true, B_Object_Object, A_Object);
@ -251,10 +253,10 @@ Future testInterfaceSubtype() async {
expect(false, B_dynamic_dynamic, B_String_dynamic);
expect(true, B_String_dynamic, B_String_dynamic);
DartType C_Object_Object = instantiate(C, [Object_, Object_]);
DartType C_num_num = instantiate(C, [num_, num_]);
DartType C_int_String = instantiate(C, [int_, String_]);
DartType C_dynamic_dynamic = instantiate(C, [dynamic_, dynamic_]);
DartType C_Object_Object = instantiate(types, C, [Object_, Object_]);
DartType C_num_num = instantiate(types, C, [num_, num_]);
DartType C_int_String = instantiate(types, C, [int_, String_]);
DartType C_dynamic_dynamic = instantiate(types, C, [dynamic_, dynamic_]);
expect(true, C_Object_Object, B_Object_Object);
expect(false, C_Object_Object, B_num_num);
@ -285,7 +287,7 @@ Future testInterfaceSubtype() async {
// TODO(johnniwinther): Inheritance with different type arguments is
// currently not supported by the implementation.
//expect(true, C_int_String, instantiate(A, [A_int]));
expect(false, C_int_String, instantiate(A, [A_String]));
expect(false, C_int_String, instantiate(types, A, [A_String]));
});
}
@ -749,6 +751,8 @@ Future testStrongModeSubtyping() async {
}
}
var types = env.types;
InterfaceType ClassWithCall = env['ClassWithCall'];
DartType Object_ = env['Object'];
DartType dynamic_ = env['dynamic'];
@ -758,11 +762,16 @@ Future testStrongModeSubtyping() async {
DartType ClassWithCallType =
env.getMemberType('call', ClassWithCall.element);
InterfaceType List_Object = env.commonElements.listType(Object_);
InterfaceType List_dynamic = env.commonElements.listType(dynamic_);
InterfaceType List_void = env.commonElements.listType(void_);
InterfaceType List_Null = env.commonElements.listType(Null_);
InterfaceType List_Function = env.commonElements.listType(Function_);
InterfaceType List_Object =
env.commonElements.listType(types.defaultNullability, Object_);
InterfaceType List_dynamic =
env.commonElements.listType(types.defaultNullability, dynamic_);
InterfaceType List_void =
env.commonElements.listType(types.defaultNullability, void_);
InterfaceType List_Null =
env.commonElements.listType(types.defaultNullability, Null_);
InterfaceType List_Function =
env.commonElements.listType(types.defaultNullability, Function_);
DartType returnNum = env.getMemberType('returnNum');
DartType returnInt = env.getMemberType('returnInt');

View file

@ -58,6 +58,7 @@ testAsInstanceOf() async {
new F();
}
''');
var types = env.types;
ClassEntity A = env.getElement("A");
ClassEntity B = env.getElement("B");
ClassEntity C = env.getElement("C");
@ -68,34 +69,34 @@ testAsInstanceOf() async {
DartType intType = env['int'];
DartType stringType = env['String'];
InterfaceType C_int = instantiate(C, [intType]);
Expect.equals(instantiate(C, [intType]), C_int);
Expect.equals(instantiate(A, [intType]), env.types.asInstanceOf(C_int, A));
InterfaceType C_int = instantiate(types, C, [intType]);
Expect.equals(instantiate(types, C, [intType]), C_int);
Expect.equals(instantiate(types, A, [intType]), types.asInstanceOf(C_int, A));
InterfaceType D_int = instantiate(D, [stringType]);
Expect.equals(instantiate(A, [intType]), env.types.asInstanceOf(D_int, A));
InterfaceType D_int = instantiate(types, D, [stringType]);
Expect.equals(instantiate(types, A, [intType]), types.asInstanceOf(D_int, A));
InterfaceType E_int = instantiate(E, [intType]);
InterfaceType E_int = instantiate(types, E, [intType]);
Expect.equals(
instantiate(A, [
instantiate(A, [intType])
instantiate(types, A, [
instantiate(types, A, [intType])
]),
env.types.asInstanceOf(E_int, A));
types.asInstanceOf(E_int, A));
InterfaceType F_int_string = instantiate(F, [intType, stringType]);
InterfaceType F_int_string = instantiate(types, F, [intType, stringType]);
Expect.equals(
instantiate(B, [
instantiate(F, [intType, stringType])
instantiate(types, B, [
instantiate(types, F, [intType, stringType])
]),
env.types.asInstanceOf(F_int_string, B));
types.asInstanceOf(F_int_string, B));
Expect.equals(
instantiate(A, [
instantiate(F, [
instantiate(B, [stringType]),
instantiate(types, A, [
instantiate(types, F, [
instantiate(types, B, [stringType]),
intType
])
]),
env.types.asInstanceOf(F_int_string, A));
types.asInstanceOf(F_int_string, A));
}
/**
@ -103,12 +104,13 @@ testAsInstanceOf() async {
* through [name1] is the same as the type found through [name2].
*/
void testSubstitution(
DartTypes dartTypes,
ElementEnvironment elementEnvironment,
List<DartType> arguments,
List<DartType> parameters,
DartType type1,
DartType type2) {
DartType subst = type1.subst(arguments, parameters);
DartType subst = dartTypes.subst(arguments, parameters, type1);
Expect.equals(
type2, subst, "$type1.subst($arguments,$parameters)=$subst != $type2");
}
@ -119,6 +121,7 @@ testTypeSubstitution() async {
main() => new Class();
""");
var types = env.types;
InterfaceType Class_T_S = env["Class"];
Expect.isNotNull(Class_T_S);
Expect.isTrue(Class_T_S is InterfaceType);
@ -146,79 +149,103 @@ testTypeSubstitution() async {
List<DartType> parameters = <DartType>[T, S];
List<DartType> arguments = <DartType>[intType, StringType];
testSubstitution(types, env.elementEnvironment, arguments, parameters,
types.voidType(), types.voidType());
testSubstitution(types, env.elementEnvironment, arguments, parameters,
types.dynamicType(), types.dynamicType());
testSubstitution(
env.elementEnvironment, arguments, parameters, VoidType(), VoidType());
testSubstitution(env.elementEnvironment, arguments, parameters, DynamicType(),
DynamicType());
testSubstitution(
env.elementEnvironment, arguments, parameters, intType, intType);
testSubstitution(
env.elementEnvironment, arguments, parameters, StringType, StringType);
testSubstitution(env.elementEnvironment, arguments, parameters,
instantiate(ListClass, [intType]), instantiate(ListClass, [intType]));
testSubstitution(env.elementEnvironment, arguments, parameters,
instantiate(ListClass, [T]), instantiate(ListClass, [intType]));
testSubstitution(env.elementEnvironment, arguments, parameters,
instantiate(ListClass, [S]), instantiate(ListClass, [StringType]));
types, env.elementEnvironment, arguments, parameters, intType, intType);
testSubstitution(types, env.elementEnvironment, arguments, parameters,
StringType, StringType);
testSubstitution(
types,
env.elementEnvironment,
arguments,
parameters,
instantiate(ListClass, [
instantiate(ListClass, [T])
instantiate(types, ListClass, [intType]),
instantiate(types, ListClass, [intType]));
testSubstitution(
types,
env.elementEnvironment,
arguments,
parameters,
instantiate(types, ListClass, [T]),
instantiate(types, ListClass, [intType]));
testSubstitution(
types,
env.elementEnvironment,
arguments,
parameters,
instantiate(types, ListClass, [S]),
instantiate(types, ListClass, [StringType]));
testSubstitution(
types,
env.elementEnvironment,
arguments,
parameters,
instantiate(types, ListClass, [
instantiate(types, ListClass, [T])
]),
instantiate(ListClass, [
instantiate(ListClass, [intType])
instantiate(types, ListClass, [
instantiate(types, ListClass, [intType])
]));
testSubstitution(
types,
env.elementEnvironment,
arguments,
parameters,
instantiate(ListClass, [DynamicType()]),
instantiate(ListClass, [DynamicType()]));
instantiate(types, ListClass, [types.dynamicType()]),
instantiate(types, ListClass, [types.dynamicType()]));
testSubstitution(
types,
env.elementEnvironment,
arguments,
parameters,
instantiate(MapClass, [intType, StringType]),
instantiate(MapClass, [intType, StringType]));
instantiate(types, MapClass, [intType, StringType]),
instantiate(types, MapClass, [intType, StringType]));
testSubstitution(
types,
env.elementEnvironment,
arguments,
parameters,
instantiate(MapClass, [T, StringType]),
instantiate(MapClass, [intType, StringType]));
instantiate(types, MapClass, [T, StringType]),
instantiate(types, MapClass, [intType, StringType]));
testSubstitution(
types,
env.elementEnvironment,
arguments,
parameters,
instantiate(MapClass, [DynamicType(), StringType]),
instantiate(MapClass, [DynamicType(), StringType]));
testSubstitution(env.elementEnvironment, arguments, parameters, T, intType);
instantiate(types, MapClass, [types.dynamicType(), StringType]),
instantiate(types, MapClass, [types.dynamicType(), StringType]));
testSubstitution(
env.elementEnvironment, arguments, parameters, S, StringType);
types, env.elementEnvironment, arguments, parameters, T, intType);
testSubstitution(
types, env.elementEnvironment, arguments, parameters, S, StringType);
testSubstitution(
types,
env.elementEnvironment,
arguments,
parameters,
new FunctionType(
intType, [StringType], [], [], [], [], env.types.defaultNullability),
new FunctionType(
intType, [StringType], [], [], [], [], env.types.defaultNullability));
types.functionType(
intType, [StringType], [], [], [], [], types.defaultNullability),
types.functionType(
intType, [StringType], [], [], [], [], types.defaultNullability));
testSubstitution(
types,
env.elementEnvironment,
arguments,
parameters,
new FunctionType(
VoidType(), [T, S], [], [], [], [], env.types.defaultNullability),
new FunctionType(VoidType(), [intType, StringType], [], [], [], [],
env.types.defaultNullability));
types.functionType(
types.voidType(), [T, S], [], [], [], [], types.defaultNullability),
types.functionType(types.voidType(), [intType, StringType], [], [], [],
[], types.defaultNullability));
testSubstitution(
types,
env.elementEnvironment,
arguments,
parameters,
new FunctionType(VoidType(), [DynamicType()], [], [], [], [],
env.types.defaultNullability),
new FunctionType(VoidType(), [DynamicType()], [], [], [], [],
env.types.defaultNullability));
types.functionType(types.voidType(), [types.dynamicType()], [], [], [],
[], types.defaultNullability),
types.functionType(types.voidType(), [types.dynamicType()], [], [], [],
[], types.defaultNullability));
}

View file

@ -103,6 +103,7 @@ main() {
}
JClosedWorld closedWorld = compiler.backendClosedWorldForTesting;
DartTypes dartTypes = closedWorld.dartTypes;
ElementEnvironment elementEnvironment = closedWorld.elementEnvironment;
String func = rtiTags.functionTypeTag;
String ret = rtiTags.functionTypeReturnTypeTag;
@ -179,49 +180,51 @@ main() {
// List
expect(elementEnvironment.getRawType(List_), '[$List_rep,,]');
// List<dynamic>
expect(instantiate(List_, [dynamic_]), '[$List_rep,,]');
expect(instantiate(dartTypes, List_, [dynamic_]), '[$List_rep,,]');
// List<int>
expect(instantiate(List_, [int_]), '[$List_rep, $int_rep]');
expect(instantiate(dartTypes, List_, [int_]), '[$List_rep, $int_rep]');
// List<Typedef1>
expect(instantiate(List_, [Typedef1_]), '[$List_rep, {$func: 1, $retvoid}]',
expect(
instantiate(dartTypes, List_, [Typedef1_]),
'[$List_rep, {$func: 1, $retvoid}]',
'[$List_rep, {$func: 1, $retvoid$Typedef1_tag}]');
expect(
instantiate(List_, [Typedef2_]),
instantiate(dartTypes, List_, [Typedef2_]),
'[$List_rep, {$func: 1, $ret: $int_rep}]',
'[$List_rep, {$func: 1, $ret: $int_rep$Typedef2_tag}]');
expect(
instantiate(List_, [Typedef3_]),
instantiate(dartTypes, List_, [Typedef3_]),
'[$List_rep, {$func: 1, $ret: [$List_rep, $int_rep]}]',
'[$List_rep, {$func: 1, $ret: [$List_rep, $int_rep]$Typedef3_tag}]');
expect(instantiate(List_, [Typedef4_]), '[$List_rep, {$func: 1}]',
expect(instantiate(dartTypes, List_, [Typedef4_]), '[$List_rep, {$func: 1}]',
'[$List_rep, {$func: 1$Typedef4_tag}]');
expect(
instantiate(List_, [Typedef5_]),
instantiate(dartTypes, List_, [Typedef5_]),
'[$List_rep, {$func: 1,'
' $args: [$int_rep, $String_rep]}]',
'[$List_rep, {$func: 1,'
' $args: [$int_rep, $String_rep]$Typedef5_tag}]');
expect(
instantiate(List_, [Typedef6_]),
instantiate(dartTypes, List_, [Typedef6_]),
'[$List_rep, {$func: 1,'
' $args: [$int_rep], $opt: [$String_rep]}]',
'[$List_rep, {$func: 1,'
' $args: [$int_rep], $opt: [$String_rep]$Typedef6_tag}]');
expect(
instantiate(List_, [Typedef7_]),
instantiate(dartTypes, List_, [Typedef7_]),
'[$List_rep, {$func: 1, $args: '
'[$int_rep, $String_rep], $opt: [[$List_rep, $int_rep],,]}]',
'[$List_rep, {$func: 1, $args: '
'[$int_rep, $String_rep], $opt: [[$List_rep, $int_rep],,]'
'$Typedef7_tag}]');
expect(
instantiate(List_, [Typedef8_]),
instantiate(dartTypes, List_, [Typedef8_]),
'[$List_rep, {$func: 1, $args: [$int_rep],'
' $named: {b: $String_rep}}]',
'[$List_rep, {$func: 1, $args: [$int_rep],'
' $named: {b: $String_rep}$Typedef8_tag}]');
expect(
instantiate(List_, [Typedef9_]),
instantiate(dartTypes, List_, [Typedef9_]),
'[$List_rep, {$func: 1, '
'$args: [$int_rep, $String_rep], $named: '
'{c: [$List_rep, $int_rep], d: null}}]',
@ -229,7 +232,7 @@ main() {
'$args: [$int_rep, $String_rep], $named: {c: [$List_rep, $int_rep],'
' d: null}$Typedef9_tag}]');
expect(
instantiate(List_, [Typedef10_]),
instantiate(dartTypes, List_, [Typedef10_]),
'[$List_rep, {$func: 1, '
'$args: [{$func: 1, $retvoid, '
'$args: [$int_rep], $opt: [,]}]}]',
@ -238,7 +241,7 @@ main() {
'$args: [$int_rep], $opt: [,]}]$Typedef10_tag}]');
expect(
instantiate(List_, [Typedef11_]),
instantiate(dartTypes, List_, [Typedef11_]),
'[$List_rep, {$func: 1, $bounds: [$num_rep, $Object_rep], '
'$ret: {$futureOr: 1, $futureOrType: $int_rep}, '
'$args: [{$futureOr: 1, $futureOrType: 0}, 1, [$List_rep, -1]]}]');
@ -249,10 +252,10 @@ main() {
// Map
expect(elementEnvironment.getRawType(Map_), '[$Map_rep,,,]');
// Map<dynamic,dynamic>
expect(instantiate(Map_, [dynamic_, dynamic_]), '[$Map_rep,,,]');
expect(instantiate(dartTypes, Map_, [dynamic_, dynamic_]), '[$Map_rep,,,]');
// Map<int,String>
expect(
instantiate(Map_, [int_, String_]), '[$Map_rep, $int_rep, $String_rep]');
expect(instantiate(dartTypes, Map_, [int_, String_]),
'[$Map_rep, $int_rep, $String_rep]');
// void m1() {}
expect(findFunctionType(closedWorld, 'm1'), '{$func: 1, $retvoid}');