Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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: 2 additions & 0 deletions docs/release-notes/.FSharp.Compiler.Service/11.0.200.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
### Fixed

* Capture diagnostics emitted when transparent project checking finishes a project, including FS0247 for namespace-module name collisions. ([Issue #6036](https://github.com/dotnet/fsharp/issues/6036), [PR #20706](https://github.com/dotnet/fsharp/pull/20706))
* A project reusing cached framework imports is checked with its own `--pathmap` instead of the map of the project that filled the cache, so the ranges of its in-memory reference data name its real files. ([Issue #20474](https://github.com/dotnet/fsharp/issues/20474), [PR #20476](https://github.com/dotnet/fsharp/pull/20476))
* `GetDeclarationLocation` no longer names the compile-time directory twice for a declaration in an assembly built with a relative `--pathmap`. Such a build maps the directory it compiled in along with its file names, so a file from under that directory already starts with it, and joining the two left a path that matches no file. Other relative names, such as the `#line` names that compilers before F# 10 wrote, are still resolved against that directory. ([PR #20518](https://github.com/dotnet/fsharp/pull/20518))
* Split Linux CoreCLR CI into two parallel test batches to reduce test turnaround time. ([PR #20587](https://github.com/dotnet/fsharp/pull/20587))
* Fix `NativePtr.stackalloc` used inside the `with` handler, filter or `finally` block of a `try` expression producing an assembly that throws `InvalidProgramException` at method load. Direct or mandatory-inline allocations are now reported at compile time as error FS3924; calls to non-inline allocation helpers, including handler-local helpers, remain legal and retain their method boundary during inlining and let-binding elimination. ([Issue #20295](https://github.com/dotnet/fsharp/issues/20295), [PR #20491](https://github.com/dotnet/fsharp/pull/20491))
* `FsiEvaluationSession.EvalInteraction` and `EvalInteractionNonThrowing` evaluate every `;;`-separated interaction in the text they are given, as their documentation has always said, instead of silently discarding everything after the first. ([PR #20396](https://github.com/dotnet/fsharp/pull/20396))
Expand Down
11 changes: 6 additions & 5 deletions src/Compiler/Service/IncrementalBuild.fs
Original file line number Diff line number Diff line change
Expand Up @@ -560,12 +560,13 @@ type FrameworkImportsCache(size) =
let node = this.GetNode(tcConfig, frameworkDLLs, nonFrameworkResolutions)
let! tcGlobals, frameworkTcImports = node.GetOrComputeValue()

// If the tcGlobals was loaded from a different project, langVersion and realsig may be different
// for each cached project. So here we create a new tcGlobals, with the existing framework values
// and updated realsig and langversion
// If the tcGlobals was loaded from a different project, langVersion, realsig and pathMap may be
// different for each cached project. So here we create a new tcGlobals, with the existing framework
// values and the updated realsig, langversion and pathMap
let tcGlobals =
if tcGlobals.langVersion <> tcConfig.langVersion
|| tcGlobals.realsig <> tcConfig.realsig then
|| tcGlobals.realsig <> tcConfig.realsig
|| tcGlobals.pathMap <> tcConfig.pathMap then
TcGlobals(
tcGlobals.compilingFSharpCore,
tcGlobals.ilg,
Expand All @@ -577,7 +578,7 @@ type FrameworkImportsCache(size) =
tcGlobals.tryFindSysTypeCcuHelper,
tcGlobals.emitDebugInfoInQuotations,
tcGlobals.noDebugAttributes,
tcGlobals.pathMap,
tcConfig.pathMap,
tcConfig.langVersion,
tcConfig.realsig,
tcConfig.compilationMode
Expand Down
9 changes: 5 additions & 4 deletions src/Compiler/Service/TransparentCompiler.fs
Original file line number Diff line number Diff line change
Expand Up @@ -964,13 +964,14 @@ type internal TransparentCompiler
// Prepare the frameworkTcImportsCache
let! tcGlobals, frameworkTcImports = ComputeFrameworkImports tcConfig frameworkDLLs nonFrameworkResolutions

// If the tcGlobals was loaded from a different project, langVersion and realsig may be different
// for each cached project. So here we create a new tcGlobals, with the existing framework values
// and updated realsig and langversion
// If the tcGlobals was loaded from a different project, langVersion, realsig and pathMap may be
// different for each cached project. So here we create a new tcGlobals, with the existing
// framework values and the updated realsig, langversion and pathMap
let tcGlobals =
if
tcGlobals.langVersion <> tcConfig.langVersion
|| tcGlobals.realsig <> tcConfig.realsig
|| tcGlobals.pathMap <> tcConfig.pathMap
then
TcGlobals(
tcGlobals.compilingFSharpCore,
Expand All @@ -983,7 +984,7 @@ type internal TransparentCompiler
tcGlobals.tryFindSysTypeCcuHelper,
tcGlobals.emitDebugInfoInQuotations,
tcGlobals.noDebugAttributes,
tcGlobals.pathMap,
tcConfig.pathMap,
tcConfig.langVersion,
tcConfig.realsig,
tcConfig.compilationMode
Expand Down
82 changes: 80 additions & 2 deletions src/Compiler/Symbols/SymbolHelpers.fs
Original file line number Diff line number Diff line change
Expand Up @@ -226,18 +226,96 @@ module internal SymbolHelpers =
// This is not expected: NewDef only occurs within checking
| Item.NewDef _ -> None

/// The module or type of another assembly that an item is declared in, or the item itself when it is one.
let rec declaringEntityOfItem d =
let ofValRef (vref: ValRef) =
if vref.IsLocalRef then ValueNone else ValueSome vref.nlr.EnclosingEntity

let ofArbitraryValRef (vref: ValRef option) =
match vref with
| Some vref -> ofValRef vref
| None -> ValueNone

match d with
| Item.Value vref
| Item.CustomBuilder (_, vref) -> ofValRef vref
| Item.ActivePatternCase apref -> ofValRef apref.ActivePatternVal
| Item.UnionCase(ucinfo, _)
| Item.UnionCaseField (ucinfo, _) -> ValueSome ucinfo.TyconRef
| Item.RecdField rfinfo -> ValueSome rfinfo.TyconRef
| Item.ExnCase tcref -> ValueSome tcref
| Item.Event einfo -> ofArbitraryValRef einfo.ArbitraryValRef
| Item.Property(info = pinfo :: _) -> ofArbitraryValRef pinfo.ArbitraryValRef
| Item.MethodGroup(_, minfo :: _, _)
| Item.CtorGroup(_, minfo :: _) ->
match minfo.ArbitraryValRef with
| Some vref -> ofValRef vref
| None -> ValueSome minfo.DeclaringTyconRef
| Item.Types(_, ty :: _)
| Item.DelegateCtor ty ->
match tryNiceEntityRefOfTyOption ty with
| Some tcref -> ValueSome tcref
| None -> ValueNone
| Item.ModuleOrNamespaces (eref :: _)
| Item.UnqualifiedType (eref :: _) -> ValueSome eref
| Item.SetterArg (_, item) -> declaringEntityOfItem item
| _ -> ValueNone

/// The module or type directly under a namespace that an entity of another assembly lies in, or is.
let outermostDeclaringEntity (eref: EntityRef) =
if eref.IsLocalRef then
ValueNone
else
let (NonLocalEntityRef(ccu, path)) = eref.nlr

let rec search length =
if length > path.Length then
ValueNone
else
match NonLocalEntityRef(ccu, path[.. length - 1]).TryDeref(canError = false) with
| ValueSome entity when not entity.IsNamespace -> ValueSome entity
| ValueSome _ -> search (length + 1)
| ValueNone -> ValueNone

search 1

/// Work out the source file for an item and fix it up relative to the CCU if it is relative.
let fileNameOfItem (g: TcGlobals) qualProjectDir (m: range) h =
let file = m.FileName
if verbose then dprintf "file stored in metadata is '%s'\n" file

// Compilers before F# 10 named whatever follows a #line directive by the directive, and such a name can
// start with the directory too. The directive leaves the item in another file than the module or type
// around it, though, where a compiled file holds both. An entity read from a signature says nothing
// of the file its implementation is in.
let namedByLineDirective () =
match declaringEntityOfItem h |> ValueOption.bind outermostDeclaringEntity with
| ValueSome entity ->
let declaredIn = entity.Range

m.FileIndex <> declaredIn.FileIndex
&& not (CompilerConfig.FSharpSigFileSuffixes |> List.exists (FileSystemUtils.checkSuffix declaredIn.FileName))
| ValueNone -> false

// A relative name is relative to the directory the assembly was compiled in, as the #line names that
// compilers before F# 10 wrote are. A path map rewrites that directory along with the files compiled
// from under it, though, so such a file already starts with the directory: joining them repeats it.
let underDirectory (dir: string) =
let startsWithDirectory =
file.Length > dir.Length
&& file.StartsWithOrdinal dir
&& (file[dir.Length] = '\\' || file[dir.Length] = '/')

if startsWithDirectory && not (namedByLineDirective ()) then file else Path.Combine(dir, file)

if not (FileSystem.IsPathRootedShim file) then
match ccuOfItem g h with
| Some ccu ->
Path.Combine(ccu.SourceCodeDirectory, file)
underDirectory ccu.SourceCodeDirectory
| None ->
match qualProjectDir with
| None -> file
| Some dir -> Path.Combine(dir, file)
| Some dir -> underDirectory dir
else file

let ParamNameAndTypesOfUnaryCustomOperation g minfo =
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. -->
<Project Sdk="Microsoft.NET.Sdk">

Expand Down Expand Up @@ -549,6 +549,7 @@
<Compile Include="Signatures\MemberTests.fs" />
<Compile Include="StaticLinking\StaticLinking.fs" />
<Compile Include="FSharpChecker\CommonWorkflows.fs" />
<Compile Include="FSharpChecker\PathMap.fs" />
<Compile Include="FSharpChecker\ProjectSnapshot.fs" />
<Compile Include="FSharpChecker\TransparentCompiler.fs" />
<Compile Include="FSharpChecker\SymbolUse.fs" />
Expand Down
Loading
Loading