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

Commitbbe06d5

Browse files
dsymeKevinRansom
authored andcommitted
[RFCs FS-1037, FS-1055] allow flexible inference (subsumption) at union construction and list/sequence/array yield points (#4930)
* 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
1 parent28e0bf5 commitbbe06d5

File tree

6 files changed

+171
-76
lines changed

6 files changed

+171
-76
lines changed

‎src/fsharp/ConstraintSolver.fs‎

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -418,8 +418,6 @@ let PreferUnifyTypar (v1:Typar) (v2:Typar) =
418418
|true,false->false
419419
|_->true
420420

421-
422-
423421
/// Reorder a list of (variable, exponent) pairs so that a variable that is Preferred
424422
/// is at the head of the list, if possible
425423
letFindPreferredTypar vs=
@@ -471,12 +469,12 @@ and SolveTypStaticReq (csenv:ConstraintSolverEnv) trace req ty =
471469
| Some tpr-> SolveTypStaticReqTypar csenv trace req tpr
472470
| None-> CompleteD
473471

474-
letrecTransactDynamicReq(trace:OptionalTrace)(tpr:Typar)req=
472+
letTransactDynamicReq(trace:OptionalTrace)(tpr:Typar)req=
475473
letorig= tpr.DynamicReq
476474
trace.Exec(fun()-> tpr.SetDynamicReq req)(fun()-> tpr.SetDynamicReq orig)
477475
CompleteD
478476

479-
andSolveTypDynamicReq(csenv:ConstraintSolverEnv)trace req ty=
477+
letSolveTypDynamicReq(csenv:ConstraintSolverEnv)trace req ty=
480478
match reqwith
481479
| TyparDynamicReq.No-> CompleteD
482480
| TyparDynamicReq.Yes->
@@ -485,6 +483,19 @@ and SolveTypDynamicReq (csenv:ConstraintSolverEnv) trace req ty =
485483
TransactDynamicReq trace tpr TyparDynamicReq.Yes
486484
|_-> CompleteD
487485

486+
letTransactIsCompatFlex(trace:OptionalTrace)(tpr:Typar)req=
487+
letorig= tpr.IsCompatFlex
488+
trace.Exec(fun()-> tpr.SetIsCompatFlex req)(fun()-> tpr.SetIsCompatFlex orig)
489+
CompleteD
490+
491+
letSolveTypIsCompatFlex(csenv:ConstraintSolverEnv)trace req ty=
492+
if reqthen
493+
match tryAnyParTy csenv.g tywith
494+
| Some tprwhennot tpr.IsCompatFlex-> TransactIsCompatFlex trace tpr req
495+
|_-> CompleteD
496+
else
497+
CompleteD
498+
488499
letSubstMeasureWarnIfRigid(csenv:ConstraintSolverEnv)trace(v:Typar)ms=
489500
if v.Rigidity.WarnIfUnified&&not(isAnyParTy csenv.g(TType_measure ms))then
490501
// NOTE: we grab the name eagerly to make sure the type variable prints as a type variable
@@ -717,21 +728,23 @@ let rec SolveTyparEqualsTyp (csenv:ConstraintSolverEnv) ndeep m2 (trace:Optional
717728
CompleteD)++(fun _->
718729

719730
// Re-solve the other constraints associated with this type variable
720-
solveTypMeetsTyparConstraints csenv ndeep m2 trace ty(r.DynamicReq, r.StaticReq, r.Constraints)))
731+
solveTypMeetsTyparConstraints csenv ndeep m2 trace tyr))
721732

722733
|_-> failwith"SolveTyparEqualsTyp")
723734

724735

725-
///Given a type 'ty' and a set of constraints on thattype, solve those constraints.
726-
andsolveTypMeetsTyparConstraints(csenv:ConstraintSolverEnv)ndeep m2 trace ty(dreq,sreq,cs)=
736+
///Apply the constraints on 'typar' to thetype 'ty'
737+
andsolveTypMeetsTyparConstraints(csenv:ConstraintSolverEnv)ndeep m2 trace ty(r:Typar)=
727738
letg= csenv.g
739+
// Propagate compat flex requirements from 'tp' to 'ty'
740+
SolveTypIsCompatFlex csenv trace r.IsCompatFlex ty++(fun()->
728741
// Propagate dynamic requirements from 'tp' to 'ty'
729-
SolveTypDynamicReq csenv tracedreq ty++(fun()->
742+
SolveTypDynamicReq csenv tracer.DynamicReq ty++(fun()->
730743
// Propagate static requirements from 'tp' to 'ty'
731-
SolveTypStaticReq csenv tracesreq ty++(fun()->
744+
SolveTypStaticReq csenv tracer.StaticReq ty++(fun()->
732745

733746
// Solve constraints on 'tp' w.r.t. 'ty'
734-
cs|> IterateD(function
747+
r.Constraints|> IterateD(function
735748
| TyparConstraint.DefaultsTo(priority, dty, m)->
736749
if typeEquiv g ty dtythen
737750
CompleteD
@@ -754,7 +767,7 @@ and solveTypMeetsTyparConstraints (csenv:ConstraintSolverEnv) ndeep m2 trace ty
754767
| TyparConstraint.CoercesTo(ty2, m2)-> SolveTypSubsumesTypKeepAbbrevs csenv ndeep m2 trace None ty2 ty
755768
| TyparConstraint.MayResolveMember(traitInfo, m2)->
756769
SolveMemberConstraint csenvfalsefalse ndeep m2 trace traitInfo++(fun _-> CompleteD)
757-
)))
770+
))))
758771

759772

760773
/// Add the constraint "ty1 = ty2" to the constraint problem.

‎src/fsharp/TypeChecker.fs‎

Lines changed: 55 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -2164,11 +2164,13 @@ module GeneralizationHelpers =
21642164

21652165
// Some situations, e.g. implicit class constructions that represent functions as fields,
21662166
// do not allow generalisation over constrained typars. (since they can not be represented as fields)
2167+
//
2168+
// Don't generalize IsCompatFlex type parameters to avoid changing inferred types.
21672169
let generalizedTypars, ungeneralizableTypars3 =
21682170
generalizedTypars
21692171
|> List.partition (fun tp ->
2170-
genConstrainedTyparFlag = CanGeneralizeConstrainedTypars ||
2171-
tp.Constraints.IsEmpty)
2172+
(genConstrainedTyparFlag = CanGeneralizeConstrainedTypars ||tp.Constraints.IsEmpty) &&
2173+
nottp.IsCompatFlex)
21722174

21732175
if isNil ungeneralizableTypars1 && isNil ungeneralizableTypars2 && isNil ungeneralizableTypars3 then
21742176
generalizedTypars, freeInEnv
@@ -2930,7 +2932,7 @@ let TcRuntimeTypeTest isCast isOperator cenv denv m tgty srcTy =
29302932
if TypeDefinitelySubsumesTypeNoCoercion 0 cenv.g cenv.amap m tgty srcTy then
29312933
warning(TypeTestUnnecessary(m))
29322934

2933-
if isTyparTy cenv.g srcTy then
2935+
if isTyparTy cenv.g srcTy&& not (destTyparTy cenv.g srcTy).IsCompatFlexthen
29342936
error(IndeterminateRuntimeCoercion(denv, srcTy, tgty, m))
29352937

29362938
if isSealedTy cenv.g srcTy then
@@ -2956,20 +2958,18 @@ let TcRuntimeTypeTest isCast isOperator cenv denv m tgty srcTy =
29562958
/// Checks, warnings and constraint assertions for upcasts
29572959
let TcStaticUpcast cenv denv m tgty srcTy =
29582960
if isTyparTy cenv.g tgty then
2959-
error(IndeterminateStaticCoercion(denv, srcTy, tgty, m))
2961+
if not (destTyparTy cenv.g tgty).IsCompatFlex then
2962+
error(IndeterminateStaticCoercion(denv, srcTy, tgty, m))
2963+
//else warning(UpcastUnnecessary(m))
29602964

2961-
if isSealedTy cenv.g tgty then
2965+
if isSealedTy cenv.g tgty&& not (isTyparTy cenv.g tgty)then
29622966
warning(CoercionTargetSealed(denv, tgty, m))
29632967

29642968
if typeEquiv cenv.g srcTy tgty then
29652969
warning(UpcastUnnecessary(m))
29662970

29672971
AddCxTypeMustSubsumeType ContextInfo.NoContext denv cenv.css m NoTrace tgty srcTy
29682972

2969-
2970-
2971-
2972-
29732973
let BuildPossiblyConditionalMethodCall cenv env isMutable m isProp minfo valUseFlags minst objArgs args =
29742974

29752975
let conditionalCallDefineOpt = TryFindMethInfoStringAttribute cenv.g m cenv.g.attrib_ConditionalAttribute minfo
@@ -5460,9 +5460,11 @@ and TcExprOfUnknownType cenv env tpenv expr =
54605460
let expr', tpenv = TcExpr cenv exprty env tpenv expr
54615461
expr', exprty, tpenv
54625462

5463-
and TcExprFlex cenv flex ty (env: TcEnv) tpenv (e: SynExpr) =
5463+
and TcExprFlex cenv flexcompatty (env: TcEnv) tpenv (e: SynExpr) =
54645464
if flex then
54655465
let argty = NewInferenceType ()
5466+
if compat then
5467+
(destTyparTy cenv.g argty).SetIsCompatFlex(true)
54665468
AddCxTypeMustSubsumeType ContextInfo.NoContext env.DisplayEnv cenv.css e.Range NoTrace ty argty
54675469
let e', tpenv = TcExpr cenv argty env tpenv e
54685470
let e' = mkCoerceIfNeeded cenv.g ty argty e'
@@ -5592,7 +5594,7 @@ and TcExprThen cenv overallTy env tpenv synExpr delayed =
55925594
and TcExprs cenv env m tpenv flexes argtys args =
55935595
if List.length args <> List.length argtys then error(Error(FSComp.SR.tcExpressionCountMisMatch((List.length argtys), (List.length args)), m))
55945596
(tpenv, List.zip3 flexes argtys args) ||> List.mapFold (fun tpenv (flex, ty, e) ->
5595-
TcExprFlex cenv flex ty env tpenv e)
5597+
TcExprFlex cenv flexfalsety env tpenv e)
55965598

55975599
and CheckSuperInit cenv objTy m =
55985600
// Check the type is not abstract
@@ -5757,7 +5759,7 @@ and TcExprUndelayed cenv overallTy env tpenv (expr: SynExpr) =
57575759
else
57585760
{ env with eContextInfo = ContextInfo.CollectionElement (isArray, m) }
57595761

5760-
let args', tpenv = List.mapFold (fun tpenv (x:SynExpr) -> TcExprFlex cenv flex argty (getInitEnv x.Range) tpenv x) tpenv args
5762+
let args', tpenv = List.mapFold (fun tpenv (x:SynExpr) -> TcExprFlex cenv flexfalseargty (getInitEnv x.Range) tpenv x) tpenv args
57615763

57625764
let expr =
57635765
if isArray then Expr.Op(TOp.Array, [argty], args', m)
@@ -5844,19 +5846,37 @@ and TcExprUndelayed cenv overallTy env tpenv (expr: SynExpr) =
58445846

58455847
TcExprUndelayed cenv overallTy env tpenv replacementExpr
58465848
| _ ->
5849+
58475850
let genCollElemTy = NewInferenceType ()
5851+
58485852
let genCollTy = (if isArray then mkArrayType else mkListTy) cenv.g genCollElemTy
5853+
58495854
UnifyTypes cenv env m overallTy genCollTy
5850-
let exprty = NewInferenceType ()
5851-
let genEnumTy = mkSeqTy cenv.g genCollElemTy
5852-
AddCxTypeMustSubsumeType ContextInfo.NoContext env.DisplayEnv cenv.css m NoTrace genEnumTy exprty
5855+
5856+
let exprty = mkSeqTy cenv.g genCollElemTy
5857+
5858+
// Check the comprehension
58535859
let expr, tpenv = TcExpr cenv exprty env tpenv comp
5854-
let expr = mkCoerceIfNeeded cenv.g genEnumTy (tyOfExpr cenv.g expr) expr
5855-
(if isArray then mkCallSeqToArray else mkCallSeqToList) cenv.g m genCollElemTy
5856-
// We add a call to 'seq ... ' to make sure sequence expression compilation gets applied to the contents of the
5857-
// comprehension. But don't do this in FSharp.Core.dll since 'seq' may not yet be defined.
5858-
((if cenv.g.compilingFslib then id else mkCallSeq cenv.g m genCollElemTy)
5859-
(mkCoerceExpr(expr, genEnumTy, expr.Range, exprty))), tpenv
5860+
5861+
let expr = mkCoerceIfNeeded cenv.g exprty (tyOfExpr cenv.g expr) expr
5862+
5863+
let expr =
5864+
if cenv.g.compilingFslib then
5865+
expr
5866+
else
5867+
// We add a call to 'seq ... ' to make sure sequence expression compilation gets applied to the contents of the
5868+
// comprehension. But don't do this in FSharp.Core.dll since 'seq' may not yet be defined.
5869+
mkCallSeq cenv.g m genCollElemTy expr
5870+
5871+
let expr = mkCoerceExpr(expr, exprty, expr.Range, overallTy)
5872+
5873+
let expr =
5874+
if isArray then
5875+
mkCallSeqToArray cenv.g m genCollElemTy expr
5876+
else
5877+
mkCallSeqToList cenv.g m genCollElemTy expr
5878+
5879+
expr, tpenv
58605880

58615881
| SynExpr.LetOrUse _ ->
58625882
TcLinearExprs (TcExprThatCanBeCtorBody cenv) cenv env overallTy tpenv false expr (fun x -> x)
@@ -6069,6 +6089,7 @@ and TcIteratedLambdas cenv isFirst (env: TcEnv) overallTy takenNames tpenv e =
60696089
| e ->
60706090
// Dive into the expression to check for syntax errors and suppress them if they show.
60716091
conditionallySuppressErrorReporting (not isFirst && synExprContainsError e) (fun () ->
6092+
//TcExprFlex cenv true true overallTy env tpenv e)
60726093
TcExpr cenv overallTy env tpenv e)
60736094

60746095

@@ -6279,7 +6300,7 @@ and TcRecordConstruction cenv overallTy env tpenv optOrigExpr objTy fldsList m =
62796300
let fldsList, tpenv =
62806301
let env = { env with eContextInfo = ContextInfo.RecordFields }
62816302
(tpenv, fldsList) ||> List.mapFold (fun tpenv (fname, fexpr, fty, flex) ->
6282-
let fieldExpr, tpenv = TcExprFlex cenv flex fty env tpenv fexpr
6303+
let fieldExpr, tpenv = TcExprFlex cenv flexfalsefty env tpenv fexpr
62836304
(fname, fieldExpr), tpenv)
62846305

62856306
// Add rebindings for unbound field when an "old value" is available
@@ -8068,6 +8089,12 @@ and TcComputationExpression cenv env overallTy mWhole interpExpr builderTy tpenv
80688089
/// Also "ienumerable extraction" is performed on arguments to "for".
80698090
and TcSequenceExpression cenv env tpenv comp overallTy m =
80708091

8092+
let genEnumElemTy = NewInferenceType ()
8093+
UnifyTypes cenv env m overallTy (mkSeqTy cenv.g genEnumElemTy)
8094+
8095+
// Allow subsumption at 'yield' if the element type is nominal prior to the analysis of the body of the sequence expression
8096+
let flex = not (isTyparTy cenv.g genEnumElemTy)
8097+
80718098
let mkDelayedExpr (coreExpr:Expr) =
80728099
let m = coreExpr.Range
80738100
let overallTy = tyOfExpr cenv.g coreExpr
@@ -8217,7 +8244,7 @@ and TcSequenceExpression cenv env tpenv comp overallTy m =
82178244
if not isYield then errorR(Error(FSComp.SR.tcSeqResultsUseYield(), m))
82188245
UnifyTypes cenv env m genOuterTy (mkSeqTy cenv.g genResultTy)
82198246

8220-
let resultExpr, tpenv =TcExpr cenv genResultTy env tpenv yieldExpr
8247+
let resultExpr, tpenv =TcExprFlex cenv flex true genResultTy env tpenv yieldExpr
82218248
Some(mkCallSeqSingleton cenv.g m genResultTy resultExpr, tpenv )
82228249

82238250
| _ -> None
@@ -8233,9 +8260,6 @@ and TcSequenceExpression cenv env tpenv comp overallTy m =
82338260
let expr, tpenv = TcStmtThatCantBeCtorBody cenv env tpenv comp
82348261
Expr.Sequential(expr, mkSeqEmpty cenv env m genOuterTy, NormalSeq, SuppressSequencePointOnStmtOfSequential, m), tpenv
82358262

8236-
let genEnumElemTy = NewInferenceType ()
8237-
UnifyTypes cenv env m overallTy (mkSeqTy cenv.g genEnumElemTy)
8238-
82398263
let coreExpr, tpenv = tcSequenceExprBody env overallTy tpenv comp
82408264
let delayedExpr = mkDelayedExpr coreExpr
82418265
delayedExpr, tpenv
@@ -8823,7 +8847,7 @@ and TcItemThen cenv overallTy env tpenv (item, mItem, rest, afterResolution) del
88238847
if not vref.IsMutable then error (ValNotMutable(env.DisplayEnv, vref, mStmt))
88248848
vty
88258849
// Always allow subsumption on assignment to fields
8826-
let e2', tpenv = TcExprFlex cenv true vty2 env tpenv e2
8850+
let e2', tpenv = TcExprFlex cenv truefalsevty2 env tpenv e2
88278851
let vexp =
88288852
if isByrefTy cenv.g vty then
88298853
mkAddrSet mStmt vref e2'
@@ -8889,7 +8913,7 @@ and TcItemThen cenv overallTy env tpenv (item, mItem, rest, afterResolution) del
88898913
| DelayedSet(e2, mStmt) :: _delayed' ->
88908914
UnifyTypes cenv env mStmt overallTy cenv.g.unit_ty
88918915
// Always allow subsumption on assignment to fields
8892-
let e2', tpenv = TcExprFlex cenv true exprty env tpenv e2
8916+
let e2', tpenv = TcExprFlex cenv truefalseexprty env tpenv e2
88938917
let expr = BuildILStaticFieldSet mStmt finfo e2'
88948918
expr, tpenv
88958919
| _ ->
@@ -8927,7 +8951,7 @@ and TcItemThen cenv overallTy env tpenv (item, mItem, rest, afterResolution) del
89278951
UnifyTypes cenv env mStmt overallTy cenv.g.unit_ty
89288952
let fieldTy = rfinfo.FieldType
89298953
// Always allow subsumption on assignment to fields
8930-
let e2', tpenv = TcExprFlex cenv true fieldTy env tpenv e2
8954+
let e2', tpenv = TcExprFlex cenv truefalsefieldTy env tpenv e2
89318955
let expr = mkStaticRecdFieldSet (rfinfo.RecdFieldRef, rfinfo.TypeInst, e2', mStmt)
89328956
expr, tpenv
89338957
| _ ->
@@ -9067,7 +9091,7 @@ and TcLookupThen cenv overallTy env tpenv mObjExpr objExpr objExprTy longId dela
90679091
CheckRecdFieldMutation mItem env.DisplayEnv rfinfo
90689092
UnifyTypes cenv env mStmt overallTy cenv.g.unit_ty
90699093
// Always allow subsumption on assignment to fields
9070-
let e2', tpenv = TcExprFlex cenv true fieldTy env tpenv e2
9094+
let e2', tpenv = TcExprFlex cenv truefalsefieldTy env tpenv e2
90719095
BuildRecdFieldSet cenv.g mStmt objExpr rfinfo e2', tpenv
90729096

90739097
| _ ->
@@ -9086,7 +9110,7 @@ and TcLookupThen cenv overallTy env tpenv mObjExpr objExpr objExprTy longId dela
90869110
| DelayedSet(e2, mStmt) :: _delayed' ->
90879111
UnifyTypes cenv env mStmt overallTy cenv.g.unit_ty
90889112
// Always allow subsumption on assignment to fields
9089-
let e2', tpenv = TcExprFlex cenv true exprty env tpenv e2
9113+
let e2', tpenv = TcExprFlex cenv truefalseexprty env tpenv e2
90909114
let expr = BuildILFieldSet cenv.g mStmt objExpr finfo e2'
90919115
expr, tpenv
90929116
| _ ->

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp