Where is the "undefined type"?
I define the following type extension:
type System.Reflection.MemberInfo with
member x.GetAttribute<'T when 'T :> Attribute>(required, inherit') =
match required, Attribute.GetCustomAttribute(x, typeof<'T>, inherit') with
| true, null -> invalidOp (sprintf "Missing required attribute: %s" typeof<'T>.FullName)
| _, attr -> attr :> 'T
The last match expression ( attr :> 'T
) gives an error:
Static coercion from an attribute to 'T includes an undefined type based on information up to that point in the program. Static coercion is not allowed on some types. Additional type annotations are required.
I tried annotating the return type of the function but got the same result. I would hate to change this to a dynamic cast. Is there a way to make it work static?
a source to share
It should be dynamic, right? You have an object that is of a static type System.Attribute
and you want to cast it to an actual concrete type.
open System
type System.Reflection.MemberInfo with
member x.GetAttribute<'T when 'T :> Attribute>(required, inherit') = // '
match required, Attribute.GetCustomAttribute(x, typeof<'T>, inherit') with
| true, null -> invalidOp (
sprintf "Missing required attribute: %s" typeof<'T>.FullName) // '
| _, attr -> attr :?> 'T
a source to share
To clarify the meaning of the error message - the compiler makes the difference between static casting :>
(which is always safe, like casting from Random
to Object
) and dynamic pushing :?>
(which can crash).
In your case, you need to use dynamic cast. This is what the compiler means:
-
It says that "static coercion from an attribute to
'T
is associated with an undefined type." This means that it doesn't know (at compile time) what the actual type is being used instead of the generic parameter'T
. -
As a result, the compiler cannot check if the conversion from
Attribute
to will always be performed'T
(which is required in the case of static coercion). If, for example, the compiler has determined that the type'T
will always beObject
, then the use of static coercion will be valid.
a source to share
Corrected code in case anyone needs it (Brian's code is right too ... I just prefer type annotation in signature):
type System.Reflection.MemberInfo with
member x.GetAttribute<'T when 'T :> Attribute>(required, inherit') : 'T =
match required, Attribute.GetCustomAttribute(x, typeof<'T>, inherit') with
| true, null -> invalidOp (sprintf "Missing required attribute: %s" typeof<'T>.FullName)
| _, attr -> downcast attr
a source to share