Part of duplicate code analysis: #2557
Summary
internal/difc/labels.go defines two separate wrapper types — SecrecyLabel and IntegrityLabel — that are structurally near-identical. Each wraps a *Label, delegates all operations to the shared checkFlowHelper, and implements the same set of methods (getLabel, CanFlowTo, CheckFlow, Clone). The only semantic difference is the checkSubset boolean passed to checkFlowHelper.
Duplication Details
Pattern: Symmetric label wrapper types with identical method bodies
Impact Analysis
- Maintainability: Medium — adding a method (e.g.,
IsEmpty(), Merge()) or changing getLabel nil-guard logic requires updating both types identically
- Bug Risk: Medium — a subtle fix to
Clone's nil guard in one type could be missed in the other
- Design Concern: If a third label type is needed in the future (e.g.,
ConfidentialityLabel), a third identical block must be added
Refactoring Recommendations
Option A — Go generics (preferred if Go 1.21+ generics constraints are acceptable):
Introduce a single generic FlowLabel[T] with a checkSubset bool field, parametrizing CanFlowTo / CheckFlow / Clone via a type constraint. This eliminates the duplicate method bodies while preserving type safety.
type labelConfig struct {
checkSubset bool
name string
}
// Internal generic wrapper — not exported
type flowLabel struct {
Label *Label
config labelConfig
}
func (l *flowLabel) getLabel() *Label { if l == nil { return nil }; return l.Label }
func (l *flowLabel) canFlowTo(target *flowLabel) bool {
ok, _ := checkFlowHelper(l.getLabel(), target.getLabel(), l.config.checkSubset, l.config.name)
return ok
}
// ... etc.
// Public types remain for callers
type SecrecyLabel struct { fl flowLabel }
type IntegrityLabel struct { fl flowLabel }
- Estimated effort: 1–2 hours
- Benefits: single nil-guard, single
Clone implementation, easy to add a third label type
Option B — Keep separate types, extract common nil-guard:
A smaller refactor — extract the repeated getLabel() pattern into a standalone function:
func getLabelOrNil[T interface{ getInner() *Label }](l T) *Label { ... }
This is a narrower improvement but lower risk.
Option C — Accept as intentional: The current checkFlowHelper already centralises the complex logic. The wrapper duplication is ~36 lines and well-documented. If no new label types are planned, leave as-is.
Implementation Checklist
Parent Issue
See parent analysis report: #2557
Related to #2557
Generated by Duplicate Code Detector · ◷
Part of duplicate code analysis: #2557
Summary
internal/difc/labels.godefines two separate wrapper types —SecrecyLabelandIntegrityLabel— that are structurally near-identical. Each wraps a*Label, delegates all operations to the sharedcheckFlowHelper, and implements the same set of methods (getLabel,CanFlowTo,CheckFlow,Clone). The only semantic difference is thecheckSubsetboolean passed tocheckFlowHelper.Duplication Details
Pattern: Symmetric label wrapper types with identical method bodies
Severity: Medium
Occurrences: 2 types × ~18 lines = ~36 lines duplicated
Locations:
internal/difc/labels.go~lines 156–282 (SecrecyLabeland its methods)internal/difc/labels.go~lines 296–340 (IntegrityLabeland its methods)Code Sample (near-identical structure):
Impact Analysis
IsEmpty(),Merge()) or changinggetLabelnil-guard logic requires updating both types identicallyClone's nil guard in one type could be missed in the otherConfidentialityLabel), a third identical block must be addedRefactoring Recommendations
Option A — Go generics (preferred if Go 1.21+ generics constraints are acceptable):
Introduce a single generic
FlowLabel[T]with acheckSubset boolfield, parametrizingCanFlowTo/CheckFlow/Clonevia a type constraint. This eliminates the duplicate method bodies while preserving type safety.Cloneimplementation, easy to add a third label typeOption B — Keep separate types, extract common nil-guard:
A smaller refactor — extract the repeated
getLabel()pattern into a standalone function:This is a narrower improvement but lower risk.
Option C — Accept as intentional: The current
checkFlowHelperalready centralises the complex logic. The wrapper duplication is ~36 lines and well-documented. If no new label types are planned, leave as-is.Implementation Checklist
checkFlowHelpercall sitesParent Issue
See parent analysis report: #2557
Related to #2557