Skip to content

Commit 230f82b

Browse files
TIHancartermp
authored andcommitted
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 <[email protected]> * Update PostInferenceChecks.fs
1 parent 1e8edef commit 230f82b

File tree

4 files changed

+69
-4
lines changed

4 files changed

+69
-4
lines changed

src/fsharp/PostInferenceChecks.fs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -313,7 +313,7 @@ let RecordAnonRecdInfo cenv (anonInfo: AnonRecdTypeInfo) =
313313
// approx walk of type
314314
//--------------------------------------------------------------------------
315315

316-
let rec CheckTypeDeep (cenv: cenv) ((visitTy, visitTyconRefOpt, visitAppTyOpt, visitTraitSolutionOpt, visitTyparOpt) as f) g env isInner ty =
316+
let rec CheckTypeDeep (cenv: cenv) ((visitTy, visitTyconRefOpt, visitAppTyOpt, visitTraitSolutionOpt, visitTyparOpt) as f) (g: TcGlobals) env isInner ty =
317317
// We iterate the _solved_ constraints as well, to pick up any record of trait constraint solutions
318318
// This means we walk _all_ the constraints _everywhere_ in a type, including
319319
// 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
332332
| _ -> ())
333333
| _ -> ()
334334

335-
let ty = stripTyparEqns ty
335+
let ty =
336+
if g.compilingFslib then
337+
match stripTyparEqns ty with
338+
// When compiling FSharp.Core, do not strip type equations at this point if we can't dereference a tycon.
339+
| TType_app (tcref, _) when not tcref.CanDeref -> ty
340+
| _ -> stripTyEqns g ty
341+
else
342+
stripTyEqns g ty
336343
visitTy ty
337344

338345
match ty with

tests/fsharp/Compiler/CompilerAssert.fs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ let main argv = 0"""
211211
typeCheckResults.Errors
212212
|> Array.distinctBy (fun e -> e.Severity, e.ErrorNumber, e.StartLineAlternate, e.StartColumn, e.EndLineAlternate, e.EndColumn, e.Message)
213213

214-
Assert.AreEqual(Array.length expectedTypeErrors, errors.Length, sprintf "Type check errors: %A" typeCheckResults.Errors)
214+
Assert.AreEqual(Array.length expectedTypeErrors, errors.Length, sprintf "Type check errors: %A" errors)
215215

216216
Array.zip errors expectedTypeErrors
217217
|> Array.iter (fun (info, expectedError) ->

tests/fsharp/Compiler/Language/SpanTests.fs

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace FSharp.Compiler.UnitTests
44

55
open System
6+
open FSharp.Compiler.SourceCodeServices
67
open NUnit.Framework
78

89
#if NETCOREAPP
@@ -50,4 +51,55 @@ test ()
5051
// We expect this error until System.Reflection.Emit gets fixed for emitting `modreq` on method calls.
5152
// See: https://github.com/dotnet/corefx/issues/29254
5253
CompilerAssert.RunScript script [ "Method not found: '!0 ByRef System.ReadOnlySpan`1.get_Item(Int32)'." ]
53-
#endif
54+
55+
56+
[<Test>]
57+
let ``Invalid usage of type abbreviated span should fail to compile``() =
58+
CompilerAssert.TypeCheckWithErrors """
59+
open System
60+
61+
type Bytes = ReadOnlySpan<byte>
62+
63+
type Test() =
64+
65+
member _.M1 (data: Bytes) =
66+
let x =
67+
if false then
68+
failwith ""
69+
else
70+
data
71+
x
72+
73+
member _.M2 (data: Bytes) =
74+
let x =
75+
if false then
76+
failwithf ""
77+
else
78+
data
79+
x
80+
81+
let test () =
82+
let span = ReadOnlySpan<_>(Array.empty)
83+
let result = Test().M1(span)
84+
let result = Test().M2(span)
85+
0
86+
"""
87+
[|
88+
FSharpErrorSeverity.Error, 412, (11, 17, 11, 28), "A type instantiation involves a byref type. This is not permitted by the rules of Common IL."
89+
FSharpErrorSeverity.Error, 412, (19, 17, 19, 29), "A type instantiation involves a byref type. This is not permitted by the rules of Common IL."
90+
FSharpErrorSeverity.Error, 412, (19, 27, 19, 29), "A type instantiation involves a byref type. This is not permitted by the rules of Common IL."
91+
|]
92+
93+
[<Test>]
94+
let ``Type abbreviation that boxes a span should fail to compile``() =
95+
CompilerAssert.TypeCheckWithErrors """
96+
open System
97+
98+
type TA = Span<int> * Span<int>
99+
100+
let f (x: TA) = ()
101+
"""
102+
[|
103+
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."
104+
|]
105+
#endif
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,8 @@
11

22
neg_byref_13.fs(2,6,2,8): typecheck error FS0445: The type abbreviation contains byrefs. This is not permitted by F#.
3+
4+
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.
5+
6+
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.
7+
8+
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.

0 commit comments

Comments
 (0)