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

Forbid unsafe types in records #76588

Merged
merged 7 commits into from
Jan 17, 2025
Merged

Conversation

333fred
Copy link
Member

@333fred 333fred commented Dec 30, 2024

The specification for records forbids the use of unsafe types as an instance field of the type. However, we didn't check that in all cases; we only checked when generating the Equals method for the record type. This meant that if the user provided their own definition of Equals, they could bypass this restriction. We also did not check for nested unsafe types, so int*[] was permitted in any scenario. We have 2 options for fixing this:

  1. Treat it as a specification bug, and update the spec to follow the current behavior. We'd therefore fix Errors about prohibiting pointer fields on records not shown in the code, they're only visible on the build output #66312 by moving the diagnostic to SourceNamedTypeSymbol.AfterMembersChecks, and only error when the user didn't provide their own implementation of Equals.
  2. Treat it as a compiler bug, and forbid use of unsafe types in all scenarios.

I've opted for path 2 here, but we can discuss whether this is too aggressive and if we should opt for path 1 instead. Fixes #66312.

[The specification](https://github.com/dotnet/csharplang/blob/main/proposals/csharp-9.0/records.md#members-of-a-record-type) for records forbids the use of unsafe types as an instance field of the type. However, we didn't check that in all cases; we only checked when generating the `Equals` method for the record type. This meant that if the user provided their own definition of `Equals`, they could bypass this restriction. We also did not check for nested unsafe types, so `int*[]` was permitted in any scenario. We have 2 options for fixing this:

1. Treat it as a specification bug, and update the spec to follow the current behavior. We'd therefore fix dotnet#66312 by moving the diagnostic to SourceNamedTypeSymbol.AfterMembersChecks, and only error when the user didn't provide their own implementation of `Equals`.
2. Treat it as a compiler bug, and forbid use of unsafe types in all scenarios.

I've opted for path 2 here, but we can discuss whether this is too aggressive and if we should opt for path 1 instead. Fixes dotnet#66312.
@333fred 333fred requested a review from a team as a code owner December 30, 2024 22:04
@dotnet-issue-labeler dotnet-issue-labeler bot added Area-Compilers untriaged Issues and PRs which have not yet been triaged by a lead labels Dec 30, 2024
@333fred
Copy link
Member Author

333fred commented Dec 30, 2024

We also need to decide what to do with manually-implemented properties that have unsafe types. As pointed out by @hamarb123, even with this change we'll still generate invalid IL for PrintMembers in such a case, where we cast the pointer to object. By my reading of the spec, it says we should make it work; nothing about the definition of PrintMembers specifies that this cast needs to occur, and we could instead convert the pointer to IntPtr before doing the print. The main question is whether we should do this, or just forbid all pointer types in records, period.

@AlekseyTs
Copy link
Contributor

It looks like more test base-lines need an adjustment

@AlekseyTs
Copy link
Contributor

Done with review pass (commit 1)

@jaredpar jaredpar added Feature - Records Records and removed untriaged Issues and PRs which have not yet been triaged by a lead labels Jan 6, 2025
* upstream/main: (368 commits)
  Cleanup tests
  Add test
  Add test
  Add test
  Fix issue parsing regex category
  Properly simplify pattern when converting to pattern matching
  update publishdata after VS 17.13 snap
  Simplify
  Docs
  Do not lift type parameters in extract method declared within the selected region
  Fix ExtractMethod in VB elseif blocks
  Rework our Helix Process (dotnet#76703)
  Stash and restore original culture in CultureNormalizer (dotnet#76713)
  PR comments
  Adding checks for mutable structs.
  Add additional tests for string escape sequences
  CodeGenerator.EmitStackAlloc - Avoid capturing blob array (dotnet#76660)
  Update comments and exception type for LSP stdio configuration based on review feedback
  Fix race generating Microsoft.Managed.Core.CurrentVersions.targets (dotnet#76701)
  Update FileDownloader.cs
  ...
@333fred
Copy link
Member Author

333fred commented Jan 14, 2025

@AlekseyTs addressed your feedback. The spec part of this change is at dotnet/csharplang#9050, clarifying what "unsafe types" is actually supposed to mean.

@AlekseyTs
Copy link
Contributor

Done with review pass (commit 3)

Copy link
Contributor

@AlekseyTs AlekseyTs left a comment

Choose a reason for hiding this comment

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

LGTM (commit 4)

@333fred
Copy link
Member Author

333fred commented Jan 16, 2025

@dotnet/roslyn-compiler for a second review

@hamarb123
Copy link

hamarb123 commented Jan 16, 2025

Did you end up blocking manually implemented pointer type properties, or allowing them (and fixing the PrintMembers), out of curiosity. Based on the spec change I assume they're allowed?

@333fred
Copy link
Member Author

333fred commented Jan 16, 2025

Did you end up blocking manually implemented pointer type properties, or allowing them (and fixing the PrintMembers), out of curiosity. Based on the spec change I assume they're allowed?

No change was made to locations without fields.

@333fred
Copy link
Member Author

333fred commented Jan 16, 2025

@dotnet/roslyn-compiler for a second review

@333fred 333fred enabled auto-merge (squash) January 16, 2025 23:18
* upstream/main: (172 commits)
  Move impl of ILspWorkpace to EditorTestWorkspace/LspTestWorkspace (dotnet#76753)
  Field-backed properties: report diagnostic for variable named field declared in accessor (dotnet#76671)
  Add more tests
  Update 'use nameof instead of typeof' to support generic types
  Update dependencies from https://github.com/dotnet/arcade build 20250115.2
  Add docs
  invert
  Update src/Analyzers/CSharp/Tests/CSharpAnalyzers.UnitTests.projitems
  Update options
  Fixup tests
  fixup options
  Update tests
  Add test
  Fix trivia
  Handle params
  Support modifiers with simple lambda parameters. (dotnet#75400)
  Handle params
  Use helper
  Add fixes
  Flesh out
  ...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
5 participants