Perform type inference on explicitly typed fields.
R=scheglov@google.com Review-Url: https://codereview.chromium.org/2905123002 .
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
-4
@@ -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
-3
@@ -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
-4
@@ -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;
|
||||
|
||||
+1
-1
@@ -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;
|
||||
|
||||
+1
-1
@@ -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 {}
|
||||
|
||||
+1
-1
@@ -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 {}
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
+1
-1
@@ -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::•()
|
||||
;
|
||||
|
||||
+1
-1
@@ -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::•()
|
||||
;
|
||||
|
||||
+1
-1
@@ -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);
|
||||
|
||||
+1
-1
@@ -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 {}
|
||||
|
||||
+1
-1
@@ -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() {}
|
||||
+12
@@ -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 {}
|
||||
+12
@@ -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
|
||||
;
|
||||
+12
@@ -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 {}
|
||||
+1
-1
@@ -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 {
|
||||
|
||||
+1
-1
@@ -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 {
|
||||
|
||||
+1
-1
@@ -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 {
|
||||
|
||||
+1
-1
@@ -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>
|
||||
|
||||
+1
-1
@@ -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>
|
||||
|
||||
+1
-1
@@ -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>
|
||||
|
||||
+1
-1
@@ -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>
|
||||
|
||||
+1
-1
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user