Skip to content

Commit 0cf7512

Browse files
alexmarkovCommit Bot
authored and
Commit Bot
committed
[vm] Correct token position for AssertAssignable in implicit field setters
The real token position is required in case debugger stopped on an exception thrown from AssertAssignable and trying to evaluate an expression which uses receiver. Without token position all local variables (including receiver) are considered out of scope (as frame's token position is out of range). TEST=runtime/observatory/tests/service/regress_48279_test.dart Fixes #48279 Change-Id: Idb6a8e12185367ceac2034269b8f046272384006 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/231748 Reviewed-by: Ben Konyi <[email protected]> Commit-Queue: Alexander Markov <[email protected]>
1 parent deb9cd3 commit 0cf7512

File tree

3 files changed

+53
-5
lines changed

3 files changed

+53
-5
lines changed
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// Copyright (c) 2022, 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+
// This test verifies that generic type argument ('T') can be evaluated
6+
// when stopped on an exception which is thrown during type check in
7+
// the implicit field setter.
8+
// Regression test for https://github.com/dart-lang/sdk/issues/48279.
9+
10+
import 'package:test/test.dart';
11+
import 'package:vm_service/vm_service.dart';
12+
13+
import 'common/service_test_common.dart';
14+
import 'common/test_helper.dart';
15+
16+
class A<T, U, V> {
17+
List<T> foo = [];
18+
}
19+
20+
testeeMain() {
21+
A<num, Object, Object> object = A<int, String, String>();
22+
object.foo = <double>[];
23+
}
24+
25+
var tests = <IsolateTest>[
26+
hasStoppedWithUnhandledException,
27+
(VmService? service, IsolateRef? isolateRef) async {
28+
print("We stopped!");
29+
final isolateId = isolateRef!.id!;
30+
final stack = await service!.getStack(isolateId);
31+
final topFrame = stack.frames![0];
32+
expect(topFrame.function!.name, equals('foo='));
33+
final result = await service.evaluateInFrame(isolateId, 0, 'T');
34+
print(result);
35+
expect((result as InstanceRef).name, equals("int"));
36+
}
37+
];
38+
39+
main(args) => runIsolateTests(
40+
args,
41+
tests,
42+
'regress_48279_test.dart',
43+
pause_on_unhandled_exceptions: true,
44+
testeeConcurrent: testeeMain,
45+
);

runtime/vm/compiler/frontend/kernel_to_il.cc

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1839,13 +1839,14 @@ Fragment FlowGraphBuilder::CheckBoolean(TokenPosition position) {
18391839

18401840
Fragment FlowGraphBuilder::CheckAssignable(const AbstractType& dst_type,
18411841
const String& dst_name,
1842-
AssertAssignableInstr::Kind kind) {
1842+
AssertAssignableInstr::Kind kind,
1843+
TokenPosition token_pos) {
18431844
Fragment instructions;
18441845
if (!dst_type.IsTopTypeForSubtyping()) {
18451846
LocalVariable* top_of_stack = MakeTemporary();
18461847
instructions += LoadLocal(top_of_stack);
1847-
instructions += AssertAssignableLoadTypeArguments(TokenPosition::kNoSource,
1848-
dst_type, dst_name, kind);
1848+
instructions +=
1849+
AssertAssignableLoadTypeArguments(token_pos, dst_type, dst_name, kind);
18491850
instructions += Drop();
18501851
}
18511852
return instructions;
@@ -3679,7 +3680,8 @@ FlowGraph* FlowGraphBuilder::BuildGraphOfFieldAccessor(
36793680
setter_value->needs_type_check();
36803681
if (needs_type_check) {
36813682
body += CheckAssignable(setter_value->type(), setter_value->name(),
3682-
AssertAssignableInstr::kParameterCheck);
3683+
AssertAssignableInstr::kParameterCheck,
3684+
field.token_pos());
36833685
}
36843686
body += BuildNullAssertions();
36853687
if (field.is_late()) {

runtime/vm/compiler/frontend/kernel_to_il.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,8 @@ class FlowGraphBuilder : public BaseFlowGraphBuilder {
243243
Fragment CheckAssignable(
244244
const AbstractType& dst_type,
245245
const String& dst_name,
246-
AssertAssignableInstr::Kind kind = AssertAssignableInstr::kUnknown);
246+
AssertAssignableInstr::Kind kind = AssertAssignableInstr::kUnknown,
247+
TokenPosition token_pos = TokenPosition::kNoSource);
247248

248249
Fragment AssertAssignableLoadTypeArguments(
249250
TokenPosition position,

0 commit comments

Comments
 (0)