[ty] Add type definitions for `Type::SpecialForm`s (#21544)

This commit is contained in:
Alex Waygood 2025-11-20 18:14:30 +00:00 committed by GitHub
parent 6e84f4fd7a
commit c4767f5aa8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 479 additions and 61 deletions

View File

@ -213,6 +213,7 @@ impl<'db> DefinitionsOrTargets<'db> {
| ty_python_semantic::types::TypeDefinition::Function(definition)
| ty_python_semantic::types::TypeDefinition::TypeVar(definition)
| ty_python_semantic::types::TypeDefinition::TypeAlias(definition)
| ty_python_semantic::types::TypeDefinition::SpecialForm(definition)
| ty_python_semantic::types::TypeDefinition::NewType(definition) => {
ResolvedDefinition::Definition(definition)
}

View File

@ -68,6 +68,134 @@ mod tests {
");
}
#[test]
fn goto_type_of_typing_dot_literal() {
let test = cursor_test(
r#"
from typing import Literal
a<CURSOR>b = Literal
"#,
);
assert_snapshot!(test.goto_type_definition(), @r"
info[goto-type-definition]: Type definition
--> stdlib/typing.pyi:351:1
|
349 | Final: _SpecialForm
350 |
351 | Literal: _SpecialForm
| ^^^^^^^
352 | TypedDict: _SpecialForm
|
info: Source
--> main.py:4:1
|
2 | from typing import Literal
3 |
4 | ab = Literal
| ^^
|
");
}
// this is a slightly different case to the one above,
// since `Any` is a class in typeshed rather than a variable
#[test]
fn goto_type_of_typing_dot_any() {
let test = cursor_test(
r#"
from typing import Any
a<CURSOR>b = Any
"#,
);
assert_snapshot!(test.goto_type_definition(), @r#"
info[goto-type-definition]: Type definition
--> stdlib/typing.pyi:166:7
|
164 | # from _typeshed import AnnotationForm
165 |
166 | class Any:
| ^^^
167 | """Special type indicating an unconstrained type.
|
info: Source
--> main.py:4:1
|
2 | from typing import Any
3 |
4 | ab = Any
| ^^
|
"#);
}
// Similarly, `Generic` is a `type[]` type in typeshed
#[test]
fn goto_type_of_typing_dot_generic() {
let test = cursor_test(
r#"
from typing import Generic
a<CURSOR>b = Generic
"#,
);
assert_snapshot!(test.goto_type_definition(), @r"
info[goto-type-definition]: Type definition
--> stdlib/typing.pyi:770:1
|
768 | def __class_getitem__(cls, args: TypeVar | tuple[TypeVar, ...]) -> _Final: ...
769 |
770 | Generic: type[_Generic]
| ^^^^^^^
771 |
772 | class _ProtocolMeta(ABCMeta):
|
info: Source
--> main.py:4:1
|
2 | from typing import Generic
3 |
4 | ab = Generic
| ^^
|
");
}
#[test]
fn goto_type_of_ty_extensions_special_form() {
let test = cursor_test(
r#"
from ty_extensions import AlwaysTruthy
a<CURSOR>b = AlwaysTruthy
"#,
);
assert_snapshot!(test.goto_type_definition(), @r"
info[goto-type-definition]: Type definition
--> stdlib/ty_extensions.pyi:21:1
|
19 | # Types
20 | Unknown = object()
21 | AlwaysTruthy = object()
| ^^^^^^^^^^^^
22 | AlwaysFalsy = object()
|
info: Source
--> main.py:4:1
|
2 | from ty_extensions import AlwaysTruthy
3 |
4 | ab = AlwaysTruthy
| ^^
|
");
}
#[test]
fn goto_type_of_expression_with_function_type() {
let test = cursor_test(

View File

@ -601,6 +601,25 @@ mod tests {
w[: int] = z
---------------------------------------------
info[inlay-hint-location]: Inlay Hint Target
--> stdlib/typing.pyi:351:1
|
349 | Final: _SpecialForm
350 |
351 | Literal: _SpecialForm
| ^^^^^^^
352 | TypedDict: _SpecialForm
|
info: Source
--> main2.py:6:5
|
5 | x = 1
6 | y[: Literal[1]] = x
| ^^^^^^^
7 | z[: int] = i(1)
8 | w[: int] = z
|
info[inlay-hint-location]: Inlay Hint Target
--> stdlib/builtins.pyi:348:7
|
@ -668,6 +687,44 @@ mod tests {
x4[: int], y4[: str] = (x3, y3)
---------------------------------------------
info[inlay-hint-location]: Inlay Hint Target
--> stdlib/typing.pyi:351:1
|
349 | Final: _SpecialForm
350 |
351 | Literal: _SpecialForm
| ^^^^^^^
352 | TypedDict: _SpecialForm
|
info: Source
--> main2.py:8:6
|
7 | x1, y1 = (1, 'abc')
8 | x2[: Literal[1]], y2[: Literal["abc"]] = (x1, y1)
| ^^^^^^^
9 | x3[: int], y3[: str] = (i(1), s('abc'))
10 | x4[: int], y4[: str] = (x3, y3)
|
info[inlay-hint-location]: Inlay Hint Target
--> stdlib/typing.pyi:351:1
|
349 | Final: _SpecialForm
350 |
351 | Literal: _SpecialForm
| ^^^^^^^
352 | TypedDict: _SpecialForm
|
info: Source
--> main2.py:8:24
|
7 | x1, y1 = (1, 'abc')
8 | x2[: Literal[1]], y2[: Literal["abc"]] = (x1, y1)
| ^^^^^^^
9 | x3[: int], y3[: str] = (i(1), s('abc'))
10 | x4[: int], y4[: str] = (x3, y3)
|
info[inlay-hint-location]: Inlay Hint Target
--> stdlib/builtins.pyi:348:7
|
@ -772,6 +829,44 @@ mod tests {
x4[: int], y4[: str] = x3, y3
---------------------------------------------
info[inlay-hint-location]: Inlay Hint Target
--> stdlib/typing.pyi:351:1
|
349 | Final: _SpecialForm
350 |
351 | Literal: _SpecialForm
| ^^^^^^^
352 | TypedDict: _SpecialForm
|
info: Source
--> main2.py:8:6
|
7 | x1, y1 = 1, 'abc'
8 | x2[: Literal[1]], y2[: Literal["abc"]] = x1, y1
| ^^^^^^^
9 | x3[: int], y3[: str] = i(1), s('abc')
10 | x4[: int], y4[: str] = x3, y3
|
info[inlay-hint-location]: Inlay Hint Target
--> stdlib/typing.pyi:351:1
|
349 | Final: _SpecialForm
350 |
351 | Literal: _SpecialForm
| ^^^^^^^
352 | TypedDict: _SpecialForm
|
info: Source
--> main2.py:8:24
|
7 | x1, y1 = 1, 'abc'
8 | x2[: Literal[1]], y2[: Literal["abc"]] = x1, y1
| ^^^^^^^
9 | x3[: int], y3[: str] = i(1), s('abc')
10 | x4[: int], y4[: str] = x3, y3
|
info[inlay-hint-location]: Inlay Hint Target
--> stdlib/builtins.pyi:348:7
|
@ -876,6 +971,44 @@ mod tests {
w[: tuple[int, str]] = z
---------------------------------------------
info[inlay-hint-location]: Inlay Hint Target
--> stdlib/typing.pyi:351:1
|
349 | Final: _SpecialForm
350 |
351 | Literal: _SpecialForm
| ^^^^^^^
352 | TypedDict: _SpecialForm
|
info: Source
--> main2.py:8:11
|
7 | x = (1, 'abc')
8 | y[: tuple[Literal[1], Literal["abc"]]] = x
| ^^^^^^^
9 | z[: tuple[int, str]] = (i(1), s('abc'))
10 | w[: tuple[int, str]] = z
|
info[inlay-hint-location]: Inlay Hint Target
--> stdlib/typing.pyi:351:1
|
349 | Final: _SpecialForm
350 |
351 | Literal: _SpecialForm
| ^^^^^^^
352 | TypedDict: _SpecialForm
|
info: Source
--> main2.py:8:23
|
7 | x = (1, 'abc')
8 | y[: tuple[Literal[1], Literal["abc"]]] = x
| ^^^^^^^
9 | z[: tuple[int, str]] = (i(1), s('abc'))
10 | w[: tuple[int, str]] = z
|
info[inlay-hint-location]: Inlay Hint Target
--> stdlib/builtins.pyi:348:7
|
@ -978,6 +1111,63 @@ mod tests {
x3[: int], (y3[: str], z3[: int]) = (i(1), (s('abc'), i(2)))
x4[: int], (y4[: str], z4[: int]) = (x3, (y3, z3))
---------------------------------------------
info[inlay-hint-location]: Inlay Hint Target
--> stdlib/typing.pyi:351:1
|
349 | Final: _SpecialForm
350 |
351 | Literal: _SpecialForm
| ^^^^^^^
352 | TypedDict: _SpecialForm
|
info: Source
--> main2.py:8:6
|
7 | x1, (y1, z1) = (1, ('abc', 2))
8 | x2[: Literal[1]], (y2[: Literal["abc"]], z2[: Literal[2]]) = (x1, (y1, z1))
| ^^^^^^^
9 | x3[: int], (y3[: str], z3[: int]) = (i(1), (s('abc'), i(2)))
10 | x4[: int], (y4[: str], z4[: int]) = (x3, (y3, z3))
|
info[inlay-hint-location]: Inlay Hint Target
--> stdlib/typing.pyi:351:1
|
349 | Final: _SpecialForm
350 |
351 | Literal: _SpecialForm
| ^^^^^^^
352 | TypedDict: _SpecialForm
|
info: Source
--> main2.py:8:25
|
7 | x1, (y1, z1) = (1, ('abc', 2))
8 | x2[: Literal[1]], (y2[: Literal["abc"]], z2[: Literal[2]]) = (x1, (y1, z1))
| ^^^^^^^
9 | x3[: int], (y3[: str], z3[: int]) = (i(1), (s('abc'), i(2)))
10 | x4[: int], (y4[: str], z4[: int]) = (x3, (y3, z3))
|
info[inlay-hint-location]: Inlay Hint Target
--> stdlib/typing.pyi:351:1
|
349 | Final: _SpecialForm
350 |
351 | Literal: _SpecialForm
| ^^^^^^^
352 | TypedDict: _SpecialForm
|
info: Source
--> main2.py:8:47
|
7 | x1, (y1, z1) = (1, ('abc', 2))
8 | x2[: Literal[1]], (y2[: Literal["abc"]], z2[: Literal[2]]) = (x1, (y1, z1))
| ^^^^^^^
9 | x3[: int], (y3[: str], z3[: int]) = (i(1), (s('abc'), i(2)))
10 | x4[: int], (y4[: str], z4[: int]) = (x3, (y3, z3))
|
info[inlay-hint-location]: Inlay Hint Target
--> stdlib/builtins.pyi:348:7
|
@ -1113,6 +1303,25 @@ mod tests {
z: int = i(1)
w[: int] = z
---------------------------------------------
info[inlay-hint-location]: Inlay Hint Target
--> stdlib/typing.pyi:351:1
|
349 | Final: _SpecialForm
350 |
351 | Literal: _SpecialForm
| ^^^^^^^
352 | TypedDict: _SpecialForm
|
info: Source
--> main2.py:6:5
|
5 | x: int = 1
6 | y[: Literal[1]] = x
| ^^^^^^^
7 | z: int = i(1)
8 | w[: int] = z
|
info[inlay-hint-location]: Inlay Hint Target
--> stdlib/builtins.pyi:348:7
|

View File

@ -1109,7 +1109,7 @@ from typing import List, Dict
# error: [invalid-type-form] "Int literals are not allowed in this context in a type expression"
InvalidList = List[1]
# error: [invalid-type-form] "`typing.typing.List` requires exactly one argument"
# error: [invalid-type-form] "`typing.List` requires exactly one argument"
ListTooManyArgs = List[int, str]
# error: [invalid-type-form] "Int literals are not allowed in this context in a type expression"
@ -1118,10 +1118,10 @@ InvalidDict1 = Dict[1, str]
# error: [invalid-type-form] "Int literals are not allowed in this context in a type expression"
InvalidDict2 = Dict[str, 2]
# error: [invalid-type-form] "`typing.typing.Dict` requires exactly two arguments, got 1"
# error: [invalid-type-form] "`typing.Dict` requires exactly two arguments, got 1"
DictTooFewArgs = Dict[str]
# error: [invalid-type-form] "`typing.typing.Dict` requires exactly two arguments, got 3"
# error: [invalid-type-form] "`typing.Dict` requires exactly two arguments, got 3"
DictTooManyArgs = Dict[str, int, float]
def _(

View File

@ -7503,7 +7503,7 @@ impl<'db> Type<'db> {
name = enum_literal.name(db)
),
),
Type::SpecialForm(special_form) => Type::string_literal(db, special_form.repr()),
Type::SpecialForm(special_form) => Type::string_literal(db, &special_form.to_string()),
Type::KnownInstance(known_instance) => Type::StringLiteral(StringLiteralType::new(
db,
known_instance.repr(db).to_compact_string(),
@ -7525,7 +7525,7 @@ impl<'db> Type<'db> {
Type::string_literal(db, &format!("'{}'", literal.value(db).escape_default()))
}
Type::LiteralString => Type::LiteralString,
Type::SpecialForm(special_form) => Type::string_literal(db, special_form.repr()),
Type::SpecialForm(special_form) => Type::string_literal(db, &special_form.to_string()),
Type::KnownInstance(known_instance) => Type::StringLiteral(StringLiteralType::new(
db,
known_instance.repr(db).to_compact_string(),
@ -7604,13 +7604,14 @@ impl<'db> Type<'db> {
Self::Union(_) | Self::Intersection(_) => None,
Self::SpecialForm(special_form) => special_form.definition(db),
// These types have no definition
Self::Dynamic(_)
| Self::Never
| Self::Callable(_)
| Self::AlwaysTruthy
| Self::AlwaysFalsy
| Self::SpecialForm(_)
| Self::TypeIs(_) => None,
}
}

View File

@ -4828,7 +4828,7 @@ impl KnownClass {
}
/// Return the module in which we should look up the definition for this class
fn canonical_module(self, db: &dyn Db) -> KnownModule {
pub(super) fn canonical_module(self, db: &dyn Db) -> KnownModule {
match self {
Self::Bool
| Self::Object

View File

@ -13,6 +13,7 @@ pub enum TypeDefinition<'db> {
TypeVar(Definition<'db>),
TypeAlias(Definition<'db>),
NewType(Definition<'db>),
SpecialForm(Definition<'db>),
}
impl TypeDefinition<'_> {
@ -23,6 +24,7 @@ impl TypeDefinition<'_> {
| Self::Function(definition)
| Self::TypeVar(definition)
| Self::TypeAlias(definition)
| Self::SpecialForm(definition)
| Self::NewType(definition) => {
let module = parsed_module(db, definition.file(db)).load(db);
Some(definition.focus_range(db, &module))
@ -41,6 +43,7 @@ impl TypeDefinition<'_> {
| Self::Function(definition)
| Self::TypeVar(definition)
| Self::TypeAlias(definition)
| Self::SpecialForm(definition)
| Self::NewType(definition) => {
let module = parsed_module(db, definition.file(db)).load(db);
Some(definition.full_range(db, &module))

View File

@ -10872,7 +10872,7 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
if let Some(builder) = self.context.report_lint(&INVALID_TYPE_FORM, subscript) {
builder.into_diagnostic(format_args!(
"`typing.{}` requires exactly one argument",
special_form.repr()
special_form.name()
));
}
Type::unknown()
@ -10907,7 +10907,7 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
{
builder.into_diagnostic(format_args!(
"`typing.{}` requires exactly two arguments, got {}",
special_form.repr(),
special_form.name(),
arguments.len()
));
}
@ -10931,7 +10931,7 @@ impl<'db, 'ast> TypeInferenceBuilder<'db, 'ast> {
if let Some(builder) = self.context.report_lint(&INVALID_TYPE_FORM, subscript) {
builder.into_diagnostic(format_args!(
"`typing.{}` requires exactly two arguments, got 1",
special_form.repr()
special_form.name()
));
}

View File

@ -1318,10 +1318,9 @@ impl<'db> TypeInferenceBuilder<'db, '_> {
self.infer_type_expression(arguments_slice);
if let Some(builder) = self.context.report_lint(&INVALID_TYPE_FORM, subscript) {
let diag = builder.into_diagnostic(format_args!(
"Special form `{}` expected exactly one type parameter",
special_form.repr()
));
let diag = builder.into_diagnostic(
"Special form `typing.TypeIs` expected exactly one type parameter",
);
diagnostic::add_type_expression_reference_link(diag);
}

View File

@ -4,6 +4,10 @@
use super::{ClassType, Type, class::KnownClass};
use crate::db::Db;
use crate::module_resolver::{KnownModule, file_to_module};
use crate::resolve_module;
use crate::semantic_index::place::ScopedPlaceId;
use crate::semantic_index::{FileScopeId, place_table, use_def_map};
use crate::types::TypeDefinition;
use ruff_db::files::File;
use std::str::FromStr;
@ -435,59 +439,132 @@ impl SpecialFormType {
}
}
/// Return the repr of the symbol at runtime
pub(super) const fn repr(self) -> &'static str {
/// Return the name of the symbol at runtime
pub(super) const fn name(self) -> &'static str {
match self {
SpecialFormType::Any => "typing.Any",
SpecialFormType::Annotated => "typing.Annotated",
SpecialFormType::Literal => "typing.Literal",
SpecialFormType::LiteralString => "typing.LiteralString",
SpecialFormType::Optional => "typing.Optional",
SpecialFormType::Union => "typing.Union",
SpecialFormType::NoReturn => "typing.NoReturn",
SpecialFormType::Never => "typing.Never",
SpecialFormType::Tuple => "typing.Tuple",
SpecialFormType::Type => "typing.Type",
SpecialFormType::TypingSelf => "typing.Self",
SpecialFormType::Final => "typing.Final",
SpecialFormType::ClassVar => "typing.ClassVar",
SpecialFormType::Callable => "typing.Callable",
SpecialFormType::Concatenate => "typing.Concatenate",
SpecialFormType::Unpack => "typing.Unpack",
SpecialFormType::Required => "typing.Required",
SpecialFormType::NotRequired => "typing.NotRequired",
SpecialFormType::TypeAlias => "typing.TypeAlias",
SpecialFormType::TypeGuard => "typing.TypeGuard",
SpecialFormType::TypedDict => "typing.TypedDict",
SpecialFormType::TypeIs => "typing.TypeIs",
SpecialFormType::List => "typing.List",
SpecialFormType::Dict => "typing.Dict",
SpecialFormType::DefaultDict => "typing.DefaultDict",
SpecialFormType::Set => "typing.Set",
SpecialFormType::FrozenSet => "typing.FrozenSet",
SpecialFormType::Counter => "typing.Counter",
SpecialFormType::Deque => "typing.Deque",
SpecialFormType::ChainMap => "typing.ChainMap",
SpecialFormType::OrderedDict => "typing.OrderedDict",
SpecialFormType::ReadOnly => "typing.ReadOnly",
SpecialFormType::Unknown => "ty_extensions.Unknown",
SpecialFormType::AlwaysTruthy => "ty_extensions.AlwaysTruthy",
SpecialFormType::AlwaysFalsy => "ty_extensions.AlwaysFalsy",
SpecialFormType::Not => "ty_extensions.Not",
SpecialFormType::Intersection => "ty_extensions.Intersection",
SpecialFormType::TypeOf => "ty_extensions.TypeOf",
SpecialFormType::CallableTypeOf => "ty_extensions.CallableTypeOf",
SpecialFormType::Top => "ty_extensions.Top",
SpecialFormType::Bottom => "ty_extensions.Bottom",
SpecialFormType::Protocol => "typing.Protocol",
SpecialFormType::Generic => "typing.Generic",
SpecialFormType::NamedTuple => "typing.NamedTuple",
SpecialFormType::Any => "Any",
SpecialFormType::Annotated => "Annotated",
SpecialFormType::Literal => "Literal",
SpecialFormType::LiteralString => "LiteralString",
SpecialFormType::Optional => "Optional",
SpecialFormType::Union => "Union",
SpecialFormType::NoReturn => "NoReturn",
SpecialFormType::Never => "Never",
SpecialFormType::Tuple => "Tuple",
SpecialFormType::Type => "Type",
SpecialFormType::TypingSelf => "Self",
SpecialFormType::Final => "Final",
SpecialFormType::ClassVar => "ClassVar",
SpecialFormType::Callable => "Callable",
SpecialFormType::Concatenate => "Concatenate",
SpecialFormType::Unpack => "Unpack",
SpecialFormType::Required => "Required",
SpecialFormType::NotRequired => "NotRequired",
SpecialFormType::TypeAlias => "TypeAlias",
SpecialFormType::TypeGuard => "TypeGuard",
SpecialFormType::TypedDict => "TypedDict",
SpecialFormType::TypeIs => "TypeIs",
SpecialFormType::List => "List",
SpecialFormType::Dict => "Dict",
SpecialFormType::DefaultDict => "DefaultDict",
SpecialFormType::Set => "Set",
SpecialFormType::FrozenSet => "FrozenSet",
SpecialFormType::Counter => "Counter",
SpecialFormType::Deque => "Deque",
SpecialFormType::ChainMap => "ChainMap",
SpecialFormType::OrderedDict => "OrderedDict",
SpecialFormType::ReadOnly => "ReadOnly",
SpecialFormType::Unknown => "Unknown",
SpecialFormType::AlwaysTruthy => "AlwaysTruthy",
SpecialFormType::AlwaysFalsy => "AlwaysFalsy",
SpecialFormType::Not => "Not",
SpecialFormType::Intersection => "Intersection",
SpecialFormType::TypeOf => "TypeOf",
SpecialFormType::CallableTypeOf => "CallableTypeOf",
SpecialFormType::Top => "Top",
SpecialFormType::Bottom => "Bottom",
SpecialFormType::Protocol => "Protocol",
SpecialFormType::Generic => "Generic",
SpecialFormType::NamedTuple => "NamedTuple",
}
}
/// Return the module(s) in which this special form could be defined
fn definition_modules(self) -> &'static [KnownModule] {
match self {
SpecialFormType::Any
| SpecialFormType::Annotated
| SpecialFormType::Literal
| SpecialFormType::LiteralString
| SpecialFormType::Optional
| SpecialFormType::Union
| SpecialFormType::NoReturn
| SpecialFormType::Never
| SpecialFormType::Tuple
| SpecialFormType::Type
| SpecialFormType::TypingSelf
| SpecialFormType::Final
| SpecialFormType::ClassVar
| SpecialFormType::Callable
| SpecialFormType::Concatenate
| SpecialFormType::Unpack
| SpecialFormType::Required
| SpecialFormType::NotRequired
| SpecialFormType::TypeAlias
| SpecialFormType::TypeGuard
| SpecialFormType::TypedDict
| SpecialFormType::TypeIs
| SpecialFormType::ReadOnly
| SpecialFormType::Protocol
| SpecialFormType::Generic
| SpecialFormType::NamedTuple
| SpecialFormType::List
| SpecialFormType::Dict
| SpecialFormType::DefaultDict
| SpecialFormType::Set
| SpecialFormType::FrozenSet
| SpecialFormType::Counter
| SpecialFormType::Deque
| SpecialFormType::ChainMap
| SpecialFormType::OrderedDict => &[KnownModule::Typing, KnownModule::TypingExtensions],
SpecialFormType::Unknown
| SpecialFormType::AlwaysTruthy
| SpecialFormType::AlwaysFalsy
| SpecialFormType::Not
| SpecialFormType::Intersection
| SpecialFormType::TypeOf
| SpecialFormType::CallableTypeOf
| SpecialFormType::Top
| SpecialFormType::Bottom => &[KnownModule::TyExtensions],
}
}
pub(super) fn definition(self, db: &dyn Db) -> Option<TypeDefinition<'_>> {
self.definition_modules()
.iter()
.find_map(|module| {
let file = resolve_module(db, &module.name())?.file(db)?;
let scope = FileScopeId::global().to_scope_id(db, file);
let symbol_id = place_table(db, scope).symbol_id(self.name())?;
use_def_map(db, scope)
.end_of_scope_bindings(ScopedPlaceId::Symbol(symbol_id))
.next()?
.binding
.definition()
})
.map(TypeDefinition::SpecialForm)
}
}
impl std::fmt::Display for SpecialFormType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(self.repr())
write!(
f,
"{}.{}",
self.definition_modules()[0].as_str(),
self.name()
)
}
}