Skip to content
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
164 changes: 164 additions & 0 deletions dag/test/claim/decl_facts_reflection_witness_test.dag
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
module test.claim.decl_facts_reflection_witness_test

import v2.std.decl_facts_skeleton {
decl_facts_nullary_variant_value_identity_gap_note,
decl_facts_outer_record_constructor_lexeme_authority_note,
skeleton_contains_marshal_atom_lexeme,
skeleton_contains_outer_record_constructor_lexeme,
skeleton_marshal_atom_lexeme_count,
skeleton_outer_record_constructor_lexeme_count,
}
import test.fixture.decl_facts_reflection.witness_support {
decl_facts_reflection_fixture_facts,
decl_fact_skeleton_for_qualified_name,
}
import v2.std.collection { Absent, Present }
import v2.std.algebra { length }

data decl_facts_reflection_witness_note: String = "Step-1 prerequisite (#7796), PARTIAL: outer record-constructor SPELLING (OuterRecordConstructorLexeme) is reflected and tested via executing witnesses. Exact parent-variant identity and nullary variant VALUE identity remain open — parse-only decl_facts cannot ground dissolves_to: SingleAuthority or field: WholeDeclaration; see decl_facts_nullary_variant_value_identity_gap_note. Rust tests in v1-compiler-tests are developer convenience only (compile-only in CI; nextest retired 2026-07-11)."

data qn_planted_scaffold_specimen: String = "test.fixture.decl_facts_reflection.specimens.planted_scaffold_specimen"
data qn_planted_terminal_specimen: String = "test.fixture.decl_facts_reflection.specimens.planted_terminal_specimen"
data qn_planted_nullary_disposition_specimen: String = "test.fixture.decl_facts_reflection.specimens.planted_nullary_disposition_specimen"
data qn_planted_named_field_ref_specimen: String = "test.fixture.decl_facts_reflection.specimens.planted_named_field_ref_specimen"
data qn_planted_plain_int_specimen: String = "test.fixture.decl_facts_reflection.specimens.planted_plain_int_specimen"
data qn_uses_param_only: String = "test.fixture.decl_facts_reflection.specimens.uses_param_only"
data qn_uses_local: String = "test.fixture.decl_facts_reflection.specimens.uses_local"

test fn w_fixture_pool_decl_facts_nonempty() -> Bool {
length(xs: decl_facts_reflection_fixture_facts()) > 0
}

test fn w_outer_record_constructor_scaffold_lexeme_surfaces() -> Bool {
match decl_fact_skeleton_for_qualified_name(
facts: decl_facts_reflection_fixture_facts(),
qn: qn_planted_scaffold_specimen
) {
Present { value: skeleton } =>
skeleton_contains_outer_record_constructor_lexeme(node: skeleton, lexeme: "Scaffold")
&& skeleton_outer_record_constructor_lexeme_count(node: skeleton, lexeme: "Scaffold") == 1
Absent => false
}
}

test fn w_outer_record_constructor_terminal_lexeme_surfaces() -> Bool {
match decl_fact_skeleton_for_qualified_name(
facts: decl_facts_reflection_fixture_facts(),
qn: qn_planted_terminal_specimen
) {
Present { value: skeleton } =>
skeleton_contains_outer_record_constructor_lexeme(node: skeleton, lexeme: "Terminal")
Absent => false
}
}

test fn w_declaration_ref_bind_fields_surface_in_scaffold_specimen() -> Bool {
match decl_fact_skeleton_for_qualified_name(
facts: decl_facts_reflection_fixture_facts(),
qn: qn_planted_scaffold_specimen
) {
Present { value: skeleton } =>
skeleton_contains_outer_record_constructor_lexeme(node: skeleton, lexeme: "DeclarationRef")
&& skeleton_contains_marshal_atom_lexeme(
node: skeleton,
lexeme: "test.fixture.decl_facts_reflection.specimens"
)
&& skeleton_contains_marshal_atom_lexeme(node: skeleton, lexeme: "planted_scaffold_specimen")
&& !skeleton_contains_marshal_atom_lexeme(node: skeleton, lexeme: "WholeDeclaration")
Absent => false
}
}

test fn w_named_field_declaration_ref_surfaces() -> Bool {
match decl_fact_skeleton_for_qualified_name(
facts: decl_facts_reflection_fixture_facts(),
qn: qn_planted_named_field_ref_specimen
) {
Present { value: skeleton } =>
skeleton_contains_outer_record_constructor_lexeme(node: skeleton, lexeme: "NamedField")
&& skeleton_contains_marshal_atom_lexeme(node: skeleton, lexeme: "dissolves_to")
Absent => false
}
}

test fn w_plain_int_specimen_has_no_coproduct_constructor_lexemes() -> Bool {
match decl_fact_skeleton_for_qualified_name(
facts: decl_facts_reflection_fixture_facts(),
qn: qn_planted_plain_int_specimen
) {
Present { value: skeleton } =>
!skeleton_contains_outer_record_constructor_lexeme(node: skeleton, lexeme: "Scaffold")
&& !skeleton_contains_outer_record_constructor_lexeme(node: skeleton, lexeme: "Terminal")
&& !skeleton_contains_marshal_atom_lexeme(node: skeleton, lexeme: "SingleAuthority")
&& !skeleton_contains_outer_record_constructor_lexeme(node: skeleton, lexeme: "DeclarationRef")
Absent => false
}
}

test fn w_nullary_variant_value_absent_without_infer_stamping_top_level() -> Bool {
match decl_fact_skeleton_for_qualified_name(
facts: decl_facts_reflection_fixture_facts(),
qn: qn_planted_nullary_disposition_specimen
) {
Present { value: skeleton } =>
!skeleton_contains_marshal_atom_lexeme(node: skeleton, lexeme: "SingleAuthority")
Absent => false
}
}

test fn w_nullary_variant_value_absent_without_infer_stamping_nested() -> Bool {
match decl_fact_skeleton_for_qualified_name(
facts: decl_facts_reflection_fixture_facts(),
qn: qn_planted_scaffold_specimen
) {
Present { value: skeleton } =>
!skeleton_contains_marshal_atom_lexeme(node: skeleton, lexeme: "SingleAuthority")
Absent => false
}
}

test fn w_fn_body_param_reference_does_not_gain_constructor_lexemes() -> Bool {
match decl_fact_skeleton_for_qualified_name(
facts: decl_facts_reflection_fixture_facts(),
qn: qn_uses_param_only
) {
Present { value: skeleton } =>
!skeleton_contains_outer_record_constructor_lexeme(node: skeleton, lexeme: "Scaffold")
&& !skeleton_contains_marshal_atom_lexeme(node: skeleton, lexeme: "SingleAuthority")
&& !skeleton_contains_outer_record_constructor_lexeme(node: skeleton, lexeme: "DeclarationRef")
Absent => false
}
}

test fn w_fn_body_local_bindings_do_not_gain_constructor_lexemes() -> Bool {
match decl_fact_skeleton_for_qualified_name(
facts: decl_facts_reflection_fixture_facts(),
qn: qn_uses_local
) {
Present { value: skeleton } =>
!skeleton_contains_outer_record_constructor_lexeme(node: skeleton, lexeme: "Scaffold")
&& !skeleton_contains_marshal_atom_lexeme(node: skeleton, lexeme: "SingleAuthority")
&& !skeleton_contains_outer_record_constructor_lexeme(node: skeleton, lexeme: "DeclarationRef")
Absent => false
}
}

test fn w_gap_note_names_infer_binding_kind_authority() -> Bool {
string_contains(
s: decl_facts_nullary_variant_value_identity_gap_note,
pattern: "VariantValueBinding",
) && string_contains(
s: decl_facts_nullary_variant_value_identity_gap_note,
pattern: "lookup_variant_parent_enum",
)
}

test fn w_authority_note_names_constructor_lexeme_not_variant_identity() -> Bool {
string_contains(
s: decl_facts_outer_record_constructor_lexeme_authority_note,
pattern: "OuterRecordConstructorLexeme",
) && string_contains(
s: decl_facts_outer_record_constructor_lexeme_authority_note,
pattern: "not variant identity",
)
}
39 changes: 39 additions & 0 deletions dag/test/fixture/decl_facts_reflection/specimens.dag
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
module test.fixture.decl_facts_reflection.specimens

import std.types { String, Int }
import std.disposition { Disposition, Scaffold, Terminal, SingleAuthority }
import std.decl_ref { DeclarationRef, WholeDeclaration, NamedField }

data planted_scaffold_specimen: Disposition = Scaffold {
dissolves_to: SingleAuthority,
bind: DeclarationRef {
module_path: "test.fixture.decl_facts_reflection.specimens",
decl_name: "planted_scaffold_specimen",
field: WholeDeclaration
}
}

data planted_terminal_specimen: Disposition = Terminal {
reason: "fixture terminal arm"
}

data planted_nullary_disposition_specimen: Disposition = SingleAuthority

data planted_named_field_ref_specimen: DeclarationRef = DeclarationRef {
module_path: "test.fixture.decl_facts_reflection.specimens",
decl_name: "planted_scaffold_specimen",
field: NamedField { field_name: "dissolves_to" }
}

data planted_plain_int_specimen: Int = 42

data planted_plain_string_specimen: String = "hello"

fn uses_param_only(x: Int) -> Int {
x
}

fn uses_local(y: Int) -> Int {
let z = y
z
}
28 changes: 28 additions & 0 deletions dag/test/fixture/decl_facts_reflection/witness_support.dag
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
module test.fixture.decl_facts_reflection.witness_support

import std.types { List }
import v2.std.decl_facts_skeleton {
DeclFactQualifiedNameResolution,
decl_fact_skeleton_for_resolution,
resolve_decl_fact_by_qualified_name,
}
import v2.std.decl_index { DeclFact, decl_facts }
import v2.std.node { Node }
import v2.std.collection { Absent, Present }

data decl_facts_reflection_fixture_pool_roots: List<String> = [
"dag/test/fixture/decl_facts_reflection",
]

fn decl_facts_reflection_fixture_facts() -> List<DeclFact> {
decl_facts(pool_roots: decl_facts_reflection_fixture_pool_roots)
}

fn decl_fact_skeleton_for_qualified_name(
facts: List<DeclFact>,
qn: String
) -> Node? {
decl_fact_skeleton_for_resolution(
resolution: resolve_decl_fact_by_qualified_name(facts: facts, qn: qn)
)
}
7 changes: 6 additions & 1 deletion src/v1/stage0/src/coproduct_reflection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -664,7 +664,12 @@ fn marshal_generic(
let name = node_authored_name(node, si);
let mut edges: Vec<Value> = Vec::with_capacity(node.children.len() + 1);
let mut refs: std::collections::BTreeSet<String> = std::collections::BTreeSet::new();
if node_references_param(node, &name, param_names) {
if matches!(node.expr_data.as_ref(), ExprData::ExprRecordLit { .. }) && !name.is_empty() {
// Outer record-constructor SPELLING (OuterRecordConstructorLexeme) from ExprRecordLit
// authored name — not resolved parent-variant identity; see
// `v2.std.decl_facts_skeleton` `decl_facts_outer_record_constructor_lexeme_authority_note`.
edges.push(edge_positional(ctx, atom_identity_node(ctx, &name)));
} else if node_references_param(node, &name, param_names) {
edges.push(edge_positional(ctx, atom_identity_node(ctx, &name)));
} else if matches!(node.expr_data.as_ref(), ExprData::ExprCall { .. }) && !name.is_empty() {
// G2 live-read call reachability: callee atoms make cross-fn carrier chains
Expand Down
Loading
Loading