Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 7bbd8ea

Browse files
committed
Introduce a representation of the type Never?.
This type is equivalent to the existing type `Null`, but we need it anyway because `Null` can only be accessed via the type provider, and there are circumstances where we need to create this type and don't have access to the type provider. It also may prove beneficial to be able to distinguish between `Null` and `Never?` in diagnostic messages. Change-Id: I6118e87c8c4736a508a3f366f2762a96198db7ca Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/103540 Reviewed-by: Konstantin Shcheglov <[email protected]> Reviewed-by: Mike Fairhurst <[email protected]> Reviewed-by: Brian Wilkerson <[email protected]>
1 parent 28f7019 commit 7bbd8ea

File tree

1 file changed

+40
-6
lines changed

1 file changed

+40
-6
lines changed

pkg/analyzer/lib/src/dart/element/type.dart

Lines changed: 40 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -56,14 +56,31 @@ typedef List<DartType> TypeArgumentsComputer();
5656
*/
5757
class BottomTypeImpl extends TypeImpl {
5858
/**
59-
* The unique instance of this class.
59+
* The unique instance of this class, nullable.
60+
*
61+
* This behaves equivalently to the `Null` type, but we distinguish it for two
62+
* reasons: (1) there are circumstances where we need access to this type, but
63+
* we don't have access to the type provider, so using `Never?` is a
64+
* convenient solution. (2) we may decide that the distinction is convenient
65+
* in diagnostic messages (this is TBD).
6066
*/
61-
static final BottomTypeImpl instance = new BottomTypeImpl._();
67+
static final BottomTypeImpl instanceNullable =
68+
new BottomTypeImpl._(NullabilitySuffix.question);
69+
70+
/**
71+
* The unique instance of this class, non-nullable.
72+
*/
73+
static final BottomTypeImpl instance =
74+
new BottomTypeImpl._(NullabilitySuffix.none);
75+
76+
@override
77+
final NullabilitySuffix nullabilitySuffix;
6278

6379
/**
6480
* Prevent the creation of instances of this class.
6581
*/
66-
BottomTypeImpl._() : super(new NeverElementImpl(), "Never") {
82+
BottomTypeImpl._(this.nullabilitySuffix)
83+
: super(new NeverElementImpl(), "Never") {
6784
(element as NeverElementImpl).type = this;
6885
}
6986

@@ -74,7 +91,10 @@ class BottomTypeImpl extends TypeImpl {
7491
bool get isBottom => true;
7592

7693
@override
77-
NullabilitySuffix get nullabilitySuffix => NullabilitySuffix.none;
94+
bool get isDartCoreNull {
95+
// `Never?` is equivalent to `Null`, so make sure it behaves the same.
96+
return nullabilitySuffix == NullabilitySuffix.question;
97+
}
7898

7999
@override
80100
bool operator ==(Object object) => identical(object, this);
@@ -119,8 +139,22 @@ class BottomTypeImpl extends TypeImpl {
119139

120140
@override
121141
TypeImpl withNullability(NullabilitySuffix nullabilitySuffix) {
122-
// The bottom type is always non-nullable.
123-
return this;
142+
switch (nullabilitySuffix) {
143+
case NullabilitySuffix.question:
144+
return instanceNullable;
145+
case NullabilitySuffix.star:
146+
// This should never happen. Converting `Never` to a legacy type should
147+
// yield `Null`, because prior to NNBD, `Null` was at the bottom of the
148+
// type hierarchy.
149+
//
150+
// However, due to bugs elsewhere in the analyzer, this does still
151+
// happen sometimes, so for now just coerce to `Never?`.
152+
// TODO(paulberry): change this to throw an exception.
153+
return instanceNullable;
154+
case NullabilitySuffix.none:
155+
return instance;
156+
}
157+
throw StateError('Unexpected nullabilitySuffix: $nullabilitySuffix');
124158
}
125159
}
126160

0 commit comments

Comments
 (0)