Skip to content
Open
1 change: 1 addition & 0 deletions docs/release-notes/.FSharp.Compiler.Service/11.0.100.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,4 @@

* Added warning FS3884 when a function or delegate value is used as an interpolated string argument. ([PR #19289](https://github.com/dotnet/fsharp/pull/19289))
* Add `#version;;` directive to F# Interactive to display version and environment information. ([Issue #13307](https://github.com/dotnet/fsharp/issues/13307), [PR #19332](https://github.com/dotnet/fsharp/pull/19332))
* Added warning FS3885 when `let ... in` with explicit `in` keyword has a body that extends to subsequent lines, which causes all subsequent lines to become part of the `let` body due to the parser's greedy behavior. ([Issue #7741](https://github.com/dotnet/fsharp/issues/7741), [PR #19501](https://github.com/dotnet/fsharp/pull/19501))
1 change: 1 addition & 0 deletions docs/release-notes/.Language/preview.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

* Warn (FS3884) when a function or delegate value is used as an interpolated string argument, since it will be formatted via `ToString` rather than being applied. ([PR #19289](https://github.com/dotnet/fsharp/pull/19289))
* Added `MethodOverloadsCache` language feature (preview) that caches overload resolution results for repeated method calls, significantly improving compilation performance. ([PR #19072](https://github.com/dotnet/fsharp/pull/19072))
* Warn (FS3885) when `let ... in` with explicit `in` keyword has a body that extends to subsequent lines, causing unexpected scoping. ([Issue #7741](https://github.com/dotnet/fsharp/issues/7741), [PR #19501](https://github.com/dotnet/fsharp/pull/19501))

### Fixed

Expand Down
2 changes: 2 additions & 0 deletions src/Compiler/FSComp.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1809,8 +1809,10 @@ featureWarnWhenFunctionValueUsedAsInterpolatedStringArg,"Warn when a function va
featureMethodOverloadsCache,"Support for caching method overload resolution results for improved compilation performance."
featureImplicitDIMCoverage,"Implicit dispatch slot coverage for default interface member implementations"
featurePreprocessorElif,"#elif preprocessor directive"
featureWarnOnLetInSequenceExpression,"Warn when 'let ... in' is used in a sequence expression and the body extends to subsequent lines"
3880,optsLangVersionOutOfSupport,"Language version '%s' is out of support. The last .NET SDK supporting it is available at https://dotnet.microsoft.com/en-us/download/dotnet/%s"
3881,optsUnrecognizedLanguageFeature,"Unrecognized language feature name: '%s'. Use a valid feature name such as 'NameOf' or 'StringInterpolation'."
3882,lexHashElifMustBeFirst,"#elif directive must appear as the first non-whitespace character on a line"
3883,lexHashElifMustHaveIdent,"#elif directive should be immediately followed by an identifier"
3884,tcFunctionValueUsedAsInterpolatedStringArg,"This expression is a function value. When used in an interpolated string it will be formatted using its 'ToString' method, which is likely not the intended behavior. Consider applying the function to its arguments."
3885,tcLetExpressionWithInHasMultiLineBody,"The use of 'in' in 'let ... in' on a single line followed by additional code on subsequent lines causes all subsequent lines to be part of the 'let' body. This may lead to unexpected scoping. Either remove the 'in' keyword and rely on indentation, or add parentheses to clarify the intended scope."
3 changes: 3 additions & 0 deletions src/Compiler/Facilities/LanguageFeatures.fs
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ type LanguageFeature =
| MethodOverloadsCache
| ImplicitDIMCoverage
| PreprocessorElif
| WarnOnLetInSequenceExpression

/// LanguageVersion management
type LanguageVersion(versionText, ?disabledFeaturesArray: LanguageFeature array) =
Expand Down Expand Up @@ -251,6 +252,7 @@ type LanguageVersion(versionText, ?disabledFeaturesArray: LanguageFeature array)
// Put stabilized features here for F# 11.0 previews via .NET SDK preview channels
LanguageFeature.WarnWhenFunctionValueUsedAsInterpolatedStringArg, languageVersion110
LanguageFeature.PreprocessorElif, languageVersion110
LanguageFeature.WarnOnLetInSequenceExpression, languageVersion110

// Difference between languageVersion110 and preview - 11.0 gets turned on automatically by picking a preview .NET 11 SDK
// previewVersion is only when "preview" is specified explicitly in project files and users also need a preview SDK
Expand Down Expand Up @@ -453,6 +455,7 @@ type LanguageVersion(versionText, ?disabledFeaturesArray: LanguageFeature array)
| LanguageFeature.MethodOverloadsCache -> FSComp.SR.featureMethodOverloadsCache ()
| LanguageFeature.ImplicitDIMCoverage -> FSComp.SR.featureImplicitDIMCoverage ()
| LanguageFeature.PreprocessorElif -> FSComp.SR.featurePreprocessorElif ()
| LanguageFeature.WarnOnLetInSequenceExpression -> FSComp.SR.featureWarnOnLetInSequenceExpression ()

/// Get a version string associated with the given feature.
static member GetFeatureVersionString feature =
Expand Down
1 change: 1 addition & 0 deletions src/Compiler/Facilities/LanguageFeatures.fsi
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ type LanguageFeature =
| MethodOverloadsCache
| ImplicitDIMCoverage
| PreprocessorElif
| WarnOnLetInSequenceExpression

/// LanguageVersion management
type LanguageVersion =
Expand Down
2 changes: 1 addition & 1 deletion src/Compiler/Interactive/fsi.fs
Original file line number Diff line number Diff line change
Expand Up @@ -1532,7 +1532,7 @@ type internal FsiConsoleInput

/// Try to get the first line, if we snarfed it while probing.
member _.TryGetFirstLine() =
let r = firstLine in
let r = firstLine
firstLine <- None
r

Expand Down
20 changes: 18 additions & 2 deletions src/Compiler/SyntaxTree/LexFilter.fs
Original file line number Diff line number Diff line change
Expand Up @@ -1680,8 +1680,24 @@ type LexFilterImpl (
if debug then dprintf "IN at %a (becomes %s)\n" outputPos tokenStartPos (if blockLet then "ODECLEND" else "IN")
if tokenStartCol < offsidePos.Column then warn tokenTup (FSComp.SR.lexfltIncorrentIndentationOfIn())
popCtxt()
// Make sure we queue a dummy token at this position to check if any other pop rules apply
delayToken(pool.UseLocation(tokenTup, ODUMMY token))

if blockLet && lexbuf.SupportsFeature LanguageFeature.WarnOnLetInSequenceExpression then
let nextTokenTup = peekNextTokenTup()
let nextTokenStartPos = startPosOfTokenTup nextTokenTup

if nextTokenStartPos.Line = tokenStartPos.Line then
// When the body expression starts on the same line as the 'in' keyword in light syntax,
// push a new seq block to limit the body scope to that line. This prevents the parser
// from greedily capturing all subsequent lines as part of the let body.
pushCtxtSeqBlock tokenTup AddBlockEnd
else
// Body starts on a new line after 'in' — the user intentionally placed the body
// on the next line, so use standard behavior.
delayToken(pool.UseLocation(tokenTup, ODUMMY token))
else
// Make sure we queue a dummy token at this position to check if any other pop rules apply
delayToken(pool.UseLocation(tokenTup, ODUMMY token))

returnToken tokenLexbufState (if blockLet then ODECLEND(mkSynRange tokenTup.StartPos tokenTup.EndPos, true) else token)

// Balancing rule. Encountering a 'done' balances with a 'do'. i.e. even a non-offside 'done' closes a 'do'
Expand Down
2 changes: 1 addition & 1 deletion src/Compiler/Utilities/HashMultiMap.fs
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ type internal HashMultiMap<'Key, 'Value when 'Key: not null>(size: int, comparer
| _ -> false

member s.Remove(k: 'Key) =
let res = s.ContainsKey(k) in
let res = s.ContainsKey(k)
s.Remove(k)
res

Expand Down
10 changes: 10 additions & 0 deletions src/Compiler/xlf/FSComp.txt.cs.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions src/Compiler/xlf/FSComp.txt.de.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions src/Compiler/xlf/FSComp.txt.es.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions src/Compiler/xlf/FSComp.txt.fr.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions src/Compiler/xlf/FSComp.txt.it.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions src/Compiler/xlf/FSComp.txt.ja.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions src/Compiler/xlf/FSComp.txt.ko.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions src/Compiler/xlf/FSComp.txt.pl.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading