You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
A superseded-image-assembly entry has no staleness check — it survives the image rebuild that retires it #3223
superseded-image-assemblies (pack lane) / --superseded-image-assembly (build-project) drops an
image assembly from a container build's reference set, for the one case the shadow set structurally
cannot see: a type moving OUT of an image-shipped assembly into a module in the same repo, where the ProjectReference edge that would have shadowed the stale copy is the edge the move deletes. See Doc/Architecture/ModuleBuildArchitecture → "Moving a type OUT of an image-shipped assembly into a
module".
It fails closed on three inputs today: an empty name, a name the image does not carry, and a name the
run already builds from source.
It does not detect the fourth: an entry that has gone STALE. Once the pin moves onto an image
built after the move, that image's copy of the assembly no longer defines the conflicting types — but the assembly still exists, so the "not carried by the image" check does not fire. The entry then
sits in the caller's workflow doing nothing, and nothing says so.
Why it matters rather than being untidy
A stale entry is not inert. It keeps dropping a real image assembly from the reference set, so the
day someone legitimately needs a different type from it, the compile fails with a CS0246 that
points at the consuming code and not at the stale declaration that caused it. And this exact shape —
an allow-style entry that outlives its reason with nothing to retire it — is a recurring defect
class here, not a hypothetical.
The durable check
Refuse the build when the image's copy of a superseded assembly defines none of the type names
this run's source defines. That is the precise statement of "there is nothing left to supersede":
the tester already reads the container's assemblies, so their type names are available as metadata;
the run's own source type names are available from the compilations it is about to make;
an empty intersection ⇒ the entry has done its job and must be removed, named in the error.
Ordering matters: the check needs the source's declared type names, so it belongs after the graph's
compilations are known rather than at option-validation time — which is why it was not folded into
the three cheap checks.
Deliberately not built with the original change: it is a second mechanism with its own failure modes,
and shipping it half-formed alongside a fix that unblocks a blocked pipeline would have been the
worse trade. Filed instead so the omission is visible.
Activity