Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed type abbreviation from bypassing ByRefLike rules #7953

Merged
merged 6 commits into from
Dec 16, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions src/fsharp/PostInferenceChecks.fs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
2 changes: 1 addition & 1 deletion tests/fsharp/Compiler/CompilerAssert.fs
Original file line number Diff line number Diff line change
Expand Up @@ -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) ->
Expand Down
54 changes: 53 additions & 1 deletion tests/fsharp/Compiler/Language/SpanTests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace FSharp.Compiler.UnitTests

open System
open FSharp.Compiler.SourceCodeServices
open NUnit.Framework

#if NETCOREAPP
Expand Down Expand Up @@ -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


[<Test>]
let ``Invalid usage of type abbreviated span should fail to compile``() =
CompilerAssert.TypeCheckWithErrors """
open System

type Bytes = ReadOnlySpan<byte>

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."
|]

[<Test>]
let ``Type abbreviation that boxes a span should fail to compile``() =
CompilerAssert.TypeCheckWithErrors """
open System

type TA = Span<int> * Span<int>

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
6 changes: 6 additions & 0 deletions tests/fsharp/typecheck/sigs/neg_byref_13.bsl
Original file line number Diff line number Diff line change
@@ -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.