xref: /aosp_15_r20/build/blueprint/provider.go (revision 1fa6dee971e1612fa5cc0aa5ca2d35a22e2c34a3)
1*1fa6dee9SAndroid Build Coastguard Worker// Copyright 2020 Google Inc. All rights reserved.
2*1fa6dee9SAndroid Build Coastguard Worker//
3*1fa6dee9SAndroid Build Coastguard Worker// Licensed under the Apache License, Version 2.0 (the "License");
4*1fa6dee9SAndroid Build Coastguard Worker// you may not use this file except in compliance with the License.
5*1fa6dee9SAndroid Build Coastguard Worker// You may obtain a copy of the License at
6*1fa6dee9SAndroid Build Coastguard Worker//
7*1fa6dee9SAndroid Build Coastguard Worker//     http://www.apache.org/licenses/LICENSE-2.0
8*1fa6dee9SAndroid Build Coastguard Worker//
9*1fa6dee9SAndroid Build Coastguard Worker// Unless required by applicable law or agreed to in writing, software
10*1fa6dee9SAndroid Build Coastguard Worker// distributed under the License is distributed on an "AS IS" BASIS,
11*1fa6dee9SAndroid Build Coastguard Worker// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*1fa6dee9SAndroid Build Coastguard Worker// See the License for the specific language governing permissions and
13*1fa6dee9SAndroid Build Coastguard Worker// limitations under the License.
14*1fa6dee9SAndroid Build Coastguard Worker
15*1fa6dee9SAndroid Build Coastguard Workerpackage blueprint
16*1fa6dee9SAndroid Build Coastguard Worker
17*1fa6dee9SAndroid Build Coastguard Workerimport (
18*1fa6dee9SAndroid Build Coastguard Worker	"encoding/gob"
19*1fa6dee9SAndroid Build Coastguard Worker	"fmt"
20*1fa6dee9SAndroid Build Coastguard Worker
21*1fa6dee9SAndroid Build Coastguard Worker	"github.com/google/blueprint/gobtools"
22*1fa6dee9SAndroid Build Coastguard Worker	"github.com/google/blueprint/proptools"
23*1fa6dee9SAndroid Build Coastguard Worker)
24*1fa6dee9SAndroid Build Coastguard Worker
25*1fa6dee9SAndroid Build Coastguard Worker// This file implements Providers, modelled after Bazel
26*1fa6dee9SAndroid Build Coastguard Worker// (https://docs.bazel.build/versions/master/skylark/rules.html#providers).
27*1fa6dee9SAndroid Build Coastguard Worker// Each provider can be associated with a mutator, in which case the value for the provider for a
28*1fa6dee9SAndroid Build Coastguard Worker// module can only be set during the mutator call for the module, and the value can only be
29*1fa6dee9SAndroid Build Coastguard Worker// retrieved after the mutator call for the module. For providers not associated with a mutator, the
30*1fa6dee9SAndroid Build Coastguard Worker// value can for the provider for a module can only be set during GenerateBuildActions for the
31*1fa6dee9SAndroid Build Coastguard Worker// module, and the value can only be retrieved after GenerateBuildActions for the module.
32*1fa6dee9SAndroid Build Coastguard Worker//
33*1fa6dee9SAndroid Build Coastguard Worker// Providers are globally registered during init() and given a unique ID.  The value of a provider
34*1fa6dee9SAndroid Build Coastguard Worker// for a module is stored in an []any indexed by the ID.  If the value of a provider has
35*1fa6dee9SAndroid Build Coastguard Worker// not been set, the value in the []any will be nil.
36*1fa6dee9SAndroid Build Coastguard Worker//
37*1fa6dee9SAndroid Build Coastguard Worker// If the storage used by the provider value arrays becomes too large:
38*1fa6dee9SAndroid Build Coastguard Worker//  sizeof([]interface) * number of providers * number of modules that have a provider value set
39*1fa6dee9SAndroid Build Coastguard Worker// then the storage can be replaced with something like a bitwise trie.
40*1fa6dee9SAndroid Build Coastguard Worker//
41*1fa6dee9SAndroid Build Coastguard Worker// The purpose of providers is to provide a serializable checkpoint between modules to enable
42*1fa6dee9SAndroid Build Coastguard Worker// Blueprint to skip parts of the analysis phase when inputs haven't changed.  To that end,
43*1fa6dee9SAndroid Build Coastguard Worker// values passed to providers should be treated as immutable by callers to both the getters and
44*1fa6dee9SAndroid Build Coastguard Worker// setters.  Go doesn't provide any way to enforce immutability on arbitrary types, so it may be
45*1fa6dee9SAndroid Build Coastguard Worker// necessary for the getters and setters to make deep copies of the values, likely extending
46*1fa6dee9SAndroid Build Coastguard Worker// proptools.CloneProperties to do so.
47*1fa6dee9SAndroid Build Coastguard Worker
48*1fa6dee9SAndroid Build Coastguard Workertype typedProviderKey[K any] struct {
49*1fa6dee9SAndroid Build Coastguard Worker	providerKey
50*1fa6dee9SAndroid Build Coastguard Worker}
51*1fa6dee9SAndroid Build Coastguard Worker
52*1fa6dee9SAndroid Build Coastguard Workertype providerKey struct {
53*1fa6dee9SAndroid Build Coastguard Worker	id      int
54*1fa6dee9SAndroid Build Coastguard Worker	typ     string
55*1fa6dee9SAndroid Build Coastguard Worker	mutator string
56*1fa6dee9SAndroid Build Coastguard Worker}
57*1fa6dee9SAndroid Build Coastguard Worker
58*1fa6dee9SAndroid Build Coastguard Workertype providerKeyGob struct {
59*1fa6dee9SAndroid Build Coastguard Worker	Id      int
60*1fa6dee9SAndroid Build Coastguard Worker	Typ     string
61*1fa6dee9SAndroid Build Coastguard Worker	Mutator string
62*1fa6dee9SAndroid Build Coastguard Worker}
63*1fa6dee9SAndroid Build Coastguard Worker
64*1fa6dee9SAndroid Build Coastguard Workerfunc (m *providerKey) ToGob() *providerKeyGob {
65*1fa6dee9SAndroid Build Coastguard Worker	return &providerKeyGob{
66*1fa6dee9SAndroid Build Coastguard Worker		Id:      m.id,
67*1fa6dee9SAndroid Build Coastguard Worker		Typ:     m.typ,
68*1fa6dee9SAndroid Build Coastguard Worker		Mutator: m.mutator,
69*1fa6dee9SAndroid Build Coastguard Worker	}
70*1fa6dee9SAndroid Build Coastguard Worker}
71*1fa6dee9SAndroid Build Coastguard Worker
72*1fa6dee9SAndroid Build Coastguard Workerfunc (m *providerKey) FromGob(data *providerKeyGob) {
73*1fa6dee9SAndroid Build Coastguard Worker	m.id = data.Id
74*1fa6dee9SAndroid Build Coastguard Worker	m.typ = data.Typ
75*1fa6dee9SAndroid Build Coastguard Worker	m.mutator = data.Mutator
76*1fa6dee9SAndroid Build Coastguard Worker}
77*1fa6dee9SAndroid Build Coastguard Worker
78*1fa6dee9SAndroid Build Coastguard Workerfunc (m *providerKey) GobEncode() ([]byte, error) {
79*1fa6dee9SAndroid Build Coastguard Worker	return gobtools.CustomGobEncode[providerKeyGob](m)
80*1fa6dee9SAndroid Build Coastguard Worker}
81*1fa6dee9SAndroid Build Coastguard Worker
82*1fa6dee9SAndroid Build Coastguard Workerfunc (m *providerKey) GobDecode(data []byte) error {
83*1fa6dee9SAndroid Build Coastguard Worker	return gobtools.CustomGobDecode[providerKeyGob](data, m)
84*1fa6dee9SAndroid Build Coastguard Worker}
85*1fa6dee9SAndroid Build Coastguard Worker
86*1fa6dee9SAndroid Build Coastguard Workerfunc (p *providerKey) provider() *providerKey { return p }
87*1fa6dee9SAndroid Build Coastguard Worker
88*1fa6dee9SAndroid Build Coastguard Workertype AnyProviderKey interface {
89*1fa6dee9SAndroid Build Coastguard Worker	provider() *providerKey
90*1fa6dee9SAndroid Build Coastguard Worker}
91*1fa6dee9SAndroid Build Coastguard Workertype ProviderKey[K any] struct {
92*1fa6dee9SAndroid Build Coastguard Worker	*typedProviderKey[K]
93*1fa6dee9SAndroid Build Coastguard Worker}
94*1fa6dee9SAndroid Build Coastguard Worker
95*1fa6dee9SAndroid Build Coastguard Workervar _ AnyProviderKey = (*providerKey)(nil)
96*1fa6dee9SAndroid Build Coastguard Workervar _ AnyProviderKey = ProviderKey[bool]{}
97*1fa6dee9SAndroid Build Coastguard Worker
98*1fa6dee9SAndroid Build Coastguard Workervar providerRegistry []*providerKey
99*1fa6dee9SAndroid Build Coastguard Worker
100*1fa6dee9SAndroid Build Coastguard Worker// NewProvider returns a ProviderKey for the given type.
101*1fa6dee9SAndroid Build Coastguard Worker//
102*1fa6dee9SAndroid Build Coastguard Worker// The returned ProviderKey can be used to set a value of the ProviderKey's type for a module
103*1fa6dee9SAndroid Build Coastguard Worker// inside GenerateBuildActions for the module, and to get the value from GenerateBuildActions from
104*1fa6dee9SAndroid Build Coastguard Worker// any module later in the build graph.
105*1fa6dee9SAndroid Build Coastguard Workerfunc NewProvider[K any]() ProviderKey[K] {
106*1fa6dee9SAndroid Build Coastguard Worker	var defaultValue K
107*1fa6dee9SAndroid Build Coastguard Worker	gob.Register(defaultValue)
108*1fa6dee9SAndroid Build Coastguard Worker	return NewMutatorProvider[K]("")
109*1fa6dee9SAndroid Build Coastguard Worker}
110*1fa6dee9SAndroid Build Coastguard Worker
111*1fa6dee9SAndroid Build Coastguard Worker// NewMutatorProvider returns a ProviderKey for the given type.
112*1fa6dee9SAndroid Build Coastguard Worker//
113*1fa6dee9SAndroid Build Coastguard Worker// The returned ProviderKey can be used to set a value of the ProviderKey's type for a module inside
114*1fa6dee9SAndroid Build Coastguard Worker// the given mutator for the module, and to get the value from GenerateBuildActions from any
115*1fa6dee9SAndroid Build Coastguard Worker// module later in the build graph in the same mutator, or any module in a later mutator or during
116*1fa6dee9SAndroid Build Coastguard Worker// GenerateBuildActions.
117*1fa6dee9SAndroid Build Coastguard Workerfunc NewMutatorProvider[K any](mutator string) ProviderKey[K] {
118*1fa6dee9SAndroid Build Coastguard Worker	checkCalledFromInit()
119*1fa6dee9SAndroid Build Coastguard Worker
120*1fa6dee9SAndroid Build Coastguard Worker	typ := fmt.Sprintf("%T", *new(K))
121*1fa6dee9SAndroid Build Coastguard Worker
122*1fa6dee9SAndroid Build Coastguard Worker	provider := ProviderKey[K]{
123*1fa6dee9SAndroid Build Coastguard Worker		typedProviderKey: &typedProviderKey[K]{
124*1fa6dee9SAndroid Build Coastguard Worker			providerKey: providerKey{
125*1fa6dee9SAndroid Build Coastguard Worker				id:      len(providerRegistry),
126*1fa6dee9SAndroid Build Coastguard Worker				typ:     typ,
127*1fa6dee9SAndroid Build Coastguard Worker				mutator: mutator,
128*1fa6dee9SAndroid Build Coastguard Worker			},
129*1fa6dee9SAndroid Build Coastguard Worker		},
130*1fa6dee9SAndroid Build Coastguard Worker	}
131*1fa6dee9SAndroid Build Coastguard Worker
132*1fa6dee9SAndroid Build Coastguard Worker	providerRegistry = append(providerRegistry, &provider.providerKey)
133*1fa6dee9SAndroid Build Coastguard Worker
134*1fa6dee9SAndroid Build Coastguard Worker	return provider
135*1fa6dee9SAndroid Build Coastguard Worker}
136*1fa6dee9SAndroid Build Coastguard Worker
137*1fa6dee9SAndroid Build Coastguard Worker// initProviders fills c.providerMutators with the *mutatorInfo associated with each provider ID,
138*1fa6dee9SAndroid Build Coastguard Worker// if any.
139*1fa6dee9SAndroid Build Coastguard Workerfunc (c *Context) initProviders() {
140*1fa6dee9SAndroid Build Coastguard Worker	c.providerMutators = make([]*mutatorInfo, len(providerRegistry))
141*1fa6dee9SAndroid Build Coastguard Worker	for _, provider := range providerRegistry {
142*1fa6dee9SAndroid Build Coastguard Worker		for _, mutator := range c.mutatorInfo {
143*1fa6dee9SAndroid Build Coastguard Worker			if mutator.name == provider.mutator {
144*1fa6dee9SAndroid Build Coastguard Worker				c.providerMutators[provider.id] = mutator
145*1fa6dee9SAndroid Build Coastguard Worker			}
146*1fa6dee9SAndroid Build Coastguard Worker		}
147*1fa6dee9SAndroid Build Coastguard Worker	}
148*1fa6dee9SAndroid Build Coastguard Worker}
149*1fa6dee9SAndroid Build Coastguard Worker
150*1fa6dee9SAndroid Build Coastguard Worker// setProvider sets the value for a provider on a moduleInfo.  Verifies that it is called during the
151*1fa6dee9SAndroid Build Coastguard Worker// appropriate mutator or GenerateBuildActions pass for the provider, and that the value is of the
152*1fa6dee9SAndroid Build Coastguard Worker// appropriate type.  The value should not be modified after being passed to setProvider.
153*1fa6dee9SAndroid Build Coastguard Worker//
154*1fa6dee9SAndroid Build Coastguard Worker// Once Go has generics the value parameter can be typed:
155*1fa6dee9SAndroid Build Coastguard Worker// setProvider(type T)(m *moduleInfo, provider ProviderKey(T), value T)
156*1fa6dee9SAndroid Build Coastguard Workerfunc (c *Context) setProvider(m *moduleInfo, provider *providerKey, value any) {
157*1fa6dee9SAndroid Build Coastguard Worker	if provider.mutator == "" {
158*1fa6dee9SAndroid Build Coastguard Worker		if !m.startedGenerateBuildActions {
159*1fa6dee9SAndroid Build Coastguard Worker			panic(fmt.Sprintf("Can't set value of provider %s before GenerateBuildActions started",
160*1fa6dee9SAndroid Build Coastguard Worker				provider.typ))
161*1fa6dee9SAndroid Build Coastguard Worker		} else if m.finishedGenerateBuildActions {
162*1fa6dee9SAndroid Build Coastguard Worker			panic(fmt.Sprintf("Can't set value of provider %s after GenerateBuildActions finished",
163*1fa6dee9SAndroid Build Coastguard Worker				provider.typ))
164*1fa6dee9SAndroid Build Coastguard Worker		}
165*1fa6dee9SAndroid Build Coastguard Worker	} else {
166*1fa6dee9SAndroid Build Coastguard Worker		expectedMutator := c.providerMutators[provider.id]
167*1fa6dee9SAndroid Build Coastguard Worker		if expectedMutator == nil {
168*1fa6dee9SAndroid Build Coastguard Worker			panic(fmt.Sprintf("Can't set value of provider %s associated with unregistered mutator %s",
169*1fa6dee9SAndroid Build Coastguard Worker				provider.typ, provider.mutator))
170*1fa6dee9SAndroid Build Coastguard Worker		} else if c.mutatorFinishedForModule(expectedMutator, m) {
171*1fa6dee9SAndroid Build Coastguard Worker			panic(fmt.Sprintf("Can't set value of provider %s after mutator %s finished",
172*1fa6dee9SAndroid Build Coastguard Worker				provider.typ, provider.mutator))
173*1fa6dee9SAndroid Build Coastguard Worker		} else if !c.mutatorStartedForModule(expectedMutator, m) {
174*1fa6dee9SAndroid Build Coastguard Worker			panic(fmt.Sprintf("Can't set value of provider %s before mutator %s started",
175*1fa6dee9SAndroid Build Coastguard Worker				provider.typ, provider.mutator))
176*1fa6dee9SAndroid Build Coastguard Worker		}
177*1fa6dee9SAndroid Build Coastguard Worker	}
178*1fa6dee9SAndroid Build Coastguard Worker
179*1fa6dee9SAndroid Build Coastguard Worker	if m.providers == nil {
180*1fa6dee9SAndroid Build Coastguard Worker		m.providers = make([]any, len(providerRegistry))
181*1fa6dee9SAndroid Build Coastguard Worker	}
182*1fa6dee9SAndroid Build Coastguard Worker
183*1fa6dee9SAndroid Build Coastguard Worker	if m.providers[provider.id] != nil {
184*1fa6dee9SAndroid Build Coastguard Worker		panic(fmt.Sprintf("Value of provider %s is already set", provider.typ))
185*1fa6dee9SAndroid Build Coastguard Worker	}
186*1fa6dee9SAndroid Build Coastguard Worker
187*1fa6dee9SAndroid Build Coastguard Worker	m.providers[provider.id] = value
188*1fa6dee9SAndroid Build Coastguard Worker
189*1fa6dee9SAndroid Build Coastguard Worker	if m.providerInitialValueHashes == nil {
190*1fa6dee9SAndroid Build Coastguard Worker		m.providerInitialValueHashes = make([]uint64, len(providerRegistry))
191*1fa6dee9SAndroid Build Coastguard Worker	}
192*1fa6dee9SAndroid Build Coastguard Worker	hash, err := proptools.CalculateHash(value)
193*1fa6dee9SAndroid Build Coastguard Worker	if err != nil {
194*1fa6dee9SAndroid Build Coastguard Worker		panic(fmt.Sprintf("Can't set value of provider %s: %s", provider.typ, err.Error()))
195*1fa6dee9SAndroid Build Coastguard Worker	}
196*1fa6dee9SAndroid Build Coastguard Worker	m.providerInitialValueHashes[provider.id] = hash
197*1fa6dee9SAndroid Build Coastguard Worker}
198*1fa6dee9SAndroid Build Coastguard Worker
199*1fa6dee9SAndroid Build Coastguard Worker// provider returns the value, if any, for a given provider for a module.  Verifies that it is
200*1fa6dee9SAndroid Build Coastguard Worker// called after the appropriate mutator or GenerateBuildActions pass for the provider on the module.
201*1fa6dee9SAndroid Build Coastguard Worker// If the value for the provider was not set it returns nil.  The return value should always be considered read-only.
202*1fa6dee9SAndroid Build Coastguard Worker//
203*1fa6dee9SAndroid Build Coastguard Worker// Once Go has generics the return value can be typed and the type assert by callers can be dropped:
204*1fa6dee9SAndroid Build Coastguard Worker// provider(type T)(m *moduleInfo, provider ProviderKey(T)) T
205*1fa6dee9SAndroid Build Coastguard Workerfunc (c *Context) provider(m *moduleInfo, provider *providerKey) (any, bool) {
206*1fa6dee9SAndroid Build Coastguard Worker	if provider.mutator == "" {
207*1fa6dee9SAndroid Build Coastguard Worker		if !m.finishedGenerateBuildActions {
208*1fa6dee9SAndroid Build Coastguard Worker			panic(fmt.Sprintf("Can't get value of provider %s before GenerateBuildActions finished",
209*1fa6dee9SAndroid Build Coastguard Worker				provider.typ))
210*1fa6dee9SAndroid Build Coastguard Worker		}
211*1fa6dee9SAndroid Build Coastguard Worker	} else {
212*1fa6dee9SAndroid Build Coastguard Worker		expectedMutator := c.providerMutators[provider.id]
213*1fa6dee9SAndroid Build Coastguard Worker		if expectedMutator != nil && !c.mutatorFinishedForModule(expectedMutator, m) {
214*1fa6dee9SAndroid Build Coastguard Worker			panic(fmt.Sprintf("Can't get value of provider %s before mutator %s finished",
215*1fa6dee9SAndroid Build Coastguard Worker				provider.typ, provider.mutator))
216*1fa6dee9SAndroid Build Coastguard Worker		}
217*1fa6dee9SAndroid Build Coastguard Worker	}
218*1fa6dee9SAndroid Build Coastguard Worker
219*1fa6dee9SAndroid Build Coastguard Worker	if len(m.providers) > provider.id {
220*1fa6dee9SAndroid Build Coastguard Worker		if p := m.providers[provider.id]; p != nil {
221*1fa6dee9SAndroid Build Coastguard Worker			return p, true
222*1fa6dee9SAndroid Build Coastguard Worker		}
223*1fa6dee9SAndroid Build Coastguard Worker	}
224*1fa6dee9SAndroid Build Coastguard Worker
225*1fa6dee9SAndroid Build Coastguard Worker	return nil, false
226*1fa6dee9SAndroid Build Coastguard Worker}
227*1fa6dee9SAndroid Build Coastguard Worker
228*1fa6dee9SAndroid Build Coastguard Workerfunc (c *Context) mutatorFinishedForModule(mutator *mutatorInfo, m *moduleInfo) bool {
229*1fa6dee9SAndroid Build Coastguard Worker	if c.finishedMutators[mutator.index] {
230*1fa6dee9SAndroid Build Coastguard Worker		// mutator pass finished for all modules
231*1fa6dee9SAndroid Build Coastguard Worker		return true
232*1fa6dee9SAndroid Build Coastguard Worker	}
233*1fa6dee9SAndroid Build Coastguard Worker
234*1fa6dee9SAndroid Build Coastguard Worker	return m.finishedMutator >= mutator.index
235*1fa6dee9SAndroid Build Coastguard Worker}
236*1fa6dee9SAndroid Build Coastguard Worker
237*1fa6dee9SAndroid Build Coastguard Workerfunc (c *Context) mutatorStartedForModule(mutator *mutatorInfo, m *moduleInfo) bool {
238*1fa6dee9SAndroid Build Coastguard Worker	if c.finishedMutators[mutator.index] {
239*1fa6dee9SAndroid Build Coastguard Worker		// mutator pass finished for all modules
240*1fa6dee9SAndroid Build Coastguard Worker		return true
241*1fa6dee9SAndroid Build Coastguard Worker	}
242*1fa6dee9SAndroid Build Coastguard Worker
243*1fa6dee9SAndroid Build Coastguard Worker	return m.startedMutator >= mutator.index
244*1fa6dee9SAndroid Build Coastguard Worker}
245*1fa6dee9SAndroid Build Coastguard Worker
246*1fa6dee9SAndroid Build Coastguard Worker// OtherModuleProviderContext is a helper interface that is a subset of ModuleContext, BottomUpMutatorContext, or
247*1fa6dee9SAndroid Build Coastguard Worker// TopDownMutatorContext for use in OtherModuleProvider.
248*1fa6dee9SAndroid Build Coastguard Workertype OtherModuleProviderContext interface {
249*1fa6dee9SAndroid Build Coastguard Worker	OtherModuleProvider(m Module, provider AnyProviderKey) (any, bool)
250*1fa6dee9SAndroid Build Coastguard Worker}
251*1fa6dee9SAndroid Build Coastguard Worker
252*1fa6dee9SAndroid Build Coastguard Workervar _ OtherModuleProviderContext = BaseModuleContext(nil)
253*1fa6dee9SAndroid Build Coastguard Workervar _ OtherModuleProviderContext = ModuleContext(nil)
254*1fa6dee9SAndroid Build Coastguard Workervar _ OtherModuleProviderContext = BottomUpMutatorContext(nil)
255*1fa6dee9SAndroid Build Coastguard Workervar _ OtherModuleProviderContext = TopDownMutatorContext(nil)
256*1fa6dee9SAndroid Build Coastguard Worker
257*1fa6dee9SAndroid Build Coastguard Worker// OtherModuleProvider reads the provider for the given module.  If the provider has been set the value is
258*1fa6dee9SAndroid Build Coastguard Worker// returned and the boolean is true.  If it has not been set the zero value of the provider's type  is returned
259*1fa6dee9SAndroid Build Coastguard Worker// and the boolean is false.  The value returned may be a deep copy of the value originally passed to SetProvider.
260*1fa6dee9SAndroid Build Coastguard Worker//
261*1fa6dee9SAndroid Build Coastguard Worker// OtherModuleProviderContext is a helper interface that accepts ModuleContext, BottomUpMutatorContext, or
262*1fa6dee9SAndroid Build Coastguard Worker// TopDownMutatorContext.
263*1fa6dee9SAndroid Build Coastguard Workerfunc OtherModuleProvider[K any](ctx OtherModuleProviderContext, module Module, provider ProviderKey[K]) (K, bool) {
264*1fa6dee9SAndroid Build Coastguard Worker	value, ok := ctx.OtherModuleProvider(module, provider)
265*1fa6dee9SAndroid Build Coastguard Worker	if !ok {
266*1fa6dee9SAndroid Build Coastguard Worker		var k K
267*1fa6dee9SAndroid Build Coastguard Worker		return k, false
268*1fa6dee9SAndroid Build Coastguard Worker	}
269*1fa6dee9SAndroid Build Coastguard Worker	return value.(K), ok
270*1fa6dee9SAndroid Build Coastguard Worker}
271*1fa6dee9SAndroid Build Coastguard Worker
272*1fa6dee9SAndroid Build Coastguard Worker// SingletonModuleProviderContext is a helper interface that is a subset of Context and SingletonContext for use in
273*1fa6dee9SAndroid Build Coastguard Worker// SingletonModuleProvider.
274*1fa6dee9SAndroid Build Coastguard Workertype SingletonModuleProviderContext interface {
275*1fa6dee9SAndroid Build Coastguard Worker	ModuleProvider(m Module, provider AnyProviderKey) (any, bool)
276*1fa6dee9SAndroid Build Coastguard Worker}
277*1fa6dee9SAndroid Build Coastguard Worker
278*1fa6dee9SAndroid Build Coastguard Workervar _ SingletonModuleProviderContext = &Context{}
279*1fa6dee9SAndroid Build Coastguard Workervar _ SingletonModuleProviderContext = SingletonContext(nil)
280*1fa6dee9SAndroid Build Coastguard Worker
281*1fa6dee9SAndroid Build Coastguard Worker// SingletonModuleProvider reads the provider for the given module.  If the provider has been set the value is
282*1fa6dee9SAndroid Build Coastguard Worker// returned and the boolean is true.  If it has not been set the zero value of the provider's type  is returned
283*1fa6dee9SAndroid Build Coastguard Worker// and the boolean is false.  The value returned may be a deep copy of the value originally passed to SetProvider.
284*1fa6dee9SAndroid Build Coastguard Worker//
285*1fa6dee9SAndroid Build Coastguard Worker// SingletonModuleProviderContext is a helper interface that accepts Context or SingletonContext.
286*1fa6dee9SAndroid Build Coastguard Workerfunc SingletonModuleProvider[K any](ctx SingletonModuleProviderContext, module Module, provider ProviderKey[K]) (K, bool) {
287*1fa6dee9SAndroid Build Coastguard Worker	value, ok := ctx.ModuleProvider(module, provider)
288*1fa6dee9SAndroid Build Coastguard Worker	if !ok {
289*1fa6dee9SAndroid Build Coastguard Worker		var k K
290*1fa6dee9SAndroid Build Coastguard Worker		return k, false
291*1fa6dee9SAndroid Build Coastguard Worker	}
292*1fa6dee9SAndroid Build Coastguard Worker	return value.(K), ok
293*1fa6dee9SAndroid Build Coastguard Worker}
294*1fa6dee9SAndroid Build Coastguard Worker
295*1fa6dee9SAndroid Build Coastguard Worker// ModuleProviderContext is a helper interface that is a subset of ModuleContext, BottomUpMutatorContext, or
296*1fa6dee9SAndroid Build Coastguard Worker// TopDownMutatorContext for use in ModuleProvider.
297*1fa6dee9SAndroid Build Coastguard Workertype ModuleProviderContext interface {
298*1fa6dee9SAndroid Build Coastguard Worker	Provider(provider AnyProviderKey) (any, bool)
299*1fa6dee9SAndroid Build Coastguard Worker}
300*1fa6dee9SAndroid Build Coastguard Worker
301*1fa6dee9SAndroid Build Coastguard Workervar _ ModuleProviderContext = BaseModuleContext(nil)
302*1fa6dee9SAndroid Build Coastguard Workervar _ ModuleProviderContext = ModuleContext(nil)
303*1fa6dee9SAndroid Build Coastguard Workervar _ ModuleProviderContext = BottomUpMutatorContext(nil)
304*1fa6dee9SAndroid Build Coastguard Workervar _ ModuleProviderContext = TopDownMutatorContext(nil)
305*1fa6dee9SAndroid Build Coastguard Worker
306*1fa6dee9SAndroid Build Coastguard Worker// ModuleProvider reads the provider for the current module.  If the provider has been set the value is
307*1fa6dee9SAndroid Build Coastguard Worker// returned and the boolean is true.  If it has not been set the zero value of the provider's type  is returned
308*1fa6dee9SAndroid Build Coastguard Worker// and the boolean is false.  The value returned may be a deep copy of the value originally passed to SetProvider.
309*1fa6dee9SAndroid Build Coastguard Worker//
310*1fa6dee9SAndroid Build Coastguard Worker// ModuleProviderContext is a helper interface that accepts ModuleContext, BottomUpMutatorContext, or
311*1fa6dee9SAndroid Build Coastguard Worker// TopDownMutatorContext.
312*1fa6dee9SAndroid Build Coastguard Workerfunc ModuleProvider[K any](ctx ModuleProviderContext, provider ProviderKey[K]) (K, bool) {
313*1fa6dee9SAndroid Build Coastguard Worker	value, ok := ctx.Provider(provider)
314*1fa6dee9SAndroid Build Coastguard Worker	if !ok {
315*1fa6dee9SAndroid Build Coastguard Worker		var k K
316*1fa6dee9SAndroid Build Coastguard Worker		return k, false
317*1fa6dee9SAndroid Build Coastguard Worker	}
318*1fa6dee9SAndroid Build Coastguard Worker	return value.(K), ok
319*1fa6dee9SAndroid Build Coastguard Worker}
320*1fa6dee9SAndroid Build Coastguard Worker
321*1fa6dee9SAndroid Build Coastguard Worker// SetProviderContext is a helper interface that is a subset of ModuleContext, BottomUpMutatorContext, or
322*1fa6dee9SAndroid Build Coastguard Worker// TopDownMutatorContext for use in SetProvider.
323*1fa6dee9SAndroid Build Coastguard Workertype SetProviderContext interface {
324*1fa6dee9SAndroid Build Coastguard Worker	SetProvider(provider AnyProviderKey, value any)
325*1fa6dee9SAndroid Build Coastguard Worker}
326*1fa6dee9SAndroid Build Coastguard Worker
327*1fa6dee9SAndroid Build Coastguard Workervar _ SetProviderContext = BaseModuleContext(nil)
328*1fa6dee9SAndroid Build Coastguard Workervar _ SetProviderContext = ModuleContext(nil)
329*1fa6dee9SAndroid Build Coastguard Workervar _ SetProviderContext = BottomUpMutatorContext(nil)
330*1fa6dee9SAndroid Build Coastguard Workervar _ SetProviderContext = TopDownMutatorContext(nil)
331*1fa6dee9SAndroid Build Coastguard Worker
332*1fa6dee9SAndroid Build Coastguard Worker// SetProvider sets the value for a provider for the current module.  It panics if not called
333*1fa6dee9SAndroid Build Coastguard Worker// during the appropriate mutator or GenerateBuildActions pass for the provider, if the value
334*1fa6dee9SAndroid Build Coastguard Worker// is not of the appropriate type, or if the value has already been set.  The value should not
335*1fa6dee9SAndroid Build Coastguard Worker// be modified after being passed to SetProvider.
336*1fa6dee9SAndroid Build Coastguard Worker//
337*1fa6dee9SAndroid Build Coastguard Worker// SetProviderContext is a helper interface that accepts ModuleContext, BottomUpMutatorContext, or
338*1fa6dee9SAndroid Build Coastguard Worker// TopDownMutatorContext.
339*1fa6dee9SAndroid Build Coastguard Workerfunc SetProvider[K any](ctx SetProviderContext, provider ProviderKey[K], value K) {
340*1fa6dee9SAndroid Build Coastguard Worker	ctx.SetProvider(provider, value)
341*1fa6dee9SAndroid Build Coastguard Worker}
342