Skip to content

Commit

Permalink
Version 3.7.0-314.0.dev
Browse files Browse the repository at this point in the history
Merge 2de8b5e into dev
  • Loading branch information
Dart CI committed Jan 10, 2025
2 parents 3202683 + 2de8b5e commit 05e5306
Show file tree
Hide file tree
Showing 169 changed files with 6,037 additions and 3,251 deletions.
2 changes: 1 addition & 1 deletion DEPS
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ vars = {
"markdown_rev": "19aaded4300d24bedcbf52ade792b203ddf030b0",
"material_color_utilities_rev": "799b6ba2f3f1c28c67cc7e0b4f18e0c7d7f3c03e",
# dart-native-interop-team@ is rolling breaking changes manually while the assets features are in experimental.
"native_rev": "0f9cb0bea17cdd39bacc498e36d687d6baddd0a3", # disable tools/rev_sdk_deps.dart
"native_rev": "14368a80bae9e3f381a2e59c91405338d82451ee", # disable tools/rev_sdk_deps.dart
"package_config_rev": "07097d7ae60d40b34ce8daabdce318ecc168b7d1",
"pool_rev": "bf27900420ba382b6e5c0484ab3c79daad703dcd",
"protobuf_rev": "b7dd58cdbd879beee4c3fbf8ee80fce8e97bad26",
Expand Down
4 changes: 1 addition & 3 deletions pkg/_fe_analyzer_shared/lib/src/scanner/string_scanner.dart
Original file line number Diff line number Diff line change
Expand Up @@ -100,9 +100,7 @@ class StringScanner extends AbstractScanner {
bool asciiOnly, int extraOffset, bool allowLazy) {
return new StringTokenImpl.fromSubstring(
type, _string, start, scanOffset + extraOffset, tokenStart,
canonicalize: true,
precedingComments: comments,
allowLazyFoo: allowLazy);
canonicalize: true, precedingComments: comments, allowLazy: allowLazy);
}

@override
Expand Down
8 changes: 4 additions & 4 deletions pkg/_fe_analyzer_shared/lib/src/scanner/token_impl.dart
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,10 @@ class StringTokenImpl extends SimpleToken implements StringToken {
TokenType type, String data, int start, int end, int charOffset,
{bool canonicalize = false,
CommentToken? precedingComments,
bool allowLazyFoo = true})
bool allowLazy = true})
: super(type, charOffset, precedingComments) {
int length = end - start;
if (!allowLazyFoo || length <= LAZY_THRESHOLD) {
if (!allowLazy || length <= LAZY_THRESHOLD) {
valueOrLazySubstring = canonicalize
? canonicalizeSubString(data, start, end)
: data.substring(start, end);
Expand All @@ -73,10 +73,10 @@ class StringTokenImpl extends SimpleToken implements StringToken {
*/
StringTokenImpl.fromUtf8Bytes(TokenType type, Uint8List data, int start,
int end, bool asciiOnly, int charOffset,
{CommentToken? precedingComments, bool allowLazyFoo = true})
{CommentToken? precedingComments, bool allowLazy = true})
: super(type, charOffset, precedingComments) {
int length = end - start;
if (!allowLazyFoo || length <= LAZY_THRESHOLD) {
if (!allowLazy || length <= LAZY_THRESHOLD) {
valueOrLazySubstring =
canonicalizeUtf8SubString(data, start, end, asciiOnly);
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ class Utf8BytesScanner extends AbstractScanner {
bool asciiOnly, int extraOffset, bool allowLazy) {
return new StringTokenImpl.fromUtf8Bytes(
type, _bytes, start, byteOffset + extraOffset, asciiOnly, tokenStart,
precedingComments: comments, allowLazyFoo: allowLazy);
precedingComments: comments, allowLazy: allowLazy);
}

@override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import '../flow_analysis/flow_analysis_operations.dart';
import '../types/shared_type.dart';
import 'nullability_suffix.dart';
import 'type_constraint.dart';

/// Callback API used by the shared type analyzer to query and manipulate the
/// client's representation of variables and types.
Expand Down Expand Up @@ -698,6 +699,40 @@ abstract interface class TypeAnalyzerOperations<
/// Returns [type] suffixed with the [suffix].
TypeStructure withNullabilitySuffixInternal(
TypeStructure type, NullabilitySuffix suffix);

TypeConstraintGenerator<
TypeStructure,
SharedNamedFunctionParameterStructure<TypeStructure>,
Variable,
TypeParameterStructure,
TypeDeclarationType,
TypeDeclaration,
Object>
createTypeConstraintGenerator(
{required TypeConstraintGenerationDataForTesting<TypeStructure,
TypeParameterStructure, Variable, Object>?
typeConstraintGenerationDataForTesting,
required List<TypeParameterStructure> typeParametersToInfer,
required TypeAnalyzerOperations<TypeStructure, Variable,
TypeParameterStructure, TypeDeclarationType, TypeDeclaration>
typeAnalyzerOperations,
required bool inferenceUsingBoundsIsEnabled});

MergedTypeConstraint<TypeStructure, TypeParameterStructure, Variable,
TypeDeclarationType, TypeDeclaration>
mergeInConstraintsFromBound(
{required TypeParameterStructure typeParameterToInfer,
required List<TypeParameterStructure> typeParametersToInfer,
required TypeStructure lower,
required Map<
TypeParameterStructure,
MergedTypeConstraint<TypeStructure, TypeParameterStructure,
Variable, TypeDeclarationType, TypeDeclaration>>
inferencePhaseConstraints,
required TypeConstraintGenerationDataForTesting<TypeStructure,
TypeParameterStructure, Variable, Object>?
dataForTesting,
required bool inferenceUsingBoundsIsEnabled});
}

mixin TypeAnalyzerOperationsMixin<
Expand Down Expand Up @@ -893,6 +928,96 @@ mixin TypeAnalyzerOperationsMixin<
SharedTypeView<TypeStructure> type) {
return new SharedTypeSchemaView(type.unwrapTypeView());
}

@override
MergedTypeConstraint<TypeStructure, TypeParameterStructure, Variable,
TypeDeclarationType, TypeDeclaration>
mergeInConstraintsFromBound(
{required TypeParameterStructure typeParameterToInfer,
required List<TypeParameterStructure> typeParametersToInfer,
required TypeStructure lower,
required Map<
TypeParameterStructure,
MergedTypeConstraint<TypeStructure, TypeParameterStructure,
Variable, TypeDeclarationType, TypeDeclaration>>
inferencePhaseConstraints,
required TypeConstraintGenerationDataForTesting<TypeStructure,
TypeParameterStructure, Variable, Object>?
dataForTesting,
required bool inferenceUsingBoundsIsEnabled}) {
// The type parameter's bound may refer to itself (or other type
// parameters), so we might have to create an additional constraint.
// Consider this example from
// https://github.com/dart-lang/language/issues/3009:
//
// class A<X extends A<X>> {}
// class B extends A<B> {}
// class C extends B {}
// void f<X extends A<X>>(X x) {}
// void main() {
// f(C()); // should infer f<B>(C()).
// }
//
// In order for `f(C())` to be inferred as `f<B>(C())`, we need to
// generate the constraint `X <: B`. To do this, we first take the lower
// constraint we've accumulated so far (which, in this example, is `C`,
// due to the presence of the actual argument `C()`), and use subtype
// constraint generation to match it against the explicit bound (which
// is `A<X>`; hence we perform `C <# A<X>`). If this produces any
// constraints (i.e. `X <: B` in this example), then they are added to
// the set of constraints just before choosing the final type.

TypeStructure typeParameterToInferBound = typeParameterToInfer.bound!;

// TODO(cstefantsova): Pass [dataForTesting] when
// [InferenceDataForTesting] is merged with [TypeInferenceResultForTesting].
TypeConstraintGenerator<
TypeStructure,
SharedNamedFunctionParameterStructure<TypeStructure>,
Variable,
TypeParameterStructure,
TypeDeclarationType,
TypeDeclaration,
Object> typeConstraintGatherer =
createTypeConstraintGenerator(
typeConstraintGenerationDataForTesting: null,
typeParametersToInfer: typeParametersToInfer,
typeAnalyzerOperations: this,
inferenceUsingBoundsIsEnabled: inferenceUsingBoundsIsEnabled);
typeConstraintGatherer.performSubtypeConstraintGenerationInternal(
lower, typeParameterToInferBound,
leftSchema: true, astNodeForTesting: null);
Map<
TypeParameterStructure,
MergedTypeConstraint<
TypeStructure,
TypeParameterStructure,
Variable,
TypeDeclarationType,
TypeDeclaration>> constraintsPerTypeVariable =
typeConstraintGatherer.computeConstraints();
for (TypeParameterStructure typeParameter
in constraintsPerTypeVariable.keys) {
MergedTypeConstraint<TypeStructure, TypeParameterStructure, Variable,
TypeDeclarationType, TypeDeclaration> constraint =
constraintsPerTypeVariable[typeParameter]!;
constraint.origin = new TypeConstraintFromExtendsClause(
typeParameterName: typeParameterToInfer.displayName,
boundType: new SharedTypeView(typeParameterToInferBound),
extendsType: new SharedTypeView(typeParameterToInferBound));
if (!constraint.isEmpty(this)) {
MergedTypeConstraint? constraintForParameter =
inferencePhaseConstraints[typeParameter];
if (constraintForParameter == null) {
inferencePhaseConstraints[typeParameter] = constraint;
} else {
constraintForParameter.mergeInTypeSchemaUpper(constraint.upper, this);
constraintForParameter.mergeInTypeSchemaLower(constraint.lower, this);
}
}
}
return constraintsPerTypeVariable[typeParameterToInfer]!;
}
}

/// Abstract interface of a type constraint generator.
Expand Down Expand Up @@ -1832,6 +1957,12 @@ abstract class TypeConstraintGenerator<

return false;
}

/// Returns the set of type constraints that was gathered.
Map<
TypeParameterStructure,
MergedTypeConstraint<TypeStructure, TypeParameterStructure, Variable,
TypeDeclarationType, TypeDeclaration>> computeConstraints();
}

mixin TypeConstraintGeneratorMixin<
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -365,3 +365,41 @@ class UnknownTypeConstraintOrigin<
return <String>[];
}
}

/// Data structure maintaining intermediate type inference results, such as
/// type constraints, for testing purposes. Under normal execution, no
/// instance of this class should be created.
class TypeConstraintGenerationDataForTesting<
TypeStructure extends SharedTypeStructure<TypeStructure>,
TypeParameterStructure extends SharedTypeParameterStructure<TypeStructure>,
Variable extends Object,
AstNode extends Object> {
/// Map from nodes requiring type inference to the generated type constraints
/// for the node.
final Map<
AstNode,
List<
GeneratedTypeConstraint<TypeStructure, TypeParameterStructure,
Variable>>> generatedTypeConstraints = {};

/// Merges [other] into the receiver, combining the constraints.
///
/// The method reuses data structures from [other] whenever possible, to
/// avoid extra memory allocations. This process is destructive to [other]
/// because the changes made to the reused structures will be visible to
/// [other].
void mergeIn(
TypeConstraintGenerationDataForTesting<TypeStructure,
TypeParameterStructure, Variable, AstNode>
other) {
for (AstNode node in other.generatedTypeConstraints.keys) {
List<GeneratedTypeConstraint>? constraints =
generatedTypeConstraints[node];
if (constraints != null) {
constraints.addAll(other.generatedTypeConstraints[node]!);
} else {
generatedTypeConstraints[node] = other.generatedTypeConstraints[node]!;
}
}
}
}
18 changes: 18 additions & 0 deletions pkg/_fe_analyzer_shared/test/mini_ast.dart
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,14 @@ import 'package:_fe_analyzer_shared/src/type_inference/type_analyzer.dart'
as shared;
import 'package:_fe_analyzer_shared/src/type_inference/type_analyzer.dart'
hide MapPatternEntry, RecordPatternField;
import 'package:_fe_analyzer_shared/src/type_inference/type_constraint.dart';
import 'package:_fe_analyzer_shared/src/type_inference/type_analyzer_operations.dart';
import 'package:_fe_analyzer_shared/src/type_inference/variable_bindings.dart';
import 'package:_fe_analyzer_shared/src/types/shared_type.dart';
import 'package:test/test.dart';

import 'type_inference/type_constraint_gatherer_test.dart';

import 'mini_ir.dart';
import 'mini_types.dart';

Expand Down Expand Up @@ -3225,6 +3228,21 @@ class MiniAstOperations
Type withNullabilitySuffixInternal(Type type, NullabilitySuffix modifier) {
return type.withNullability(modifier);
}

@override
TypeConstraintGenerator<Type, NamedFunctionParameter, Var, TypeParameter,
Type, String, Node>
createTypeConstraintGenerator(
{required TypeConstraintGenerationDataForTesting?
typeConstraintGenerationDataForTesting,
required List<TypeParameter> typeParametersToInfer,
required TypeAnalyzerOperations<Type, Var, TypeParameter, Type,
String>
typeAnalyzerOperations,
required bool inferenceUsingBoundsIsEnabled}) {
return TypeConstraintGatherer(
{for (var typeParameter in typeParametersToInfer) typeParameter.name});
}
}

/// Representation of an expression or statement in the pseudo-Dart language
Expand Down
Loading

0 comments on commit 05e5306

Please sign in to comment.