Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit5cac4f6

Browse files
dsymeKevinRansom
authored andcommitted
[RFCs FS-1037] allow flexible inference (subsumption) at union construction (dotnet#5030)
* allow flexible types for union constructor* fix tests and add a test case for structs* quotation test* fix typo* allow flexible inference (subsumption) at list/sequence/array yield points* allow flexible inference (subsumption) at list/sequence/array yield points* suppress warnings for compat purposes* fix build* do not generalize IsCompatFlex variables to ensure code compat* use compat flex for union constructor flex* use compat flex for union constructor flex
1 parentaf95593 commit5cac4f6

File tree

7 files changed

+84
-41
lines changed

7 files changed

+84
-41
lines changed

‎src/fsharp/TypeChecker.fs‎

Lines changed: 36 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2899,27 +2899,39 @@ let MakeApplicableExprNoFlex cenv expr =
28992899
/// This "special" node is immediately eliminated by the use of IteratedFlexibleAdjustArityOfLambdaBody as soon as we
29002900
/// first transform the tree (currently in optimization)
29012901

2902-
let MakeApplicableExprWithFlex cenv (env: TcEnv) expr =
2902+
let MakeApplicableExprWithFlex cenv (env: TcEnv)compatexpr =
29032903
let exprTy = tyOfExpr cenv.g expr
29042904
let m = expr.Range
29052905

29062906
let isNonFlexibleType ty = isSealedTy cenv.g ty
29072907

29082908
let argTys, retTy = stripFunTy cenv.g exprTy
29092909
let curriedActualTypes = argTys |> List.map (tryDestRefTupleTy cenv.g)
2910-
if (curriedActualTypes.IsEmpty ||
2911-
curriedActualTypes |> List.exists (List.exists (isByrefTy cenv.g)) ||
2912-
curriedActualTypes |> List.forall (List.forall isNonFlexibleType)) then
2913-
2910+
let noFlexInserted =
2911+
(curriedActualTypes.IsEmpty ||
2912+
curriedActualTypes |> List.exists (List.exists (isByrefTy cenv.g)) ||
2913+
curriedActualTypes |> List.forall (List.forall isNonFlexibleType))
2914+
2915+
if noFlexInserted then
29142916
ApplicableExpr (cenv, expr, true)
29152917
else
29162918
let curriedFlexibleTypes =
29172919
curriedActualTypes |> List.mapSquared (fun actualType ->
2918-
if isNonFlexibleType actualType
2919-
then actualType
2920+
2921+
if isNonFlexibleType actualType then
2922+
actualType
29202923
else
2924+
29212925
let flexibleType = NewInferenceType ()
2922-
AddCxTypeMustSubsumeType ContextInfo.NoContext env.DisplayEnv cenv.css m NoTrace actualType flexibleType;
2926+
2927+
// For backwards compatibility mark some extra flexibility points as IsCompatFlex, meaning that the
2928+
// type variable will not be generalized
2929+
if compat then
2930+
let tp = destTyparTy cenv.g flexibleType
2931+
tp.SetIsCompatFlex(true)
2932+
2933+
AddCxTypeMustSubsumeType ContextInfo.NoContext env.DisplayEnv cenv.css m NoTrace actualType flexibleType
2934+
29232935
flexibleType)
29242936

29252937
// Create a coercion to represent the expansion of the application
@@ -5179,7 +5191,7 @@ and TcPat warnOnUpper cenv env topValInfo vFlags (tpenv, names, takenNames) ty p
51795191
let args = match args with SynConstructorArgs.Pats args -> args | _ -> error(Error(FSComp.SR.tcNamedActivePattern(apinfo.ActiveTags.[idx]), m))
51805192
// TOTAL/PARTIAL ACTIVE PATTERNS
51815193
let _, vexp, _, _, tinst, _ = TcVal true cenv env tpenv vref None None m
5182-
let vexp = MakeApplicableExprWithFlex cenv env vexp
5194+
let vexp = MakeApplicableExprWithFlex cenv envfalsevexp
51835195
let vexpty = vexp.Type
51845196

51855197
let activePatArgsAsSynPats, patarg =
@@ -5465,8 +5477,13 @@ and TcExprOfUnknownType cenv env tpenv expr =
54655477
and TcExprFlex cenv flex compat ty (env: TcEnv) tpenv (e: SynExpr) =
54665478
if flex then
54675479
let argty = NewInferenceType ()
5480+
5481+
// For backwards compatibility mark some extra flexibility points as IsCompatFlex, meaning that the
5482+
// type variable will not be generalized
54685483
if compat then
5469-
(destTyparTy cenv.g argty).SetIsCompatFlex(true)
5484+
let tp = destTyparTy cenv.g argty
5485+
tp.SetIsCompatFlex(true)
5486+
54705487
AddCxTypeMustSubsumeType ContextInfo.NoContext env.DisplayEnv cenv.css e.Range NoTrace ty argty
54715488
let e', tpenv = TcExpr cenv argty env tpenv e
54725489
let e' = mkCoerceIfNeeded cenv.g ty argty e'
@@ -8583,9 +8600,9 @@ and TcItemThen cenv overallTy env tpenv (item, mItem, rest, afterResolution) del
85838600
let lam = mkMultiLambda mItem vs (constrApp, tyOfExpr cenv.g constrApp)
85848601
lam)
85858602
UnionCaseOrExnCheck env nargtys nargs mItem
8586-
let expr = mkExpr()
8587-
let exprTy =tyOfExpr cenv.gexpr
8588-
PropagateThenTcDelayed cenv overallTy env tpenv mItem(MakeApplicableExprNoFlex cenvexpr) exprTy ExprAtomicFlag.Atomic delayed
8603+
let expr =MakeApplicableExprWithFlex cenv env true (mkExpr())
8604+
let exprTy = expr.Type
8605+
PropagateThenTcDelayed cenv overallTy env tpenv mItem expr exprTy ExprAtomicFlag.Atomic delayed
85898606

85908607
| Item.Types(nm, (typ::_)) ->
85918608

@@ -8878,15 +8895,15 @@ and TcItemThen cenv overallTy env tpenv (item, mItem, rest, afterResolution) del
88788895
// - it isn't a VSlotDirectCall (uses of base values do not take type arguments
88798896
let checkTys tpenv kinds = TcTypesOrMeasures (Some kinds) cenv NewTyparsOK CheckCxs ItemOccurence.UseInType env tpenv tys mItem
88808897
let _, vexp, isSpecial, _, _, tpenv = TcVal true cenv env tpenv vref (Some (NormalValUse, checkTys)) (Some afterResolution) mItem
8881-
let vexpFlex = (if isSpecial then MakeApplicableExprNoFlex cenv vexp else MakeApplicableExprWithFlex cenv env vexp)
8898+
let vexpFlex = (if isSpecial then MakeApplicableExprNoFlex cenv vexp else MakeApplicableExprWithFlex cenv envfalsevexp)
88828899
// We need to eventually record the type resolution for an expression, but this is done
88838900
// inside PropagateThenTcDelayed, so we don't have to explicitly call 'CallExprHasTypeSink' here
88848901
PropagateThenTcDelayed cenv overallTy env tpenv mExprAndTypeArgs vexpFlex vexpFlex.Type ExprAtomicFlag.Atomic otherDelayed
88858902

88868903
// Value get
88878904
| _ ->
88888905
let _, vexp, isSpecial, _, _, tpenv = TcVal true cenv env tpenv vref None (Some afterResolution) mItem
8889-
let vexpFlex = (if isSpecial then MakeApplicableExprNoFlex cenv vexp else MakeApplicableExprWithFlex cenv env vexp)
8906+
let vexpFlex = (if isSpecial then MakeApplicableExprNoFlex cenv vexp else MakeApplicableExprWithFlex cenv envfalsevexp)
88908907
PropagateThenTcDelayed cenv overallTy env tpenv mItem vexpFlex vexpFlex.Type ExprAtomicFlag.Atomic delayed
88918908

88928909
| Item.Property (nm, pinfos) ->
@@ -8947,7 +8964,7 @@ and TcItemThen cenv overallTy env tpenv (item, mItem, rest, afterResolution) del
89478964

89488965
// Add an I_nop if this is an initonly field to make sure we never recognize it as an lvalue. See mkExprAddrOfExpr.
89498966
mkAsmExpr ([ mkNormalLdsfld fspec ] @ (if finfo.IsInitOnly then [ AI_nop ] else []), finfo.TypeInst, [], [exprty], mItem)
8950-
PropagateThenTcDelayed cenv overallTy env tpenv mItem (MakeApplicableExprWithFlex cenv env expr) exprty ExprAtomicFlag.Atomic delayed
8967+
PropagateThenTcDelayed cenv overallTy env tpenv mItem (MakeApplicableExprWithFlex cenv envfalseexpr) exprty ExprAtomicFlag.Atomic delayed
89518968

89528969
| Item.RecdField rfinfo ->
89538970
// Get static F# field or literal
@@ -8976,7 +8993,7 @@ and TcItemThen cenv overallTy env tpenv (item, mItem, rest, afterResolution) del
89768993
| Some lit -> Expr.Const(lit, mItem, exprty)
89778994
// Get static F# field
89788995
| None -> mkStaticRecdFieldGet (fref, rfinfo.TypeInst, mItem)
8979-
PropagateThenTcDelayed cenv overallTy env tpenv mItem (MakeApplicableExprWithFlex cenv env expr) exprty ExprAtomicFlag.Atomic delayed
8996+
PropagateThenTcDelayed cenv overallTy env tpenv mItem (MakeApplicableExprWithFlex cenv envfalseexpr) exprty ExprAtomicFlag.Atomic delayed
89808997

89818998
| Item.Event einfo ->
89828999
// Instance IL event (fake up event-as-value)
@@ -9112,7 +9129,7 @@ and TcLookupThen cenv overallTy env tpenv mObjExpr objExpr objExprTy longId dela
91129129

91139130
// Instance F# Record or Class field
91149131
let objExpr' = mkRecdFieldGet cenv.g (objExpr, rfinfo.RecdFieldRef, rfinfo.TypeInst, mExprAndItem)
9115-
PropagateThenTcDelayed cenv overallTy env tpenv mExprAndItem (MakeApplicableExprWithFlex cenv env objExpr') fieldTy ExprAtomicFlag.Atomic delayed
9132+
PropagateThenTcDelayed cenv overallTy env tpenv mExprAndItem (MakeApplicableExprWithFlex cenv envfalseobjExpr') fieldTy ExprAtomicFlag.Atomic delayed
91169133

91179134
| Item.ILField finfo ->
91189135
// Get or set instance IL field
@@ -9129,7 +9146,7 @@ and TcLookupThen cenv overallTy env tpenv mObjExpr objExpr objExprTy longId dela
91299146
expr, tpenv
91309147
| _ ->
91319148
let expr = BuildILFieldGet cenv.g cenv.amap mExprAndItem objExpr finfo
9132-
PropagateThenTcDelayed cenv overallTy env tpenv mExprAndItem (MakeApplicableExprWithFlex cenv env expr) exprty ExprAtomicFlag.Atomic delayed
9149+
PropagateThenTcDelayed cenv overallTy env tpenv mExprAndItem (MakeApplicableExprWithFlex cenv envfalseexpr) exprty ExprAtomicFlag.Atomic delayed
91339150

91349151
| Item.Event einfo ->
91359152
// Instance IL event (fake up event-as-value)

‎tests/fsharp/core/quotes/test.fsx‎

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1744,6 +1744,30 @@ module QuotationStructUnionTests =
17441744
//test "check NewUnionCase" (<@ A1(1,2) @> |> (function NewUnionCase(unionCase,[ Int32 1; Int32 2 ]) -> true | _ -> false))
17451745

17461746

1747+
moduleFlexibleUnionConstructorTests=
1748+
1749+
[<Struct>]
1750+
typeT=| Aofseq<int>
1751+
1752+
typeU=| Bofseq<int>
1753+
lettestList=[1..3]
1754+
lettestFunction caseName x=
1755+
match xwith
1756+
| Call(None,_,
1757+
[PropertyGet(None,_,_);
1758+
Let(_, Lambda(_, NewUnionCase(unioncase,_)),
1759+
Lambda(_, Application(_, Coerce(_, ty))))])->
1760+
unioncase.Name= caseName&&
1761+
ty.Name="IEnumerable`1"
1762+
|_->false
1763+
1764+
test"check struct flexible union constructor"
1765+
(<@ testList|> A@>|> testFunction"A")
1766+
1767+
test"check flexible union constructor"
1768+
(<@ testList|> B@>|> testFunction"B")
1769+
1770+
17471771
moduleEqualityOnExprDoesntFail=
17481772
letq=<@1@>
17491773
check"we09ceo"(q.Equals(1))false

‎tests/fsharp/typecheck/sigs/neg20.bsl‎

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -131,24 +131,6 @@ but here has type
131131

132132
neg20.fs(99,26,99,33): typecheck error FS0001: All elements of a list constructor expression must have the same type. This expression was expectedto have type 'B', but here has type 'A'.
133133

134-
neg20.fs(108,12,108,16): typecheck error FS0001: Type mismatch. Expecting a
135-
'B* B-> 'a'
136-
but given a
137-
'A* A-> Data'
138-
The type 'B' doesnot match the type 'A'
139-
140-
neg20.fs(109,12,109,16): typecheck error FS0001: Type mismatch. Expecting a
141-
'A* B-> 'a'
142-
but given a
143-
'A* A-> Data'
144-
The type 'B' doesnot match the type 'A'
145-
146-
neg20.fs(110,12,110,16): typecheck error FS0001: Type mismatch. Expecting a
147-
'B* A-> 'a'
148-
but given a
149-
'A* A-> Data'
150-
The type 'B' doesnot match the type 'A'
151-
152134
neg20.fs(128,19,128,22): typecheck error FS0001: This expression was expectedto have type
153135
'string'
154136
but here has type

‎tests/fsharp/typecheck/sigs/neg20.fs‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -105,9 +105,9 @@ module NoSubsumptionForLists2 =
105105
letpBB=(new B(),new B())
106106
letpAB=(new A(),new B())
107107
letpBA=(new B(),new A())
108-
pBB|> Data//notpermitted (questionable)
109-
pAB|> Data//notpermitted (questionable)
110-
pBA|> Data//notpermitted (questionable)
108+
pBB|> Data// permitted
109+
pAB|> Data// permitted
110+
pBA|> Data// permitted
111111
pBB|> data// permitted
112112
pAB|> data// permitted
113113
pBA|> data// permitted
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// #Conformance #TypesAndModules #Unions
2+
// DU constructor should be flexible when piping
3+
//<Expects status=success></Expects>
4+
5+
typeFoo= Itemsofseq<int>
6+
[1;2;3]|> Items
7+
8+
exit0
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// #Conformance #TypesAndModules #Unions
2+
// Struct DU constructor should be flexible when piping
3+
//<Expects status=success></Expects>
4+
5+
[<Struct>]
6+
typeFoo= Itemsofseq<int>
7+
[1;2;3]|> Items
8+
9+
exit0

‎tests/fsharpqa/Source/Conformance/BasicTypeAndModuleDefinitions/UnionTypes/env.lst‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,4 +99,7 @@ NoMTSOURCE=Overload_ToString.fs COMPILE_ONLY=1 SCFLAGS=--warnaserror+ FSIMOD
9999
SOURCE=E_UnionFieldConflictingName.fs SCFLAGS="--test:ErrorRanges"# E_UnionFieldConflictingName.fs
100100
SOURCE=E_UnionConstructorBadFieldName.fs SCFLAGS="--test:ErrorRanges"# E_UnionConstructorBadFieldName.fs
101101
SOURCE=E_FieldNameUsedMulti.fs SCFLAGS="--test:ErrorRanges"# E_FieldNameUsedMulti.fs
102-
SOURCE=E_FieldMemberClash.fs SCFLAGS="--test:ErrorRanges"# E_FieldMemberClash.fs
102+
SOURCE=E_FieldMemberClash.fs SCFLAGS="--test:ErrorRanges"# E_FieldMemberClash.fs
103+
104+
SOURCE=ConstructorFlexibleWhenPiping.fsx# ConstructorFlexibleWhenPiping.fsx
105+
SOURCE=StructConstructorFlexibleWhenPiping.fsx# StructConstructorFlexibleWhenPiping.fsx

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp