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.