Skip to content

Seal file's four variants, discriminated by kind() #645

Closed

Description

@David-Noble-at-work

Feature: #625 · Part 2, phase 5 of sealed-provider-resources.md. This phase is where the feature's goal is met.

Any, Regular, Directory, SymbolicLink each become a sealed interface over an unexported struct (any, regular, directory, symbolicLink). Announcements keep naming provider.Regular and friends, so all four fragments stay byte-identical.

The discriminator (ruling 6)

Each variant interface declares kind() <Interface>:

type Regular interface { Resource; kind() Regular }
type Directory interface { Resource; kind() Directory }

Go compares full method signatures, result types included, so *regular cannot satisfy Directory. And because a type may declare only one method named kind, mutual exclusivity is structural — a concrete type cannot be two kinds at once. Four differently-named markers would keep the kinds distinct but say nothing about exclusivity; one name with four result types says both, and says it to the compiler.

Why this is not optional

Regular and Directory have identical exported method sets — verified 2026-08-24:

Regular    Digest Equal Etag Exists MismatchesKind String Unmarshal{JSON,Text,YAML}
Directory  Digest Equal Etag Exists MismatchesKind String Unmarshal{JSON,Text,YAML}

As bare interfaces they are structurally interchangeable: r.(Directory) would succeed for a regular file and every kind-honesty guarantee from #616 would evaporate without a single test failing.

And file is not merely an aesthetic exception. Its variants carry zero exported fields, so tryHydrateStruct fills nothing yet still forges and returns an identity-less *Regular. Part 1 alone leaves the most-used provider open on the very path that motivates the feature.

Watch here

op.RegisterResourceMint gains four interface→struct registrations. *Any's resolution at activation (op.KindResolver) and #616's supersession rules must be re-pinned against interface types rather than concrete ones — that is where a silent regression would hide.

Activity

  1. David-Noble-at-work commented on Aug 24, 2026

    @David-Noble-at-work
    ContributorAuthor

    Blocked on #650 before the transformation starts: the unexported struct for file.Any cannot be named any — that shadows the predeclared identifier for the whole package, including DiscoverAny(…, value any). Regular, Directory, and SymbolicLink lowercase cleanly; only this one needs a decision.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions