O Swift Framework retorna a extensão do método 'uso ambíguo de' no lldb

8

Atualizei para o Xcode 11 e o swift 5 e encontrei um problema com as extensões de método quando elas são disponibilizadas por meio de uma estrutura. Mais especificamente, em um projeto estruturado como este:

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

Tudo compila e executa bem, mas ao executar sessões de depuração no subprojeto, todas as extensões no 'Framework' retornam error: ambiguous use ofquando invocadas a partir da linha de comando lldb. Aqui está um exemplo de código para dar uma idéia:

Crie um projeto de linha de comando para macOs e adicione um novo destino, 'MagicFramework' e em um arquivo Spells.swift (verifique se o arquivo está visível para Main & MagicFramework)

import Foundation

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

Em seguida, crie um subprojeto 'Assistente' e em um arquivo wizard.swift (visível apenas para o Assistente):

import Foundation
import MagicFramework


public class Tadaa {

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

no arquivo main.swift do Assistente, adicione:

import Foundation

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

print(aa)

Você deve ter a seguinte estrutura:

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

então crie e execute o sub 'Assistente', com um ponto de interrupção ativado spell.castSpell()no Tadaa. No prompt do lldb, digite:

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

porque?? Este problema não ocorreu com o Xcode 10.

Alex
fonte

Respostas:

7

Na minha humilde opinião, isso só pode ser um bug.

Se eu definir o exemplo que você está dando na sua pergunta, eu posso reproduzir o problema.

No ponto de interrupção, eu recebo

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

assim como você descreveu.

No entanto, se eu procurar a função castSpellno lldb, recebo:

(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

Então isso significa que o lldb encontrou exatamente uma correspondência: a extensão na MagicFrameworkbiblioteca. Portanto, não há razão para que isso seja ambíguo.

Por uma questão de completude, também verifiquei o tipo da variável spellcomo llbd a vê:

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

Então, para resumir: o lldb sabe que o tipo é String. Ele sabe que existe uma função castSpelldefinida na extensão e conhece exatamente uma implementação da referida função. Mas ainda mostra a mensagem de erro.

Portanto, a menos que eu esteja perdendo algo essencial aqui, isso deve ser um bug do lldb.

Lutz
fonte
Parece certo :) muito obrigado pelos detalhes! Você sabe que existe uma maneira de contornar isso?
20919 Alex
1
Desculpe Alex, não faço ideia de como contornar isso para uma lib dinâmica. Mas se você pode fazer o seu MagicFramework uma biblioteca estática, então este deve ser nenhum problema (Mach-O tipo de configurações de compilação para o alvo, certifique-se de executar Produto-> Pasta compilação limpa após alterar essa configuração)
Lutz
@ Alex e Lutz Obrigado por esta pergunta e resposta. Eu encontrei um trabalho horrível por aí, mas um trabalho por aí mesmo assim. Adicionei temporariamente uma classe D com métodos estáticos que chamam os métodos da extensão (tomando o objeto como parâmetro) e depois chamamos a extensão a partir daí; o que me ajudará até que isso seja corrigido.
aepryus
0

Eu tive o mesmo problema com minha extensão. Na minha situação, essa é uma função única que estou usando bastante durante a depuração, então acabei de criar uma função global que, no seu caso, aceitaria a string e chamaria essa extensão dentro. Muito parecido com o que @aepryus apontou no comentário para a primeira resposta.

import Foundation

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

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

Em seguida, use-o assim:

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

(lldb) 
Anton Ogarkov
fonte