Skip to content

Commit a8b607c

Browse files
authored
Merge pull request #1278 from dsyme/srtp-1
[RFC FS-1017] Allow all inferrable SRTP constraints to be written in signatures
2 parents 9cbedee + f56cb28 commit a8b607c

File tree

7 files changed

+68
-34
lines changed

7 files changed

+68
-34
lines changed

src/fsharp/TypeChecker.fs

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4133,13 +4133,12 @@ let rec TcTyparConstraint ridx cenv newOk checkCxs occ (env: TcEnv) tpenv c =
41334133
AddCxMethodConstraint env.DisplayEnv cenv.css m NoTrace traitInfo
41344134
tpenv
41354135

4136-
and TcPseudoMemberSpec cenv newOk env synTypars tpenv memSpfn m =
4136+
and TcPseudoMemberSpec cenv newOk env synTypes tpenv memSpfn m =
41374137
#if ALLOW_MEMBER_CONSTRAINTS_ON_MEASURES
41384138
let tps,tpenv = List.mapFold (TcTyparOrMeasurePar None cenv env newOk) tpenv synTypars
41394139
#else
4140-
let tps,tpenv = List.mapFold (TcTypar cenv env newOk) tpenv synTypars
4140+
let tys,tpenv = List.mapFold (TcTypeAndRecover cenv newOk CheckCxs ItemOccurence.UseInType env) tpenv synTypes
41414141
#endif
4142-
let tys = List.map mkTyparTy tps
41434142
match memSpfn with
41444143
| SynMemberSig.Member (valSpfn,memberFlags,m) ->
41454144
// REVIEW: Test pseudo constraints cannot refer to polymorphic methods.
@@ -5824,7 +5823,8 @@ and TcExprUndelayed cenv overallTy env tpenv (expr: SynExpr) =
58245823
TcLongIdentThen cenv overallTy env tpenv lidwd [ DelayedApp(ExprAtomicFlag.Atomic, e1, mStmt); MakeDelayedSet(e2,mStmt) ]
58255824

58265825
| SynExpr.TraitCall(tps,memSpfn,arg,m) ->
5827-
let (TTrait(_,logicalCompiledName,_,argtys,returnTy,_) as traitInfo),tpenv = TcPseudoMemberSpec cenv NewTyparsOK env tps tpenv memSpfn m
5826+
let synTypes = tps |> List.map (fun tp -> SynType.Var(tp,m))
5827+
let (TTrait(_,logicalCompiledName,_,argtys,returnTy,_) as traitInfo),tpenv = TcPseudoMemberSpec cenv NewTyparsOK env synTypes tpenv memSpfn m
58285828
if List.contains logicalCompiledName BakedInTraitConstraintNames then
58295829
warning(BakedInMemberConstraintName(logicalCompiledName,m))
58305830

@@ -8478,11 +8478,13 @@ and TcItemThen cenv overallTy env tpenv (item,mItem,rest,afterOverloadResolution
84788478
let logicalCompiledName = ComputeLogicalName id memberFlags
84798479
let traitInfo = TTrait(argTys,logicalCompiledName,memberFlags,argTys,Some retTy, sln)
84808480

8481-
AddCxMethodConstraint env.DisplayEnv cenv.css mItem NoTrace traitInfo
8482-
84838481
let expr = Expr.Op(TOp.TraitCall(traitInfo), [], ves, mItem)
84848482
let expr = mkLambdas mItem [] vs (expr,retTy)
8485-
PropagateThenTcDelayed cenv overallTy env tpenv mItem (MakeApplicableExprNoFlex cenv expr) (tyOfExpr cenv.g expr) ExprAtomicFlag.NonAtomic delayed
8483+
let resultExpr = PropagateThenTcDelayed cenv overallTy env tpenv mItem (MakeApplicableExprNoFlex cenv expr) (tyOfExpr cenv.g expr) ExprAtomicFlag.NonAtomic delayed
8484+
// Add the constraint after the arguments have been checked to allow annotations to kick in on rigid type parameters
8485+
AddCxMethodConstraint env.DisplayEnv cenv.css mItem NoTrace traitInfo
8486+
resultExpr
8487+
84868488

84878489
| Item.DelegateCtor typ ->
84888490
match delayed with

src/fsharp/ast.fs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -391,7 +391,7 @@ and
391391
/// F# syntax is 'typar :> type
392392
| WhereTyparSubtypeOfType of SynTypar * SynType * range
393393
/// F# syntax is ^T : (static member MemberName : ^T * int -> ^T)
394-
| WhereTyparSupportsMember of SynTypar list * SynMemberSig * range
394+
| WhereTyparSupportsMember of SynType list * SynMemberSig * range
395395
/// F# syntax is 'typar : enum<'UnderlyingType>
396396
| WhereTyparIsEnum of SynTypar * SynType list * range
397397
/// F# syntax is 'typar : delegate<'Args,unit>

src/fsharp/pars.fsy

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2172,7 +2172,8 @@ typeConstraint:
21722172
{ WhereTyparSupportsNull($1,lhs parseState) }
21732173

21742174
| typar COLON LPAREN classMemberSpfn rparen
2175-
{ WhereTyparSupportsMember([ $1 ],$4,lhs parseState) }
2175+
{ let tp = $1
2176+
WhereTyparSupportsMember([ SynType.Var(tp, tp.Range) ],$4,lhs parseState) }
21762177

21772178
| LPAREN typarAlts rparen COLON LPAREN classMemberSpfn rparen
21782179
{ WhereTyparSupportsMember(List.rev($2),$6,lhs parseState) }
@@ -2193,8 +2194,8 @@ typeConstraint:
21932194
| nm -> raiseParseErrorAt (rhs parseState 3) (FSComp.SR.parsUnexpectedIdentifier(nm)) }
21942195

21952196
typarAlts:
2196-
| typarAlts OR typar { $3::$1 }
2197-
| typar { [$1] }
2197+
| typarAlts OR appType { $3::$1 }
2198+
| appType { [$1] }
21982199

21992200
/* The core of a union type definition */
22002201
unionTypeRepr:

tests/fsharp/core/members/ops/test.fsx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -345,7 +345,13 @@ module MiscOperatorOverloadTests =
345345
res
346346

347347

348+
// See https://github.com/Microsoft/visualfsharp/issues/1306
349+
module OperatorConstraintsWithExplicitRigidTypeParameters =
350+
type M() = class end
348351

352+
let inline empty< ^R when ( ^R or M) : (static member ( $ ) : ^R * M -> ^R)> =
353+
let m = M()
354+
Unchecked.defaultof< ^R> $ m: ^R
349355

350356
module EnumerationOperatorTests =
351357
let x1 : System.DateTimeKind = enum 3

tests/fsharp/core/subtype/test.fsx

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1725,6 +1725,53 @@ module GenericPropertyConstraintSolvedByRecord =
17251725

17261726
let v = print_foo_memb { foo=1 }
17271727

1728+
1729+
module SRTPFix =
1730+
1731+
open System
1732+
1733+
let inline konst x _ = x
1734+
1735+
type CFunctor() =
1736+
static member inline fmap (f : ^a -> ^b, a : ^a list) = List.map f a
1737+
static member inline fmap (f : ^a -> ^b, a : ^a option) =
1738+
match a with
1739+
| None -> None
1740+
| Some x -> Some (f x)
1741+
1742+
// default implementation of replace
1743+
static member inline replace< ^a, ^b, ^c, ^d, ^e when ^a :> CFunctor and (^a or ^d) : (static member fmap : (^b -> ^c) * ^d -> ^e) > (a, f) =
1744+
((^a or ^d) : (static member fmap : (^b -> ^c) * ^d -> ^e) (konst a, f))
1745+
1746+
// call overridden replace if present
1747+
static member inline replace< ^a, ^b, ^c when ^b : (static member replace : ^a * ^b -> ^c)>(a : ^a, f : ^b) =
1748+
(^b : (static member replace : ^a * ^b -> ^c) (a, f))
1749+
1750+
let inline replace_instance< ^a, ^b, ^c, ^d when (^a or ^c) : (static member replace : ^b * ^c -> ^d)> (a : ^b, f : ^c) =
1751+
((^a or ^c) : (static member replace : ^b * ^c -> ^d) (a, f))
1752+
1753+
let inline fmap_instance< ^a, ^b, ^c, ^d, ^e when (^a or ^d) : (static member fmap : (^b -> ^c) * ^d -> ^e)>(f : ^b -> ^c, a : ^d) =
1754+
((^a or ^d) : (static member fmap : (^b -> ^c) * ^d -> ^e) (f, a))
1755+
1756+
let inline fmap (f : ^a -> ^b) (a : ^c) =
1757+
fmap_instance<CFunctor, _, _, _, _> (f, a)
1758+
1759+
let inline replace (a : ^a) (f : ^b) : ^a0 when (CFunctor or ^b) : (static member replace : ^a * ^b -> ^a0) =
1760+
replace_instance<CFunctor, _, _, _> (a, f)
1761+
1762+
(*
1763+
type test(arg : string) = class
1764+
member __.data = arg
1765+
static member inline fmap (f : char -> char, a : test) = String.map f a.data
1766+
static member inline replace (a : char, f : test) = test.fmap (konst a, f)
1767+
end
1768+
1769+
let _ =
1770+
printfn "%A" <| fmap id [1;2;3];
1771+
printfn "%A" <| replace 5 [1;2;3];
1772+
printfn "%A" <| fmap ((+) 1) (Some 2);
1773+
printfn "%A" <| replace 'q' (test("HI"))
1774+
*)
17281775
let aa =
17291776
if not failures.IsEmpty then (printfn "Test Failed, failures = %A" failures; exit 1)
17301777

tests/fsharp/typecheck/sigs/neg60.bsl

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -64,12 +64,8 @@ but here has type
6464

6565
neg60.fs(71,36,71,40): typecheck error FS0043: The type 'System.Nullable<int>' does not have 'null' as a proper value. To create a null value for a Nullable type use 'System.Nullable()'.
6666

67-
neg60.fs(77,20,77,22): typecheck error FS0001: The type 'System.Nullable<int>' does not support the operator '?>='. Consider opening the module 'Microsoft.FSharp.Linq.NullableOperators'.
68-
6967
neg60.fs(77,16,77,19): typecheck error FS0043: The type 'System.Nullable<int>' does not support the operator '?>='. Consider opening the module 'Microsoft.FSharp.Linq.NullableOperators'.
7068

71-
neg60.fs(78,20,78,22): typecheck error FS0001: None of the types 'System.Nullable<int>, int' support the operator '?>='. Consider opening the module 'Microsoft.FSharp.Linq.NullableOperators'.
72-
7369
neg60.fs(78,16,78,19): typecheck error FS0043: None of the types 'System.Nullable<int>, int' support the operator '?>='. Consider opening the module 'Microsoft.FSharp.Linq.NullableOperators'.
7470

7571
neg60.fs(79,18,79,21): typecheck error FS0001: The type ''a * 'b' does not match the type 'int'
@@ -82,4 +78,4 @@ neg60.fs(80,19,80,20): typecheck error FS0043: Expecting a type supporting the o
8278

8379
neg60.fs(81,22,81,34): typecheck error FS0002: This function takes too many arguments, or is used in a context where a function is not expected
8480

85-
neg60.fs(87,14,87,15): typecheck error FS0001: The type 'System.Nullable<int>' does not support the operator '?=?'. Consider opening the module 'Microsoft.FSharp.Linq.NullableOperators'.
81+
neg60.fs(87,10,87,13): typecheck error FS0043: The type 'System.Nullable<int>' does not support the operator '?=?'. Consider opening the module 'Microsoft.FSharp.Linq.NullableOperators'.

tests/fsharpqa/Source/Diagnostics/General/E_NullableOperators01.fs

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -25,39 +25,21 @@ let _ = iq <? iq
2525
let _ = iq =? iq
2626
let _ = iq <>? iq
2727

28-
//<Expects status="error" span="(7,16-7,18)" id="FS0001">None of the types 'System\.Nullable<int>, int' support the operator '\?>='\. Consider opening the module 'Microsoft\.FSharp\.Linq\.NullableOperators'\.$</Expects>
2928
//<Expects status="error" span="(7,12-7,15)" id="FS0043">None of the types 'System\.Nullable<int>, int' support the operator '\?>='\. Consider opening the module 'Microsoft\.FSharp\.Linq\.NullableOperators'\.$</Expects>
30-
//<Expects status="error" span="(8,15-8,17)" id="FS0001">The type 'System\.Nullable<int>' does not support the operator '\?>'\. Consider opening the module 'Microsoft\.FSharp\.Linq\.NullableOperators'\.$</Expects>
3129
//<Expects status="error" span="(8,12-8,14)" id="FS0043">The type 'System\.Nullable<int>' does not support the operator '\?>'\. Consider opening the module 'Microsoft\.FSharp\.Linq\.NullableOperators'\.$</Expects>
32-
//<Expects status="error" span="(9,16-9,18)" id="FS0001">The type 'System\.Nullable<int>' does not support the operator '\?<='\. Consider opening the module 'Microsoft\.FSharp\.Linq\.NullableOperators'\.$</Expects>
3330
//<Expects status="error" span="(9,12-9,15)" id="FS0043">The type 'System\.Nullable<int>' does not support the operator '\?<='\. Consider opening the module 'Microsoft\.FSharp\.Linq\.NullableOperators'\.$</Expects>
34-
//<Expects status="error" span="(10,15-10,17)" id="FS0001">The type 'System\.Nullable<int>' does not support the operator '\?<'\. Consider opening the module 'Microsoft\.FSharp\.Linq\.NullableOperators'\.$</Expects>
3531
//<Expects status="error" span="(10,12-10,14)" id="FS0043">The type 'System\.Nullable<int>' does not support the operator '\?<'\. Consider opening the module 'Microsoft\.FSharp\.Linq\.NullableOperators'\.$</Expects>
36-
//<Expects status="error" span="(11,15-11,17)" id="FS0001">The type 'System\.Nullable<int>' does not support the operator '\?='\. Consider opening the module 'Microsoft\.FSharp\.Linq\.NullableOperators'\.$</Expects>
3732
//<Expects status="error" span="(11,12-11,14)" id="FS0043">The type 'System\.Nullable<int>' does not support the operator '\?='\. Consider opening the module 'Microsoft\.FSharp\.Linq\.NullableOperators'\.$</Expects>
38-
//<Expects status="error" span="(12,16-12,18)" id="FS0001">The type 'System\.Nullable<int>' does not support the operator '\?<>'\. Consider opening the module 'Microsoft\.FSharp\.Linq\.NullableOperators'\.$</Expects>
3933
//<Expects status="error" span="(12,12-12,15)" id="FS0043">The type 'System\.Nullable<int>' does not support the operator '\?<>'\. Consider opening the module 'Microsoft\.FSharp\.Linq\.NullableOperators'\.$</Expects>
40-
//<Expects status="error" span="(14,17-14,19)" id="FS0001">The type 'System\.Nullable<int>' does not support the operator '\?>=\?'\. Consider opening the module 'Microsoft\.FSharp\.Linq\.NullableOperators'\.$</Expects>
4134
//<Expects status="error" span="(14,12-14,16)" id="FS0043">The type 'System\.Nullable<int>' does not support the operator '\?>=\?'\. Consider opening the module 'Microsoft\.FSharp\.Linq\.NullableOperators'\.$</Expects>
42-
//<Expects status="error" span="(15,16-15,18)" id="FS0001">The type 'System\.Nullable<int>' does not support the operator '\?>\?'\. Consider opening the module 'Microsoft\.FSharp\.Linq\.NullableOperators'\.$</Expects>
4335
//<Expects status="error" span="(15,12-15,15)" id="FS0043">The type 'System\.Nullable<int>' does not support the operator '\?>\?'\. Consider opening the module 'Microsoft\.FSharp\.Linq\.NullableOperators'\.$</Expects>
44-
//<Expects status="error" span="(16,17-16,19)" id="FS0001">The type 'System\.Nullable<int>' does not support the operator '\?<=\?'\. Consider opening the module 'Microsoft\.FSharp\.Linq\.NullableOperators'\.$</Expects>
4536
//<Expects status="error" span="(16,12-16,16)" id="FS0043">The type 'System\.Nullable<int>' does not support the operator '\?<=\?'\. Consider opening the module 'Microsoft\.FSharp\.Linq\.NullableOperators'\.$</Expects>
46-
//<Expects status="error" span="(17,16-17,18)" id="FS0001">The type 'System\.Nullable<int>' does not support the operator '\?<\?'\. Consider opening the module 'Microsoft\.FSharp\.Linq\.NullableOperators'\.$</Expects>
4737
//<Expects status="error" span="(17,12-17,15)" id="FS0043">The type 'System\.Nullable<int>' does not support the operator '\?<\?'\. Consider opening the module 'Microsoft\.FSharp\.Linq\.NullableOperators'\.$</Expects>
48-
//<Expects status="error" span="(18,16-18,18)" id="FS0001">The type 'System\.Nullable<int>' does not support the operator '\?=\?'\. Consider opening the module 'Microsoft\.FSharp\.Linq\.NullableOperators'\.$</Expects>
4938
//<Expects status="error" span="(18,12-18,15)" id="FS0043">The type 'System\.Nullable<int>' does not support the operator '\?=\?'\. Consider opening the module 'Microsoft\.FSharp\.Linq\.NullableOperators'\.$</Expects>
50-
//<Expects status="error" span="(19,17-19,19)" id="FS0001">The type 'System\.Nullable<int>' does not support the operator '\?<>\?'\. Consider opening the module 'Microsoft\.FSharp\.Linq\.NullableOperators'\.$</Expects>
5139
//<Expects status="error" span="(19,12-19,16)" id="FS0043">The type 'System\.Nullable<int>' does not support the operator '\?<>\?'\. Consider opening the module 'Microsoft\.FSharp\.Linq\.NullableOperators'\.$</Expects>
52-
//<Expects status="error" span="(21,16-21,18)" id="FS0001">The type 'System\.Nullable<int>' does not support the operator '>=\?'\. Consider opening the module 'Microsoft\.FSharp\.Linq\.NullableOperators'\.$</Expects>
5340
//<Expects status="error" span="(21,12-21,15)" id="FS0043">The type 'System\.Nullable<int>' does not support the operator '>=\?'\. Consider opening the module 'Microsoft\.FSharp\.Linq\.NullableOperators'\.$</Expects>
54-
//<Expects status="error" span="(22,15-22,17)" id="FS0001">The type 'System\.Nullable<int>' does not support the operator '>\?'\. Consider opening the module 'Microsoft\.FSharp\.Linq\.NullableOperators'\.$</Expects>
5541
//<Expects status="error" span="(22,12-22,14)" id="FS0043">The type 'System\.Nullable<int>' does not support the operator '>\?'\. Consider opening the module 'Microsoft\.FSharp\.Linq\.NullableOperators'\.$</Expects>
56-
//<Expects status="error" span="(23,16-23,18)" id="FS0001">The type 'System\.Nullable<int>' does not support the operator '<=\?'\. Consider opening the module 'Microsoft\.FSharp\.Linq\.NullableOperators'\.$</Expects>
5742
//<Expects status="error" span="(23,12-23,15)" id="FS0043">The type 'System\.Nullable<int>' does not support the operator '<=\?'\. Consider opening the module 'Microsoft\.FSharp\.Linq\.NullableOperators'\.$</Expects>
58-
//<Expects status="error" span="(24,15-24,17)" id="FS0001">The type 'System\.Nullable<int>' does not support the operator '<\?'\. Consider opening the module 'Microsoft\.FSharp\.Linq\.NullableOperators'\.$</Expects>
5943
//<Expects status="error" span="(24,12-24,14)" id="FS0043">The type 'System\.Nullable<int>' does not support the operator '<\?'\. Consider opening the module 'Microsoft\.FSharp\.Linq\.NullableOperators'\.$</Expects>
60-
//<Expects status="error" span="(25,15-25,17)" id="FS0001">The type 'System\.Nullable<int>' does not support the operator '=\?'\. Consider opening the module 'Microsoft\.FSharp\.Linq\.NullableOperators'\.$</Expects>
6144
//<Expects status="error" span="(25,12-25,14)" id="FS0043">The type 'System\.Nullable<int>' does not support the operator '=\?'\. Consider opening the module 'Microsoft\.FSharp\.Linq\.NullableOperators'\.$</Expects>
62-
//<Expects status="error" span="(26,16-26,18)" id="FS0001">The type 'System\.Nullable<int>' does not support the operator '<>\?'\. Consider opening the module 'Microsoft\.FSharp\.Linq\.NullableOperators'\.$</Expects>
6345
//<Expects status="error" span="(26,12-26,15)" id="FS0043">The type 'System\.Nullable<int>' does not support the operator '<>\?'\. Consider opening the module 'Microsoft\.FSharp\.Linq\.NullableOperators'\.$</Expects>

0 commit comments

Comments
 (0)