Skip to content

Commit a4e76d1

Browse files
authored
Merge branch 'main' into revert-19710-ilxgen-fallback
2 parents d29902d + fe180de commit a4e76d1

54 files changed

Lines changed: 2649 additions & 225 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎azure-pipelines.yml‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,8 @@ extends:
126126
variables:
127127
- name: _SignType
128128
value: Real
129+
- name: BclPackageVersion
130+
value: '10.0.13'
129131
steps:
130132
- checkout: self
131133
clean: true
@@ -143,6 +145,11 @@ extends:
143145
/p:OfficialBuildId=$(BUILD.BUILDNUMBER)
144146
/p:VisualStudioDropName=$(VisualStudioDropName)
145147
/p:GenerateSbom=true
148+
/p:SystemCollectionsImmutablePackageVersion=$(BclPackageVersion)
149+
/p:SystemCompositionPackageVersion=$(BclPackageVersion)
150+
/p:SystemDiagnosticsDiagnosticSourcePackageVersion=$(BclPackageVersion)
151+
/p:SystemReflectionMetadataPackageVersion=$(BclPackageVersion)
152+
/p:SystemSecurityCryptographyXmlPackageVersion=$(BclPackageVersion)
146153
env:
147154
NativeToolsOnMachine: true
148155
FSHARP_CACHE_OVERRIDE: 256

‎docs/release-notes/.FSharp.Compiler.Service/11.0.200.md‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
* Completion: respect EditorBrowsableAttribute ([PR #20729](https://github.com/dotnet/fsharp/pull/20729))
55
* Runtime-async sequences allow awaits inside `try/with` bodies, filters and handlers, and reject overlapping `MoveNextAsync` calls. ([PR #20655](https://github.com/dotnet/fsharp/pull/20655))
66
* F# Interactive gains a JSON-RPC server mode, `--fsi-server-jsonrpc:<pipe name>`, in which a host submits interactions over a named pipe and receives structured results — diagnostics with positions, escaping exceptions, the values each interaction bound, and the session's own process id — instead of recovering them by looking for a `SERVER-PROMPT>` marker in the output text. Program output continues to flow through the redirected console streams. The pipe admits only the user running the session; `--fsi-server-client-pid:<pid>` names the host process whose exit ends the session. `FsiEvaluationSession` exposes both options as `JsonRpcServerPipeName` and `JsonRpcClientProcessId`. The mode is part of the .NET fsi only. ([PR #20396](https://github.com/dotnet/fsharp/pull/20396))
7+
* Include individual active-pattern cases from unopened modules in pattern completion. ([PR #20719](https://github.com/dotnet/fsharp/pull/20719))
78

89
### Fixed
910

@@ -38,8 +39,10 @@
3839
### Changed
3940

4041
* Revert the IlxGen fallback from [PR #19710](https://github.com/dotnet/fsharp/pull/19710) that silently defaulted type variables missing from the IL type environment. Code generation reports FS0073 again instead of emitting wrong IL, which had masked [Issue #20812](https://github.com/dotnet/fsharp/issues/20812). ([PR #20821](https://github.com/dotnet/fsharp/pull/20821))
42+
* Debugger: emit a call for a self tail call in non-optimized builds ([PR #20782](https://github.com/dotnet/fsharp/pull/20782))
4143
* Remove the unused internal `--test:NoErrorText` switch and its argument-only diagnostic formatting. ([PR #20742](https://github.com/dotnet/fsharp/pull/20742))
4244
* Assign seven previously preview-only features to [F# 11.2](https://fsharp.github.io/fsharp-compiler-docs/release-notes/Language.html#11.2), now the default language version. `default`, `latest`, and `latestmajor` select F# 11.2; explicit `11` and `11.0` retain F# 11.0 behavior. Preview SDK projects use the same compiler default unless `LangVersion` is explicitly set. `FromEndSlicing` remains preview-only. ([PR #20617](https://github.com/dotnet/fsharp/pull/20617))
4345
* Add `SynExceptionDefnReprTrivia` with the range of the `exception` keyword to `SynExceptionDefnRepr`. ([Fantomas Issue #3483](https://github.com/fsprojects/fantomas/issues/3483), [PR #20612](https://github.com/dotnet/fsharp/pull/20612))
4446
* Add `WhenKeyword` to `SynMatchClauseTrivia` with the range of the `when` keyword in match clauses. ([PR #20734](https://github.com/dotnet/fsharp/pull/20734))
4547
* Add `OfKeyword` to `SynUnionCaseTrivia` with the range of the `of` keyword in union cases and exception definitions. ([PR #20635](https://github.com/dotnet/fsharp/pull/20635))
48+
* Optimizer: key debug inline specializations on type arguments and witnesses ([PR #20844](https://github.com/dotnet/fsharp/pull/20844))

‎docs/release-notes/.FSharp.Core/11.0.200.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
### Fixed
66

7+
* Correct `FSharpValue.PreComputeTuplePropertyInfo` to report that struct tuples store elements in fields, not properties, and recommend supported tuple readers instead of reporting a valid index as out of range. ([Issue #20801](https://github.com/dotnet/fsharp/issues/20801), [PR #20815](https://github.com/dotnet/fsharp/pull/20815))
78
* Quotation debug text from `Expr.ToString()`, `Expr.ToString(full)`, and `%A` now prints struct tuple construction as `NewStructTuple`; reference tuples remain `NewTuple`. ([Issue #20800](https://github.com/dotnet/fsharp/issues/20800), [PR #20814](https://github.com/dotnet/fsharp/pull/20814))
89

910
### Changed

‎docs/release-notes/.VisualStudio/18.vNext.md‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
### Added
22

3+
* Suggest active-pattern cases from unopened modules and offer valid Add Open and qualification edits. ([PR #20719](https://github.com/dotnet/fsharp/pull/20719))
34
* Add maintainer-requested F# Apex Visual Studio integration tests on DartLab-1ES CloudTest, using PR pipeline definitions pinned to an explicitly requested commit SHA. ([PR #20625](https://github.com/dotnet/fsharp/pull/20625))
45
* Code-fixes for FS3888 (compiler-semantic attribute on the `.fs` but not the `.fsi`): copy the attribute into the `.fsi`, or remove it from the `.fs`. ([Issue #19560](https://github.com/dotnet/fsharp/issues/19560), [PR #19880](https://github.com/dotnet/fsharp/pull/19880))
56
* Expand `<inheritdoc/>` in IDE tooltips, completion, and signature help, inheriting XML documentation from base classes, interfaces, overridden members, and constructors. ([Issue #19175](https://github.com/dotnet/fsharp/issues/19175), [PR #19188](https://github.com/dotnet/fsharp/pull/19188))
@@ -23,6 +24,7 @@
2324
* Fix `NotSupportedException` in the memory-mapped-file optimization when copying `ReadOnlyMemory` into `MemoryMappedFileViewStream`. ([Issue #20263](https://github.com/dotnet/fsharp/issues/20263))
2425
* Reduce allocations in the VS project options reactor: the command-line options and project options caches and the mailbox reply payloads now hold struct tuples, and `IProjectSite.CompilationBinOutputPath` returns `string voption` picked with a new `Array.tryPickV`. ([PR #20413](https://github.com/dotnet/fsharp/pull/20413))
2526
* Build a single-file project's `OtherOptions` reference flags with one array comprehension instead of two `Array.ofSeq` calls and an `Array.append`. ([PR #20499](https://github.com/dotnet/fsharp/pull/20499))
27+
* Keep concurrent completion requests from mixing their suggestion lists. ([PR #20719](https://github.com/dotnet/fsharp/pull/20719))
2628
* Fix syntax coloring being lost for a whole file when one symbol resolves into metadata that could not be read. ([Issue #20269](https://github.com/dotnet/fsharp/issues/20269), [PR #20274](https://github.com/dotnet/fsharp/pull/20274))
2729
* Go To Definition into an F# project built with a path map (`DeterministicSourcePaths` or `PathMap`) opens its source instead of a generated signature: the IDE no longer applies `--pathmap` to the project options it checks with. ([PR #20470](https://github.com/dotnet/fsharp/pull/20470))
2830
* Fix completion after a closed backticked identifier on the same line. ([PR #20785](https://github.com/dotnet/fsharp/issues/20785))
@@ -31,6 +33,7 @@
3133

3234
* Rename "inline hints" to "inlay hints" in VS options for consistency with industry terminology. ([PR #19318](https://github.com/dotnet/fsharp/pull/19318))
3335
* Unused analyzers: disable in VS when file has errors ([PR #19892](https://github.com/dotnet/fsharp/pull/19892))
36+
* Reuse current-project symbol catalogues for completion and Add Open requests that share a file-check result. ([PR #20719](https://github.com/dotnet/fsharp/pull/20719))
3437
* Move to Roslyn's unified ExternalAccess library ([PR #20099](https://github.com/dotnet/fsharp/pull/20099))
3538
* Remove trailing whitespace from source files. No functional change: whitespace inside string literals and inactive `#if` regions is preserved. ([PR #20355](https://github.com/dotnet/fsharp/pull/20355))
3639
* The VS project options reactor keeps single-file and script project options in a named record instead of a five-place tuple, and its text-view subscription plumbing uses `voption` instead of `option`. ([PR #20455](https://github.com/dotnet/fsharp/pull/20455))

‎eng/Packages.props‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
<!-- Security: pin the transitive MessagePack (pulled via StreamJsonRpc) to a patched version.
3131
Versions < 2.5.301 have known vulnerabilities (NU1902/NU1903). Transitive pinning applies it
3232
wherever StreamJsonRpc is used (FSharp.Compiler.LanguageServer and the CLASP.Framework.Proxy). -->
33-
<PackageVersion Include="MessagePack" Version="2.5.302" />
33+
<PackageVersion Include="MessagePack" Version="2.5.303" />
3434
<PackageVersion Include="Microsoft.Build" Version="$(MicrosoftBuildVersion)" />
3535
<PackageVersion Include="Microsoft.Build.Framework" Version="$(MicrosoftBuildFrameworkVersion)" />
3636
<PackageVersion Include="Microsoft.Build.Tasks.Core" Version="$(MicrosoftBuildTasksCoreVersion)" />

‎eng/Version.Details.xml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<Dependencies>
3-
<Source Uri="https://github.com/dotnet/dotnet" Mapping="fsharp" Sha="a69d27567bd8be379e504329c965b9ca3fdf53fd" BarId="337438" />
3+
<Source Uri="https://github.com/dotnet/dotnet" Mapping="fsharp" Sha="ee344f85ef890dd92974e9b93d75906f1f8c39f3" BarId="337683" />
44
<ProductDependencies>
55
<Dependency Name="Microsoft.Build" Version="18.13.0-1.26516.14">
66
<Uri>https://github.com/dotnet/msbuild</Uri>

‎src/Compiler/Checking/NameResolution.fsi‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1009,5 +1009,7 @@ val GetVisibleNamespacesAndModulesAtPoint:
10091009

10101010
val IsItemResolvable: NameResolver -> NameResolutionEnv -> range -> AccessorDomain -> string list -> Item -> bool
10111011

1012+
val ItemIsUnseen: AccessorDomain -> TcGlobals -> ImportMap -> range -> allowUnseen: UnseenItems -> Item -> bool
1013+
10121014
val TrySelectExtensionMethInfoOfILExtMem:
10131015
range -> ImportMap -> TType -> TyconRef * MethInfo * ExtensionMethodPriority -> MethInfo option

‎src/Compiler/CodeGen/IlxGen.fs‎

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4606,7 +4606,10 @@ and GenApp (cenv: cenv) cgbuf eenv (f, fty, tyargs, curriedArgs, m) sequel =
46064606

46074607
match (stripDebugPoints f, tyargs, curriedArgs) with
46084608
// Look for tailcall to turn into branch
4609-
| Expr.Val(v, _, _), _, _ when IsBranchTailcall cenv eenv (v, tyargs, curriedArgs) sequel ->
4609+
| Expr.Val(v, _, _), _, _ when
4610+
cenv.options.localOptimizationsEnabled
4611+
&& IsBranchTailcall cenv eenv (v, tyargs, curriedArgs) sequel
4612+
->
46104613
let kind, mark = ListAssoc.find g.valRefEq v eenv.innerVals // already checked above in when guard
46114614

46124615
// Generate the arguments for the direct tail call.
@@ -4803,7 +4806,11 @@ and GenApp (cenv: cenv) cgbuf eenv (f, fty, tyargs, curriedArgs, m) sequel =
48034806
if isNil laterArgs && not isSelfInit then
48044807
let isDllImport = IsValRefIsDllImport g vref
48054808
let hasByrefArg = mspec.FormalArgTypes |> List.exists IsILTypeByref
4806-
let makesNoCriticalTailcalls = vref.MakesNoCriticalTailcalls
4809+
4810+
let makesNoCriticalTailcalls =
4811+
vref.MakesNoCriticalTailcalls
4812+
&& not (IsBranchTailcall cenv eenv (vref, tyargs, curriedArgs) sequel)
4813+
48074814
let hasStructObjArg = (boxity = AsValue) && takesInstanceArg
48084815

48094816
CanTailcall(

‎src/Compiler/FSharp.Compiler.Service.fsproj‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -580,8 +580,6 @@
580580
<Compile Include="Service\ServiceCompilerDiagnostics.fsi" />
581581
<Compile Include="Service\ServiceCompilerDiagnostics.fs" />
582582
<Compile Include="Service\ServiceConstants.fs" />
583-
<Compile Include="Service\ServiceDeclarationLists.fsi" />
584-
<Compile Include="Service\ServiceDeclarationLists.fs" />
585583
<Compile Include="Service\ServiceLexing.fsi" />
586584
<Compile Include="Service\ServiceLexing.fs" />
587585
<Compile Include="Service\ServiceParseTreeWalk.fsi" />
@@ -598,6 +596,8 @@
598596
<Compile Include="Service\FSharpParseFileResults.fs" />
599597
<Compile Include="Service\ServiceParsedInputOps.fsi" />
600598
<Compile Include="Service\ServiceParsedInputOps.fs" />
599+
<Compile Include="Service\ServiceDeclarationLists.fsi" />
600+
<Compile Include="Service\ServiceDeclarationLists.fs" />
601601
<Compile Include="Service\ServiceAssemblyContent.fsi" />
602602
<Compile Include="Service\ServiceAssemblyContent.fs" />
603603
<Compile Include="Service\ServiceXmlDocParser.fsi" />

‎src/Compiler/Optimize/Optimizer.fs‎

Lines changed: 40 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -443,7 +443,7 @@ type cenv =
443443

444444
realsig: bool
445445

446-
specializedInlineVals: HashMultiMap<Stamp, TType * Expr>
446+
specializedInlineVals: HashMultiMap<Stamp, TType list * Expr>
447447

448448
forcedInlineVals: Dictionary<Stamp, bool>
449449

@@ -462,12 +462,12 @@ type IncrementalOptimizationEnv =
462462
{ /// An identifier to help with name generation
463463
latestBoundId: Ident option
464464

465-
/// Prevents recursive inlining/specialization. Maps lambda ID to a list of specialized types
465+
/// Prevents recursive inlining/specialization. Maps lambda ID to a list of instantiations
466466
/// currently being processed. An empty list means "block unconditionally" (used by normal
467467
/// inlining and non-concrete debug specialization). A non-empty list means "block only these
468-
/// specific type specializations" (used by concrete debug specialization, allowing different
469-
/// type instantiations of the same function to proceed).
470-
dontInline: Map<Stamp, TType list>
468+
/// specific instantiations" (used by concrete debug specialization, allowing different
469+
/// instantiations of the same function to proceed).
470+
dontInline: Map<Stamp, TType list list>
471471

472472
/// Recursively bound vars. If an sub-expression that is a candidate for method splitting
473473
/// contains any of these variables then don't split it, for fear of mucking up tailcalls.
@@ -2749,6 +2749,29 @@ let FloatInlineIfLambdaCaptures g expr =
27492749
rebind bind.Expr
27502750
| _ -> expr
27512751

2752+
let private traitConstraintsOfTyarg tyarg =
2753+
match tyarg with
2754+
// The witnesses selected for a call live in the constraint cells of its solved type arguments.
2755+
| TType_var(tp, _) ->
2756+
tp.Constraints
2757+
|> List.choose (function
2758+
| TyparConstraint.MayResolveMember(traitInfo, _) -> Some traitInfo
2759+
| _ -> None)
2760+
| _ -> []
2761+
2762+
let private solvedTraitEquiv g aenv (traitInfo1: TraitConstraintInfo) (traitInfo2: TraitConstraintInfo) =
2763+
traitsAEquiv g aenv traitInfo1 traitInfo2
2764+
&& traitSlnAEquiv g aenv traitInfo1.Solution traitInfo2.Solution
2765+
2766+
let private tyargEquiv g aenv tyarg1 tyarg2 =
2767+
typeAEquiv g aenv tyarg1 tyarg2
2768+
&& List.lengthsEqAndForall2 (solvedTraitEquiv g aenv) (traitConstraintsOfTyarg tyarg1) (traitConstraintsOfTyarg tyarg2)
2769+
2770+
let private specializationKeyEquiv g tyargs1 tyargs2 =
2771+
// Under --checknulls the specialized body keeps or drops null guards by the nullness of the type arguments.
2772+
let aenv = TypeEquivEnv.EmptyWithNullChecks g
2773+
List.lengthsEqAndForall2 (tyargEquiv g aenv) tyargs1 tyargs2
2774+
27522775
/// Optimize/analyze an expression
27532776
let rec OptimizeExpr cenv (env: IncrementalOptimizationEnv) expr =
27542777
cenv.stackGuard.Guard(fun () ->
@@ -3950,10 +3973,9 @@ and TryInlineApplication cenv env finfo (valExpr: Expr) (tyargs: TType list, arg
39503973
|| (not alwaysInline
39513974
&& vref.ShouldInline
39523975
&& not (shouldForceInlineInDebug cenv env vref)) ->
3953-
let traits =
3976+
let hasNoTraits =
39543977
let tps, _ = tryDestForallTy g vref.Type
3955-
GetTraitConstraintInfosOfTypars g tps
3956-
let hasNoTraits = traits.IsEmpty
3978+
GetTraitConstraintInfosOfTypars g tps |> List.isEmpty
39573979

39583980
// Direct-calling an SRTP callee is only safe when every tyarg is a bare typar: then the
39593981
// callee's SRTP constraints land on the caller's own typars and IlxGen rewrites the
@@ -4027,16 +4049,16 @@ and TryInlineApplication cenv env finfo (valExpr: Expr) (tyargs: TType list, arg
40274049

40284050
let allTyargsAreConcrete = List.isEmpty freeTypars
40294051

4030-
// Proceed with specialization only if this (stamp, type) pair isn't already being
4052+
// Proceed with specialization only if this (stamp, instantiation) pair isn't already being
40314053
// processed. For concrete type args, allow different type instantiations of the same
40324054
// function (e.g. sum<int, int->int> can call sum<int, int> in its body). For
40334055
// non-concrete type args, never specialize recursively.
40344056
let canSpecialize =
40354057
match Map.tryFind origLambdaId env.dontInline with
4036-
| Some tys ->
4058+
| Some insts ->
40374059
allTyargsAreConcrete &&
4038-
not tys.IsEmpty &&
4039-
not (tys |> List.exists (typeEquiv g specLambdaTy))
4060+
not insts.IsEmpty &&
4061+
not (insts |> List.exists (specializationKeyEquiv g tyargs))
40404062
| None -> true
40414063

40424064
if not canSpecialize then
@@ -4046,25 +4068,20 @@ and TryInlineApplication cenv env finfo (valExpr: Expr) (tyargs: TType list, arg
40464068
else
40474069

40484070
let specialize () =
4049-
let existingTypes = defaultArg (Map.tryFind origLambdaId argEnv.dontInline) []
4050-
let types = if allTyargsAreConcrete then specLambdaTy :: existingTypes else []
4071+
let existingInsts = defaultArg (Map.tryFind origLambdaId argEnv.dontInline) []
4072+
let insts = if allTyargsAreConcrete then tyargs :: existingInsts else []
40514073
let env =
40524074
{ argEnv with
4053-
dontInline = Map.add origLambdaId types argEnv.dontInline }
4075+
dontInline = Map.add origLambdaId insts argEnv.dontInline }
40544076
OptimizeExpr cenv env specLambda |> fst
40554077

4056-
// The type-only cache key does not include selected SRTP witnesses.
4057-
let canCacheSpecialization =
4058-
allTyargsAreConcrete &&
4059-
(hasNoTraits || not (g.langVersion.SupportsFeature LanguageFeature.ExtensionConstraintSolutions))
4060-
40614078
let specLambdaR =
4062-
if canCacheSpecialization then
4063-
match cenv.specializedInlineVals.FindAll(origLambdaId) |> List.tryFind (fun (ty, _) -> typeEquiv g ty specLambdaTy) with
4079+
if allTyargsAreConcrete then
4080+
match cenv.specializedInlineVals.FindAll(origLambdaId) |> List.tryFind (fun (inst, _) -> specializationKeyEquiv g inst tyargs) with
40644081
| Some (_, body) -> copyExpr g CloneAll body
40654082
| None ->
40664083
let specLambdaR = specialize ()
4067-
cenv.specializedInlineVals.Add(origLambdaId, (specLambdaTy, specLambdaR))
4084+
cenv.specializedInlineVals.Add(origLambdaId, (tyargs, specLambdaR))
40684085
specLambdaR
40694086
else
40704087
specialize ()

0 commit comments

Comments
 (0)