Skip to content

Commit 6bba750

Browse files
committed
Issue 42797. Understand in legacy libraries that a function returning Never (in Null Safety library) never returns.
[email protected] Bug: #42797 Change-Id: I14e50c231935a4025d33762843f5a54a1ee2154c Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/155500 Reviewed-by: Brian Wilkerson <[email protected]>
1 parent b4ebbb7 commit 6bba750

File tree

3 files changed

+35
-2
lines changed

3 files changed

+35
-2
lines changed

pkg/analyzer/lib/src/dart/analysis/driver.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ typedef WorkToWaitAfterComputingResult = Future<void> Function(String path);
9191
/// TODO(scheglov) Clean up the list of implicitly analyzed files.
9292
class AnalysisDriver implements AnalysisDriverGeneric {
9393
/// The version of data format, should be incremented on every format change.
94-
static const int DATA_VERSION = 106;
94+
static const int DATA_VERSION = 107;
9595

9696
/// The length of the list returned by [_computeDeclaredVariablesSignature].
9797
static const int _declaredVariablesSignatureLength = 4;

pkg/analyzer/lib/src/dart/resolver/exit_detector.dart

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import 'package:analyzer/dart/ast/ast.dart';
66
import 'package:analyzer/dart/ast/token.dart';
77
import 'package:analyzer/dart/ast/visitor.dart';
88
import 'package:analyzer/dart/element/element.dart';
9+
import 'package:analyzer/src/dart/element/type.dart';
910

1011
/// Instances of the class `ExitDetector` determine whether the visited AST node
1112
/// is guaranteed to terminate by executing a `return` statement, `throw`
@@ -423,7 +424,7 @@ class ExitDetector extends GeneralizingAstVisitor<bool> {
423424
}
424425
}
425426
Element element = node.methodName.staticElement;
426-
if (element != null && element.hasAlwaysThrows) {
427+
if (_elementExits(element)) {
427428
return true;
428429
}
429430
return _nodeExits(node.argumentList);
@@ -660,4 +661,14 @@ class ExitDetector extends GeneralizingAstVisitor<bool> {
660661
static bool exits(AstNode node) {
661662
return ExitDetector()._nodeExits(node);
662663
}
664+
665+
static bool _elementExits(Element element) {
666+
if (element is ExecutableElement) {
667+
var declaration = element.declaration;
668+
return declaration.hasAlwaysThrows ||
669+
identical(declaration.returnType, NeverTypeImpl.instance);
670+
}
671+
672+
return false;
673+
}
663674
}

pkg/analyzer/test/src/diagnostics/missing_return_test.dart

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,12 @@ import 'package:analyzer/src/test_utilities/package_mixin.dart';
77
import 'package:test_reflective_loader/test_reflective_loader.dart';
88

99
import '../dart/resolution/driver_resolution.dart';
10+
import '../dart/resolution/with_null_safety_mixin.dart';
1011

1112
main() {
1213
defineReflectiveSuite(() {
1314
defineReflectiveTests(MissingReturnTest);
15+
defineReflectiveTests(MissingReturnWithNullSafetyTest);
1416
});
1517
}
1618

@@ -213,3 +215,23 @@ class B extends A {
213215
]);
214216
}
215217
}
218+
219+
@reflectiveTest
220+
class MissingReturnWithNullSafetyTest extends DriverResolutionTest
221+
with WithNullSafetyMixin {
222+
test_returnNever() async {
223+
newFile('/test/lib/a.dart', content: r'''
224+
Never foo() {
225+
throw 0;
226+
}
227+
''');
228+
await assertNoErrorsInCode(r'''
229+
// @dart = 2.8
230+
import 'a.dart';
231+
232+
int f() {
233+
foo();
234+
}
235+
''');
236+
}
237+
}

0 commit comments

Comments
 (0)