Skip to content

[CFE] add 'Function' as type identifier check in CFE #45736

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4385,6 +4385,15 @@ const MessageCode messageForInLoopWithConstVariable = const MessageCode(
message: r"""A for-in loop-variable can't be 'const'.""",
tip: r"""Try removing the 'const' modifier.""");

// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Code<Null> codeFunctionAsTypeParameter = messageFunctionAsTypeParameter;

// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const MessageCode messageFunctionAsTypeParameter = const MessageCode(
"FunctionAsTypeParameter",
message:
r"""'Function' is a built-in identifier, could not used as a type identifier.""");

// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Code<Null> codeFunctionTypeDefaultValue = messageFunctionTypeDefaultValue;

Expand All @@ -4406,6 +4415,30 @@ const MessageCode messageFunctionTypedParameterVar = const MessageCode(
r"""Function-typed parameters can't specify 'const', 'final' or 'var' in place of a return type.""",
tip: r"""Try replacing the keyword with a return type.""");

// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Template<
Message Function(String name)> templateFunctionUsedAsDec = const Template<
Message Function(String name)>(
messageTemplate:
r"""'Function' is a built-in identifier, could not used as a #name name.""",
withArguments: _withArgumentsFunctionUsedAsDec);

// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Code<Message Function(String name)> codeFunctionUsedAsDec =
const Code<Message Function(String name)>(
"FunctionUsedAsDec",
);

// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
Message _withArgumentsFunctionUsedAsDec(String name) {
if (name.isEmpty) throw 'No name provided';
name = demangleMixinApplicationName(name);
return new Message(codeFunctionUsedAsDec,
message:
"""'Function' is a built-in identifier, could not used as a ${name} name.""",
arguments: {'name': name});
}

// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Code<Null> codeGeneratorReturnsValue = messageGeneratorReturnsValue;

Expand Down
48 changes: 47 additions & 1 deletion pkg/front_end/lib/src/fasta/source/source_library_builder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1464,6 +1464,48 @@ class SourceLibraryBuilder extends LibraryBuilderImpl {
new VoidTypeDeclarationBuilder(const VoidType(), this, charOffset));
}

void _checkBadFunctionParameter(List<TypeVariableBuilder> typeVariables) {
if (typeVariables == null || typeVariables.isEmpty) {
return;
}

for (TypeVariableBuilder type in typeVariables) {
if (type.name == "Function") {
addProblem(messageFunctionAsTypeParameter, type.charOffset,
type.name.length, type.fileUri);
}
}
}

void _checkBadFunctionDeclUse(String className, TypeParameterScopeKind kind,
int charOffset) {
String decType;
switch (kind) {
case TypeParameterScopeKind.classDeclaration:
decType = "class";
break;
case TypeParameterScopeKind.mixinDeclaration:
decType = "mixin";
break;
case TypeParameterScopeKind.extensionDeclaration:
decType = "extension";
break;
default:
break;
}
if (className != "Function") {
return;
}
if (decType == "class" && importUri.scheme == "dart") {
// Allow declaration of class Function in the sdk.
return;
}
if (decType != null) {
addProblem(templateFunctionUsedAsDec.withArguments(decType), charOffset,
className?.length, fileUri);
}
}

/// Add a problem that might not be reported immediately.
///
/// Problems will be issued after source information has been added.
Expand Down Expand Up @@ -1573,6 +1615,8 @@ class SourceLibraryBuilder extends LibraryBuilderImpl {
int nameOffset,
int endOffset,
int supertypeOffset) {
_checkBadFunctionDeclUse(className, kind, nameOffset);
_checkBadFunctionParameter(typeVariables);
// Nested declaration began in `OutlineBuilder.beginClassDeclaration`.
TypeParameterScopeBuilder declaration =
endNestedDeclaration(kind, className)
Expand Down Expand Up @@ -1805,6 +1849,9 @@ class SourceLibraryBuilder extends LibraryBuilderImpl {
int startOffset,
int nameOffset,
int endOffset) {
_checkBadFunctionDeclUse(
extensionName, TypeParameterScopeKind.extensionDeclaration, nameOffset);
_checkBadFunctionParameter(typeVariables);
// Nested declaration began in `OutlineBuilder.beginExtensionDeclaration`.
TypeParameterScopeBuilder declaration = endNestedDeclaration(
TypeParameterScopeKind.extensionDeclaration, extensionName)
Expand Down Expand Up @@ -1836,7 +1883,6 @@ class SourceLibraryBuilder extends LibraryBuilderImpl {
nameOffset,
endOffset,
referenceFrom);

constructorReferences.clear();
Map<String, TypeVariableBuilder> typeVariablesByName =
checkTypeVariables(typeVariables, extensionBuilder);
Expand Down
2 changes: 2 additions & 0 deletions pkg/front_end/messages.status
Original file line number Diff line number Diff line change
Expand Up @@ -369,9 +369,11 @@ ForInLoopNotAssignable/part_wrapped_statement: Fail
ForInLoopNotAssignable/statement: Fail
ForInLoopTypeNotIterablePartNullability/example: Fail # Cannot occur but needed for symmetry with ForInLoopTypeNotIterableNullability
ForInLoopWithConstVariable/example: Fail
FunctionAsTypeParameter/analyzerCode: Fail
FunctionTypeDefaultValue/example: Fail
FunctionTypedParameterVar/part_wrapped_script1: Fail
FunctionTypedParameterVar/script1: Fail
FunctionUsedAsDec/analyzerCode: Fail
GeneratorReturnsValue/example: Fail
GetterNotFound/example: Fail
GetterWithFormals/example: Fail
Expand Down
14 changes: 14 additions & 0 deletions pkg/front_end/messages.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1797,6 +1797,20 @@ NotAPrefixInTypeAnnotation:
T.String field;
}

FunctionUsedAsDec:
template: "'Function' is a built-in identifier, could not used as a #name name."
script:
- class Function {}
- extension Function on int {}
- mixin Function {}

FunctionAsTypeParameter:
template: "'Function' is a built-in identifier, could not used as a type identifier."
script:
- class C<Function> {}
- mixin A<Function> {}
- extension A<Function> on List<Function> {}

UnresolvedPrefixInTypeAnnotation:
template: "'#name.#name2' can't be used as a type because '#name' isn't defined."
analyzerCode: NOT_A_TYPE
Expand Down
7 changes: 7 additions & 0 deletions pkg/front_end/testcases/general/function_bad_use.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
class Function {}

class C<Function> {}

mixin M<Function> implements List<Function> {}

main() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
class Function {}

class C<Function> {}

mixin M<Function> implements List<Function> {}
main() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
class C<Function> {}

class Function {}

main() {}
mixin M<Function> implements List<Function> {}
32 changes: 32 additions & 0 deletions pkg/front_end/testcases/general/function_bad_use.dart.weak.expect
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
library /*isNonNullableByDefault*/;
//
// Problems in library:
//
// pkg/front_end/testcases/general/function_bad_use.dart:1:7: Error: 'Function' is a built-in identifier, could not used as a class name.
// class Function {}
// ^^^^^^^^
//
// pkg/front_end/testcases/general/function_bad_use.dart:3:9: Error: 'Function' is a built-in identifier, could not used as a type identifier.
// class C<Function> {}
// ^^^^^^^^
//
// pkg/front_end/testcases/general/function_bad_use.dart:5:9: Error: 'Function' is a built-in identifier, could not used as a type identifier.
// mixin M<Function> implements List<Function> {}
// ^^^^^^^^
//
import self as self;
import "dart:core" as core;

class Function extends core::Object {
synthetic constructor •() → self::Function
: super core::Object::•()
;
}
class C<Function extends core::Object? = dynamic> extends core::Object {
synthetic constructor •() → self::C<self::C::Function%>
: super core::Object::•()
;
}
abstract class M<Function extends core::Object? = dynamic> extends core::Object implements core::List<self::M::Function%> /*isMixinDeclaration*/ {
}
static method main() → dynamic {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
library /*isNonNullableByDefault*/;
//
// Problems in library:
//
// pkg/front_end/testcases/general/function_bad_use.dart:1:7: Error: 'Function' is a built-in identifier, could not used as a class name.
// class Function {}
// ^^^^^^^^
//
// pkg/front_end/testcases/general/function_bad_use.dart:3:9: Error: 'Function' is a built-in identifier, could not used as a type identifier.
// class C<Function> {}
// ^^^^^^^^
//
// pkg/front_end/testcases/general/function_bad_use.dart:5:9: Error: 'Function' is a built-in identifier, could not used as a type identifier.
// mixin M<Function> implements List<Function> {}
// ^^^^^^^^
//
import self as self;
import "dart:core" as core;

class Function extends core::Object {
synthetic constructor •() → self::Function
;
}
class C<Function extends core::Object? = dynamic> extends core::Object {
synthetic constructor •() → self::C<self::C::Function%>
;
}
abstract class M<Function extends core::Object? = dynamic> extends core::Object implements core::List<self::M::Function%> /*isMixinDeclaration*/ {
}
static method main() → dynamic
;
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
library /*isNonNullableByDefault*/;
//
// Problems in library:
//
// pkg/front_end/testcases/general/function_bad_use.dart:1:7: Error: 'Function' is a built-in identifier, could not used as a class name.
// class Function {}
// ^^^^^^^^
//
// pkg/front_end/testcases/general/function_bad_use.dart:3:9: Error: 'Function' is a built-in identifier, could not used as a type identifier.
// class C<Function> {}
// ^^^^^^^^
//
// pkg/front_end/testcases/general/function_bad_use.dart:5:9: Error: 'Function' is a built-in identifier, could not used as a type identifier.
// mixin M<Function> implements List<Function> {}
// ^^^^^^^^
//
import self as self;
import "dart:core" as core;

class Function extends core::Object {
synthetic constructor •() → self::Function
: super core::Object::•()
;
}
class C<Function extends core::Object? = dynamic> extends core::Object {
synthetic constructor •() → self::C<self::C::Function%>
: super core::Object::•()
;
}
abstract class M<Function extends core::Object? = dynamic> extends core::Object implements core::List<self::M::Function%> /*isMixinDeclaration*/ {
}
static method main() → dynamic {}
3 changes: 2 additions & 1 deletion pkg/front_end/testcases/general/ignore_function.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@ class B implements Function {
operator ==(other) => false;
}

// CFE Error here: Function is built-in id, could not used as type id.
class Function {
core.bool operator ==(core.Object other) => false;
}

main() {}
main() {}
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
library;
//
// Problems in library:
//
// pkg/front_end/testcases/general/ignore_function.dart:18:7: Error: 'Function' is a built-in identifier, could not used as a class name.
// class Function {
// ^^^^^^^^
//
import self as self;
import "dart:core" as core;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
library;
//
// Problems in library:
//
// pkg/front_end/testcases/general/ignore_function.dart:18:7: Error: 'Function' is a built-in identifier, could not used as a class name.
// class Function {
// ^^^^^^^^
//
import self as self;
import "dart:core" as core;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
library;
//
// Problems in library:
//
// pkg/front_end/testcases/general/ignore_function.dart:18:7: Error: 'Function' is a built-in identifier, could not used as a class name.
// class Function {
// ^^^^^^^^
//
import self as self;
import "dart:core" as core;

Expand Down