Fix constructor invocation type inference.

Three problems are fixed:

- I forgot to pass the `downwards` flag when doing downwards inference.

- I forgot to initialize the `formalTypes` and `actualTypes` arrays.

- I wasn't tracking whether constructor type arguments were implicit
  or explicit, so constructor type inference wasn't actually
  happening.

R=scheglov@google.com

Review-Url: https://codereview.chromium.org/2864853002 .
This commit is contained in:
Paul Berry
2017-05-08 14:41:52 -07:00
parent d34d4e545c
commit 4eee6cb5ea
22 changed files with 393 additions and 51 deletions
-1
View File
@@ -39,7 +39,6 @@
<excludeFolder url="file://$MODULE_DIR$/test/source/packages" />
<excludeFolder url="file://$MODULE_DIR$/test/src/packages" />
<excludeFolder url="file://$MODULE_DIR$/test/src/plugin/packages" />
<excludeFolder url="file://$MODULE_DIR$/test/src/utilities/packages" />
<excludeFolder url="file://$MODULE_DIR$/test/stress/packages" />
<excludeFolder url="file://$MODULE_DIR$/test/stress/replay/packages" />
<excludeFolder url="file://$MODULE_DIR$/test/stress/utilities/packages" />
+3 -1
View File
@@ -12,6 +12,9 @@
<excludeFolder url="file://$MODULE_DIR$/test/plugin/packages" />
<excludeFolder url="file://$MODULE_DIR$/test/src/channel/packages" />
<excludeFolder url="file://$MODULE_DIR$/test/src/packages" />
<excludeFolder url="file://$MODULE_DIR$/test/src/utilities/change_builder/packages" />
<excludeFolder url="file://$MODULE_DIR$/test/src/utilities/packages" />
<excludeFolder url="file://$MODULE_DIR$/test/support/packages" />
<excludeFolder url="file://$MODULE_DIR$/test/utilities/packages" />
<excludeFolder url="file://$MODULE_DIR$/test/utilities/subscriptions/packages" />
<excludeFolder url="file://$MODULE_DIR$/tool/packages" />
@@ -21,6 +24,5 @@
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="Dart SDK" level="application" />
<orderEntry type="library" name="Dart SDK" level="project" />
<orderEntry type="library" name="Dart Packages" level="project" />
</component>
</module>
@@ -35,6 +35,10 @@ import 'package:kernel/ast.dart';
/// shadow-ify [DartType], since analyzer ASTs need to be able to record the
/// exact tokens that were used to specify a type.
abstract class AstFactory<V> {
/// Creates an [Arguments] data structure.
Arguments arguments(List<Expression> positional,
{List<DartType> types, List<NamedExpression> named});
/// Creates an `as` expression.
AsExpression asExpression(Expression operand, Token operator, DartType type);
@@ -132,6 +136,10 @@ abstract class AstFactory<V> {
/// Creates a return statement.
Statement returnStatement(Expression expression, Token token);
/// Updates an [Arguments] data structure with the given generic [types].
/// Should only be used when [types] were specified explicitly.
void setExplicitArgumentTypes(Arguments arguments, List<DartType> types);
/// Creates a read of a static variable.
StaticGet staticGet(Member readTarget, Token token);
@@ -14,7 +14,7 @@ import '../parser/identifier_context.dart' show IdentifierContext;
import 'package:front_end/src/fasta/builder/ast_factory.dart' show AstFactory;
import 'package:front_end/src/fasta/kernel/kernel_shadow_ast.dart'
show KernelField;
show KernelArguments, KernelField;
import 'package:front_end/src/fasta/kernel/utils.dart' show offsetForToken;
@@ -567,9 +567,9 @@ class BodyBuilder extends ScopeListener<JumpTarget> implements BuilderHelper {
arguments.getRange(0, firstNamedArgumentIndex));
List<NamedExpression> named = new List<NamedExpression>.from(
arguments.getRange(firstNamedArgumentIndex, arguments.length));
push(new Arguments(positional, named: named));
push(astFactory.arguments(positional, named: named));
} else {
push(new Arguments(arguments));
push(astFactory.arguments(arguments));
}
}
@@ -783,7 +783,7 @@ class BodyBuilder extends ScopeListener<JumpTarget> implements BuilderHelper {
coreTypes.getClass("dart:core", "NoSuchMethodError").constructors.first;
return new Throw(new ConstructorInvocation(
constructor,
new Arguments(<Expression>[
astFactory.arguments(<Expression>[
astFactory.nullLiteral(null),
new SymbolLiteral(name),
new ListLiteral(arguments.positional),
@@ -1932,7 +1932,7 @@ class BodyBuilder extends ScopeListener<JumpTarget> implements BuilderHelper {
void endNewExpression(Token token) {
debugEvent("NewExpression");
Token nameToken = token.next;
Arguments arguments = pop();
KernelArguments arguments = pop();
String name = pop();
List<DartType> typeArguments = pop();
var type = pop();
@@ -1945,7 +1945,7 @@ class BodyBuilder extends ScopeListener<JumpTarget> implements BuilderHelper {
if (typeArguments != null) {
assert(arguments.types.isEmpty);
arguments.types.addAll(typeArguments);
astFactory.setExplicitArgumentTypes(arguments, typeArguments);
}
String errorName;
@@ -2545,7 +2545,7 @@ class BodyBuilder extends ScopeListener<JumpTarget> implements BuilderHelper {
String message = formatUnexpected(uri, charOffset, error);
Builder constructor = library.loader.getCompileTimeError();
return new Throw(buildStaticInvocation(constructor.target,
new Arguments(<Expression>[new StringLiteral(message)])));
astFactory.arguments(<Expression>[new StringLiteral(message)])));
}
Expression buildAbstractClassInstantiationError(String className,
@@ -2554,7 +2554,7 @@ class BodyBuilder extends ScopeListener<JumpTarget> implements BuilderHelper {
charOffset);
Builder constructor = library.loader.getAbstractClassInstantiationError();
return new Throw(buildStaticInvocation(constructor.target,
new Arguments(<Expression>[new StringLiteral(className)])));
astFactory.arguments(<Expression>[new StringLiteral(className)])));
}
Statement buildCompileTimeErrorStatement(error, [int charOffset = -1]) {
@@ -118,7 +118,8 @@ abstract class FastaAccessor implements Accessor {
}
Expression makeInvalidWrite(Expression value) {
return buildThrowNoSuchMethodError(new Arguments(<Expression>[value]),
return buildThrowNoSuchMethodError(
helper.astFactory.arguments(<Expression>[value]),
isSetter: true);
}
@@ -209,7 +210,8 @@ abstract class ErrorAccessor implements FastaAccessor {
@override
Expression buildAssignment(Expression value, {bool voidContext: false}) {
return buildError(new Arguments(<Expression>[value]), isSetter: true);
return buildError(helper.astFactory.arguments(<Expression>[value]),
isSetter: true);
}
@override
@@ -217,7 +219,8 @@ abstract class ErrorAccessor implements FastaAccessor {
{int offset: TreeNode.noOffset,
bool voidContext: false,
Procedure interfaceTarget}) {
return buildError(new Arguments(<Expression>[value]), isGetter: true);
return buildError(helper.astFactory.arguments(<Expression>[value]),
isGetter: true);
}
@override
@@ -225,7 +228,8 @@ abstract class ErrorAccessor implements FastaAccessor {
{int offset: TreeNode.noOffset,
bool voidContext: false,
Procedure interfaceTarget}) {
return buildError(new Arguments(<Expression>[new IntLiteral(1)]),
return buildError(
helper.astFactory.arguments(<Expression>[new IntLiteral(1)]),
isGetter: true);
}
@@ -234,14 +238,16 @@ abstract class ErrorAccessor implements FastaAccessor {
{int offset: TreeNode.noOffset,
bool voidContext: false,
Procedure interfaceTarget}) {
return buildError(new Arguments(<Expression>[new IntLiteral(1)]),
return buildError(
helper.astFactory.arguments(<Expression>[new IntLiteral(1)]),
isGetter: true);
}
@override
Expression buildNullAwareAssignment(Expression value, DartType type,
{bool voidContext: false}) {
return buildError(new Arguments(<Expression>[value]), isSetter: true);
return buildError(helper.astFactory.arguments(<Expression>[value]),
isSetter: true);
}
@override
@@ -254,7 +260,8 @@ abstract class ErrorAccessor implements FastaAccessor {
@override
Expression makeInvalidWrite(Expression value) {
return buildError(new Arguments(<Expression>[value]), isSetter: true);
return buildError(helper.astFactory.arguments(<Expression>[value]),
isSetter: true);
}
}
@@ -321,14 +321,14 @@ class IndexAccessor extends Accessor {
this.getter, this.setter, Token token)
: super(helper, token);
Expression _makeSimpleRead() => helper.astFactory.methodInvocation(
receiver, indexGetName, new Arguments(<Expression>[index]), getter)
Expression _makeSimpleRead() => helper.astFactory.methodInvocation(receiver,
indexGetName, helper.astFactory.arguments(<Expression>[index]), getter)
..fileOffset = offsetForToken(token);
Expression _makeSimpleWrite(Expression value, bool voidContext) {
if (!voidContext) return _makeWriteAndReturn(value);
return helper.astFactory.methodInvocation(receiver, indexSetName,
new Arguments(<Expression>[index, value]), setter)
helper.astFactory.arguments(<Expression>[index, value]), setter)
..fileOffset = offsetForToken(token);
}
@@ -346,15 +346,18 @@ class IndexAccessor extends Accessor {
}
Expression _makeRead() {
return builtGetter = helper.astFactory.methodInvocation(receiverAccess(),
indexGetName, new Arguments(<Expression>[indexAccess()]), getter)
return builtGetter = helper.astFactory.methodInvocation(
receiverAccess(),
indexGetName,
helper.astFactory.arguments(<Expression>[indexAccess()]),
getter)
..fileOffset = offsetForToken(token);
}
Expression _makeWrite(Expression value, bool voidContext) {
if (!voidContext) return _makeWriteAndReturn(value);
return helper.astFactory.methodInvocation(receiverAccess(), indexSetName,
new Arguments(<Expression>[indexAccess(), value]), setter)
helper.astFactory.arguments(<Expression>[indexAccess(), value]), setter)
..fileOffset = offsetForToken(token);
}
@@ -368,7 +371,7 @@ class IndexAccessor extends Accessor {
.methodInvocation(
receiverAccess(),
indexSetName,
new Arguments(
helper.astFactory.arguments(
<Expression>[indexAccess(), new VariableGet(valueVariable)]),
setter)
..fileOffset = offsetForToken(token));
@@ -394,13 +397,16 @@ class ThisIndexAccessor extends Accessor {
Expression _makeSimpleRead() {
return helper.astFactory.methodInvocation(new ThisExpression(),
indexGetName, new Arguments(<Expression>[index]), getter);
indexGetName, helper.astFactory.arguments(<Expression>[index]), getter);
}
Expression _makeSimpleWrite(Expression value, bool voidContext) {
if (!voidContext) return _makeWriteAndReturn(value);
return helper.astFactory.methodInvocation(new ThisExpression(),
indexSetName, new Arguments(<Expression>[index, value]), setter);
return helper.astFactory.methodInvocation(
new ThisExpression(),
indexSetName,
helper.astFactory.arguments(<Expression>[index, value]),
setter);
}
indexAccess() {
@@ -411,7 +417,7 @@ class ThisIndexAccessor extends Accessor {
Expression _makeRead() => builtGetter = helper.astFactory.methodInvocation(
new ThisExpression(),
indexGetName,
new Arguments(<Expression>[indexAccess()]),
helper.astFactory.arguments(<Expression>[indexAccess()]),
getter);
Expression _makeWrite(Expression value, bool voidContext) {
@@ -419,7 +425,7 @@ class ThisIndexAccessor extends Accessor {
return helper.astFactory.methodInvocation(
new ThisExpression(),
indexSetName,
new Arguments(<Expression>[indexAccess(), value]),
helper.astFactory.arguments(<Expression>[indexAccess(), value]),
setter);
}
@@ -429,7 +435,7 @@ class ThisIndexAccessor extends Accessor {
.methodInvocation(
new ThisExpression(),
indexSetName,
new Arguments(
helper.astFactory.arguments(
<Expression>[indexAccess(), new VariableGet(valueVariable)]),
setter));
return makeLet(
@@ -454,30 +460,32 @@ class SuperIndexAccessor extends Accessor {
}
Expression _makeSimpleRead() => new SuperMethodInvocation(
indexGetName, new Arguments(<Expression>[index]), getter);
indexGetName, helper.astFactory.arguments(<Expression>[index]), getter);
Expression _makeSimpleWrite(Expression value, bool voidContext) {
if (!voidContext) return _makeWriteAndReturn(value);
return new SuperMethodInvocation(
indexSetName, new Arguments(<Expression>[index, value]), setter);
return new SuperMethodInvocation(indexSetName,
helper.astFactory.arguments(<Expression>[index, value]), setter);
}
Expression _makeRead() {
return builtGetter = new SuperMethodInvocation(
indexGetName, new Arguments(<Expression>[indexAccess()]), getter);
return builtGetter = new SuperMethodInvocation(indexGetName,
helper.astFactory.arguments(<Expression>[indexAccess()]), getter);
}
Expression _makeWrite(Expression value, bool voidContext) {
if (!voidContext) return _makeWriteAndReturn(value);
return new SuperMethodInvocation(indexSetName,
new Arguments(<Expression>[indexAccess(), value]), setter);
return new SuperMethodInvocation(
indexSetName,
helper.astFactory.arguments(<Expression>[indexAccess(), value]),
setter);
}
_makeWriteAndReturn(Expression value) {
var valueVariable = new VariableDeclaration.forValue(value);
var dummy = new VariableDeclaration.forValue(new SuperMethodInvocation(
indexSetName,
new Arguments(
helper.astFactory.arguments(
<Expression>[indexAccess(), new VariableGet(valueVariable)]),
setter));
return makeLet(
@@ -537,8 +545,8 @@ Expression makeLet(VariableDeclaration variable, Expression body) {
Expression makeBinary(AstFactory astFactory, Expression left, Name operator,
Procedure interfaceTarget, Expression right,
{int offset: TreeNode.noOffset}) {
return astFactory.methodInvocation(
left, operator, new Arguments(<Expression>[right]), interfaceTarget)
return astFactory.methodInvocation(left, operator,
astFactory.arguments(<Expression>[right]), interfaceTarget)
..fileOffset = offset;
}
@@ -12,6 +12,12 @@ import 'kernel_shadow_ast.dart';
/// Concrete implementation of [builder.AstFactory] for building a kernel AST.
class KernelAstFactory implements AstFactory<VariableDeclaration> {
@override
Arguments arguments(List<Expression> positional,
{List<DartType> types, List<NamedExpression> named}) {
return new KernelArguments(positional, types: types, named: named);
}
@override
AsExpression asExpression(Expression operand, Token operator, DartType type) {
return new KernelAsExpression(operand, type)
@@ -167,6 +173,11 @@ class KernelAstFactory implements AstFactory<VariableDeclaration> {
..fileOffset = offsetForToken(token);
}
@override
void setExplicitArgumentTypes(Arguments arguments, List<DartType> types) {
KernelArguments.setExplicitArgumentTypes(arguments, types);
}
@override
StaticGet staticGet(Member readTarget, Token token) {
return new KernelStaticGet(readTarget)..fileOffset = offsetForToken(token);
@@ -23,6 +23,23 @@ import 'package:front_end/src/fasta/type_inference/type_inferrer.dart';
import 'package:front_end/src/fasta/type_inference/type_promotion.dart';
import 'package:kernel/ast.dart';
/// Concrete shadow object representing a set of invocation arguments.
class KernelArguments extends Arguments {
bool _hasExplicitTypeArguments;
KernelArguments(List<Expression> positional,
{List<DartType> types, List<NamedExpression> named})
: _hasExplicitTypeArguments = types != null && types.isNotEmpty,
super(positional, types: types, named: named);
static void setExplicitArgumentTypes(
KernelArguments arguments, List<DartType> types) {
arguments.types.clear();
arguments.types.addAll(types);
arguments._hasExplicitTypeArguments = true;
}
}
/// Shadow object for [AsExpression].
class KernelAsExpression extends AsExpression implements KernelExpression {
KernelAsExpression(Expression operand, DartType type) : super(operand, type);
@@ -109,15 +126,16 @@ class KernelConstructorInvocation extends ConstructorInvocation
@override
DartType _inferExpression(
KernelTypeInferrer inferrer, DartType typeContext, bool typeNeeded) {
KernelArguments arguments = this.arguments;
return inferrer.inferConstructorInvocation(
typeContext,
typeNeeded,
fileOffset,
target,
arguments.types.isEmpty ? null : arguments.types,
arguments._hasExplicitTypeArguments ? arguments.types : null,
_forEachArgument, (type) {
arguments = new Arguments(arguments.positional,
named: arguments.named, types: type.typeArguments);
arguments.types.clear();
arguments.types.addAll(type.typeArguments);
});
}
}
@@ -169,9 +169,12 @@ abstract class TypeInferrerImpl<S, E, V, F> extends TypeInferrer<S, E, V, F> {
[],
[],
typeContext,
typesFromDownwardsInference);
typesFromDownwardsInference,
downwards: true);
substitution = Substitution.fromPairs(
targetTypeParameters, typesFromDownwardsInference);
formalTypes = [];
actualTypes = [];
} else {
inferredClassType = targetClass.rawType;
}
-7
View File
@@ -76,7 +76,6 @@ inference/block_bodied_lambdas_no_return: Fail
inference/block_bodied_lambdas_sync_star: Fail
inference/circular_reference_via_closures: Fail
inference/circular_reference_via_closures_initializer_types: Fail
inference/constructors_downwards_with_constraint: Fail
inference/constructors_infer_from_arguments: Fail
inference/constructors_infer_from_arguments_argument_not_assignable: Fail
inference/constructors_infer_from_arguments_const: Fail
@@ -84,9 +83,7 @@ inference/constructors_infer_from_arguments_const_with_upper_bound: Fail
inference/constructors_infer_from_arguments_downwards_from_constructor: Fail
inference/constructors_infer_from_arguments_factory: Fail
inference/constructors_infer_from_arguments_factory_calls_constructor: Fail
inference/constructors_infer_from_arguments_named: Fail
inference/constructors_infer_from_arguments_named_factory: Fail
inference/constructors_infer_from_arguments_redirecting: Fail
inference/constructors_infer_from_arguments_redirecting_factory: Fail
inference/constructors_inference_f_bounded: Fail
inference/constructors_reverse_type_parameters: Fail
@@ -101,10 +98,8 @@ inference/downwards_inference_inside_top_level: Fail
inference/downwards_inference_on_function_arguments_infer_downwards: Fail
inference/downwards_inference_on_function_expressions: Fail
inference/downwards_inference_on_function_of_t_using_the_t: Fail
inference/downwards_inference_on_generic_constructor_arguments_empty_list: Fail
inference/downwards_inference_on_generic_constructor_arguments_infer_downwards: Fail
inference/downwards_inference_on_generic_function_expressions: Fail
inference/downwards_inference_on_instance_creations_infer_downwards: Fail
inference/downwards_inference_on_list_literals_infer_downwards: Fail
inference/downwards_inference_on_list_literals_infer_if_value_types_match_context: Fail
inference/downwards_inference_on_map_literals: Fail
@@ -177,7 +172,6 @@ inference/infer_statics_transitively_a: Fail
inference/infer_throw: Fail
inference/infer_type_on_var_from_field: Fail
inference/infer_typed_map_literal: Fail
inference/infer_types_on_generic_instantiations_5: Fail
inference/infer_types_on_loop_indices_for_each_loop: Fail
inference/infer_types_on_loop_indices_for_loop_with_inference: Fail
inference/infer_variable_void: Fail
@@ -204,7 +198,6 @@ inference/inferred_type_via_closure_multiple_levels_of_nesting: Fail
inference/inferred_type_via_closure_type_depends_on_args: Fail
inference/inferred_type_via_closure_type_independent_of_args_field: Fail
inference/inferred_type_via_closure_type_independent_of_args_top_level: Fail
inference/instantiate_to_bounds_invoke_constructor_no_bound: Fail
inference/instantiate_to_bounds_invoke_constructor_type_args_exact: Fail
inference/lambda_does_not_have_propagated_type_hint: Fail
inference/list_literals_can_infer_null_top_level: Fail
@@ -0,0 +1,22 @@
library test;
import self as self;
import "dart:core" as core;
class A extends core::Object {
constructor •() → void
: super core::Object::•()
;
}
class B extends self::A {
constructor •() → void
: super self::A::•()
;
}
class Foo<T extends self::A> extends core::Object {
constructor •() → void
: super core::Object::•()
;
}
static method main() → void {
self::Foo<self::B> foo = new self::Foo::•<self::B>();
}
@@ -0,0 +1,13 @@
library test;
import self as self;
import "dart:core" as core;
class C<T extends core::Object> extends core::Object {
field self::C::T t = null;
constructor named(core::List<self::C::T> t) → void
: super core::Object::•()
;
}
static method main() → dynamic {
self::C<core::int> x = new self::C::named<core::int>(<core::int>[]);
}
@@ -0,0 +1,16 @@
library test;
import self as self;
import "dart:core" as core;
class C<T extends core::Object> extends core::Object {
field self::C::T t;
constructor •(dynamic t) → void
: self::C::t = t, super core::Object::•()
;
constructor named(core::List<self::C::T> t) → void
: this self::C::•(t.[](0))
;
}
static method main() → dynamic {
self::C<core::int> x = new self::C::named<core::int>(<core::int>[42]);
}
@@ -0,0 +1,16 @@
library test;
import self as self;
import "dart:core" as core;
class F3<T extends core::Object> extends core::Object {
constructor •(core::Iterable<core::Iterable<self::F3::T>> a) → void
: super core::Object::•() {}
}
class F4<T extends core::Object> extends core::Object {
constructor •({core::Iterable<core::Iterable<self::F4::T>> a = null}) → void
: super core::Object::•() {}
}
static method main() → void {
new self::F3::•<dynamic>(<core::Iterable<dynamic>>[]);
new self::F4::•<dynamic>(a: <core::Iterable<dynamic>>[]);
}
@@ -0,0 +1,112 @@
library test;
import self as self;
import "dart:core" as core;
class A<S extends core::Object, T extends core::Object> extends core::Object {
field self::A::S x;
field self::A::T y;
constructor •(dynamic x, dynamic y) → void
: self::A::x = x, self::A::y = y, super core::Object::•()
;
constructor named(dynamic x, dynamic y) → void
: self::A::x = x, self::A::y = y, super core::Object::•()
;
}
class B<S extends core::Object, T extends core::Object> extends self::A<self::B::T, self::B::S> {
constructor •(self::B::S y, self::B::T x) → void
: super self::A::•(x, y)
;
constructor named(self::B::S y, self::B::T x) → void
: super self::A::named(x, y)
;
}
class C<S extends core::Object> extends self::B<self::C::S, self::C::S> {
constructor •(self::C::S a) → void
: super self::B::•(a, a)
;
constructor named(self::C::S a) → void
: super self::B::named(a, a)
;
}
class D<S extends core::Object, T extends core::Object> extends self::B<self::D::T, core::int> {
constructor •(self::D::T a) → void
: super self::B::•(a, 3)
;
constructor named(self::D::T a) → void
: super self::B::named(a, 3)
;
}
class E<S extends core::Object, T extends core::Object> extends self::A<self::C<self::E::S>, self::E::T> {
constructor •(self::E::T a) → void
: super self::A::•(null, a)
;
}
class F<S extends core::Object, T extends core::Object> extends self::A<self::F::S, self::F::T> {
constructor •(self::F::S x, self::F::T y, {core::List<self::F::S> a = null, core::List<self::F::T> b = null}) → void
: super self::A::•(x, y)
;
constructor named(self::F::S x, self::F::T y, [self::F::S a = null, self::F::T b = null]) → void
: super self::A::•(a, b)
;
}
static method main() → void {
{
self::A<core::int, core::String> a0 = new self::A::•<core::int, core::String>(3, "hello");
self::A<core::int, core::String> a1 = new self::A::named<core::int, core::String>(3, "hello");
self::A<core::int, core::String> a2 = new self::A::•<core::int, core::String>(3, "hello");
self::A<core::int, core::String> a3 = new self::A::named<core::int, core::String>(3, "hello");
self::A<core::int, core::String> a4 = new self::A::•<core::int, dynamic>(3, "hello");
self::A<core::int, core::String> a5 = new self::A::named<dynamic, dynamic>(3, "hello");
}
{
self::A<core::int, core::String> a0 = new self::A::•<core::int, core::String>("hello", 3);
self::A<core::int, core::String> a1 = new self::A::named<core::int, core::String>("hello", 3);
}
{
self::A<core::int, core::String> a0 = new self::B::•<core::String, core::int>("hello", 3);
self::A<core::int, core::String> a1 = new self::B::named<core::String, core::int>("hello", 3);
self::A<core::int, core::String> a2 = new self::B::•<core::String, core::int>("hello", 3);
self::A<core::int, core::String> a3 = new self::B::named<core::String, core::int>("hello", 3);
self::A<core::int, core::String> a4 = new self::B::•<core::String, dynamic>("hello", 3);
self::A<core::int, core::String> a5 = new self::B::named<dynamic, dynamic>("hello", 3);
}
{
self::A<core::int, core::String> a0 = new self::B::•<core::String, core::int>(3, "hello");
self::A<core::int, core::String> a1 = new self::B::named<core::String, core::int>(3, "hello");
}
{
self::A<core::int, core::int> a0 = new self::C::•<core::int>(3);
self::A<core::int, core::int> a1 = new self::C::named<core::int>(3);
self::A<core::int, core::int> a2 = new self::C::•<core::int>(3);
self::A<core::int, core::int> a3 = new self::C::named<core::int>(3);
self::A<core::int, core::int> a4 = new self::C::•<dynamic>(3);
self::A<core::int, core::int> a5 = new self::C::named<dynamic>(3);
}
{
self::A<core::int, core::int> a0 = new self::C::•<core::int>("hello");
self::A<core::int, core::int> a1 = new self::C::named<core::int>("hello");
}
{
self::A<core::int, core::String> a0 = new self::D::•<dynamic, core::String>("hello");
self::A<core::int, core::String> a1 = new self::D::named<dynamic, core::String>("hello");
self::A<core::int, core::String> a2 = new self::D::•<core::int, core::String>("hello");
self::A<core::int, core::String> a3 = new self::D::named<core::String, core::String>("hello");
self::A<core::int, core::String> a4 = new self::D::•<core::num, dynamic>("hello");
self::A<core::int, core::String> a5 = new self::D::named<dynamic, dynamic>("hello");
}
{
self::A<core::int, core::String> a0 = new self::D::•<dynamic, core::String>(3);
self::A<core::int, core::String> a1 = new self::D::named<dynamic, core::String>(3);
}
{
self::A<self::C<core::int>, core::String> a0 = new self::E::•<core::int, core::String>("hello");
}
{
self::A<core::int, core::String> a0 = new self::F::•<core::int, core::String>(3, "hello", a: <core::int>[3], b: <core::String>["hello"]);
self::A<core::int, core::String> a1 = new self::F::•<core::int, core::String>(3, "hello", a: <core::int>["hello"], b: <core::String>[3]);
self::A<core::int, core::String> a2 = new self::F::named<core::int, core::String>(3, "hello", 3, "hello");
self::A<core::int, core::String> a3 = new self::F::named<core::int, core::String>(3, "hello");
self::A<core::int, core::String> a4 = new self::F::named<core::int, core::String>(3, "hello", "hello", 3);
self::A<core::int, core::String> a5 = new self::F::named<core::int, core::String>(3, "hello", "hello");
}
}
@@ -30,3 +30,5 @@ foo() {
.m(null, null);
String z = new /*@typeArgs=dynamic*/ B().m(null, null);
}
main() {}
@@ -0,0 +1,35 @@
library test;
import self as self;
import "dart:core" as core;
abstract class I<E extends core::Object> extends core::Object {
constructor •() → void
: super core::Object::•()
;
abstract method m(dynamic a, dynamic f) → core::String;
}
abstract class A<E extends core::Object> extends core::Object implements self::I<self::A::E> {
const constructor •() → void
: super core::Object::•()
;
abstract method m(dynamic a, dynamic f) → core::String;
}
abstract class M extends core::Object {
final field core::int y = 0;
constructor •() → void
: super core::Object::•()
;
}
class B<E extends core::Object> extends self::A<self::B::E> implements self::M {
const constructor •() → void
: super self::A::•()
;
get y() → core::int
return 0;
method m(dynamic a, dynamic f) → dynamic {}
}
static method foo() → dynamic {
core::int y = new self::B::•<dynamic>().m(null, null);
core::String z = new self::B::•<dynamic>().m(null, null);
}
static method main() → dynamic {}
@@ -0,0 +1,17 @@
// Copyright (c) 2017, 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.
/*@testedFeatures=inference*/
library test;
class A<T> {
A(B<List<T>> b);
}
class B<T> {}
main() {
var /*@type=A<dynamic>*/ x =
new /*@typeArgs=dynamic*/ A(new /*@typeArgs=List<dynamic>*/ B());
}
@@ -0,0 +1,17 @@
library test;
import self as self;
import "dart:core" as core;
class A<T extends core::Object> extends core::Object {
constructor •(self::B<core::List<self::A::T>> b) → void
: super core::Object::•()
;
}
class B<T extends core::Object> extends core::Object {
constructor •() → void
: super core::Object::•()
;
}
static method main() → dynamic {
dynamic x = new self::A::•<dynamic>(new self::B::•<dynamic>());
}
@@ -0,0 +1,14 @@
library test;
import self as self;
import "dart:core" as core;
class A<T extends core::Object> extends core::Object {
constructor •(self::B<core::List<self::A::T>> b) → void
;
}
class B<T extends core::Object> extends core::Object {
constructor •() → void
;
}
static method main() → dynamic
;
@@ -0,0 +1,17 @@
library test;
import self as self;
import "dart:core" as core;
class A<T extends core::Object> extends core::Object {
constructor •(self::B<core::List<self::A::T>> b) → void
: super core::Object::•()
;
}
class B<T extends core::Object> extends core::Object {
constructor •() → void
: super core::Object::•()
;
}
static method main() → dynamic {
self::A<dynamic> x = new self::A::•<dynamic>(new self::B::•<core::List<dynamic>>());
}
@@ -0,0 +1,12 @@
library test;
import self as self;
import "dart:core" as core;
class C<T extends core::Object> extends core::Object {
constructor •() → void
: super core::Object::•()
;
}
static method main() → dynamic {
self::C<dynamic> v = new self::C::•<dynamic>();
}