Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift Framework returns 'ambiguous use of' method extension in lldb

I've upgraded to Xcode 11 & swift 5, and hit an an issue with method extensions when they are made available through a framework. More specifically, in a project structured like this:

-> Main Project
-> Framework created from sources in 'Main Project'
-> Subproject using the above Framework (Sources packaged in the framework are not visible to the sub-project)

Everything compiles and runs fine, but when running debug sessions on the subproject, all extensions in 'Framework' return error: ambiguous use of when invoked from the lldb command line. Here is a code sample to give an idea:

Create a macOs command line project, and add a new target, 'MagicFramework', and in a file Spells.swift (make sure the file is visible to Main & MagicFramework)

import Foundation

extension String {
    public func castSpell() -> String {
        return "✨ " + self
    }
}

Then create a subproject 'Wizard', and in a file wizard.swift (visible to Wizard only):

import Foundation
import MagicFramework


public class Tadaa {

    public func magic(spell:String) -> String {
        return spell.castSpell()
    }
}

in Wizard's main.swift file, add:

import Foundation

let aa = Tadaa().magic(spell: "this is magic")

print(aa)

You should have the following structure:

-> Main project
----> MagicFramework
----> Wizard subproject

then build&run 'Wizard' sub, with a break point on spell.castSpell() in Tadaa. At the lldb prompt, type:

(lldb)po spell.castSpell()
error: <EXPR>:3:1: error: ambiguous use of 'castSpell()'
spell.castSpell()

why?? This problem didn't occur with Xcode 10.

like image 924
Alex Avatar asked Nov 05 '19 06:11

Alex


1 Answers

In my humble opinion, this can only be a bug.

If I set up the example you are giving in your question, I can reproduce the problem.

On the breakpoint, I get

(lldb) po spell.castSpell()
error: <EXPR>:3:1: error: ambiguous use of 'castSpell()'
spell.castSpell()
^

just as you described.

However, if I look up the function castSpell in lldb, I get:

(lldb) image lookup -vn castSpell
1 match found in /Users/lameyl01/Library/Developer/Xcode/DerivedData/Main-dsjbnoyousgzmrdnqxtxoeyeyzpv/Build/Products/Debug/MagicFramework.framework/Versions/A/MagicFramework:
        Address: MagicFramework[0x0000000000000ab0] (MagicFramework.__TEXT.__text + 0)
        Summary: MagicFramework`(extension in MagicFramework):Swift.String.castSpell() -> Swift.String at Spells.swift:12
         Module: file = "/Users/lameyl01/Library/Developer/Xcode/DerivedData/Main-dsjbnoyousgzmrdnqxtxoeyeyzpv/Build/Products/Debug/MagicFramework.framework/Versions/A/MagicFramework", arch = "x86_64"
    CompileUnit: id = {0x00000000}, file = "/Users/lameyl01/tmp/Main/MagicFramework/Spells.swift", language = "swift"
       Function: id = {0x100000038}, name = "(extension in MagicFramework):Swift.String.castSpell() -> Swift.String", mangled = "$sSS14MagicFrameworkE9castSpellSSyF", range = [0x000000010033fab0-0x000000010033fb21)
       FuncType: id = {0x100000038}, byte-size = 8, decl = Spells.swift:12, compiler_type = "() -> ()"
         Blocks: id = {0x100000038}, range = [0x10033fab0-0x10033fb21)
      LineEntry: [0x000000010033fab0-0x000000010033fabf): /Users/lameyl01/tmp/Main/MagicFramework/Spells.swift:12
         Symbol: id = {0x00000005}, range = [0x000000010033fab0-0x000000010033fb21), name="(extension in MagicFramework):Swift.String.castSpell() -> Swift.String", mangled="$sSS14MagicFrameworkE9castSpellSSyF"
       Variable: id = {0x100000055}, name = "self", type = "Swift.String", location = DW_OP_fbreg(-16), decl = Spells.swift:12

So that means that lldb has found exactly one match: The extension in the MagicFramework library. So there is no reason why this should be ambiguous.

For the sake of completeness I also checked the type of the variable spell as llbd sees it:

(lldb) frame variable spell
(String) spell = "this is magic"

So to summarize: lldb knows the type is String. It knows that there is a function castSpell defined in the extension and it knows of exactly one implementation of said function. But still it shows the error message.

So unless I'm missing something essential here, this must be a lldb bug.

like image 196
Lutz Avatar answered Nov 04 '22 05:11

Lutz