From f939b71c6efd0e2faf794de6be59cc59cc8b5b9d Mon Sep 17 00:00:00 2001 From: Alfonso Garcia-Caro Date: Mon, 29 Aug 2022 23:10:17 +0900 Subject: [PATCH] Don't lose attributes of method parameters (#12) Temporary fix, remove when upstream dotnet#13786 is fixed. --- src/Compiler/Checking/CheckComputationExpressions.fs | 2 +- src/Compiler/Checking/CheckExpressions.fs | 7 ++++--- src/Compiler/Checking/MethodCalls.fs | 2 +- src/Compiler/Checking/NicePrint.fs | 4 ++-- src/Compiler/Checking/PostInferenceChecks.fs | 4 ++-- src/Compiler/Checking/infos.fs | 12 ++++++------ src/Compiler/Checking/infos.fsi | 6 +++--- src/Compiler/Service/FSharpCheckerResults.fs | 2 +- src/Compiler/Service/ServiceDeclarationLists.fs | 2 +- src/Compiler/Symbols/Symbols.fs | 6 ++---- 10 files changed, 23 insertions(+), 24 deletions(-) diff --git a/src/Compiler/Checking/CheckComputationExpressions.fs b/src/Compiler/Checking/CheckComputationExpressions.fs index 0f98af01961c..8aa0924514f4 100644 --- a/src/Compiler/Checking/CheckComputationExpressions.fs +++ b/src/Compiler/Checking/CheckComputationExpressions.fs @@ -434,7 +434,7 @@ let TcComputationExpression (cenv: cenv) env (overallTy: OverallTy) tpenv (mWhol argInfos |> List.map (fun (_nm, __maintainsVarSpaceUsingBind, _maintainsVarSpace, _allowInto, _isLikeZip, _isLikeJoin, _isLikeGroupJoin, _joinConditionWord, methInfo) -> match methInfo.GetParamAttribs(cenv.amap, mWhole) with - | [curriedArgInfo] -> Some curriedArgInfo // one for the actual argument group + | [curriedArgInfo] -> Some (List.map fst curriedArgInfo) // one for the actual argument group | _ -> None) |> Some | _ -> None diff --git a/src/Compiler/Checking/CheckExpressions.fs b/src/Compiler/Checking/CheckExpressions.fs index 1b65421daba1..04bed1f183bf 100644 --- a/src/Compiler/Checking/CheckExpressions.fs +++ b/src/Compiler/Checking/CheckExpressions.fs @@ -4043,7 +4043,7 @@ and TcPseudoMemberSpec cenv newOk env synTypes tpenv synMemberSig m = let logicalCompiledName = ComputeLogicalName id memberFlags for argInfos in curriedArgInfos do for argInfo in argInfos do - let info = CrackParamAttribsInfo g argInfo + let info, _ = CrackParamAttribsInfo g argInfo let (ParamAttribs(isParamArrayArg, isInArg, isOutArg, optArgInfo, callerInfo, reflArgInfo)) = info if isParamArrayArg || isInArg || isOutArg || optArgInfo.IsOptional || callerInfo <> CallerInfo.NoCallerInfo || reflArgInfo <> ReflectedArgInfo.None then if g.langVersion.SupportsFeature(LanguageFeature.InterfacesWithAbstractStaticMembers) then @@ -9211,6 +9211,7 @@ and GenerateMatchingSimpleArgumentTypes (cenv: cenv) (calledMeth: MethInfo) mIte let g = cenv.g let curriedMethodArgAttribs = calledMeth.GetParamAttribs(cenv.amap, mItem) curriedMethodArgAttribs + |> List.map (List.map fst) |> List.map (List.filter isSimpleFormalArg >> NewInferenceTypes g) and UnifyMatchingSimpleArgumentTypes (cenv: cenv) (env: TcEnv) exprTy (calledMeth: MethInfo) mMethExpr mItem = @@ -9264,7 +9265,7 @@ and TcMethodApplication_SplitSynArguments let singleMethodCurriedArgs = match candidates with | [calledMeth] when List.forall isNil namedCurriedCallerArgs -> - let curriedCalledArgs = calledMeth.GetParamAttribs(cenv.amap, mItem) + let curriedCalledArgs = calledMeth.GetParamAttribs(cenv.amap, mItem) |> List.map (List.map fst) match curriedCalledArgs with | [arg :: _] when isSimpleFormalArg arg -> Some(curriedCalledArgs) | _ -> None @@ -9499,7 +9500,7 @@ and TcAdhocChecksOnLibraryMethods (cenv: cenv) (env: TcEnv) isInstance (finalCal if HasHeadType g g.tcref_System_Collections_Generic_Dictionary finalCalledMethInfo.ApparentEnclosingType && finalCalledMethInfo.IsConstructor && not (finalCalledMethInfo.GetParamDatas(cenv.amap, mItem, finalCalledMeth.CalledTyArgs) - |> List.existsSquared (fun (ParamData(_, _, _, _, _, _, _, ty)) -> + |> List.existsSquared (fun (ParamData(_, _, _, _, _, _, _, ty), _) -> HasHeadType g g.tcref_System_Collections_Generic_IEqualityComparer ty)) then match argsOfAppTy g finalCalledMethInfo.ApparentEnclosingType with diff --git a/src/Compiler/Checking/MethodCalls.fs b/src/Compiler/Checking/MethodCalls.fs index 1d5e66d9a2ad..e8a1af1f8fac 100644 --- a/src/Compiler/Checking/MethodCalls.fs +++ b/src/Compiler/Checking/MethodCalls.fs @@ -474,7 +474,7 @@ type CalledMethArgSet<'T> = let MakeCalledArgs amap m (minfo: MethInfo) minst = // Mark up the arguments with their position, so we can sort them back into order later let paramDatas = minfo.GetParamDatas(amap, m, minst) - paramDatas |> List.mapiSquared (fun i j (ParamData(isParamArrayArg, isInArg, isOutArg, optArgInfo, callerInfoFlags, nmOpt, reflArgInfo, calledArgTy)) -> + paramDatas |> List.mapiSquared (fun i j (ParamData(isParamArrayArg, isInArg, isOutArg, optArgInfo, callerInfoFlags, nmOpt, reflArgInfo, calledArgTy), _) -> { Position=(i,j) IsParamArray=isParamArrayArg OptArgInfo=optArgInfo diff --git a/src/Compiler/Checking/NicePrint.fs b/src/Compiler/Checking/NicePrint.fs index b67e74f67fb4..a799b075081a 100755 --- a/src/Compiler/Checking/NicePrint.fs +++ b/src/Compiler/Checking/NicePrint.fs @@ -1492,7 +1492,7 @@ module InfoMemberPrinting = let layout = layoutXmlDocOfMethInfo denv infoReader minfo layout let paramsL = - let paramDatas = minfo.GetParamDatas(amap, m, minst) + let paramDatas = minfo.GetParamDatas(amap, m, minst) |> List.map (List.map fst) if List.forall isNil paramDatas then WordL.structUnit else @@ -1535,7 +1535,7 @@ module InfoMemberPrinting = PrintTypes.layoutTyparDecls denv idL true minfo.FormalMethodTypars ^^ SepL.leftParen - let paramDatas = minfo.GetParamDatas (amap, m, minst) + let paramDatas = minfo.GetParamDatas (amap, m, minst) |> List.map (List.map fst) let layout = layout ^^ sepListL RightL.comma ((List.concat >> List.map (layoutParamData denv)) paramDatas) layout ^^ RightL.rightParen ^^ WordL.colon ^^ PrintTypes.layoutType denv retTy diff --git a/src/Compiler/Checking/PostInferenceChecks.fs b/src/Compiler/Checking/PostInferenceChecks.fs index b4d9acf83f91..7c0242404195 100644 --- a/src/Compiler/Checking/PostInferenceChecks.fs +++ b/src/Compiler/Checking/PostInferenceChecks.fs @@ -2343,13 +2343,13 @@ let CheckEntityDefn cenv env (tycon: Entity) = if numCurriedArgSets > 1 && (minfo.GetParamDatas(cenv.amap, m, minfo.FormalMethodInst) - |> List.existsSquared (fun (ParamData(isParamArrayArg, _isInArg, isOutArg, optArgInfo, callerInfo, _, reflArgInfo, ty)) -> + |> List.existsSquared (fun (ParamData(isParamArrayArg, _isInArg, isOutArg, optArgInfo, callerInfo, _, reflArgInfo, ty), _) -> isParamArrayArg || isOutArg || reflArgInfo.AutoQuote || optArgInfo.IsOptional || callerInfo <> NoCallerInfo || isByrefLikeTy g m ty)) then errorR(Error(FSComp.SR.chkCurriedMethodsCantHaveOutParams(), m)) if numCurriedArgSets = 1 then minfo.GetParamDatas(cenv.amap, m, minfo.FormalMethodInst) - |> List.iterSquared (fun (ParamData(_, isInArg, _, optArgInfo, callerInfo, _, _, ty)) -> + |> List.iterSquared (fun (ParamData(_, isInArg, _, optArgInfo, callerInfo, _, _, ty), _) -> ignore isInArg match (optArgInfo, callerInfo) with | _, NoCallerInfo -> () diff --git a/src/Compiler/Checking/infos.fs b/src/Compiler/Checking/infos.fs index 1c0612eb611e..d1347b660e1c 100644 --- a/src/Compiler/Checking/infos.fs +++ b/src/Compiler/Checking/infos.fs @@ -335,7 +335,7 @@ let CrackParamAttribsInfo g (ty: TType, argInfo: ArgReprInfo) = | ValueSome optTy when typeEquiv g g.int32_ty optTy -> CallerFilePath | _ -> CallerLineNumber - ParamAttribs(isParamArrayArg, isInArg, isOutArg, optArgInfo, callerInfo, reflArgInfo) + ParamAttribs(isParamArrayArg, isInArg, isOutArg, optArgInfo, callerInfo, reflArgInfo), argInfo.Attribs #if !NO_TYPEPROVIDERS @@ -1170,7 +1170,7 @@ type MethInfo = if p.Type.TypeRef.FullName = "System.Int32" then CallerFilePath else CallerLineNumber - ParamAttribs(isParamArrayArg, isInArg, isOutArg, optArgInfo, callerInfo, reflArgInfo) ] ] + ParamAttribs(isParamArrayArg, isInArg, isOutArg, optArgInfo, callerInfo, reflArgInfo), [] ] ] | FSMeth(g, _, vref, _) -> GetArgInfosOfMember x.IsCSharpStyleExtensionMember g vref @@ -1191,7 +1191,7 @@ type MethInfo = | None -> ReflectedArgInfo.None let isOutArg = p.PUntaint((fun p -> p.IsOut && not p.IsIn), m) let isInArg = p.PUntaint((fun p -> p.IsIn && not p.IsOut), m) - ParamAttribs(isParamArrayArg, isInArg, isOutArg, optArgInfo, NoCallerInfo, reflArgInfo)] ] + ParamAttribs(isParamArrayArg, isInArg, isOutArg, optArgInfo, NoCallerInfo, reflArgInfo), [] ] ] #endif /// Get the signature of an abstract method slot. @@ -1292,13 +1292,13 @@ type MethInfo = #endif let paramAttribs = x.GetParamAttribs(amap, m) - (paramAttribs, paramNamesAndTypes) ||> List.map2 (List.map2 (fun info (ParamNameAndType(nmOpt, pty)) -> + (paramAttribs, paramNamesAndTypes) ||> List.map2 (List.map2 (fun (info, attribs) (ParamNameAndType(nmOpt, pty)) -> let (ParamAttribs(isParamArrayArg, isInArg, isOutArg, optArgInfo, callerInfo, reflArgInfo)) = info - ParamData(isParamArrayArg, isInArg, isOutArg, optArgInfo, callerInfo, nmOpt, reflArgInfo, pty))) + ParamData(isParamArrayArg, isInArg, isOutArg, optArgInfo, callerInfo, nmOpt, reflArgInfo, pty), attribs)) /// Get the ParamData objects for the parameters of a MethInfo member x.HasParamArrayArg(amap, m, minst) = - x.GetParamDatas(amap, m, minst) |> List.existsSquared (fun (ParamData(isParamArrayArg, _, _, _, _, _, _, _)) -> isParamArrayArg) + x.GetParamDatas(amap, m, minst) |> List.existsSquared (fun (ParamData(isParamArrayArg, _, _, _, _, _, _, _), _) -> isParamArrayArg) /// Select all the type parameters of the declaring type of a method. /// diff --git a/src/Compiler/Checking/infos.fsi b/src/Compiler/Checking/infos.fsi index 63a24eb65020..83d4aaa3c3eb 100644 --- a/src/Compiler/Checking/infos.fsi +++ b/src/Compiler/Checking/infos.fsi @@ -146,7 +146,7 @@ type ParamAttribs = callerInfo: CallerInfo * reflArgInfo: ReflectedArgInfo -val CrackParamAttribsInfo: TcGlobals -> ty: TType * argInfo: ArgReprInfo -> ParamAttribs +val CrackParamAttribsInfo: TcGlobals -> ty: TType * argInfo: ArgReprInfo -> ParamAttribs * Attribs /// Describes an F# use of an IL type, including the type instantiation associated with the type at a particular usage point. [] @@ -512,10 +512,10 @@ type MethInfo = member GetCustomAttrs: unit -> ILAttributes /// Get the parameter attributes of a method info, which get combined with the parameter names and types - member GetParamAttribs: amap: ImportMap * m: range -> ParamAttribs list list + member GetParamAttribs: amap: ImportMap * m: range -> (ParamAttribs * Attribs) list list /// Get the ParamData objects for the parameters of a MethInfo - member GetParamDatas: amap: ImportMap * m: range * minst: TType list -> ParamData list list + member GetParamDatas: amap: ImportMap * m: range * minst: TType list -> (ParamData * Attribs) list list /// Get the parameter types of a method info member GetParamTypes: amap: ImportMap * m: range * minst: TType list -> TType list list diff --git a/src/Compiler/Service/FSharpCheckerResults.fs b/src/Compiler/Service/FSharpCheckerResults.fs index f1ce239ccd57..fe066b8e9928 100644 --- a/src/Compiler/Service/FSharpCheckerResults.fs +++ b/src/Compiler/Service/FSharpCheckerResults.fs @@ -569,7 +569,7 @@ type internal TypeCheckInfo match meth.GetParamDatas(amap, m, meth.FormalMethodInst) with | x :: _ -> x - |> List.choose (fun (ParamData (_isParamArray, _isInArg, _isOutArg, _optArgInfo, _callerInfo, name, _, ty)) -> + |> List.choose (fun (ParamData (_isParamArray, _isInArg, _isOutArg, _optArgInfo, _callerInfo, name, _, ty), _) -> match name with | Some id -> Some(Item.ArgName(Some id, ty, Some(ArgumentContainer.Method meth), id.idRange)) | None -> None) diff --git a/src/Compiler/Service/ServiceDeclarationLists.fs b/src/Compiler/Service/ServiceDeclarationLists.fs index bc5a70b5b4d6..b59cd345ff40 100644 --- a/src/Compiler/Service/ServiceDeclarationLists.fs +++ b/src/Compiler/Service/ServiceDeclarationLists.fs @@ -782,7 +782,7 @@ module internal DescriptionListsImpl = | Item.CtorGroup(_, minfo :: _) | Item.MethodGroup(_, minfo :: _, _) -> - let paramDatas = minfo.GetParamDatas(amap, m, minfo.FormalMethodInst) |> List.head + let paramDatas = minfo.GetParamDatas(amap, m, minfo.FormalMethodInst) |> List.head |> List.map fst let retTy = minfo.GetFSharpReturnType(amap, m, minfo.FormalMethodInst) let _prettyTyparInst, prettyParams, prettyRetTyL, _prettyConstraintsL = PrettyParamsOfParamDatas g denv item.TyparInstantiation paramDatas retTy // FUTURE: prettyTyparInst is the pretty version of the known instantiations of type parameters in the output. It could be returned diff --git a/src/Compiler/Symbols/Symbols.fs b/src/Compiler/Symbols/Symbols.fs index b27175e2a44f..33dbfa36f404 100644 --- a/src/Compiler/Symbols/Symbols.fs +++ b/src/Compiler/Symbols/Symbols.fs @@ -2051,10 +2051,8 @@ type FSharpMemberOrFunctionOrValue(cenv, d:FSharpMemberOrValData, item) = | M m | C m -> [ for argTys in m.GetParamDatas(cenv.amap, range0, m.FormalMethodInst) do yield - [ for ParamData(isParamArrayArg, isInArg, isOutArg, optArgInfo, _callerInfo, nmOpt, _reflArgInfo, pty) in argTys do - // INCOMPLETENESS: Attribs is empty here, so we can't look at attributes for - // either .NET or F# parameters - let argInfo: ArgReprInfo = { Name=nmOpt; Attribs= [] } + [ for ParamData(isParamArrayArg, isInArg, isOutArg, optArgInfo, _callerInfo, nmOpt, _reflArgInfo, pty), attribs in argTys do + let argInfo: ArgReprInfo = { Name=nmOpt; Attribs=attribs } let m = match nmOpt with | Some v -> v.idRange