swiftlang/swift

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

Open

#87.218 aberto em 13 de fev. de 2026

Ver no GitHub
 (3 comments) (0 reactions) (0 assignees)Swift (10.719 forks)batch import
compilerdiagnostics qualityexpressionsgood first issuemutatingtype checker

Métricas do repositório

Stars
 (69.989 stars)
Métricas de merge de PR
 (Mesclagem média 7d 6h) (556 fundiu PRs em 30d)

Description

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'
}

Guia do colaborador