Skip to content

Commit 33d7e9e

Browse files
committed
do not cache unsolved typars
1 parent 12efe3b commit 33d7e9e

File tree

5 files changed

+69
-14
lines changed

5 files changed

+69
-14
lines changed

src/Compiler/Checking/TypeRelations.fs

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,13 @@ type CanCoerce =
2929
type TTypeCacheKey =
3030
| TTypeCacheKey of TypeStructure * TypeStructure * CanCoerce
3131
static member TryGetFromStrippedTypes(ty1, ty2, canCoerce) =
32+
match ty1, ty2 with
33+
| TType_measure _, TType_measure _
34+
| TType_var _, _ | _, TType_var _ ->
35+
ValueNone
36+
| _ ->
3237
let t1, t2 = getTypeStructure ty1, getTypeStructure ty2
33-
if t1.IsPossiblyInfinite || t2.IsPossiblyInfinite then
38+
if t1.IsUnsolved || t2.IsUnsolved then
3439
ValueNone
3540
else
3641
ValueSome (TTypeCacheKey(t1, t2, canCoerce))
@@ -137,10 +142,6 @@ let rec TypeFeasiblySubsumesType ndeep (g: TcGlobals) (amap: ImportMap) m (ty1:
137142

138143
let checkSubsumes ty1 ty2 =
139144
match ty1, ty2 with
140-
| TType_measure _, TType_measure _
141-
| TType_var _, _ | _, TType_var _ ->
142-
true
143-
144145
| TType_app (tc1, l1, _), TType_app (tc2, l2, _) when tyconRefEq g tc1 tc2 ->
145146
List.lengthsEqAndForall2 (TypesFeasiblyEquiv ndeep g amap m) l1 l2
146147

@@ -160,13 +161,15 @@ let rec TypeFeasiblySubsumesType ndeep (g: TcGlobals) (amap: ImportMap) m (ty1:
160161
// See if any interface in type hierarchy of ty2 is a supertype of ty1
161162
List.exists (TypeFeasiblySubsumesType (ndeep + 1) g amap m ty1 NoCoerce) interfaces
162163

163-
if g.langVersion.SupportsFeature LanguageFeature.UseTypeSubsumptionCache then
164+
match ty1, ty2 with
165+
| TType_measure _, TType_measure _
166+
| TType_var _, _ | _, TType_var _ -> true
167+
| _ when g.langVersion.SupportsFeature LanguageFeature.UseTypeSubsumptionCache ->
164168
match TTypeCacheKey.TryGetFromStrippedTypes(ty1, ty2, canCoerce) with
165169
| ValueSome key ->
166170
(getTypeSubsumptionCache g).GetOrAdd(key, fun _ -> checkSubsumes ty1 ty2)
167171
| _ -> checkSubsumes ty1 ty2
168-
else
169-
checkSubsumes ty1 ty2
172+
| _-> checkSubsumes ty1 ty2
170173

171174
and TypeFeasiblySubsumesTypeWithSupertypeCheck g amap m ndeep ty1 ty2 =
172175
match GetSuperTypeOfType g amap m ty2 with

src/Compiler/Utilities/TypeHashing.fs

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -399,16 +399,18 @@ module StructuralUtilities =
399399
| TupInfo of b: bool
400400
| MeasureOne
401401
| MeasureRational of int * int
402-
| NeverEqual of never: NeverEqual
402+
| Unsolved of never: NeverEqual
403403

404404
type TypeStructure =
405405
| TypeStructure of TypeToken[]
406-
| PossiblyInfinite of never: NeverEqual
406+
407+
member x.IsUnsolved =
408+
let (TypeStructure tokens) = x in tokens |> Seq.exists _.IsUnsolved
407409

408410
let inline toNullnessToken (n: Nullness) =
409411
match n.TryEvaluate() with
410412
| ValueSome k -> TypeToken.Nullness k
411-
| _ -> TypeToken.NeverEqual NeverEqual.Singleton
413+
| _ -> TypeToken.Unsolved NeverEqual.Singleton
412414

413415
let rec private accumulateMeasure (m: Measure) =
414416
seq {
@@ -461,8 +463,11 @@ module StructuralUtilities =
461463
yield! accumulateTType r
462464
toNullnessToken n
463465
| TType_var(r, n) ->
464-
TypeToken.Stamp r.Stamp
465-
toNullnessToken n
466+
if r.IsSolved then
467+
TypeToken.Stamp r.Stamp
468+
toNullnessToken n
469+
else
470+
TypeToken.Unsolved NeverEqual.Singleton
466471
| TType_measure m -> yield! accumulateMeasure m
467472
}
468473

@@ -471,7 +476,7 @@ module StructuralUtilities =
471476
let tokens = tokens |> Seq.truncate 256 |> Array.ofSeq
472477

473478
if tokens.Length = 256 then
474-
PossiblyInfinite NeverEqual.Singleton
479+
TypeStructure [| TypeToken.Unsolved NeverEqual.Singleton |]
475480
else
476481
TypeStructure tokens
477482

tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,7 @@
277277
<Compile Include="Interop\Literals.fs" />
278278
<Compile Include="Scripting\Interactive.fs" />
279279
<Compile Include="Scripting\TypeCheckOnlyTests.fs" />
280+
<Compile Include="TypeChecks\TypeRelations.fs" />
280281
<Compile Include="TypeChecks\SeqTypeCheckTests.fs" />
281282
<Compile Include="TypeChecks\CheckDeclarationsTests.fs" />
282283
<Compile Include="TypeChecks\Graph\Utils.fs" />
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
module MyModule
2+
3+
type IFoo<'T when 'T :> IFoo<'T>> =
4+
abstract member Bar: other:'T -> unit
5+
6+
[<AbstractClass>]
7+
type FooBase() =
8+
9+
interface IFoo<FooBase> with
10+
member this.Bar (other: FooBase) = ()
11+
12+
[<Sealed>]
13+
type FooDerived<'T>() =
14+
inherit FooBase()
15+
16+
interface IFoo<FooDerived<'T>> with
17+
member this.Bar other = ()
18+
19+
type IFooContainer<'T> =
20+
abstract member Foo: FooDerived<'T>
21+
22+
let inline bar<'a when 'a :> IFoo<'a>> (x: 'a) (y: 'a) = x.Bar y
23+
let inline takeSame<'a> (x: 'a) (y: 'a) = ()
24+
25+
// Successfully compiles under .NET 9 + F# 9
26+
// Error under .NET 10 + F# 10: Program.fs(26,13): Error FS0193 : The type 'FooDerived<'TId>' does not match the type 'FooBase'
27+
let callBar_NewlyBroken (foo1: IFooContainer<'TId>) (foo2: IFooContainer<'TId>) =
28+
bar foo1.Foo foo2.Foo
29+
30+
// Successfully compiles under both versions
31+
let callBar (foo1: IFooContainer<'TId>) (foo2: IFooContainer<'TId>) =
32+
let id1 = foo1.Foo
33+
let id2 = foo2.Foo
34+
bar id1 id2
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
module TypeChecks.TypeRelations
2+
3+
open Xunit
4+
open FSharp.Test.Compiler
5+
open FSharp.Test
6+
7+
[<Theory; FileInlineData("CrgpLibrary.fs")>]
8+
let ``Unsolved type variables are not cached`` compilation =
9+
compilation
10+
|> getCompilation
11+
|> typecheck
12+
|> shouldSucceed

0 commit comments

Comments
 (0)