From efccc97e756565fcad60a60513179857daece7e3 Mon Sep 17 00:00:00 2001 From: Will Smith Date: Mon, 16 Dec 2019 14:57:28 -0800 Subject: [PATCH] Fixed type abbreviation from bypassing ByRefLike rules (#7953) * Trying to fix span type abbrev * Fixed type abbrev issue on span * Fixing build * Update test * Apply suggestions from code review I like @cartermps test name changes. Co-Authored-By: Phillip Carter * Update PostInferenceChecks.fs --- src/fsharp/PostInferenceChecks.fs | 11 +++- tests/fsharp/Compiler/CompilerAssert.fs | 2 +- tests/fsharp/Compiler/Language/SpanTests.fs | 54 +++++++++++++++++++- tests/fsharp/typecheck/sigs/neg_byref_13.bsl | 6 +++ 4 files changed, 69 insertions(+), 4 deletions(-) diff --git a/src/fsharp/PostInferenceChecks.fs b/src/fsharp/PostInferenceChecks.fs index c718a94665f..1730f88bd2c 100644 --- a/src/fsharp/PostInferenceChecks.fs +++ b/src/fsharp/PostInferenceChecks.fs @@ -313,7 +313,7 @@ let RecordAnonRecdInfo cenv (anonInfo: AnonRecdTypeInfo) = // approx walk of type //-------------------------------------------------------------------------- -let rec CheckTypeDeep (cenv: cenv) ((visitTy, visitTyconRefOpt, visitAppTyOpt, visitTraitSolutionOpt, visitTyparOpt) as f) g env isInner ty = +let rec CheckTypeDeep (cenv: cenv) ((visitTy, visitTyconRefOpt, visitAppTyOpt, visitTraitSolutionOpt, visitTyparOpt) as f) (g: TcGlobals) env isInner ty = // We iterate the _solved_ constraints as well, to pick up any record of trait constraint solutions // This means we walk _all_ the constraints _everywhere_ in a type, including // those attached to _solved_ type variables. This is used by PostTypeCheckSemanticChecks to detect uses of @@ -332,7 +332,14 @@ let rec CheckTypeDeep (cenv: cenv) ((visitTy, visitTyconRefOpt, visitAppTyOpt, v | _ -> ()) | _ -> () - let ty = stripTyparEqns ty + let ty = + if g.compilingFslib then + match stripTyparEqns ty with + // When compiling FSharp.Core, do not strip type equations at this point if we can't dereference a tycon. + | TType_app (tcref, _) when not tcref.CanDeref -> ty + | _ -> stripTyEqns g ty + else + stripTyEqns g ty visitTy ty match ty with diff --git a/tests/fsharp/Compiler/CompilerAssert.fs b/tests/fsharp/Compiler/CompilerAssert.fs index 50102ab21c4..1c753cd25e0 100644 --- a/tests/fsharp/Compiler/CompilerAssert.fs +++ b/tests/fsharp/Compiler/CompilerAssert.fs @@ -211,7 +211,7 @@ let main argv = 0""" typeCheckResults.Errors |> Array.distinctBy (fun e -> e.Severity, e.ErrorNumber, e.StartLineAlternate, e.StartColumn, e.EndLineAlternate, e.EndColumn, e.Message) - Assert.AreEqual(Array.length expectedTypeErrors, errors.Length, sprintf "Type check errors: %A" typeCheckResults.Errors) + Assert.AreEqual(Array.length expectedTypeErrors, errors.Length, sprintf "Type check errors: %A" errors) Array.zip errors expectedTypeErrors |> Array.iter (fun (info, expectedError) -> diff --git a/tests/fsharp/Compiler/Language/SpanTests.fs b/tests/fsharp/Compiler/Language/SpanTests.fs index cbac744a719..646032880ac 100644 --- a/tests/fsharp/Compiler/Language/SpanTests.fs +++ b/tests/fsharp/Compiler/Language/SpanTests.fs @@ -3,6 +3,7 @@ namespace FSharp.Compiler.UnitTests open System +open FSharp.Compiler.SourceCodeServices open NUnit.Framework #if NETCOREAPP @@ -50,4 +51,55 @@ test () // We expect this error until System.Reflection.Emit gets fixed for emitting `modreq` on method calls. // See: https://github.com/dotnet/corefx/issues/29254 CompilerAssert.RunScript script [ "Method not found: '!0 ByRef System.ReadOnlySpan`1.get_Item(Int32)'." ] -#endif \ No newline at end of file + + + [] + let ``Invalid usage of type abbreviated span should fail to compile``() = + CompilerAssert.TypeCheckWithErrors """ +open System + +type Bytes = ReadOnlySpan + +type Test() = + + member _.M1 (data: Bytes) = + let x = + if false then + failwith "" + else + data + x + + member _.M2 (data: Bytes) = + let x = + if false then + failwithf "" + else + data + x + +let test () = + let span = ReadOnlySpan<_>(Array.empty) + let result = Test().M1(span) + let result = Test().M2(span) + 0 + """ + [| + FSharpErrorSeverity.Error, 412, (11, 17, 11, 28), "A type instantiation involves a byref type. This is not permitted by the rules of Common IL." + FSharpErrorSeverity.Error, 412, (19, 17, 19, 29), "A type instantiation involves a byref type. This is not permitted by the rules of Common IL." + FSharpErrorSeverity.Error, 412, (19, 27, 19, 29), "A type instantiation involves a byref type. This is not permitted by the rules of Common IL." + |] + + [] + let ``Type abbreviation that boxes a span should fail to compile``() = + CompilerAssert.TypeCheckWithErrors """ +open System + +type TA = Span * Span + +let f (x: TA) = () + """ + [| + FSharpErrorSeverity.Error, 3300, (6, 8, 6, 9), "The parameter 'x' has an invalid type 'TA'. This is not permitted by the rules of Common IL." + |] +#endif diff --git a/tests/fsharp/typecheck/sigs/neg_byref_13.bsl b/tests/fsharp/typecheck/sigs/neg_byref_13.bsl index 92efcae6d94..985177e9793 100644 --- a/tests/fsharp/typecheck/sigs/neg_byref_13.bsl +++ b/tests/fsharp/typecheck/sigs/neg_byref_13.bsl @@ -1,2 +1,8 @@ neg_byref_13.fs(2,6,2,8): typecheck error FS0445: The type abbreviation contains byrefs. This is not permitted by F#. + +neg_byref_13.fs(3,12,3,13): typecheck error FS3300: The parameter 'x' has an invalid type 'M5'. This is not permitted by the rules of Common IL. + +neg_byref_13.fs(3,5,3,10): typecheck error FS3301: The function or method has an invalid return type 'M5'. This is not permitted by the rules of Common IL. + +neg_byref_13.fs(3,20,3,21): typecheck error FS0412: A type instantiation involves a byref type. This is not permitted by the rules of Common IL. \ No newline at end of file