Revision of "Adjusts dart2js backend to handle method type arguments"

Adjusted version of CL https://codereview.chromium.org/1976213002/,
only changed by adding entries in status files for the test
'tests/language/generic_methods_type_expression_test.dart'.

Review URL: https://codereview.chromium.org/2001393003 .
This commit is contained in:
Erik Ernst
2016-05-24 11:12:02 +02:00
parent 552dc14877
commit af79c19a53
23 changed files with 372 additions and 57 deletions
@@ -52,6 +52,17 @@ class Flags {
static const String conditionalDirectives = '--conditional-directives';
// Experimental flags.
// Considerations about this feature (esp. locations where generalizations
// or changes are required for full support of generic methods) are marked
// with 'GENERIC_METHODS'. The approach taken is to parse generic methods,
// introduce AST nodes for them, generate corresponding types (such that
// front end treatment is consistent with the code that programmers wrote),
// but considering all method type variables to have bound `dynamic` no
// matter which bound they have syntactically (such that their value as types
// is unchecked), and then replacing method type variables by a `DynamicType`
// (such that the backend does not need to take method type arguments into
// account).
static const String genericMethodSyntax = '--generic-method-syntax';
static const String resolveOnly = '--resolve-only';
}
@@ -250,9 +250,17 @@ abstract class ConstantCompilerBase implements ConstantCompiler {
ConstantValue value = getConstantValue(expression);
if (elementType.isMalformed && !value.isNull) {
if (isConst) {
ErroneousElement element = elementType.element;
reporter.reportErrorMessage(
node, element.messageKind, element.messageArguments);
// TODO(johnniwinther): Check that it is possible to reach this
// point in a situation where `elementType is! MalformedType`.
if (elementType is MalformedType) {
ErroneousElement element = elementType.element;
reporter.reportErrorMessage(
node, element.messageKind, element.messageArguments);
} else {
assert(elementType is MethodTypeVariableType);
reporter.reportErrorMessage(
node, MessageKind.TYPE_VARIABLE_FROM_METHOD_NOT_REIFIED);
}
} else {
// We need to throw an exception at runtime.
expression = null;
@@ -2734,10 +2734,18 @@ class IrBuilder {
type = program.unaliasType(type);
if (type.isMalformed) {
ErroneousElement element = type.element;
ir.Primitive message = buildStringConstant(element.message);
String message;
if (type is MalformedType) {
ErroneousElement element = type.element;
message = element.message;
} else {
assert(type is MethodTypeVariableType);
message = "Method type variables are not reified, "
"so they cannot be tested dynamically";
}
ir.Primitive irMessage = buildStringConstant(message);
return buildStaticFunctionInvocation(program.throwTypeErrorHelper,
<ir.Primitive>[message], sourceInformation);
<ir.Primitive>[irMessage], sourceInformation);
}
List<ir.Primitive> typeArguments = const <ir.Primitive>[];
@@ -495,7 +495,8 @@ class TreePrinter {
: makeFunctionBody(exp.body);
result = new tree.FunctionExpression(
constructorName(exp),
// TODO(eernst): retrieve and pass the actual type variables.
// GENERIC_METHODS: In order to support generic methods fully,
// we must retrieve and pass the actual type variables here.
null, // typeVariables
parameters,
body,
@@ -516,7 +517,8 @@ class TreePrinter {
tree.Node body = makeFunctionBody(exp.body);
result = new tree.FunctionExpression(
functionName(exp),
// TODO(eernst): retrieve and pass the actual type variables.
// GENERIC_METHODS: In order to support generic methods fully,
// we must retrieve and pass the actual type variables here.
null, // typeVariables
parameters,
body,
@@ -802,7 +804,8 @@ class TreePrinter {
} else if (stmt is FunctionDeclaration) {
tree.FunctionExpression function = new tree.FunctionExpression(
stmt.name != null ? makeIdentifier(stmt.name) : null,
// TODO(eernst): retrieve and pass the actual type variables.
// GENERIC_METHODS: In order to support generic methods fully,
// we must retrieve and pass the actual type variables here.
null, // typeVariables
makeParameters(stmt.parameters),
makeFunctionBody(stmt.body),
@@ -971,7 +974,8 @@ class TreePrinter {
if (param.isFunction) {
tree.Node definition = new tree.FunctionExpression(
makeIdentifier(param.name),
// TODO(eernst): retrieve and pass the actual type variables.
// GENERIC_METHODS: In order to support generic methods fully,
// we must retrieve and pass the actual type variables here.
null, // typeVariables
makeParameters(param.parameters),
null, // body
+99 -9
View File
@@ -10,7 +10,7 @@ import 'common/resolution.dart' show Resolution;
import 'common.dart';
import 'core_types.dart';
import 'elements/elements.dart';
import 'elements/modelx.dart' show TypeDeclarationElementX;
import 'elements/modelx.dart' show TypeDeclarationElementX, ErroneousElementX;
import 'ordered_typeset.dart' show OrderedTypeSet;
import 'util/util.dart' show equalElements;
@@ -124,7 +124,7 @@ abstract class DartType {
bool get isTypeVariable => kind == TypeKind.TYPE_VARIABLE;
/// Is [: true :] if this type is a malformed type.
bool get isMalformed => kind == TypeKind.MALFORMED_TYPE;
bool get isMalformed => false;
/// Is `true` if this type is declared by an enum.
bool get isEnumType => false;
@@ -164,6 +164,15 @@ abstract class DartType {
type.accept(visitor, argument);
}
}
/// Returns a [DartType] which corresponds to [this] except that each
/// contained [MethodTypeVariableType] is replaced by a [DynamicType].
/// GENERIC_METHODS: Temporary, only used with '--generic-method-syntax'.
DartType get dynamifyMethodTypeVariableType => this;
/// Returns true iff [this] is or contains a [MethodTypeVariableType].
/// GENERIC_METHODS: Temporary, only used with '--generic-method-syntax'
bool get containsMethodTypeVariableType => false;
}
/**
@@ -234,6 +243,25 @@ class TypeVariableType extends DartType {
String toString() => name;
}
/// Provides a thin model of method type variables: They are treated as if
/// their value were `dynamic` when used in a type annotation, and as a
/// malformed type when used in an `as` or `is` expression.
class MethodTypeVariableType extends TypeVariableType {
MethodTypeVariableType(TypeVariableElement element) : super(element);
@override
bool get treatAsDynamic => true;
@override
bool get isMalformed => true;
@override
DartType get dynamifyMethodTypeVariableType => const DynamicType();
@override
get containsMethodTypeVariableType => true;
}
/// Internal type representing the result of analyzing a statement.
class StatementType extends DartType {
Element get element => null;
@@ -313,6 +341,9 @@ class MalformedType extends DartType {
// Malformed types are treated as dynamic.
bool get treatAsDynamic => true;
@override
bool get isMalformed => true;
accept(DartTypeVisitor visitor, var argument) {
return visitor.visitMalformedType(this, argument);
}
@@ -341,9 +372,13 @@ abstract class GenericType extends DartType {
final TypeDeclarationElement element;
final List<DartType> typeArguments;
GenericType(TypeDeclarationElement element, this.typeArguments,
GenericType(TypeDeclarationElement element, List<DartType> typeArguments,
{bool checkTypeArgumentCount: true})
: this.element = element {
: this.element = element,
this.typeArguments = typeArguments,
this.containsMethodTypeVariableType =
typeArguments.any(_typeContainsMethodTypeVariableType)
{
assert(invariant(CURRENT_ELEMENT_SPANNABLE, element != null,
message: "Missing element for generic type."));
assert(invariant(element, () {
@@ -405,6 +440,17 @@ abstract class GenericType extends DartType {
return sb.toString();
}
@override
final bool containsMethodTypeVariableType;
@override
DartType get dynamifyMethodTypeVariableType {
if (!containsMethodTypeVariableType) return this;
List<DartType> newTypeArguments = typeArguments.map(
(DartType type) => type.dynamifyMethodTypeVariableType).toList();
return createInstantiation(newTypeArguments);
}
int get hashCode {
int hash = element.hashCode;
for (DartType argument in typeArguments) {
@@ -586,11 +632,21 @@ class FunctionType extends DartType {
}
FunctionType.internal(FunctionTypedElement this.element,
[DartType this.returnType = const DynamicType(),
this.parameterTypes = const <DartType>[],
this.optionalParameterTypes = const <DartType>[],
this.namedParameters = const <String>[],
this.namedParameterTypes = const <DartType>[]]) {
[DartType returnType = const DynamicType(),
List<DartType> parameterTypes = const <DartType>[],
List<DartType> optionalParameterTypes = const <DartType>[],
List<String> namedParameters = const <String>[],
List<DartType> namedParameterTypes = const <DartType>[]])
: this.returnType = returnType,
this.parameterTypes = parameterTypes,
this.optionalParameterTypes = optionalParameterTypes,
this.namedParameters = namedParameters,
this.namedParameterTypes = namedParameterTypes,
this.containsMethodTypeVariableType =
returnType.containsMethodTypeVariableType ||
parameterTypes.any(_typeContainsMethodTypeVariableType) ||
optionalParameterTypes.any(_typeContainsMethodTypeVariableType) ||
namedParameterTypes.any(_typeContainsMethodTypeVariableType) {
assert(invariant(
CURRENT_ELEMENT_SPANNABLE, element == null || element.isDeclaration));
// Assert that optional and named parameters are not used at the same time.
@@ -718,6 +774,28 @@ class FunctionType extends DartType {
int computeArity() => parameterTypes.length;
@override
DartType get dynamifyMethodTypeVariableType {
if (!containsMethodTypeVariableType) return this;
DartType eraseIt(DartType type) => type.dynamifyMethodTypeVariableType;
DartType newReturnType = returnType.dynamifyMethodTypeVariableType;
List<DartType> newParameterTypes = parameterTypes.map(eraseIt).toList();
List<DartType> newOptionalParameterTypes =
optionalParameterTypes.map(eraseIt).toList();
List<DartType> newNamedParameterTypes =
namedParameterTypes.map(eraseIt).toList();
return new FunctionType.internal(
element,
newReturnType,
newParameterTypes,
newOptionalParameterTypes,
namedParameters,
newNamedParameterTypes);
}
@override
final bool containsMethodTypeVariableType;
int get hashCode {
int hash = 3 * returnType.hashCode;
for (DartType parameter in parameterTypes) {
@@ -745,6 +823,9 @@ class FunctionType extends DartType {
}
}
bool _typeContainsMethodTypeVariableType(DartType type) =>
type.containsMethodTypeVariableType;
class TypedefType extends GenericType {
DartType _unaliased;
@@ -1347,6 +1428,15 @@ class Types implements DartTypes {
static ClassElement getClassContext(DartType type) {
TypeVariableType typeVariable = type.typeVariableOccurrence;
if (typeVariable == null) return null;
// GENERIC_METHODS: When generic method support is complete enough to
// include a runtime value for method type variables this must be updated.
// For full support the global assumption that all type variables are
// declared by the same enclosing class will not hold: Both an enclosing
// method and an enclosing class may define type variables, so the return
// type cannot be [ClassElement] and the caller must be prepared to look in
// two locations, not one. Currently we ignore method type variables by
// returning in the next statement.
if (typeVariable.element.typeDeclaration is! ClassElement) return null;
return typeVariable.element.typeDeclaration;
}
@@ -430,6 +430,7 @@ enum MessageKind {
TYPE_ARGUMENT_COUNT_MISMATCH,
TYPE_VARIABLE_IN_CONSTANT,
TYPE_VARIABLE_WITHIN_STATIC_MEMBER,
TYPE_VARIABLE_FROM_METHOD_NOT_REIFIED,
TYPEDEF_FORMAL_WITH_DEFAULT,
UNARY_OPERATOR_BAD_ARITY,
UNBOUND_LABEL,
@@ -1152,6 +1153,38 @@ void main() => new C().m(null);
"""
]),
MessageKind.TYPE_VARIABLE_FROM_METHOD_NOT_REIFIED: const MessageTemplate(
MessageKind.TYPE_VARIABLE_FROM_METHOD_NOT_REIFIED,
"Method type variables are not reified.",
howToFix: "Try using the intended upper bound of the "
"type variable, or dynamic."
// TODO(eernst): These examples should be commented in with an `options:`
// specifying "--generic-method-syntax" and made to work; moreover, the
// compiler/dart2js test 'generic_method_type_usage' should be transformed to
// similar examples of the relevant `MessageKind` entries.
//
// examples: const [
// """
// // Method type variables are not reified, so they cannot be returned.
// Type f<T>() => T;
//
// main() => f<int>();
// """,
// """
// // Method type variables are not reified, so they cannot be tested dynamically.
// bool f<T>(Object o) => o is T;
//
// main() => f<int>(42);
// """,
// """
// // Method type variables are not reified, so they cannot be tested dynamically.
// bool f<T>(Object o) => o as T;
//
// main() => f<int>(42);
// """
// ]
),
MessageKind.INVALID_TYPE_VARIABLE_BOUND: const MessageTemplate(
MessageKind.INVALID_TYPE_VARIABLE_BOUND,
"'#{typeArgument}' is not a subtype of bound '#{bound}' for "
+6 -1
View File
@@ -2703,7 +2703,12 @@ class JavaScriptImpactTransformer extends ImpactTransformer {
if (type.isTypedef) {
backend.compiler.world.allTypedefs.add(type.element);
}
if (type.isTypeVariable) {
if (type.isTypeVariable && type is! MethodTypeVariableType) {
// GENERIC_METHODS: The `is!` test above filters away method type
// variables, because they have the value `dynamic` with the
// incomplete support for generic methods offered with
// '--generic-method-syntax'. This must be revised in order to
// support generic methods fully.
ClassElement cls = type.element.enclosingClass;
backend.rti.registerClassUsingTypeVariableExpression(cls);
registerBackendImpact(transformed, impacts.typeVariableExpression);
@@ -252,7 +252,12 @@ class _RuntimeTypes implements RuntimeTypes {
compiler.resolverWorld.isChecks.forEach((DartType type) {
if (type.isTypeVariable) {
TypeVariableElement variable = type.element;
classesUsingTypeVariableTests.add(variable.typeDeclaration);
// GENERIC_METHODS: When generic method support is complete enough to
// include a runtime value for method type variables, this may need to
// be updated: It simply ignores method type arguments.
if (variable.typeDeclaration is ClassElement) {
classesUsingTypeVariableTests.add(variable.typeDeclaration);
}
}
});
// Add is-checks that result from classes using type variables in checks.
@@ -719,7 +719,17 @@ class ConstructorResolver extends CommonResolverVisitor<ConstructorResult> {
ConstructorResult constructorResultForType(Node node, DartType type,
{PrefixElement prefix}) {
String name = type.name;
if (type.isMalformed) {
if (type.isTypeVariable) {
return reportAndCreateErroneousConstructorElement(
node,
ConstructorResultKind.INVALID_TYPE,
type,
resolver.enclosingElement,
name,
MessageKind.CANNOT_INSTANTIATE_TYPE_VARIABLE,
{'typeVariableName': name});
} else if (type.isMalformed) {
// `type is MalformedType`: `MethodTypeVariableType` is handled above.
return new ConstructorResult.forError(
ConstructorResultKind.INVALID_TYPE, type.element, type);
} else if (type.isInterfaceType) {
@@ -733,15 +743,6 @@ class ConstructorResolver extends CommonResolverVisitor<ConstructorResult> {
name,
MessageKind.CANNOT_INSTANTIATE_TYPEDEF,
{'typedefName': name});
} else if (type.isTypeVariable) {
return reportAndCreateErroneousConstructorElement(
node,
ConstructorResultKind.INVALID_TYPE,
type,
resolver.enclosingElement,
name,
MessageKind.CANNOT_INSTANTIATE_TYPE_VARIABLE,
{'typeVariableName': name});
}
return reporter.internalError(node, "Unexpected constructor type $type");
}
@@ -314,10 +314,12 @@ class SignatureResolver extends MappingVisitor<FormalElementX> {
nodes = nodes.tail;
TypeVariableElementX variableElement =
new TypeVariableElementX(variableName, element, index, node);
// TODO(eernst): When type variables are implemented fully we will need
// to resolve the actual bounds; currently we just claim [dynamic].
// GENERIC_METHODS: When method type variables are implemented fully we
// must resolve the actual bounds; currently we just claim that
// every method type variable has upper bound [dynamic].
variableElement.boundCache = const DynamicType();
TypeVariableType variableType = new TypeVariableType(variableElement);
TypeVariableType variableType =
new MethodTypeVariableType(variableElement);
variableElement.typeCache = variableType;
return variableType;
}, growable: false);
@@ -206,10 +206,6 @@ class TypeResolver {
}
}
} else if (element.isTypeVariable) {
// FIXME: check enclosing, which may be not class, not typedef (so
// it's a generic method) then set the type to `const DynamicType()`.
// This should later be fixed such that we don't tell the user that they
// wrote `dynamic` anywhere.
TypeVariableElement typeVariable = element;
Element outer =
visitor.enclosingElement.outermostEnclosingMemberOrTopLevel;
+41 -15
View File
@@ -2578,13 +2578,17 @@ class SsaBuilder extends ast.Visitor
"${localsHandler.contextClass}.");
}
/// Build a [HTypeConversion] for convertion [original] to type [type].
/// Build a [HTypeConversion] for converting [original] to type [type].
///
/// Invariant: [type] must be valid in the context.
/// See [LocalsHandler.substInContext].
HInstruction buildTypeConversion(
HInstruction original, DartType type, int kind) {
if (type == null) return original;
// GENERIC_METHODS: The following statement was added for parsing and
// ignoring method type variables; must be generalized for full support of
// generic methods.
type = type.dynamifyMethodTypeVariableType;
type = type.unaliased;
assert(assertTypeInContext(type, original));
if (type.isInterfaceType && !type.treatAsRaw) {
@@ -3805,8 +3809,15 @@ class SsaBuilder extends ast.Visitor
void visitAs(ast.Send node, ast.Node expression, DartType type, _) {
HInstruction expressionInstruction = visitAndPop(expression);
if (type.isMalformed) {
ErroneousElement element = type.element;
generateTypeError(node, element.message);
String message;
if (type is MalformedType) {
ErroneousElement element = type.element;
message = element.message;
} else {
assert(type is MethodTypeVariableType);
message = "Method type variables are not reified.";
}
generateTypeError(node, message);
} else {
HInstruction converted = buildTypeConversion(expressionInstruction,
localsHandler.substInContext(type), HTypeConversion.CAST_TYPE_CHECK);
@@ -3832,7 +3843,20 @@ class SsaBuilder extends ast.Visitor
HInstruction buildIsNode(
ast.Node node, DartType type, HInstruction expression) {
type = localsHandler.substInContext(type).unaliased;
if (type.isFunctionType) {
if (type.isMalformed) {
String message;
if (type is MethodTypeVariableType) {
message = "Method type variables are not reified, "
"so they cannot be tested with an `is` expression.";
} else {
assert(type is MalformedType);
ErroneousElement element = type.element;
message = element.message;
}
generateTypeError(node, message);
HInstruction call = pop();
return new HIs.compound(type, expression, call, backend.boolType);
} else if (type.isFunctionType) {
List arguments = [buildFunctionType(type), expression];
pushInvokeDynamic(
node,
@@ -3867,11 +3891,6 @@ class SsaBuilder extends ast.Visitor
pushInvokeStatic(node, helper, inputs, typeMask: backend.boolType);
HInstruction call = pop();
return new HIs.compound(type, expression, call, backend.boolType);
} else if (type.isMalformed) {
ErroneousElement element = type.element;
generateTypeError(node, element.message);
HInstruction call = pop();
return new HIs.compound(type, expression, call, backend.boolType);
} else {
if (backend.hasDirectCheckFor(type)) {
return new HIs.direct(type, expression, backend.boolType);
@@ -5337,12 +5356,19 @@ class SsaBuilder extends ast.Visitor
/// Generate the literal for [typeVariable] in the current context.
void generateTypeVariableLiteral(
ast.Send node, TypeVariableType typeVariable) {
DartType type = localsHandler.substInContext(typeVariable);
HInstruction value = analyzeTypeArgument(type,
sourceInformation: sourceInformationBuilder.buildGet(node));
pushInvokeStatic(node, helpers.runtimeTypeToString, [value],
typeMask: backend.stringType);
pushInvokeStatic(node, helpers.createRuntimeType, [pop()]);
// GENERIC_METHODS: This provides thin support for method type variables
// by treating them as malformed when evaluated as a literal. For full
// support of generic methods this must be revised.
if (typeVariable is MethodTypeVariableType) {
generateTypeError(node, "Method type variables are not reified");
} else {
DartType type = localsHandler.substInContext(typeVariable);
HInstruction value = analyzeTypeArgument(type,
sourceInformation: sourceInformationBuilder.buildGet(node));
pushInvokeStatic(node, helpers.runtimeTypeToString, [value],
typeMask: backend.stringType);
pushInvokeStatic(node, helpers.createRuntimeType, [pop()]);
}
}
/// Generate a call to a type literal.
+2
View File
@@ -780,6 +780,8 @@ class SsaInstructionSimplifier extends HBaseVisitor
return inputType.isInMask(checkedType, classWorld) ? input : node;
}
HInstruction removeCheck(HCheck node) => node.checkedInput;
VariableElement findConcreteFieldForDynamicAccess(
HInstruction receiver, Selector selector) {
TypeMask receiverType = receiver.instructionType;
@@ -7,7 +7,7 @@
/// Dart test verifying that the parser can handle type parameterization of
/// local function declarations, and declarations of function parameters.
library generic_functions_test;
library generic_local_functions_test;
import "package:expect/expect.dart";
@@ -0,0 +1,23 @@
// Copyright (c) 2016, 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.
//
// DartOptions=--generic-method-syntax
/// Dart test on the usage of method type arguments in a function typed
/// parameter declaration.
library generic_methods_function_type_test;
import "package:expect/expect.dart";
class C<V> {
U m1<U>(U f(V v), V v) => f(v);
V m2<U>(V f(U v), U u) => f(u);
}
main() {
Expect.equals(new C<int>().m1<int>((x) => x, 10), 10);
Expect.equals(new C<int>().m2<int>((x) => x, 20), 20);
}
@@ -0,0 +1,3 @@
analyzer:
language:
enableGenericMethods: true
@@ -0,0 +1,31 @@
// Copyright (c) 2016, 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.
//
// DartOptions=--generic-method-syntax
/// Dart test on the usage of method type arguments in object creation. With
/// '--generic-method-syntax', the type argument is available at runtime,
/// but erased to `dynamic`.
library generic_methods_new_test;
import "package:expect/expect.dart";
class C<E> {
E e;
C(this.e);
}
C<T> f1<T>(T t) => new C<T>(t);
List<T> f2<T>(T t) => <T>[t];
main() {
C c = f1<int>(42);
List i = f2<String>("Hello!");
Expect.isTrue(c is C<int> && c is C<String>); // C<dynamic>.
Expect.isTrue(i is List<String> && i is List<int>); // List<dynamic>.
Expect.equals(c.e, 42);
Expect.equals(i[0], "Hello!");
}
@@ -0,0 +1,3 @@
analyzer:
language:
enableGenericMethods: true
@@ -0,0 +1,52 @@
// Copyright (c) 2016, 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.
//
// DartOptions=--generic-method-syntax
/// Dart test on the usage of method type arguments in type expressions. With
/// '--generic-method-syntax', the type argument is available at runtime,
/// but erased to `dynamic`.
library generic_methods_type_expression_test;
import "package:expect/expect.dart";
bool f1<T>(Object o) => o is T;
bool f2<T>(Object o) => o is List<T>;
bool f3<T>(Object o) => o is! T;
bool f4<T>(Object o) => o is! List<T>;
T f5<T>(Object o) => o as T;
List<T> f6<T>(Object o) => o as List<T>;
Type f7<T>() => T;
class TypeValue<X> {
Type get value => X;
}
Type f8<T>() => new TypeValue<List<T>>().value;
main() {
String s = "Hello!";
List<String> ss = <String>[s];
Expect.throws(() => f1<int>(42), (e) => e is TypeError);
Expect.throws(() => f1<String>(42), (e) => e is TypeError);
Expect.equals(f2<int>(<int>[42]), true);
Expect.equals(f2<String>(<int>[42]), true); // `is List<dynamic>` is true.
Expect.throws(() => f3<int>(42), (e) => e is TypeError);
Expect.throws(() => f3<String>(42), (e) => e is TypeError);
Expect.equals(f4<int>(<int>[42]), false);
Expect.equals(f4<String>(<int>[42]), false); // `is! List<dynamic>` is false.
Expect.throws(() => f5<String>(s), (e) => e is TypeError);
Expect.throws(() => f5<int>(s), (e) => e is TypeError);
Expect.equals(f6<String>(ss), ss);
Expect.equals(f6<int>(ss), ss); // `as List<dynamic>` succeeds.
Expect.throws(() => f7<int>(), (e) => e is TypeError);
Expect.equals(f8<int>(), List); // Returns `List<dynamic>`.
}
@@ -0,0 +1,3 @@
analyzer:
language:
enableGenericMethods: true
+6
View File
@@ -49,6 +49,9 @@ generic_methods_test: CompiletimeError # Issue 25869
generic_functions_test: CompiletimeError # Issue 25869
generic_local_functions_test: CompiletimeError # Issue 25869
generic_sends_test: CompiletimeError # Issue 25869
generic_methods_new_test: CompiletimeError # Issue 25869
generic_methods_function_type_test: CompiletimeError # Issue 25869
generic_methods_type_expression_test: CompiletimeError # Issue 25869
[ ($compiler == none || $compiler == precompiler || $compiler == dart2app) && ($runtime == vm || $runtime == dart_precompiled || $runtime == dart_product) ]
@@ -94,6 +97,9 @@ generic_methods_test: RuntimeError # Issue 25869
generic_functions_test: RuntimeError # Issue 25869
generic_local_functions_test: RuntimeError # Issue 25869
generic_sends_test: RuntimeError # Issue 25869
generic_methods_new_test: RuntimeError # Issue 25869
generic_methods_function_type_test: RuntimeError # Issue 25869
generic_methods_type_expression_test: RuntimeError # Issue 25869
config_import_test: Skip # Issue 26250
[ $compiler == none && $runtime == dartium && $system == linux && $arch != x64 ]
+3
View File
@@ -506,3 +506,6 @@ generic_functions_test: CompileTimeError # Issue 25868
generic_local_functions_test: CompileTimeError # Issue 25868
generic_methods_test: CompileTimeError # Issue 25868
generic_sends_test: CompileTimeError # Issue 25868
generic_methods_new_test: CompiletimeError # Issue 25868
generic_methods_function_type_test: CompiletimeError # Issue 25868
generic_methods_type_expression_test: CompiletimeError # Issue 25868
+3 -3
View File
@@ -50,6 +50,9 @@ generic_functions_test: CompileTimeError # DartOptions not passed to compiler.
generic_local_functions_test: CompileTimeError # DartOptions not passed to compiler.
generic_methods_test: CompileTimeError # DartOptions not passed to compiler.
generic_sends_test: CompileTimeError # DartOptions not passed to compiler.
generic_methods_new_test: CompiletimeError # DartOptions not passed to compiler.
generic_methods_function_type_test: CompiletimeError # DartOptions not passed to compiler.
generic_methods_type_expression_test: CompiletimeError # DartOptions not passed to compiler.
[ $compiler == dart2js ]
invocation_mirror_empty_arguments_test: Fail # Issue 24331
@@ -132,9 +135,6 @@ malbounded_type_test_test/03: Fail # Issue 14121
malbounded_type_test_test/04: Fail # Issue 14121
malbounded_type_test2_test: Fail # Issue 14121
default_factory2_test/01: Fail # Issue 14121
generic_functions_test: Crash # Issue 26436
generic_local_functions_test: Crash # Issue 26436
generic_methods_test: Crash # Issue 26436
[ $compiler == dart2js && $unchecked ]
type_checks_in_factory_method_test: RuntimeError # Issue 12746