diff --git a/eng/Versions.props b/eng/Versions.props
index 52f7368090..e0d9422182 100644
--- a/eng/Versions.props
+++ b/eng/Versions.props
@@ -15,7 +15,7 @@
80
- 100
+ 1010
diff --git a/src/Compiler/Checking/TypeHierarchy.fs b/src/Compiler/Checking/TypeHierarchy.fs
index f6949c707d..a778b516d9 100644
--- a/src/Compiler/Checking/TypeHierarchy.fs
+++ b/src/Compiler/Checking/TypeHierarchy.fs
@@ -355,8 +355,13 @@ let ImportILTypeFromMetadata amap m scoref tinst minst ilTy =
/// Read an Abstract IL type from metadata, including any attributes that may affect the type itself, and convert to an F# type.
let ImportILTypeFromMetadataWithAttributes amap m scoref tinst minst ilTy getCattrs =
let ty = RescopeAndImportILType scoref amap m (tinst@minst) ilTy
- // If the type is a byref and one of attributes from a return or parameter has IsReadOnly, then it's a inref.
- if isByrefTy amap.g ty && TryFindILAttribute amap.g.attrib_IsReadOnlyAttribute (getCattrs ()) then
+ // If the type is a byref and one of attributes from a return or parameter has
+ // - a `IsReadOnlyAttribute` - it's an inref
+ // - a `RequiresLocationAttribute` (in which case it's a `ref readonly`) which we treat as inref,
+ // latter is an ad-hoc fix for https://github.com/dotnet/runtime/issues/94317.
+ if isByrefTy amap.g ty
+ && (TryFindILAttribute amap.g.attrib_IsReadOnlyAttribute (getCattrs ())
+ || TryFindILAttribute amap.g.attrib_RequiresLocationAttribute (getCattrs ())) then
mkInByrefTy amap.g (destByrefTy amap.g ty)
else
ty
@@ -428,4 +433,3 @@ let FixupNewTypars m (formalEnclosingTypars: Typars) (tinst: TType list) (tpsori
let tprefInst = mkTyparInst formalEnclosingTypars tinst @ renaming
(tpsorig, tps) ||> List.iter2 (fun tporig tp -> tp.SetConstraints (CopyTyparConstraints m tprefInst tporig))
renaming, tptys
-
diff --git a/src/Compiler/TypedTree/TcGlobals.fs b/src/Compiler/TypedTree/TcGlobals.fs
index 01bd1a1283..301096d092 100755
--- a/src/Compiler/TypedTree/TcGlobals.fs
+++ b/src/Compiler/TypedTree/TcGlobals.fs
@@ -1423,6 +1423,7 @@ type TcGlobals(
member val attrib_ParamArrayAttribute = findSysAttrib "System.ParamArrayAttribute"
member val attrib_IDispatchConstantAttribute = tryFindSysAttrib "System.Runtime.CompilerServices.IDispatchConstantAttribute"
member val attrib_IUnknownConstantAttribute = tryFindSysAttrib "System.Runtime.CompilerServices.IUnknownConstantAttribute"
+ member val attrib_RequiresLocationAttribute = findSysAttrib "System.Runtime.CompilerServices.RequiresLocationAttribute"
// We use 'findSysAttrib' here because lookup on attribute is done by name comparison, and can proceed
// even if the type is not found in a system assembly.
diff --git a/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj b/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj
index 111ba0c94e..e533dc1654 100644
--- a/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj
+++ b/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj
@@ -29,7 +29,7 @@
FsUnit.fs
-
+
@@ -112,7 +112,7 @@
-
+
@@ -175,7 +175,7 @@
-
+
@@ -191,7 +191,7 @@
-
+
@@ -225,6 +225,7 @@
+
@@ -322,5 +323,5 @@
-
+
diff --git a/tests/FSharp.Compiler.ComponentTests/Interop/ByrefTests.fs b/tests/FSharp.Compiler.ComponentTests/Interop/ByrefTests.fs
new file mode 100644
index 0000000000..dca7589c90
--- /dev/null
+++ b/tests/FSharp.Compiler.ComponentTests/Interop/ByrefTests.fs
@@ -0,0 +1,56 @@
+// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information.
+
+namespace Interop
+
+open FSharp.Test
+open FSharp.Test.Compiler
+
+module ``Byref interop verification tests`` =
+
+ []
+ let ``Test that ref readonly is treated as inref`` () =
+
+ FSharp """
+ module ByrefTest
+ open System.Runtime.CompilerServices
+ type MyRecord = { Value : int } with
+ member this.SetValue(v: int) = (Unsafe.AsRef &this.Value) <- v
+
+ let check mr =
+ if mr.Value <> 1 then
+ failwith "Value should be 1"
+
+ mr.SetValue(42)
+
+ if mr.Value <> 42 then
+ failwith $"Value should be 42, but is {mr.Value}"
+ 0
+
+ []
+ let main _ =
+ let mr = { Value = 1 }
+ check mr
+ """
+ |> asExe
+ |> compileAndRun
+ |> shouldSucceed
+
+ []
+ let ``Test that ref readonly is treated as inref for ROS .ctor`` () =
+ FSharp """
+ module Foo
+ open System
+
+
+ []
+ let main _ =
+ let mutable bt: int = 42
+ let ros = ReadOnlySpan(&bt)
+
+ if ros.Length <> 1 || ros[0] <> 42 then
+ failwith "Unexpected result"
+ 0
+ """
+ |> asExe
+ |> compileAndRun
+ |> shouldSucceed
\ No newline at end of file