ruff/crates/ruff_python_parser/tests/snapshots/valid_syntax@expressions__dictionary.py.snap
Ibraheem Ahmed c9dff5c7d5
[ty] AST garbage collection (#18482)
## Summary

Garbage collect ASTs once we are done checking a given file. Queries
with a cross-file dependency on the AST will reparse the file on demand.
This reduces ty's peak memory usage by ~20-30%.

The primary change of this PR is adding a `node_index` field to every
AST node, that is assigned by the parser. `ParsedModule` can use this to
create a flat index of AST nodes any time the file is parsed (or
reparsed). This allows `AstNodeRef` to simply index into the current
instance of the `ParsedModule`, instead of storing a pointer directly.

The indices are somewhat hackily (using an atomic integer) assigned by
the `parsed_module` query instead of by the parser directly. Assigning
the indices in source-order in the (recursive) parser turns out to be
difficult, and collecting the nodes during semantic indexing is
impossible as `SemanticIndex` does not hold onto a specific
`ParsedModuleRef`, which the pointers in the flat AST are tied to. This
means that we have to do an extra AST traversal to assign and collect
the nodes into a flat index, but the small performance impact (~3% on
cold runs) seems worth it for the memory savings.

Part of https://github.com/astral-sh/ty/issues/214.
2025-06-13 08:40:11 -04:00

1393 lines
74 KiB
Text

---
source: crates/ruff_python_parser/tests/fixtures.rs
input_file: crates/ruff_python_parser/resources/valid/expressions/dictionary.py
---
## AST
```
Module(
ModModule {
node_index: AtomicNodeIndex(..),
range: 0..622,
body: [
Expr(
StmtExpr {
node_index: AtomicNodeIndex(..),
range: 9..11,
value: Dict(
ExprDict {
node_index: AtomicNodeIndex(..),
range: 9..11,
items: [],
},
),
},
),
Expr(
StmtExpr {
node_index: AtomicNodeIndex(..),
range: 12..18,
value: Dict(
ExprDict {
node_index: AtomicNodeIndex(..),
range: 12..18,
items: [
DictItem {
key: Some(
NumberLiteral(
ExprNumberLiteral {
node_index: AtomicNodeIndex(..),
range: 13..14,
value: Int(
1,
),
},
),
),
value: NumberLiteral(
ExprNumberLiteral {
node_index: AtomicNodeIndex(..),
range: 16..17,
value: Int(
2,
),
},
),
},
],
},
),
},
),
Expr(
StmtExpr {
node_index: AtomicNodeIndex(..),
range: 19..43,
value: Dict(
ExprDict {
node_index: AtomicNodeIndex(..),
range: 19..43,
items: [
DictItem {
key: Some(
NumberLiteral(
ExprNumberLiteral {
node_index: AtomicNodeIndex(..),
range: 20..21,
value: Int(
1,
),
},
),
),
value: NumberLiteral(
ExprNumberLiteral {
node_index: AtomicNodeIndex(..),
range: 23..24,
value: Int(
2,
),
},
),
},
DictItem {
key: Some(
Name(
ExprName {
node_index: AtomicNodeIndex(..),
range: 26..27,
id: Name("a"),
ctx: Load,
},
),
),
value: NumberLiteral(
ExprNumberLiteral {
node_index: AtomicNodeIndex(..),
range: 29..30,
value: Int(
1,
),
},
),
},
DictItem {
key: Some(
Name(
ExprName {
node_index: AtomicNodeIndex(..),
range: 32..33,
id: Name("b"),
ctx: Load,
},
),
),
value: StringLiteral(
ExprStringLiteral {
node_index: AtomicNodeIndex(..),
range: 35..42,
value: StringLiteralValue {
inner: Single(
StringLiteral {
range: 35..42,
node_index: AtomicNodeIndex(..),
value: "hello",
flags: StringLiteralFlags {
quote_style: Single,
prefix: Empty,
triple_quoted: false,
},
},
),
},
},
),
},
],
},
),
},
),
Expr(
StmtExpr {
node_index: AtomicNodeIndex(..),
range: 66..69,
value: Dict(
ExprDict {
node_index: AtomicNodeIndex(..),
range: 66..69,
items: [],
},
),
},
),
Expr(
StmtExpr {
node_index: AtomicNodeIndex(..),
range: 70..100,
value: Dict(
ExprDict {
node_index: AtomicNodeIndex(..),
range: 70..100,
items: [
DictItem {
key: Some(
NumberLiteral(
ExprNumberLiteral {
node_index: AtomicNodeIndex(..),
range: 76..77,
value: Int(
1,
),
},
),
),
value: NumberLiteral(
ExprNumberLiteral {
node_index: AtomicNodeIndex(..),
range: 83..84,
value: Int(
2,
),
},
),
},
DictItem {
key: Some(
NumberLiteral(
ExprNumberLiteral {
node_index: AtomicNodeIndex(..),
range: 90..91,
value: Int(
3,
),
},
),
),
value: NumberLiteral(
ExprNumberLiteral {
node_index: AtomicNodeIndex(..),
range: 97..98,
value: Int(
4,
),
},
),
},
],
},
),
},
),
Expr(
StmtExpr {
node_index: AtomicNodeIndex(..),
range: 111..132,
value: Dict(
ExprDict {
node_index: AtomicNodeIndex(..),
range: 111..132,
items: [
DictItem {
key: Some(
Dict(
ExprDict {
node_index: AtomicNodeIndex(..),
range: 112..118,
items: [
DictItem {
key: Some(
NumberLiteral(
ExprNumberLiteral {
node_index: AtomicNodeIndex(..),
range: 113..114,
value: Int(
1,
),
},
),
),
value: NumberLiteral(
ExprNumberLiteral {
node_index: AtomicNodeIndex(..),
range: 116..117,
value: Int(
2,
),
},
),
},
],
},
),
),
value: Dict(
ExprDict {
node_index: AtomicNodeIndex(..),
range: 120..131,
items: [
DictItem {
key: Some(
NumberLiteral(
ExprNumberLiteral {
node_index: AtomicNodeIndex(..),
range: 121..122,
value: Int(
3,
),
},
),
),
value: Dict(
ExprDict {
node_index: AtomicNodeIndex(..),
range: 124..130,
items: [
DictItem {
key: Some(
NumberLiteral(
ExprNumberLiteral {
node_index: AtomicNodeIndex(..),
range: 125..126,
value: Int(
4,
),
},
),
),
value: NumberLiteral(
ExprNumberLiteral {
node_index: AtomicNodeIndex(..),
range: 128..129,
value: Int(
5,
),
},
),
},
],
},
),
},
],
},
),
},
],
},
),
},
),
Expr(
StmtExpr {
node_index: AtomicNodeIndex(..),
range: 155..171,
value: Dict(
ExprDict {
node_index: AtomicNodeIndex(..),
range: 155..171,
items: [
DictItem {
key: Some(
Lambda(
ExprLambda {
node_index: AtomicNodeIndex(..),
range: 156..167,
parameters: Some(
Parameters {
range: 163..164,
node_index: AtomicNodeIndex(
0,
),
posonlyargs: [],
args: [
ParameterWithDefault {
range: 163..164,
node_index: AtomicNodeIndex(..),
parameter: Parameter {
range: 163..164,
node_index: AtomicNodeIndex(..),
name: Identifier {
id: Name("x"),
range: 163..164,
node_index: AtomicNodeIndex(..),
},
annotation: None,
},
default: None,
},
],
vararg: None,
kwonlyargs: [],
kwarg: None,
},
),
body: Name(
ExprName {
node_index: AtomicNodeIndex(..),
range: 166..167,
id: Name("x"),
ctx: Load,
},
),
},
),
),
value: NumberLiteral(
ExprNumberLiteral {
node_index: AtomicNodeIndex(..),
range: 169..170,
value: Int(
1,
),
},
),
},
],
},
),
},
),
Expr(
StmtExpr {
node_index: AtomicNodeIndex(..),
range: 172..202,
value: Dict(
ExprDict {
node_index: AtomicNodeIndex(..),
range: 172..202,
items: [
DictItem {
key: Some(
StringLiteral(
ExprStringLiteral {
node_index: AtomicNodeIndex(..),
range: 173..176,
value: StringLiteralValue {
inner: Single(
StringLiteral {
range: 173..176,
node_index: AtomicNodeIndex(..),
value: "A",
flags: StringLiteralFlags {
quote_style: Single,
prefix: Empty,
triple_quoted: false,
},
},
),
},
},
),
),
value: Lambda(
ExprLambda {
node_index: AtomicNodeIndex(..),
range: 178..192,
parameters: Some(
Parameters {
range: 185..186,
node_index: AtomicNodeIndex(
0,
),
posonlyargs: [],
args: [
ParameterWithDefault {
range: 185..186,
node_index: AtomicNodeIndex(..),
parameter: Parameter {
range: 185..186,
node_index: AtomicNodeIndex(..),
name: Identifier {
id: Name("p"),
range: 185..186,
node_index: AtomicNodeIndex(..),
},
annotation: None,
},
default: None,
},
],
vararg: None,
kwonlyargs: [],
kwarg: None,
},
),
body: NoneLiteral(
ExprNoneLiteral {
node_index: AtomicNodeIndex(..),
range: 188..192,
},
),
},
),
},
DictItem {
key: Some(
StringLiteral(
ExprStringLiteral {
node_index: AtomicNodeIndex(..),
range: 194..197,
value: StringLiteralValue {
inner: Single(
StringLiteral {
range: 194..197,
node_index: AtomicNodeIndex(..),
value: "B",
flags: StringLiteralFlags {
quote_style: Single,
prefix: Empty,
triple_quoted: false,
},
},
),
},
},
),
),
value: Name(
ExprName {
node_index: AtomicNodeIndex(..),
range: 199..200,
id: Name("C"),
ctx: Load,
},
),
},
],
},
),
},
),
Expr(
StmtExpr {
node_index: AtomicNodeIndex(..),
range: 224..237,
value: Dict(
ExprDict {
node_index: AtomicNodeIndex(..),
range: 224..237,
items: [
DictItem {
key: Some(
Named(
ExprNamed {
node_index: AtomicNodeIndex(..),
range: 226..232,
target: Name(
ExprName {
node_index: AtomicNodeIndex(..),
range: 226..227,
id: Name("x"),
ctx: Store,
},
),
value: NumberLiteral(
ExprNumberLiteral {
node_index: AtomicNodeIndex(..),
range: 231..232,
value: Int(
1,
),
},
),
},
),
),
value: Name(
ExprName {
node_index: AtomicNodeIndex(..),
range: 235..236,
id: Name("y"),
ctx: Load,
},
),
},
],
},
),
},
),
Expr(
StmtExpr {
node_index: AtomicNodeIndex(..),
range: 238..258,
value: Dict(
ExprDict {
node_index: AtomicNodeIndex(..),
range: 238..258,
items: [
DictItem {
key: Some(
Named(
ExprNamed {
node_index: AtomicNodeIndex(..),
range: 240..246,
target: Name(
ExprName {
node_index: AtomicNodeIndex(..),
range: 240..241,
id: Name("x"),
ctx: Store,
},
),
value: NumberLiteral(
ExprNumberLiteral {
node_index: AtomicNodeIndex(..),
range: 245..246,
value: Int(
1,
),
},
),
},
),
),
value: Named(
ExprNamed {
node_index: AtomicNodeIndex(..),
range: 250..256,
target: Name(
ExprName {
node_index: AtomicNodeIndex(..),
range: 250..251,
id: Name("y"),
ctx: Store,
},
),
value: NumberLiteral(
ExprNumberLiteral {
node_index: AtomicNodeIndex(..),
range: 255..256,
value: Int(
2,
),
},
),
},
),
},
],
},
),
},
),
Expr(
StmtExpr {
node_index: AtomicNodeIndex(..),
range: 284..289,
value: Dict(
ExprDict {
node_index: AtomicNodeIndex(..),
range: 284..289,
items: [
DictItem {
key: None,
value: Name(
ExprName {
node_index: AtomicNodeIndex(..),
range: 287..288,
id: Name("d"),
ctx: Load,
},
),
},
],
},
),
},
),
Expr(
StmtExpr {
node_index: AtomicNodeIndex(..),
range: 290..301,
value: Dict(
ExprDict {
node_index: AtomicNodeIndex(..),
range: 290..301,
items: [
DictItem {
key: Some(
Name(
ExprName {
node_index: AtomicNodeIndex(..),
range: 291..292,
id: Name("a"),
ctx: Load,
},
),
),
value: Name(
ExprName {
node_index: AtomicNodeIndex(..),
range: 294..295,
id: Name("b"),
ctx: Load,
},
),
},
DictItem {
key: None,
value: Name(
ExprName {
node_index: AtomicNodeIndex(..),
range: 299..300,
id: Name("d"),
ctx: Load,
},
),
},
],
},
),
},
),
Expr(
StmtExpr {
node_index: AtomicNodeIndex(..),
range: 302..312,
value: Dict(
ExprDict {
node_index: AtomicNodeIndex(..),
range: 302..312,
items: [
DictItem {
key: None,
value: Name(
ExprName {
node_index: AtomicNodeIndex(..),
range: 305..306,
id: Name("a"),
ctx: Load,
},
),
},
DictItem {
key: None,
value: Name(
ExprName {
node_index: AtomicNodeIndex(..),
range: 310..311,
id: Name("b"),
ctx: Load,
},
),
},
],
},
),
},
),
Expr(
StmtExpr {
node_index: AtomicNodeIndex(..),
range: 313..338,
value: Dict(
ExprDict {
node_index: AtomicNodeIndex(..),
range: 313..338,
items: [
DictItem {
key: Some(
StringLiteral(
ExprStringLiteral {
node_index: AtomicNodeIndex(..),
range: 314..317,
value: StringLiteralValue {
inner: Single(
StringLiteral {
range: 314..317,
node_index: AtomicNodeIndex(..),
value: "a",
flags: StringLiteralFlags {
quote_style: Double,
prefix: Empty,
triple_quoted: false,
},
},
),
},
},
),
),
value: StringLiteral(
ExprStringLiteral {
node_index: AtomicNodeIndex(..),
range: 319..322,
value: StringLiteralValue {
inner: Single(
StringLiteral {
range: 319..322,
node_index: AtomicNodeIndex(..),
value: "b",
flags: StringLiteralFlags {
quote_style: Double,
prefix: Empty,
triple_quoted: false,
},
},
),
},
},
),
},
DictItem {
key: None,
value: Name(
ExprName {
node_index: AtomicNodeIndex(..),
range: 326..327,
id: Name("c"),
ctx: Load,
},
),
},
DictItem {
key: Some(
StringLiteral(
ExprStringLiteral {
node_index: AtomicNodeIndex(..),
range: 329..332,
value: StringLiteralValue {
inner: Single(
StringLiteral {
range: 329..332,
node_index: AtomicNodeIndex(..),
value: "d",
flags: StringLiteralFlags {
quote_style: Double,
prefix: Empty,
triple_quoted: false,
},
},
),
},
},
),
),
value: StringLiteral(
ExprStringLiteral {
node_index: AtomicNodeIndex(..),
range: 334..337,
value: StringLiteralValue {
inner: Single(
StringLiteral {
range: 334..337,
node_index: AtomicNodeIndex(..),
value: "e",
flags: StringLiteralFlags {
quote_style: Double,
prefix: Empty,
triple_quoted: false,
},
},
),
},
},
),
},
],
},
),
},
),
Expr(
StmtExpr {
node_index: AtomicNodeIndex(..),
range: 339..367,
value: Dict(
ExprDict {
node_index: AtomicNodeIndex(..),
range: 339..367,
items: [
DictItem {
key: Some(
NumberLiteral(
ExprNumberLiteral {
node_index: AtomicNodeIndex(..),
range: 340..341,
value: Int(
1,
),
},
),
),
value: NumberLiteral(
ExprNumberLiteral {
node_index: AtomicNodeIndex(..),
range: 343..344,
value: Int(
2,
),
},
),
},
DictItem {
key: None,
value: Dict(
ExprDict {
node_index: AtomicNodeIndex(..),
range: 348..366,
items: [
DictItem {
key: Some(
StringLiteral(
ExprStringLiteral {
node_index: AtomicNodeIndex(..),
range: 349..357,
value: StringLiteralValue {
inner: Single(
StringLiteral {
range: 349..357,
node_index: AtomicNodeIndex(..),
value: "nested",
flags: StringLiteralFlags {
quote_style: Single,
prefix: Empty,
triple_quoted: false,
},
},
),
},
},
),
),
value: StringLiteral(
ExprStringLiteral {
node_index: AtomicNodeIndex(..),
range: 359..365,
value: StringLiteralValue {
inner: Single(
StringLiteral {
range: 359..365,
node_index: AtomicNodeIndex(..),
value: "dict",
flags: StringLiteralFlags {
quote_style: Single,
prefix: Empty,
triple_quoted: false,
},
},
),
},
},
),
},
],
},
),
},
],
},
),
},
),
Expr(
StmtExpr {
node_index: AtomicNodeIndex(..),
range: 368..393,
value: Dict(
ExprDict {
node_index: AtomicNodeIndex(..),
range: 368..393,
items: [
DictItem {
key: Some(
BinOp(
ExprBinOp {
node_index: AtomicNodeIndex(..),
range: 369..374,
left: Name(
ExprName {
node_index: AtomicNodeIndex(..),
range: 369..370,
id: Name("x"),
ctx: Load,
},
),
op: Mult,
right: NumberLiteral(
ExprNumberLiteral {
node_index: AtomicNodeIndex(..),
range: 373..374,
value: Int(
1,
),
},
),
},
),
),
value: BinOp(
ExprBinOp {
node_index: AtomicNodeIndex(..),
range: 376..382,
left: Name(
ExprName {
node_index: AtomicNodeIndex(..),
range: 376..377,
id: Name("y"),
ctx: Load,
},
),
op: Pow,
right: NumberLiteral(
ExprNumberLiteral {
node_index: AtomicNodeIndex(..),
range: 381..382,
value: Int(
2,
),
},
),
},
),
},
DictItem {
key: None,
value: Call(
ExprCall {
node_index: AtomicNodeIndex(..),
range: 386..392,
func: Name(
ExprName {
node_index: AtomicNodeIndex(..),
range: 386..390,
id: Name("call"),
ctx: Load,
},
),
arguments: Arguments {
range: 390..392,
node_index: AtomicNodeIndex(..),
args: [],
keywords: [],
},
},
),
},
],
},
),
},
),
Expr(
StmtExpr {
node_index: AtomicNodeIndex(..),
range: 460..471,
value: Dict(
ExprDict {
node_index: AtomicNodeIndex(..),
range: 460..471,
items: [
DictItem {
key: None,
value: UnaryOp(
ExprUnaryOp {
node_index: AtomicNodeIndex(..),
range: 464..469,
op: Not,
operand: Name(
ExprName {
node_index: AtomicNodeIndex(..),
range: 468..469,
id: Name("x"),
ctx: Load,
},
),
},
),
},
],
},
),
},
),
Expr(
StmtExpr {
node_index: AtomicNodeIndex(..),
range: 494..515,
value: Dict(
ExprDict {
node_index: AtomicNodeIndex(..),
range: 494..515,
items: [
DictItem {
key: Some(
NumberLiteral(
ExprNumberLiteral {
node_index: AtomicNodeIndex(..),
range: 495..496,
value: Int(
1,
),
},
),
),
value: If(
ExprIf {
node_index: AtomicNodeIndex(..),
range: 498..514,
test: BooleanLiteral(
ExprBooleanLiteral {
node_index: AtomicNodeIndex(..),
range: 503..507,
value: true,
},
),
body: Name(
ExprName {
node_index: AtomicNodeIndex(..),
range: 498..499,
id: Name("x"),
ctx: Load,
},
),
orelse: Name(
ExprName {
node_index: AtomicNodeIndex(..),
range: 513..514,
id: Name("y"),
ctx: Load,
},
),
},
),
},
],
},
),
},
),
Expr(
StmtExpr {
node_index: AtomicNodeIndex(..),
range: 516..575,
value: DictComp(
ExprDictComp {
node_index: AtomicNodeIndex(..),
range: 516..575,
key: If(
ExprIf {
node_index: AtomicNodeIndex(..),
range: 517..533,
test: BooleanLiteral(
ExprBooleanLiteral {
node_index: AtomicNodeIndex(..),
range: 522..526,
value: true,
},
),
body: Name(
ExprName {
node_index: AtomicNodeIndex(..),
range: 517..518,
id: Name("x"),
ctx: Load,
},
),
orelse: Name(
ExprName {
node_index: AtomicNodeIndex(..),
range: 532..533,
id: Name("y"),
ctx: Load,
},
),
},
),
value: Name(
ExprName {
node_index: AtomicNodeIndex(..),
range: 535..536,
id: Name("y"),
ctx: Load,
},
),
generators: [
Comprehension {
range: 537..555,
node_index: AtomicNodeIndex(..),
target: Name(
ExprName {
node_index: AtomicNodeIndex(..),
range: 541..542,
id: Name("x"),
ctx: Store,
},
),
iter: Call(
ExprCall {
node_index: AtomicNodeIndex(..),
range: 546..555,
func: Name(
ExprName {
node_index: AtomicNodeIndex(..),
range: 546..551,
id: Name("range"),
ctx: Load,
},
),
arguments: Arguments {
range: 551..555,
node_index: AtomicNodeIndex(..),
args: [
NumberLiteral(
ExprNumberLiteral {
node_index: AtomicNodeIndex(..),
range: 552..554,
value: Int(
10,
),
},
),
],
keywords: [],
},
},
),
ifs: [],
is_async: false,
},
Comprehension {
range: 556..574,
node_index: AtomicNodeIndex(..),
target: Name(
ExprName {
node_index: AtomicNodeIndex(..),
range: 560..561,
id: Name("y"),
ctx: Store,
},
),
iter: Call(
ExprCall {
node_index: AtomicNodeIndex(..),
range: 565..574,
func: Name(
ExprName {
node_index: AtomicNodeIndex(..),
range: 565..570,
id: Name("range"),
ctx: Load,
},
),
arguments: Arguments {
range: 570..574,
node_index: AtomicNodeIndex(..),
args: [
NumberLiteral(
ExprNumberLiteral {
node_index: AtomicNodeIndex(..),
range: 571..573,
value: Int(
10,
),
},
),
],
keywords: [],
},
},
),
ifs: [],
is_async: false,
},
],
},
),
},
),
Expr(
StmtExpr {
node_index: AtomicNodeIndex(..),
range: 576..600,
value: Dict(
ExprDict {
node_index: AtomicNodeIndex(..),
range: 576..600,
items: [
DictItem {
key: Some(
Set(
ExprSet {
node_index: AtomicNodeIndex(..),
range: 577..583,
elts: [
NumberLiteral(
ExprNumberLiteral {
node_index: AtomicNodeIndex(..),
range: 578..579,
value: Int(
1,
),
},
),
NumberLiteral(
ExprNumberLiteral {
node_index: AtomicNodeIndex(..),
range: 581..582,
value: Int(
2,
),
},
),
],
},
),
),
value: NumberLiteral(
ExprNumberLiteral {
node_index: AtomicNodeIndex(..),
range: 585..586,
value: Int(
3,
),
},
),
},
DictItem {
key: Some(
Name(
ExprName {
node_index: AtomicNodeIndex(..),
range: 588..589,
id: Name("x"),
ctx: Load,
},
),
),
value: Dict(
ExprDict {
node_index: AtomicNodeIndex(..),
range: 591..598,
items: [
DictItem {
key: Some(
NumberLiteral(
ExprNumberLiteral {
node_index: AtomicNodeIndex(..),
range: 592..593,
value: Int(
1,
),
},
),
),
value: NumberLiteral(
ExprNumberLiteral {
node_index: AtomicNodeIndex(..),
range: 595..596,
value: Int(
2,
),
},
),
},
],
},
),
},
],
},
),
},
),
Expr(
StmtExpr {
node_index: AtomicNodeIndex(..),
range: 601..621,
value: Dict(
ExprDict {
node_index: AtomicNodeIndex(..),
range: 601..621,
items: [
DictItem {
key: Some(
Name(
ExprName {
node_index: AtomicNodeIndex(..),
range: 603..604,
id: Name("x"),
ctx: Load,
},
),
),
value: Name(
ExprName {
node_index: AtomicNodeIndex(..),
range: 608..609,
id: Name("y"),
ctx: Load,
},
),
},
DictItem {
key: Some(
Name(
ExprName {
node_index: AtomicNodeIndex(..),
range: 613..614,
id: Name("z"),
ctx: Load,
},
),
),
value: Name(
ExprName {
node_index: AtomicNodeIndex(..),
range: 618..619,
id: Name("a"),
ctx: Load,
},
),
},
],
},
),
},
),
],
},
)
```