Question about declaration context name mangling

just to clarify since this part of Mangling.rst is a little confusing; in the following example, the module Baz is the module that contains the protocol extension on _Bar, and Foo is the module being extended, correct?

// example 2: 's3Foo4_BarP3BazE' -> (extension in Baz):Foo._Bar

// 's': language is swift 
// '3Foo': namespace module is 'Foo'
// '4_BarP': protocol ('P') is '_Bar', which is 4 characters long
// '3BazE': perpetrator module is 'Baz'

moreover, since _Bar is a protocol, can we assume that _Bar was always declared by Foo?

Basically yes. There's no such thing as "the module being extended"; the only purpose of Foo here is to say that _Bar was defined in Foo.

1 Like

if the module Baz were to extend _Bar with a property like qux:Int { get } , would the mangled name still be s3Foo4_BarP3BazE3quxSivg? or would it be s3Baz4_BarP3BazE3quxSivg, or something else entirely?

// module Foo
protocol _Bar 
// module Baz 
import Foo

extension _Bar 
    var qux:Int 

It would be the first, $s3Foo4_BarP3BazE3quxSivg

1 Like

I suggest exploring these with swift-demangle --expand, it helps with which names apply to which, uh, other names.

% xcrun swift-demangle --expand s3Foo4_BarP3BazE3quxSivg    
Demangling for $s3Foo4_BarP3BazE3quxSivg
        kind=Module, text="Baz"
          kind=Module, text="Foo"
          kind=Identifier, text="_Bar"
      kind=Identifier, text="qux"
          kind=Module, text="Swift"
          kind=Identifier, text="Int"
$s3Foo4_BarP3BazE3quxSivg ---> (extension in Baz):Foo._Bar.qux.getter : Swift.Int

wow, that’s really useful, thanks!

…the postfix notation is really coming out strong in this example:

  • 3Foo "Foo"
  • 4_Bar "_Bar"
  • P protocol $(pop) in module $(pop)
  • 3Baz "Baz"
  • E extension in module $(pop) of $(pop)
  • 3qux "qux"
  • Si hardcoded shorthand for Swift.Int
  • v variable of type $(pop) named $(pop) in $(pop)
  • g getter for $(pop)

IIRC the demangler really does work like this, scanning forward to chunk things into words? lexemes? and then pushing and popping them on a stack.

1 Like

is there a general way to determine what module a symbol is declared in, based on only its mangled name?

this is motivated by Filtering out @_exported import symbols from symbol graphs

There’s no general way because the symbol operators don’t all have the same format. But working from the demangle tree it should always be possible to walk up the contexts until you get to a module. As demonstrated, though, it’s not always the first identifier in the symbol or anything.

1 Like

is there an API in the runtime i can use to get this demangle tree? i'm really at a loss for how to filter symbols in symbolgraphs by declaring module…

It really does sound like something should expose demangle trees—one of the Syntax libraries if not the runtime itself. But then to your actual question, I’m pretty sure that information is elsewhere in symbolgraphs (not my area of expertise) and you should not be trying to do it through mangled names.

(In retrospect I wonder if the extension node is the only one that’s in the “wrong” order in mangled form, but it’s too late to change that.)

1 Like

i agree. unfortunately according to @franklin in the other thread it is not in the symbolgraphs :pensive:

1 Like

I’m guessing SymbolGraphGen could emit the original defining module in symbol graphs though, since it has access to the decl.

1 Like

that sounds like the best solution. should i open an issue on github to track it?

Sounds good. If you're interested in implementing the new behaviour, feel free to reach out for pointers, @QuietMisdreavus and I are happy to help :slight_smile:

1 Like