Skip to content

Commit 523f03a

Browse files
kallentuCommit Queue
authored and
Commit Queue
committed
[cfe] Local and top level function wildcard type parameters are non-binding.
This CL adds `isWildcard` to `StructuralVariableBuilder` and allows type variables in functions and function types. It also removes them from scope so they can't be used. Bug: #55655 Change-Id: I26237375480318dd0c9a01cb59b3426b783ca7be Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/372240 Reviewed-by: Johnni Winther <[email protected]> Commit-Queue: Kallen Tu <[email protected]> Reviewed-by: Chloe Stefantsova <[email protected]>
1 parent 5e12a4a commit 523f03a

20 files changed

+117
-10
lines changed

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

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -578,14 +578,17 @@ class StructuralVariableBuilder extends TypeVariableBuilderBase {
578578

579579
final StructuralParameter actualParameter;
580580

581+
final bool isWildcard;
582+
581583
@override
582584
StructuralVariableBuilder? actualOrigin;
583585

584586
StructuralVariableBuilder(
585587
String name, Builder? compilationUnit, int charOffset, Uri? fileUri,
586588
{TypeBuilder? bound,
587589
Variance? variableVariance,
588-
List<MetadataBuilder>? metadata})
590+
List<MetadataBuilder>? metadata,
591+
this.isWildcard = false})
589592
: actualParameter =
590593
new StructuralParameter(name == noNameSentinel ? null : name, null)
591594
..fileOffset = charOffset
@@ -596,7 +599,8 @@ class StructuralVariableBuilder extends TypeVariableBuilderBase {
596599
variableVariance: variableVariance,
597600
metadata: metadata);
598601

599-
StructuralVariableBuilder.fromKernel(StructuralParameter parameter)
602+
StructuralVariableBuilder.fromKernel(StructuralParameter parameter,
603+
{this.isWildcard = false})
600604
: actualParameter = parameter,
601605
// TODO(johnniwinther): Do we need to support synthesized type
602606
// parameters from kernel?

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

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5137,6 +5137,7 @@ class BodyBuilder extends StackListenerImpl
51375137
kind: ScopeKind.typeParameters));
51385138
if (nominalVariableBuilders != null) {
51395139
for (NominalVariableBuilder builder in nominalVariableBuilders) {
5140+
if (builder.isWildcard) continue;
51405141
String name = builder.name;
51415142
NominalVariableBuilder? existing = scope.lookupLocalMember(name,
51425143
setter: false) as NominalVariableBuilder?;
@@ -5158,6 +5159,7 @@ class BodyBuilder extends StackListenerImpl
51585159
kind: ScopeKind.typeParameters));
51595160
if (structuralVariableBuilders != null) {
51605161
for (StructuralVariableBuilder builder in structuralVariableBuilders) {
5162+
if (builder.isWildcard) continue;
51615163
String name = builder.name;
51625164
StructuralVariableBuilder? existing = scope.lookupLocalMember(name,
51635165
setter: false) as StructuralVariableBuilder?;
@@ -8798,10 +8800,14 @@ class BodyBuilder extends StackListenerImpl
87988800
}
87998801
TypeVariableBuilderBase variable = inFunctionType
88008802
? new StructuralVariableBuilder(
8801-
typeVariableName, libraryBuilder, typeVariableCharOffset, uri)
8803+
typeVariableName, libraryBuilder, typeVariableCharOffset, uri,
8804+
isWildcard: libraryFeatures.wildcardVariables.isEnabled &&
8805+
typeVariableName == '_')
88028806
: new NominalVariableBuilder(
88038807
typeVariableName, libraryBuilder, typeVariableCharOffset, uri,
8804-
kind: TypeVariableKind.function);
8808+
kind: TypeVariableKind.function,
8809+
isWildcard: libraryFeatures.wildcardVariables.isEnabled &&
8810+
typeVariableName == '_');
88058811
if (annotations != null) {
88068812
switch (variable) {
88078813
case StructuralVariableBuilder():

pkg/front_end/lib/src/fasta/source/source_function_builder.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,7 @@ abstract class SourceFunctionBuilderImpl extends SourceMemberBuilderImpl
259259
if (typeVariables == null) return parent;
260260
Map<String, Builder> local = <String, Builder>{};
261261
for (NominalVariableBuilder variable in typeVariables!) {
262+
if (variable.isWildcard) continue;
262263
local[variable.name] = variable;
263264
}
264265
return new Scope(

pkg/front_end/lib/src/fasta/source/source_library_builder.dart

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2539,6 +2539,7 @@ class SourceCompilationUnitImpl implements SourceCompilationUnit {
25392539
Map<String, StructuralVariableBuilder> typeVariablesByName =
25402540
<String, StructuralVariableBuilder>{};
25412541
for (StructuralVariableBuilder tv in typeVariables) {
2542+
if (tv.isWildcard) continue;
25422543
StructuralVariableBuilder? existing = typeVariablesByName[tv.name];
25432544
if (existing != null) {
25442545
addProblem(messageTypeVariableDuplicatedName, tv.charOffset,
@@ -2600,7 +2601,9 @@ class SourceCompilationUnitImpl implements SourceCompilationUnit {
26002601
Uri fileUri) {
26012602
StructuralVariableBuilder builder = new StructuralVariableBuilder(
26022603
name, _sourceLibraryBuilder, charOffset, fileUri,
2603-
bound: bound, metadata: metadata);
2604+
bound: bound,
2605+
metadata: metadata,
2606+
isWildcard: libraryFeatures.wildcardVariables.isEnabled && name == '_');
26042607

26052608
unboundStructuralVariables.add(builder);
26062609
return builder;
@@ -2677,8 +2680,7 @@ class SourceCompilationUnitImpl implements SourceCompilationUnit {
26772680
kind: kind,
26782681
variableVariance:
26792682
variable.parameter.isLegacyCovariant ? null : variable.variance,
2680-
isWildcard: libraryFeatures.wildcardVariables.isEnabled &&
2681-
variable.isWildcard);
2683+
isWildcard: variable.isWildcard);
26822684
copy.add(newVariable);
26832685
unboundNominalVariables.add(newVariable);
26842686
}
@@ -4453,7 +4455,8 @@ class SourceLibraryBuilder extends LibraryBuilderImpl {
44534455
variable.name, this, variable.charOffset, variable.fileUri,
44544456
bound: variable.bound?.clone(newTypes, this, declaration),
44554457
variableVariance:
4456-
variable.parameter.isLegacyCovariant ? null : variable.variance);
4458+
variable.parameter.isLegacyCovariant ? null : variable.variance,
4459+
isWildcard: variable.isWildcard);
44574460
copy.add(newVariable);
44584461
unboundStructuralVariables.add(newVariable);
44594462
}

pkg/front_end/testcases/wildcard_variables/class_type_parameters.dart

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,4 +24,8 @@ class DoesNotUseTypeVariable<_> {
2424
Type returnsBB() {
2525
return _;
2626
}
27+
28+
Type alsoReturnsBB<_, _ extends int>() {
29+
return _;
30+
}
2731
}

pkg/front_end/testcases/wildcard_variables/class_type_parameters.dart.strong.expect

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@ class DoesNotUseTypeVariable<_ extends core::Object? = dynamic> extends core::Ob
4343
method returnsBB() → core::Type {
4444
return #C3;
4545
}
46+
method alsoReturnsBB<_ extends core::Object? = dynamic, _ extends core::int>() → core::Type {
47+
return #C3;
48+
}
4649
}
4750

4851
constants {

pkg/front_end/testcases/wildcard_variables/class_type_parameters.dart.strong.modular.expect

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@ class DoesNotUseTypeVariable<_ extends core::Object? = dynamic> extends core::Ob
4343
method returnsBB() → core::Type {
4444
return #C3;
4545
}
46+
method alsoReturnsBB<_ extends core::Object? = dynamic, _ extends core::int>() → core::Type {
47+
return #C3;
48+
}
4649
}
4750

4851
constants {

pkg/front_end/testcases/wildcard_variables/class_type_parameters.dart.strong.outline.expect

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,4 +35,6 @@ class DoesNotUseTypeVariable<_ extends core::Object? = dynamic> extends core::Ob
3535
;
3636
method returnsBB() → core::Type
3737
;
38+
method alsoReturnsBB<_ extends core::Object? = dynamic, _ extends core::int>() → core::Type
39+
;
3840
}

pkg/front_end/testcases/wildcard_variables/class_type_parameters.dart.strong.transformed.expect

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@ class DoesNotUseTypeVariable<_ extends core::Object? = dynamic> extends core::Ob
4343
method returnsBB() → core::Type {
4444
return #C3;
4545
}
46+
method alsoReturnsBB<_ extends core::Object? = dynamic, _ extends core::int>() → core::Type {
47+
return #C3;
48+
}
4649
}
4750

4851
constants {

pkg/front_end/testcases/wildcard_variables/class_type_parameters.dart.textual_outline.expect

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,5 @@ class D<_, _> {}
1818

1919
class DoesNotUseTypeVariable<_> {
2020
Type returnsBB() {}
21+
Type alsoReturnsBB<_, _ extends int>() {}
2122
}

pkg/front_end/testcases/wildcard_variables/class_type_parameters.dart.textual_outline_modelled.expect

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ class C<T, _ extends _> extends A<T, _> {
1515
class D<_, _> {}
1616

1717
class DoesNotUseTypeVariable<_> {
18+
Type alsoReturnsBB<_, _ extends int>() {}
1819
Type returnsBB() {}
1920
}
2021

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
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+
typedef F = void Function<_, _ extends int, _>();
6+
7+
void fn(void Function<_, _>() x) {}
8+
void fn1<_, _ extends int>(void Function<_, _>() x) {}
9+
10+
test() {
11+
void foo1(void Function<_, _ extends int>() x) {}
12+
void foo2<_, _ extends int>() {}
13+
void foo3(F x) {}
14+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
library;
2+
import self as self;
3+
import "dart:core" as core;
4+
5+
typedef F = <_ extends core::Object? = dynamic, _ extends core::int = dynamic, _ extends core::Object? = dynamic>() → void;
6+
static method fn(<_ extends core::Object? = dynamic, _ extends core::Object? = dynamic>() → void x) → void {}
7+
static method fn1<_ extends core::Object? = dynamic, _ extends core::int>(<_ extends core::Object? = dynamic, _ extends core::Object? = dynamic>() → void x) → void {}
8+
static method test() → dynamic {
9+
function foo1(<_ extends core::Object? = dynamic, _ extends core::int>() → void x) → void {}
10+
function foo2<_ extends core::Object? = dynamic, _ extends core::int>() → void {}
11+
function foo3(<_ extends core::Object? = dynamic, _ extends core::int = dynamic, _ extends core::Object? = dynamic>() → void x) → void {}
12+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
library;
2+
import self as self;
3+
import "dart:core" as core;
4+
5+
typedef F = <_ extends core::Object? = dynamic, _ extends core::int = dynamic, _ extends core::Object? = dynamic>() → void;
6+
static method fn(<_ extends core::Object? = dynamic, _ extends core::Object? = dynamic>() → void x) → void {}
7+
static method fn1<_ extends core::Object? = dynamic, _ extends core::int>(<_ extends core::Object? = dynamic, _ extends core::Object? = dynamic>() → void x) → void {}
8+
static method test() → dynamic {
9+
function foo1(<_ extends core::Object? = dynamic, _ extends core::int>() → void x) → void {}
10+
function foo2<_ extends core::Object? = dynamic, _ extends core::int>() → void {}
11+
function foo3(<_ extends core::Object? = dynamic, _ extends core::int = dynamic, _ extends core::Object? = dynamic>() → void x) → void {}
12+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
library;
2+
import self as self;
3+
import "dart:core" as core;
4+
5+
typedef F = <_ extends core::Object? = dynamic, _ extends core::int = dynamic, _ extends core::Object? = dynamic>() → void;
6+
static method fn(<_ extends core::Object? = dynamic, _ extends core::Object? = dynamic>() → void x) → void
7+
;
8+
static method fn1<_ extends core::Object? = dynamic, _ extends core::int>(<_ extends core::Object? = dynamic, _ extends core::Object? = dynamic>() → void x) → void
9+
;
10+
static method test() → dynamic
11+
;
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
library;
2+
import self as self;
3+
import "dart:core" as core;
4+
5+
typedef F = <_ extends core::Object? = dynamic, _ extends core::int = dynamic, _ extends core::Object? = dynamic>() → void;
6+
static method fn(<_ extends core::Object? = dynamic, _ extends core::Object? = dynamic>() → void x) → void {}
7+
static method fn1<_ extends core::Object? = dynamic, _ extends core::int>(<_ extends core::Object? = dynamic, _ extends core::Object? = dynamic>() → void x) → void {}
8+
static method test() → dynamic {
9+
function foo1(<_ extends core::Object? = dynamic, _ extends core::int>() → void x) → void {}
10+
function foo2<_ extends core::Object? = dynamic, _ extends core::int>() → void {}
11+
function foo3(<_ extends core::Object? = dynamic, _ extends core::int = dynamic, _ extends core::Object? = dynamic>() → void x) → void {}
12+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
typedef F = void Function<_, _ extends int, _>();
2+
3+
void fn(void Function<_, _>() x) {}
4+
5+
void fn1<_, _ extends int>(void Function<_, _>() x) {}
6+
7+
test() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
test() {}
2+
3+
typedef F = void Function<_, _ extends int, _>();
4+
5+
void fn(void Function<_, _>() x) {}
6+
7+
void fn1<_, _ extends int>(void Function<_, _>() x) {}

tests/language/wildcard_variables/non_binding/top_level_typedef_test.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ void main<_ extends _>() {
2020
_ foo<_ extends _>([_ _ = int]) => _;
2121
_ bar<_ extends _>([_ _ = _]) => int;
2222
Expect.type<Type>(foo());
23-
Expect.type<int>(bar());
23+
Expect.type<Type>(bar());
2424
}
2525

2626
class CConst {

tests/language/wildcard_variables/non_binding/top_level_variable_test.dart

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ import 'package:expect/expect.dart';
1212
var _ = 2;
1313

1414
void main() {
15-
Clas().member();
15+
Clas().member(); // Top level _ is 4 after this call.
16+
_ = 2;
1617

1718
int _ = _;
1819
int _ = 3;

0 commit comments

Comments
 (0)