[cfe] Add LocalTypeParameterScope

This cleans up the LocalScope interface and the handling of named function expressions.

Change-Id: Id0432910a9e65d8ae966dfab67c66248639d241a
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/419842
Reviewed-by: Chloe Stefantsova <cstefantsova@google.com>
Commit-Queue: Johnni Winther <johnniwinther@google.com>
This commit is contained in:
Johnni Winther
2025-04-03 03:43:30 -07:00
committed by Commit Queue
parent bdf0f64b2f
commit dced5e0482
42 changed files with 284 additions and 108 deletions
@@ -966,8 +966,9 @@ class ForwardingListener implements Listener {
}
@override
void endFunctionName(Token beginToken, Token token) {
listener?.endFunctionName(beginToken, token);
void endFunctionName(
Token beginToken, Token token, bool isFunctionExpression) {
listener?.endFunctionName(beginToken, token, isFunctionExpression);
}
@override
@@ -812,7 +812,23 @@ class Listener implements UnescapeErrorListener {
void beginFunctionName(Token token) {}
void endFunctionName(Token beginToken, Token token) {
/// The end of the function name in either a local function declaration, like
/// 'local' in:
///
/// void m() {
/// void local() {}
/// }
///
/// or an erroneous function expression, like 'local' in:
///
/// void m() {
/// var f = void local() {};
/// }
///
/// The boolean [isFunctionExpression] indicates that we are in the latter
/// case.
void endFunctionName(
Token beginToken, Token token, bool isFunctionExpression) {
logEvent("FunctionName");
}
@@ -5222,7 +5222,7 @@ class Parser {
reportRecoverableError(
beforeName.next!, codes.messageNamedFunctionExpression);
}
listener.endFunctionName(begin, token);
listener.endFunctionName(begin, token, isFunctionExpression);
token = parseFormalParametersRequiredOpt(formals, MemberKind.Local);
token = parseInitializersOpt(token);
token = parseAsyncOptBody(
+2 -1
View File
@@ -2105,7 +2105,8 @@ class AstBuilder extends StackListener {
}
@override
void endFunctionName(Token beginToken, Token token) {
void endFunctionName(
Token beginToken, Token token, bool isFunctionExpression) {
debugEvent("FunctionName");
}
@@ -981,9 +981,9 @@ class ForwardingTestListener extends ForwardingListener {
}
@override
void endFunctionName(Token beginToken, Token token) {
void endFunctionName(Token beginToken, Token token, bool isFunctionExpression) {
end('FunctionName');
super.endFunctionName(beginToken, token);
super.endFunctionName(beginToken, token, isFunctionExpression);
}
@override
+33 -16
View File
@@ -4,6 +4,7 @@
import '../builder/builder.dart';
import '../builder/declaration_builders.dart';
import '../builder/variable_builder.dart';
import 'scope.dart';
abstract class LocalScope implements LookupScope {
@@ -27,9 +28,7 @@ abstract class LocalScope implements LookupScope {
/// If name was used previously in this scope, this method returns the read
/// offsets which can be used for reporting a compile-time error about
/// [name] being used before its declared.
List<int>? declare(String name, Builder builder);
void addLocalVariable(String name, Builder builder);
List<int>? declare(String name, VariableBuilder builder);
@override
Builder? lookupGetable(String name, int charOffset, Uri fileUri);
@@ -117,7 +116,7 @@ final class LocalScopeImpl extends BaseLocalScope
/// Names declared in this scope.
@override
Map<String, Builder>? _local;
Map<String, VariableBuilder>? _local;
@override
Map<String, List<int>>? usedNames;
@@ -128,12 +127,7 @@ final class LocalScopeImpl extends BaseLocalScope
LocalScopeImpl(this._parent, this.kind, this.classNameOrDebugName);
@override
void addLocalVariable(String name, Builder builder) {
(_local ??= {})[name] = builder;
}
@override
List<int>? declare(String name, Builder builder) {
List<int>? declare(String name, VariableBuilder builder) {
List<int>? previousOffsets = usedNames?[name];
if (previousOffsets != null && previousOffsets.isNotEmpty) {
return previousOffsets;
@@ -157,12 +151,7 @@ final class LocalScopeImpl extends BaseLocalScope
mixin ImmutableLocalScopeMixin implements LocalScope {
@override
void addLocalVariable(String name, Builder builder) {
throw new UnsupportedError('$runtimeType($kind).addLocalMember');
}
@override
List<int>? declare(String name, Builder builder) {
List<int>? declare(String name, VariableBuilder builder) {
throw new UnsupportedError('$runtimeType($kind).declare');
}
@@ -171,6 +160,34 @@ mixin ImmutableLocalScopeMixin implements LocalScope {
Map<String, List<int>>? get usedNames => null;
}
final class LocalTypeParameterScope extends BaseLocalScope
with LookupScopeMixin, ImmutableLocalScopeMixin, LocalScopeMixin {
@override
final LocalScope? _parent;
@override
final ScopeKind kind;
@override
final Map<String, TypeParameterBuilder>? _local;
final String _debugName;
LocalTypeParameterScope(
{required this.kind,
LocalScope? parent,
Map<String, TypeParameterBuilder>? local,
required String debugName})
: _parent = parent,
_local = local,
_debugName = debugName;
@override
String get classNameOrDebugName => _debugName;
@override
String toString() =>
"$runtimeType(${kind}, $classNameOrDebugName, ${_local?.keys})";
}
final class FixedLocalScope extends BaseLocalScope
with LookupScopeMixin, ImmutableLocalScopeMixin, LocalScopeMixin {
@override
+30 -17
View File
@@ -5085,41 +5085,49 @@ class BodyBuilder extends StackListenerImpl
void enterNominalVariablesScope(
List<NominalParameterBuilder>? nominalVariableBuilders) {
debugEvent("enterNominalVariableScope");
enterLocalScope(_localScope.createNestedScope(
debugName: "function-type scope", kind: ScopeKind.typeParameters));
Map<String, TypeParameterBuilder> typeParameters = {};
if (nominalVariableBuilders != null) {
for (NominalParameterBuilder builder in nominalVariableBuilders) {
if (builder.isWildcard) continue;
String name = builder.name;
Builder? existing = _localScope.lookupLocalVariable(name);
TypeParameterBuilder? existing = typeParameters[name];
if (existing == null) {
_localScope.addLocalVariable(name, builder);
typeParameters[name] = builder;
} else {
// Coverage-ignore-block(suite): Not run.
reportDuplicatedDeclaration(existing, name, builder.fileOffset);
}
}
}
enterLocalScope(new LocalTypeParameterScope(
local: typeParameters,
parent: _localScope,
debugName: "local function type parameter scope",
kind: ScopeKind.typeParameters));
}
void enterStructuralVariablesScope(
List<StructuralParameterBuilder>? structuralVariableBuilders) {
debugEvent("enterStructuralVariableScope");
enterLocalScope(_localScope.createNestedScope(
debugName: "function-type scope", kind: ScopeKind.typeParameters));
Map<String, TypeParameterBuilder> typeParameters = {};
if (structuralVariableBuilders != null) {
for (StructuralParameterBuilder builder in structuralVariableBuilders) {
if (builder.isWildcard) continue;
String name = builder.name;
Builder? existing = _localScope.lookupLocalVariable(name);
TypeParameterBuilder? existing = typeParameters[name];
if (existing == null) {
_localScope.addLocalVariable(name, builder);
typeParameters[name] = builder;
} else {
// Coverage-ignore-block(suite): Not run.
reportDuplicatedDeclaration(existing, name, builder.fileOffset);
}
}
}
enterLocalScope(new LocalTypeParameterScope(
local: typeParameters,
parent: _localScope,
debugName: "function-type scope",
kind: ScopeKind.typeParameters));
}
@override
@@ -7273,7 +7281,8 @@ class BodyBuilder extends StackListenerImpl
void handleNamedRecordField(Token colon) => handleNamedArgument(colon);
@override
void endFunctionName(Token beginToken, Token token) {
void endFunctionName(
Token beginToken, Token token, bool isFunctionExpression) {
debugEvent("FunctionName");
Identifier name = pop() as Identifier;
Token nameToken = name.token;
@@ -7290,20 +7299,24 @@ class BodyBuilder extends StackListenerImpl
isLocalFunction: true,
isWildcard: isWildcard)
..fileOffset = name.nameOffset;
// TODO(ahe): Why are we looking up in local scope, but declaring in parent
// scope?
Builder? existing = _localScope.lookupLocalVariable(name.name);
if (existing != null) {
// Coverage-ignore-block(suite): Not run.
reportDuplicatedDeclaration(existing, name.name, name.nameOffset);
}
push(new FunctionDeclarationImpl(
variable,
// The real function node is created later.
dummyFunctionNode)
..fileOffset = beginToken.charOffset);
if (!(libraryFeatures.wildcardVariables.isEnabled && variable.isWildcard)) {
declareVariable(variable, _localScopes.previous);
// The local scope stack contains a type parameter scope for the local
// function on top of the scope for the block in which the local function
// declaration occurs. So for a local function declaration, we add the
// declaration to the previous scope, i.e. the block scope.
//
// For a named function expression, a nested scope is created to hold the
// name, so that it doesn't pollute the block scope (the named function
// expression is erroneous and should introduce the name in the scope) and
// we therefore use the current scope in this case.
LocalScope scope =
isFunctionExpression ? _localScope : _localScopes.previous;
declareVariable(variable, scope);
}
}
@@ -1054,9 +1054,12 @@ abstract class AbstractParserAstListener implements Listener {
}
@override
void endFunctionName(Token beginToken, Token token) {
void endFunctionName(
Token beginToken, Token token, bool isFunctionExpression) {
FunctionNameEnd data = new FunctionNameEnd(ParserAstType.END,
beginToken: beginToken, token: token);
beginToken: beginToken,
token: token,
isFunctionExpression: isFunctionExpression);
seen(data);
}
@@ -5373,15 +5376,19 @@ class FunctionNameBegin extends ParserAstNode {
class FunctionNameEnd extends ParserAstNode {
final Token beginToken;
final Token token;
final bool isFunctionExpression;
FunctionNameEnd(ParserAstType type,
{required this.beginToken, required this.token})
{required this.beginToken,
required this.token,
required this.isFunctionExpression})
: super("FunctionName", type);
@override
Map<String, Object?> get deprecatedArguments => {
"beginToken": beginToken,
"token": token,
"isFunctionExpression": isFunctionExpression,
};
@override
@@ -818,7 +818,7 @@ beginCompilationUnit(Future)
handleType(await, null)
beginFunctionName(foo)
handleIdentifier(foo, localFunctionDeclaration)
endFunctionName(await, ()
endFunctionName(await, (, false)
beginFormalParameters((, MemberKind.Local)
beginMetadataStar(int)
endMetadataStar(0)
@@ -855,7 +855,7 @@ beginCompilationUnit(Future)
handleType(await, null)
beginFunctionName(bar)
handleIdentifier(bar, localFunctionDeclaration)
endFunctionName(await, ()
endFunctionName(await, (, false)
beginFormalParameters((, MemberKind.Local)
beginMetadataStar(await)
endMetadataStar(0)
@@ -2019,7 +2019,7 @@ parseUnit(Future)
listener: beginFunctionName(foo)
ensureIdentifier(await, localFunctionDeclaration)
listener: handleIdentifier(foo, localFunctionDeclaration)
listener: endFunctionName(await, ()
listener: endFunctionName(await, (, false)
parseFormalParametersRequiredOpt(foo, MemberKind.Local)
parseFormalParametersRest((, MemberKind.Local)
listener: beginFormalParameters((, MemberKind.Local)
@@ -2096,7 +2096,7 @@ parseUnit(Future)
listener: beginFunctionName(bar)
ensureIdentifier(await, localFunctionDeclaration)
listener: handleIdentifier(bar, localFunctionDeclaration)
listener: endFunctionName(await, ()
listener: endFunctionName(await, (, false)
parseFormalParametersRequiredOpt(bar, MemberKind.Local)
parseFormalParametersRest((, MemberKind.Local)
listener: beginFormalParameters((, MemberKind.Local)
@@ -96,7 +96,7 @@ beginCompilationUnit(import)
handleVoidKeyword(void)
beginFunctionName(writeMessage)
handleIdentifier(writeMessage, localFunctionDeclaration)
endFunctionName(void, ()
endFunctionName(void, (, false)
beginFormalParameters((, MemberKind.Local)
beginMetadataStar(String)
endMetadataStar(0)
@@ -200,7 +200,7 @@ parseUnit(import)
listener: beginFunctionName(writeMessage)
ensureIdentifier(void, localFunctionDeclaration)
listener: handleIdentifier(writeMessage, localFunctionDeclaration)
listener: endFunctionName(void, ()
listener: endFunctionName(void, (, false)
parseFormalParametersRequiredOpt(writeMessage, MemberKind.Local)
parseFormalParametersRest((, MemberKind.Local)
listener: beginFormalParameters((, MemberKind.Local)
@@ -91,7 +91,7 @@ beginCompilationUnit(import)
handleNoType(;)
beginFunctionName(getNumber)
handleIdentifier(getNumber, localFunctionDeclaration)
endFunctionName(getNumber, ()
endFunctionName(getNumber, (, false)
beginFormalParameters((, MemberKind.Local)
endFormalParameters(0, (, ), MemberKind.Local)
handleNoInitializers()
@@ -196,7 +196,7 @@ parseUnit(import)
listener: beginFunctionName(getNumber)
ensureIdentifier(;, localFunctionDeclaration)
listener: handleIdentifier(getNumber, localFunctionDeclaration)
listener: endFunctionName(getNumber, ()
listener: endFunctionName(getNumber, (, false)
parseFormalParametersRequiredOpt(getNumber, MemberKind.Local)
parseFormalParametersRest((, MemberKind.Local)
listener: beginFormalParameters((, MemberKind.Local)
@@ -46,7 +46,7 @@ beginCompilationUnit(void)
handleNoType(})
beginFunctionName(onX)
handleIdentifier(onX, localFunctionDeclaration)
endFunctionName(onX, ()
endFunctionName(onX, (, false)
beginFormalParameters((, MemberKind.Local)
beginMetadataStar(e)
endMetadataStar(0)
@@ -98,7 +98,7 @@ parseUnit(void)
listener: beginFunctionName(onX)
ensureIdentifier(}, localFunctionDeclaration)
listener: handleIdentifier(onX, localFunctionDeclaration)
listener: endFunctionName(onX, ()
listener: endFunctionName(onX, (, false)
parseFormalParametersRequiredOpt(onX, MemberKind.Local)
parseFormalParametersRest((, MemberKind.Local)
listener: beginFormalParameters((, MemberKind.Local)
@@ -17,7 +17,7 @@ beginCompilationUnit(main)
handleNoType({)
beginFunctionName(local)
handleIdentifier(local, localFunctionDeclaration)
endFunctionName(local, ()
endFunctionName(local, (, false)
beginFormalParameters((, MemberKind.Local)
endFormalParameters(0, (, ), MemberKind.Local)
handleNoInitializers()
@@ -40,7 +40,7 @@ parseUnit(main)
listener: beginFunctionName(local)
ensureIdentifier({, localFunctionDeclaration)
listener: handleIdentifier(local, localFunctionDeclaration)
listener: endFunctionName(local, ()
listener: endFunctionName(local, (, false)
parseFormalParametersRequiredOpt(local, MemberKind.Local)
parseFormalParametersRest((, MemberKind.Local)
listener: beginFormalParameters((, MemberKind.Local)
@@ -931,7 +931,7 @@ beginCompilationUnit(import)
beginFunctionName(fun)
handleIdentifier(fun, localFunctionDeclaration)
handleRecoverableError(NamedFunctionExpression, fun, fun)
endFunctionName(void, ()
endFunctionName(void, (, true)
beginFormalParameters((, MemberKind.Local)
endFormalParameters(0, (, ), MemberKind.Local)
handleNoInitializers()
@@ -1559,7 +1559,7 @@ parseUnit(import)
listener: handleIdentifier(fun, localFunctionDeclaration)
reportRecoverableError(fun, NamedFunctionExpression)
listener: handleRecoverableError(NamedFunctionExpression, fun, fun)
listener: endFunctionName(void, ()
listener: endFunctionName(void, (, true)
parseFormalParametersRequiredOpt(fun, MemberKind.Local)
parseFormalParametersRest((, MemberKind.Local)
listener: beginFormalParameters((, MemberKind.Local)
@@ -444,7 +444,7 @@ beginCompilationUnit(void)
handleType(int, null)
beginFunctionName(async)
handleIdentifier(async, localFunctionDeclaration)
endFunctionName(int, ()
endFunctionName(int, (, false)
beginFormalParameters((, MemberKind.Local)
beginMetadataStar(int)
endMetadataStar(0)
@@ -502,7 +502,7 @@ beginCompilationUnit(void)
endRecordType((, null, 2, false)
beginFunctionName(async)
handleIdentifier(async, localFunctionDeclaration)
endFunctionName((, ()
endFunctionName((, (, false)
beginFormalParameters((, MemberKind.Local)
beginMetadataStar(int)
endMetadataStar(0)
@@ -560,7 +560,7 @@ beginCompilationUnit(void)
endRecordType((, null, 2, false)
beginFunctionName(async)
handleIdentifier(async, localFunctionDeclaration)
endFunctionName((, ()
endFunctionName((, (, false)
beginFormalParameters((, MemberKind.Local)
beginMetadataStar(int)
endMetadataStar(0)
@@ -886,7 +886,7 @@ parseUnit(void)
ensureIdentifier(int, localFunctionDeclaration)
inPlainSync()
listener: handleIdentifier(async, localFunctionDeclaration)
listener: endFunctionName(int, ()
listener: endFunctionName(int, (, false)
parseFormalParametersRequiredOpt(async, MemberKind.Local)
parseFormalParametersRest((, MemberKind.Local)
listener: beginFormalParameters((, MemberKind.Local)
@@ -999,7 +999,7 @@ parseUnit(void)
ensureIdentifier(), localFunctionDeclaration)
inPlainSync()
listener: handleIdentifier(async, localFunctionDeclaration)
listener: endFunctionName((, ()
listener: endFunctionName((, (, false)
parseFormalParametersRequiredOpt(async, MemberKind.Local)
parseFormalParametersRest((, MemberKind.Local)
listener: beginFormalParameters((, MemberKind.Local)
@@ -1112,7 +1112,7 @@ parseUnit(void)
ensureIdentifier(), localFunctionDeclaration)
inPlainSync()
listener: handleIdentifier(async, localFunctionDeclaration)
listener: endFunctionName((, ()
listener: endFunctionName((, (, false)
parseFormalParametersRequiredOpt(async, MemberKind.Local)
parseFormalParametersRest((, MemberKind.Local)
listener: beginFormalParameters((, MemberKind.Local)
@@ -175,7 +175,7 @@ const Map<String, ({int hitCount, int missCount})> _expect = {
),
// 100.0%.
"package:front_end/src/base/local_scope.dart": (
hitCount: 60,
hitCount: 59,
missCount: 0,
),
// 100.0%.
@@ -655,7 +655,7 @@ const Map<String, ({int hitCount, int missCount})> _expect = {
),
// 100.0%.
"package:front_end/src/kernel/body_builder.dart": (
hitCount: 7247,
hitCount: 7243,
missCount: 0,
),
// 100.0%.
@@ -1001,7 +1001,7 @@ const Map<String, ({int hitCount, int missCount})> _expect = {
),
// 100.0%.
"package:front_end/src/source/type_parameter_scope_builder.dart": (
hitCount: 1720,
hitCount: 1760,
missCount: 0,
),
// 100.0%.
@@ -1036,7 +1036,7 @@ const Map<String, ({int hitCount, int missCount})> _expect = {
),
// 100.0%.
"package:front_end/src/type_inference/inference_visitor.dart": (
hitCount: 8291,
hitCount: 8312,
missCount: 0,
),
// 100.0%.
+4 -2
View File
@@ -1151,11 +1151,13 @@ class ParserTestListener implements Listener {
}
@override
void endFunctionName(Token beginToken, Token token) {
void endFunctionName(
Token beginToken, Token token, bool isFunctionExpression) {
indent--;
seen(beginToken);
seen(token);
doPrint('endFunctionName(' '$beginToken, ' '$token)');
doPrint(
'endFunctionName(' '$beginToken, ' '$token, ' '$isFunctionExpression)');
}
@override
@@ -1308,6 +1308,7 @@ pm
pn
pointed
pointwise
pollute
polluted
polymorphism
pool
@@ -0,0 +1,8 @@
// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
void test() {
void local() {}
void local() {}
}
@@ -0,0 +1,22 @@
library;
//
// Problems in library:
//
// pkg/front_end/testcases/general/duplicate_local_function.dart:7:8: Error: 'local' is already declared in this scope.
// void local() {}
// ^^^^^
// pkg/front_end/testcases/general/duplicate_local_function.dart:6:8: Context: Previous declaration of 'local'.
// void local() {}
// ^^^^^
//
import self as self;
static method test() → void {
function local() → void {}
{
invalid-expression "pkg/front_end/testcases/general/duplicate_local_function.dart:7:8: Error: 'local' is already declared in this scope.
void local() {}
^^^^^";
function local() → void {}
}
}
@@ -0,0 +1,22 @@
library;
//
// Problems in library:
//
// pkg/front_end/testcases/general/duplicate_local_function.dart:7:8: Error: 'local' is already declared in this scope.
// void local() {}
// ^^^^^
// pkg/front_end/testcases/general/duplicate_local_function.dart:6:8: Context: Previous declaration of 'local'.
// void local() {}
// ^^^^^
//
import self as self;
static method test() → void {
function local() → void {}
{
invalid-expression "pkg/front_end/testcases/general/duplicate_local_function.dart:7:8: Error: 'local' is already declared in this scope.
void local() {}
^^^^^";
function local() → void {}
}
}
@@ -0,0 +1,5 @@
library;
import self as self;
static method test() → void
;
@@ -0,0 +1,22 @@
library;
//
// Problems in library:
//
// pkg/front_end/testcases/general/duplicate_local_function.dart:7:8: Error: 'local' is already declared in this scope.
// void local() {}
// ^^^^^
// pkg/front_end/testcases/general/duplicate_local_function.dart:6:8: Context: Previous declaration of 'local'.
// void local() {}
// ^^^^^
//
import self as self;
static method test() → void {
function local() → void {}
{
invalid-expression "pkg/front_end/testcases/general/duplicate_local_function.dart:7:8: Error: 'local' is already declared in this scope.
void local() {}
^^^^^";
function local() → void {}
}
}
@@ -42,13 +42,6 @@ library;
// var x = T<T>() {};
// ^
//
// pkg/front_end/testcases/general/named_function_scope.dart:52:13: Error: 'T' is already declared in this scope.
// var x = T<T>() {};
// ^
// pkg/front_end/testcases/general/named_function_scope.dart:52:15: Context: Previous declaration of 'T'.
// var x = T<T>() {};
// ^
//
// pkg/front_end/testcases/general/named_function_scope.dart:55:5: Error: Local variable 'T' can't be referenced before it is declared.
// T t;
// ^
@@ -155,12 +148,7 @@ static method test() → dynamic {
}
{
invalid-type x = block {
{
invalid-expression "pkg/front_end/testcases/general/named_function_scope.dart:52:13: Error: 'T' is already declared in this scope.
var x = T<T>() {};
^";
function T<T extends core::Object? = dynamic>() → Null {}
}
function T<T extends core::Object? = dynamic>() → Null {}
} =>invalid-expression "pkg/front_end/testcases/general/named_function_scope.dart:52:13: Error: A function expression can't have a name.
var x = T<T>() {};
^";
@@ -42,13 +42,6 @@ library;
// var x = T<T>() {};
// ^
//
// pkg/front_end/testcases/general/named_function_scope.dart:52:13: Error: 'T' is already declared in this scope.
// var x = T<T>() {};
// ^
// pkg/front_end/testcases/general/named_function_scope.dart:52:15: Context: Previous declaration of 'T'.
// var x = T<T>() {};
// ^
//
// pkg/front_end/testcases/general/named_function_scope.dart:55:5: Error: Local variable 'T' can't be referenced before it is declared.
// T t;
// ^
@@ -155,12 +148,7 @@ static method test() → dynamic {
}
{
invalid-type x = block {
{
invalid-expression "pkg/front_end/testcases/general/named_function_scope.dart:52:13: Error: 'T' is already declared in this scope.
var x = T<T>() {};
^";
function T<T extends core::Object? = dynamic>() → Null {}
}
function T<T extends core::Object? = dynamic>() → Null {}
} =>invalid-expression "pkg/front_end/testcases/general/named_function_scope.dart:52:13: Error: A function expression can't have a name.
var x = T<T>() {};
^";
@@ -42,13 +42,6 @@ library;
// var x = T<T>() {};
// ^
//
// pkg/front_end/testcases/general/named_function_scope.dart:52:13: Error: 'T' is already declared in this scope.
// var x = T<T>() {};
// ^
// pkg/front_end/testcases/general/named_function_scope.dart:52:15: Context: Previous declaration of 'T'.
// var x = T<T>() {};
// ^
//
// pkg/front_end/testcases/general/named_function_scope.dart:55:5: Error: Local variable 'T' can't be referenced before it is declared.
// T t;
// ^
@@ -155,12 +148,7 @@ static method test() → dynamic {
}
{
invalid-type x = block {
{
invalid-expression "pkg/front_end/testcases/general/named_function_scope.dart:52:13: Error: 'T' is already declared in this scope.
var x = T<T>() {};
^";
function T<T extends core::Object? = dynamic>() → Null {}
}
function T<T extends core::Object? = dynamic>() → Null {}
} =>invalid-expression "pkg/front_end/testcases/general/named_function_scope.dart:52:13: Error: A function expression can't have a name.
var x = T<T>() {};
^";
@@ -0,0 +1,9 @@
// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
void test() {
var f = void foo() {
foo();
};
}
@@ -0,0 +1,19 @@
library;
//
// Problems in library:
//
// pkg/front_end/testcases/general/recursive_named_function_expression.dart:6:16: Error: A function expression can't have a name.
// var f = void foo() {
// ^^^
//
import self as self;
static method test() → void {
invalid-type f = block {
function foo() → void {
foo(){() → void};
}
} =>invalid-expression "pkg/front_end/testcases/general/recursive_named_function_expression.dart:6:11: Error: A function expression can't have a name.
var f = void foo() {
^";
}
@@ -0,0 +1,19 @@
library;
//
// Problems in library:
//
// pkg/front_end/testcases/general/recursive_named_function_expression.dart:6:16: Error: A function expression can't have a name.
// var f = void foo() {
// ^^^
//
import self as self;
static method test() → void {
invalid-type f = block {
function foo() → void {
foo(){() → void};
}
} =>invalid-expression "pkg/front_end/testcases/general/recursive_named_function_expression.dart:6:11: Error: A function expression can't have a name.
var f = void foo() {
^";
}
@@ -0,0 +1,5 @@
library;
import self as self;
static method test() → void
;
@@ -0,0 +1,19 @@
library;
//
// Problems in library:
//
// pkg/front_end/testcases/general/recursive_named_function_expression.dart:6:16: Error: A function expression can't have a name.
// var f = void foo() {
// ^^^
//
import self as self;
static method test() → void {
invalid-type f = block {
function foo() → void {
foo(){() → void};
}
} =>invalid-expression "pkg/front_end/testcases/general/recursive_named_function_expression.dart:6:11: Error: A function expression can't have a name.
var f = void foo() {
^";
}