Version 2.18.0-231.0.dev

Merge commit 'ff03ff9f77b327cfd0e97ff88da3654e960191a5' into 'dev'
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5139f56..34479e4 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -196,7 +196,7 @@
 * `dart pub outdated` now shows which of your dependencies are discontinued.
 * `dart pub publish` will now list all the files it is about to publish.
 
-## 2.17.4 - 2022-06-20
+## 2.17.5 - 2022-06-22
 
 This is a patch release that fixes:
 
diff --git a/pkg/compiler/lib/src/js_backend/annotations.dart b/pkg/compiler/lib/src/js_backend/annotations.dart
index 7fc51bc..1736e2a 100644
--- a/pkg/compiler/lib/src/js_backend/annotations.dart
+++ b/pkg/compiler/lib/src/js_backend/annotations.dart
@@ -114,6 +114,18 @@
       17, 'index-bounds:check',
       forFunctionsOnly: false, internalOnly: false);
 
+  /// Annotation for a `late` field to omit the checks on the late field. The
+  /// annotation is not restricted to a field since it is copied from the field
+  /// to the getter and setter.
+  // TODO(45682): Make this annotation apply to local and static late variables.
+  static const PragmaAnnotation lateTrust = PragmaAnnotation(18, 'late:trust');
+
+  /// Annotation for a `late` field to perform the checks on the late field. The
+  /// annotation is not restricted to a field since it is copied from the field
+  /// to the getter and setter.
+  // TODO(45682): Make this annotation apply to local and static late variables.
+  static const PragmaAnnotation lateCheck = PragmaAnnotation(19, 'late:check');
+
   static const List<PragmaAnnotation> values = [
     noInline,
     tryInline,
@@ -133,6 +145,8 @@
     downcastCheck,
     indexBoundsTrust,
     indexBoundsCheck,
+    lateTrust,
+    lateCheck,
   ];
 
   static const Map<PragmaAnnotation, Set<PragmaAnnotation>> implies = {
@@ -150,6 +164,8 @@
     downcastCheck: {downcastTrust},
     asTrust: {asCheck},
     asCheck: {asTrust},
+    lateTrust: {lateCheck},
+    lateCheck: {lateTrust},
   };
   static const Map<PragmaAnnotation, Set<PragmaAnnotation>> requires = {
     noThrows: {noInline},
@@ -317,12 +333,12 @@
   /// annotation.
   void forEachNoSideEffects(void f(FunctionEntity function));
 
-  /// What should the compiler do with parameter type assertions in [member].
+  /// What the compiler should do with parameter type assertions in [member].
   ///
   /// If [member] is `null`, the default policy is returned.
   CheckPolicy getParameterCheckPolicy(MemberEntity? member);
 
-  /// What should the compiler do with implicit downcasts in [member].
+  /// What the compiler should do with implicit downcasts in [member].
   ///
   /// If [member] is `null`, the default policy is returned.
   CheckPolicy getImplicitDowncastCheckPolicy(MemberEntity? member);
@@ -334,16 +350,20 @@
   /// If [member] is `null`, the default policy is returned.
   CheckPolicy getConditionCheckPolicy(MemberEntity? member);
 
-  /// Whether should the compiler do with explicit casts in [member].
+  /// What the compiler should do with explicit casts in [member].
   ///
   /// If [member] is `null`, the default policy is returned.
   CheckPolicy getExplicitCastCheckPolicy(MemberEntity? member);
 
-  /// What should the compiler do with index bounds checks `[]`, `[]=` and
+  /// What the compiler should do with index bounds checks `[]`, `[]=` and
   /// `removeLast()` operations in the body of [member].
   ///
   /// If [member] is `null`, the default policy is returned.
   CheckPolicy getIndexBoundsCheckPolicy(MemberEntity? member);
+
+  /// What the compiler should do with late field checks in the body of
+  /// [member]. [member] is usually the getter or setter for a late field.
+  CheckPolicy getLateVariableCheckPolicy(MemberEntity member);
 }
 
 class AnnotationsDataImpl implements AnnotationsData {
@@ -356,6 +376,7 @@
   final CheckPolicy _defaultConditionCheckPolicy;
   final CheckPolicy _defaultExplicitCastCheckPolicy;
   final CheckPolicy _defaultIndexBoundsCheckPolicy;
+  final CheckPolicy _defaultLateVariableCheckPolicy;
   final bool _defaultDisableInlining;
   final Map<MemberEntity, EnumSet<PragmaAnnotation>> pragmaAnnotations;
 
@@ -368,6 +389,7 @@
             options.defaultExplicitCastCheckPolicy,
         this._defaultIndexBoundsCheckPolicy =
             options.defaultIndexBoundsCheckPolicy,
+        this._defaultLateVariableCheckPolicy = CheckPolicy.checked,
         this._defaultDisableInlining = options.disableInlining;
 
   factory AnnotationsDataImpl.readFromDataSource(
@@ -554,6 +576,20 @@
     }
     return _defaultIndexBoundsCheckPolicy;
   }
+
+  @override
+  CheckPolicy getLateVariableCheckPolicy(MemberEntity member) {
+    EnumSet<PragmaAnnotation>? annotations = pragmaAnnotations[member];
+    if (annotations != null) {
+      if (annotations.contains(PragmaAnnotation.lateTrust)) {
+        return CheckPolicy.trusted;
+      } else if (annotations.contains(PragmaAnnotation.lateCheck)) {
+        return CheckPolicy.checked;
+      }
+    }
+    // TODO(sra): Look for annotations on enclosing class and library.
+    return _defaultLateVariableCheckPolicy;
+  }
 }
 
 class AnnotationsDataBuilder {
diff --git a/pkg/compiler/lib/src/kernel/transformations/late_lowering.dart b/pkg/compiler/lib/src/kernel/transformations/late_lowering.dart
index 11cfe13..aecd53d 100644
--- a/pkg/compiler/lib/src/kernel/transformations/late_lowering.dart
+++ b/pkg/compiler/lib/src/kernel/transformations/late_lowering.dart
@@ -540,6 +540,7 @@
     // The initializer is copied from [field] to [getter] so we copy the
     // transformer flags to reflect whether the getter contains super calls.
     getter.transformerFlags = field.transformerFlags;
+    _copyAnnotations(getter, field);
     enclosingClass.addProcedure(getter);
 
     VariableDeclaration setterValue = VariableDeclaration('value', type: type)
@@ -593,12 +594,25 @@
           reference: field.setterReference)
         ..fileOffset = fileOffset
         ..isNonNullableByDefault = true;
+      _copyAnnotations(setter, field);
       enclosingClass.addProcedure(setter);
     }
 
     return backingField;
   }
 
+  void _copyAnnotations(Member target, Member source) {
+    for (final annotation in source.annotations) {
+      if (annotation is ConstantExpression) {
+        target.addAnnotation(
+            ConstantExpression(annotation.constant, annotation.type)
+              ..fileOffset = annotation.fileOffset);
+      } else {
+        throw StateError('Non-constant annotation on $source');
+      }
+    }
+  }
+
   TreeNode transformField(Field field, Member contextMember) {
     _contextMember = contextMember;
 
diff --git a/pkg/compiler/lib/src/ssa/builder.dart b/pkg/compiler/lib/src/ssa/builder.dart
index 41b6d82..2f79457 100644
--- a/pkg/compiler/lib/src/ssa/builder.dart
+++ b/pkg/compiler/lib/src/ssa/builder.dart
@@ -4957,7 +4957,10 @@
     HInstruction value = arguments[0];
     HInstruction name = options.omitLateNames ? null : arguments[1];
 
-    push(HLateReadCheck(value, name,
+    CheckPolicy policy = closedWorld.annotationsData
+        .getLateVariableCheckPolicy(_currentFrame.member);
+
+    push(HLateReadCheck(value, name, policy.isTrusted,
         _abstractValueDomain.excludeLateSentinel(value.instructionType))
       ..sourceInformation = sourceInformation);
   }
@@ -4979,7 +4982,11 @@
     HInstruction value = arguments[0];
     HInstruction name = options.omitLateNames ? null : arguments[1];
 
-    push(HLateWriteOnceCheck(value, name, _abstractValueDomain.dynamicType)
+    CheckPolicy policy = closedWorld.annotationsData
+        .getLateVariableCheckPolicy(_currentFrame.member);
+
+    push(HLateWriteOnceCheck(
+        value, name, policy.isTrusted, _abstractValueDomain.dynamicType)
       ..sourceInformation = sourceInformation);
   }
 
@@ -5000,7 +5007,11 @@
     HInstruction value = arguments[0];
     HInstruction name = options.omitLateNames ? null : arguments[1];
 
-    push(HLateInitializeOnceCheck(value, name, _abstractValueDomain.dynamicType)
+    CheckPolicy policy = closedWorld.annotationsData
+        .getLateVariableCheckPolicy(_currentFrame.member);
+
+    push(HLateInitializeOnceCheck(
+        value, name, policy.isTrusted, _abstractValueDomain.dynamicType)
       ..sourceInformation = sourceInformation);
   }
 
diff --git a/pkg/compiler/lib/src/ssa/codegen.dart b/pkg/compiler/lib/src/ssa/codegen.dart
index 718d79c..3e7e544 100644
--- a/pkg/compiler/lib/src/ssa/codegen.dart
+++ b/pkg/compiler/lib/src/ssa/codegen.dart
@@ -409,9 +409,12 @@
       assert(graph.isValid(), 'Graph not valid after ${phase.name}');
     }
 
+    // Remove trusted late checks first to uncover read-modify-write patterns in
+    // instruction selection.
+    runPhase(SsaTrustedLateCheckRemover(_abstractValueDomain));
     runPhase(SsaInstructionSelection(_options, _closedWorld));
     runPhase(SsaTypeKnownRemover());
-    runPhase(SsaTrustedCheckRemover(_options));
+    runPhase(SsaTrustedPrimitiveCheckRemover(_options));
     runPhase(SsaAssignmentChaining(_closedWorld));
     runPhase(SsaInstructionMerger(_abstractValueDomain, generateAtUseSite));
     runPhase(SsaConditionMerger(generateAtUseSite, controlFlowOperators));
diff --git a/pkg/compiler/lib/src/ssa/codegen_helpers.dart b/pkg/compiler/lib/src/ssa/codegen_helpers.dart
index dfc43d5..7adc686 100644
--- a/pkg/compiler/lib/src/ssa/codegen_helpers.dart
+++ b/pkg/compiler/lib/src/ssa/codegen_helpers.dart
@@ -404,10 +404,10 @@
 
 /// Remove [HPrimitiveCheck] instructions from the graph in '--trust-primitives'
 /// mode.
-class SsaTrustedCheckRemover extends HBaseVisitor with CodegenPhase {
+class SsaTrustedPrimitiveCheckRemover extends HBaseVisitor with CodegenPhase {
   final CompilerOptions _options;
 
-  SsaTrustedCheckRemover(this._options);
+  SsaTrustedPrimitiveCheckRemover(this._options);
 
   @override
   void visitGraph(HGraph graph) {
@@ -438,6 +438,56 @@
   }
 }
 
+/// Remove trusted late variable checks.
+class SsaTrustedLateCheckRemover extends HBaseVisitor with CodegenPhase {
+  final AbstractValueDomain _abstractValueDomain;
+
+  SsaTrustedLateCheckRemover(this._abstractValueDomain);
+
+  @override
+  void visitGraph(HGraph graph) {
+    visitDominatorTree(graph);
+  }
+
+  @override
+  void visitBasicBlock(HBasicBlock block) {
+    HInstruction instruction = block.first;
+    while (instruction != null) {
+      HInstruction next = instruction.next;
+      instruction.accept(this);
+      instruction = next;
+    }
+  }
+
+  @override
+  void visitLateCheck(HLateCheck instruction) {
+    if (!instruction.isTrusted) return;
+    final inputs = instruction.inputs.toList();
+    instruction.block.rewrite(instruction, instruction.checkedInput);
+    instruction.block.remove(instruction);
+    // TODO(sra): There might be a unused name.
+
+    // Remove pure unused inputs.
+    for (HInstruction input in inputs) {
+      if (input.usedBy.isNotEmpty) continue;
+      HBasicBlock block = input.block;
+      if (block == null) continue; // Already removed.
+      if (input.isPure(_abstractValueDomain)) {
+        // Special cases that are removed properly by other phases.
+        if (input is HParameterValue) continue;
+        if (input is HLocalValue) continue;
+        if (input is HPhi) continue;
+        block.remove(input);
+        continue;
+      }
+      if (input is HFieldGet) {
+        if (input.canThrow(_abstractValueDomain)) continue;
+        block.remove(input);
+      }
+    }
+  }
+}
+
 /// Use the result of static and field assignments where it is profitable to use
 /// the result of the assignment instead of the value.
 ///
diff --git a/pkg/compiler/lib/src/ssa/nodes.dart b/pkg/compiler/lib/src/ssa/nodes.dart
index b9c10ba..50b2f2e 100644
--- a/pkg/compiler/lib/src/ssa/nodes.dart
+++ b/pkg/compiler/lib/src/ssa/nodes.dart
@@ -594,13 +594,14 @@
   visitBoolConversion(HBoolConversion node) => visitCheck(node);
   @override
   visitNullCheck(HNullCheck node) => visitCheck(node);
+  visitLateCheck(HLateCheck node) => visitCheck(node);
   @override
-  visitLateReadCheck(HLateReadCheck node) => visitCheck(node);
+  visitLateReadCheck(HLateReadCheck node) => visitLateCheck(node);
   @override
-  visitLateWriteOnceCheck(HLateWriteOnceCheck node) => visitCheck(node);
+  visitLateWriteOnceCheck(HLateWriteOnceCheck node) => visitLateCheck(node);
   @override
   visitLateInitializeOnceCheck(HLateInitializeOnceCheck node) =>
-      visitCheck(node);
+      visitLateCheck(node);
   @override
   visitPrimitiveCheck(HPrimitiveCheck node) => visitCheck(node);
   @override
@@ -3702,7 +3703,12 @@
 /// A check for a late sentinel to determine if a late field may be read from or
 /// written to.
 abstract class HLateCheck extends HCheck {
-  HLateCheck(HInstruction input, HInstruction /*?*/ name, AbstractValue type)
+  // Checks may be 'trusted' and result in no runtime check. This is done by
+  // compiling with the checks in place and removing them after optimizations.
+  final bool isTrusted;
+
+  HLateCheck(HInstruction input, HInstruction /*?*/ name, this.isTrusted,
+      AbstractValue type)
       : super([input, if (name != null) name], type);
 
   bool get hasName => inputs.length > 1;
@@ -3721,8 +3727,9 @@
 
 /// A check that a late field has been initialized and can therefore be read.
 class HLateReadCheck extends HLateCheck {
-  HLateReadCheck(HInstruction input, HInstruction name, AbstractValue type)
-      : super(input, name, type);
+  HLateReadCheck(
+      HInstruction input, HInstruction name, bool isTrusted, AbstractValue type)
+      : super(input, name, isTrusted, type);
 
   @override
   accept(HVisitor visitor) => visitor.visitLateReadCheck(this);
@@ -3734,7 +3741,7 @@
   bool typeEquals(HInstruction other) => other is HLateReadCheck;
 
   @override
-  bool dataEquals(HLateReadCheck other) => true;
+  bool dataEquals(HLateReadCheck other) => isTrusted == other.isTrusted;
 
   bool isRedundant(JClosedWorld closedWorld) {
     AbstractValueDomain abstractValueDomain = closedWorld.abstractValueDomain;
@@ -3755,8 +3762,9 @@
 /// is that the latter occurs on writes performed as part of the initializer
 /// expression.
 class HLateWriteOnceCheck extends HLateCheck {
-  HLateWriteOnceCheck(HInstruction input, HInstruction name, AbstractValue type)
-      : super(input, name, type);
+  HLateWriteOnceCheck(
+      HInstruction input, HInstruction name, bool isTrusted, AbstractValue type)
+      : super(input, name, isTrusted, type);
 
   @override
   accept(HVisitor visitor) => visitor.visitLateWriteOnceCheck(this);
@@ -3768,7 +3776,7 @@
   bool typeEquals(HInstruction other) => other is HLateWriteOnceCheck;
 
   @override
-  bool dataEquals(HLateWriteOnceCheck other) => true;
+  bool dataEquals(HLateWriteOnceCheck other) => isTrusted == other.isTrusted;
 
   bool isRedundant(JClosedWorld closedWorld) {
     AbstractValueDomain abstractValueDomain = closedWorld.abstractValueDomain;
@@ -3790,8 +3798,8 @@
 /// expression.
 class HLateInitializeOnceCheck extends HLateCheck {
   HLateInitializeOnceCheck(
-      HInstruction input, HInstruction name, AbstractValue type)
-      : super(input, name, type);
+      HInstruction input, HInstruction name, bool isTrusted, AbstractValue type)
+      : super(input, name, isTrusted, type);
 
   @override
   accept(HVisitor visitor) => visitor.visitLateInitializeOnceCheck(this);
@@ -3803,7 +3811,8 @@
   bool typeEquals(HInstruction other) => other is HLateInitializeOnceCheck;
 
   @override
-  bool dataEquals(HLateInitializeOnceCheck other) => true;
+  bool dataEquals(HLateInitializeOnceCheck other) =>
+      isTrusted == other.isTrusted;
 
   bool isRedundant(JClosedWorld closedWorld) {
     AbstractValueDomain abstractValueDomain = closedWorld.abstractValueDomain;
diff --git a/pkg/compiler/lib/src/ssa/tracer.dart b/pkg/compiler/lib/src/ssa/tracer.dart
index f04fe16..5f7a465 100644
--- a/pkg/compiler/lib/src/ssa/tracer.dart
+++ b/pkg/compiler/lib/src/ssa/tracer.dart
@@ -670,22 +670,25 @@
   @override
   String visitLateReadCheck(HLateReadCheck node) {
     String checkedInput = temporaryId(node.checkedInput);
+    String trust = node.isTrusted ? '.trusted' : '';
     String comment = node.hasName ? "(${temporaryId(node.name)})" : "";
-    return "LateReadCheck$comment: $checkedInput";
+    return "LateReadCheck$trust$comment: $checkedInput";
   }
 
   @override
   String visitLateWriteOnceCheck(HLateWriteOnceCheck node) {
     String checkedInput = temporaryId(node.checkedInput);
+    String trust = node.isTrusted ? '.trusted' : '';
     String comment = node.hasName ? "(${temporaryId(node.name)})" : "";
-    return "LateWriteOnceCheck$comment: $checkedInput";
+    return "LateWriteOnceCheck$trust$comment: $checkedInput";
   }
 
   @override
   String visitLateInitializeOnceCheck(HLateInitializeOnceCheck node) {
     String checkedInput = temporaryId(node.checkedInput);
+    String trust = node.isTrusted ? '.trusted' : '';
     String comment = node.hasName ? "(${temporaryId(node.name)})" : "";
-    return "LateInitializeOnceCheck$comment: $checkedInput";
+    return "LateInitializeOnceCheck$trust$comment: $checkedInput";
   }
 
   @override
diff --git a/pkg/front_end/testcases/dart2js/late_fields_with_annotation.dart b/pkg/front_end/testcases/dart2js/late_fields_with_annotation.dart
new file mode 100644
index 0000000..f425129a
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/late_fields_with_annotation.dart
@@ -0,0 +1,50 @@
+// Copyright (c) 2022, 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.
+
+void main() {
+  testUninitializedNonFinalInstanceField();
+  testUninitializedFinalInstanceField();
+  testInitializedNonFinalInstanceField();
+  testInitializedFinalInstanceField();
+}
+
+class C {
+  @pragma('dart2js:late:trust')
+  late int a;
+
+  @pragma('dart2js:late:check')
+  late final int b;
+
+  @pragma('dart2js:late:trust')
+  @pragma('dart2js:tryInline')
+  late int c = -1;
+
+  @pragma('dart2js:late:check')
+  @pragma('dart2js:noInline')
+  late final int d = -1;
+}
+
+var c = C();
+
+void testUninitializedNonFinalInstanceField() {
+  print(c.a);
+  c.a = 42;
+  print(c.a);
+}
+
+void testUninitializedFinalInstanceField() {
+  print(c.b);
+  c.b = 42;
+  print(c.b);
+}
+
+void testInitializedNonFinalInstanceField() {
+  print(c.c);
+  c.c = 42;
+  print(c.c);
+}
+
+void testInitializedFinalInstanceField() {
+  print(c.d);
+}
diff --git a/pkg/front_end/testcases/dart2js/late_fields_with_annotation.dart.strong.expect b/pkg/front_end/testcases/dart2js/late_fields_with_annotation.dart.strong.expect
new file mode 100644
index 0000000..da24f72
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/late_fields_with_annotation.dart.strong.expect
@@ -0,0 +1,64 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+  @#C3
+  late field core::int a;
+  @#C5
+  late final [setter] field core::int b;
+  @#C3
+  @#C7
+  late field core::int c = 1.{core::int::unary-}(){() → core::int};
+  @#C5
+  @#C9
+  late final field core::int d = 1.{core::int::unary-}(){() → core::int};
+  synthetic constructor •() → self::C
+    : super core::Object::•()
+    ;
+  static method _#new#tearOff() → self::C
+    return new self::C::•();
+}
+static field self::C c = new self::C::•();
+static method main() → void {
+  self::testUninitializedNonFinalInstanceField();
+  self::testUninitializedFinalInstanceField();
+  self::testInitializedNonFinalInstanceField();
+  self::testInitializedFinalInstanceField();
+}
+static method testUninitializedNonFinalInstanceField() → void {
+  core::print(self::c.{self::C::a}{core::int});
+  self::c.{self::C::a} = 42;
+  core::print(self::c.{self::C::a}{core::int});
+}
+static method testUninitializedFinalInstanceField() → void {
+  core::print(self::c.{self::C::b}{core::int});
+  self::c.{self::C::b} = 42;
+  core::print(self::c.{self::C::b}{core::int});
+}
+static method testInitializedNonFinalInstanceField() → void {
+  core::print(self::c.{self::C::c}{core::int});
+  self::c.{self::C::c} = 42;
+  core::print(self::c.{self::C::c}{core::int});
+}
+static method testInitializedFinalInstanceField() → void {
+  core::print(self::c.{self::C::d}{core::int});
+}
+
+constants  {
+  #C1 = "dart2js:late:trust"
+  #C2 = null
+  #C3 = core::pragma {name:#C1, options:#C2}
+  #C4 = "dart2js:late:check"
+  #C5 = core::pragma {name:#C4, options:#C2}
+  #C6 = "dart2js:tryInline"
+  #C7 = core::pragma {name:#C6, options:#C2}
+  #C8 = "dart2js:noInline"
+  #C9 = core::pragma {name:#C8, options:#C2}
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///late_fields_with_annotation.dart:
+- pragma._ (from org-dartlang-sdk:///lib/core/annotations.dart:188:9)
+- Object. (from org-dartlang-sdk:///lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/dart2js/late_fields_with_annotation.dart.strong.transformed.expect b/pkg/front_end/testcases/dart2js/late_fields_with_annotation.dart.strong.transformed.expect
new file mode 100644
index 0000000..25f45c8
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/late_fields_with_annotation.dart.strong.transformed.expect
@@ -0,0 +1,102 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:_late_helper" as _la;
+import "dart:_internal" as _in;
+
+class C extends core::Object {
+  field core::int _#C#a#A = _in::createSentinel<core::int>();
+  field core::int _#C#b#F = _in::createSentinel<core::int>();
+  field core::int _#C#c#AI = _in::createSentinel<core::int>();
+  field core::int _#C#d#FI = _in::createSentinel<core::int>();
+  synthetic constructor •() → self::C
+    : super core::Object::•()
+    ;
+  static method _#new#tearOff() → self::C
+    return new self::C::•();
+  @#C3
+  get a() → core::int
+    return _la::_lateReadCheck<core::int>(this.{self::C::_#C#a#A}{core::int}, "a");
+  @#C3
+  set a(core::int value) → void
+    this.{self::C::_#C#a#A} = value;
+  @#C5
+  get b() → core::int
+    return _la::_lateReadCheck<core::int>(this.{self::C::_#C#b#F}{core::int}, "b");
+  @#C5
+  set b(core::int value) → void {
+    _la::_lateWriteOnceCheck(this.{self::C::_#C#b#F}{core::int}, "b");
+    this.{self::C::_#C#b#F} = value;
+  }
+  @#C3
+  @#C7
+  get c() → core::int {
+    core::int value = this.{self::C::_#C#c#AI}{core::int};
+    if(_in::isSentinel(value))
+      value = this.{self::C::_#C#c#AI} = 1.{core::int::unary-}(){() → core::int};
+    return value;
+  }
+  @#C3
+  @#C7
+  set c(core::int value) → void
+    this.{self::C::_#C#c#AI} = value;
+  @#C5
+  @#C9
+  get d() → core::int {
+    core::int value = this.{self::C::_#C#d#FI}{core::int};
+    if(_in::isSentinel(value)) {
+      final core::int result = 1.{core::int::unary-}(){() → core::int};
+      _la::_lateInitializeOnceCheck(this.{self::C::_#C#d#FI}{core::int}, "d");
+      value = this.{self::C::_#C#d#FI} = result;
+    }
+    return value;
+  }
+}
+static field self::C c = new self::C::•();
+static method main() → void {
+  self::testUninitializedNonFinalInstanceField();
+  self::testUninitializedFinalInstanceField();
+  self::testInitializedNonFinalInstanceField();
+  self::testInitializedFinalInstanceField();
+}
+static method testUninitializedNonFinalInstanceField() → void {
+  core::print(self::c.{self::C::a}{core::int});
+  self::c.{self::C::a} = 42;
+  core::print(self::c.{self::C::a}{core::int});
+}
+static method testUninitializedFinalInstanceField() → void {
+  core::print(self::c.{self::C::b}{core::int});
+  self::c.{self::C::b} = 42;
+  core::print(self::c.{self::C::b}{core::int});
+}
+static method testInitializedNonFinalInstanceField() → void {
+  core::print(self::c.{self::C::c}{core::int});
+  self::c.{self::C::c} = 42;
+  core::print(self::c.{self::C::c}{core::int});
+}
+static method testInitializedFinalInstanceField() → void {
+  core::print(self::c.{self::C::d}{core::int});
+}
+
+constants  {
+  #C1 = "dart2js:late:trust"
+  #C2 = null
+  #C3 = core::pragma {name:#C1, options:#C2}
+  #C4 = "dart2js:late:check"
+  #C5 = core::pragma {name:#C4, options:#C2}
+  #C6 = "dart2js:tryInline"
+  #C7 = core::pragma {name:#C6, options:#C2}
+  #C8 = "dart2js:noInline"
+  #C9 = core::pragma {name:#C8, options:#C2}
+}
+
+Extra constant evaluation status:
+Evaluated: InstanceInvocation @ org-dartlang-testcase:///late_fields_with_annotation.dart:21:16 -> DoubleConstant(-1.0)
+Evaluated: InstanceInvocation @ org-dartlang-testcase:///late_fields_with_annotation.dart:25:22 -> DoubleConstant(-1.0)
+Extra constant evaluation: evaluated: 77, effectively constant: 2
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///late_fields_with_annotation.dart:
+- pragma._ (from org-dartlang-sdk:///lib/core/annotations.dart:188:9)
+- Object. (from org-dartlang-sdk:///lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/dart2js/late_fields_with_annotation.dart.textual_outline.expect b/pkg/front_end/testcases/dart2js/late_fields_with_annotation.dart.textual_outline.expect
new file mode 100644
index 0000000..be65036
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/late_fields_with_annotation.dart.textual_outline.expect
@@ -0,0 +1,20 @@
+void main() {}
+
+class C {
+  @pragma('dart2js:late:trust')
+  late int a;
+  @pragma('dart2js:late:check')
+  late final int b;
+  @pragma('dart2js:late:trust')
+  @pragma('dart2js:tryInline')
+  late int c = -1;
+  @pragma('dart2js:late:check')
+  @pragma('dart2js:noInline')
+  late final int d = -1;
+}
+
+var c = C();
+void testUninitializedNonFinalInstanceField() {}
+void testUninitializedFinalInstanceField() {}
+void testInitializedNonFinalInstanceField() {}
+void testInitializedFinalInstanceField() {}
diff --git a/pkg/front_end/testcases/dart2js/late_fields_with_annotation.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/dart2js/late_fields_with_annotation.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..6a154d0
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/late_fields_with_annotation.dart.textual_outline_modelled.expect
@@ -0,0 +1,19 @@
+class C {
+  @pragma('dart2js:late:check')
+  late final int b;
+  @pragma('dart2js:late:check')
+  @pragma('dart2js:noInline')
+  late final int d = -1;
+  @pragma('dart2js:late:trust')
+  late int a;
+  @pragma('dart2js:late:trust')
+  @pragma('dart2js:tryInline')
+  late int c = -1;
+}
+
+var c = C();
+void main() {}
+void testInitializedFinalInstanceField() {}
+void testInitializedNonFinalInstanceField() {}
+void testUninitializedFinalInstanceField() {}
+void testUninitializedNonFinalInstanceField() {}
diff --git a/pkg/front_end/testcases/dart2js/late_fields_with_annotation.dart.weak.expect b/pkg/front_end/testcases/dart2js/late_fields_with_annotation.dart.weak.expect
new file mode 100644
index 0000000..da24f72
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/late_fields_with_annotation.dart.weak.expect
@@ -0,0 +1,64 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+  @#C3
+  late field core::int a;
+  @#C5
+  late final [setter] field core::int b;
+  @#C3
+  @#C7
+  late field core::int c = 1.{core::int::unary-}(){() → core::int};
+  @#C5
+  @#C9
+  late final field core::int d = 1.{core::int::unary-}(){() → core::int};
+  synthetic constructor •() → self::C
+    : super core::Object::•()
+    ;
+  static method _#new#tearOff() → self::C
+    return new self::C::•();
+}
+static field self::C c = new self::C::•();
+static method main() → void {
+  self::testUninitializedNonFinalInstanceField();
+  self::testUninitializedFinalInstanceField();
+  self::testInitializedNonFinalInstanceField();
+  self::testInitializedFinalInstanceField();
+}
+static method testUninitializedNonFinalInstanceField() → void {
+  core::print(self::c.{self::C::a}{core::int});
+  self::c.{self::C::a} = 42;
+  core::print(self::c.{self::C::a}{core::int});
+}
+static method testUninitializedFinalInstanceField() → void {
+  core::print(self::c.{self::C::b}{core::int});
+  self::c.{self::C::b} = 42;
+  core::print(self::c.{self::C::b}{core::int});
+}
+static method testInitializedNonFinalInstanceField() → void {
+  core::print(self::c.{self::C::c}{core::int});
+  self::c.{self::C::c} = 42;
+  core::print(self::c.{self::C::c}{core::int});
+}
+static method testInitializedFinalInstanceField() → void {
+  core::print(self::c.{self::C::d}{core::int});
+}
+
+constants  {
+  #C1 = "dart2js:late:trust"
+  #C2 = null
+  #C3 = core::pragma {name:#C1, options:#C2}
+  #C4 = "dart2js:late:check"
+  #C5 = core::pragma {name:#C4, options:#C2}
+  #C6 = "dart2js:tryInline"
+  #C7 = core::pragma {name:#C6, options:#C2}
+  #C8 = "dart2js:noInline"
+  #C9 = core::pragma {name:#C8, options:#C2}
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///late_fields_with_annotation.dart:
+- pragma._ (from org-dartlang-sdk:///lib/core/annotations.dart:188:9)
+- Object. (from org-dartlang-sdk:///lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/dart2js/late_fields_with_annotation.dart.weak.modular.expect b/pkg/front_end/testcases/dart2js/late_fields_with_annotation.dart.weak.modular.expect
new file mode 100644
index 0000000..da24f72
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/late_fields_with_annotation.dart.weak.modular.expect
@@ -0,0 +1,64 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+  @#C3
+  late field core::int a;
+  @#C5
+  late final [setter] field core::int b;
+  @#C3
+  @#C7
+  late field core::int c = 1.{core::int::unary-}(){() → core::int};
+  @#C5
+  @#C9
+  late final field core::int d = 1.{core::int::unary-}(){() → core::int};
+  synthetic constructor •() → self::C
+    : super core::Object::•()
+    ;
+  static method _#new#tearOff() → self::C
+    return new self::C::•();
+}
+static field self::C c = new self::C::•();
+static method main() → void {
+  self::testUninitializedNonFinalInstanceField();
+  self::testUninitializedFinalInstanceField();
+  self::testInitializedNonFinalInstanceField();
+  self::testInitializedFinalInstanceField();
+}
+static method testUninitializedNonFinalInstanceField() → void {
+  core::print(self::c.{self::C::a}{core::int});
+  self::c.{self::C::a} = 42;
+  core::print(self::c.{self::C::a}{core::int});
+}
+static method testUninitializedFinalInstanceField() → void {
+  core::print(self::c.{self::C::b}{core::int});
+  self::c.{self::C::b} = 42;
+  core::print(self::c.{self::C::b}{core::int});
+}
+static method testInitializedNonFinalInstanceField() → void {
+  core::print(self::c.{self::C::c}{core::int});
+  self::c.{self::C::c} = 42;
+  core::print(self::c.{self::C::c}{core::int});
+}
+static method testInitializedFinalInstanceField() → void {
+  core::print(self::c.{self::C::d}{core::int});
+}
+
+constants  {
+  #C1 = "dart2js:late:trust"
+  #C2 = null
+  #C3 = core::pragma {name:#C1, options:#C2}
+  #C4 = "dart2js:late:check"
+  #C5 = core::pragma {name:#C4, options:#C2}
+  #C6 = "dart2js:tryInline"
+  #C7 = core::pragma {name:#C6, options:#C2}
+  #C8 = "dart2js:noInline"
+  #C9 = core::pragma {name:#C8, options:#C2}
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///late_fields_with_annotation.dart:
+- pragma._ (from org-dartlang-sdk:///lib/core/annotations.dart:188:9)
+- Object. (from org-dartlang-sdk:///lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/dart2js/late_fields_with_annotation.dart.weak.outline.expect b/pkg/front_end/testcases/dart2js/late_fields_with_annotation.dart.weak.outline.expect
new file mode 100644
index 0000000..1142ec6
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/late_fields_with_annotation.dart.weak.outline.expect
@@ -0,0 +1,41 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+  @core::pragma::_("dart2js:late:trust")
+  late field core::int a;
+  @core::pragma::_("dart2js:late:check")
+  late final [setter] field core::int b;
+  @core::pragma::_("dart2js:late:trust")
+  @core::pragma::_("dart2js:tryInline")
+  late field core::int c;
+  @core::pragma::_("dart2js:late:check")
+  @core::pragma::_("dart2js:noInline")
+  late final field core::int d;
+  synthetic constructor •() → self::C
+    ;
+  static method _#new#tearOff() → self::C
+    return new self::C::•();
+}
+static field self::C c;
+static method main() → void
+  ;
+static method testUninitializedNonFinalInstanceField() → void
+  ;
+static method testUninitializedFinalInstanceField() → void
+  ;
+static method testInitializedNonFinalInstanceField() → void
+  ;
+static method testInitializedFinalInstanceField() → void
+  ;
+
+
+Extra constant evaluation status:
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///late_fields_with_annotation.dart:13:4 -> InstanceConstant(const pragma{pragma.name: "dart2js:late:trust", pragma.options: null})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///late_fields_with_annotation.dart:16:4 -> InstanceConstant(const pragma{pragma.name: "dart2js:late:check", pragma.options: null})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///late_fields_with_annotation.dart:19:4 -> InstanceConstant(const pragma{pragma.name: "dart2js:late:trust", pragma.options: null})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///late_fields_with_annotation.dart:20:4 -> InstanceConstant(const pragma{pragma.name: "dart2js:tryInline", pragma.options: null})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///late_fields_with_annotation.dart:23:4 -> InstanceConstant(const pragma{pragma.name: "dart2js:late:check", pragma.options: null})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///late_fields_with_annotation.dart:24:4 -> InstanceConstant(const pragma{pragma.name: "dart2js:noInline", pragma.options: null})
+Extra constant evaluation: evaluated: 7, effectively constant: 6
diff --git a/pkg/front_end/testcases/dart2js/late_fields_with_annotation.dart.weak.transformed.expect b/pkg/front_end/testcases/dart2js/late_fields_with_annotation.dart.weak.transformed.expect
new file mode 100644
index 0000000..25f45c8
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/late_fields_with_annotation.dart.weak.transformed.expect
@@ -0,0 +1,102 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:_late_helper" as _la;
+import "dart:_internal" as _in;
+
+class C extends core::Object {
+  field core::int _#C#a#A = _in::createSentinel<core::int>();
+  field core::int _#C#b#F = _in::createSentinel<core::int>();
+  field core::int _#C#c#AI = _in::createSentinel<core::int>();
+  field core::int _#C#d#FI = _in::createSentinel<core::int>();
+  synthetic constructor •() → self::C
+    : super core::Object::•()
+    ;
+  static method _#new#tearOff() → self::C
+    return new self::C::•();
+  @#C3
+  get a() → core::int
+    return _la::_lateReadCheck<core::int>(this.{self::C::_#C#a#A}{core::int}, "a");
+  @#C3
+  set a(core::int value) → void
+    this.{self::C::_#C#a#A} = value;
+  @#C5
+  get b() → core::int
+    return _la::_lateReadCheck<core::int>(this.{self::C::_#C#b#F}{core::int}, "b");
+  @#C5
+  set b(core::int value) → void {
+    _la::_lateWriteOnceCheck(this.{self::C::_#C#b#F}{core::int}, "b");
+    this.{self::C::_#C#b#F} = value;
+  }
+  @#C3
+  @#C7
+  get c() → core::int {
+    core::int value = this.{self::C::_#C#c#AI}{core::int};
+    if(_in::isSentinel(value))
+      value = this.{self::C::_#C#c#AI} = 1.{core::int::unary-}(){() → core::int};
+    return value;
+  }
+  @#C3
+  @#C7
+  set c(core::int value) → void
+    this.{self::C::_#C#c#AI} = value;
+  @#C5
+  @#C9
+  get d() → core::int {
+    core::int value = this.{self::C::_#C#d#FI}{core::int};
+    if(_in::isSentinel(value)) {
+      final core::int result = 1.{core::int::unary-}(){() → core::int};
+      _la::_lateInitializeOnceCheck(this.{self::C::_#C#d#FI}{core::int}, "d");
+      value = this.{self::C::_#C#d#FI} = result;
+    }
+    return value;
+  }
+}
+static field self::C c = new self::C::•();
+static method main() → void {
+  self::testUninitializedNonFinalInstanceField();
+  self::testUninitializedFinalInstanceField();
+  self::testInitializedNonFinalInstanceField();
+  self::testInitializedFinalInstanceField();
+}
+static method testUninitializedNonFinalInstanceField() → void {
+  core::print(self::c.{self::C::a}{core::int});
+  self::c.{self::C::a} = 42;
+  core::print(self::c.{self::C::a}{core::int});
+}
+static method testUninitializedFinalInstanceField() → void {
+  core::print(self::c.{self::C::b}{core::int});
+  self::c.{self::C::b} = 42;
+  core::print(self::c.{self::C::b}{core::int});
+}
+static method testInitializedNonFinalInstanceField() → void {
+  core::print(self::c.{self::C::c}{core::int});
+  self::c.{self::C::c} = 42;
+  core::print(self::c.{self::C::c}{core::int});
+}
+static method testInitializedFinalInstanceField() → void {
+  core::print(self::c.{self::C::d}{core::int});
+}
+
+constants  {
+  #C1 = "dart2js:late:trust"
+  #C2 = null
+  #C3 = core::pragma {name:#C1, options:#C2}
+  #C4 = "dart2js:late:check"
+  #C5 = core::pragma {name:#C4, options:#C2}
+  #C6 = "dart2js:tryInline"
+  #C7 = core::pragma {name:#C6, options:#C2}
+  #C8 = "dart2js:noInline"
+  #C9 = core::pragma {name:#C8, options:#C2}
+}
+
+Extra constant evaluation status:
+Evaluated: InstanceInvocation @ org-dartlang-testcase:///late_fields_with_annotation.dart:21:16 -> DoubleConstant(-1.0)
+Evaluated: InstanceInvocation @ org-dartlang-testcase:///late_fields_with_annotation.dart:25:22 -> DoubleConstant(-1.0)
+Extra constant evaluation: evaluated: 77, effectively constant: 2
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///late_fields_with_annotation.dart:
+- pragma._ (from org-dartlang-sdk:///lib/core/annotations.dart:188:9)
+- Object. (from org-dartlang-sdk:///lib/core/object.dart:25:9)
diff --git a/tools/VERSION b/tools/VERSION
index 7fe1fe7..580e6a0 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 18
 PATCH 0
-PRERELEASE 230
+PRERELEASE 231
 PRERELEASE_PATCH 0
\ No newline at end of file