-
Notifications
You must be signed in to change notification settings - Fork 789
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
typeof doesn't work with ref struct types. #10426
Comments
This is by design, since this kind of operation requires boxing. You'll notice that if you try |
No, I'm not talking about I am talking about the The compiler should special-case |
Moreover, in C#, calling |
@dsyme, @vzarytovskii should we reopen this? |
If C# allows it, I think it makes sense to allow it as well |
@vzarytovskii I agree. As mentioned, this is |
Let me re-open. |
This has bitten me when doing Expression trees. I need to be able to locate a op_Implicit that converts Span into ReadOnlySpan. open System.Linq.Expressions
let convertSpanToReadOnlySpan (expr:Expression) =
if expr.Type = typeof<System.ReadOnlySpan<byte>> then expr
elif expr.Type = typeof<System.Span<byte>> then
let mi = typeof<System.Span<byte>>.GetMethod("op_Implicit",[| typeof<System.Span<byte>> |])
Expression.Call(mi,expr)
else
failwith "the expr is not Span<byte> or ReadOnlySpan<byte>"
Every one of the typeof operators is showing error FS0412: A type instantiation involves a byref type. This is not permitted by the rules of Common IL. Has any work on this been done yet? This is almost a year ago now since re-opening. It also causes an issue for something like this as well: /// this is a really nice little function for find and creating the appropriate op_Implicit to convert expr into the 'Out type
let opImplicit<'Out> (expr:Expression) =
let mi = expr.Type.GetMethod("op_Implicit",[|expr.Type|])
if mi.ReturnType = typeof<'Out> then
Expression.Call(mi,expr)
else
let mi = typeof<'Out>.GetMethod("op_Implicit",[|expr.Type|])
if mi.ReturnType = typeof<'Out> then
Expression.Call(mi,expr)
else
failwith $"no op_Implicit operator exists to convert {expr.Type} to {typeof<'Out>}"
//This works but its ridculous since I can't use the op_Implicit I defined above
Expression.Constant(Array.init 16 byte)
|> fun buff ->
let mi =
typeof<System.MemoryExtensions>.GetMethods()//("AsSpan",1,[|System.Type.MakeGenericMethodParameter(0)|])
|> Seq.filter (fun mi -> mi.Name = "AsSpan" && mi.IsGenericMethod && (let p = mi.GetParameters() in p.Length = 1 && (p[0]).ParameterType.IsArray))
|> Seq.head
let mi' = mi.MakeGenericMethod(typeof<byte>)
Expression.Call(mi',buff)
|> fun asspan ->
//opImplicit<System.ReadOnlySpan<byte>> asspan /// I'd like to be able to do this but I can't
asspan.Type.GetMethods()
|> Seq.filter (fun mi -> mi.Name = "op_Implicit")
|> Seq.filter (fun mi -> mi.ReturnType.Name = "ReadOnlySpan`1")
|> Seq.head
|> fun mi ->
Expression.Call(mi,asspan)
|> fun readonlyspan ->
let mi =
typeof<System.BitConverter>.GetMethods()
|> Seq.filter (fun mi -> mi.Name = "ToInt32") // I have to do this because typeof<System.ReadOnlySpan<byte>> doesn't work
|> Seq.filter (fun mi -> let p = mi.GetParameters() in p.Length = 1 && p[0].ParameterType.Name = "ReadOnlySpan`1") // I have to do this because typeof<System.ReadOnlySpan<byte>> doesn't work
|> Seq.head
Expression.Call(mi,readonlyspan)
|> fun convertToDouble ->
Expression.Lambda<System.Func<int>>(convertToDouble).Compile().Invoke()
I'd be willing to work on this, if someone could point me to the section of the compiler that this issue would be in. Thanks, |
@patrickallensimpson Looking at the error number and its usage. I think a good place to start will be here inside of Happy to help you to get started if you are interested . |
The title is quite descriptive. Try running
typeof<System.ReadOnlySpan<int>>;;
in FSI to reproduce.It will fail with
error FS0412: A type instantiation involves a byref type. This is not permitted by the rules of Common IL.
Tested with .NET 5's
dotnet fsi
.The text was updated successfully, but these errors were encountered: