I cannot really explain why the compiler emits this warning in your particular case - I agree with @ildjarn that you can safely ignore it, because the compiler is probably just being overly cautious.
However, I can give you an example where the warning might actually give you a useful hint that something might not go as you would expect. If we had a mutable struct
like this:
[<Struct>]
type Test =
val mutable ticks : int64
member x.Inc() = x.ticks <- x.ticks + 1L
new (init) = { ticks = init }
Now, the Inc
method mutates the struct (and you can also access the mutable field ticks
). We can try writing a function that creates a Test
value and mutates it:
let foo () =
let t = Test(1L)
t.Inc() // Warning: The value has been copied to ensure the original is not mutated
t
We did not mark the local value t
as mutable
, so the compiler tries to make sure the value is not mutated when we call Inc
. It does not know whether Inc
mutates the value or not, so the only safe thing is to create a copy - and thus foo
returns the value Test(1L)
.
If we mark t
as mutable
, then the compiler does not have to worry about mutating it as a result of a call and so it does not give the warning (and the function returns Test(2L)
):
let foo () =
let mutable t = Test(1L)
t.Inc()
t
I'm not really sure what is causing the warning in your example though. Perhaps the compiler thinks (as a result of some intermediate representation) that Ticks
operation could mutate the left-hand-side value (System.DateTime.Now
and t
respectively) and it wants to prevent that.
The odd thing is that if you write your own DateTime
struct in F#, you get a warning in both cases unless you mark the variable t
as mutable
(which is what I'd expect), but the behaviour with standard DateTime
is different. So perhaps the compiler knows something about the standard type that I'm missing...