swiftlang/swift

Suboptimal diagnostics on mutating on immutable + optional value on non-optional parameter

Open

#87.218 aperta il 13 feb 2026

Vedi su GitHub
 (3 commenti) (0 reazioni) (0 assegnatari)Swift (10.719 fork)batch import
compilerdiagnostics qualityexpressionsgood first issuemutatingtype checker

Metriche repository

Star
 (69.989 star)
Metriche merge PR
 (Merge medio 7g 6h) (556 PR mergiate in 30 g)

Descrizione

Description

Trying to use a mutating method on an immutable value and an optional argument in place for a non-optional parameter may produce worse diagnostics than what would be emitted independently:

  • "error: cannot use mutating member on immutable value" → isn't emitted.
  • "error: no exact matches in call to instance method 'X'" → emitted instead of the more accurate "error: value of optional type 'T?' must be unwrapped to a value of type 'T'".

Reproduction

func buildThing() {
    let dictionary = [String: [String]]()
    var optionalValue: String?
    if let array = dictionary["foo"] {
        array.append(optionalValue) 
            // ❌ No exact matches in call to instance method 'append'
                // ℹ️ Found candidate with type '(__owned String) -> ()'
    }
}

Expected behavior

I think it should be possible to diagnose the "Cannot use mutating member on immutable value" in this scenario. All overloads of append on Array are mutating.

Environment

swift-driver version: 1.127.14.1 Apple Swift version 6.2 (swiftlang-6.2.0.19.9 clang-1700.3.19.1) Target: arm64-apple-macosx26.0

Additional information

By itself, this emits the right diagnostic:

func buildThingB() {
    let dictionary = [String: [String]]()
    if let array = dictionary["foo"] {
        array.append("bar")
           // ❌ Cannot use mutating member on immutable value: 'array' is a 'let' constant
    }
}

And so does this:

func buildThingC() {
    var dictionary = [String: [String]]()
    var optionalValue: String?
    dictionary["foo"]!.append(optionalValue)
        // ❌ Value of optional type 'String?' must be unwrapped to a value of type 'String'
            // ℹ️ Coalesce using '??' to provide a default when the optional value contains 'nil'
            // ℹ️ Force-unwrap using '!' to abort execution if the optional value contains 'nil'
}

And the compiler is able to emit both diagnostics at once under other (similar) circumstances:

func buildThingD() {
    let dictionary = [String: [String]]()
    var optionalValue: String?
    dictionary["foo"]!.append(optionalValue)
        // ❌ Cannot use mutating member on immutable value: 'dictionary' is a 'let' constant
        // ❌ Value of optional type 'String?' must be unwrapped to a value of type 'String'
            // ℹ️ Coalesce using '??' to provide a default when the optional value contains 'nil'
            // ℹ️ Force-unwrap using '!' to abort execution if the optional value contains 'nil'
}

Guida contributor