Swift Framework devuelve la extensión del método 'uso ambiguo de' en lldb

8

He actualizado a Xcode 11 y swift 5, y he encontrado un problema con las extensiones de método cuando están disponibles a través de un marco. Más específicamente, en un proyecto estructurado así:

-> 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)

Todo se compila y funciona bien, pero cuando se ejecutan sesiones de depuración en el subproyecto, todas las extensiones en 'Framework' regresan error: ambiguous use of cuando se invocan desde la línea de comando lldb. Aquí hay un ejemplo de código para dar una idea:

Cree un proyecto de línea de comandos de macOs y agregue un nuevo objetivo, 'MagicFramework', y en un archivo Spells.swift (asegúrese de que el archivo sea visible para Main & MagicFramework)

import Foundation

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

Luego, cree un subproyecto 'Asistente' y en un archivo wizard.swift (visible solo para el Asistente):

import Foundation
import MagicFramework


public class Tadaa {

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

en el archivo main.swift del Asistente, agregue:

import Foundation

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

print(aa)

Debe tener la siguiente estructura:

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

luego construya y ejecute el sub 'Asistente', con un punto de interrupción spell.castSpell()en Tadaa. En el indicador lldb, escriba:

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

¿¿por qué?? Este problema no ocurrió con Xcode 10.

Alex
fuente

Respuestas:

7

En mi humilde opinión, esto solo puede ser un error.

Si configuro el ejemplo que está dando en su pregunta, puedo reproducir el problema.

En el punto de quiebre, consigo

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

tal como lo describiste.

Sin embargo, si busco la función castSpellen lldb, obtengo:

(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

Eso significa que lldb ha encontrado exactamente una coincidencia: la extensión en MagicFramework biblioteca. Por lo tanto, no hay razón para que esto sea ambiguo.

En aras de la integridad, también verifiqué el tipo de variable spellcomo lo ve llbd:

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

Para resumir: lldb sabe que el tipo es String. Se sabe que hay una función castSpelldefinida en la extensión y sabe exactamente de una implementación de dicha función. Pero aún así muestra el mensaje de error.

Entonces, a menos que me falte algo esencial aquí, esto debe ser un error de lldb.

Lutz
fuente
Suena bien :) muchas gracias por los detalles! ¿Sabes que hay una manera de solucionarlo?
Alex
1
Lo siento Alex, no tengo idea de cómo solucionar esto para una lib dinámica. Pero si puede hacer que su MagicFramework sea una biblioteca estática, entonces esto no debería ser un problema (escriba Mach-O en la Configuración de compilación para el destino, asegúrese de ejecutar Product-> Clean Build Folder después de cambiar esta configuración)
Lutz
@Alex y Lutz Gracias por esta pregunta y respuesta. Encontré una solución horrible, pero una solución alternativa. Agregué temporalmente una clase D con métodos estáticos que llaman a los métodos de la extensión (tomando el objeto como parámetro) y luego llamo a la extensión desde allí; lo que me ayudará hasta que esto se solucione.
aepryus
0

Tuve el mismo problema con mi extensión. En mi situación, esa es una función única que estoy usando mucho durante la depuración, por lo que acabo de crear una función global que en su caso simplemente aceptaría la cadena y llamaría a esa extensión dentro. Realmente similar a lo que @aepryus ha señalado en el comentario a la primera respuesta.

import Foundation

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

func castSpell(_ string: String) -> String {
    return string.castSpell()
}

Entonces úsalo así:

(lldb) po castSpell("this is magic")
"✨ this is magic"

(lldb) 
Anton Ogarkov
fuente