Perform type inference on explicitly typed fields.

R=scheglov@google.com

Review-Url: https://codereview.chromium.org/2905123002 .
This commit is contained in:
Paul Berry
2017-05-25 13:22:24 -07:00
parent f65c7ecbdf
commit cefc4cc768
41 changed files with 121 additions and 52 deletions
@@ -6,6 +6,8 @@ library fasta.field_builder;
import 'builder.dart' show LibraryBuilder, MemberBuilder;
import 'package:kernel/ast.dart' show DartType;
abstract class FieldBuilder<T> extends MemberBuilder {
final String name;
@@ -15,6 +17,8 @@ abstract class FieldBuilder<T> extends MemberBuilder {
this.name, this.modifiers, LibraryBuilder compilationUnit, int charOffset)
: super(compilationUnit, charOffset);
DartType get builtType;
void set initializer(T value);
bool get isField => true;
@@ -366,6 +366,7 @@ class BodyBuilder extends ScopeListener<JumpTarget> implements BuilderHelper {
"Unhandled: '${field.name}' has more than one declaration.");
}
field.initializer = initializer;
_typeInferrer.inferFieldInitializer(field.builtType, initializer);
}
}
pop(); // Type.
@@ -22,7 +22,7 @@ import 'package:front_end/src/fasta/source/source_library_builder.dart'
import 'package:front_end/src/fasta/type_inference/type_inference_listener.dart'
show TypeInferenceListener;
import 'package:kernel/ast.dart' show Expression, Field, Name;
import 'package:kernel/ast.dart' show DartType, Expression, Field, Name;
import 'kernel_builder.dart'
show Builder, FieldBuilder, KernelTypeBuilder, MetadataBuilder;
@@ -94,4 +94,7 @@ class KernelFieldBuilder extends FieldBuilder<Expression> {
initializer = expression;
}
}
@override
DartType get builtType => field.type;
}
@@ -1070,14 +1070,14 @@ class KernelTypeInferenceEngine extends TypeInferenceEngineImpl {
@override
KernelTypeInferrer createLocalTypeInferrer(
Uri uri, TypeInferenceListener listener) {
return new KernelTypeInferrer._(this, uri.toString(), listener);
return new KernelTypeInferrer._(this, uri.toString(), listener, false);
}
@override
KernelTypeInferrer createTopLevelTypeInferrer(
KernelField field, TypeInferenceListener listener) {
return field._typeInferrer =
new KernelTypeInferrer._(this, getFieldUri(field), listener);
new KernelTypeInferrer._(this, getFieldUri(field), listener, true);
}
@override
@@ -1128,8 +1128,8 @@ class KernelTypeInferrer extends TypeInferrerImpl {
final typePromoter = new KernelTypePromoter();
KernelTypeInferrer._(KernelTypeInferenceEngine engine, String uri,
TypeInferenceListener listener)
: super(engine, uri, listener);
TypeInferenceListener listener, bool topLevel)
: super(engine, uri, listener, topLevel);
@override
Expression getFieldInitializer(KernelField field) {
@@ -1165,7 +1165,7 @@ class KernelTypeInferrer extends TypeInferrerImpl {
}
@override
DartType inferFieldInitializer(
DartType inferFieldTopLevel(
KernelField field, DartType type, bool typeNeeded) {
return inferExpression(field.initializer, type, typeNeeded);
}
@@ -156,7 +156,7 @@ abstract class TypeInferenceEngineImpl extends TypeInferenceEngine {
var typeInferrer = getFieldTypeInferrer(field);
var type = getFieldDeclaredType(field);
var inferredType = typeInferrer.inferDeclarationType(
typeInferrer.inferFieldInitializer(field, type, type == null));
typeInferrer.inferFieldTopLevel(field, type, type == null));
if (type == null && strongMode && updateType) {
instrumentation?.record(
Uri.parse(typeInferrer.uri),
@@ -149,6 +149,9 @@ abstract class TypeInferrer {
/// Gets the [FieldNode] corresponding to the given [readTarget], if any.
FieldNode getFieldNodeForReadTarget(Member readTarget);
/// Performs full type inference on the given field initializer.
void inferFieldInitializer(DartType declaredType, Expression initializer);
/// Performs type inference on the given function body.
void inferFunctionBody(
DartType returnType, AsyncMarker asyncMarker, Statement body);
@@ -187,11 +190,12 @@ abstract class TypeInferrerImpl extends TypeInferrer {
/// inside a closure.
ClosureContext closureContext;
TypeInferrerImpl(TypeInferenceEngineImpl engine, this.uri, this.listener)
TypeInferrerImpl(
TypeInferenceEngineImpl engine, this.uri, this.listener, bool topLevel)
: coreTypes = engine.coreTypes,
strongMode = engine.strongMode,
classHierarchy = engine.classHierarchy,
instrumentation = engine.instrumentation,
instrumentation = topLevel ? null : engine.instrumentation,
typeSchemaEnvironment = engine.typeSchemaEnvironment;
/// Gets the type promoter that should be used to promote types during
@@ -300,11 +304,17 @@ abstract class TypeInferrerImpl extends TypeInferrer {
DartType inferExpression(
Expression expression, DartType typeContext, bool typeNeeded);
@override
void inferFieldInitializer(DartType declaredType, Expression initializer) {
assert(closureContext == null);
inferExpression(initializer, declaredType, false);
}
/// Performs type inference on the given [field]'s initializer expression.
///
/// Derived classes should provide an implementation that calls
/// [inferExpression] for the given [field]'s initializer expression.
DartType inferFieldInitializer(
DartType inferFieldTopLevel(
KernelField field, DartType type, bool typeNeeded);
@override
+1
View File
@@ -300,6 +300,7 @@ inference/simple_literal_int: Crash
inference/simple_literal_null: Crash
inference/static_method_tear_off: Crash
inference/string_literal: Crash
inference/subexpressions_of_explicitly_typed_fields: Crash
inference/top_level_return_and_yield: Crash
inference/toplevel_inference_toplevel_var: Crash
inference/type_cast: Crash
@@ -4,10 +4,10 @@ import "dart:async" as asy;
import "dart:core" as core;
static field asy::Future<core::int> futureInt = null;
static field () → asy::Future<core::int> f = () → dynamic => self::futureInt;
static field () → asy::Future<core::int> g = () → dynamic /* originally async */ {
final asy::Completer<asy::FutureOr<dynamic>> :completer = asy::Completer::sync<asy::FutureOr<dynamic>>();
asy::FutureOr<dynamic> :return_value;
static field () → asy::Future<core::int> f = () → asy::Future<core::int> => self::futureInt;
static field () → asy::Future<core::int> g = () → asy::Future<core::int> /* originally async */ {
final asy::Completer<asy::FutureOr<core::int>> :completer = asy::Completer::sync<asy::FutureOr<core::int>>();
asy::FutureOr<core::int> :return_value;
dynamic :async_op_then;
dynamic :async_op_error;
dynamic :await_jump_var = 0;
@@ -3,9 +3,9 @@ import self as self;
import "dart:async" as asy;
import "dart:core" as core;
static field () → asy::Future<core::int> f = () → dynamic /* originally async */ {
final asy::Completer<asy::FutureOr<dynamic>> :completer = asy::Completer::sync<asy::FutureOr<dynamic>>();
asy::FutureOr<dynamic> :return_value;
static field () → asy::Future<core::int> f = () → asy::Future<core::int> /* originally async */ {
final asy::Completer<asy::FutureOr<core::int>> :completer = asy::Completer::sync<asy::FutureOr<core::int>>();
asy::FutureOr<core::int> :return_value;
dynamic :async_op_then;
dynamic :async_op_error;
dynamic :await_jump_var = 0;
@@ -4,10 +4,10 @@ import "dart:async" as asy;
import "dart:core" as core;
static field asy::FutureOr<core::int> futureOrInt = null;
static field () → asy::FutureOr<core::int> f = () → dynamic => self::futureOrInt;
static field () → asy::Future<core::int> g = () → dynamic /* originally async */ {
final asy::Completer<asy::FutureOr<dynamic>> :completer = asy::Completer::sync<asy::FutureOr<dynamic>>();
asy::FutureOr<dynamic> :return_value;
static field () → asy::FutureOr<core::int> f = () → asy::FutureOr<core::int> => self::futureOrInt;
static field () → asy::Future<core::int> g = () → asy::Future<core::int> /* originally async */ {
final asy::Completer<asy::FutureOr<core::int>> :completer = asy::Completer::sync<asy::FutureOr<core::int>>();
asy::FutureOr<core::int> :return_value;
dynamic :async_op_then;
dynamic :async_op_error;
dynamic :await_jump_var = 0;
@@ -11,8 +11,8 @@ class A extends core::Object {
operator -(dynamic other) → core::double
return 2.0;
}
static field core::int v_add = new self::A::•().+("foo");
static field core::double v_minus = new self::A::•().-("bar");
static field core::int v_add = new self::A::•().{self::A::+}("foo");
static field core::double v_minus = new self::A::•().{self::A::-}("bar");
static method main() → dynamic {
self::v_add;
self::v_minus;
@@ -2,8 +2,8 @@ library test;
import self as self;
import "dart:core" as core;
static field core::num a = 1.==(2) ? 1 : 2.0;
static field core::num b = 1.==(2) ? 1.0 : 2;
static field core::num a = 1.{core::num::==}(2) ? 1 : 2.0;
static field core::num b = 1.{core::num::==}(2) ? 1.0 : 2;
static method main() → dynamic {
self::a;
self::b;
@@ -12,8 +12,8 @@ class A extends core::Object {
return 2.0;
}
static field self::A a = new self::A::•();
static field core::int v_complement = self::a.~();
static field core::double v_negate = self::a.unary-();
static field core::int v_complement = self::a.{self::A::~}();
static field core::double v_negate = self::a.{self::A::unary-}();
static method main() → dynamic {
self::a;
self::v_complement;
@@ -14,7 +14,7 @@ class C extends self::B {
;
method f() → dynamic {}
}
static field dynamic x = new self::C::•().f();
static field dynamic x = new self::C::•().{self::C::f}();
static method main() → dynamic {
self::x;
}
@@ -10,7 +10,7 @@ class C extends core::Object {
return true;
}
static field self::C c = new self::C::•();
static field core::bool x = self::c.*(self::c);
static field core::bool x = self::c.{self::C::*}(self::c);
static method main() → dynamic {
self::c;
self::x;
@@ -15,7 +15,7 @@ abstract class C extends core::Object implements self::I {
;
}
static field self::C c;
static field core::bool x = self::c.*(self::c);
static field core::bool x = self::c.{self::I::*}(self::c);
static method main() → dynamic {
self::c;
}
@@ -10,7 +10,7 @@ class C extends core::Object {
return true;
}
static field self::C c = new self::C::•();
static field core::bool x = self::c.unary-();
static field core::bool x = self::c.{self::C::unary-}();
static method main() → dynamic {
self::c;
self::x;
@@ -15,7 +15,7 @@ abstract class C extends core::Object implements self::I {
;
}
static field self::C c;
static field core::bool x = self::c.unary-();
static field core::bool x = self::c.{self::I::unary-}();
static method main() → dynamic {
self::c;
}
@@ -9,7 +9,7 @@ class C extends core::Object {
method g() → core::bool
return true;
}
static field core::bool x = self::f().g();
static field core::bool x = self::f().{self::C::g}();
static method f() → self::C
return null;
static method main() → dynamic {}
@@ -14,7 +14,7 @@ abstract class C extends core::Object implements self::I {
: super core::Object::•()
;
}
static field core::bool x = self::f().g();
static field core::bool x = self::f().{self::I::g}();
static method f() → self::C
return null;
static method main() → dynamic {}
@@ -2,7 +2,7 @@ library test;
import self as self;
import "dart:core" as core;
static field core::List<() → core::Object> v = <dynamic>[self::f, self::g];
static field core::List<() → core::Object> v = <() → core::Object>[self::f, self::g];
static method f() → core::int
return null;
static method g() → core::String
@@ -2,7 +2,7 @@ library test;
import self as self;
import "dart:core" as core;
static field core::List<((core::String) → core::int) → core::Object> v = <dynamic>[self::f, self::g];
static field core::List<((core::String) → core::int) → core::Object> v = <((core::String) → core::int) → core::Object>[self::f, self::g];
static method f((core::String) → core::int x) → core::int
return null;
static method g((core::String) → core::int x) → core::String
@@ -2,7 +2,7 @@ library test;
import self as self;
import "dart:core" as core;
static field core::List<(core::int) → core::Object> v = <dynamic>[self::f, self::g];
static field core::List<(core::int) → core::Object> v = <(core::int) → core::Object>[self::f, self::g];
static method f(core::int x) → core::int
return null;
static method g(core::int x) → core::String
@@ -3,7 +3,7 @@ import self as self;
import "dart:core" as core;
class C extends core::Object {
static final field (core::bool) → core::bool f = (core::bool b) → dynamic => b;
static final field (core::bool) → core::bool f = (core::bool b) → core::bool => b;
constructor •() → void
: super core::Object::•()
;
@@ -3,7 +3,7 @@ import self as self;
import "dart:core" as core;
class C extends core::Object {
static final field (core::bool) → core::int f = (core::bool b) → dynamic => 1;
static final field (core::bool) → core::int f = (core::bool b) → core::int => 1;
constructor •() → void
: super core::Object::•()
;
@@ -2,7 +2,7 @@ library test;
import self as self;
import "dart:core" as core;
static final field (core::bool) → core::int f = (core::bool b) → dynamic => 1;
static final field (core::bool) → core::int f = (core::bool b) → core::int => 1;
static method main() → dynamic {
self::f;
}
@@ -2,8 +2,8 @@ library test;
import self as self;
import "dart:core" as core;
static field core::List<core::int> x1 = <dynamic>[1, 2, 3];
static field core::List<core::num> x2 = <dynamic>[1, 2.0, 3];
static field core::List<core::int> x1 = <core::int>[1, 2, 3];
static field core::List<core::num> x2 = <core::num>[1, 2.0, 3];
static method test1() → dynamic {
self::x1.{core::List::add}("hi");
self::x1.{core::List::add}(4.0);
@@ -14,5 +14,5 @@ class D<T extends core::Object> extends core::Object {
: super core::Object::•()
;
}
static field self::D<core::int> f = new self::C::•().f<core::int>();
static field self::D<core::int> f = new self::C::•().{self::C::f}<core::int>();
static method main() → dynamic {}
@@ -15,5 +15,5 @@ class D<T extends core::Object> extends core::Object {
;
}
static field self::C c;
static field self::D<core::int> f = self::c.f<core::int>();
static field self::D<core::int> f = self::c.{self::C::f}<core::int>();
static method main() → dynamic {}
@@ -0,0 +1,14 @@
// 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 C {
List<num> x = /*@typeArgs=num*/ [0];
}
List<num> y = /*@typeArgs=num*/ [0];
main() {}
@@ -0,0 +1,12 @@
library test;
import self as self;
import "dart:core" as core;
class C extends core::Object {
field core::List<core::num> x = <dynamic>[0];
constructor •() → void
: super core::Object::•()
;
}
static field core::List<core::num> y = <dynamic>[0];
static method main() → dynamic {}
@@ -0,0 +1,12 @@
library test;
import self as self;
import "dart:core" as core;
class C extends core::Object {
field core::List<core::num> x;
constructor •() → void
;
}
static field core::List<core::num> y;
static method main() → dynamic
;
@@ -0,0 +1,12 @@
library test;
import self as self;
import "dart:core" as core;
class C extends core::Object {
field core::List<core::num> x = <core::num>[0];
constructor •() → void
: super core::Object::•()
;
}
static field core::List<core::num> y = <core::num>[0];
static method main() → dynamic {}
@@ -7,7 +7,7 @@ class C<T extends core::Object> extends core::Object {
: super core::Object::•()
;
}
static field self::C<dynamic> v = new self::C::•<dynamic>(() → dynamic {
static field self::C<dynamic> v = new self::C::•<dynamic>(() → core::int {
return 1;
});
static method main() → dynamic {
@@ -7,7 +7,7 @@ class C<T extends core::Object> extends core::Object {
: super core::Object::•()
;
}
static field self::C<core::int> v = new self::C::•<core::int>(() → dynamic {
static field self::C<core::int> v = new self::C::•<core::int>(() → core::int {
return 1;
});
static method main() → dynamic {
@@ -7,7 +7,7 @@ class C extends core::Object {
: super core::Object::•()
;
}
static field self::C v = new self::C::•(() → dynamic {
static field self::C v = new self::C::•(() → core::int {
return 1;
});
static method main() → dynamic {
@@ -2,7 +2,7 @@ library test;
import self as self;
import "dart:core" as core;
static field core::List<dynamic> v = self::f<dynamic>(() → dynamic {
static field core::List<dynamic> v = self::f<dynamic>(() → core::int {
return 1;
});
static method f<T extends core::Object>(() → self::f::T g) → core::List<self::f::T>
@@ -2,7 +2,7 @@ library test;
import self as self;
import "dart:core" as core;
static field dynamic v = self::f.call(() → dynamic {
static field dynamic v = self::f.call(() → core::int {
return 1;
});
static method f<T extends core::Object>(() → self::f::T g) → core::List<self::f::T>
@@ -2,7 +2,7 @@ library test;
import self as self;
import "dart:core" as core;
static field core::List<core::int> v = self::f<core::int>(() → dynamic {
static field core::List<core::int> v = self::f<core::int>(() → core::int {
return 1;
});
static method f<T extends core::Object>(() → self::f::T g) → core::List<self::f::T>
@@ -2,7 +2,7 @@ library test;
import self as self;
import "dart:core" as core;
static field dynamic v = self::f.call(() → dynamic {
static field dynamic v = self::f.call(() → core::int {
return 1;
});
static method f<T extends core::Object>(() → self::f::T g) → core::List<self::f::T>
@@ -9,7 +9,7 @@ class C extends core::Object {
method f(dynamic x) → core::double
return 1.0;
}
static field core::double v = new self::C::•().f(() → dynamic {
static field core::double v = new self::C::•().{self::C::f}(() → core::int {
return 1;
});
static method main() → dynamic {