Skip to content

Add opt-in inconsistent_default_argument_in_file rule#6796

Open
nenadvulic wants to merge 2 commits into
realm:mainfrom
nenadvulic:feature/inconsistent-default-argument-in-file
Open

Add opt-in inconsistent_default_argument_in_file rule#6796
nenadvulic wants to merge 2 commits into
realm:mainfrom
nenadvulic:feature/inconsistent-default-argument-in-file

Conversation

@nenadvulic

@nenadvulic nenadvulic commented Jul 1, 2026

Copy link
Copy Markdown

Summary

Adds a new opt-in rule inconsistent_default_argument_in_file (kind: lint), as discussed in #6668.

It flags overloaded functions declared on the same type — the type's primary declaration and any extensions of it in the same file — when a shared (label, type) parameter uses different default values. This catches accidental default drift across overloads that callers reasonably expect to behave the same, e.g.:

struct Network {
  func fetch(_ url: URL, retries: Int = 3) {}
  func fetch(_ url: URL, headers: [String: String], retries: Int = 0) {} // ← silently drops to 0
}

Scope

Per the agreement with @SimplyDanny and @rgoldberg in #6668, this is the intentionally small, purely syntactic, single-file variant:

  • Opt-in (disabled by default) — teams that want the "overloads share defaults" invariant get it; others aren't bothered.
  • Behavior = across_one_type: a type's primary declaration plus all extensions of it in the same file are treated as one scope (matched via the fully-qualified lexical type name, e.g. Foo.Bar).
  • Nested types form their own scope (separately): Parent.f(…) and Parent.Nested.f(…) are functions on different types, so they are never compared — comparing them would produce false positives.
  • The offending parameter is the one whose default diverges from the first declaration of that shared parameter, in source order.

Deliberately out of scope here (left to a potential future analyzer rule, so no name clash):

  • call_default_arguments and override_default_arguments — both need type/symbol resolution unavailable to a syntactic rule.
  • Cross-file cases.

The _in_file suffix keeps the name honest about the limitation and leaves room for a fully-general analyzer rule later. Config options floated in the discussion (container_scope, nested_containers, parameter_grouping, …) are intentionally not included yet; they can be layered on additively without breaking the v1 defaults.

Examples

Triggering:

struct S {
  func f(x: Int = 1) {}
  func f(↓x: Int = 2, y: Int) {}
}
struct S {
  func f(x: Int = 1) {}
}
extension S {
  func f(↓x: Int = 2, y: Int) {}
}

Non-triggering (same default, one-sided default, different type, different scope, nested type):

struct S {
  func f(x: Int = 1) {}
  func f(x: Int = 1, y: Int) {}
}
struct Outer {
  func f(x: Int = 1) {}
  struct Inner {
    func f(x: Int = 2) {} // different scope
  }
}

Closes #6668.

@nenadvulic nenadvulic force-pushed the feature/inconsistent-default-argument-in-file branch from 5911061 to 1e4bc4c Compare July 1, 2026 08:39
@SwiftLintBot

SwiftLintBot commented Jul 1, 2026

Copy link
Copy Markdown
12 Warnings
⚠️ This PR introduced a violation in DuckDuckGo: /iOS/AutofillCredentialProvider/CredentialProvider/Shared/ActionMessageView.swift:112:25: Warning: Overloaded functions declared on the same type (its primary declaration and any extensions of it in the same file) should not use different default values for a shared parameter, as this is usually an accidental drift that callers do not expect (inconsistent_default_argument_in_file)
⚠️ This PR introduced a violation in DuckDuckGo: /iOS/AutofillCredentialProvider/CredentialProvider/Shared/ActionMessageView.swift:132:33: Warning: Overloaded functions declared on the same type (its primary declaration and any extensions of it in the same file) should not use different default values for a shared parameter, as this is usually an accidental drift that callers do not expect (inconsistent_default_argument_in_file)
⚠️ This PR introduced a violation in DuckDuckGo: /iOS/Core/Pixel.swift:295:29: Warning: Overloaded functions declared on the same type (its primary declaration and any extensions of it in the same file) should not use different default values for a shared parameter, as this is usually an accidental drift that callers do not expect (inconsistent_default_argument_in_file)
⚠️ This PR introduced a violation in DuckDuckGo: /SharedPackages/BrowserServicesKit/Sources/BrowserServicesKit/Email/EmailManager.swift:721:52: Warning: Overloaded functions declared on the same type (its primary declaration and any extensions of it in the same file) should not use different default values for a shared parameter, as this is usually an accidental drift that callers do not expect (inconsistent_default_argument_in_file)
⚠️ This PR introduced a violation in DuckDuckGo: /macOS/LocalPackages/BuildToolPlugins/Plugins/InputFilesChecker/Errors.swift:148:9: Warning: Overloaded functions declared on the same type (its primary declaration and any extensions of it in the same file) should not use different default values for a shared parameter, as this is usually an accidental drift that callers do not expect (inconsistent_default_argument_in_file)
⚠️ This PR introduced a violation in Firefox: /firefox-ios/Client/Extensions/UIView+Screenshot.swift:43:69: Warning: Overloaded functions declared on the same type (its primary declaration and any extensions of it in the same file) should not use different default values for a shared parameter, as this is usually an accidental drift that callers do not expect (inconsistent_default_argument_in_file)
⚠️ This PR introduced a violation in Realm: /RealmSwift/Tests/KVOTests.swift:193:9: Warning: Overloaded functions declared on the same type (its primary declaration and any extensions of it in the same file) should not use different default values for a shared parameter, as this is usually an accidental drift that callers do not expect (inconsistent_default_argument_in_file)
⚠️ This PR introduced a violation in Realm: /RealmSwift/Tests/KVOTests.swift:214:9: Warning: Overloaded functions declared on the same type (its primary declaration and any extensions of it in the same file) should not use different default values for a shared parameter, as this is usually an accidental drift that callers do not expect (inconsistent_default_argument_in_file)
⚠️ This PR introduced a violation in Realm: /RealmSwift/Tests/ProjectionTests.swift:734:35: Warning: Overloaded functions declared on the same type (its primary declaration and any extensions of it in the same file) should not use different default values for a shared parameter, as this is usually an accidental drift that callers do not expect (inconsistent_default_argument_in_file)
⚠️ This PR introduced a violation in Realm: /RealmSwift/Tests/ProjectionTests.swift:760:35: Warning: Overloaded functions declared on the same type (its primary declaration and any extensions of it in the same file) should not use different default values for a shared parameter, as this is usually an accidental drift that callers do not expect (inconsistent_default_argument_in_file)
⚠️ This PR introduced a violation in Realm: /RealmSwift/Tests/ProjectionTests.swift:786:35: Warning: Overloaded functions declared on the same type (its primary declaration and any extensions of it in the same file) should not use different default values for a shared parameter, as this is usually an accidental drift that callers do not expect (inconsistent_default_argument_in_file)
⚠️ This PR introduced a violation in WordPress: /Modules/Sources/WordPressData/Swift/WordPressComRestApi+Defaults.swift:18:41: Warning: Overloaded functions declared on the same type (its primary declaration and any extensions of it in the same file) should not use different default values for a shared parameter, as this is usually an accidental drift that callers do not expect (inconsistent_default_argument_in_file)
19 Messages
📖 Building this branch resulted in a binary size of 28242.07 KiB vs 28200.24 KiB when built on main (0% larger).
📖 Linting Aerial with this PR took 0.64 s vs 0.65 s on main (1% faster).
📖 Linting Alamofire with this PR took 0.94 s vs 0.96 s on main (2% faster).
📖 Linting Brave with this PR took 6.03 s vs 6.07 s on main (0% faster).
📖 Linting DuckDuckGo with this PR took 26.04 s vs 25.93 s on main (0% slower).
📖 Linting Firefox with this PR took 10.44 s vs 10.44 s on main (0% slower).
📖 Linting Kickstarter with this PR took 7.44 s vs 7.43 s on main (0% slower).
📖 Linting Moya with this PR took 0.35 s vs 0.35 s on main (0% slower).
📖 Linting NetNewsWire with this PR took 2.34 s vs 2.35 s on main (0% faster).
📖 Linting Nimble with this PR took 0.54 s vs 0.53 s on main (1% slower).
📖 Linting PocketCasts with this PR took 6.97 s vs 6.89 s on main (1% slower).
📖 Linting Quick with this PR took 0.37 s vs 0.35 s on main (5% slower).
📖 Linting Realm with this PR took 2.45 s vs 2.45 s on main (0% slower).
📖 Linting Sourcery with this PR took 1.49 s vs 1.49 s on main (0% slower).
📖 Linting Swift with this PR took 4.29 s vs 4.29 s on main (0% slower).
📖 Linting SwiftLintPerformanceTests with this PR took 0.16 s vs 0.16 s on main (0% slower).
📖 Linting VLC with this PR took 1.09 s vs 1.08 s on main (0% slower).
📖 Linting Wire with this PR took 15.39 s vs 15.33 s on main (0% slower).
📖 Linting WordPress with this PR took 9.9 s vs 9.93 s on main (0% faster).

Generated by 🚫 Danger

Flag overloaded functions declared on the same type (its primary
declaration and any extensions of it in the same file) when a shared
(label, type) parameter uses divergent default values. Nested types form
their own scope; cross-file/semantic cases are left to a future analyzer
rule.

Issue: realm#6668
@nenadvulic nenadvulic force-pushed the feature/inconsistent-default-argument-in-file branch from 1e4bc4c to 9eb5641 Compare July 1, 2026 10:30
@nenadvulic

nenadvulic commented Jul 1, 2026

Copy link
Copy Markdown
Author

@SimplyDanny the rule behaves exactly as scoped in this thread 6668 : grouping by (label, type) within a type's declaration + its extensions in the same file, nested types isolated.

All matches are intra-type (no cross-type false matches). The mix of real catches and intentional differences is expected and is the reason for the opt-in default; teams that want the "overloads share defaults" invariant enable it, others aren't affected.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add inconsistent_default_argument rule

2 participants