Recursive direction of RecursiveTypeProperties?

I’ve been trying to add a new flag to RecursiveTypeProperties, and I was perplexed for a while by the fact that generic types recurse in the opposite direction when compared to other types.

For example, the properties of a TupleType are the union of the properties used within the tuple; but in contrast the properties of a ClassType instance are the union of its parent properties – not the properties used within the class. This seems like a shortcut to avoid deep introspection of the class, and therefore any given HasXYZ property on a generic type really means MayHaveXYZ. Is this a correct interpretation of the implementation? Does anything in the language or the implementation require the “may have XYZ” approach over deep introspection?

Thanks,
Dave

Recursive type properties are supposed to capture qualities of the type that propagate from its structural representation. Tuple elements, generic arguments, the parent of a nested type, etc. all form part of the structure of the type name.

I don’t think these are different directions. If a ClassType has a parent type, the parent type is nested inside the ClassType. That is, Foo<T>.Bar is represented as ClassType(Bar, parent: GenericStructType(Foo, arguments: [GenericTypeParamType(T)])).

Hi Jordan –

To use your example, if Bar doesn’t use any of the generic parameters from its parent types, then recursively merging in HasUnboundType from the parent types feels weird and untrue; but seemingly harmless.

I’m asking because I’m experimenting with a new type property that behaves somewhat like IsLValue or HasDynamicSelf but doesn’t make sense to inherit from parent types. This happens to work for IsLValue and HasDynamicSelf because they’re never set on parent types, but that won’t be true for the property I’m experimenting with.

Ah, it’s not untrue. Remember that Foo<Int>.Bar and Foo<String>.Bar are different types in Swift, so Foo.Bar is just as unbound as Foo. (Well, maybe not just as unbound. But still unbound.)

It sounds like your new property may not actually be fully recursive if it only propagates outwards for tuples (and paren-types). Can you share what it is?

Thanks @jrose for helping me understand RecursiveTypeProperties. Let’s use a concrete example:

struct Ant<Bear> { struct Cat { var dog : Int }; force_error }

In the above example, I feel lost to why Cat recursively inherits any flags from Ant. Inheriting HasError from Ant feels wrong because there Cat has no error. Inheriting generics related flags similarly feels wrong because Cat never uses the generic parameter Bear. What am I missing?

Hey @jrose and @Joe_Groff – I was thinking your comments more, and I think I get it now. I was overly tempted by the RecursiveTypeProperties implementation which is very close to what I want. To test my understanding, is it fair to say that recursive type properties are not “random” recursive flags, but those specific to the types that contribute to the type name. Correct?

I think what I want is something like RecursiveTypeProperties but that recurses over members/properties/fields/elements. Do we have something like that? (Perhaps now you can see why the IsLValue flag helped lead me astray.)

I think you’re treating ClassType as something it’s not. There isn’t just one ClassType for a particular nested type declaration. I already mentioned Foo<Int>.Bar and Foo<String>.Bar, but we also have Foo<$T0>.Bar and Foo<ERROR>.Bar.


We deliberately don’t have features that recurse over members because that would break resilience, where you’re not allowed to look at members. What are you really trying to do?

Deliberately not recursing over members is useful to know. I have a serialization test that is failing right now where more Decls are being deserialized than expected, but I didn’t realize that also represented a resiliency problem. I thought it was just about deserialization performance.

I was planning on refactoring how/where the bit gets computed to make the serialization test pass. That should fix the resiliency too and avoid the desire to use recursive type properties. Thanks!