Skip to content

Unable to generate obsolete methods from generative TP #70

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

Closed
sergey-tihon opened this issue Jan 18, 2016 · 2 comments
Closed

Unable to generate obsolete methods from generative TP #70

sergey-tihon opened this issue Jan 18, 2016 · 2 comments

Comments

@sergey-tihon
Copy link
Member

Seems that generative TP cannot produce methods with Obsolete attribute

Here is the simple generative type provider that provide single static method

module ObsoleteProvider

open System.Reflection
open ProviderImplementation.ProvidedTypes
open Microsoft.FSharp.Core.CompilerServices
open Microsoft.FSharp.Quotations

[<TypeProvider>]
type public ObsoleteProvider (cfg : TypeProviderConfig) as this =
    inherit TypeProviderForNamespaces ()

    let ns = "Bug"
    let asm = Assembly.GetExecutingAssembly()
    let tempAsmPath = System.IO.Path.ChangeExtension(System.IO.Path.GetTempFileName(), ".dll")
    let tempAsm = ProvidedAssembly tempAsmPath

    let t = ProvidedTypeDefinition(asm, ns, "Obsolete", Some typeof<obj>, IsErased = false)
    let parameters = [ProvidedStaticParameter("temp", typeof<string>)]

    do
        t.DefineStaticParameters(
            parameters,
            fun typeName args ->
                let g = ProvidedTypeDefinition(asm, ns, typeName, Some typeof<obj>, IsErased = false)

                let m = ProvidedMethod("Call",[], typeof<int>, IsStaticMethod = true)
                m.InvokeCode <- fun args -> <@@3@@>
                //m.AddObsoleteAttribute("Deprecated", false)
                g.AddMember m

                tempAsm.AddTypes [g]

                g
            )

    do
        this.RegisterRuntimeAssemblyLocationAsProbingFolder cfg
        tempAsm.AddTypes [t]
        this.AddNamespace(ns, [t])

[<assembly:TypeProviderAssembly>]
do ()

If I execute simple usage script

#r "ObsoleteTypeProvider.dll"
type T = Bug.Obsolete<"">
T.Call()

I receive output as expected

type T =
class
static member Call : unit -> int
end
val it : int = 3

But If I uncomment line m.AddObsoleteAttribute("Deprecated", false) and execute the same script I receive

demo.fsx(2,10): error FS3033: The type provider 'ObsoleteProvider+ObsoleteProvider' reported an error: Parameter count does not match passed in argument value count.

//cc @dsyme @dmitry-a-morozov @mavnn @ovatsus @pezipink

@dsyme
Copy link
Contributor

dsyme commented Jan 20, 2016

Could you check if the generative DLL is produced correctly by the type provider? Or find the exception stacktrace? The bug could be in codegen in this repo, or perhaps the F# compiler. May require a bit of type provider debugging work to grab the dll from temp storage.

@sergey-tihon
Copy link
Member Author

Exception occurs on this line https://github.com/fsprojects/FSharp.TypeProviders.StarterPack/blob/master/src/ProvidedTypes.fs#L1841

StackTrace:

at System.Reflection.Emit.CustomAttributeBuilder.InitCustomAttributeBuilder(ConstructorInfo con, Object[] constructorArgs, PropertyInfo[] namedProperties, Object[] propertyValues, FieldInfo[] namedFields, Object[] fieldValues)

Seems like we are trying to call wrong ObsoleteAttribute constructor (that has one param)
image
with two arguments
image

Sooo, probably here
https://github.com/fsprojects/FSharp.TypeProviders.StarterPack/blob/master/src/ProvidedTypes.fs#L137
should be

typeof<System.ObsoleteAttribute>.GetConstructors()
|> Array.find (fun x -> x.GetParameters().Length = 2)

instead of

typeof<System.ObsoleteAttribute>.GetConstructors()
|> Array.find (fun x -> x.GetParameters().Length = 1)

because ConstructorArguments always has two arguments

 member __.ConstructorArguments = 
    upcast [|CustomAttributeTypedArgument(typeof<string>, message) ;             
             CustomAttributeTypedArgument(typeof<bool>, isError)  |]

sergey-tihon added a commit that referenced this issue Jan 20, 2016

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
Fix for #70
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants