devscout_rs/extract/types.rs
1// ---------------------------------------------------------------------------
2// Graph fragment extraction and its helpers. Scope: defs =
3// namespace-level+nested types with public method names plus enum members;
4// refs = using directives, base-list types,
5// object-creation types, field/property/parameter/return types, generic
6// type arguments, and member-access qualifier.member candidates. No
7// call-graph resolution.
8// ---------------------------------------------------------------------------
9
10/// Represents `DefRecord`.
11pub struct DefRecord {
12 /// The id value.
13 pub id: String,
14 /// The name value.
15 pub name: String,
16 /// The namespace value.
17 pub namespace: String,
18 /// The kind value.
19 pub kind: String,
20 /// The line value.
21 pub line: usize,
22 /// The methods value.
23 pub methods: Vec<String>,
24 /// Declared property names, source order, deduped
25 /// (indexers excluded by construction: `indexer_declaration` is a
26 /// different grammar node). NO accessibility filter, deliberately
27 /// asymmetric with `methods`: static/const/readonly/expression-bodied all
28 /// count and only indexers are excluded, so a private member is still a
29 /// member of the type. Empty for every
30 /// enum-member def.
31 pub properties: Vec<String>,
32 /// Declared field names, source order, deduped, every
33 /// declarator of every `field_declaration` ("private int a, b;"
34 /// contributes both). `event_field_declaration` is a distinct node type
35 /// and is NOT a field for this purpose. Same no-accessibility-filter
36 /// rule as `properties`.
37 pub fields: Vec<String>,
38 /// (method name, declared return type NAME) pairs in
39 /// FIRST-declaration source order, parallel to `methods` (same
40 /// `is_recorded_method` predicate, so the two can never drift). The
41 /// first declaration of a name claims the slot outright: a later
42 /// overload with a different return type is ignored, and a first
43 /// declaration whose return type yields no fact (void, var, a
44 /// predefined type) BLOCKS the name rather than letting a later
45 /// overload stand in for it. A Vec of pairs, not a map: the serialized
46 /// key order is significant (see graph.rs's FragDef).
47 pub method_returns: Vec<(String, String)>,
48 /// The extension methods this type declares: every method
49 /// whose FIRST parameter carries the `this` modifier, in source order,
50 /// deduped by (name, thisType, arityMin, arityMax). Appended LAST, after
51 /// `method_returns`, and omitted at serialization when empty. Unlike
52 /// `methods` there is NO accessibility filter (`internal static class
53 /// FooExtensions` is the shape this feature exists for) and no `static`
54 /// check on either the method or its class -- C# already disallows a
55 /// `this` parameter anywhere else, so the parameter modifier IS the
56 /// discriminator.
57 pub extension_methods: Vec<ExtensionMethod>,
58 /// The DIRECT base-type identifiers this
59 /// declaration lists, in source order, deduped. Same base_list traversal
60 /// `record_base_list` walks for its `inherits` refs, reduced to a base
61 /// IDENTIFIER because the resolver re-RESOLVES these names through the
62 /// ordinary ladder rather than matching them; the resulting closure is
63 /// what lets the extension tier see an inherited instance member and
64 /// decline. Appended after `extension_methods` and omitted when empty.
65 pub bases: Vec<String>,
66 /// The declaring type's OWN type-parameter names (`class
67 /// MongoRepository<T>` records `["T"]`), empty for every non-generic
68 /// declaration. This is the ctor-DI resolver's "is this def itself an
69 /// open-generic implementation" signal. Appended after `bases`, omitted
70 /// when empty.
71 pub type_params: Vec<String>,
72 /// Per base name that carried a type-argument list, that
73 /// list's generic-arg descriptors relative to `type_params` (a `"*"`
74 /// wildcard marks a position that is a pass-through of the declaring
75 /// type's own parameter). A `Vec` of pairs, not a map, for the same
76 /// reason `method_returns` is: the serialized key order is significant.
77 /// Appended after `type_params`, omitted when empty; a base
78 /// with no type-argument list at all contributes no entry.
79 pub base_generic_args: Vec<(String, Vec<String>)>,
80 /// The methods this type declares that a test
81 /// framework would DISCOVER as tests, in source order, deduped. Appended
82 /// LAST, after `base_generic_args`, and omitted at serialization when
83 /// empty. The attribute IS the fact, which is why this is the one member
84 /// fact with no accessibility filter at all and why no file, folder or
85 /// type-name convention is read anywhere.
86 pub test_methods: Vec<String>,
87 /// (property name, declared type fact) pairs for exactly the
88 /// properties `properties` records, in the same source order and under the
89 /// same dedup. A property whose declared type yields no fact (a predefined
90 /// type) has no entry, so the two lists are parallel but not equal in
91 /// length. A `Vec` of pairs, not a map, for the same reason
92 /// `method_returns` is one: the serialized key order is significant.
93 /// Appended LAST, after `test_methods`.
94 pub property_types: Vec<(String, Fact)>,
95 /// (field name, declared type fact) pairs for exactly the
96 /// fields `fields` records, in the same source order and under the same
97 /// dedup. A field whose declared type yields no fact (a predefined type)
98 /// has no entry, so the two lists are parallel but not equal in length.
99 /// Every declarator of one `field_declaration` shares that declaration's
100 /// own type node, so `private int a, b;` gives `a` and `b` the SAME
101 /// fact -- the same declarator sharing `fields`'s own collection loop
102 /// already relies on. A `Vec` of pairs, not a map, for the same reason
103 /// `property_types` is one: the serialized key order is significant.
104 /// Appended LAST, after `property_types`.
105 pub field_types: Vec<(String, Fact)>,
106 /// Per method name that `method_returns` also records an
107 /// entry for, that return type's top-level generic-arg descriptors --
108 /// the same capture `base_generic_args` keeps beside `bases`, for the
109 /// same reason: `method_returns` records only the return type's bare
110 /// identifier ("Task" for `Task<Order> GetAsync()`), and this is what
111 /// lets the resolver unwrap ONE `Task<...>`/`ValueTask<...>` layer off
112 /// an AWAITED call's callee without ever touching `method_returns`
113 /// itself, which an unawaited use of the very same callee reads
114 /// unchanged. A `Vec` of pairs, not a map, for the same reason
115 /// `method_returns` is one: the serialized key order is significant.
116 /// Appended LAST of all, after `field_types`; a method whose return
117 /// type carries no type-argument list at all contributes no entry.
118 pub method_return_args: Vec<(String, Vec<String>)>,
119 /// Declared METHOD names this type does NOT record in `methods`,
120 /// because `is_recorded_method` gates that list on a literal `public`
121 /// modifier (or `kind == "interface"`, where every method already
122 /// counts as public and this list is always empty). Same predicate,
123 /// same `method_declaration` node kind, same source order and dedup as
124 /// `methods` -- the two lists partition a type's method declarations
125 /// with no overlap and no gap. Unlike `properties`/`fields`, which
126 /// already carry every accessibility with no filter at all, `methods`
127 /// needed a counterpart list for a non-public method (protected,
128 /// internal, private or no-modifier/private-by-default) to be
129 /// recorded anywhere. Consulted by the resolver ONLY for
130 /// hierarchy-internal receivers -- a `base.` lookup and the `this.`
131 /// shape's own typed-receiver walk -- never by the scored tier's
132 /// vouching or veto, which keep reading `methods` alone. Appended
133 /// LAST of all, after `method_return_args`.
134 pub non_public_methods: Vec<String>,
135 /// Method name -> the (min, max) argument-count RANGE every overload
136 /// sharing that name accepts, one tuple per overload, in declaration
137 /// order -- covers EVERY `method_declaration`, public and non-public
138 /// alike (unlike `methods`/`non_public_methods`, which only say a name
139 /// exists, this says what a CALL of that name needs to look like).
140 /// `min` excludes a parameter carrying a default value or the `params`
141 /// modifier; `max` is the total parameter count, or -1 (unbounded) when
142 /// the trailing parameter is a `params` array -- the same sentinel
143 /// `ExtensionMethod::arity_max` already uses. A `Vec` of pairs, not a
144 /// map, for the same reason `method_returns` is one: the serialized key
145 /// order is significant. Consulted by the resolver's arity-aware call
146 /// vouching: a ref carrying an `argCount` binds to `methods`/
147 /// `non_public_methods` only when SOME overload's range admits it: a
148 /// same-named instance member at the wrong arity does not shadow the
149 /// extension tier. A read (no `argCount`) never consults this table.
150 /// Appended LAST of all, after `non_public_methods`.
151 pub method_arities: Vec<(String, Vec<(usize, i64)>)>,
152 /// Method name -> per-overload parameter type descriptors (see
153 /// `type_descriptor`), one `Vec<String>` per overload in declaration
154 /// order -- covers EVERY `method_declaration`, public and non-public
155 /// alike, same method set as `method_arities`. A position naming the
156 /// enclosing method's or type's own type parameter is recorded as `"*"`
157 /// (wildcard); a parameter carrying the `this` modifier is written
158 /// `"this <descriptor>"` (the extension-method marker). For a
159 /// `delegate` def this carries exactly one entry, keyed `"Invoke"`,
160 /// built from the delegate's own parameter list (a delegate has no
161 /// body, so it is not one of the `method_declaration` overloads this
162 /// otherwise iterates). A `Vec` of pairs, not a map, for the same
163 /// reason `method_returns` is one: the serialized key order is
164 /// significant. Appended LAST of all, after `method_arities`.
165 pub method_params: Vec<(String, Vec<Vec<String>>)>,
166 /// Declared method names carrying the literal `override` modifier,
167 /// source order, deduped. Appended LAST of all, after `method_params`.
168 /// Consulted only by the resolver's member-level `overrides` pass,
169 /// itself run only for a type the resolver already knows is a
170 /// registered DI implementation -- see `graph.rs`'s `FragDef`.
171 pub override_methods: Vec<String>,
172 /// 1-based last line of the complete declaration node.
173 pub end_line: usize,
174}
175
176/// One `extensionMethods` entry. Field order (`name`, `thisType`, `arityMin`,
177/// `arityMax`, `thisArgs`) is significant: it fixes the serialized field
178/// order.
179#[derive(Debug, Clone, PartialEq)]
180pub struct ExtensionMethod {
181 /// The name value.
182 pub name: String,
183 /// The this type value.
184 pub this_type: String,
185 /// Non-this parameters a caller cannot
186 /// leave out: no default value AND no `params` modifier.
187 pub arity_min: usize,
188 /// Total non-this parameter count, or -1 when the trailing parameter is a
189 /// `params` array (unbounded above). Signed precisely so -1 can be the
190 /// sentinel written as a JSON number.
191 pub arity_max: i64,
192 /// The this-parameter type's TOP-LEVEL
193 /// type-argument descriptors, present only when that type is generic.
194 /// A position naming one of the method's or the enclosing class's own type
195 /// parameters is recorded as "*" (wildcard).
196 pub this_args: Option<Vec<String>>,
197}
198
199/// Represents `RefRecord`.
200pub struct RefRecord {
201 /// The kind value.
202 pub kind: String,
203 /// The name value.
204 pub name: String,
205 /// The qualified value.
206 pub qualified: Option<String>,
207 /// The member value.
208 pub member: Option<String>,
209 /// The line value.
210 pub line: usize,
211 /// `None` only for 'imports' refs -- a using directive is not
212 /// namespace-scoped, so `ns` is deliberately `null`. Every other ref
213 /// carries `Some(ns)`, where `ns`
214 /// may itself be the empty string at file scope.
215 pub namespace: Option<String>,
216 /// The type arg count value.
217 pub type_arg_count: Option<usize>,
218 /// `true` when a uses-member qualifier carried a
219 /// type-argument list anywhere (`Cache<T>.x`, `Ns.Cache<T>.x`): syntax
220 /// only a TYPE can carry, so the resolver treats it as type-certainty
221 /// for non-enum member emission. Always `false` for every other ref
222 /// kind.
223 pub generic: bool,
224 /// The declared type NAME of the receiver a uses-member
225 /// qualifier names, when the enclosing scope holds exactly one fact for
226 /// it (a declared local, a `var x = new T()` local, a parameter, a
227 /// field, or a primary-constructor parameter). Set ONLY for a BARE,
228 /// non-generic qualifier -- see the `member_access_expression` arm's
229 /// guard, which is what makes the chain-tail hazard structurally
230 /// impossible. Always `None` for every other ref kind.
231 pub receiver_type: Option<String>,
232 /// The argument count of the call this
233 /// member access is the CALLEE of (`argument_list` named-child count),
234 /// recorded only when the access is the `function` field of an
235 /// `invocation_expression`. A property read (`x.P`) carries `None`, which
236 /// is what keeps it out of the arity-matched extension tier entirely.
237 /// Appended AFTER `receiver_type`. Always `None` for every other ref kind.
238 pub arg_count: Option<usize>,
239 /// The DECLARED receiver type's top-level
240 /// type-argument descriptors, present only when that type is generic. A
241 /// position naming a type parameter of the enclosing method or class is
242 /// recorded as "*" (wildcard): nothing at the fact site knows its binding.
243 /// Travels with `receiver_type` -- the fact carries both or neither.
244 /// Appended LAST, after `arg_count`.
245 pub receiver_args: Option<Vec<String>>,
246 /// The walk's own type_stack verbatim: the enclosing type simple
247 /// names, OUTERMOST first, the same order type_id joins with "+" to build
248 /// a nested def id. Empty at namespace level, and empty is exactly what an
249 /// absent key deserializes to. Appended LAST, after `receiver_args`.
250 pub outer_types: Vec<String>,
251 /// Generic-arg descriptors for a 'ctor-param' ref's
252 /// parameter type (same descriptor shape as `receiver_args`: a `"*"`
253 /// wildcard for a pass-through of the enclosing type's own type
254 /// parameter), present only when that type is generic. `None` for every
255 /// other ref kind. Appended LAST of all, after `outer_types` -- 'ctor-param'
256 /// is a ref kind no other caller touches, so putting it after that
257 /// "last of all" field costs no other ref kind a single byte.
258 pub args: Option<Vec<String>>,
259 /// The type whose PROPERTY the qualifier's last segment is, for
260 /// a two-segment chain whose head the enclosing scope has a fact for
261 /// ("a.Settings" in `a.Settings.Reload()`). Never travels with
262 /// `receiver_type`: that one is bare-qualifier-only and this one is
263 /// dotted-qualifier-only, which is what keeps the chain-tail hazard
264 /// structurally impossible -- the resolver reaches the tail's type through
265 /// the head type's RECORDED property types, never by inheriting the head's
266 /// own. Appended after `args`.
267 pub receiver_property_owner: Option<String>,
268 /// The type whose METHOD a `var x = Q.M(...)` initializer
269 /// called, and that method's name. Always set as a pair, and never
270 /// alongside `receiver_type`: the local's type is whatever `M` returns, a
271 /// lookup only the resolver can do. Appended LAST of all.
272 pub receiver_call_owner: Option<String>,
273 /// The receiver call member value.
274 pub receiver_call_member: Option<String>,
275 /// `true` for a `base.M` qualifier -- the member lookup starts at the
276 /// enclosing type's bases and never considers the enclosing type
277 /// itself. `false` for every other ref kind, including a plain `this.M`
278 /// qualifier (which resolves through the ordinary typed-receiver path
279 /// against the enclosing type itself). Appended LAST of all.
280 pub receiver_base: bool,
281 /// `true` when this ref's `receiver_call_owner`/`receiver_call_member`
282 /// pair came from an AWAITED call (`var x = await Q.M()`, `_client` a
283 /// field: `var order = await _client.FetchAsync()`) -- the resolver reads
284 /// it to decide whether to unwrap exactly one `Task<...>`/`ValueTask<...>`
285 /// layer off `M`'s recorded return type before typing the local. `false`
286 /// for an unawaited call fact and for every ref carrying no call fact at
287 /// all, which is what keeps `var t = x.FetchAsync(); t.Wait();` typed as
288 /// `Task` rather than unwrapped. Appended LAST of all, after
289 /// `receiver_base`.
290 pub receiver_awaited: bool,
291 /// `true` when this ref's qualifier is a bare identifier for which the
292 /// enclosing MEMBER's own fact table -- `Scope::has_local_fact`, the
293 /// SAME `member_facts` table `receiver_fact_for` reads first -- holds
294 /// ANY entry for the name: a local, a parameter, an explicitly-typed
295 /// lambda parameter, a pattern designation, or an `out` designation,
296 /// typed or taken-but-unknown. A member-scoped name always shadows a
297 /// same-named field regardless of whether anything vouches for its
298 /// type, so the resolver's bare-identifier field/property fallback
299 /// (Unit B) reads this to refuse running at all when it is `true` --
300 /// the one shape a resolved `receiver_type`/`receiver_call_owner` of
301 /// `None` cannot itself distinguish from "no fact anywhere for this
302 /// name". `false` for a dotted or generic qualifier, for `this.`/
303 /// `base.` (never asked of the enclosing scope's local table), and for
304 /// every ref kind but `uses-member`. Appended LAST of all, after
305 /// `receiver_awaited`.
306 pub receiver_local: bool,
307 /// Set when this ref's qualifier is an untyped lambda parameter whose
308 /// type is a delegate parameter of some OTHER callee -- a lookup only
309 /// the resolver can do. Never set alongside `receiver_type` or
310 /// `receiver_call_owner`: the three are mutually exclusive on one ref.
311 /// `receiver_local` still reads `true` for such a ref (the parameter
312 /// IS a member-scoped name), and `receiver_type` stays `None`. Appended
313 /// LAST of all, after `receiver_local`.
314 pub receiver_lambda: Option<LambdaSlot>,
315 /// `true` when `receiver_type` came off a declaration whose own type
316 /// node was a `nullable_type` (`Widget? w`) -- see `Fact::nullable`,
317 /// which this carries verbatim off the SAME receiver fact
318 /// `receiver_type`/`receiver_args` already came off. `false` for every
319 /// ref kind, and for a `receiver_type` that came from anywhere but a
320 /// plain declared-type fact (a call-hop return, a lambda-slot type, a
321 /// bare field/property fallback: none of those can be nullable-
322 /// annotated, since none of them read a type node directly). Appended
323 /// LAST of all, after `receiver_lambda`.
324 pub receiver_nullable: bool,
325 /// The parameter count of each delegate-shaped argument of the
326 /// invocation this ref is the callee of -- a lambda literal, or a bare
327 /// identifier naming one unshadowed local function in scope -- one
328 /// entry per argument position (`None` at every other position), or
329 /// `None` entirely when the ref is not invocation-shaped or names no
330 /// such argument at all. `x => ...` counts 1 parameter, `(a, b) => ...`
331 /// counts 2, `() => ...` counts 0, a local function counts its own
332 /// declared parameters -- the argument's OWN arity, never the delegate
333 /// type it will end up bound to (that binding is exactly what this fact
334 /// lets the resolver judge, rather than assume). Appended LAST of all,
335 /// after `receiver_nullable`.
336 pub lambda_arg_arity: Option<Vec<Option<usize>>>,
337}
338
339/// Represents `UsingRecord`.
340pub enum UsingRecord {
341 /// The value value.
342 Alias {
343 /// The alias name.
344 alias: String,
345 /// The aliased target.
346 target: String,
347 /// Whether the directive is global.
348 global: bool,
349 },
350 /// The value value.
351 Plain {
352 /// The imported namespace text.
353 text: String,
354 /// Whether the directive is global.
355 global: bool,
356 },
357}
358
359/// Represents `Extraction`.
360pub struct Extraction {
361 /// The purpose value.
362 pub purpose: Option<String>,
363 /// The defs value.
364 pub defs: Vec<DefRecord>,
365 /// The usings value.
366 pub usings: Vec<UsingRecord>,
367 /// The refs value.
368 pub refs: Vec<RefRecord>,
369 /// Every member the file's types declare, appended LAST after
370 /// `refs` in both the fragment and the `extract-dump` shape.
371 pub names: Vec<NameRecord>,
372 /// Every two-type-argument DI service registration the file's
373 /// invocations record, appended LAST after `names`. See
374 /// `RegistrationRecord`.
375 pub registrations: Vec<RegistrationRecord>,
376}
377
378/// One two-type-argument DI service registration.
379///
380/// The shape is an invocation whose method name begins `Add` or `TryAdd`
381/// and ends `Singleton`, `Scoped` or `Transient`, carrying exactly two type
382/// arguments -- the first the service type, the second the implementation
383/// type. `service`/`implementation` carry the type argument's raw text
384/// verbatim (dotted when the source wrote it qualified); splitting a dotted
385/// name into its bare tail plus its full qualified form, the way an
386/// ordinary type reference does, is the resolver's job, not the
387/// extractor's.
388#[derive(Debug, Clone, PartialEq)]
389pub struct RegistrationRecord {
390 /// The service (first type argument) name, as written.
391 pub service: String,
392 /// The implementation (second type argument) name, as written.
393 pub implementation: String,
394 /// The registration call's enclosing namespace.
395 pub namespace: String,
396 /// The registration call's 1-based line.
397 pub line: usize,
398}
399
400/// One declared name and the line its own NAME TOKEN sits on. Deliberately
401/// not the declaration node's start row: a member's span begins
402/// at its attribute list, so an attributed member would point a reader at the
403/// `[` line instead of the line carrying the name they searched for.
404///
405/// Serialized field order (`name`, `kind`, `line`, `owner`) is significant;
406/// `owner` is omitted when empty, which is how a markup or resource
407/// key -- built by `markup.rs`, owned by no C# type -- serializes with three
408/// fields.
409#[derive(Debug, Clone, PartialEq)]
410pub struct NameRecord {
411 /// The name value.
412 pub name: String,
413 /// The kind value.
414 pub kind: String,
415 /// The line value.
416 pub line: usize,
417 /// The owner value.
418 pub owner: String,
419}
420
421/// One untyped lambda parameter's callee slot.
422///
423/// The name's type is the delegate parameter of the invocation the lambda
424/// sits inside as an argument -- a lookup only the resolver can do (it has
425/// to look up the callee's own delegate-typed parameter at `arg_index` and
426/// read ITS `index`-th parameter type). `owner`/`member` name the callee like
427/// a call fact's `type_name`/`call` do; `arg_count`/`arg_index` locate the
428/// lambda among the callee's arguments; `arity`/`index` locate this
429/// parameter inside the lambda itself.
430#[derive(Debug, Clone, PartialEq, Eq)]
431pub struct LambdaSlot {
432 /// The type-name text the callee is invoked on: the identifier's
433 /// in-file fact type, the identifier itself when the name is not taken
434 /// (a static class), or the innermost enclosing type for `this.M(...)`
435 /// / bare `M(...)`.
436 pub owner: String,
437 /// The callee method name.
438 pub member: String,
439 /// The argument count of the callee invocation.
440 pub arg_count: usize,
441 /// The position of the lambda among the callee invocation's arguments.
442 pub arg_index: usize,
443 /// The lambda's own parameter count.
444 pub arity: usize,
445 /// This parameter's position inside the lambda's parameter list.
446 pub index: usize,
447}
448
449/// One receiver fact: the declared type NAME plus that type's top-level
450/// type-argument descriptors when it carried any. Two facts agree only when
451/// BOTH halves do, so `Box<int> a` and `Box<string> a` in sibling blocks
452/// conflict exactly like two different type names would.
453#[derive(Clone, PartialEq, Eq)]
454pub struct Fact {
455 /// The type name value.
456 pub type_name: String,
457 /// The args value.
458 pub args: Option<Vec<String>>,
459 /// When set, the name's type is whatever the method of this name returns
460 /// on the type `type_name` stands for, a lookup only the resolver can do.
461 /// Part of the equality the table compares, so `var x = A.Make()` and
462 /// `var x = A.Build()` in sibling blocks conflict exactly like two
463 /// different type names would.
464 pub call: Option<String>,
465 /// `true` when this is a call fact (`call.is_some()`) built from an
466 /// AWAITED invocation (`var x = await Q.M()`); meaningless -- and always
467 /// `false` -- when `call` is `None`. Part of the equality the table
468 /// compares, so `var x = Q.M()` and `var x = await Q.M()` in sibling
469 /// blocks conflict exactly like two different callees would, rather than
470 /// silently picking one awaited-ness for a name the source gives two.
471 pub awaited: bool,
472 /// `true` when the declaration's own type node was, at its TOP level, an
473 /// `array_type` (`Widget[]`) -- set ONLY by `type_fact`, `false`
474 /// everywhere else (a call fact, a receiver-args unwrap, `this`/`base`'s
475 /// own fact: none of those can be an array). `base_type_identifier`
476 /// already collapses `Widget[]` to the same `type_name`/`args` shape a
477 /// plain `Widget` field would carry (the element type's own base
478 /// identifier, no type-argument list), so this bit is the ONLY signal
479 /// left that distinguishes "one Widget" from "an array of Widget" --
480 /// needed by the lambda-parameter element-typing rule, which must tell
481 /// `Widget[]` apart from `Widget` even though both facts otherwise read
482 /// identically. Part of the equality the table compares.
483 pub is_array: bool,
484 /// `true` when the declaration's own type node was, at its TOP level, a
485 /// `nullable_type` (`Widget?`) -- set ONLY by `type_fact`, `false`
486 /// everywhere else, mirroring `is_array`: a call fact, a receiver-args
487 /// unwrap and `this`/`base`'s own fact are never nullable-annotated.
488 /// `base_type_identifier` already unwraps `Widget?` to the same
489 /// `type_name` a plain `Widget` field would carry, so this bit is the
490 /// only signal left that a `System.Nullable<T>` sits between the
491 /// declared name and the value -- needed so the resolver can refuse a
492 /// member the wrapper itself owns (`.Value`, `.HasValue`,
493 /// `.GetValueOrDefault`) rather than binding `T`'s own same-named
494 /// member. Part of the equality the table compares.
495 pub nullable: bool,
496 /// When set, the name is an untyped lambda parameter whose type is the
497 /// corresponding delegate parameter of the callee this slot names -- a
498 /// lookup only the resolver can do; `type_name` is empty and `call` is
499 /// `None`. Part of the equality the table compares, so two sibling
500 /// lambdas binding the same parameter name to different callees
501 /// conflict exactly like two different type names would.
502 pub lambda: Option<LambdaSlot>,
503}