Skip to content

Commit

Permalink
Version 3.4.0-159.0.dev
Browse files Browse the repository at this point in the history
Merge 0d9d7f4 into dev
  • Loading branch information
Dart CI committed Feb 21, 2024
2 parents 67b99f9 + 0d9d7f4 commit a30222a
Show file tree
Hide file tree
Showing 41 changed files with 2,132 additions and 1,080 deletions.
2 changes: 1 addition & 1 deletion DEPS
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ vars = {
"flute_rev": "a531c96a8b43d015c6bfbbfe3ab54867b0763b8b",
"glob_rev": "ef5f0650f66dc64587b11757fe3303538cfeb1d8",
"html_rev": "327e37a6a4dd46599737ee982f280d73a8f646f7",
"http_rev": "f0a02f98f7c921e86ecc81c70f38bb6fbccc81b9", # https://github.com/dart-lang/sdk/issues/54165
"http_rev": "6d9f9efe04886d9685fbfb1a76ba24a71b6c951c",
"http_multi_server_rev": "ba9d07f3596b24718ddf45c9e071d40879cca565",
"http_parser_rev": "84db8b029d9b51859a0bb4966859af009f9442e3",
"intl_rev": "5d65e3808ce40e6282e40881492607df4e35669f",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ class IgnoreDiagnosticInAnalysisOptionsFile extends AbstractIgnoreDiagnostic {
var edit = editor.edits.single;
var replacement = edit.replacement;

// HACK(dantup): The YAML editor currently produces inconsistent line
// TODO(dantup): The YAML editor currently produces inconsistent line
// endings in edits when the source file contains '\r\n'.
// https://github.com/dart-lang/yaml_edit/issues/65
var analysisOptionsEol = content.contains('\r')
Expand Down
125 changes: 73 additions & 52 deletions pkg/analyzer/lib/src/dart/resolver/record_literal_resolver.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ import 'package:analyzer/dart/element/nullability_suffix.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/error/listener.dart';
import 'package:analyzer/src/dart/ast/ast.dart';
import 'package:analyzer/src/dart/ast/extensions.dart';
import 'package:analyzer/src/dart/element/extensions.dart';
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/dart/element/type_schema.dart';
import 'package:analyzer/src/diagnostic/diagnostic_factory.dart';
import 'package:analyzer/src/error/codes.g.dart';
import 'package:analyzer/src/generated/resolver.dart';
Expand All @@ -28,41 +28,50 @@ class RecordLiteralResolver {
required DartType? contextType,
}) {
_resolveFields(node, contextType);
_buildType(node);

_reportDuplicateFieldDefinitions(node);
_reportInvalidFieldNames(node);
}

void _buildType(RecordLiteralImpl node) {
final positionalFields = <RecordTypePositionalFieldImpl>[];
final namedFields = <RecordTypeNamedFieldImpl>[];
for (final field in node.fields) {
final fieldType = field.typeOrThrow;
/// If [contextType] is a record type, and the type schemas contained in it
/// should be used for inferring the expressions in [node], returns it as a
/// [RecordType]. Otherwise returns `null`.
///
/// The type schemas contained in [contextType] should only be used for
/// inferring the expressions in [node] if it is a record type with a shape
/// that matches the shape of [node].
RecordType? _matchContextType(RecordLiteralImpl node, DartType? contextType) {
if (contextType is! RecordType) return null;
if (contextType.namedFields.length + contextType.positionalFields.length !=
node.fields.length) {
return null;
}
var numPositionalFields = 0;
for (var field in node.fields) {
if (field is NamedExpressionImpl) {
namedFields.add(
RecordTypeNamedFieldImpl(
name: field.name.label.name,
type: fieldType,
),
);
if (contextType.namedField(field.name.label.name) == null) {
return null;
}
} else {
positionalFields.add(
RecordTypePositionalFieldImpl(
type: fieldType,
),
);
numPositionalFields++;
}
}

_resolver.inferenceHelper.recordStaticType(
node,
RecordTypeImpl(
positionalFields: positionalFields,
namedFields: namedFields,
nullabilitySuffix: NullabilitySuffix.none,
),
);
if (contextType.positionalFields.length != numPositionalFields) {
return null;
}
// At this point we've established that:
// - The total number of fields in the context matches the total number of
// fields in the literal.
// - The number of positional fields in the context matches the number of
// positional fields in the literal.
// Therefore, the number of named fields in the context must match the
// number of named fields in the literal.
//
// We've also established that for each named field in the literal, there's
// a corresponding named field in the context. Therefore, the literal and
// the context have exactly the same set of named fields. So they match up
// to reordering of named fields.
return contextType;
}

/// Report any named fields in the record literal [node] that use a previously
Expand Down Expand Up @@ -122,47 +131,59 @@ class RecordLiteralResolver {
}
}

void _resolveField(ExpressionImpl field, DartType? contextType) {
_resolver.analyzeExpression(field, contextType);
DartType _resolveField(ExpressionImpl field, DartType? contextType) {
var staticType = _resolver.analyzeExpression(field, contextType);
field = _resolver.popRewrite()!;

// Implicit cast from `dynamic`.
if (contextType != null && field.typeOrThrow is DynamicType) {
field.staticType = contextType;
if (field is NamedExpressionImpl) {
field.expression.staticType = contextType;
if (contextType != null &&
contextType is! UnknownInferredType &&
staticType is DynamicType) {
var greatestClosureOfSchema =
_resolver.typeSystem.greatestClosureOfSchema(contextType);
if (!_resolver.typeSystem
.isSubtypeOf(staticType, greatestClosureOfSchema)) {
return greatestClosureOfSchema;
}
}

if (field.typeOrThrow is VoidType) {
if (staticType is VoidType) {
errorReporter.atNode(
field,
CompileTimeErrorCode.USE_OF_VOID_RESULT,
);
}

return staticType;
}

void _resolveFields(RecordLiteralImpl node, DartType? contextType) {
if (contextType is RecordType) {
var index = 0;
for (final field in node.fields) {
DartType? fieldContextType;
if (field is NamedExpressionImpl) {
final name = field.name.label.name;
fieldContextType = contextType.namedField(name)?.type;
} else {
final positionalFields = contextType.positionalFields;
if (index < positionalFields.length) {
fieldContextType = positionalFields[index++].type;
}
}
_resolveField(field, fieldContextType);
}
} else {
for (final field in node.fields) {
_resolveField(field, null);
final positionalFields = <RecordTypePositionalFieldImpl>[];
final namedFields = <RecordTypeNamedFieldImpl>[];
var contextTypeAsRecord = _matchContextType(node, contextType);
var index = 0;
for (final field in node.fields) {
if (field is NamedExpressionImpl) {
final name = field.name.label.name;
var fieldContextType = contextTypeAsRecord?.namedField(name)!.type;
namedFields.add(RecordTypeNamedFieldImpl(
name: name, type: _resolveField(field, fieldContextType)));
} else {
var fieldContextType =
contextTypeAsRecord?.positionalFields[index++].type;
positionalFields.add(RecordTypePositionalFieldImpl(
type: _resolveField(field, fieldContextType)));
}
}

_resolver.inferenceHelper.recordStaticType(
node,
RecordTypeImpl(
positionalFields: positionalFields,
namedFields: namedFields,
nullabilitySuffix: NullabilitySuffix.none,
),
);
}

/// Returns whether [name] is a name forbidden for record fields because it
Expand Down
Loading

0 comments on commit a30222a

Please sign in to comment.