Version 2.15.0-176.0.dev

Merge commit 'f4180854c71cbec340f66fd1c605dc58f70ea38e' into 'dev'
diff --git a/pkg/analyzer/lib/src/dart/constant/constant_verifier.dart b/pkg/analyzer/lib/src/dart/constant/constant_verifier.dart
index 6adbb19..4a5e452 100644
--- a/pkg/analyzer/lib/src/dart/constant/constant_verifier.dart
+++ b/pkg/analyzer/lib/src/dart/constant/constant_verifier.dart
@@ -445,7 +445,7 @@
   /// Check if the object [obj] matches the type [type] according to runtime
   /// type checking rules.
   bool _runtimeTypeMatch(DartObjectImpl obj, DartType type) {
-    return _evaluationEngine.runtimeTypeMatch(_currentLibrary, obj, type);
+    return _currentLibrary.typeSystem.runtimeTypeMatch(obj, type);
   }
 
   /// Validate that the given expression is a compile time constant. Return the
diff --git a/pkg/analyzer/lib/src/dart/constant/evaluation.dart b/pkg/analyzer/lib/src/dart/constant/evaluation.dart
index ac84337..70f5d10 100644
--- a/pkg/analyzer/lib/src/dart/constant/evaluation.dart
+++ b/pkg/analyzer/lib/src/dart/constant/evaluation.dart
@@ -30,32 +30,6 @@
 /// Helper class encapsulating the methods for evaluating constants and
 /// constant instance creation expressions.
 class ConstantEvaluationEngine {
-  /// Parameter to "fromEnvironment" methods that denotes the default value.
-  static const String _DEFAULT_VALUE_PARAM = "defaultValue";
-
-  /// Source of RegExp matching declarable operator names.
-  /// From sdk/lib/internal/symbol.dart.
-  static const String _OPERATOR_RE =
-      "(?:[\\-+*/%&|^]|\\[\\]=?|==|~/?|<[<=]?|>[>=]?|unary-)";
-
-  /// Source of RegExp matching Dart reserved words.
-  /// From sdk/lib/internal/symbol.dart.
-  static const String _RESERVED_WORD_RE =
-      "(?:assert|break|c(?:a(?:se|tch)|lass|on(?:st|tinue))|"
-      "d(?:efault|o)|e(?:lse|num|xtends)|f(?:alse|inal(?:ly)?|or)|"
-      "i[fns]|n(?:ew|ull)|ret(?:hrow|urn)|s(?:uper|witch)|t(?:h(?:is|row)|"
-      "r(?:ue|y))|v(?:ar|oid)|w(?:hile|ith))";
-
-  /// Source of RegExp matching any public identifier.
-  /// From sdk/lib/internal/symbol.dart.
-  static const String _PUBLIC_IDENTIFIER_RE =
-      "(?!$_RESERVED_WORD_RE\\b(?!\\\$))[a-zA-Z\$][\\w\$]*";
-
-  /// RegExp that validates a non-empty non-private symbol.
-  /// From sdk/lib/internal/symbol.dart.
-  static final RegExp _PUBLIC_SYMBOL_PATTERN = RegExp(
-      "^(?:$_OPERATOR_RE\$|$_PUBLIC_IDENTIFIER_RE(?:=?\$|[.](?!\$)))+?\$");
-
   /// The set of variables declared on the command line using '-D'.
   final DeclaredVariables _declaredVariables;
 
@@ -72,76 +46,6 @@
   })  : _declaredVariables = declaredVariables,
         _isNonNullableByDefault = isNonNullableByDefault;
 
-  /// Check that the arguments to a call to fromEnvironment() are correct. The
-  /// [arguments] are the AST nodes of the arguments. The [argumentValues] are
-  /// the values of the unnamed arguments. The [namedArgumentValues] are the
-  /// values of the named arguments. The [expectedDefaultValueType] is the
-  /// allowed type of the "defaultValue" parameter (if present). Note:
-  /// "defaultValue" is always allowed to be null. Return `true` if the
-  /// arguments are correct, `false` if there is an error.
-  bool checkFromEnvironmentArguments(
-      LibraryElementImpl library,
-      List<Expression> arguments,
-      List<DartObjectImpl?> argumentValues,
-      Map<String, DartObjectImpl> namedArgumentValues,
-      InterfaceType expectedDefaultValueType) {
-    int argumentCount = arguments.length;
-    if (argumentCount < 1 || argumentCount > 2) {
-      return false;
-    }
-    if (arguments[0] is NamedExpression) {
-      return false;
-    }
-    if (argumentValues[0]!.type != library.typeProvider.stringType) {
-      return false;
-    }
-    if (argumentCount == 2) {
-      Expression secondArgument = arguments[1];
-      if (secondArgument is NamedExpression) {
-        if (!(secondArgument.name.label.name == _DEFAULT_VALUE_PARAM)) {
-          return false;
-        }
-        var defaultValueType = namedArgumentValues[_DEFAULT_VALUE_PARAM]!.type;
-        if (!(defaultValueType == expectedDefaultValueType ||
-            defaultValueType == library.typeProvider.nullType)) {
-          return false;
-        }
-      } else {
-        return false;
-      }
-    }
-    return true;
-  }
-
-  /// Check that the arguments to a call to Symbol() are correct. The
-  /// [arguments] are the AST nodes of the arguments. The [argumentValues] are
-  /// the values of the unnamed arguments. The [namedArgumentValues] are the
-  /// values of the named arguments. Return `true` if the arguments are correct,
-  /// `false` if there is an error.
-  bool checkSymbolArguments(
-      LibraryElementImpl library,
-      List<Expression> arguments,
-      List<DartObjectImpl?> argumentValues,
-      Map<String, DartObjectImpl> namedArgumentValues) {
-    if (arguments.length != 1) {
-      return false;
-    }
-    if (arguments[0] is NamedExpression) {
-      return false;
-    }
-    if (argumentValues[0]!.type != library.typeProvider.stringType) {
-      return false;
-    }
-    var name = argumentValues[0]?.toStringValue();
-    if (name == null) {
-      return false;
-    }
-    if (_isNonNullableByDefault) {
-      return true;
-    }
-    return isValidPublicSymbol(name);
-  }
-
   /// Compute the constant value associated with the given [constant].
   void computeConstantValue(ConstantEvaluationTarget constant) {
     if (constant is Element) {
@@ -186,7 +90,7 @@
         // of the final field will be checked later, when the constructor is
         // invoked).
         if (dartObject != null && constant.isConst) {
-          if (!runtimeTypeMatch(library, dartObject, constant.type)) {
+          if (!library.typeSystem.runtimeTypeMatch(dartObject, constant.type)) {
             // TODO(brianwilkerson) This should not be reported if
             //  CompileTimeErrorCode.INVALID_ASSIGNMENT has already been
             //  reported (that is, if the static types are also wrong).
@@ -366,387 +270,17 @@
   }
 
   DartObjectImpl? evaluateConstructorCall(
-      LibraryElementImpl library,
-      AstNode node,
-      List<Expression> arguments,
-      ConstructorElement constructor,
-      ConstantVisitor constantVisitor,
-      ErrorReporter errorReporter,
-      {ConstructorInvocation? invocation}) {
-    if (!constructor.isConst) {
-      if (node is InstanceCreationExpression && node.keyword != null) {
-        errorReporter.reportErrorForToken(
-            CompileTimeErrorCode.CONST_WITH_NON_CONST, node.keyword!);
-      } else {
-        errorReporter.reportErrorForNode(
-            CompileTimeErrorCode.CONST_WITH_NON_CONST, node);
-      }
-      return null;
-    }
-
-    if (!(constructor.declaration as ConstructorElementImpl).isCycleFree) {
-      // It's not safe to evaluate this constructor, so bail out.
-      // TODO(paulberry): ensure that a reasonable error message is produced
-      // in this case, as well as other cases involving constant expression
-      // circularities (e.g. "compile-time constant expression depends on
-      // itself")
-      return DartObjectImpl.validWithUnknownValue(
-        library.typeSystem,
-        constructor.returnType,
-      );
-    }
-
-    int argumentCount = arguments.length;
-    var argumentValues = List<DartObjectImpl?>.filled(argumentCount, null);
-    Map<String, NamedExpression>? namedNodes;
-    Map<String, DartObjectImpl>? namedValues;
-    for (int i = 0; i < argumentCount; i++) {
-      Expression argument = arguments[i];
-      if (argument is NamedExpression) {
-        namedNodes ??= HashMap<String, NamedExpression>();
-        namedValues ??= HashMap<String, DartObjectImpl>();
-        String name = argument.name.label.name;
-        namedNodes[name] = argument;
-        namedValues[name] = constantVisitor._valueOf(argument.expression);
-      } else {
-        var argumentValue = constantVisitor._valueOf(argument);
-        argumentValues[i] = argumentValue;
-      }
-    }
-    namedNodes ??= const {};
-    namedValues ??= const {};
-
-    invocation ??= ConstructorInvocation(
-      constructor,
-      argumentValues,
-      namedValues,
-    );
-
-    constructor = followConstantRedirectionChain(constructor);
-    InterfaceType definingType = constructor.returnType;
-    if (constructor.isFactory) {
-      // We couldn't find a non-factory constructor.
-      // See if it's because we reached an external const factory constructor
-      // that we can emulate.
-      ClassElement definingClass = constructor.enclosingElement;
-      if (constructor.name == "fromEnvironment") {
-        if (!checkFromEnvironmentArguments(
-            library, arguments, argumentValues, namedValues, definingType)) {
-          errorReporter.reportErrorForNode(
-              CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, node);
-          return null;
-        }
-        String? variableName =
-            argumentCount < 1 ? null : argumentValues[0]?.toStringValue();
-        if (definingClass == library.typeProvider.boolElement) {
-          return FromEnvironmentEvaluator(
-            library.typeSystem,
-            _declaredVariables,
-          ).getBool2(variableName, namedValues, constructor);
-        } else if (definingClass == library.typeProvider.intElement) {
-          return FromEnvironmentEvaluator(
-            library.typeSystem,
-            _declaredVariables,
-          ).getInt2(variableName, namedValues, constructor);
-        } else if (definingClass == library.typeProvider.stringElement) {
-          return FromEnvironmentEvaluator(
-            library.typeSystem,
-            _declaredVariables,
-          ).getString2(variableName, namedValues, constructor);
-        }
-      } else if (constructor.name == 'hasEnvironment' &&
-          definingClass == library.typeProvider.boolElement) {
-        var name =
-            argumentCount < 1 ? null : argumentValues[0]?.toStringValue();
-        return FromEnvironmentEvaluator(
-          library.typeSystem,
-          _declaredVariables,
-        ).hasEnvironment(name);
-      } else if (constructor.name == "" &&
-          definingClass == library.typeProvider.symbolElement &&
-          argumentCount == 1) {
-        if (!checkSymbolArguments(
-            library, arguments, argumentValues, namedValues)) {
-          errorReporter.reportErrorForNode(
-              CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, node);
-          return null;
-        }
-        var argumentValue = argumentValues[0]?.toStringValue();
-        return DartObjectImpl(
-          library.typeSystem,
-          definingType,
-          SymbolState(argumentValue),
-        );
-      }
-      // Either it's an external const factory constructor that we can't
-      // emulate, or an error occurred (a cycle, or a const constructor trying
-      // to delegate to a non-const constructor).
-      // In the former case, the best we can do is consider it an unknown value.
-      // In the latter case, the error has already been reported, so considering
-      // it an unknown value will suppress further errors.
-      return DartObjectImpl.validWithUnknownValue(
-        library.typeSystem,
-        definingType,
-      );
-    }
-
-    var fieldMap = HashMap<String, DartObjectImpl>();
-
-    // The errors reported while computing values for field initializers, or
-    // default values for the constructor parameters, cannot be reported
-    // into the current ErrorReporter, because they usually happen in a
-    // different source. But they still should cause a constant evaluation
-    // error for the current node.
-    var externalErrorListener = BooleanErrorListener();
-    var externalErrorReporter = ErrorReporter(
-      externalErrorListener,
-      constructor.source,
-      isNonNullableByDefault: library.isNonNullableByDefault,
-    );
-
-    // Start with final fields that are initialized at their declaration site.
-    List<FieldElement> fields = constructor.enclosingElement.fields;
-    for (int i = 0; i < fields.length; i++) {
-      FieldElement field = fields[i];
-      if ((field.isFinal || field.isConst) &&
-          !field.isStatic &&
-          field is ConstFieldElementImpl) {
-        var fieldValue = field.evaluationResult?.value;
-
-        // It is possible that the evaluation result is null.
-        // This happens for example when we have duplicate fields; for example:
-        // `class Test {final x = 1; final x = 2; const Test();}`.
-        if (fieldValue == null) {
-          continue;
-        }
-        // Match the value and the type.
-        DartType fieldType =
-            FieldMember.from(field, constructor.returnType).type;
-        if (!runtimeTypeMatch(library, fieldValue, fieldType)) {
-          errorReporter.reportErrorForNode(
-              CompileTimeErrorCode.CONST_CONSTRUCTOR_FIELD_TYPE_MISMATCH,
-              node,
-              [fieldValue.type, field.name, fieldType]);
-        }
-        fieldMap[field.name] = fieldValue;
-      }
-    }
-    // Now evaluate the constructor declaration.
-    Map<String, DartObjectImpl> parameterMap =
-        HashMap<String, DartObjectImpl>();
-    List<ParameterElement> parameters = constructor.parameters;
-    int parameterCount = parameters.length;
-
-    for (int i = 0; i < parameterCount; i++) {
-      ParameterElement parameter = parameters[i];
-      ParameterElement baseParameter = parameter.declaration;
-      DartObjectImpl? argumentValue;
-      AstNode? errorTarget;
-      if (baseParameter.isNamed) {
-        argumentValue = namedValues[baseParameter.name];
-        errorTarget = namedNodes[baseParameter.name];
-      } else if (i < argumentCount) {
-        argumentValue = argumentValues[i];
-        errorTarget = arguments[i];
-      }
-      // No argument node that we can direct error messages to, because we
-      // are handling an optional parameter that wasn't specified.  So just
-      // direct error messages to the constructor call.
-      errorTarget ??= node;
-      if (argumentValue == null && baseParameter is ParameterElementImpl) {
-        // The parameter is an optional positional parameter for which no value
-        // was provided, so use the default value.
-        var evaluationResult = baseParameter.evaluationResult;
-        if (evaluationResult == null) {
-          // No default was provided, so the default value is null.
-          argumentValue = _nullObject(library);
-        } else if (evaluationResult.value != null) {
-          argumentValue = evaluationResult.value;
-        }
-      }
-      if (argumentValue != null) {
-        if (!runtimeTypeMatch(library, argumentValue, parameter.type)) {
-          errorReporter.reportErrorForNode(
-              CompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH,
-              errorTarget,
-              [argumentValue.type, parameter.type]);
-        }
-        if (baseParameter.isInitializingFormal) {
-          var field = (parameter as FieldFormalParameterElement).field;
-          if (field != null) {
-            DartType fieldType = field.type;
-            if (fieldType != parameter.type) {
-              // We've already checked that the argument can be assigned to the
-              // parameter; we also need to check that it can be assigned to
-              // the field.
-              if (!runtimeTypeMatch(library, argumentValue, fieldType)) {
-                errorReporter.reportErrorForNode(
-                    CompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH,
-                    errorTarget,
-                    [argumentValue.type, fieldType]);
-              }
-            }
-            String fieldName = field.name;
-            if (fieldMap.containsKey(fieldName)) {
-              errorReporter.reportErrorForNode(
-                  CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, node);
-            }
-            fieldMap[fieldName] = argumentValue;
-          }
-        }
-        String name = baseParameter.name;
-        parameterMap[name] = argumentValue;
-      }
-    }
-    ConstantVisitor initializerVisitor = ConstantVisitor(
-      this,
-      constructor.library as LibraryElementImpl,
-      externalErrorReporter,
-      lexicalEnvironment: parameterMap,
-      substitution: Substitution.fromInterfaceType(definingType),
-    );
-    var constructorBase = constructor.declaration as ConstructorElementImpl;
-    var initializers = constructorBase.constantInitializers;
-    String? superName;
-    NodeList<Expression>? superArguments;
-    for (var i = 0; i < initializers.length; i++) {
-      var initializer = initializers[i];
-      if (initializer is ConstructorFieldInitializer) {
-        Expression initializerExpression = initializer.expression;
-        var evaluationResult = initializerExpression.accept(initializerVisitor);
-        if (evaluationResult != null) {
-          String fieldName = initializer.fieldName.name;
-          if (fieldMap.containsKey(fieldName)) {
-            errorReporter.reportErrorForNode(
-                CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, node);
-          }
-          fieldMap[fieldName] = evaluationResult;
-          var getter = definingType.getGetter(fieldName);
-          if (getter != null) {
-            PropertyInducingElement field = getter.variable;
-            if (!runtimeTypeMatch(library, evaluationResult, field.type)) {
-              errorReporter.reportErrorForNode(
-                  CompileTimeErrorCode.CONST_CONSTRUCTOR_FIELD_TYPE_MISMATCH,
-                  node,
-                  [evaluationResult.type, fieldName, field.type]);
-            }
-          }
-        } else {
-          errorReporter.reportErrorForNode(
-              CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, node);
-        }
-      } else if (initializer is SuperConstructorInvocation) {
-        var name = initializer.constructorName;
-        if (name != null) {
-          superName = name.name;
-        }
-        superArguments = initializer.argumentList.arguments;
-      } else if (initializer is RedirectingConstructorInvocation) {
-        // This is a redirecting constructor, so just evaluate the constructor
-        // it redirects to.
-        var constructor = initializer.staticElement;
-        if (constructor != null && constructor.isConst) {
-          // Instantiate the constructor with the in-scope type arguments.
-          constructor = ConstructorMember.from(constructor, definingType);
-
-          var result = evaluateConstructorCall(
-              library,
-              node,
-              initializer.argumentList.arguments,
-              constructor,
-              initializerVisitor,
-              externalErrorReporter,
-              invocation: invocation);
-          if (externalErrorListener.errorReported) {
-            errorReporter.reportErrorForNode(
-                CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, node);
-          }
-          return result;
-        }
-      } else if (initializer is AssertInitializer) {
-        var condition = initializer.condition;
-        var evaluationResult = condition.accept(initializerVisitor);
-        if (evaluationResult == null ||
-            !evaluationResult.isBool ||
-            evaluationResult.toBoolValue() == false) {
-          errorReporter.reportErrorForNode(
-              CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, node);
-          return null;
-        }
-      }
-    }
-    // Evaluate explicit or implicit call to super().
-    var superclass = definingType.superclass;
-    if (superclass != null && !superclass.isDartCoreObject) {
-      var superConstructor =
-          superclass.lookUpConstructor(superName, constructor.library);
-      if (superConstructor != null) {
-        superArguments ??= astFactory.nodeList<Expression>(node);
-
-        if (constructor is ConstructorMember && constructor.isLegacy) {
-          superConstructor =
-              Member.legacy(superConstructor) as ConstructorElement;
-        }
-
-        evaluateSuperConstructorCall(library, node, fieldMap, superConstructor,
-            superArguments, initializerVisitor, externalErrorReporter);
-      }
-    }
-    if (externalErrorListener.errorReported) {
-      errorReporter.reportErrorForNode(
-          CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, node);
-    }
-    return DartObjectImpl(
-      library.typeSystem,
-      definingType,
-      GenericState(fieldMap, invocation: invocation),
-    );
-  }
-
-  void evaluateSuperConstructorCall(
-      LibraryElementImpl library,
-      AstNode node,
-      Map<String, DartObjectImpl> fieldMap,
-      ConstructorElement? superConstructor,
-      List<Expression> superArguments,
-      ConstantVisitor initializerVisitor,
-      ErrorReporter errorReporter) {
-    if (superConstructor != null && superConstructor.isConst) {
-      var evaluationResult = evaluateConstructorCall(library, node,
-          superArguments, superConstructor, initializerVisitor, errorReporter);
-      if (evaluationResult != null) {
-        fieldMap[GenericState.SUPERCLASS_FIELD] = evaluationResult;
-      }
-    }
-  }
-
-  /// Attempt to follow the chain of factory redirections until a constructor is
-  /// reached which is not a const factory constructor. Return the constant
-  /// constructor which terminates the chain of factory redirections, if the
-  /// chain terminates. If there is a problem (e.g. a redirection can't be
-  /// found, or a cycle is encountered), the chain will be followed as far as
-  /// possible and then a const factory constructor will be returned.
-  ConstructorElement followConstantRedirectionChain(
-      ConstructorElement constructor) {
-    var constructorsVisited = <ConstructorElement>{};
-    while (true) {
-      var redirectedConstructor = getConstRedirectedConstructor(constructor);
-      if (redirectedConstructor == null) {
-        break;
-      } else {
-        var constructorBase = constructor.declaration;
-        constructorsVisited.add(constructorBase);
-        var redirectedConstructorBase = redirectedConstructor.declaration;
-        if (constructorsVisited.contains(redirectedConstructorBase)) {
-          // Cycle in redirecting factory constructors--this is not allowed
-          // and is checked elsewhere--see
-          // [ErrorVerifier.checkForRecursiveFactoryRedirect()]).
-          break;
-        }
-      }
-      constructor = redirectedConstructor;
-    }
-    return constructor;
+    LibraryElementImpl library,
+    AstNode node,
+    List<Expression> arguments,
+    ConstructorElement constructor,
+    ConstantVisitor constantVisitor,
+    ErrorReporter errorReporter, {
+    ConstructorInvocation? invocation,
+  }) {
+    return _InstanceCreationEvaluator.evaluate(this, _declaredVariables,
+        errorReporter, library, node, constructor, arguments, constantVisitor,
+        isNullSafe: _isNonNullableByDefault, invocation: invocation);
   }
 
   /// Generate an error indicating that the given [constant] is not a valid
@@ -786,7 +320,7 @@
 
   /// If [constructor] redirects to another const constructor, return the
   /// const constructor it redirects to.  Otherwise return `null`.
-  ConstructorElement? getConstRedirectedConstructor(
+  static ConstructorElement? getConstRedirectedConstructor(
       ConstructorElement constructor) {
     if (!constructor.isFactory) {
       return null;
@@ -814,33 +348,13 @@
     return redirectedConstructor;
   }
 
-  /// Check if the object [obj] matches the type [type] according to runtime
-  /// type checking rules.
-  bool runtimeTypeMatch(
-    LibraryElementImpl library,
-    DartObjectImpl obj,
-    DartType type,
-  ) {
-    var typeSystem = library.typeSystem;
-    if (!typeSystem.isNonNullableByDefault) {
-      type = typeSystem.toLegacyType(type);
-    }
-    var objType = obj.type;
-    return typeSystem.isSubtypeOf(objType, type);
-  }
-
-  DartObjectImpl _nullObject(LibraryElementImpl library) {
+  static DartObjectImpl _nullObject(LibraryElementImpl library) {
     return DartObjectImpl(
       library.typeSystem,
       library.typeProvider.nullType,
       NullState.NULL_STATE,
     );
   }
-
-  /// Determine whether the given string is a valid name for a public symbol
-  /// (i.e. whether it is allowed for a call to the Symbol constructor).
-  static bool isValidPublicSymbol(String name) =>
-      name.isEmpty || name == "void" || _PUBLIC_SYMBOL_PATTERN.hasMatch(name);
 }
 
 /// Interface for [AnalysisTarget]s for which constant evaluation can be
@@ -943,7 +457,7 @@
   })  : _lexicalEnvironment = lexicalEnvironment,
         _substitution = substitution {
     _dartObjectComputer = DartObjectComputer(
-      _library.typeSystem,
+      typeSystem,
       _errorReporter,
     );
   }
@@ -1324,7 +838,7 @@
 
   @override
   DartObjectImpl visitNullLiteral(NullLiteral node) {
-    return evaluationEngine._nullObject(_library);
+    return ConstantEvaluationEngine._nullObject(_library);
   }
 
   @override
@@ -1805,7 +1319,7 @@
     if (expressionValue != null) {
       return expressionValue;
     }
-    return evaluationEngine._nullObject(_library);
+    return ConstantEvaluationEngine._nullObject(_library);
   }
 }
 
@@ -2317,3 +1831,632 @@
     return value.toString();
   }
 }
+
+/// The result of evaluation the initializers declared on a const constructor.
+class _InitializersEvaluationResult {
+  /// The result of a const evaluation of an initializer, if one was performed,
+  /// otherwise `null`.
+  ///
+  /// If a redirecting initializer which redirects to a const constructor was
+  /// encountered, [result] is the result of evaluating that call.
+  ///
+  /// If an assert initializer is encountered, and the evaluation of this assert
+  /// results in an error or a `false` value, [result] is `null`.
+  final DartObjectImpl? result;
+
+  /// Whether evaluation of the const instance creation expression which led to
+  /// evaluating constructor initializers is complete.
+  ///
+  /// If `true`, `result` should be used as the result of said const instance
+  /// creation expression evaluation.
+  final bool evaluationIsComplete;
+
+  /// If a superinitializer was encountered, the name of the super constructor,
+  /// otherwise `null`.
+  final String? superName;
+
+  /// If a superinitializer was encountered, the arguments passed to the super
+  /// constructor, otherwise `null`.
+  final NodeList<Expression>? superArguments;
+
+  _InitializersEvaluationResult(
+    this.result, {
+    required this.evaluationIsComplete,
+    this.superName,
+    this.superArguments,
+  });
+}
+
+/// An evaluator which evaluates a const instance creation expression.
+///
+/// [_InstanceCreationEvaluator.evaluate] is the main entrypoint.
+class _InstanceCreationEvaluator {
+  /// Parameter to "fromEnvironment" methods that denotes the default value.
+  static const String _default_value_param = 'defaultValue';
+
+  /// Source of RegExp matching declarable operator names.
+  /// From sdk/lib/internal/symbol.dart.
+  static const String _operator_pattern =
+      "(?:[\\-+*/%&|^]|\\[\\]=?|==|~/?|<[<=]?|>[>=]?|unary-)";
+
+  /// Source of RegExp matching any public identifier.
+  /// From sdk/lib/internal/symbol.dart.
+  static const String _public_identifier_pattern =
+      "(?!$_reserved_word_pattern\\b(?!\\\$))[a-zA-Z\$][\\w\$]*";
+
+  /// RegExp that validates a non-empty non-private symbol.
+  /// From sdk/lib/internal/symbol.dart.
+  static final RegExp _public_symbol_pattern =
+      RegExp('^(?:$_operator_pattern\$|'
+          '$_public_identifier_pattern(?:=?\$|[.](?!\$)))+?\$');
+
+  /// Source of RegExp matching Dart reserved words.
+  /// From sdk/lib/internal/symbol.dart.
+  static const String _reserved_word_pattern =
+      "(?:assert|break|c(?:a(?:se|tch)|lass|on(?:st|tinue))|"
+      "d(?:efault|o)|e(?:lse|num|xtends)|f(?:alse|inal(?:ly)?|or)|"
+      "i[fns]|n(?:ew|ull)|ret(?:hrow|urn)|s(?:uper|witch)|t(?:h(?:is|row)|"
+      "r(?:ue|y))|v(?:ar|oid)|w(?:hile|ith))";
+
+  final ConstantEvaluationEngine _evaluationEngine;
+
+  /// The set of variables declared on the command line using '-D'.
+  final DeclaredVariables _declaredVariables;
+
+  final LibraryElementImpl _library;
+
+  final ErrorReporter _errorReporter;
+
+  final BooleanErrorListener _externalErrorListener = BooleanErrorListener();
+
+  /// An error reporter for errors determined while computing values for field
+  /// initializers, or default values for the constructor parameters.
+  ///
+  /// Such errors cannot be reported into [_errorReporter], because they usually
+  /// happen in a different source. But they still should cause a constant
+  /// evaluation error for the current node.
+  late final ErrorReporter _externalErrorReporter = ErrorReporter(
+    _externalErrorListener,
+    _constructor.source,
+    isNonNullableByDefault: _library.isNonNullableByDefault,
+  );
+
+  late final ConstantVisitor _initializerVisitor = ConstantVisitor(
+    _evaluationEngine,
+    _constructor.library as LibraryElementImpl,
+    _externalErrorReporter,
+    lexicalEnvironment: _parameterMap,
+    substitution: Substitution.fromInterfaceType(definingType),
+  );
+
+  final AstNode _node;
+
+  final ConstructorElement _constructor;
+
+  final ConstructorInvocation _invocation;
+
+  final Map<String, NamedExpression> _namedNodes;
+
+  final Map<String, DartObjectImpl> _namedValues;
+
+  final List<DartObjectImpl> _argumentValues;
+
+  final Map<String, DartObjectImpl> _parameterMap = HashMap();
+
+  final Map<String, DartObjectImpl> _fieldMap = HashMap();
+
+  _InstanceCreationEvaluator.generative(
+    this._evaluationEngine,
+    this._declaredVariables,
+    this._errorReporter,
+    this._library,
+    this._node,
+    this._constructor, {
+    required Map<String, NamedExpression> namedNodes,
+    required Map<String, DartObjectImpl> namedValues,
+    required List<DartObjectImpl> argumentValues,
+    required ConstructorInvocation invocation,
+  })  : _namedNodes = namedNodes,
+        _namedValues = namedValues,
+        _argumentValues = argumentValues,
+        _invocation = invocation;
+
+  InterfaceType get definingType => _constructor.returnType;
+
+  DartObjectImpl? get firstArgument => _argumentValues[0];
+
+  TypeProvider get typeProvider => _library.typeProvider;
+
+  TypeSystemImpl get typeSystem => _library.typeSystem;
+
+  /// Evaluates this constructor call as a factory constructor call.
+  DartObjectImpl? evaluateFactoryConstructorCall(
+    List<Expression> arguments, {
+    required bool isNullSafe,
+  }) {
+    ClassElement definingClass = _constructor.enclosingElement;
+    var argumentCount = arguments.length;
+    if (_constructor.name == "fromEnvironment") {
+      if (!_checkFromEnvironmentArguments(arguments, definingType)) {
+        _errorReporter.reportErrorForNode(
+            CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, _node);
+        return null;
+      }
+      String? variableName =
+          argumentCount < 1 ? null : firstArgument?.toStringValue();
+      if (definingClass == typeProvider.boolElement) {
+        return FromEnvironmentEvaluator(typeSystem, _declaredVariables)
+            .getBool2(variableName, _namedValues, _constructor);
+      } else if (definingClass == typeProvider.intElement) {
+        return FromEnvironmentEvaluator(typeSystem, _declaredVariables)
+            .getInt2(variableName, _namedValues, _constructor);
+      } else if (definingClass == typeProvider.stringElement) {
+        return FromEnvironmentEvaluator(typeSystem, _declaredVariables)
+            .getString2(variableName, _namedValues, _constructor);
+      }
+    } else if (_constructor.name == 'hasEnvironment' &&
+        definingClass == typeProvider.boolElement) {
+      var name = argumentCount < 1 ? null : firstArgument?.toStringValue();
+      return FromEnvironmentEvaluator(typeSystem, _declaredVariables)
+          .hasEnvironment(name);
+    } else if (_constructor.name == "" &&
+        definingClass == typeProvider.symbolElement &&
+        argumentCount == 1) {
+      if (!_checkSymbolArguments(arguments, isNullSafe: isNullSafe)) {
+        _errorReporter.reportErrorForNode(
+            CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, _node);
+        return null;
+      }
+      return DartObjectImpl(
+        typeSystem,
+        definingType,
+        SymbolState(firstArgument?.toStringValue()),
+      );
+    }
+    // Either it's an external const factory constructor that we can't
+    // emulate, or an error occurred (a cycle, or a const constructor trying to
+    // delegate to a non-const constructor).
+    //
+    // In the former case, the best we can do is consider it an unknown value.
+    // In the latter case, the error has already been reported, so considering
+    // it an unknown value will suppress further errors.
+    return DartObjectImpl.validWithUnknownValue(typeSystem, definingType);
+  }
+
+  DartObjectImpl? evaluateGenerativeConstructorCall(
+      List<Expression> arguments) {
+    // Start with final fields that are initialized at their declaration site.
+    _checkFields();
+
+    _checkParameters(arguments);
+    var evaluationResult = _checkInitializers();
+    if (evaluationResult.evaluationIsComplete) {
+      return evaluationResult.result;
+    }
+    _checkSuperConstructorCall(
+        superName: evaluationResult.superName,
+        superArguments: evaluationResult.superArguments);
+    if (_externalErrorListener.errorReported) {
+      _errorReporter.reportErrorForNode(
+          CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, _node);
+    }
+    return DartObjectImpl(
+      typeSystem,
+      definingType,
+      GenericState(_fieldMap, invocation: _invocation),
+    );
+  }
+
+  void _checkFields() {
+    var fields = _constructor.enclosingElement.fields;
+    for (var i = 0; i < fields.length; i++) {
+      var field = fields[i];
+      if ((field.isFinal || field.isConst) &&
+          !field.isStatic &&
+          field is ConstFieldElementImpl) {
+        var fieldValue = field.evaluationResult?.value;
+
+        // It is possible that the evaluation result is null.
+        // This happens for example when we have duplicate fields.
+        // `class Test {final x = 1; final x = 2; const Test();}`
+        if (fieldValue == null) {
+          continue;
+        }
+        // Match the value and the type.
+        var fieldType = FieldMember.from(field, _constructor.returnType).type;
+        if (!typeSystem.runtimeTypeMatch(fieldValue, fieldType)) {
+          _errorReporter.reportErrorForNode(
+              CompileTimeErrorCode.CONST_CONSTRUCTOR_FIELD_TYPE_MISMATCH,
+              _node,
+              [fieldValue.type, field.name, fieldType]);
+        }
+        _fieldMap[field.name] = fieldValue;
+      }
+    }
+  }
+
+  /// Check that the arguments to a call to `fromEnvironment()` are correct.
+  ///
+  /// The [arguments] are the AST nodes of the arguments. The [argumentValues]
+  /// are the values of the unnamed arguments. The [namedArgumentValues] are the
+  /// values of the named arguments. The [expectedDefaultValueType] is the
+  /// allowed type of the "defaultValue" parameter (if present). Note:
+  /// "defaultValue" is always allowed to be `null`. Return `true` if the
+  /// arguments are correct, `false` otherwise.
+  bool _checkFromEnvironmentArguments(
+    List<Expression> arguments,
+    InterfaceType expectedDefaultValueType,
+  ) {
+    var argumentCount = arguments.length;
+    if (argumentCount < 1 || argumentCount > 2) {
+      return false;
+    }
+    if (arguments[0] is NamedExpression) {
+      return false;
+    }
+    if (firstArgument!.type != typeProvider.stringType) {
+      return false;
+    }
+    if (argumentCount == 2) {
+      var secondArgument = arguments[1];
+      if (secondArgument is NamedExpression) {
+        if (!(secondArgument.name.label.name == _default_value_param)) {
+          return false;
+        }
+        var defaultValueType = _namedValues[_default_value_param]!.type;
+        if (!(defaultValueType == expectedDefaultValueType ||
+            defaultValueType == typeProvider.nullType)) {
+          return false;
+        }
+      } else {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  _InitializersEvaluationResult _checkInitializers() {
+    var constructorBase = _constructor.declaration as ConstructorElementImpl;
+    // If we encounter a superinitializer, store the name of the constructor,
+    // and the arguments.
+    String? superName;
+    NodeList<Expression>? superArguments;
+    for (var initializer in constructorBase.constantInitializers) {
+      if (initializer is ConstructorFieldInitializer) {
+        var initializerExpression = initializer.expression;
+        var evaluationResult =
+            initializerExpression.accept(_initializerVisitor);
+        if (evaluationResult != null) {
+          var fieldName = initializer.fieldName.name;
+          if (_fieldMap.containsKey(fieldName)) {
+            _errorReporter.reportErrorForNode(
+                CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, _node);
+          }
+          _fieldMap[fieldName] = evaluationResult;
+          var getter = definingType.getGetter(fieldName);
+          if (getter != null) {
+            var field = getter.variable;
+            if (!typeSystem.runtimeTypeMatch(evaluationResult, field.type)) {
+              _errorReporter.reportErrorForNode(
+                  CompileTimeErrorCode.CONST_CONSTRUCTOR_FIELD_TYPE_MISMATCH,
+                  _node,
+                  [evaluationResult.type, fieldName, field.type]);
+            }
+          }
+        } else {
+          _errorReporter.reportErrorForNode(
+              CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, _node);
+        }
+      } else if (initializer is SuperConstructorInvocation) {
+        var name = initializer.constructorName;
+        if (name != null) {
+          superName = name.name;
+        }
+        superArguments = initializer.argumentList.arguments;
+      } else if (initializer is RedirectingConstructorInvocation) {
+        // This is a redirecting constructor, so just evaluate the constructor
+        // it redirects to.
+        var constructor = initializer.staticElement;
+        if (constructor != null && constructor.isConst) {
+          // Instantiate the constructor with the in-scope type arguments.
+          constructor = ConstructorMember.from(constructor, definingType);
+          var result = _evaluationEngine.evaluateConstructorCall(
+              _library,
+              _node,
+              initializer.argumentList.arguments,
+              constructor,
+              _initializerVisitor,
+              _externalErrorReporter,
+              invocation: _invocation);
+          if (_externalErrorListener.errorReported) {
+            _errorReporter.reportErrorForNode(
+                CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, _node);
+          }
+          return _InitializersEvaluationResult(result,
+              evaluationIsComplete: true);
+        }
+      } else if (initializer is AssertInitializer) {
+        var condition = initializer.condition;
+        var evaluationResult = condition.accept(_initializerVisitor);
+        if (evaluationResult == null ||
+            !evaluationResult.isBool ||
+            evaluationResult.toBoolValue() == false) {
+          _errorReporter.reportErrorForNode(
+              CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, _node);
+          return _InitializersEvaluationResult(null,
+              evaluationIsComplete: true);
+        }
+      }
+    }
+    return _InitializersEvaluationResult(null,
+        evaluationIsComplete: false,
+        superName: superName,
+        superArguments: superArguments);
+  }
+
+  void _checkParameters(List<Expression> arguments) {
+    var parameters = _constructor.parameters;
+    var parameterCount = parameters.length;
+
+    for (var i = 0; i < parameterCount; i++) {
+      var parameter = parameters[i];
+      var baseParameter = parameter.declaration;
+      DartObjectImpl? argumentValue;
+      AstNode? errorTarget;
+      if (baseParameter.isNamed) {
+        argumentValue = _namedValues[baseParameter.name];
+        errorTarget = _namedNodes[baseParameter.name];
+      } else if (i < arguments.length) {
+        argumentValue = _argumentValues[i];
+        errorTarget = arguments[i];
+      }
+      // No argument node that we can direct error messages to, because we
+      // are handling an optional parameter that wasn't specified.  So just
+      // direct error messages to the constructor call.
+      errorTarget ??= _node;
+      if (argumentValue == null && baseParameter is ParameterElementImpl) {
+        // The parameter is an optional positional parameter for which no value
+        // was provided, so use the default value.
+        var evaluationResult = baseParameter.evaluationResult;
+        if (evaluationResult == null) {
+          // No default was provided, so the default value is null.
+          argumentValue = ConstantEvaluationEngine._nullObject(_library);
+        } else if (evaluationResult.value != null) {
+          argumentValue = evaluationResult.value;
+        }
+      }
+      if (argumentValue != null) {
+        if (!typeSystem.runtimeTypeMatch(argumentValue, parameter.type)) {
+          _errorReporter.reportErrorForNode(
+            CompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH,
+            errorTarget,
+            [argumentValue.type, parameter.type],
+          );
+        }
+        if (baseParameter.isInitializingFormal) {
+          var field = (parameter as FieldFormalParameterElement).field;
+          if (field != null) {
+            var fieldType = field.type;
+            if (fieldType != parameter.type) {
+              // We've already checked that the argument can be assigned to the
+              // parameter; we also need to check that it can be assigned to
+              // the field.
+              if (!typeSystem.runtimeTypeMatch(argumentValue, fieldType)) {
+                _errorReporter.reportErrorForNode(
+                  CompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH,
+                  errorTarget,
+                  [argumentValue.type, fieldType],
+                );
+              }
+            }
+            var fieldName = field.name;
+            if (_fieldMap.containsKey(fieldName)) {
+              _errorReporter.reportErrorForNode(
+                  CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, _node);
+            }
+            _fieldMap[fieldName] = argumentValue;
+          }
+        }
+        _parameterMap[baseParameter.name] = argumentValue;
+      }
+    }
+  }
+
+  /// Checks an explicit or implicit call to `super()`.
+  ///
+  /// If a superinitializer was declared on the constructor declaration,
+  /// [superName] and [superArguments] are the name of the super constructor
+  /// referenced therein, and the arguments passed to the super constructor.
+  /// Otherwise these parameters are `null`.
+  void _checkSuperConstructorCall({
+    required String? superName,
+    required NodeList<Expression>? superArguments,
+  }) {
+    var superclass = definingType.superclass;
+    if (superclass != null && !superclass.isDartCoreObject) {
+      var superConstructor =
+          superclass.lookUpConstructor(superName, _constructor.library);
+      if (superConstructor == null) {
+        return;
+      }
+
+      var constructor = _constructor;
+      if (constructor is ConstructorMember && constructor.isLegacy) {
+        superConstructor =
+            Member.legacy(superConstructor) as ConstructorElement;
+      }
+      if (superConstructor.isConst) {
+        var evaluationResult = _evaluationEngine.evaluateConstructorCall(
+          _library,
+          _node,
+          superArguments ?? astFactory.nodeList(_node),
+          superConstructor,
+          _initializerVisitor,
+          _externalErrorReporter,
+        );
+        if (evaluationResult != null) {
+          _fieldMap[GenericState.SUPERCLASS_FIELD] = evaluationResult;
+        }
+      }
+    }
+  }
+
+  /// Checks that the arguments to a call to [Symbol.new] are correct.
+  ///
+  /// The [arguments] are the AST nodes of the arguments. The [argumentValues]
+  /// are the values of the unnamed arguments. The [namedArgumentValues] are the
+  /// values of the named arguments. Returns `true` if the arguments are
+  /// correct, `false` otherwise.
+  bool _checkSymbolArguments(List<Expression> arguments,
+      {required bool isNullSafe}) {
+    if (arguments.length != 1) {
+      return false;
+    }
+    if (arguments[0] is NamedExpression) {
+      return false;
+    }
+    if (firstArgument!.type != typeProvider.stringType) {
+      return false;
+    }
+    var name = firstArgument?.toStringValue();
+    if (name == null) {
+      return false;
+    }
+    if (isNullSafe) {
+      return true;
+    }
+    return _isValidPublicSymbol(name);
+  }
+
+  /// Evaluates [node] as an instance creation expression using [constructor].
+  static DartObjectImpl? evaluate(
+    ConstantEvaluationEngine evaluationEngine,
+    DeclaredVariables declaredVariables,
+    ErrorReporter errorReporter,
+    LibraryElementImpl library,
+    AstNode node,
+    ConstructorElement constructor,
+    List<Expression> arguments,
+    ConstantVisitor constantVisitor, {
+    required bool isNullSafe,
+    ConstructorInvocation? invocation,
+  }) {
+    if (!constructor.isConst) {
+      if (node is InstanceCreationExpression && node.keyword != null) {
+        errorReporter.reportErrorForToken(
+            CompileTimeErrorCode.CONST_WITH_NON_CONST, node.keyword!);
+      } else {
+        errorReporter.reportErrorForNode(
+            CompileTimeErrorCode.CONST_WITH_NON_CONST, node);
+      }
+      return null;
+    }
+
+    if (!(constructor.declaration as ConstructorElementImpl).isCycleFree) {
+      // It's not safe to evaluate this constructor, so bail out.
+      // TODO(paulberry): ensure that a reasonable error message is produced
+      // in this case, as well as other cases involving constant expression
+      // cycles (e.g. "compile-time constant expression depends on itself").
+      return DartObjectImpl.validWithUnknownValue(
+        library.typeSystem,
+        constructor.returnType,
+      );
+    }
+
+    var argumentCount = arguments.length;
+    var argumentValues = <DartObjectImpl>[];
+    var namedNodes = <String, NamedExpression>{};
+    var namedValues = <String, DartObjectImpl>{};
+    for (var i = 0; i < argumentCount; i++) {
+      var argument = arguments[i];
+      if (argument is NamedExpression) {
+        var name = argument.name.label.name;
+        namedNodes[name] = argument;
+        namedValues[name] = constantVisitor._valueOf(argument.expression);
+      } else {
+        argumentValues.add(constantVisitor._valueOf(argument));
+      }
+    }
+
+    invocation ??= ConstructorInvocation(
+      constructor,
+      argumentValues,
+      namedValues,
+    );
+
+    constructor = _followConstantRedirectionChain(constructor);
+
+    var evaluator = _InstanceCreationEvaluator.generative(
+      evaluationEngine,
+      declaredVariables,
+      errorReporter,
+      library,
+      node,
+      constructor,
+      namedNodes: namedNodes,
+      namedValues: namedValues,
+      argumentValues: argumentValues,
+      invocation: invocation,
+    );
+
+    if (constructor.isFactory) {
+      // We couldn't find a non-factory constructor.
+      // See if it's because we reached an external const factory constructor
+      // that we can emulate.
+      return evaluator.evaluateFactoryConstructorCall(arguments,
+          isNullSafe: isNullSafe);
+    } else {
+      return evaluator.evaluateGenerativeConstructorCall(arguments);
+    }
+  }
+
+  /// Attempt to follow the chain of factory redirections until a constructor is
+  /// reached which is not a const factory constructor. Return the constant
+  /// constructor which terminates the chain of factory redirections, if the
+  /// chain terminates. If there is a problem (e.g. a redirection can't be
+  /// found, or a cycle is encountered), the chain will be followed as far as
+  /// possible and then a const factory constructor will be returned.
+  static ConstructorElement _followConstantRedirectionChain(
+      ConstructorElement constructor) {
+    var constructorsVisited = <ConstructorElement>{};
+    while (true) {
+      var redirectedConstructor =
+          ConstantEvaluationEngine.getConstRedirectedConstructor(constructor);
+      if (redirectedConstructor == null) {
+        break;
+      } else {
+        var constructorBase = constructor.declaration;
+        constructorsVisited.add(constructorBase);
+        var redirectedConstructorBase = redirectedConstructor.declaration;
+        if (constructorsVisited.contains(redirectedConstructorBase)) {
+          // Cycle in redirecting factory constructors--this is not allowed
+          // and is checked elsewhere--see
+          // [ErrorVerifier.checkForRecursiveFactoryRedirect()]).
+          break;
+        }
+      }
+      constructor = redirectedConstructor;
+    }
+    return constructor;
+  }
+
+  /// Determine whether the given string is a valid name for a public symbol
+  /// (i.e. whether it is allowed for a call to the Symbol constructor).
+  static bool _isValidPublicSymbol(String name) =>
+      name.isEmpty || name == "void" || _public_symbol_pattern.hasMatch(name);
+}
+
+extension RuntimeExtensions on TypeSystemImpl {
+  /// Returns whether [obj] matches the [type] according to runtime
+  /// type-checking rules.
+  bool runtimeTypeMatch(
+    DartObjectImpl obj,
+    DartType type,
+  ) {
+    if (!isNonNullableByDefault) {
+      type = toLegacyType(type);
+    }
+    var objType = obj.type;
+    return isSubtypeOf(objType, type);
+  }
+}
diff --git a/tools/VERSION b/tools/VERSION
index 33318f2..10b379b 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 15
 PATCH 0
-PRERELEASE 175
+PRERELEASE 176
 PRERELEASE_PATCH 0
\ No newline at end of file