383b470d39
The test was written when a more disruptive solution for the unsoundness fix was planned. A more lenient solution was found and the test is updated accordingly. Closes #43707 Change-Id: I31936fdc3aa0ae23fddd72c850eca5da50b22352 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/166620 Reviewed-by: Paul Berry <paulberry@google.com> Commit-Queue: Johnni Winther <johnniwinther@google.com>
348 lines
8.0 KiB
Dart
348 lines
8.0 KiB
Dart
// Copyright (c) 2020, 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.
|
|
|
|
abstract class A {
|
|
Never get getter;
|
|
Never method();
|
|
Never operator +(int other);
|
|
Never operator [](int other);
|
|
}
|
|
|
|
class C {
|
|
static int staticField = 0;
|
|
|
|
static int get staticGetterSetter => staticField;
|
|
|
|
static set staticGetterSetter(int? value) {}
|
|
|
|
int instanceField;
|
|
|
|
int get instanceGetterSetter => instanceField;
|
|
|
|
set instanceGetterSetter(int? value) {}
|
|
|
|
int operator [](int index) => instanceField;
|
|
|
|
operator []=(int index, int? value) {}
|
|
|
|
static late String error;
|
|
|
|
get throwingGetter => throw 'Null access';
|
|
|
|
C(this.instanceField);
|
|
}
|
|
|
|
class D extends C {
|
|
D(int field) : super(field);
|
|
|
|
int ifNullAssignSuper(int f()) {
|
|
return super.instanceField ??= f(); // ignore: dead_null_aware_expression
|
|
}
|
|
|
|
int ifNullAssignSuper_nullableSetter(int f()) {
|
|
return super.instanceGetterSetter ??=
|
|
f(); // ignore: dead_null_aware_expression
|
|
}
|
|
|
|
int ifNullAssignSuperIndex(int f()) {
|
|
return super[0] ??= f(); // ignore: dead_null_aware_expression
|
|
}
|
|
}
|
|
|
|
class E {
|
|
int instanceField;
|
|
|
|
E(this.instanceField);
|
|
}
|
|
|
|
extension EExt on E {
|
|
int get instanceGetterSetter => instanceField;
|
|
|
|
set instanceGetterSetter(int? value) {}
|
|
|
|
int operator [](int index) => instanceField;
|
|
|
|
operator []=(int index, int? value) {}
|
|
}
|
|
|
|
extension IntQExt on int? {
|
|
int extendedMethod(int value) => value;
|
|
|
|
int get extendedGetter => 0;
|
|
}
|
|
|
|
class NeverField {
|
|
late Never n;
|
|
|
|
NeverField();
|
|
NeverField.initializingFormal(this.n);
|
|
}
|
|
|
|
enum Hand { left, right }
|
|
|
|
late Never topLevelNever;
|
|
|
|
int neverParameter(Never n) {
|
|
return 42;
|
|
}
|
|
|
|
int neverInitializingFormal(Never n) {
|
|
return 42;
|
|
}
|
|
|
|
bool isPromoteToNever(int i) {
|
|
if (i is int) return true;
|
|
return false;
|
|
}
|
|
|
|
bool isPromoteToNever_noIf(int i) {
|
|
return i is int;
|
|
}
|
|
|
|
bool isNotPromoteToNever(int i) {
|
|
if (i is! int) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool isNotPromoteToNever_noIf(int i) {
|
|
return i is! int;
|
|
}
|
|
|
|
int equalNullPromoteToNever(int f()) {
|
|
if (f() == null) {
|
|
// ignore: unnecessary_null_comparison
|
|
return 42;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int equalNullPromoteToNever_noIf(int f()) {
|
|
f() == null; // ignore: unnecessary_null_comparison
|
|
return 42;
|
|
}
|
|
|
|
int notEqualNullPromoteToNever(int f()) {
|
|
if (f() != null) return 0; // ignore: unnecessary_null_comparison
|
|
return 42;
|
|
}
|
|
|
|
int notEqualNullPromoteToNever_noIf(int f()) {
|
|
f() != null; // ignore: unnecessary_null_comparison
|
|
return 42;
|
|
}
|
|
|
|
int nullEqualPromoteToNever(int f()) {
|
|
if (null == f()) {
|
|
// ignore: unnecessary_null_comparison
|
|
return 42;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int nullEqualPromoteToNever_noIf(int f()) {
|
|
null == f(); // ignore: unnecessary_null_comparison
|
|
return 42;
|
|
}
|
|
|
|
int nullNotEqualPromoteToNever(int f()) {
|
|
if (null != f()) return 0; // ignore: unnecessary_null_comparison
|
|
return 42;
|
|
}
|
|
|
|
int nullNotEqualPromoteToNever_noIf(int f()) {
|
|
null != f(); // ignore: unnecessary_null_comparison
|
|
return 42;
|
|
}
|
|
|
|
int unnecessaryIfNull(int f(), int g()) {
|
|
return f() ?? g(); // ignore: dead_null_aware_expression
|
|
}
|
|
|
|
int ifNullAssignLocal(int local, int f()) {
|
|
return local ??= f(); // ignore: dead_null_aware_expression
|
|
}
|
|
|
|
int ifNullAssignStatic(int f()) {
|
|
return C.staticField ??= f(); // ignore: dead_null_aware_expression
|
|
}
|
|
|
|
int ifNullAssignStaticGetter_nullableSetter(int f()) {
|
|
return C.staticGetterSetter ??= f(); // ignore: dead_null_aware_expression
|
|
}
|
|
|
|
int ifNullAssignField(C c, int f()) {
|
|
return c.instanceField ??= f(); // ignore: dead_null_aware_expression
|
|
}
|
|
|
|
int ifNullAssignGetter_nullableSetter(C c, int f()) {
|
|
return c.instanceGetterSetter ??= f(); // ignore: dead_null_aware_expression
|
|
}
|
|
|
|
int ifNullAssignGetter_implicitExtension(E e, int f()) {
|
|
return e.instanceGetterSetter ??= f(); // ignore: dead_null_aware_expression
|
|
}
|
|
|
|
int ifNullAssignGetter_explicitExtension(E e, int f()) {
|
|
return EExt(e).instanceGetterSetter ??=
|
|
f(); // ignore: dead_null_aware_expression
|
|
}
|
|
|
|
int ifNullAssignIndex(List<int> x, int f()) {
|
|
return x[0] ??= f(); // ignore: dead_null_aware_expression
|
|
}
|
|
|
|
int? ifNullAssignIndex_nullAware(List<int>? x, int f()) {
|
|
return x?[0] ??= f(); // ignore: dead_null_aware_expression
|
|
}
|
|
|
|
int ifNullAssignIndex_nullableSetter(C x, int f()) {
|
|
return x[0] ??= f(); // ignore: dead_null_aware_expression
|
|
}
|
|
|
|
int ifNullAssignIndex_implicitExtension(E x, int f()) {
|
|
return x[0] ??= f(); // ignore: dead_null_aware_expression
|
|
}
|
|
|
|
int ifNullAssignIndex_explicitExtension(E x, int f()) {
|
|
return EExt(x)[0] ??= f(); // ignore: dead_null_aware_expression
|
|
}
|
|
|
|
int ifNullAssignSuper(D d, int f()) {
|
|
return d.ifNullAssignSuper(f);
|
|
}
|
|
|
|
int ifNullAssignSuper_nullableSetter(D d, int f()) {
|
|
return d.ifNullAssignSuper_nullableSetter(f);
|
|
}
|
|
|
|
int ifNullAssignSuperIndex(D d, int f()) {
|
|
return d.ifNullAssignSuperIndex(f);
|
|
}
|
|
|
|
int? ifNullAssignNullAwareField(C? c, int f()) {
|
|
return c?.instanceField ??= f(); // ignore: dead_null_aware_expression
|
|
}
|
|
|
|
int ifNullAssignNullAwareStatic(int f()) {
|
|
return C?.staticField ??= f(); // ignore: dead_null_aware_expression
|
|
}
|
|
|
|
void unnecessaryNullAwareAccess(int f()) {
|
|
f()?.gcd(throw 'Null access'); // ignore: invalid_null_aware_operator
|
|
}
|
|
|
|
void unnecessaryNullAwareAccess_cascaded(int f()) {
|
|
f()?..gcd(throw 'Null access'); // ignore: invalid_null_aware_operator
|
|
}
|
|
|
|
void unnecessaryNullAwareAccess_methodOnObject(int f()) {
|
|
// ignore: invalid_null_aware_operator
|
|
f()?.toString().compareTo(throw 'Null access');
|
|
}
|
|
|
|
void unnecessaryNullAwareAccess_cascaded_methodOnObject(int f()) {
|
|
// ignore: invalid_null_aware_operator
|
|
f()?..toString().compareTo(throw 'Null access');
|
|
}
|
|
|
|
void unnecessaryNullAwareAccess_methodOnExtension(int f()) {
|
|
// ignore: invalid_null_aware_operator
|
|
f()?.extendedMethod(throw 'Null access');
|
|
}
|
|
|
|
void unnecessaryNullAwareAccess_cascaded_methodOnExtension(int f()) {
|
|
// ignore: invalid_null_aware_operator
|
|
f()?..extendedMethod(throw 'Null access');
|
|
}
|
|
|
|
void unnecessaryNullAwareAccess_methodOnExtension_explicit(int f()) {
|
|
// ignore: invalid_null_aware_operator
|
|
IntQExt(f())?.extendedMethod(throw 'Null access');
|
|
}
|
|
|
|
void unnecessaryNullAwareAccess_getter(C f()) {
|
|
f()?.throwingGetter; // ignore: invalid_null_aware_operator
|
|
}
|
|
|
|
void unnecessaryNullAwareAccess_cascaded_getter(C f()) {
|
|
f()?..throwingGetter; // ignore: invalid_null_aware_operator
|
|
}
|
|
|
|
void unnecessaryNullAwareAccess_getterOnObject(int f()) {
|
|
// ignore: invalid_null_aware_operator
|
|
f()?.hashCode.remainder(throw 'Null access');
|
|
}
|
|
|
|
void unnecessaryNullAwareAccess_cascaded_getterOnObject(int f()) {
|
|
// ignore: invalid_null_aware_operator
|
|
f()?..hashCode.remainder(throw 'Null access');
|
|
}
|
|
|
|
void unnecessaryNullAwareAccess_getterOnExtension(int f()) {
|
|
// ignore: invalid_null_aware_operator
|
|
f()?.extendedGetter.remainder(throw 'Null access');
|
|
}
|
|
|
|
void unnecessaryNullAwareAccess_cascaded_getterOnExtension(int f()) {
|
|
// ignore: invalid_null_aware_operator
|
|
f()?..extendedGetter.remainder(throw 'Null access');
|
|
}
|
|
|
|
void unnecessaryNullAwareAccess_getterOnExtension_explicit(int f()) {
|
|
// ignore: invalid_null_aware_operator
|
|
IntQExt(f())?.extendedGetter.remainder(throw 'Null access');
|
|
}
|
|
|
|
void getterReturnsNever(A a) {
|
|
a.getter;
|
|
// Should throw if `getter` completes normally.
|
|
}
|
|
|
|
void methodReturnsNever(A a) {
|
|
a.method();
|
|
// Should throw if `method` completes normally.
|
|
}
|
|
|
|
void operatorReturnsNever(A a) {
|
|
a + 1;
|
|
// Should throw if `+` completes normally.
|
|
}
|
|
|
|
void indexReturnsNever(A a) {
|
|
a[0];
|
|
// Should throw if `[]` completes normally.
|
|
}
|
|
|
|
void returnsNeverInExpression(A a) {
|
|
List<Never> x = [a.method()];
|
|
// Should throw if `method` completes normally.
|
|
}
|
|
|
|
void returnsNeverInVariable(A a) {
|
|
Never x = a.method();
|
|
// Should throw if `method` completes normally.
|
|
}
|
|
|
|
int switchOnBool(bool b) {
|
|
switch (b) {
|
|
case true:
|
|
return 0;
|
|
case false:
|
|
return 1;
|
|
}
|
|
return 42;
|
|
}
|
|
|
|
void switchOnEnum(Hand hand) {
|
|
switch (hand) {
|
|
case Hand.left:
|
|
return;
|
|
case Hand.right:
|
|
return;
|
|
}
|
|
// Should throw if the implicit `default` branch is taken.
|
|
}
|