Fix nullability of inferred dynamic types

Change-Id: Ib27c5ade4a57bbfa73c528adbafaaa19be53c97c
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/102301
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
diff --git a/pkg/analysis_server/lib/src/nullability/constraint_variable_gatherer.dart b/pkg/analysis_server/lib/src/nullability/constraint_variable_gatherer.dart
index ea6265c..c7d0d5f 100644
--- a/pkg/analysis_server/lib/src/nullability/constraint_variable_gatherer.dart
+++ b/pkg/analysis_server/lib/src/nullability/constraint_variable_gatherer.dart
@@ -8,6 +8,7 @@
 import 'package:analysis_server/src/nullability/nullability_graph.dart';
 import 'package:analysis_server/src/nullability/nullability_node.dart';
 import 'package:analysis_server/src/nullability/transitional_api.dart';
+import 'package:analysis_server/src/nullability/unit_propagation.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/visitor.dart';
 import 'package:analyzer/dart/element/element.dart';
@@ -56,7 +57,7 @@
         ? new DecoratedType(
             DynamicTypeImpl.instance,
             NullabilityNode.forInferredDynamicType(
-                _graph, enclosingNode.offset),
+                _graph, _variables.constraints, enclosingNode.offset),
             _graph)
         : type.accept(this);
   }
@@ -192,6 +193,10 @@
 /// ([ConstraintVariableGatherer], which finds all the variables that need to be
 /// constrained).
 abstract class VariableRecorder {
+  /// Gets the [Constraints] object currently in use.  Note: this will go away
+  /// when we stop using constraint variables for migration.
+  Constraints get constraints;
+
   /// Associates decorated type information with the given [element].
   void recordDecoratedElementType(Element element, DecoratedType type);
 
diff --git a/pkg/analysis_server/lib/src/nullability/nullability_node.dart b/pkg/analysis_server/lib/src/nullability/nullability_node.dart
index cc5ee45..b5c809d 100644
--- a/pkg/analysis_server/lib/src/nullability/nullability_node.dart
+++ b/pkg/analysis_server/lib/src/nullability/nullability_node.dart
@@ -46,9 +46,10 @@
   /// TODO(paulberry): this should go away; we should decorate the actual
   /// inferred type rather than assuming `dynamic`.
   factory NullabilityNode.forInferredDynamicType(
-      NullabilityGraph graph, int offset) {
+      NullabilityGraph graph, Constraints constraints, int offset) {
     var node = _NullabilityNodeSimple(
         TypeIsNullable(null), 'inferredDynamic($offset)');
+    constraints.record([], node._nullable);
     graph.connect(NullabilityNode.always, node);
     return node;
   }
diff --git a/pkg/analysis_server/lib/src/nullability/transitional_api.dart b/pkg/analysis_server/lib/src/nullability/transitional_api.dart
index ffbad45..90c0fc7 100644
--- a/pkg/analysis_server/lib/src/nullability/transitional_api.dart
+++ b/pkg/analysis_server/lib/src/nullability/transitional_api.dart
@@ -148,7 +148,7 @@
 
   final Variables _variables;
 
-  final _constraints = Solver();
+  final Solver _constraints;
 
   final NullabilityGraph _graph;
 
@@ -162,10 +162,11 @@
       {bool permissive: false,
       NullabilityMigrationAssumptions assumptions:
           const NullabilityMigrationAssumptions()})
-      : this._(permissive, assumptions, NullabilityGraph());
+      : this._(permissive, assumptions, NullabilityGraph(), Solver());
 
-  NullabilityMigration._(this._permissive, this.assumptions, this._graph)
-      : _variables = Variables(_graph);
+  NullabilityMigration._(
+      this._permissive, this.assumptions, this._graph, this._constraints)
+      : _variables = Variables(_graph, _constraints);
 
   Map<Source, List<PotentialModification>> finish() {
     _constraints.applyHeuristics();
@@ -275,7 +276,10 @@
 
   final NullabilityGraph _graph;
 
-  Variables(this._graph);
+  @override
+  final Constraints constraints;
+
+  Variables(this._graph, this.constraints);
 
   @override
   DecoratedType decoratedElementType(Element element, {bool create: false}) =>
diff --git a/pkg/analysis_server/test/src/nullability/migration_visitor_test.dart b/pkg/analysis_server/test/src/nullability/migration_visitor_test.dart
index 88cccb6..d4e2e9f 100644
--- a/pkg/analysis_server/test/src/nullability/migration_visitor_test.dart
+++ b/pkg/analysis_server/test/src/nullability/migration_visitor_test.dart
@@ -29,9 +29,6 @@
 
 @reflectiveTest
 class ConstraintGathererTest extends ConstraintsTestBase {
-  @override
-  final _Constraints constraints = _Constraints();
-
   void assertConditional(
       NullabilityNode node, NullabilityNode left, NullabilityNode right) {
     var conditionalNode = node as NullabilityNodeForLUB;
@@ -793,8 +790,6 @@
 }
 
 abstract class ConstraintsTestBase extends MigrationVisitorTestBase {
-  Constraints get constraints;
-
   /// Analyzes the given source code, producing constraint variables and
   /// constraints for it.
   @override
@@ -935,9 +930,12 @@
 
   final NullabilityGraph graph;
 
-  MigrationVisitorTestBase() : this._(NullabilityGraph());
+  final _Constraints constraints;
 
-  MigrationVisitorTestBase._(this.graph) : _variables = _Variables(graph);
+  MigrationVisitorTestBase() : this._(NullabilityGraph(), _Constraints());
+
+  MigrationVisitorTestBase._(this.graph, this.constraints)
+      : _variables = _Variables(graph, constraints);
 
   TypeProvider get typeProvider => testAnalysisResult.typeProvider;
 
@@ -1027,7 +1025,8 @@
 
   final _possiblyOptional = <DefaultFormalParameter, NullabilityNode>{};
 
-  _Variables(NullabilityGraph graph) : super(graph);
+  _Variables(NullabilityGraph graph, Constraints constraints)
+      : super(graph, constraints);
 
   /// Gets the [ExpressionChecks] associated with the given [expression].
   ExpressionChecks checkExpression(Expression expression) =>