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

Method observeImplication

inference/engine.go:500–549  ·  view source on GitHub ↗

observeImplication augments the inferred map with a new implication discovered as the result of an assertion. In particular, we note that all assertions discovered as FullTriggers by the assertions or affiliations analyzer are of the form `nilable X -> nilable Y`, so this method just takes the `prod

(
	producerSite,
	consumerSite primitiveSite,
	assertion primitiveFullTrigger,
)

Source from the content-addressed store, hash-verified

498// - If both sites are undetermined (i.e. both are under-constrained nodes in the implication graph)
499// then we simply ensure that this assertion is present as en edge between them.
500func (e *Engine) observeImplication(
501 producerSite,
502 consumerSite primitiveSite,
503 assertion primitiveFullTrigger,
504) {
505 // When we observe an implication between the producer site (PS) and consumer site (CS), we
506 // check their existing values in the inferred map (denoted as P and C) and behave accordingly:
507 // * If either P or C is determined, the other site will be determined. Note that we do not
508 // need to continue processing after either case since we are handling the same implication
509 // (i.e., no need to handle P => C and then C => P again). This also ensures that we do not
510 // report duplicate errors when P and C are both determined and have conflicting nilabilities.
511 // Specifically:
512 // * P is nilable => C must be nilable
513 // * P is nonnil => this implication does not yield more information which can be safely discarded
514 // * C is nilable => this implication does not yield more information which can be safely discarded
515 // * C is nonnil => P must be nonnil
516 //
517 // * If _both_ P and C are "undetermined or does not exist", we should create an implication
518 // edge between PS and CS.
519
520 // Nilable (true) producer => Nilable (true) consumer. We do not care about "ok" here since
521 // the "ok" in the type assertion below implies this "ok == true".
522 producer, _ := e.inferredMap.Load(producerSite)
523 if v, ok := producer.(*DeterminedVal); ok {
524 if v.Bool.Val() {
525 e.observeSiteExplanation(consumerSite, TrueBecauseDeepConstraint{
526 InternalAssertion: assertion,
527 DeeperExplanation: v.Bool,
528 })
529 }
530 return
531 }
532
533 // Nonnil (false) consumer => Nonnil (false) producer. We do not care about "ok" here since
534 // the "ok" in the type assertion below implies this "ok == true".
535 consumer, _ := e.inferredMap.Load(consumerSite)
536 if v, ok := consumer.(*DeterminedVal); ok {
537 if !v.Bool.Val() {
538 e.observeSiteExplanation(producerSite, FalseBecauseDeepConstraint{
539 InternalAssertion: assertion,
540 DeeperExplanation: v.Bool,
541 })
542 }
543 return
544 }
545
546 // If we reach here, it means that the existing values for the producer and consumer are
547 // undetermined (or non-existent), so we can simply add an implication edge in the graph.
548 e.inferredMap.StoreImplication(producerSite, consumerSite, assertion)
549}
550
551// GobRegister must be called in an `init` function before attempting to run any procedure that can
552// deal with InferredAnnotationMaps as Facts. If not, gob encoding/decoding will be unable to handle

Callers 2

ObserveUpstreamMethod · 0.95

Calls 4

StoreImplicationMethod · 0.80
ValMethod · 0.65
LoadMethod · 0.45

Tested by

no test coverage detected