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>
This commit is contained in:
Johnni Winther 2018-07-09 12:24:04 +00:00 committed by commit-bot@chromium.org
parent 3a1b09dc63
commit 1c673b1046
51 changed files with 546 additions and 176 deletions

View file

@ -1051,9 +1051,6 @@ class CommonElements {
FunctionEntity get getRuntimeTypeArgumentIntercepted =>
_findHelperFunction('getRuntimeTypeArgumentIntercepted');
FunctionEntity get runtimeTypeToString =>
_findHelperFunction('runtimeTypeToString');
FunctionEntity get assertIsSubtype => _findHelperFunction('assertIsSubtype');
FunctionEntity get checkSubtype => _findHelperFunction('checkSubtype');

View file

@ -361,6 +361,9 @@ abstract class DeferredLoadTask extends CompilerTask {
_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

View file

@ -264,8 +264,9 @@ class InterfaceType extends DartType {
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 @@ class TypedefType extends DartType {
}
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;
}

View file

@ -380,6 +380,9 @@ class ResolutionEnqueuer extends EnqueuerImpl {
_worldBuilder.registerTypeVariableTypeLiteral(type);
}
break;
case TypeUseKind.RTI_VALUE:
failedAt(CURRENT_ELEMENT_SPANNABLE, "Unexpected type use: $typeUse.");
break;
}
}

View file

@ -448,7 +448,6 @@ class BackendImpacts {
return _typeVariableExpression ??= new BackendImpact(staticUses: [
_commonElements.setRuntimeTypeInfo,
_commonElements.getRuntimeTypeInfo,
_commonElements.runtimeTypeToString,
_commonElements.createRuntimeType
], otherImpacts: [
listValues,

View file

@ -16,7 +16,6 @@ import '../universe/world_builder.dart';
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 @@ class ConstantEmitter implements ConstantValueVisitor<jsAst.Expression, Null> {
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 @@ class ConstantEmitter implements ConstantValueVisitor<jsAst.Expression, Null> {
this._rtiNeed,
this._rtiEncoder,
this._allocatorAnalysis,
this._namer,
this._task,
this.constantReferenceGenerator,
this.makeConstantList);
@ -280,19 +277,21 @@ class ConstantEmitter implements ConstantValueVisitor<jsAst.Expression, Null> {
@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

View file

@ -210,6 +210,9 @@ class CodegenEnqueuer extends EnqueuerImpl {
_worldBuilder.registerTypeVariableTypeLiteral(type);
}
break;
case TypeUseKind.RTI_VALUE:
_worldBuilder.registerTypeArgument(type);
break;
}
}

View file

@ -202,6 +202,9 @@ class JavaScriptImpactTransformer extends ImpactTransformer {
}
hasTypeLiteral = true;
break;
case TypeUseKind.RTI_VALUE:
failedAt(CURRENT_ELEMENT_SPANNABLE, "Unexpected type use: $typeUse.");
break;
}
}

View file

@ -250,6 +250,7 @@ class TrivialRuntimeTypesChecksBuilder implements RuntimeTypesChecksBuilder {
..checkedInstance = true
..typeArgument = true
..checkedTypeArgument = true
..typeLiteral = true
..functionType = _computeFunctionType(_elementEnvironment, cls,
strongMode: options.strongMode);
classUseMap[cls] = classUse;
@ -340,10 +341,12 @@ abstract class RuntimeTypesSubstitutionsMixin
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 @@ abstract class RuntimeTypesSubstitutionsMixin
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 @@ class RuntimeTypesImpl extends _RuntimeTypesBase
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 @@ class RuntimeTypesImpl extends _RuntimeTypesBase
isFunctionChecked =
isFunctionChecked || t.element == _commonElements.functionClass;
}
testedTypeVisitor.visitType(t, false);
testedTypeVisitor.visitType(t, TypeVisitorState.direct);
}
explicitIsChecks.forEach(processCheckedType);
@ -2057,7 +2075,7 @@ class RuntimeTypesImpl extends _RuntimeTypesBase
DartType bound =
_elementEnvironment.getTypeVariableBound(typeVariable.element);
processCheckedType(bound);
liveTypeVisitor.visit(bound, true);
liveTypeVisitor.visit(bound, TypeVisitorState.typeArgument);
}
}
}
@ -2334,6 +2352,7 @@ class TypeRepresentationGenerator
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 @@ class TypeRepresentationGenerator
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 @@ class TypeCheck {
'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 @@ class ClassUse {
///
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 @@ class ClassUse {
if (checkedTypeArgument) {
properties.add('checkedTypeArgument');
}
if (typeLiteral) {
properties.add('rtiValue');
}
if (functionType != null) {
properties.add('functionType');
}

View file

@ -167,7 +167,6 @@ class Emitter extends js_emitter.EmitterBase {
_closedWorld.rtiNeed,
compiler.backend.rtiEncoder,
_closedWorld.allocatorAnalysis,
namer,
task,
this.constantReference,
constantListGenerator);

View file

@ -84,7 +84,6 @@ class ModelEmitter {
_closedWorld.rtiNeed,
compiler.backend.rtiEncoder,
_closedWorld.allocatorAnalysis,
namer,
task,
this.generateConstantReference,
constantListGenerator);

View file

@ -276,7 +276,9 @@ class TypeConverter implements DartTypeVisitor<DartType, EntityConverter> {
@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

View file

@ -827,7 +827,8 @@ class TypeConverter extends DartTypeVisitor<DartType, Null> {
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) =>

View file

@ -983,7 +983,8 @@ abstract class ElementCreatorMixin implements KernelToElementMapBase {
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 @@ class DartTypeConverter extends ir.DartTypeVisitor<DartType> {
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 @@ class JsKernelToElementMap extends KernelToElementMapBase
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;

View file

@ -2852,15 +2852,9 @@ class KernelSsaGraphBuilder extends ir.Visitor
HInstruction value = typeBuilder.analyzeTypeArgument(
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);

View file

@ -2208,6 +2208,11 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
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) {

View file

@ -77,6 +77,9 @@ abstract class CodegenWorldBuilder implements WorldBuilder {
/// 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 @@ class CodegenWorldBuilderImpl extends WorldBuilderBase
final KernelToWorldBuilder _elementMap;
final GlobalLocalsMap _globalLocalsMap;
final Set<DartType> _liveTypeArguments = new Set<DartType>();
CodegenWorldBuilderImpl(
this._elementMap,
this._globalLocalsMap,
@ -688,4 +693,10 @@ class CodegenWorldBuilderImpl extends WorldBuilderBase
f(member);
});
}
void registerTypeArgument(DartType type) {
_liveTypeArguments.add(type);
}
Iterable<DartType> get constTypeLiterals => _liveTypeArguments;
}

View file

@ -582,6 +582,7 @@ enum TypeUseKind {
NATIVE_INSTANTIATION,
IMPLICIT_CAST,
PARAMETER_CHECK,
RTI_VALUE,
}
/// Use of a [DartType].
@ -629,6 +630,9 @@ class TypeUse {
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 @@ class TypeUse {
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;

View file

@ -348,8 +348,7 @@ class JSInvocationMirror implements Invocation {
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 @@ class BoundClosure extends TearOffClosure {
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 @@ class BoundClosure extends TearOffClosure {
@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 @@ class TypeErrorImplementation extends Error implements TypeError {
/// 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 @@ class CastErrorImplementation extends Error implements CastError {
/// 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;
}

View file

@ -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 @@ String getClassName(var object) {
* 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 @@ String _getRuntimeTypeAsStringV2(var rti, List<String> genericContext) {
/// 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 runtimeTypeToStringV1(var rti, {String onTypeVariable(int i)}) {
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 @@ String runtimeTypeToStringV2(var rti, List<String> genericContext) {
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 @@ String _functionRtiToStringV1(var rti, String onTypeVariable(int i)) {
} 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 @@ String _functionRtiToStringV1(var rti, String onTypeVariable(int i)) {
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 @@ String _functionRtiToStringV1(var rti, String onTypeVariable(int i)) {
sep = '';
for (var argument in optionalArguments) {
argumentsText += sep;
argumentsText +=
runtimeTypeToStringV1(argument, onTypeVariable: onTypeVariable);
argumentsText += runtimeTypeToStringV1(argument);
sep = ', ';
}
argumentsText += ']';
@ -316,9 +313,8 @@ String _functionRtiToStringV1(var rti, String onTypeVariable(int i)) {
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 @@ String joinArguments(var types, int startIndex) {
: 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 @@ String joinArgumentsV1(var types, int startIndex,
if (argument != null) {
allDynamic = false;
}
buffer
.write(runtimeTypeToStringV1(argument, onTypeVariable: onTypeVariable));
buffer.write(runtimeTypeToStringV1(argument));
}
return allDynamic ? '' : '<$buffer>';
}
@ -480,22 +474,19 @@ String joinArgumentsV1(var types, int startIndex,
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 @@ String getRuntimeTypeString(var object) {
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));
}
/**

View file

@ -616,7 +616,6 @@ LayoutTests/fast/dom/Range/range-detached-exceptions_t01: RuntimeError # Please
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/partial-layout-overlay-scrollbars_t01: RuntimeError # Pleas
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-constructor_t01: RuntimeError # Please triage t
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/offset-position-writing-modes_t01: Pass, RuntimeError # Iss
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-assertion_t01: RuntimeError # Please
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/distribution-update-recalcs-style_t01: RuntimeError
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/Range/range-processing-instructions_t01: RuntimeError # Ple
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-for-event-path_t01: RuntimeError # Plea
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-insertNode-splittext_t01: RuntimeError # Please
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/distribution-update-recalcs-style_t01: RuntimeError
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

View file

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

View file

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

View file

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

View file

@ -10,6 +10,8 @@ test(o) => o is Function;
main() {
test(
/*kernel.checks=[],functionType,instance*/
/*strong.checks=[],instance*/ () {});
/*strong.checks=[],instance*/
/*omit.checks=[],instance*/
() {});
test(null);
}

View file

@ -9,5 +9,9 @@ test(o) => o is Function();
main() {
test(/*checks=[],functionType,instance*/ () {});
test(/*checks=[],functionType,instance*/ (a) {});
test(
/*kernel.checks=[],functionType,instance*/
/*strong.checks=[],instance*/
/*omit.checks=[],instance*/
(a) {});
}

View file

@ -13,6 +13,7 @@ class A<T> {
return
/*kernel.checks=[$signature],instance*/
/*strong.checks=[],instance*/
/*omit.checks=[],instance*/
(T t, String s) {};
}
}

View file

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

View file

@ -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) {}
}

View file

@ -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:*/

View file

@ -14,6 +14,7 @@ import 'package:js/js.dart';
/*kernel.class: A:checkedTypeArgument,checks=[],typeArgument*/
/*strong.class: A:checkedInstance,checkedTypeArgument,checks=[],typeArgument*/
/*omit.class: A:checkedTypeArgument,checks=[],typeArgument*/
@JS()
@anonymous
class A<T> {

View file

@ -6,15 +6,18 @@ import 'package:meta/dart2js.dart';
/*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

View file

@ -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>() {

View file

@ -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}");

View file

@ -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

View file

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

View file

@ -27,6 +27,7 @@ main(List<String> args) {
dataDir,
const RtiEmissionDataComputer(),
args: args,
testOmit: true,
skipForStrong: [
// Dart 1 semantics:
'call.dart',
@ -50,6 +51,7 @@ class Tags {
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 @@ abstract class ComputeValueMixin {
if (classUse.checkedTypeArgument) {
features.add(Tags.checkedTypeArgument);
}
if (classUse.typeLiteral) {
features.add(Tags.typeLiteral);
}
}
return features.getText();
}

View file

@ -187,9 +187,11 @@ main() {
// 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 @@ main() {
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]');

View file

@ -37,7 +37,7 @@ foo<Y>(int x) {
void main() {
var name = '${Wrap}';
if (name.length < 4) return; // minified.
if ('$Object' != 'Object') return; // minified
Expect.equals(
'Wrap<(int) => ((int) => void) => (int) => void>',

View file

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

View file

@ -101,6 +101,7 @@ generic_method_dynamic_type_test: Fail, OK # Tests expected output of Type.toStr
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 ]

View file

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

View file

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

View file

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

View file

@ -14,7 +14,7 @@ main() {
// `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);
}

View file

@ -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 D<X, Y, Z> {}
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());
}

View file

@ -11,6 +11,11 @@ class Class<T> {
}
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());
}

View file

@ -25,12 +25,16 @@ main() {
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);

View file

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

View file

@ -19,9 +19,13 @@ class Derived2<U, V>
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>,

View file

@ -552,10 +552,7 @@ partial_tearoff_instantiation_test/05: Pass # for the wrong reason.
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 @@ wrong_number_type_arguments_test/none: Pass
[ $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 @@ constructor_redirect_test/01: Crash # Assertion failure: Cannot find value Insta
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/13: MissingRuntimeError
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/27: MissingCompileTimeError
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