Skip to content

Commit 0d16ff6

Browse files
johnniwinthercommit-bot@chromium.org
authored andcommitted
[cfe] Handle static type of access on Never
Closes #41273 Change-Id: Ia236481ab47033198d7952086cdf5c9c8f5a34b7 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/142366 Commit-Queue: Johnni Winther <[email protected]> Reviewed-by: Dmitry Stefantsov <[email protected]>
1 parent a90b845 commit 0d16ff6

22 files changed

+667
-143
lines changed

pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1036,23 +1036,10 @@ class TypeInferrerImpl implements TypeInferrer {
10361036

10371037
if (receiverType is FunctionType && name == callName) {
10381038
return const ObjectAccessTarget.callFunction();
1039-
}
1040-
1041-
Class classNode = receiverType is InterfaceType
1042-
? receiverType.classNode
1043-
: coreTypes.objectClass;
1044-
Member interfaceMember =
1045-
_getInterfaceMember(classNode, name, setter, fileOffset);
1046-
ObjectAccessTarget target;
1047-
if (interfaceMember != null) {
1048-
target = new ObjectAccessTarget.interfaceMember(interfaceMember);
1049-
} else if (receiverType is DynamicType) {
1050-
target = const ObjectAccessTarget.dynamic();
10511039
} else if (receiverType is NeverType) {
10521040
switch (receiverType.nullability) {
10531041
case Nullability.nonNullable:
1054-
target = const ObjectAccessTarget.never();
1055-
break;
1042+
return const ObjectAccessTarget.never();
10561043
case Nullability.nullable:
10571044
case Nullability.legacy:
10581045
// Never? and Never* are equivalent to Null.
@@ -1066,6 +1053,17 @@ class TypeInferrerImpl implements TypeInferrer {
10661053
fileOffset,
10671054
library.fileUri);
10681055
}
1056+
}
1057+
Class classNode = receiverType is InterfaceType
1058+
? receiverType.classNode
1059+
: coreTypes.objectClass;
1060+
Member interfaceMember =
1061+
_getInterfaceMember(classNode, name, setter, fileOffset);
1062+
ObjectAccessTarget target;
1063+
if (interfaceMember != null) {
1064+
target = new ObjectAccessTarget.interfaceMember(interfaceMember);
1065+
} else if (receiverType is DynamicType) {
1066+
target = const ObjectAccessTarget.dynamic();
10691067
} else if (receiverType is InvalidType) {
10701068
target = const ObjectAccessTarget.invalid();
10711069
} else if (receiverType is InterfaceType &&
@@ -1940,6 +1938,10 @@ class TypeInferrerImpl implements TypeInferrer {
19401938
Member equalsMember =
19411939
findInterfaceMember(variable.type, equalsName, variable.fileOffset)
19421940
.member;
1941+
// Ensure operator == member even for `Never`.
1942+
equalsMember ??= findInterfaceMember(const DynamicType(), equalsName, -1,
1943+
instrumented: false)
1944+
.member;
19431945
return new NullAwareGuard(
19441946
variable, variable.fileOffset, equalsMember, this);
19451947
}
@@ -2736,7 +2738,7 @@ class TypeInferrerImpl implements TypeInferrer {
27362738
isImplicitCall: isImplicitCall);
27372739
assert(name != equalsName);
27382740
return createNullAwareExpressionInferenceResult(
2739-
result.inferredType,
2741+
const NeverType(Nullability.nonNullable),
27402742
result.applyResult(new MethodInvocation(receiver, name, arguments)
27412743
..fileOffset = fileOffset),
27422744
nullAwareGuards);

pkg/front_end/test/spell_checking_list_code.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -689,6 +689,7 @@ nulls
689689
o
690690
oauth
691691
obj
692+
obligated
692693
observatory
693694
observe
694695
obstruct
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
library;
2+
import self as self;
3+
import "dart:core" as core;
4+
import "issue41210_lib1.dart" as iss;
5+
6+
import "org-dartlang-testcase:///issue41210_lib1.dart";
7+
8+
abstract class _C&Object&A extends core::Object implements iss::A /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/ {
9+
const synthetic constructor •() → self::_C&Object&A*
10+
: super core::Object::•()
11+
;
12+
method /* from org-dartlang-testcase:///issue41210_lib1.dart */ method({core::String* s = #C1}) → core::String*
13+
return s;
14+
}
15+
abstract class _C&Object&A&B extends self::_C&Object&A implements iss::B /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/ {
16+
const synthetic constructor •() → self::_C&Object&A&B*
17+
: super self::_C&Object&A::•()
18+
;
19+
abstract forwarding-stub method method({core::String* s = #C1}) → core::String*;
20+
}
21+
class C extends self::_C&Object&A&B {
22+
synthetic constructor •() → self::C*
23+
: super self::_C&Object&A&B::•()
24+
;
25+
abstract forwarding-stub method method({core::String* s = #C1}) → core::String*;
26+
}
27+
static method main() → dynamic {
28+
core::print(new self::C::•().{self::C::method}());
29+
}
30+
31+
library;
32+
import self as iss;
33+
import "dart:core" as core;
34+
import "issue41210_lib2.dart" as iss2;
35+
36+
import "org-dartlang-testcase:///issue41210_lib2.dart";
37+
38+
abstract class A extends core::Object implements iss2::Interface /*isMixinDeclaration*/ {
39+
method method({core::String* s = #C1}) → core::String*
40+
return s;
41+
}
42+
abstract class B extends core::Object implements iss2::Interface {
43+
synthetic constructor •() → iss::B*
44+
: super core::Object::•()
45+
;
46+
abstract member-signature method method() → core::String*;
47+
}
48+
static method main() → void {}
49+
50+
library /*isNonNullableByDefault*/;
51+
import self as iss2;
52+
import "dart:core" as core;
53+
54+
abstract class Interface extends core::Object {
55+
synthetic constructor •() → iss2::Interface
56+
: super core::Object::•()
57+
;
58+
abstract method method() → core::String;
59+
}
60+
61+
constants {
62+
#C1 = "hello"
63+
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
library;
2+
import self as self;
3+
import "dart:core" as core;
4+
import "issue41210_lib1.dart" as iss;
5+
6+
import "org-dartlang-testcase:///issue41210_lib1.dart";
7+
8+
abstract class _C&Object&A extends core::Object implements iss::A /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/ {
9+
const synthetic constructor •() → self::_C&Object&A*
10+
: super core::Object::•()
11+
;
12+
method /* from org-dartlang-testcase:///issue41210_lib1.dart */ method({core::String* s = #C1}) → core::String*
13+
return s;
14+
}
15+
abstract class _C&Object&A&B extends self::_C&Object&A implements iss::B /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/ {
16+
const synthetic constructor •() → self::_C&Object&A&B*
17+
: super self::_C&Object&A::•()
18+
;
19+
abstract forwarding-stub method method({core::String* s = #C1}) → core::String*;
20+
}
21+
class C extends self::_C&Object&A&B {
22+
synthetic constructor •() → self::C*
23+
: super self::_C&Object&A&B::•()
24+
;
25+
abstract forwarding-stub method method({core::String* s = #C1}) → core::String*;
26+
}
27+
static method main() → dynamic {
28+
core::print(new self::C::•().{self::C::method}());
29+
}
30+
31+
library;
32+
import self as iss;
33+
import "dart:core" as core;
34+
import "issue41210_lib2.dart" as iss2;
35+
36+
import "org-dartlang-testcase:///issue41210_lib2.dart";
37+
38+
abstract class A extends core::Object implements iss2::Interface /*isMixinDeclaration*/ {
39+
method method({core::String* s = #C1}) → core::String*
40+
return s;
41+
}
42+
abstract class B extends core::Object implements iss2::Interface {
43+
synthetic constructor •() → iss::B*
44+
: super core::Object::•()
45+
;
46+
abstract member-signature method method() → core::String*;
47+
}
48+
static method main() → void {}
49+
50+
library /*isNonNullableByDefault*/;
51+
import self as iss2;
52+
import "dart:core" as core;
53+
54+
abstract class Interface extends core::Object {
55+
synthetic constructor •() → iss2::Interface
56+
: super core::Object::•()
57+
;
58+
abstract method method() → core::String;
59+
}
60+
61+
constants {
62+
#C1 = "hello"
63+
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
library;
2+
import self as self;
3+
import "dart:core" as core;
4+
import "issue41210b_lib1.dart" as iss;
5+
6+
import "org-dartlang-testcase:///issue41210b_lib1.dart";
7+
8+
abstract class _C&Object&A extends core::Object implements iss::A /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/ {
9+
const synthetic constructor •() → self::_C&Object&A*
10+
: super core::Object::•()
11+
;
12+
method /* from org-dartlang-testcase:///issue41210b_lib1.dart */ method({core::String* s = #C1}) → core::String*
13+
return s;
14+
}
15+
abstract class _C&Object&A&B extends self::_C&Object&A implements iss::B /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/ {
16+
const synthetic constructor •() → self::_C&Object&A&B*
17+
: super self::_C&Object&A::•()
18+
;
19+
abstract member-signature method /* from org-dartlang-testcase:///issue41210b_lib1.dart */ method() → core::String*;
20+
}
21+
class C extends self::_C&Object&A&B {
22+
synthetic constructor •() → self::C*
23+
: super self::_C&Object&A&B::•()
24+
;
25+
}
26+
static method main() → dynamic {
27+
core::print(new self::C::•().{iss::A::method}());
28+
}
29+
30+
library;
31+
import self as iss;
32+
import "dart:core" as core;
33+
import "issue41210b_lib2.dart" as iss2;
34+
35+
import "org-dartlang-testcase:///issue41210b_lib2.dart";
36+
37+
abstract class A extends core::Object implements iss2::Interface /*isMixinDeclaration*/ {
38+
method method({core::String* s = #C1}) → core::String*
39+
return s;
40+
}
41+
abstract class B extends core::Object implements iss2::Interface {
42+
synthetic constructor •() → iss::B*
43+
: super core::Object::•()
44+
;
45+
abstract member-signature method method() → core::String*;
46+
}
47+
static method main() → void {}
48+
49+
library /*isNonNullableByDefault*/;
50+
import self as iss2;
51+
import "dart:core" as core;
52+
53+
abstract class Interface extends core::Object {
54+
synthetic constructor •() → iss2::Interface
55+
: super core::Object::•()
56+
;
57+
abstract method method() → core::String;
58+
}
59+
60+
constants {
61+
#C1 = "hello"
62+
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
library;
2+
import self as self;
3+
import "dart:core" as core;
4+
import "issue41210b_lib1.dart" as iss;
5+
6+
import "org-dartlang-testcase:///issue41210b_lib1.dart";
7+
8+
abstract class _C&Object&A extends core::Object implements iss::A /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/ {
9+
const synthetic constructor •() → self::_C&Object&A*
10+
: super core::Object::•()
11+
;
12+
method /* from org-dartlang-testcase:///issue41210b_lib1.dart */ method({core::String* s = #C1}) → core::String*
13+
return s;
14+
}
15+
abstract class _C&Object&A&B extends self::_C&Object&A implements iss::B /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/ {
16+
const synthetic constructor •() → self::_C&Object&A&B*
17+
: super self::_C&Object&A::•()
18+
;
19+
abstract member-signature method /* from org-dartlang-testcase:///issue41210b_lib1.dart */ method() → core::String*;
20+
}
21+
class C extends self::_C&Object&A&B {
22+
synthetic constructor •() → self::C*
23+
: super self::_C&Object&A&B::•()
24+
;
25+
}
26+
static method main() → dynamic {
27+
core::print(new self::C::•().{iss::A::method}());
28+
}
29+
30+
library;
31+
import self as iss;
32+
import "dart:core" as core;
33+
import "issue41210b_lib2.dart" as iss2;
34+
35+
import "org-dartlang-testcase:///issue41210b_lib2.dart";
36+
37+
abstract class A extends core::Object implements iss2::Interface /*isMixinDeclaration*/ {
38+
method method({core::String* s = #C1}) → core::String*
39+
return s;
40+
}
41+
abstract class B extends core::Object implements iss2::Interface {
42+
synthetic constructor •() → iss::B*
43+
: super core::Object::•()
44+
;
45+
abstract member-signature method method() → core::String*;
46+
}
47+
static method main() → void {}
48+
49+
library /*isNonNullableByDefault*/;
50+
import self as iss2;
51+
import "dart:core" as core;
52+
53+
abstract class Interface extends core::Object {
54+
synthetic constructor •() → iss2::Interface
55+
: super core::Object::•()
56+
;
57+
abstract method method() → core::String;
58+
}
59+
60+
constants {
61+
#C1 = "hello"
62+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
void test(var x) {
6+
if (x is Never) {
7+
Never n1 = x.toString();
8+
Never n2 = x.runtimeType;
9+
Never n3 = x.someGetter;
10+
Never n4 = x.someMethod();
11+
Never n5 = x + x;
12+
Never n6 = x[x];
13+
Never n7 = x();
14+
Never n8 = x.runtimeType();
15+
Never n9 = x.toString;
16+
x.runtimeType = Object;
17+
x.toString = () => '';
18+
var v1 = x.toString();
19+
var v2 = x.runtimeType;
20+
var v3 = x.someGetter;
21+
var v4 = x.someMethod();
22+
var v5 = x + x;
23+
var v6 = x[x];
24+
var v7 = x();
25+
var v8 = x.runtimeType();
26+
var v9 = x.toString;
27+
}
28+
}
29+
30+
main() {
31+
test(null);
32+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
library /*isNonNullableByDefault*/;
2+
import self as self;
3+
4+
static method test(dynamic x) → void
5+
;
6+
static method main() → dynamic
7+
;
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
library /*isNonNullableByDefault*/;
2+
import self as self;
3+
import "dart:core" as core;
4+
5+
static method test(dynamic x) → void {
6+
if(x is{ForNonNullableByDefault} Never) {
7+
Never n1 = x{Never}.toString();
8+
Never n2 = x{Never}.runtimeType;
9+
Never n3 = x{Never}.someGetter;
10+
Never n4 = x{Never}.someMethod();
11+
Never n5 = x{Never}.+(x{Never});
12+
Never n6 = x{Never}.[](x{Never});
13+
Never n7 = x{Never}.call();
14+
Never n8 = x{Never}.runtimeType();
15+
Never n9 = x{Never}.toString;
16+
x{Never}.runtimeType = core::Object;
17+
x{Never}.toString = () → core::String => "";
18+
Never v1 = x{Never}.toString();
19+
Never v2 = x{Never}.runtimeType;
20+
Never v3 = x{Never}.someGetter;
21+
Never v4 = x{Never}.someMethod();
22+
Never v5 = x{Never}.+(x{Never});
23+
Never v6 = x{Never}.[](x{Never});
24+
Never v7 = x{Never}.call();
25+
Never v8 = x{Never}.runtimeType();
26+
Never v9 = x{Never}.toString;
27+
}
28+
}
29+
static method main() → dynamic {
30+
self::test(null);
31+
}

0 commit comments

Comments
 (0)