From 4976d9b4107099abbad5f27386b9fff6b6d8b966 Mon Sep 17 00:00:00 2001 From: Gauthier Segay Date: Sat, 23 Sep 2023 02:46:45 +0200 Subject: [PATCH 01/29] Initial look at issue meant to give priority to extension method if a property of same name exists and arguments are passed to it (assuming property is not a function value). Lots of things to sort out, this just takes care of the first layer of interaction between CheckExpression and NameResolution. Given impact on service / tooling, it is not clear that adding an entry in NameResolution.Item is the best choice, may reconsider into changing the return type of ResolveLongIdentInTypePrim instead. --- src/Compiler/Checking/CheckExpressions.fs | 17 ++++-- src/Compiler/Checking/NameResolution.fs | 51 +++++++++++++----- src/Compiler/Checking/NameResolution.fsi | 4 ++ src/Compiler/Service/FSharpCheckerResults.fs | 6 ++- src/Compiler/Service/ItemKey.fs | 7 +++ .../Service/ServiceDeclarationLists.fs | 17 +++++- src/Compiler/Symbols/SymbolHelpers.fs | 52 ++++++++++++++++--- src/Compiler/Symbols/Symbols.fs | 2 + 8 files changed, 130 insertions(+), 26 deletions(-) diff --git a/src/Compiler/Checking/CheckExpressions.fs b/src/Compiler/Checking/CheckExpressions.fs index c52fb1cf8aa..20ccf5b36e0 100644 --- a/src/Compiler/Checking/CheckExpressions.fs +++ b/src/Compiler/Checking/CheckExpressions.fs @@ -8358,7 +8358,8 @@ and TcItemThen (cenv: cenv) (overallTy: OverallTy) env tpenv (tinstEnclosing, it match usageTextOpt() with | None -> error(Error(FSComp.SR.tcCustomOperationNotUsedCorrectly nm, mItem)) | Some usageText -> error(Error(FSComp.SR.tcCustomOperationNotUsedCorrectly2(nm, usageText), mItem)) - + | Item.AmbiguousMethGroupOrProperty _ -> + failwith "todo: type check based on delayed items?" // These items are not expected here - they are only used for reporting symbols from name resolution to language service | Item.ActivePatternCase _ | Item.AnonRecdField _ @@ -8373,6 +8374,7 @@ and TcItemThen (cenv: cenv) (overallTy: OverallTy) env tpenv (tinstEnclosing, it | Item.Types(_, []) -> error(Error(FSComp.SR.tcLookupMayNotBeUsedHere(), mItem)) + /// Type check the application of a union case. Also used to cover constructions of F# exception values, and /// applications of active pattern result labels. // @@ -8552,7 +8554,7 @@ and TcTypeItemThen (cenv: cenv) overallTy env nm ty tpenv mItem tinstEnclosing d let item = Item.Types(nm, [ty]) CallNameResolutionSink cenv.tcSink (mExprAndTypeArgs, env.NameEnv, item, emptyTyparInst, ItemOccurence.Use, env.eAccessRights) let typeNameResInfo = GetLongIdentTypeNameInfo otherDelayed - let item, mItem, rest, afterResolution = ResolveExprDotLongIdentAndComputeRange cenv.tcSink cenv.nameResolver (unionRanges mExprAndTypeArgs mLongId) ad env.eNameResEnv ty longId typeNameResInfo IgnoreOverrides true + let item, mItem, rest, afterResolution = ResolveExprDotLongIdentAndComputeRange cenv.tcSink cenv.nameResolver (unionRanges mExprAndTypeArgs mLongId) ad env.eNameResEnv ty longId typeNameResInfo IgnoreOverrides true None TcItemThen cenv overallTy env tpenv ((argsOfAppTy g ty), item, mItem, rest, afterResolution) None otherDelayed | DelayedTypeApp(tyargs, _mTypeArgs, mExprAndTypeArgs) :: _delayed' -> @@ -9116,8 +9118,13 @@ and TcLookupThen cenv overallTy env tpenv mObjExpr objExpr objExprTy longId dela // Canonicalize inference problem prior to '.' lookup on variable types if isTyparTy g objExprTy then CanonicalizePartialInferenceProblem cenv.css env.DisplayEnv mExprAndLongId (freeInTypeLeftToRight g false objExprTy) - - let item, mItem, rest, afterResolution = ResolveExprDotLongIdentAndComputeRange cenv.tcSink cenv.nameResolver mExprAndLongId ad env.NameEnv objExprTy longId TypeNameResolutionInfo.Default findFlag false + // + let maybeAppliedArgExpr = + match delayed with + | [] -> None + | DelayedItem.DelayedApp(argExpr=argExpr) :: _ -> Some argExpr + | _ -> None + let item, mItem, rest, afterResolution = ResolveExprDotLongIdentAndComputeRange cenv.tcSink cenv.nameResolver mExprAndLongId ad env.NameEnv objExprTy longId TypeNameResolutionInfo.Default findFlag false maybeAppliedArgExpr TcLookupItemThen cenv overallTy env tpenv mObjExpr objExpr objExprTy delayed item mItem rest afterResolution and TcLookupItemThen cenv overallTy env tpenv mObjExpr objExpr objExprTy delayed item mItem rest afterResolution = @@ -9259,6 +9266,8 @@ and TcLookupItemThen cenv overallTy env tpenv mObjExpr objExpr objExprTy delayed TcTraitItemThen cenv overallTy env (Some objExpr) traitInfo tpenv mItem delayed | Item.FakeInterfaceCtor _ | Item.DelegateCtor _ -> error (Error (FSComp.SR.tcConstructorsCannotBeFirstClassValues(), mItem)) + | Item.AmbiguousMethGroupOrProperty _ -> + failwith "todo: type check based on delayed items?" // These items are not expected here - they can't be the result of a instance member dot-lookup "expr.Ident" | Item.ActivePatternResult _ diff --git a/src/Compiler/Checking/NameResolution.fs b/src/Compiler/Checking/NameResolution.fs index 292343dd223..f3db723dab0 100644 --- a/src/Compiler/Checking/NameResolution.fs +++ b/src/Compiler/Checking/NameResolution.fs @@ -246,6 +246,11 @@ type Item = /// Represents the potential resolution of an unqualified name to a type. | UnqualifiedType of TyconRef list + /// Represents resolution of property which may have extension methods of same name + | AmbiguousMethGroupOrProperty of displayName: string * infos: Item list + + static member MakeAmbiguousMethGroupOrProperty (nm, infos: Item list) = + Item.AmbiguousMethGroupOrProperty (nm, infos) static member MakeMethGroup (nm, minfos: MethInfo list) = let minfos = minfos |> List.sortBy (fun minfo -> minfo.NumArgs |> List.sum) Item.MethodGroup (nm, minfos, None) @@ -271,6 +276,7 @@ type Item = | Item.Property(name = nm) -> nm |> ConvertValLogicalNameToDisplayNameCore | Item.MethodGroup(_, FSMeth(_, _, v, _) :: _, _) -> v.DisplayNameCore | Item.MethodGroup(nm, _, _) -> nm |> ConvertValLogicalNameToDisplayNameCore + | Item.AmbiguousMethGroupOrProperty(displayName=nm) -> nm |> ConvertValLogicalNameToDisplayNameCore | Item.CtorGroup(nm, ILMeth(_, ilMethInfo, _) :: _) -> match ilMethInfo.ApparentEnclosingType |> tryNiceEntityRefOfTy with | ValueSome tcref -> tcref.DisplayNameCore @@ -2226,7 +2232,8 @@ let CheckAllTyparsInferrable amap m item = (freeInType CollectTyparsNoCaching (minfo.GetFSharpReturnType(amap, m, fminst)))) let free = Zset.diff freeInDeclaringType.FreeTypars freeInArgsAndRetType.FreeTypars free.IsEmpty) - + | Item.AmbiguousMethGroupOrProperty(infos=_infos) -> + failwith "RFC XXX extension member priority over property when ..." | Item.Trait _ | Item.CtorGroup _ | Item.FakeInterfaceCtor _ @@ -2575,7 +2582,10 @@ let CheckNestedTypesOfType (ncenv: NameResolver) (resInfo: ResolutionInfo) ad nm // REVIEW: this shows up on performance logs. Consider for example endless resolutions of "List.map" to // the empty set of results, or "x.Length" for a list or array type. This indicates it could be worth adding a cache here. -let rec ResolveLongIdentInTypePrim (ncenv: NameResolver) nenv lookupKind (resInfo: ResolutionInfo) depth m ad (id: Ident) (rest: Ident list) findFlag (typeNameResInfo: TypeNameResolutionInfo) ty = + +// maybeAppliedArgExpr is used in context of resolving extension method that would override property name, it may contain argExpr coming from the DelayedApp(argExpr: SynExpr) +// see RFC XXX +let rec ResolveLongIdentInTypePrim (ncenv: NameResolver) nenv lookupKind (resInfo: ResolutionInfo) depth m ad (id: Ident) (rest: Ident list) findFlag (typeNameResInfo: TypeNameResolutionInfo) ty (maybeAppliedArgExpr: SynExpr option) = let g = ncenv.g let m = unionRanges m id.idRange let nm = id.idText // used to filter the searches of the tables @@ -2611,6 +2621,15 @@ let rec ResolveLongIdentInTypePrim (ncenv: NameResolver) nenv lookupKind (resInf success [resInfo, Item.Trait traitInfo, rest] | Some (PropertyItem psets) when isLookUpExpr -> + // RFC XXXX prefer extension method when ... + let extensionMethods = + match maybeAppliedArgExpr with + | None -> None + | Some _argExpr -> + // todo: consider if filtering candidates based on argExpr:SynExpr is meaningful + // or to leave it to type checker + let methods = ExtensionMethInfosOfTypeInScope ResultCollectionSettings.AllResults ncenv.InfoReader nenv optFilter isInstanceFilter m ty + Some(Item.MakeMethGroup(nm, methods)) let pinfos = psets |> ExcludeHiddenOfPropInfos g ncenv.amap m // fold the available extension members into the overload resolution @@ -2619,8 +2638,14 @@ let rec ResolveLongIdentInTypePrim (ncenv: NameResolver) nenv lookupKind (resInf // make sure to keep the intrinsic pinfos before the extension pinfos in the list, // since later on this logic is used when giving preference to intrinsic definitions match DecodeFSharpEvent (pinfos@extensionPropInfos) ad g ncenv m with - | Some x -> success [resInfo, x, rest] - | None -> raze (UndefinedName (depth, FSComp.SR.undefinedNameFieldConstructorOrMember, id, NoSuggestions)) + | Some x -> + match extensionMethods with + | None -> success [resInfo, x, rest] + | Some extensionMethods -> success [resInfo, Item.MakeAmbiguousMethGroupOrProperty(nm,[extensionMethods;x]), rest] + | None -> + // todo: consider if we should check extension method, but we'd probably won't have matched + // `Some(PropertyItem psets) when isLookUpExpr` in the first place. + raze (UndefinedName (depth, FSComp.SR.undefinedNameFieldConstructorOrMember, id, NoSuggestions)) | Some(MethodItem msets) when isLookUpExpr -> let minfos = msets |> ExcludeHiddenOfMethInfos g ncenv.amap m @@ -2753,13 +2778,13 @@ and ResolveLongIdentInNestedTypes (ncenv: NameResolver) nenv lookupKind resInfo resInfo.AddEntity(id.idRange, tcref) | _ -> resInfo - ResolveLongIdentInTypePrim ncenv nenv lookupKind resInfo depth m ad id2 rest findFlag typeNameResInfo ty + ResolveLongIdentInTypePrim ncenv nenv lookupKind resInfo depth m ad id2 rest findFlag typeNameResInfo ty None |> AtMostOneResult m) /// Resolve a long identifier using type-qualified name resolution. let ResolveLongIdentInType sink (ncenv: NameResolver) nenv lookupKind m ad id findFlag typeNameResInfo ty = let resInfo, item, rest = - ResolveLongIdentInTypePrim ncenv nenv lookupKind ResolutionInfo.Empty 0 m ad id [] findFlag typeNameResInfo ty + ResolveLongIdentInTypePrim ncenv nenv lookupKind ResolutionInfo.Empty 0 m ad id [] findFlag typeNameResInfo ty None |> AtMostOneResult m |> ForceRaise @@ -2775,7 +2800,7 @@ let private ResolveLongIdentInTyconRef (ncenv: NameResolver) nenv lookupKind (re match resInfo.EnclosingTypeInst with | [] -> FreshenTycon ncenv m tcref | tinstEnclosing -> FreshenTyconWithEnclosingTypeInst ncenv m tinstEnclosing tcref - ty |> ResolveLongIdentInTypePrim ncenv nenv lookupKind resInfo depth m ad id rest IgnoreOverrides typeNameResInfo + ResolveLongIdentInTypePrim ncenv nenv lookupKind resInfo depth m ad id rest IgnoreOverrides typeNameResInfo ty None let private ResolveLongIdentInTyconRefs atMostOne (ncenv: NameResolver) nenv lookupKind depth m ad id rest typeNameResInfo idRange tcrefs = tcrefs |> CollectResults2 atMostOne (fun (resInfo: ResolutionInfo, tcref) -> @@ -3879,9 +3904,9 @@ let ResolveNestedField sink (ncenv: NameResolver) nenv ad recdTy lid = /// determine any valid members // // QUERY (instantiationGenerator cleanup): it would be really nice not to flow instantiationGenerator to here. -let private ResolveExprDotLongIdent (ncenv: NameResolver) m ad nenv ty (id: Ident) rest (typeNameResInfo: TypeNameResolutionInfo) findFlag = +let private ResolveExprDotLongIdent (ncenv: NameResolver) m ad nenv ty (id: Ident) rest (typeNameResInfo: TypeNameResolutionInfo) findFlag maybeArgExpr = let lookupKind = LookupKind.Expr LookupIsInstance.Yes - let adhocDotSearchAccessible = AtMostOneResult m (ResolveLongIdentInTypePrim ncenv nenv lookupKind ResolutionInfo.Empty 1 m ad id rest findFlag typeNameResInfo ty) + let adhocDotSearchAccessible = AtMostOneResult m (ResolveLongIdentInTypePrim ncenv nenv lookupKind ResolutionInfo.Empty 1 m ad id rest findFlag typeNameResInfo ty maybeArgExpr) match adhocDotSearchAccessible with | Exception _ -> // If the dot is not resolved by adhoc overloading then look for a record field @@ -3901,7 +3926,7 @@ let private ResolveExprDotLongIdent (ncenv: NameResolver) m ad nenv ty (id: Iden let adhocDotSearchAll () = let lookupKind = LookupKind.Expr LookupIsInstance.Ambivalent - ResolveLongIdentInTypePrim ncenv nenv lookupKind ResolutionInfo.Empty 1 m AccessibleFromSomeFSharpCode id rest findFlag typeNameResInfo ty + ResolveLongIdentInTypePrim ncenv nenv lookupKind ResolutionInfo.Empty 1 m AccessibleFromSomeFSharpCode id rest findFlag typeNameResInfo ty None dotFieldIdSearch +++ adhocDotSearchAll |> AtMostOneResult m @@ -4014,12 +4039,12 @@ let (|NonOverridable|_|) namedItem = /// Called for 'expression.Bar' - for VS IntelliSense, we can filter out static members from method groups /// Also called for 'GenericType.Bar' - for VS IntelliSense, we can filter out non-static members from method groups -let ResolveExprDotLongIdentAndComputeRange (sink: TcResultsSink) (ncenv: NameResolver) wholem ad nenv ty lid (typeNameResInfo: TypeNameResolutionInfo) findFlag staticOnly = - let resolveExpr findFlag = +let ResolveExprDotLongIdentAndComputeRange (sink: TcResultsSink) (ncenv: NameResolver) wholem ad nenv ty lid (typeNameResInfo: TypeNameResolutionInfo) findFlag staticOnly maybeArgExpr = + let inline resolveExpr findFlag = let resInfo, item, rest = match lid with | id :: rest -> - ResolveExprDotLongIdent ncenv wholem ad nenv ty id rest typeNameResInfo findFlag + ResolveExprDotLongIdent ncenv wholem ad nenv ty id rest typeNameResInfo findFlag maybeArgExpr | _ -> error(InternalError("ResolveExprDotLongIdentAndComputeRange", wholem)) let itemRange = ComputeItemRange wholem lid rest resInfo, item, rest, itemRange diff --git a/src/Compiler/Checking/NameResolution.fsi b/src/Compiler/Checking/NameResolution.fsi index 5dcc55efc94..a1bcd915a8b 100755 --- a/src/Compiler/Checking/NameResolution.fsi +++ b/src/Compiler/Checking/NameResolution.fsi @@ -144,6 +144,9 @@ type Item = /// Represents the potential resolution of an unqualified name to a type. | UnqualifiedType of TyconRef list + /// Represents resolution of property which may have extension methods of same name + | AmbiguousMethGroupOrProperty of displayName: string * infos: Item list + /// The text for the item to use in the declaration list. /// This does not include backticks, parens etc. /// @@ -808,6 +811,7 @@ val internal ResolveExprDotLongIdentAndComputeRange: typeNameResInfo: TypeNameResolutionInfo -> findFlag: FindMemberFlag -> staticOnly: bool -> + maybeAppliedArgExpr: SynExpr option -> Item * range * Ident list * AfterResolution /// A generator of type instantiations used when no more specific type instantiation is known. diff --git a/src/Compiler/Service/FSharpCheckerResults.fs b/src/Compiler/Service/FSharpCheckerResults.fs index b526c09a796..1fc224cfd83 100644 --- a/src/Compiler/Service/FSharpCheckerResults.fs +++ b/src/Compiler/Service/FSharpCheckerResults.fs @@ -929,7 +929,11 @@ type internal TypeCheckInfo | Item.CustomBuilder _ | Item.OtherName _ | Item.ActivePatternCase _ -> CompletionItemKind.Other - + | Item.AmbiguousMethGroupOrProperty _ -> + #if DEBUG + failwith "Item.AmbiguousMethGroupOrProperty : not sorted out, maybe wrong design" + #endif + CompletionItemKind.Other let isUnresolved = match assemblySymbol with | ValueSome x -> Some x.UnresolvedSymbol diff --git a/src/Compiler/Service/ItemKey.fs b/src/Compiler/Service/ItemKey.fs index c44fc6401d2..958769cc687 100644 --- a/src/Compiler/Service/ItemKey.fs +++ b/src/Compiler/Service/ItemKey.fs @@ -582,6 +582,13 @@ and [] ItemKeyStoreBuilder(tcGlobals: TcGlobals) = | Item.CtorGroup (_, (_ :: _ :: _)) -> () | Item.ModuleOrNamespaces (_ :: _ :: _) -> () + // todo: sort out + | Item.AmbiguousMethGroupOrProperty _ -> + #if DEBUG + failwith "Item.AmbiguousMethGroupOrProperty : not sorted out, maybe wrong design" + #endif + () + let postCount = b.Count fixup.WriteInt32(postCount - preCount) diff --git a/src/Compiler/Service/ServiceDeclarationLists.fs b/src/Compiler/Service/ServiceDeclarationLists.fs index 104ae1da0ff..64f6c0c14e0 100644 --- a/src/Compiler/Service/ServiceDeclarationLists.fs +++ b/src/Compiler/Service/ServiceDeclarationLists.fs @@ -525,7 +525,11 @@ module DeclarationListHelpers = | Item.UnqualifiedType [] | Item.ModuleOrNamespaces [] | Item.CustomOperation (_, _, None) -> ToolTipElement.None - + | Item.AmbiguousMethGroupOrProperty _ -> + #if DEBUG + failwith "Item.AmbiguousMethGroupOrProperty : not sorted out, maybe wrong design" + #endif + ToolTipElement.None /// Format the structured version of a tooltip for an item let FormatStructuredDescriptionOfItem isDecl infoReader ad m denv item symbol width = DiagnosticsScope.Protect m @@ -877,6 +881,8 @@ module internal DescriptionListsImpl = | Item.CtorGroup(_,[]) | Item.Property(info = []) -> [], emptyL + | Item.AmbiguousMethGroupOrProperty _ -> + failwith "todo: type check based on delayed items?" /// Compute the index of the VS glyph shown with an item in the Intellisense menu @@ -970,6 +976,11 @@ module internal DescriptionListsImpl = | Item.NewDef _ | Item.OtherName _ | Item.SetterArg _ -> FSharpGlyph.Variable + | Item.AmbiguousMethGroupOrProperty _ -> + #if DEBUG + failwith "Item.AmbiguousMethGroupOrProperty : not sorted out, maybe wrong design" + #endif + FSharpGlyph.Error // These empty lists are not expected to occur | Item.ModuleOrNamespaces [] @@ -977,7 +988,6 @@ module internal DescriptionListsImpl = FSharpGlyph.Error ) - /// Select the items that participate in a MethodGroup. let SelectMethodGroupItems g m item = #if NO_TYPEPROVIDERS @@ -1003,6 +1013,9 @@ module internal DescriptionListsImpl = | Item.Property(info = pinfos) -> let pinfo = List.head pinfos if pinfo.IsIndexer then [item] else [] + | Item.AmbiguousMethGroupOrProperty _ -> + failwith "todo: type check based on delayed items?" + #if !NO_TYPEPROVIDERS | ItemIsWithStaticArguments m g _ -> // we pretend that provided-types-with-static-args are method-like in order to get ParamInfo for them diff --git a/src/Compiler/Symbols/SymbolHelpers.fs b/src/Compiler/Symbols/SymbolHelpers.fs index 6e4dbc284fe..ce89cd6fa2b 100644 --- a/src/Compiler/Symbols/SymbolHelpers.fs +++ b/src/Compiler/Symbols/SymbolHelpers.fs @@ -120,7 +120,11 @@ module internal SymbolHelpers = | Item.DelegateCtor ty | Item.FakeInterfaceCtor ty -> ty |> tryNiceEntityRefOfTyOption |> Option.map (rangeOfEntityRef preferFlag) | Item.NewDef _ -> None - + | Item.AmbiguousMethGroupOrProperty(infos=infos) -> + #if DEBUG + failwith "Item.AmbiguousMethGroupOrProperty : not sorted out, maybe wrong design" + #endif + rangeOfItem g preferFlag (List.head infos) // Provided type definitions do not have a useful F# CCU for the purposes of goto-definition. let computeCcuOfTyconRef (tcref: TyconRef) = #if !NO_TYPEPROVIDERS @@ -217,7 +221,11 @@ module internal SymbolHelpers = // This is not expected: NewDef only occurs within checking | Item.NewDef _ -> None - + | Item.AmbiguousMethGroupOrProperty _ -> + #if DEBUG + failwith "Item.AmbiguousMethGroupOrProperty : not sorted out, maybe wrong design" + #endif + None /// Work out the source file for an item and fix it up relative to the CCU if it is relative. let fileNameOfItem (g: TcGlobals) qualProjectDir (m: range) h = let file = m.FileName @@ -338,7 +346,11 @@ module internal SymbolHelpers = | Item.UnqualifiedType [] | Item.Types(_, []) -> FSharpXmlDoc.None - + | Item.AmbiguousMethGroupOrProperty _ -> + #if DEBUG + failwith "Item.AmbiguousMethGroupOrProperty : not sorted out, maybe wrong design" + #endif + FSharpXmlDoc.None |> GetXmlDocFromLoader infoReader /// Produce an XmlComment with a signature or raw text, given the F# comment and the item @@ -405,7 +417,11 @@ module internal SymbolHelpers = // These are not expected to occur | Item.Types(_, []) | Item.ModuleOrNamespaces [] -> false - + | Item.AmbiguousMethGroupOrProperty _ -> + #if DEBUG + failwith "Item.AmbiguousMethGroupOrProperty : not sorted out, maybe wrong design" + #endif + false //| _ -> false member x.Equals(item1, item2) = @@ -498,7 +514,11 @@ module internal SymbolHelpers = | Item.Event evt -> evt.ComputeHashCode() | Item.Property(info = pis) -> hash (pis |> List.map (fun pi -> pi.ComputeHashCode())) | Item.UnqualifiedType(tcref :: _) -> hash tcref.LogicalName - + | Item.AmbiguousMethGroupOrProperty _ -> + #if DEBUG + failwith "Item.AmbiguousMethGroupOrProperty : not sorted out, maybe wrong design" + #endif + 0 // These are not expected to occur, see InEqualityRelation and ItemWhereTypIsPreferred | Item.ActivePatternResult _ | Item.AnonRecdField _ @@ -511,6 +531,7 @@ module internal SymbolHelpers = | Item.Types _ | Item.DelegateCtor _ | Item.ModuleOrNamespaces [] -> 0 + ) } /// Remove all duplicate items @@ -592,6 +613,11 @@ module internal SymbolHelpers = | Item.MethodGroup(_, [], _) | Item.ModuleOrNamespaces [] | Item.Property(info = []) -> "" + | Item.AmbiguousMethGroupOrProperty _ -> + #if DEBUG + failwith "Item.AmbiguousMethGroupOrProperty : not sorted out, maybe wrong design" + #endif + "" /// Output the description of a language item let rec GetXmlCommentForItem (infoReader: InfoReader) m item = @@ -719,7 +745,11 @@ module internal SymbolHelpers = | Item.DelegateCtor _ -> //| _ -> GetXmlCommentForItemAux None infoReader m item - + | Item.AmbiguousMethGroupOrProperty _ -> + #if DEBUG + failwith "Item.AmbiguousMethGroupOrProperty : not sorted out, maybe wrong design" + #endif + FSharpXmlDoc.None |> GetXmlDocFromLoader infoReader let IsAttribute (infoReader: InfoReader) item = @@ -944,6 +974,11 @@ module internal SymbolHelpers = | Item.ImplicitOp _ | Item.ActivePatternResult _ // "let (|Foo|Bar|) = .. Fo$o ..." - no keyword -> None + | Item.AmbiguousMethGroupOrProperty _ -> + #if DEBUG + failwith "Item.AmbiguousMethGroupOrProperty : not sorted out, maybe wrong design" + #endif + None /// Select the items that participate in a MethodGroup. // @@ -989,3 +1024,8 @@ module internal SymbolHelpers = | Item.UnionCaseField _ | Item.UnqualifiedType _ | Item.ActivePatternResult _ -> [] + | Item.AmbiguousMethGroupOrProperty _ -> + #if DEBUG + failwith "Item.AmbiguousMethGroupOrProperty : not sorted out, maybe wrong design" + #endif + [] diff --git a/src/Compiler/Symbols/Symbols.fs b/src/Compiler/Symbols/Symbols.fs index e59caf2c6d4..104ddc2489c 100644 --- a/src/Compiler/Symbols/Symbols.fs +++ b/src/Compiler/Symbols/Symbols.fs @@ -343,6 +343,8 @@ type FSharpSymbol(cenv: SymbolEnv, item: unit -> Item, access: FSharpSymbol -> C // These cases cover misc. corned cases (non-symbol types) | Item.Types _ | Item.DelegateCtor _ -> dflt() + | Item.AmbiguousMethGroupOrProperty _ -> + failwith "todo: type check based on delayed items?" abstract Accessibility: FSharpAccessibility default _.Accessibility = FSharpAccessibility(taccessPublic) From a315a7d9eca7deae5695db35267ec06c61e79271 Mon Sep 17 00:00:00 2001 From: Gauthier Segay Date: Sat, 23 Sep 2023 12:14:50 +0200 Subject: [PATCH 02/29] bring it back to the simplest thing that could possibly work, and it seems to work on toy example. --- src/Compiler/Checking/CheckExpressions.fs | 5 +- src/Compiler/Checking/NameResolution.fs | 29 +++-------- src/Compiler/Checking/NameResolution.fsi | 3 -- src/Compiler/Service/FSharpCheckerResults.fs | 6 +-- src/Compiler/Service/ItemKey.fs | 7 --- .../Service/ServiceDeclarationLists.fs | 16 +----- src/Compiler/Symbols/SymbolHelpers.fs | 49 ++----------------- src/Compiler/Symbols/Symbols.fs | 2 - 8 files changed, 14 insertions(+), 103 deletions(-) diff --git a/src/Compiler/Checking/CheckExpressions.fs b/src/Compiler/Checking/CheckExpressions.fs index 20ccf5b36e0..a4dba8306d7 100644 --- a/src/Compiler/Checking/CheckExpressions.fs +++ b/src/Compiler/Checking/CheckExpressions.fs @@ -8358,8 +8358,7 @@ and TcItemThen (cenv: cenv) (overallTy: OverallTy) env tpenv (tinstEnclosing, it match usageTextOpt() with | None -> error(Error(FSComp.SR.tcCustomOperationNotUsedCorrectly nm, mItem)) | Some usageText -> error(Error(FSComp.SR.tcCustomOperationNotUsedCorrectly2(nm, usageText), mItem)) - | Item.AmbiguousMethGroupOrProperty _ -> - failwith "todo: type check based on delayed items?" + // These items are not expected here - they are only used for reporting symbols from name resolution to language service | Item.ActivePatternCase _ | Item.AnonRecdField _ @@ -9266,8 +9265,6 @@ and TcLookupItemThen cenv overallTy env tpenv mObjExpr objExpr objExprTy delayed TcTraitItemThen cenv overallTy env (Some objExpr) traitInfo tpenv mItem delayed | Item.FakeInterfaceCtor _ | Item.DelegateCtor _ -> error (Error (FSComp.SR.tcConstructorsCannotBeFirstClassValues(), mItem)) - | Item.AmbiguousMethGroupOrProperty _ -> - failwith "todo: type check based on delayed items?" // These items are not expected here - they can't be the result of a instance member dot-lookup "expr.Ident" | Item.ActivePatternResult _ diff --git a/src/Compiler/Checking/NameResolution.fs b/src/Compiler/Checking/NameResolution.fs index f3db723dab0..d3dec15919c 100644 --- a/src/Compiler/Checking/NameResolution.fs +++ b/src/Compiler/Checking/NameResolution.fs @@ -246,11 +246,6 @@ type Item = /// Represents the potential resolution of an unqualified name to a type. | UnqualifiedType of TyconRef list - /// Represents resolution of property which may have extension methods of same name - | AmbiguousMethGroupOrProperty of displayName: string * infos: Item list - - static member MakeAmbiguousMethGroupOrProperty (nm, infos: Item list) = - Item.AmbiguousMethGroupOrProperty (nm, infos) static member MakeMethGroup (nm, minfos: MethInfo list) = let minfos = minfos |> List.sortBy (fun minfo -> minfo.NumArgs |> List.sum) Item.MethodGroup (nm, minfos, None) @@ -276,7 +271,6 @@ type Item = | Item.Property(name = nm) -> nm |> ConvertValLogicalNameToDisplayNameCore | Item.MethodGroup(_, FSMeth(_, _, v, _) :: _, _) -> v.DisplayNameCore | Item.MethodGroup(nm, _, _) -> nm |> ConvertValLogicalNameToDisplayNameCore - | Item.AmbiguousMethGroupOrProperty(displayName=nm) -> nm |> ConvertValLogicalNameToDisplayNameCore | Item.CtorGroup(nm, ILMeth(_, ilMethInfo, _) :: _) -> match ilMethInfo.ApparentEnclosingType |> tryNiceEntityRefOfTy with | ValueSome tcref -> tcref.DisplayNameCore @@ -2232,8 +2226,6 @@ let CheckAllTyparsInferrable amap m item = (freeInType CollectTyparsNoCaching (minfo.GetFSharpReturnType(amap, m, fminst)))) let free = Zset.diff freeInDeclaringType.FreeTypars freeInArgsAndRetType.FreeTypars free.IsEmpty) - | Item.AmbiguousMethGroupOrProperty(infos=_infos) -> - failwith "RFC XXX extension member priority over property when ..." | Item.Trait _ | Item.CtorGroup _ | Item.FakeInterfaceCtor _ @@ -2621,15 +2613,6 @@ let rec ResolveLongIdentInTypePrim (ncenv: NameResolver) nenv lookupKind (resInf success [resInfo, Item.Trait traitInfo, rest] | Some (PropertyItem psets) when isLookUpExpr -> - // RFC XXXX prefer extension method when ... - let extensionMethods = - match maybeAppliedArgExpr with - | None -> None - | Some _argExpr -> - // todo: consider if filtering candidates based on argExpr:SynExpr is meaningful - // or to leave it to type checker - let methods = ExtensionMethInfosOfTypeInScope ResultCollectionSettings.AllResults ncenv.InfoReader nenv optFilter isInstanceFilter m ty - Some(Item.MakeMethGroup(nm, methods)) let pinfos = psets |> ExcludeHiddenOfPropInfos g ncenv.amap m // fold the available extension members into the overload resolution @@ -2639,9 +2622,13 @@ let rec ResolveLongIdentInTypePrim (ncenv: NameResolver) nenv lookupKind (resInf // since later on this logic is used when giving preference to intrinsic definitions match DecodeFSharpEvent (pinfos@extensionPropInfos) ad g ncenv m with | Some x -> - match extensionMethods with + match maybeAppliedArgExpr with | None -> success [resInfo, x, rest] - | Some extensionMethods -> success [resInfo, Item.MakeAmbiguousMethGroupOrProperty(nm,[extensionMethods;x]), rest] + | Some _argExpr -> + // RFC XXXX prefer extension method when ... + let methods = ExtensionMethInfosOfTypeInScope ResultCollectionSettings.AllResults ncenv.InfoReader nenv optFilter isInstanceFilter m ty + let extensionMethods = Item.MakeMethGroup(nm, methods) + success ((resInfo,extensionMethods,rest)::[resInfo,x,rest]) | None -> // todo: consider if we should check extension method, but we'd probably won't have matched // `Some(PropertyItem psets) when isLookUpExpr` in the first place. @@ -4039,12 +4026,12 @@ let (|NonOverridable|_|) namedItem = /// Called for 'expression.Bar' - for VS IntelliSense, we can filter out static members from method groups /// Also called for 'GenericType.Bar' - for VS IntelliSense, we can filter out non-static members from method groups -let ResolveExprDotLongIdentAndComputeRange (sink: TcResultsSink) (ncenv: NameResolver) wholem ad nenv ty lid (typeNameResInfo: TypeNameResolutionInfo) findFlag staticOnly maybeArgExpr = +let ResolveExprDotLongIdentAndComputeRange (sink: TcResultsSink) (ncenv: NameResolver) wholem ad nenv ty lid (typeNameResInfo: TypeNameResolutionInfo) findFlag staticOnly maybeAppliedArgExpr = let inline resolveExpr findFlag = let resInfo, item, rest = match lid with | id :: rest -> - ResolveExprDotLongIdent ncenv wholem ad nenv ty id rest typeNameResInfo findFlag maybeArgExpr + ResolveExprDotLongIdent ncenv wholem ad nenv ty id rest typeNameResInfo findFlag maybeAppliedArgExpr | _ -> error(InternalError("ResolveExprDotLongIdentAndComputeRange", wholem)) let itemRange = ComputeItemRange wholem lid rest resInfo, item, rest, itemRange diff --git a/src/Compiler/Checking/NameResolution.fsi b/src/Compiler/Checking/NameResolution.fsi index a1bcd915a8b..08adc72ae3f 100755 --- a/src/Compiler/Checking/NameResolution.fsi +++ b/src/Compiler/Checking/NameResolution.fsi @@ -144,9 +144,6 @@ type Item = /// Represents the potential resolution of an unqualified name to a type. | UnqualifiedType of TyconRef list - /// Represents resolution of property which may have extension methods of same name - | AmbiguousMethGroupOrProperty of displayName: string * infos: Item list - /// The text for the item to use in the declaration list. /// This does not include backticks, parens etc. /// diff --git a/src/Compiler/Service/FSharpCheckerResults.fs b/src/Compiler/Service/FSharpCheckerResults.fs index 1fc224cfd83..b526c09a796 100644 --- a/src/Compiler/Service/FSharpCheckerResults.fs +++ b/src/Compiler/Service/FSharpCheckerResults.fs @@ -929,11 +929,7 @@ type internal TypeCheckInfo | Item.CustomBuilder _ | Item.OtherName _ | Item.ActivePatternCase _ -> CompletionItemKind.Other - | Item.AmbiguousMethGroupOrProperty _ -> - #if DEBUG - failwith "Item.AmbiguousMethGroupOrProperty : not sorted out, maybe wrong design" - #endif - CompletionItemKind.Other + let isUnresolved = match assemblySymbol with | ValueSome x -> Some x.UnresolvedSymbol diff --git a/src/Compiler/Service/ItemKey.fs b/src/Compiler/Service/ItemKey.fs index 958769cc687..c44fc6401d2 100644 --- a/src/Compiler/Service/ItemKey.fs +++ b/src/Compiler/Service/ItemKey.fs @@ -582,13 +582,6 @@ and [] ItemKeyStoreBuilder(tcGlobals: TcGlobals) = | Item.CtorGroup (_, (_ :: _ :: _)) -> () | Item.ModuleOrNamespaces (_ :: _ :: _) -> () - // todo: sort out - | Item.AmbiguousMethGroupOrProperty _ -> - #if DEBUG - failwith "Item.AmbiguousMethGroupOrProperty : not sorted out, maybe wrong design" - #endif - () - let postCount = b.Count fixup.WriteInt32(postCount - preCount) diff --git a/src/Compiler/Service/ServiceDeclarationLists.fs b/src/Compiler/Service/ServiceDeclarationLists.fs index 64f6c0c14e0..3b3963afbff 100644 --- a/src/Compiler/Service/ServiceDeclarationLists.fs +++ b/src/Compiler/Service/ServiceDeclarationLists.fs @@ -525,11 +525,7 @@ module DeclarationListHelpers = | Item.UnqualifiedType [] | Item.ModuleOrNamespaces [] | Item.CustomOperation (_, _, None) -> ToolTipElement.None - | Item.AmbiguousMethGroupOrProperty _ -> - #if DEBUG - failwith "Item.AmbiguousMethGroupOrProperty : not sorted out, maybe wrong design" - #endif - ToolTipElement.None + /// Format the structured version of a tooltip for an item let FormatStructuredDescriptionOfItem isDecl infoReader ad m denv item symbol width = DiagnosticsScope.Protect m @@ -881,9 +877,6 @@ module internal DescriptionListsImpl = | Item.CtorGroup(_,[]) | Item.Property(info = []) -> [], emptyL - | Item.AmbiguousMethGroupOrProperty _ -> - failwith "todo: type check based on delayed items?" - /// Compute the index of the VS glyph shown with an item in the Intellisense menu let GlyphOfItem(denv, item) : FSharpGlyph = @@ -976,11 +969,6 @@ module internal DescriptionListsImpl = | Item.NewDef _ | Item.OtherName _ | Item.SetterArg _ -> FSharpGlyph.Variable - | Item.AmbiguousMethGroupOrProperty _ -> - #if DEBUG - failwith "Item.AmbiguousMethGroupOrProperty : not sorted out, maybe wrong design" - #endif - FSharpGlyph.Error // These empty lists are not expected to occur | Item.ModuleOrNamespaces [] @@ -1013,8 +1001,6 @@ module internal DescriptionListsImpl = | Item.Property(info = pinfos) -> let pinfo = List.head pinfos if pinfo.IsIndexer then [item] else [] - | Item.AmbiguousMethGroupOrProperty _ -> - failwith "todo: type check based on delayed items?" #if !NO_TYPEPROVIDERS | ItemIsWithStaticArguments m g _ -> diff --git a/src/Compiler/Symbols/SymbolHelpers.fs b/src/Compiler/Symbols/SymbolHelpers.fs index ce89cd6fa2b..564453e5995 100644 --- a/src/Compiler/Symbols/SymbolHelpers.fs +++ b/src/Compiler/Symbols/SymbolHelpers.fs @@ -120,11 +120,7 @@ module internal SymbolHelpers = | Item.DelegateCtor ty | Item.FakeInterfaceCtor ty -> ty |> tryNiceEntityRefOfTyOption |> Option.map (rangeOfEntityRef preferFlag) | Item.NewDef _ -> None - | Item.AmbiguousMethGroupOrProperty(infos=infos) -> - #if DEBUG - failwith "Item.AmbiguousMethGroupOrProperty : not sorted out, maybe wrong design" - #endif - rangeOfItem g preferFlag (List.head infos) + // Provided type definitions do not have a useful F# CCU for the purposes of goto-definition. let computeCcuOfTyconRef (tcref: TyconRef) = #if !NO_TYPEPROVIDERS @@ -221,11 +217,7 @@ module internal SymbolHelpers = // This is not expected: NewDef only occurs within checking | Item.NewDef _ -> None - | Item.AmbiguousMethGroupOrProperty _ -> - #if DEBUG - failwith "Item.AmbiguousMethGroupOrProperty : not sorted out, maybe wrong design" - #endif - None + /// Work out the source file for an item and fix it up relative to the CCU if it is relative. let fileNameOfItem (g: TcGlobals) qualProjectDir (m: range) h = let file = m.FileName @@ -346,12 +338,6 @@ module internal SymbolHelpers = | Item.UnqualifiedType [] | Item.Types(_, []) -> FSharpXmlDoc.None - | Item.AmbiguousMethGroupOrProperty _ -> - #if DEBUG - failwith "Item.AmbiguousMethGroupOrProperty : not sorted out, maybe wrong design" - #endif - FSharpXmlDoc.None - |> GetXmlDocFromLoader infoReader /// Produce an XmlComment with a signature or raw text, given the F# comment and the item let GetXmlCommentForItemAux (xmlDoc: XmlDoc option) (infoReader: InfoReader) m d = @@ -417,11 +403,6 @@ module internal SymbolHelpers = // These are not expected to occur | Item.Types(_, []) | Item.ModuleOrNamespaces [] -> false - | Item.AmbiguousMethGroupOrProperty _ -> - #if DEBUG - failwith "Item.AmbiguousMethGroupOrProperty : not sorted out, maybe wrong design" - #endif - false //| _ -> false member x.Equals(item1, item2) = @@ -514,11 +495,7 @@ module internal SymbolHelpers = | Item.Event evt -> evt.ComputeHashCode() | Item.Property(info = pis) -> hash (pis |> List.map (fun pi -> pi.ComputeHashCode())) | Item.UnqualifiedType(tcref :: _) -> hash tcref.LogicalName - | Item.AmbiguousMethGroupOrProperty _ -> - #if DEBUG - failwith "Item.AmbiguousMethGroupOrProperty : not sorted out, maybe wrong design" - #endif - 0 + // These are not expected to occur, see InEqualityRelation and ItemWhereTypIsPreferred | Item.ActivePatternResult _ | Item.AnonRecdField _ @@ -613,11 +590,6 @@ module internal SymbolHelpers = | Item.MethodGroup(_, [], _) | Item.ModuleOrNamespaces [] | Item.Property(info = []) -> "" - | Item.AmbiguousMethGroupOrProperty _ -> - #if DEBUG - failwith "Item.AmbiguousMethGroupOrProperty : not sorted out, maybe wrong design" - #endif - "" /// Output the description of a language item let rec GetXmlCommentForItem (infoReader: InfoReader) m item = @@ -745,11 +717,6 @@ module internal SymbolHelpers = | Item.DelegateCtor _ -> //| _ -> GetXmlCommentForItemAux None infoReader m item - | Item.AmbiguousMethGroupOrProperty _ -> - #if DEBUG - failwith "Item.AmbiguousMethGroupOrProperty : not sorted out, maybe wrong design" - #endif - FSharpXmlDoc.None |> GetXmlDocFromLoader infoReader let IsAttribute (infoReader: InfoReader) item = @@ -974,11 +941,6 @@ module internal SymbolHelpers = | Item.ImplicitOp _ | Item.ActivePatternResult _ // "let (|Foo|Bar|) = .. Fo$o ..." - no keyword -> None - | Item.AmbiguousMethGroupOrProperty _ -> - #if DEBUG - failwith "Item.AmbiguousMethGroupOrProperty : not sorted out, maybe wrong design" - #endif - None /// Select the items that participate in a MethodGroup. // @@ -1024,8 +986,3 @@ module internal SymbolHelpers = | Item.UnionCaseField _ | Item.UnqualifiedType _ | Item.ActivePatternResult _ -> [] - | Item.AmbiguousMethGroupOrProperty _ -> - #if DEBUG - failwith "Item.AmbiguousMethGroupOrProperty : not sorted out, maybe wrong design" - #endif - [] diff --git a/src/Compiler/Symbols/Symbols.fs b/src/Compiler/Symbols/Symbols.fs index 104ddc2489c..e59caf2c6d4 100644 --- a/src/Compiler/Symbols/Symbols.fs +++ b/src/Compiler/Symbols/Symbols.fs @@ -343,8 +343,6 @@ type FSharpSymbol(cenv: SymbolEnv, item: unit -> Item, access: FSharpSymbol -> C // These cases cover misc. corned cases (non-symbol types) | Item.Types _ | Item.DelegateCtor _ -> dflt() - | Item.AmbiguousMethGroupOrProperty _ -> - failwith "todo: type check based on delayed items?" abstract Accessibility: FSharpAccessibility default _.Accessibility = FSharpAccessibility(taccessPublic) From 20c1e7e5287ec171e891579170e68e657a9726bd Mon Sep 17 00:00:00 2001 From: Gauthier Segay Date: Sat, 23 Sep 2023 12:46:18 +0200 Subject: [PATCH 03/29] Do not break all indexed properties in the world (that is, when there are no extension methods in scope). --- src/Compiler/Checking/NameResolution.fs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/Compiler/Checking/NameResolution.fs b/src/Compiler/Checking/NameResolution.fs index d3dec15919c..c6167d3c00f 100644 --- a/src/Compiler/Checking/NameResolution.fs +++ b/src/Compiler/Checking/NameResolution.fs @@ -2626,9 +2626,11 @@ let rec ResolveLongIdentInTypePrim (ncenv: NameResolver) nenv lookupKind (resInf | None -> success [resInfo, x, rest] | Some _argExpr -> // RFC XXXX prefer extension method when ... - let methods = ExtensionMethInfosOfTypeInScope ResultCollectionSettings.AllResults ncenv.InfoReader nenv optFilter isInstanceFilter m ty - let extensionMethods = Item.MakeMethGroup(nm, methods) - success ((resInfo,extensionMethods,rest)::[resInfo,x,rest]) + match ExtensionMethInfosOfTypeInScope ResultCollectionSettings.AllResults ncenv.InfoReader nenv optFilter isInstanceFilter m ty with + | [] -> success [resInfo, x, rest] + | methods -> + let extensionMethods = Item.MakeMethGroup(nm, methods) + success ((resInfo,extensionMethods,rest)::[resInfo,x,rest]) | None -> // todo: consider if we should check extension method, but we'd probably won't have matched // `Some(PropertyItem psets) when isLookUpExpr` in the first place. From 82478cb87c8b6ef9fdc92349b55ea5909c275697 Mon Sep 17 00:00:00 2001 From: Gauthier Segay Date: Wed, 4 Oct 2023 22:05:03 +0200 Subject: [PATCH 04/29] Implementation: singling out indexer properties and properties with FSharpFunc as type. Tests: covering a bunch of allowed and disallowed shadowing cases. --- src/Compiler/Checking/NameResolution.fs | 43 +++- src/Compiler/FSComp.txt | 1 + src/Compiler/Facilities/LanguageFeatures.fs | 6 +- src/Compiler/Facilities/LanguageFeatures.fsi | 2 + src/Compiler/xlf/FSComp.txt.cs.xlf | 5 + src/Compiler/xlf/FSComp.txt.de.xlf | 5 + src/Compiler/xlf/FSComp.txt.es.xlf | 5 + src/Compiler/xlf/FSComp.txt.fr.xlf | 5 + src/Compiler/xlf/FSComp.txt.it.xlf | 5 + src/Compiler/xlf/FSComp.txt.ja.xlf | 5 + src/Compiler/xlf/FSComp.txt.ko.xlf | 5 + src/Compiler/xlf/FSComp.txt.pl.xlf | 5 + src/Compiler/xlf/FSComp.txt.pt-BR.xlf | 5 + src/Compiler/xlf/FSComp.txt.ru.xlf | 5 + src/Compiler/xlf/FSComp.txt.tr.xlf | 5 + src/Compiler/xlf/FSComp.txt.zh-Hans.xlf | 5 + src/Compiler/xlf/FSComp.txt.zh-Hant.xlf | 5 + .../FSharp.Compiler.ComponentTests.fsproj | 1 + ...dowFunctionPropertyWithExtensionMethod.fsx | 20 ++ ...ionPropertyWithExtensionMethod.fsx.err.bsl | 8 + ...tionPropertyWithExtensionMethod.fsx.il.bsl | 0 ...hadowFunctionPropertyWithTypeExtension.fsx | 19 ++ ...ctionPropertyWithTypeExtension.fsx.err.bsl | 13 + ...nctionPropertyWithTypeExtension.fsx.il.bsl | 0 ...adowIndexedPropertyWithExtensionMethod.fsx | 23 ++ ...xedPropertyWithExtensionMethod.fsx.err.bsl | 4 + ...exedPropertyWithExtensionMethod.fsx.il.bsl | 0 ...ShadowIndexedPropertyWithTypeExtension.fsx | 20 ++ ...dexedPropertyWithTypeExtension.fsx.err.bsl | 4 + ...ndexedPropertyWithTypeExtension.fsx.il.bsl | 0 .../ShadowWithExtensionMethod.fsx | 20 ++ .../ShadowWithExtensionMethod.fsx.err.bsl | 0 .../ShadowWithExtensionMethod.fsx.il.bsl | 228 ++++++++++++++++++ .../ShadowWithTypeExtension.fsx | 19 ++ .../ShadowWithTypeExtension.fsx.err.bsl | 0 .../ShadowWithTypeExtension.fsx.il.bsl | 227 +++++++++++++++++ .../TypeExtensions/PropertyShadowingTests.fs | 61 +++++ tests/FSharp.Test.Utilities/Compiler.fs | 110 ++++++--- tests/FSharp.Test.Utilities/CompilerAssert.fs | 29 ++- .../DirectoryAttribute.fs | 11 +- tests/FSharp.Test.Utilities/ILChecker.fs | 74 +++--- 41 files changed, 910 insertions(+), 98 deletions(-) create mode 100644 tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/E_CannotShadowFunctionPropertyWithExtensionMethod.fsx create mode 100644 tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/E_CannotShadowFunctionPropertyWithExtensionMethod.fsx.err.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/E_CannotShadowFunctionPropertyWithExtensionMethod.fsx.il.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/E_CannotShadowFunctionPropertyWithTypeExtension.fsx create mode 100644 tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/E_CannotShadowFunctionPropertyWithTypeExtension.fsx.err.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/E_CannotShadowFunctionPropertyWithTypeExtension.fsx.il.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/E_CannotShadowIndexedPropertyWithExtensionMethod.fsx create mode 100644 tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/E_CannotShadowIndexedPropertyWithExtensionMethod.fsx.err.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/E_CannotShadowIndexedPropertyWithExtensionMethod.fsx.il.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/E_CannotShadowIndexedPropertyWithTypeExtension.fsx create mode 100644 tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/E_CannotShadowIndexedPropertyWithTypeExtension.fsx.err.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/E_CannotShadowIndexedPropertyWithTypeExtension.fsx.il.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/ShadowWithExtensionMethod.fsx create mode 100644 tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/ShadowWithExtensionMethod.fsx.err.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/ShadowWithExtensionMethod.fsx.il.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/ShadowWithTypeExtension.fsx create mode 100644 tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/ShadowWithTypeExtension.fsx.err.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/ShadowWithTypeExtension.fsx.il.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowingTests.fs diff --git a/src/Compiler/Checking/NameResolution.fs b/src/Compiler/Checking/NameResolution.fs index c6167d3c00f..0d18a771762 100644 --- a/src/Compiler/Checking/NameResolution.fs +++ b/src/Compiler/Checking/NameResolution.fs @@ -2576,7 +2576,7 @@ let CheckNestedTypesOfType (ncenv: NameResolver) (resInfo: ResolutionInfo) ad nm // the empty set of results, or "x.Length" for a list or array type. This indicates it could be worth adding a cache here. // maybeAppliedArgExpr is used in context of resolving extension method that would override property name, it may contain argExpr coming from the DelayedApp(argExpr: SynExpr) -// see RFC XXX +// see RFC 1137 let rec ResolveLongIdentInTypePrim (ncenv: NameResolver) nenv lookupKind (resInfo: ResolutionInfo) depth m ad (id: Ident) (rest: Ident list) findFlag (typeNameResInfo: TypeNameResolutionInfo) ty (maybeAppliedArgExpr: SynExpr option) = let g = ncenv.g let m = unionRanges m id.idRange @@ -2614,7 +2614,7 @@ let rec ResolveLongIdentInTypePrim (ncenv: NameResolver) nenv lookupKind (resInf | Some (PropertyItem psets) when isLookUpExpr -> let pinfos = psets |> ExcludeHiddenOfPropInfos g ncenv.amap m - + // fold the available extension members into the overload resolution let extensionPropInfos = ExtensionPropInfosOfTypeInScope ResultCollectionSettings.AllResults ncenv.InfoReader nenv optFilter isInstanceFilter ad m ty @@ -2622,15 +2622,36 @@ let rec ResolveLongIdentInTypePrim (ncenv: NameResolver) nenv lookupKind (resInf // since later on this logic is used when giving preference to intrinsic definitions match DecodeFSharpEvent (pinfos@extensionPropInfos) ad g ncenv m with | Some x -> - match maybeAppliedArgExpr with - | None -> success [resInfo, x, rest] - | Some _argExpr -> - // RFC XXXX prefer extension method when ... - match ExtensionMethInfosOfTypeInScope ResultCollectionSettings.AllResults ncenv.InfoReader nenv optFilter isInstanceFilter m ty with - | [] -> success [resInfo, x, rest] - | methods -> - let extensionMethods = Item.MakeMethGroup(nm, methods) - success ((resInfo,extensionMethods,rest)::[resInfo,x,rest]) + match maybeAppliedArgExpr, g.langVersion.SupportsFeature LanguageFeature.PreferExtensionMethodOverPlainProperty with + | None, _ + | _, false -> + success [resInfo, x, rest] + | Some _argExpr, true -> + // RFC 1137 prefer extension method when ... + + let ignoreProperty (p: PropInfo) = + // do not hide properties if: + // * is indexed property + // * is function type + if p.IsIndexer then + true + else + match p.GetPropertyType(ncenv.amap, m) with + | TType_var(typar={typar_solution = Some (TType_fun _) }) -> + true + | _ -> false + + match x with + | Item.Property(info=ps) when ps |> List.exists ignoreProperty -> + success [resInfo, x, rest] + | _ -> + // lookup in-scope extension methods + // to keep in sync with the same expression in `| Some(MethodItem msets) when isLookupExpr` below + match ExtensionMethInfosOfTypeInScope ResultCollectionSettings.AllResults ncenv.InfoReader nenv optFilter isInstanceFilter m ty with + | [] -> success [resInfo, x, rest] + | methods -> + let extensionMethods = Item.MakeMethGroup(nm, methods) + success ((resInfo,extensionMethods,rest)::[resInfo,x,rest]) | None -> // todo: consider if we should check extension method, but we'd probably won't have matched // `Some(PropertyItem psets) when isLookUpExpr` in the first place. diff --git a/src/Compiler/FSComp.txt b/src/Compiler/FSComp.txt index 9f091d07533..a2420efea0b 100644 --- a/src/Compiler/FSComp.txt +++ b/src/Compiler/FSComp.txt @@ -1588,6 +1588,7 @@ featureChkNotTailRecursive,"Raises warnings if a member or function has the 'Tai featureWhileBang,"'while!' expression" featureExtendedFixedBindings,"extended fixed bindings for byref and GetPinnableReference" featurePreferStringGetPinnableReference,"prefer String.GetPinnableReference in fixed bindings" +featurePreferExtensionMethodOverPlainProperty,"prefer extension method over plain property" 3354,tcNotAFunctionButIndexerNamedIndexingNotYetEnabled,"This value supports indexing, e.g. '%s.[index]'. The syntax '%s[index]' requires /langversion:preview. See https://aka.ms/fsharp-index-notation." 3354,tcNotAFunctionButIndexerIndexingNotYetEnabled,"This expression supports indexing, e.g. 'expr.[index]'. The syntax 'expr[index]' requires /langversion:preview. See https://aka.ms/fsharp-index-notation." 3355,tcNotAnIndexerNamedIndexingNotYetEnabled,"The value '%s' is not a function and does not support index notation." diff --git a/src/Compiler/Facilities/LanguageFeatures.fs b/src/Compiler/Facilities/LanguageFeatures.fs index 9a60cc17136..7aecae1d274 100644 --- a/src/Compiler/Facilities/LanguageFeatures.fs +++ b/src/Compiler/Facilities/LanguageFeatures.fs @@ -79,6 +79,7 @@ type LanguageFeature = | WhileBang | ExtendedFixedBindings | PreferStringGetPinnableReference + | PreferExtensionMethodOverPlainProperty /// LanguageVersion management type LanguageVersion(versionText) = @@ -181,6 +182,9 @@ type LanguageVersion(versionText) = LanguageFeature.WhileBang, previewVersion LanguageFeature.ExtendedFixedBindings, previewVersion LanguageFeature.PreferStringGetPinnableReference, previewVersion + + // F# preview next + LanguageFeature.PreferExtensionMethodOverPlainProperty, previewVersion ] static let defaultLanguageVersion = LanguageVersion("default") @@ -315,7 +319,7 @@ type LanguageVersion(versionText) = | LanguageFeature.WhileBang -> FSComp.SR.featureWhileBang () | LanguageFeature.ExtendedFixedBindings -> FSComp.SR.featureExtendedFixedBindings () | LanguageFeature.PreferStringGetPinnableReference -> FSComp.SR.featurePreferStringGetPinnableReference () - + | LanguageFeature.PreferExtensionMethodOverPlainProperty -> FSComp.SR.featurePreferExtensionMethodOverPlainProperty() /// Get a version string associated with the given feature. static member GetFeatureVersionString feature = match features.TryGetValue feature with diff --git a/src/Compiler/Facilities/LanguageFeatures.fsi b/src/Compiler/Facilities/LanguageFeatures.fsi index c1cb2378d4e..2048ff632b1 100644 --- a/src/Compiler/Facilities/LanguageFeatures.fsi +++ b/src/Compiler/Facilities/LanguageFeatures.fsi @@ -69,6 +69,8 @@ type LanguageFeature = | WhileBang | ExtendedFixedBindings | PreferStringGetPinnableReference + /// RFC-1137 + | PreferExtensionMethodOverPlainProperty /// LanguageVersion management type LanguageVersion = diff --git a/src/Compiler/xlf/FSComp.txt.cs.xlf b/src/Compiler/xlf/FSComp.txt.cs.xlf index 52dc4b8f648..fd5d0485524 100644 --- a/src/Compiler/xlf/FSComp.txt.cs.xlf +++ b/src/Compiler/xlf/FSComp.txt.cs.xlf @@ -397,6 +397,11 @@ správa balíčků + + prefer extension method over plain property + prefer extension method over plain property + + prefer String.GetPinnableReference in fixed bindings prefer String.GetPinnableReference in fixed bindings diff --git a/src/Compiler/xlf/FSComp.txt.de.xlf b/src/Compiler/xlf/FSComp.txt.de.xlf index e03fb2842a3..71d2e89f85a 100644 --- a/src/Compiler/xlf/FSComp.txt.de.xlf +++ b/src/Compiler/xlf/FSComp.txt.de.xlf @@ -397,6 +397,11 @@ Paketverwaltung + + prefer extension method over plain property + prefer extension method over plain property + + prefer String.GetPinnableReference in fixed bindings prefer String.GetPinnableReference in fixed bindings diff --git a/src/Compiler/xlf/FSComp.txt.es.xlf b/src/Compiler/xlf/FSComp.txt.es.xlf index 827cc7aaff7..8cbccc02aa1 100644 --- a/src/Compiler/xlf/FSComp.txt.es.xlf +++ b/src/Compiler/xlf/FSComp.txt.es.xlf @@ -397,6 +397,11 @@ administración de paquetes + + prefer extension method over plain property + prefer extension method over plain property + + prefer String.GetPinnableReference in fixed bindings prefer String.GetPinnableReference in fixed bindings diff --git a/src/Compiler/xlf/FSComp.txt.fr.xlf b/src/Compiler/xlf/FSComp.txt.fr.xlf index 59e745efb6b..4150d0e3b95 100644 --- a/src/Compiler/xlf/FSComp.txt.fr.xlf +++ b/src/Compiler/xlf/FSComp.txt.fr.xlf @@ -397,6 +397,11 @@ Package Management + + prefer extension method over plain property + prefer extension method over plain property + + prefer String.GetPinnableReference in fixed bindings prefer String.GetPinnableReference in fixed bindings diff --git a/src/Compiler/xlf/FSComp.txt.it.xlf b/src/Compiler/xlf/FSComp.txt.it.xlf index 3b3bcd658c0..8af504212c0 100644 --- a/src/Compiler/xlf/FSComp.txt.it.xlf +++ b/src/Compiler/xlf/FSComp.txt.it.xlf @@ -397,6 +397,11 @@ gestione pacchetti + + prefer extension method over plain property + prefer extension method over plain property + + prefer String.GetPinnableReference in fixed bindings prefer String.GetPinnableReference in fixed bindings diff --git a/src/Compiler/xlf/FSComp.txt.ja.xlf b/src/Compiler/xlf/FSComp.txt.ja.xlf index 049db2ffa38..ab67562a432 100644 --- a/src/Compiler/xlf/FSComp.txt.ja.xlf +++ b/src/Compiler/xlf/FSComp.txt.ja.xlf @@ -397,6 +397,11 @@ パッケージの管理 + + prefer extension method over plain property + prefer extension method over plain property + + prefer String.GetPinnableReference in fixed bindings prefer String.GetPinnableReference in fixed bindings diff --git a/src/Compiler/xlf/FSComp.txt.ko.xlf b/src/Compiler/xlf/FSComp.txt.ko.xlf index b1598f8fc53..8ff71851cbb 100644 --- a/src/Compiler/xlf/FSComp.txt.ko.xlf +++ b/src/Compiler/xlf/FSComp.txt.ko.xlf @@ -397,6 +397,11 @@ 패키지 관리 + + prefer extension method over plain property + prefer extension method over plain property + + prefer String.GetPinnableReference in fixed bindings prefer String.GetPinnableReference in fixed bindings diff --git a/src/Compiler/xlf/FSComp.txt.pl.xlf b/src/Compiler/xlf/FSComp.txt.pl.xlf index c5ba8412724..31ba024bd1a 100644 --- a/src/Compiler/xlf/FSComp.txt.pl.xlf +++ b/src/Compiler/xlf/FSComp.txt.pl.xlf @@ -397,6 +397,11 @@ zarządzanie pakietami + + prefer extension method over plain property + prefer extension method over plain property + + prefer String.GetPinnableReference in fixed bindings prefer String.GetPinnableReference in fixed bindings diff --git a/src/Compiler/xlf/FSComp.txt.pt-BR.xlf b/src/Compiler/xlf/FSComp.txt.pt-BR.xlf index 8e2cf14f74d..a486708f7a5 100644 --- a/src/Compiler/xlf/FSComp.txt.pt-BR.xlf +++ b/src/Compiler/xlf/FSComp.txt.pt-BR.xlf @@ -397,6 +397,11 @@ gerenciamento de pacotes + + prefer extension method over plain property + prefer extension method over plain property + + prefer String.GetPinnableReference in fixed bindings prefer String.GetPinnableReference in fixed bindings diff --git a/src/Compiler/xlf/FSComp.txt.ru.xlf b/src/Compiler/xlf/FSComp.txt.ru.xlf index 2cbbdb37444..a1423e63b46 100644 --- a/src/Compiler/xlf/FSComp.txt.ru.xlf +++ b/src/Compiler/xlf/FSComp.txt.ru.xlf @@ -397,6 +397,11 @@ управление пакетами + + prefer extension method over plain property + prefer extension method over plain property + + prefer String.GetPinnableReference in fixed bindings prefer String.GetPinnableReference in fixed bindings diff --git a/src/Compiler/xlf/FSComp.txt.tr.xlf b/src/Compiler/xlf/FSComp.txt.tr.xlf index 146c1fffa58..a231d473814 100644 --- a/src/Compiler/xlf/FSComp.txt.tr.xlf +++ b/src/Compiler/xlf/FSComp.txt.tr.xlf @@ -397,6 +397,11 @@ paket yönetimi + + prefer extension method over plain property + prefer extension method over plain property + + prefer String.GetPinnableReference in fixed bindings prefer String.GetPinnableReference in fixed bindings diff --git a/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf b/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf index 2414d300d75..7e96d99fe60 100644 --- a/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf +++ b/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf @@ -397,6 +397,11 @@ 包管理 + + prefer extension method over plain property + prefer extension method over plain property + + prefer String.GetPinnableReference in fixed bindings prefer String.GetPinnableReference in fixed bindings diff --git a/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf b/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf index 4ab439ee37d..c9594fadeb8 100644 --- a/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf +++ b/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf @@ -397,6 +397,11 @@ 套件管理 + + prefer extension method over plain property + prefer extension method over plain property + + prefer String.GetPinnableReference in fixed bindings prefer String.GetPinnableReference in fixed bindings diff --git a/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj b/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj index a5c8d0ad7a1..4a7f360f66f 100644 --- a/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj +++ b/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj @@ -235,6 +235,7 @@ + diff --git a/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/E_CannotShadowFunctionPropertyWithExtensionMethod.fsx b/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/E_CannotShadowFunctionPropertyWithExtensionMethod.fsx new file mode 100644 index 00000000000..31fdc72d693 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/E_CannotShadowFunctionPropertyWithExtensionMethod.fsx @@ -0,0 +1,20 @@ +open System.Runtime.CompilerServices + +type Foo() = + member val X : int -> int = (+) 1 with get,set + +[] +type FooExt = + [] + static member X (f: Foo, i: int -> int) = f.X <- i; f + +let f = Foo() +f.X 1 +if f.X 0 <> 1 then + System.Environment.Exit 1 +f.X <- (-) 1 + +if f.X 2 <> -1 then + System.Environment.Exit 2 + +f.X((-) 1) // This expression was expected to have type 'int' but here has type ''a -> 'c' \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/E_CannotShadowFunctionPropertyWithExtensionMethod.fsx.err.bsl b/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/E_CannotShadowFunctionPropertyWithExtensionMethod.fsx.err.bsl new file mode 100644 index 00000000000..85e445736c6 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/E_CannotShadowFunctionPropertyWithExtensionMethod.fsx.err.bsl @@ -0,0 +1,8 @@ +E_CannotShadowFunctionPropertyWithExtensionMethod.fsx (20,5)-(20,10) typecheck error This expression was expected to have type + 'int' +but here has type + ''a -> 'c' +E_CannotShadowFunctionPropertyWithExtensionMethod.fsx (20,5)-(20,10) typecheck error This expression was expected to have type + 'int' +but here has type + ''a -> 'b' \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/E_CannotShadowFunctionPropertyWithExtensionMethod.fsx.il.bsl b/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/E_CannotShadowFunctionPropertyWithExtensionMethod.fsx.il.bsl new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/E_CannotShadowFunctionPropertyWithTypeExtension.fsx b/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/E_CannotShadowFunctionPropertyWithTypeExtension.fsx new file mode 100644 index 00000000000..3bf9617edc7 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/E_CannotShadowFunctionPropertyWithTypeExtension.fsx @@ -0,0 +1,19 @@ +open System.Runtime.CompilerServices + +type Foo() = + member val X : int -> int = (+) 1 with get,set + +module Exts = + type Foo with + member f.X (i: int -> int, j) = f.X i <- j // note: the RFC excludes hiding function typed properties +open Exts +let f = Foo() +f.X 1 +if f.X 0 <> 1 then + System.Environment.Exit 1 +f.X <- (-) 1 + +if f.X 2 <> -1 then + System.Environment.Exit 2 + +f.X((-) 1) // This expression was expected to have type 'int' but here has type ''a -> 'c' \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/E_CannotShadowFunctionPropertyWithTypeExtension.fsx.err.bsl b/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/E_CannotShadowFunctionPropertyWithTypeExtension.fsx.err.bsl new file mode 100644 index 00000000000..7523058fb49 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/E_CannotShadowFunctionPropertyWithTypeExtension.fsx.err.bsl @@ -0,0 +1,13 @@ +E_CannotShadowFunctionPropertyWithTypeExtension.fsx (8,45)-(8,46) typecheck error This expression was expected to have type + 'int' +but here has type + 'int -> int' +E_CannotShadowFunctionPropertyWithTypeExtension.fsx (8,41)-(8,51) typecheck error Invalid mutation of a constant expression. Consider copying the expression to a mutable local, e.g. 'let mutable x = ...'. +E_CannotShadowFunctionPropertyWithTypeExtension.fsx (19,5)-(19,10) typecheck error This expression was expected to have type + 'int' +but here has type + ''a -> 'c' +E_CannotShadowFunctionPropertyWithTypeExtension.fsx (19,5)-(19,10) typecheck error This expression was expected to have type + 'int' +but here has type + ''a -> 'b' \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/E_CannotShadowFunctionPropertyWithTypeExtension.fsx.il.bsl b/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/E_CannotShadowFunctionPropertyWithTypeExtension.fsx.il.bsl new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/E_CannotShadowIndexedPropertyWithExtensionMethod.fsx b/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/E_CannotShadowIndexedPropertyWithExtensionMethod.fsx new file mode 100644 index 00000000000..5c0ace71525 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/E_CannotShadowIndexedPropertyWithExtensionMethod.fsx @@ -0,0 +1,23 @@ +open System.Runtime.CompilerServices + +type Foo() = + let mutable x = 0 + member _.X + with get (i: int) = i + x + and set(i: int) value = x <- i + value + +[] +type FooExt = + [] + static member X (f: Foo, i: int, j) = f.X(i) <- j // note: the RFC excludes hiding indexed properties + +let f = Foo() + +if f.X 0 <> 0 then + System.Environment.Exit 1 +f.X 1 <- 1 +if f.X 0 <> 2 then + System.Environment.Exit 2 +;; +// This expression was expected to have type ... +f.X(1,2) \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/E_CannotShadowIndexedPropertyWithExtensionMethod.fsx.err.bsl b/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/E_CannotShadowIndexedPropertyWithExtensionMethod.fsx.err.bsl new file mode 100644 index 00000000000..a7537411869 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/E_CannotShadowIndexedPropertyWithExtensionMethod.fsx.err.bsl @@ -0,0 +1,4 @@ +E_CannotShadowIndexedPropertyWithExtensionMethod.fsx (23,5)-(23,8) typecheck error This expression was expected to have type + 'int' +but here has type + 'int * int' \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/E_CannotShadowIndexedPropertyWithExtensionMethod.fsx.il.bsl b/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/E_CannotShadowIndexedPropertyWithExtensionMethod.fsx.il.bsl new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/E_CannotShadowIndexedPropertyWithTypeExtension.fsx b/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/E_CannotShadowIndexedPropertyWithTypeExtension.fsx new file mode 100644 index 00000000000..cdf288110d3 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/E_CannotShadowIndexedPropertyWithTypeExtension.fsx @@ -0,0 +1,20 @@ +type Foo() = + let mutable x = 0 + member _.X + with get (i: int) = i + x + and set(i: int) value = x <- i + value + +module Exts = + type Foo with + member f.X (i: int, j) = f.X i <- j // note: the RFC excludes hiding indexed properties +open Exts +let f = Foo() + +if f.X 0 <> 0 then + System.Environment.Exit 1 +f.X 1 <- 1 +if f.X 0 <> 2 then + System.Environment.Exit 2 +;; +// This expression was expected to have type ... +f.X(1,2) \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/E_CannotShadowIndexedPropertyWithTypeExtension.fsx.err.bsl b/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/E_CannotShadowIndexedPropertyWithTypeExtension.fsx.err.bsl new file mode 100644 index 00000000000..ec65c7a754b --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/E_CannotShadowIndexedPropertyWithTypeExtension.fsx.err.bsl @@ -0,0 +1,4 @@ +E_CannotShadowIndexedPropertyWithTypeExtension.fsx (20,5)-(20,8) typecheck error This expression was expected to have type + 'int' +but here has type + 'int * int' \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/E_CannotShadowIndexedPropertyWithTypeExtension.fsx.il.bsl b/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/E_CannotShadowIndexedPropertyWithTypeExtension.fsx.il.bsl new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/ShadowWithExtensionMethod.fsx b/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/ShadowWithExtensionMethod.fsx new file mode 100644 index 00000000000..d12f6aa9007 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/ShadowWithExtensionMethod.fsx @@ -0,0 +1,20 @@ +open System.Runtime.CompilerServices + +type Foo() = + member val X : int = 0 with get,set + +[] +type FooExt = + [] + static member X (f: Foo, i: int) = f.X <- i; f + + +let f = Foo() +f.X(1) +if f.X <> 1 then + System.Environment.Exit 1 + +f.X(1).X(2).X(3) + +if f.X <> 3 then + System.Environment.Exit 2 diff --git a/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/ShadowWithExtensionMethod.fsx.err.bsl b/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/ShadowWithExtensionMethod.fsx.err.bsl new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/ShadowWithExtensionMethod.fsx.il.bsl b/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/ShadowWithExtensionMethod.fsx.il.bsl new file mode 100644 index 00000000000..66c098c1490 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/ShadowWithExtensionMethod.fsx.il.bsl @@ -0,0 +1,228 @@ + + + + + +.assembly extern runtime { } +.assembly extern FSharp.Core { } +.assembly assembly +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32, + int32, + int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ) + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.mresource public FSharpSignatureData.assembly +{ + + +} +.mresource public FSharpOptimizationData.assembly +{ + + +} +.module assembly.dll + +.imagebase {value} +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 +.corflags 0x00000001 + + + + + +.class public abstract auto ansi sealed assembly + extends [runtime]System.Object +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .class auto ansi serializable nested public Foo + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 ) + .field assembly int32 X@ + .method public specialname rtspecialname + instance void .ctor() cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: callvirt instance void [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: pop + IL_0008: ldarg.0 + IL_0009: ldc.i4.0 + IL_000a: stfld int32 assembly/Foo::X@ + IL_000f: ret + } + + .method public hidebysig specialname + instance int32 get_X() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldfld int32 assembly/Foo::X@ + IL_0006: ret + } + + .method public hidebysig specialname + instance void set_X(int32 v) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: stfld int32 assembly/Foo::X@ + IL_0007: ret + } + + .property instance int32 X() + { + .set instance void assembly/Foo::set_X(int32) + .get instance int32 assembly/Foo::get_X() + } + } + + .class auto ansi serializable nested public FooExt + extends [runtime]System.Object + { + .custom instance void [runtime]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 ) + .method public static class assembly/Foo + X(class assembly/Foo f, + int32 i) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: stfld int32 assembly/Foo::X@ + IL_0007: ldarg.0 + IL_0008: ret + } + + } + + .method public specialname static class assembly/Foo + get_f() cil managed + { + + .maxstack 8 + IL_0000: ldsfld class assembly/Foo ''.$assembly$fsx::f@12 + IL_0005: ret + } + + .method assembly specialname static class assembly/Foo + get_f@9() cil managed + { + + .maxstack 8 + IL_0000: ldsfld class assembly/Foo ''.$assembly$fsx::'f@9-1' + IL_0005: ret + } + + .method assembly specialname static class assembly/Foo + 'get_f@9-1'() cil managed + { + + .maxstack 8 + IL_0000: ldsfld class assembly/Foo ''.$assembly$fsx::'f@9-2' + IL_0005: ret + } + + .property class assembly/Foo + f() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 09 00 00 00 00 00 ) + .get class assembly/Foo assembly::get_f() + } + .property class assembly/Foo + f@9() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 09 00 00 00 00 00 ) + .get class assembly/Foo assembly::get_f@9() + } + .property class assembly/Foo + 'f@9-1'() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 09 00 00 00 00 00 ) + .get class assembly/Foo assembly::'get_f@9-1'() + } +} + +.class private abstract auto ansi sealed ''.$assembly$fsx + extends [runtime]System.Object +{ + .field static assembly initonly class assembly/Foo f@12 + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field static assembly initonly class assembly/Foo 'f@9-1' + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field static assembly initonly class assembly/Foo 'f@9-2' + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field static assembly int32 init@ + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) + .method private specialname rtspecialname static + void .cctor() cil managed + { + + .maxstack 4 + IL_0000: newobj instance void assembly/Foo::.ctor() + IL_0005: stsfld class assembly/Foo ''.$assembly$fsx::f@12 + IL_000a: call class assembly/Foo assembly::get_f() + IL_000f: ldc.i4.1 + IL_0010: stfld int32 assembly/Foo::X@ + IL_0015: call class assembly/Foo assembly::get_f() + IL_001a: pop + IL_001b: call class assembly/Foo assembly::get_f() + IL_0020: ldfld int32 assembly/Foo::X@ + IL_0025: ldc.i4.1 + IL_0026: beq.s IL_0030 + + IL_0028: ldc.i4.1 + IL_0029: call void [runtime]System.Environment::Exit(int32) + IL_002e: br.s IL_0030 + + IL_0030: call class assembly/Foo assembly::get_f() + IL_0035: ldc.i4.1 + IL_0036: stfld int32 assembly/Foo::X@ + IL_003b: call class assembly/Foo assembly::get_f() + IL_0040: stsfld class assembly/Foo ''.$assembly$fsx::'f@9-2' + IL_0045: call class assembly/Foo assembly::'get_f@9-1'() + IL_004a: ldc.i4.2 + IL_004b: stfld int32 assembly/Foo::X@ + IL_0050: call class assembly/Foo assembly::'get_f@9-1'() + IL_0055: stsfld class assembly/Foo ''.$assembly$fsx::'f@9-1' + IL_005a: call class assembly/Foo assembly::get_f@9() + IL_005f: ldc.i4.3 + IL_0060: stfld int32 assembly/Foo::X@ + IL_0065: call class assembly/Foo assembly::get_f@9() + IL_006a: pop + IL_006b: call class assembly/Foo assembly::get_f() + IL_0070: ldfld int32 assembly/Foo::X@ + IL_0075: ldc.i4.3 + IL_0076: beq.s IL_0080 + + IL_0078: ldc.i4.2 + IL_0079: call void [runtime]System.Environment::Exit(int32) + IL_007e: br.s IL_0080 + + IL_0080: ret + } + +} + + + + + diff --git a/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/ShadowWithTypeExtension.fsx b/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/ShadowWithTypeExtension.fsx new file mode 100644 index 00000000000..41c5d727327 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/ShadowWithTypeExtension.fsx @@ -0,0 +1,19 @@ +open System.Runtime.CompilerServices + +type Foo() = + member val X : int = 0 with get,set + +module Exts = + type Foo with + member f.X (i: int) = f.X <- i; f + +open Exts +let f = Foo() +f.X(1) +if f.X <> 1 then + System.Environment.Exit 1 + +f.X(1).X(2).X(3) + +if f.X <> 3 then + System.Environment.Exit 2 diff --git a/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/ShadowWithTypeExtension.fsx.err.bsl b/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/ShadowWithTypeExtension.fsx.err.bsl new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/ShadowWithTypeExtension.fsx.il.bsl b/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/ShadowWithTypeExtension.fsx.il.bsl new file mode 100644 index 00000000000..b9883181ec6 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/ShadowWithTypeExtension.fsx.il.bsl @@ -0,0 +1,227 @@ + + + + + +.assembly extern runtime { } +.assembly extern FSharp.Core { } +.assembly assembly +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32, + int32, + int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ) + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.mresource public FSharpSignatureData.assembly +{ + + +} +.mresource public FSharpOptimizationData.assembly +{ + + +} +.module assembly.dll + +.imagebase {value} +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 +.corflags 0x00000001 + + + + + +.class public abstract auto ansi sealed assembly + extends [runtime]System.Object +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .class auto ansi serializable nested public Foo + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 ) + .field assembly int32 X@ + .method public specialname rtspecialname + instance void .ctor() cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: callvirt instance void [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: pop + IL_0008: ldarg.0 + IL_0009: ldc.i4.0 + IL_000a: stfld int32 assembly/Foo::X@ + IL_000f: ret + } + + .method public hidebysig specialname + instance int32 get_X() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldfld int32 assembly/Foo::X@ + IL_0006: ret + } + + .method public hidebysig specialname + instance void set_X(int32 v) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: stfld int32 assembly/Foo::X@ + IL_0007: ret + } + + .property instance int32 X() + { + .set instance void assembly/Foo::set_X(int32) + .get instance int32 assembly/Foo::get_X() + } + } + + .class abstract auto ansi sealed nested public Exts + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .method public static class assembly/Foo + Foo.X(class assembly/Foo f, + int32 i) cil managed + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: stfld int32 assembly/Foo::X@ + IL_0007: ldarg.0 + IL_0008: ret + } + + } + + .method public specialname static class assembly/Foo + get_f() cil managed + { + + .maxstack 8 + IL_0000: ldsfld class assembly/Foo ''.$assembly$fsx::f@11 + IL_0005: ret + } + + .method assembly specialname static class assembly/Foo + get_f@8() cil managed + { + + .maxstack 8 + IL_0000: ldsfld class assembly/Foo ''.$assembly$fsx::'f@8-1' + IL_0005: ret + } + + .method assembly specialname static class assembly/Foo + 'get_f@8-1'() cil managed + { + + .maxstack 8 + IL_0000: ldsfld class assembly/Foo ''.$assembly$fsx::'f@8-2' + IL_0005: ret + } + + .property class assembly/Foo + f() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 09 00 00 00 00 00 ) + .get class assembly/Foo assembly::get_f() + } + .property class assembly/Foo + f@8() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 09 00 00 00 00 00 ) + .get class assembly/Foo assembly::get_f@8() + } + .property class assembly/Foo + 'f@8-1'() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 09 00 00 00 00 00 ) + .get class assembly/Foo assembly::'get_f@8-1'() + } +} + +.class private abstract auto ansi sealed ''.$assembly$fsx + extends [runtime]System.Object +{ + .field static assembly initonly class assembly/Foo f@11 + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field static assembly initonly class assembly/Foo 'f@8-1' + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field static assembly initonly class assembly/Foo 'f@8-2' + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field static assembly int32 init@ + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) + .method private specialname rtspecialname static + void .cctor() cil managed + { + + .maxstack 4 + IL_0000: newobj instance void assembly/Foo::.ctor() + IL_0005: stsfld class assembly/Foo ''.$assembly$fsx::f@11 + IL_000a: call class assembly/Foo assembly::get_f() + IL_000f: ldc.i4.1 + IL_0010: stfld int32 assembly/Foo::X@ + IL_0015: call class assembly/Foo assembly::get_f() + IL_001a: pop + IL_001b: call class assembly/Foo assembly::get_f() + IL_0020: ldfld int32 assembly/Foo::X@ + IL_0025: ldc.i4.1 + IL_0026: beq.s IL_0030 + + IL_0028: ldc.i4.1 + IL_0029: call void [runtime]System.Environment::Exit(int32) + IL_002e: br.s IL_0030 + + IL_0030: call class assembly/Foo assembly::get_f() + IL_0035: ldc.i4.1 + IL_0036: stfld int32 assembly/Foo::X@ + IL_003b: call class assembly/Foo assembly::get_f() + IL_0040: stsfld class assembly/Foo ''.$assembly$fsx::'f@8-2' + IL_0045: call class assembly/Foo assembly::'get_f@8-1'() + IL_004a: ldc.i4.2 + IL_004b: stfld int32 assembly/Foo::X@ + IL_0050: call class assembly/Foo assembly::'get_f@8-1'() + IL_0055: stsfld class assembly/Foo ''.$assembly$fsx::'f@8-1' + IL_005a: call class assembly/Foo assembly::get_f@8() + IL_005f: ldc.i4.3 + IL_0060: stfld int32 assembly/Foo::X@ + IL_0065: call class assembly/Foo assembly::get_f@8() + IL_006a: pop + IL_006b: call class assembly/Foo assembly::get_f() + IL_0070: ldfld int32 assembly/Foo::X@ + IL_0075: ldc.i4.3 + IL_0076: beq.s IL_0080 + + IL_0078: ldc.i4.2 + IL_0079: call void [runtime]System.Environment::Exit(int32) + IL_007e: br.s IL_0080 + + IL_0080: ret + } + +} + + + + + diff --git a/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowingTests.fs b/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowingTests.fs new file mode 100644 index 00000000000..c5db46dd29e --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowingTests.fs @@ -0,0 +1,61 @@ +module FSharp.Compiler.ComponentTests.TypeChecks.TypeExtensions.PropertyShadowingTests +open Xunit +open FSharp.Test +open FSharp.Test.Compiler + +let [] folder = __SOURCE_DIRECTORY__ + "/PropertyShadowing" + +[] +let ``can hide property`` compilation = + compilation + |> asFsx + |> withOptions ["--langversion:preview"] + |> verifyBaselines + |> compileAndRun + |> shouldSucceed + + +[] +let ``cannot hide property`` compilation = + compilation + |> asFsx + |> withOptions ["--langversion:preview"] + |> verifyBaselines + |> compile + |> shouldFail + + +[] +let ``cannot hide property v7.0`` compilation = + compilation + |> asFsx + |> withOptions ["--langversion:7.0"] + |> verifyBaselines + |> compile + |> shouldFail + diff --git a/tests/FSharp.Test.Utilities/Compiler.fs b/tests/FSharp.Test.Utilities/Compiler.fs index aabefaf4b35..fcfa8ee0666 100644 --- a/tests/FSharp.Test.Utilities/Compiler.fs +++ b/tests/FSharp.Test.Utilities/Compiler.fs @@ -945,7 +945,14 @@ module rec Compiler = match s.OutputPath with | None -> failwith "Compilation didn't produce any output. Unable to run. (Did you forget to set output type to Exe?)" | Some p -> - let (exitCode, output, errors) = CompilerAssert.ExecuteAndReturnResult (p, s.Dependencies, false) + let isFsx = + match s.Compilation with + | FS fs -> + match fs.Source with + | SourceCodeFileKind.Fsx _ -> true + | _ -> false + | _ -> false + let exitCode, output, errors = CompilerAssert.ExecuteAndReturnResult (p, isFsx, s.Dependencies, false) printfn "---------output-------\n%s\n-------" output printfn "---------errors-------\n%s\n-------" errors let executionResult = { s with Output = Some (ExecutionOutput { ExitCode = exitCode; StdOut = output; StdErr = errors }) } @@ -1075,10 +1082,37 @@ module rec Compiler = | _ -> failwith "FSI running only supports F#." + let convenienceBaselineInstructions baseline expected actual = + $"""to update baseline: +$ cp {baseline.FilePath} {baseline.BslSource} +to compare baseline: +$ code --diff {baseline.FilePath} {baseline.BslSource} +Expected: +{expected} +Actual: +{actual}""" + let updateBaseline () = + snd (Int32.TryParse(Environment.GetEnvironmentVariable("TEST_UPDATE_BSL"))) <> 0 + let updateBaseLineIfEnvironmentSaysSo baseline = + if updateBaseline () then + if FileSystem.FileExistsShim baseline.FilePath then + FileSystem.CopyShim(baseline.FilePath, baseline.BslSource, true) + + let assertBaseline expected actual baseline fOnFail = + if expected <> actual then + fOnFail() + updateBaseLineIfEnvironmentSaysSo baseline + createBaselineErrors baseline actual + Assert.AreEqual(expected, actual, convenienceBaselineInstructions baseline expected actual) + elif FileSystem.FileExistsShim baseline.FilePath then + FileSystem.FileDeleteShim baseline.FilePath + + let private createBaselineErrors (baselineFile: BaselineFile) (actualErrors: string) : unit = - FileSystem.OpenFileForWriteShim(baselineFile.FilePath + ".err").Write(actualErrors) + printfn $"creating baseline error file for convenience: {baselineFile.FilePath}, expected: {baselineFile.BslSource}" + FileSystem.OpenFileForWriteShim(baselineFile.FilePath).Write(actualErrors) - let private verifyFSBaseline (fs) : unit = + let private verifyFSBaseline fs : unit = match fs.Baseline with | None -> failwith "Baseline was not provided." | Some bsl -> @@ -1089,16 +1123,21 @@ module rec Compiler = let typecheckDiagnostics = fs |> typecheckFSharpSourceAndReturnErrors - let errorsActual = (typecheckDiagnostics |> Array.map (sprintf "%A") |> String.concat "\n").Replace("\r\n","\n") + let errorsActual = + (typecheckDiagnostics + |> Array.map (sprintf "%A") + |> String.concat "\n" + ).Replace("\r\n","\n") if errorsExpectedBaseLine <> errorsActual then fs.CreateOutputDirectory() createBaselineErrors bsl.FSBaseline errorsActual + updateBaseLineIfEnvironmentSaysSo bsl.FSBaseline + let errorMsg = (convenienceBaselineInstructions bsl.FSBaseline errorsExpectedBaseLine errorsActual) + Assert.AreEqual(errorsExpectedBaseLine, errorsActual, errorMsg) elif FileSystem.FileExistsShim(bsl.FSBaseline.FilePath) then FileSystem.FileDeleteShim(bsl.FSBaseline.FilePath) - Assert.AreEqual(errorsExpectedBaseLine, errorsActual, $"\nExpected:\n{errorsExpectedBaseLine}\nActual:\n{errorsActual}") - /// Check the typechecker output against the baseline, if invoked with empty baseline, will expect no error/warnings output. let verifyBaseline (cUnit: CompilationUnit) : CompilationUnit = match cUnit with @@ -1121,37 +1160,42 @@ module rec Compiler = let verifyILBinary (il: string list) (dll: string)= ILChecker.checkIL dll il - let private verifyFSILBaseline (baseline: Baseline option) (result: CompilationOutput) : unit = - match baseline with - | None -> failwith "Baseline was not provided." - | Some bsl -> - match result.OutputPath with - | None -> failwith "Operation didn't produce any output!" - | Some p -> - let expectedIL = - match bsl.ILBaseline.Content with - | Some b -> b - | None -> String.Empty - let (success, errorMsg, actualIL) = ILChecker.verifyILAndReturnActual p expectedIL - - if not success then - // Failed try update baselines if required - // If we are here then the il file has been produced we can write it back to the baseline location - // if the environment variable TEST_UPDATE_BSL has been set - if snd (Int32.TryParse(Environment.GetEnvironmentVariable("TEST_UPDATE_BSL"))) <> 0 then - match baseline with - | Some baseline -> System.IO.File.Copy(baseline.ILBaseline.FilePath, baseline.ILBaseline.BslSource, true) - | None -> () - - createBaselineErrors bsl.ILBaseline actualIL - Assert.Fail(errorMsg) + let private verifyFSILBaseline (baseline: Baseline) (result: CompilationOutput) : unit = + match result.OutputPath with + | None -> failwith "Operation didn't produce any output!" + | Some p -> + let expectedIL = + match baseline.ILBaseline.Content with + | Some b -> b + | None -> String.Empty + let success, errorMsg, actualIL = ILChecker.verifyILAndReturnActual p expectedIL + + if not success then + // Failed try update baselines if required + // If we are here then the il file has been produced we can write it back to the baseline location + // if the environment variable TEST_UPDATE_BSL has been set + updateBaseLineIfEnvironmentSaysSo baseline.ILBaseline + createBaselineErrors baseline.ILBaseline actualIL + let errorMsg = (convenienceBaselineInstructions baseline.ILBaseline expectedIL actualIL) + errorMsg + Assert.Fail(errorMsg) let verifyILBaseline (cUnit: CompilationUnit) : CompilationUnit = match cUnit with | FS fs -> - match fs |> compileFSharp with - | CompilationResult.Failure a -> failwith $"Build failure: {a}" - | CompilationResult.Success s -> verifyFSILBaseline fs.Baseline s + match fs |> compileFSharp, fs.Baseline with + | CompilationResult.Failure a, Some baseline -> + match baseline.ILBaseline.Content with + | Some "" -> () + | Some il -> + failwith $"Build failure: {a} while expected il\n{il}" + | None -> + if not (FileSystem.FileExistsShim baseline.ILBaseline.BslSource) && updateBaseline () then + File.WriteAllText(baseline.ILBaseline.BslSource, "") + else + failwith $"Build failure empty baseline at {baseline.ILBaseline.BslSource}: {a}" + | CompilationResult.Success s, Some baseline -> verifyFSILBaseline baseline s + | _, None -> + failwithf $"Baseline was not provided." | _ -> failwith "Baseline tests are only supported for F#." cUnit diff --git a/tests/FSharp.Test.Utilities/CompilerAssert.fs b/tests/FSharp.Test.Utilities/CompilerAssert.fs index a0eea96e1d4..e406dc5adbc 100644 --- a/tests/FSharp.Test.Utilities/CompilerAssert.fs +++ b/tests/FSharp.Test.Utilities/CompilerAssert.fs @@ -261,18 +261,27 @@ module rec CompilerAssertHelpers = let checker = FSharpChecker.Create(suggestNamesForErrors=true) // Unlike C# whose entrypoint is always string[] F# can make an entrypoint with 0 args, or with an array of string[] - let mkDefaultArgs (entryPoint:MethodInfo) : obj[] = [| + let mkDefaultArgs (entryPoint:MethodBase) : obj[] = [| if entryPoint.GetParameters().Length = 1 then yield Array.empty |] - let executeAssemblyEntryPoint (asm: Assembly) = - let entryPoint = asm.EntryPoint + let executeAssemblyEntryPoint (asm: Assembly) isFsx = + let entryPoint : MethodBase = asm.EntryPoint + let entryPoint = + if isNull entryPoint && isFsx then + // lookup the last static constructor + // of the assembly types, which should match + // the equivalent of a .fsx entry point + let moduleInitType = asm.GetTypes() |> Array.last + moduleInitType.GetConstructors(BindingFlags.Static ||| BindingFlags.NonPublic).[0] :> MethodBase + else + entryPoint let args = mkDefaultArgs entryPoint captureConsoleOutputs (fun () -> entryPoint.Invoke(Unchecked.defaultof, args) |> ignore) #if NETCOREAPP - let executeBuiltApp assembly deps = + let executeBuiltApp assembly deps isFsx = let ctxt = AssemblyLoadContext("ContextName", true) try ctxt.add_Resolving(fun ctxt name -> @@ -281,7 +290,7 @@ module rec CompilerAssertHelpers = |> Option.map ctxt.LoadFromAssemblyPath |> Option.defaultValue null) - ctxt.LoadFromAssemblyPath assembly |> executeAssemblyEntryPoint + executeAssemblyEntryPoint (ctxt.LoadFromAssemblyPath assembly) isFsx finally ctxt.Unload() #else @@ -577,8 +586,8 @@ module rec CompilerAssertHelpers = succeeded, stdout.ToString(), stderr.ToString(), exn - let executeBuiltAppAndReturnResult (outputFilePath: string) (deps: string list) : (int * string * string) = - let succeeded, stdout, stderr, _ = executeBuiltApp outputFilePath deps + let executeBuiltAppAndReturnResult (outputFilePath: string) (deps: string list) isFsx : (int * string * string) = + let succeeded, stdout, stderr, _ = executeBuiltApp outputFilePath deps isFsx let exitCode = if succeeded then 0 else -1 exitCode, stdout, stderr @@ -681,10 +690,10 @@ Updated automatically, please check diffs in your pull request, changes must be static member CompileRaw(cmpl: Compilation, ?ignoreWarnings) = returnCompilation cmpl (defaultArg ignoreWarnings false) - static member ExecuteAndReturnResult (outputFilePath: string, deps: string list, newProcess: bool) = + static member ExecuteAndReturnResult (outputFilePath: string, isFsx: bool, deps: string list, newProcess: bool) = // If we execute in-process (true by default), then the only way of getting STDOUT is to redirect it to SB, and STDERR is from catching an exception. if not newProcess then - executeBuiltAppAndReturnResult outputFilePath deps + executeBuiltAppAndReturnResult outputFilePath deps isFsx else executeBuiltAppNewProcessAndReturnResult outputFilePath @@ -710,7 +719,7 @@ Updated automatically, please check diffs in your pull request, changes must be Assert.Fail errors onOutput output else - let _succeeded, _stdout, _stderr, exn = executeBuiltApp outputFilePath deps + let _succeeded, _stdout, _stderr, exn = executeBuiltApp outputFilePath deps false exn |> Option.iter raise) static member ExecutionHasOutput(cmpl: Compilation, expectedOutput: string) = diff --git a/tests/FSharp.Test.Utilities/DirectoryAttribute.fs b/tests/FSharp.Test.Utilities/DirectoryAttribute.fs index fbb40b70b17..01999873a84 100644 --- a/tests/FSharp.Test.Utilities/DirectoryAttribute.fs +++ b/tests/FSharp.Test.Utilities/DirectoryAttribute.fs @@ -35,7 +35,8 @@ type DirectoryAttribute(dir: string) = // if there are multiple files being processed, add extra directory for each test to avoid reference file conflicts let extraDirectory = if multipleFiles then - filename.Substring(0, filename.Length - 3) // remove .fs + let extension = Path.GetExtension(filename) + filename.Substring(0, filename.Length - extension.Length) // remove .fs/the extension |> normalizeName else "" let outputDirectory = outputDirectory methodName extraDirectory @@ -78,7 +79,7 @@ type DirectoryAttribute(dir: string) = | None -> sourceFilePath + baselineSuffix + ".il.bsl" let fsOutFilePath = normalizePathSeparator (Path.ChangeExtension(outputDirectoryPath ++ filename, ".err")) - let ilOutFilePath = normalizePathSeparator ( Path.ChangeExtension(outputDirectoryPath ++ filename, ".il")) + let ilOutFilePath = normalizePathSeparator (Path.ChangeExtension(outputDirectoryPath ++ filename, ".il.err")) let fsBslSource = readFileOrDefault fsBslFilePath let ilBslSource = readFileOrDefault ilBslFilePath @@ -88,8 +89,8 @@ type DirectoryAttribute(dir: string) = Some { SourceFilename = Some sourceFilePath - FSBaseline = { FilePath = fsOutFilePath; BslSource=fsBslFilePath; Content = fsBslSource } - ILBaseline = { FilePath = ilOutFilePath; BslSource=ilBslFilePath ; Content = ilBslSource } + FSBaseline = { FilePath = fsOutFilePath; BslSource = fsBslFilePath; Content = fsBslSource } + ILBaseline = { FilePath = ilOutFilePath; BslSource = ilBslFilePath; Content = ilBslSource } } Options = [] OutputType = Library @@ -98,7 +99,7 @@ type DirectoryAttribute(dir: string) = References = [] OutputDirectory = outputDirectory TargetFramework = TargetFramework.Current - StaticLink = false + StaticLink = false } |> FS new([] dirs: string[]) = DirectoryAttribute(Path.Combine(dirs) : string) diff --git a/tests/FSharp.Test.Utilities/ILChecker.fs b/tests/FSharp.Test.Utilities/ILChecker.fs index 58ba5e1b7fe..8164f876a52 100644 --- a/tests/FSharp.Test.Utilities/ILChecker.fs +++ b/tests/FSharp.Test.Utilities/ILChecker.fs @@ -104,48 +104,46 @@ module ILChecker = |> Array.skipWhile(String.IsNullOrWhiteSpace) |> Array.rev - expectedIL - |> List.map (fun (ilCode: string) -> ilCode.Trim()) - |> List.iter (fun (ilCode: string) -> - let expectedLines = ilCode |> normalizeILText (Some assemblyName) |> prepareLines - - if expectedLines.Length = 0 then - errorMsgOpt <- Some("ExpectedLines length invalid: 0") - else - let startIndex = - let index = actualIL.IndexOf(expectedLines[0].Trim()) - if index > 0 then - index - else - 0 - let actualLines = actualIL.Substring(startIndex) |> prepareLines - - let errors = ResizeArray() - if actualLines.Length < expectedLines.Length then - let msg = $"\nExpected at least %d{expectedLines.Length} lines but found only %d{actualLines.Length}\n" - errorMsgOpt <- Some(msg + "\nExpected:\n" + ilCode + "\n") + match expectedIL with + | [] -> errorMsgOpt <- Some "No Expected IL" + | expectedIL -> + expectedIL + |> List.map (fun (ilCode: string) -> ilCode.Trim()) + |> List.iter (fun (ilCode: string) -> + let expectedLines = ilCode |> normalizeILText (Some assemblyName) |> prepareLines + + if expectedLines.Length = 0 then + errorMsgOpt <- Some("ExpectedLines length invalid: 0") else - for i = 0 to expectedLines.Length - 1 do - let expected = expectedLines[i].Trim() - let actual = actualLines[i].Trim() - if expected <> actual then - errors.Add $"\n==\nName: '%s{actualLines[0]}'\n\nExpected:\t %s{expected}\nActual:\t\t %s{actual}\n==" - - if errors.Count > 0 then - let msg = String.concat "\n" errors + "\n\n\Expected:\n" + ilCode + "\n" - errorMsgOpt <- Some(msg + "\n\n\nActual:\n" + String.Join("\n", actualLines, 0, expectedLines.Length)) - ) - - if expectedIL.Length = 0 then - errorMsgOpt <- Some ("No Expected IL") + let startIndex = + let index = actualIL.IndexOf(expectedLines[0].Trim()) + if index > 0 then + index + else + 0 + let actualLines = actualIL.Substring(startIndex) |> prepareLines + + let errors = ResizeArray() + if actualLines.Length < expectedLines.Length then + let msg = $"\nExpected at least %d{expectedLines.Length} lines but found only %d{actualLines.Length}\n" + errorMsgOpt <- Some(msg + "\nExpected:\n" + ilCode + "\n") + else + for i = 0 to expectedLines.Length - 1 do + let expected = expectedLines[i].Trim() + let actual = actualLines[i].Trim() + if expected <> actual then + errors.Add $"\n==\nName: '%s{actualLines[0]}'\n\nExpected:\t %s{expected}\nActual:\t\t %s{actual}\n==" - match errorMsgOpt with - | Some(msg) -> errorMsgOpt <- Some(msg + "\n\n\nEntire actual:\n" + actualIL) - | _ -> () + if errors.Count > 0 then + let msg = String.concat "\n" errors + "\n\n\Expected:\n" + ilCode + "\n" + errorMsgOpt <- Some(msg + "\n\n\nActual:\n" + String.Join("\n", actualLines, 0, expectedLines.Length)) + ) match errorMsgOpt with - | Some(errorMsg) -> (false, errorMsg, actualIL) - | _ -> (true, String.Empty, String.Empty) + | Some msg -> + let msg = msg + "\n\n\nEntire actual:\n" + actualIL + (false, msg, actualIL) + | _ -> (true, String.Empty, actualIL) let private checkILPrim ildasmArgs dllFilePath = let actualIL = generateIL dllFilePath ildasmArgs From 4ab54579b2df21d23ff94e3c1af7a045ab03cd76 Mon Sep 17 00:00:00 2001 From: Gauthier Segay Date: Thu, 5 Oct 2023 08:12:55 +0200 Subject: [PATCH 05/29] Update LanguageFeatures.fs --- src/Compiler/Facilities/LanguageFeatures.fs | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/Compiler/Facilities/LanguageFeatures.fs b/src/Compiler/Facilities/LanguageFeatures.fs index ee5b951aea4..e44806661ea 100644 --- a/src/Compiler/Facilities/LanguageFeatures.fs +++ b/src/Compiler/Facilities/LanguageFeatures.fs @@ -186,9 +186,6 @@ type LanguageVersion(versionText) = // F# preview LanguageFeature.FromEndSlicing, previewVersion LanguageFeature.UnmanagedConstraintCsharpInterop, previewVersion - LanguageFeature.WhileBang, previewVersion - LanguageFeature.ExtendedFixedBindings, previewVersion - LanguageFeature.PreferStringGetPinnableReference, previewVersion // F# preview next LanguageFeature.PreferExtensionMethodOverPlainProperty, previewVersion From 3ff50f74e826f9792e96372df3de6b287f495a18 Mon Sep 17 00:00:00 2001 From: Gauthier Segay Date: Thu, 5 Oct 2023 12:41:36 +0200 Subject: [PATCH 06/29] minimize diff --- src/Compiler/Checking/CheckExpressions.fs | 1 - src/Compiler/Checking/NameResolution.fs | 3 ++- src/Compiler/Service/ServiceDeclarationLists.fs | 3 ++- src/Compiler/Symbols/SymbolHelpers.fs | 6 ++++-- 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/Compiler/Checking/CheckExpressions.fs b/src/Compiler/Checking/CheckExpressions.fs index a4dba8306d7..b09a3e70b69 100644 --- a/src/Compiler/Checking/CheckExpressions.fs +++ b/src/Compiler/Checking/CheckExpressions.fs @@ -8373,7 +8373,6 @@ and TcItemThen (cenv: cenv) (overallTy: OverallTy) env tpenv (tinstEnclosing, it | Item.Types(_, []) -> error(Error(FSComp.SR.tcLookupMayNotBeUsedHere(), mItem)) - /// Type check the application of a union case. Also used to cover constructions of F# exception values, and /// applications of active pattern result labels. // diff --git a/src/Compiler/Checking/NameResolution.fs b/src/Compiler/Checking/NameResolution.fs index 0d18a771762..4a256f483b9 100644 --- a/src/Compiler/Checking/NameResolution.fs +++ b/src/Compiler/Checking/NameResolution.fs @@ -2226,6 +2226,7 @@ let CheckAllTyparsInferrable amap m item = (freeInType CollectTyparsNoCaching (minfo.GetFSharpReturnType(amap, m, fminst)))) let free = Zset.diff freeInDeclaringType.FreeTypars freeInArgsAndRetType.FreeTypars free.IsEmpty) + | Item.Trait _ | Item.CtorGroup _ | Item.FakeInterfaceCtor _ @@ -2614,7 +2615,7 @@ let rec ResolveLongIdentInTypePrim (ncenv: NameResolver) nenv lookupKind (resInf | Some (PropertyItem psets) when isLookUpExpr -> let pinfos = psets |> ExcludeHiddenOfPropInfos g ncenv.amap m - + // fold the available extension members into the overload resolution let extensionPropInfos = ExtensionPropInfosOfTypeInScope ResultCollectionSettings.AllResults ncenv.InfoReader nenv optFilter isInstanceFilter ad m ty diff --git a/src/Compiler/Service/ServiceDeclarationLists.fs b/src/Compiler/Service/ServiceDeclarationLists.fs index 3b3963afbff..563352045a0 100644 --- a/src/Compiler/Service/ServiceDeclarationLists.fs +++ b/src/Compiler/Service/ServiceDeclarationLists.fs @@ -878,6 +878,7 @@ module internal DescriptionListsImpl = | Item.Property(info = []) -> [], emptyL + /// Compute the index of the VS glyph shown with an item in the Intellisense menu let GlyphOfItem(denv, item) : FSharpGlyph = /// Find the glyph for the given representation. @@ -976,6 +977,7 @@ module internal DescriptionListsImpl = FSharpGlyph.Error ) + /// Select the items that participate in a MethodGroup. let SelectMethodGroupItems g m item = #if NO_TYPEPROVIDERS @@ -1001,7 +1003,6 @@ module internal DescriptionListsImpl = | Item.Property(info = pinfos) -> let pinfo = List.head pinfos if pinfo.IsIndexer then [item] else [] - #if !NO_TYPEPROVIDERS | ItemIsWithStaticArguments m g _ -> // we pretend that provided-types-with-static-args are method-like in order to get ParamInfo for them diff --git a/src/Compiler/Symbols/SymbolHelpers.fs b/src/Compiler/Symbols/SymbolHelpers.fs index 564453e5995..f5ce5d312ca 100644 --- a/src/Compiler/Symbols/SymbolHelpers.fs +++ b/src/Compiler/Symbols/SymbolHelpers.fs @@ -338,6 +338,7 @@ module internal SymbolHelpers = | Item.UnqualifiedType [] | Item.Types(_, []) -> FSharpXmlDoc.None + |> GetXmlDocFromLoader infoReader /// Produce an XmlComment with a signature or raw text, given the F# comment and the item let GetXmlCommentForItemAux (xmlDoc: XmlDoc option) (infoReader: InfoReader) m d = @@ -404,7 +405,8 @@ module internal SymbolHelpers = | Item.Types(_, []) | Item.ModuleOrNamespaces [] -> false //| _ -> false - + + member x.Equals(item1, item2) = // This may explore assemblies that are not in the reference set. // In this case just bail out and assume items are not equal @@ -508,7 +510,6 @@ module internal SymbolHelpers = | Item.Types _ | Item.DelegateCtor _ | Item.ModuleOrNamespaces [] -> 0 - ) } /// Remove all duplicate items @@ -717,6 +718,7 @@ module internal SymbolHelpers = | Item.DelegateCtor _ -> //| _ -> GetXmlCommentForItemAux None infoReader m item + |> GetXmlDocFromLoader infoReader let IsAttribute (infoReader: InfoReader) item = From 6ca457679cde0e439054a56bd5fa09eb9f00ab0f Mon Sep 17 00:00:00 2001 From: Gauthier Segay Date: Sat, 7 Oct 2023 19:28:55 +0200 Subject: [PATCH 07/29] do not break chained calls when there is an extension method with same name defined. --- src/Compiler/Checking/NameResolution.fs | 60 +++-- .../ShadowingAndStillOkWithChainedCalls.fsx | 27 ++ ...wingAndStillOkWithChainedCalls.fsx.err.bsl | 0 ...owingAndStillOkWithChainedCalls.fsx.il.bsl | 255 ++++++++++++++++++ .../TypeExtensions/PropertyShadowingTests.fs | 1 + 5 files changed, 315 insertions(+), 28 deletions(-) create mode 100644 tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/ShadowingAndStillOkWithChainedCalls.fsx create mode 100644 tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/ShadowingAndStillOkWithChainedCalls.fsx.err.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/ShadowingAndStillOkWithChainedCalls.fsx.il.bsl diff --git a/src/Compiler/Checking/NameResolution.fs b/src/Compiler/Checking/NameResolution.fs index 4a256f483b9..bc658c6b89a 100644 --- a/src/Compiler/Checking/NameResolution.fs +++ b/src/Compiler/Checking/NameResolution.fs @@ -2623,36 +2623,40 @@ let rec ResolveLongIdentInTypePrim (ncenv: NameResolver) nenv lookupKind (resInf // since later on this logic is used when giving preference to intrinsic definitions match DecodeFSharpEvent (pinfos@extensionPropInfos) ad g ncenv m with | Some x -> - match maybeAppliedArgExpr, g.langVersion.SupportsFeature LanguageFeature.PreferExtensionMethodOverPlainProperty with - | None, _ - | _, false -> + if + not (g.langVersion.SupportsFeature LanguageFeature.PreferExtensionMethodOverPlainProperty) + || not (List.isEmpty rest) // if not empty, it is .X.Y... + then success [resInfo, x, rest] - | Some _argExpr, true -> - // RFC 1137 prefer extension method when ... - - let ignoreProperty (p: PropInfo) = - // do not hide properties if: - // * is indexed property - // * is function type - if p.IsIndexer then - true - else - match p.GetPropertyType(ncenv.amap, m) with - | TType_var(typar={typar_solution = Some (TType_fun _) }) -> + else + match maybeAppliedArgExpr with + | None -> success [resInfo, x, rest] + | Some _argExpr -> + // RFC 1137 prefer extension method when ... + + let ignoreProperty (p: PropInfo) = + // do not hide properties if: + // * is indexed property + // * is function type + if p.IsIndexer then true - | _ -> false - - match x with - | Item.Property(info=ps) when ps |> List.exists ignoreProperty -> - success [resInfo, x, rest] - | _ -> - // lookup in-scope extension methods - // to keep in sync with the same expression in `| Some(MethodItem msets) when isLookupExpr` below - match ExtensionMethInfosOfTypeInScope ResultCollectionSettings.AllResults ncenv.InfoReader nenv optFilter isInstanceFilter m ty with - | [] -> success [resInfo, x, rest] - | methods -> - let extensionMethods = Item.MakeMethGroup(nm, methods) - success ((resInfo,extensionMethods,rest)::[resInfo,x,rest]) + else + match p.GetPropertyType(ncenv.amap, m) with + | TType_var(typar={typar_solution = Some (TType_fun _) }) -> + true + | _ -> false + + match x with + | Item.Property(info=ps) when ps |> List.exists ignoreProperty -> + success [resInfo, x, rest] + | _ -> + // lookup in-scope extension methods + // to keep in sync with the same expression in `| Some(MethodItem msets) when isLookupExpr` below + match ExtensionMethInfosOfTypeInScope ResultCollectionSettings.AllResults ncenv.InfoReader nenv optFilter isInstanceFilter m ty with + | [] -> success [resInfo, x, rest] + | methods -> + let extensionMethods = Item.MakeMethGroup(nm, methods) + success ((resInfo,extensionMethods,rest)::[resInfo,x,rest]) | None -> // todo: consider if we should check extension method, but we'd probably won't have matched // `Some(PropertyItem psets) when isLookUpExpr` in the first place. diff --git a/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/ShadowingAndStillOkWithChainedCalls.fsx b/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/ShadowingAndStillOkWithChainedCalls.fsx new file mode 100644 index 00000000000..8e9ffd219a9 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/ShadowingAndStillOkWithChainedCalls.fsx @@ -0,0 +1,27 @@ +open System.Runtime.CompilerServices + +type Foo() = + member val X : int = 0 with get,set + +[] +type FooExt = + [] + static member X (f: Foo, i: int) = f.X <- i; f + [] + static member X (f: Foo, i: string) = + f.X <- + let x = f.X + let v = x.ToString() + v.Length + i.Length + f + + +let f = Foo() +f.X(1) +if f.X <> 1 then + System.Environment.Exit 1 + +f.X(1).X(2).X(3) + +if f.X <> 3 then + System.Environment.Exit 2 diff --git a/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/ShadowingAndStillOkWithChainedCalls.fsx.err.bsl b/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/ShadowingAndStillOkWithChainedCalls.fsx.err.bsl new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/ShadowingAndStillOkWithChainedCalls.fsx.il.bsl b/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/ShadowingAndStillOkWithChainedCalls.fsx.il.bsl new file mode 100644 index 00000000000..907ff8c1523 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/ShadowingAndStillOkWithChainedCalls.fsx.il.bsl @@ -0,0 +1,255 @@ + + + + + +.assembly extern runtime { } +.assembly extern FSharp.Core { } +.assembly assembly +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32, + int32, + int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ) + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.mresource public FSharpSignatureData.assembly +{ + + +} +.mresource public FSharpOptimizationData.assembly +{ + + +} +.module assembly.dll + +.imagebase {value} +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 +.corflags 0x00000001 + + + + + +.class public abstract auto ansi sealed assembly + extends [runtime]System.Object +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .class auto ansi serializable nested public Foo + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 ) + .field assembly int32 X@ + .method public specialname rtspecialname + instance void .ctor() cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: callvirt instance void [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: pop + IL_0008: ldarg.0 + IL_0009: ldc.i4.0 + IL_000a: stfld int32 assembly/Foo::X@ + IL_000f: ret + } + + .method public hidebysig specialname + instance int32 get_X() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldfld int32 assembly/Foo::X@ + IL_0006: ret + } + + .method public hidebysig specialname + instance void set_X(int32 v) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: stfld int32 assembly/Foo::X@ + IL_0007: ret + } + + .property instance int32 X() + { + .set instance void assembly/Foo::set_X(int32) + .get instance int32 assembly/Foo::get_X() + } + } + + .class auto ansi serializable nested public FooExt + extends [runtime]System.Object + { + .custom instance void [runtime]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 ) + .method public static class assembly/Foo + X(class assembly/Foo f, + int32 i) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.1 + IL_0002: stfld int32 assembly/Foo::X@ + IL_0007: ldarg.0 + IL_0008: ret + } + + .method public static class assembly/Foo + X(class assembly/Foo f, + string i) cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 5 + .locals init (int32 V_0, + string V_1) + IL_0000: ldarg.0 + IL_0001: ldarg.0 + IL_0002: ldfld int32 assembly/Foo::X@ + IL_0007: stloc.0 + IL_0008: ldloca.s V_0 + IL_000a: constrained. [runtime]System.Int32 + IL_0010: callvirt instance string [runtime]System.Object::ToString() + IL_0015: stloc.1 + IL_0016: ldloc.1 + IL_0017: callvirt instance int32 [runtime]System.String::get_Length() + IL_001c: ldarg.1 + IL_001d: callvirt instance int32 [runtime]System.String::get_Length() + IL_0022: add + IL_0023: stfld int32 assembly/Foo::X@ + IL_0028: ldarg.0 + IL_0029: ret + } + + } + + .method public specialname static class assembly/Foo + get_f() cil managed + { + + .maxstack 8 + IL_0000: ldsfld class assembly/Foo ''.$assembly$fsx::f@19 + IL_0005: ret + } + + .method assembly specialname static class assembly/Foo + get_f@9() cil managed + { + + .maxstack 8 + IL_0000: ldsfld class assembly/Foo ''.$assembly$fsx::'f@9-1' + IL_0005: ret + } + + .method assembly specialname static class assembly/Foo + 'get_f@9-1'() cil managed + { + + .maxstack 8 + IL_0000: ldsfld class assembly/Foo ''.$assembly$fsx::'f@9-2' + IL_0005: ret + } + + .property class assembly/Foo + f() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 09 00 00 00 00 00 ) + .get class assembly/Foo assembly::get_f() + } + .property class assembly/Foo + f@9() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 09 00 00 00 00 00 ) + .get class assembly/Foo assembly::get_f@9() + } + .property class assembly/Foo + 'f@9-1'() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 09 00 00 00 00 00 ) + .get class assembly/Foo assembly::'get_f@9-1'() + } +} + +.class private abstract auto ansi sealed ''.$assembly$fsx + extends [runtime]System.Object +{ + .field static assembly initonly class assembly/Foo f@19 + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field static assembly initonly class assembly/Foo 'f@9-1' + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field static assembly initonly class assembly/Foo 'f@9-2' + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field static assembly int32 init@ + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) + .method private specialname rtspecialname static + void .cctor() cil managed + { + + .maxstack 4 + IL_0000: newobj instance void assembly/Foo::.ctor() + IL_0005: stsfld class assembly/Foo ''.$assembly$fsx::f@19 + IL_000a: call class assembly/Foo assembly::get_f() + IL_000f: ldc.i4.1 + IL_0010: stfld int32 assembly/Foo::X@ + IL_0015: call class assembly/Foo assembly::get_f() + IL_001a: pop + IL_001b: call class assembly/Foo assembly::get_f() + IL_0020: ldfld int32 assembly/Foo::X@ + IL_0025: ldc.i4.1 + IL_0026: beq.s IL_0030 + + IL_0028: ldc.i4.1 + IL_0029: call void [runtime]System.Environment::Exit(int32) + IL_002e: br.s IL_0030 + + IL_0030: call class assembly/Foo assembly::get_f() + IL_0035: ldc.i4.1 + IL_0036: stfld int32 assembly/Foo::X@ + IL_003b: call class assembly/Foo assembly::get_f() + IL_0040: stsfld class assembly/Foo ''.$assembly$fsx::'f@9-2' + IL_0045: call class assembly/Foo assembly::'get_f@9-1'() + IL_004a: ldc.i4.2 + IL_004b: stfld int32 assembly/Foo::X@ + IL_0050: call class assembly/Foo assembly::'get_f@9-1'() + IL_0055: stsfld class assembly/Foo ''.$assembly$fsx::'f@9-1' + IL_005a: call class assembly/Foo assembly::get_f@9() + IL_005f: ldc.i4.3 + IL_0060: stfld int32 assembly/Foo::X@ + IL_0065: call class assembly/Foo assembly::get_f@9() + IL_006a: pop + IL_006b: call class assembly/Foo assembly::get_f() + IL_0070: ldfld int32 assembly/Foo::X@ + IL_0075: ldc.i4.3 + IL_0076: beq.s IL_0080 + + IL_0078: ldc.i4.2 + IL_0079: call void [runtime]System.Environment::Exit(int32) + IL_007e: br.s IL_0080 + + IL_0080: ret + } + +} + + + + + diff --git a/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowingTests.fs b/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowingTests.fs index c5db46dd29e..67e512a37ad 100644 --- a/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowingTests.fs +++ b/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowingTests.fs @@ -11,6 +11,7 @@ let [] folder = __SOURCE_DIRECTORY__ + "/PropertyShadowing" , Includes=[| "ShadowWithExtensionMethod.fsx" "ShadowWithTypeExtension.fsx" + "ShadowingAndStillOkWithChainedCalls.fsx" |] )>] let ``can hide property`` compilation = From 189cfe1e6642ab67eab65bf91078749b3d67547d Mon Sep 17 00:00:00 2001 From: Gauthier Segay Date: Sat, 7 Oct 2023 19:34:22 +0200 Subject: [PATCH 08/29] fantomas --- src/Compiler/Facilities/LanguageFeatures.fs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Compiler/Facilities/LanguageFeatures.fs b/src/Compiler/Facilities/LanguageFeatures.fs index e44806661ea..204cccfd9d3 100644 --- a/src/Compiler/Facilities/LanguageFeatures.fs +++ b/src/Compiler/Facilities/LanguageFeatures.fs @@ -186,7 +186,7 @@ type LanguageVersion(versionText) = // F# preview LanguageFeature.FromEndSlicing, previewVersion LanguageFeature.UnmanagedConstraintCsharpInterop, previewVersion - + // F# preview next LanguageFeature.PreferExtensionMethodOverPlainProperty, previewVersion ] @@ -325,7 +325,8 @@ type LanguageVersion(versionText) = | LanguageFeature.WhileBang -> FSComp.SR.featureWhileBang () | LanguageFeature.ExtendedFixedBindings -> FSComp.SR.featureExtendedFixedBindings () | LanguageFeature.PreferStringGetPinnableReference -> FSComp.SR.featurePreferStringGetPinnableReference () - | LanguageFeature.PreferExtensionMethodOverPlainProperty -> FSComp.SR.featurePreferExtensionMethodOverPlainProperty() + | LanguageFeature.PreferExtensionMethodOverPlainProperty -> FSComp.SR.featurePreferExtensionMethodOverPlainProperty () + /// Get a version string associated with the given feature. static member GetFeatureVersionString feature = match features.TryGetValue feature with From 81cedce3809f0f9129867ac30b8cef5ce7090e4d Mon Sep 17 00:00:00 2001 From: Gauthier Segay Date: Sat, 7 Oct 2023 21:12:04 +0200 Subject: [PATCH 09/29] actual chained calls should remain in the sample... --- .../ShadowingAndStillOkWithChainedCalls.fsx | 8 +-- ...owingAndStillOkWithChainedCalls.fsx.il.bsl | 62 ++++++++----------- 2 files changed, 30 insertions(+), 40 deletions(-) diff --git a/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/ShadowingAndStillOkWithChainedCalls.fsx b/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/ShadowingAndStillOkWithChainedCalls.fsx index 8e9ffd219a9..d48bd949440 100644 --- a/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/ShadowingAndStillOkWithChainedCalls.fsx +++ b/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/ShadowingAndStillOkWithChainedCalls.fsx @@ -1,3 +1,4 @@ +#nowarn "52" open System.Runtime.CompilerServices type Foo() = @@ -9,11 +10,8 @@ type FooExt = static member X (f: Foo, i: int) = f.X <- i; f [] static member X (f: Foo, i: string) = - f.X <- - let x = f.X - let v = x.ToString() - v.Length + i.Length - f + // chained call on the property are still ok + f.X <- f.X.ToString().Length + i.Length; f let f = Foo() diff --git a/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/ShadowingAndStillOkWithChainedCalls.fsx.il.bsl b/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/ShadowingAndStillOkWithChainedCalls.fsx.il.bsl index 907ff8c1523..b7969f50320 100644 --- a/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/ShadowingAndStillOkWithChainedCalls.fsx.il.bsl +++ b/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/ShadowingAndStillOkWithChainedCalls.fsx.il.bsl @@ -117,8 +117,7 @@ .custom instance void [runtime]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = ( 01 00 00 00 ) .maxstack 5 - .locals init (int32 V_0, - string V_1) + .locals init (int32 V_0) IL_0000: ldarg.0 IL_0001: ldarg.0 IL_0002: ldfld int32 assembly/Foo::X@ @@ -126,15 +125,13 @@ IL_0008: ldloca.s V_0 IL_000a: constrained. [runtime]System.Int32 IL_0010: callvirt instance string [runtime]System.Object::ToString() - IL_0015: stloc.1 - IL_0016: ldloc.1 - IL_0017: callvirt instance int32 [runtime]System.String::get_Length() - IL_001c: ldarg.1 - IL_001d: callvirt instance int32 [runtime]System.String::get_Length() - IL_0022: add - IL_0023: stfld int32 assembly/Foo::X@ - IL_0028: ldarg.0 - IL_0029: ret + IL_0015: callvirt instance int32 [runtime]System.String::get_Length() + IL_001a: ldarg.1 + IL_001b: callvirt instance int32 [runtime]System.String::get_Length() + IL_0020: add + IL_0021: stfld int32 assembly/Foo::X@ + IL_0026: ldarg.0 + IL_0027: ret } } @@ -144,25 +141,25 @@ { .maxstack 8 - IL_0000: ldsfld class assembly/Foo ''.$assembly$fsx::f@19 + IL_0000: ldsfld class assembly/Foo ''.$assembly$fsx::f@17 IL_0005: ret } .method assembly specialname static class assembly/Foo - get_f@9() cil managed + get_f@10() cil managed { .maxstack 8 - IL_0000: ldsfld class assembly/Foo ''.$assembly$fsx::'f@9-1' + IL_0000: ldsfld class assembly/Foo ''.$assembly$fsx::'f@10-1' IL_0005: ret } .method assembly specialname static class assembly/Foo - 'get_f@9-1'() cil managed + 'get_f@10-1'() cil managed { .maxstack 8 - IL_0000: ldsfld class assembly/Foo ''.$assembly$fsx::'f@9-2' + IL_0000: ldsfld class assembly/Foo ''.$assembly$fsx::'f@10-2' IL_0005: ret } @@ -173,27 +170,27 @@ .get class assembly/Foo assembly::get_f() } .property class assembly/Foo - f@9() + f@10() { .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 09 00 00 00 00 00 ) - .get class assembly/Foo assembly::get_f@9() + .get class assembly/Foo assembly::get_f@10() } .property class assembly/Foo - 'f@9-1'() + 'f@10-1'() { .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 09 00 00 00 00 00 ) - .get class assembly/Foo assembly::'get_f@9-1'() + .get class assembly/Foo assembly::'get_f@10-1'() } } .class private abstract auto ansi sealed ''.$assembly$fsx extends [runtime]System.Object { - .field static assembly initonly class assembly/Foo f@19 + .field static assembly initonly class assembly/Foo f@17 .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) - .field static assembly initonly class assembly/Foo 'f@9-1' + .field static assembly initonly class assembly/Foo 'f@10-1' .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) - .field static assembly initonly class assembly/Foo 'f@9-2' + .field static assembly initonly class assembly/Foo 'f@10-2' .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) .field static assembly int32 init@ .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) @@ -205,7 +202,7 @@ .maxstack 4 IL_0000: newobj instance void assembly/Foo::.ctor() - IL_0005: stsfld class assembly/Foo ''.$assembly$fsx::f@19 + IL_0005: stsfld class assembly/Foo ''.$assembly$fsx::f@17 IL_000a: call class assembly/Foo assembly::get_f() IL_000f: ldc.i4.1 IL_0010: stfld int32 assembly/Foo::X@ @@ -224,16 +221,16 @@ IL_0035: ldc.i4.1 IL_0036: stfld int32 assembly/Foo::X@ IL_003b: call class assembly/Foo assembly::get_f() - IL_0040: stsfld class assembly/Foo ''.$assembly$fsx::'f@9-2' - IL_0045: call class assembly/Foo assembly::'get_f@9-1'() + IL_0040: stsfld class assembly/Foo ''.$assembly$fsx::'f@10-2' + IL_0045: call class assembly/Foo assembly::'get_f@10-1'() IL_004a: ldc.i4.2 IL_004b: stfld int32 assembly/Foo::X@ - IL_0050: call class assembly/Foo assembly::'get_f@9-1'() - IL_0055: stsfld class assembly/Foo ''.$assembly$fsx::'f@9-1' - IL_005a: call class assembly/Foo assembly::get_f@9() + IL_0050: call class assembly/Foo assembly::'get_f@10-1'() + IL_0055: stsfld class assembly/Foo ''.$assembly$fsx::'f@10-1' + IL_005a: call class assembly/Foo assembly::get_f@10() IL_005f: ldc.i4.3 IL_0060: stfld int32 assembly/Foo::X@ - IL_0065: call class assembly/Foo assembly::get_f@9() + IL_0065: call class assembly/Foo assembly::get_f@10() IL_006a: pop IL_006b: call class assembly/Foo assembly::get_f() IL_0070: ldfld int32 assembly/Foo::X@ @@ -248,8 +245,3 @@ } } - - - - - From 73dfd351b6ef1acbca8cbf00cc868363788579f5 Mon Sep 17 00:00:00 2001 From: Gauthier Segay Date: Sat, 7 Oct 2023 21:20:11 +0200 Subject: [PATCH 10/29] minimize diff --- src/Compiler/Service/ServiceDeclarationLists.fs | 2 +- src/Compiler/Symbols/SymbolHelpers.fs | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Compiler/Service/ServiceDeclarationLists.fs b/src/Compiler/Service/ServiceDeclarationLists.fs index 563352045a0..104ae1da0ff 100644 --- a/src/Compiler/Service/ServiceDeclarationLists.fs +++ b/src/Compiler/Service/ServiceDeclarationLists.fs @@ -878,7 +878,7 @@ module internal DescriptionListsImpl = | Item.Property(info = []) -> [], emptyL - + /// Compute the index of the VS glyph shown with an item in the Intellisense menu let GlyphOfItem(denv, item) : FSharpGlyph = /// Find the glyph for the given representation. diff --git a/src/Compiler/Symbols/SymbolHelpers.fs b/src/Compiler/Symbols/SymbolHelpers.fs index f5ce5d312ca..c2e4a3cccac 100644 --- a/src/Compiler/Symbols/SymbolHelpers.fs +++ b/src/Compiler/Symbols/SymbolHelpers.fs @@ -338,6 +338,7 @@ module internal SymbolHelpers = | Item.UnqualifiedType [] | Item.Types(_, []) -> FSharpXmlDoc.None + |> GetXmlDocFromLoader infoReader /// Produce an XmlComment with a signature or raw text, given the F# comment and the item @@ -404,7 +405,9 @@ module internal SymbolHelpers = // These are not expected to occur | Item.Types(_, []) | Item.ModuleOrNamespaces [] -> false + //| _ -> false + member x.Equals(item1, item2) = From 281a2a9c0e26418fd8d5a86fb55fe43006c8066f Mon Sep 17 00:00:00 2001 From: Gauthier Segay Date: Sun, 8 Oct 2023 16:28:18 +0200 Subject: [PATCH 11/29] adding test for support of BCL System.Linq.Enumerable.Count() adding tests for before the feature on all the previous positive tests --- .../PropertyShadowing/LinqCount.fsx | 4 + .../PropertyShadowing/LinqCount.fsx.il.bsl | 118 ++++++++++++++++++ .../LinqCount.fsx.support.added.later.err.bsl | 1 + .../LinqCount.fsx.support.added.later.il.bsl | 0 ...sionMethod.fsx.support.added.later.err.bsl | 2 + ...nsionMethod.fsx.support.added.later.il.bsl | 0 ...eExtension.fsx.support.added.later.err.bsl | 2 + ...peExtension.fsx.support.added.later.il.bsl | 0 ...ainedCalls.fsx.support.added.later.err.bsl | 2 + ...hainedCalls.fsx.support.added.later.il.bsl | 0 .../TypeExtensions/PropertyShadowingTests.fs | 22 +++- .../DirectoryAttribute.fs | 2 +- 12 files changed, 150 insertions(+), 3 deletions(-) create mode 100644 tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/LinqCount.fsx create mode 100644 tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/LinqCount.fsx.il.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/LinqCount.fsx.support.added.later.err.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/LinqCount.fsx.support.added.later.il.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/ShadowWithExtensionMethod.fsx.support.added.later.err.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/ShadowWithExtensionMethod.fsx.support.added.later.il.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/ShadowWithTypeExtension.fsx.support.added.later.err.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/ShadowWithTypeExtension.fsx.support.added.later.il.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/ShadowingAndStillOkWithChainedCalls.fsx.support.added.later.err.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/ShadowingAndStillOkWithChainedCalls.fsx.support.added.later.il.bsl diff --git a/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/LinqCount.fsx b/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/LinqCount.fsx new file mode 100644 index 00000000000..0e7661abe7b --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/LinqCount.fsx @@ -0,0 +1,4 @@ +open System.Linq +let r = ResizeArray() +r.Count +r.Count(fun _ -> true) diff --git a/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/LinqCount.fsx.il.bsl b/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/LinqCount.fsx.il.bsl new file mode 100644 index 00000000000..684fa3ce5e7 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/LinqCount.fsx.il.bsl @@ -0,0 +1,118 @@ + + + + + +.assembly extern runtime { } +.assembly extern FSharp.Core { } +.assembly extern System.Collections +{ + .publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A ) + .ver 8:0:0:0 +} +.assembly extern System.Linq +{ + .publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A ) + .ver 8:0:0:0 +} +.assembly assembly +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32, + int32, + int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ) + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.mresource public FSharpSignatureData.assembly +{ + + +} +.mresource public FSharpOptimizationData.assembly +{ + + +} +.module assembly.dll + +.imagebase {value} +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 +.corflags 0x00000001 + + + + + +.class public abstract auto ansi sealed assembly + extends [runtime]System.Object +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname clo@4 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .method assembly static bool Invoke(int32 _arg1) cil managed + { + + .maxstack 8 + IL_0000: ldc.i4.1 + IL_0001: ret + } + + } + + .method public specialname static class [System.Collections]System.Collections.Generic.List`1 + get_r() cil managed + { + + .maxstack 8 + IL_0000: ldsfld class [System.Collections]System.Collections.Generic.List`1 ''.$assembly$fsx::r@2 + IL_0005: ret + } + + .property class [System.Collections]System.Collections.Generic.List`1 + r() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 09 00 00 00 00 00 ) + .get class [System.Collections]System.Collections.Generic.List`1 assembly::get_r() + } +} + +.class private abstract auto ansi sealed ''.$assembly$fsx + extends [runtime]System.Object +{ + .field static assembly initonly class [System.Collections]System.Collections.Generic.List`1 r@2 + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field static assembly int32 init@ + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) + .method private specialname rtspecialname static + void .cctor() cil managed + { + + .maxstack 8 + IL_0000: newobj instance void class [System.Collections]System.Collections.Generic.List`1::.ctor() + IL_0005: stsfld class [System.Collections]System.Collections.Generic.List`1 ''.$assembly$fsx::r@2 + IL_000a: call class [System.Collections]System.Collections.Generic.List`1 assembly::get_r() + IL_000f: callvirt instance int32 class [System.Collections]System.Collections.Generic.List`1::get_Count() + IL_0014: pop + IL_0015: call class [System.Collections]System.Collections.Generic.List`1 assembly::get_r() + IL_001a: ldnull + IL_001b: ldftn bool assembly/clo@4::Invoke(int32) + IL_0021: newobj instance void class [runtime]System.Func`2::.ctor(object, + native int) + IL_0026: call int32 [System.Linq]System.Linq.Enumerable::Count(class [runtime]System.Collections.Generic.IEnumerable`1, + class [runtime]System.Func`2) + IL_002b: pop + IL_002c: ret + } + +} + + + + + diff --git a/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/LinqCount.fsx.support.added.later.err.bsl b/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/LinqCount.fsx.support.added.later.err.bsl new file mode 100644 index 00000000000..829ea13ac59 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/LinqCount.fsx.support.added.later.err.bsl @@ -0,0 +1 @@ +LinqCount.fsx (4,1)-(4,8) typecheck error This value is not a function and cannot be applied. \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/LinqCount.fsx.support.added.later.il.bsl b/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/LinqCount.fsx.support.added.later.il.bsl new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/ShadowWithExtensionMethod.fsx.support.added.later.err.bsl b/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/ShadowWithExtensionMethod.fsx.support.added.later.err.bsl new file mode 100644 index 00000000000..43881e3a026 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/ShadowWithExtensionMethod.fsx.support.added.later.err.bsl @@ -0,0 +1,2 @@ +ShadowWithExtensionMethod.fsx (13,1)-(13,4) typecheck error This value is not a function and cannot be applied. +ShadowWithExtensionMethod.fsx (17,1)-(17,4) typecheck error This value is not a function and cannot be applied. \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/ShadowWithExtensionMethod.fsx.support.added.later.il.bsl b/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/ShadowWithExtensionMethod.fsx.support.added.later.il.bsl new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/ShadowWithTypeExtension.fsx.support.added.later.err.bsl b/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/ShadowWithTypeExtension.fsx.support.added.later.err.bsl new file mode 100644 index 00000000000..ea6a175c648 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/ShadowWithTypeExtension.fsx.support.added.later.err.bsl @@ -0,0 +1,2 @@ +ShadowWithTypeExtension.fsx (12,1)-(12,4) typecheck error This value is not a function and cannot be applied. +ShadowWithTypeExtension.fsx (16,1)-(16,4) typecheck error This value is not a function and cannot be applied. \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/ShadowWithTypeExtension.fsx.support.added.later.il.bsl b/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/ShadowWithTypeExtension.fsx.support.added.later.il.bsl new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/ShadowingAndStillOkWithChainedCalls.fsx.support.added.later.err.bsl b/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/ShadowingAndStillOkWithChainedCalls.fsx.support.added.later.err.bsl new file mode 100644 index 00000000000..9885a2f82bb --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/ShadowingAndStillOkWithChainedCalls.fsx.support.added.later.err.bsl @@ -0,0 +1,2 @@ +ShadowingAndStillOkWithChainedCalls.fsx (18,1)-(18,4) typecheck error This value is not a function and cannot be applied. +ShadowingAndStillOkWithChainedCalls.fsx (22,1)-(22,4) typecheck error This value is not a function and cannot be applied. \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/ShadowingAndStillOkWithChainedCalls.fsx.support.added.later.il.bsl b/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/ShadowingAndStillOkWithChainedCalls.fsx.support.added.later.il.bsl new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowingTests.fs b/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowingTests.fs index 67e512a37ad..5da11809cd0 100644 --- a/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowingTests.fs +++ b/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowingTests.fs @@ -12,6 +12,7 @@ let [] folder = __SOURCE_DIRECTORY__ + "/PropertyShadowing" "ShadowWithExtensionMethod.fsx" "ShadowWithTypeExtension.fsx" "ShadowingAndStillOkWithChainedCalls.fsx" + "LinqCount.fsx" |] )>] let ``can hide property`` compilation = @@ -21,7 +22,25 @@ let ``can hide property`` compilation = |> verifyBaselines |> compileAndRun |> shouldSucceed - + +[] +let ``cannot hide property v7.0 support added later`` compilation = + compilation + |> asFsx + |> withOptions ["--langversion:7.0"] + |> verifyBaselines + |> compile + |> shouldFail [ verifyBaselines |> compile |> shouldFail - diff --git a/tests/FSharp.Test.Utilities/DirectoryAttribute.fs b/tests/FSharp.Test.Utilities/DirectoryAttribute.fs index 01999873a84..5365abdbdb5 100644 --- a/tests/FSharp.Test.Utilities/DirectoryAttribute.fs +++ b/tests/FSharp.Test.Utilities/DirectoryAttribute.fs @@ -45,7 +45,7 @@ type DirectoryAttribute(dir: string) = | Some path -> path.FullName | None -> failwith "Can't set the output directory" let sourceFilePath = normalizePathSeparator (path ++ filename) - let fsBslFilePath = sourceFilePath + ".err.bsl" + let fsBslFilePath = sourceFilePath + baselineSuffix + ".err.bsl" let ilBslFilePath = let ilBslPaths = [| #if DEBUG From 63e5c91b86e97a798204fac415f08dfcc16c0d1b Mon Sep 17 00:00:00 2001 From: Gauthier Segay Date: Sun, 8 Oct 2023 16:50:23 +0200 Subject: [PATCH 12/29] (minor) formatting. --- tests/FSharp.Test.Utilities/Compiler.fs | 32 ++++++++++++------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/tests/FSharp.Test.Utilities/Compiler.fs b/tests/FSharp.Test.Utilities/Compiler.fs index fcfa8ee0666..52c9b033119 100644 --- a/tests/FSharp.Test.Utilities/Compiler.fs +++ b/tests/FSharp.Test.Utilities/Compiler.fs @@ -1162,22 +1162,22 @@ Actual: let private verifyFSILBaseline (baseline: Baseline) (result: CompilationOutput) : unit = match result.OutputPath with - | None -> failwith "Operation didn't produce any output!" - | Some p -> - let expectedIL = - match baseline.ILBaseline.Content with - | Some b -> b - | None -> String.Empty - let success, errorMsg, actualIL = ILChecker.verifyILAndReturnActual p expectedIL - - if not success then - // Failed try update baselines if required - // If we are here then the il file has been produced we can write it back to the baseline location - // if the environment variable TEST_UPDATE_BSL has been set - updateBaseLineIfEnvironmentSaysSo baseline.ILBaseline - createBaselineErrors baseline.ILBaseline actualIL - let errorMsg = (convenienceBaselineInstructions baseline.ILBaseline expectedIL actualIL) + errorMsg - Assert.Fail(errorMsg) + | None -> failwith "Operation didn't produce any output!" + | Some p -> + let expectedIL = + match baseline.ILBaseline.Content with + | Some b -> b + | None -> String.Empty + let success, errorMsg, actualIL = ILChecker.verifyILAndReturnActual p expectedIL + + if not success then + // Failed try update baselines if required + // If we are here then the il file has been produced we can write it back to the baseline location + // if the environment variable TEST_UPDATE_BSL has been set + updateBaseLineIfEnvironmentSaysSo baseline.ILBaseline + createBaselineErrors baseline.ILBaseline actualIL + let errorMsg = (convenienceBaselineInstructions baseline.ILBaseline expectedIL actualIL) + errorMsg + Assert.Fail(errorMsg) let verifyILBaseline (cUnit: CompilationUnit) : CompilationUnit = match cUnit with From 136a875e50420990b994432a3af6adee1050041f Mon Sep 17 00:00:00 2001 From: Gauthier Segay Date: Sun, 8 Oct 2023 20:05:24 +0200 Subject: [PATCH 13/29] fixing partially applied function piped to ignore (https://github.com/fsharp/fslang-suggestions/issues/1327) making .net framework tests fail --- tests/FSharp.Test.Utilities/CompilerAssert.fs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tests/FSharp.Test.Utilities/CompilerAssert.fs b/tests/FSharp.Test.Utilities/CompilerAssert.fs index f7f0b4e9641..1dcbcb846ff 100644 --- a/tests/FSharp.Test.Utilities/CompilerAssert.fs +++ b/tests/FSharp.Test.Utilities/CompilerAssert.fs @@ -297,7 +297,7 @@ module rec CompilerAssertHelpers = type Worker () = inherit MarshalByRefObject() - member x.ExecuteTestCase assemblyPath (deps: string[]) = + member x.ExecuteTestCase assemblyPath (deps: string[]) isFsx = AppDomain.CurrentDomain.add_AssemblyResolve(ResolveEventHandler(fun _ args -> deps |> Array.tryFind (fun (x: string) -> Path.GetFileNameWithoutExtension x = AssemblyName(args.Name).Name) @@ -305,7 +305,8 @@ module rec CompilerAssertHelpers = |> Option.map Assembly.LoadFile |> Option.defaultValue null)) - Assembly.LoadFrom assemblyPath |> executeAssemblyEntryPoint + let assembly = Assembly.LoadFrom assemblyPath + executeAssemblyEntryPoint assembly isFsx let adSetup = let setup = new System.AppDomainSetup () @@ -629,7 +630,7 @@ type CompilerAssert private () = if errors.Length > 0 then Assert.Fail (sprintf "Compile had warnings and/or errors: %A" errors) - executeBuiltApp outputExe [] |> ignore + executeBuiltApp outputExe [] false |> ignore ) static let compileLibraryAndVerifyILWithOptions options (source: SourceCodeFileKind) (f: ILVerifier -> unit) = From 92bf07c73942ab3d150b8a89b3106f3ec860a142 Mon Sep 17 00:00:00 2001 From: Gauthier Segay Date: Sun, 8 Oct 2023 21:06:36 +0200 Subject: [PATCH 14/29] adjust baselines that differ between .net framework and .netcore --- .../LinqCount.fsx.il.net472.bsl | 114 +++++++++++++++++ .../LinqCount.fsx.il.netcore.bsl | 118 ++++++++++++++++++ 2 files changed, 232 insertions(+) create mode 100644 tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/LinqCount.fsx.il.net472.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/LinqCount.fsx.il.netcore.bsl diff --git a/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/LinqCount.fsx.il.net472.bsl b/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/LinqCount.fsx.il.net472.bsl new file mode 100644 index 00000000000..3b62d843887 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/LinqCount.fsx.il.net472.bsl @@ -0,0 +1,114 @@ + + + + + +.assembly extern runtime { } +.assembly extern FSharp.Core { } +.assembly extern System.Core +{ + .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) + .ver 4:0:0:0 +} +.assembly assembly +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32, + int32, + int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ) + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.mresource public FSharpSignatureData.assembly +{ + + +} +.mresource public FSharpOptimizationData.assembly +{ + + +} +.module assembly.dll + +.imagebase {value} +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 +.corflags 0x00000001 + + + + + +.class public abstract auto ansi sealed assembly + extends [runtime]System.Object +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname clo@4 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .method assembly static bool Invoke(int32 _arg1) cil managed + { + + .maxstack 8 + IL_0000: ldc.i4.1 + IL_0001: ret + } + + } + + .method public specialname static class [runtime]System.Collections.Generic.List`1 + get_r() cil managed + { + + .maxstack 8 + IL_0000: ldsfld class [runtime]System.Collections.Generic.List`1 ''.$assembly$fsx::r@2 + IL_0005: ret + } + + .property class [runtime]System.Collections.Generic.List`1 + r() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 09 00 00 00 00 00 ) + .get class [runtime]System.Collections.Generic.List`1 assembly::get_r() + } +} + +.class private abstract auto ansi sealed ''.$assembly$fsx + extends [runtime]System.Object +{ + .field static assembly initonly class [runtime]System.Collections.Generic.List`1 r@2 + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field static assembly int32 init@ + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) + .method private specialname rtspecialname static + void .cctor() cil managed + { + + .maxstack 8 + IL_0000: newobj instance void class [runtime]System.Collections.Generic.List`1::.ctor() + IL_0005: stsfld class [runtime]System.Collections.Generic.List`1 ''.$assembly$fsx::r@2 + IL_000a: call class [runtime]System.Collections.Generic.List`1 assembly::get_r() + IL_000f: callvirt instance int32 class [runtime]System.Collections.Generic.List`1::get_Count() + IL_0014: pop + IL_0015: call class [runtime]System.Collections.Generic.List`1 assembly::get_r() + IL_001a: ldnull + IL_001b: ldftn bool assembly/clo@4::Invoke(int32) + IL_0021: newobj instance void class [runtime]System.Func`2::.ctor(object, + native int) + IL_0026: call int32 [System.Core]System.Linq.Enumerable::Count(class [runtime]System.Collections.Generic.IEnumerable`1, + class [runtime]System.Func`2) + IL_002b: pop + IL_002c: ret + } + +} + + + + + + diff --git a/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/LinqCount.fsx.il.netcore.bsl b/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/LinqCount.fsx.il.netcore.bsl new file mode 100644 index 00000000000..684fa3ce5e7 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/LinqCount.fsx.il.netcore.bsl @@ -0,0 +1,118 @@ + + + + + +.assembly extern runtime { } +.assembly extern FSharp.Core { } +.assembly extern System.Collections +{ + .publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A ) + .ver 8:0:0:0 +} +.assembly extern System.Linq +{ + .publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A ) + .ver 8:0:0:0 +} +.assembly assembly +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32, + int32, + int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ) + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.mresource public FSharpSignatureData.assembly +{ + + +} +.mresource public FSharpOptimizationData.assembly +{ + + +} +.module assembly.dll + +.imagebase {value} +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 +.corflags 0x00000001 + + + + + +.class public abstract auto ansi sealed assembly + extends [runtime]System.Object +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .class abstract auto autochar serializable sealed nested assembly beforefieldinit specialname clo@4 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 06 00 00 00 00 00 ) + .method assembly static bool Invoke(int32 _arg1) cil managed + { + + .maxstack 8 + IL_0000: ldc.i4.1 + IL_0001: ret + } + + } + + .method public specialname static class [System.Collections]System.Collections.Generic.List`1 + get_r() cil managed + { + + .maxstack 8 + IL_0000: ldsfld class [System.Collections]System.Collections.Generic.List`1 ''.$assembly$fsx::r@2 + IL_0005: ret + } + + .property class [System.Collections]System.Collections.Generic.List`1 + r() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 09 00 00 00 00 00 ) + .get class [System.Collections]System.Collections.Generic.List`1 assembly::get_r() + } +} + +.class private abstract auto ansi sealed ''.$assembly$fsx + extends [runtime]System.Object +{ + .field static assembly initonly class [System.Collections]System.Collections.Generic.List`1 r@2 + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field static assembly int32 init@ + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) + .method private specialname rtspecialname static + void .cctor() cil managed + { + + .maxstack 8 + IL_0000: newobj instance void class [System.Collections]System.Collections.Generic.List`1::.ctor() + IL_0005: stsfld class [System.Collections]System.Collections.Generic.List`1 ''.$assembly$fsx::r@2 + IL_000a: call class [System.Collections]System.Collections.Generic.List`1 assembly::get_r() + IL_000f: callvirt instance int32 class [System.Collections]System.Collections.Generic.List`1::get_Count() + IL_0014: pop + IL_0015: call class [System.Collections]System.Collections.Generic.List`1 assembly::get_r() + IL_001a: ldnull + IL_001b: ldftn bool assembly/clo@4::Invoke(int32) + IL_0021: newobj instance void class [runtime]System.Func`2::.ctor(object, + native int) + IL_0026: call int32 [System.Linq]System.Linq.Enumerable::Count(class [runtime]System.Collections.Generic.IEnumerable`1, + class [runtime]System.Func`2) + IL_002b: pop + IL_002c: ret + } + +} + + + + + From 30f50b28adcfb365fe355643c7693890a3826318 Mon Sep 17 00:00:00 2001 From: Gauthier Segay Date: Sun, 8 Oct 2023 23:49:40 +0200 Subject: [PATCH 15/29] checking event handlers aren't affected by the feature --- .../PropertyShadowing/E_NoChangeForEvent.fsx | 18 ++++++++++++++++++ .../E_NoChangeForEvent.fsx.err.bsl | 3 +++ .../E_NoChangeForEvent.fsx.il.bsl | 0 .../TypeExtensions/PropertyShadowingTests.fs | 2 ++ 4 files changed, 23 insertions(+) create mode 100644 tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/E_NoChangeForEvent.fsx create mode 100644 tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/E_NoChangeForEvent.fsx.err.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/E_NoChangeForEvent.fsx.il.bsl diff --git a/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/E_NoChangeForEvent.fsx b/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/E_NoChangeForEvent.fsx new file mode 100644 index 00000000000..5fc471bf2bd --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/E_NoChangeForEvent.fsx @@ -0,0 +1,18 @@ +#nowarn "52" +open System.Runtime.CompilerServices +open System.Data +[] +type DataSetExts = + [] + static member Disposed(self: DataSet) = self + +let d = System.Data.DataSet() +d.Disposed().Disposed().add_Disposed(fun a b -> ()) + +module Exts = + type DataSet with + member x.Disposed() = x + +open Exts + +d.Disposed().Disposed().add_Disposed(fun a b -> ()) \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/E_NoChangeForEvent.fsx.err.bsl b/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/E_NoChangeForEvent.fsx.err.bsl new file mode 100644 index 00000000000..e022666431a --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/E_NoChangeForEvent.fsx.err.bsl @@ -0,0 +1,3 @@ +E_NoChangeForEvent.fsx (9,9)-(9,30) typecheck warning It is recommended that objects supporting the IDisposable interface are created using the syntax 'new Type(args)', rather than 'Type(args)' or 'Type' as a function value representing the constructor, to indicate that resources may be owned by the generated value +E_NoChangeForEvent.fsx (10,1)-(10,11) typecheck error This value is not a function and cannot be applied. +E_NoChangeForEvent.fsx (18,1)-(18,11) typecheck error This value is not a function and cannot be applied. \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/E_NoChangeForEvent.fsx.il.bsl b/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/E_NoChangeForEvent.fsx.il.bsl new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowingTests.fs b/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowingTests.fs index 5da11809cd0..4754cb7edb8 100644 --- a/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowingTests.fs +++ b/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowingTests.fs @@ -50,6 +50,7 @@ let ``cannot hide property v7.0 support added later`` compilation = "E_CannotShadowIndexedPropertyWithTypeExtension.fsx" "E_CannotShadowFunctionPropertyWithExtensionMethod.fsx" "E_CannotShadowFunctionPropertyWithTypeExtension.fsx" + "E_NoChangeForEvent.fsx" |] )>] let ``cannot hide property`` compilation = @@ -69,6 +70,7 @@ let ``cannot hide property`` compilation = "E_CannotShadowIndexedPropertyWithTypeExtension.fsx" "E_CannotShadowFunctionPropertyWithExtensionMethod.fsx" "E_CannotShadowFunctionPropertyWithTypeExtension.fsx" + "E_NoChangeForEvent.fsx" |] )>] let ``cannot hide property v7.0`` compilation = From 53611ba2bc13ede333dd3917b824a8853614704e Mon Sep 17 00:00:00 2001 From: Gauthier Segay Date: Tue, 10 Oct 2023 15:48:00 +0200 Subject: [PATCH 16/29] separate out Property and Method in DeclarationListInfo.Create, not clear how many things will be broken, but it does what is expected in VS --- src/Compiler/Service/ServiceDeclarationLists.fs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Compiler/Service/ServiceDeclarationLists.fs b/src/Compiler/Service/ServiceDeclarationLists.fs index 104ae1da0ff..fbc3972f9c4 100644 --- a/src/Compiler/Service/ServiceDeclarationLists.fs +++ b/src/Compiler/Service/ServiceDeclarationLists.fs @@ -1138,6 +1138,11 @@ type DeclarationListInfo(declarations: DeclarationListItem[], isForType: bool, i // Remove all duplicates. We've put the types first, so this removes the DelegateCtor and DefaultStructCtor's. |> RemoveDuplicateCompletionItems g |> List.groupBy (fun x -> + // RFC-1137 + // we do not solely group by item name but also add Kind, + // due to not desiring to merge Property and Method bearing same name + // (from type extension or extension methods). + x.Kind, match x.Unresolved with | Some u -> match u.Namespace with From bdf1c33ed7e029847a6030776ddb3f92ed7099f7 Mon Sep 17 00:00:00 2001 From: Gauthier Segay Date: Sun, 15 Oct 2023 17:05:31 +0200 Subject: [PATCH 17/29] handling of static property --- .../Checking/CheckComputationExpressions.fs | 2 +- src/Compiler/Checking/CheckDeclarations.fs | 2 +- src/Compiler/Checking/CheckExpressions.fs | 20 +- src/Compiler/Checking/CheckPatterns.fs | 2 +- src/Compiler/Checking/NameResolution.fs | 44 ++-- src/Compiler/Checking/NameResolution.fsi | 2 + .../ShadowStaticProperty.fsx | 26 +++ .../ShadowStaticProperty.fsx.il.bsl | 193 ++++++++++++++++++ ...icProperty.fsx.support.added.later.err.bsl | 2 + ...ticProperty.fsx.support.added.later.il.bsl | 0 .../TypeExtensions/PropertyShadowingTests.fs | 2 + 11 files changed, 263 insertions(+), 32 deletions(-) create mode 100644 tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/ShadowStaticProperty.fsx create mode 100644 tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/ShadowStaticProperty.fsx.il.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/ShadowStaticProperty.fsx.support.added.later.err.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/ShadowStaticProperty.fsx.support.added.later.il.bsl diff --git a/src/Compiler/Checking/CheckComputationExpressions.fs b/src/Compiler/Checking/CheckComputationExpressions.fs index e27dcffc7bf..e9f0fecedab 100644 --- a/src/Compiler/Checking/CheckComputationExpressions.fs +++ b/src/Compiler/Checking/CheckComputationExpressions.fs @@ -58,7 +58,7 @@ let (|JoinRelation|_|) cenv env (expr: SynExpr) = let isOpName opName vref s = (s = opName) && - match ResolveExprLongIdent cenv.tcSink cenv.nameResolver m ad env.eNameResEnv TypeNameResolutionInfo.Default [ident(opName, m)] with + match ResolveExprLongIdent cenv.tcSink cenv.nameResolver m ad env.eNameResEnv TypeNameResolutionInfo.Default [ident(opName, m)] None with | Result (_, Item.Value vref2, []) -> valRefEq cenv.g vref vref2 | _ -> false diff --git a/src/Compiler/Checking/CheckDeclarations.fs b/src/Compiler/Checking/CheckDeclarations.fs index 8f41152c420..39bedd8afa6 100644 --- a/src/Compiler/Checking/CheckDeclarations.fs +++ b/src/Compiler/Checking/CheckDeclarations.fs @@ -2380,7 +2380,7 @@ module TcExceptionDeclarations = match reprIdOpt with | Some longId -> let resolution = - ResolveExprLongIdent cenv.tcSink cenv.nameResolver m ad env.NameEnv TypeNameResolutionInfo.Default longId + ResolveExprLongIdent cenv.tcSink cenv.nameResolver m ad env.NameEnv TypeNameResolutionInfo.Default longId None |> ForceRaise match resolution with | _, Item.ExnCase exnc, [] -> diff --git a/src/Compiler/Checking/CheckExpressions.fs b/src/Compiler/Checking/CheckExpressions.fs index b09a3e70b69..61c7692ef8f 100644 --- a/src/Compiler/Checking/CheckExpressions.fs +++ b/src/Compiler/Checking/CheckExpressions.fs @@ -3811,6 +3811,13 @@ type DelayedItem = /// Represents the valueExpr in "item <- valueExpr", also "item.[indexerArgs] <- valueExpr" etc. | DelayedSet of SynExpr * range +module DelayedItem = + let maybeAppliedArgForPreferExtensionOverProperty delayed = + match delayed with + | [] -> None + | DelayedItem.DelayedApp(argExpr=argExpr) :: _ -> Some argExpr + | _ -> None + let MakeDelayedSet(e: SynExpr, m) = // We have longId <- e. Wrap 'e' in another pair of parentheses to ensure it's never interpreted as // a named argument, e.g. for "el.Checked <- (el = el2)" @@ -8083,7 +8090,7 @@ and TcNameOfExpr (cenv: cenv) env tpenv (synArg: SynExpr) = // However we don't commit for a type names - nameof allows 'naked' type names and thus all type name // resolutions are checked separately in the next step. let typeNameResInfo = GetLongIdentTypeNameInfo delayed - let nameResolutionResult = ResolveLongIdentAsExprAndComputeRange cenv.tcSink cenv.nameResolver (rangeOfLid longId) ad env.eNameResEnv typeNameResInfo longId + let nameResolutionResult = ResolveLongIdentAsExprAndComputeRange cenv.tcSink cenv.nameResolver (rangeOfLid longId) ad env.eNameResEnv typeNameResInfo longId None let resolvesAsExpr = match nameResolutionResult with | Result (_, item, _, _, _ as res) @@ -8300,7 +8307,8 @@ and TcLongIdentThen (cenv: cenv) (overallTy: OverallTy) env tpenv (SynLongIdent( let ad = env.eAccessRights let typeNameResInfo = GetLongIdentTypeNameInfo delayed let nameResolutionResult = - ResolveLongIdentAsExprAndComputeRange cenv.tcSink cenv.nameResolver (rangeOfLid longId) ad env.eNameResEnv typeNameResInfo longId + let maybeAppliedArgExpr = DelayedItem.maybeAppliedArgForPreferExtensionOverProperty delayed + ResolveLongIdentAsExprAndComputeRange cenv.tcSink cenv.nameResolver (rangeOfLid longId) ad env.eNameResEnv typeNameResInfo longId maybeAppliedArgExpr |> ForceRaise TcItemThen cenv overallTy env tpenv nameResolutionResult None delayed @@ -9116,12 +9124,8 @@ and TcLookupThen cenv overallTy env tpenv mObjExpr objExpr objExprTy longId dela // Canonicalize inference problem prior to '.' lookup on variable types if isTyparTy g objExprTy then CanonicalizePartialInferenceProblem cenv.css env.DisplayEnv mExprAndLongId (freeInTypeLeftToRight g false objExprTy) - // - let maybeAppliedArgExpr = - match delayed with - | [] -> None - | DelayedItem.DelayedApp(argExpr=argExpr) :: _ -> Some argExpr - | _ -> None + + let maybeAppliedArgExpr = DelayedItem.maybeAppliedArgForPreferExtensionOverProperty delayed let item, mItem, rest, afterResolution = ResolveExprDotLongIdentAndComputeRange cenv.tcSink cenv.nameResolver mExprAndLongId ad env.NameEnv objExprTy longId TypeNameResolutionInfo.Default findFlag false maybeAppliedArgExpr TcLookupItemThen cenv overallTy env tpenv mObjExpr objExpr objExprTy delayed item mItem rest afterResolution diff --git a/src/Compiler/Checking/CheckPatterns.fs b/src/Compiler/Checking/CheckPatterns.fs index 252066f8681..00cce3110ee 100644 --- a/src/Compiler/Checking/CheckPatterns.fs +++ b/src/Compiler/Checking/CheckPatterns.fs @@ -486,7 +486,7 @@ and IsNameOf (cenv: cenv) (env: TcEnv) ad m (id: Ident) = let g = cenv.g id.idText = "nameof" && try - match ResolveExprLongIdent cenv.tcSink cenv.nameResolver m ad env.NameEnv TypeNameResolutionInfo.Default [id] with + match ResolveExprLongIdent cenv.tcSink cenv.nameResolver m ad env.NameEnv TypeNameResolutionInfo.Default [id] None with | Result (_, Item.Value vref, _) -> valRefEq g vref g.nameof_vref | _ -> false with _ -> false diff --git a/src/Compiler/Checking/NameResolution.fs b/src/Compiler/Checking/NameResolution.fs index bc658c6b89a..60bd4d66c9c 100644 --- a/src/Compiler/Checking/NameResolution.fs +++ b/src/Compiler/Checking/NameResolution.fs @@ -2577,7 +2577,7 @@ let CheckNestedTypesOfType (ncenv: NameResolver) (resInfo: ResolutionInfo) ad nm // the empty set of results, or "x.Length" for a list or array type. This indicates it could be worth adding a cache here. // maybeAppliedArgExpr is used in context of resolving extension method that would override property name, it may contain argExpr coming from the DelayedApp(argExpr: SynExpr) -// see RFC 1137 +// see RFC-1137 let rec ResolveLongIdentInTypePrim (ncenv: NameResolver) nenv lookupKind (resInfo: ResolutionInfo) depth m ad (id: Ident) (rest: Ident list) findFlag (typeNameResInfo: TypeNameResolutionInfo) ty (maybeAppliedArgExpr: SynExpr option) = let g = ncenv.g let m = unionRanges m id.idRange @@ -2618,7 +2618,7 @@ let rec ResolveLongIdentInTypePrim (ncenv: NameResolver) nenv lookupKind (resInf // fold the available extension members into the overload resolution let extensionPropInfos = ExtensionPropInfosOfTypeInScope ResultCollectionSettings.AllResults ncenv.InfoReader nenv optFilter isInstanceFilter ad m ty - + // make sure to keep the intrinsic pinfos before the extension pinfos in the list, // since later on this logic is used when giving preference to intrinsic definitions match DecodeFSharpEvent (pinfos@extensionPropInfos) ad g ncenv m with @@ -2632,7 +2632,7 @@ let rec ResolveLongIdentInTypePrim (ncenv: NameResolver) nenv lookupKind (resInf match maybeAppliedArgExpr with | None -> success [resInfo, x, rest] | Some _argExpr -> - // RFC 1137 prefer extension method when ... + // RFC-1137 prefer extension method when ... let ignoreProperty (p: PropInfo) = // do not hide properties if: @@ -2806,7 +2806,7 @@ let ResolveLongIdentInType sink (ncenv: NameResolver) nenv lookupKind m ad id fi ResolutionInfo.SendEntityPathToSink (sink, ncenv, nenv, ItemOccurence.UseInType, ad, resInfo, ResultTyparChecker(fun () -> CheckAllTyparsInferrable ncenv.amap m item)) item, rest -let private ResolveLongIdentInTyconRef (ncenv: NameResolver) nenv lookupKind (resInfo: ResolutionInfo) depth m ad id rest typeNameResInfo tcref = +let private ResolveLongIdentInTyconRef (ncenv: NameResolver) nenv lookupKind (resInfo: ResolutionInfo) depth m ad id rest typeNameResInfo tcref maybeAppliedArgExpr = #if !NO_TYPEPROVIDERS // No dotting through type generators to get to a member! CheckForDirectReferenceToGeneratedType (tcref, PermitDirectReferenceToGeneratedType.No, m) @@ -2815,12 +2815,12 @@ let private ResolveLongIdentInTyconRef (ncenv: NameResolver) nenv lookupKind (re match resInfo.EnclosingTypeInst with | [] -> FreshenTycon ncenv m tcref | tinstEnclosing -> FreshenTyconWithEnclosingTypeInst ncenv m tinstEnclosing tcref - ResolveLongIdentInTypePrim ncenv nenv lookupKind resInfo depth m ad id rest IgnoreOverrides typeNameResInfo ty None + ResolveLongIdentInTypePrim ncenv nenv lookupKind resInfo depth m ad id rest IgnoreOverrides typeNameResInfo ty maybeAppliedArgExpr -let private ResolveLongIdentInTyconRefs atMostOne (ncenv: NameResolver) nenv lookupKind depth m ad id rest typeNameResInfo idRange tcrefs = +let private ResolveLongIdentInTyconRefs atMostOne (ncenv: NameResolver) nenv lookupKind depth m ad id rest typeNameResInfo idRange tcrefs maybeAppliedArgExpr = tcrefs |> CollectResults2 atMostOne (fun (resInfo: ResolutionInfo, tcref) -> let resInfo = resInfo.AddEntity(idRange, tcref) - tcref |> ResolveLongIdentInTyconRef ncenv nenv lookupKind resInfo depth m ad id rest typeNameResInfo |> AtMostOneResult m) + ResolveLongIdentInTyconRef ncenv nenv lookupKind resInfo depth m ad id rest typeNameResInfo tcref maybeAppliedArgExpr |> AtMostOneResult m) //------------------------------------------------------------------------- // ResolveExprLongIdentInModuleOrNamespace @@ -2869,7 +2869,7 @@ let rec ResolveExprLongIdentInModuleOrNamespace (ncenv: NameResolver) nenv (type let typeNameResInfo = TypeNameResolutionInfo.ResolveToTypeRefs typeNameResInfo.StaticArgsInfo CheckForTypeLegitimacyAndMultipleGenericTypeAmbiguities (tcrefs, typeNameResInfo, PermitDirectReferenceToGeneratedType.No, unionRanges m id.idRange) - ResolveLongIdentInTyconRefs ResultCollectionSettings.AtMostOneResult ncenv nenv lookupKind (depth+1) m ad id2 rest2 typeNameResInfo id.idRange tcrefs + ResolveLongIdentInTyconRefs ResultCollectionSettings.AtMostOneResult ncenv nenv lookupKind (depth+1) m ad id2 rest2 typeNameResInfo id.idRange tcrefs None // Check if we've got some explicit type arguments | _ -> @@ -2967,7 +2967,7 @@ let ResolveUnqualifiedTyconRefs nenv tcrefs = /// Resolve F# "A.B.C" syntax in expressions /// Not all of the sequence will necessarily be swallowed, i.e. we return some identifiers /// that may represent further actions, e.g. further lookups. -let rec ResolveExprLongIdentPrim sink (ncenv: NameResolver) first fullyQualified m ad nenv (typeNameResInfo: TypeNameResolutionInfo) (id: Ident) (rest: Ident list) isOpenDecl = +let rec ResolveExprLongIdentPrim sink (ncenv: NameResolver) first fullyQualified m ad nenv (typeNameResInfo: TypeNameResolutionInfo) (id: Ident) (rest: Ident list) isOpenDecl maybeAppliedArgExpr = let lookupKind = LookupKind.Expr LookupIsInstance.No @@ -2985,9 +2985,9 @@ let rec ResolveExprLongIdentPrim sink (ncenv: NameResolver) first fullyQualified | [] -> raze (Error(FSComp.SR.nrGlobalUsedOnlyAsFirstName(), id.idRange)) | [next] -> - ResolveExprLongIdentPrim sink ncenv false fullyQualified m ad nenv typeNameResInfo next [] isOpenDecl + ResolveExprLongIdentPrim sink ncenv false fullyQualified m ad nenv typeNameResInfo next [] isOpenDecl maybeAppliedArgExpr | id2 :: rest2 -> - ResolveExprLongIdentPrim sink ncenv false FullyQualified m ad nenv typeNameResInfo id2 rest2 isOpenDecl + ResolveExprLongIdentPrim sink ncenv false FullyQualified m ad nenv typeNameResInfo id2 rest2 isOpenDecl maybeAppliedArgExpr else if isNil rest && fullyQualified <> FullyQualified then let mutable typeError = None @@ -3122,7 +3122,7 @@ let rec ResolveExprLongIdentPrim sink (ncenv: NameResolver) first fullyQualified let tcrefs = let typeNameResInfo = TypeNameResolutionInfo.ResolveToTypeRefs typeNameResInfo.StaticArgsInfo CheckForTypeLegitimacyAndMultipleGenericTypeAmbiguities (tcrefs, typeNameResInfo, PermitDirectReferenceToGeneratedType.No, unionRanges m id.idRange) - ResolveLongIdentInTyconRefs ResultCollectionSettings.AtMostOneResult ncenv nenv lookupKind 1 m ad id2 rest2 typeNameResInfo id.idRange tcrefs + ResolveLongIdentInTyconRefs ResultCollectionSettings.AtMostOneResult ncenv nenv lookupKind 1 m ad id2 rest2 typeNameResInfo id.idRange tcrefs maybeAppliedArgExpr | _ -> NoResultsOrUsefulErrors @@ -3176,10 +3176,10 @@ let rec ResolveExprLongIdentPrim sink (ncenv: NameResolver) first fullyQualified ResolutionInfo.SendEntityPathToSink(sink, ncenv, nenv, ItemOccurence.Use, ad, resInfo, ResultTyparChecker(fun () -> CheckAllTyparsInferrable ncenv.amap m item)) success (resInfo.EnclosingTypeInst, item, rest) -let ResolveExprLongIdent sink (ncenv: NameResolver) m ad nenv typeNameResInfo lid = +let ResolveExprLongIdent sink (ncenv: NameResolver) m ad nenv typeNameResInfo lid maybeAppliedArgExpr = match lid with | [] -> raze (Error(FSComp.SR.nrInvalidExpression(textOfLid lid), m)) - | id :: rest -> ResolveExprLongIdentPrim sink ncenv true OpenQualified m ad nenv typeNameResInfo id rest false + | id :: rest -> ResolveExprLongIdentPrim sink ncenv true OpenQualified m ad nenv typeNameResInfo id rest false maybeAppliedArgExpr //------------------------------------------------------------------------- // Resolve F#/IL "." syntax in patterns @@ -3217,7 +3217,7 @@ let rec ResolvePatternLongIdentInModuleOrNamespace (ncenv: NameResolver) nenv nu match rest with | id2 :: rest2 -> let tcrefs = tcrefs.Force() - ResolveLongIdentInTyconRefs ResultCollectionSettings.AtMostOneResult (ncenv: NameResolver) nenv LookupKind.Pattern (depth+1) m ad id2 rest2 numTyArgsOpt id.idRange tcrefs + ResolveLongIdentInTyconRefs ResultCollectionSettings.AtMostOneResult (ncenv: NameResolver) nenv LookupKind.Pattern (depth+1) m ad id2 rest2 numTyArgsOpt id.idRange tcrefs None | _ -> NoResultsOrUsefulErrors @@ -3320,7 +3320,7 @@ let rec ResolvePatternLongIdentPrim sink (ncenv: NameResolver) fullyQualified wa let tcrefs = LookupTypeNameInEnvNoArity fullyQualified id.idText nenv if isNil tcrefs then NoResultsOrUsefulErrors else let tcrefs = tcrefs |> List.map (fun tcref -> (ResolutionInfo.Empty, tcref)) - ResolveLongIdentInTyconRefs ResultCollectionSettings.AtMostOneResult ncenv nenv LookupKind.Pattern 1 id.idRange ad id2 rest2 numTyArgsOpt id.idRange tcrefs + ResolveLongIdentInTyconRefs ResultCollectionSettings.AtMostOneResult ncenv nenv LookupKind.Pattern 1 id.idRange ad id2 rest2 numTyArgsOpt id.idRange tcrefs None | _ -> NoResultsOrUsefulErrors @@ -3611,7 +3611,7 @@ let rec ResolveFieldInModuleOrNamespace (ncenv: NameResolver) nenv ad (resInfo: let tcrefs = LookupTypeNameInEntityMaybeHaveArity (ncenv.amap, id.idRange, ad, id.idText, TypeNameResolutionStaticArgsInfo.Indefinite, modref) if isNil tcrefs then NoResultsOrUsefulErrors else let tcrefs = tcrefs |> List.map (fun tcref -> (ResolutionInfo.Empty, tcref)) - let tyconSearch = ResolveLongIdentInTyconRefs ResultCollectionSettings.AllResults ncenv nenv LookupKind.RecdField (depth+1) m ad id2 rest2 typeNameResInfo id.idRange tcrefs + let tyconSearch = ResolveLongIdentInTyconRefs ResultCollectionSettings.AllResults ncenv nenv LookupKind.RecdField (depth+1) m ad id2 rest2 typeNameResInfo id.idRange tcrefs None // choose only fields let tyconSearch = tyconSearch |?> List.choose (function resInfo, Item.RecdField(RecdFieldInfo(_, rfref)), rest -> Some(resInfo, FieldResolution(FreshenRecdFieldRef ncenv m rfref, false), rest) | _ -> None) tyconSearch @@ -3740,7 +3740,7 @@ let ResolveFieldPrim sink (ncenv: NameResolver) nenv ad ty (mp, id: Ident) allFi let tcrefs = LookupTypeNameInEnvNoArity OpenQualified tn.idText nenv if isNil tcrefs then NoResultsOrUsefulErrors else let tcrefs = tcrefs |> List.map (fun tcref -> (ResolutionInfo.Empty, tcref)) - let tyconSearch = ResolveLongIdentInTyconRefs ResultCollectionSettings.AllResults ncenv nenv LookupKind.RecdField 1 m ad id2 rest2 typeNameResInfo tn.idRange tcrefs + let tyconSearch = ResolveLongIdentInTyconRefs ResultCollectionSettings.AllResults ncenv nenv LookupKind.RecdField 1 m ad id2 rest2 typeNameResInfo tn.idRange tcrefs None // choose only fields let tyconSearch = tyconSearch |?> List.choose (function resInfo, Item.RecdField(RecdFieldInfo(_, rfref)), rest -> Some(resInfo, FieldResolution(FreshenRecdFieldRef ncenv m rfref, false), rest) | _ -> None) tyconSearch @@ -3852,7 +3852,7 @@ let ResolveNestedField sink (ncenv: NameResolver) nenv ad recdTy lid = if isNil tcrefs then NoResultsOrUsefulErrors else - ResolveLongIdentInTyconRefs ResultCollectionSettings.AllResults ncenv nenv LookupKind.RecdField 1 tyconId.idRange ad fieldId rest typeNameResInfo fieldId.idRange tcrefs + ResolveLongIdentInTyconRefs ResultCollectionSettings.AllResults ncenv nenv LookupKind.RecdField 1 tyconId.idRange ad fieldId rest typeNameResInfo fieldId.idRange tcrefs None |?> List.choose (fun x -> match x with | _, (Item.RecdField _ as item), rest -> Some (fieldId, item, rest) @@ -3993,8 +3993,10 @@ type AfterResolution = /// Resolve a long identifier occurring in an expression position. /// /// Called for 'TypeName.Bar' - for VS IntelliSense, we can filter out instance members from method groups -let ResolveLongIdentAsExprAndComputeRange (sink: TcResultsSink) (ncenv: NameResolver) wholem ad nenv typeNameResInfo lid = - match ResolveExprLongIdent sink ncenv wholem ad nenv typeNameResInfo lid with +// maybeAppliedArgExpr is used in context of resolving extension method that would override property name, it may contain argExpr coming from the DelayedApp(argExpr: SynExpr) +// see RFC-1137 +let ResolveLongIdentAsExprAndComputeRange (sink: TcResultsSink) (ncenv: NameResolver) wholem ad nenv typeNameResInfo lid (maybeAppliedArgExpr: SynExpr option) = + match ResolveExprLongIdent sink ncenv wholem ad nenv typeNameResInfo lid maybeAppliedArgExpr with | Exception e -> Exception e | Result (tinstEnclosing, item1, rest) -> let itemRange = ComputeItemRange wholem lid rest diff --git a/src/Compiler/Checking/NameResolution.fsi b/src/Compiler/Checking/NameResolution.fsi index 08adc72ae3f..35f67c896d7 100755 --- a/src/Compiler/Checking/NameResolution.fsi +++ b/src/Compiler/Checking/NameResolution.fsi @@ -774,6 +774,7 @@ val internal ResolveExprLongIdent: nenv: NameResolutionEnv -> typeNameResInfo: TypeNameResolutionInfo -> lid: Ident list -> + maybeAppliedArgExpr: SynExpr option -> ResultOrException val internal getRecordFieldsInScope: NameResolutionEnv -> Item list @@ -794,6 +795,7 @@ val internal ResolveLongIdentAsExprAndComputeRange: nenv: NameResolutionEnv -> typeNameResInfo: TypeNameResolutionInfo -> lid: Ident list -> + maybeAppliedArgExpr: SynExpr option -> ResultOrException /// Resolve a long identifier occurring in an expression position, qualified by a type. diff --git a/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/ShadowStaticProperty.fsx b/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/ShadowStaticProperty.fsx new file mode 100644 index 00000000000..3d891da058a --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/ShadowStaticProperty.fsx @@ -0,0 +1,26 @@ +type Foo private () = + static let mutable x = 0 + static member X + with get () = x + and set v = x <- v + +module Exts = + type Foo with + static member X v = Foo.X <- v + +open Exts +Foo.X(1) + +if Foo.X <> 1 then + System.Environment.Exit 1 + +module Exts2 = + type Foo with + static member X v = Foo.X <- v * 2 + +open Exts2 + +Foo.X 2 + +if Foo.X <> 4 then + System.Environment.Exit 2 diff --git a/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/ShadowStaticProperty.fsx.il.bsl b/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/ShadowStaticProperty.fsx.il.bsl new file mode 100644 index 00000000000..ee9e1d3b8a2 --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/ShadowStaticProperty.fsx.il.bsl @@ -0,0 +1,193 @@ + + + + + +.assembly extern runtime { } +.assembly extern FSharp.Core { } +.assembly assembly +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32, + int32, + int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ) + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.mresource public FSharpSignatureData.assembly +{ + + +} +.mresource public FSharpOptimizationData.assembly +{ + + +} +.module assembly.dll + +.imagebase {value} +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 +.corflags 0x00000001 + + + + + +.class public abstract auto ansi sealed assembly + extends [runtime]System.Object +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .class auto ansi serializable nested public Foo + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 ) + .field static assembly int32 x + .field static assembly int32 init@1 + .method assembly specialname rtspecialname + instance void .ctor() cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: callvirt instance void [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: pop + IL_0008: ret + } + + .method public specialname static int32 + get_X() cil managed + { + + .maxstack 8 + IL_0000: volatile. + IL_0002: ldsfld int32 assembly/Foo::init@1 + IL_0007: ldc.i4.1 + IL_0008: bge.s IL_0011 + + IL_000a: call void [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives/IntrinsicFunctions::FailStaticInit() + IL_000f: br.s IL_0011 + + IL_0011: ldsfld int32 assembly/Foo::x + IL_0016: ret + } + + .method public specialname static void + set_X(int32 v) cil managed + { + + .maxstack 8 + IL_0000: volatile. + IL_0002: ldsfld int32 assembly/Foo::init@1 + IL_0007: ldc.i4.1 + IL_0008: bge.s IL_0011 + + IL_000a: call void [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives/IntrinsicFunctions::FailStaticInit() + IL_000f: br.s IL_0011 + + IL_0011: ldarg.0 + IL_0012: stsfld int32 assembly/Foo::x + IL_0017: ret + } + + .method private specialname rtspecialname static + void .cctor() cil managed + { + + .maxstack 8 + IL_0000: ldc.i4.0 + IL_0001: stsfld int32 ''.$assembly$fsx::init@ + IL_0006: ldsfld int32 ''.$assembly$fsx::init@ + IL_000b: pop + IL_000c: ret + } + + .property int32 X() + { + .set void assembly/Foo::set_X(int32) + .get int32 assembly/Foo::get_X() + } + } + + .class abstract auto ansi sealed nested public Exts2 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .method public static void Foo.X.Static(int32 v) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldc.i4.2 + IL_0002: mul + IL_0003: call void assembly/Foo::set_X(int32) + IL_0008: ret + } + + } + + .class abstract auto ansi sealed nested public Exts + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .method public static void Foo.X.Static(int32 v) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call void assembly/Foo::set_X(int32) + IL_0006: ret + } + + } + +} + +.class private abstract auto ansi sealed ''.$assembly$fsx + extends [runtime]System.Object +{ + .field static assembly int32 init@ + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) + .method private specialname rtspecialname static + void .cctor() cil managed + { + + .maxstack 8 + IL_0000: ldc.i4.0 + IL_0001: stsfld int32 assembly/Foo::x + IL_0006: ldc.i4.1 + IL_0007: volatile. + IL_0009: stsfld int32 assembly/Foo::init@1 + IL_000e: ldc.i4.1 + IL_000f: call void assembly/Foo::set_X(int32) + IL_0014: call int32 assembly/Foo::get_X() + IL_0019: ldc.i4.1 + IL_001a: beq.s IL_0024 + + IL_001c: ldc.i4.1 + IL_001d: call void [runtime]System.Environment::Exit(int32) + IL_0022: br.s IL_0024 + + IL_0024: ldc.i4.4 + IL_0025: call void assembly/Foo::set_X(int32) + IL_002a: call int32 assembly/Foo::get_X() + IL_002f: ldc.i4.4 + IL_0030: beq.s IL_003a + + IL_0032: ldc.i4.2 + IL_0033: call void [runtime]System.Environment::Exit(int32) + IL_0038: br.s IL_003a + + IL_003a: ret + } + +} + + + + + diff --git a/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/ShadowStaticProperty.fsx.support.added.later.err.bsl b/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/ShadowStaticProperty.fsx.support.added.later.err.bsl new file mode 100644 index 00000000000..5721a44c50f --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/ShadowStaticProperty.fsx.support.added.later.err.bsl @@ -0,0 +1,2 @@ +ShadowStaticProperty.fsx (12,1)-(12,6) typecheck error This value is not a function and cannot be applied. +ShadowStaticProperty.fsx (23,1)-(23,6) typecheck error This value is not a function and cannot be applied. \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/ShadowStaticProperty.fsx.support.added.later.il.bsl b/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/ShadowStaticProperty.fsx.support.added.later.il.bsl new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowingTests.fs b/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowingTests.fs index 4754cb7edb8..b990d7d9327 100644 --- a/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowingTests.fs +++ b/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowingTests.fs @@ -13,6 +13,7 @@ let [] folder = __SOURCE_DIRECTORY__ + "/PropertyShadowing" "ShadowWithTypeExtension.fsx" "ShadowingAndStillOkWithChainedCalls.fsx" "LinqCount.fsx" + "ShadowStaticProperty.fsx" |] )>] let ``can hide property`` compilation = @@ -31,6 +32,7 @@ let ``can hide property`` compilation = "ShadowWithTypeExtension.fsx" "ShadowingAndStillOkWithChainedCalls.fsx" "LinqCount.fsx" + "ShadowStaticProperty.fsx" |] , BaselineSuffix = ".support.added.later" )>] From dbdc338b4c5257bb665c2c691341e56b3461d30c Mon Sep 17 00:00:00 2001 From: Gauthier Segay Date: Sun, 22 Oct 2023 17:25:27 +0200 Subject: [PATCH 18/29] adjust DeclarationListInfo grouping logic to be specific to singling out extension method only, rather than the kind of all items (type and ctor method were being split, causing a test to fail and more entries in the completion list not related to accessing properties or extension methods). --- src/Compiler/Service/ServiceDeclarationLists.fs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Compiler/Service/ServiceDeclarationLists.fs b/src/Compiler/Service/ServiceDeclarationLists.fs index fbc3972f9c4..4d894a1f62d 100644 --- a/src/Compiler/Service/ServiceDeclarationLists.fs +++ b/src/Compiler/Service/ServiceDeclarationLists.fs @@ -1139,10 +1139,10 @@ type DeclarationListInfo(declarations: DeclarationListItem[], isForType: bool, i |> RemoveDuplicateCompletionItems g |> List.groupBy (fun x -> // RFC-1137 - // we do not solely group by item name but also add Kind, - // due to not desiring to merge Property and Method bearing same name - // (from type extension or extension methods). - x.Kind, + // we do not solely group by item name but also add a discriminator + // derived from Kind, due to not desiring to merge Property and + // extension Method bearing same name. + (match x.Kind with | CompletionItemKind.Method(isExtension=true) -> Some x.Kind | _ -> None), match x.Unresolved with | Some u -> match u.Namespace with From ce1753b37bf5f6809f4806559e0f251040ab19dd Mon Sep 17 00:00:00 2001 From: Gauthier Segay Date: Tue, 31 Oct 2023 01:32:52 +0100 Subject: [PATCH 19/29] add test checking the latest opened type extension takes precedence --- .../ShadowWithLastOpenedTypeExtensions.fsx | 46 ++ ...owWithLastOpenedTypeExtensions.fsx.err.bsl | 0 ...dowWithLastOpenedTypeExtensions.fsx.il.bsl | 557 ++++++++++++++++++ ...Extensions.fsx.support.added.later.err.bsl | 2 + ...eExtensions.fsx.support.added.later.il.bsl | 0 .../TypeExtensions/PropertyShadowingTests.fs | 2 + 6 files changed, 607 insertions(+) create mode 100644 tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/ShadowWithLastOpenedTypeExtensions.fsx create mode 100644 tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/ShadowWithLastOpenedTypeExtensions.fsx.err.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/ShadowWithLastOpenedTypeExtensions.fsx.il.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/ShadowWithLastOpenedTypeExtensions.fsx.support.added.later.err.bsl create mode 100644 tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/ShadowWithLastOpenedTypeExtensions.fsx.support.added.later.il.bsl diff --git a/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/ShadowWithLastOpenedTypeExtensions.fsx b/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/ShadowWithLastOpenedTypeExtensions.fsx new file mode 100644 index 00000000000..980fca2a2fd --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/ShadowWithLastOpenedTypeExtensions.fsx @@ -0,0 +1,46 @@ +#nowarn "52" +open System + +type Foo private () = + static let mutable x = 0 + static member X + with get () = x + and set v = x <- v + +module Exts = + type Foo with + static member X v = Foo.X <- v + +open Exts + +let todo1 = + async { + Foo.X(1) + if Foo.X <> 1 then + return Error 1 + else + return Ok () + } + +match todo1 |> Async.RunSynchronously with +| Ok _ -> () +| Error e -> System.Environment.Exit e + +module Exts2 = + type Foo with + static member X v = Foo.X <- v * 2 + +open Exts2 + +let todo2 = + async { + Foo.X(1) + if Foo.X <> 2 then + return Error 2 + else + return Ok () + } + +match todo2 |> Async.RunSynchronously with +| Ok _ -> () +| Error e -> System.Environment.Exit e diff --git a/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/ShadowWithLastOpenedTypeExtensions.fsx.err.bsl b/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/ShadowWithLastOpenedTypeExtensions.fsx.err.bsl new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/ShadowWithLastOpenedTypeExtensions.fsx.il.bsl b/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/ShadowWithLastOpenedTypeExtensions.fsx.il.bsl new file mode 100644 index 00000000000..2244a998dae --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/ShadowWithLastOpenedTypeExtensions.fsx.il.bsl @@ -0,0 +1,557 @@ + + + + + +.assembly extern runtime { } +.assembly extern FSharp.Core { } +.assembly assembly +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32, + int32, + int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 ) + .hash algorithm 0x00008004 + .ver 0:0:0:0 +} +.mresource public FSharpSignatureData.assembly +{ + + +} +.mresource public FSharpOptimizationData.assembly +{ + + +} +.module assembly.dll + +.imagebase {value} +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 +.corflags 0x00000001 + + + + + +.class public abstract auto ansi sealed assembly + extends [runtime]System.Object +{ + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .class auto ansi serializable nested public Foo + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 ) + .field static assembly int32 x + .field static assembly int32 init@4 + .method assembly specialname rtspecialname + instance void .ctor() cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: callvirt instance void [runtime]System.Object::.ctor() + IL_0006: ldarg.0 + IL_0007: pop + IL_0008: ret + } + + .method public specialname static int32 + get_X() cil managed + { + + .maxstack 8 + IL_0000: volatile. + IL_0002: ldsfld int32 assembly/Foo::init@4 + IL_0007: ldc.i4.1 + IL_0008: bge.s IL_0011 + + IL_000a: call void [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives/IntrinsicFunctions::FailStaticInit() + IL_000f: br.s IL_0011 + + IL_0011: ldsfld int32 assembly/Foo::x + IL_0016: ret + } + + .method public specialname static void + set_X(int32 v) cil managed + { + + .maxstack 8 + IL_0000: volatile. + IL_0002: ldsfld int32 assembly/Foo::init@4 + IL_0007: ldc.i4.1 + IL_0008: bge.s IL_0011 + + IL_000a: call void [FSharp.Core]Microsoft.FSharp.Core.LanguagePrimitives/IntrinsicFunctions::FailStaticInit() + IL_000f: br.s IL_0011 + + IL_0011: ldarg.0 + IL_0012: stsfld int32 assembly/Foo::x + IL_0017: ret + } + + .method private specialname rtspecialname static + void .cctor() cil managed + { + + .maxstack 8 + IL_0000: ldc.i4.0 + IL_0001: stsfld int32 ''.$assembly$fsx::init@ + IL_0006: ldsfld int32 ''.$assembly$fsx::init@ + IL_000b: pop + IL_000c: ret + } + + .property int32 X() + { + .set void assembly/Foo::set_X(int32) + .get int32 assembly/Foo::get_X() + } + } + + .class auto ansi serializable sealed nested assembly beforefieldinit 'todo1@20-1' + extends class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>,class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn> + { + .field public valuetype [FSharp.Core]Microsoft.FSharp.Core.FSharpResult`2 'value' + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) + .method assembly specialname rtspecialname + instance void .ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.FSharpResult`2 'value') cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>,class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn>::.ctor() + IL_0006: ldarg.0 + IL_0007: ldarg.1 + IL_0008: stfld valuetype [FSharp.Core]Microsoft.FSharp.Core.FSharpResult`2 assembly/'todo1@20-1'::'value' + IL_000d: ret + } + + .method public strict virtual instance class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn + Invoke(valuetype [FSharp.Core]Microsoft.FSharp.Control.AsyncActivation`1> ctxt) cil managed + { + + .maxstack 8 + IL_0000: ldarg.1 + IL_0001: ldarg.0 + IL_0002: ldfld valuetype [FSharp.Core]Microsoft.FSharp.Core.FSharpResult`2 assembly/'todo1@20-1'::'value' + IL_0007: tail. + IL_0009: call class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn valuetype [FSharp.Core]Microsoft.FSharp.Control.AsyncActivation`1>::Success(valuetype [FSharp.Core]Microsoft.FSharp.Control.AsyncActivation`1, + !0) + IL_000e: ret + } + + } + + .class auto ansi serializable sealed nested assembly beforefieldinit 'todo1@22-2' + extends class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>,class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn> + { + .field public valuetype [FSharp.Core]Microsoft.FSharp.Core.FSharpResult`2 'value' + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) + .method assembly specialname rtspecialname + instance void .ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.FSharpResult`2 'value') cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>,class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn>::.ctor() + IL_0006: ldarg.0 + IL_0007: ldarg.1 + IL_0008: stfld valuetype [FSharp.Core]Microsoft.FSharp.Core.FSharpResult`2 assembly/'todo1@22-2'::'value' + IL_000d: ret + } + + .method public strict virtual instance class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn + Invoke(valuetype [FSharp.Core]Microsoft.FSharp.Control.AsyncActivation`1> ctxt) cil managed + { + + .maxstack 8 + IL_0000: ldarg.1 + IL_0001: ldarg.0 + IL_0002: ldfld valuetype [FSharp.Core]Microsoft.FSharp.Core.FSharpResult`2 assembly/'todo1@22-2'::'value' + IL_0007: tail. + IL_0009: call class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn valuetype [FSharp.Core]Microsoft.FSharp.Control.AsyncActivation`1>::Success(valuetype [FSharp.Core]Microsoft.FSharp.Control.AsyncActivation`1, + !0) + IL_000e: ret + } + + } + + .class auto ansi serializable sealed nested assembly beforefieldinit todo1@18 + extends class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>> + { + .field static assembly initonly class assembly/todo1@18 @_instance + .method assembly specialname rtspecialname + instance void .ctor() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>>::.ctor() + IL_0006: ret + } + + .method public strict virtual instance class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1> + Invoke(class [FSharp.Core]Microsoft.FSharp.Core.Unit unitVar) cil managed + { + + .maxstack 6 + .locals init (valuetype [FSharp.Core]Microsoft.FSharp.Core.FSharpResult`2 V_0) + IL_0000: ldc.i4.1 + IL_0001: call void assembly/Foo::set_X(int32) + IL_0006: call int32 assembly/Foo::get_X() + IL_000b: ldc.i4.1 + IL_000c: beq.s IL_0023 + + IL_000e: ldc.i4.1 + IL_000f: call valuetype [FSharp.Core]Microsoft.FSharp.Core.FSharpResult`2 valuetype [FSharp.Core]Microsoft.FSharp.Core.FSharpResult`2::NewError(!1) + IL_0014: stloc.0 + IL_0015: ldloc.0 + IL_0016: newobj instance void assembly/'todo1@20-1'::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.FSharpResult`2) + IL_001b: tail. + IL_001d: call class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 [FSharp.Core]Microsoft.FSharp.Control.AsyncPrimitives::MakeAsync>(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn>) + IL_0022: ret + + IL_0023: ldnull + IL_0024: call valuetype [FSharp.Core]Microsoft.FSharp.Core.FSharpResult`2 valuetype [FSharp.Core]Microsoft.FSharp.Core.FSharpResult`2::NewOk(!0) + IL_0029: stloc.0 + IL_002a: ldloc.0 + IL_002b: newobj instance void assembly/'todo1@22-2'::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.FSharpResult`2) + IL_0030: tail. + IL_0032: call class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 [FSharp.Core]Microsoft.FSharp.Control.AsyncPrimitives::MakeAsync>(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn>) + IL_0037: ret + } + + .method private specialname rtspecialname static + void .cctor() cil managed + { + + .maxstack 10 + IL_0000: newobj instance void assembly/todo1@18::.ctor() + IL_0005: stsfld class assembly/todo1@18 assembly/todo1@18::@_instance + IL_000a: ret + } + + } + + .class auto ansi serializable sealed nested assembly beforefieldinit 'todo2@39-1' + extends class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>,class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn> + { + .field public valuetype [FSharp.Core]Microsoft.FSharp.Core.FSharpResult`2 'value' + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) + .method assembly specialname rtspecialname + instance void .ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.FSharpResult`2 'value') cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>,class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn>::.ctor() + IL_0006: ldarg.0 + IL_0007: ldarg.1 + IL_0008: stfld valuetype [FSharp.Core]Microsoft.FSharp.Core.FSharpResult`2 assembly/'todo2@39-1'::'value' + IL_000d: ret + } + + .method public strict virtual instance class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn + Invoke(valuetype [FSharp.Core]Microsoft.FSharp.Control.AsyncActivation`1> ctxt) cil managed + { + + .maxstack 8 + IL_0000: ldarg.1 + IL_0001: ldarg.0 + IL_0002: ldfld valuetype [FSharp.Core]Microsoft.FSharp.Core.FSharpResult`2 assembly/'todo2@39-1'::'value' + IL_0007: tail. + IL_0009: call class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn valuetype [FSharp.Core]Microsoft.FSharp.Control.AsyncActivation`1>::Success(valuetype [FSharp.Core]Microsoft.FSharp.Control.AsyncActivation`1, + !0) + IL_000e: ret + } + + } + + .class auto ansi serializable sealed nested assembly beforefieldinit 'todo2@41-2' + extends class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>,class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn> + { + .field public valuetype [FSharp.Core]Microsoft.FSharp.Core.FSharpResult`2 'value' + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) + .method assembly specialname rtspecialname + instance void .ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.FSharpResult`2 'value') cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>,class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn>::.ctor() + IL_0006: ldarg.0 + IL_0007: ldarg.1 + IL_0008: stfld valuetype [FSharp.Core]Microsoft.FSharp.Core.FSharpResult`2 assembly/'todo2@41-2'::'value' + IL_000d: ret + } + + .method public strict virtual instance class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn + Invoke(valuetype [FSharp.Core]Microsoft.FSharp.Control.AsyncActivation`1> ctxt) cil managed + { + + .maxstack 8 + IL_0000: ldarg.1 + IL_0001: ldarg.0 + IL_0002: ldfld valuetype [FSharp.Core]Microsoft.FSharp.Core.FSharpResult`2 assembly/'todo2@41-2'::'value' + IL_0007: tail. + IL_0009: call class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn valuetype [FSharp.Core]Microsoft.FSharp.Control.AsyncActivation`1>::Success(valuetype [FSharp.Core]Microsoft.FSharp.Control.AsyncActivation`1, + !0) + IL_000e: ret + } + + } + + .class auto ansi serializable sealed nested assembly beforefieldinit todo2@37 + extends class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>> + { + .field static assembly initonly class assembly/todo2@37 @_instance + .method assembly specialname rtspecialname + instance void .ctor() cil managed + { + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>>::.ctor() + IL_0006: ret + } + + .method public strict virtual instance class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1> + Invoke(class [FSharp.Core]Microsoft.FSharp.Core.Unit unitVar) cil managed + { + + .maxstack 6 + .locals init (valuetype [FSharp.Core]Microsoft.FSharp.Core.FSharpResult`2 V_0) + IL_0000: ldc.i4.2 + IL_0001: call void assembly/Foo::set_X(int32) + IL_0006: call int32 assembly/Foo::get_X() + IL_000b: ldc.i4.2 + IL_000c: beq.s IL_0023 + + IL_000e: ldc.i4.2 + IL_000f: call valuetype [FSharp.Core]Microsoft.FSharp.Core.FSharpResult`2 valuetype [FSharp.Core]Microsoft.FSharp.Core.FSharpResult`2::NewError(!1) + IL_0014: stloc.0 + IL_0015: ldloc.0 + IL_0016: newobj instance void assembly/'todo2@39-1'::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.FSharpResult`2) + IL_001b: tail. + IL_001d: call class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 [FSharp.Core]Microsoft.FSharp.Control.AsyncPrimitives::MakeAsync>(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn>) + IL_0022: ret + + IL_0023: ldnull + IL_0024: call valuetype [FSharp.Core]Microsoft.FSharp.Core.FSharpResult`2 valuetype [FSharp.Core]Microsoft.FSharp.Core.FSharpResult`2::NewOk(!0) + IL_0029: stloc.0 + IL_002a: ldloc.0 + IL_002b: newobj instance void assembly/'todo2@41-2'::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.FSharpResult`2) + IL_0030: tail. + IL_0032: call class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 [FSharp.Core]Microsoft.FSharp.Control.AsyncPrimitives::MakeAsync>(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2,class [FSharp.Core]Microsoft.FSharp.Control.AsyncReturn>) + IL_0037: ret + } + + .method private specialname rtspecialname static + void .cctor() cil managed + { + + .maxstack 10 + IL_0000: newobj instance void assembly/todo2@37::.ctor() + IL_0005: stsfld class assembly/todo2@37 assembly/todo2@37::@_instance + IL_000a: ret + } + + } + + .class abstract auto ansi sealed nested public Exts2 + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .method public static void Foo.X.Static(int32 v) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldc.i4.2 + IL_0002: mul + IL_0003: call void assembly/Foo::set_X(int32) + IL_0008: ret + } + + } + + .class abstract auto ansi sealed nested public Exts + extends [runtime]System.Object + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 ) + .method public static void Foo.X.Static(int32 v) cil managed + { + + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call void assembly/Foo::set_X(int32) + IL_0006: ret + } + + } + + .method public specialname static class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1> + get_todo1() cil managed + { + + .maxstack 8 + IL_0000: ldsfld class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1> ''.$assembly$fsx::todo1@16 + IL_0005: ret + } + + .method assembly specialname static valuetype [FSharp.Core]Microsoft.FSharp.Core.FSharpResult`2 + get_matchValue@25() cil managed + { + + .maxstack 8 + IL_0000: ldsfld valuetype [FSharp.Core]Microsoft.FSharp.Core.FSharpResult`2 ''.$assembly$fsx::matchValue@25 + IL_0005: ret + } + + .method public specialname static class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1> + get_todo2() cil managed + { + + .maxstack 8 + IL_0000: ldsfld class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1> ''.$assembly$fsx::todo2@35 + IL_0005: ret + } + + .method assembly specialname static valuetype [FSharp.Core]Microsoft.FSharp.Core.FSharpResult`2 + 'get_matchValue@44-1'() cil managed + { + + .maxstack 8 + IL_0000: ldsfld valuetype [FSharp.Core]Microsoft.FSharp.Core.FSharpResult`2 ''.$assembly$fsx::'matchValue@44-1' + IL_0005: ret + } + + .property class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1> + todo1() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 09 00 00 00 00 00 ) + .get class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1> assembly::get_todo1() + } + .property valuetype [FSharp.Core]Microsoft.FSharp.Core.FSharpResult`2 + matchValue@25() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 09 00 00 00 00 00 ) + .get valuetype [FSharp.Core]Microsoft.FSharp.Core.FSharpResult`2 assembly::get_matchValue@25() + } + .property class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1> + todo2() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 09 00 00 00 00 00 ) + .get class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1> assembly::get_todo2() + } + .property valuetype [FSharp.Core]Microsoft.FSharp.Core.FSharpResult`2 + 'matchValue@44-1'() + { + .custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 09 00 00 00 00 00 ) + .get valuetype [FSharp.Core]Microsoft.FSharp.Core.FSharpResult`2 assembly::'get_matchValue@44-1'() + } +} + +.class private abstract auto ansi sealed ''.$assembly$fsx + extends [runtime]System.Object +{ + .field static assembly initonly class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1> todo1@16 + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field static assembly initonly valuetype [FSharp.Core]Microsoft.FSharp.Core.FSharpResult`2 matchValue@25 + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field static assembly initonly class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1> todo2@35 + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field static assembly initonly valuetype [FSharp.Core]Microsoft.FSharp.Core.FSharpResult`2 'matchValue@44-1' + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .field static assembly int32 init@ + .custom instance void [runtime]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [runtime]System.Diagnostics.DebuggerBrowsableState) = ( 01 00 00 00 00 00 00 00 ) + .custom instance void [runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) + .custom instance void [runtime]System.Diagnostics.DebuggerNonUserCodeAttribute::.ctor() = ( 01 00 00 00 ) + .method private specialname rtspecialname static + void .cctor() cil managed + { + + .maxstack 5 + IL_0000: ldc.i4.0 + IL_0001: stsfld int32 assembly/Foo::x + IL_0006: ldc.i4.1 + IL_0007: volatile. + IL_0009: stsfld int32 assembly/Foo::init@4 + IL_000e: call class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::get_DefaultAsyncBuilder() + IL_0013: ldsfld class assembly/todo1@18 assembly/todo1@18::@_instance + IL_0018: callvirt instance class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder::Delay>(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>) + IL_001d: stsfld class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1> ''.$assembly$fsx::todo1@16 + IL_0022: call class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1> assembly::get_todo1() + IL_0027: ldnull + IL_0028: ldnull + IL_0029: call !!0 [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync::RunSynchronously>(class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1, + class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1, + class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1) + IL_002e: stsfld valuetype [FSharp.Core]Microsoft.FSharp.Core.FSharpResult`2 ''.$assembly$fsx::matchValue@25 + IL_0033: ldsflda valuetype [FSharp.Core]Microsoft.FSharp.Core.FSharpResult`2 ''.$assembly$fsx::matchValue@25 + IL_0038: call instance int32 valuetype [FSharp.Core]Microsoft.FSharp.Core.FSharpResult`2::get_Tag() + IL_003d: ldc.i4.1 + IL_003e: bne.un.s IL_0042 + + IL_0040: br.s IL_0044 + + IL_0042: br.s IL_0053 + + IL_0044: ldsflda valuetype [FSharp.Core]Microsoft.FSharp.Core.FSharpResult`2 ''.$assembly$fsx::matchValue@25 + IL_0049: call instance !1 valuetype [FSharp.Core]Microsoft.FSharp.Core.FSharpResult`2::get_ErrorValue() + IL_004e: call void [runtime]System.Environment::Exit(int32) + IL_0053: call class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder [FSharp.Core]Microsoft.FSharp.Core.ExtraTopLevelOperators::get_DefaultAsyncBuilder() + IL_0058: ldsfld class assembly/todo2@37 assembly/todo2@37::@_instance + IL_005d: callvirt instance class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1 [FSharp.Core]Microsoft.FSharp.Control.FSharpAsyncBuilder::Delay>(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2>) + IL_0062: stsfld class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1> ''.$assembly$fsx::todo2@35 + IL_0067: call class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1> assembly::get_todo2() + IL_006c: ldnull + IL_006d: ldnull + IL_006e: call !!0 [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync::RunSynchronously>(class [FSharp.Core]Microsoft.FSharp.Control.FSharpAsync`1, + class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1, + class [FSharp.Core]Microsoft.FSharp.Core.FSharpOption`1) + IL_0073: stsfld valuetype [FSharp.Core]Microsoft.FSharp.Core.FSharpResult`2 ''.$assembly$fsx::'matchValue@44-1' + IL_0078: ldsflda valuetype [FSharp.Core]Microsoft.FSharp.Core.FSharpResult`2 ''.$assembly$fsx::'matchValue@44-1' + IL_007d: call instance int32 valuetype [FSharp.Core]Microsoft.FSharp.Core.FSharpResult`2::get_Tag() + IL_0082: ldc.i4.1 + IL_0083: bne.un.s IL_0087 + + IL_0085: br.s IL_0089 + + IL_0087: br.s IL_0098 + + IL_0089: ldsflda valuetype [FSharp.Core]Microsoft.FSharp.Core.FSharpResult`2 ''.$assembly$fsx::'matchValue@44-1' + IL_008e: call instance !1 valuetype [FSharp.Core]Microsoft.FSharp.Core.FSharpResult`2::get_ErrorValue() + IL_0093: call void [runtime]System.Environment::Exit(int32) + IL_0098: ret + } + +} + + + + + diff --git a/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/ShadowWithLastOpenedTypeExtensions.fsx.support.added.later.err.bsl b/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/ShadowWithLastOpenedTypeExtensions.fsx.support.added.later.err.bsl new file mode 100644 index 00000000000..8ba0a6f2ffb --- /dev/null +++ b/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/ShadowWithLastOpenedTypeExtensions.fsx.support.added.later.err.bsl @@ -0,0 +1,2 @@ +ShadowWithLastOpenedTypeExtensions.fsx (18,9)-(18,14) typecheck error This value is not a function and cannot be applied. +ShadowWithLastOpenedTypeExtensions.fsx (37,9)-(37,14) typecheck error This value is not a function and cannot be applied. \ No newline at end of file diff --git a/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/ShadowWithLastOpenedTypeExtensions.fsx.support.added.later.il.bsl b/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowing/ShadowWithLastOpenedTypeExtensions.fsx.support.added.later.il.bsl new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowingTests.fs b/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowingTests.fs index b990d7d9327..fe178ad1975 100644 --- a/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowingTests.fs +++ b/tests/FSharp.Compiler.ComponentTests/TypeChecks/TypeExtensions/PropertyShadowingTests.fs @@ -14,6 +14,7 @@ let [] folder = __SOURCE_DIRECTORY__ + "/PropertyShadowing" "ShadowingAndStillOkWithChainedCalls.fsx" "LinqCount.fsx" "ShadowStaticProperty.fsx" + "ShadowWithLastOpenedTypeExtensions.fsx" |] )>] let ``can hide property`` compilation = @@ -33,6 +34,7 @@ let ``can hide property`` compilation = "ShadowingAndStillOkWithChainedCalls.fsx" "LinqCount.fsx" "ShadowStaticProperty.fsx" + "ShadowWithLastOpenedTypeExtensions.fsx" |] , BaselineSuffix = ".support.added.later" )>] From 868dd90a14bd124546c2ec054b4f8345e977f2c9 Mon Sep 17 00:00:00 2001 From: Gauthier Segay Date: Tue, 31 Oct 2023 02:25:40 +0100 Subject: [PATCH 20/29] minimize diff --- src/Compiler/Checking/NameResolution.fs | 4 ++-- src/Compiler/Facilities/LanguageFeatures.fs | 2 -- src/Compiler/Symbols/SymbolHelpers.fs | 2 -- 3 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/Compiler/Checking/NameResolution.fs b/src/Compiler/Checking/NameResolution.fs index 17e1210c9a7..e6c59edcd5f 100644 --- a/src/Compiler/Checking/NameResolution.fs +++ b/src/Compiler/Checking/NameResolution.fs @@ -2618,7 +2618,7 @@ let rec ResolveLongIdentInTypePrim (ncenv: NameResolver) nenv lookupKind (resInf // fold the available extension members into the overload resolution let extensionPropInfos = ExtensionPropInfosOfTypeInScope ResultCollectionSettings.AllResults ncenv.InfoReader nenv optFilter isInstanceFilter ad m ty - + // make sure to keep the intrinsic pinfos before the extension pinfos in the list, // since later on this logic is used when giving preference to intrinsic definitions match DecodeFSharpEvent (pinfos@extensionPropInfos) ad g ncenv m with @@ -4057,7 +4057,7 @@ let (|NonOverridable|_|) namedItem = /// Called for 'expression.Bar' - for VS IntelliSense, we can filter out static members from method groups /// Also called for 'GenericType.Bar' - for VS IntelliSense, we can filter out non-static members from method groups let ResolveExprDotLongIdentAndComputeRange (sink: TcResultsSink) (ncenv: NameResolver) wholem ad nenv ty lid (typeNameResInfo: TypeNameResolutionInfo) findFlag staticOnly maybeAppliedArgExpr = - let inline resolveExpr findFlag = + let resolveExpr findFlag = let resInfo, item, rest = match lid with | id :: rest -> diff --git a/src/Compiler/Facilities/LanguageFeatures.fs b/src/Compiler/Facilities/LanguageFeatures.fs index 204cccfd9d3..0be7dacab18 100644 --- a/src/Compiler/Facilities/LanguageFeatures.fs +++ b/src/Compiler/Facilities/LanguageFeatures.fs @@ -186,8 +186,6 @@ type LanguageVersion(versionText) = // F# preview LanguageFeature.FromEndSlicing, previewVersion LanguageFeature.UnmanagedConstraintCsharpInterop, previewVersion - - // F# preview next LanguageFeature.PreferExtensionMethodOverPlainProperty, previewVersion ] diff --git a/src/Compiler/Symbols/SymbolHelpers.fs b/src/Compiler/Symbols/SymbolHelpers.fs index c2e4a3cccac..2d03e413cd8 100644 --- a/src/Compiler/Symbols/SymbolHelpers.fs +++ b/src/Compiler/Symbols/SymbolHelpers.fs @@ -408,8 +408,6 @@ module internal SymbolHelpers = //| _ -> false - - member x.Equals(item1, item2) = // This may explore assemblies that are not in the reference set. // In this case just bail out and assume items are not equal From 6efe48d9ebc1e78113cd2ebd37cf25f3fde69cc8 Mon Sep 17 00:00:00 2001 From: Gauthier Segay Date: Tue, 31 Oct 2023 02:27:17 +0100 Subject: [PATCH 21/29] minimize diff --- src/Compiler/Symbols/SymbolHelpers.fs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Compiler/Symbols/SymbolHelpers.fs b/src/Compiler/Symbols/SymbolHelpers.fs index 2d03e413cd8..6e4dbc284fe 100644 --- a/src/Compiler/Symbols/SymbolHelpers.fs +++ b/src/Compiler/Symbols/SymbolHelpers.fs @@ -407,7 +407,7 @@ module internal SymbolHelpers = | Item.ModuleOrNamespaces [] -> false //| _ -> false - + member x.Equals(item1, item2) = // This may explore assemblies that are not in the reference set. // In this case just bail out and assume items are not equal From 6a9791f6cc5f6e59ca729917e991b827d00541dc Mon Sep 17 00:00:00 2001 From: Vlad Zarytovskii Date: Wed, 1 Nov 2023 19:07:17 +0100 Subject: [PATCH 22/29] Fix test (new error message) --- tests/fsharp/typecheck/sigs/neg02.vsbsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/fsharp/typecheck/sigs/neg02.vsbsl b/tests/fsharp/typecheck/sigs/neg02.vsbsl index 46e4ce5cb46..9249fc3adba 100644 --- a/tests/fsharp/typecheck/sigs/neg02.vsbsl +++ b/tests/fsharp/typecheck/sigs/neg02.vsbsl @@ -7,4 +7,4 @@ neg02.fs(17,21,17,26): typecheck error FS3351: Feature 'static abstract interfac neg02.fs(17,21,17,26): typecheck error FS3350: Feature 'static abstract interface members' is not available in F# 6.0. Please use language version 7.0 or greater. -neg02.fs(17,21,17,24): typecheck error FS0855: No abstract or interface member was found that corresponds to this override +neg02.fs(17,21,17,24): typecheck error FS0855: No static abstract member was found that corresponds to this override From 61b583fec7fdc948a0d7d5573ea572d7cbfdb30a Mon Sep 17 00:00:00 2001 From: Gauthier Segay Date: Fri, 10 Nov 2023 17:23:42 +0100 Subject: [PATCH 23/29] fix bad merge on baseline file --- tests/fsharp/typecheck/sigs/neg02.vsbsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/fsharp/typecheck/sigs/neg02.vsbsl b/tests/fsharp/typecheck/sigs/neg02.vsbsl index 9249fc3adba..67d2399013a 100644 --- a/tests/fsharp/typecheck/sigs/neg02.vsbsl +++ b/tests/fsharp/typecheck/sigs/neg02.vsbsl @@ -7,4 +7,4 @@ neg02.fs(17,21,17,26): typecheck error FS3351: Feature 'static abstract interfac neg02.fs(17,21,17,26): typecheck error FS3350: Feature 'static abstract interface members' is not available in F# 6.0. Please use language version 7.0 or greater. -neg02.fs(17,21,17,24): typecheck error FS0855: No static abstract member was found that corresponds to this override +neg02.fs(17,21,17,24): typecheck error FS0855: No abstract or interface member was found that corresponds to this override \ No newline at end of file From cbbcb02a2c3892dfb9b7840b209dd8aedaa25c1d Mon Sep 17 00:00:00 2001 From: Gauthier Segay Date: Fri, 10 Nov 2023 17:33:02 +0100 Subject: [PATCH 24/29] better comments explaining the properties that are singled out / can't be overtaken by extension methods. --- src/Compiler/Checking/NameResolution.fs | 15 +++++++++++++-- src/Compiler/Checking/infos.fs | 5 +++++ src/Compiler/Checking/infos.fsi | 5 +++++ 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/src/Compiler/Checking/NameResolution.fs b/src/Compiler/Checking/NameResolution.fs index 2cc31be9227..c5e50a97a30 100644 --- a/src/Compiler/Checking/NameResolution.fs +++ b/src/Compiler/Checking/NameResolution.fs @@ -2642,8 +2642,19 @@ let rec ResolveLongIdentInTypePrim (ncenv: NameResolver) nenv lookupKind (resInf let ignoreProperty (p: PropInfo) = // do not hide properties if: - // * is indexed property - // * is function type + // * is indexed property e.g.: + // ```fsharp + // member x.Prop with + // get (indexPiece1:int,indexPiece2: string) = ... + // and set (indexPiece1:int,indexPiece2: string) value = ... + // ``` + // which is called like this: obj.Prop(1,"a") or obj.Prop(1,"a") <- someValue + // * is function type e.g.: + // ```fsharp + // member x.Prop with + // get () = fun a -> printfn $"{a}" + // ``` + // which is called like this: obj.Prop 123 if p.IsIndexer then true else diff --git a/src/Compiler/Checking/infos.fs b/src/Compiler/Checking/infos.fs index af33e162200..05f361c1f81 100644 --- a/src/Compiler/Checking/infos.fs +++ b/src/Compiler/Checking/infos.fs @@ -1851,6 +1851,11 @@ type PropInfo = | None -> false /// Indicates if this property is an indexer property, i.e. a property with arguments. + /// + /// member x.Prop with + /// get (indexPiece1:int,indexPiece2: string) = ... + /// and set (indexPiece1:int,indexPiece2: string) value = ... + /// member x.IsIndexer = match x with | ILProp(ILPropInfo(_, pdef)) -> pdef.Args.Length <> 0 diff --git a/src/Compiler/Checking/infos.fsi b/src/Compiler/Checking/infos.fsi index 5f6aab66a91..ee3131d67fe 100644 --- a/src/Compiler/Checking/infos.fsi +++ b/src/Compiler/Checking/infos.fsi @@ -836,6 +836,11 @@ type PropInfo = member IsFSharpExplicitInterfaceImplementation: bool /// Indicates if this property is an indexer property, i.e. a property with arguments. + /// + /// member x.Prop with + /// get (indexPiece1:int,indexPiece2: string) = ... + /// and set (indexPiece1:int,indexPiece2: string) value = ... + /// member IsIndexer: bool /// Indicates if the property is logically a 'newslot', i.e. hides any previous slots of the same name. From 15e29112e872f551f88de22cf6a15dc0e1754fdd Mon Sep 17 00:00:00 2001 From: Gauthier Segay Date: Sat, 11 Nov 2023 01:45:35 +0100 Subject: [PATCH 25/29] revisit DeclarationListInfo.Create to avoid regression where we'd show both event and extension method (only event can be called). The new logic 100% preserves the previous behaviour in absence of the particular condition we are interested for in RFC-1137. In case the condition for RFC-1137 hits, we partition the items for those to be split apart (property and extension methods), taking care of discarding items as we yield the expected tuples that correspond to each item and the rest is processed as it was originally. There are still probably loopholes with items showing up separated, but this would only impact if there are actually extension method and property with same name. --- .../Service/ServiceDeclarationLists.fs | 84 +++++++++++++++---- 1 file changed, 66 insertions(+), 18 deletions(-) diff --git a/src/Compiler/Service/ServiceDeclarationLists.fs b/src/Compiler/Service/ServiceDeclarationLists.fs index 4d894a1f62d..2aaaa4ddac2 100644 --- a/src/Compiler/Service/ServiceDeclarationLists.fs +++ b/src/Compiler/Service/ServiceDeclarationLists.fs @@ -1128,6 +1128,7 @@ type DeclarationListInfo(declarations: DeclarationListItem[], isForType: bool, i ) (0, 0, []) if verbose then dprintf "service.ml: mkDecls: %d found groups after filtering\n" (List.length items); + let supportsPreferExtsMethodsOverProperty = denv.g.langVersion.SupportsFeature Features.LanguageFeature.PreferExtensionMethodOverPlainProperty // Group by full name for unresolved items and by display name for resolved ones. let decls = @@ -1138,33 +1139,80 @@ type DeclarationListInfo(declarations: DeclarationListItem[], isForType: bool, i // Remove all duplicates. We've put the types first, so this removes the DelegateCtor and DefaultStructCtor's. |> RemoveDuplicateCompletionItems g |> List.groupBy (fun x -> - // RFC-1137 - // we do not solely group by item name but also add a discriminator - // derived from Kind, due to not desiring to merge Property and - // extension Method bearing same name. - (match x.Kind with | CompletionItemKind.Method(isExtension=true) -> Some x.Kind | _ -> None), - match x.Unresolved with - | Some u -> - match u.Namespace with - | [||] -> u.DisplayName - | ns -> (ns |> String.concat ".") + "." + u.DisplayName - | None -> x.Item.DisplayName) - - |> List.map (fun (_, items) -> - let item = items.Head - let textInDeclList = + match x.Unresolved with + | Some u -> + match u.Namespace with + | [||] -> u.DisplayName + | ns -> (ns |> String.concat ".") + "." + u.DisplayName + | None -> x.Item.DisplayName) + |> List.map ( + let textInDeclList item = match item.Unresolved with | Some u -> u.DisplayName | None -> item.Item.DisplayNameCore - let textInCode = + let textInCode (item: CompletionItem) = match item.Item with | Item.TypeVar (name, typar) -> (if typar.StaticReq = Syntax.TyparStaticReq.None then "'" else " ^") + name | _ -> match item.Unresolved with | Some u -> u.DisplayName | None -> item.Item.DisplayName - textInDeclList, textInCode, items) - + if not supportsPreferExtsMethodsOverProperty then + // we don't pay the cost of filtering specific to RFC-1137 + // nor risk a change in behaviour for the intellisense item list + // if the feature is disabled + fun (_, items) -> + let item = items.Head + [textInDeclList item, textInCode item, items] + else + // RFC-1137 shenanigans: + // due to not desiring to merge Property and extension Method bearing same name, + // but still merging extension method if it tries to shadow other stuff than a Property + // we proceed with a pre-scan to see if we hit the particular case, in which case we partition + // items to be split and those that were initially remaining grouped. + // If we don't hit the specific case, or have a single entry, we keep the same logic as originally + // N.B: due to the logic returning 1 to N instead of 1, the next stage of the pipeline is List.concat + // introduced for this RFC + let hasBothPropertiesAndExtensionMethods items = + let rec inner hasProperty hasExtensionMethod items = + if hasProperty && hasExtensionMethod then + true + else + match items with + | [] -> hasProperty && hasExtensionMethod + | item :: tail when item.Kind = CompletionItemKind.Property -> inner true hasExtensionMethod tail + | item :: tail when item.Kind = CompletionItemKind.Method(isExtension=true) -> inner hasProperty true tail + | _ :: tail -> inner hasProperty hasExtensionMethod tail + inner false false items + function + | _, ([_] as items) + | _,items when not (hasBothPropertiesAndExtensionMethods items) -> + let item = items.Head + [textInDeclList item, textInCode item, items] + | _, items (* RFC-1137 we have both property and extension method ...*) -> + let toSplit, together = + items + |> List.partition + (fun item -> + match item.Kind with + | CompletionItemKind.Property | CompletionItemKind.Method(isExtension=true) -> true + | _ -> false + ) + [ + let rec createSublists list = + match list with + | [] -> [] + | _::tail -> list :: createSublists tail + for items in createSublists toSplit do + let item = items.Head + textInDeclList item, textInCode item, items + if not together.IsEmpty then + let item = together.Head + textInDeclList item, textInCode item, items + ] + ) + // RFC-1137: concat previous result + |> List.concat // Filter out operators, active patterns (as values) |> List.filter (fun (_textInDeclList, textInCode, items) -> not (isOperatorItem textInCode items) && From da5d08c1ecb3fc9e2a5d7796e37d0a73aa1ecbcd Mon Sep 17 00:00:00 2001 From: Gauthier Segay Date: Sat, 11 Nov 2023 01:48:00 +0100 Subject: [PATCH 26/29] minimize diff --- tests/fsharp/typecheck/sigs/neg02.vsbsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/fsharp/typecheck/sigs/neg02.vsbsl b/tests/fsharp/typecheck/sigs/neg02.vsbsl index 67d2399013a..46e4ce5cb46 100644 --- a/tests/fsharp/typecheck/sigs/neg02.vsbsl +++ b/tests/fsharp/typecheck/sigs/neg02.vsbsl @@ -7,4 +7,4 @@ neg02.fs(17,21,17,26): typecheck error FS3351: Feature 'static abstract interfac neg02.fs(17,21,17,26): typecheck error FS3350: Feature 'static abstract interface members' is not available in F# 6.0. Please use language version 7.0 or greater. -neg02.fs(17,21,17,24): typecheck error FS0855: No abstract or interface member was found that corresponds to this override \ No newline at end of file +neg02.fs(17,21,17,24): typecheck error FS0855: No abstract or interface member was found that corresponds to this override From 33c6a9ab8c06bab8e10281031c246358ccfad0c6 Mon Sep 17 00:00:00 2001 From: Gauthier Segay Date: Sat, 11 Nov 2023 03:12:56 +0100 Subject: [PATCH 27/29] try to make fantomas happy, despite I don't see the difference --- src/Compiler/Checking/infos.fsi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Compiler/Checking/infos.fsi b/src/Compiler/Checking/infos.fsi index ee3131d67fe..041c652650a 100644 --- a/src/Compiler/Checking/infos.fsi +++ b/src/Compiler/Checking/infos.fsi @@ -837,9 +837,9 @@ type PropInfo = /// Indicates if this property is an indexer property, i.e. a property with arguments. /// - /// member x.Prop with + /// member x.Prop with /// get (indexPiece1:int,indexPiece2: string) = ... - /// and set (indexPiece1:int,indexPiece2: string) value = ... + /// and set (indexPiece1:int,indexPiece2: string) value = ... /// member IsIndexer: bool From 54c0cb9f6e8bbb0fa097a635c88d8fb51d4f1ef5 Mon Sep 17 00:00:00 2001 From: Gauthier Segay Date: Sat, 11 Nov 2023 08:19:22 +0100 Subject: [PATCH 28/29] minimize diff --- src/Compiler/Service/ServiceDeclarationLists.fs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Compiler/Service/ServiceDeclarationLists.fs b/src/Compiler/Service/ServiceDeclarationLists.fs index 2aaaa4ddac2..c1326641789 100644 --- a/src/Compiler/Service/ServiceDeclarationLists.fs +++ b/src/Compiler/Service/ServiceDeclarationLists.fs @@ -1139,12 +1139,12 @@ type DeclarationListInfo(declarations: DeclarationListItem[], isForType: bool, i // Remove all duplicates. We've put the types first, so this removes the DelegateCtor and DefaultStructCtor's. |> RemoveDuplicateCompletionItems g |> List.groupBy (fun x -> - match x.Unresolved with - | Some u -> - match u.Namespace with - | [||] -> u.DisplayName - | ns -> (ns |> String.concat ".") + "." + u.DisplayName - | None -> x.Item.DisplayName) + match x.Unresolved with + | Some u -> + match u.Namespace with + | [||] -> u.DisplayName + | ns -> (ns |> String.concat ".") + "." + u.DisplayName + | None -> x.Item.DisplayName) |> List.map ( let textInDeclList item = match item.Unresolved with From 4d49ba5e7d8682429afdbb07ef6f7be613d62d02 Mon Sep 17 00:00:00 2001 From: Gauthier Segay Date: Sat, 11 Nov 2023 08:24:42 +0100 Subject: [PATCH 29/29] formatting & add a comment explaining usage of `createSublists` --- src/Compiler/Service/ServiceDeclarationLists.fs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Compiler/Service/ServiceDeclarationLists.fs b/src/Compiler/Service/ServiceDeclarationLists.fs index c1326641789..1251432d51c 100644 --- a/src/Compiler/Service/ServiceDeclarationLists.fs +++ b/src/Compiler/Service/ServiceDeclarationLists.fs @@ -1202,7 +1202,12 @@ type DeclarationListInfo(declarations: DeclarationListItem[], isForType: bool, i let rec createSublists list = match list with | [] -> [] - | _::tail -> list :: createSublists tail + | _ :: tail -> list :: createSublists tail + + // we use createSublists here so the `items` sent down the + // pipeline have their first element being the actual + // item, in order for the glyph to be the correct one + // notice how the later stage uses `GlyphOfItem(denv,items.Head)` for items in createSublists toSplit do let item = items.Head textInDeclList item, textInCode item, items