[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:
Johnni Winther 2020-02-07 10:02:05 +00:00 committed by commit-bot@chromium.org
parent b978cb1cb5
commit 4267085fa5
11 changed files with 232 additions and 6 deletions

View file

@ -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;

View file

@ -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) {

View file

@ -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();

View file

@ -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
;

View file

@ -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!";

View file

@ -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!";

View file

@ -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) {}
}

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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