-
Notifications
You must be signed in to change notification settings - Fork 789
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Deduplicate module names #2728
Deduplicate module names #2728
Conversation
@alfonsogarciacaro You can always say |
@alfonsogarciacaro you can run those failing tests locally, no need to wait long time until CI finishes. |
@cartermp @vasily-kirichenko The build script refuses to run the tests locally for me. |
@alfonsogarciacaro Install NUnit 3 test runner adapter VS extension, find a failing test in test explorer and run it. |
tests now work on my machine. |
@alfonsogarciacaro it looks it's one step further. It can't write down the IL because the module is twice in the ILTypeDef list @dsyme it's failing at: |
I think the whole approach is wrong. These implicit modules need to get different internal names. I think we discussed that already somewhere. I will try to look deeper tomorrow. But the qname sorter is definitely too late and fixes only symptoms |
A couple of notes:
|
@alfonsogarciacaro I'll wirk on this first thing in the morning, followed by the stack overflow issue. I understand now how important this is for Fable 1.0 |
@dsyme Awesome, thank you! |
I think I fixed it with this deduplication trick: https://github.com/alfonsogarciacaro/visualfsharp/pull/4/commits/7fcc07d50ade37f9e3269c73dc77ecc48309343c#diff-d58c6e25aebd2ff64de33a050b0228ccR1766 |
OK. I think now Impl and Sig files are synced and deduplicated. Ready for review |
Open Question: do we need to do the same for fsi? |
src/absil/ilwrite.fs
Outdated
@@ -471,7 +471,8 @@ type MetadataTable<'T> = | |||
t |> Array.iteri (fun i x -> h.[x] <- (i+1)) | |||
|
|||
member tbl.AddUniqueEntry nm geterr x = | |||
if tbl.dict.ContainsKey x then failwith ("duplicate entry '"+geterr x+"' in "+nm+" table") | |||
if tbl.dict.ContainsKey x then | |||
failwith ("duplicate entry '" + geterr x + "' in " + nm + " table") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
failwithf
maybe?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just changed alignment
src/absil/ilwrite.fs
Outdated
@@ -3547,7 +3548,7 @@ let writeBinaryAndReportMappings (outfile, ilg: ILGlobals, pdbfile: string optio | |||
// Store the public key from the signer into the manifest. This means it will be written | |||
// to the binary and also acts as an indicator to leave space for delay sign | |||
|
|||
reportTime showTimes "Write Started"; | |||
reportTime showTimes "Write Started" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💪
src/fsharp/ast.fs
Outdated
|
||
member x.Range = | ||
let (QualifiedNameOfFile t) = x | ||
t.idRange |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I find the old code more compact and readable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed on this one
src/fsharp/fsc.fs
Outdated
@@ -303,7 +303,7 @@ module InterfaceFileWriter = | |||
fprintfn os "#light" | |||
fprintfn os "" | |||
|
|||
for (TImplFile(_, _, mexpr, _, _)) in declaredImpls do | |||
for (TImplFile(_fileName, _, _, mexpr, _, _)) in declaredImpls do |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Other unused fields are ignored with _
, so should _fileName
.
src/fsharp/fsc.fs
Outdated
|
||
let inputs = | ||
// Deduplicate module names | ||
let seen = Dictionary<_,Set<_>>() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's unclear what type this seen
thing has. Could you add a comment or, at least, types?
src/fsharp/fsc.fs
Outdated
let qualifiedNameOfFile = if count = 1 then qualifiedNameOfFile else QualifiedNameOfFile(Ident(id.idText + "___" + count.ToString(),id.idRange)) | ||
let input = ParsedInput.SigFile (ParsedSigFileInput.ParsedSigFileInput(fileName,qualifiedNameOfFile,scopedPragmas,hashDirectives,modules)) | ||
input,x | ||
| _ -> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These two branches have a lot in common. Maybe it's worth to extract some logic in a function or two?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, my preference is to encapsulate such name generators (though I haven't done it particularly well - see the ones in ast.fs which are not suitable here since they use range line number information). So
type UniqueNameGenerator() =
let seen = Dictionary...
member x.GetName(text) =
match seen.TryGetValue text with
| true, paths ->
let count = if paths.Contains path then paths.Count else paths.Count + 1
seen.[text] <- Set.add path paths
if count = 1 then text else text + "___" + count.ToString()
etc
src/fsharp/fsc.fs
Outdated
@@ -1812,7 +1846,7 @@ let main1(Args (ctok, tcGlobals, tcImports: TcImports, frameworkTcImports, gener | |||
// it as the updated global error logger and never remove it | |||
let oldLogger = errorLogger | |||
let errorLogger = | |||
let scopedPragmas = [ for (TImplFile(_, pragmas, _, _, _)) in typedImplFiles do yield! pragmas ] | |||
let scopedPragmas = [ for (TImplFile(_fileName, _, pragmas, _, _, _)) in typedImplFiles do yield! pragmas ] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same, just use _
.
src/fsharp/fsc.fs
Outdated
error(Error(FSComp.SR.fscProblemWritingBinary(outfile, msg), rangeCmdArgs)) | ||
with e -> | ||
errorRecoveryNoRange e | ||
exiter.Exit 1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why nested try..with
? Is it for handling possible exceptions thrown by error(Error(FSComp.SR.fscProblemWritingBinary(outfile, msg), rangeCmdArgs))
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
He's just changing the indenting in this case ( @forki - perhaps remove the formatting changes to make the PR minimal? I don't mind either way though)
It's hard to review because of lots of whitespace changes. |
As written in slack I will revert all changes that are unrelated. Stay
tuned
Am 31.03.2017 14:11 schrieb "Vasily Kirichenko" <notifications@github.com>:
… It's hard to review because of lots of whitespace changes.
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
<#2728 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AADgNBNVvQBNHihKofKtkOLpdXX7aW30ks5rrO1fgaJpZM4MtEnP>
.
|
@forki Stepping back a bit, this whole QualifiedNameOfFile stuff is really irritating. AFAICS it's only used for the names given to these internally generated classes: That's all. Just a simple name. So easy. I believe the only issue is that name must match between the processing of the signature of implementation - because other files are allowed to access straight into these items - e.g. when taking the address of a mutable static fields. So on a quick glance your approach is basically right - generate nice names but be careful about de-duplicating. That said, there's probably a much easier way to do this all (the whole thing, not just the de-duplicating) given the end result is so simple, or even just to somehow get rid of the information altogether |
My approach is to try to not break backwards compatibility. ;-) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
minor changes requested
src/fsharp/ast.fs
Outdated
|
||
member x.Range = | ||
let (QualifiedNameOfFile t) = x | ||
t.idRange |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed on this one
src/fsharp/fsc.fs
Outdated
error(Error(FSComp.SR.fscProblemWritingBinary(outfile, msg), rangeCmdArgs)) | ||
with e -> | ||
errorRecoveryNoRange e | ||
exiter.Exit 1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
He's just changing the indenting in this case ( @forki - perhaps remove the formatting changes to make the PR minimal? I don't mind either way though)
src/fsharp/fsc.fs
Outdated
let qualifiedNameOfFile = if count = 1 then qualifiedNameOfFile else QualifiedNameOfFile(Ident(id.idText + "___" + count.ToString(),id.idRange)) | ||
let input = ParsedInput.SigFile (ParsedSigFileInput.ParsedSigFileInput(fileName,qualifiedNameOfFile,scopedPragmas,hashDirectives,modules)) | ||
input,x | ||
| _ -> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, my preference is to encapsulate such name generators (though I haven't done it particularly well - see the ones in ast.fs which are not suitable here since they use range line number information). So
type UniqueNameGenerator() =
let seen = Dictionary...
member x.GetName(text) =
match seen.TryGetValue text with
| true, paths ->
let count = if paths.Contains path then paths.Count else paths.Count + 1
seen.[text] <- Set.add path paths
if count = 1 then text else text + "___" + count.ToString()
etc
Agreed. |
@alfonsogarciacaro You say you need this for Fable 1.0 - I presume you need it integrated to FCS? thanks |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cool! So how do we get that into FCS? ;-)
@forki has removed the whitespace changes and I've tried to implement some of the comments, please review. @dsyme Yes, this would be needed for FCS. I can send a PR there but I guess it's no use, as changes in this repo will flow to FCS anyway. It would be ideal if a new FCS version is pushed to nuget, but it it's cumbersome to do it at this moment, I can just fork it and add the change manually for the time being. |
@alfonsogarciacaro Please submit just the fix to FCS. Don't worry about the test |
@alfonsogarciacaro Kevin |
Giving it a shot at continuing #2686. Apparently I cannot run the tests locally so let see what CI says.