Skip to content

Commit 7074704

Browse files
johnniwinthercommit-bot@chromium.org
authored andcommitted
Add hint for .runtimeType.toString()
Change-Id: I0a20f1fc42bc475c9acdf40b3d8aae16edbc8ea9 Reviewed-on: https://dart-review.googlesource.com/64845 Commit-Queue: Johnni Winther <[email protected]> Reviewed-by: Sigmund Cherem <[email protected]>
1 parent 87e21a1 commit 7074704

File tree

5 files changed

+105
-1
lines changed

5 files changed

+105
-1
lines changed

pkg/compiler/lib/src/dart2js.dart

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -682,6 +682,12 @@ safe to use:
682682
Note: a well-typed program is not guaranteed to have valid inputs. For
683683
example, an int index argument may be null or out of range.
684684
685+
--lax-runtime-type-to-string
686+
Omits reified class type arguments when these are only needed for `toString`
687+
on `runtimeType`. This is useful if `runtimeType.toString()` is only used
688+
for debugging. Note that semantics of other uses of `.runtimeType`, for
689+
instance `a.runtimeType == b.runtimeType`, is not affected by this flag.
690+
685691
The following options are only used for compiler development and may
686692
be removed in a future version:
687693

pkg/compiler/lib/src/diagnostics/messages.dart

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ library dart2js.messages;
1717
import 'package:front_end/src/fasta/scanner.dart' show ErrorToken, Token;
1818
import 'generated/shared_messages.dart' as shared_messages;
1919
import '../constants/expressions.dart' show ConstantExpression;
20+
import '../commandline_options.dart';
2021
import 'invariant.dart' show failedAt;
2122
import 'spannable.dart' show CURRENT_ELEMENT_SPANNABLE;
2223

@@ -90,6 +91,8 @@ enum MessageKind {
9091
RETHROW_OUTSIDE_CATCH,
9192
RETURN_IN_GENERATIVE_CONSTRUCTOR,
9293
RETURN_IN_GENERATOR,
94+
RUNTIME_TYPE_TO_STRING_OBJECT,
95+
RUNTIME_TYPE_TO_STRING_SUBTYPE,
9396
STRING_EXPECTED,
9497
UNDEFINED_GETTER,
9598
UNDEFINED_INSTANCE_GETTER_BUT_SETTER,
@@ -609,6 +612,25 @@ become a compile-time error in the future."""),
609612
"Overriding 'noSuchMethod' causes the compiler to generate "
610613
"more code and prevents the compiler from doing some optimizations.",
611614
howToFix: "Consider removing this 'noSuchMethod' implementation."),
615+
616+
MessageKind.RUNTIME_TYPE_TO_STRING_OBJECT: const MessageTemplate(
617+
MessageKind.RUNTIME_TYPE_TO_STRING_OBJECT,
618+
"Using '.runtimeType.toString()' causes the compiler to generate "
619+
"more code because it needs to preserve type arguments on all "
620+
"generic classes, even if they are not necessary elsewhere.",
621+
howToFix: "If used only for debugging, consider using option "
622+
"${Flags.laxRuntimeTypeToString} to reduce the code size "
623+
"impact."),
624+
625+
MessageKind.RUNTIME_TYPE_TO_STRING_SUBTYPE: const MessageTemplate(
626+
MessageKind.RUNTIME_TYPE_TO_STRING_SUBTYPE,
627+
"Using '.runtimeType.toString()' here causes the compiler to "
628+
"generate more code because it needs to preserve type arguments on "
629+
"all generic subtypes of '#{receiverType}', even if they are not "
630+
"necessary elsewhere.",
631+
howToFix: "If used only for debugging, consider using option "
632+
"${Flags.laxRuntimeTypeToString} to reduce the code size "
633+
"impact."),
612634
}); // End of TEMPLATES.
613635

614636
String toString() => template;

pkg/compiler/lib/src/options.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@ class CompilerOptions implements DiagnosticOptions {
189189
bool omitImplicitChecks = false;
190190

191191
/// Whether to omit class type arguments only needed for `toString` on
192-
/// `RuntimeType`.
192+
/// `Object.runtimeType`.
193193
bool laxRuntimeTypeToString = false;
194194

195195
/// What should the compiler do with type assertions of assignments.

pkg/compiler/lib/src/ssa/kernel_impact.dart

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -639,6 +639,27 @@ class KernelImpactBuilder extends ir.Visitor {
639639
if (node.name.name == Identifiers.runtimeType_) {
640640
if (_options.strongMode) {
641641
RuntimeTypeUse runtimeTypeUse = computeRuntimeTypeUse(elementMap, node);
642+
if (_options.omitImplicitChecks) {
643+
switch (runtimeTypeUse.kind) {
644+
case RuntimeTypeUseKind.string:
645+
if (!_options.laxRuntimeTypeToString) {
646+
if (runtimeTypeUse.receiverType == commonElements.objectType) {
647+
reporter.reportHintMessage(
648+
computeSourceSpanFromTreeNode(node),
649+
MessageKind.RUNTIME_TYPE_TO_STRING_OBJECT);
650+
} else {
651+
reporter.reportHintMessage(
652+
computeSourceSpanFromTreeNode(node),
653+
MessageKind.RUNTIME_TYPE_TO_STRING_SUBTYPE,
654+
{'receiverType': '${runtimeTypeUse.receiverType}.'});
655+
}
656+
}
657+
break;
658+
case RuntimeTypeUseKind.equals:
659+
case RuntimeTypeUseKind.unknown:
660+
break;
661+
}
662+
}
642663
impactBuilder.registerRuntimeTypeUse(runtimeTypeUse);
643664
} else {
644665
impactBuilder.registerRuntimeTypeUse(new RuntimeTypeUse(
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
import 'package:async_helper/async_helper.dart';
6+
import 'package:compiler/src/commandline_options.dart';
7+
import 'package:compiler/src/diagnostics/messages.dart';
8+
import 'package:expect/expect.dart';
9+
10+
import '../memory_compiler.dart';
11+
12+
test(String code, List<String> options, List<MessageKind> expectedHints) async {
13+
DiagnosticCollector collector = new DiagnosticCollector();
14+
CompilationResult result = await runCompiler(
15+
memorySourceFiles: {'main.dart': code},
16+
options: options,
17+
diagnosticHandler: collector);
18+
Expect.isTrue(result.isSuccess);
19+
List<MessageKind> actualHints =
20+
collector.hints.map((c) => c.messageKind).toList();
21+
String message = "Unexpected hints for $options on\n$code\n"
22+
"Expected: ${expectedHints}\n"
23+
"Actual : ${actualHints}";
24+
Expect.listEquals(expectedHints, actualHints, message);
25+
}
26+
27+
String runtimeTypeToStringObject = '''
28+
main() {
29+
print(new Object().runtimeType.toString());
30+
}
31+
''';
32+
33+
String runtimeTypeToStringClass = '''
34+
class Class {}
35+
36+
main() {
37+
print(new Class().runtimeType.toString());
38+
}
39+
''';
40+
41+
main() {
42+
asyncTest(() async {
43+
await test(runtimeTypeToStringObject, [], []);
44+
await test(runtimeTypeToStringObject, [Flags.omitImplicitChecks],
45+
[MessageKind.RUNTIME_TYPE_TO_STRING_OBJECT]);
46+
await test(runtimeTypeToStringObject,
47+
[Flags.omitImplicitChecks, Flags.laxRuntimeTypeToString], []);
48+
49+
await test(runtimeTypeToStringClass, [], []);
50+
await test(runtimeTypeToStringClass, [Flags.omitImplicitChecks],
51+
[MessageKind.RUNTIME_TYPE_TO_STRING_SUBTYPE]);
52+
await test(runtimeTypeToStringClass,
53+
[Flags.omitImplicitChecks, Flags.laxRuntimeTypeToString], []);
54+
});
55+
}

0 commit comments

Comments
 (0)