Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Low level struct updates #5602

Merged
merged 28 commits into from
Jan 13, 2022
Merged
Changes from 1 commit
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
38b1386
Lifetime updates
jaredpar Nov 16, 2021
4a2ac0c
format
jaredpar Dec 30, 2021
b83e114
moving forward
jaredpar Dec 30, 2021
d3e5c34
more progress
jaredpar Dec 30, 2021
5023c9e
rename to RefThisEscapes
jaredpar Dec 30, 2021
776a7cd
better RefThisEscapes documentation and rules
jaredpar Dec 30, 2021
4dca026
pull out the compat considerations into their own section
jaredpar Dec 30, 2021
6478bfc
progress
jaredpar Dec 30, 2021
e515d58
major progress
jaredpar Dec 30, 2021
7aef477
core parts of the doc are in shape now
jaredpar Dec 31, 2021
ce9f258
edits complete
jaredpar Dec 31, 2021
a60f9c3
edits
jaredpar Jan 3, 2022
4a61b91
Apply suggestions from code review
jaredpar Jan 3, 2022
5edbfe9
PR feedback
jaredpar Jan 3, 2022
3cabddd
Better sample
jaredpar Jan 3, 2022
f9eb4de
more
jaredpar Jan 3, 2022
33bddf4
feedback
jaredpar Jan 4, 2022
97225d7
Update proposals/low-level-struct-improvements.md
jaredpar Jan 5, 2022
1a38089
Update proposals/low-level-struct-improvements.md
jaredpar Jan 5, 2022
b74e897
Apply suggestions from code review
jaredpar Jan 5, 2022
f9f57fe
Update proposals/low-level-struct-improvements.md
jaredpar Jan 5, 2022
26876d6
Fixed a flaw with [DoesNotEscape]
jaredpar Jan 5, 2022
d10b06d
Apply suggestions from code review
jaredpar Jan 5, 2022
6c1ac07
ref assembly discussion
jaredpar Jan 13, 2022
d57a315
Apply suggestions from code review
jaredpar Jan 13, 2022
df1dca0
Apply suggestions from code review
jaredpar Jan 13, 2022
dafa854
PR feedback
jaredpar Jan 13, 2022
4b89f19
Update proposals/low-level-struct-improvements.md
jaredpar Jan 13, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions proposals/low-level-struct-improvements.md
Original file line number Diff line number Diff line change
Expand Up @@ -790,6 +790,31 @@ Several ideas for having implicit opt-in to `ref` capture were explored and disc

These implicit opt-in strategies all have significant holes while an explicit opt-in is fully generalizable and makes the span safety rule different explicit in the code.

### Reference Assemblies
A reference assembly for a compilation using features described in this proposal must maintain the elements that convey span safety information. That means all lifetime annotation attributes and `[RefFieldEscapes]` must be preserved in their original position. Any attempt to replace or omit them can lead to invalid reference assemblies.

Representing `ref` fields is more nuanaced. Ideally a `ref` field would appear in a reference assembly as would any other field. However a `ref` field represents a change to the metadata format and that can cause issues with tool chains that are not updated to understand this metadata change. A concrete example is C++/CLI which will likely error if it consumes a `ref` field. Hence it's advantageous if `ref` fields can be omitted from reference assemblies in our core libraries.

A `ref` field by itself has no impact on span safety rules. As a conecrete example consider that flipping the existing `Span<T>` defintion to use a `ref` field has no impact on consumption. Hence the `ref` itself can be omitted safely. However a `ref` field does have other impacts to consumption that must be preserved:

- A `ref struct` which has a `ref` field is never considered `unmanaged`
- The type of the `ref` field impacts infinite generic expansion rules. Hence if the type of a `ref` field contains a type parameter that must be preserved

Given those rules here is a valid reference assembly transformation for a `ref struct`:

```c#
// Impl assembly
ref struct S<T> {
ref T _field;
}

// Ref assembly
ref struct S<T> {
object _o; // force unmanaged
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't the additional field change the size of the ref struct for the consumer?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generally size is calculated at runtime based on the impl assembly, not the reference assembly. It's generally considered acceptable for reference assemblies to add / remove fields. Been a common practice in GenAPI for a number of years.

T _f; // mantain generic expansion protections
}
```

### Why isn't assignability to ref field a scope?
It may seem attractive to think of the ability to assign to a `ref` field as just another scope concept instead of an orthogonal concept. Essentially *assignable to field* as an escape scope between *heap* and *calling method*. This falls a part though when looking at practical examples. Consider for example the following:

Expand Down