Local Vars With Global Name
ID |
swift.local_global_name_collision |
Severity |
low |
Remediation Complexity |
trivial |
Remediation Risk |
low |
Remediation Effort |
low |
Resource |
Reliability |
Language |
Swift |
Tags |
naming, reliability, shadowing |
Description
Reports a local let / var declaration whose name matches a
top-level declaration in the same source file. Shadowing a global with
a local makes references ambiguous to the reader: every use site
forces a mental lookup to decide which binding is in play.
let limit = 100
func report() {
let limit = 5 // FLAW — shadows top-level `limit`
print(limit) // which one?
}
Rationale
Swift permits the shadowing, but the compiler picks the innermost binding silently. Refactors that move code across scopes can flip which value is read with no warning. Naming the local differently keeps the call graph stable across edits and frees the global from being touched defensively when the file grows.
Remediation
Rename the local — or, if the local was supposed to override the global value at every call site, promote the change to the global itself:
let limit = 100
func report() {
let perPage = 5
print(perPage)
}
When not to fire
The idiomatic same-name optional rebind is allowed:
func render(_ name: String?) {
guard let name = name else { return } // OK — narrows the optional
print(name)
}
func snapshot() {
let limit = limit // OK — same-name rebind
print(limit)
}
The rule is single-file: top-level declarations imported from another module are not considered.