blob: 0d6acbd4c0172568e926553eab1597b0d6626525 [file] [log] [blame]
// 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.
// Requirements=nnbd-strong
/// Test that `Never` has all members, and that as a result no extensions
/// apply to it. Also test that `Never` is inferred as the type of a
/// throw expression, and as the return type of function literals that
/// never return.
import 'package:expect/expect.dart';
/// A call of the form staticErrorIfNotNever(t) will produce a static error
/// unless `t` has type `Never`.
void staticErrorIfNotNever<T extends Never>(T t) {}
void neverHasAllMembers(Never x) {
{
// getters
var t = x.arglebargle;
staticErrorIfNotNever(t);
}
{
// setter
x.arglebargle = 3;
}
{
// operator[]
x[0] = 3;
}
{
// methods
var t = x.arglebargle(0);
staticErrorIfNotNever(t);
}
{
// methods with named parameters
var t = x.arglebargle(foo: 0);
staticErrorIfNotNever(t);
}
{
// call method
var t = x(3);
staticErrorIfNotNever(t);
}
{
// Object members
staticErrorIfNotNever(x.toString());
staticErrorIfNotNever(x.toString);
staticErrorIfNotNever(x.runtimeType);
staticErrorIfNotNever(x.noSuchMethod);
staticErrorIfNotNever(x.noSuchMethod(x));
staticErrorIfNotNever(x.hashCode);
staticErrorIfNotNever(x == x);
staticErrorIfNotNever(x == 3);
staticErrorIfNotNever(3 == x);
// ^^^^^^^^^^^^^^^^^^^^^
// [analyzer] COMPILE_TIME_ERROR.COULD_NOT_INFER
// [cfe] Inferred type argument 'bool' doesn't conform to the bound 'Never' of the type variable 'T' on 'staticErrorIfNotNever'.
}
}
extension NeverExt on Never {
int neverMethod() => 3;
}
extension ObjectExt on Object {
int objectMethod() => 3;
}
void extensionsDontApply(Never x) {
{
var t = x.neverMethod();
staticErrorIfNotNever(t);
}
{
var t = x.objectMethod();
staticErrorIfNotNever(t);
}
{
var t = NeverExt(x).neverMethod();
staticErrorIfNotNever(t);
// ^^^^^^^^^^^^^^^^^^^^^
// [analyzer] COMPILE_TIME_ERROR.COULD_NOT_INFER
// [cfe] Inferred type argument 'int' doesn't conform to the bound 'Never' of the type variable 'T' on 'staticErrorIfNotNever'.
}
{
var t = ObjectExt(x).objectMethod();
staticErrorIfNotNever(t);
// ^^^^^^^^^^^^^^^^^^^^^
// [analyzer] COMPILE_TIME_ERROR.COULD_NOT_INFER
// [cfe] Inferred type argument 'int' doesn't conform to the bound 'Never' of the type variable 'T' on 'staticErrorIfNotNever'.
}
}
void throwHasTypeNever() {
var t = throw "hello";
staticErrorIfNotNever(t);
}
void neverReturns(bool b) {
{
var f = () => throw "Unreachable";
var t = f();
staticErrorIfNotNever(t);
}
{
var f = () {
if (b) {
throw "argle";
} else {
throw "bargle";
}
};
var t = f();
staticErrorIfNotNever(t);
}
}
void main() {
neverHasAllMembers(throw "Unreachable");
extensionsDontApply(throw "Unreachable");
throwHasTypeNever();
neverReturns(true);
}