mirror of
https://github.com/dart-lang/sdk
synced 2024-11-02 10:49:00 +00:00
[cfe] Handle opt-out Null override of opt-in Never
Closes #40387 Closes #40420 Change-Id: I2f0810cadcba5f74bdd5a47060ffb14dc8fe7f07 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/134702 Commit-Queue: Johnni Winther <johnniwinther@google.com> Reviewed-by: Dmitry Stefantsov <dmitryas@google.com>
This commit is contained in:
parent
b978cb1cb5
commit
4267085fa5
11 changed files with 232 additions and 6 deletions
|
@ -46,6 +46,8 @@ import 'package:kernel/src/bounds_checks.dart'
|
|||
findTypeArgumentIssues,
|
||||
getGenericTypeName;
|
||||
|
||||
import 'package:kernel/src/legacy_erasure.dart';
|
||||
|
||||
import 'package:kernel/text/text_serialization_verifier.dart';
|
||||
|
||||
import 'package:kernel/type_algebra.dart' show Substitution, substitute;
|
||||
|
@ -1166,6 +1168,11 @@ abstract class ClassBuilderImpl extends DeclarationBuilderImpl
|
|||
declaredType = declaredSubstitution.substituteType(declaredType);
|
||||
}
|
||||
|
||||
if (!declaredMember.isNonNullableByDefault &&
|
||||
interfaceMember.isNonNullableByDefault) {
|
||||
interfaceType = legacyErasure(types.hierarchy.coreTypes, interfaceType);
|
||||
}
|
||||
|
||||
bool inParameter = declaredParameter != null || asIfDeclaredParameter;
|
||||
DartType subtype = inParameter ? interfaceType : declaredType;
|
||||
DartType supertype = inParameter ? declaredType : interfaceType;
|
||||
|
|
|
@ -886,7 +886,8 @@ class IsNeverTypeSubtypeOf implements TypeRelation<NeverType> {
|
|||
|
||||
IsSubtypeOf isInterfaceRelated(InterfaceType s, NeverType t, Types types) {
|
||||
if (s.classNode == types.hierarchy.nullClass) {
|
||||
if (t.nullability == Nullability.nullable) {
|
||||
if (t.nullability == Nullability.nullable ||
|
||||
t.nullability == Nullability.legacy) {
|
||||
return const IsSubtypeOf.always();
|
||||
}
|
||||
if (t.nullability == Nullability.nonNullable) {
|
||||
|
|
|
@ -64,6 +64,30 @@ main() {
|
|||
throws(() => inferredLocalNever = throwing());
|
||||
}
|
||||
|
||||
class B extends A {
|
||||
Null neverField;
|
||||
Null neverMethod(Null value) => value;
|
||||
Null get neverProperty => null;
|
||||
void set neverProperty(Null value) {}
|
||||
|
||||
Null nullField;
|
||||
Null nullMethod(Null value) => value;
|
||||
Null get nullProperty => null;
|
||||
void set nullProperty(Null value) {}
|
||||
}
|
||||
|
||||
class C extends A {
|
||||
Never neverField;
|
||||
Never neverMethod(Never value) => value;
|
||||
Never get neverProperty => null;
|
||||
void set neverProperty(Never value) {}
|
||||
|
||||
Never nullField;
|
||||
Never nullMethod(Never value) => value;
|
||||
Never get nullProperty => null;
|
||||
void set nullProperty(Never value) {}
|
||||
}
|
||||
|
||||
throws(void Function() f) {
|
||||
try {
|
||||
f();
|
||||
|
|
|
@ -1,9 +1,46 @@
|
|||
library;
|
||||
import self as self;
|
||||
import "never_opt_out_lib.dart" as nev;
|
||||
import "dart:core" as core;
|
||||
|
||||
import "org-dartlang-testcase:///never_opt_out_lib.dart";
|
||||
|
||||
class B extends nev::A {
|
||||
field core::Null? neverField;
|
||||
field core::Null? nullField;
|
||||
synthetic constructor •() → self::B*
|
||||
;
|
||||
method neverMethod(core::Null? value) → core::Null?
|
||||
;
|
||||
get neverProperty() → core::Null?
|
||||
;
|
||||
set neverProperty(core::Null? value) → void
|
||||
;
|
||||
method nullMethod(core::Null? value) → core::Null?
|
||||
;
|
||||
get nullProperty() → core::Null?
|
||||
;
|
||||
set nullProperty(core::Null? value) → void
|
||||
;
|
||||
}
|
||||
class C extends nev::A {
|
||||
field Never* neverField;
|
||||
field Never* nullField;
|
||||
synthetic constructor •() → self::C*
|
||||
;
|
||||
method neverMethod(Never* value) → Never*
|
||||
;
|
||||
get neverProperty() → Never*
|
||||
;
|
||||
set neverProperty(Never* value) → void
|
||||
;
|
||||
method nullMethod(Never* value) → Never*
|
||||
;
|
||||
get nullProperty() → Never*
|
||||
;
|
||||
set nullProperty(Never* value) → void
|
||||
;
|
||||
}
|
||||
static field Never* optOutNever;
|
||||
static field core::Null? inferredOptOutNever;
|
||||
static method main() → dynamic
|
||||
|
@ -12,10 +49,29 @@ static method throws(() →* void f) → dynamic
|
|||
;
|
||||
|
||||
library /*isNonNullableByDefault*/;
|
||||
import self as self2;
|
||||
import self as nev;
|
||||
import "dart:core" as core;
|
||||
|
||||
import "org-dartlang-testcase:///never_opt_out.dart";
|
||||
|
||||
class A extends core::Object {
|
||||
field Never neverField;
|
||||
field core::Null? nullField;
|
||||
synthetic constructor •() → nev::A
|
||||
;
|
||||
method neverMethod(Never value) → Never
|
||||
;
|
||||
get neverProperty() → Never
|
||||
;
|
||||
set neverProperty(Never value) → void
|
||||
;
|
||||
method nullMethod(core::Null? value) → core::Null?
|
||||
;
|
||||
get nullProperty() → core::Null?
|
||||
;
|
||||
set nullProperty(core::Null? value) → void
|
||||
;
|
||||
}
|
||||
static field Never optInNever;
|
||||
static method throwing() → Never
|
||||
;
|
||||
|
|
|
@ -1,10 +1,44 @@
|
|||
library;
|
||||
import self as self;
|
||||
import "dart:core" as core;
|
||||
import "never_opt_out_lib.dart" as nev;
|
||||
import "dart:core" as core;
|
||||
|
||||
import "org-dartlang-testcase:///never_opt_out_lib.dart";
|
||||
|
||||
class B extends nev::A {
|
||||
field core::Null? neverField = null;
|
||||
field core::Null? nullField = null;
|
||||
synthetic constructor •() → self::B*
|
||||
: super nev::A::•()
|
||||
;
|
||||
method neverMethod(core::Null? value) → core::Null?
|
||||
return value;
|
||||
get neverProperty() → core::Null?
|
||||
return null;
|
||||
set neverProperty(core::Null? value) → void {}
|
||||
method nullMethod(core::Null? value) → core::Null?
|
||||
return value;
|
||||
get nullProperty() → core::Null?
|
||||
return null;
|
||||
set nullProperty(core::Null? value) → void {}
|
||||
}
|
||||
class C extends nev::A {
|
||||
field Never* neverField = null;
|
||||
field Never* nullField = null;
|
||||
synthetic constructor •() → self::C*
|
||||
: super nev::A::•()
|
||||
;
|
||||
method neverMethod(Never* value) → Never*
|
||||
return value;
|
||||
get neverProperty() → Never*
|
||||
return null;
|
||||
set neverProperty(Never* value) → void {}
|
||||
method nullMethod(Never* value) → Never*
|
||||
return value;
|
||||
get nullProperty() → Never*
|
||||
return null;
|
||||
set nullProperty(Never* value) → void {}
|
||||
}
|
||||
static field Never* optOutNever;
|
||||
static field core::Null? inferredOptOutNever = nev::optInNever;
|
||||
static method main() → dynamic {
|
||||
|
@ -65,11 +99,40 @@ static method throws(() →* void f) → dynamic {
|
|||
}
|
||||
|
||||
library /*isNonNullableByDefault*/;
|
||||
//
|
||||
// Problems in library:
|
||||
//
|
||||
// pkg/front_end/testcases/nnbd/never_opt_out_lib.dart:19:28: Error: A value of type 'Type' can't be assigned to a variable of type 'Null?'.
|
||||
// - 'Type' is from 'dart:core'.
|
||||
// Null get nullProperty => Null;
|
||||
// ^
|
||||
//
|
||||
import self as nev;
|
||||
import "dart:core" as core;
|
||||
import "never_opt_out.dart" as self;
|
||||
|
||||
import "org-dartlang-testcase:///never_opt_out.dart";
|
||||
|
||||
class A extends core::Object {
|
||||
field Never neverField = throw "Should not reach here";
|
||||
field core::Null? nullField = null;
|
||||
synthetic constructor •() → nev::A
|
||||
: super core::Object::•()
|
||||
;
|
||||
method neverMethod(Never value) → Never
|
||||
return value;
|
||||
get neverProperty() → Never
|
||||
return throw "Should not reach here";
|
||||
set neverProperty(Never value) → void {}
|
||||
method nullMethod(core::Null? value) → core::Null?
|
||||
return value;
|
||||
get nullProperty() → core::Null?
|
||||
return let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/never_opt_out_lib.dart:19:28: Error: A value of type 'Type' can't be assigned to a variable of type 'Null?'.
|
||||
- 'Type' is from 'dart:core'.
|
||||
Null get nullProperty => Null;
|
||||
^" in core::Null? as{TypeError,ForNonNullableByDefault} core::Null?;
|
||||
set nullProperty(core::Null? value) → void {}
|
||||
}
|
||||
static field Never optInNever = self::optOutNever;
|
||||
static method throwing() → Never
|
||||
return throw "Never!";
|
||||
|
|
|
@ -1,10 +1,44 @@
|
|||
library;
|
||||
import self as self;
|
||||
import "dart:core" as core;
|
||||
import "never_opt_out_lib.dart" as nev;
|
||||
import "dart:core" as core;
|
||||
|
||||
import "org-dartlang-testcase:///never_opt_out_lib.dart";
|
||||
|
||||
class B extends nev::A {
|
||||
field core::Null? neverField = null;
|
||||
field core::Null? nullField = null;
|
||||
synthetic constructor •() → self::B*
|
||||
: super nev::A::•()
|
||||
;
|
||||
method neverMethod(core::Null? value) → core::Null?
|
||||
return value;
|
||||
get neverProperty() → core::Null?
|
||||
return null;
|
||||
set neverProperty(core::Null? value) → void {}
|
||||
method nullMethod(core::Null? value) → core::Null?
|
||||
return value;
|
||||
get nullProperty() → core::Null?
|
||||
return null;
|
||||
set nullProperty(core::Null? value) → void {}
|
||||
}
|
||||
class C extends nev::A {
|
||||
field Never* neverField = null;
|
||||
field Never* nullField = null;
|
||||
synthetic constructor •() → self::C*
|
||||
: super nev::A::•()
|
||||
;
|
||||
method neverMethod(Never* value) → Never*
|
||||
return value;
|
||||
get neverProperty() → Never*
|
||||
return null;
|
||||
set neverProperty(Never* value) → void {}
|
||||
method nullMethod(Never* value) → Never*
|
||||
return value;
|
||||
get nullProperty() → Never*
|
||||
return null;
|
||||
set nullProperty(Never* value) → void {}
|
||||
}
|
||||
static field Never* optOutNever;
|
||||
static field core::Null? inferredOptOutNever = nev::optInNever;
|
||||
static method main() → dynamic {
|
||||
|
@ -65,11 +99,37 @@ static method throws(() →* void f) → dynamic {
|
|||
}
|
||||
|
||||
library /*isNonNullableByDefault*/;
|
||||
//
|
||||
// Problems in library:
|
||||
//
|
||||
// pkg/front_end/testcases/nnbd/never_opt_out_lib.dart:19:28: Warning: Assigning value of type 'Type' to a variable of type 'Null?'.
|
||||
// - 'Type' is from 'dart:core'.
|
||||
// Null get nullProperty => Null;
|
||||
// ^
|
||||
//
|
||||
import self as nev;
|
||||
import "dart:core" as core;
|
||||
import "never_opt_out.dart" as self;
|
||||
|
||||
import "org-dartlang-testcase:///never_opt_out.dart";
|
||||
|
||||
class A extends core::Object {
|
||||
field Never neverField = throw "Should not reach here";
|
||||
field core::Null? nullField = null;
|
||||
synthetic constructor •() → nev::A
|
||||
: super core::Object::•()
|
||||
;
|
||||
method neverMethod(Never value) → Never
|
||||
return value;
|
||||
get neverProperty() → Never
|
||||
return throw "Should not reach here";
|
||||
set neverProperty(Never value) → void {}
|
||||
method nullMethod(core::Null? value) → core::Null?
|
||||
return value;
|
||||
get nullProperty() → core::Null?
|
||||
return core::Null? as{TypeError,ForNonNullableByDefault} core::Null?;
|
||||
set nullProperty(core::Null? value) → void {}
|
||||
}
|
||||
static field Never optInNever = self::optOutNever;
|
||||
static method throwing() → Never
|
||||
return throw "Never!";
|
||||
|
|
|
@ -7,3 +7,15 @@ import 'never_opt_out.dart';
|
|||
Never throwing() => throw 'Never!';
|
||||
|
||||
Never optInNever = optOutNever;
|
||||
|
||||
class A {
|
||||
Never neverField = throw "Should not reach here";
|
||||
Never neverMethod(Never value) => value;
|
||||
Never get neverProperty => throw "Should not reach here";
|
||||
void set neverProperty(Never value) {}
|
||||
|
||||
Null nullField = null;
|
||||
Null nullMethod(Null value) => value;
|
||||
Null get nullProperty => Null;
|
||||
void set nullProperty(Null value) {}
|
||||
}
|
||||
|
|
|
@ -55,6 +55,7 @@ inference_new/infer_field_override_getter_overrides_setter: TypeCheckError
|
|||
nnbd/inheritance_from_opt_in: TypeCheckError
|
||||
nnbd/messages_with_types_opt_in: TypeCheckError
|
||||
nnbd/messages_with_types_opt_out: TypeCheckError
|
||||
nnbd/never_opt_out: TypeCheckError
|
||||
|
||||
rasta/native_is_illegal: Pass # Issue 29763
|
||||
|
||||
|
|
|
@ -171,6 +171,7 @@ instantiate_to_bound/non_simple_generic_function_in_bound_regress: RuntimeError
|
|||
nnbd/inheritance_from_opt_in: TypeCheckError
|
||||
nnbd/messages_with_types_opt_in: TypeCheckError
|
||||
nnbd/messages_with_types_opt_out: TypeCheckError
|
||||
nnbd/never_opt_out: TypeCheckError
|
||||
rasta/abstract_constructor: RuntimeError
|
||||
rasta/bad_constructor_redirection: RuntimeError
|
||||
rasta/bad_continue: RuntimeError
|
||||
|
|
|
@ -1246,7 +1246,7 @@ nnbd/messages_with_types_opt_out: TypeCheckError
|
|||
nnbd/missing_required_named_parameter: TextSerializationFailure
|
||||
nnbd/mixin_from_opt_in: TextSerializationFailure
|
||||
nnbd/mixin_from_opt_out: TextSerializationFailure
|
||||
nnbd/never_opt_out: TextSerializationFailure
|
||||
nnbd/never_opt_out: TypeCheckError
|
||||
nnbd/never_receiver: TextSerializationFailure
|
||||
nnbd/nnbd_opt_out_language_version: TextSerializationFailure
|
||||
nnbd/nnbd_opt_out_language_version_try_to_trick: TextSerializationFailure
|
||||
|
|
|
@ -65,4 +65,5 @@ general_nnbd_opt_out/void_methods: RuntimeError
|
|||
general_nnbd_opt_out/warn_unresolved_sends: InstrumentationMismatch # Test assumes Dart 1.0 semantics
|
||||
nnbd/inheritance_from_opt_in: TypeCheckError
|
||||
nnbd/messages_with_types_opt_in: TypeCheckError
|
||||
nnbd/messages_with_types_opt_out: TypeCheckError
|
||||
nnbd/messages_with_types_opt_out: TypeCheckError
|
||||
nnbd/never_opt_out: TypeCheckError
|
Loading…
Reference in a new issue