[dart2js] Split entities.dart to migrate some definitions

- migrate elements/jumps.dart, elements/names.dart, ir/util.dat

Change-Id: I57fc9c42dc0cca407bba38dfbf89fe7bfa6bd15d
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/241380
Reviewed-by: Joshua Litt <joshualitt@google.com>
Commit-Queue: Stephen Adams <sra@google.com>
diff --git a/pkg/compiler/lib/src/deferred_load/deferred_load.dart b/pkg/compiler/lib/src/deferred_load/deferred_load.dart
index 4bbfbdc..ab74ec9 100644
--- a/pkg/compiler/lib/src/deferred_load/deferred_load.dart
+++ b/pkg/compiler/lib/src/deferred_load/deferred_load.dart
@@ -317,7 +317,8 @@
 
   /// A sentinel used only by the [ImportSet] corresponding to the
   /// [_mainOutputUnit].
-  final ImportEntity _mainImport = ImportEntity(true, 'main#main', null, null);
+  final ImportEntity _mainImport =
+      ImportEntity(true, 'main#main', Uri(), Uri());
 
   /// A set containing (eventually) all output units that will result from the
   /// program.
diff --git a/pkg/compiler/lib/src/elements/entities.dart b/pkg/compiler/lib/src/elements/entities.dart
index e0f8380..788a702 100644
--- a/pkg/compiler/lib/src/elements/entities.dart
+++ b/pkg/compiler/lib/src/elements/entities.dart
@@ -6,79 +6,13 @@
 
 library entities;
 
-import 'package:front_end/src/api_unstable/dart2js.dart' show AsyncModifier;
-
-import '../common.dart';
 import '../serialization/serialization.dart';
 import '../universe/call_structure.dart' show CallStructure;
 import '../util/util.dart';
-import 'names.dart';
 import 'types.dart';
 
-/// Abstract interface for entities.
-///
-/// Implement this directly if the entity is not a Dart language entity.
-/// Entities defined within the Dart language should implement [Element].
-///
-/// For instance, the JavaScript backend need to create synthetic variables for
-/// calling intercepted classes and such variables do not correspond to an
-/// entity in the Dart source code nor in the terminology of the Dart language
-/// and should therefore implement [Entity] directly.
-abstract class Entity implements Spannable {
-  String get name;
-}
-
-/// Stripped down super interface for library like entities.
-///
-/// Currently only [LibraryElement] but later also kernel based Dart classes
-/// and/or Dart-in-JS classes.
-abstract class LibraryEntity extends Entity {
-  /// Return the canonical uri that identifies this library.
-  Uri /*!*/ get canonicalUri;
-
-  /// Returns whether or not this library has opted into null safety.
-  bool get isNonNullableByDefault;
-}
-
-/// Stripped down super interface for import entities.
-///
-/// The [name] property corresponds to the prefix name, if any.
-class ImportEntity {
-  final String /*?*/ name;
-
-  /// The canonical URI of the library where this import occurs
-  /// (where the import is declared).
-  final Uri enclosingLibraryUri;
-
-  /// Whether the import is a deferred import.
-  final bool isDeferred;
-
-  /// The target import URI.
-  final Uri uri;
-
-  ImportEntity(this.isDeferred, this.name, this.uri, this.enclosingLibraryUri);
-
-  @override
-  String toString() => 'import($name:${isDeferred ? ' deferred' : ''})';
-}
-
-/// Stripped down super interface for class like entities.
-///
-/// Currently only [ClassElement] but later also kernel based Dart classes
-/// and/or Dart-in-JS classes.
-abstract class ClassEntity extends Entity {
-  /// If this is a normal class, the enclosing library for this class. If this
-  /// is a closure class, the enclosing class of the closure for which it was
-  /// created.
-  LibraryEntity get library;
-
-  /// Whether this is a synthesized class for a closurized method or local
-  /// function.
-  bool get isClosure;
-
-  /// Whether this is an abstract class.
-  bool get isAbstract;
-}
+import 'entities_migrated.dart';
+export 'entities_migrated.dart';
 
 abstract class TypeVariableEntity extends Entity {
   /// The class or generic method that declared this type variable.
@@ -89,66 +23,6 @@
   int get index;
 }
 
-/// Stripped down super interface for member like entities, that is,
-/// constructors, methods, fields etc.
-///
-/// Currently only [MemberElement] but later also kernel based Dart members
-/// and/or Dart-in-JS properties.
-abstract class MemberEntity extends Entity {
-  /// The [Name] of member which takes privacy and getter/setter naming into
-  /// account.
-  Name get memberName;
-
-  /// Whether this is a member of a library.
-  bool get isTopLevel;
-
-  /// Whether this is a static member of a class.
-  bool get isStatic;
-
-  /// Whether this is an instance member of a class.
-  bool get isInstanceMember;
-
-  /// Whether this is a constructor.
-  bool get isConstructor;
-
-  /// Whether this is a field.
-  bool get isField;
-
-  /// Whether this is a normal method (neither constructor, getter or setter)
-  /// or operator method.
-  bool get isFunction;
-
-  /// Whether this is a getter.
-  bool get isGetter;
-
-  /// Whether this is a setter.
-  bool get isSetter;
-
-  /// Whether this member is assignable, i.e. a non-final, non-const field.
-  bool /*!*/ get isAssignable;
-
-  /// Whether this member is constant, i.e. a constant field or constructor.
-  bool /*!*/ get isConst;
-
-  /// Whether this member is abstract, i.e. an abstract method, getter or
-  /// setter.
-  bool /*!*/ get isAbstract;
-
-  /// The enclosing class if this is a constructor, instance member or
-  /// static member of a class.
-  ClassEntity get enclosingClass;
-
-  /// The enclosing library if this is a library member, otherwise the
-  /// enclosing library of the [enclosingClass].
-  LibraryEntity get library;
-}
-
-/// Stripped down super interface for field like entities.
-///
-/// Currently only [FieldElement] but later also kernel based Dart fields
-/// and/or Dart-in-JS field-like properties.
-abstract class FieldEntity extends MemberEntity {}
-
 /// Stripped down super interface for function like entities.
 ///
 /// Currently only [MethodElement] but later also kernel based Dart constructors
@@ -165,61 +39,6 @@
   AsyncMarker get asyncMarker;
 }
 
-/// Enum for the synchronous/asynchronous function body modifiers.
-class AsyncMarker {
-  /// The default function body marker.
-  static const AsyncMarker SYNC = AsyncMarker._(AsyncModifier.Sync);
-
-  /// The `sync*` function body marker.
-  static const AsyncMarker SYNC_STAR =
-      AsyncMarker._(AsyncModifier.SyncStar, isYielding: true);
-
-  /// The `async` function body marker.
-  static const AsyncMarker ASYNC =
-      AsyncMarker._(AsyncModifier.Async, isAsync: true);
-
-  /// The `async*` function body marker.
-  static const AsyncMarker ASYNC_STAR =
-      AsyncMarker._(AsyncModifier.AsyncStar, isAsync: true, isYielding: true);
-
-  /// Is `true` if this marker defines the function body to have an
-  /// asynchronous result, that is, either a [Future] or a [Stream].
-  final bool isAsync;
-
-  /// Is `true` if this marker defines the function body to have a plural
-  /// result, that is, either an [Iterable] or a [Stream].
-  final bool isYielding;
-
-  final AsyncModifier asyncParserState;
-
-  const AsyncMarker._(this.asyncParserState,
-      {this.isAsync = false, this.isYielding = false});
-
-  @override
-  String toString() {
-    return '${isAsync ? 'async' : 'sync'}${isYielding ? '*' : ''}';
-  }
-
-  /// Canonical list of marker values.
-  ///
-  /// Added to make [AsyncMarker] enum-like.
-  static const List<AsyncMarker> values = <AsyncMarker>[
-    SYNC,
-    SYNC_STAR,
-    ASYNC,
-    ASYNC_STAR
-  ];
-
-  /// Index to this marker within [values].
-  ///
-  /// Added to make [AsyncMarker] enum-like.
-  int get index => values.indexOf(this);
-}
-
-/// Values for variance annotations.
-/// This needs to be kept in sync with values of `Variance` in `dart:_rti`.
-enum Variance { legacyCovariant, covariant, contravariant, invariant }
-
 /// Stripped down super interface for constructor like entities.
 ///
 /// Currently only [ConstructorElement] but later also kernel based Dart
@@ -249,18 +68,6 @@
   ConstructorEntity get constructor;
 }
 
-/// An entity that defines a local entity (memory slot) in generated code.
-///
-/// Parameters, local variables and local functions (can) define local entity
-/// and thus implement [Local] through [LocalElement]. For non-element locals,
-/// like `this` and boxes, specialized [Local] classes are created.
-///
-/// Type variables can introduce locals in factories and constructors
-/// but since one type variable can introduce different locals in different
-/// factories and constructors it is not itself a [Local] but instead
-/// a non-element [Local] is created through a specialized class.
-abstract class Local extends Entity {}
-
 /// The structure of function parameters.
 class ParameterStructure {
   /// Tag used for identifying serialized [ParameterStructure] objects in a
diff --git a/pkg/compiler/lib/src/elements/entities_migrated.dart b/pkg/compiler/lib/src/elements/entities_migrated.dart
new file mode 100644
index 0000000..7e7a26f
--- /dev/null
+++ b/pkg/compiler/lib/src/elements/entities_migrated.dart
@@ -0,0 +1,207 @@
+// Copyright (c) 2016, 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.
+
+library entities.migrated;
+
+import 'package:front_end/src/api_unstable/dart2js.dart' show AsyncModifier;
+
+// TODO(48820): This was imported from `common.dart`.
+import '../diagnostics/spannable.dart' show Spannable;
+
+import 'names.dart';
+
+/// Abstract interface for entities.
+///
+/// Implement this directly if the entity is not a Dart language entity.
+/// Entities defined within the Dart language should implement [Element].
+///
+/// For instance, the JavaScript backend need to create synthetic variables for
+/// calling intercepted classes and such variables do not correspond to an
+/// entity in the Dart source code nor in the terminology of the Dart language
+/// and should therefore implement [Entity] directly.
+abstract class Entity implements Spannable {
+  // Not all entities have names. Imports with no prefix and some local
+  // variables are unnamed. Some entities have a name that is the empty string
+  // (e.g. the default constructor).
+  String? get name;
+}
+
+/// Stripped down super interface for library like entities.
+///
+/// Currently only [LibraryElement] but later also kernel based Dart classes
+/// and/or Dart-in-JS classes.
+abstract class LibraryEntity extends Entity {
+  /// Return the canonical uri that identifies this library.
+  Uri get canonicalUri;
+
+  /// Returns whether or not this library has opted into null safety.
+  bool get isNonNullableByDefault;
+}
+
+/// Stripped down super interface for import entities.
+///
+/// The [name] property corresponds to the prefix name, if any.
+class ImportEntity {
+  final String? name;
+
+  /// The canonical URI of the library where this import occurs
+  /// (where the import is declared).
+  final Uri enclosingLibraryUri;
+
+  /// Whether the import is a deferred import.
+  final bool isDeferred;
+
+  /// The target import URI.
+  final Uri uri;
+
+  ImportEntity(this.isDeferred, this.name, this.uri, this.enclosingLibraryUri);
+
+  @override
+  String toString() => 'import($name:${isDeferred ? ' deferred' : ''})';
+}
+
+/// Stripped down super interface for class like entities.
+///
+/// Currently only [ClassElement] but later also kernel based Dart classes
+/// and/or Dart-in-JS classes.
+abstract class ClassEntity extends Entity {
+  /// If this is a normal class, the enclosing library for this class. If this
+  /// is a closure class, the enclosing class of the closure for which it was
+  /// created.
+  LibraryEntity get library;
+
+  /// Whether this is a synthesized class for a closurized method or local
+  /// function.
+  bool get isClosure;
+
+  /// Whether this is an abstract class.
+  bool get isAbstract;
+}
+
+/// Stripped down super interface for member like entities, that is,
+/// constructors, methods, fields etc.
+///
+/// Currently only [MemberElement] but later also kernel based Dart members
+/// and/or Dart-in-JS properties.
+abstract class MemberEntity extends Entity {
+  /// The [Name] of member which takes privacy and getter/setter naming into
+  /// account.
+  Name get memberName;
+
+  /// Whether this is a member of a library.
+  bool get isTopLevel;
+
+  /// Whether this is a static member of a class.
+  bool get isStatic;
+
+  /// Whether this is an instance member of a class.
+  bool get isInstanceMember;
+
+  /// Whether this is a constructor.
+  bool get isConstructor;
+
+  /// Whether this is a field.
+  bool get isField;
+
+  /// Whether this is a normal method (neither constructor, getter or setter)
+  /// or operator method.
+  bool get isFunction;
+
+  /// Whether this is a getter.
+  bool get isGetter;
+
+  /// Whether this is a setter.
+  bool get isSetter;
+
+  /// Whether this member is assignable, i.e. a non-final, non-const field.
+  bool get isAssignable;
+
+  /// Whether this member is constant, i.e. a constant field or constructor.
+  bool get isConst;
+
+  /// Whether this member is abstract, i.e. an abstract method, getter or
+  /// setter.
+  bool get isAbstract;
+
+  /// The enclosing class if this is a constructor, instance member or
+  /// static member of a class.
+  ClassEntity? get enclosingClass;
+
+  /// The enclosing library if this is a library member, otherwise the
+  /// enclosing library of the [enclosingClass].
+  LibraryEntity get library;
+}
+
+/// Stripped down super interface for field like entities.
+///
+/// Currently only [FieldElement] but later also kernel based Dart fields
+/// and/or Dart-in-JS field-like properties.
+abstract class FieldEntity extends MemberEntity {}
+
+/// An entity that defines a local entity (memory slot) in generated code.
+///
+/// Parameters, local variables and local functions (can) define local entity
+/// and thus implement [Local] through [LocalElement]. For non-element locals,
+/// like `this` and boxes, specialized [Local] classes are created.
+///
+/// Type variables can introduce locals in factories and constructors
+/// but since one type variable can introduce different locals in different
+/// factories and constructors it is not itself a [Local] but instead
+/// a non-element [Local] is created through a specialized class.
+abstract class Local extends Entity {}
+
+/// Enum for the synchronous/asynchronous function body modifiers.
+class AsyncMarker {
+  /// The default function body marker.
+  static const AsyncMarker SYNC = AsyncMarker._(AsyncModifier.Sync);
+
+  /// The `sync*` function body marker.
+  static const AsyncMarker SYNC_STAR =
+      AsyncMarker._(AsyncModifier.SyncStar, isYielding: true);
+
+  /// The `async` function body marker.
+  static const AsyncMarker ASYNC =
+      AsyncMarker._(AsyncModifier.Async, isAsync: true);
+
+  /// The `async*` function body marker.
+  static const AsyncMarker ASYNC_STAR =
+      AsyncMarker._(AsyncModifier.AsyncStar, isAsync: true, isYielding: true);
+
+  /// Is `true` if this marker defines the function body to have an
+  /// asynchronous result, that is, either a [Future] or a [Stream].
+  final bool isAsync;
+
+  /// Is `true` if this marker defines the function body to have a plural
+  /// result, that is, either an [Iterable] or a [Stream].
+  final bool isYielding;
+
+  final AsyncModifier asyncParserState;
+
+  const AsyncMarker._(this.asyncParserState,
+      {this.isAsync = false, this.isYielding = false});
+
+  @override
+  String toString() {
+    return '${isAsync ? 'async' : 'sync'}${isYielding ? '*' : ''}';
+  }
+
+  /// Canonical list of marker values.
+  ///
+  /// Added to make [AsyncMarker] enum-like.
+  static const List<AsyncMarker> values = <AsyncMarker>[
+    SYNC,
+    SYNC_STAR,
+    ASYNC,
+    ASYNC_STAR
+  ];
+
+  /// Index to this marker within [values].
+  ///
+  /// Added to make [AsyncMarker] enum-like.
+  int get index => values.indexOf(this);
+}
+
+/// Values for variance annotations.
+/// This needs to be kept in sync with values of `Variance` in `dart:_rti`.
+enum Variance { legacyCovariant, covariant, contravariant, invariant }
diff --git a/pkg/compiler/lib/src/elements/entity_utils.dart b/pkg/compiler/lib/src/elements/entity_utils.dart
index cb548cf..dc5b5e0 100644
--- a/pkg/compiler/lib/src/elements/entity_utils.dart
+++ b/pkg/compiler/lib/src/elements/entity_utils.dart
@@ -10,7 +10,7 @@
     show isUserDefinableOperator, isMinusOperator;
 
 import '../js_backend/namer.dart';
-import 'entities.dart';
+import 'entities.dart' show Entity, FunctionEntity;
 
 // Somewhat stable ordering for libraries using [Uri]s
 int compareLibrariesUris(Uri a, Uri b) {
@@ -111,6 +111,11 @@
 /// The results returned from this method are guaranteed to be valid
 /// JavaScript identifiers, except it may include reserved words for
 /// non-operator names.
+// TODO(sra): The namer uses another, different, version of this function. Make
+// it clearer that this function is not used for JavaScript naming, but is
+// useful in creating identifiers for other purposes like data formats for file
+// names.  Break the connection to Namer.  Rename this function and move it to a
+// more general String utils place.
 String operatorNameToIdentifier(String name) {
   if (name == null) {
     return name;
diff --git a/pkg/compiler/lib/src/elements/jumps.dart b/pkg/compiler/lib/src/elements/jumps.dart
index 322ec51..f6080e2 100644
--- a/pkg/compiler/lib/src/elements/jumps.dart
+++ b/pkg/compiler/lib/src/elements/jumps.dart
@@ -2,11 +2,9 @@
 // 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.
 
-// @dart = 2.10
-
 library elements.jumps;
 
-import 'entities.dart';
+import 'entities_migrated.dart' show Entity, Local;
 
 /// The label entity defined by a labeled statement.
 abstract class LabelDefinition extends Entity {
diff --git a/pkg/compiler/lib/src/elements/names.dart b/pkg/compiler/lib/src/elements/names.dart
index 84f3e25..90f5e15 100644
--- a/pkg/compiler/lib/src/elements/names.dart
+++ b/pkg/compiler/lib/src/elements/names.dart
@@ -2,13 +2,11 @@
 // 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.
 
-// @dart = 2.10
-
 library dart2js.elements.names;
 
 import 'package:front_end/src/api_unstable/dart2js.dart' show $_;
 
-import 'entities.dart' show LibraryEntity;
+import 'entities_migrated.dart' show LibraryEntity;
 
 /// A [Name] represents the abstraction of a Dart identifier which takes privacy
 /// and setter into account.
@@ -17,9 +15,9 @@
   /// Create a [Name] for an identifier [text]. If [text] begins with '_' a
   /// private name with respect to [library] is created. If [isSetter] is `true`
   /// the created name represents the setter name 'text='.
-  factory Name(String text, LibraryEntity library, {bool isSetter = false}) {
+  factory Name(String text, LibraryEntity? library, {bool isSetter = false}) {
     if (isPrivateName(text)) {
-      return PrivateName(text, library, isSetter: isSetter);
+      return PrivateName(text, library!, isSetter: isSetter);
     }
     return PublicName(text, isSetter: isSetter);
   }
@@ -53,7 +51,8 @@
   bool isSimilarTo(Name other);
   int get similarHashCode;
 
-  LibraryEntity get library;
+  // TODO(sra): Should this rather throw for public names?
+  LibraryEntity? get library;
 
   /// Returns `true` when [s] is private if used as an identifier.
   static bool isPrivateName(String s) => !s.isEmpty && s.codeUnitAt(0) == $_;
@@ -98,7 +97,7 @@
   int get similarHashCode => text.hashCode + 11 * isSetter.hashCode;
 
   @override
-  LibraryEntity get library => null;
+  LibraryEntity? get library => null;
 
   @override
   String toString() => isSetter ? '$text=' : text;
diff --git a/pkg/compiler/lib/src/inferrer/builder_kernel.dart b/pkg/compiler/lib/src/inferrer/builder_kernel.dart
index 97fc077..d1f6982 100644
--- a/pkg/compiler/lib/src/inferrer/builder_kernel.dart
+++ b/pkg/compiler/lib/src/inferrer/builder_kernel.dart
@@ -2109,6 +2109,8 @@
     if (target == null) {
       // TODO(johnniwinther): Remove this when the CFE checks for missing
       //  concrete super targets.
+      // TODO(48820): If this path is infeasible, update types on
+      //  getEffectiveSuperTarget.
       return handleSuperNoSuchMethod(node, selector, null);
     }
     MemberEntity member = _elementMap.getMember(target);
diff --git a/pkg/compiler/lib/src/ir/util.dart b/pkg/compiler/lib/src/ir/util.dart
index 359fbfc..e0f1ff5 100644
--- a/pkg/compiler/lib/src/ir/util.dart
+++ b/pkg/compiler/lib/src/ir/util.dart
@@ -2,12 +2,12 @@
 // 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.
 
-// @dart = 2.10
-
 import 'package:kernel/ast.dart' as ir;
 
-import '../common.dart';
-import '../elements/entities.dart';
+// TODO(48820): revert to '../common.dart':
+import '../diagnostics/source_span.dart';
+import '../elements/entities_migrated.dart'
+    show AsyncMarker, MemberEntity, Variance;
 
 /// Returns a textual representation of [node] that include the runtime type and
 /// hash code of the node and a one line prefix of the node toString text.
@@ -19,10 +19,10 @@
   return '(${node.runtimeType}:${node.hashCode})${blockText}';
 }
 
-/// Comparator for the canonical order or named parameters.
+/// Comparator for the canonical order for named parameters.
 // TODO(johnniwinther): Remove this when named parameters are sorted in dill.
 int namedOrdering(ir.VariableDeclaration a, ir.VariableDeclaration b) {
-  return a.name.compareTo(b.name);
+  return a.name!.compareTo(b.name!);
 }
 
 /// Comparator for the declaration order of parameters.
@@ -30,18 +30,17 @@
   return a.fileOffset.compareTo(b.fileOffset);
 }
 
-SourceSpan computeSourceSpanFromTreeNode(ir.TreeNode node) {
+SourceSpan? computeSourceSpanFromTreeNode(ir.TreeNode node) {
   // TODO(johnniwinther): Use [ir.Location] directly as a [SourceSpan].
-  Uri uri;
-  int offset;
-  while (node != null) {
-    if (node.fileOffset != ir.TreeNode.noOffset) {
-      offset = node.fileOffset;
+  Uri? uri;
+  late int offset;
+  for (ir.TreeNode? current = node; current != null; current = current.parent) {
+    if (current.fileOffset != ir.TreeNode.noOffset) {
+      offset = current.fileOffset;
       // @patch annotations have no location.
-      uri = node.location?.file;
+      uri = current.location?.file;
       break;
     }
-    node = node.parent;
   }
   if (uri != null) {
     return SourceSpan(uri, offset, offset + 1);
@@ -100,34 +99,33 @@
 /// the parent of the let node, i.e. the parent node of the original null-aware
 /// expression. [let] returns the let node created for the encoding.
 class NullAwareExpression {
+  final ir.Let let;
   final ir.VariableDeclaration syntheticVariable;
   final ir.Expression expression;
 
-  NullAwareExpression(this.syntheticVariable, this.expression);
+  NullAwareExpression(this.let, this.syntheticVariable, this.expression);
 
-  ir.Expression get receiver => syntheticVariable.initializer;
+  ir.Expression get receiver => syntheticVariable.initializer!;
 
-  ir.TreeNode get parent => syntheticVariable.parent.parent;
-
-  ir.Let get let => syntheticVariable.parent;
+  ir.TreeNode get parent => let.parent!;
 
   @override
   String toString() => let.toString();
 }
 
-NullAwareExpression getNullAwareExpression(ir.TreeNode node) {
+NullAwareExpression? getNullAwareExpression(ir.TreeNode node) {
   if (node is ir.Let) {
     ir.Expression body = node.body;
     if (node.variable.name == null &&
         node.variable.isFinal &&
         body is ir.ConditionalExpression) {
-      if (body.condition is ir.EqualsNull) {
-        ir.EqualsNull equalsNull = body.condition;
-        ir.Expression receiver = equalsNull.expression;
+      final condition = body.condition;
+      if (condition is ir.EqualsNull) {
+        ir.Expression receiver = condition.expression;
         if (receiver is ir.VariableGet && receiver.variable == node.variable) {
           // We have
           //   let #t1 = e0 in #t1 == null ? null : e1
-          return NullAwareExpression(node.variable, body.otherwise);
+          return NullAwareExpression(node, node.variable, body.otherwise);
         }
       }
     }
@@ -137,11 +135,11 @@
 
 /// Check whether [node] is immediately guarded by a
 /// [ir.CheckLibraryIsLoaded], and hence the node is a deferred access.
-ir.LibraryDependency getDeferredImport(ir.TreeNode node) {
+ir.LibraryDependency? getDeferredImport(ir.TreeNode node) {
   // Note: this code relies on the CFE generating the code as we expect it here.
   // If one day we optimize away redundant CheckLibraryIsLoaded instructions,
   // we'd need to derive this information directly from the CFE (See #35005),
-  ir.TreeNode parent = node.parent;
+  ir.TreeNode? parent = node.parent;
 
   // TODO(sigmund): remove when CFE generates the correct tree (#35320). For
   // instance, it currently generates
@@ -160,7 +158,7 @@
         parent is ir.InstanceGetterInvocation ||
         parent is ir.DynamicInvocation ||
         parent is ir.FunctionInvocation) {
-      parent = parent.parent;
+      parent = parent!.parent;
     }
   }
 
@@ -177,8 +175,8 @@
   const _FreeVariableVisitor();
 
   bool visit(ir.DartType type) {
-    if (type != null) return type.accept(this);
-    return false;
+    assert(type as dynamic != null); // TODO(48820): Remove.
+    return type.accept(this);
   }
 
   bool visitList(List<ir.DartType> types) {
@@ -265,15 +263,15 @@
     importUri.path
         .contains('native_null_assertions/web_library_interfaces.dart');
 
-bool nodeIsInWebLibrary(ir.TreeNode node) {
+bool nodeIsInWebLibrary(ir.TreeNode? node) {
   if (node == null) return false;
   if (node is ir.Library) return _isWebLibrary(node.importUri);
   return nodeIsInWebLibrary(node.parent);
 }
 
 bool memberEntityIsInWebLibrary(MemberEntity entity) {
-  var importUri = entity?.library?.canonicalUri;
-  if (importUri == null) return false;
+  var importUri = entity.library.canonicalUri;
+  assert(importUri as dynamic != null); // TODO(48820): Remove.
   return _isWebLibrary(importUri);
 }
 
@@ -285,7 +283,7 @@
 ///
 /// See [ir.ProcedureStubKind.ConcreteMixinStub] for why concrete mixin stubs
 /// are inserted in the first place.
-ir.Member getEffectiveSuperTarget(ir.Member target) {
+ir.Member? getEffectiveSuperTarget(ir.Member? target) {
   if (target is ir.Procedure) {
     if (target.stubKind == ir.ProcedureStubKind.ConcreteMixinStub) {
       return getEffectiveSuperTarget(target.stubTarget);