Skip to content

Commit

Permalink
Propose to use :> instead of :?> - fixes dotnet#1127
Browse files Browse the repository at this point in the history
  • Loading branch information
forki committed May 9, 2016
1 parent 1d4ee97 commit e07d985
Show file tree
Hide file tree
Showing 10 changed files with 77 additions and 54 deletions.
30 changes: 19 additions & 11 deletions src/fsharp/CompileOps.fs
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ let GetRangeOfError(err:PhasedError) =
| IndentationProblem(_,m)
| ErrorFromAddingTypeEquation(_,_,_,_,_,_,m)
| ErrorFromApplyingDefault(_,_,_,_,_,m)
| ErrorsFromAddingSubsumptionConstraint(_,_,_,_,_,m)
| ErrorsFromAddingSubsumptionConstraint(_,_,_,_,_,_,m)
| FunctionExpected(_,_,m)
| BakedInMemberConstraintName(_,m)
| StandardOperatorRedefinitionWarning(_,m)
Expand Down Expand Up @@ -369,6 +369,7 @@ let GetErrorNumber(err:PhasedError) =
#if EXTENSIONTYPING
| :? TypeProviderError as e -> e.Number
#endif
| ErrorsFromAddingSubsumptionConstraint (_,_,_,_,_,ContextInfo.DowncastUsedInsteadOfUpcast,_) -> fst (FSComp.SR.considerUpcast("",""))
| _ -> 193
GetFromException err.Exception

Expand Down Expand Up @@ -413,9 +414,9 @@ let SplitRelatedErrors(err:PhasedError) =
| ErrorFromApplyingDefault(g,denv,tp,defaultType,e,m) ->
let e,related = SplitRelatedException e
ErrorFromApplyingDefault(g,denv,tp,defaultType,e.Exception,m)|>ToPhased, related
| ErrorsFromAddingSubsumptionConstraint(g,denv,t1,t2,e,m) ->
| ErrorsFromAddingSubsumptionConstraint(g,denv,t1,t2,e,contextInfo,m) ->
let e,related = SplitRelatedException e
ErrorsFromAddingSubsumptionConstraint(g,denv,t1,t2,e.Exception,m)|>ToPhased, related
ErrorsFromAddingSubsumptionConstraint(g,denv,t1,t2,e.Exception,contextInfo,m)|>ToPhased, related
| ErrorFromAddingConstraint(x,e,m) ->
let e,related = SplitRelatedException e
ErrorFromAddingConstraint(x,e.Exception,m)|>ToPhased, related
Expand Down Expand Up @@ -645,7 +646,7 @@ let OutputPhasedErrorR (os:System.Text.StringBuilder) (err:PhasedError) =
match contextInfo with
| ContextInfo.OmittedElseBranch -> os.Append(FSComp.SR.missingElseBranch(t2)) |> ignore
| ContextInfo.ElseBranchWithDifferentType -> os.Append(FSComp.SR.elseBranchHasWrongType(t1,t2)) |> ignore
| ContextInfo.NoContext -> os.Append(ErrorFromAddingTypeEquation1E().Format t2 t1 tpcs) |> ignore
| _ -> os.Append(ErrorFromAddingTypeEquation1E().Format t2 t1 tpcs) |> ignore
| ErrorFromAddingTypeEquation(_,_,_,_,((ConstraintSolverTypesNotInSubsumptionRelation _ | ConstraintSolverError _) as e), _, _) ->
OutputExceptionR os e
| ErrorFromAddingTypeEquation(g,denv,t1,t2,e,_,_) ->
Expand All @@ -659,13 +660,20 @@ let OutputPhasedErrorR (os:System.Text.StringBuilder) (err:PhasedError) =
os.Append(ErrorFromApplyingDefault1E().Format defaultType) |> ignore
OutputExceptionR os e
os.Append(ErrorFromApplyingDefault2E().Format) |> ignore
| ErrorsFromAddingSubsumptionConstraint(g,denv,t1,t2,e,_) ->
if not (typeEquiv g t1 t2) then (
let t1,t2,tpcs = NicePrint.minimalStringsOfTwoTypes denv t1 t2
if t1 <> (t2 + tpcs) then
os.Append(ErrorsFromAddingSubsumptionConstraintE().Format t2 t1 tpcs) |> ignore
)
OutputExceptionR os e
| ErrorsFromAddingSubsumptionConstraint(g,denv,t1,t2,e,contextInfo,_) ->
match contextInfo with
| ContextInfo.DowncastUsedInsteadOfUpcast ->
let t1,t2,_ = NicePrint.minimalStringsOfTwoTypes denv t1 t2
os.Append(FSComp.SR.considerUpcast(t1,t2) |> snd) |> ignore
| _ ->
if not (typeEquiv g t1 t2) then
let t1,t2,tpcs = NicePrint.minimalStringsOfTwoTypes denv t1 t2
if t1 <> (t2 + tpcs) then
os.Append(ErrorsFromAddingSubsumptionConstraintE().Format t2 t1 tpcs) |> ignore
else
OutputExceptionR os e
else
OutputExceptionR os e
| UpperCaseIdentifierInPattern(_) ->
os.Append(UpperCaseIdentifierInPatternE().Format) |> ignore
| NotUpperCaseConstructor(_) ->
Expand Down
29 changes: 19 additions & 10 deletions src/fsharp/ConstraintSolver.fs
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,10 @@ type ContextInfo =
| OmittedElseBranch
/// The type equation comes from an else branch that might have different type than the corresponding if branch.
| ElseBranchWithDifferentType
/// The type equation comes from a runtime type test.
| RuntimeTypeTest
/// The type equation comes from an downcast where a upcast could be used.
| DowncastUsedInsteadOfUpcast

exception ConstraintSolverTupleDiffLengths of DisplayEnv * TType list * TType list * range * range
exception ConstraintSolverInfiniteTypes of DisplayEnv * TType * TType * range * range
Expand All @@ -135,7 +139,7 @@ exception ConstraintSolverRelatedInformation of string option * range * exn

exception ErrorFromApplyingDefault of TcGlobals * DisplayEnv * Tast.Typar * TType * exn * range
exception ErrorFromAddingTypeEquation of TcGlobals * DisplayEnv * TType * TType * exn * ContextInfo * range
exception ErrorsFromAddingSubsumptionConstraint of TcGlobals * DisplayEnv * TType * TType * exn * range
exception ErrorsFromAddingSubsumptionConstraint of TcGlobals * DisplayEnv * TType * TType * exn * ContextInfo * range
exception ErrorFromAddingConstraint of DisplayEnv * exn * range
exception PossibleOverload of DisplayEnv * string * exn * range
exception UnresolvedOverloading of DisplayEnv * exn list * string * range
Expand Down Expand Up @@ -1918,9 +1922,16 @@ and private DefinitelyEquiv (csenv:ConstraintSolverEnv) isConstraint calledArg (

// Assert a subtype constraint, and wrap an ErrorsFromAddingSubsumptionConstraint error around any failure
// to allow us to report the outer types involved in the constraint
and private SolveTypSubsumesTypWithReport (csenv:ConstraintSolverEnv) ndeep m trace ty1 ty2 =
and private SolveTypSubsumesTypWithReport contextInfo (csenv:ConstraintSolverEnv) ndeep m trace ty1 ty2 =
TryD (fun () -> SolveTypSubsumesTypKeepAbbrevs csenv ndeep m trace ty1 ty2)
(fun res -> ErrorD (ErrorsFromAddingSubsumptionConstraint(csenv.g,csenv.DisplayEnv,ty1,ty2,res,m)))
(fun res ->
match contextInfo with
| ContextInfo.RuntimeTypeTest ->
// test if we can cast other way around
match CollectThenUndo (fun newTrace -> SolveTypSubsumesTypKeepAbbrevs csenv ndeep m (OptionalTrace.WithTrace newTrace) ty2 ty1) with
| OkResult _ -> ErrorD (ErrorsFromAddingSubsumptionConstraint(csenv.g,csenv.DisplayEnv,ty1,ty2,res,ContextInfo.DowncastUsedInsteadOfUpcast,m))
| _ -> ErrorD (ErrorsFromAddingSubsumptionConstraint(csenv.g,csenv.DisplayEnv,ty1,ty2,res,ContextInfo.NoContext,m))
| _ -> ErrorD (ErrorsFromAddingSubsumptionConstraint(csenv.g,csenv.DisplayEnv,ty1,ty2,res,contextInfo,m)))

and private SolveTypEqualsTypWithReport contextInfo (csenv:ConstraintSolverEnv) ndeep m trace ty1 ty2 =
TryD (fun () -> SolveTypEqualsTypKeepAbbrevs csenv ndeep m trace ty1 ty2)
Expand All @@ -1937,7 +1948,7 @@ and ArgsMustSubsumeOrConvert
let g = csenv.g
let m = callerArg.Range
let calledArgTy = AdjustCalledArgType csenv.InfoReader isConstraint calledArg callerArg
SolveTypSubsumesTypWithReport csenv ndeep m trace calledArgTy callerArg.Type ++ (fun () ->
SolveTypSubsumesTypWithReport ContextInfo.NoContext csenv ndeep m trace calledArgTy callerArg.Type ++ (fun () ->

if calledArg.IsParamArray && isArray1DTy g calledArgTy && not (isArray1DTy g callerArg.Type)
then
Expand All @@ -1953,10 +1964,10 @@ and MustUnifyInsideUndo csenv ndeep trace ty1 ty2 =

and ArgsMustSubsumeOrConvertInsideUndo (csenv:ConstraintSolverEnv) ndeep trace isConstraint calledArg (CallerArg(callerArgTy,m,_,_) as callerArg) =
let calledArgTy = AdjustCalledArgType csenv.InfoReader isConstraint calledArg callerArg
SolveTypSubsumesTypWithReport csenv ndeep m (WithTrace trace) calledArgTy callerArgTy
SolveTypSubsumesTypWithReport ContextInfo.NoContext csenv ndeep m (WithTrace trace) calledArgTy callerArgTy

and TypesMustSubsumeOrConvertInsideUndo (csenv:ConstraintSolverEnv) ndeep trace m calledArgTy callerArgTy =
SolveTypSubsumesTypWithReport csenv ndeep m trace calledArgTy callerArgTy
SolveTypSubsumesTypWithReport ContextInfo.NoContext csenv ndeep m trace calledArgTy callerArgTy

and ArgsEquivInsideUndo (csenv:ConstraintSolverEnv) _trace isConstraint calledArg (CallerArg(callerArgTy,m,_,_) as callerArg) =
let calledArgTy = AdjustCalledArgType csenv.InfoReader isConstraint calledArg callerArg
Expand Down Expand Up @@ -2435,10 +2446,8 @@ let AddCxTypeMustSubsumeTypeMatchingOnlyUndoIfFailed denv css m ty1 ty2 =
let csenv = { csenv with MatchingOnly = true }
UndoIfFailed (fun trace -> SolveTypSubsumesTypKeepAbbrevs csenv 0 m (WithTrace(trace)) ty1 ty2)



let AddCxTypeMustSubsumeType denv css m trace ty1 ty2 =
SolveTypSubsumesTypWithReport (MakeConstraintSolverEnv css m denv) 0 m trace ty1 ty2
let AddCxTypeMustSubsumeType contextInfo denv css m trace ty1 ty2 =
SolveTypSubsumesTypWithReport contextInfo (MakeConstraintSolverEnv css m denv) 0 m trace ty1 ty2
|> RaiseOperationResult

let AddCxMethodConstraint denv css m trace traitInfo =
Expand Down
8 changes: 6 additions & 2 deletions src/fsharp/ConstraintSolver.fsi
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ type ContextInfo =
| OmittedElseBranch
/// The type equation comes from an else branch that might have different type than the corresponding if branch.
| ElseBranchWithDifferentType
/// The type equation comes from a runtime type test.
| RuntimeTypeTest
/// The type equation comes from an downcast where a upcast could be used.
| DowncastUsedInsteadOfUpcast

exception ConstraintSolverTupleDiffLengths of DisplayEnv * TType list * TType list * range * range
exception ConstraintSolverInfiniteTypes of DisplayEnv * TType * TType * range * range
Expand All @@ -66,7 +70,7 @@ exception ConstraintSolverError of string * range * rang
exception ConstraintSolverRelatedInformation of string option * range * exn
exception ErrorFromApplyingDefault of TcGlobals * DisplayEnv * Typar * TType * exn * range
exception ErrorFromAddingTypeEquation of TcGlobals * DisplayEnv * TType * TType * exn * ContextInfo * range
exception ErrorsFromAddingSubsumptionConstraint of TcGlobals * DisplayEnv * TType * TType * exn * range
exception ErrorsFromAddingSubsumptionConstraint of TcGlobals * DisplayEnv * TType * TType * exn * ContextInfo * range
exception ErrorFromAddingConstraint of DisplayEnv * exn * range
exception UnresolvedConversionOperator of DisplayEnv * TType * TType * range
exception PossibleOverload of DisplayEnv * string * exn * range
Expand Down Expand Up @@ -106,7 +110,7 @@ val AddConstraint : ConstraintSolverEnv -> int -> Ra
val AddCxTypeEqualsType : ContextInfo -> DisplayEnv -> ConstraintSolverState -> range -> TType -> TType -> unit
val AddCxTypeEqualsTypeUndoIfFailed : DisplayEnv -> ConstraintSolverState -> range -> TType -> TType -> bool
val AddCxTypeEqualsTypeMatchingOnlyUndoIfFailed : DisplayEnv -> ConstraintSolverState -> range -> TType -> TType -> bool
val AddCxTypeMustSubsumeType : DisplayEnv -> ConstraintSolverState -> range -> OptionalTrace -> TType -> TType -> unit
val AddCxTypeMustSubsumeType : ContextInfo -> DisplayEnv -> ConstraintSolverState -> range -> OptionalTrace -> TType -> TType -> unit
val AddCxTypeMustSubsumeTypeUndoIfFailed : DisplayEnv -> ConstraintSolverState -> range -> TType -> TType -> bool
val AddCxTypeMustSubsumeTypeMatchingOnlyUndoIfFailed : DisplayEnv -> ConstraintSolverState -> range -> TType -> TType -> bool
val AddCxMethodConstraint : DisplayEnv -> ConstraintSolverState -> range -> OptionalTrace -> TraitConstraintInfo -> unit
Expand Down
1 change: 1 addition & 0 deletions src/fsharp/FSComp.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1293,3 +1293,4 @@ estApplyStaticArgumentsForMethodNotImplemented,"A type provider implemented GetS
3195,optsResponseFileNameInvalid,"Response file name '%s' is empty, contains invalid characters, has a drive specification without an absolute path, or is too long"
3196,fsharpCoreNotFoundToBeCopied,"Cannot find FSharp.Core.dll in compiler's directory"
3197,etMissingStaticArgumentsToMethod,"This provided method requires static parameters"
3198,considerUpcast,"The conversion from %s to %s is a compile-time safe upcast, not a downcast. Consider using the :> (upcast) operator instead of the :?> (downcast) operator."
24 changes: 12 additions & 12 deletions src/fsharp/TypeChecker.fs
Original file line number Diff line number Diff line change
Expand Up @@ -2814,7 +2814,7 @@ let MakeApplicableExprWithFlex cenv (env: TcEnv) expr =
then actualType
else
let flexibleType = NewInferenceType ()
AddCxTypeMustSubsumeType env.DisplayEnv cenv.css m NoTrace actualType flexibleType;
AddCxTypeMustSubsumeType ContextInfo.NoContext env.DisplayEnv cenv.css m NoTrace actualType flexibleType;
flexibleType)

// Create a coercion to represent the expansion of the application
Expand All @@ -2836,7 +2836,7 @@ let TcRuntimeTypeTest isCast cenv denv m tgty srcTy =
if isSealedTy cenv.g tgty ||
isTyparTy cenv.g tgty ||
not (isInterfaceTy cenv.g srcTy) then
AddCxTypeMustSubsumeType denv cenv.css m NoTrace srcTy tgty
AddCxTypeMustSubsumeType ContextInfo.RuntimeTypeTest denv cenv.css m NoTrace srcTy tgty

if isErasedType cenv.g tgty then
if isCast then
Expand All @@ -2860,7 +2860,7 @@ let TcStaticUpcast cenv denv m tgty srcTy =
if typeEquiv cenv.g srcTy tgty then
warning(UpcastUnnecessary(m))

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



Expand Down Expand Up @@ -3265,7 +3265,7 @@ let mkSeqCollect cenv env m enumElemTy genTy lam enumExpr =
mkCallSeqCollect cenv.g m enumElemTy genResultTy lam enumExpr

let mkSeqUsing cenv (env: TcEnv) m resourceTy genTy resourceExpr lam =
AddCxTypeMustSubsumeType env.DisplayEnv cenv.css m NoTrace cenv.g.system_IDisposable_typ resourceTy
AddCxTypeMustSubsumeType ContextInfo.NoContext env.DisplayEnv cenv.css m NoTrace cenv.g.system_IDisposable_typ resourceTy
let genResultTy = NewInferenceType ()
UnifyTypes cenv env m genTy (mkSeqTy cenv.g genResultTy)
mkCallSeqUsing cenv.g m resourceTy genResultTy resourceExpr lam
Expand Down Expand Up @@ -3889,7 +3889,7 @@ let rec TcTyparConstraint ridx cenv newOk checkCxs occ (env: TcEnv) tpenv c =
let tp',tpenv = TcTypar cenv env newOk tpenv tp
if (newOk = NoNewTypars) && isSealedTy cenv.g ty' then
errorR(Error(FSComp.SR.tcInvalidConstraintTypeSealed(),m))
AddCxTypeMustSubsumeType env.DisplayEnv cenv.css m NoTrace ty' (mkTyparTy tp')
AddCxTypeMustSubsumeType ContextInfo.NoContext env.DisplayEnv cenv.css m NoTrace ty' (mkTyparTy tp')
tpenv

| WhereTyparSupportsNull(tp,m) -> checkSimpleConstraint tp m AddCxTypeMustSupportNull
Expand Down Expand Up @@ -4267,7 +4267,7 @@ and TcTypeOrMeasure optKind cenv newOk checkCxs occ env (tpenv:SyntacticUnscoped
| SynType.HashConstraint(ty,m) ->
let tp = TcAnonTypeOrMeasure (Some TyparKind.Type) cenv TyparRigidity.WarnIfNotRigid TyparDynamicReq.Yes newOk m
let ty',tpenv = TcTypeAndRecover cenv newOk checkCxs occ env tpenv ty
AddCxTypeMustSubsumeType env.DisplayEnv cenv.css m NoTrace ty' (mkTyparTy tp)
AddCxTypeMustSubsumeType ContextInfo.NoContext env.DisplayEnv cenv.css m NoTrace ty' (mkTyparTy tp)
tp.AsType, tpenv

| SynType.StaticConstant (c, m) ->
Expand Down Expand Up @@ -5125,7 +5125,7 @@ and TcExprOfUnknownType cenv env tpenv expr =
and TcExprFlex cenv flex ty (env: TcEnv) tpenv (e: SynExpr) =
if flex then
let argty = NewInferenceType ()
AddCxTypeMustSubsumeType env.DisplayEnv cenv.css e.Range NoTrace ty argty
AddCxTypeMustSubsumeType ContextInfo.NoContext env.DisplayEnv cenv.css e.Range NoTrace ty argty
let e',tpenv = TcExpr cenv argty env tpenv e
let e' = mkCoerceIfNeeded cenv.g ty argty e'
e',tpenv
Expand Down Expand Up @@ -5499,7 +5499,7 @@ and TcExprUndelayed cenv overallTy env tpenv (expr: SynExpr) =
UnifyTypes cenv env m overallTy genCollTy
let exprty = NewInferenceType ()
let genEnumTy = mkSeqTy cenv.g genCollElemTy
AddCxTypeMustSubsumeType env.DisplayEnv cenv.css m NoTrace genEnumTy exprty
AddCxTypeMustSubsumeType ContextInfo.NoContext env.DisplayEnv cenv.css m NoTrace genEnumTy exprty
let expr,tpenv = TcExpr cenv exprty env tpenv comp
let expr = mkCoerceIfNeeded cenv.g genEnumTy (tyOfExpr cenv.g expr) expr
(if isArray then mkCallSeqToArray else mkCallSeqToList) cenv.g m genCollElemTy
Expand Down Expand Up @@ -7783,7 +7783,7 @@ and TcSequenceExpression cenv env tpenv comp overallTy m =

if not isYield then errorR(Error(FSComp.SR.tcUseYieldBangForMultipleResults(),m))

AddCxTypeMustSubsumeType env.DisplayEnv cenv.css m NoTrace genOuterTy genExprTy
AddCxTypeMustSubsumeType ContextInfo.NoContext env.DisplayEnv cenv.css m NoTrace genOuterTy genExprTy
Some(mkCoerceExpr(resultExpr,genOuterTy,m,genExprTy), tpenv)

| SynExpr.YieldOrReturn((isYield,_),yieldExpr,m) ->
Expand Down Expand Up @@ -8549,7 +8549,7 @@ and TcLookupThen cenv overallTy env tpenv mObjExpr objExpr objExprTy longId dela
RecdFieldInstanceChecks cenv.g cenv.amap ad mItem rfinfo
let tgty = rfinfo.EnclosingType
let valu = isStructTy cenv.g tgty
AddCxTypeMustSubsumeType env.DisplayEnv cenv.css mItem NoTrace tgty objExprTy
AddCxTypeMustSubsumeType ContextInfo.NoContext env.DisplayEnv cenv.css mItem NoTrace tgty objExprTy
let objExpr = if valu then objExpr else mkCoerceExpr(objExpr,tgty,mExprAndItem,objExprTy)
let fieldTy = rfinfo.FieldType
match delayed with
Expand Down Expand Up @@ -9922,7 +9922,7 @@ and TcAttribute cenv (env: TcEnv) attrTgt (synAttr: SynAttribute) =
let propNameItem = Item.SetterArg(id, setterItem)
CallNameResolutionSink cenv.tcSink (id.idRange,env.NameEnv,propNameItem,propNameItem,ItemOccurence.Use,env.DisplayEnv,ad)

AddCxTypeMustSubsumeType env.DisplayEnv cenv.css m NoTrace argty argtyv
AddCxTypeMustSubsumeType ContextInfo.NoContext env.DisplayEnv cenv.css m NoTrace argty argtyv

AttribNamedArg(nm,argty,isProp,mkAttribExpr expr))

Expand Down Expand Up @@ -10065,7 +10065,7 @@ and TcLetBinding cenv isUse env containerInfo declKind tpenv (binds,bindsm,scope
let mkCleanup (tm,tmty) =
if isUse then
(allValsDefinedByPattern,(tm,tmty)) ||> FlatList.foldBack (fun v (tm,tmty) ->
AddCxTypeMustSubsumeType denv cenv.css v.Range NoTrace cenv.g.system_IDisposable_typ v.Type
AddCxTypeMustSubsumeType ContextInfo.NoContext denv cenv.css v.Range NoTrace cenv.g.system_IDisposable_typ v.Type
let cleanupE = BuildDisposableCleanup cenv env m v
mkTryFinally cenv.g (tm,cleanupE,m,tmty,SequencePointInBodyOfTry,NoSequencePointAtFinally),tmty)
else
Expand Down
4 changes: 2 additions & 2 deletions tests/fsharp/typecheck/sigs/neg61.bsl
Original file line number Diff line number Diff line change
Expand Up @@ -88,12 +88,12 @@ neg61.fs(174,22,174,23): typecheck error FS0041: Possible overload: 'member Linq
int
is not compatible with type
System.Linq.IQueryable<'a>
The type 'int' is not compatible with the type 'System.Linq.IQueryable<'a>'.
.
neg61.fs(174,22,174,23): typecheck error FS0041: Possible overload: 'member Linq.QueryBuilder.Source : source:System.Collections.Generic.IEnumerable<'T> -> Linq.QuerySource<'T,System.Collections.IEnumerable>'. Type constraint mismatch. The type
int
is not compatible with type
System.Collections.Generic.IEnumerable<'a>
The type 'int' is not compatible with the type 'System.Collections.Generic.IEnumerable<'a>'.
.

neg61.fs(180,19,180,31): typecheck error FS3153: Arguments to query operators may require parentheses, e.g. 'where (x > y)' or 'groupBy (x.Length / 10)'

Expand Down
Loading

0 comments on commit e07d985

Please sign in to comment.