@@ -5,6 +5,7 @@ namespace FSharp.Compiler.SourceCodeServices
55open  FSharp.Compiler  
66open  FSharp.Compiler .AbstractIL .Internal .Library  
77open  FSharp.Compiler .AbstractIL .IL  
8+ open  FSharp.Compiler .ErrorLogger  
89open  FSharp.Compiler .Lib  
910open  FSharp.Compiler .Infos  
1011open  FSharp.Compiler .QuotationTranslator  
@@ -35,13 +36,26 @@ module ExprTranslationImpl =
3536          isinstVals:  ValMap < TType  *  Expr >   
3637
3738          substVals:  ValMap < Expr > 
39+ 
40+           /// Indicates that we disable generation of witnesses 
41+            suppressWitnesses:  bool 
42+ 
43+           /// All witnesses in scope and their mapping to lambda variables. 
44+            // 
45+           // Note: this uses an immutable HashMap/Dictionary with an IEqualityComparer that captures TcGlobals, see 
46+           // the point where the empty initial object is created. 
47+           witnessesInScope:  TraitWitnessInfoHashMap < int > 
48+ 
3849        } 
3950
40-         static member  Empty  =  
51+         static member  Empty  g   =  
4152            {  vs= ValMap<_>. Empty
42-               tyvs =  Map.empty  ; 
53+               tyvs =  Map.empty
4354              isinstVals =  ValMap<_>. Empty 
44-               substVals =  ValMap<_>. Empty } 
55+               substVals =  ValMap<_>. Empty
56+               suppressWitnesses =  false 
57+               witnessesInScope =  EmptyTraitWitnessInfoHashMap g
58+             } 
4559
4660        member  env.BindTypar   ( v :  Typar ,  gp )  =  
4761            {  env with  tyvs =  env.tyvs.Add( v.Stamp,  gp )  } 
@@ -81,7 +95,7 @@ type E =
8195    |  IfThenElse   of  FSharpExpr  *  FSharpExpr  *  FSharpExpr   
8296    |  DecisionTree   of  FSharpExpr  *  ( FSharpMemberOrFunctionOrValue  list  *  FSharpExpr )  list 
8397    |  DecisionTreeSuccess of  int  *  FSharpExpr  list 
84-     |  Call of  FSharpExpr  option  *  FSharpMemberOrFunctionOrValue  *  FSharpType  list  *  FSharpType  list  *  FSharpExpr  list  
98+     |  Call of  FSharpExpr  option  *  FSharpMemberOrFunctionOrValue  *  FSharpType  list  *  FSharpType  list  *  FSharpExpr  list  *   FSharpExpr   list   
8599    |  NewObject of  FSharpMemberOrFunctionOrValue  *  FSharpType  list  *  FSharpExpr  list  
86100    |  LetRec of  (  FSharpMemberOrFunctionOrValue  *  FSharpExpr )  list  *  FSharpExpr   
87101    |  Let of  ( FSharpMemberOrFunctionOrValue  *  FSharpExpr )  *  FSharpExpr  
@@ -117,6 +131,7 @@ type E =
117131    |  ILFieldGet of  FSharpExpr  option  *  FSharpType  *  string  
118132    |  ILFieldSet of  FSharpExpr  option  *  FSharpType  *  string   *  FSharpExpr  
119133    |  ILAsm of  string  *  FSharpType  list  *  FSharpExpr  list 
134+     |  WitnessArg of  int 
120135
121136/// Used to represent the information at an object expression member  
122137and  [<Sealed>]   FSharpObjectExprOverride ( sgn :  FSharpAbstractSignature ,  gps :  FSharpGenericParameter list ,  args :  FSharpMemberOrFunctionOrValue list list ,  body :  FSharpExpr )  =  
@@ -128,10 +143,11 @@ and [<Sealed>]  FSharpObjectExprOverride(sgn: FSharpAbstractSignature, gps: FSha
128143/// The type of expressions provided through the compiler API. 
129144and  [<Sealed>]  FSharpExpr   ( cenv ,  f :  ( unit  ->  FSharpExpr ) option ,  e :  E ,  m :  range ,  ty )  = 
130145
146+     let mutable  e  =  match  f with  None ->  e |  Some _  ->  Unchecked.defaultof< E> 
131147    member  x.Range  =  m
132148    member  x.Type  =  FSharpType( cenv,  ty) 
133149    member  x.cenv  =  cenv
134-     member  x.E  =  match  f  with  None  ->  e  |  Some f  ->  f () .E
150+     member  x.E  =  match  box e  with  null  ->  ( e  <-  f.Value () .E);  e  |   _   ->  e 
135151    override  x.ToString ()  =  sprintf " %+A "   x.E
136152
137153    member  x.ImmediateSubExpressions  =  
@@ -150,7 +166,7 @@ and [<Sealed>] FSharpExpr (cenv, f: (unit -> FSharpExpr) option, e: E, m: range,
150166        |  E.NewUnionCase (_ unionType,  _ unionCase,  es)  ->  es
151167        |  E.NewTuple (_ tupleType,  es)  ->  es
152168        |  E.TupleGet (_ tupleType,  _ itemIndex,  tupleExpr)  ->  [ tupleExpr] 
153-         |  E.Call ( objOpt,  _ b,  _ c,  _ d,  es)  ->  ( match  objOpt with  None ->  es |  Some x ->  x ::  es) 
169+         |  E.Call ( objOpt,  _ b,  _ c,  _ d,  ws ,   es)  ->  ( match  objOpt with  None ->  ws  @   es |  Some x ->  x ::  ws  @  es) 
154170        |  E.NewObject (_ a,  _ b,  c)  ->  c
155171        |  E.FSharpFieldGet ( objOpt,  _ b,  _ c)  ->  ( match  objOpt with  None ->  []  |  Some x ->  [ x]) 
156172        |  E.FSharpFieldSet ( objOpt,  _ b,  _ c,  d)  ->  ( match  objOpt with  None ->  [ d]  |  Some x ->  [ x; d]) 
@@ -187,7 +203,7 @@ and [<Sealed>] FSharpExpr (cenv, f: (unit -> FSharpExpr) option, e: E, m: range,
187203        |  E.UnionCaseSet ( obj,  _ unionType,  _ unionCase,  _ unionField,  valueExpr)  ->  [  yield  obj;  yield  valueExpr ] 
188204        |  E.TraitCall (_ sourceTypes,  _ traitName,  _ memberFlags,  _ paramTypes,  _ retTypes,  args)  ->  args
189205        |  E.Unused ->  []  // unexpected 
190- 
206+          |  E.WitnessArg  _ n  ->   [] 
191207
192208/// The implementation of the conversion operation 
193209module  FSharpExprConvert  = 
@@ -409,19 +425,19 @@ module FSharpExprConvert =
409425        let  ( numEnclTypeArgs ,  _ ,  isNewObj ,  _valUseFlags ,  _isSelfInit ,  takesInstanceArg ,  _isPropGet ,  _isPropSet )  =  
410426            GetMemberCallInfo cenv.g ( vref,  vFlags) 
411427
412-         let  isMember ,  curriedArgInfos  =  
428+         let  isMember ,  tps ,   curriedArgInfos  =  
413429
414430            match  vref.MemberInfo with  
415431            |  Some _  when  not  vref.IsExtensionMember ->  
416432                // This is an application of a member method 
417433                // We only count one argument block for these. 
418-                 let  _tps ,  curriedArgInfos ,  _ ,  _  =  GetTypeOfMemberInFSharpForm cenv.g vref 
419-                 true ,  curriedArgInfos
434+                 let  tps ,  curriedArgInfos ,  _ ,  _  =  GetTypeOfMemberInFSharpForm cenv.g vref 
435+                 true ,  tps ,   curriedArgInfos
420436            |  _  ->  
421437                // This is an application of a module value or extension member 
422438                let  arities  =  arityOfVal vref.Deref 
423-                 let  _tps ,  curriedArgInfos ,  _ ,  _  =  GetTopValTypeInFSharpForm cenv.g arities vref.Type m
424-                 false ,  curriedArgInfos
439+                 let  tps ,  curriedArgInfos ,  _ ,  _  =  GetTopValTypeInFSharpForm cenv.g arities vref.Type m
440+                 false ,  tps ,   curriedArgInfos
425441
426442        // Compute the object arguments as they appear in a compiled call 
427443        // Strip off the object argument, if any. The curriedArgInfos are already adjusted to compiled member form 
@@ -467,12 +483,35 @@ module FSharpExprConvert =
467483            if  isMember then  
468484                let  callArgs  =  ( objArgs ::  untupledCurriedArgs)  |>  List.concat
469485                let  enclTyArgs ,  methTyArgs  =  List.splitAfter numEnclTypeArgs tyargs
486+                 let  witnessArgsR  =  GetWitnessArgs cenv env vref m tps tyargs
470487                // tailcall 
471-                 ConvObjectModelCallLinear cenv env ( isNewObj,  FSharpMemberOrFunctionOrValue( cenv,  vref),  enclTyArgs,  methTyArgs,  callArgs)  contf2
488+                 ConvObjectModelCallLinear cenv env ( isNewObj,  FSharpMemberOrFunctionOrValue( cenv,  vref),  enclTyArgs,  methTyArgs,  witnessArgsR ,   callArgs)  contf2
472489            else 
473490                let  v  =  FSharpMemberOrFunctionOrValue( cenv,  vref) 
491+                 let  witnessArgsR  =  GetWitnessArgs cenv env vref m vref.Typars tyargs
474492                // tailcall 
475-                 ConvObjectModelCallLinear cenv env ( false ,  v,  [],  tyargs,  List.concat untupledCurriedArgs)  contf2
493+                 ConvObjectModelCallLinear cenv env ( false ,  v,  [],  tyargs,  witnessArgsR,  List.concat untupledCurriedArgs)  contf2
494+ 
495+     and  GetWitnessArgs  cenv  ( env :  ExprTranslationEnv )  ( vref :  ValRef )  m tps tyargs  :  FSharpExpr list  = 
496+         let  g  =  cenv.g
497+         if  cenv.g.langVersion.SupportsFeature( Features.LanguageFeature.WitnessPassing)  &&  not  env.suppressWitnesses then  
498+             let  witnessExprs  =  
499+                 match  ConstraintSolver.CodegenWitnessesForTyparInst cenv.tcValF g cenv.amap m tps tyargs with 
500+                 // There is a case where optimized code makes expressions that do a shift-left on the 'char' 
501+                 // type.  There is no witness for this case.  This is due to the code 
502+                 //    let inline HashChar (x:char) = (# "or" (# "shl" x 16 : int #) x : int #) 
503+                 // in FSharp.Core.  
504+                 |  ErrorResult _   when  vref.LogicalName =   " op_LeftShift"   &&  tyargs.Length =  1  ->  [] 
505+                 |  res ->  CommitOperationResult res
506+             let  env  =  {  env with  suppressWitnesses =  true  } 
507+             witnessExprs |>  List.map ( fun  arg  ->  
508+                 match  arg with  
509+                 |  Choice1Of2 traitInfo ->  
510+                     ConvWitnessInfo cenv env m traitInfo
511+                 |  Choice2Of2 arg ->  
512+                     ConvExpr cenv env arg)  
513+         else 
514+             [] 
476515
477516    and  ConvExprPrim   ( cenv :  SymbolEnv )  ( env :  ExprTranslationEnv )  expr  =  
478517        // Eliminate integer 'for' loops  
@@ -554,7 +593,7 @@ module FSharpExprConvert =
554593                    let  vslR  =  List.map ( List.map ( ConvVal cenv))  tmvs 
555594                    let  sgn  =  FSharpAbstractSignature( cenv,  slotsig) 
556595                    let  tpsR  =  [  for  tp in  tps ->  FSharpGenericParameter( cenv,  tp)  ] 
557-                     let  env  =  ExprTranslationEnv.Empty .BindTypars ( Seq.zip tps tpsR |>  Seq.toList) 
596+                     let  env  =  env .BindTypars ( Seq.zip tps tpsR |>  Seq.toList) 
558597                    let  env  =  env.BindCurriedVals tmvs
559598                    let  bodyR  =  ConvExpr cenv env body
560599                    FSharpObjectExprOverride( sgn,  tpsR,  vslR,  bodyR)  ] 
@@ -841,9 +880,29 @@ module FSharpExprConvert =
841880                ConvExprPrim cenv env replExpr
842881
843882            |  _  ->  wfail ( sprintf " unhandled construct in AST" ,  m) 
883+         |  Expr.WitnessArg ( traitInfo,  _ m)  -> 
884+             ConvWitnessInfoPrim cenv env traitInfo
844885        |  _  ->  
845886            wfail ( sprintf " unhandled construct in AST" ,  expr.Range) 
846887
888+     and  ConvWitnessInfoPrim  _cenv env traitInfo  :  E  = 
889+         let  witnessInfo  =  traitInfo.TraitKey
890+         let  env  =  {  env with  suppressWitnesses =  true  } 
891+         // First check if this is a witness in ReflectedDefinition code 
892+         if  env.witnessesInScope.ContainsKey witnessInfo then  
893+             let  witnessArgIdx  =  env.witnessesInScope.[ witnessInfo] 
894+             E.WitnessArg( witnessArgIdx) 
895+         // Otherwise it is a witness in a quotation literal  
896+         else 
897+             //failwith "witness not found" 
898+             E.WitnessArg(- 1 ) 
899+ 
900+     and  ConvWitnessInfo  cenv env m traitInfo  :  FSharpExpr  = 
901+         let  g  =  cenv.g
902+         let  witnessInfo  =  traitInfo.TraitKey
903+         let  witnessTy  =  GenWitnessTy g witnessInfo 
904+         let  traitInfoR  =  ConvWitnessInfoPrim cenv env traitInfo
905+         Mk cenv m witnessTy traitInfoR
847906
848907    and  ConvLetBind  cenv env  ( bind  :  Binding )  =  
849908        match  bind.Expr with  
@@ -895,7 +954,7 @@ module FSharpExprConvert =
895954        let  enclosingType  =  generalizedTyconRef tcref
896955
897956        let  makeCall  minfo  = 
898-             ConvObjectModelCallLinear cenv env ( isNewObj,  minfo,  enclTypeArgs,  methTypeArgs,  callArgs)  id   
957+             ConvObjectModelCallLinear cenv env ( isNewObj,  minfo,  enclTypeArgs,  methTypeArgs,  [],   callArgs)  id   
899958
900959        let  makeFSCall  isMember  ( vr :  ValRef )  = 
901960            let  memOrVal  = 
@@ -1079,7 +1138,7 @@ module FSharpExprConvert =
10791138          with  e ->  
10801139            failwithf " An IL call to '%s  ' could not be resolved: %s "   ( ilMethRef.ToString())  e.Message
10811140
1082-     and  ConvObjectModelCallLinear  cenv env  ( isNewObj ,  v :  FSharpMemberOrFunctionOrValue ,  enclTyArgs ,  methTyArgs ,  callArgs )  contF  = 
1141+     and  ConvObjectModelCallLinear  cenv env  ( isNewObj ,  v :  FSharpMemberOrFunctionOrValue ,  enclTyArgs ,  methTyArgs ,  witnessArgsR :   FSharpExpr list ,   callArgs )  contF  = 
10831142        let  enclTyArgsR  =  ConvTypes cenv enclTyArgs
10841143        let  methTyArgsR  =  ConvTypes cenv methTyArgs
10851144        let  obj ,  callArgs  =  
@@ -1095,8 +1154,7 @@ module FSharpExprConvert =
10951154            if  isNewObj then  
10961155                E.NewObject( v,  enclTyArgsR,  callArgsR)  
10971156            else  
1098-                 E.Call( objR,  v,  enclTyArgsR,  methTyArgsR,  callArgsR)) 
1099- 
1157+                 E.Call( objR,  v,  enclTyArgsR,  methTyArgsR,  witnessArgsR,  callArgsR)) 
11001158
11011159    and  ConvExprs  cenv env args  =  List.map ( ConvExpr cenv env)  args 
11021160
@@ -1255,7 +1313,7 @@ and FSharpImplementationFileContents(cenv, mimpl) =
12551313        let  v  =  FSharpMemberOrFunctionOrValue( cenv,  mkLocalValRef v) 
12561314        let  gps  =  v.GenericParameters
12571315        let  vslR  =  List.map ( List.map ( FSharpExprConvert.ConvVal cenv))  vsl 
1258-         let  env  =  ExprTranslationEnv.Empty.BindTypars ( Seq.zip tps gps |>  Seq.toList) 
1316+         let  env  =  ExprTranslationEnv.Empty( cenv.g ) .BindTypars ( Seq.zip tps gps |>  Seq.toList) 
12591317        let  env  =  env.BindCurriedVals vsl 
12601318        let  e  =  FSharpExprConvert.ConvExprOnDemand cenv env body
12611319        FSharpImplementationFileDeclaration.MemberOrFunctionOrValue( v,  vslR,  e)  
@@ -1277,7 +1335,7 @@ and FSharpImplementationFileContents(cenv, mimpl) =
12771335        |  TMDefLet( bind,  _ m)   -> 
12781336            [  yield  getBind bind  ] 
12791337        |  TMDefDo( expr,  _ m)   -> 
1280-             [  let  expr  =  FSharpExprConvert.ConvExprOnDemand cenv ExprTranslationEnv.Empty expr
1338+             [  let  expr  =  FSharpExprConvert.ConvExprOnDemand cenv ( ExprTranslationEnv.Empty( cenv.g ))  expr
12811339              yield  FSharpImplementationFileDeclaration.InitAction expr  ] 
12821340        |  TMDefs mdefs ->  
12831341            [  for  mdef in  mdefs do  yield !  getDecls mdef ] 
@@ -1303,7 +1361,8 @@ module BasicPatterns =
13031361    let  (| NewUnionCase | _ |)  ( e :  FSharpExpr )  =  match  e.E with  E.NewUnionCase ( e,  tys,  es)  ->  Some ( e,  tys,  es)  |  _  ->  None
13041362    let  (| NewTuple | _ |)  ( e :  FSharpExpr )  =  match  e.E with  E.NewTuple ( ty,  es)  ->  Some ( ty,  es)  |  _  ->  None
13051363    let  (| TupleGet | _ |)  ( e :  FSharpExpr )  =  match  e.E with  E.TupleGet ( ty,  n,  es)  ->  Some ( ty,  n,  es)  |  _  ->  None
1306-     let  (| Call | _ |)  ( e :  FSharpExpr )  =  match  e.E with  E.Call ( a,  b,  c,  d,  e)  ->  Some ( a,  b,  c,  d,  e)  |  _  ->  None
1364+     let  (| Call | _ |)  ( e :  FSharpExpr )  =  match  e.E with  E.Call ( a,  b,  c,  d,  _ e,  f)  ->  Some ( a,  b,  c,  d,  f)  |  _  ->  None
1365+     let  (| CallWithWitnesses | _ |)  ( e :  FSharpExpr )  =  match  e.E with  E.Call ( a,  b,  c,  d,  e,  f)  ->  Some ( a,  b,  c,  d,  e,  f)  |  _  ->  None
13071366    let  (| NewObject | _ |)  ( e :  FSharpExpr )  =  match  e.E with  E.NewObject ( a,  b,  c)  ->  Some ( a,  b,  c)  |  _  ->  None
13081367    let  (| FSharpFieldGet | _ |)  ( e :  FSharpExpr )  =  match  e.E with  E.FSharpFieldGet ( a,  b,  c)  ->  Some ( a,  b,  c)  |  _  ->  None
13091368    let  (| AnonRecordGet | _ |)  ( e :  FSharpExpr )  =  match  e.E with  E.AnonRecordGet ( a,  b,  c)  ->  Some ( a,  b,  c)  |  _  ->  None
@@ -1335,4 +1394,5 @@ module BasicPatterns =
13351394    let  (| DecisionTreeSuccess | _ |)  ( e :  FSharpExpr )  =  match  e.E with  E.DecisionTreeSuccess ( a,  b)  ->  Some ( a,  b)  |  _  ->  None
13361395    let  (| UnionCaseSet | _ |)  ( e :  FSharpExpr )  =  match  e.E with  E.UnionCaseSet ( a,  b,  c,  d,  e)  ->  Some ( a,  b,  c,  d,  e)  |  _  ->  None
13371396    let  (| TraitCall | _ |)  ( e :  FSharpExpr )  =  match  e.E with  E.TraitCall ( a,  b,  c,  d,  e,  f)  ->  Some ( a,  b,  c,  d,  e,  f)  |  _  ->  None
1397+     let  (| WitnessArg | _ |)  ( e :  FSharpExpr )  =  match  e.E with  E.WitnessArg n ->  Some n |  _  ->  None
13381398
0 commit comments