diff --git a/src/fsharp/PostInferenceChecks.fs b/src/fsharp/PostInferenceChecks.fs index b25836e3d04..f59d94502f9 100644 --- a/src/fsharp/PostInferenceChecks.fs +++ b/src/fsharp/PostInferenceChecks.fs @@ -1543,10 +1543,12 @@ let CheckRecdField isUnion cenv env (tycon:Tycon) (rfield:RecdField) = (not isUnion && IsHiddenRecdField env.sigToImplRemapInfo (tcref.MakeNestedRecdFieldRef rfield)) let access = AdjustAccess isHidden (fun () -> tycon.CompilationPath) rfield.Accessibility CheckTypeForAccess cenv env (fun () -> rfield.Name) access m rfield.FormalType - + if TyconRefHasAttribute g m g.attrib_IsByRefLikeAttribute tcref then // Permit Span fields in IsByRefLike types CheckTypePermitOuterSpanLike cenv env m rfield.FormalType + if cenv.reportErrors then + CheckForByrefType cenv env rfield.FormalType (fun () -> errorR(Error(FSComp.SR.chkCantStoreByrefValue(), tycon.Range))) else CheckTypeNoByrefs cenv env m rfield.FormalType if cenv.reportErrors then diff --git a/tests/fsharp/typecheck/sigs/neg107.bsl b/tests/fsharp/typecheck/sigs/neg107.bsl index 8fd63e7a802..d3610f83a11 100644 --- a/tests/fsharp/typecheck/sigs/neg107.bsl +++ b/tests/fsharp/typecheck/sigs/neg107.bsl @@ -64,3 +64,13 @@ neg107.fsx(53,34,53,38): typecheck error FS3234: Struct members cannot return th neg107.fsx(67,34,67,40): typecheck error FS3234: Struct members cannot return the address of fields of the struct by reference neg107.fsx(67,34,67,38): typecheck error FS3234: Struct members cannot return the address of fields of the struct by reference + +neg107.fsx(71,19,71,20): typecheck error FS0412: A type instantiation involves a byref type. This is not permitted by the rules of Common IL. + +neg107.fsx(71,14,71,18): typecheck error FS0437: A type would store a byref typed value. This is not permitted by Common IL. + +neg107.fsx(71,19,71,20): typecheck error FS0412: A type instantiation involves a byref type. This is not permitted by the rules of Common IL. + +neg107.fsx(71,19,71,20): typecheck error FS0412: A type instantiation involves a byref type. This is not permitted by the rules of Common IL. + +neg107.fsx(71,19,71,20): typecheck error FS0412: A type instantiation involves a byref type. This is not permitted by the rules of Common IL. diff --git a/tests/fsharp/typecheck/sigs/neg107.fsx b/tests/fsharp/typecheck/sigs/neg107.fsx index 2dcaafee7a3..1df5dec5fd4 100644 --- a/tests/fsharp/typecheck/sigs/neg107.fsx +++ b/tests/fsharp/typecheck/sigs/neg107.fsx @@ -65,3 +65,10 @@ namespace Test val mutable x : TestMut1 member this.XAddr = &this.x.x // not allowed, Struct members cannot return the address of fields of the struct by reference", not entirely clear why C# disallowed this + + module DisallowIsByRefLikeWithByRefField = + [] + type Beef(x: byref) = + + member __.X = &x + diff --git a/tests/fsharp/typecheck/sigs/neg107.vsbsl b/tests/fsharp/typecheck/sigs/neg107.vsbsl index 8fd63e7a802..d3610f83a11 100644 --- a/tests/fsharp/typecheck/sigs/neg107.vsbsl +++ b/tests/fsharp/typecheck/sigs/neg107.vsbsl @@ -64,3 +64,13 @@ neg107.fsx(53,34,53,38): typecheck error FS3234: Struct members cannot return th neg107.fsx(67,34,67,40): typecheck error FS3234: Struct members cannot return the address of fields of the struct by reference neg107.fsx(67,34,67,38): typecheck error FS3234: Struct members cannot return the address of fields of the struct by reference + +neg107.fsx(71,19,71,20): typecheck error FS0412: A type instantiation involves a byref type. This is not permitted by the rules of Common IL. + +neg107.fsx(71,14,71,18): typecheck error FS0437: A type would store a byref typed value. This is not permitted by Common IL. + +neg107.fsx(71,19,71,20): typecheck error FS0412: A type instantiation involves a byref type. This is not permitted by the rules of Common IL. + +neg107.fsx(71,19,71,20): typecheck error FS0412: A type instantiation involves a byref type. This is not permitted by the rules of Common IL. + +neg107.fsx(71,19,71,20): typecheck error FS0412: A type instantiation involves a byref type. This is not permitted by the rules of Common IL. diff --git a/vsintegration/src/FSharp.Editor/Formatting/BraceMatchingService.fs b/vsintegration/src/FSharp.Editor/Formatting/BraceMatchingService.fs index 7b795f0cc82..511988985a0 100644 --- a/vsintegration/src/FSharp.Editor/Formatting/BraceMatchingService.fs +++ b/vsintegration/src/FSharp.Editor/Formatting/BraceMatchingService.fs @@ -2,10 +2,10 @@ namespace Microsoft.VisualStudio.FSharp.Editor -open System open System.ComponentModel.Composition open Microsoft.CodeAnalysis.Editor open Microsoft.FSharp.Compiler.SourceCodeServices +open System.Runtime.InteropServices [] type internal FSharpBraceMatchingService @@ -14,19 +14,21 @@ type internal FSharpBraceMatchingService checkerProvider: FSharpCheckerProvider, projectInfoManager: FSharpProjectOptionsManager ) = - static let defaultUserOpName = "BraceMatching" - static member GetBraceMatchingResult(checker: FSharpChecker, sourceText, fileName, parsingOptions: FSharpParsingOptions, position: int, userOpName: string) = + static member GetBraceMatchingResult(checker: FSharpChecker, sourceText, fileName, parsingOptions: FSharpParsingOptions, position: int, userOpName: string, [] forFormatting: bool) = async { let! matchedBraces = checker.MatchBraces(fileName, sourceText.ToString(), parsingOptions, userOpName) let isPositionInRange range = match RoslynHelpers.TryFSharpRangeToTextSpan(sourceText, range) with | None -> false - | Some range -> - let length = position - range.Start - length >= 0 && length <= range.Length + | Some span -> + if forFormatting then + let length = position - span.Start + length >= 0 && length <= span.Length + else + span.Contains position return matchedBraces |> Array.tryFind(fun (left, right) -> isPositionInRange left || isPositionInRange right) } diff --git a/vsintegration/src/FSharp.Editor/Formatting/EditorFormattingService.fs b/vsintegration/src/FSharp.Editor/Formatting/EditorFormattingService.fs index f5fdc45016a..03061fa350f 100644 --- a/vsintegration/src/FSharp.Editor/Formatting/EditorFormattingService.fs +++ b/vsintegration/src/FSharp.Editor/Formatting/EditorFormattingService.fs @@ -50,7 +50,7 @@ type internal FSharpEditorFormattingService x.Tag <> FSharpTokenTag.LINE_COMMENT) let! (left, right) = - FSharpBraceMatchingService.GetBraceMatchingResult(checker, sourceText, filePath, parsingOptions, position, "FormattingService") + FSharpBraceMatchingService.GetBraceMatchingResult(checker, sourceText, filePath, parsingOptions, position, "FormattingService", forFormatting=true) if right.StartColumn = firstMeaningfulToken.LeftColumn then // Replace the indentation on this line with the indentation of the left bracket diff --git a/vsintegration/tests/UnitTests/BraceMatchingServiceTests.fs b/vsintegration/tests/UnitTests/BraceMatchingServiceTests.fs index 3ec9c9e0be2..e323cc8db20 100644 --- a/vsintegration/tests/UnitTests/BraceMatchingServiceTests.fs +++ b/vsintegration/tests/UnitTests/BraceMatchingServiceTests.fs @@ -161,26 +161,23 @@ let main argv = 0 // return an integer exit code""" this.VerifyBraceMatch(code, "(printfn", ")endBrace") - [] - [] - [", [|9;10;11;14;15;16|])>] - [", [|9;10;11;12;15;15;16;17|])>] - [] - []\nlet a7 = 70", [|0;1;2;21;22;23|])>] - [] - member this.BraceMatchingBothSides_Bug2092(fileContents: string, matchingPositions: int[]) = - // https://github.com/Microsoft/visualfsharp/issues/2092 + [] + [] + [", [|9;10;15|])>] + [", [|9;10;11;15;16|])>] + [] + []\nlet a7 = 70", [|0;1;22|])>] + [] + member this.DoNotMatchOnInnerSide(fileContents: string, matchingPositions: int[]) = let sourceText = SourceText.From(fileContents) - let parsingOptions, _ = checker.GetParsingOptionsFromProjectOptions projectOptions - matchingPositions - |> Array.iter (fun position -> + + for position in matchingPositions do match FSharpBraceMatchingService.GetBraceMatchingResult(checker, sourceText, fileName, parsingOptions, position, "UnitTest") |> Async.RunSynchronously with | Some _ -> () | None -> match position with | 0 -> "" | _ -> fileContents.[position - 1] |> sprintf " (previous character '%c')" - |> sprintf "Didn't find a matching brace at position '%d', character '%c'%s" position fileContents.[position] + |> sprintf "Didn't find a matching brace at position '%d' %s" position |> Assert.Fail - ) \ No newline at end of file diff --git a/vsintegration/tests/UnitTests/IndentationServiceTests.fs b/vsintegration/tests/UnitTests/IndentationServiceTests.fs index 83ce946655c..5139e313a48 100644 --- a/vsintegration/tests/UnitTests/IndentationServiceTests.fs +++ b/vsintegration/tests/UnitTests/IndentationServiceTests.fs @@ -170,6 +170,7 @@ while true do |> Array.map (fun (lineNumber, expectedIndentation) -> ( Some(expectedIndentation), lineNumber, autoIndentTemplate )) + [] member this.TestIndentation() = for (expectedIndentation, lineNumber, template) in testCases do let sourceText = SourceText.From(template) @@ -179,7 +180,8 @@ while true do match expectedIndentation with | None -> Assert.IsTrue(actualIndentation.IsNone, "No indentation was expected at line {0}", lineNumber) | Some indentation -> Assert.AreEqual(expectedIndentation.Value, actualIndentation.Value, "Indentation on line {0} doesn't match", lineNumber) - + + [] member this.TestAutoIndentation() = for (expectedIndentation, lineNumber, template) in autoIndentTestCases do