diff --git a/docs/release-notes/.FSharp.Compiler.Service/9.0.200.md b/docs/release-notes/.FSharp.Compiler.Service/9.0.200.md index b9046b9f446..8edf6f814d1 100644 --- a/docs/release-notes/.FSharp.Compiler.Service/9.0.200.md +++ b/docs/release-notes/.FSharp.Compiler.Service/9.0.200.md @@ -21,6 +21,7 @@ * Completion: fix qualified completion in sequence expressions [PR #18111](https://github.com/dotnet/fsharp/pull/18111) * Symbols: try to use ValReprInfoForDisplay in Mfv.CurriedParameterGroups ([PR #18124](https://github.com/dotnet/fsharp/pull/18124)) * Shim/file system: fix leaks of the shim [PR #18144](https://github.com/dotnet/fsharp/pull/18144) +* Fix for `Obsolete` attribute warning/error not taken into account when used with a unit of measure [PR #18182](https://github.com/dotnet/fsharp/pull/18182) ### Added diff --git a/src/Compiler/Checking/AttributeChecking.fs b/src/Compiler/Checking/AttributeChecking.fs index 8ef659ac20e..563af942829 100644 --- a/src/Compiler/Checking/AttributeChecking.fs +++ b/src/Compiler/Checking/AttributeChecking.fs @@ -417,7 +417,27 @@ let CheckEntityAttributes g (tcref: TyconRef) m = CheckFSharpAttributes g tcref.Attribs m let CheckILEventAttributes g (tcref: TyconRef) cattrs m = - CheckILAttributes g (isByrefLikeTyconRef g m tcref) cattrs m + CheckILAttributes g (isByrefLikeTyconRef g m tcref) cattrs m + +let CheckUnitOfMeasureAttributes g (measure: Measure) = + let checkAttribs tm m = + let attribs = + ListMeasureConOccsWithNonZeroExponents g true tm + |> List.map fst + |> List.map(_.Attribs) + |> List.concat + + CheckFSharpAttributes g attribs m |> CommitOperationResult + + match measure with + | Measure.Const(range = m) -> checkAttribs measure m + | Measure.Inv ms -> checkAttribs measure ms.Range + | Measure.One(m) -> checkAttribs measure m + | Measure.RationalPower(measure = ms1) -> checkAttribs measure ms1.Range + | Measure.Prod(measure1= ms1; measure2= ms2) -> + checkAttribs ms1 ms1.Range + checkAttribs ms2 ms2.Range + | Measure.Var(typar) -> checkAttribs measure typar.Range /// Check the attributes associated with a method, returning warnings and errors as data. let CheckMethInfoAttributes g m tyargsOpt (minfo: MethInfo) = diff --git a/src/Compiler/Checking/AttributeChecking.fsi b/src/Compiler/Checking/AttributeChecking.fsi index b4a608ef1d1..663198f9247 100644 --- a/src/Compiler/Checking/AttributeChecking.fsi +++ b/src/Compiler/Checking/AttributeChecking.fsi @@ -89,6 +89,8 @@ val CheckEntityAttributes: g: TcGlobals -> tcref: TyconRef -> m: range -> Operat val CheckUnionCaseAttributes: g: TcGlobals -> x: UnionCaseRef -> m: range -> OperationResult +val CheckUnitOfMeasureAttributes: g: TcGlobals -> measure: Measure -> unit + val CheckRecdFieldAttributes: g: TcGlobals -> x: RecdFieldRef -> m: range -> OperationResult val CheckValAttributes: g: TcGlobals -> x: ValRef -> m: range -> OperationResult diff --git a/src/Compiler/Checking/CheckDeclarations.fs b/src/Compiler/Checking/CheckDeclarations.fs index bec5c9d9966..23c547b36b8 100644 --- a/src/Compiler/Checking/CheckDeclarations.fs +++ b/src/Compiler/Checking/CheckDeclarations.fs @@ -3241,6 +3241,13 @@ module EstablishTypeDefinitionCores = warning(Error(FSComp.SR.chkAttributeAliased(attrib.TypeRef.FullName), tycon.Id.idRange)) | _ -> () + // Check for attributes in unit-of-measure declarations + // [] type x = 1 + // ^ + match stripTyEqns g ty with + | TType_measure tm -> CheckUnitOfMeasureAttributes g tm + | _ -> () + checkAttributeAliased ty tycon g.attrib_AutoOpenAttribute checkAttributeAliased ty tycon g.attrib_StructAttribute @@ -3807,11 +3814,11 @@ module EstablishTypeDefinitionCores = and accInMeasure measureTy acc = match stripUnitEqns measureTy with - | Measure.Const tcref when ListSet.contains (===) tcref.Deref tycons -> + | Measure.Const(tyconRef= tcref) when ListSet.contains (===) tcref.Deref tycons -> (tycon, tcref.Deref) :: acc - | Measure.Const tcref when tcref.IsTypeAbbrev -> + | Measure.Const(tyconRef= tcref) when tcref.IsTypeAbbrev -> accInMeasure (reduceTyconRefAbbrevMeasureable tcref) acc - | Measure.Prod (ms1, ms2) -> accInMeasure ms1 (accInMeasure ms2 acc) + | Measure.Prod(measure1= ms1; measure2= ms2) -> accInMeasure ms1 (accInMeasure ms2 acc) | Measure.Inv invTy -> accInMeasure invTy acc | _ -> acc diff --git a/src/Compiler/Checking/CheckPatterns.fs b/src/Compiler/Checking/CheckPatterns.fs index 487c66b0c8c..5d447da6021 100644 --- a/src/Compiler/Checking/CheckPatterns.fs +++ b/src/Compiler/Checking/CheckPatterns.fs @@ -803,7 +803,7 @@ and TcPatLongIdentLiteral warnOnUpper (cenv: cenv) env vFlags patEnv ty (mLongId match vref.LiteralValue with | None -> error (Error(FSComp.SR.tcNonLiteralCannotBeUsedInPattern(), m)) | Some lit -> - let _, _, _, vexpty, _, _ = TcVal true cenv env tpenv vref None None mLongId + let _, _, _, vexpty, _, _ = TcVal cenv env tpenv vref None None mLongId CheckValAccessible mLongId env.AccessRights vref CheckFSharpAttributes g vref.Attribs mLongId |> CommitOperationResult CheckNoArgsForLiteral args m diff --git a/src/Compiler/Checking/ConstraintSolver.fs b/src/Compiler/Checking/ConstraintSolver.fs index 8be7ec551ea..82141080743 100644 --- a/src/Compiler/Checking/ConstraintSolver.fs +++ b/src/Compiler/Checking/ConstraintSolver.fs @@ -42,6 +42,7 @@ module internal FSharp.Compiler.ConstraintSolver +open FSharp.Compiler.Text.Range open Internal.Utilities.Collections open Internal.Utilities.Library open Internal.Utilities.Library.Extras @@ -734,7 +735,7 @@ let SubstMeasureWarnIfRigid (csenv: ConstraintSolverEnv) trace (v: Typar) ms = // Propagate static requirements from 'tp' to 'ty' do! SolveTypStaticReq csenv trace v.StaticReq (TType_measure ms) SubstMeasure v ms - if v.Rigidity = TyparRigidity.Anon && measureEquiv csenv.g ms Measure.One then + if v.Rigidity = TyparRigidity.Anon && measureEquiv csenv.g ms (Measure.One ms.Range) then return! WarnD(Error(FSComp.SR.csCodeLessGeneric(), v.Range)) else () @@ -760,17 +761,17 @@ let UnifyMeasureWithOne (csenv: ConstraintSolverEnv) trace ms = match FindPreferredTypar nonRigidVars with | (v, e) :: vs -> let unexpandedCons = ListMeasureConOccsWithNonZeroExponents csenv.g false ms - let newms = ProdMeasures (List.map (fun (c, e') -> Measure.RationalPower (Measure.Const c, NegRational (DivRational e' e))) unexpandedCons + let newms = ProdMeasures (List.map (fun (c, e') -> Measure.RationalPower(Measure.Const(c, ms.Range), NegRational (DivRational e' e))) unexpandedCons @ List.map (fun (v, e') -> Measure.RationalPower (Measure.Var v, NegRational (DivRational e' e))) (vs @ rigidVars)) SubstMeasureWarnIfRigid csenv trace v newms // Otherwise we require ms to be 1 - | [] -> if measureEquiv csenv.g ms Measure.One then CompleteD else localAbortD + | [] -> if measureEquiv csenv.g ms (Measure.One ms.Range) then CompleteD else localAbortD /// Imperatively unify unit-of-measure expression ms1 against ms2 let UnifyMeasures (csenv: ConstraintSolverEnv) trace ms1 ms2 = - UnifyMeasureWithOne csenv trace (Measure.Prod(ms1, Measure.Inv ms2)) + UnifyMeasureWithOne csenv trace (Measure.Prod(ms1, Measure.Inv ms2, (unionRanges ms1.Range ms2.Range))) /// Simplify a unit-of-measure expression ms that forms part of a type scheme. /// We make substitutions for vars, which are the (remaining) bound variables @@ -791,7 +792,7 @@ let SimplifyMeasure g vars ms = let newms = ProdMeasures [ for (c, e') in nonZeroCon do - Measure.RationalPower (Measure.Const c, NegRational (DivRational e' e)) + Measure.RationalPower (Measure.Const(c, ms.Range), NegRational (DivRational e' e)) for (v', e') in nonZeroVar do if typarEq v v' then newvarExpr @@ -1329,13 +1330,13 @@ and SolveTypeEqualsType (csenv: ConstraintSolverEnv) ndeep m2 (trace: OptionalTr // Catch float<_>=float<1>, float32<_>=float32<1> and decimal<_>=decimal<1> | (_, TType_app (tc2, [ms2], _)) when (tc2.IsMeasureableReprTycon && typeEquiv csenv.g sty1 (reduceTyconRefMeasureableOrProvided csenv.g tc2 [ms2])) -> trackErrors { - do! SolveTypeEqualsType csenv ndeep m2 trace None (TType_measure Measure.One) ms2 + do! SolveTypeEqualsType csenv ndeep m2 trace None (TType_measure(Measure.One m2)) ms2 do! SolveNullnessEquiv csenv m2 trace ty1 ty2 (nullnessOfTy g sty1) (nullnessOfTy g sty2) } | (TType_app (tc1, [ms1], _), _) when (tc1.IsMeasureableReprTycon && typeEquiv csenv.g sty2 (reduceTyconRefMeasureableOrProvided csenv.g tc1 [ms1])) -> trackErrors { - do! SolveTypeEqualsType csenv ndeep m2 trace None ms1 (TType_measure Measure.One) + do! SolveTypeEqualsType csenv ndeep m2 trace None ms1 (TType_measure(Measure.One m2)) do! SolveNullnessEquiv csenv m2 trace ty1 ty2 (nullnessOfTy g sty1) (nullnessOfTy g sty2) } @@ -1518,13 +1519,13 @@ and SolveTypeSubsumesType (csenv: ConstraintSolverEnv) ndeep m2 (trace: Optional // Enforce the identities float=float<1>, float32=float32<1> and decimal=decimal<1> | _, TType_app (tc2, [ms2], _) when tc2.IsMeasureableReprTycon && typeEquiv csenv.g sty1 (reduceTyconRefMeasureableOrProvided csenv.g tc2 [ms2]) -> trackErrors { - do! SolveTypeEqualsTypeKeepAbbrevsWithCxsln csenv ndeep m2 trace cxsln ms2 (TType_measure Measure.One) + do! SolveTypeEqualsTypeKeepAbbrevsWithCxsln csenv ndeep m2 trace cxsln ms2 (TType_measure(Measure.One m2)) do! SolveNullnessSubsumesNullness csenv m2 trace ty1 ty2 (nullnessOfTy g sty1) (nullnessOfTy g sty2) } | TType_app (tc1, [ms1], _), _ when tc1.IsMeasureableReprTycon && typeEquiv csenv.g sty2 (reduceTyconRefMeasureableOrProvided csenv.g tc1 [ms1]) -> trackErrors { - do! SolveTypeEqualsTypeKeepAbbrevsWithCxsln csenv ndeep m2 trace cxsln ms1 (TType_measure Measure.One) + do! SolveTypeEqualsTypeKeepAbbrevsWithCxsln csenv ndeep m2 trace cxsln ms1 (TType_measure(Measure.One m2)) do! SolveNullnessSubsumesNullness csenv m2 trace ty1 ty2 (nullnessOfTy g sty1) (nullnessOfTy g sty2) } @@ -1620,7 +1621,7 @@ and DepthCheck ndeep m = and SolveDimensionlessNumericType (csenv: ConstraintSolverEnv) ndeep m2 trace ty = match getMeasureOfType csenv.g ty with | Some (tcref, _) -> - SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace ty (mkWoNullAppTy tcref [TType_measure Measure.One]) + SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace ty (mkWoNullAppTy tcref [TType_measure(Measure.One m2)]) | None -> CompleteD @@ -1727,7 +1728,7 @@ and SolveMemberConstraint (csenv: ConstraintSolverEnv) ignoreUnresolvedOverload | Some (tcref, ms1) -> let ms2 = freshMeasure () do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace argTy2 (mkWoNullAppTy tcref [TType_measure ms2]) - do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace retTy (mkWoNullAppTy tcref [TType_measure (Measure.Prod(ms1, if nm = "op_Multiply" then ms2 else Measure.Inv ms2))]) + do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace retTy (mkWoNullAppTy tcref [TType_measure (Measure.Prod(ms1, (if nm = "op_Multiply" then ms2 else Measure.Inv ms2), unionRanges ms1.Range ms2.Range))]) return TTraitBuiltIn | _ -> @@ -1736,7 +1737,7 @@ and SolveMemberConstraint (csenv: ConstraintSolverEnv) ignoreUnresolvedOverload | Some (tcref, ms2) -> let ms1 = freshMeasure () do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace argTy1 (mkWoNullAppTy tcref [TType_measure ms1]) - do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace retTy (mkWoNullAppTy tcref [TType_measure (Measure.Prod(ms1, if nm = "op_Multiply" then ms2 else Measure.Inv ms2))]) + do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace retTy (mkWoNullAppTy tcref [TType_measure (Measure.Prod(ms1, (if nm = "op_Multiply" then ms2 else Measure.Inv ms2), unionRanges ms1.Range ms2.Range))]) return TTraitBuiltIn | _ -> @@ -1870,7 +1871,7 @@ and SolveMemberConstraint (csenv: ConstraintSolverEnv) ignoreUnresolvedOverload match getMeasureOfType g argTy1 with | Some (tcref, _) -> let ms1 = freshMeasure () - do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace argTy1 (mkWoNullAppTy tcref [TType_measure (Measure.Prod (ms1, ms1))]) + do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace argTy1 (mkWoNullAppTy tcref [TType_measure (Measure.Prod (ms1, ms1, ms1.Range))]) do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace retTy (mkWoNullAppTy tcref [TType_measure ms1]) return TTraitBuiltIn | None -> @@ -1923,7 +1924,7 @@ and SolveMemberConstraint (csenv: ConstraintSolverEnv) ignoreUnresolvedOverload do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace argTy2 argTy1 match getMeasureOfType g argTy1 with | None -> do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace retTy argTy1 - | Some (tcref, _) -> do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace retTy (mkWoNullAppTy tcref [TType_measure Measure.One]) + | Some (tcref, ms) -> do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace retTy (mkWoNullAppTy tcref [TType_measure(Measure.One ms.Range)]) return TTraitBuiltIn | _ -> diff --git a/src/Compiler/Checking/Expressions/CheckExpressions.fs b/src/Compiler/Checking/Expressions/CheckExpressions.fs index 16dc49c1a61..9987f02759c 100644 --- a/src/Compiler/Checking/Expressions/CheckExpressions.fs +++ b/src/Compiler/Checking/Expressions/CheckExpressions.fs @@ -798,27 +798,28 @@ let TcConst (cenv: cenv) (overallTy: TType) m env synConst = let g = cenv.g let rec tcMeasure ms = match ms with - | SynMeasure.One _ -> Measure.One + | SynMeasure.One m -> Measure.One m | SynMeasure.Named(tc, m) -> let ad = env.eAccessRights let _, tcref, _ = ForceRaise(ResolveTypeLongIdent cenv.tcSink cenv.nameResolver ItemOccurrence.Use OpenQualified env.eNameResEnv ad tc TypeNameResolutionStaticArgsInfo.DefiniteEmpty PermitDirectReferenceToGeneratedType.No) match tcref.TypeOrMeasureKind with | TyparKind.Type -> error(Error(FSComp.SR.tcExpectedUnitOfMeasureNotType(), m)) - | TyparKind.Measure -> Measure.Const tcref + | TyparKind.Measure -> Measure.Const(tcref, ms.Range) | SynMeasure.Power(measure = ms; power = exponent) -> Measure.RationalPower (tcMeasure ms, TcSynRationalConst exponent) - | SynMeasure.Product(measure1 = ms1; measure2 = ms2) -> Measure.Prod(tcMeasure ms1, tcMeasure ms2) + | SynMeasure.Product(measure1 = ms1; measure2 = ms2; range= m) -> + Measure.Prod(tcMeasure ms1, tcMeasure ms2, m) | SynMeasure.Divide(ms1, _, (SynMeasure.Seq (_ :: _ :: _, _) as ms2), m) -> warning(Error(FSComp.SR.tcImplicitMeasureFollowingSlash(), m)) let factor1 = ms1 |> Option.defaultValue (SynMeasure.One Range.Zero) - Measure.Prod(tcMeasure factor1, Measure.Inv (tcMeasure ms2)) - | SynMeasure.Divide(measure1 = ms1; measure2 = ms2) -> + Measure.Prod(tcMeasure factor1, Measure.Inv (tcMeasure ms2), ms.Range) + | SynMeasure.Divide(measure1 = ms1; measure2 = ms2; range= m) -> let factor1 = ms1 |> Option.defaultValue (SynMeasure.One Range.Zero) - Measure.Prod(tcMeasure factor1, Measure.Inv (tcMeasure ms2)) + Measure.Prod(tcMeasure factor1, Measure.Inv (tcMeasure ms2), ms.Range) | SynMeasure.Seq(mss, _) -> ProdMeasures (List.map tcMeasure mss) | SynMeasure.Anon _ -> error(Error(FSComp.SR.tcUnexpectedMeasureAnon(), m)) - | SynMeasure.Var(_, m) -> error(Error(FSComp.SR.tcNonZeroConstantCannotHaveGenericUnit(), m)) - | SynMeasure.Paren(measure, _) -> tcMeasure measure + | SynMeasure.Var(range= m) -> error(Error(FSComp.SR.tcNonZeroConstantCannotHaveGenericUnit(), m)) + | SynMeasure.Paren(measure= measure) -> tcMeasure measure let unif expectedTy = UnifyTypes cenv env m overallTy expectedTy @@ -829,7 +830,7 @@ let TcConst (cenv: cenv) (overallTy: TType) m env synConst = (mkWoNullAppTy tcr [TType_measure (Measure.Var (NewAnonTypar (TyparKind.Measure, m, TyparRigidity.Anon, (if iszero then TyparStaticReq.None else TyparStaticReq.HeadType), TyparDynamicReq.No)))]) | SynConst.Measure(synMeasure = ms) -> mkWoNullAppTy tcr [TType_measure (tcMeasure ms)] - | _ -> mkWoNullAppTy tcr [TType_measure Measure.One] + | _ -> mkWoNullAppTy tcr [TType_measure(Measure.One m)] unif measureTy let expandedMeasurablesEnabled = @@ -2739,7 +2740,7 @@ let TcValEarlyGeneralizationConsistencyCheck (cenv: cenv) (env: TcEnv) (v: Val, /// instantiationInfoOpt is is also set when building the final call for a reference to an /// F# object model member, in which case the instantiationInfoOpt is the type instantiation /// inferred by member overload resolution. -let TcVal checkAttributes (cenv: cenv) env (tpenv: UnscopedTyparEnv) (vref: ValRef) instantiationInfoOpt optAfterResolution m = +let TcVal (cenv: cenv) env (tpenv: UnscopedTyparEnv) (vref: ValRef) instantiationInfoOpt optAfterResolution m = let g = cenv.g let tpsorig, _, _, _, tinst, _ as res = @@ -2749,8 +2750,7 @@ let TcVal checkAttributes (cenv: cenv) env (tpenv: UnscopedTyparEnv) (vref: ValR CheckValAccessible m env.eAccessRights vref - if checkAttributes then - CheckValAttributes g vref m |> CommitOperationResult + CheckValAttributes g vref m |> CommitOperationResult let vTy = vref.Type @@ -3046,7 +3046,7 @@ let BuildPossiblyConditionalMethodCall (cenv: cenv) env isMutable m isProp minfo | _ -> #endif let tcVal valref valUse ttypes m = - let _, exprForVal, _, tau, _, _ = TcVal true cenv env emptyUnscopedTyparEnv valref (Some (valUse, (fun x _ -> ttypes, x))) None m + let _, exprForVal, _, tau, _, _ = TcVal cenv env emptyUnscopedTyparEnv valref (Some (valUse, (fun x _ -> ttypes, x))) None m exprForVal, tau BuildMethodCall tcVal g cenv.amap isMutable m isProp minfo valUseFlags minst objArgs args staticTyOpt @@ -4550,7 +4550,7 @@ and TcLongIdentType kindOpt (cenv: cenv) newOk checkConstraints occ iwsam env tp error(Error(FSComp.SR.tcExpectedUnitOfMeasureNotType(), m)) TType_measure (NewErrorMeasure ()), tpenv | _, TyparKind.Measure -> - TType_measure (Measure.Const tcref), tpenv + TType_measure (Measure.Const(tcref, m)), tpenv | _, TyparKind.Type -> TcTypeApp cenv newOk checkConstraints occ env tpenv m tcref tinstEnclosing [] inst @@ -4585,7 +4585,7 @@ and TcLongIdentAppType kindOpt (cenv: cenv) newOk checkConstraints occ iwsam env match args, postfix with | [arg], true -> let ms, tpenv = TcMeasure cenv newOk checkConstraints occ env tpenv arg m - TType_measure (Measure.Prod(Measure.Const tcref, ms)), tpenv + TType_measure (Measure.Prod(Measure.Const(tcref, tcref.Range), ms, ms.Range)), tpenv | _, _ -> errorR(Error(FSComp.SR.tcUnitsOfMeasureInvalidInTypeConstructor(), m)) @@ -4715,7 +4715,7 @@ and TcTypeStaticConstant kindOpt tpenv c m = errorR(Error(FSComp.SR.parsInvalidLiteralInType(), m)) NewErrorType (), tpenv | SynConst.Int32 1, _ -> - TType_measure Measure.One, tpenv + TType_measure (Measure.One m), tpenv | _ -> errorR(Error(FSComp.SR.parsInvalidLiteralInType(), m)) NewErrorType (), tpenv @@ -4736,7 +4736,7 @@ and TcTypeMeasureApp kindOpt (cenv: cenv) newOk checkConstraints occ env tpenv a | (None | Some TyparKind.Measure), [arg2], true -> let ms1, tpenv = TcMeasure cenv newOk checkConstraints occ env tpenv arg1 m1 let ms2, tpenv = TcMeasure cenv newOk checkConstraints occ env tpenv arg2 m - TType_measure (Measure.Prod(ms1, ms2)), tpenv + TType_measure (Measure.Prod(ms1, ms2, unionRanges ms1.Range ms2.Range)), tpenv | _ -> errorR(Error(FSComp.SR.tcTypeParameterInvalidAsTypeConstructor(), m)) @@ -4810,12 +4810,13 @@ and TcMeasuresAsTuple (cenv: cenv) newOk checkConstraints occ env (tpenv: Unscop gather args tpenv ms1 | SynTupleTypeSegment.Star _ :: SynTupleTypeSegment.Type ty :: args -> let ms1, tpenv = TcMeasure cenv newOk checkConstraints occ env tpenv ty m - gather args tpenv (Measure.Prod(acc, ms1)) + gather args tpenv (Measure.Prod(acc, ms1, unionRanges acc.Range ms1.Range)) | SynTupleTypeSegment.Slash _ :: SynTupleTypeSegment.Type ty :: args -> let ms1, tpenv = TcMeasure cenv newOk checkConstraints occ env tpenv ty m - gather args tpenv (Measure.Prod(acc, Measure.Inv ms1)) + let ms2 = Measure.Inv ms1 + gather args tpenv (Measure.Prod(acc, ms2, unionRanges acc.Range ms2.Range)) | _ -> failwith "impossible" - gather args tpenv Measure.One + gather args tpenv (Measure.One m) and TcTypesOrMeasures optKinds (cenv: cenv) newOk checkConstraints occ env tpenv args m = match optKinds with @@ -4823,7 +4824,15 @@ and TcTypesOrMeasures optKinds (cenv: cenv) newOk checkConstraints occ env tpenv List.mapFold (TcTypeOrMeasure None cenv newOk checkConstraints occ WarnOnIWSAM.Yes env) tpenv args | Some kinds -> if List.length kinds = List.length args then - List.mapFold (fun tpenv (arg, kind) -> TcTypeOrMeasure (Some kind) cenv newOk checkConstraints occ WarnOnIWSAM.Yes env tpenv arg) tpenv (List.zip args kinds) + let ttypes, tpenv = List.mapFold (fun tpenv (arg, kind) -> TcTypeOrMeasure (Some kind) cenv newOk checkConstraints occ WarnOnIWSAM.Yes env tpenv arg) tpenv (List.zip args kinds) + + for ttype in ttypes do + match stripTyEqns cenv.g ttype with + | TType_measure tm -> CheckUnitOfMeasureAttributes cenv.g tm + | _ -> () + + ttypes, tpenv + elif isNil kinds then error(Error(FSComp.SR.tcUnexpectedTypeArguments(), m)) else error(Error(FSComp.SR.tcTypeParameterArityMismatch((List.length kinds), (List.length args)), m)) @@ -5077,7 +5086,7 @@ and TcTypeOrMeasureAndRecover kindOpt (cenv: cenv) newOk checkConstraints occ iw let recoveryTy = match kindOpt, newOk with - | Some TyparKind.Measure, NoNewTypars -> TType_measure Measure.One + | Some TyparKind.Measure, NoNewTypars -> TType_measure(Measure.One ty.Range) | Some TyparKind.Measure, _ -> TType_measure (NewErrorMeasure ()) | _, NoNewTypars -> g.obj_ty_ambivalent | _ -> NewErrorType () @@ -5163,7 +5172,7 @@ and TcPatLongIdentActivePatternCase warnOnUpper (cenv: cenv) (env: TcEnv) vFlags CallNameResolutionSink cenv.tcSink (mLongId, env.NameEnv, item, emptyTyparInst, ItemOccurrence.Pattern, env.eAccessRights) // TOTAL/PARTIAL ACTIVE PATTERNS - let _, vExpr, _, _, tinst, _ = TcVal true cenv env tpenv vref None None m + let _, vExpr, _, _, tinst, _ = TcVal cenv env tpenv vref None None m let vExpr = MakeApplicableExprWithFlex cenv env vExpr let vExprTy = vExpr.Type @@ -7673,6 +7682,14 @@ and TcConstExpr cenv (overallTy: OverallTy) env m tpenv c = TcNonPropagatingExprLeafThenConvert cenv overallTy env m (fun () -> let cTy = NewInferenceType g let c' = TcConst cenv cTy m env c + let rec checkAttributeInMeasure ty = + match stripTyEqns g ty with + | TType_app(typeInstantiation= ttypes) -> ttypes |> List.iter checkAttributeInMeasure + | TType_fun(rangeType= rangeType) -> checkAttributeInMeasure rangeType + | TType_measure tm -> CheckUnitOfMeasureAttributes g tm + | _ -> () + + checkAttributeInMeasure cTy Expr.Const (c', m, cTy), cTy, tpenv) //------------------------------------------------------------------------- @@ -9258,7 +9275,7 @@ and TcValueItemThen cenv overallTy env vref tpenv mItem afterResolution delayed error (Error(FSComp.SR.expressionHasNoName(), mExprAndTypeArgs)) | _ -> let checkTys tpenv kinds = TcTypesOrMeasures (Some kinds) cenv NewTyparsOK CheckCxs ItemOccurrence.UseInType env tpenv tys mItem - let _, vExpr, isSpecial, _, _, tpenv = TcVal true cenv env tpenv vref (Some (NormalValUse, checkTys)) (Some afterResolution) mItem + let _, vExpr, isSpecial, _, _, tpenv = TcVal cenv env tpenv vref (Some (NormalValUse, checkTys)) (Some afterResolution) mItem let vexpFlex = (if isSpecial then MakeApplicableExprNoFlex cenv vExpr else MakeApplicableExprWithFlex cenv env vExpr) // We need to eventually record the type resolution for an expression, but this is done @@ -9267,7 +9284,7 @@ and TcValueItemThen cenv overallTy env vref tpenv mItem afterResolution delayed // Value get | _ -> - let _, vExpr, isSpecial, _, _, tpenv = TcVal true cenv env tpenv vref None (Some afterResolution) mItem + let _, vExpr, isSpecial, _, _, tpenv = TcVal cenv env tpenv vref None (Some afterResolution) mItem let vExpr, tpenv = match vExpr with @@ -11155,7 +11172,7 @@ and TcNormalizedBinding declKind (cenv: cenv) env tpenv overallTy safeThisValOpt let supportEnforceAttributeTargets = (g.langVersion.SupportsFeature(LanguageFeature.EnforceAttributeTargets) && memberFlagsOpt.IsNone && not attrs.IsEmpty) - && not isVolatile // // VolatileFieldAttribute has a special treatment(specific error FS823) + && not isVolatile // VolatileFieldAttribute has a special treatment(specific error FS823) if supportEnforceAttributeTargets then TcAttributeTargetsOnLetBindings { cenv with tcSink = TcResultsSink.NoSink } env attrs overallPatTy overallExprTy (not declaredTypars.IsEmpty) isClassLetBinding diff --git a/src/Compiler/Checking/Expressions/CheckExpressions.fsi b/src/Compiler/Checking/Expressions/CheckExpressions.fsi index 0e4e17a8f83..ed18b07a58a 100644 --- a/src/Compiler/Checking/Expressions/CheckExpressions.fsi +++ b/src/Compiler/Checking/Expressions/CheckExpressions.fsi @@ -919,7 +919,6 @@ val TcPatLongIdentActivePatternCase: val ConvSynPatToSynExpr: synPat: SynPat -> SynExpr val TcVal: - checkAttributes: bool -> cenv: TcFileState -> env: TcEnv -> tpenv: UnscopedTyparEnv -> diff --git a/src/Compiler/Checking/TypeRelations.fs b/src/Compiler/Checking/TypeRelations.fs index 6c38b68d80a..d180bb778dd 100644 --- a/src/Compiler/Checking/TypeRelations.fs +++ b/src/Compiler/Checking/TypeRelations.fs @@ -176,7 +176,7 @@ let ChooseTyparSolutionAndRange (g: TcGlobals) amap (tp:Typar) = let initialTy = match tp.Kind with | TyparKind.Type -> g.obj_ty_noNulls - | TyparKind.Measure -> TType_measure Measure.One + | TyparKind.Measure -> TType_measure(Measure.One m) // Loop through the constraints computing the lub (((initialTy, false), m), tp.Constraints) ||> List.fold (fun ((maxTy, isRefined), _) tpc -> let join m x = @@ -226,8 +226,8 @@ let ChooseTyparSolutionAndRange (g: TcGlobals) amap (tp:Typar) = maxTy, m let ChooseTyparSolution g amap tp = - let ty, _m = ChooseTyparSolutionAndRange g amap tp - if tp.Rigidity = TyparRigidity.Anon && typeEquiv g ty (TType_measure Measure.One) then + let ty, m = ChooseTyparSolutionAndRange g amap tp + if tp.Rigidity = TyparRigidity.Anon && typeEquiv g ty (TType_measure(Measure.One m)) then warning(Error(FSComp.SR.csCodeLessGeneric(), tp.Range)) ty diff --git a/src/Compiler/Checking/import.fs b/src/Compiler/Checking/import.fs index a1deee1c8a1..c40fd73b234 100644 --- a/src/Compiler/Checking/import.fs +++ b/src/Compiler/Checking/import.fs @@ -6,6 +6,7 @@ module internal FSharp.Compiler.Import open System.Collections.Concurrent open System.Collections.Generic open System.Collections.Immutable +open FSharp.Compiler.Text.Range open Internal.Utilities.Library open Internal.Utilities.Library.Extras open Internal.Utilities.TypeHashing @@ -553,16 +554,19 @@ let rec ImportProvidedType (env: ImportMap) (m: range) (* (tinst: TypeInst) *) ( if tp.Kind = TyparKind.Measure then let rec conv ty = match ty with - | TType_app (tcref, [ty1;ty2], _) when tyconRefEq g tcref g.measureproduct_tcr -> Measure.Prod (conv ty1, conv ty2) + | TType_app (tcref, [ty1;ty2], _) when tyconRefEq g tcref g.measureproduct_tcr -> + let ms1: Measure = conv ty1 + let ms2: Measure = conv ty2 + Measure.Prod(ms1, ms2, unionRanges ms1.Range ms2.Range) | TType_app (tcref, [ty1], _) when tyconRefEq g tcref g.measureinverse_tcr -> Measure.Inv (conv ty1) - | TType_app (tcref, [], _) when tyconRefEq g tcref g.measureone_tcr -> Measure.One - | TType_app (tcref, [], _) when tcref.TypeOrMeasureKind = TyparKind.Measure -> Measure.Const tcref + | TType_app (tcref, [], _) when tyconRefEq g tcref g.measureone_tcr -> Measure.One(tcref.Range) + | TType_app (tcref, [], _) when tcref.TypeOrMeasureKind = TyparKind.Measure -> Measure.Const(tcref, tcref.Range) | TType_app (tcref, _, _) -> errorR(Error(FSComp.SR.impInvalidMeasureArgument1(tcref.CompiledName, tp.Name), m)) - Measure.One + Measure.One(tcref.Range) | _ -> errorR(Error(FSComp.SR.impInvalidMeasureArgument2(tp.Name), m)) - Measure.One + Measure.One(Range.Zero) TType_measure (conv genericArg) else diff --git a/src/Compiler/Service/ItemKey.fs b/src/Compiler/Service/ItemKey.fs index 3c030f84c90..49cdda18940 100644 --- a/src/Compiler/Service/ItemKey.fs +++ b/src/Compiler/Service/ItemKey.fs @@ -362,7 +362,7 @@ and [] ItemKeyStoreBuilder(tcGlobals: TcGlobals) = | Measure.Var typar -> writeString ItemKeyTags.typeMeasureVar writeTypar isStandalone typar - | Measure.Const tcref -> + | Measure.Const(tyconRef = tcref) -> writeString ItemKeyTags.typeMeasureCon writeEntityRef tcref | _ -> () diff --git a/src/Compiler/Symbols/Exprs.fs b/src/Compiler/Symbols/Exprs.fs index 91480597cc2..5ec81f6861d 100644 --- a/src/Compiler/Symbols/Exprs.fs +++ b/src/Compiler/Symbols/Exprs.fs @@ -3,6 +3,7 @@ namespace FSharp.Compiler.Symbols open FSharp.Compiler +open FSharp.Compiler.Text.Range open Internal.Utilities.Library open Internal.Utilities.Library.Extras open FSharp.Compiler.AbstractIL.IL @@ -775,7 +776,7 @@ module FSharpExprConvert = let argTy2 = tyOfExpr g arg2 let resTy = match getMeasureOfType g argTy1, getMeasureOfType g argTy2 with - | Some (tcref, ms1), Some (_tcref2, ms2) -> mkWoNullAppTy tcref [TType_measure (Measure.Prod(ms1, if isMul then ms2 else Measure.Inv ms2))] + | Some (tcref, ms1), Some (_tcref2, ms2) -> mkWoNullAppTy tcref [TType_measure (Measure.Prod(ms1, (if isMul then ms2 else Measure.Inv ms2), unionRanges ms1.Range ms2.Range))] | Some _, None -> argTy1 | None, Some _ -> argTy2 | None, None -> argTy1 diff --git a/src/Compiler/Symbols/Symbols.fs b/src/Compiler/Symbols/Symbols.fs index c2772cf8736..36823f65dc0 100644 --- a/src/Compiler/Symbols/Symbols.fs +++ b/src/Compiler/Symbols/Symbols.fs @@ -2512,9 +2512,9 @@ type FSharpType(cenv, ty:TType) = DiagnosticsLogger.protectAssemblyExploration true <| fun () -> match stripTyparEqns ty with | TType_app (tcref, tyargs, _) -> FSharpEntity(cenv, tcref, tyargs).IsUnresolved - | TType_measure (Measure.Const tcref) -> FSharpEntity(cenv, tcref).IsUnresolved + | TType_measure (Measure.Const(tyconRef= tcref)) -> FSharpEntity(cenv, tcref).IsUnresolved | TType_measure (Measure.Prod _) -> FSharpEntity(cenv, cenv.g.measureproduct_tcr).IsUnresolved - | TType_measure Measure.One -> FSharpEntity(cenv, cenv.g.measureone_tcr).IsUnresolved + | TType_measure (Measure.One _) -> FSharpEntity(cenv, cenv.g.measureone_tcr).IsUnresolved | TType_measure (Measure.Inv _) -> FSharpEntity(cenv, cenv.g.measureinverse_tcr).IsUnresolved | _ -> false @@ -2528,7 +2528,7 @@ type FSharpType(cenv, ty:TType) = isResolved() && protect <| fun () -> match stripTyparEqns ty with - | TType_app _ | TType_measure (Measure.Const _ | Measure.Prod _ | Measure.Inv _ | Measure.One) -> true + | TType_app _ | TType_measure (Measure.Const _ | Measure.Prod _ | Measure.Inv _ | Measure.One _) -> true | _ -> false member _.IsMeasureType = @@ -2556,9 +2556,9 @@ type FSharpType(cenv, ty:TType) = protect <| fun () -> match stripTyparEqns ty with | TType_app (tcref, tyargs, _) -> FSharpEntity(cenv, tcref, tyargs) - | TType_measure (Measure.Const tcref) -> FSharpEntity(cenv, tcref) + | TType_measure (Measure.Const(tyconRef= tcref)) -> FSharpEntity(cenv, tcref) | TType_measure (Measure.Prod _) -> FSharpEntity(cenv, cenv.g.measureproduct_tcr) - | TType_measure Measure.One -> FSharpEntity(cenv, cenv.g.measureone_tcr) + | TType_measure (Measure.One _) -> FSharpEntity(cenv, cenv.g.measureone_tcr) | TType_measure (Measure.Inv _) -> FSharpEntity(cenv, cenv.g.measureinverse_tcr) | _ -> invalidOp "not a named type" @@ -2587,8 +2587,8 @@ type FSharpType(cenv, ty:TType) = | TType_tuple (_, tyargs) -> (tyargs |> List.map (fun ty -> FSharpType(cenv, ty)) |> makeReadOnlyCollection) | TType_fun(domainTy, rangeTy, _) -> [| FSharpType(cenv, domainTy); FSharpType(cenv, rangeTy) |] |> makeReadOnlyCollection | TType_measure (Measure.Const _) -> [| |] |> makeReadOnlyCollection - | TType_measure (Measure.Prod (t1, t2)) -> [| FSharpType(cenv, TType_measure t1); FSharpType(cenv, TType_measure t2) |] |> makeReadOnlyCollection - | TType_measure Measure.One -> [| |] |> makeReadOnlyCollection + | TType_measure (Measure.Prod(measure1= t1; measure2 = t2)) -> [| FSharpType(cenv, TType_measure t1); FSharpType(cenv, TType_measure t2) |] |> makeReadOnlyCollection + | TType_measure (Measure.One _) -> [| |] |> makeReadOnlyCollection | TType_measure (Measure.Inv t1) -> [| FSharpType(cenv, TType_measure t1) |] |> makeReadOnlyCollection | _ -> invalidOp "not a named type" diff --git a/src/Compiler/SyntaxTree/SyntaxTree.fs b/src/Compiler/SyntaxTree/SyntaxTree.fs index 8977e8fba6b..bd918e8848a 100644 --- a/src/Compiler/SyntaxTree/SyntaxTree.fs +++ b/src/Compiler/SyntaxTree/SyntaxTree.fs @@ -202,6 +202,18 @@ type SynMeasure = | Paren of measure: SynMeasure * range: range + member x.Range = + match x with + | SynMeasure.Named(range = m) + | SynMeasure.Product(range = m) + | SynMeasure.Seq(range = m) + | SynMeasure.Divide(range = m) + | SynMeasure.Power(range = m) + | SynMeasure.One(range = m) + | SynMeasure.Anon(range = m) + | SynMeasure.Var(range = m) + | SynMeasure.Paren(range = m) -> m + [] type SynRationalConst = diff --git a/src/Compiler/SyntaxTree/SyntaxTree.fsi b/src/Compiler/SyntaxTree/SyntaxTree.fsi index 654a3971175..f50adfa289d 100644 --- a/src/Compiler/SyntaxTree/SyntaxTree.fsi +++ b/src/Compiler/SyntaxTree/SyntaxTree.fsi @@ -213,6 +213,8 @@ type SynMeasure = /// A parenthesized measure | Paren of measure: SynMeasure * range: range + member Range: range + /// Represents an unchecked syntax tree of F# unit of measure exponents. [] type SynRationalConst = diff --git a/src/Compiler/TypedTree/TypedTree.fs b/src/Compiler/TypedTree/TypedTree.fs index 1aaa21eb294..11ff117cc25 100644 --- a/src/Compiler/TypedTree/TypedTree.fs +++ b/src/Compiler/TypedTree/TypedTree.fs @@ -4559,16 +4559,16 @@ type Measure = | Var of typar: Typar /// A constant, leaf unit-of-measure such as 'kg' or 'm' - | Const of tyconRef: TyconRef + | Const of tyconRef: TyconRef * range: range /// A product of two units of measure - | Prod of measure1: Measure * measure2: Measure + | Prod of measure1: Measure * measure2: Measure * range: range /// An inverse of a units of measure expression | Inv of measure: Measure /// The unit of measure '1', e.g. float = float<1> - | One + | One of range: range /// Raising a measure to a rational power | RationalPower of measure: Measure * power: Rational @@ -4577,7 +4577,16 @@ type Measure = //[] //member x.DebugText = x.ToString() - override x.ToString() = sprintf "%+A" x + override x.ToString() = sprintf "%+A" x + + member x.Range = + match x with + | Var(typar) -> typar.Range + | Const(range= m) -> m + | Prod(range= m) -> m + | Inv(m) -> m.Range + | One(range= m) -> m + | RationalPower(measure= ms) -> ms.Range type Attribs = Attrib list diff --git a/src/Compiler/TypedTree/TypedTree.fsi b/src/Compiler/TypedTree/TypedTree.fsi index 73eeb760b4c..82a0a8d84c4 100644 --- a/src/Compiler/TypedTree/TypedTree.fsi +++ b/src/Compiler/TypedTree/TypedTree.fsi @@ -3202,22 +3202,24 @@ type Measure = | Var of typar: Typar /// A constant, leaf unit-of-measure such as 'kg' or 'm' - | Const of tyconRef: TyconRef + | Const of tyconRef: TyconRef * range: range /// A product of two units of measure - | Prod of measure1: Measure * measure2: Measure + | Prod of measure1: Measure * measure2: Measure * range: range /// An inverse of a units of measure expression | Inv of measure: Measure /// The unit of measure '1', e.g. float = float<1> - | One + | One of range: range /// Raising a measure to a rational power | RationalPower of measure: Measure * power: Rational override ToString: unit -> string + member Range: range + type Attribs = Attrib list [] diff --git a/src/Compiler/TypedTree/TypedTreeOps.fs b/src/Compiler/TypedTree/TypedTreeOps.fs index ca7292c6369..e2bc362c784 100644 --- a/src/Compiler/TypedTree/TypedTreeOps.fs +++ b/src/Compiler/TypedTree/TypedTreeOps.fs @@ -228,12 +228,12 @@ let rec remapTypeAux (tyenv: Remap) (ty: TType) = and remapMeasureAux tyenv unt = match unt with - | Measure.One -> unt - | Measure.Const tcref -> - match tyenv.tyconRefRemap.TryFind tcref with - | Some tcref -> Measure.Const tcref + | Measure.One _ -> unt + | Measure.Const(entityRef, m) -> + match tyenv.tyconRefRemap.TryFind entityRef with + | Some tcref -> Measure.Const(tcref, m) | None -> unt - | Measure.Prod(u1, u2) -> Measure.Prod(remapMeasureAux tyenv u1, remapMeasureAux tyenv u2) + | Measure.Prod(u1, u2, m) -> Measure.Prod(remapMeasureAux tyenv u1, remapMeasureAux tyenv u2, m) | Measure.RationalPower(u, q) -> Measure.RationalPower(remapMeasureAux tyenv u, q) | Measure.Inv u -> Measure.Inv(remapMeasureAux tyenv u) | Measure.Var tp as unt -> @@ -444,7 +444,7 @@ let reduceTyconRefAbbrevMeasureable (tcref: TyconRef) = let rec stripUnitEqnsFromMeasureAux canShortcut unt = match stripUnitEqnsAux canShortcut unt with - | Measure.Const tcref when tcref.IsTypeAbbrev -> + | Measure.Const(tyconRef= tcref) when tcref.IsTypeAbbrev -> stripUnitEqnsFromMeasureAux canShortcut (reduceTyconRefAbbrevMeasureable tcref) | m -> m @@ -457,20 +457,20 @@ let stripUnitEqnsFromMeasure m = stripUnitEqnsFromMeasureAux false m /// What is the contribution of unit-of-measure constant ucref to unit-of-measure expression measure? let rec MeasureExprConExponent g abbrev ucref unt = match (if abbrev then stripUnitEqnsFromMeasure unt else stripUnitEqns unt) with - | Measure.Const ucrefR -> if tyconRefEq g ucrefR ucref then OneRational else ZeroRational + | Measure.Const(tyconRef= ucrefR) -> if tyconRefEq g ucrefR ucref then OneRational else ZeroRational | Measure.Inv untR -> NegRational(MeasureExprConExponent g abbrev ucref untR) - | Measure.Prod(unt1, unt2) -> AddRational(MeasureExprConExponent g abbrev ucref unt1) (MeasureExprConExponent g abbrev ucref unt2) - | Measure.RationalPower(untR, q) -> MulRational (MeasureExprConExponent g abbrev ucref untR) q + | Measure.Prod(measure1= unt1; measure2= unt2) -> AddRational(MeasureExprConExponent g abbrev ucref unt1) (MeasureExprConExponent g abbrev ucref unt2) + | Measure.RationalPower(measure= untR; power= q) -> MulRational (MeasureExprConExponent g abbrev ucref untR) q | _ -> ZeroRational /// What is the contribution of unit-of-measure constant ucref to unit-of-measure expression measure /// after remapping tycons? let rec MeasureConExponentAfterRemapping g r ucref unt = match stripUnitEqnsFromMeasure unt with - | Measure.Const ucrefR -> if tyconRefEq g (r ucrefR) ucref then OneRational else ZeroRational + | Measure.Const(tyconRef= ucrefR) -> if tyconRefEq g (r ucrefR) ucref then OneRational else ZeroRational | Measure.Inv untR -> NegRational(MeasureConExponentAfterRemapping g r ucref untR) - | Measure.Prod(unt1, unt2) -> AddRational(MeasureConExponentAfterRemapping g r ucref unt1) (MeasureConExponentAfterRemapping g r ucref unt2) - | Measure.RationalPower(untR, q) -> MulRational (MeasureConExponentAfterRemapping g r ucref untR) q + | Measure.Prod(measure1= unt1; measure2= unt2) -> AddRational(MeasureConExponentAfterRemapping g r ucref unt1) (MeasureConExponentAfterRemapping g r ucref unt2) + | Measure.RationalPower(measure= untR; power= q) -> MulRational (MeasureConExponentAfterRemapping g r ucref untR) q | _ -> ZeroRational /// What is the contribution of unit-of-measure variable tp to unit-of-measure expression unt? @@ -478,8 +478,8 @@ let rec MeasureVarExponent tp unt = match stripUnitEqnsFromMeasure unt with | Measure.Var tpR -> if typarEq tp tpR then OneRational else ZeroRational | Measure.Inv untR -> NegRational(MeasureVarExponent tp untR) - | Measure.Prod(unt1, unt2) -> AddRational(MeasureVarExponent tp unt1) (MeasureVarExponent tp unt2) - | Measure.RationalPower(untR, q) -> MulRational (MeasureVarExponent tp untR) q + | Measure.Prod(measure1= unt1; measure2= unt2) -> AddRational(MeasureVarExponent tp unt1) (MeasureVarExponent tp unt2) + | Measure.RationalPower(measure = untR; power= q) -> MulRational (MeasureVarExponent tp untR) q | _ -> ZeroRational /// List the *literal* occurrences of unit variables in a unit expression, without repeats @@ -487,8 +487,8 @@ let ListMeasureVarOccs unt = let rec gather acc unt = match stripUnitEqnsFromMeasure unt with | Measure.Var tp -> if List.exists (typarEq tp) acc then acc else tp :: acc - | Measure.Prod(unt1, unt2) -> gather (gather acc unt1) unt2 - | Measure.RationalPower(untR, _) -> gather acc untR + | Measure.Prod(measure1= unt1; measure2= unt2) -> gather (gather acc unt1) unt2 + | Measure.RationalPower(measure= untR) -> gather acc untR | Measure.Inv untR -> gather acc untR | _ -> acc gather [] unt @@ -502,9 +502,9 @@ let ListMeasureVarOccsWithNonZeroExponents untexpr = else let e = MeasureVarExponent tp untexpr if e = ZeroRational then acc else (tp, e) :: acc - | Measure.Prod(unt1, unt2) -> gather (gather acc unt1) unt2 + | Measure.Prod(measure1= unt1; measure2= unt2) -> gather (gather acc unt1) unt2 | Measure.Inv untR -> gather acc untR - | Measure.RationalPower(untR, _) -> gather acc untR + | Measure.RationalPower(measure= untR) -> gather acc untR | _ -> acc gather [] untexpr @@ -512,13 +512,13 @@ let ListMeasureVarOccsWithNonZeroExponents untexpr = let ListMeasureConOccsWithNonZeroExponents g eraseAbbrevs untexpr = let rec gather acc unt = match (if eraseAbbrevs then stripUnitEqnsFromMeasure unt else stripUnitEqns unt) with - | Measure.Const c -> + | Measure.Const(tyconRef= c) -> if List.exists (fun (cR, _) -> tyconRefEq g c cR) acc then acc else let e = MeasureExprConExponent g eraseAbbrevs c untexpr if e = ZeroRational then acc else (c, e) :: acc - | Measure.Prod(unt1, unt2) -> gather (gather acc unt1) unt2 + | Measure.Prod(measure1= unt1; measure2= unt2) -> gather (gather acc unt1) unt2 | Measure.Inv untR -> gather acc untR - | Measure.RationalPower(untR, _) -> gather acc untR + | Measure.RationalPower(measure= untR) -> gather acc untR | _ -> acc gather [] untexpr @@ -527,9 +527,9 @@ let ListMeasureConOccsWithNonZeroExponents g eraseAbbrevs untexpr = let ListMeasureConOccsAfterRemapping g r unt = let rec gather acc unt = match stripUnitEqnsFromMeasure unt with - | Measure.Const c -> if List.exists (tyconRefEq g (r c)) acc then acc else r c :: acc - | Measure.Prod(unt1, unt2) -> gather (gather acc unt1) unt2 - | Measure.RationalPower(untR, _) -> gather acc untR + | Measure.Const(tyconRef= c) -> if List.exists (tyconRefEq g (r c)) acc then acc else r c :: acc + | Measure.Prod(measure1= unt1; measure2= unt2) -> gather (gather acc unt1) unt2 + | Measure.RationalPower(measure= untR) -> gather acc untR | Measure.Inv untR -> gather acc untR | _ -> acc @@ -538,19 +538,19 @@ let ListMeasureConOccsAfterRemapping g r unt = /// Construct a measure expression representing the n'th power of a measure let MeasurePower u n = if n = 1 then u - elif n = 0 then Measure.One + elif n = 0 then Measure.One(range0) else Measure.RationalPower (u, intToRational n) let MeasureProdOpt m1 m2 = match m1, m2 with - | Measure.One, _ -> m2 - | _, Measure.One -> m1 - | _, _ -> Measure.Prod (m1, m2) + | Measure.One _, _ -> m2 + | _, Measure.One _ -> m1 + | _, _ -> Measure.Prod (m1, m2, unionRanges m1.Range m2.Range) /// Construct a measure expression representing the product of a list of measures let ProdMeasures ms = match ms with - | [] -> Measure.One + | [] -> Measure.One(range0) | m :: ms -> List.foldBack MeasureProdOpt ms m let isDimensionless g ty = @@ -580,9 +580,23 @@ let normalizeMeasure g ms = let vs = ListMeasureVarOccsWithNonZeroExponents ms let cs = ListMeasureConOccsWithNonZeroExponents g false ms match vs, cs with - | [], [] -> Measure.One + | [], [] -> Measure.One(ms.Range) | [(v, e)], [] when e = OneRational -> Measure.Var v - | vs, cs -> List.foldBack (fun (v, e) -> fun m -> Measure.Prod (Measure.RationalPower (Measure.Var v, e), m)) vs (List.foldBack (fun (c, e) -> fun m -> Measure.Prod (Measure.RationalPower (Measure.Const c, e), m)) cs Measure.One) + | vs, cs -> + List.foldBack + (fun (v, e) -> + fun unt -> + let measureVar = Measure.Var(v) + let measureRational = Measure.RationalPower(measureVar, e) + Measure.Prod(measureRational, unt, unionRanges measureRational.Range unt.Range)) + vs + (List.foldBack + (fun (c, e) -> + fun unt -> + let measureConst = Measure.Const(c, c.Range) + let measureRational = Measure.RationalPower(measureConst, e) + let prodM = unionRanges measureConst.Range unt.Range + Measure.Prod(measureRational, unt, prodM)) cs (Measure.One(ms.Range))) let tryNormalizeMeasureInType g ty = match ty with @@ -916,14 +930,14 @@ let tryNiceEntityRefOfTy ty = let ty = stripTyparEqnsAux KnownWithoutNull false ty match ty with | TType_app (tcref, _, _) -> ValueSome tcref - | TType_measure (Measure.Const tcref) -> ValueSome tcref + | TType_measure (Measure.Const(tyconRef= tcref)) -> ValueSome tcref | _ -> ValueNone let tryNiceEntityRefOfTyOption ty = let ty = stripTyparEqnsAux KnownWithoutNull false ty match ty with | TType_app (tcref, _, _) -> Some tcref - | TType_measure (Measure.Const tcref) -> Some tcref + | TType_measure (Measure.Const(tyconRef= tcref)) -> Some tcref | _ -> None let mkInstForAppTy g ty = @@ -1159,7 +1173,7 @@ let getMeasureOfType g ty = match ty with | AppTy g (tcref, [tyarg]) -> match stripTyEqns g tyarg with - | TType_measure ms when not (measureEquiv g ms Measure.One) -> Some (tcref, ms) + | TType_measure ms when not (measureEquiv g ms (Measure.One(tcref.Range))) -> Some (tcref, ms) | _ -> None | _ -> None diff --git a/src/Compiler/TypedTree/TypedTreeOps.fsi b/src/Compiler/TypedTree/TypedTreeOps.fsi index bda6c2c3187..6433cf16d3e 100755 --- a/src/Compiler/TypedTree/TypedTreeOps.fsi +++ b/src/Compiler/TypedTree/TypedTreeOps.fsi @@ -843,6 +843,8 @@ val CollectAllNoCaching: FreeVarOptions val CollectAll: FreeVarOptions +val ListMeasureVarOccs: Measure -> Typar list + val accFreeInTypes: FreeVarOptions -> TType list -> FreeTyvars -> FreeTyvars val accFreeInType: FreeVarOptions -> TType -> FreeTyvars -> FreeTyvars diff --git a/src/Compiler/TypedTree/TypedTreePickle.fs b/src/Compiler/TypedTree/TypedTreePickle.fs index 3ce2e68396d..d2b3bd0ec79 100644 --- a/src/Compiler/TypedTree/TypedTreePickle.fs +++ b/src/Compiler/TypedTree/TypedTreePickle.fs @@ -1535,7 +1535,7 @@ let p_measure_one = p_byte 4 // Pickle a unit-of-measure variable or constructor let p_measure_varcon unt st = match unt with - | Measure.Const tcref -> p_measure_con tcref st + | Measure.Const(tyconRef= tcref) -> p_measure_con tcref st | Measure.Var v -> p_measure_var v st | _ -> pfailwith st "p_measure_varcon: expected measure variable or constructor" @@ -1564,12 +1564,12 @@ let rec p_measure_power unt q st = let rec p_normalized_measure unt st = let unt = stripUnitEqnsAux false unt match unt with - | Measure.Const tcref -> p_measure_con tcref st + | Measure.Const(tyconRef= tcref) -> p_measure_con tcref st | Measure.Inv x -> p_byte 1 st; p_normalized_measure x st - | Measure.Prod(x1, x2) -> p_byte 2 st; p_normalized_measure x1 st; p_normalized_measure x2 st + | Measure.Prod(measure1= x1; measure2= x2) -> p_byte 2 st; p_normalized_measure x1 st; p_normalized_measure x2 st | Measure.Var v -> p_measure_var v st - | Measure.One -> p_measure_one st - | Measure.RationalPower(x, q) -> p_measure_power x q st + | Measure.One _ -> p_measure_one st + | Measure.RationalPower(measure= x; power= q) -> p_measure_power x q st // By normalizing the unit-of-measure and treating integer powers as a special case, // we ensure that the pickle format for rational powers of units (byte 5 followed by @@ -1585,11 +1585,11 @@ let u_rational st = let rec u_measure_expr st = let tag = u_byte st match tag with - | 0 -> let a = u_tcref st in Measure.Const a + | 0 -> let a = u_tcref st in Measure.Const(a, range0) | 1 -> let a = u_measure_expr st in Measure.Inv a - | 2 -> let a, b = u_tup2 u_measure_expr u_measure_expr st in Measure.Prod (a, b) - | 3 -> let a = u_tpref st in Measure.Var a - | 4 -> Measure.One + | 2 -> let a, b = u_tup2 u_measure_expr u_measure_expr st in Measure.Prod (a, b, range0) + | 3 -> let a = u_tpref st in Measure.Var(a) + | 4 -> Measure.One(range0) | 5 -> let a = u_measure_expr st in let b = u_rational st in Measure.RationalPower (a, b) | _ -> ufailwith st "u_measure_expr" diff --git a/tests/FSharp.Compiler.ComponentTests/Language/ObsoleteAttributeCheckingTests.fs b/tests/FSharp.Compiler.ComponentTests/Language/ObsoleteAttributeCheckingTests.fs index 002bef2f41b..d9a8bfb28f0 100644 --- a/tests/FSharp.Compiler.ComponentTests/Language/ObsoleteAttributeCheckingTests.fs +++ b/tests/FSharp.Compiler.ComponentTests/Language/ObsoleteAttributeCheckingTests.fs @@ -1,6 +1,5 @@ namespace Language -open FSharp.Test open Xunit open FSharp.Test.Compiler @@ -37,6 +36,350 @@ let c = C() (Warning 44, Line 7, Col 9, Line 7, Col 10, "This construct is deprecated. Use B instead") ] + + [] + let ``Obsolete attribute warning taken into account when used with a literal`` () = + Fsx """ +open System +[] +let myLit = 12 + +let myRes = myLit + """ + |> typecheck + |> shouldFail + |> withDiagnostics [ + (Warning 44, Line 6, Col 13, Line 6, Col 18, "This construct is deprecated. Use lit2") + ] + + [] + let ``Obsolete attribute error taken into account when used with a literal`` () = + Fsx """ +open System +[] +let myLit = 12 + +let myRes = myLit + """ + |> typecheck + |> shouldFail + |> withDiagnostics [ + (Error 101, Line 6, Col 13, Line 6, Col 18, "This construct is deprecated. Use lit2") + ] + + [] + let ``Obsolete attribute warning taken into account when used with a simple unit of measure`` () = + Fsx """ +open System +[] +type cm + +let myCm = 3 + """ + |> typecheck + |> shouldFail + |> withDiagnostics [ + (Warning 44, Line 6, Col 14, Line 6, Col 16, "This construct is deprecated. Use cm2") + ] + + [] + let ``Obsolete attribute error taken into account when used with a simple unit of measure`` () = + Fsx """ +open System +[] +type cm + +let myCm = 3 + """ + |> typecheck + |> shouldFail + |> withDiagnostics [ + (Error 101, Line 6, Col 14, Line 6, Col 16, "This construct is deprecated. Use cm2") + ] + + [] + let ``Obsolete attribute warning taken into account when used with a simple unit of measure type abbrev`` () = + Fsx """ +open System +[] type cm + +[] type ml = cm^3 + +type Mls = int * int + +type IMl2 = + abstract member Ml2 : x: int * y: int -> int + abstract member Ml3 : x: int * y: int -> int + """ + |> typecheck + |> shouldFail + |> withDiagnostics [ + (Warning 44, Line 5, Col 23, Line 5, Col 25, "This construct is deprecated. Use something else") + (Warning 44, Line 7, Col 16, Line 7, Col 18, "This construct is deprecated. Use something else") + (Warning 44, Line 7, Col 26, Line 7, Col 28, "This construct is deprecated. Use something else") + (Warning 44, Line 10, Col 34, Line 10, Col 36, "This construct is deprecated. Use something else") + (Warning 44, Line 10, Col 47, Line 10, Col 49, "This construct is deprecated. Use something else") + (Warning 44, Line 11, Col 34, Line 11, Col 36, "This construct is deprecated. Use something else") + (Warning 44, Line 11, Col 47, Line 11, Col 49, "This construct is deprecated. Use something else") + (Warning 44, Line 11, Col 58, Line 11, Col 60, "This construct is deprecated. Use something else") + ] + + [] + let ``Obsolete attribute error taken into account when used with a simple unit of measure type abbrev`` () = + Fsx """ +open System +[] type cm + +[] type ml = cm^3 + """ + |> typecheck + |> shouldFail + |> withDiagnostics [ + (Error 101, Line 5, Col 23, Line 5, Col 25, "This construct is deprecated. Use something else") + ] + + [] + let ``Obsolete attribute warning taken into account when used with a complex unit of measure definition`` () = + Fsx """ +open System +[] +type kg + +[] type m + +[] +type s + +// Force, Newtons. +[] type N = kg m / s^2 + """ + |> typecheck + |> shouldFail + |> withDiagnostics [ + (Warning 44, Line 12, Col 22, Line 12, Col 24, "This construct is deprecated. Use kg2"); + (Warning 44, Line 12, Col 29, Line 12, Col 30, "This construct is deprecated. Use s2") + ] + + [] + let ``Obsolete attribute error taken into account when used with a complex unit of measure definition`` () = + Fsx """ +open System +[] +type kg + +[] type m + +[] +type s + +// Force, Newtons. +[] type N = kg m / s^2 + """ + |> typecheck + |> shouldFail + |> withDiagnostics [ + (Error 101, Line 12, Col 22, Line 12, Col 24, "This construct is deprecated. Use kg2"); + ] + + [] + let ``Obsolete attribute warning taken into account when used within a complex unit of measure`` () = + Fsx """ +open System + +[] +type kg + +[] +type cm + +let myCm = 3 + +let cm2 = 3 * 3 + """ + |> typecheck + |> shouldFail + |> withDiagnostics [ + (Warning 44, Line 10, Col 14, Line 10, Col 16, "This construct is deprecated. Use cm2"); + (Warning 44, Line 12, Col 13, Line 12, Col 15, "This construct is deprecated. Use cm2"); + (Warning 44, Line 12, Col 24, Line 12, Col 26, "This construct is deprecated. Use cm2") + ] + + [] + let ``Obsolete attribute warning taken into account when used within a complex unit of measure. Define conversion constants.`` () = + Fsx """ +open System + +[] +type m + +[] +type cm + +let cmPerMeter : float = 100.0 +let mPerCm = 0.01 + """ + |> typecheck + |> shouldFail + |> withDiagnostics [ + (Warning 44, Line 10, Col 24, Line 10, Col 26, "This construct is deprecated. Use cm2") + (Warning 44, Line 10, Col 27, Line 10, Col 28, "This construct is deprecated. Use m2") + (Warning 44, Line 10, Col 38, Line 10, Col 40, "This construct is deprecated. Use cm2") + (Warning 44, Line 10, Col 41, Line 10, Col 42, "This construct is deprecated. Use m2") + (Warning 44, Line 11, Col 19, Line 11, Col 20, "This construct is deprecated. Use m2") + (Warning 44, Line 11, Col 21, Line 11, Col 23, "This construct is deprecated. Use cm2") + ] + + [] + let ``Obsolete attribute warning taken into account when used with a complex(multiple obsolete) unit of measure`` () = + Fsx """ +open System + +[] +type kg + +[] +type cm + +let myCm = 3 + """ + |> typecheck + |> shouldFail + |> withDiagnostics [ + (Warning 44, Line 10, Col 14, Line 10, Col 16, "This construct is deprecated. Use cm2"); + (Warning 44, Line 10, Col 17, Line 10, Col 19, "This construct is deprecated. Use kg2") + ] + + [] + let ``TopLevel - Obsolete attribute warning taken into account when used with a complex(multiple obsolete) unit of measure usages`` () = + Fsx """ +open System +// Distance, meters. +[] type m + +// Time, seconds. +[] type s + +let genericSumUnits (x: float<'u>) (y: float<'u>) = x + y + +let genericSumUnits2 (x: float) (y: float) = () + +let genericSumUnits3 (x: float) (y: float) (z: float) = () + +let genericSumUnits4 (x: float, y: float) = () + +let genericSumUnits5 (x: float, y: float, z: float) = () + +let v1 = 3.1 +let v2 = 2.7 +let x1 = 1.2 +let t1 = 1.0 + +let result1 = genericSumUnits v1 v2 + +let res = System.Collections.Generic.Dictionary,int>() + """ + |> typecheck + |> shouldFail + |> withDiagnostics [ + (Warning 44, Line 11, Col 32, Line 11, Col 33, "This construct is deprecated. Use m2") + (Warning 44, Line 11, Col 46, Line 11, Col 47, "This construct is deprecated. Use s2") + (Warning 44, Line 13, Col 32, Line 13, Col 33, "This construct is deprecated. Use m2") + (Warning 44, Line 13, Col 46, Line 13, Col 47, "This construct is deprecated. Use s2") + (Warning 44, Line 13, Col 60, Line 13, Col 61, "This construct is deprecated. Use m2") + (Warning 44, Line 15, Col 32, Line 15, Col 33, "This construct is deprecated. Use m2") + (Warning 44, Line 15, Col 45, Line 15, Col 46, "This construct is deprecated. Use s2") + (Warning 44, Line 17, Col 32, Line 17, Col 33, "This construct is deprecated. Use m2") + (Warning 44, Line 17, Col 45, Line 17, Col 46, "This construct is deprecated. Use s2") + (Warning 44, Line 17, Col 58, Line 17, Col 59, "This construct is deprecated. Use m2") + (Warning 44, Line 19, Col 14, Line 19, Col 15, "This construct is deprecated. Use m2") + (Warning 44, Line 19, Col 16, Line 19, Col 17, "This construct is deprecated. Use s2") + (Warning 44, Line 20, Col 14, Line 20, Col 15, "This construct is deprecated. Use m2") + (Warning 44, Line 20, Col 16, Line 20, Col 17, "This construct is deprecated. Use s2") + (Warning 44, Line 21, Col 14, Line 21, Col 15, "This construct is deprecated. Use m2") + (Warning 44, Line 22, Col 14, Line 22, Col 15, "This construct is deprecated. Use s2") + (Warning 44, Line 26, Col 53, Line 26, Col 54, "This construct is deprecated. Use m2") + (Warning 44, Line 26, Col 60, Line 26, Col 61, "This construct is deprecated. Use s2") + ] + + [] + let ``Class- Obsolete attribute warning taken into account when used with a complex(multiple obsolete) unit of measure usages`` () = + Fsx """ +open System +// Distance, meters. +[] type m + +// Time, seconds. +[] type s + +type MyClass() = + let genericSumUnits (x: float<'u>) (y: float<'u>) = x + y + + let genericSumUnits2 (x: float) (y: float) = () + + static let genericSumUnits3 (x: float) (y: float) (z: float) = () + + let genericSumUnits4 (x: float, y: float) = () + + let genericSumUnits5 (x: float, y: float, z: float) = () + + member this.Prop = 3.1 + + member this.Prop2 = 2.7 + + member this.Prop3 = 1.2 + + member this.Prop4 = 1.0 + + member this.GenericSumUnits (x: float<'u>) (y: float<'u>) = x + y + + member this.GenericSumUnits2 (x: float) (y: float) = () + + member this.GenericSumUnits3 (x: float) (y: float) (z: float) = () + + member this.GenericSumUnits4 (x: float, y: float) = () + + member this.GenericSumUnits5 (x: float, y: float, z: float) = () + +type A<[] 'u>(x: int) = + member _.X = x + +type B(x: int, y: int) = + member _.X = x + """ + |> typecheck + |> shouldFail + |> withDiagnostics [ + (Warning 44, Line 30, Col 44, Line 30, Col 45, "This construct is deprecated. Use m2") + (Warning 44, Line 30, Col 58, Line 30, Col 59, "This construct is deprecated. Use s2") + (Warning 44, Line 32, Col 44, Line 32, Col 45, "This construct is deprecated. Use m2") + (Warning 44, Line 32, Col 58, Line 32, Col 59, "This construct is deprecated. Use s2") + (Warning 44, Line 32, Col 72, Line 32, Col 73, "This construct is deprecated. Use m2") + (Warning 44, Line 34, Col 44, Line 34, Col 45, "This construct is deprecated. Use m2") + (Warning 44, Line 34, Col 57, Line 34, Col 58, "This construct is deprecated. Use s2") + (Warning 44, Line 36, Col 44, Line 36, Col 45, "This construct is deprecated. Use m2") + (Warning 44, Line 36, Col 57, Line 36, Col 58, "This construct is deprecated. Use s2") + (Warning 44, Line 36, Col 70, Line 36, Col 71, "This construct is deprecated. Use m2") + (Warning 44, Line 12, Col 36, Line 12, Col 37, "This construct is deprecated. Use m2") + (Warning 44, Line 12, Col 50, Line 12, Col 51, "This construct is deprecated. Use s2") + (Warning 44, Line 14, Col 43, Line 14, Col 44, "This construct is deprecated. Use m2") + (Warning 44, Line 14, Col 57, Line 14, Col 58, "This construct is deprecated. Use s2") + (Warning 44, Line 14, Col 71, Line 14, Col 72, "This construct is deprecated. Use m2") + (Warning 44, Line 16, Col 36, Line 16, Col 37, "This construct is deprecated. Use m2") + (Warning 44, Line 16, Col 49, Line 16, Col 50, "This construct is deprecated. Use s2") + (Warning 44, Line 18, Col 36, Line 18, Col 37, "This construct is deprecated. Use m2") + (Warning 44, Line 18, Col 49, Line 18, Col 50, "This construct is deprecated. Use s2") + (Warning 44, Line 18, Col 62, Line 18, Col 63, "This construct is deprecated. Use m2") + (Warning 44, Line 20, Col 28, Line 20, Col 29, "This construct is deprecated. Use m2") + (Warning 44, Line 20, Col 30, Line 20, Col 31, "This construct is deprecated. Use s2") + (Warning 44, Line 22, Col 29, Line 22, Col 30, "This construct is deprecated. Use m2") + (Warning 44, Line 22, Col 31, Line 22, Col 32, "This construct is deprecated. Use s2") + (Warning 44, Line 24, Col 29, Line 24, Col 30, "This construct is deprecated. Use m2") + (Warning 44, Line 26, Col 29, Line 26, Col 30, "This construct is deprecated. Use s2") + (Warning 44, Line 38, Col 31, Line 38, Col 32, "This construct is deprecated. Use m2") + (Warning 44, Line 41, Col 15, Line 41, Col 16, "This construct is deprecated. Use m2") + (Warning 44, Line 41, Col 26, Line 41, Col 27, "This construct is deprecated. Use s2") + ] + [] let ``Obsolete attribute error taken into account when used instantiating a type`` () = Fsx """ diff --git a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.debug.bsl b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.debug.bsl index cf5037bc449..6004f3fb62d 100644 --- a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.debug.bsl +++ b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.debug.bsl @@ -8116,6 +8116,8 @@ FSharp.Compiler.Syntax.SynMeasure: FSharp.Compiler.Syntax.SynMeasure+Product FSharp.Compiler.Syntax.SynMeasure: FSharp.Compiler.Syntax.SynMeasure+Seq FSharp.Compiler.Syntax.SynMeasure: FSharp.Compiler.Syntax.SynMeasure+Tags FSharp.Compiler.Syntax.SynMeasure: FSharp.Compiler.Syntax.SynMeasure+Var +FSharp.Compiler.Syntax.SynMeasure: FSharp.Compiler.Text.Range Range +FSharp.Compiler.Syntax.SynMeasure: FSharp.Compiler.Text.Range get_Range() FSharp.Compiler.Syntax.SynMeasure: Int32 Tag FSharp.Compiler.Syntax.SynMeasure: Int32 get_Tag() FSharp.Compiler.Syntax.SynMeasure: System.String ToString() diff --git a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.release.bsl b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.release.bsl index cf5037bc449..6004f3fb62d 100644 --- a/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.release.bsl +++ b/tests/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.SurfaceArea.netstandard20.release.bsl @@ -8116,6 +8116,8 @@ FSharp.Compiler.Syntax.SynMeasure: FSharp.Compiler.Syntax.SynMeasure+Product FSharp.Compiler.Syntax.SynMeasure: FSharp.Compiler.Syntax.SynMeasure+Seq FSharp.Compiler.Syntax.SynMeasure: FSharp.Compiler.Syntax.SynMeasure+Tags FSharp.Compiler.Syntax.SynMeasure: FSharp.Compiler.Syntax.SynMeasure+Var +FSharp.Compiler.Syntax.SynMeasure: FSharp.Compiler.Text.Range Range +FSharp.Compiler.Syntax.SynMeasure: FSharp.Compiler.Text.Range get_Range() FSharp.Compiler.Syntax.SynMeasure: Int32 Tag FSharp.Compiler.Syntax.SynMeasure: Int32 get_Tag() FSharp.Compiler.Syntax.SynMeasure: System.String ToString()