Skip to content

Commit 1d52761

Browse files
kallentuCommit Queue
authored and
Commit Queue
committed
[cfe] Build a lowered name for wildcard variables.
Each wildcard variable will have a unique name meaning that each local, formal, and type parameter named `_` will be named something similar to `_#wc<index>#<type>`. This will allow the DDC tests to pass. Change-Id: Ic5362e46142c4a51cd461280ca33a8a5ba5b910f Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/373621 Reviewed-by: Chloe Stefantsova <[email protected]> Commit-Queue: Kallen Tu <[email protected]>
1 parent 0ca3991 commit 1d52761

File tree

46 files changed

+375
-179
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+375
-179
lines changed

pkg/front_end/lib/src/api_prototype/lowering_predicates.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ export '../kernel/constructor_tearoff_lowering.dart'
1212
isConstructorTearOffLowering,
1313
isTearOffLowering,
1414
isTypedefTearOffLowering;
15+
export '../kernel/wildcard_lowering.dart';
1516

1617
// Coverage-ignore(suite): Not run.
1718
/// Returns `true` if [node] is the field holding the value of a lowered late

pkg/front_end/lib/src/base/scope.dart

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -344,13 +344,7 @@ class TypeParameterScope with LookupScopeMixin {
344344
if (typeVariableBuilders == null) return parent;
345345
Map<String, Builder> map = {};
346346
for (TypeVariableBuilderBase typeVariableBuilder in typeVariableBuilders) {
347-
// TODO(johnniwinther,kallentu): Why are structural variables treated
348-
// differently from nominal variable here but not for instance in
349-
// `BodyBuilder.enterStructuralVariablesScope`?
350-
if (typeVariableBuilder is NominalVariableBuilder &&
351-
typeVariableBuilder.isWildcard) {
352-
continue;
353-
}
347+
if (typeVariableBuilder.isWildcard) continue;
354348
map[typeVariableBuilder.name] = typeVariableBuilder;
355349
}
356350
return new TypeParameterScope(parent, map);

pkg/front_end/lib/src/builder/formal_parameter_builder.dart

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import '../base/scope.dart' show LookupScope;
1717
import '../kernel/body_builder.dart' show BodyBuilder;
1818
import '../kernel/body_builder_context.dart';
1919
import '../kernel/internal_ast.dart' show VariableDeclarationImpl;
20+
import '../kernel/wildcard_lowering.dart';
2021
import '../source/constructor_declaration.dart';
2122
import '../source/builder_factory.dart';
2223
import '../source/source_factory_builder.dart';
@@ -197,8 +198,10 @@ class FormalParameterBuilder extends ModifierBuilderImpl
197198
}
198199

199200
FormalParameterBuilder forPrimaryConstructor(BuilderFactory builderFactory) {
201+
// Primary constructors should not have a lowered wildcard name.
202+
String formalName = isWildcardLoweredFormalParameter(name) ? '_' : name;
200203
return new FormalParameterBuilder(kind, modifiers | initializingFormalMask,
201-
builderFactory.addInferableType(), name, null, charOffset,
204+
builderFactory.addInferableType(), formalName, null, charOffset,
202205
fileUri: fileUri,
203206
isExtensionThis: isExtensionThis,
204207
hasImmediatelyDeclaredInitializer: hasImmediatelyDeclaredInitializer)

pkg/front_end/lib/src/builder/type_variable_builder.dart

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ sealed class TypeVariableBuilderBase extends TypeDeclarationBuilderImpl
3232

3333
final TypeVariableKind kind;
3434

35+
final bool isWildcard;
36+
3537
@override
3638
final Uri? fileUri;
3739

@@ -41,7 +43,8 @@ sealed class TypeVariableBuilderBase extends TypeDeclarationBuilderImpl
4143
this.defaultType,
4244
required this.kind,
4345
Variance? variableVariance,
44-
List<MetadataBuilder>? metadata})
46+
List<MetadataBuilder>? metadata,
47+
this.isWildcard = false})
4548
: super(metadata, 0, name, compilationUnit, charOffset);
4649

4750
@override
@@ -191,8 +194,6 @@ class NominalVariableBuilder extends TypeVariableBuilderBase {
191194

192195
final TypeParameter actualParameter;
193196

194-
final bool isWildcard;
195-
196197
@override
197198
NominalVariableBuilder? actualOrigin;
198199

@@ -202,7 +203,7 @@ class NominalVariableBuilder extends TypeVariableBuilderBase {
202203
required TypeVariableKind kind,
203204
Variance? variableVariance,
204205
List<MetadataBuilder>? metadata,
205-
this.isWildcard = false})
206+
super.isWildcard = false})
206207
: actualParameter =
207208
new TypeParameter(name == noNameSentinel ? null : name, null)
208209
..fileOffset = charOffset
@@ -226,7 +227,7 @@ class NominalVariableBuilder extends TypeVariableBuilderBase {
226227
///
227228
/// class A<X extends A<X>> {}
228229
NominalVariableBuilder.fromKernel(TypeParameter parameter,
229-
{required Loader? loader, this.isWildcard = false})
230+
{required Loader? loader, super.isWildcard = false})
230231
: actualParameter = parameter,
231232
// TODO(johnniwinther): Do we need to support synthesized type
232233
// parameters from kernel?
@@ -587,8 +588,6 @@ class StructuralVariableBuilder extends TypeVariableBuilderBase {
587588

588589
final StructuralParameter actualParameter;
589590

590-
final bool isWildcard;
591-
592591
@override
593592
StructuralVariableBuilder? actualOrigin;
594593

@@ -597,7 +596,7 @@ class StructuralVariableBuilder extends TypeVariableBuilderBase {
597596
{TypeBuilder? bound,
598597
Variance? variableVariance,
599598
List<MetadataBuilder>? metadata,
600-
this.isWildcard = false})
599+
super.isWildcard = false})
601600
: actualParameter =
602601
new StructuralParameter(name == noNameSentinel ? null : name, null)
603602
..fileOffset = charOffset
@@ -609,7 +608,7 @@ class StructuralVariableBuilder extends TypeVariableBuilderBase {
609608
metadata: metadata);
610609

611610
StructuralVariableBuilder.fromKernel(StructuralParameter parameter,
612-
{this.isWildcard = false})
611+
{super.isWildcard = false})
613612
: actualParameter = parameter,
614613
// TODO(johnniwinther): Do we need to support synthesized type
615614
// parameters from kernel?

pkg/front_end/lib/src/kernel/body_builder.dart

Lines changed: 50 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ import 'package:kernel/type_algebra.dart';
4444
import 'package:kernel/type_environment.dart';
4545

4646
import '../api_prototype/experimental_flags.dart';
47+
import '../api_prototype/lowering_predicates.dart';
4748
import '../base/constant_context.dart' show ConstantContext;
4849
import '../base/identifiers.dart'
4950
show
@@ -105,7 +106,6 @@ import 'benchmarker.dart' show Benchmarker;
105106
import 'body_builder_context.dart';
106107
import 'collections.dart';
107108
import 'constness.dart' show Constness;
108-
import 'constructor_tearoff_lowering.dart';
109109
import 'expression_generator.dart';
110110
import 'expression_generator_helper.dart';
111111
import 'forest.dart' show Forest;
@@ -430,6 +430,9 @@ class BodyBuilder extends StackListenerImpl
430430

431431
JumpTarget? continueTarget;
432432

433+
/// Index for building unique lowered names for wildcard variables.
434+
int wildcardVariableIndex = 0;
435+
433436
BodyBuilder(
434437
{required this.libraryBuilder,
435438
required BodyBuilderContext context,
@@ -1924,17 +1927,24 @@ class BodyBuilder extends StackListenerImpl
19241927
: new List<FormalParameterBuilder>.generate(
19251928
parameters.positionalParameters.length, (int i) {
19261929
VariableDeclaration formal = parameters.positionalParameters[i];
1930+
String formalName = formal.name!;
1931+
bool isWildcard = libraryFeatures.wildcardVariables.isEnabled &&
1932+
formalName == '_';
1933+
if (isWildcard) {
1934+
formalName =
1935+
createWildcardFormalParameterName(wildcardVariableIndex);
1936+
wildcardVariableIndex++;
1937+
}
19271938
return new FormalParameterBuilder(
19281939
FormalParameterKind.requiredPositional,
19291940
/* modifiers = */ 0,
19301941
const ImplicitTypeBuilder(),
1931-
formal.name!,
1942+
formalName,
19321943
libraryBuilder,
19331944
formal.fileOffset,
19341945
fileUri: uri,
19351946
hasImmediatelyDeclaredInitializer: false,
1936-
isWildcard: libraryFeatures.wildcardVariables.isEnabled &&
1937-
formal.name! == '_')
1947+
isWildcard: isWildcard)
19381948
..variable = formal;
19391949
}, growable: false);
19401950
enterLocalScope(new FormalParameters(formals, fileOffset, noLength, uri)
@@ -3950,7 +3960,14 @@ class BodyBuilder extends StackListenerImpl
39503960
bool isLate = (currentLocalVariableModifiers & lateMask) != 0;
39513961
bool isRequired = (currentLocalVariableModifiers & requiredMask) != 0;
39523962
assert(isConst == (constantContext == ConstantContext.inferred));
3953-
VariableDeclaration variable = new VariableDeclarationImpl(identifier.name,
3963+
String name = identifier.name;
3964+
bool isWildcard =
3965+
libraryFeatures.wildcardVariables.isEnabled && name == '_';
3966+
if (isWildcard) {
3967+
name = createWildcardVariableName(wildcardVariableIndex);
3968+
wildcardVariableIndex++;
3969+
}
3970+
VariableDeclaration variable = new VariableDeclarationImpl(name,
39543971
forSyntheticToken: identifier.token.isSynthetic,
39553972
initializer: initializer,
39563973
type: currentLocalVariableType,
@@ -3960,8 +3977,7 @@ class BodyBuilder extends StackListenerImpl
39603977
isRequired: isRequired,
39613978
hasDeclaredInitializer: initializer != null,
39623979
isStaticLate: isFinal && initializer == null,
3963-
isWildcard: identifier.name == '_' &&
3964-
libraryFeatures.wildcardVariables.isEnabled)
3980+
isWildcard: isWildcard)
39653981
..fileOffset = identifier.nameOffset
39663982
..fileEqualsOffset = offsetForToken(equalsToken);
39673983
typeInferrer.assignedVariables.declare(variable);
@@ -5647,6 +5663,13 @@ class BodyBuilder extends StackListenerImpl
56475663
}
56485664
} else {
56495665
String parameterName = name?.name ?? '';
5666+
bool isWildcard =
5667+
libraryFeatures.wildcardVariables.isEnabled && parameterName == '_';
5668+
if (isWildcard) {
5669+
parameterName =
5670+
createWildcardFormalParameterName(wildcardVariableIndex);
5671+
wildcardVariableIndex++;
5672+
}
56505673
parameter = new FormalParameterBuilder(
56515674
kind,
56525675
modifiers,
@@ -7427,12 +7450,18 @@ class BodyBuilder extends StackListenerImpl
74277450
debugEvent("FunctionName");
74287451
Identifier name = pop() as Identifier;
74297452
Token nameToken = name.token;
7430-
VariableDeclaration variable = new VariableDeclarationImpl(name.name,
7453+
String identifierName = name.name;
7454+
bool isWildcard =
7455+
libraryFeatures.wildcardVariables.isEnabled && identifierName == '_';
7456+
if (isWildcard) {
7457+
identifierName = createWildcardVariableName(wildcardVariableIndex);
7458+
wildcardVariableIndex++;
7459+
}
7460+
VariableDeclaration variable = new VariableDeclarationImpl(identifierName,
74317461
forSyntheticToken: nameToken.isSynthetic,
74327462
isFinal: true,
74337463
isLocalFunction: true,
7434-
isWildcard:
7435-
libraryFeatures.wildcardVariables.isEnabled && name.name == '_')
7464+
isWildcard: isWildcard)
74367465
..fileOffset = name.nameOffset;
74377466
// TODO(ahe): Why are we looking up in local scope, but declaring in parent
74387467
// scope?
@@ -9013,16 +9042,19 @@ class BodyBuilder extends StackListenerImpl
90139042
unhandled("${name.runtimeType}", "beginTypeVariable.name",
90149043
token.charOffset, uri);
90159044
}
9045+
bool isWildcard =
9046+
libraryFeatures.wildcardVariables.isEnabled && typeVariableName == '_';
9047+
if (isWildcard) {
9048+
typeVariableName = createWildcardTypeVariableName(wildcardVariableIndex);
9049+
wildcardVariableIndex++;
9050+
}
90169051
TypeVariableBuilderBase variable = inFunctionType
90179052
? new StructuralVariableBuilder(
90189053
typeVariableName, libraryBuilder, typeVariableCharOffset, uri,
9019-
isWildcard: libraryFeatures.wildcardVariables.isEnabled &&
9020-
typeVariableName == '_')
9054+
isWildcard: isWildcard)
90219055
: new NominalVariableBuilder(
90229056
typeVariableName, libraryBuilder, typeVariableCharOffset, uri,
9023-
kind: TypeVariableKind.function,
9024-
isWildcard: libraryFeatures.wildcardVariables.isEnabled &&
9025-
typeVariableName == '_');
9057+
kind: TypeVariableKind.function, isWildcard: isWildcard);
90269058
if (annotations != null) {
90279059
switch (variable) {
90289060
case StructuralVariableBuilder():
@@ -9244,6 +9276,9 @@ class BodyBuilder extends StackListenerImpl
92449276
List<Initializer> buildFieldInitializer(String name, int fieldNameOffset,
92459277
int assignmentOffset, Expression expression,
92469278
{FormalParameterBuilder? formal}) {
9279+
if (isWildcardLoweredFormalParameter(name)) {
9280+
name = '_';
9281+
}
92479282
Builder? builder = _context.lookupLocalMember(name);
92489283
if (builder?.next != null) {
92499284
// Duplicated name, already reported.
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
const String wildcardPrefix = '_#wc';
6+
const String wildcardFormalSuffix = '#formal';
7+
const String wildcardTypeVariableSuffix = '#type';
8+
const String wildcardVariableSuffix = '#var';
9+
10+
/// Returns the named used for a wildcard formal parameter using [index].
11+
String createWildcardFormalParameterName(int index) {
12+
return '$wildcardPrefix$index$wildcardFormalSuffix';
13+
}
14+
15+
/// Returns the named used for a wildcard type variable using [index].
16+
String createWildcardTypeVariableName(int index) {
17+
return '$wildcardPrefix$index$wildcardTypeVariableSuffix';
18+
}
19+
20+
/// Returns the named used for a wildcard variable using [index].
21+
String createWildcardVariableName(int index) {
22+
return '$wildcardPrefix$index$wildcardVariableSuffix';
23+
}
24+
25+
/// Whether the given [name] is a wildcard formal parameter.
26+
bool isWildcardLoweredFormalParameter(String name) {
27+
return name.startsWith(wildcardPrefix) && name.endsWith(wildcardFormalSuffix);
28+
}
29+
30+
/// Whether the given [name] is a wildcard type variable.
31+
bool isWildcardLoweredTypeVariable(String name) {
32+
return name.startsWith(wildcardPrefix) &&
33+
name.endsWith(wildcardTypeVariableSuffix);
34+
}
35+
36+
/// Whether the given [name] is a wildcard variable.
37+
bool isWildcardLoweredVariable(String name) {
38+
return name.startsWith(wildcardPrefix) &&
39+
name.endsWith(wildcardVariableSuffix);
40+
}

pkg/front_end/lib/src/source/outline_builder.dart

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1724,14 +1724,17 @@ class OutlineBuilder extends StackListenerImpl {
17241724
if (formal.isNamed) {
17251725
firstNamedParameterOffset = formal.charOffset;
17261726
}
1727+
// Primary constructors should not have a lowered wildcard name.
1728+
String formalName =
1729+
isWildcardLoweredFormalParameter(formal.name) ? '_' : formal.name;
17271730
_builderFactory.addPrimaryConstructorField(
17281731
// TODO(johnniwinther): Support annotations on annotations on fields
17291732
// defined through a primary constructor. This is not needed for
17301733
// extension types where the field is not part of the AST but will
17311734
// be needed when primary constructors are generally supported.
17321735
metadata: null,
17331736
type: formal.type,
1734-
name: formal.name,
1737+
name: formalName,
17351738
charOffset: formal.charOffset);
17361739
formals[i] = formal.forPrimaryConstructor(_builderFactory);
17371740
}

0 commit comments

Comments
 (0)