Skip to content

Commit fb7617d

Browse files
committed
Merge remote-tracking branch 'upstream/main' into merges/main-to-release/dev17.8
2 parents 9db5a67 + 4a9701c commit fb7617d

31 files changed

+617
-41
lines changed

global.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
"Microsoft.VisualStudio.Component.FSharp"
1313
]
1414
},
15-
"xcopy-msbuild": "17.6.0-2"
15+
"xcopy-msbuild": "17.7.0"
1616
},
1717
"native-tools": {
1818
"perl": "5.38.0.1"

src/Compiler/SyntaxTree/LexFilter.fs

+53-26
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ type Context =
4646
| CtxtElse of Position
4747
| CtxtDo of Position
4848
| CtxtInterfaceHead of Position
49-
| CtxtTypeDefns of Position // 'type <here> =', not removed when we find the "="
49+
| CtxtTypeDefns of Position * equalsEndPos: Position option // 'type <here> =', not removed when we find the "="
5050

5151
| CtxtNamespaceHead of Position * token
5252
| CtxtModuleHead of Position * token * LexingModuleAttributes * isNested: bool
@@ -69,7 +69,7 @@ type Context =
6969
member c.StartPos =
7070
match c with
7171
| CtxtNamespaceHead (p, _) | CtxtModuleHead (p, _, _, _) | CtxtException p | CtxtModuleBody (p, _) | CtxtNamespaceBody p
72-
| CtxtLetDecl (_, p) | CtxtDo p | CtxtInterfaceHead p | CtxtTypeDefns p | CtxtParen (_, p) | CtxtMemberHead p | CtxtMemberBody p
72+
| CtxtLetDecl (_, p) | CtxtDo p | CtxtInterfaceHead p | CtxtTypeDefns(p, _) | CtxtParen (_, p) | CtxtMemberHead p | CtxtMemberBody p
7373
| CtxtWithAsLet p
7474
| CtxtWithAsAugment p
7575
| CtxtMatchClauses (_, p) | CtxtIf p | CtxtMatch p | CtxtFor p | CtxtWhile p | CtxtWhen p | CtxtFunction p | CtxtFun p | CtxtTry p | CtxtThen p | CtxtElse p | CtxtVanilla (p, _)
@@ -742,7 +742,7 @@ type LexFilterImpl (
742742

743743
//let indexerNotationWithoutDot = lexbuf.SupportsFeature LanguageFeature.IndexerNotationWithoutDot
744744

745-
let tryPushCtxt strict tokenTup (newCtxt: Context) =
745+
let tryPushCtxt strict ignoreIndent tokenTup (newCtxt: Context) =
746746
let rec undentationLimit strict stack =
747747
match newCtxt, stack with
748748
| _, [] -> PositionWithColumn(newCtxt.StartPos, -1)
@@ -960,8 +960,10 @@ type LexFilterImpl (
960960
// These contexts can have their contents exactly aligning
961961
| _, (CtxtParen _ | CtxtFor _ | CtxtWhen _ | CtxtWhile _ | CtxtTypeDefns _ | CtxtMatch _ | CtxtModuleBody (_, true) | CtxtNamespaceBody _ | CtxtTry _ | CtxtMatchClauses _ | CtxtSeqBlock _ as limitCtxt :: _)
962962
-> PositionWithColumn(limitCtxt.StartPos, limitCtxt.StartCol)
963-
963+
964964
let isCorrectIndent =
965+
if ignoreIndent then true else
966+
965967
match newCtxt with
966968
// Don't bother to check pushes of Vanilla blocks since we've
967969
// always already pushed a SeqBlock at this position.
@@ -992,7 +994,7 @@ type LexFilterImpl (
992994
true
993995

994996
let pushCtxt tokenTup newCtxt =
995-
tryPushCtxt false tokenTup newCtxt |> ignore
997+
tryPushCtxt false false tokenTup newCtxt |> ignore
996998

997999
let rec popCtxt() =
9981000
match offsideStack with
@@ -1008,6 +1010,10 @@ type LexFilterImpl (
10081010

10091011
let replaceCtxt p ctxt = popCtxt(); pushCtxt p ctxt
10101012

1013+
let replaceCtxtIgnoreIndent p ctxt =
1014+
popCtxt()
1015+
tryPushCtxt false true p ctxt |> ignore
1016+
10111017
//----------------------------------------------------------------------------
10121018
// Peek ahead at a token, either from the old lexer or from our delayedStack
10131019
//--------------------------------------------------------------------------
@@ -1679,7 +1685,7 @@ type LexFilterImpl (
16791685
// | B
16801686
//
16811687
// <TOKEN> <-- close the type context sequence block here *)
1682-
| _, CtxtTypeDefns posType :: _ when offsidePos.Column = posType.Column && not (isTypeSeqBlockElementContinuator token) -> -1
1688+
| _, CtxtTypeDefns(posType, _) :: _ when offsidePos.Column = posType.Column && not (isTypeSeqBlockElementContinuator token) -> -1
16831689

16841690
// This ensures we close a namespace body when we see the next namespace definition
16851691
//
@@ -1822,7 +1828,7 @@ type LexFilterImpl (
18221828
popCtxt()
18231829
reprocess()
18241830

1825-
| _, CtxtTypeDefns offsidePos :: _
1831+
| _, CtxtTypeDefns(offsidePos, _) :: _
18261832
when isSemiSemi || (if relaxWhitespace2OffsideRule || isTypeContinuator token then tokenStartCol + 1 else tokenStartCol) <= offsidePos.Column ->
18271833
if debug then dprintf "token at column %d is offside from TYPE(offsidePos=%a)! pop and reprocess\n" tokenStartCol outputPos offsidePos
18281834
popCtxt()
@@ -2076,8 +2082,9 @@ type LexFilterImpl (
20762082
pushCtxtSeqBlock tokenTup AddBlockEnd
20772083
returnToken tokenLexbufState token
20782084

2079-
| EQUALS, CtxtTypeDefns _ :: _ ->
2085+
| EQUALS, CtxtTypeDefns(p, _) :: _ ->
20802086
if debug then dprintf "CtxType: EQUALS, pushing CtxtSeqBlock\n"
2087+
replaceCtxtIgnoreIndent tokenTup (CtxtTypeDefns(p, Some tokenTup.EndPos))
20812088
pushCtxtSeqBlock tokenTup AddBlockEnd
20822089
returnToken tokenLexbufState token
20832090

@@ -2202,7 +2209,7 @@ type LexFilterImpl (
22022209
let leadingBar = match (peekNextToken()) with BAR -> true | _ -> false
22032210

22042211
if debug then dprintf "WITH, pushing CtxtMatchClauses, lookaheadTokenStartPos = %a, tokenStartPos = %a\n" outputPos lookaheadTokenStartPos outputPos tokenStartPos
2205-
tryPushCtxt strictIndentation lookaheadTokenTup (CtxtMatchClauses(leadingBar, lookaheadTokenStartPos)) |> ignore
2212+
tryPushCtxt strictIndentation false lookaheadTokenTup (CtxtMatchClauses(leadingBar, lookaheadTokenStartPos)) |> ignore
22062213

22072214
returnToken tokenLexbufState OWITH
22082215

@@ -2385,22 +2392,42 @@ type LexFilterImpl (
23852392
pushCtxt tokenTup (CtxtFun tokenStartPos)
23862393
returnToken tokenLexbufState OFUN
23872394

2395+
// type I = interface .... end
2396+
| INTERFACE, CtxtSeqBlock _ :: CtxtTypeDefns(typePos, Some equalsEndPos) :: _ when
2397+
(tokenTup.LastTokenPos = equalsEndPos &&
2398+
2399+
// Allow deindenting interface representation when started after `=`:
2400+
//
2401+
// type I = interface
2402+
// abstract P: int
2403+
// end
2404+
2405+
let allowDeindent = tokenTup.EndPos.Line = equalsEndPos.Line
2406+
2407+
let lookaheadTokenTup = peekNextTokenTup ()
2408+
let lookaheadTokenStartPos = startPosOfTokenTup lookaheadTokenTup
2409+
match lookaheadTokenTup.Token with
2410+
| END ->
2411+
lookaheadTokenStartPos.Column >= typePos.Column
2412+
2413+
| DEFAULT | OVERRIDE | INTERFACE | NEW | TYPE | STATIC | MEMBER | ABSTRACT | INHERIT | LBRACK_LESS ->
2414+
let limitPos = if allowDeindent then typePos else tokenTup.StartPos
2415+
lookaheadTokenStartPos.Column >= limitPos.Column + 1
2416+
2417+
| _ ->
2418+
false) ->
2419+
2420+
if debug then dprintf "INTERFACE, pushing CtxtParen, tokenStartPos = %a\n" outputPos tokenStartPos
2421+
pushCtxt tokenTup (CtxtParen (token, tokenStartPos))
2422+
pushCtxtSeqBlock tokenTup AddBlockEnd
2423+
returnToken tokenLexbufState token
2424+
2425+
// type C with interface .... with
2426+
// type C = interface .... with
23882427
| INTERFACE, _ ->
2389-
let lookaheadTokenTup = peekNextTokenTup()
2390-
let lookaheadTokenStartPos = startPosOfTokenTup lookaheadTokenTup
2391-
match lookaheadTokenTup.Token with
2392-
// type I = interface .... end
2393-
| DEFAULT | OVERRIDE | INTERFACE | NEW | TYPE | STATIC | END | MEMBER | ABSTRACT | INHERIT | LBRACK_LESS ->
2394-
if debug then dprintf "INTERFACE, pushing CtxtParen, tokenStartPos = %a, lookaheadTokenStartPos = %a\n" outputPos tokenStartPos outputPos lookaheadTokenStartPos
2395-
pushCtxt tokenTup (CtxtParen (token, tokenStartPos))
2396-
pushCtxtSeqBlock tokenTup AddBlockEnd
2397-
returnToken tokenLexbufState token
2398-
// type C with interface .... with
2399-
// type C = interface .... with
2400-
| _ ->
2401-
if debug then dprintf "INTERFACE, pushing CtxtInterfaceHead, tokenStartPos = %a, lookaheadTokenStartPos = %a\n" outputPos tokenStartPos outputPos lookaheadTokenStartPos
2402-
pushCtxt tokenTup (CtxtInterfaceHead tokenStartPos)
2403-
returnToken tokenLexbufState OINTERFACE_MEMBER
2428+
if debug then dprintf "INTERFACE, pushing CtxtInterfaceHead, tokenStartPos = %a, lookaheadTokenStartPos \n" outputPos tokenStartPos
2429+
pushCtxt tokenTup (CtxtInterfaceHead tokenStartPos)
2430+
returnToken tokenLexbufState OINTERFACE_MEMBER
24042431

24052432
| CLASS, _ ->
24062433
if debug then dprintf "CLASS, pushing CtxtParen(%a)\n" outputPos tokenStartPos
@@ -2411,7 +2438,7 @@ type LexFilterImpl (
24112438
| TYPE, _ ->
24122439
insertComingSoonTokens("TYPE", TYPE_COMING_SOON, TYPE_IS_HERE)
24132440
if debug then dprintf "TYPE, pushing CtxtTypeDefns(%a)\n" outputPos tokenStartPos
2414-
pushCtxt tokenTup (CtxtTypeDefns tokenStartPos)
2441+
pushCtxt tokenTup (CtxtTypeDefns(tokenStartPos, None))
24152442
pool.Return tokenTup
24162443
hwTokenFetch useBlockRule
24172444

@@ -2582,7 +2609,7 @@ type LexFilterImpl (
25822609
pushCtxtSeqBlockAt strictIndentation false fallbackToken (peekNextTokenTup ()) addBlockEnd
25832610

25842611
and pushCtxtSeqBlockAt strict (useFallback: bool) (fallbackToken: TokenTup) (tokenTup: TokenTup) addBlockEnd =
2585-
let pushed = tryPushCtxt strict tokenTup (CtxtSeqBlock(FirstInSeqBlock, startPosOfTokenTup tokenTup, addBlockEnd))
2612+
let pushed = tryPushCtxt strict false tokenTup (CtxtSeqBlock(FirstInSeqBlock, startPosOfTokenTup tokenTup, addBlockEnd))
25862613
if not pushed && useFallback then
25872614
// The upcoming token isn't sufficiently indented to start the new context.
25882615
// The parser expects proper contexts structure, so we push a new recovery context at the fallback token position.

src/Compiler/pars.fsy

+8-1
Original file line numberDiff line numberDiff line change
@@ -1773,7 +1773,7 @@ tyconClassDefn:
17731773
| classOrInterfaceOrStruct classDefnBlock END
17741774
{ false, ($1, $2), Some(rhs2 parseState 1 3) }
17751775

1776-
| classOrInterfaceOrStruct classDefnBlock recover
1776+
| classOrInterfaceOrStruct classDefnBlock ends_coming_soon_or_recover
17771777
{ reportParseErrorAt (rhs parseState 1) (FSComp.SR.parsUnmatchedClassInterfaceOrStruct())
17781778
let m = (rhs parseState 1, $2) ||> unionRangeWithListBy (fun (d: SynMemberDefn) -> d.Range)
17791779
false, ($1, $2), Some(m) }
@@ -2019,6 +2019,13 @@ classDefnMember:
20192019
| Some(mWithKwd, members, m) -> Some mWithKwd, Some members, unionRanges (rhs2 parseState 1 4) m
20202020
[ SynMemberDefn.Interface($4, mWithKwd, members, mWhole) ] }
20212021

2022+
| opt_attributes opt_access interfaceMember recover
2023+
{ let mInterface = rhs parseState 3
2024+
if not (isNil $1) then errorR(Error(FSComp.SR.parsAttributesAreNotPermittedOnInterfaceImplementations(), rhs parseState 1))
2025+
if Option.isSome $2 then errorR(Error(FSComp.SR.parsInterfacesHaveSameVisibilityAsEnclosingType(), mInterface))
2026+
let ty = SynType.FromParseError(mInterface.EndRange)
2027+
[ SynMemberDefn.Interface(ty, None, None, rhs2 parseState 1 3) ] }
2028+
20222029
| opt_attributes opt_access abstractMemberFlags opt_inline nameop opt_explicitValTyparDecls COLON topTypeWithTypeConstraints classMemberSpfnGetSet opt_ODECLEND
20232030
{ let ty, arity = $8
20242031
let isInline, doc, id, explicitValTyparDecls = (Option.isSome $4), grabXmlDoc(parseState, $1, 1), $5, $6

tests/FSharp.Compiler.ComponentTests/Conformance/LexicalFiltering/OffsideExceptions/OffsideExceptions.fs

+6
Original file line numberDiff line numberDiff line change
@@ -480,6 +480,12 @@ raise (new Exception("exit 1"))
480480
EndLine = 5
481481
EndColumn = 31 }
482482
Message = "Expecting member body" }
483+
{ Error = Error 3113
484+
Range = { StartLine = 6
485+
StartColumn = 9
486+
EndLine = 6
487+
EndColumn = 9 }
488+
Message = "Unexpected end of input in type definition" }
483489
] |> ignore
484490

485491
[<Theory; File "RelaxWhitespace2.fs">]

tests/benchmarks/CompiledCodeBenchmarks/TaskPerf/TaskPerf/TaskPerf.fs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
(*
2-
msbuild tests\fsharp\perf\tasks\FS\TaskPerf.fsproj /p:Configuration=Release
3-
dotnet artifacts\bin\TaskPerf\Release\netcoreapp2.1\TaskPerf.dll
2+
msbuild tests\benchmarks\CompiledCodeBenchmarks\TaskPerf\TaskPerf\TaskPerf.fsproj /p:Configuration=Release
3+
dotnet artifacts\bin\TaskPerf\Release\net7.0\TaskPerf.dll
44
*)
55

66
namespace TaskPerf

tests/benchmarks/CompiledCodeBenchmarks/TaskPerf/TaskPerfCSharp/TaskPerfCSharp.csproj

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
4-
<TargetFrameworks>netcoreapp3.1</TargetFrameworks>
4+
<TargetFrameworks>net7.0</TargetFrameworks>
55
<OutputType>Library</OutputType>
66
<LangVersion>8.0</LangVersion>
77
</PropertyGroup>

tests/fsharp/typecheck/sigs/neg71.vsbsl

+3-1
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,6 @@ neg71.fsx(128,5,128,81): parse info FS3520: XML comment is not placed on a valid
1717

1818
neg71.fsx(168,1,168,28): typecheck error FS0960: 'let' and 'do' bindings must come before member and interface definitions in type definitions
1919

20-
neg71.fsx(168,9,168,18): typecheck error FS0039: The value or constructor 'Simulator' is not defined.
20+
neg71.fsx(104,14,104,14): typecheck error FS0887: The type ''a' is not an interface type
21+
22+
neg71.fsx(104,14,104,14): typecheck error FS0909: All implemented interfaces should be declared on the initial declaration of the type
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
module Module
2+
3+
type T =
4+
inherit as t
5+
6+
member this.P = 1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
ImplFile
2+
(ParsedImplFileInput
3+
("/root/Member/Inherit 08.fs", false, QualifiedNameOfFile Module, [], [],
4+
[SynModuleOrNamespace
5+
([Module], false, NamedModule,
6+
[Types
7+
([SynTypeDefn
8+
(SynComponentInfo
9+
([], None, [], [T],
10+
PreXmlDoc ((3,0), FSharp.Compiler.Xml.XmlDocCollector),
11+
false, None, (3,5--3,6)),
12+
ObjectModel
13+
(Unspecified,
14+
[Inherit
15+
(LongIdent (SynLongIdent ([], [], [])), None,
16+
(4,4--4,11));
17+
Member
18+
(SynBinding
19+
(None, Normal, false, false, [],
20+
PreXmlDoc ((4,12), FSharp.Compiler.Xml.XmlDocCollector),
21+
SynValData
22+
(Some { IsInstance = true
23+
IsDispatchSlot = false
24+
IsOverrideOrExplicitImpl = false
25+
IsFinal = false
26+
GetterOrSetterIsCompilerGenerated = false
27+
MemberKind = Member },
28+
SynValInfo
29+
([[SynArgInfo ([], false, None)]; []],
30+
SynArgInfo ([], false, None)), None, None),
31+
LongIdent
32+
(SynLongIdent
33+
([this; P], [(6,15--6,16)], [None; None]), None,
34+
None, Pats [], None, (6,11--6,17)), None,
35+
Const (Int32 1, (6,20--6,21)), (6,11--6,17),
36+
NoneAtInvisible,
37+
{ LeadingKeyword = Member (6,4--6,10)
38+
InlineKeyword = None
39+
EqualsRange = Some (6,18--6,19) }), (4,12--6,21))],
40+
(4,4--6,21)), [], None, (3,5--6,21),
41+
{ LeadingKeyword = Type (3,0--3,4)
42+
EqualsRange = Some (3,7--3,8)
43+
WithKeyword = None })], (3,0--6,21))],
44+
PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None,
45+
(1,0--6,21), { LeadingKeyword = Module (1,0--1,6) })], (true, true),
46+
{ ConditionalDirectives = []
47+
CodeComments = [] }, set []))
48+
49+
(4,12)-(4,14) parse error Unexpected keyword 'as' in type definition
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
module Module
2+
3+
type T =
4+
interface
5+
6+
member this.P = 1
7+
8+
()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
ImplFile
2+
(ParsedImplFileInput
3+
("/root/Member/Interface 08.fs", false, QualifiedNameOfFile Module, [], [],
4+
[SynModuleOrNamespace
5+
([Module], false, NamedModule,
6+
[Types
7+
([SynTypeDefn
8+
(SynComponentInfo
9+
([], None, [], [T],
10+
PreXmlDoc ((3,0), FSharp.Compiler.Xml.XmlDocCollector),
11+
false, None, (3,5--3,6)),
12+
ObjectModel
13+
(Unspecified,
14+
[Interface
15+
(FromParseError (4,13--4,13), None, None, (4,4--4,13));
16+
Member
17+
(SynBinding
18+
(None, Normal, false, false, [],
19+
PreXmlDoc ((6,4), FSharp.Compiler.Xml.XmlDocCollector),
20+
SynValData
21+
(Some { IsInstance = true
22+
IsDispatchSlot = false
23+
IsOverrideOrExplicitImpl = false
24+
IsFinal = false
25+
GetterOrSetterIsCompilerGenerated = false
26+
MemberKind = Member },
27+
SynValInfo
28+
([[SynArgInfo ([], false, None)]; []],
29+
SynArgInfo ([], false, None)), None, None),
30+
LongIdent
31+
(SynLongIdent
32+
([this; P], [(6,15--6,16)], [None; None]), None,
33+
None, Pats [], None, (6,11--6,17)), None,
34+
Const (Int32 1, (6,20--6,21)), (6,11--6,17),
35+
NoneAtInvisible,
36+
{ LeadingKeyword = Member (6,4--6,10)
37+
InlineKeyword = None
38+
EqualsRange = Some (6,18--6,19) }), (6,4--6,21))],
39+
(4,4--6,21)), [], None, (3,5--6,21),
40+
{ LeadingKeyword = Type (3,0--3,4)
41+
EqualsRange = Some (3,7--3,8)
42+
WithKeyword = None })], (3,0--6,21));
43+
Expr (Const (Unit, (8,0--8,2)), (8,0--8,2))],
44+
PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None,
45+
(1,0--8,2), { LeadingKeyword = Module (1,0--1,6) })], (true, true),
46+
{ ConditionalDirectives = []
47+
CodeComments = [] }, set []))
48+
49+
(4,14)-(6,4) parse error Incomplete structured construct at or before this point in member definition
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
module Module
2+
3+
type T =
4+
interface
5+
6+
type T2 = int
7+
8+
()

0 commit comments

Comments
 (0)