Static arguments for type providers cannot be of type "obj"
- Dominant language
- F#
- Stars
- 4.3k
- Forks
- 876
- Avg merge
- 4d 11h
- Merged PRs (30d)
- 131
Description
A static parameter for a provided type that has the type `obj` (or any other type that is not a direct type of a constant expression that does not involve upcasting) cannot ever be given an explicit value.
**Repro steps**
```fs
namespace Providers
open ProviderImplementation.ProvidedTypes
open FSharp.Core.CompilerServices
open System.Reflection
[]do()
[]
type public ConstantTypeProvider(config) as this =
inherit TypeProviderForNamespaces(config)
do
let param = ProvidedStaticParameter("value", typeof);
let thisAssembly = Assembly.GetExecutingAssembly()
let namespaceName = typeof.Namespace
let definition = ProvidedTypeDefinition(thisAssembly, namespaceName, "Const", Some typeof)
let makeType (typeName: string) (parameterValues: obj array) =
let definition = ProvidedTypeDefinition(thisAssembly, namespaceName, typeName, Some typeof)
let value = parameterValues[0]
//failwith (sprintf "%A" parameterValues[0])
definition.AddMember(ProvidedField.Literal("Value", value.GetType(), value))
this.AddNamespace(namespaceName, [definition])
definition
definition.DefineStaticParameters([param], makeType)
this.AddNamespace(namespaceName, [definition])
```
```fs
[]
let v = Providers.Const.Value
printf "%A" v
```
**Expected behavior**
The program should compile and "2" should be printed.
**Actual behavior**
```
error FS3047: Unknown static argument kind 'System.Object' when resolving a reference to a provided type or method 'Const,value="2"'
error FS1109: A reference to the type 'Providers.Const,value="2"' in assembly 'Providers' was found, but the type could not be found in that assembly
```
**Known workarounds**
I am not aware of any workarounds that could produce a provided type based on a constant expression of an arbitrary type.
**Related information**
This or a similar issue prevents the following static arguments from being accepted:
* const (expr:obj).
* Same but with `ValueType`, `Enum` or any less specific type than those permitted by constant expressions, or, in general, const (upcast expr) when the static parameter has a less specific type.
* `null` (any type).
I am led to believe that this is a bug for the following reasons:
* The specification does not seem to mention any restriction on the types of static arguments, so I presume it should be able to be anything that can be given to `ApplyStaticArguments`.
* *Implicit* arguments (those where the parameter is optional and no value is given) work fine and the value is correctly passed to `ApplyStaticArguments` (although *any* type works there).
* `ApplyStaticArguments` is actually still called here, even with the errors. This can be verified by uncommenting `failwith` and observing that "2" is thrown.
* There are other contexts where constant expressions can be treated as `obj`, such as in custom attributes.
From what I can tell, at least a part of the issue is caused [here](https://github.com/dotnet/fsharp/blob/2ea701e432b2d55332bbc1852416c99c34bcab2d/src/Compiler/TypedTree/TypeProviders.fs#L1410), where the type is hard-checked against a list of concrete types.
Being able to accept a type argument of an arbitrary type can have all sorts of nice use cases, from specifying values in queries, formatting, hashing, serialization, or other operations on constant expressions.
[FSharpObjectConstExample.zip](https://github.com/user-attachments/files/18792617/FSharpObjectConstExample.zip)
Contributor guide
Assessment
This issue has not been assessed yet.