Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions docs/release-notes/.FSharp.Compiler.Service/11.0.100.md
Original file line number Diff line number Diff line change
Expand Up @@ -164,13 +164,14 @@
* Support for the `<include>` XML documentation tag: at compile time, documentation is copied from an external XML file selected by an XPath query and emitted into the generated documentation file. `<inheritdoc>` remains unsupported. ([Issue #19175](https://github.com/dotnet/fsharp/issues/19175), [PR #19186](https://github.com/dotnet/fsharp/pull/19186))
* Expand `<inheritdoc/>` at tooling time. In IDE tooltips, completion, and signature help, documentation is inherited from base classes, interfaces, overridden members, and constructors (matched by parameter signature). The FCS Symbols API (`FSharpSymbol.XmlDoc`) additionally resolves explicit `cref` targets, but does not expand constructor inheritance. The compiler emits the tag verbatim into generated XML documentation files, matching C#; `<include>` is not implemented. ([Issue #19175](https://github.com/dotnet/fsharp/issues/19175), [PR #19188](https://github.com/dotnet/fsharp/pull/19188))
* Add symbol and type highlighting to F# diagnostics ([PR #20097](https://github.com/dotnet/fsharp/pull/20097))
* IL: add `ILPreNamespace`, make `ILPreTypeDef` creation lazy ([PR #20092](https://github.com/dotnet/fsharp/pull/20092))
* IL: use empty tables for members when possible ([PR #20249](https://github.com/dotnet/fsharp/pull/20249))

### Improved

* Nullness warning FS3261 on dotted method or property access (e.g. `x.Member`) now underlines the receiver expression and includes the member name and (when known) the binding name in the message. ([Issue #19658](https://github.com/dotnet/fsharp/issues/19658), [PR #19814](https://github.com/dotnet/fsharp/pull/19814))
* Direct delegate construction ([PR ##19993](https://github.com/dotnet/fsharp/pull/19993))
* IL: add `ILPreNamespace`, make `ILPreTypeDef` creation lazy ([PR #20092](https://github.com/dotnet/fsharp/pull/20092))
* IL: share ILCallingConv instances ([PR #20254](https://github.com/dotnet/fsharp/pull/20254)
* IL: use empty tables for members when possible ([PR #20249](https://github.com/dotnet/fsharp/pull/20249))

### Changed

Expand Down
48 changes: 48 additions & 0 deletions src/Compiler/AbstractIL/il.fs
Original file line number Diff line number Diff line change
Expand Up @@ -683,6 +683,9 @@ type ILCallingConv =

static member Static = ILCallingConvStatics.Static

static member Create(thisConv, argConv) =
ILCallingConvStatics.Get(thisConv, argConv)

override x.ToString() =
if x.IsStatic then "static" else "instance"

Expand All @@ -693,10 +696,55 @@ and ILCallingConvStatics() =

static let staticCallConv = Callconv(ILThisConvention.Static, ILArgConvention.Default)

/// Every combination, so that reading metadata never allocates a calling convention. The two
/// common ones above are placed in the table too, so all uses share one instance per combination.
static let allCallConvs =
let thisConvs =
[|
ILThisConvention.Instance
ILThisConvention.InstanceExplicit
ILThisConvention.Static
|]

let argConvs =
[|
ILArgConvention.Default
ILArgConvention.CDecl
ILArgConvention.StdCall
ILArgConvention.ThisCall
ILArgConvention.FastCall
ILArgConvention.VarArg
|]

Array.init (thisConvs.Length * argConvs.Length) (fun i ->
match thisConvs[i / argConvs.Length], argConvs[i % argConvs.Length] with
| ILThisConvention.Instance, ILArgConvention.Default -> instanceCallConv
| ILThisConvention.Static, ILArgConvention.Default -> staticCallConv
| thisConv, argConv -> Callconv(thisConv, argConv))

static member Instance = instanceCallConv

static member Static = staticCallConv

static member Get(thisConv, argConv) =
// Explicit, so adding a case to either union is a compile error here rather than a bad index.
let thisIdx =
match thisConv with
| ILThisConvention.Instance -> 0
| ILThisConvention.InstanceExplicit -> 1
| ILThisConvention.Static -> 2

let argIdx =
match argConv with
| ILArgConvention.Default -> 0
| ILArgConvention.CDecl -> 1
| ILArgConvention.StdCall -> 2
| ILArgConvention.ThisCall -> 3
| ILArgConvention.FastCall -> 4
| ILArgConvention.VarArg -> 5

allCallConvs[thisIdx * 6 + argIdx]

type ILBoxity =
| AsObject
| AsValue
Expand Down
15 changes: 10 additions & 5 deletions src/Compiler/AbstractIL/il.fsi
Original file line number Diff line number Diff line change
Expand Up @@ -175,17 +175,22 @@ type ILThisConvention =

[<StructuralEquality; StructuralComparison>]
type ILCallingConv =
private
| Callconv of ILThisConvention * ILArgConvention

member internal IsInstance: bool
member internal IsInstanceExplicit: bool
member internal IsStatic: bool
member internal ThisConv: ILThisConvention
member internal BasicConv: ILArgConvention
member IsInstance: bool
member IsInstanceExplicit: bool
member IsStatic: bool
member ThisConv: ILThisConvention
member BasicConv: ILArgConvention

static member Instance: ILCallingConv
static member Static: ILCallingConv

/// Returns the shared instance for this combination. Since the representation is private and there
/// are only 18 combinations, no calling convention is ever allocated per method signature.
static member Create: ILThisConvention * ILArgConvention -> ILCallingConv

/// Array shapes. For most purposes the rank is the only thing that matters.
type internal ILArrayBound = int32 option

Expand Down
6 changes: 3 additions & 3 deletions src/Compiler/AbstractIL/ilpars.fsy
Original file line number Diff line number Diff line change
Expand Up @@ -189,11 +189,11 @@ typSpec:

callConv:
INSTANCE callKind
{ Callconv (ILThisConvention.Instance,$2) }
{ ILCallingConv.Create (ILThisConvention.Instance,$2) }
| EXPLICIT callKind
{ Callconv (ILThisConvention.InstanceExplicit,$2) }
{ ILCallingConv.Create (ILThisConvention.InstanceExplicit,$2) }
| callKind
{ Callconv (ILThisConvention.Static,$1) }
{ ILCallingConv.Create (ILThisConvention.Static,$1) }

callKind:
/* EMPTY */
Expand Down
6 changes: 3 additions & 3 deletions src/Compiler/AbstractIL/ilprint.fs
Original file line number Diff line number Diff line change
Expand Up @@ -365,15 +365,15 @@ and output_bcc os bcc =
| ILArgConvention.Default -> " "
| ILArgConvention.VarArg -> "vararg ")

and output_callconv os (Callconv(hasthis, cc)) =
and output_callconv os (callconv: ILCallingConv) =
output_string
os
(match hasthis with
(match callconv.ThisConv with
| ILThisConvention.Instance -> "instance "
| ILThisConvention.InstanceExplicit -> "explicit "
| ILThisConvention.Static -> "")

output_bcc os cc
output_bcc os callconv.BasicConv

and goutput_dlocref env os (dref: ILType) =
match dref with
Expand Down
2 changes: 1 addition & 1 deletion src/Compiler/AbstractIL/ilread.fs
Original file line number Diff line number Diff line change
Expand Up @@ -2861,7 +2861,7 @@ and byteAsCallConv b =
ILArgConvention.Default

let generic = (b &&& e_IMAGE_CEE_CS_CALLCONV_GENERIC) <> 0x0uy
generic, Callconv(byteAsHasThis b, cc)
generic, ILCallingConv.Create(byteAsHasThis b, cc)

and seekReadMemberRefAsMethodData ctxt numTypars idx : VarArgMethodData =
ctxt.seekReadMemberRefAsMethodData (MemberRefAsMspecIdx(numTypars, idx))
Expand Down
6 changes: 3 additions & 3 deletions src/Compiler/AbstractIL/ilreflect.fs
Original file line number Diff line number Diff line change
Expand Up @@ -694,15 +694,15 @@ let envPopEntryPts emEnv =
// convCallConv
//----------------------------------------------------------------------------

let convCallConv (Callconv(hasThis, basic)) =
let convCallConv (callConv: ILCallingConv) =
let ccA =
match hasThis with
match callConv.ThisConv with
| ILThisConvention.Static -> CallingConventions.Standard
| ILThisConvention.InstanceExplicit -> CallingConventions.ExplicitThis
| ILThisConvention.Instance -> CallingConventions.HasThis

let ccB =
match basic with
match callConv.BasicConv with
| ILArgConvention.Default -> enum 0
| ILArgConvention.CDecl -> enum 0
| ILArgConvention.StdCall -> enum 0
Expand Down
6 changes: 3 additions & 3 deletions src/Compiler/AbstractIL/ilwrite.fs
Original file line number Diff line number Diff line change
Expand Up @@ -838,10 +838,10 @@ let hasthisToByte hasthis =
| ILThisConvention.InstanceExplicit -> e_IMAGE_CEE_CS_CALLCONV_INSTANCE_EXPLICIT
| ILThisConvention.Static -> 0x00uy

let callconvToByte ntypars (Callconv (hasthis, bcc)) =
hasthisToByte hasthis |||
let callconvToByte ntypars (callconv: ILCallingConv) =
hasthisToByte callconv.ThisConv |||
(if ntypars > 0 then e_IMAGE_CEE_CS_CALLCONV_GENERIC else 0x00uy) |||
(match bcc with
(match callconv.BasicConv with
| ILArgConvention.FastCall -> e_IMAGE_CEE_CS_CALLCONV_FASTCALL
| ILArgConvention.StdCall -> e_IMAGE_CEE_CS_CALLCONV_STDCALL
| ILArgConvention.ThisCall -> e_IMAGE_CEE_CS_CALLCONV_THISCALL
Expand Down
6 changes: 3 additions & 3 deletions src/Compiler/TypedTree/TypedTreePickle.fs
Original file line number Diff line number Diff line change
Expand Up @@ -1285,8 +1285,8 @@ and p_ILBasicCallConv x st =
| ILArgConvention.VarArg -> 5)
st

and p_ILCallConv (Callconv(x, y)) st =
p_tup2 p_ILHasThis p_ILBasicCallConv (x, y) st
and p_ILCallConv (x: ILCallingConv) st =
p_tup2 p_ILHasThis p_ILBasicCallConv (x.ThisConv, x.BasicConv) st

and p_ILCallSig x st =
p_tup3 p_ILCallConv p_ILTypes p_ILType (x.CallingConv, x.ArgTypes, x.ReturnType) st
Expand Down Expand Up @@ -1316,7 +1316,7 @@ let u_ILHasThis st =

let u_ILCallConv st =
let a, b = u_tup2 u_ILHasThis u_ILBasicCallConv st
Callconv(a, b)
ILCallingConv.Create(a, b)

let u_ILTypeRef st =
let a, b, c = u_tup3 u_ILScopeRef u_strings u_string st
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -319,22 +319,26 @@ FSharp.Compiler.AbstractIL.IL+ILCallingConv: Boolean Equals(ILCallingConv)
FSharp.Compiler.AbstractIL.IL+ILCallingConv: Boolean Equals(ILCallingConv, System.Collections.IEqualityComparer)
FSharp.Compiler.AbstractIL.IL+ILCallingConv: Boolean Equals(System.Object)
FSharp.Compiler.AbstractIL.IL+ILCallingConv: Boolean Equals(System.Object, System.Collections.IEqualityComparer)
FSharp.Compiler.AbstractIL.IL+ILCallingConv: ILArgConvention Item2
FSharp.Compiler.AbstractIL.IL+ILCallingConv: ILArgConvention get_Item2()
FSharp.Compiler.AbstractIL.IL+ILCallingConv: Boolean IsInstance
FSharp.Compiler.AbstractIL.IL+ILCallingConv: Boolean IsInstanceExplicit
FSharp.Compiler.AbstractIL.IL+ILCallingConv: Boolean IsStatic
FSharp.Compiler.AbstractIL.IL+ILCallingConv: Boolean get_IsInstance()
FSharp.Compiler.AbstractIL.IL+ILCallingConv: Boolean get_IsInstanceExplicit()
FSharp.Compiler.AbstractIL.IL+ILCallingConv: Boolean get_IsStatic()
FSharp.Compiler.AbstractIL.IL+ILCallingConv: ILArgConvention BasicConv
FSharp.Compiler.AbstractIL.IL+ILCallingConv: ILArgConvention get_BasicConv()
FSharp.Compiler.AbstractIL.IL+ILCallingConv: ILCallingConv Create(ILThisConvention, ILArgConvention)
FSharp.Compiler.AbstractIL.IL+ILCallingConv: ILCallingConv Instance
FSharp.Compiler.AbstractIL.IL+ILCallingConv: ILCallingConv NewCallconv(ILThisConvention, ILArgConvention)
FSharp.Compiler.AbstractIL.IL+ILCallingConv: ILCallingConv Static
FSharp.Compiler.AbstractIL.IL+ILCallingConv: ILCallingConv get_Instance()
FSharp.Compiler.AbstractIL.IL+ILCallingConv: ILCallingConv get_Static()
FSharp.Compiler.AbstractIL.IL+ILCallingConv: ILThisConvention Item1
FSharp.Compiler.AbstractIL.IL+ILCallingConv: ILThisConvention get_Item1()
FSharp.Compiler.AbstractIL.IL+ILCallingConv: ILThisConvention ThisConv
FSharp.Compiler.AbstractIL.IL+ILCallingConv: ILThisConvention get_ThisConv()
FSharp.Compiler.AbstractIL.IL+ILCallingConv: Int32 CompareTo(ILCallingConv)
FSharp.Compiler.AbstractIL.IL+ILCallingConv: Int32 CompareTo(System.Object)
FSharp.Compiler.AbstractIL.IL+ILCallingConv: Int32 CompareTo(System.Object, System.Collections.IComparer)
FSharp.Compiler.AbstractIL.IL+ILCallingConv: Int32 GetHashCode()
FSharp.Compiler.AbstractIL.IL+ILCallingConv: Int32 GetHashCode(System.Collections.IEqualityComparer)
FSharp.Compiler.AbstractIL.IL+ILCallingConv: Int32 Tag
FSharp.Compiler.AbstractIL.IL+ILCallingConv: Int32 get_Tag()
FSharp.Compiler.AbstractIL.IL+ILCallingConv: System.String ToString()
FSharp.Compiler.AbstractIL.IL+ILCallingSignature: Boolean Equals(ILCallingSignature)
FSharp.Compiler.AbstractIL.IL+ILCallingSignature: Boolean Equals(ILCallingSignature, System.Collections.IEqualityComparer)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ module ModuleReader =
MethodAttributes.NewSlot |||
MethodAttributes.SpecialName

let callingConv = Callconv(ILThisConvention.Instance, ILArgConvention.Default)
let callingConv = ILCallingConv.Instance
let parameters = []
let ret = mkILReturn ILType.Void
let genericParams = []
Expand Down
Loading