[VM runtime] Improve type error messages in Dart 2 (fixes #32564).

Hide private class _Future and map it to core lib class Future.
In Dart 2, show dynamic as type argument(s) of raw generic types.

Change-Id: I70b0e1707bc767d04838ac12d16b3ad15623f51f
Reviewed-on: https://dart-review.googlesource.com/48502
Reviewed-by: Siva Annamalai <asiva@google.com>
This commit is contained in:
Régis Crelier 2018-03-28 17:12:04 +00:00
parent ebdee7ee0f
commit 85b4c604c5
7 changed files with 40 additions and 19 deletions

View file

@ -3550,8 +3550,13 @@ RawString* Class::GenerateUserVisibleName() const {
return Symbols::List().raw();
#endif // !defined(PRODUCT)
}
const String& name = String::Handle(Name());
return String::ScrubName(name);
String& name = String::Handle(Name());
name = String::ScrubName(name);
if (name.raw() == Symbols::FutureImpl().raw() &&
library() == Library::AsyncLibrary()) {
return Symbols::Future().raw();
}
return name.raw();
}
void Class::set_script(const Script& value) const {
@ -4778,7 +4783,6 @@ RawString* TypeArguments::SubvectorName(intptr_t from_index,
NameVisibility name_visibility) const {
Thread* thread = Thread::Current();
Zone* zone = thread->zone();
ASSERT(from_index + len <= Length());
String& name = String::Handle(zone);
const intptr_t num_strings =
(len == 0) ? 2 : 2 * len + 1; // "<""T"", ""T"">".
@ -4786,8 +4790,14 @@ RawString* TypeArguments::SubvectorName(intptr_t from_index,
pieces.Add(Symbols::LAngleBracket());
AbstractType& type = AbstractType::Handle(zone);
for (intptr_t i = 0; i < len; i++) {
type = TypeAt(from_index + i);
name = type.BuildName(name_visibility);
if (from_index + i < Length()) {
type = TypeAt(from_index + i);
name = type.BuildName(name_visibility);
} else {
// Show dynamic type argument in strong mode.
ASSERT(thread->isolate()->strong());
name = Symbols::Dynamic().raw();
}
pieces.Add(name);
if (i < len - 1) {
pieces.Add(Symbols::CommaSpace());
@ -16529,8 +16539,10 @@ RawString* AbstractType::BuildName(NameVisibility name_visibility) const {
num_type_params = num_args;
} else {
ASSERT(num_args == 0); // Type is raw.
// No need to fill up with "dynamic".
num_type_params = 0;
// No need to fill up with "dynamic", unless running in strong mode.
if (!thread->isolate()->strong()) {
num_type_params = 0;
}
}
} else {
// The actual type argument vector can be longer than necessary, because
@ -16549,7 +16561,8 @@ RawString* AbstractType::BuildName(NameVisibility name_visibility) const {
GrowableHandlePtrArray<const String> pieces(zone, 4);
pieces.Add(class_name);
if ((num_type_params == 0) ||
args.IsRaw(first_type_param_index, num_type_params)) {
(!thread->isolate()->strong() &&
args.IsRaw(first_type_param_index, num_type_params))) {
// Do nothing.
} else {
const String& args_name = String::Handle(
@ -22532,7 +22545,7 @@ int64_t Closure::ComputeHash() const {
const Function& func = Function::Handle(zone, function());
uint32_t result = 0;
if (func.IsImplicitInstanceClosureFunction()) {
// Implicit instance closures are not unqiue, so combine function's hash
// Implicit instance closures are not unique, so combine function's hash
// code with identityHashCode of cached receiver.
result = static_cast<uint32_t>(func.ComputeClosureHash());
const Context& context = Context::Handle(zone, this->context());

View file

@ -136,6 +136,7 @@ class ObjectPointerVisitor;
V(AwaitTempVarPrefix, ":await_temp_var_") \
V(AwaitContextVar, ":await_ctx_var") \
V(AwaitJumpVar, ":await_jump_var") \
V(FutureImpl, "_Future") \
V(Future, "Future") \
V(FutureOr, "FutureOr") \
V(FutureMicrotask, "Future.microtask") \

View file

@ -35,11 +35,11 @@ main() {
var d;
d = new Derived(); // //# 00: continued
Expect.equals("Derived", d.t.toString()); // //# 00: continued
Expect.equals("Derived<dynamic>", d.t.toString()); // //# 00: continued
d = new Derived<bool>(); // //# 00: continued
Expect.equals("Derived<bool>", d.t.toString()); // //# 00: continued
d = new Derived<Derived>(); // //# 00: continued
Expect.equals("Derived<Derived>", d.t.toString()); // //# 00: continued
Expect.equals("Derived<Derived<dynamic>>", d.t.toString()); // //# 00: continued
d = new Derived(); // //# 01: continued
@ -50,23 +50,23 @@ main() {
Expect.equals("Derived<Derived<int>>", d.t.toString()); // //# 01: continued
d = new Derived(); // //# 02: continued
Expect.equals("Derived<Derived>", d.t.toString()); // //# 02: continued
Expect.equals("Derived<Derived<dynamic>>", d.t.toString()); // //# 02: continued
d = new Derived<bool>(); // //# 02: continued
Expect.equals("Derived<Derived<bool>>", d.t.toString()); // //# 02: continued
d = new Derived<Derived>(); // //# 02: continued
Expect.equals("Derived<Derived<Derived>>", d.t.toString()); // //# 02: continued
Expect.equals("Derived<Derived<Derived<dynamic>>>", d.t.toString()); // //# 02: continued
d = new Derived1(); // //# 03: continued
Expect.equals("Derived2", d.t.toString()); // //# 03: continued
Expect.equals("Derived2<dynamic>", d.t.toString()); // //# 03: continued
d = new Derived2(); // //# 03: continued
Expect.equals("Derived1", d.t.toString()); // //# 03: continued
Expect.equals("Derived1<dynamic>", d.t.toString()); // //# 03: continued
d = new Derived2<Derived1<int>>(); // //# 03: continued
Expect.equals("Derived1<Derived1<int>>", d.t.toString()); // //# 03: continued
d = new Derived1(); // //# 04: continued
Expect.equals("Derived2", d.t.toString()); // //# 04: continued
Expect.equals("Derived2<dynamic>", d.t.toString()); // //# 04: continued
d = new Derived2(); // //# 04: continued
Expect.equals("Derived1<Derived2>", d.t.toString()); // //# 04: continued
Expect.equals("Derived1<Derived2<dynamic>>", d.t.toString()); // //# 04: continued
d = new Derived2<Derived1<int>>(); // //# 04: continued
Expect.equals("Derived1<Derived2<Derived1<int>>>", d.t.toString()); // //# 04: continued
}

View file

@ -11,5 +11,5 @@ class A<T extends B<T>> {}
class B<T> extends A {}
main() {
Expect.equals("B<B>", new B<B>().runtimeType.toString());
Expect.equals("B<B<dynamic>>", new B<B>().runtimeType.toString());
}

View file

@ -776,6 +776,7 @@ covariance_field_test/05: RuntimeError
ct_const_test: RuntimeError # Issue 2992; RangeError: Maximum call stack size exceeded
custom_await_stack_trace_test: RuntimeError # Issue 29920; Uncaught Expect.equals(at index 0: Expected <Blah \x0ABloop\x0ABleep\x0A...>
cyclic_type2_test: RuntimeError # Issue 29920; Uncaught ReferenceError: V is not defined
cyclic_type_test/00: RuntimeError # Issue 32564: <dynamic> not printed.
cyclic_type_test/02: RuntimeError # Issue 29920; Uncaught RangeError: Maximum call stack size exceeded
cyclic_type_test/03: RuntimeError # Issue 29920; Uncaught ReferenceError: U is not defined
cyclic_type_test/04: RuntimeError # Issue 29920; Uncaught ReferenceError: U is not defined
@ -790,6 +791,7 @@ example_constructor_test: RuntimeError # Expect.equals(expected: <0 1 2 3 4 5 6
exception_test: RuntimeError # DDC doesn't implement NullThrownError?; Expect.isTrue(false) fails.
expect_test: RuntimeError # Issue 29920; Expect.identical did not fail
f_bounded_quantification3_test: RuntimeError # Issue 29920; Uncaught Error: type arguments should not be null: (F1, F2) => {
f_bounded_quantification4_test: RuntimeError # Issue 32564: <dynamic> not printed.
field3_test/01: MissingCompileTimeError
field_increment_bailout_test: RuntimeError # Issue 29920; UnimplementedError: JsInstanceMirror.delegate unimplemented
field_initialization_order_test/none: RuntimeError # Expect.equals(expected: <b.a.ai.bi.>, actual: <b.bi.a.ai.>) fails.
@ -833,6 +835,7 @@ local_function_test/none: RuntimeError # Expect.equals(expected: <true>, actual:
many_overridden_no_such_method_test: RuntimeError # UnimplementedError: JsInstanceMirror.delegate unimplemented; UnimplementedError: JsInstanceMirror.delegate unimplemented
method_override7_test/03: MissingCompileTimeError # Issue 30514
mint_arithmetic_test: RuntimeError # Issue 29920; Expect.equals(expected: <4294967297>, actual: <1>) fails.
mixin_mixin6_test: RuntimeError # Issue 32564: <dynamic> not printed.
modulo_test: RuntimeError # Ints and doubles are unified.; Expect.throws fails: Did not throw
multiline_newline_test/04: MissingCompileTimeError
multiline_newline_test/04r: MissingCompileTimeError

View file

@ -1285,7 +1285,9 @@ async_star_regression_2238_test: CompileTimeError, RuntimeError
class_keyword_test/02: MissingCompileTimeError # Issue 13627
constructor3_test: Fail, OK, Pass
cyclic_type2_test: Fail, OK
cyclic_type_test/00: RuntimeError, OK # Not running in strong mode.
cyclic_type_test/02: Fail, OK # Non-contractive types are not supported in the vm.
cyclic_type_test/03: RuntimeError, OK # Not running in strong mode.
cyclic_type_test/04: Fail, OK
deferred_redirecting_factory_test: Fail, Crash # Issue 23408
duplicate_export_negative_test: Fail # Issue 6134
@ -1293,12 +1295,14 @@ dynamic_prefix_core_test/01: RuntimeError # Issue 12478
example_constructor_test: Fail, OK
export_ambiguous_main_negative_test: Fail # Issue 14763
field_initialization_order_test: Fail, OK
f_bounded_quantification4_test: RuntimeError, OK # Not running in strong mode.
generic_methods_bounds_test/02: MissingRuntimeError
library_env_test/has_html_support: RuntimeError, OK
library_env_test/has_no_io_support: RuntimeError, OK
main_not_a_function_test: Skip
mixin_illegal_super_use_test: Skip # Issues 24478 and 23773
mixin_illegal_superclass_test: Skip # Issues 24478 and 23773
mixin_mixin6_test: RuntimeError, OK # Not running in strong mode.
multiline_strings_test: Fail # Issue 23020
no_main_test/01: Skip
regress_19413_test: MissingCompileTimeError

View file

@ -26,7 +26,7 @@ class C<T> = S<List<T>> with B implements K<T>; // B is raw.
main() {
var c = new C<int>();
Expect.equals("Map<dynamic, Set>", c.m().toString());
Expect.equals("Map<dynamic, Set<dynamic>>", c.m().toString());
Expect.isTrue(c is K<int>);
Expect.isTrue(c is J);
Expect.isTrue(c is I<Set>);