Skip to content

Commit

Permalink
new NeedsGuarding method for consumers
Browse files Browse the repository at this point in the history
added NeedsGuard and SetNeedsGuard logic
  • Loading branch information
sonalmahajan15 committed Oct 19, 2023
1 parent 5febad4 commit 3504a06
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 17 deletions.
72 changes: 57 additions & 15 deletions annotation/consume_trigger.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,13 +62,14 @@ type ConsumingAnnotationTrigger interface {
// This implies loss of information about the assignment. This method is used to track such assignments and print
// a more informative error message.
AddAssignment(Assignment)
}

// customPos has the below default implementations, in which case ConsumeTrigger.Pos() will return a default value.
// To return non-default position values, this method should be overridden appropriately.
func (t *TriggerIfNonNil) customPos() (token.Pos, bool) { return 0, false }
func (t *TriggerIfDeepNonNil) customPos() (token.Pos, bool) { return 0, false }
func (t *ConsumeTriggerTautology) customPos() (token.Pos, bool) { return 0, false }
// NeedsGuard returns true if the trigger needs to be guarded, for example, by a nil check or an ok form.
NeedsGuard() bool

// SetNeedsGuard sets the underlying Guard-Neediness of this ConsumerTrigger, if present.
// Default setting for ConsumerTriggers is that they need a guard. Override this method to set the need for a guard to false.
SetNeedsGuard(bool)
}

// Prestring is an interface used to encode objects that have compact on-the-wire encodings
// (via gob) but can still be expanded into verbose string representations on demand using
Expand Down Expand Up @@ -132,12 +133,13 @@ func (a *assignmentFlow) String() string {

// TriggerIfNonNil is triggered if the contained Annotation is non-nil
type TriggerIfNonNil struct {
Ann Key
Ann Key
IsGuardNotNeeded bool // ConsumeTriggers need guards by default, when applicable. Set this to true when guards are not needed.
assignmentFlow
}

// Kind returns Conditional.
func (t *TriggerIfNonNil) Kind() TriggerKind { return Conditional }
func (*TriggerIfNonNil) Kind() TriggerKind { return Conditional }

// UnderlyingSite the underlying site this trigger's nilability depends on.
func (t *TriggerIfNonNil) UnderlyingSite() Key { return t.Ann }
Expand All @@ -148,10 +150,22 @@ func (t *TriggerIfNonNil) CheckConsume(annMap Map) bool {
return ok && !ann.IsNilable
}

// customPos has the below default implementation for TriggerIfNonNil, in which case ConsumeTrigger.Pos() will return a default value.
// To return non-default position values, this method should be overridden appropriately.
func (*TriggerIfNonNil) customPos() (token.Pos, bool) { return token.NoPos, false }

// NeedsGuard is the default implementation for TriggerIfNonNil. To return non-default value, this method should be overridden.
func (t *TriggerIfNonNil) NeedsGuard() bool { return !t.IsGuardNotNeeded }

// SetNeedsGuard sets the underlying Guard-Neediness of this ConsumerTrigger
func (t *TriggerIfNonNil) SetNeedsGuard(b bool) {
t.IsGuardNotNeeded = !b
}

// equals returns true if the passed ConsumingAnnotationTrigger is equal to this one
func (t *TriggerIfNonNil) equals(other ConsumingAnnotationTrigger) bool {
if other, ok := other.(*TriggerIfNonNil); ok {
return t.Ann.equals(other.Ann)
return t.Ann.equals(other.Ann) && t.IsGuardNotNeeded == other.IsGuardNotNeeded
}
return false
}
Expand Down Expand Up @@ -189,12 +203,13 @@ func (t TriggerIfNonNilPrestring) String() string {

// TriggerIfDeepNonNil is triggered if the contained Annotation is deeply non-nil
type TriggerIfDeepNonNil struct {
Ann Key
Ann Key
IsGuardNotNeeded bool // ConsumeTriggers need guards by default, when applicable. Set this to true when guards are not needed.
assignmentFlow
}

// Kind returns DeepConditional.
func (t *TriggerIfDeepNonNil) Kind() TriggerKind { return DeepConditional }
func (*TriggerIfDeepNonNil) Kind() TriggerKind { return DeepConditional }

// UnderlyingSite the underlying site this trigger's nilability depends on.
func (t *TriggerIfDeepNonNil) UnderlyingSite() Key { return t.Ann }
Expand All @@ -205,10 +220,22 @@ func (t *TriggerIfDeepNonNil) CheckConsume(annMap Map) bool {
return ok && !ann.IsDeepNilable
}

// customPos has the below default implementation for TriggerIfDeepNonNil, in which case ConsumeTrigger.Pos() will return a default value.
// To return non-default position values, this method should be overridden appropriately.
func (*TriggerIfDeepNonNil) customPos() (token.Pos, bool) { return token.NoPos, false }

// NeedsGuard default implementation for TriggerIfDeepNonNil. To return non-default value, this method should be overridden.
func (t *TriggerIfDeepNonNil) NeedsGuard() bool { return !t.IsGuardNotNeeded }

// SetNeedsGuard sets the underlying Guard-Neediness of this ConsumerTrigger
func (t *TriggerIfDeepNonNil) SetNeedsGuard(b bool) {
t.IsGuardNotNeeded = !b
}

// equals returns true if the passed ConsumingAnnotationTrigger is equal to this one
func (t *TriggerIfDeepNonNil) equals(other ConsumingAnnotationTrigger) bool {
if other, ok := other.(*TriggerIfDeepNonNil); ok {
return t.Ann.equals(other.Ann)
return t.Ann.equals(other.Ann) && t.IsGuardNotNeeded == other.IsGuardNotNeeded
}
return false
}
Expand Down Expand Up @@ -246,6 +273,7 @@ func (t TriggerIfDeepNonNilPrestring) String() string {

// ConsumeTriggerTautology is used at consumption sites were consuming nil is always an error
type ConsumeTriggerTautology struct {
IsGuardNotNeeded bool // ConsumeTriggers need guards by default, when applicable. Set this to true when guards are not needed.
assignmentFlow
}

Expand All @@ -260,10 +288,24 @@ func (*ConsumeTriggerTautology) CheckConsume(Map) bool {
return true
}

// customPos has the below default implementation for ConsumeTriggerTautology, in which case ConsumeTrigger.Pos() will return a default value.
// To return non-default position values, this method should be overridden appropriately.
func (*ConsumeTriggerTautology) customPos() (token.Pos, bool) { return token.NoPos, false }

// NeedsGuard default implementation for ConsumeTriggerTautology. To return non-default value, this method should be overridden.
func (c *ConsumeTriggerTautology) NeedsGuard() bool { return !c.IsGuardNotNeeded }

// SetNeedsGuard sets the underlying Guard-Neediness of this ConsumerTrigger
func (c *ConsumeTriggerTautology) SetNeedsGuard(b bool) {
c.IsGuardNotNeeded = !b
}

// equals returns true if the passed ConsumingAnnotationTrigger is equal to this one
func (*ConsumeTriggerTautology) equals(other ConsumingAnnotationTrigger) bool {
_, ok := other.(*ConsumeTriggerTautology)
return ok
func (c *ConsumeTriggerTautology) equals(other ConsumingAnnotationTrigger) bool {
if other, ok := other.(*ConsumeTriggerTautology); ok {
return c.IsGuardNotNeeded == other.IsGuardNotNeeded
}
return false
}

// Copy returns a deep copy of this ConsumingAnnotationTrigger
Expand Down
3 changes: 2 additions & 1 deletion annotation/produce_trigger.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ type ProducingAnnotationTrigger interface {
NeedsGuardMatch() bool

// SetNeedsGuard sets the underlying Guard-Neediness of this ProduceTrigger, if present
// This should be very sparingly used, and only with utter conviction of correctness
// This should be very sparingly used, and only with utter conviction of correctness.
// Default setting for ProduceTriggers is to not need a guard. Override this method to set the need for a guard to true.
SetNeedsGuard(bool)

Prestring() Prestring
Expand Down
2 changes: 1 addition & 1 deletion assertion/function/assertiontree/backprop_util.go
Original file line number Diff line number Diff line change
Expand Up @@ -735,7 +735,7 @@ func exprAsDeepProducer(rootNode *RootAssertionNode, expr ast.Expr) annotation.P
// trigger is ignored and replaced with an always-nilable-producing
// instance of annotation.GuardMissing
func CheckGuardOnFullTrigger(trigger annotation.FullTrigger) annotation.FullTrigger {
if trigger.Producer.Annotation.NeedsGuardMatch() && !trigger.Consumer.GuardMatched {
if trigger.Producer.Annotation.NeedsGuardMatch() && trigger.Consumer.Annotation.NeedsGuard() && !trigger.Consumer.GuardMatched {
return annotation.FullTrigger{
Producer: &annotation.ProduceTrigger{
Annotation: &annotation.GuardMissing{
Expand Down

0 comments on commit 3504a06

Please sign in to comment.