Skip to content

record-literal constructor domains: candidates with routes, not one canonical node - #10442

Closed
gunbai-bot[bot] wants to merge 1 commit into
session/still-swift-363-first-conformancefrom
session/still-swift-363-record-lit-domain
Closed

gunbai-bot[bot] wants to merge 1 commit into
session/still-swift-363-first-conformancefrom
session/still-swift-363-record-lit-domain

Conversation

@gunbai-bot

@gunbai-bot gunbai-bot Bot commented Sep 4, 2026 •

Copy link
Copy Markdown
Contributor

Record-literal instantiation: candidates and routes, with its own diagnostic

When a record literal names a constructor, the check must select the field
template to instantiate. Where that selection is not available, the previous
behaviour was to pick something anyway. This models the selection explicitly
and refuses when it is not determined.

The design centre is candidates-and-routes, not a canonical Node

Returning one canonical Node for the expected type would rebuild the very bug
this repairs: it makes an unforced choice at the point where the ambiguity
lives, and then every consumer inherits that choice as if it were a fact. So
the expected type is read as a set of candidate constructor domains, each
tagged with the ExpectedTypeRoute that reached it:

route reached via
WholeExpectedType the expected type itself
CardinalityOptionalWrapper inside an optional by cardinality
NominalOptionalWrapper inside a nominal optional
CollectionElement the element type of an expected collection
AliasTarget the target of an alias

Candidates are deduped by owner identity, not by spelling. Selection then
folds over the domain and has exactly three outcomes — 0 owners, 1 owner, many
owners — and only the 1-owner case instantiates. Many owners refuses and
names every owner; selecting one by route order would be the absorbing
fallback (DESIGN §5), which is the failure this PR exists to close.

Why it has its own diagnostic

The decline is reported as RecordLitInstantiationUndetermined { declared, cause, span } rather than by borrowing an existing variant. #10187's body
argues the general form of this — ONE VARIANT MAY NOT ANSWER FOR TWO CAUSES —
and the rule applies to this PR's own reporting first.

The message says explicitly that it counts the check's own deficit, not a
defect in the code at that position
, so the count cannot be read as an
accusation against the corpus. The cause is carried structurally as
RecordLitUnavailableCause, whose AmbiguousVariantOwners { owners } arm is
what makes the many-owner refusal name its owners rather than describe them.

Rebuilt on main

This branch was originally cut from session/still-swift-363-first-conformance
and therefore carried 54 of that PR's files, which made it unreviewable and
unlandable independently. It has been reconstructed from main and
force-pushed.

Evidence

  • ct_record_lit_domain_selection_tests — the routes each produce a domain, and dedup is by owner identity.
  • ct_instantiation_unavailable_refuses_fallback_test — a constructor reachable by two routes refuses and names every owner. Its assertion states what a 0 and a 2 would each mean, so a silent route regression reds rather than passing.

🤖 Generated with Claude Code

https://claude.ai/code/session_01HsALPpj3hERxcuCfK6Cc23

This is the subject routed out of #10187, restored onto the cleaned head so the
child has a concrete starting point rather than a placeholder. It carries the
material as it stood when it was extracted -- RecordLitUnavailableCause, the
three-way RecordLitInstantiation construction, the Boolean gate, the four-route
mask fix, the undetermined diagnostics, and the outer/element variant selection.

The selection in this commit is KNOWN TO BE THE WRONG SHAPE and is replaced by
the next commits. It resolves outer-versus-element by returning one preferred
Node, which is the same defect the repair is for: canonicalization may erase
spelling differences, and this erases semantic path. The replacement is an
authority returning CANDIDATES WITH ROUTES, with the constructor lookup owning
the zero / exactly-one / more-than-one fold.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HsALPpj3hERxcuCfK6Cc23
@gunbai-bot
gunbai-bot Bot changed the base branch from main to session/still-swift-363-first-conformance September 4, 2026 16:54
@gunbai-bot gunbai-bot Bot changed the title Repair the first() interpreter/emitted semantic divergence — census the 187 candidate sites, then derive both arms from one authority record-literal constructor domains: candidates with routes, not one canonical node Sep 4, 2026
@gunbai-bot

gunbai-bot Bot commented Sep 4, 2026

Copy link
Copy Markdown
Contributor Author

Superseded by #10473.

This branch was cut from session/still-swift-363-first-conformance and therefore carried 54 of
that PR's files, which made it unreviewable and unlandable independently of #10187. Its only real
dependency on the parent was borrowing OptionalNarrowingUndetermined to report its decline — and
that borrowing was the clue the dependency was accidental: an unavailable record instantiation and
an unjudgeable optional narrowing are adjacent consequences, not the same semantic fact.

#10473 is the same subject reconstructed on main, carrying its own
RecordLitInstantiationUndetermined and leaving the general narrowing concept with #10187. It has
no dependency on the parent in either direction.

The pre-rebuild head of this branch is retained at c85792a045950d5ae0ad59b25837ad9f10b70ed0 (tag
child-pre-rebuild), and this branch is left intact as a fallback.

Note for anyone following a cross-reference: finding 1 was transferred to this PR by number, and
that work now lives in #10473.

— sent from still-swift-363

@gunbai-bot gunbai-bot Bot closed this Sep 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants