Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit fd20c7b

Browse files
creliercommit-bot@chromium.org
authored andcommitted
[VM/nnbd] Print nullability of types by default.
Only '?' is shown by default. To print '*' and '%', use debugging flag --show-internal-names. Fix expectations in tests. Change-Id: Idc60fbfb4d477602eb0c713f4bdcc1e573a3328a Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/135790 Commit-Queue: Régis Crelier <[email protected]> Reviewed-by: Alexander Markov <[email protected]> Reviewed-by: Liam Appelbe <[email protected]>
1 parent dae3084 commit fd20c7b

File tree

5 files changed

+75
-43
lines changed

5 files changed

+75
-43
lines changed

runtime/vm/dart_api_impl_test.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6086,7 +6086,7 @@ TEST_CASE(DartAPI_GetNullableType) {
60866086
EXPECT_VALID(name);
60876087
const char* name_cstr = "";
60886088
EXPECT_VALID(Dart_StringToCString(name, &name_cstr));
6089-
EXPECT_STREQ("Class", name_cstr);
6089+
EXPECT_STREQ("Class?", name_cstr);
60906090

60916091
name = Dart_GetField(type, NewString("name"));
60926092
EXPECT_VALID(name);

runtime/vm/debugger.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1542,7 +1542,7 @@ RawTypeArguments* ActivationFrame::BuildParameters(
15421542
mapping_offset -= size;
15431543
for (intptr_t j = 0; j < size; ++j) {
15441544
type_param = TypeParameter::RawCast(type_params.TypeAt(j));
1545-
name = type_param.Name();
1545+
name = type_param.name();
15461546
// Write the names in backwards in terms of chain of functions.
15471547
// But keep the order of names within the same function. so they
15481548
// match up with the order of the types in 'type_arguments'.

runtime/vm/object.cc

Lines changed: 53 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -73,9 +73,8 @@ DEFINE_FLAG(
7373
show_internal_names,
7474
false,
7575
"Show names of internal classes (e.g. \"OneByteString\") in error messages "
76-
"instead of showing the corresponding interface names (e.g. \"String\")");
77-
// TODO(regis): Remove this temporary flag used to debug nullability.
78-
DEFINE_FLAG(bool, show_nullability, false, "Show nullability in type names");
76+
"instead of showing the corresponding interface names (e.g. \"String\"). "
77+
"Also show legacy nullability in type names.");
7978
DEFINE_FLAG(bool, use_lib_cache, false, "Use library name cache");
8079
DEFINE_FLAG(bool, use_exp_cache, false, "Use library exported name cache");
8180

@@ -5664,7 +5663,11 @@ void TypeArguments::PrintSubvectorName(intptr_t from_index,
56645663
for (intptr_t i = 0; i < len; i++) {
56655664
if (from_index + i < Length()) {
56665665
type = TypeAt(from_index + i);
5667-
type.PrintName(name_visibility, printer);
5666+
if (type.IsNull()) {
5667+
printer->AddString("null"); // Unfinalized vector.
5668+
} else {
5669+
type.PrintName(name_visibility, printer);
5670+
}
56685671
} else {
56695672
printer->AddString("dynamic");
56705673
}
@@ -18084,17 +18087,26 @@ RawString* AbstractType::PrintURIs(URIs* uris) {
1808418087
return Symbols::FromConcatAll(thread, pieces);
1808518088
}
1808618089

18087-
static const char* NullabilitySuffix(Nullability value) {
18090+
const char* AbstractType::NullabilitySuffix(
18091+
NameVisibility name_visibility) const {
18092+
if (IsDynamicType() || IsVoidType() || IsNullType()) {
18093+
// Hide nullable suffix.
18094+
return "";
18095+
}
1808818096
// Keep in sync with Nullability enum in runtime/vm/object.h.
18089-
switch (value) {
18097+
switch (nullability()) {
1809018098
case Nullability::kUndetermined:
18091-
return "%";
18099+
return (FLAG_show_internal_names || name_visibility == kInternalName)
18100+
? "%"
18101+
: "";
1809218102
case Nullability::kNullable:
1809318103
return "?";
1809418104
case Nullability::kNonNullable:
1809518105
return "";
1809618106
case Nullability::kLegacy:
18097-
return "*";
18107+
return (FLAG_show_internal_names || name_visibility == kInternalName)
18108+
? "*"
18109+
: "";
1809818110
default:
1809918111
UNREACHABLE();
1810018112
}
@@ -18121,9 +18133,7 @@ void AbstractType::PrintName(NameVisibility name_visibility,
1812118133
Zone* zone = thread->zone();
1812218134
if (IsTypeParameter()) {
1812318135
printer->AddString(String::Handle(zone, TypeParameter::Cast(*this).name()));
18124-
if (FLAG_show_nullability) {
18125-
printer->AddString(NullabilitySuffix(nullability()));
18126-
}
18136+
printer->AddString(NullabilitySuffix(name_visibility));
1812718137
return;
1812818138
}
1812918139
const TypeArguments& args = TypeArguments::Handle(zone, arguments());
@@ -18136,9 +18146,14 @@ void AbstractType::PrintName(NameVisibility name_visibility,
1813618146
const Function& signature_function =
1813718147
Function::Handle(zone, Type::Cast(*this).signature());
1813818148
if (!cls.IsTypedefClass()) {
18139-
signature_function.PrintSignature(kUserVisibleName, printer);
18140-
if (FLAG_show_nullability) {
18141-
printer->AddString(NullabilitySuffix(nullability()));
18149+
const char* suffix = NullabilitySuffix(name_visibility);
18150+
if (suffix[0] != '\0') {
18151+
printer->AddString("(");
18152+
}
18153+
signature_function.PrintSignature(name_visibility, printer);
18154+
if (suffix[0] != '\0') {
18155+
printer->AddString(")");
18156+
printer->AddString(suffix);
1814218157
}
1814318158
return;
1814418159
}
@@ -18148,9 +18163,7 @@ void AbstractType::PrintName(NameVisibility name_visibility,
1814818163
if (!IsFinalized() || IsBeingFinalized()) {
1814918164
// TODO(regis): Check if this is dead code.
1815018165
printer->AddString(class_name);
18151-
if (FLAG_show_nullability) {
18152-
printer->AddString(NullabilitySuffix(nullability()));
18153-
}
18166+
printer->AddString(NullabilitySuffix(name_visibility));
1815418167
return;
1815518168
}
1815618169
// Print the name of a typedef as a regular, possibly parameterized, class.
@@ -18188,9 +18201,7 @@ void AbstractType::PrintName(NameVisibility name_visibility,
1818818201
args.PrintSubvectorName(first_type_param_index, num_type_params,
1818918202
name_visibility, printer);
1819018203
}
18191-
if (FLAG_show_nullability) {
18192-
printer->AddString(NullabilitySuffix(nullability()));
18193-
}
18204+
printer->AddString(NullabilitySuffix(name_visibility));
1819418205
// The name is only used for type checking and debugging purposes.
1819518206
// Unless profiling data shows otherwise, it is not worth caching the name in
1819618207
// the type.
@@ -19251,32 +19262,42 @@ const char* Type::ToCString() const {
1925119262
return "Type: null";
1925219263
}
1925319264
Zone* zone = Thread::Current()->zone();
19265+
ZoneTextBuffer args(zone);
1925419266
const TypeArguments& type_args = TypeArguments::Handle(zone, arguments());
19255-
const char* args_cstr = type_args.IsNull() ? "null" : type_args.ToCString();
19267+
const char* args_cstr = "";
19268+
if (!type_args.IsNull()) {
19269+
type_args.PrintSubvectorName(0, type_args.Length(), kInternalName, &args);
19270+
args_cstr = args.buffer();
19271+
}
1925619272
const Class& cls = Class::Handle(zone, type_class());
1925719273
const char* class_name;
1925819274
const String& name = String::Handle(zone, cls.Name());
1925919275
class_name = name.IsNull() ? "<null>" : name.ToCString();
19276+
const char* suffix = NullabilitySuffix(kInternalName);
1926019277
if (IsFunctionType()) {
1926119278
const Function& sig_fun = Function::Handle(zone, signature());
1926219279
ZoneTextBuffer sig(zone);
19280+
if (suffix[0] != '\0') {
19281+
sig.AddString("(");
19282+
}
1926319283
sig_fun.PrintSignature(kInternalName, &sig);
19284+
if (suffix[0] != '\0') {
19285+
sig.AddString(")");
19286+
sig.AddString(suffix);
19287+
}
1926419288
if (cls.IsClosureClass()) {
1926519289
ASSERT(type_args.IsNull());
1926619290
return OS::SCreate(zone, "Function Type: %s", sig.buffer());
1926719291
}
19268-
return OS::SCreate(zone, "Function Type: %s (class: %s, args: %s)",
19269-
sig.buffer(), class_name, args_cstr);
19292+
return OS::SCreate(zone, "Function Type: %s (%s%s%s)", sig.buffer(),
19293+
class_name, args_cstr, suffix);
1927019294
}
19271-
if (type_args.IsNull()) {
19272-
return OS::SCreate(zone, "Type: class '%s'", class_name);
19273-
} else if (IsFinalized() && IsRecursive()) {
19295+
if (IsFinalized() && IsRecursive()) {
1927419296
const intptr_t hash = Hash();
19275-
return OS::SCreate(zone, "Type: (H%" Px ") class '%s', args:[%s]", hash,
19276-
class_name, args_cstr);
19297+
return OS::SCreate(zone, "Type: (H%" Px ") %s%s%s", hash, class_name,
19298+
args_cstr, suffix);
1927719299
} else {
19278-
return OS::SCreate(zone, "Type: class '%s', args:[%s]", class_name,
19279-
args_cstr);
19300+
return OS::SCreate(zone, "Type: %s%s%s", class_name, args_cstr, suffix);
1928019301
}
1928119302
}
1928219303

@@ -19713,7 +19734,8 @@ const char* TypeParameter::ToCString() const {
1971319734
Thread* thread = Thread::Current();
1971419735
ZoneTextBuffer printer(thread->zone());
1971519736
printer.Printf("TypeParameter: name ");
19716-
printer.AddString(String::Handle(Name()));
19737+
printer.AddString(String::Handle(name()));
19738+
printer.AddString(NullabilitySuffix(kInternalName));
1971719739
printer.Printf("; index: %" Pd ";", index());
1971819740
if (IsFunctionTypeParameter()) {
1971919741
const Function& function = Function::Handle(parameterized_function());

runtime/vm/object.h

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7051,6 +7051,13 @@ class TypeArguments : public Instance {
70517051
// Names of internal classes are mapped to their public interfaces.
70527052
RawString* UserVisibleName() const;
70537053

7054+
// Print the internal or public name of a subvector of this type argument
7055+
// vector, e.g. "<T, dynamic, List<T>, int>".
7056+
void PrintSubvectorName(intptr_t from_index,
7057+
intptr_t len,
7058+
NameVisibility name_visibility,
7059+
ZoneTextBuffer* printer) const;
7060+
70547061
// Check if the subvector of length 'len' starting at 'from_index' of this
70557062
// type argument vector consists solely of DynamicType.
70567063
bool IsRaw(intptr_t from_index, intptr_t len) const {
@@ -7227,13 +7234,6 @@ class TypeArguments : public Instance {
72277234
intptr_t from_index,
72287235
intptr_t len) const;
72297236

7230-
// Return the internal or public name of a subvector of this type argument
7231-
// vector, e.g. "<T, dynamic, List<T>, int>".
7232-
void PrintSubvectorName(intptr_t from_index,
7233-
intptr_t len,
7234-
NameVisibility name_visibility,
7235-
ZoneTextBuffer* printer) const;
7236-
72377237
RawArray* instantiations() const;
72387238
void set_instantiations(const Array& value) const;
72397239
RawAbstractType* const* TypeAddr(intptr_t index) const;
@@ -7364,6 +7364,10 @@ class AbstractType : public Instance {
73647364
// Return a formatted string of the uris.
73657365
static RawString* PrintURIs(URIs* uris);
73667366

7367+
// Returns a C-String (possibly "") representing the nullability of this type.
7368+
// Legacy and undetermined suffixes are only displayed with kInternalName.
7369+
virtual const char* NullabilitySuffix(NameVisibility name_visibility) const;
7370+
73677371
// The name of this type, including the names of its type arguments, if any.
73687372
virtual RawString* Name() const;
73697373

tests/language_2/type_object/runtime_type_function_test.dart

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ main() {
6868

6969
check(fn('dynamic', ''), main); // Top-level tear-off.
7070
check(fn('void', ''), Xyzzy.foo); // Class static member tear-off.
71-
check(fn('void', 'Object'), [].add); // Instance tear-off.
71+
check(fn('void', 'Object'), new MyList().add); // Instance tear-off.
7272
check(fn('int', ''), () => 1); // closure.
7373

7474
var s = new Xyzzy().runtimeType.toString();
@@ -83,8 +83,8 @@ main() {
8383
check(fn('String', 'String', {'a': 'String', 'b': 'dynamic'}), Xyzzy.nam);
8484

8585
// Instance method tear-offs.
86-
check(fn('void', 'Object'), <String>[].add);
87-
check(fn('void', 'Object'), <int>[].add);
86+
check(fn('void', 'Object'), new MyList<String>().add);
87+
check(fn('void', 'Object'), new MyList<int>().add);
8888
check(fn('void', 'int'), new Xyzzy().intAdd);
8989

9090
check(fn('String', 'Object'), new G<String, int>().foo);
@@ -122,6 +122,12 @@ class Xyzzy {
122122
void intAdd(int x) {}
123123
}
124124

125+
// Using 'MyList' instead of core lib 'List' keeps covariant parameter type of
126+
// tear-offs 'Object' (legacy lib) instead of 'Object?' (opted-in lib).
127+
class MyList<E> {
128+
void add(E value) {}
129+
}
130+
125131
class G<U, V> {
126132
U foo(V x) => null;
127133
U moo(V f(U x)) => null;

0 commit comments

Comments
 (0)