Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Draft to check for failures on CI
Alternative to #111984
For two scenarios touched on in issue #104511, we can solve them through different paths in the same InitializeFieldDescs method:
Static field on a struct, of a generic struct type that indirectly references the type hosting the field, i.e.
We have existing infrastructure for doing cycle-avoidant type loads in cases like this -
tkTypeDefToAvoidIfPossible
- so we just need to sense that we've encountered a scenario where it might be necessary. We can do this by checking whether the field is:We already know 1 & 2, so I add a bit of signature decoding to determine 3. If all three conditions are met we use
tkTypeDefToAvoidIfPossible
to avoid loading ourselves when loading the field type. This feels like a decent compromise to fix this scenario and shouldn't impact the vast majority of fields in existing applications.Static field on an interface, of a struct type that implements said interface, i.e.
tkTypeDefToAvoidIfPossible
can't save us here and flowing it through into the place where interfaces are loaded would require some significant code changes, so I decided to see if I could narrowly target a workaround based on our existing handling of self-referential static fields.This PR's approach is to look up the type of each static struct field on an interface, and if it's a typedef (not a typeref, which means it's in the current module and can form a cycle), we scan the interfaceimpl table for that typedef to see if we're in it. If we are, treat the field type as if it's a reference to us. This taps into the existing logic for handling self-referential static fields and seems to work, though I had to tweak some code related to enums.
The cost of doing this could get prohibitive for large numbers of static struct type fields on an interface, though I'm having trouble imagining a scenario that would require that, and there are some fairly obvious ways to optimize it.