Skip to content
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

Extension method on byref can mutate an immutable value #5355

Closed
cartermp opened this issue Jul 19, 2018 · 6 comments
Closed

Extension method on byref can mutate an immutable value #5355

cartermp opened this issue Jul 19, 2018 · 6 comments
Labels
Milestone

Comments

@cartermp
Copy link
Contributor

Consider the following F# code:

open System
open System.Runtime.CompilerServices

[<Extension>]
type Ext() =
    [<Extension>]
    static member inline Change(dt: byref<DateTime>) = dt <- DateTime.Now

let f() =
    let dt = DateTime.Now
    printfn "%d" dt.Ticks
    
    let dtRef = &dt
    
    dtRef.Change()
    printfn "%d" dt.Ticks

    dtRef.Change()
    printfn "%d" dt.Ticks

    dtRef.Change()
    printfn "%d" dt.Ticks

[<EntryPoint>]
let main argv =
    f()
    0 // return an integer exit code

Executing with ctrl-f5:

636676140835468566
636676140835876165
636676140835877191
636676140835878063
@cartermp
Copy link
Contributor Author

cartermp commented Jul 19, 2018

Note that this can also be done with reference types:

open System
open System.Runtime.CompilerServices

[<Extension>]
type Ext() =
    [<Extension>]
    static member inline Change(s: byref<string>) = s <-"Hoopty"

let f() =
    let s = "beef"
    printfn "%s" s
    
    let dtRef = &s
    
    dtRef.Change()
    printfn "%s" s

    dtRef.Change()
    printfn "%s" s

    dtRef.Change()
    printfn "%s" s

[<EntryPoint>]
let main argv =
    f()
    0 // return an integer exit code

Gives

beef
Hoopty
Hoopty
Hoopty

@cartermp cartermp added this to the 15.9 milestone Jul 19, 2018
@TIHan TIHan self-assigned this Jul 19, 2018
@TIHan
Copy link
Member

TIHan commented Jul 19, 2018

Highly aware of this. Looking into it.

@zpodlovics
Copy link

zpodlovics commented Jul 20, 2018

I guess this is the same or similar problem as the this <- v whole structs replacement here:
fsharp/fslang-design#287 (comment)

Please do not disallow byref access to immutable/read-only structures, as it used for performance critical work (if I remember correctly the readonly/immutable byref changed to inref<'T> to fix this).

@TIHan
Copy link
Member

TIHan commented Jul 20, 2018

@zpodlovics it looks like it is similar, but those are referring to instance members.

I think I know what's happening in the compiler, but it needs more investigation. Basically on calls like this we lose information that it was a byref or a inref; it only compares the destination type of the byref.

@TIHan
Copy link
Member

TIHan commented Jul 31, 2018

I have a fix for this coming soon.

@TIHan
Copy link
Member

TIHan commented Aug 8, 2018

Resolved.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants