Skip to content

Commit 24ef671

Browse files
authored
Ad-hoc fix for ref readonly parameters (#16232)
* Test should fail * Threat ref readonly as inref * Fixed condition in test
1 parent c2031c2 commit 24ef671

File tree

4 files changed

+70
-8
lines changed

4 files changed

+70
-8
lines changed

src/Compiler/Checking/TypeHierarchy.fs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -355,8 +355,13 @@ let ImportILTypeFromMetadata amap m scoref tinst minst ilTy =
355355
/// Read an Abstract IL type from metadata, including any attributes that may affect the type itself, and convert to an F# type.
356356
let ImportILTypeFromMetadataWithAttributes amap m scoref tinst minst ilTy getCattrs =
357357
let ty = RescopeAndImportILType scoref amap m (tinst@minst) ilTy
358-
// If the type is a byref and one of attributes from a return or parameter has IsReadOnly, then it's a inref.
359-
if isByrefTy amap.g ty && TryFindILAttribute amap.g.attrib_IsReadOnlyAttribute (getCattrs ()) then
358+
// If the type is a byref and one of attributes from a return or parameter has
359+
// - a `IsReadOnlyAttribute` - it's an inref
360+
// - a `RequiresLocationAttribute` (in which case it's a `ref readonly`) which we treat as inref,
361+
// latter is an ad-hoc fix for https://github.com/dotnet/runtime/issues/94317.
362+
if isByrefTy amap.g ty
363+
&& (TryFindILAttribute amap.g.attrib_IsReadOnlyAttribute (getCattrs ())
364+
|| TryFindILAttribute amap.g.attrib_RequiresLocationAttribute (getCattrs ())) then
360365
mkInByrefTy amap.g (destByrefTy amap.g ty)
361366
else
362367
ty
@@ -428,4 +433,3 @@ let FixupNewTypars m (formalEnclosingTypars: Typars) (tinst: TType list) (tpsori
428433
let tprefInst = mkTyparInst formalEnclosingTypars tinst @ renaming
429434
(tpsorig, tps) ||> List.iter2 (fun tporig tp -> tp.SetConstraints (CopyTyparConstraints m tprefInst tporig))
430435
renaming, tptys
431-

src/Compiler/TypedTree/TcGlobals.fs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1423,6 +1423,7 @@ type TcGlobals(
14231423
member val attrib_ParamArrayAttribute = findSysAttrib "System.ParamArrayAttribute"
14241424
member val attrib_IDispatchConstantAttribute = tryFindSysAttrib "System.Runtime.CompilerServices.IDispatchConstantAttribute"
14251425
member val attrib_IUnknownConstantAttribute = tryFindSysAttrib "System.Runtime.CompilerServices.IUnknownConstantAttribute"
1426+
member val attrib_RequiresLocationAttribute = findSysAttrib "System.Runtime.CompilerServices.RequiresLocationAttribute"
14261427

14271428
// We use 'findSysAttrib' here because lookup on attribute is done by name comparison, and can proceed
14281429
// even if the type is not found in a system assembly.

tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
<ItemGroup>
3030
<Compile Include="..\service\FsUnit.fs">
3131
<Link>FsUnit.fs</Link>
32-
</Compile>
32+
</Compile>
3333
<Compile Include="Conformance\BasicGrammarElements\AccessibilityAnnotations\Basic\Basic.fs" />
3434
<Compile Include="Conformance\BasicGrammarElements\AccessibilityAnnotations\OnOverridesAndIFaceImpl\OnOverridesAndIFaceImpl.fs" />
3535
<Compile Include="Conformance\BasicGrammarElements\AccessibilityAnnotations\OnTypeMembers\OnTypeMembers.fs" />
@@ -112,7 +112,7 @@
112112
<Compile Include="Conformance\Types\RecordTypes\AnonymousRecords.fs" />
113113
<Compile Include="Conformance\Types\RecordTypes\RecordTypes.fs" />
114114
<Compile Include="Conformance\Types\StructTypes\StructTypes.fs" />
115-
<Compile Include="Conformance\Types\StructTypes\StructActivePatterns.fs" />
115+
<Compile Include="Conformance\Types\StructTypes\StructActivePatterns.fs" />
116116
<Compile Include="Conformance\Types\TypeConstraints\CheckingSyntacticTypes\CheckingSyntacticTypes.fs" />
117117
<Compile Include="Conformance\Types\TypeConstraints\LogicalPropertiesOfTypes\LogicalPropertiesOfTypes.fs" />
118118
<Compile Include="Conformance\Types\TypeConstraints\IWSAMsAndSRTPs\IWSAMsAndSRTPsTests.fs" />
@@ -176,7 +176,7 @@
176176
<Compile Include="ErrorMessages\DontSuggestTests.fs" />
177177
<Compile Include="ErrorMessages\ElseBranchHasWrongTypeTests.fs" />
178178
<Compile Include="ErrorMessages\InvalidLiteralTests.fs" />
179-
<Compile Include="ErrorMessages\InvalidNumericLiteralTests.fs" />
179+
<Compile Include="ErrorMessages\InvalidNumericLiteralTests.fs" />
180180
<Compile Include="ErrorMessages\MissingElseBranch.fs" />
181181
<Compile Include="ErrorMessages\MissingExpressionTests.fs" />
182182
<Compile Include="ErrorMessages\ModuleTests.fs" />
@@ -192,7 +192,7 @@
192192
<Compile Include="ErrorMessages\Repro1548.fs" />
193193
<Compile Include="ErrorMessages\WarnIfDiscardedInList.fs" />
194194
<Compile Include="ErrorMessages\UnionCasePatternMatchingErrors.fs" />
195-
<Compile Include="ErrorMessages\InterfaceImplInAugmentationsTests.fs" />
195+
<Compile Include="ErrorMessages\InterfaceImplInAugmentationsTests.fs" />
196196
<Compile Include="ErrorMessages\ExtendedDiagnosticDataTests.fs" />
197197
<Compile Include="Language\IndexerSetterParamArray.fs" />
198198
<Compile Include="Language\MultiDimensionalArrayTests.fs" />
@@ -226,6 +226,7 @@
226226
<Compile Include="Interop\RequiredAndInitOnlyProperties.fs" />
227227
<Compile Include="Interop\StaticsInInterfaces.fs" />
228228
<Compile Include="Interop\VisibilityTests.fs" />
229+
<Compile Include="Interop\ByrefTests.fs" />
229230
<Compile Include="Scripting\Interactive.fs" />
230231
<Compile Include="TypeChecks\SeqTypeCheckTests.fs" />
231232
<Compile Include="TypeChecks\CheckDeclarationsTests.fs" />
@@ -324,5 +325,5 @@
324325
<ItemGroup Condition="'$(FSHARPCORE_USE_PACKAGE)' == 'true'">
325326
<PackageReference Include="FSharp.Core" Version="$(FSharpCoreShippedPackageVersionValue)" />
326327
</ItemGroup>
327-
328+
328329
</Project>
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information.
2+
3+
namespace Interop
4+
5+
open FSharp.Test
6+
open FSharp.Test.Compiler
7+
8+
module ``Byref interop verification tests`` =
9+
10+
[<FactForNETCOREAPP>]
11+
let ``Test that ref readonly is treated as inref`` () =
12+
13+
FSharp """
14+
module ByrefTest
15+
open System.Runtime.CompilerServices
16+
type MyRecord = { Value : int } with
17+
member this.SetValue(v: int) = (Unsafe.AsRef<int> &this.Value) <- v
18+
19+
let check mr =
20+
if mr.Value <> 1 then
21+
failwith "Value should be 1"
22+
23+
mr.SetValue(42)
24+
25+
if mr.Value <> 42 then
26+
failwith $"Value should be 42, but is {mr.Value}"
27+
0
28+
29+
[<EntryPoint>]
30+
let main _ =
31+
let mr = { Value = 1 }
32+
check mr
33+
"""
34+
|> asExe
35+
|> compileAndRun
36+
|> shouldSucceed
37+
38+
[<FactForNETCOREAPP>]
39+
let ``Test that ref readonly is treated as inref for ROS .ctor`` () =
40+
FSharp """
41+
module Foo
42+
open System
43+
44+
45+
[<EntryPoint>]
46+
let main _ =
47+
let mutable bt: int = 42
48+
let ros = ReadOnlySpan<int>(&bt)
49+
50+
if ros.Length <> 1 || ros[0] <> 42 then
51+
failwith "Unexpected result"
52+
0
53+
"""
54+
|> asExe
55+
|> compileAndRun
56+
|> shouldSucceed

0 commit comments

Comments
 (0)