Skip to content

Commit

Permalink
RFC FS-1124 - Interfaces with static abstract methods (#13119)
Browse files Browse the repository at this point in the history
Co-authored-by: Don Syme <dsyme@users.noreply.github.com>
Co-authored-by: Don Syme <donsyme@fastmail.fm>
Co-authored-by: Petr Pokorny <petrpokorny@microsoft.com>
  • Loading branch information
4 people authored Aug 9, 2022
1 parent f8b56cb commit bdb6462
Show file tree
Hide file tree
Showing 154 changed files with 5,853 additions and 1,714 deletions.
4 changes: 2 additions & 2 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
"internalConsoleOptions": "neverOpen",
"suppressJITOptimizations": true,
"stopAtEntry": false,
"justMyCode": false,
"justMyCode": true,
"enableStepFiltering": true,
"symbolOptions": {
"searchMicrosoftSymbolServer": true,
Expand Down Expand Up @@ -73,7 +73,7 @@
"enabled": true
}
},
"justMyCode": false,
"justMyCode": true,
"enableStepFiltering": false,
}
]
Expand Down
38 changes: 22 additions & 16 deletions src/Compiler/AbstractIL/il.fs
Original file line number Diff line number Diff line change
Expand Up @@ -1370,7 +1370,7 @@ type ILInstr =

| I_call of ILTailcall * ILMethodSpec * ILVarArgs
| I_callvirt of ILTailcall * ILMethodSpec * ILVarArgs
| I_callconstraint of ILTailcall * ILType * ILMethodSpec * ILVarArgs
| I_callconstraint of callvirt: bool * ILTailcall * ILType * ILMethodSpec * ILVarArgs
| I_calli of ILTailcall * ILCallingSignature * ILVarArgs
| I_ldftn of ILMethodSpec
| I_newobj of ILMethodSpec * ILVarArgs
Expand Down Expand Up @@ -3410,9 +3410,6 @@ let mkNormalCall mspec = I_call(Normalcall, mspec, None)

let mkNormalCallvirt mspec = I_callvirt(Normalcall, mspec, None)

let mkNormalCallconstraint (ty, mspec) =
I_callconstraint(Normalcall, ty, mspec, None)

let mkNormalNewobj mspec = I_newobj(mspec, None)

/// Comment on common object cache sizes:
Expand Down Expand Up @@ -3822,18 +3819,24 @@ let mkILClassCtor impl =
let mk_ospec (ty: ILType, callconv, nm, genparams, formal_args, formal_ret) =
OverridesSpec(mkILMethRef (ty.TypeRef, callconv, nm, genparams, formal_args, formal_ret), ty)

let mkILGenericVirtualMethod (nm, access, genparams, actual_args, actual_ret, impl) =
let mkILGenericVirtualMethod (nm, callconv: ILCallingConv, access, genparams, actual_args, actual_ret, impl) =
let attributes =
convertMemberAccess access
||| MethodAttributes.CheckAccessOnOverride
||| (match impl with
| MethodBody.Abstract -> MethodAttributes.Abstract ||| MethodAttributes.Virtual
| _ -> MethodAttributes.Virtual)
||| (if callconv.IsInstance then
enum 0
else
MethodAttributes.Static)

ILMethodDef(
name = nm,
attributes =
(convertMemberAccess access
||| MethodAttributes.CheckAccessOnOverride
||| (match impl with
| MethodBody.Abstract -> MethodAttributes.Abstract ||| MethodAttributes.Virtual
| _ -> MethodAttributes.Virtual)),
attributes = attributes,
implAttributes = MethodImplAttributes.Managed,
genericParams = genparams,
callingConv = ILCallingConv.Instance,
callingConv = callconv,
parameters = actual_args,
ret = actual_ret,
isEntryPoint = false,
Expand All @@ -3842,8 +3845,11 @@ let mkILGenericVirtualMethod (nm, access, genparams, actual_args, actual_ret, im
body = notlazy impl
)

let mkILNonGenericVirtualMethod (nm, access, args, ret, impl) =
mkILGenericVirtualMethod (nm, access, mkILEmptyGenericParams, args, ret, impl)
let mkILNonGenericVirtualMethod (nm, callconv, access, args, ret, impl) =
mkILGenericVirtualMethod (nm, callconv, access, mkILEmptyGenericParams, args, ret, impl)

let mkILNonGenericVirtualInstanceMethod (nm, access, args, ret, impl) =
mkILNonGenericVirtualMethod (nm, ILCallingConv.Instance, access, args, ret, impl)

let mkILGenericNonVirtualMethod (nm, access, genparams, actual_args, actual_ret, impl) =
ILMethodDef(
Expand Down Expand Up @@ -4267,7 +4273,7 @@ let mkILDelegateMethods access (ilg: ILGlobals) (iltyp_AsyncCallback, iltyp_IAsy

let one nm args ret =
let mdef =
mkILNonGenericVirtualMethod (nm, access, args, mkILReturn ret, MethodBody.Abstract)
mkILNonGenericVirtualInstanceMethod (nm, access, args, mkILReturn ret, MethodBody.Abstract)

mdef.WithAbstract(false).WithHideBySig(true).WithRuntime(true)

Expand Down Expand Up @@ -5298,7 +5304,7 @@ and refsOfILInstr s x =
| I_callvirt (_, mr, varargs) ->
refsOfILMethodSpec s mr
refsOfILVarArgs s varargs
| I_callconstraint (_, tr, mr, varargs) ->
| I_callconstraint (_, _, tr, mr, varargs) ->
refsOfILType s tr
refsOfILMethodSpec s mr
refsOfILVarArgs s varargs
Expand Down
9 changes: 6 additions & 3 deletions src/Compiler/AbstractIL/il.fsi
Original file line number Diff line number Diff line change
Expand Up @@ -523,7 +523,7 @@ type internal ILInstr =
// Method call
| I_call of ILTailcall * ILMethodSpec * ILVarArgs
| I_callvirt of ILTailcall * ILMethodSpec * ILVarArgs
| I_callconstraint of ILTailcall * ILType * ILMethodSpec * ILVarArgs
| I_callconstraint of callvirt: bool * ILTailcall * ILType * ILMethodSpec * ILVarArgs
| I_calli of ILTailcall * ILCallingSignature * ILVarArgs
| I_ldftn of ILMethodSpec
| I_newobj of ILMethodSpec * ILVarArgs
Expand Down Expand Up @@ -1970,7 +1970,6 @@ type internal ILLocalsAllocator =
/// Derived functions for making some common patterns of instructions.
val internal mkNormalCall: ILMethodSpec -> ILInstr
val internal mkNormalCallvirt: ILMethodSpec -> ILInstr
val internal mkNormalCallconstraint: ILType * ILMethodSpec -> ILInstr
val internal mkNormalNewobj: ILMethodSpec -> ILInstr
val internal mkCallBaseConstructor: ILType * ILType list -> ILInstr list
val internal mkNormalStfld: ILFieldSpec -> ILInstr
Expand Down Expand Up @@ -2025,12 +2024,16 @@ val internal mkILNonGenericStaticMethod:
string * ILMemberAccess * ILParameter list * ILReturn * MethodBody -> ILMethodDef

val internal mkILGenericVirtualMethod:
string * ILMemberAccess * ILGenericParameterDefs * ILParameter list * ILReturn * MethodBody -> ILMethodDef
string * ILCallingConv * ILMemberAccess * ILGenericParameterDefs * ILParameter list * ILReturn * MethodBody ->
ILMethodDef

val internal mkILGenericNonVirtualMethod:
string * ILMemberAccess * ILGenericParameterDefs * ILParameter list * ILReturn * MethodBody -> ILMethodDef

val internal mkILNonGenericVirtualMethod:
string * ILCallingConv * ILMemberAccess * ILParameter list * ILReturn * MethodBody -> ILMethodDef

val internal mkILNonGenericVirtualInstanceMethod:
string * ILMemberAccess * ILParameter list * ILReturn * MethodBody -> ILMethodDef

val internal mkILNonGenericInstanceMethod:
Expand Down
3 changes: 2 additions & 1 deletion src/Compiler/AbstractIL/ilmorph.fs
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,8 @@ let morphILTypesInILInstr ((factualTy, fformalTy)) i =
| I_calli (a, mref, varargs) -> I_calli(a, callsig_ty2ty factualTy mref, morphILVarArgs factualTy varargs)
| I_call (a, mr, varargs) -> I_call(a, conv_mspec mr, morphILVarArgs factualTy varargs)
| I_callvirt (a, mr, varargs) -> I_callvirt(a, conv_mspec mr, morphILVarArgs factualTy varargs)
| I_callconstraint (a, ty, mr, varargs) -> I_callconstraint(a, factualTy ty, conv_mspec mr, morphILVarArgs factualTy varargs)
| I_callconstraint (callvirt, a, ty, mr, varargs) ->
I_callconstraint(callvirt, a, factualTy ty, conv_mspec mr, morphILVarArgs factualTy varargs)
| I_newobj (mr, varargs) -> I_newobj(conv_mspec mr, morphILVarArgs factualTy varargs)
| I_ldftn mr -> I_ldftn(conv_mspec mr)
| I_ldvirtftn mr -> I_ldvirtftn(conv_mspec mr)
Expand Down
4 changes: 2 additions & 2 deletions src/Compiler/AbstractIL/ilprint.fs
Original file line number Diff line number Diff line change
Expand Up @@ -893,11 +893,11 @@ let rec goutput_instr env os inst =
output_string os "callvirt "
goutput_vararg_mspec env os (mspec, varargs)
output_after_tailcall os tl
| I_callconstraint (tl, ty, mspec, varargs) ->
| I_callconstraint (callvirt, tl, ty, mspec, varargs) ->
output_tailness os tl
output_string os "constraint. "
goutput_typ env os ty
output_string os " callvirt "
output_string os (if callvirt then " callvirt " else " call ")
goutput_vararg_mspec env os (mspec, varargs)
output_after_tailcall os tl
| I_castclass ty ->
Expand Down
22 changes: 14 additions & 8 deletions src/Compiler/AbstractIL/ilread.fs
Original file line number Diff line number Diff line change
Expand Up @@ -626,17 +626,23 @@ let instrs () =
i_stsfld, I_field_instr(volatilePrefix (fun x fspec -> I_stsfld(x, fspec)))
i_ldflda, I_field_instr(noPrefixes I_ldflda)
i_ldsflda, I_field_instr(noPrefixes I_ldsflda)
i_call, I_method_instr(tailPrefix (fun tl (mspec, y) -> I_call(tl, mspec, y)))
(i_call,
I_method_instr(
constraintOrTailPrefix (fun (c, tl) (mspec, y) ->
match c with
| Some ty -> I_callconstraint(false, tl, ty, mspec, y)
| None -> I_call(tl, mspec, y))
))
i_ldftn, I_method_instr(noPrefixes (fun (mspec, _y) -> I_ldftn mspec))
i_ldvirtftn, I_method_instr(noPrefixes (fun (mspec, _y) -> I_ldvirtftn mspec))
i_newobj, I_method_instr(noPrefixes I_newobj)
i_callvirt,
I_method_instr(
constraintOrTailPrefix (fun (c, tl) (mspec, y) ->
match c with
| Some ty -> I_callconstraint(tl, ty, mspec, y)
| None -> I_callvirt(tl, mspec, y))
)
(i_callvirt,
I_method_instr(
constraintOrTailPrefix (fun (c, tl) (mspec, y) ->
match c with
| Some ty -> I_callconstraint(true, tl, ty, mspec, y)
| None -> I_callvirt(tl, mspec, y))
))
i_leave_s, I_unconditional_i8_instr(noPrefixes (fun x -> I_leave x))
i_br_s, I_unconditional_i8_instr(noPrefixes I_br)
i_leave, I_unconditional_i32_instr(noPrefixes (fun x -> I_leave x))
Expand Down
5 changes: 3 additions & 2 deletions src/Compiler/AbstractIL/ilreflect.fs
Original file line number Diff line number Diff line change
Expand Up @@ -1391,9 +1391,10 @@ let rec emitInstr cenv (modB: ModuleBuilder) emEnv (ilG: ILGenerator) instr =
emitSilverlightCheck ilG
emitInstrCall cenv emEnv ilG OpCodes.Callvirt tail mspec varargs

| I_callconstraint (tail, ty, mspec, varargs) ->
| I_callconstraint (callvirt, tail, ty, mspec, varargs) ->
ilG.Emit(OpCodes.Constrained, convType cenv emEnv ty)
emitInstrCall cenv emEnv ilG OpCodes.Callvirt tail mspec varargs
let instr = if callvirt then OpCodes.Callvirt else OpCodes.Call
emitInstrCall cenv emEnv ilG instr tail mspec varargs

| I_calli (tail, callsig, None) ->
emitInstrTail cenv ilG tail (fun () ->
Expand Down
5 changes: 3 additions & 2 deletions src/Compiler/AbstractIL/ilwrite.fs
Original file line number Diff line number Diff line change
Expand Up @@ -1922,10 +1922,11 @@ module Codebuf =
emitTailness cenv codebuf tl
emitMethodSpecInstr cenv codebuf env i_callvirt (mspec, varargs)
//emitAfterTailcall codebuf tl
| I_callconstraint (tl, ty, mspec, varargs) ->
| I_callconstraint (callvirt, tl, ty, mspec, varargs) ->
emitTailness cenv codebuf tl
emitConstrained cenv codebuf env ty
emitMethodSpecInstr cenv codebuf env i_callvirt (mspec, varargs)
let instr = if callvirt then i_callvirt else i_call
emitMethodSpecInstr cenv codebuf env instr (mspec, varargs)
//emitAfterTailcall codebuf tl
| I_newobj (mspec, varargs) ->
emitMethodSpecInstr cenv codebuf env i_newobj (mspec, varargs)
Expand Down
2 changes: 1 addition & 1 deletion src/Compiler/Checking/CheckComputationExpressions.fs
Original file line number Diff line number Diff line change
Expand Up @@ -468,7 +468,7 @@ let TcComputationExpression (cenv: cenv) env (overallTy: OverallTy) tpenv (mWhol
match info with
| None -> false
| Some args ->
args |> List.exists (fun (isParamArrayArg, _isInArg, isOutArg, optArgInfo, _callerInfo, _reflArgInfo) -> isParamArrayArg || isOutArg || optArgInfo.IsOptional))
args |> List.exists (fun (ParamAttribs(isParamArrayArg, _isInArg, isOutArg, optArgInfo, _callerInfo, _reflArgInfo)) -> isParamArrayArg || isOutArg || optArgInfo.IsOptional))
else
false

Expand Down
Loading

0 comments on commit bdb6462

Please sign in to comment.