Skip to content

Commit

Permalink
[vm/compiler] Fix type of Parameter in a CatchBlockEntry
Browse files Browse the repository at this point in the history
Parameter in a CatchBlockEntry may correspond to a late local variable
which was not initialized yet, so its type should correctly state
that it can be sentinel.

TEST=vm/dart/flutter_regress_109261_test
Fixes flutter/flutter#109261

Change-Id: Ia6fbbe4b9963323f84438b3f618437276e51f256
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/254440
Commit-Queue: Alexander Markov <alexmarkov@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
  • Loading branch information
alexmarkov authored and Commit Bot committed Aug 10, 2022
1 parent 61314e9 commit 6ad3805
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 0 deletions.
69 changes: 69 additions & 0 deletions runtime/tests/vm/dart/flutter_regress_109261_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
// Copyright (c) 2022, 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.

// Regression test for https://github.com/flutter/flutter/issues/109261.
// Varifies that uninitialized final late local variable can be correctly
// used in a catch block.

import 'package:expect/expect.dart';

void testWriteToUninitialized() {
late final int computationResult;

try {
throw 'bye';
} catch (e, s) {
computationResult = 42;
}

Expect.equals(42, computationResult);
}

void testWriteToInitialized() {
Expect.throws(() {
late final int computationResult;

try {
computationResult = 10;
throw 'bye';
} catch (e, s) {
computationResult = 42;
}
});
}

void testReadFromUninitialized() {
Expect.throws(() {
late final int computationResult;

try {
if (int.parse('1') == 2) {
// Unreachable, just to avoid compile-time error "Late variable '...'
// without initializer is definitely unassigned."
computationResult = 10;
}
throw 'bye';
} catch (e, s) {
print(computationResult);
}
});
}

void testReadFromInitialized() {
late final int computationResult;

try {
computationResult = 10;
throw 'bye';
} catch (e, s) {
Expect.equals(10, computationResult);
}
}

main() {
testWriteToUninitialized();
testWriteToInitialized();
testReadFromUninitialized();
testReadFromInitialized();
}
2 changes: 2 additions & 0 deletions runtime/vm/compiler/backend/compile_type.h
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,8 @@ class CompileType : public ZoneAllocated {
// represent unknown type.
static CompileType Dynamic();

static CompileType DynamicOrSentinel();

static CompileType Null();

// Create non-nullable Bool type.
Expand Down
10 changes: 10 additions & 0 deletions runtime/vm/compiler/backend/type_propagator.cc
Original file line number Diff line number Diff line change
Expand Up @@ -686,6 +686,11 @@ CompileType CompileType::Dynamic() {
&Object::dynamic_type());
}

CompileType CompileType::DynamicOrSentinel() {
return CompileType(kCanBeNull, kCanBeSentinel, kDynamicCid,
&Object::dynamic_type());
}

CompileType CompileType::Null() {
return CompileType(kCanBeNull, kCannotBeSentinel, kNullCid,
&Type::ZoneHandle(Type::NullType()));
Expand Down Expand Up @@ -1264,6 +1269,11 @@ CompileType ParameterInstr::ComputeType() const {
}
}

if (block_->IsCatchBlockEntry()) {
// Parameter of a catch block may correspond to a late local variable.
return CompileType::DynamicOrSentinel();
}

return CompileType::Dynamic();
}

Expand Down

0 comments on commit 6ad3805

Please sign in to comment.