Is `Symbol.type` always `nil`? [SymbolKit]

I’m experimenting with SymbolKit in order to prototype some tooling ideas I had and I came accross Symbol.type.

If I have

struct Foo { }
struct Bar {
    var baz: Foo
}

then it seems like the symbol baz should have the precise identifier for Foo in its type property. Instead, it’s nil. And every symbol in every symbol graph file for every module I’ve tried is nil.

What’s up with that?

If it helps the symbol graph files were emitted with this version of Swift:

swift-driver version: 1.26.21 Apple Swift version 5.5.2 (swiftlang-1300.0.47.5 clang-1300.0.29.30)
Target: x86_64-apple-macosx12.0

It doesn't actually seem that the Swift compiler is emitting that field in symbol graph files. The precise identifier (aka "USR") of symbols is available in the identifier.precise property. I wonder if the type property models a field that's no longer part of the symbol graph and we should just remove it from the Swift model (cc @QuietMisdreavus if you have ideas).

From what i can tell, that field hasn't been emitted by the Swift compiler since symbol graphs were originally supported. I wonder if this is something that was intended to be supported, but never got implemented (that's speculation on my part, though; i'd ask @bitjammer for more info).

Yes, I just haven’t gotten around to it. I originally intended to put a structure in there similar to the typerefs that I used in reflection metadata, in order to visualize types in a new way, rather than just abbreviated textual declarations.

1 Like

Thank you all for your help! I’m glad to hear that the symbol’s type is intended to be discoverable. @franklin thanks for the term “USR” — that was very helpful (found a definition here: https://github.com/apple/swift/blob/main/docs/Lexicon.md#usr).

I’m particularly interested to hear about the “structure […] similar to the typerefs […] used in reflection metadata,” you mentioned @bitjammer. Does that mean emitting objects into the symbol graph which represent a more full type of a symbol, like a USR for a generic type + a mapping of the bound type parameters? e.g. so you could pull apart the type [Int]? and find the symbols for Optional, Array, and Int from that type?

If so, that would be really neat! My purpose is basically exactly what you said: a tool to help programmers visualize the connections between types & find the symbols which connect types. An example would be given the type [Int] you could find your way to an Int by using its subscript or with the property count; whereas with the type [String] you could get to an Int via count, but not with its subscript. With plain nominal types this is easy enough, but it gets a little trickier when dealing with structural or generic types.

So far I’ve been getting away with just scanning through the the “declaration fragments” and pulling the “precise identifiers” out of fragments which have kind “typeIdentifier,” but to make my project really work well I think something like this would be essential (either that or I’m going to be parsing declaration fragments myself!).

Yes, exactly! For function types, the parameter and return types; generic types, etc.

Yeah, the declaration fragments are really just a convenience for the purposes of displaying a particular element on the documentation pages (The "Declaration" box) and you shouldn't have to be the one to parse that.

I'm so glad you're thinking of ways to use the structural data instead of the presentation data. It was always my goal for the Symbol Graph format to use the data to show relationships between symbols in new ways, rather than bake in a particular presentation experience.

Please file an SR though! I think there are some really cool ways we could show the concrete types of things in various contexts.

3 Likes

Thanks for your response! That's super cool & very exciting. Count me as a fan of this idea!

Created [SR-15852] Add structural type data to symbol graph - Swift

2 Likes