Include bounds in type literals
Change-Id: Ieb3e5b09e88c98f8943a6e7ca9031c8a6ab776e1
Reviewed-on: https://dart-review.googlesource.com/63820
Commit-Queue: Johnni Winther <johnniwinther@google.com>
Reviewed-by: Sigmund Cherem <sigmund@google.com>
diff --git a/pkg/compiler/lib/src/common_elements.dart b/pkg/compiler/lib/src/common_elements.dart
index c54b666..8a39e86 100644
--- a/pkg/compiler/lib/src/common_elements.dart
+++ b/pkg/compiler/lib/src/common_elements.dart
@@ -1051,9 +1051,6 @@
FunctionEntity get getRuntimeTypeArgumentIntercepted =>
_findHelperFunction('getRuntimeTypeArgumentIntercepted');
- FunctionEntity get runtimeTypeToString =>
- _findHelperFunction('runtimeTypeToString');
-
FunctionEntity get assertIsSubtype => _findHelperFunction('assertIsSubtype');
FunctionEntity get checkSubtype => _findHelperFunction('checkSubtype');
diff --git a/pkg/compiler/lib/src/deferred_load.dart b/pkg/compiler/lib/src/deferred_load.dart
index 54daa5c..fa9b677 100644
--- a/pkg/compiler/lib/src/deferred_load.dart
+++ b/pkg/compiler/lib/src/deferred_load.dart
@@ -361,6 +361,9 @@
_collectTypeDependencies(type, dependencies);
}
break;
+ case TypeUseKind.RTI_VALUE:
+ failedAt(element, "Unexpected type use: $typeUse.");
+ break;
}
}, visitDynamicUse: (DynamicUse dynamicUse) {
// TODO(johnniwinther): Use rti need data to skip unneeded type
diff --git a/pkg/compiler/lib/src/elements/types.dart b/pkg/compiler/lib/src/elements/types.dart
index dc244d9..231c558 100644
--- a/pkg/compiler/lib/src/elements/types.dart
+++ b/pkg/compiler/lib/src/elements/types.dart
@@ -264,8 +264,9 @@
class TypedefType extends DartType {
final TypedefEntity element;
final List<DartType> typeArguments;
+ final FunctionType unaliased;
- TypedefType(this.element, this.typeArguments);
+ TypedefType(this.element, this.typeArguments, this.unaliased);
bool get isTypedef => true;
@@ -291,9 +292,11 @@
}
List<DartType> newTypeArguments =
_substTypes(typeArguments, arguments, parameters);
- if (!identical(typeArguments, newTypeArguments)) {
+ FunctionType newUnaliased = unaliased.subst(arguments, parameters);
+ if (!identical(typeArguments, newTypeArguments) ||
+ !identical(unaliased, newUnaliased)) {
// Create a new type only if necessary.
- return new TypedefType(element, newTypeArguments);
+ return new TypedefType(element, newTypeArguments, newUnaliased);
}
return this;
}
diff --git a/pkg/compiler/lib/src/enqueue.dart b/pkg/compiler/lib/src/enqueue.dart
index c89e967..8a0d580 100644
--- a/pkg/compiler/lib/src/enqueue.dart
+++ b/pkg/compiler/lib/src/enqueue.dart
@@ -380,6 +380,9 @@
_worldBuilder.registerTypeVariableTypeLiteral(type);
}
break;
+ case TypeUseKind.RTI_VALUE:
+ failedAt(CURRENT_ELEMENT_SPANNABLE, "Unexpected type use: $typeUse.");
+ break;
}
}
diff --git a/pkg/compiler/lib/src/js_backend/backend_impact.dart b/pkg/compiler/lib/src/js_backend/backend_impact.dart
index 9adf701..361ac44 100644
--- a/pkg/compiler/lib/src/js_backend/backend_impact.dart
+++ b/pkg/compiler/lib/src/js_backend/backend_impact.dart
@@ -448,7 +448,6 @@
return _typeVariableExpression ??= new BackendImpact(staticUses: [
_commonElements.setRuntimeTypeInfo,
_commonElements.getRuntimeTypeInfo,
- _commonElements.runtimeTypeToString,
_commonElements.createRuntimeType
], otherImpacts: [
listValues,
diff --git a/pkg/compiler/lib/src/js_backend/constant_emitter.dart b/pkg/compiler/lib/src/js_backend/constant_emitter.dart
index 0ce6141..f3e8913 100644
--- a/pkg/compiler/lib/src/js_backend/constant_emitter.dart
+++ b/pkg/compiler/lib/src/js_backend/constant_emitter.dart
@@ -16,7 +16,6 @@
import 'allocator_analysis.dart' show JAllocatorAnalysis;
import 'constant_system_javascript.dart';
import 'js_backend.dart';
-import 'namer.dart';
import 'runtime_types.dart';
typedef jsAst.Expression _ConstantReferenceGenerator(ConstantValue constant);
@@ -42,7 +41,6 @@
final RuntimeTypesNeed _rtiNeed;
final RuntimeTypesEncoder _rtiEncoder;
final JAllocatorAnalysis _allocatorAnalysis;
- final Namer _namer;
final CodeEmitterTask _task;
final _ConstantReferenceGenerator constantReferenceGenerator;
final _ConstantListGenerator makeConstantList;
@@ -59,7 +57,6 @@
this._rtiNeed,
this._rtiEncoder,
this._allocatorAnalysis,
- this._namer,
this._task,
this.constantReferenceGenerator,
this.makeConstantList);
@@ -280,19 +277,21 @@
@override
jsAst.Expression visitType(TypeConstantValue constant, [_]) {
- DartType type = constant.representedType;
- jsAst.Name typeName;
- Entity element;
- if (type is InterfaceType) {
- element = type.element;
- } else if (type is TypedefType) {
- element = type.element;
- } else {
- assert(type is DynamicType);
+ DartType type = constant.representedType.unaliased;
+
+ jsAst.Expression unexpected(TypeVariableType _variable) {
+ TypeVariableType variable = _variable;
+ throw failedAt(
+ NO_LOCATION_SPANNABLE,
+ "Unexpected type variable '${variable}'"
+ " in constant '${constant.toDartText()}'");
}
- typeName = _namer.runtimeTypeName(element);
- return new jsAst.Call(getHelperProperty(_commonElements.createRuntimeType),
- [js.quoteName(typeName)]);
+
+ jsAst.Expression rti =
+ _rtiEncoder.getTypeRepresentation(_emitter, type, unexpected);
+
+ return new jsAst.Call(
+ getHelperProperty(_commonElements.createRuntimeType), [rti]);
}
@override
diff --git a/pkg/compiler/lib/src/js_backend/enqueuer.dart b/pkg/compiler/lib/src/js_backend/enqueuer.dart
index 4e72531..7d9d0b3 100644
--- a/pkg/compiler/lib/src/js_backend/enqueuer.dart
+++ b/pkg/compiler/lib/src/js_backend/enqueuer.dart
@@ -210,6 +210,9 @@
_worldBuilder.registerTypeVariableTypeLiteral(type);
}
break;
+ case TypeUseKind.RTI_VALUE:
+ _worldBuilder.registerTypeArgument(type);
+ break;
}
}
diff --git a/pkg/compiler/lib/src/js_backend/impact_transformer.dart b/pkg/compiler/lib/src/js_backend/impact_transformer.dart
index b7a388a..a4fb279 100644
--- a/pkg/compiler/lib/src/js_backend/impact_transformer.dart
+++ b/pkg/compiler/lib/src/js_backend/impact_transformer.dart
@@ -202,6 +202,9 @@
}
hasTypeLiteral = true;
break;
+ case TypeUseKind.RTI_VALUE:
+ failedAt(CURRENT_ELEMENT_SPANNABLE, "Unexpected type use: $typeUse.");
+ break;
}
}
diff --git a/pkg/compiler/lib/src/js_backend/runtime_types.dart b/pkg/compiler/lib/src/js_backend/runtime_types.dart
index 0835bf8..00dd8de 100644
--- a/pkg/compiler/lib/src/js_backend/runtime_types.dart
+++ b/pkg/compiler/lib/src/js_backend/runtime_types.dart
@@ -250,6 +250,7 @@
..checkedInstance = true
..typeArgument = true
..checkedTypeArgument = true
+ ..typeLiteral = true
..functionType = _computeFunctionType(_elementEnvironment, cls,
strongMode: options.strongMode);
classUseMap[cls] = classUse;
@@ -340,10 +341,12 @@
bool isNativeClass = _closedWorld.nativeData.isNativeClass(cls);
if (classUse.typeArgument ||
+ classUse.typeLiteral ||
(isNativeClass && classUse.checkedInstance)) {
Substitution substitution = computeSubstitution(cls, cls);
// We need [cls] at runtime - even if [cls] is not instantiated. Either
- // as a type argument or for an is-test if [cls] is native.
+ // as a type argument, for a type literal or for an is-test if [cls] is
+ // native.
checks.add(new TypeCheck(cls, substitution, needsIs: isNativeClass));
}
@@ -492,7 +495,7 @@
for (ClassEntity cls in classUseMap.keys) {
ClassUse classUse = classUseMap[cls] ?? emptyUse;
- if (classUse.instance || classUse.typeArgument) {
+ if (classUse.instance || classUse.typeArgument || classUse.typeLiteral) {
// Add checks only for classes that are live either as instantiated
// classes or type arguments passed at runtime.
computeChecks(cls);
@@ -1935,54 +1938,69 @@
Set<FunctionType> checkedFunctionTypes = new Set<FunctionType>();
TypeVisitor liveTypeVisitor =
- new TypeVisitor(onClass: (ClassEntity cls, {bool inTypeArgument}) {
+ new TypeVisitor(onClass: (ClassEntity cls, {TypeVisitorState state}) {
ClassUse classUse = classUseMap.putIfAbsent(cls, () => new ClassUse());
- if (inTypeArgument) {
- classUse.typeArgument = true;
+ switch (state) {
+ case TypeVisitorState.typeArgument:
+ classUse.typeArgument = true;
+ break;
+ case TypeVisitorState.typeLiteral:
+ classUse.typeLiteral = true;
+ break;
+ case TypeVisitorState.direct:
+ break;
}
});
TypeVisitor testedTypeVisitor =
- new TypeVisitor(onClass: (ClassEntity cls, {bool inTypeArgument}) {
+ new TypeVisitor(onClass: (ClassEntity cls, {TypeVisitorState state}) {
ClassUse classUse = classUseMap.putIfAbsent(cls, () => new ClassUse());
- if (inTypeArgument) {
- classUse.typeArgument = true;
- classUse.checkedTypeArgument = true;
- } else {
- classUse.checkedInstance = true;
+ switch (state) {
+ case TypeVisitorState.typeArgument:
+ classUse.typeArgument = true;
+ classUse.checkedTypeArgument = true;
+ break;
+ case TypeVisitorState.typeLiteral:
+ break;
+ case TypeVisitorState.direct:
+ classUse.checkedInstance = true;
+ break;
}
});
codegenWorldBuilder.instantiatedTypes.forEach((InterfaceType type) {
- liveTypeVisitor.visitType(type, false);
+ liveTypeVisitor.visitType(type, TypeVisitorState.direct);
ClassUse classUse =
classUseMap.putIfAbsent(type.element, () => new ClassUse());
classUse.instance = true;
FunctionType callType = _types.getCallType(type);
if (callType != null) {
- testedTypeVisitor.visitType(callType, false);
+ testedTypeVisitor.visitType(callType, TypeVisitorState.direct);
}
});
for (FunctionEntity element
in codegenWorldBuilder.staticFunctionsNeedingGetter) {
FunctionType functionType = _elementEnvironment.getFunctionType(element);
- testedTypeVisitor.visitType(functionType, false);
+ testedTypeVisitor.visitType(functionType, TypeVisitorState.direct);
}
for (FunctionEntity element in codegenWorldBuilder.closurizedMembers) {
FunctionType functionType = _elementEnvironment.getFunctionType(element);
- testedTypeVisitor.visitType(functionType, false);
+ testedTypeVisitor.visitType(functionType, TypeVisitorState.direct);
}
void processMethodTypeArguments(_, Set<DartType> typeArguments) {
for (DartType typeArgument in typeArguments) {
- liveTypeVisitor.visit(typeArgument, true);
+ liveTypeVisitor.visit(typeArgument, TypeVisitorState.typeArgument);
}
}
codegenWorldBuilder.forEachStaticTypeArgument(processMethodTypeArguments);
codegenWorldBuilder.forEachDynamicTypeArgument(processMethodTypeArguments);
+ codegenWorldBuilder.constTypeLiterals.forEach((DartType type) {
+ liveTypeVisitor.visitType(type, TypeVisitorState.typeLiteral);
+ });
bool isFunctionChecked = false;
@@ -1993,7 +2011,7 @@
isFunctionChecked =
isFunctionChecked || t.element == _commonElements.functionClass;
}
- testedTypeVisitor.visitType(t, false);
+ testedTypeVisitor.visitType(t, TypeVisitorState.direct);
}
explicitIsChecks.forEach(processCheckedType);
@@ -2057,7 +2075,7 @@
DartType bound =
_elementEnvironment.getTypeVariableBound(typeVariable.element);
processCheckedType(bound);
- liveTypeVisitor.visit(bound, true);
+ liveTypeVisitor.visit(bound, TypeVisitorState.typeArgument);
}
}
}
@@ -2334,6 +2352,7 @@
final NativeBasicData _nativeData;
// If true, compile using strong mode.
final bool _strongMode;
+
OnVariableCallback onVariable;
ShouldEncodeTypedefCallback shouldEncodeTypedef;
Map<TypeVariableType, jsAst.Expression> typedefBindings;
@@ -2413,7 +2432,7 @@
jsAst.Expression visitInterfaceType(InterfaceType type, Emitter emitter) {
jsAst.Expression name = getJavaScriptClassName(type.element, emitter);
jsAst.Expression result;
- if (type.treatAsRaw) {
+ if ((!_strongMode && type.treatAsRaw) || type.typeArguments.isEmpty) {
result = name;
} else {
// Visit all type arguments. This is done even for jsinterop classes to
@@ -2770,64 +2789,73 @@
'TypeCheck(cls=$cls,needsIs=$needsIs,substitution=$substitution)';
}
-class TypeVisitor extends DartTypeVisitor<void, bool> {
+enum TypeVisitorState { direct, typeArgument, typeLiteral }
+
+class TypeVisitor extends DartTypeVisitor<void, TypeVisitorState> {
Set<FunctionTypeVariable> _visitedFunctionTypeVariables =
new Set<FunctionTypeVariable>();
- final void Function(ClassEntity entity, {bool inTypeArgument}) onClass;
- final void Function(TypeVariableEntity entity, {bool inTypeArgument})
+ final void Function(ClassEntity entity, {TypeVisitorState state}) onClass;
+ final void Function(TypeVariableEntity entity, {TypeVisitorState state})
onTypeVariable;
- final void Function(FunctionType type, {bool inTypeArgument}) onFunctionType;
+ final void Function(FunctionType type, {TypeVisitorState state})
+ onFunctionType;
TypeVisitor({this.onClass, this.onTypeVariable, this.onFunctionType});
- visitType(DartType type, bool inTypeArgument) =>
- type.accept(this, inTypeArgument);
+ visitType(DartType type, TypeVisitorState state) => type.accept(this, state);
- visitTypes(List<DartType> types, bool inTypeArgument) {
+ visitTypes(List<DartType> types, TypeVisitorState state) {
for (DartType type in types) {
- visitType(type, inTypeArgument);
+ visitType(type, state);
}
}
@override
- void visitTypeVariableType(TypeVariableType type, bool inTypeArgument) {
+ void visitTypeVariableType(TypeVariableType type, TypeVisitorState state) {
if (onTypeVariable != null) {
- onTypeVariable(type.element, inTypeArgument: inTypeArgument);
+ onTypeVariable(type.element, state: state);
}
}
@override
- visitInterfaceType(InterfaceType type, bool inTypeArgument) {
+ visitInterfaceType(InterfaceType type, TypeVisitorState state) {
if (onClass != null) {
- onClass(type.element, inTypeArgument: inTypeArgument);
+ onClass(type.element, state: state);
}
- visitTypes(type.typeArguments, true);
+ visitTypes(
+ type.typeArguments,
+ state == TypeVisitorState.typeLiteral
+ ? state
+ : TypeVisitorState.typeArgument);
}
@override
- visitFunctionType(FunctionType type, bool inTypeArgument) {
+ visitFunctionType(FunctionType type, TypeVisitorState state) {
if (onFunctionType != null) {
- onFunctionType(type, inTypeArgument: inTypeArgument);
+ onFunctionType(type, state: state);
}
// Visit all nested types as type arguments; these types are not runtime
// instances but runtime type representations.
- visitType(type.returnType, true);
- visitTypes(type.parameterTypes, true);
- visitTypes(type.optionalParameterTypes, true);
- visitTypes(type.namedParameterTypes, true);
+ state = state == TypeVisitorState.typeLiteral
+ ? state
+ : TypeVisitorState.typeArgument;
+ visitType(type.returnType, state);
+ visitTypes(type.parameterTypes, state);
+ visitTypes(type.optionalParameterTypes, state);
+ visitTypes(type.namedParameterTypes, state);
_visitedFunctionTypeVariables.removeAll(type.typeVariables);
}
@override
- visitTypedefType(TypedefType type, bool inTypeArgument) {
- visitType(type.unaliased, inTypeArgument);
+ visitTypedefType(TypedefType type, TypeVisitorState state) {
+ visitType(type.unaliased, state);
}
@override
- visitFunctionTypeVariable(FunctionTypeVariable type, bool inTypeArgument) {
+ visitFunctionTypeVariable(FunctionTypeVariable type, TypeVisitorState state) {
if (_visitedFunctionTypeVariables.add(type)) {
- visitType(type.bound, inTypeArgument);
+ visitType(type.bound, state);
}
}
}
@@ -2914,6 +2942,17 @@
///
bool checkedTypeArgument = false;
+ /// Whether the class is used in a constant type literal.
+ ///
+ /// For instance `A`, `B` and `C` in:
+ ///
+ /// class A {}
+ /// class B<T> {}
+ /// class C {}
+ /// main() => A == B<C>;
+ ///
+ bool typeLiteral = false;
+
/// The function type of the class, if any.
///
/// This is only set if the function type is needed at runtime. For instance,
@@ -2942,6 +2981,9 @@
if (checkedTypeArgument) {
properties.add('checkedTypeArgument');
}
+ if (typeLiteral) {
+ properties.add('rtiValue');
+ }
if (functionType != null) {
properties.add('functionType');
}
diff --git a/pkg/compiler/lib/src/js_emitter/full_emitter/emitter.dart b/pkg/compiler/lib/src/js_emitter/full_emitter/emitter.dart
index b8f4d31..d9910c9 100644
--- a/pkg/compiler/lib/src/js_emitter/full_emitter/emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/full_emitter/emitter.dart
@@ -167,7 +167,6 @@
_closedWorld.rtiNeed,
compiler.backend.rtiEncoder,
_closedWorld.allocatorAnalysis,
- namer,
task,
this.constantReference,
constantListGenerator);
diff --git a/pkg/compiler/lib/src/js_emitter/startup_emitter/model_emitter.dart b/pkg/compiler/lib/src/js_emitter/startup_emitter/model_emitter.dart
index 46bce90..2f22884 100644
--- a/pkg/compiler/lib/src/js_emitter/startup_emitter/model_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/startup_emitter/model_emitter.dart
@@ -84,7 +84,6 @@
_closedWorld.rtiNeed,
compiler.backend.rtiEncoder,
_closedWorld.allocatorAnalysis,
- namer,
task,
this.generateConstantReference,
constantListGenerator);
diff --git a/pkg/compiler/lib/src/js_model/elements.dart b/pkg/compiler/lib/src/js_model/elements.dart
index 79be26a..17de922 100644
--- a/pkg/compiler/lib/src/js_model/elements.dart
+++ b/pkg/compiler/lib/src/js_model/elements.dart
@@ -276,7 +276,9 @@
@override
DartType visitTypedefType(TypedefType type, EntityConverter converter) {
return new TypedefType(
- converter(type.element), visitList(type.typeArguments, converter));
+ converter(type.element),
+ visitList(type.typeArguments, converter),
+ visit(type.unaliased, converter));
}
@override
diff --git a/pkg/compiler/lib/src/js_model/js_strategy.dart b/pkg/compiler/lib/src/js_model/js_strategy.dart
index 9179c63..a613ed6 100644
--- a/pkg/compiler/lib/src/js_model/js_strategy.dart
+++ b/pkg/compiler/lib/src/js_model/js_strategy.dart
@@ -827,7 +827,8 @@
DartType visitTypedefType(TypedefType type, _) {
var element = toBackendEntity(type.element);
var args = _visitList(type.typeArguments);
- return new TypedefType(element, args);
+ var unaliased = convert(type.unaliased);
+ return new TypedefType(element, args, unaliased);
}
List<DartType> _visitList(List<DartType> list) =>
diff --git a/pkg/compiler/lib/src/kernel/element_map_impl.dart b/pkg/compiler/lib/src/kernel/element_map_impl.dart
index 0623dec..cdbfe78 100644
--- a/pkg/compiler/lib/src/kernel/element_map_impl.dart
+++ b/pkg/compiler/lib/src/kernel/element_map_impl.dart
@@ -983,7 +983,8 @@
TypedefType typedefType = new TypedefType(
typedef,
new List<DartType>.filled(
- node.typeParameters.length, const DynamicType()));
+ node.typeParameters.length, const DynamicType()),
+ getDartType(node.type));
return _typedefs.register(
typedef, new TypedefData(node, typedef, typedefType));
}
@@ -1820,6 +1821,11 @@
elementMap.getTypeVariable(node.parameter));
}
}
+ if (node.parameter.parent is ir.Typedef) {
+ // Typedefs are only used in type literals so we never need their type
+ // variables.
+ return const DynamicType();
+ }
return new TypeVariableType(elementMap.getTypeVariable(node.parameter));
}
@@ -2319,7 +2325,8 @@
new TypedefType(
newTypedef,
new List<DartType>.filled(
- data.node.typeParameters.length, const DynamicType()))));
+ data.node.typeParameters.length, const DynamicType()),
+ getDartType(data.node.type))));
assert(newTypedef.typedefIndex == oldTypedef.typedefIndex);
}
for (int memberIndex = 0;
diff --git a/pkg/compiler/lib/src/ssa/builder_kernel.dart b/pkg/compiler/lib/src/ssa/builder_kernel.dart
index 82c06b1..78867a0 100644
--- a/pkg/compiler/lib/src/ssa/builder_kernel.dart
+++ b/pkg/compiler/lib/src/ssa/builder_kernel.dart
@@ -2853,14 +2853,8 @@
dartType, sourceElement,
sourceInformation: sourceInformation);
_pushStaticInvocation(
- _commonElements.runtimeTypeToString,
- <HInstruction>[value],
- abstractValueDomain.stringType,
- const <DartType>[],
- sourceInformation: sourceInformation);
- _pushStaticInvocation(
_commonElements.createRuntimeType,
- <HInstruction>[pop()],
+ <HInstruction>[value],
_typeInferenceMap.getReturnTypeOf(_commonElements.createRuntimeType),
const <DartType>[],
sourceInformation: sourceInformation);
diff --git a/pkg/compiler/lib/src/ssa/codegen.dart b/pkg/compiler/lib/src/ssa/codegen.dart
index d72a6b5..947432d 100644
--- a/pkg/compiler/lib/src/ssa/codegen.dart
+++ b/pkg/compiler/lib/src/ssa/codegen.dart
@@ -2208,6 +2208,11 @@
generateConstant(node.constant, node.sourceInformation);
_registry.registerConstantUse(new ConstantUse.literal(node.constant));
+ if (node.constant.isType) {
+ TypeConstantValue typeConstant = node.constant;
+ _registry.registerTypeUse(
+ new TypeUse.constTypeLiteral(typeConstant.representedType));
+ }
}
visitNot(HNot node) {
diff --git a/pkg/compiler/lib/src/universe/codegen_world_builder.dart b/pkg/compiler/lib/src/universe/codegen_world_builder.dart
index fecaed8..8c448bd 100644
--- a/pkg/compiler/lib/src/universe/codegen_world_builder.dart
+++ b/pkg/compiler/lib/src/universe/codegen_world_builder.dart
@@ -77,6 +77,9 @@
/// an ordering that is less sensitive to perturbations in the source code.
List<ConstantValue> getConstantsForEmission(
[Comparator<ConstantValue> preSortCompare]);
+
+ /// Returns the types that are live as constant type literals.
+ Iterable<DartType> get constTypeLiterals;
}
class CodegenWorldBuilderImpl extends WorldBuilderBase
@@ -162,6 +165,8 @@
final KernelToWorldBuilder _elementMap;
final GlobalLocalsMap _globalLocalsMap;
+ final Set<DartType> _liveTypeArguments = new Set<DartType>();
+
CodegenWorldBuilderImpl(
this._elementMap,
this._globalLocalsMap,
@@ -688,4 +693,10 @@
f(member);
});
}
+
+ void registerTypeArgument(DartType type) {
+ _liveTypeArguments.add(type);
+ }
+
+ Iterable<DartType> get constTypeLiterals => _liveTypeArguments;
}
diff --git a/pkg/compiler/lib/src/universe/use.dart b/pkg/compiler/lib/src/universe/use.dart
index 0db511d..5cfeed7 100644
--- a/pkg/compiler/lib/src/universe/use.dart
+++ b/pkg/compiler/lib/src/universe/use.dart
@@ -582,6 +582,7 @@
NATIVE_INSTANTIATION,
IMPLICIT_CAST,
PARAMETER_CHECK,
+ RTI_VALUE,
}
/// Use of a [DartType].
@@ -629,6 +630,9 @@
case TypeUseKind.PARAMETER_CHECK:
sb.write('param:');
break;
+ case TypeUseKind.RTI_VALUE:
+ sb.write('typeArg:');
+ break;
}
sb.write(type);
return sb.toString();
@@ -692,6 +696,11 @@
return new TypeUse.internal(type, TypeUseKind.NATIVE_INSTANTIATION);
}
+ /// [type] used as a direct RTI value.
+ factory TypeUse.constTypeLiteral(DartType type) {
+ return new TypeUse.internal(type, TypeUseKind.RTI_VALUE);
+ }
+
bool operator ==(other) {
if (identical(this, other)) return true;
if (other is! TypeUse) return false;
diff --git a/sdk/lib/_internal/js_runtime/lib/js_helper.dart b/sdk/lib/_internal/js_runtime/lib/js_helper.dart
index 9e2f105..6e5d05d 100644
--- a/sdk/lib/_internal/js_runtime/lib/js_helper.dart
+++ b/sdk/lib/_internal/js_runtime/lib/js_helper.dart
@@ -348,8 +348,7 @@
int start = _arguments.length - _typeArgumentCount;
var list = <Type>[];
for (int index = 0; index < _typeArgumentCount; index++) {
- list.add(
- createRuntimeType(runtimeTypeToString(_arguments[start + index])));
+ list.add(createRuntimeType(_arguments[start + index]));
}
return list;
}
@@ -3027,7 +3026,8 @@
toString() {
var receiver = _receiver == null ? _self : _receiver;
- return "Closure '$_name' of ${Primitives.objectToHumanReadableString(receiver)}";
+ return "Closure '$_name' of "
+ "${Primitives.objectToHumanReadableString(receiver)}";
}
@NoInline()
@@ -3062,8 +3062,8 @@
@NoSideEffects()
static String computeFieldNamed(String fieldName) {
var template = new BoundClosure('self', 'target', 'receiver', 'name');
- var names = JSArray
- .markFixedList(JS('', 'Object.getOwnPropertyNames(#)', template));
+ var names = JSArray.markFixedList(
+ JS('', 'Object.getOwnPropertyNames(#)', template));
for (int i = 0; i < names.length; i++) {
var name = names[i];
if (JS('bool', '#[#] === #', template, name, fieldName)) {
@@ -3556,8 +3556,8 @@
/// Normal type error caused by a failed subtype test.
TypeErrorImplementation(Object value, String type)
- : message = "TypeError: ${Error.safeToString(value)}: "
- "type '${_typeDescription(value)}' is not a subtype of type '$type'";
+ : message = "TypeError: ${Error.safeToString(value)}: type "
+ "'${_typeDescription(value)}' is not a subtype of type '$type'";
TypeErrorImplementation.fromMessage(String this.message);
@@ -3571,8 +3571,8 @@
/// Normal cast error caused by a failed type cast.
CastErrorImplementation(Object value, Object type)
- : message = "CastError: ${Error.safeToString(value)}: "
- "type '${_typeDescription(value)}' is not a subtype of type '$type'";
+ : message = "CastError: ${Error.safeToString(value)}: type "
+ "'${_typeDescription(value)}' is not a subtype of type '$type'";
String toString() => message;
}
diff --git a/sdk/lib/_internal/js_runtime/lib/js_rti.dart b/sdk/lib/_internal/js_runtime/lib/js_rti.dart
index 74a6352..f724172 100644
--- a/sdk/lib/_internal/js_runtime/lib/js_rti.dart
+++ b/sdk/lib/_internal/js_runtime/lib/js_rti.dart
@@ -42,26 +42,28 @@
part of _js_helper;
-Type createRuntimeType(String name) {
- // Use a 'JS' cast to String. Since this is registered as used by the
- // backend, type inference assumes the worst (name is dynamic).
- return new TypeImpl(JS('String', '#', name));
+/// Called from generated code.
+Type createRuntimeType(rti) {
+ return new TypeImpl(rti);
}
class TypeImpl implements Type {
- final String _typeName;
+ final dynamic _rti;
+ String __typeName;
String _unmangledName;
+ int _hashCode;
- TypeImpl(this._typeName);
+ TypeImpl(this._rti);
+
+ String get _typeName => __typeName ??= runtimeTypeToString(_rti);
String toString() {
- if (_unmangledName != null) return _unmangledName;
- String unmangledName = unmangleAllIdentifiersIfPreservedAnyways(_typeName);
- return _unmangledName = unmangledName;
+ return _unmangledName ??=
+ unmangleAllIdentifiersIfPreservedAnyways(_typeName);
}
// TODO(ahe): This is a poor hashCode as it collides with its name.
- int get hashCode => _typeName.hashCode;
+ int get hashCode => _hashCode ??= _typeName.hashCode;
bool operator ==(other) {
return (other is TypeImpl) && _typeName == other._typeName;
@@ -171,10 +173,10 @@
* of type 4, the JavaScript array, where the first element represents the class
* and the remaining elements represent the type arguments.
*/
-String _getRuntimeTypeAsStringV1(var rti, {String onTypeVariable(int i)}) {
+String _getRuntimeTypeAsStringV1(var rti) {
assert(isJsArray(rti));
String className = rawRtiToJsConstructorName(getIndex(rti, 0));
- return '$className${joinArgumentsV1(rti, 1, onTypeVariable: onTypeVariable)}';
+ return '$className${joinArgumentsV1(rti, 1)}';
}
String _getRuntimeTypeAsStringV2(var rti, List<String> genericContext) {
@@ -186,29 +188,27 @@
/// Returns a human-readable representation of the type representation [rti].
///
/// Called from generated code.
-///
-/// [onTypeVariable] is used only from dart:mirrors.
@NoInline()
-String runtimeTypeToString(var rti, {String onTypeVariable(int i)}) {
+String runtimeTypeToString(var rti) {
return JS_GET_FLAG('STRONG_MODE')
? runtimeTypeToStringV2(rti, null)
- : runtimeTypeToStringV1(rti, onTypeVariable: onTypeVariable);
+ : runtimeTypeToStringV1(rti);
}
-String runtimeTypeToStringV1(var rti, {String onTypeVariable(int i)}) {
+String runtimeTypeToStringV1(var rti) {
if (rti == null) {
return 'dynamic';
}
if (isJsArray(rti)) {
// A list representing a type with arguments.
- return _getRuntimeTypeAsStringV1(rti, onTypeVariable: onTypeVariable);
+ return _getRuntimeTypeAsStringV1(rti);
}
if (isJsFunction(rti)) {
// A reference to the constructor.
return rawRtiToJsConstructorName(rti);
}
if (rti is int) {
- return '${onTypeVariable == null ? rti : onTypeVariable(rti)}';
+ return '${rti}';
}
String functionPropertyName = JS_GET_NAME(JsGetName.FUNCTION_TYPE_TAG);
if (JS('bool', 'typeof #[#] != "undefined"', rti, functionPropertyName)) {
@@ -218,9 +218,9 @@
String typedefPropertyName = JS_GET_NAME(JsGetName.TYPEDEF_TAG);
var typedefInfo = JS('', '#[#]', rti, typedefPropertyName);
if (typedefInfo != null) {
- return runtimeTypeToStringV1(typedefInfo, onTypeVariable: onTypeVariable);
+ return runtimeTypeToStringV1(typedefInfo);
}
- return _functionRtiToStringV1(rti, onTypeVariable);
+ return _functionRtiToStringV1(rti);
}
// We should not get here.
return 'unknown-reified-type';
@@ -263,7 +263,7 @@
return 'unknown-reified-type';
}
-String _functionRtiToStringV1(var rti, String onTypeVariable(int i)) {
+String _functionRtiToStringV1(var rti) {
String returnTypeText;
String voidTag = JS_GET_NAME(JsGetName.FUNCTION_TYPE_VOID_RETURN_TAG);
if (JS('bool', '!!#[#]', rti, voidTag)) {
@@ -271,8 +271,7 @@
} else {
String returnTypeTag = JS_GET_NAME(JsGetName.FUNCTION_TYPE_RETURN_TYPE_TAG);
var returnRti = JS('', '#[#]', rti, returnTypeTag);
- returnTypeText =
- runtimeTypeToStringV1(returnRti, onTypeVariable: onTypeVariable);
+ returnTypeText = runtimeTypeToStringV1(returnRti);
}
String argumentsText = '';
@@ -285,8 +284,7 @@
List arguments = JS('JSFixedArray', '#[#]', rti, requiredParamsTag);
for (var argument in arguments) {
argumentsText += sep;
- argumentsText +=
- runtimeTypeToStringV1(argument, onTypeVariable: onTypeVariable);
+ argumentsText += runtimeTypeToStringV1(argument);
sep = ', ';
}
}
@@ -300,8 +298,7 @@
sep = '';
for (var argument in optionalArguments) {
argumentsText += sep;
- argumentsText +=
- runtimeTypeToStringV1(argument, onTypeVariable: onTypeVariable);
+ argumentsText += runtimeTypeToStringV1(argument);
sep = ', ';
}
argumentsText += ']';
@@ -316,9 +313,8 @@
sep = '';
for (String name in extractKeys(namedArguments)) {
argumentsText += sep;
- argumentsText += runtimeTypeToStringV1(
- JS('', '#[#]', namedArguments, name),
- onTypeVariable: onTypeVariable);
+ argumentsText +=
+ runtimeTypeToStringV1(JS('', '#[#]', namedArguments, name));
argumentsText += ' $name';
sep = ', ';
}
@@ -454,8 +450,7 @@
: joinArgumentsV1(types, startIndex);
}
-String joinArgumentsV1(var types, int startIndex,
- {String onTypeVariable(int i)}) {
+String joinArgumentsV1(var types, int startIndex) {
if (types == null) return '';
assert(isJsArray(types));
bool firstArgument = true;
@@ -471,8 +466,7 @@
if (argument != null) {
allDynamic = false;
}
- buffer
- .write(runtimeTypeToStringV1(argument, onTypeVariable: onTypeVariable));
+ buffer.write(runtimeTypeToStringV1(argument));
}
return allDynamic ? '' : '<$buffer>';
}
@@ -480,22 +474,19 @@
String joinArgumentsV2(var types, int startIndex, List<String> genericContext) {
if (types == null) return '';
assert(isJsArray(types));
- bool firstArgument = true;
+ var separator = '';
bool allDynamic = true;
StringBuffer buffer = new StringBuffer('');
for (int index = startIndex; index < getLength(types); index++) {
- if (firstArgument) {
- firstArgument = false;
- } else {
- buffer.write(', ');
- }
+ buffer.write(separator);
+ separator = ', ';
var argument = getIndex(types, index);
if (argument != null) {
allDynamic = false;
}
buffer.write(runtimeTypeToStringV2(argument, genericContext));
}
- return allDynamic ? '' : '<$buffer>';
+ return (!JS_GET_FLAG('STRONG_MODE') && allDynamic) ? '' : '<$buffer>';
}
/**
@@ -519,9 +510,32 @@
return "$className${joinArguments(rti, 0)}";
}
+/// Returns the full type of [o] in the runtime type representation.
+getRti(o) {
+ if (o is Closure) {
+ // This excludes classes that implement Function via a `call` method, but
+ // includes classes generated to represent closures in closure conversion.
+ var functionRti = extractFunctionTypeObjectFrom(o);
+ if (functionRti != null) return functionRti;
+ }
+ var interceptor = getInterceptor(o);
+ var type = getRawRuntimeType(interceptor);
+ if (o == null) return type;
+ if (JS('bool', 'typeof # != "object"', o)) return type;
+ var rti = getRuntimeTypeInfo(o);
+ if (rti != null) {
+ // If the type has type variables (that is, `rti != null`), make a copy of
+ // the type arguments and insert [o] in the first position to create a
+ // compound type representation.
+ rti = JS('JSExtendableArray', '#.slice()', rti); // Make a copy.
+ JS('', '#.splice(0, 0, #)', rti, type); // Insert type at position 0.
+ type = rti;
+ }
+ return type;
+}
+
Type getRuntimeType(var object) {
- String type = getRuntimeTypeString(object);
- return new TypeImpl(type);
+ return new TypeImpl(getRti(object));
}
/**
diff --git a/tests/co19/co19-dart2js.status b/tests/co19/co19-dart2js.status
index 4c34ac7..deb4a7f 100644
--- a/tests/co19/co19-dart2js.status
+++ b/tests/co19/co19-dart2js.status
@@ -616,7 +616,6 @@
LayoutTests/fast/dom/Range/range-expand_t01: RuntimeError # Please triage this failure
LayoutTests/fast/dom/Range/range-insertNode-separate-endContainer_t01: RuntimeError # Please triage this failure
LayoutTests/fast/dom/Range/range-insertNode-splittext_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/dom/SelectorAPI/dumpNodeList-2_t01: RuntimeError # Please triage this failure
LayoutTests/fast/dom/StyleSheet/css-medialist-item_t01: RuntimeError # Please triage this failure
LayoutTests/fast/dom/StyleSheet/detached-parent-rule-without-wrapper_t01: RuntimeError # Please triage this failure
LayoutTests/fast/dom/StyleSheet/detached-stylesheet-without-wrapper_t01: RuntimeError # Please triage this failure
@@ -662,7 +661,6 @@
LayoutTests/fast/dom/set-innerHTML_t01: RuntimeError # Please triage this failure
LayoutTests/fast/dom/shadow/distribution-crash_t01: RuntimeError
LayoutTests/fast/dom/shadow/distribution-update-recalcs-style_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/dom/shadow/event-path_t01: RuntimeError # Please triage this failure
LayoutTests/fast/dom/shadow/insertion-point-list-menu-crash_t01: RuntimeError
LayoutTests/fast/dom/shadow/insertion-point-shadow-crash_t01: RuntimeError
LayoutTests/fast/dom/shadow/insertion-point-video-crash_t01: RuntimeError
@@ -1744,7 +1742,6 @@
LayoutTests/fast/dom/Range/range-detached-exceptions_t01: RuntimeError # Please triage this failure
LayoutTests/fast/dom/Range/range-insertNode-separate-endContainer_t01: RuntimeError # Please triage this failure
LayoutTests/fast/dom/Range/range-insertNode-splittext_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/dom/SelectorAPI/dumpNodeList-2_t01: RuntimeError # Please triage this failure
LayoutTests/fast/dom/StyleSheet/css-medialist-item_t01: RuntimeError # Please triage this failure
LayoutTests/fast/dom/StyleSheet/detached-stylesheet-without-wrapper_t01: RuntimeError # Please triage this failure
LayoutTests/fast/dom/Window/getMatchedCSSRules-with-pseudo-elements-complex_t01: Pass, RuntimeError # Issue 29634
@@ -1771,7 +1768,6 @@
LayoutTests/fast/dom/partial-layout-overlay-scrollbars_t01: RuntimeError # Please triage this failure
LayoutTests/fast/dom/set-innerHTML_t01: RuntimeError # Please triage this failure
LayoutTests/fast/dom/shadow/content-pseudo-element-css-text_t01: Pass, RuntimeError # Issue 29634
-LayoutTests/fast/dom/shadow/event-path_t01: RuntimeError # Please triage this failure
LayoutTests/fast/dom/shadow/host-context-pseudo-class-css-text_t01: Pass, RuntimeError # Issue 29634
LayoutTests/fast/dom/shadow/host-pseudo-class-css-text_t01: Pass, RuntimeError # Issue 29634
LayoutTests/fast/dom/shadow/pseudoclass-update-checked-option_t01: RuntimeError # Please triage this failure
@@ -2713,7 +2709,6 @@
LayoutTests/fast/dom/Range/range-insertNode-separate-endContainer_t01: RuntimeError # Please triage this failure
LayoutTests/fast/dom/Range/range-insertNode-splittext_t01: RuntimeError # Please triage this failure
LayoutTests/fast/dom/SelectorAPI/caseTagX_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/dom/SelectorAPI/dumpNodeList-2_t01: RuntimeError # Please triage this failure
LayoutTests/fast/dom/StyleSheet/css-insert-import-rule-to-shadow-stylesheets_t01: RuntimeError # Please triage this failure
LayoutTests/fast/dom/StyleSheet/css-medialist-item_t01: RuntimeError # Please triage this failure
LayoutTests/fast/dom/StyleSheet/detached-parent-rule-without-wrapper_t01: RuntimeError # Please triage this failure
@@ -2810,7 +2805,6 @@
LayoutTests/fast/dom/shadow/elementfrompoint_t01: RuntimeError # Please triage this failure
LayoutTests/fast/dom/shadow/elements-in-frameless-document_t01: RuntimeError # Issue 28983
LayoutTests/fast/dom/shadow/event-path-not-in-document_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/dom/shadow/event-path_t01: RuntimeError # Please triage this failure
LayoutTests/fast/dom/shadow/form-in-shadow_t01: RuntimeError # Please triage this failure
LayoutTests/fast/dom/shadow/get-distributed-nodes-orphan_t01: RuntimeError # Please triage this failure
LayoutTests/fast/dom/shadow/get-element-by-id-in-shadow-mutation_t01: RuntimeError # Please triage this failure
@@ -4311,7 +4305,6 @@
LayoutTests/fast/dom/Selection/getRangeAt_t01: RuntimeError # Please triage this failure
LayoutTests/fast/dom/SelectorAPI/caseID_t01: RuntimeError # Please triage this failure
LayoutTests/fast/dom/SelectorAPI/caseTagX_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/dom/SelectorAPI/dumpNodeList-2_t01: RuntimeError # Please triage this failure
LayoutTests/fast/dom/StyleSheet/css-insert-import-rule-to-shadow-stylesheets_t01: RuntimeError # Please triage this failure
LayoutTests/fast/dom/StyleSheet/css-medialist-item_t01: RuntimeError # Please triage this failure
LayoutTests/fast/dom/StyleSheet/detached-parent-rule-without-wrapper_t01: RuntimeError # Please triage this failure
@@ -4440,7 +4433,6 @@
LayoutTests/fast/dom/shadow/distribution-update-recalcs-style_t01: RuntimeError # Please triage this failure
LayoutTests/fast/dom/shadow/elementfrompoint_t01: RuntimeError # Please triage this failure
LayoutTests/fast/dom/shadow/elements-in-frameless-document_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/dom/shadow/event-path_t01: RuntimeError # Please triage this failure
LayoutTests/fast/dom/shadow/get-distributed-nodes-orphan_t01: RuntimeError # Please triage this failure
LayoutTests/fast/dom/shadow/get-element-by-id-in-shadow-mutation_t01: RuntimeError # Please triage this failure
LayoutTests/fast/dom/shadow/getComputedStyle-composed-parent-dirty_t01: RuntimeError # Please triage this failure
@@ -5885,7 +5877,6 @@
LayoutTests/fast/dom/Range/range-isPointInRange_t01: RuntimeError # Please triage this failure
LayoutTests/fast/dom/Range/range-on-detached-node_t01: RuntimeError # Please triage this failure
LayoutTests/fast/dom/Range/surroundContents-for-detached-node_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/dom/SelectorAPI/dumpNodeList-2_t01: RuntimeError # Please triage this failure
LayoutTests/fast/dom/StyleSheet/css-insert-import-rule-to-shadow-stylesheets_t01: RuntimeError # Please triage this failure
LayoutTests/fast/dom/StyleSheet/css-medialist-item_t01: RuntimeError # Please triage this failure
LayoutTests/fast/dom/StyleSheet/detached-shadow-style_t01: RuntimeError # Please triage this failure
@@ -5961,7 +5952,6 @@
LayoutTests/fast/dom/shadow/elementfrompoint_t01: RuntimeError # Please triage this failure
LayoutTests/fast/dom/shadow/elements-in-frameless-document_t01: RuntimeError # Please triage this failure
LayoutTests/fast/dom/shadow/event-path-not-in-document_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/dom/shadow/event-path_t01: RuntimeError # Please triage this failure
LayoutTests/fast/dom/shadow/form-in-shadow_t01: RuntimeError # Please triage this failure
LayoutTests/fast/dom/shadow/get-distributed-nodes-orphan_t01: RuntimeError # Please triage this failure
LayoutTests/fast/dom/shadow/get-element-by-id-in-shadow-mutation_t01: RuntimeError # Please triage this failure
diff --git a/tests/compiler/dart2js/inference/data/non_null.dart b/tests/compiler/dart2js/inference/data/non_null.dart
new file mode 100644
index 0000000..da87bbe
--- /dev/null
+++ b/tests/compiler/dart2js/inference/data/non_null.dart
@@ -0,0 +1,52 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/*element: main:[null]*/
+main() {
+ nonNullStaticField();
+ nonNullInstanceField1();
+ nonNullInstanceField2();
+ nonNullLocal();
+}
+
+/*element: staticField:[null|exact=JSUInt31]*/
+var staticField;
+
+/*element: nonNullStaticField:[exact=JSUInt31]*/
+nonNullStaticField() => staticField ??= 42;
+
+/*element: Class1.:[exact=Class1]*/
+class Class1 {
+ /*element: Class1.field:[null|exact=JSUInt31]*/
+ var field;
+}
+
+/*element: nonNullInstanceField1:[exact=JSUInt31]*/
+nonNullInstanceField1() {
+ return new Class1(). /*[exact=Class1]*/ /*update: [exact=Class1]*/ field ??=
+ 42;
+}
+
+/*element: Class2.:[exact=Class2]*/
+class Class2 {
+ /*element: Class2.field:[null|exact=JSUInt31]*/
+ var field;
+
+ /*element: Class2.method:[exact=JSUInt31]*/
+ method() {
+ return /*[exact=Class2]*/ /*update: [exact=Class2]*/ field ??= 42;
+ }
+}
+
+/*element: nonNullInstanceField2:[exact=JSUInt31]*/
+nonNullInstanceField2() {
+ return new Class2(). /*invoke: [exact=Class2]*/ method();
+}
+
+// TODO(johnniwinther): We should infer that the returned value cannot be null.
+/*element: nonNullLocal:[null|exact=JSUInt31]*/
+nonNullLocal() {
+ var local = null;
+ return local ??= 42;
+}
diff --git a/tests/compiler/dart2js/inference/data/type_literal.dart b/tests/compiler/dart2js/inference/data/type_literal.dart
new file mode 100644
index 0000000..b0d8246
--- /dev/null
+++ b/tests/compiler/dart2js/inference/data/type_literal.dart
@@ -0,0 +1,25 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/*element: main:[null]*/
+main() {
+ typeLiteral();
+ typeLiteralToString();
+ typeLiteralSubstring();
+}
+
+/*element: typeLiteral:[exact=TypeImpl]*/
+typeLiteral() => Object;
+
+/*kernel.element: typeLiteralToString:[null|subclass=Object]*/
+/*strong.element: typeLiteralToString:[exact=JSString]*/
+typeLiteralToString() => (Object). /*invoke: [exact=TypeImpl]*/ toString();
+
+/*element: typeLiteralSubstring:[exact=JSString]*/
+typeLiteralSubstring() {
+ String name = (List). /*invoke: [exact=TypeImpl]*/ toString();
+ name = name. /*strong.invoke: [exact=JSString]*/ substring(
+ 0, name. /*strong.invoke: [exact=JSString]*/ indexOf('<'));
+ return name;
+}
diff --git a/tests/compiler/dart2js/rti/data/indirect_type_literal.dart b/tests/compiler/dart2js/rti/data/indirect_type_literal.dart
new file mode 100644
index 0000000..bd9a39f
--- /dev/null
+++ b/tests/compiler/dart2js/rti/data/indirect_type_literal.dart
@@ -0,0 +1,23 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+class A<T> {}
+
+class B<T extends num> {}
+
+/*class: Indirect:exp,needsArgs*/
+class Indirect<T> {
+ Type get type => T;
+}
+
+void main() {
+ Expect.equals(A, new Indirect<A>().type);
+ Expect.equals(A, new Indirect<A<dynamic>>().type);
+ Expect.notEquals(A, new Indirect<A<num>>().type);
+ Expect.equals(B, new Indirect<B>().type);
+ Expect.equals(B, new Indirect<B<num>>().type);
+ Expect.notEquals(B, new Indirect<B<int>>().type);
+}
diff --git a/tests/compiler/dart2js/rti/emission/closure_function.dart b/tests/compiler/dart2js/rti/emission/closure_function.dart
index 9b11f64..1874f1a 100644
--- a/tests/compiler/dart2js/rti/emission/closure_function.dart
+++ b/tests/compiler/dart2js/rti/emission/closure_function.dart
@@ -10,6 +10,8 @@
main() {
test(
/*kernel.checks=[],functionType,instance*/
- /*strong.checks=[],instance*/ () {});
+ /*strong.checks=[],instance*/
+ /*omit.checks=[],instance*/
+ () {});
test(null);
}
diff --git a/tests/compiler/dart2js/rti/emission/closure_function_type.dart b/tests/compiler/dart2js/rti/emission/closure_function_type.dart
index 22ffd4f..b37395b 100644
--- a/tests/compiler/dart2js/rti/emission/closure_function_type.dart
+++ b/tests/compiler/dart2js/rti/emission/closure_function_type.dart
@@ -9,5 +9,9 @@
main() {
test(/*checks=[],functionType,instance*/ () {});
- test(/*checks=[],functionType,instance*/ (a) {});
+ test(
+ /*kernel.checks=[],functionType,instance*/
+ /*strong.checks=[],instance*/
+ /*omit.checks=[],instance*/
+ (a) {});
}
diff --git a/tests/compiler/dart2js/rti/emission/closure_signature_unneeded.dart b/tests/compiler/dart2js/rti/emission/closure_signature_unneeded.dart
index 6ffe4e3..52b2ec9 100644
--- a/tests/compiler/dart2js/rti/emission/closure_signature_unneeded.dart
+++ b/tests/compiler/dart2js/rti/emission/closure_signature_unneeded.dart
@@ -13,6 +13,7 @@
return
/*kernel.checks=[$signature],instance*/
/*strong.checks=[],instance*/
+ /*omit.checks=[],instance*/
(T t, String s) {};
}
}
diff --git a/tests/compiler/dart2js/rti/emission/dynamic_type_literal.dart b/tests/compiler/dart2js/rti/emission/dynamic_type_literal.dart
new file mode 100644
index 0000000..8f7ce92
--- /dev/null
+++ b/tests/compiler/dart2js/rti/emission/dynamic_type_literal.dart
@@ -0,0 +1,12 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/*class: global#Type:checks=[],instance,typeLiteral*/
+
+import "package:expect/expect.dart";
+
+void main() {
+ Expect.isTrue(dynamic is Type);
+ Expect.isFalse(dynamic == Type);
+}
diff --git a/tests/compiler/dart2js/rti/emission/function_type_argument_strong.dart b/tests/compiler/dart2js/rti/emission/function_type_argument_strong.dart
index faa845a..cac5f11 100644
--- a/tests/compiler/dart2js/rti/emission/function_type_argument_strong.dart
+++ b/tests/compiler/dart2js/rti/emission/function_type_argument_strong.dart
@@ -5,12 +5,14 @@
import 'package:expect/expect.dart';
import 'package:meta/dart2js.dart';
-/*class: C:checkedInstance,checks=[],instance,typeArgument*/
+/*strong.class: C:checkedInstance,checks=[],instance,typeArgument*/
+/*omit.class: C:checks=[],instance,typeArgument*/
class C {
call(int i) {}
}
-/*class: D:checkedInstance,checks=[],instance,typeArgument*/
+/*strong.class: D:checkedInstance,checks=[],instance,typeArgument*/
+/*omit.class: D:checks=[],instance,typeArgument*/
class D {
call(double i) {}
}
diff --git a/tests/compiler/dart2js/rti/emission/generic_methods_dynamic_02_strong.dart b/tests/compiler/dart2js/rti/emission/generic_methods_dynamic_02_strong.dart
index ccc9db9..e091714 100644
--- a/tests/compiler/dart2js/rti/emission/generic_methods_dynamic_02_strong.dart
+++ b/tests/compiler/dart2js/rti/emission/generic_methods_dynamic_02_strong.dart
@@ -6,10 +6,12 @@
library generic_methods_dynamic_test;
-/*class: A:checkedInstance,checks=[],typeArgument*/
+/*strong.class: A:checkedInstance,checks=[],typeArgument*/
+/*omit.class: A:*/
class A {}
-/*class: B:checks=[],instance*/
+/*strong.class: B:checks=[],instance*/
+/*omit.class: B:*/
class B {}
/*class: C:*/
diff --git a/tests/compiler/dart2js/rti/emission/jsinterop_generic_factory_args.dart b/tests/compiler/dart2js/rti/emission/jsinterop_generic_factory_args.dart
index de9bc8b..963c073 100644
--- a/tests/compiler/dart2js/rti/emission/jsinterop_generic_factory_args.dart
+++ b/tests/compiler/dart2js/rti/emission/jsinterop_generic_factory_args.dart
@@ -14,6 +14,7 @@
/*kernel.class: A:checkedTypeArgument,checks=[],typeArgument*/
/*strong.class: A:checkedInstance,checkedTypeArgument,checks=[],typeArgument*/
+/*omit.class: A:checkedTypeArgument,checks=[],typeArgument*/
@JS()
@anonymous
class A<T> {
diff --git a/tests/compiler/dart2js/rti/emission/list.dart b/tests/compiler/dart2js/rti/emission/list.dart
index 997bd49..0c8d312 100644
--- a/tests/compiler/dart2js/rti/emission/list.dart
+++ b/tests/compiler/dart2js/rti/emission/list.dart
@@ -6,15 +6,18 @@
/*kernel.class: global#JSArray:checkedInstance,checks=[$isIterable],instance*/
/*strong.class: global#JSArray:checkedInstance,checks=[$isIterable,$isList],instance*/
+/*omit.class: global#JSArray:checkedInstance,checks=[$isIterable],instance*/
/*class: global#Iterable:checkedInstance*/
/*kernel.class: A:checkedTypeArgument,checks=[],typeArgument*/
/*strong.class: A:checkedInstance,checkedTypeArgument,checks=[],typeArgument*/
+/*omit.class: A:checkedTypeArgument,checks=[],typeArgument*/
class A {}
/*kernel.class: B:checks=[],typeArgument*/
/*strong.class: B:checkedInstance,checks=[],typeArgument*/
+/*omit.class: B:checks=[],typeArgument*/
class B {}
@noInline
diff --git a/tests/compiler/dart2js/rti/emission/local_function_list_literal_strong.dart b/tests/compiler/dart2js/rti/emission/local_function_list_literal_strong.dart
index f3ac8a5..e4ded08 100644
--- a/tests/compiler/dart2js/rti/emission/local_function_list_literal_strong.dart
+++ b/tests/compiler/dart2js/rti/emission/local_function_list_literal_strong.dart
@@ -4,7 +4,8 @@
import 'package:expect/expect.dart';
-/*class: global#JSArray:checkedInstance,checks=[$isIterable,$isList],instance*/
+/*strong.class: global#JSArray:checkedInstance,checks=[$isIterable,$isList],instance*/
+/*omit.class: global#JSArray:checkedInstance,checks=[$isList],instance*/
@NoInline()
method<T>() {
diff --git a/tests/compiler/dart2js/rti/emission/runtime_type_instantiate_to_string1_strong.dart b/tests/compiler/dart2js/rti/emission/runtime_type_instantiate_to_string1_strong.dart
index da4456d..3123b79 100644
--- a/tests/compiler/dart2js/rti/emission/runtime_type_instantiate_to_string1_strong.dart
+++ b/tests/compiler/dart2js/rti/emission/runtime_type_instantiate_to_string1_strong.dart
@@ -3,7 +3,8 @@
// BSD-style license that can be found in the LICENSE file.
main() {
- /*checks=[],functionType,instance*/
+ /*strong.checks=[],functionType,instance*/
+ /*omit.checks=[],instance*/
T id<T>(T t) => t;
int Function(int) x = id;
print("${x.runtimeType}");
diff --git a/tests/compiler/dart2js/rti/emission/static_argument_strong.dart b/tests/compiler/dart2js/rti/emission/static_argument_strong.dart
index 7bdc190..4df0ab4 100644
--- a/tests/compiler/dart2js/rti/emission/static_argument_strong.dart
+++ b/tests/compiler/dart2js/rti/emission/static_argument_strong.dart
@@ -4,18 +4,22 @@
import 'package:meta/dart2js.dart';
-/*class: I1:checkedInstance*/
+/*strong.class: I1:checkedInstance*/
+/*omit.class: I1:*/
class I1 {}
-/*class: I2:checkedInstance,checkedTypeArgument,checks=[],typeArgument*/
+/*strong.class: I2:checkedInstance,checkedTypeArgument,checks=[],typeArgument*/
+/*omit.class: I2:checkedTypeArgument,checks=[],typeArgument*/
class I2 {}
// TODO(32954): Exclude $isI1 because foo is only called directly.
-/*class: A:checks=[$isI1,$isI2],instance*/
+/*strong.class: A:checks=[$isI1,$isI2],instance*/
+/*omit.class: A:checks=[$isI2],instance*/
class A implements I1, I2 {}
// TODO(32954): Exclude $isI1 because foo is only called directly.
-/*class: B:checks=[$isI1,$isI2],instance*/
+/*strong.class: B:checks=[$isI1,$isI2],instance*/
+/*omit.class: B:checks=[$isI2],instance*/
class B implements I1, I2 {}
@noInline
diff --git a/tests/compiler/dart2js/rti/emission/type_literal.dart b/tests/compiler/dart2js/rti/emission/type_literal.dart
new file mode 100644
index 0000000..e46e083
--- /dev/null
+++ b/tests/compiler/dart2js/rti/emission/type_literal.dart
@@ -0,0 +1,18 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:expect/expect.dart';
+
+/*class: Class1:checks=[],typeLiteral*/
+class Class1 {}
+
+/*class: Class2:checks=[],typeLiteral*/
+class Class2<X> {}
+
+void main() {
+ String name1 = '${Class1}';
+ String name2 = '${Class2}';
+ Expect.equals('Class1', name1);
+ Expect.equals('Class2<dynamic>', name2);
+}
diff --git a/tests/compiler/dart2js/rti/rti_emission_test.dart b/tests/compiler/dart2js/rti/rti_emission_test.dart
index a5aa305..36fefb6 100644
--- a/tests/compiler/dart2js/rti/rti_emission_test.dart
+++ b/tests/compiler/dart2js/rti/rti_emission_test.dart
@@ -27,6 +27,7 @@
dataDir,
const RtiEmissionDataComputer(),
args: args,
+ testOmit: true,
skipForStrong: [
// Dart 1 semantics:
'call.dart',
@@ -50,6 +51,7 @@
static const String checkedInstance = 'checkedInstance';
static const String typeArgument = 'typeArgument';
static const String checkedTypeArgument = 'checkedTypeArgument';
+ static const String typeLiteral = 'typeLiteral';
static const String functionType = 'functionType';
}
@@ -87,6 +89,9 @@
if (classUse.checkedTypeArgument) {
features.add(Tags.checkedTypeArgument);
}
+ if (classUse.typeLiteral) {
+ features.add(Tags.typeLiteral);
+ }
}
return features.getText();
}
diff --git a/tests/compiler/dart2js/rti/type_representation_test.dart b/tests/compiler/dart2js/rti/type_representation_test.dart
index a4a6f9e..147cd0d 100644
--- a/tests/compiler/dart2js/rti/type_representation_test.dart
+++ b/tests/compiler/dart2js/rti/type_representation_test.dart
@@ -187,9 +187,11 @@
// List<E>
expect(elementEnvironment.getThisType(List_), '[$List_rep, $List_E_rep]');
// List
- expect(elementEnvironment.getRawType(List_), '$List_rep');
+ expect(elementEnvironment.getRawType(List_),
+ strongMode ? '[$List_rep,,]' : '$List_rep');
// List<dynamic>
- expect(instantiate(List_, [dynamic_]), '$List_rep');
+ expect(instantiate(List_, [dynamic_]),
+ strongMode ? '[$List_rep,,]' : '$List_rep');
// List<int>
expect(instantiate(List_, [int_]), '[$List_rep, $int_rep]');
// List<Typedef1>
@@ -263,9 +265,11 @@
expect(elementEnvironment.getThisType(Map_),
'[$Map_rep, $Map_K_rep, $Map_V_rep]');
// Map
- expect(elementEnvironment.getRawType(Map_), '$Map_rep');
+ expect(elementEnvironment.getRawType(Map_),
+ strongMode ? '[$Map_rep,,,]' : '$Map_rep');
// Map<dynamic,dynamic>
- expect(instantiate(Map_, [dynamic_, dynamic_]), '$Map_rep');
+ expect(instantiate(Map_, [dynamic_, dynamic_]),
+ strongMode ? '[$Map_rep,,,]' : '$Map_rep');
// Map<int,String>
expect(
instantiate(Map_, [int_, String_]), '[$Map_rep, $int_rep, $String_rep]');
diff --git a/tests/compiler/dart2js_extra/28749_test.dart b/tests/compiler/dart2js_extra/28749_test.dart
index ca4d3bf..1795ea6 100644
--- a/tests/compiler/dart2js_extra/28749_test.dart
+++ b/tests/compiler/dart2js_extra/28749_test.dart
@@ -37,7 +37,7 @@
void main() {
var name = '${Wrap}';
- if (name.length < 4) return; // minified.
+ if ('$Object' != 'Object') return; // minified
Expect.equals(
'Wrap<(int) => ((int) => void) => (int) => void>',
diff --git a/tests/compiler/dart2js_extra/bounded_type_literal_test.dart b/tests/compiler/dart2js_extra/bounded_type_literal_test.dart
new file mode 100644
index 0000000..ad0fbe8
--- /dev/null
+++ b/tests/compiler/dart2js_extra/bounded_type_literal_test.dart
@@ -0,0 +1,27 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// dart2jsOptions=--strong
+
+import 'package:expect/expect.dart';
+
+class Foo<T extends num> {}
+
+main() {
+ var a = new Foo();
+ var b = Foo;
+ Expect.equals(a.runtimeType, b);
+
+ var runtimeTypeToString = "${a.runtimeType}";
+ var typeLiteralToString = "${b}";
+ Expect.equals(runtimeTypeToString, typeLiteralToString);
+
+ if ('$Object' == 'Object') {
+ // `true` if non-minified.
+ Expect.equals("Foo<num>", runtimeTypeToString);
+ Expect.equals("Foo<num>", typeLiteralToString);
+ }
+ print(runtimeTypeToString);
+ print(typeLiteralToString);
+}
diff --git a/tests/compiler/dart2js_extra/dart2js_extra.status b/tests/compiler/dart2js_extra/dart2js_extra.status
index 43feede..f56e2f2 100644
--- a/tests/compiler/dart2js_extra/dart2js_extra.status
+++ b/tests/compiler/dart2js_extra/dart2js_extra.status
@@ -101,6 +101,7 @@
mirrors_used_warning_test/minif: Fail, OK # Tests warning that minified code will be broken.
runtime_type_test: Fail, OK # Tests extected output of Type.toString().
to_string_test: Fail # Issue 7179.
+type_literal_test: Fail, OK # Tests expected output of Type.toString().
typevariable_typedef_test: Fail, OK # Tests expected output of Type.toString().
[ $compiler == dart2js && !$strong ]
diff --git a/tests/compiler/dart2js_extra/dynamic_type_literal_test.dart b/tests/compiler/dart2js_extra/dynamic_type_literal_test.dart
new file mode 100644
index 0000000..3231717
--- /dev/null
+++ b/tests/compiler/dart2js_extra/dynamic_type_literal_test.dart
@@ -0,0 +1,14 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// dart2jsOptions=--strong --omit-implicit-checks
+
+// Test generation of 'dynamic' type literals.
+
+import "package:expect/expect.dart";
+
+void main() {
+ Expect.isTrue(dynamic is Type);
+ Expect.isFalse(dynamic == Type);
+}
diff --git a/tests/compiler/dart2js_extra/generic_type_error_message_test.dart b/tests/compiler/dart2js_extra/generic_type_error_message_test.dart
new file mode 100644
index 0000000..8becaf9
--- /dev/null
+++ b/tests/compiler/dart2js_extra/generic_type_error_message_test.dart
@@ -0,0 +1,35 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// dart2jsOptions=--strong
+
+import 'package:expect/expect.dart';
+
+class Foo<T extends num> {}
+
+class Bar<T extends num> {}
+
+main() {
+ test(new Foo(), Foo, expectTypeArguments: false);
+ test(new Bar() as Bar<num>, Bar, expectTypeArguments: true);
+}
+
+void test(dynamic object, Type type, {bool expectTypeArguments}) {
+ bool caught = false;
+ try {
+ print(type);
+ object as List<String>;
+ } catch (e) {
+ String expected = '$type';
+ if (!expectTypeArguments) {
+ expected = expected.substring(0, expected.indexOf('<'));
+ }
+ expected = "'$expected'";
+ Expect.isTrue(e.toString().contains(expected),
+ 'Expected "$expected" in the message: $e');
+ caught = true;
+ print(e);
+ }
+ Expect.isTrue(caught);
+}
diff --git a/tests/compiler/dart2js_extra/indirect_type_literal_test.dart b/tests/compiler/dart2js_extra/indirect_type_literal_test.dart
new file mode 100644
index 0000000..8929796
--- /dev/null
+++ b/tests/compiler/dart2js_extra/indirect_type_literal_test.dart
@@ -0,0 +1,24 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// dart2jsOptions=--strong
+
+import "package:expect/expect.dart";
+
+class A<T> {}
+
+class B<T extends num> {}
+
+class Indirect<T> {
+ Type get type => T;
+}
+
+void main() {
+ Expect.equals(A, new Indirect<A>().type);
+ Expect.equals(A, new Indirect<A<dynamic>>().type);
+ Expect.notEquals(A, new Indirect<A<num>>().type);
+ Expect.equals(B, new Indirect<B>().type);
+ Expect.equals(B, new Indirect<B<num>>().type);
+ Expect.notEquals(B, new Indirect<B<int>>().type);
+}
diff --git a/tests/compiler/dart2js_extra/lax_runtime_type_instantiate_to_string_test.dart b/tests/compiler/dart2js_extra/lax_runtime_type_instantiate_to_string_test.dart
index d8b456c..26ba4e8 100644
--- a/tests/compiler/dart2js_extra/lax_runtime_type_instantiate_to_string_test.dart
+++ b/tests/compiler/dart2js_extra/lax_runtime_type_instantiate_to_string_test.dart
@@ -14,7 +14,7 @@
// `true` if non-minified.
// The signature of `id` is not otherwise needed so the instantiation
// wrapper doesn't have a function type.
- Expect.equals("Instantiation1", toString);
+ Expect.equals("Instantiation1<dynamic>", toString);
}
print(toString);
}
diff --git a/tests/compiler/dart2js_extra/runtime_type_test.dart b/tests/compiler/dart2js_extra/runtime_type_test.dart
index c307ef4..f127dbe 100644
--- a/tests/compiler/dart2js_extra/runtime_type_test.dart
+++ b/tests/compiler/dart2js_extra/runtime_type_test.dart
@@ -2,6 +2,8 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
+// dart2jsOptions=--strong
+
// Test that Type.toString returns nice strings for native classes with
// reserved names and for raw types.
@@ -14,17 +16,18 @@
class Class$With$Dollar {}
void main() {
- Expect.equals('C', new C().runtimeType.toString());
+ Expect.equals('C<dynamic>', new C().runtimeType.toString());
Expect.equals('C<int>', new C<int>().runtimeType.toString());
Expect.equals('C<double>', new C<double>().runtimeType.toString());
Expect.equals('C<num>', new C<num>().runtimeType.toString());
Expect.equals('C<bool>', new C<bool>().runtimeType.toString());
- Expect.equals('D', new D().runtimeType.toString());
+ Expect.equals('D<dynamic, dynamic, dynamic>', new D().runtimeType.toString());
Expect.equals('D<dynamic, int, dynamic>',
new D<dynamic, int, dynamic>().runtimeType.toString());
D d = new D<dynamic, D, D<dynamic, dynamic, int>>();
Expect.equals(
- 'D<dynamic, D, D<dynamic, dynamic, int>>', d.runtimeType.toString());
+ 'D<dynamic, D<dynamic, dynamic, dynamic>, D<dynamic, dynamic, int>>',
+ d.runtimeType.toString());
Expect.equals(r'C<Class$With$Dollar>',
new C<Class$With$Dollar>().runtimeType.toString());
}
diff --git a/tests/compiler/dart2js_extra/runtime_type_to_string1_test.dart b/tests/compiler/dart2js_extra/runtime_type_to_string1_test.dart
index 8c6cbb4..80fa25c 100644
--- a/tests/compiler/dart2js_extra/runtime_type_to_string1_test.dart
+++ b/tests/compiler/dart2js_extra/runtime_type_to_string1_test.dart
@@ -11,6 +11,11 @@
}
main() {
- Expect.equals((Class).toString(), new Class().runtimeType.toString());
- Expect.equals((Class).toString(), new Class<int>().runtimeType.toString());
+ // Since the type argument of `Class` is only needed for
+ // `.runtimeType.toString()`, it is not reified, and the toString is therefore
+ // only 'Class'.
+ String className = (Class).toString();
+ className = className.substring(0, className.indexOf('<'));
+ Expect.equals(className, new Class().runtimeType.toString());
+ Expect.equals(className, new Class<int>().runtimeType.toString());
}
diff --git a/tests/compiler/dart2js_extra/type_error_message_test.dart b/tests/compiler/dart2js_extra/type_error_message_test.dart
index d097577..6f34931 100644
--- a/tests/compiler/dart2js_extra/type_error_message_test.dart
+++ b/tests/compiler/dart2js_extra/type_error_message_test.dart
@@ -25,12 +25,16 @@
C<String, String> x = (new C<C<int, String>, String>()) as dynamic;
} catch (e) {
String nameOfC = (C).toString();
+ if (nameOfC.contains('<')) {
+ nameOfC = nameOfC.substring(0, nameOfC.indexOf('<'));
+ }
String nameOfInt = (int).toString();
String nameOfString = (String).toString();
String expected =
- '$nameOfC<$nameOfC<$nameOfInt, $nameOfString>, $nameOfString>';
+ "'$nameOfC<$nameOfC<$nameOfInt, $nameOfString>, $nameOfString>'";
Expect.isTrue(e.toString().contains(expected),
- 'Expected "$expected" in the message');
+ 'Expected "$expected" in the message: $e');
+ print(e);
caught = true;
}
Expect.isTrue(caught);
diff --git a/tests/compiler/dart2js_extra/type_literal_test.dart b/tests/compiler/dart2js_extra/type_literal_test.dart
new file mode 100644
index 0000000..4426847
--- /dev/null
+++ b/tests/compiler/dart2js_extra/type_literal_test.dart
@@ -0,0 +1,18 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// dart2jsOptions=--strong
+
+import 'package:expect/expect.dart';
+
+class Class1 {}
+
+class Class2<X> {}
+
+void main() {
+ String name1 = '${Class1}';
+ String name2 = '${Class2}';
+ Expect.equals('Class1', name1);
+ Expect.equals('Class2<dynamic>', name2);
+}
diff --git a/tests/language_2/cyclic_type2_test.dart b/tests/language_2/cyclic_type2_test.dart
index c90cf23..0b62f2f 100644
--- a/tests/language_2/cyclic_type2_test.dart
+++ b/tests/language_2/cyclic_type2_test.dart
@@ -19,9 +19,13 @@
main() {
var d = new Derived1<Derived1, Derived2>();
- Expect.equals("Derived1<Derived1, Derived2>", d.u.toString());
Expect.equals(
- "Derived1<Derived2<Derived2, Derived1>, Derived2>", d.v.toString());
+ "Derived1<Derived1<dynamic, dynamic>, Derived2<dynamic, dynamic>>",
+ d.u.toString());
+ Expect.equals(
+ "Derived1<Derived2<Derived2<dynamic, dynamic>, "
+ "Derived1<dynamic, dynamic>>, Derived2<dynamic, dynamic>>",
+ d.v.toString());
Expect.isTrue(d is Derived1<Derived1, Derived2>);
Expect.isFalse(d is Derived1<Derived1, Derived1>);
Expect.isTrue(d is Base<Derived1<Derived1, Derived2>,
diff --git a/tests/language_2/language_2_dart2js.status b/tests/language_2/language_2_dart2js.status
index 5fa91ed..493bbfb 100644
--- a/tests/language_2/language_2_dart2js.status
+++ b/tests/language_2/language_2_dart2js.status
@@ -552,10 +552,7 @@
partial_tearoff_instantiation_test/06: Pass # for the wrong reason.
partial_tearoff_instantiation_test/07: Pass # for the wrong reason.
partial_tearoff_instantiation_test/08: Pass # for the wrong reason.
-type_alias_equality_test/01: RuntimeError # Issue 32784
type_alias_equality_test/02: RuntimeError # Issue 32784
-type_alias_equality_test/03: RuntimeError # Issue 32784
-type_alias_equality_test/04: RuntimeError # Issue 32784
[ $compiler == dart2js && $fasta && $host_checked && $strong ]
abstract_override_adds_optional_args_concrete_subclass_test: MissingCompileTimeError
@@ -939,6 +936,7 @@
[ $compiler == dart2js && $minified ]
cyclic_type2_test: RuntimeError # Issue 31054
cyclic_type_test/0*: RuntimeError # Issue 31054
+f_bounded_quantification4_test: RuntimeError # Issue 31054
f_bounded_quantification5_test: RuntimeError # Issue 31054
generic_closure_test/01: RuntimeError # Uses runtimeType.toString()
mixin_mixin2_test: RuntimeError # Issue 31054
@@ -989,10 +987,6 @@
covariance_type_parameter_test/02: RuntimeError
covariant_subtyping_test: Crash
ct_const_test: RuntimeError
-cyclic_type_test/00: RuntimeError
-cyclic_type_test/02: RuntimeError
-cyclic_type_test/03: RuntimeError
-cyclic_type_test/04: RuntimeError
deferred_inheritance_constraints_test/extends: MissingCompileTimeError
deferred_inheritance_constraints_test/implements: MissingCompileTimeError
deferred_inheritance_constraints_test/mixin: MissingCompileTimeError
@@ -1012,7 +1006,6 @@
external_test/20: MissingRuntimeError
external_test/21: CompileTimeError
external_test/24: CompileTimeError
-f_bounded_quantification4_test: RuntimeError
field_initialization_order_test/01: MissingCompileTimeError
field_initialization_order_test/none: RuntimeError
flatten_test/05: MissingRuntimeError
@@ -1102,7 +1095,6 @@
mixin_illegal_superclass_test/28: MissingCompileTimeError
mixin_illegal_superclass_test/29: MissingCompileTimeError
mixin_illegal_superclass_test/30: MissingCompileTimeError
-mixin_mixin6_test: RuntimeError
mixin_of_mixin_test/none: CompileTimeError
mixin_super_2_test/none: CompileTimeError
mixin_super_constructor_named_test/01: MissingCompileTimeError