You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
type MyType<^T when ^T: (member o: int)> (t:^T) =
member inline this.T = t
Looks good in editor (no syntax error), but results
error FS1113: The value 'T' was marked inline but its implementation makes use of an internal or private function which is not sufficiently accessible
Is normal.
However
type MyType1<^T when ^T: (member o:int)> = {
t: ^T
}
with
member inline this.T = this.t
Provides very similar functionality, but working...
type MyType1<^T when ^T: (member o: int)> =
{ t: ^T }
member inline T: ^T
>
Excuse me, is anyone kind to tell what's the difference? Since according to the past investigation,
I found the underlying reason. The CLR that handles generics recognizes a number of [constraints](https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/generics/constraints-on-type-parameters), including type/interface constraints, but not explicit member constraints. The latter is a pure [F# thing](https://learn.microsoft.com/en-us/dotnet/fsharp/language-reference/generics/constraints). This means (now I am speculating) the compiler has to express it in IL by an interface constraint, and that can be done only if MyType is a "head type", i.e. statically known at compile time. These complications are also the reason why the F# Language Reference says that explicit member constraints are "not intended for common use".
I found an interesting stuff related to you investigation.
type a () =
member this.o x = x + 1
type A<'T> (t:'T) =
member val T = t
type MT<^T when ^T: (member o:int -> int)> (v:^T) =
inherit A<^T> (v)
module o =
let v = (MT<a> (a()) :> A<a>).T.o 1
In this case, the explicit member constraint successfully has been expressed it in IL by an interface constraint (successfully executed in fsi, SDK 9.0.103), And type ^T is NOT a "head type"... How do you think about this case?
I mean... maybe the following code snipets should be valid for F# itself (not related to CLR)
type MyType<'T when ^T: (member o: int)> (t:^T) =
member inline this.T = t
or
type MyType<'T when ^T: (member o: int)> (t:^T) =
member this.T = t
type WithBasedData<'T> (t:'T) =
member val _base = t
type MyType<^T when ^T: (member o: int)> (t:^T) =
inherit WithBasedData<'T>(t)
do
()
type MyType<^T when ^T: (member o: int)> with
member inline this.T = this._base
@ingted I missed the comment you made a month ago.
I am sorry, but this is now beyond my amateur knowledge of escape analysis and related type checking procedures.
But good that you found a workaround.
type O<'T when 'T:(member i:int)>(t:'T) as this =
[<DefaultValue>]
val mutable internalState : 'T
do
this.internalState <- t
type O<'T when 'T:(member i:int)> with
member inline this.i2 = this.internalState.i
Microsoft (R) F# Interactive version 15.2.402.0 for F# 10.0
Copyright (c) Microsoft Corporation. All Rights Reserved.
For help type #help;;
> type MyType<^T when ^T: (member o: int)> (t:^T) =
-
- member inline this.T = t;;
type MyType<^T when ^T: (member o: int)> =
new: t: ^T -> MyType<^T>
member inline T: ^T
Activity
ingted commentedon Mar 28, 2025
Hi @Martin521,
I found an interesting stuff related to you investigation.
In this case, the explicit member constraint successfully has been expressed it in IL by an interface constraint (successfully executed in fsi, SDK 9.0.103), And type ^T is NOT a "head type"... How do you think about this case?
I mean... maybe the following code snipets should be valid for F# itself (not related to CLR)
or
ingted commentedon Apr 23, 2025
If anyone come across here, I got the workaround:
Martin521 commentedon Apr 23, 2025
@ingted I missed the comment you made a month ago.
I am sorry, but this is now beyond my amateur knowledge of escape analysis and related type checking procedures.
But good that you found a workaround.
ingted commentedon May 1, 2025
A much quicker workaround:
No inherit required!!
ingted commentedon Oct 23, 2026