Skip to content

Commit bfb859d

Browse files
committed
P-037 A2.2-4R5: a constructor initializer is a call site of its own (call_kind: constructor_initializer)
The A2.2-4R4 ruling re-classified the constructor-initializer argument (formal note §10.6.10, F-CTOR-INIT, §10.1 case 3) from a vocabulary edge to a call-like fact shape: `Holder(MemoryStream r) : base(r, true)` passes the handle into a really invoked constructor's declared ordinal 0, the same ownership edge object_creation was added for, and "the callee is outside the vocabulary" would be circular. This commit lands the shape. Production: BuildGuardedFacts emits one call fact for a constructor's `: this(...)` / `: base(...)` through the shared EmitCall — the site is the ConstructorInitializerSyntax (its coordinate the `:`), the callee the target constructor's `{Type}..ctor` key with its canonical signature, first_party by declaring syntax, the arguments bound to the target constructor's declared ordinals (named arguments resolved; params and ref/out as everywhere), form `statement` (it runs first and yields nothing), tagged call_kind constructor_initializer (schema enum, producer set and spec §5.2 in step). The initializer sits beside the body, not inside it, so the invocation and object-creation loops now walk the initializer's argument syntax before the body's: `: base(Wrap(r), true)` captures r at Wrap and the initializer receives a call result, the nested_call_result reading the ruling asked for. Every member without an initializer reads exactly as before. Evidence: the registry's call-like forms gain constructor_initializer; the probe gains a constructor row, CtorInit (`Probe.CtorInit..ctor`, the freeze test learns constructor rows), whose historical columns were measured with the extractor rebuilt at each step's commit (A' 5a0de07, A2.2-1 268bbd4, A2.2-2 376f2e6, A2.2-2b 7de7a6f, A2.2-3P 80cd9aa: no_record at every step, the initializer was never visited and an empty body carries nothing) and the whole probe was re-measured into a2_2_4r5_observed with this tree's extractor: exactly the CtorInit row moves, to orphan_call:constructor_initializer (an empty forwarding body lowers to nothing, so the legacy pass admits no record and the orphan carrier holds the fact), every other row equals a2_2_3p_observed; the census gains sidecar-ctorinit-base (the 52 earlier shapes byte-identical); the oracle binds the site kind and attributes nested calls inside an initializer; the hostile census gains ctorinit-nested-call and ctorinit-named-transparent beside the re-designed vocab-constructor-initializer, all green by design; the oracle's unclassified_argument_shape kinds are empty over every input; F-CTOR-INIT moves to `closed`. The inertness control and the local rehearsal against the T before-takes are unchanged on both engines. Same instrument, no new T/R. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QfeUtLRm6KFRWcTGQZxQQb
1 parent b2aa766 commit bfb859d

21 files changed

Lines changed: 514 additions & 86 deletions

‎corpus/p037-hostile/README.md‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,11 +57,14 @@ plus the named cases:
5757
accessor, and a declared local function (the known, counted gap);
5858
- two receiver forms (`ext-*`): a reduced extension through `?.`, and a
5959
struct handle boxed into an `object` receiver;
60+
- three constructor-initializer sites (`ctorinit-*`, `vocab-constructor-initializer`):
61+
a direct forwarding, named and reordered arguments under a reference
62+
upcast, and a nested call whose result the initializer receives;
6063
- the argument shapes the frozen vocabulary had no name for (`vocab-*`): a
6164
tested operand, an interpolation hole and an indexer argument, named by the
6265
A2.2-4R4 ruling (`predicate_result`, `interpolation_hole`,
6366
`indexer_argument`), and a constructor-initializer argument, a call-like
64-
fact shape pending A2.2-4R5.
67+
fact shape since A2.2-4R5 (`call_kind: constructor_initializer`).
6568

6669
The findings these witness are classified in
6770
`corpus/p037-relevance/oracle_findings.json`; each stays RED, by name, until a
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// GENERATED by scripts/p037_hostile_census.py (P-037 A2.2-4 hostile census); do not edit.
2+
// call-like site: a constructor initializer with named, reordered arguments and a reference upcast on the handle; the target constructor's declared ordinals bind
3+
using System;
4+
using System.IO;
5+
using System.Collections.Generic;
6+
7+
static class H_ctorinit_named_transparent
8+
{
9+
class Base { public Base(Stream s, bool b) { } }
10+
sealed class Holder : Base { public Holder(MemoryStream r) : base(b: true, s: (Stream)r) { } }
11+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// GENERATED by scripts/p037_hostile_census.py (P-037 A2.2-4 hostile census); do not edit.
2+
// call-like site: a nested call inside a constructor initializer's argument; the inner call captures the handle, the initializer receives its result (nested_call_result)
3+
using System;
4+
using System.IO;
5+
using System.Collections.Generic;
6+
7+
static class H_ctorinit_nested_call
8+
{
9+
static Stream Wrap(Stream s) { return s; }
10+
class Base { public Base(Stream s, bool b) { } }
11+
sealed class Holder : Base { public Holder(MemoryStream r) : base(Wrap(r), true) { } }
12+
}

‎corpus/p037-hostile/cases/vocab-constructor-initializer.cs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// GENERATED by scripts/p037_hostile_census.py (P-037 A2.2-4 hostile census); do not edit.
2-
// vocabulary edge: an owned constructor parameter forwarded through `: base(...)`, a really invoked constructor's declared ordinal 0; ruled a call-like fact shape in A2.2-4R4, landing in A2.2-4R5 (finding F-CTOR-INIT)
2+
// call-like site: an owned constructor parameter forwarded through `: base(...)`, a really invoked constructor's declared ordinal 0 (ruled a fact shape in A2.2-4R4, landed in A2.2-4R5: call_kind constructor_initializer)
33
using System;
44
using System.IO;
55
using System.Collections.Generic;

‎corpus/p037-hostile/expected.json‎

Lines changed: 42 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,41 @@
246246
"red": {},
247247
"why": "composition: parentheses around a handle whose parameter type needs op_Implicit; the conversion wins over the transparent-looking syntax (\u00a710.6.3)"
248248
},
249+
"ctorinit-named-transparent": {
250+
"member": "H_ctorinit_named_transparent.M",
251+
"member_override": ".Holder..ctor",
252+
"carrier": "guarded_functions",
253+
"occurrences": [
254+
{
255+
"symbol": "r",
256+
"verdict": "captured",
257+
"site_kind": "constructor_initializer",
258+
"ordinal": 0,
259+
"expected": "param"
260+
}
261+
],
262+
"red": {},
263+
"why": "call-like site: a constructor initializer with named, reordered arguments and a reference upcast on the handle; the target constructor's declared ordinals bind"
264+
},
265+
"ctorinit-nested-call": {
266+
"member": "H_ctorinit_nested_call.M",
267+
"member_override": ".Holder..ctor",
268+
"carrier": "guarded_functions",
269+
"occurrences": [
270+
{
271+
"symbol": "r",
272+
"verdict": "captured",
273+
"site_kind": "invocation",
274+
"ordinal": 0,
275+
"expected": "param",
276+
"enclosing": [
277+
"nested_call_result"
278+
]
279+
}
280+
],
281+
"red": {},
282+
"why": "call-like site: a nested call inside a constructor initializer's argument; the inner call captures the handle, the initializer receives its result (nested_call_result)"
283+
},
249284
"ext-boxed-receiver": {
250285
"member": "H_ext_boxed_receiver.M",
251286
"carrier": "functions",
@@ -3038,19 +3073,18 @@
30383073
"vocab-constructor-initializer": {
30393074
"member": "H_vocab_constructor_initializer.M",
30403075
"member_override": ".Holder..ctor",
3041-
"carrier": "none",
3076+
"carrier": "guarded_functions",
30423077
"occurrences": [
30433078
{
30443079
"symbol": "r",
3045-
"verdict": "red",
3046-
"explanation": "unclassified_argument_shape:constructor_initializer"
3080+
"verdict": "captured",
3081+
"site_kind": "constructor_initializer",
3082+
"ordinal": 0,
3083+
"expected": "param"
30473084
}
30483085
],
3049-
"red": {
3050-
"unclassified_argument_shape:constructor_initializer": 1
3051-
},
3052-
"finding": "F-CTOR-INIT",
3053-
"why": "vocabulary edge: an owned constructor parameter forwarded through `: base(...)`, a really invoked constructor's declared ordinal 0; ruled a call-like fact shape in A2.2-4R4, landing in A2.2-4R5 (finding F-CTOR-INIT)"
3086+
"red": {},
3087+
"why": "call-like site: an owned constructor parameter forwarded through `: base(...)`, a really invoked constructor's declared ordinal 0 (ruled a fact shape in A2.2-4R4, landed in A2.2-4R5: call_kind constructor_initializer)"
30543088
},
30553089
"vocab-indexer-argument": {
30563090
"member": "H_vocab_indexer_argument.M",

‎corpus/p037-relevance/oracle_findings.json‎

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,6 @@
88
"evidence": "Program.cs enumerates ClassDeclarationSyntax only and, inside it, BaseMethodDeclarationSyntax with a block Body; the three A2.2-3P admission gates sit inside that loop, so these members reach neither functions[] nor guarded_functions[]. Witnessed by the probe (Box.op_Implicit, an expression-bodied conversion operator) and by four hostile cases.",
99
"status": "open: a census finding; carrying these members in the orphan carrier is a production change to be classified on its own",
1010
"red": "occurrence_not_captured"
11-
},
12-
"F-CTOR-INIT": {
13-
"class": "case 3",
14-
"title": "a constructor initializer `: base(...)` / `: this(...)` is a call-like site without a fact shape",
15-
"evidence": "`Holder(MemoryStream r) : base(r, true)` passes the owned parameter into a really invoked constructor's declared ordinal 0, the same ownership edge object_creation was added for; the frozen vocabulary has no call_kind for a ConstructorInitializerSyntax site, so no fact exists and the oracle reads the occurrence as unclassified. Ruled in A2.2-4R4 to be a fact shape (call_kind constructor_initializer; site the initializer; callee the target constructor's {Type}..ctor key; sig its canonical signature; arguments bound to the target constructor's declared ordinals; first_party by declaring syntax; the same value-flow and binding machinery), landing in A2.2-4R5. Witnessed by the hostile case vocab-constructor-initializer.",
16-
"status": "open: A2.2-4R5 adds the fact shape",
17-
"red": "unclassified_argument_shape:constructor_initializer"
1811
}
1912
},
2013
"expected_red": {
@@ -54,6 +47,13 @@
5447
"evidence": "Each is a candidate occurrence under a call-related syntax site that no frozen exclusion names; production emits no fact for any of them (correctly: no handle reaches a callee of the vocabulary), so each needs a name, never a bucket. Witnessed by four hostile cases.",
5548
"status": "closed: the A2.2-4R4 ruling. predicate_result, interpolation_hole and indexer_argument are frozen exclusions (registry, \u00a710.6.4, probe rows PredicateResult / InterpolationHole / IndexerArgument, oracle); the constructor-initializer argument is not an exclusion but a call-like fact shape, tracked as F-CTOR-INIT.",
5649
"red": "unclassified_argument_shape:*"
50+
},
51+
"F-CTOR-INIT": {
52+
"class": "case 3",
53+
"title": "a constructor initializer `: base(...)` / `: this(...)` is a call-like site without a fact shape",
54+
"evidence": "`Holder(MemoryStream r) : base(r, true)` passes the owned parameter into a really invoked constructor's declared ordinal 0, the same ownership edge object_creation was added for; the frozen vocabulary has no call_kind for a ConstructorInitializerSyntax site, so no fact exists and the oracle reads the occurrence as unclassified. Ruled in A2.2-4R4 to be a fact shape (call_kind constructor_initializer; site the initializer; callee the target constructor's {Type}..ctor key; sig its canonical signature; arguments bound to the target constructor's declared ordinals; first_party by declaring syntax; the same value-flow and binding machinery), landing in A2.2-4R5. Witnessed by the hostile case vocab-constructor-initializer.",
55+
"status": "closed: A2.2-4R5. call_kind constructor_initializer; the initializer's argument syntax is visited for nested call sites too; three hostile witnesses and the census shape sidecar-ctorinit-base are green; the probe row CtorInit reads orphan_call:constructor_initializer.",
56+
"red": "unclassified_argument_shape:constructor_initializer"
5757
}
5858
}
5959
}

‎corpus/p037-relevance/probe/case.cs‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ static void TakeDerivedRef(Derived d) { }
3030
struct Token : IDisposable { public void Dispose() { } }
3131
static void SinkObject(object o) { }
3232
static void Use6(bool b) { }
33+
class FwdBase { public FwdBase(Stream s, bool leaveOpen) { } }
3334

3435
// direct
3536
static void Plain() { var r = new MemoryStream(); Inner(r, true); } // implicit reference upcast at the parameter
@@ -77,4 +78,7 @@ static void Use6(bool b) { }
7778
static void PredicateResult() { var r = new MemoryStream(); Use6(r != null); } // the predicate's bool is the argument
7879
static void InterpolationHole() { var r = new MemoryStream(); Use4($"{r}"); } // the built string is the argument
7980
static void IndexerArgument() { var r = new MemoryStream(); var d = new Dictionary<Stream, int>(); d[r] = 1; } // the handle is the index of an accessor call outside the vocabulary
81+
82+
// call-like: a constructor initializer (A2.2-4R5); the row is this class's constructor, `Probe.CtorInit..ctor`
83+
sealed class CtorInit : FwdBase { public CtorInit(MemoryStream r) : base(r, true) { } }
8084
}

0 commit comments

Comments
 (0)