MCPcopy
hub / github.com/uber-go/nilaway / ObservePackage

Method ObservePackage

inference/engine.go:183–305  ·  view source on GitHub ↗

ObservePackage observes all the annotations and assertions computed locally about the current package. The assertions are sorted based on whether they are already known to trigger without reliance on annotation sites, such as `x` in `x = nil; x.f`, which will generate `SingleAssertionFailure`s, whet

(pkgFullTriggers []annotation.FullTrigger)

Source from the content-addressed store, hash-verified

181// observeImplication. Before all assertions are sorted and handled thus, the annotations read for
182// the package are iterated over and observed via calls to observeSiteExplanation as a <Val>BecauseAnnotation.
183func (e *Engine) ObservePackage(pkgFullTriggers []annotation.FullTrigger) {
184 // As Step 1, we do a pre-analysis of "guard missing" triggers to verify if their dereferences are always nil-safe,
185 // and hence can be deleted to not report a false positive error. Specifically, this analyis of "always safe" paths
186 // is focussed on the rich check effect functions, namely error returning functions and ok-returning functions.
187 // The process is to find all guard missing triggers reaching a function return site, and then check if all the return triggers
188 // to that function site are non-nil. If so, we can safely delete all the guard-missing triggers for this function site.
189 triggersToBeDeleted := make(map[int]bool)
190 mapSiteGuardMissing, mapSiteReturn := e.mapGuardMissingAndReturnToFuncSite(pkgFullTriggers)
191 for site, guardMissingIndices := range mapSiteGuardMissing {
192 if returnIndices, ok := mapSiteReturn[site]; ok {
193 // Check if all the return triggers to this function site are non-nil.
194 nonnilCnt := 0
195 for _, index := range returnIndices {
196 returnTrigger := pkgFullTriggers[index]
197 if returnTrigger.Producer.Annotation.Kind() != annotation.Never {
198 // break early if we find a potentially nilable trigger
199 break
200 }
201 nonnilCnt++
202 }
203
204 if nonnilCnt == len(returnIndices) {
205 // If all return triggers are non-nil, then we can safely delete all the guard-missing triggers
206 // for this function site.
207 for _, index := range guardMissingIndices {
208 triggersToBeDeleted[index] = true
209 }
210 }
211 }
212 }
213 // Add all placeholder UseAsReturnForAlwaysSafePath triggers to triggersToBeDeleted
214 for _, indices := range mapSiteReturn {
215 for _, index := range indices {
216 triggersToBeDeleted[index] = true
217 }
218 }
219
220 // Filter out the triggers that are to be deleted.
221 pkgFullTriggers = slices.DeleteFunc(pkgFullTriggers, func(t annotation.FullTrigger) bool {
222 index := slices.Index(pkgFullTriggers, t)
223 return triggersToBeDeleted[index]
224 })
225
226 // Separate out triggers with UseAsNonErrorRetDependentOnErrorRetNilability consumer from other triggers.
227 // This is needed since whether UseAsNonErrorRetDependentOnErrorRetNilability triggers should be fired
228 // is dependent on their corresponding UseAsErrorRetWithNilabilityUnknown triggers. By this separation,
229 // we can process all other triggers, including UseAsErrorRetWithNilabilityUnknown, first, and once
230 // their nilability status is known, then filter out the unnecessary UseAsNonErrorRetDependentOnErrorRetNilability
231 // triggers, and run the pkg inference process again only for the remainder triggers.
232 // Steps 2--4 below depict this approach in more detail.
233 var (
234 nonErrRetTriggers []annotation.FullTrigger
235 // In most cases all triggers will be stored in otherTriggers, so we set a proper capacity.
236 otherTriggers = make([]annotation.FullTrigger, 0, len(pkgFullTriggers))
237 )
238
239 for _, t := range pkgFullTriggers {
240 if _, ok := t.Consumer.Annotation.(*annotation.UseAsNonErrorRetDependentOnErrorRetNilability); ok {

Callers 1

runFunction · 0.95

Calls 8

buildPkgInferenceMapMethod · 0.95
siteMethod · 0.80
KindMethod · 0.65
UnderlyingSiteMethod · 0.65
ValMethod · 0.65
LoadMethod · 0.45

Tested by

no test coverage detected