diff --git a/src/Compiler/CodeGen/IlxGen.fs b/src/Compiler/CodeGen/IlxGen.fs index 2a1c876b8f5..fb4ea5ee7ac 100644 --- a/src/Compiler/CodeGen/IlxGen.fs +++ b/src/Compiler/CodeGen/IlxGen.fs @@ -521,7 +521,7 @@ let ComputeTypeAccess (tref: ILTypeRef) hidden (accessibility: Accessibility) re /// Indicates how type parameters are mapped to IL type variables [] -type TypeReprEnv(reprs: Map, count: int, templateReplacement: (TyconRef * ILTypeRef * Typars * TyparInstantiation) option) = +type TypeReprEnv(reprs: Map, count: int, templateReplacement: (TyconRef * ILTypeRef * Typars * TyparInstantiation) option) = static let empty = TypeReprEnv(count = 0, reprs = Map.empty, templateReplacement = None) @@ -536,7 +536,7 @@ type TypeReprEnv(reprs: Map, count: int, templateReplacement: (Ty /// Lookup a type parameter member _.Item(tp: Typar, m: range) = try - reprs[tp.Stamp] + reprs[tp.Stamp] |>fst with :? KeyNotFoundException -> errorR (InternalError("Undefined or unsolved type variable: " + showL (typarL tp), m)) // Random value for post-hoc diagnostic analysis on generated tree * @@ -546,7 +546,7 @@ type TypeReprEnv(reprs: Map, count: int, templateReplacement: (Ty /// then it is ignored, since it doesn't correspond to a .NET type parameter. member tyenv.AddOne(tp: Typar) = if IsNonErasedTypar tp then - TypeReprEnv(reprs.Add(tp.Stamp, uint16 count), count + 1, templateReplacement) + TypeReprEnv(reprs.Add(tp.Stamp, (uint16 count, tp)), count + 1, templateReplacement) else tyenv @@ -573,6 +573,9 @@ type TypeReprEnv(reprs: Map, count: int, templateReplacement: (Ty /// Get the environment for generating a reference to items within a type definition member eenv.ForTyconRef(tcref: TyconRef) = eenv.ForTycon tcref.Deref + /// Get a list of the Typars in this environment + member eenv.AsUserProvidedTypars() = reprs |> Map.toList |> List.map(fun (_, (_, tp)) -> tp) |> List.filter(fun tp -> not tp.IsCompilerGenerated) |> Zset.ofList typarOrder + //-------------------------------------------------------------------------- // Generate type references //-------------------------------------------------------------------------- @@ -6892,14 +6895,6 @@ and GenFreevar cenv m eenvouter tyenvinner (fv: Val) = and GetIlxClosureFreeVars cenv m (thisVars: ValRef list) boxity eenv takenNames expr = let g = cenv.g - // Choose a base name for the closure - let basename = - let boundv = eenv.letBoundVars |> List.tryFind (fun v -> not v.IsCompilerGenerated) - - match boundv with - | Some v -> v.CompiledName cenv.g.CompilerGlobalState - | None -> "clo" - // Get a unique stamp for the closure. This must be stable for things that can be part of a let rec. let uniq = match expr with @@ -6909,18 +6904,30 @@ and GetIlxClosureFreeVars cenv m (thisVars: ValRef list) boxity eenv takenNames | _ -> newUnique () // Choose a name for the closure - let ilCloTypeRef = + let ilCloTypeRef, initialFreeTyvars = + let boundvar = + eenv.letBoundVars |> List.tryFind (fun v -> not v.IsCompilerGenerated) + + let basename = + match boundvar with + | Some v -> v.CompiledName cenv.g.CompilerGlobalState + | None -> "clo" + // FSharp 1.0 bug 3404: System.Reflection doesn't like '.' and '`' in type names let basenameSafeForUseAsTypename = CleanUpGeneratedTypeName basename - let suffixmark = expr.Range - let cloName = // Ensure that we have an g.CompilerGlobalState assert (g.CompilerGlobalState |> Option.isSome) - g.CompilerGlobalState.Value.StableNameGenerator.GetUniqueCompilerGeneratedName(basenameSafeForUseAsTypename, suffixmark, uniq) + g.CompilerGlobalState.Value.StableNameGenerator.GetUniqueCompilerGeneratedName(basenameSafeForUseAsTypename, expr.Range, uniq) + + let ilCloTypeRef = NestedTypeRefForCompLoc eenv.cloc cloName + let initialFreeTyvars = + match g.realsig with + | true -> { emptyFreeTyvars with FreeTypars = eenv.tyenv.AsUserProvidedTypars() } + | false -> emptyFreeTyvars - NestedTypeRefForCompLoc eenv.cloc cloName + ilCloTypeRef, initialFreeTyvars // Collect the free variables of the closure let cloFreeVarResults = @@ -6931,7 +6938,7 @@ and GetIlxClosureFreeVars cenv m (thisVars: ValRef list) boxity eenv takenNames | None -> opts | Some(tcref, _, typars, _) -> opts.WithTemplateReplacement(tyconRefEq g tcref, typars) - freeInExpr opts expr + accFreeInExpr opts expr { emptyFreeVars with FreeTyvars = initialFreeTyvars } // Partition the free variables when some can be accessed from places besides the immediate environment // Also filter out the current value being bound, if any, as it is available from the "this" diff --git a/src/Compiler/TypedTree/CompilerGlobalState.fs b/src/Compiler/TypedTree/CompilerGlobalState.fs index 72da3da4f58..12dda2b08d8 100644 --- a/src/Compiler/TypedTree/CompilerGlobalState.fs +++ b/src/Compiler/TypedTree/CompilerGlobalState.fs @@ -73,4 +73,6 @@ let newUnique() = System.Threading.Interlocked.Increment &uniqueCount /// Unique name generator for stamps attached to to val_specs, tycon_specs etc. //++GLOBAL MUTABLE STATE (concurrency-safe) let mutable private stampCount = 0L -let newStamp() = System.Threading.Interlocked.Increment &stampCount +let newStamp() = + let stamp = System.Threading.Interlocked.Increment &stampCount + stamp \ No newline at end of file diff --git a/src/Compiler/TypedTree/TypedTreeOps.fsi b/src/Compiler/TypedTree/TypedTreeOps.fsi index 4eafbf229dc..3924cfd2dfa 100755 --- a/src/Compiler/TypedTree/TypedTreeOps.fsi +++ b/src/Compiler/TypedTree/TypedTreeOps.fsi @@ -1184,6 +1184,9 @@ val accFreeInDecisionTree: FreeVarOptions -> DecisionTree -> FreeVars -> FreeVar /// Get the free variables in a module definition. val freeInModuleOrNamespace: FreeVarOptions -> ModuleOrNamespaceContents -> FreeVars +/// Get the free variables in an expression with accumulator +val accFreeInExpr: FreeVarOptions -> Expr -> FreeVars -> FreeVars + /// Get the free variables in an expression. val freeInExpr: FreeVarOptions -> Expr -> FreeVars