diff --git a/docs/release-notes/.FSharp.Compiler.Service/8.0.300.md b/docs/release-notes/.FSharp.Compiler.Service/8.0.300.md index b8dc1de0de9..f568c530217 100644 --- a/docs/release-notes/.FSharp.Compiler.Service/8.0.300.md +++ b/docs/release-notes/.FSharp.Compiler.Service/8.0.300.md @@ -14,6 +14,7 @@ * Name resolution: keep type vars in subsequent checks ([PR #16456](https://github.com/dotnet/fsharp/pull/16456)) * Higher-order-function-based API for working with the untyped abstract syntax tree. ([PR #16462](https://github.com/dotnet/fsharp/pull/16462)) * Allow returning bool instead of unit option for partial active patterns. ([Language suggestion #1041](https://github.com/fsharp/fslang-suggestions/issues/1041), [PR #16473](https://github.com/dotnet/fsharp/pull/16473)) +* Symbols: Add GenericArguments to FSharpEntity ([PR #16470](https://github.com/dotnet/fsharp/pull/16470)) ### Changed diff --git a/src/Compiler/Checking/NameResolution.fs b/src/Compiler/Checking/NameResolution.fs index b70c297e988..68b333b52d9 100644 --- a/src/Compiler/Checking/NameResolution.fs +++ b/src/Compiler/Checking/NameResolution.fs @@ -278,7 +278,7 @@ type Item = | Item.CtorGroup(nm, _) -> nm |> DemangleGenericTypeName | Item.DelegateCtor ty -> match ty with - | AbbrevOrAppTy tcref -> tcref.DisplayNameCore + | AbbrevOrAppTy(tcref, _) -> tcref.DisplayNameCore // This case is not expected | _ -> "" | Item.UnqualifiedType(tcref :: _) -> tcref.DisplayNameCore @@ -309,7 +309,7 @@ type Item = | Item.Property(info = pinfo :: _) -> pinfo.DisplayName | Item.Event einfo -> einfo.DisplayName | Item.MethodGroup(_, minfo :: _, _) -> minfo.DisplayName - | Item.DelegateCtor (AbbrevOrAppTy tcref) -> tcref.DisplayName + | Item.DelegateCtor (AbbrevOrAppTy(tcref, _)) -> tcref.DisplayName | Item.UnqualifiedType(tcref :: _) -> tcref.DisplayName | Item.ModuleOrNamespaces(modref :: _) -> modref.DisplayName | Item.TypeVar (nm, _) -> nm |> ConvertLogicalNameToDisplayName @@ -1872,11 +1872,11 @@ let (|EntityUse|_|) (item: Item) = match item with | Item.UnqualifiedType (tcref :: _) -> ValueSome tcref | Item.ExnCase tcref -> ValueSome tcref - | Item.Types(_, [AbbrevOrAppTy tcref]) - | Item.DelegateCtor(AbbrevOrAppTy tcref) -> ValueSome tcref + | Item.Types(_, [AbbrevOrAppTy(tcref, _)]) + | Item.DelegateCtor(AbbrevOrAppTy(tcref, _)) -> ValueSome tcref | Item.CtorGroup(_, ctor :: _) -> match ctor.ApparentEnclosingType with - | AbbrevOrAppTy tcref -> ValueSome tcref + | AbbrevOrAppTy(tcref, _) -> ValueSome tcref | _ -> ValueNone | _ -> ValueNone @@ -1958,7 +1958,7 @@ let ItemsAreEffectivelyEqual g orig other = not tp1.IsCompilerGenerated && not tp1.IsFromError && not tp2.IsCompilerGenerated && not tp2.IsFromError && equals tp1.Range tp2.Range - | AbbrevOrAppTy tcref1, AbbrevOrAppTy tcref2 -> + | AbbrevOrAppTy(tcref1, _), AbbrevOrAppTy(tcref2, _) -> tyconRefDefnEq g tcref1 tcref2 | _ -> false) diff --git a/src/Compiler/Checking/infos.fs b/src/Compiler/Checking/infos.fs index 8d249521aa0..c90d49f3dcc 100644 --- a/src/Compiler/Checking/infos.fs +++ b/src/Compiler/Checking/infos.fs @@ -702,7 +702,7 @@ type MethInfo = member x.DebuggerDisplayName = match x with | ILMeth(_, y, _) -> y.DeclaringTyconRef.DisplayNameWithStaticParametersAndUnderscoreTypars + "::" + y.ILName - | FSMeth(_, AbbrevOrAppTy tcref, vref, _) -> tcref.DisplayNameWithStaticParametersAndUnderscoreTypars + "::" + vref.LogicalName + | FSMeth(_, AbbrevOrAppTy(tcref, _), vref, _) -> tcref.DisplayNameWithStaticParametersAndUnderscoreTypars + "::" + vref.LogicalName | FSMeth(_, _, vref, _) -> "??::" + vref.LogicalName #if !NO_TYPEPROVIDERS | ProvidedMeth(_, mi, _, m) -> "ProvidedMeth: " + mi.PUntaint((fun mi -> mi.Name), m) diff --git a/src/Compiler/Service/FSharpCheckerResults.fs b/src/Compiler/Service/FSharpCheckerResults.fs index 5f18a90968a..f55010a9025 100644 --- a/src/Compiler/Service/FSharpCheckerResults.fs +++ b/src/Compiler/Service/FSharpCheckerResults.fs @@ -1805,9 +1805,9 @@ type internal TypeCheckInfo |> List.sortBy (fun d -> let n = match d.Item with - | Item.Types(_, AbbrevOrAppTy tcref :: _) -> 1 + tcref.TyparsNoRange.Length + | Item.Types(_, AbbrevOrAppTy(tcref, _) :: _) -> 1 + tcref.TyparsNoRange.Length // Put delegate ctors after types, sorted by #typars. RemoveDuplicateItems will remove FakeInterfaceCtor and DelegateCtor if an earlier type is also reported with this name - | Item.DelegateCtor(AbbrevOrAppTy tcref) -> 1000 + tcref.TyparsNoRange.Length + | Item.DelegateCtor(AbbrevOrAppTy(tcref, _)) -> 1000 + tcref.TyparsNoRange.Length // Put type ctors after types, sorted by #typars. RemoveDuplicateItems will remove DefaultStructCtors if a type is also reported with this name | Item.CtorGroup(_, cinfo :: _) -> 1000 + 10 * cinfo.DeclaringTyconRef.TyparsNoRange.Length | _ -> 0 @@ -1823,10 +1823,10 @@ type internal TypeCheckInfo items |> List.groupBy (fun d -> match d.Item with - | Item.Types(_, AbbrevOrAppTy tcref :: _) + | Item.Types(_, AbbrevOrAppTy(tcref, _) :: _) | Item.ExnCase tcref -> tcref.LogicalName | Item.UnqualifiedType(tcref :: _) - | Item.DelegateCtor(AbbrevOrAppTy tcref) -> tcref.CompiledName + | Item.DelegateCtor(AbbrevOrAppTy(tcref, _)) -> tcref.CompiledName | Item.CtorGroup(_, cinfo :: _) -> cinfo.ApparentEnclosingTyconRef.CompiledName | _ -> d.Item.DisplayName) diff --git a/src/Compiler/Symbols/SymbolHelpers.fs b/src/Compiler/Symbols/SymbolHelpers.fs index 3c669d7a64c..af89176ff6e 100644 --- a/src/Compiler/Symbols/SymbolHelpers.fs +++ b/src/Compiler/Symbols/SymbolHelpers.fs @@ -284,7 +284,7 @@ module internal SymbolHelpers = | Item.DelegateCtor ty | Item.Types(_, ty :: _) -> match ty with - | AbbrevOrAppTy tcref -> + | AbbrevOrAppTy(tcref, _) -> mkXmlComment (GetXmlDocSigOfEntityRef infoReader m tcref) | _ -> FSharpXmlDoc.None @@ -462,8 +462,8 @@ module internal SymbolHelpers = | Item.UnqualifiedType tcrefs1, Item.UnqualifiedType tcrefs2 -> (tcrefs1, tcrefs2) ||> List.forall2 (fun tcref1 tcref2 -> tyconRefEq g tcref1 tcref2) - | Item.Types(_, [AbbrevOrAppTy tcref1]), Item.UnqualifiedType([tcref2]) -> tyconRefEq g tcref1 tcref2 - | Item.UnqualifiedType([tcref1]), Item.Types(_, [AbbrevOrAppTy tcref2]) -> tyconRefEq g tcref1 tcref2 + | Item.Types(_, [AbbrevOrAppTy(tcref1, _)]), Item.UnqualifiedType([tcref2]) -> tyconRefEq g tcref1 tcref2 + | Item.UnqualifiedType([tcref1]), Item.Types(_, [AbbrevOrAppTy(tcref2, _)]) -> tyconRefEq g tcref1 tcref2 | _ -> false) member x.GetHashCode item = @@ -648,7 +648,7 @@ module internal SymbolHelpers = | Item.Types(_, tys) -> let doc = match tys with - | AbbrevOrAppTy tcref :: _ -> + | AbbrevOrAppTy(tcref, _) :: _ -> if tyconRefUsesLocalXmlDoc g.compilingFSharpCore tcref || tcref.XmlDoc.NonEmpty then Some tcref.XmlDoc else diff --git a/src/Compiler/Symbols/Symbols.fs b/src/Compiler/Symbols/Symbols.fs index 6319af1089c..b5b244a6e5c 100644 --- a/src/Compiler/Symbols/Symbols.fs +++ b/src/Compiler/Symbols/Symbols.fs @@ -292,12 +292,12 @@ type FSharpSymbol(cenv: SymbolEnv, item: unit -> Item, access: FSharpSymbol -> C | Item.CtorGroup(_, cinfo :: _) -> FSharpMemberOrFunctionOrValue(cenv, C cinfo, item) :> _ - | Item.DelegateCtor (AbbrevOrAppTy tcref) -> - FSharpEntity(cenv, tcref) :>_ + | Item.DelegateCtor (AbbrevOrAppTy(tcref, tyargs)) + | Item.Types(_, AbbrevOrAppTy(tcref, tyargs) :: _) -> + FSharpEntity(cenv, tcref, tyargs) :>_ - | Item.UnqualifiedType(tcref :: _) - | Item.Types(_, AbbrevOrAppTy tcref :: _) -> - FSharpEntity(cenv, tcref) :>_ + | Item.UnqualifiedType(tcref :: _) -> + FSharpEntity(cenv, tcref) :> _ | Item.ModuleOrNamespaces(modref :: _) -> FSharpEntity(cenv, modref) :> _ @@ -355,7 +355,7 @@ type FSharpSymbol(cenv: SymbolEnv, item: unit -> Item, access: FSharpSymbol -> C member sym.TryGetAttribute<'T>() = sym.Attributes |> Seq.tryFind (fun attr -> attr.IsAttribute<'T>()) -type FSharpEntity(cenv: SymbolEnv, entity: EntityRef) = +type FSharpEntity(cenv: SymbolEnv, entity: EntityRef, tyargs: TType list) = inherit FSharpSymbol(cenv, (fun () -> checkEntityIsResolved entity @@ -383,6 +383,10 @@ type FSharpEntity(cenv: SymbolEnv, entity: EntityRef) = | None -> false | Some ccu -> ccuEq ccu cenv.g.fslibCcu + new(cenv: SymbolEnv, tcref: TyconRef) = + let _, _, tyargs = FreshenTypeInst cenv.g range0 (tcref.Typars range0) + FSharpEntity(cenv, tcref, tyargs) + member _.Entity = entity member _.LogicalName = @@ -480,6 +484,10 @@ type FSharpEntity(cenv: SymbolEnv, entity: EntityRef) = checkIsResolved() entity.TyparsNoRange |> List.map (fun tp -> FSharpGenericParameter(cenv, tp)) |> makeReadOnlyCollection + member _.GenericArguments = + checkIsResolved() + tyargs |> List.map (fun ty -> FSharpType(cenv, ty)) |> makeReadOnlyCollection + member _.IsMeasure = isResolvedAndFSharp() && (entity.TypeOrMeasureKind = TyparKind.Measure) @@ -718,7 +726,7 @@ type FSharpEntity(cenv: SymbolEnv, entity: EntityRef) = if isUnresolved() then makeReadOnlyCollection [] else entity.ModuleOrNamespaceType.AllEntities |> QueueList.toList - |> List.map (fun x -> FSharpEntity(cenv, entity.NestedTyconRef x)) + |> List.map (fun x -> FSharpEntity(cenv, entity.NestedTyconRef x, tyargs)) |> makeReadOnlyCollection member _.UnionCases = @@ -1688,7 +1696,7 @@ type FSharpMemberOrFunctionOrValue(cenv, d:FSharpMemberOrValData, item) = | Some v -> v | None -> failwith "DeclarationLocation property not available" - member _.DeclaringEntity = + member _.DeclaringEntity: FSharpEntity option = checkIsResolved() match d with | E e -> FSharpEntity(cenv, e.DeclaringTyconRef) |> Some @@ -1699,12 +1707,16 @@ type FSharpMemberOrFunctionOrValue(cenv, d:FSharpMemberOrValData, item) = | ParentNone -> None | Parent p -> FSharpEntity(cenv, p) |> Some - member _.ApparentEnclosingEntity = + member _.ApparentEnclosingEntity: FSharpEntity = + let createEntity (ttype: TType) = + let tcref, tyargs = destAppTy cenv.g ttype + FSharpEntity(cenv, tcref, tyargs) + checkIsResolved() match d with - | E e -> FSharpEntity(cenv, e.ApparentEnclosingTyconRef) - | P p -> FSharpEntity(cenv, p.ApparentEnclosingTyconRef) - | M m | C m -> FSharpEntity(cenv, m.ApparentEnclosingTyconRef) + | E e -> createEntity e.ApparentEnclosingType + | P p -> createEntity p.ApparentEnclosingType + | M m | C m -> createEntity m.ApparentEnclosingType | V v -> match v.ApparentEnclosingEntity with | ParentNone -> invalidOp "the value or member doesn't have a logical parent" @@ -2453,7 +2465,7 @@ type FSharpType(cenv, ty:TType) = let isUnresolved() = DiagnosticsLogger.protectAssemblyExploration true <| fun () -> match stripTyparEqns ty with - | TType_app (tcref, _, _) -> FSharpEntity(cenv, tcref).IsUnresolved + | TType_app (tcref, tyargs, _) -> FSharpEntity(cenv, tcref, tyargs).IsUnresolved | TType_measure (Measure.Const 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 @@ -2497,7 +2509,7 @@ type FSharpType(cenv, ty:TType) = member _.TypeDefinition = protect <| fun () -> match stripTyparEqns ty with - | TType_app (tcref, _, _) -> FSharpEntity(cenv, tcref) + | TType_app (tcref, tyargs, _) -> FSharpEntity(cenv, tcref, tyargs) | TType_measure (Measure.Const tcref) -> FSharpEntity(cenv, tcref) | TType_measure (Measure.Prod _) -> FSharpEntity(cenv, cenv.g.measureproduct_tcr) | TType_measure Measure.One -> FSharpEntity(cenv, cenv.g.measureone_tcr) diff --git a/src/Compiler/Symbols/Symbols.fsi b/src/Compiler/Symbols/Symbols.fsi index 4050073c704..5530ba53ec5 100644 --- a/src/Compiler/Symbols/Symbols.fsi +++ b/src/Compiler/Symbols/Symbols.fsi @@ -265,6 +265,10 @@ type FSharpEntity = /// Get the generic parameters, possibly including unit-of-measure parameters member GenericParameters: IList + + /// Get the generic parameters, possibly including unit-of-measure parameters + member GenericArguments: IList + #if !NO_TYPEPROVIDERS /// Get the static parameters for a provided type member StaticParameters: IList diff --git a/src/Compiler/TypedTree/TypedTreeBasics.fs b/src/Compiler/TypedTree/TypedTreeBasics.fs index 651eadd0d65..c71994685d3 100644 --- a/src/Compiler/TypedTree/TypedTreeBasics.fs +++ b/src/Compiler/TypedTree/TypedTreeBasics.fs @@ -265,7 +265,7 @@ let stripUnitEqns unt = stripUnitEqnsAux false unt /// Detect a use of a nominal type, including type abbreviations. let (|AbbrevOrAppTy|_|) (ty: TType) = match stripTyparEqns ty with - | TType_app (tcref, _, _) -> Some tcref + | TType_app (tcref, tinst, _) -> Some(tcref, tinst) | _ -> None //--------------------------------------------------------------------------- diff --git a/src/Compiler/TypedTree/TypedTreeBasics.fsi b/src/Compiler/TypedTree/TypedTreeBasics.fsi index 8a73a609316..ea1f5979262 100644 --- a/src/Compiler/TypedTree/TypedTreeBasics.fsi +++ b/src/Compiler/TypedTree/TypedTreeBasics.fsi @@ -135,7 +135,7 @@ val stripTyparEqns: ty: TType -> TType val stripUnitEqns: unt: Measure -> Measure /// Detect a use of a nominal type, including type abbreviations. -val (|AbbrevOrAppTy|_|): ty: TType -> TyconRef option +val (|AbbrevOrAppTy|_|): ty: TType -> (TyconRef * TypeInst) option val mkLocalValRef: v: Val -> ValRef 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 b6eeea8f992..e53606d2de3 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 @@ -4868,8 +4868,10 @@ FSharp.Compiler.Symbols.FSharpEntity: System.Collections.Generic.IList`1[FSharp. FSharp.Compiler.Symbols.FSharpEntity: System.Collections.Generic.IList`1[FSharp.Compiler.Symbols.FSharpStaticParameter] get_StaticParameters() FSharp.Compiler.Symbols.FSharpEntity: System.Collections.Generic.IList`1[FSharp.Compiler.Symbols.FSharpType] AllInterfaces FSharp.Compiler.Symbols.FSharpEntity: System.Collections.Generic.IList`1[FSharp.Compiler.Symbols.FSharpType] DeclaredInterfaces +FSharp.Compiler.Symbols.FSharpEntity: System.Collections.Generic.IList`1[FSharp.Compiler.Symbols.FSharpType] GenericArguments FSharp.Compiler.Symbols.FSharpEntity: System.Collections.Generic.IList`1[FSharp.Compiler.Symbols.FSharpType] get_AllInterfaces() FSharp.Compiler.Symbols.FSharpEntity: System.Collections.Generic.IList`1[FSharp.Compiler.Symbols.FSharpType] get_DeclaredInterfaces() +FSharp.Compiler.Symbols.FSharpEntity: System.Collections.Generic.IList`1[FSharp.Compiler.Symbols.FSharpType] get_GenericArguments() FSharp.Compiler.Symbols.FSharpEntity: System.Collections.Generic.IList`1[FSharp.Compiler.Symbols.FSharpUnionCase] UnionCases FSharp.Compiler.Symbols.FSharpEntity: System.Collections.Generic.IList`1[FSharp.Compiler.Symbols.FSharpUnionCase] get_UnionCases() FSharp.Compiler.Symbols.FSharpEntity: System.String AccessPath 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 b6eeea8f992..e53606d2de3 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 @@ -4868,8 +4868,10 @@ FSharp.Compiler.Symbols.FSharpEntity: System.Collections.Generic.IList`1[FSharp. FSharp.Compiler.Symbols.FSharpEntity: System.Collections.Generic.IList`1[FSharp.Compiler.Symbols.FSharpStaticParameter] get_StaticParameters() FSharp.Compiler.Symbols.FSharpEntity: System.Collections.Generic.IList`1[FSharp.Compiler.Symbols.FSharpType] AllInterfaces FSharp.Compiler.Symbols.FSharpEntity: System.Collections.Generic.IList`1[FSharp.Compiler.Symbols.FSharpType] DeclaredInterfaces +FSharp.Compiler.Symbols.FSharpEntity: System.Collections.Generic.IList`1[FSharp.Compiler.Symbols.FSharpType] GenericArguments FSharp.Compiler.Symbols.FSharpEntity: System.Collections.Generic.IList`1[FSharp.Compiler.Symbols.FSharpType] get_AllInterfaces() FSharp.Compiler.Symbols.FSharpEntity: System.Collections.Generic.IList`1[FSharp.Compiler.Symbols.FSharpType] get_DeclaredInterfaces() +FSharp.Compiler.Symbols.FSharpEntity: System.Collections.Generic.IList`1[FSharp.Compiler.Symbols.FSharpType] get_GenericArguments() FSharp.Compiler.Symbols.FSharpEntity: System.Collections.Generic.IList`1[FSharp.Compiler.Symbols.FSharpUnionCase] UnionCases FSharp.Compiler.Symbols.FSharpEntity: System.Collections.Generic.IList`1[FSharp.Compiler.Symbols.FSharpUnionCase] get_UnionCases() FSharp.Compiler.Symbols.FSharpEntity: System.String AccessPath diff --git a/tests/service/Symbols.fs b/tests/service/Symbols.fs index b3d6261d60a..42427a3a89b 100644 --- a/tests/service/Symbols.fs +++ b/tests/service/Symbols.fs @@ -327,7 +327,7 @@ open System findSymbolUseByName "IDisposable" checkResults |> ignore - [] + [] let ``Interface 04 - Type arg`` () = let _, checkResults = getParseAndCheckResults """ open System.Collections.Generic @@ -335,7 +335,8 @@ open System.Collections.Generic IList """ let symbolUse = findSymbolUseByName "IList`1" checkResults - let _, typeArg = symbolUse.GenericArguments[0] + let symbol = symbolUse.Symbol :?> FSharpEntity + let typeArg = symbol.GenericArguments[0] typeArg.Format(symbolUse.DisplayContext) |> shouldEqual "int" [] @@ -351,7 +352,8 @@ type I<'T> = getSymbolUses checkResults |> Seq.findBack (fun symbolUse -> symbolUse.Symbol.DisplayName = "I") - let _, typeArg = symbolUse.GenericArguments[0] + let symbol = symbolUse.Symbol :?> FSharpEntity + let typeArg = symbol.GenericArguments[0] typeArg.Format(symbolUse.DisplayContext) |> shouldEqual "int" [] @@ -367,9 +369,18 @@ type I<'T> = getSymbolUses checkResults |> Seq.findBack (fun symbolUse -> symbolUse.Symbol.DisplayName = "I") - let _, typeArg = symbolUse.GenericArguments[0] + let symbol = symbolUse.Symbol :?> FSharpEntity + let typeArg = symbol.GenericArguments[0] typeArg.Format(symbolUse.DisplayContext) |> shouldEqual "int" + [] + let ``Operator 01 - Type arg`` () = + let _, checkResults = getParseAndCheckResults """ +[1] |> ignore +""" + let symbolUses = checkResults.GetAllUsesOfAllSymbolsInFile() + () + [] let ``FSharpType.Format can use prefix representations`` () = let _, checkResults = getParseAndCheckResults """