R08BREAKINGfunctionSymbol Unexported
Flags when a previously exported symbol loses its export keyword. All external modules importing this symbol will break.
Applies to
TypeScriptPythonGoJavaRust
Why it matters
When a symbol is unexported, every file in the codebase (and every downstream consumer of the package) that imports it will get a compilation error. Unlike parameter changes that affect call sites, unexporting affects import statements — a fundamentally different blast radius.
Example
Before (exported)
// utils.ts
export function calculateTax(amount: number): number {
return amount * 0.2;
}After (unexported)
// utils.ts (BREAKING — no longer exported)
function calculateTax(amount: number): number {
return amount * 0.2;
}What you see in the terminal
$ npx dg check
[BREAKING] calculateTax (visibility_changed)
src/utils.ts:2
Symbol was unexported. All external importers will fail to resolve this symbol.How detection works
The classifier checks the exported boolean field on both old and new signatures. If the old signature was exported and the new one is not, the rule fires.
if (oldSig.exported === true && newSig.exported !== true) {
// BREAKING: symbol was unexported
}Real-world scenario
A developer moves a utility function to be module-internal because it is only used within the file. However, three other modules import it. Those imports will break with "Module has no exported member 'calculateTax'".
Edge cases
- In Go, changing an exported function from uppercase to lowercase (Calc -> calc) is equivalent
- In Rust, removing the pub modifier triggers this rule
- In Python, adding a leading underscore (_calc) is a convention, not enforcement