diff --git a/docs/roadmap/remediation.md b/docs/roadmap/remediation.md index 9be758d..d72eabc 100644 --- a/docs/roadmap/remediation.md +++ b/docs/roadmap/remediation.md @@ -218,6 +218,8 @@ declarations, and existing diagnostic sites. ## Finding 7 — Each derived companion keeps a copy of the same tier context +**Status** — Complete. Each tier creates at most one shared derived context and has no per-input context table. The development check and full race suite passed. + **Priority P3.** `acquireUnderlayGroupScopes` allocates a context pointer slot for every input, even in tiers with no bindings. Each derived input then gets an addressable copy of the same main context with the same diff --git a/internal/engine/import_acquisition.go b/internal/engine/import_acquisition.go index 8277125..8bc0872 100644 --- a/internal/engine/import_acquisition.go +++ b/internal/engine/import_acquisition.go @@ -38,31 +38,30 @@ func acquireImportedInput(request importAcquisitionRequest, policy *acquisitionP source := request.input.input.source context := request.input.input.filesystem main := request.main - resolved, diagnostic := resolvedFilesystemContext{}, (*Diagnostic)(nil) - if request.input.resolved != nil { - resolved = *request.input.resolved - } else { - resolved, diagnostic = resolveFilesystemContext(source, context, main, tier.hostToken) - } - if diagnostic != nil { - return nil, sourceInfos(main.source), nil, []Diagnostic{*diagnostic} + resolved := request.input.resolved + if resolved == nil { + value, diagnostic := resolveFilesystemContext(source, context, main, tier.hostToken) + if diagnostic != nil { + return nil, sourceInfos(main.source), nil, []Diagnostic{*diagnostic} + } + resolved = &value } if resolved.native == nil { - if diagnostic := validateResolvedFilesystemDirectories(resolved); diagnostic != nil { + if diagnostic := validateResolvedFilesystemDirectories(*resolved); diagnostic != nil { return nil, sourceInfos(main.source), nil, []Diagnostic{*diagnostic} } } - access, err := openResolvedFilesystemAccess(resolved) + access, err := openResolvedFilesystemAccess(*resolved) if err != nil { diagnostic := globFilesystemDiagnostic(err, "configuration root could not be opened", Location{}) diagnostic.Primary = nil return nil, sourceInfos(main.source), nil, []Diagnostic{diagnostic} } - composition, sources, diagnostics := acquireImportedWithAccess(request, policy, state, tier, access, resolved) + composition, sources, diagnostics := acquireImportedWithAccess(request, policy, state, tier, access, *resolved) if len(diagnostics) != 0 { return composition, sources, nil, diagnostics } - return composition, sources, &resolved, nil + return composition, sources, resolved, nil } func acquireImportedWithAccess(request importAcquisitionRequest, policy *acquisitionPolicy, loadState *acquisitionState, tier *tierAcquisitionState, access *filesystemAccess, resolved resolvedFilesystemContext) (*composedDocument, []SourceInfo, []Diagnostic) { diff --git a/internal/engine/load_request.go b/internal/engine/load_request.go index abe7630..10dcbe6 100644 --- a/internal/engine/load_request.go +++ b/internal/engine/load_request.go @@ -276,23 +276,27 @@ func applyCompletedTier( func acquireUnderlayGroupScopes(group loadGroup, index int, rule *VersionRule, state *acquisitionState, policy acquisitionPolicy, mainContext *resolvedFilesystemContext) (*acquiredUnderlayGroup, []Diagnostic) { initialBytes, initialNodes := state.accounting.bytes, state.accounting.nodes tier := &tierAcquisitionState{visited: make(map[resourceIdentity]importRoute), hostToken: &namespaceToken{}} - selected := make([]*resolvedFilesystemContext, len(group.inputs)) - for i, contribution := range group.inputs { - if contribution.filesystem == nil && contribution.mainRelative != nil && mainContext != nil { - derived := *mainContext - derived.mainPath = "" - derived.hostToken = tier.hostToken - selected[i] = &derived - } else if contribution.filesystem == nil && contribution.mainRelative != nil { - group.inputs[i].filesystem = contribution.mainRelative.Fallback + var derived *resolvedFilesystemContext + bind := func(input loadInput) (loadInput, *resolvedFilesystemContext) { + if input.filesystem != nil || input.mainRelative == nil { + return input, nil } + if mainContext == nil { + input.filesystem = input.mainRelative.Fallback + return input, nil + } + if derived == nil { + context := *mainContext + context.mainPath = "" + context.hostToken = tier.hostToken + derived = &context + } + return input, derived } nativeAnchors := make(map[*namespaceToken]string) for inputIndex, contribution := range group.inputs { - token := nativeTokenForLoadInput(contribution) - if selected[inputIndex] != nil && selected[inputIndex].native != nil { - token = selected[inputIndex].native.token - } + contribution, resolved := bind(contribution) + token := nativeTokenForLoadInput(contribution, resolved) if token != nil { if _, exists := nativeAnchors[token]; !exists { nativeAnchors[token] = explicitNamespaceAnchor(index, inputIndex+1) @@ -302,10 +306,11 @@ func acquireUnderlayGroupScopes(group loadGroup, index int, rule *VersionRule, s acquiredGroup := &acquiredUnderlayGroup{index: index} inclusionGraph := newImportInclusionGraph() for inputIndex, contribution := range group.inputs { + contribution, resolved := bind(contribution) acquired, diagnostics := acquireInput(inputAcquisitionRequest{ input: contribution, role: sourceVersionContribution, - resolved: selected[inputIndex], - withoutBase: contribution.mainRelative != nil && contribution.filesystem == nil && selected[inputIndex] == nil, + resolved: resolved, + withoutBase: contribution.mainRelative != nil && contribution.filesystem == nil && resolved == nil, directiveContext: rootDirectiveContextLayered, protectionRule: rule, }, policy, state, tier) for _, source := range acquired.sources { @@ -324,10 +329,7 @@ func acquireUnderlayGroupScopes(group loadGroup, index int, rule *VersionRule, s kind: "host", host: explicitNamespaceAnchor(index, 0), input: explicitNamespaceAnchor(index, inputIndex+1), } - token := nativeTokenForLoadInput(contribution) - if selected[inputIndex] != nil && selected[inputIndex].native != nil { - token = selected[inputIndex].native.token - } + token := nativeTokenForLoadInput(contribution, resolved) if token != nil { anchors.kind = "native" anchors.native = nativeAnchors[token] @@ -411,7 +413,10 @@ func composeUnderlayGroup(acquired *acquiredUnderlayGroup, rule *VersionRule, po return composition, nil } -func nativeTokenForLoadInput(input loadInput) *namespaceToken { +func nativeTokenForLoadInput(input loadInput, resolved *resolvedFilesystemContext) *namespaceToken { + if resolved != nil && resolved.native != nil { + return resolved.native.token + } if input.source.kind == sourceFilesystem && input.source.namespace != nil { return input.source.namespace.token }