Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
56f6c57
Fix typar pretty naming for graph type-checking.
nojaf Mar 2, 2023
48a24c6
Merge branch 'main' into typar-naming-workaround
nojaf Mar 2, 2023
f8de8c8
Do evil hack a little later.
nojaf Mar 2, 2023
6052627
Merge remote-tracking branch 'origin/typar-naming-workaround' into ty…
nojaf Mar 2, 2023
e3b71a4
Merge branch 'main' into typar-naming-workaround
nojaf Mar 3, 2023
7ea39a5
Merge branch 'main' into typar-naming-workaround
nojaf Mar 3, 2023
6265fab
Convert Typar to class, lock typar_id in SetIdent assignment.
nojaf Mar 15, 2023
dab0a3c
Merge branch 'main' into typar-naming-workaround
nojaf Mar 15, 2023
23710c5
Avoid null pointer from Unchecked.defaultof.
nojaf Mar 15, 2023
a4ab645
Merge branch 'main' into typar-naming-workaround
nojaf Mar 15, 2023
dd86ec2
Merge branch 'main' into typar-naming-workaround
nojaf Mar 15, 2023
80699a6
Merge branch 'main' into typar-naming-workaround
nojaf Mar 15, 2023
4b3ff88
Merge branch 'main' into typar-naming-workaround
nojaf Mar 16, 2023
7231992
Merge branch 'main' into typar-naming-workaround
nojaf Mar 16, 2023
6a91cd0
Extract typed tree serialization to separate module.
nojaf Mar 16, 2023
2c9dac8
Add flags to json.
nojaf Mar 16, 2023
e62a5ab
Add range to json.
nojaf Mar 16, 2023
0d88a25
Add more data to signature json.
nojaf Mar 16, 2023
9dc371e
Merge remote-tracking branch 'origin/typar-naming-workaround' into ty…
nojaf Mar 16, 2023
48fb1f3
Add more info to signature data serialization
nojaf Mar 20, 2023
b6fcd63
Merge branch 'main' into typar-naming-workaround
nojaf Mar 20, 2023
0c99e8a
Merge branch 'typar-naming-workaround' of https://github.com/nojaf/fs…
nojaf Mar 20, 2023
773ca17
Merge branch 'main' into typar-naming-workaround
vzarytovskii Mar 20, 2023
89a6628
Merge branch 'main' into typar-naming-workaround
nojaf Mar 20, 2023
16438cb
Merge branch 'main' into typar-naming-workaround
nojaf Mar 21, 2023
ff485e5
Revert most code.
nojaf Mar 21, 2023
8731fde
Don't duplicate typars in serialization.
nojaf Mar 21, 2023
53f01e5
Reapply typar naming to signature data.
nojaf Mar 21, 2023
a50ba39
Merge branch 'main' into typar-naming-workaround
nojaf Mar 21, 2023
8dc3860
Merge branch 'main' into typar-naming-workaround
nojaf Mar 22, 2023
4862b1c
Only update compiler generated typars.
nojaf Mar 22, 2023
d6af245
Merge branch 'main' into typar-naming-workaround
nojaf Mar 22, 2023
51773b6
Merge branch 'main' into typar-naming-workaround
nojaf Mar 22, 2023
55595fb
Update Typar names from declaredImpls.
nojaf Mar 23, 2023
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
2 changes: 1 addition & 1 deletion src/Compiler/Driver/CompilerImports.fs
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ let WriteSignatureData (tcConfig: TcConfig, tcGlobals, exportRemapping, ccu: Ccu
|> Option.iter (fun outputFile ->
let outputFile = FileSystem.GetFullPathShim(outputFile)
let signatureDataFile = FileSystem.ChangeExtensionShim(outputFile, ".signature-data.json")
serializeEntity signatureDataFile mspec)
TypeTreeSerialization.serializeEntity signatureDataFile mspec)

// For historical reasons, we use a different resource name for FSharp.Core, so older F# compilers
// don't complain when they see the resource.
Expand Down
47 changes: 46 additions & 1 deletion src/Compiler/Driver/ParseAndCheckInputs.fs
Original file line number Diff line number Diff line change
Expand Up @@ -1779,11 +1779,51 @@ let CheckMultipleInputsUsingGraphMode

partialResults, tcState)

/// The Typars of a Val can be determined by the call site.
/// As the type-checking can now happen in parallel, the naming is no longer deterministic.
/// Overall this only seems to affect the pickled signature data later on.
/// But in order to regain deterministic names, we re-do the pretty naming for all typars of Vals.
module UpdatePrettyNames =
let rec updateEntity (entity: Entity) =
for e in entity.ModuleOrNamespaceType.AllEntities do
updateEntity e

for v in entity.ModuleOrNamespaceType.AllValsAndMembers do
updateVal v

and private updateVal (v: Val) =
if not (List.isEmpty v.Typars) then
// Reset typar name to ?
for typar in v.Typars do
if typar.IsCompilerGenerated && typar.ILName.IsNone then
typar.typar_id <- Ident(unassignedTyparName, typar.typar_id.idRange)

let nms = PrettyTypes.PrettyTyparNames (fun _ -> true) List.empty v.Typars

(v.Typars, nms)
||> List.iter2 (fun tp nm -> tp.typar_id <- ident (nm, tp.Range))

and updateModuleOrNamespaceContent (contents: ModuleOrNamespaceContents) =
match contents with
| ModuleOrNamespaceContents.TMDefs defs ->
for def in defs do
updateModuleOrNamespaceContent def
| ModuleOrNamespaceContents.TMDefDo _
| ModuleOrNamespaceContents.TMDefOpens _ -> ()
| ModuleOrNamespaceContents.TMDefLet (binding, _) -> updateBinding binding
| ModuleOrNamespaceContents.TMDefRec (bindings = bindings) ->
for binding in bindings do
match binding with
| ModuleOrNamespaceBinding.Binding binding -> updateBinding binding
| ModuleOrNamespaceBinding.Module (_, moduleOrNamespaceContents) -> updateModuleOrNamespaceContent moduleOrNamespaceContents

and private updateBinding (binding: Binding) = updateVal binding.Var

let CheckClosedInputSet (ctok, checkForErrors, tcConfig: TcConfig, tcImports, tcGlobals, prefixPathOpt, tcState, eagerFormat, inputs) =
// tcEnvAtEndOfLastFile is the environment required by fsi.exe when incrementally adding definitions
let results, tcState =
match tcConfig.typeCheckingConfig.Mode with
| TypeCheckingMode.Graph when (not tcConfig.isInteractive && not tcConfig.deterministic) ->
| TypeCheckingMode.Graph when (not tcConfig.isInteractive) ->
CheckMultipleInputsUsingGraphMode(
ctok,
checkForErrors,
Expand All @@ -1803,5 +1843,10 @@ let CheckClosedInputSet (ctok, checkForErrors, tcConfig: TcConfig, tcImports, tc
let tcState, declaredImpls, ccuContents =
CheckClosedInputSetFinish(implFiles, tcState)

for declImpl in declaredImpls do
UpdatePrettyNames.updateModuleOrNamespaceContent declImpl.Contents

UpdatePrettyNames.updateEntity ccuContents

tcState.Ccu.Deref.Contents <- ccuContents
tcState, topAttrs, declaredImpls, tcEnvAtEndOfLastFile
2 changes: 2 additions & 0 deletions src/Compiler/FSharp.Compiler.Service.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,8 @@
<Compile Include="TypedTree\TypedTreeOps.fs" />
<Compile Include="TypedTree\TypedTreePickle.fsi" />
<Compile Include="TypedTree\TypedTreePickle.fs" />
<Compile Include="TypedTree\TypeTreeSerialization.fsi" />
<Compile Include="TypedTree\TypeTreeSerialization.fs" />
<Compile Include="Checking\import.fsi" />
<Compile Include="Checking\import.fs" />
<Compile Include="Checking\TypeHierarchy.fsi" />
Expand Down
161 changes: 161 additions & 0 deletions src/Compiler/TypedTree/TypeTreeSerialization.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
module FSharp.Compiler.TypeTreeSerialization

open System.CodeDom.Compiler
open FSharp.Compiler.Text
open Internal.Utilities.Library

open FSharp.Compiler.IO
open FSharp.Compiler.TypedTree

type TypedTreeNode =
{
Kind: string
Name: string
Children: TypedTreeNode list
Flags: int64 option
Range: range option
CompilationPath: CompilationPath option
}

let rec visitEntity (entity: Entity) : TypedTreeNode =
let kind =
if entity.IsModule then "module"
elif entity.IsNamespace then "namespace"
elif entity.IsUnionTycon then "union"
elif entity.IsRecordTycon then "record"
elif entity.IsFSharpClassTycon then "class"
elif entity.IsErased then "erased"
elif entity.IsEnumTycon then "enum"
elif entity.IsTypeAbbrev then "abbreviation"
elif entity.IsFSharpObjectModelTycon then "objectModel"
elif entity.IsFSharpException then "exception"
elif entity.IsFSharpDelegateTycon then "delegate"
elif entity.IsFSharpInterfaceTycon then "interface"
else "other"

let children =
seq {
if entity.IsModuleOrNamespace then
yield! Seq.map visitEntity entity.ModuleOrNamespaceType.AllEntities

yield! Seq.map visitVal entity.ModuleOrNamespaceType.AllValsAndMembers
yield! visitAttributes entity.Attribs
}

{
Kind = kind
Name = entity.CompiledName
Children = Seq.toList children
Flags = Some entity.entity_flags.PickledBits
Range = Some entity.Range
CompilationPath = Some entity.CompilationPath
}

and visitVal (v: Val) : TypedTreeNode =
let children =
seq {
yield! visitAttributes v.Attribs

match v.ValReprInfo with
| None -> ()
| Some (ValReprInfo (_, args, result)) ->
yield! args |> Seq.collect id |> Seq.map visitArgReprInfo
yield visitArgReprInfo result

yield!
v.Typars
|> Seq.map (fun typar ->
{
Name = typar.Name
Kind = "typar"
Children = []
Flags = Some typar.typar_flags.PickledBits
Range = Some typar.Range
CompilationPath = None
})
}

{
Name = v.CompiledName None
Kind = "val"
Children = Seq.toList children
Flags = Some v.val_flags.PickledBits
Range = Some v.Range
CompilationPath = None
}

and visitAttribute (a: Attrib) : TypedTreeNode =
{
Kind = "attribute"
Name = a.TyconRef.CompiledName
Children = List.empty
Flags = None
Range = Some a.Range
// I don't think the tycon ComplicationPath is relevant here.
CompilationPath = None
}

and visitAttributes (attribs: Attribs) : TypedTreeNode seq = List.map visitAttribute attribs

and visitArgReprInfo (argReprInfo: ArgReprInfo) =
{
Name = argReprInfo.Name |> Option.map (fun i -> i.idText) |> Option.defaultValue ""
Kind = "ArgInfo"
Children = []
Flags = None
Range = None
CompilationPath = None
}

let write (writer: IndentedTextWriter) key value =
writer.WriteLine($"\"%s{key}\": \"{value}\",")

let rec serializeNode (writer: IndentedTextWriter) (addTrailingComma: bool) (node: TypedTreeNode) =
writer.WriteLine("{")
// Add indent after opening {
writer.Indent <- writer.Indent + 1

write writer "name" node.Name
write writer "kind" node.Kind

node.Flags |> Option.iter (write writer "flags")
node.Range |> Option.iter (write writer "range")

node.CompilationPath
|> Option.iter (fun cp -> cp.MangledPath |> String.concat "," |> write writer "compilationPath")

if node.Children.IsEmpty then
writer.WriteLine("\"children\": []")
else
writer.WriteLine("\"children\": [")

// Add indent after opening [
writer.Indent <- writer.Indent + 1

node.Children
|> List.iteri (fun idx -> serializeNode writer (idx + 1 < node.Children.Length))

// Remove indent before closing ]
writer.Indent <- writer.Indent - 1
writer.WriteLine("]")

// Remove indent before closing }
writer.Indent <- writer.Indent - 1

if addTrailingComma then
writer.WriteLine("},")
else
writer.WriteLine("}")

let rec serializeEntity path (entity: Entity) =
let root = visitEntity entity
use sw = new System.IO.StringWriter()
use writer = new IndentedTextWriter(sw)
serializeNode writer false root
writer.Flush()
let json = sw.ToString()

use out =
FileSystem.OpenFileForWriteShim(path, fileMode = System.IO.FileMode.Create)

out.WriteAllText(json)
8 changes: 8 additions & 0 deletions src/Compiler/TypedTree/TypeTreeSerialization.fsi
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/// Helper code to serialize the typed tree to json
/// This code is invoked via the `--test:DumpSignatureData` flag.
module internal FSharp.Compiler.TypeTreeSerialization

open FSharp.Compiler.TypedTree

/// Serialize an entity to a very basic json structure.
val serializeEntity: path: string -> entity: Entity -> unit
103 changes: 0 additions & 103 deletions src/Compiler/TypedTree/TypedTreeOps.fs
Original file line number Diff line number Diff line change
Expand Up @@ -10497,106 +10497,3 @@ let tryAddExtensionAttributeIfNotAlreadyPresent
match tryFindExtensionAttributeIn tryFindExtensionAttribute with
| None -> entity
| Some extensionAttrib -> { entity with entity_attribs = extensionAttrib :: entity.Attribs }

type TypedTreeNode =
{
Kind: string
Name: string
Children: TypedTreeNode list
}

let rec visitEntity (entity: Entity) : TypedTreeNode =
let kind =
if entity.IsModule then
"module"
elif entity.IsNamespace then
"namespace"
else
"other"

let children =
if not entity.IsModuleOrNamespace then
Seq.empty
else
seq {
yield! Seq.map visitEntity entity.ModuleOrNamespaceType.AllEntities
yield! Seq.map visitVal entity.ModuleOrNamespaceType.AllValsAndMembers
}

{
Kind = kind
Name = entity.CompiledName
Children = Seq.toList children
}

and visitVal (v: Val) : TypedTreeNode =
let children =
seq {
match v.ValReprInfo with
| None -> ()
| Some reprInfo ->
yield!
reprInfo.ArgInfos
|> Seq.collect (fun argInfos ->
argInfos
|> Seq.map (fun argInfo -> {
Name = argInfo.Name |> Option.map (fun i -> i.idText) |> Option.defaultValue ""
Kind = "ArgInfo"
Children = []
})
)

yield!
v.Typars
|> Seq.map (fun typar -> {
Name = typar.Name
Kind = "Typar"
Children = []
})
}

{
Name = v.CompiledName None
Kind = "val"
Children = Seq.toList children
}

let rec serializeNode (writer: IndentedTextWriter) (addTrailingComma:bool) (node: TypedTreeNode) =
writer.WriteLine("{")
// Add indent after opening {
writer.Indent <- writer.Indent + 1

writer.WriteLine($"\"name\": \"{node.Name}\",")
writer.WriteLine($"\"kind\": \"{node.Kind}\",")

if node.Children.IsEmpty then
writer.WriteLine("\"children\": []")
else
writer.WriteLine("\"children\": [")

// Add indent after opening [
writer.Indent <- writer.Indent + 1

node.Children
|> List.iteri (fun idx -> serializeNode writer (idx + 1 < node.Children.Length))

// Remove indent before closing ]
writer.Indent <- writer.Indent - 1
writer.WriteLine("]")

// Remove indent before closing }
writer.Indent <- writer.Indent - 1
if addTrailingComma then
writer.WriteLine("},")
else
writer.WriteLine("}")

let rec serializeEntity path (entity: Entity) =
let root = visitEntity entity
use sw = new System.IO.StringWriter()
use writer = new IndentedTextWriter(sw)
serializeNode writer false root
writer.Flush()
let json = sw.ToString()
use out = FileSystem.OpenFileForWriteShim(path, fileMode = System.IO.FileMode.Create)
out.WriteAllText(json)
5 changes: 1 addition & 4 deletions src/Compiler/TypedTree/TypedTreeOps.fsi
Original file line number Diff line number Diff line change
Expand Up @@ -979,7 +979,7 @@ module PrettyTypes =

val NewPrettyTypars: TyparInstantiation -> Typars -> string list -> Typars * TyparInstantiation

val PrettyTyparNames: (Typar -> bool) -> string list -> Typars -> string list
val PrettyTyparNames: pred: (Typar -> bool) -> alreadyInUse: string list -> tps: Typars -> string list

val PrettifyType: TcGlobals -> TType -> TType * TyparConstraintsWithTypars

Expand Down Expand Up @@ -2695,6 +2695,3 @@ val (|EmptyModuleOrNamespaces|_|):
/// Add an System.Runtime.CompilerServices.ExtensionAttribute to the Entity if found via predicate and not already present.
val tryAddExtensionAttributeIfNotAlreadyPresent:
tryFindExtensionAttributeIn: ((Attrib list -> Attrib option) -> Attrib option) -> entity: Entity -> Entity

/// Serialize an entity to a very basic json structure.
val serializeEntity: path: string -> entity: Entity -> unit
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ type Method =
let methodOptions (method: Method) =
match method with
| Method.Sequential -> []
| Method.Graph -> [ "--test:GraphBasedChecking"; "--test:DumpCheckingGraph"; "--deterministic-" ]
| Method.Graph -> [ "--test:GraphBasedChecking"; "--test:DumpCheckingGraph" ]

let withMethod (method: Method) (cu: CompilationUnit) : CompilationUnit =
match cu with
Expand Down