From 01dda9bcc5e24199eee8ba9f2a04f3078c440ba4 Mon Sep 17 00:00:00 2001 From: Martin521 <29605222+Martin521@users.noreply.github.com> Date: Sun, 19 Nov 2023 14:33:12 +0000 Subject: [PATCH 01/16] Fix for issue83 (improve constraint error message) This includes - An addition of field "source" to TraitConstraintInfo / TTrait in TypedTree.fs/fsi - Code in CompilerImports.fs which, after import, adds the sources to all constraints - New error messages, including the constraint source, in ConstraintSolver.fs - The error messages in FSComp.txt - A new test in MemberConstraints.fs - 29 adaptations b.o. the new field in TTrait in 9 files --- .devcontainer/Dockerfile | 2 +- src/Compiler/Checking/CheckExpressions.fs | 21 +++++++------ src/Compiler/Checking/ConstraintSolver.fs | 29 ++++++++--------- src/Compiler/Checking/FindUnsolved.fs | 2 +- src/Compiler/Checking/NicePrint.fs | 2 +- src/Compiler/Checking/PostInferenceChecks.fs | 12 +++---- src/Compiler/Driver/CompilerImports.fs | 18 +++++++++++ src/Compiler/FSComp.txt | 2 ++ src/Compiler/Symbols/Exprs.fs | 8 ++--- src/Compiler/Symbols/Symbols.fs | 12 +++---- src/Compiler/TypedTree/TypedTree.fs | 31 +++++++++++-------- src/Compiler/TypedTree/TypedTree.fsi | 8 ++++- src/Compiler/TypedTree/TypedTreeOps.fs | 18 +++++------ src/Compiler/TypedTree/TypedTreePickle.fs | 4 +-- .../ConstraintSolver/MemberConstraints.fs | 10 ++++++ 15 files changed, 111 insertions(+), 68 deletions(-) diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index e1dcf31c425..48fd924ad2d 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -24,4 +24,4 @@ RUN apt-get update \ ENV DEBIAN_FRONTEND=dialog # Make sure we can build using plain dotnet -ENV BUILDING_USING_DOTNET="true" +ENV BUILDING_USING_DOTNET="true" \ No newline at end of file diff --git a/src/Compiler/Checking/CheckExpressions.fs b/src/Compiler/Checking/CheckExpressions.fs index 5c2239b073e..b9a7405d389 100644 --- a/src/Compiler/Checking/CheckExpressions.fs +++ b/src/Compiler/Checking/CheckExpressions.fs @@ -4065,14 +4065,15 @@ and TcConstraintWhereTyparSupportsMember cenv env newOk tpenv synSupportTys synM let g = cenv.g let traitInfo, tpenv = TcPseudoMemberSpec cenv newOk env synSupportTys tpenv synMemberSig m match traitInfo with - | TTrait(objTys, ".ctor", memberFlags, argTys, returnTy, _) when memberFlags.MemberKind = SynMemberKind.Constructor -> - match objTys, argTys with - | [ty], [] when typeEquiv g ty (GetFSharpViewOfReturnType g returnTy) -> - AddCxTypeMustSupportDefaultCtor env.DisplayEnv cenv.css m NoTrace ty - tpenv - | _ -> - errorR(Error(FSComp.SR.tcInvalidNewConstraint(), m)) - tpenv + | TTrait(tys=objTys; memberName=".ctor"; memberFlags=memberFlags; objAndArgTys=argTys; returnTyOpt=returnTy) + when memberFlags.MemberKind = SynMemberKind.Constructor -> + match objTys, argTys with + | [ty], [] when typeEquiv g ty (GetFSharpViewOfReturnType g returnTy) -> + AddCxTypeMustSupportDefaultCtor env.DisplayEnv cenv.css m NoTrace ty + tpenv + | _ -> + errorR(Error(FSComp.SR.tcInvalidNewConstraint(), m)) + tpenv | _ -> AddCxMethodConstraint env.DisplayEnv cenv.css m NoTrace traitInfo tpenv @@ -4114,7 +4115,7 @@ and TcPseudoMemberSpec cenv newOk env synTypes tpenv synMemberSig m = let item = Item.OtherName (Some id, memberConstraintTy, None, None, id.idRange) CallNameResolutionSink cenv.tcSink (id.idRange, env.NameEnv, item, emptyTyparInst, ItemOccurence.Use, env.AccessRights) - TTrait(tys, logicalCompiledName, memberFlags, argTys, returnTy, ref None), tpenv + TTrait(tys, logicalCompiledName, memberFlags, argTys, returnTy, ref None, ref None), tpenv | _ -> error(Error(FSComp.SR.tcInvalidConstraint(), m)) @@ -8787,7 +8788,7 @@ and TcImplicitOpItemThen (cenv: cenv) overallTy env id sln tpenv mItem delayed = let memberFlags = StaticMemberFlags SynMemberKind.Member let logicalCompiledName = ComputeLogicalName id memberFlags - let traitInfo = TTrait(argTys, logicalCompiledName, memberFlags, argTys, Some retTy, sln) + let traitInfo = TTrait(argTys, logicalCompiledName, memberFlags, argTys, Some retTy, ref None, sln) let expr = Expr.Op (TOp.TraitCall traitInfo, [], ves, mItem) let expr = mkLambdas g mItem [] vs (expr, retTy) diff --git a/src/Compiler/Checking/ConstraintSolver.fs b/src/Compiler/Checking/ConstraintSolver.fs index d54f7c59883..a74042f3826 100644 --- a/src/Compiler/Checking/ConstraintSolver.fs +++ b/src/Compiler/Checking/ConstraintSolver.fs @@ -1394,7 +1394,7 @@ and SolveDimensionlessNumericType (csenv: ConstraintSolverEnv) ndeep m2 trace ty /// /// 2. Some additional solutions are forced prior to generalization (permitWeakResolution= Yes or YesDuringCodeGen). See above and SolveMemberConstraint (csenv: ConstraintSolverEnv) ignoreUnresolvedOverload permitWeakResolution ndeep m2 trace traitInfo : OperationResult = trackErrors { - let (TTrait(supportTys, nm, memFlags, traitObjAndArgTys, retTy, sln)) = traitInfo + let (TTrait(supportTys, nm, memFlags, traitObjAndArgTys, retTy, source, sln)) = traitInfo // Do not re-solve if already solved if sln.Value.IsSome then return true else @@ -1411,8 +1411,8 @@ and SolveMemberConstraint (csenv: ConstraintSolverEnv) ignoreUnresolvedOverload let supportTys = ListSet.setify (typeAEquiv g aenv) supportTys // Rebuild the trait info after removing duplicates - let traitInfo = TTrait(supportTys, nm, memFlags, traitObjAndArgTys, retTy, sln) - let retTy = GetFSharpViewOfReturnType g retTy + let traitInfo = traitInfo.WithSupportTypes supportTys + let retTy = GetFSharpViewOfReturnType g retTy // Assert the object type if the constraint is for an instance member if memFlags.IsInstance then @@ -1754,8 +1754,11 @@ and SolveMemberConstraint (csenv: ConstraintSolverEnv) ignoreUnresolvedOverload if List.isSingleton supportTys then FSComp.SR.csTypeDoesNotSupportOperatorNullable(tyString, opName) else FSComp.SR.csTypesDoNotSupportOperatorNullable(tyString, opName) | _ -> - if List.isSingleton supportTys then FSComp.SR.csTypeDoesNotSupportOperator(tyString, opName) - else FSComp.SR.csTypesDoNotSupportOperator(tyString, opName) + match supportTys, source.Value with + | [_], Some s when s <> nm -> FSComp.SR.csTypeDoesNotSupportOperatorW(tyString, opName,s ) + | [_], _ -> FSComp.SR.csTypeDoesNotSupportOperator(tyString, opName) + | _, Some s when s <> nm -> FSComp.SR.csTypesDoNotSupportOperatorW(tyString, opName,s ) + | _, _ -> FSComp.SR.csTypesDoNotSupportOperator(tyString, opName) return! ErrorD(ConstraintSolverError(err, m, m2)) | _ -> @@ -1928,7 +1931,6 @@ and TransactMemberConstraintSolution traitInfo (trace: OptionalTrace) sln = /// Only consider overload resolution if canonicalizing or all the types are now nominal. /// That is, don't perform resolution if more nominal information may influence the set of available overloads and GetRelevantMethodsForTrait (csenv: ConstraintSolverEnv) (permitWeakResolution: PermitWeakResolution) nm traitInfo : (TType * MethInfo) list = - let (TTrait(_, _, memFlags, _, _, _)) = traitInfo let results = if permitWeakResolution.Permit || MemberConstraintSupportIsReadyForDeterminingOverloads csenv traitInfo then let m = csenv.m @@ -1938,7 +1940,7 @@ and GetRelevantMethodsForTrait (csenv: ConstraintSolverEnv) (permitWeakResolutio let minfos = [ for (supportTy, nominalTy) in nominalTys do let infos = - match memFlags.MemberKind with + match traitInfo.MemberFlags.MemberKind with | SynMemberKind.Constructor -> GetIntrinsicConstructorInfosOfType csenv.SolverState.InfoReader m nominalTy | _ -> @@ -1962,8 +1964,7 @@ and GetRelevantMethodsForTrait (csenv: ConstraintSolverEnv) (permitWeakResolutio // The trait name "op_Explicit" also covers "op_Implicit", so look for that one too. if nm = "op_Explicit" then - let (TTrait(supportTys, _, memFlags, argTys, retTy, soln)) = traitInfo - let traitInfo2 = TTrait(supportTys, "op_Implicit", memFlags, argTys, retTy, soln) + let traitInfo2 = traitInfo.WithMemberName "op_Implicit" results @ GetRelevantMethodsForTrait csenv permitWeakResolution "op_Implicit" traitInfo2 else results @@ -2020,7 +2021,7 @@ and SupportTypeOfMemberConstraintIsSolved (csenv: ConstraintSolverEnv) (traitInf /// Get all the unsolved typars (statically resolved or not) relevant to the member constraint and GetFreeTyparsOfMemberConstraint (csenv: ConstraintSolverEnv) traitInfo = - let (TTrait(supportTys, _, _, argTys, retTy, _)) = traitInfo + let (TTrait(tys=supportTys; objAndArgTys=argTys; returnTyOpt=retTy)) = traitInfo freeInTypesLeftToRightSkippingConstraints csenv.g (supportTys @ argTys @ Option.toList retTy) and MemberConstraintIsReadyForWeakResolution csenv traitInfo = @@ -2104,8 +2105,8 @@ and AddMemberConstraint (csenv: ConstraintSolverEnv) ndeep m2 (trace: OptionalTr and TraitsAreRelated (csenv: ConstraintSolverEnv) retry traitInfo1 traitInfo2 = let g = csenv.g - let (TTrait(tys1, nm1, memFlags1, argTys1, _, _)) = traitInfo1 - let (TTrait(tys2, nm2, memFlags2, argTys2, _, _)) = traitInfo2 + let (TTrait(tys=tys1; memberName=nm1; memberFlags=memFlags1; objAndArgTys=argTys1)) = traitInfo1 + let (TTrait(tys=tys2; memberName=nm2; memberFlags=memFlags2; objAndArgTys=argTys2)) = traitInfo2 memFlags1.IsInstance = memFlags2.IsInstance && nm1 = nm2 && // Multiple op_Explicit and op_Implicit constraints can exist for the same type variable. @@ -2130,8 +2131,8 @@ and EnforceConstraintConsistency (csenv: ConstraintSolverEnv) ndeep m2 trace ret match tpc1, tpc2 with | TyparConstraint.MayResolveMember(traitInfo1, _), TyparConstraint.MayResolveMember(traitInfo2, _) when TraitsAreRelated csenv retry traitInfo1 traitInfo2 -> - let (TTrait(tys1, _, _, argTys1, rty1, _)) = traitInfo1 - let (TTrait(tys2, _, _, argTys2, rty2, _)) = traitInfo2 + let (TTrait(tys=tys1; objAndArgTys=argTys1; returnTyOpt=rty1)) = traitInfo1 + let (TTrait(tys=tys2; objAndArgTys=argTys2; returnTyOpt=rty2)) = traitInfo2 if retry then match tys1, tys2 with | [ty1], [ty2] -> do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace ty1 ty2 diff --git a/src/Compiler/Checking/FindUnsolved.fs b/src/Compiler/Checking/FindUnsolved.fs index cfc34649ae5..10eb7ab672c 100644 --- a/src/Compiler/Checking/FindUnsolved.fs +++ b/src/Compiler/Checking/FindUnsolved.fs @@ -167,7 +167,7 @@ and accOp cenv env (op, tyargs, args, m) = | _ -> () /// Walk a trait call, collecting type variables -and accTraitInfo cenv env (mFallback : range) (TTrait(tys, _nm, _, argTys, retTy, _sln)) = +and accTraitInfo cenv env (mFallback : range) (TTrait(tys=tys; objAndArgTys=argTys; returnTyOpt=retTy)) = argTys |> accTypeInst cenv env mFallback retTy |> Option.iter (accTy cenv env mFallback) tys |> List.iter (accTy cenv env mFallback) diff --git a/src/Compiler/Checking/NicePrint.fs b/src/Compiler/Checking/NicePrint.fs index c7062e058d2..0a5d5f2b620 100644 --- a/src/Compiler/Checking/NicePrint.fs +++ b/src/Compiler/Checking/NicePrint.fs @@ -823,7 +823,7 @@ module PrintTypes = and layoutTraitWithInfo denv env traitInfo = let g = denv.g - let (TTrait(tys, _, memFlags, _, _, _)) = traitInfo + let (TTrait(tys=tys;memberFlags=memFlags)) = traitInfo let nm = traitInfo.MemberDisplayNameCore let nameL = ConvertValLogicalNameToDisplayLayout false (tagMember >> wordL) nm if denv.shortConstraints then diff --git a/src/Compiler/Checking/PostInferenceChecks.fs b/src/Compiler/Checking/PostInferenceChecks.fs index 62c5a2f5f11..912aa15469a 100644 --- a/src/Compiler/Checking/PostInferenceChecks.fs +++ b/src/Compiler/Checking/PostInferenceChecks.fs @@ -346,7 +346,7 @@ let rec CheckTypeDeep (cenv: cenv) (visitTy, visitTyconRefOpt, visitAppTyOpt, vi | TType_var (tp, _) when tp.Solution.IsSome -> for cx in tp.Constraints do match cx with - | TyparConstraint.MayResolveMember(TTrait(_, _, _, _, _, soln), _) -> + | TyparConstraint.MayResolveMember(TTrait(solution=soln), _) -> match visitTraitSolutionOpt, soln.Value with | Some visitTraitSolution, Some sln -> visitTraitSolution sln | _ -> () @@ -432,11 +432,11 @@ and CheckTypeConstraintDeep cenv f g env x = | TyparConstraint.IsReferenceType _ | TyparConstraint.RequiresDefaultConstructor _ -> () -and CheckTraitInfoDeep cenv (_, _, _, visitTraitSolutionOpt, _ as f) g env (TTrait(tys, _, _, argTys, retTy, soln)) = - CheckTypesDeep cenv f g env tys - CheckTypesDeep cenv f g env argTys - Option.iter (CheckTypeDeep cenv f g env true ) retTy - match visitTraitSolutionOpt, soln.Value with +and CheckTraitInfoDeep cenv (_, _, _, visitTraitSolutionOpt, _ as f) g env traitInfo = + CheckTypesDeep cenv f g env traitInfo.SupportTypes + CheckTypesDeep cenv f g env traitInfo.CompiledObjectAndArgumentTypes + Option.iter (CheckTypeDeep cenv f g env true ) traitInfo.CompiledReturnType + match visitTraitSolutionOpt, traitInfo.Solution with | Some visitTraitSolution, Some sln -> visitTraitSolution sln | _ -> () diff --git a/src/Compiler/Driver/CompilerImports.fs b/src/Compiler/Driver/CompilerImports.fs index c5419de36c0..d367b292b63 100644 --- a/src/Compiler/Driver/CompilerImports.fs +++ b/src/Compiler/Driver/CompilerImports.fs @@ -377,6 +377,21 @@ let IsExe fileName = let ext = Path.GetExtension fileName String.Compare(ext, ".exe", StringComparison.OrdinalIgnoreCase) = 0 +let addConstraintSources(ia: ImportedAssembly) = + let contents = ia.FSharpViewOfMetadata.Contents + let addCxsToMember (v: Val) = + for typar in fst v.GeneralizedType do + for cx in typar.Constraints do + match cx with + | TyparConstraint.MayResolveMember(TTrait(source=source), _) -> + source.Value <- Some v.LogicalName + | _ -> () + let rec addCxsToModule (m: ModuleOrNamespaceType) = + for e in m.ModuleAndNamespaceDefinitions do + if e.IsModuleOrNamespace then addCxsToModule e.ModuleOrNamespaceType + for memb in m.AllValsAndMembers do addCxsToMember memb + addCxsToModule contents.ModuleOrNamespaceType + type TcConfig with member tcConfig.TryResolveLibWithDirectories(r: AssemblyReference) = @@ -2234,6 +2249,9 @@ and [] TcImports let _dllinfos, phase2s = results |> Array.choose id |> List.ofArray |> List.unzip fixupOrphanCcus () let ccuinfos = List.collect (fun phase2 -> phase2 ()) phase2s + if importsBase.IsSome then + importsBase.Value.CcuTable.Values |> Seq.iter addConstraintSources + ccuTable.Values |> Seq.iter addConstraintSources return ccuinfos } diff --git a/src/Compiler/FSComp.txt b/src/Compiler/FSComp.txt index c96c6929194..42f6931627b 100644 --- a/src/Compiler/FSComp.txt +++ b/src/Compiler/FSComp.txt @@ -314,7 +314,9 @@ csIndexArgumentMismatch,"This indexer expects %d arguments but is here given %d" csExpectTypeWithOperatorButGivenFunction,"Expecting a type supporting the operator '%s' but given a function type. You may be missing an argument to a function." csExpectTypeWithOperatorButGivenTuple,"Expecting a type supporting the operator '%s' but given a tuple type" csTypesDoNotSupportOperator,"None of the types '%s' support the operator '%s'" +csTypesDoNotSupportOperatorW,"None of the types '%s' support the operator '%s' as required by '%s'" csTypeDoesNotSupportOperator,"The type '%s' does not support the operator '%s'" +csTypeDoesNotSupportOperatorW,"The type '%s' does not support the operator '%s' as required by '%s'" csTypesDoNotSupportOperatorNullable,"None of the types '%s' support the operator '%s'. Consider opening the module 'Microsoft.FSharp.Linq.NullableOperators'." csTypeDoesNotSupportOperatorNullable,"The type '%s' does not support the operator '%s'. Consider opening the module 'Microsoft.FSharp.Linq.NullableOperators'." csTypeDoesNotSupportConversion,"The type '%s' does not support a conversion to the type '%s'" diff --git a/src/Compiler/Symbols/Exprs.fs b/src/Compiler/Symbols/Exprs.fs index eabc11f3410..81f2c912ad5 100644 --- a/src/Compiler/Symbols/Exprs.fs +++ b/src/Compiler/Symbols/Exprs.fs @@ -899,12 +899,12 @@ module FSharpExprConvert = let typR = ConvType cenv (mkAppTy tycr tyargs) E.UnionCaseTag(ConvExpr cenv env arg1, typR) - | TOp.TraitCall (TTrait(tys, nm, memFlags, argTys, _retTy, _solution)), _, _ -> - let tysR = ConvTypes cenv tys + | TOp.TraitCall traitInfo, _, _ -> + let tysR = ConvTypes cenv traitInfo.SupportTypes let tyargsR = ConvTypes cenv tyargs - let argTysR = ConvTypes cenv argTys + let argTysR = ConvTypes cenv traitInfo.CompiledObjectAndArgumentTypes let argsR = ConvExprs cenv env args - E.TraitCall(tysR, nm, memFlags, argTysR, tyargsR, argsR) + E.TraitCall(tysR, traitInfo.MemberLogicalName, traitInfo.MemberFlags, argTysR, tyargsR, argsR) | TOp.RefAddrGet readonly, [ty], [e] -> let replExpr = mkRecdFieldGetAddrViaExprAddr(readonly, e, mkRefCellContentsRef g, [ty], m) diff --git a/src/Compiler/Symbols/Symbols.fs b/src/Compiler/Symbols/Symbols.fs index e59caf2c6d4..ae8980e3787 100644 --- a/src/Compiler/Symbols/Symbols.fs +++ b/src/Compiler/Symbols/Symbols.fs @@ -1461,18 +1461,18 @@ type FSharpGenericParameterMemberConstraint(cenv, info: TraitConstraintInfo) = (fun () -> Item.Trait(info)), (fun _ _ _ad -> true)) - let (TTrait(tys, nm, flags, atys, retTy, _)) = info member _.MemberSources = - tys |> List.map (fun ty -> FSharpType(cenv, ty)) |> makeReadOnlyCollection + info.SupportTypes |> List.map (fun ty -> FSharpType(cenv, ty)) |> makeReadOnlyCollection - member _.MemberName = nm + member _.MemberName = info.MemberLogicalName - member _.MemberIsStatic = not flags.IsInstance + member _.MemberIsStatic = not info.MemberFlags.IsInstance - member _.MemberArgumentTypes = atys |> List.map (fun ty -> FSharpType(cenv, ty)) |> makeReadOnlyCollection + member _.MemberArgumentTypes = + info.CompiledObjectAndArgumentTypes |> List.map (fun ty -> FSharpType(cenv, ty)) |> makeReadOnlyCollection member _.MemberReturnType = - match retTy with + match info.CompiledReturnType with | None -> FSharpType(cenv, cenv.g.unit_ty) | Some ty -> FSharpType(cenv, ty) override x.ToString() = "" diff --git a/src/Compiler/TypedTree/TypedTree.fs b/src/Compiler/TypedTree/TypedTree.fs index 3caccb5597d..1df007e00a0 100644 --- a/src/Compiler/TypedTree/TypedTree.fs +++ b/src/Compiler/TypedTree/TypedTree.fs @@ -2450,29 +2450,34 @@ type TraitWitnessInfo = type TraitConstraintInfo = /// Indicates the signature of a member constraint. Contains a mutable solution cell - /// to store the inferred solution of the constraint. - | TTrait of tys: TTypes * memberName: string * memberFlags: SynMemberFlags * objAndArgTys: TTypes * returnTyOpt: TType option * solution: TraitConstraintSln option ref + /// to store the inferred solution of the constraint. And a mutable source cell to store + /// the name of the type or member that defined the constraint. + | TTrait of tys: TTypes * memberName: string * memberFlags: SynMemberFlags * objAndArgTys: TTypes * returnTyOpt: TType option * source: string option ref * solution: TraitConstraintSln option ref /// Get the types that may provide solutions for the traits - member x.SupportTypes = (let (TTrait(tys, _, _, _, _, _)) = x in tys) + member x.SupportTypes = (let (TTrait(tys = tys)) = x in tys) /// Get the logical member name associated with the member constraint. - member x.MemberLogicalName = (let (TTrait(_, nm, _, _, _, _)) = x in nm) + member x.MemberLogicalName = (let (TTrait(memberName = nm)) = x in nm) /// Get the member flags associated with the member constraint. - member x.MemberFlags = (let (TTrait(_, _, flags, _, _, _)) = x in flags) - - member x.CompiledObjectAndArgumentTypes = (let (TTrait(_, _, _, objAndArgTys, _, _)) = x in objAndArgTys) - - member x.WithMemberKind(kind) = (let (TTrait(a, b, c, d, e, f)) = x in TTrait(a, b, { c with MemberKind=kind }, d, e, f)) + member x.MemberFlags = (let (TTrait(memberFlags = flags)) = x in flags) + member x.CompiledObjectAndArgumentTypes = (let (TTrait(objAndArgTys = objAndArgTys)) = x in objAndArgTys) + /// Get the optional return type recorded in the member constraint. - member x.CompiledReturnType = (let (TTrait(_, _, _, _, retTy, _)) = x in retTy) - + member x.CompiledReturnType = (let (TTrait(returnTyOpt = retTy)) = x in retTy) + /// Get or set the solution of the member constraint during inference member x.Solution - with get() = (let (TTrait(_, _, _, _, _, sln)) = x in sln.Value) - and set v = (let (TTrait(_, _, _, _, _, sln)) = x in sln.Value <- v) + with get() = (let (TTrait(solution = sln)) = x in sln.Value) + and set v = (let (TTrait(solution = sln)) = x in sln.Value <- v) + + member x.WithMemberKind(kind) = (let (TTrait(a, b, c, d, e, f, g)) = x in TTrait(a, b, { c with MemberKind=kind }, d, e, f, g)) + + member x.WithSupportTypes(tys) = (let (TTrait(_, b, c, d, e, f, g)) = x in TTrait(tys, b, c, d, e, f, g)) + + member x.WithMemberName(name) = (let (TTrait(a, _, c, d, e, f, g)) = x in TTrait(a, name, c, d, e, f, g)) [] member x.DebugText = x.ToString() diff --git a/src/Compiler/TypedTree/TypedTree.fsi b/src/Compiler/TypedTree/TypedTree.fsi index 55af38d9b9e..fe0f1a97ed0 100644 --- a/src/Compiler/TypedTree/TypedTree.fsi +++ b/src/Compiler/TypedTree/TypedTree.fsi @@ -1674,13 +1674,15 @@ type TraitWitnessInfo = type TraitConstraintInfo = /// Indicates the signature of a member constraint. Contains a mutable solution cell - /// to store the inferred solution of the constraint. + /// to store the inferred solution of the constraint. And a mutable source cell to store + /// the name of the type or member that defined the constraint. | TTrait of tys: TTypes * memberName: string * memberFlags: Syntax.SynMemberFlags * objAndArgTys: TTypes * returnTyOpt: TType option * + source: string option ref * solution: TraitConstraintSln option ref override ToString: unit -> string @@ -1714,6 +1716,10 @@ type TraitConstraintInfo = /// The member kind is irrelevant to the logical properties of a trait. However it adjusts /// the extension property MemberDisplayNameCore member WithMemberKind: SynMemberKind -> TraitConstraintInfo + + member WithSupportTypes: TTypes -> TraitConstraintInfo + + member WithMemberName: string -> TraitConstraintInfo /// Represents the solution of a member constraint during inference. [] diff --git a/src/Compiler/TypedTree/TypedTreeOps.fs b/src/Compiler/TypedTree/TypedTreeOps.fs index 26630f4fa82..ba1b6d97037 100644 --- a/src/Compiler/TypedTree/TypedTreeOps.fs +++ b/src/Compiler/TypedTree/TypedTreeOps.fs @@ -256,7 +256,7 @@ and remapTyparConstraintsAux tyenv cs = | TyparConstraint.IsReferenceType _ | TyparConstraint.RequiresDefaultConstructor _ -> Some x) -and remapTraitInfo tyenv (TTrait(tys, nm, flags, argTys, retTy, slnCell)) = +and remapTraitInfo tyenv (TTrait(tys, nm, flags, argTys, retTy, source, slnCell)) = let slnCell = match slnCell.Value with | None -> None @@ -292,7 +292,7 @@ and remapTraitInfo tyenv (TTrait(tys, nm, flags, argTys, retTy, slnCell)) = // in the same way as types let newSlnCell = ref slnCell - TTrait(tysR, nm, flags, argTysR, retTyR, newSlnCell) + TTrait(tysR, nm, flags, argTysR, retTyR, source, newSlnCell) and bindTypars tps tyargs tpinst = match tps with @@ -955,8 +955,8 @@ type TypeEquivEnv with TypeEquivEnv.Empty.BindEquivTypars tps1 tps2 let rec traitsAEquivAux erasureFlag g aenv traitInfo1 traitInfo2 = - let (TTrait(tys1, nm, mf1, argTys, retTy, _)) = traitInfo1 - let (TTrait(tys2, nm2, mf2, argTys2, retTy2, _)) = traitInfo2 + let (TTrait(tys1, nm, mf1, argTys, retTy, _, _)) = traitInfo1 + let (TTrait(tys2, nm2, mf2, argTys2, retTy2, _, _)) = traitInfo2 mf1.IsInstance = mf2.IsInstance && nm = nm2 && ListSet.equals (typeAEquivAux erasureFlag g aenv) tys1 tys2 && @@ -2285,7 +2285,7 @@ and accFreeInTyparConstraint opts tpc acc = | TyparConstraint.IsUnmanaged _ | TyparConstraint.RequiresDefaultConstructor _ -> acc -and accFreeInTrait opts (TTrait(tys, _, _, argTys, retTy, sln)) acc = +and accFreeInTrait opts (TTrait(tys, _, _, argTys, retTy, _, sln)) acc = Option.foldBack (accFreeInTraitSln opts) sln.Value (accFreeInTypes opts tys (accFreeInTypes opts argTys @@ -2420,7 +2420,7 @@ and accFreeInTyparConstraintLeftToRight g cxFlag thruFlag acc tpc = | TyparConstraint.IsReferenceType _ | TyparConstraint.RequiresDefaultConstructor _ -> acc -and accFreeInTraitLeftToRight g cxFlag thruFlag acc (TTrait(tys, _, _, argTys, retTy, _)) = +and accFreeInTraitLeftToRight g cxFlag thruFlag acc (TTrait(tys, _, _, argTys, retTy, _, _)) = let acc = accFreeInTypesLeftToRight g cxFlag thruFlag acc tys let acc = accFreeInTypesLeftToRight g cxFlag thruFlag acc argTys let acc = Option.fold (accFreeInTypeLeftToRight g cxFlag thruFlag) acc retTy @@ -2627,7 +2627,7 @@ type TraitConstraintInfo with /// Get the key associated with the member constraint. member traitInfo.GetWitnessInfo() = - let (TTrait(tys, nm, memFlags, objAndArgTys, rty, _)) = traitInfo + let (TTrait(tys, nm, memFlags, objAndArgTys, rty, _, _)) = traitInfo TraitWitnessInfo(tys, nm, memFlags, objAndArgTys, rty) /// Get information about the trait constraints for a set of typars. @@ -4019,7 +4019,7 @@ module DebugPrint = and auxTraitL env (ttrait: TraitConstraintInfo) = #if DEBUG - let (TTrait(tys, nm, memFlags, argTys, retTy, _)) = ttrait + let (TTrait(tys, nm, memFlags, argTys, retTy, _, _)) = ttrait match global_g with | None -> wordL (tagText "") | Some g -> @@ -5353,7 +5353,7 @@ and accFreeInOp opts op acc = | TOp.Reraise -> accUsesRethrow true acc - | TOp.TraitCall (TTrait(tys, _, _, argTys, retTy, sln)) -> + | TOp.TraitCall (TTrait(tys, _, _, argTys, retTy, _, sln)) -> Option.foldBack (accFreeVarsInTraitSln opts) sln.Value (accFreeVarsInTys opts tys (accFreeVarsInTys opts argTys diff --git a/src/Compiler/TypedTree/TypedTreePickle.fs b/src/Compiler/TypedTree/TypedTreePickle.fs index 5750c9012de..30a05701071 100644 --- a/src/Compiler/TypedTree/TypedTreePickle.fs +++ b/src/Compiler/TypedTree/TypedTreePickle.fs @@ -1437,7 +1437,7 @@ let p_trait_sln sln st = p_byte 7 st; p_tup4 p_ty (p_vref "trait") p_tys p_ty (a, b, c, d) st -let p_trait (TTrait(a, b, c, d, e, f)) st = +let p_trait (TTrait(a, b, c, d, e, _, f)) st = p_tup6 p_tys p_string p_MemberFlags p_tys (p_option p_ty) (p_option p_trait_sln) (a, b, c, d, e, f.Value) st let u_anonInfo_data st = @@ -1477,7 +1477,7 @@ let u_trait_sln st = let u_trait st = let a, b, c, d, e, f = u_tup6 u_tys u_string u_MemberFlags u_tys (u_option u_ty) (u_option u_trait_sln) st - TTrait (a, b, c, d, e, ref f) + TTrait (a, b, c, d, e, ref None, ref f) let p_rational q st = p_int32 (GetNumerator q) st; p_int32 (GetDenominator q) st diff --git a/tests/FSharp.Compiler.ComponentTests/ConstraintSolver/MemberConstraints.fs b/tests/FSharp.Compiler.ComponentTests/ConstraintSolver/MemberConstraints.fs index 3bb1770b411..ee03683f742 100644 --- a/tests/FSharp.Compiler.ComponentTests/ConstraintSolver/MemberConstraints.fs +++ b/tests/FSharp.Compiler.ComponentTests/ConstraintSolver/MemberConstraints.fs @@ -74,3 +74,13 @@ type DataItem< ^input> with """ |> compile |> shouldSucceed + + [] + let ``Explain why type needs to support operator`` () = + FSharp """ +List.average [42] |> ignore +""" + |> typecheck + |> shouldFail + |> withSingleDiagnostic + (Error 1, Line 2, Col 15, Line 2, Col 17, "The type 'int' does not support the operator 'DivideByInt' as required by 'average'") From f1d557712a6f4f915c15f85b5dba6427bc7e8108 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 19 Nov 2023 16:57:52 +0000 Subject: [PATCH 02/16] Automated command ran: xlf Co-authored-by: Martin521 <29605222+Martin521@users.noreply.github.com> --- src/Compiler/xlf/FSComp.txt.cs.xlf | 10 ++++++++++ src/Compiler/xlf/FSComp.txt.de.xlf | 10 ++++++++++ src/Compiler/xlf/FSComp.txt.es.xlf | 10 ++++++++++ src/Compiler/xlf/FSComp.txt.fr.xlf | 10 ++++++++++ src/Compiler/xlf/FSComp.txt.it.xlf | 10 ++++++++++ src/Compiler/xlf/FSComp.txt.ja.xlf | 10 ++++++++++ src/Compiler/xlf/FSComp.txt.ko.xlf | 10 ++++++++++ src/Compiler/xlf/FSComp.txt.pl.xlf | 10 ++++++++++ src/Compiler/xlf/FSComp.txt.pt-BR.xlf | 10 ++++++++++ src/Compiler/xlf/FSComp.txt.ru.xlf | 10 ++++++++++ src/Compiler/xlf/FSComp.txt.tr.xlf | 10 ++++++++++ src/Compiler/xlf/FSComp.txt.zh-Hans.xlf | 10 ++++++++++ src/Compiler/xlf/FSComp.txt.zh-Hant.xlf | 10 ++++++++++ 13 files changed, 130 insertions(+) diff --git a/src/Compiler/xlf/FSComp.txt.cs.xlf b/src/Compiler/xlf/FSComp.txt.cs.xlf index 64231d9d694..94d80857a74 100644 --- a/src/Compiler/xlf/FSComp.txt.cs.xlf +++ b/src/Compiler/xlf/FSComp.txt.cs.xlf @@ -182,6 +182,16 @@ Argument {0} neodpovídá + + The type '{0}' does not support the operator '{1}' as required by '{2}' + The type '{0}' does not support the operator '{1}' as required by '{2}' + + + + None of the types '{0}' support the operator '{1}' as required by '{2}' + None of the types '{0}' support the operator '{1}' as required by '{2}' + + The constraints 'unmanaged' and 'not struct' are inconsistent Omezení „unmanaged“ a „not struct“ jsou nekonzistentní diff --git a/src/Compiler/xlf/FSComp.txt.de.xlf b/src/Compiler/xlf/FSComp.txt.de.xlf index c689aaa5840..b29912be6c5 100644 --- a/src/Compiler/xlf/FSComp.txt.de.xlf +++ b/src/Compiler/xlf/FSComp.txt.de.xlf @@ -182,6 +182,16 @@ Das Argument "{0}" stimmt nicht überein. + + The type '{0}' does not support the operator '{1}' as required by '{2}' + The type '{0}' does not support the operator '{1}' as required by '{2}' + + + + None of the types '{0}' support the operator '{1}' as required by '{2}' + None of the types '{0}' support the operator '{1}' as required by '{2}' + + The constraints 'unmanaged' and 'not struct' are inconsistent Die Einschränkungen "unmanaged" und "not struct" sind nicht konsistent. diff --git a/src/Compiler/xlf/FSComp.txt.es.xlf b/src/Compiler/xlf/FSComp.txt.es.xlf index b4427cbcaf7..4e1fe2ccea6 100644 --- a/src/Compiler/xlf/FSComp.txt.es.xlf +++ b/src/Compiler/xlf/FSComp.txt.es.xlf @@ -182,6 +182,16 @@ El argumento "{0}" no coincide. + + The type '{0}' does not support the operator '{1}' as required by '{2}' + The type '{0}' does not support the operator '{1}' as required by '{2}' + + + + None of the types '{0}' support the operator '{1}' as required by '{2}' + None of the types '{0}' support the operator '{1}' as required by '{2}' + + The constraints 'unmanaged' and 'not struct' are inconsistent Las restricciones “no administrado” y "no estructurado" son incoherentes diff --git a/src/Compiler/xlf/FSComp.txt.fr.xlf b/src/Compiler/xlf/FSComp.txt.fr.xlf index 349e8ad63fd..cf2169abe87 100644 --- a/src/Compiler/xlf/FSComp.txt.fr.xlf +++ b/src/Compiler/xlf/FSComp.txt.fr.xlf @@ -182,6 +182,16 @@ L'argument '{0}' ne correspond pas + + The type '{0}' does not support the operator '{1}' as required by '{2}' + The type '{0}' does not support the operator '{1}' as required by '{2}' + + + + None of the types '{0}' support the operator '{1}' as required by '{2}' + None of the types '{0}' support the operator '{1}' as required by '{2}' + + The constraints 'unmanaged' and 'not struct' are inconsistent Les contraintes « non gérées » et « non structurées » sont incohérentes diff --git a/src/Compiler/xlf/FSComp.txt.it.xlf b/src/Compiler/xlf/FSComp.txt.it.xlf index 55c55facb7e..13ec4d1dc61 100644 --- a/src/Compiler/xlf/FSComp.txt.it.xlf +++ b/src/Compiler/xlf/FSComp.txt.it.xlf @@ -182,6 +182,16 @@ L'argomento '{0}' non corrisponde + + The type '{0}' does not support the operator '{1}' as required by '{2}' + The type '{0}' does not support the operator '{1}' as required by '{2}' + + + + None of the types '{0}' support the operator '{1}' as required by '{2}' + None of the types '{0}' support the operator '{1}' as required by '{2}' + + The constraints 'unmanaged' and 'not struct' are inconsistent I vincoli 'unmanaged' e 'not struct' sono incoerenti diff --git a/src/Compiler/xlf/FSComp.txt.ja.xlf b/src/Compiler/xlf/FSComp.txt.ja.xlf index 0c06cac0f88..1b78af88a64 100644 --- a/src/Compiler/xlf/FSComp.txt.ja.xlf +++ b/src/Compiler/xlf/FSComp.txt.ja.xlf @@ -182,6 +182,16 @@ 引数 '{0}' が一致しません + + The type '{0}' does not support the operator '{1}' as required by '{2}' + The type '{0}' does not support the operator '{1}' as required by '{2}' + + + + None of the types '{0}' support the operator '{1}' as required by '{2}' + None of the types '{0}' support the operator '{1}' as required by '{2}' + + The constraints 'unmanaged' and 'not struct' are inconsistent 制約 'unmanaged' と 'not struct' が矛盾しています diff --git a/src/Compiler/xlf/FSComp.txt.ko.xlf b/src/Compiler/xlf/FSComp.txt.ko.xlf index 3d9583d3222..6d00c9a9ecf 100644 --- a/src/Compiler/xlf/FSComp.txt.ko.xlf +++ b/src/Compiler/xlf/FSComp.txt.ko.xlf @@ -182,6 +182,16 @@ '{0}' 인수가 일치하지 않습니다. + + The type '{0}' does not support the operator '{1}' as required by '{2}' + The type '{0}' does not support the operator '{1}' as required by '{2}' + + + + None of the types '{0}' support the operator '{1}' as required by '{2}' + None of the types '{0}' support the operator '{1}' as required by '{2}' + + The constraints 'unmanaged' and 'not struct' are inconsistent 제약 조건 'unmanaged' 및 'not struct'가 일치하지 않습니다. diff --git a/src/Compiler/xlf/FSComp.txt.pl.xlf b/src/Compiler/xlf/FSComp.txt.pl.xlf index 65dca15b653..8107b120582 100644 --- a/src/Compiler/xlf/FSComp.txt.pl.xlf +++ b/src/Compiler/xlf/FSComp.txt.pl.xlf @@ -182,6 +182,16 @@ Argument „{0}” nie jest zgodny + + The type '{0}' does not support the operator '{1}' as required by '{2}' + The type '{0}' does not support the operator '{1}' as required by '{2}' + + + + None of the types '{0}' support the operator '{1}' as required by '{2}' + None of the types '{0}' support the operator '{1}' as required by '{2}' + + The constraints 'unmanaged' and 'not struct' are inconsistent Ograniczenia „unmanaged” i „not struct” są niespójne diff --git a/src/Compiler/xlf/FSComp.txt.pt-BR.xlf b/src/Compiler/xlf/FSComp.txt.pt-BR.xlf index ba4b50a2c6a..bd28996a5ad 100644 --- a/src/Compiler/xlf/FSComp.txt.pt-BR.xlf +++ b/src/Compiler/xlf/FSComp.txt.pt-BR.xlf @@ -182,6 +182,16 @@ O argumento '{0}' não corresponde + + The type '{0}' does not support the operator '{1}' as required by '{2}' + The type '{0}' does not support the operator '{1}' as required by '{2}' + + + + None of the types '{0}' support the operator '{1}' as required by '{2}' + None of the types '{0}' support the operator '{1}' as required by '{2}' + + The constraints 'unmanaged' and 'not struct' are inconsistent As restrições "unmanaged" e "not struct" são inconsistentes diff --git a/src/Compiler/xlf/FSComp.txt.ru.xlf b/src/Compiler/xlf/FSComp.txt.ru.xlf index e3963936887..b297c333187 100644 --- a/src/Compiler/xlf/FSComp.txt.ru.xlf +++ b/src/Compiler/xlf/FSComp.txt.ru.xlf @@ -182,6 +182,16 @@ Аргумент "{0}" не соответствует + + The type '{0}' does not support the operator '{1}' as required by '{2}' + The type '{0}' does not support the operator '{1}' as required by '{2}' + + + + None of the types '{0}' support the operator '{1}' as required by '{2}' + None of the types '{0}' support the operator '{1}' as required by '{2}' + + The constraints 'unmanaged' and 'not struct' are inconsistent Ограничения "unmanaged" и "not struct" несовместимы diff --git a/src/Compiler/xlf/FSComp.txt.tr.xlf b/src/Compiler/xlf/FSComp.txt.tr.xlf index a1e87d37ec8..c2d1701a8b3 100644 --- a/src/Compiler/xlf/FSComp.txt.tr.xlf +++ b/src/Compiler/xlf/FSComp.txt.tr.xlf @@ -182,6 +182,16 @@ '{0}' bağımsız değişkeni eşleşmiyor + + The type '{0}' does not support the operator '{1}' as required by '{2}' + The type '{0}' does not support the operator '{1}' as required by '{2}' + + + + None of the types '{0}' support the operator '{1}' as required by '{2}' + None of the types '{0}' support the operator '{1}' as required by '{2}' + + The constraints 'unmanaged' and 'not struct' are inconsistent 'unmanaged' ve 'not struct' kısıtlamaları tutarsız diff --git a/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf b/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf index a9ed1325b64..b5a3e20648e 100644 --- a/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf +++ b/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf @@ -182,6 +182,16 @@ 参数 "{0}" 不匹配 + + The type '{0}' does not support the operator '{1}' as required by '{2}' + The type '{0}' does not support the operator '{1}' as required by '{2}' + + + + None of the types '{0}' support the operator '{1}' as required by '{2}' + None of the types '{0}' support the operator '{1}' as required by '{2}' + + The constraints 'unmanaged' and 'not struct' are inconsistent 约束 "unmanaged" 和 "not struct" 不一致 diff --git a/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf b/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf index 6bef41283f5..a4831f8e25e 100644 --- a/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf +++ b/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf @@ -182,6 +182,16 @@ 引數 '{0}' 不相符 + + The type '{0}' does not support the operator '{1}' as required by '{2}' + The type '{0}' does not support the operator '{1}' as required by '{2}' + + + + None of the types '{0}' support the operator '{1}' as required by '{2}' + None of the types '{0}' support the operator '{1}' as required by '{2}' + + The constraints 'unmanaged' and 'not struct' are inconsistent 條件約束 'unmanaged' 與 'not struct' 不一致 From ba19c54356a3fbb6cdf14a05e94e4861ec94bf75 Mon Sep 17 00:00:00 2001 From: Martin521 <29605222+Martin521@users.noreply.github.com> Date: Sun, 19 Nov 2023 17:06:50 +0000 Subject: [PATCH 03/16] fixed formatting --- src/Compiler/TypedTree/TypedTree.fsi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Compiler/TypedTree/TypedTree.fsi b/src/Compiler/TypedTree/TypedTree.fsi index fe0f1a97ed0..575329e2b10 100644 --- a/src/Compiler/TypedTree/TypedTree.fsi +++ b/src/Compiler/TypedTree/TypedTree.fsi @@ -1716,9 +1716,9 @@ type TraitConstraintInfo = /// The member kind is irrelevant to the logical properties of a trait. However it adjusts /// the extension property MemberDisplayNameCore member WithMemberKind: SynMemberKind -> TraitConstraintInfo - + member WithSupportTypes: TTypes -> TraitConstraintInfo - + member WithMemberName: string -> TraitConstraintInfo /// Represents the solution of a member constraint during inference. From e668683ba0463ad95c433e7092b849c8f5aea79b Mon Sep 17 00:00:00 2001 From: Martin521 <29605222+Martin521@users.noreply.github.com> Date: Sun, 19 Nov 2023 20:09:12 +0000 Subject: [PATCH 04/16] fixed regression --- src/Compiler/Checking/ConstraintSolver.fs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Compiler/Checking/ConstraintSolver.fs b/src/Compiler/Checking/ConstraintSolver.fs index a74042f3826..48eb2eafdaa 100644 --- a/src/Compiler/Checking/ConstraintSolver.fs +++ b/src/Compiler/Checking/ConstraintSolver.fs @@ -1755,9 +1755,11 @@ and SolveMemberConstraint (csenv: ConstraintSolverEnv) ignoreUnresolvedOverload else FSComp.SR.csTypesDoNotSupportOperatorNullable(tyString, opName) | _ -> match supportTys, source.Value with - | [_], Some s when s <> nm -> FSComp.SR.csTypeDoesNotSupportOperatorW(tyString, opName,s ) + | [_], Some s when s <> nm -> + FSComp.SR.csTypeDoesNotSupportOperatorW(tyString, nm, s) | [_], _ -> FSComp.SR.csTypeDoesNotSupportOperator(tyString, opName) - | _, Some s when s <> nm -> FSComp.SR.csTypesDoNotSupportOperatorW(tyString, opName,s ) + | _, Some s when s <> nm -> + FSComp.SR.csTypesDoNotSupportOperatorW(tyString, nm, s) | _, _ -> FSComp.SR.csTypesDoNotSupportOperator(tyString, opName) return! ErrorD(ConstraintSolverError(err, m, m2)) From 882586095557238fa96ab4a369fc4fb4c997df86 Mon Sep 17 00:00:00 2001 From: Martin521 <29605222+Martin521@users.noreply.github.com> Date: Sun, 19 Nov 2023 22:27:30 +0000 Subject: [PATCH 05/16] extended test for self-referring constraints --- .devcontainer/Dockerfile | 2 +- src/Compiler/Checking/ConstraintSolver.fs | 10 ++++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 48fd924ad2d..e1dcf31c425 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -24,4 +24,4 @@ RUN apt-get update \ ENV DEBIAN_FRONTEND=dialog # Make sure we can build using plain dotnet -ENV BUILDING_USING_DOTNET="true" \ No newline at end of file +ENV BUILDING_USING_DOTNET="true" diff --git a/src/Compiler/Checking/ConstraintSolver.fs b/src/Compiler/Checking/ConstraintSolver.fs index 48eb2eafdaa..352e2a13e06 100644 --- a/src/Compiler/Checking/ConstraintSolver.fs +++ b/src/Compiler/Checking/ConstraintSolver.fs @@ -1754,12 +1754,14 @@ and SolveMemberConstraint (csenv: ConstraintSolverEnv) ignoreUnresolvedOverload if List.isSingleton supportTys then FSComp.SR.csTypeDoesNotSupportOperatorNullable(tyString, opName) else FSComp.SR.csTypesDoNotSupportOperatorNullable(tyString, opName) | _ -> + let isSameOp s = // Temporary hack for issue83 fix. Use LogicalName?? + s = nm || s = nm.ToLower() || nm.Length > 4 && nm[1..3] = "et_" && s = nm[4..] match supportTys, source.Value with - | [_], Some s when s <> nm -> - FSComp.SR.csTypeDoesNotSupportOperatorW(tyString, nm, s) + | [_], Some s when not (isSameOp s) -> + FSComp.SR.csTypeDoesNotSupportOperatorW(tyString, opName, s) | [_], _ -> FSComp.SR.csTypeDoesNotSupportOperator(tyString, opName) - | _, Some s when s <> nm -> - FSComp.SR.csTypesDoNotSupportOperatorW(tyString, nm, s) + | _, Some s when not (isSameOp s) -> + FSComp.SR.csTypesDoNotSupportOperatorW(tyString, opName, s) | _, _ -> FSComp.SR.csTypesDoNotSupportOperator(tyString, opName) return! ErrorD(ConstraintSolverError(err, m, m2)) From 1a4c3a5bf53d209ceb4e3dd2249909fba8e855ce Mon Sep 17 00:00:00 2001 From: Martin521 <29605222+Martin521@users.noreply.github.com> Date: Mon, 20 Nov 2023 08:48:18 +0000 Subject: [PATCH 06/16] fix for sign tests --- src/Compiler/Checking/ConstraintSolver.fs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Compiler/Checking/ConstraintSolver.fs b/src/Compiler/Checking/ConstraintSolver.fs index 352e2a13e06..d80278985d4 100644 --- a/src/Compiler/Checking/ConstraintSolver.fs +++ b/src/Compiler/Checking/ConstraintSolver.fs @@ -1754,8 +1754,8 @@ and SolveMemberConstraint (csenv: ConstraintSolverEnv) ignoreUnresolvedOverload if List.isSingleton supportTys then FSComp.SR.csTypeDoesNotSupportOperatorNullable(tyString, opName) else FSComp.SR.csTypesDoNotSupportOperatorNullable(tyString, opName) | _ -> - let isSameOp s = // Temporary hack for issue83 fix. Use LogicalName?? - s = nm || s = nm.ToLower() || nm.Length > 4 && nm[1..3] = "et_" && s = nm[4..] + let isSameOp s = // Temporary hack for issue83 fix. Use LogicalName?? Special handling for internal operators?? + s = nm || s = nm.ToLower() || nm.Length > 4 && nm[1..3] = "et_" && s = nm[4..].ToLower() match supportTys, source.Value with | [_], Some s when not (isSameOp s) -> FSComp.SR.csTypeDoesNotSupportOperatorW(tyString, opName, s) From e462a173e64a525f350f26d0e82054d17fade344 Mon Sep 17 00:00:00 2001 From: Martin521 <29605222+Martin521@users.noreply.github.com> Date: Mon, 20 Nov 2023 10:05:31 +0000 Subject: [PATCH 07/16] adjusted fsharpqa test --- .../EnumTypes/E_NoMethodsOnEnums01.fs | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/EnumTypes/E_NoMethodsOnEnums01.fs b/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/EnumTypes/E_NoMethodsOnEnums01.fs index b4e05661698..f480258d91f 100644 --- a/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/EnumTypes/E_NoMethodsOnEnums01.fs +++ b/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/EnumTypes/E_NoMethodsOnEnums01.fs @@ -1,6 +1,5 @@ // #Regression #Conformance #ObjectOrientedTypes #Enums //Enumerations cannot have members$ -//The type 'Season' does not support the operator 'get_One'$ type Season = Spring=0 | Summer=1 | Autumn=2 | Winter=3 with From eaefa0cca4f534bc93160a61fb7d8177e7420814 Mon Sep 17 00:00:00 2001 From: Martin521 <29605222+Martin521@users.noreply.github.com> Date: Sun, 10 Dec 2023 18:12:09 +0000 Subject: [PATCH 08/16] fix looks good to me; all local tests passing --- src/Compiler/Checking/CheckExpressions.fs | 7 ++-- src/Compiler/Checking/ConstraintSolver.fs | 29 +++++++------- src/Compiler/Checking/FindUnsolved.fs | 2 +- src/Compiler/Checking/NicePrint.fs | 2 +- src/Compiler/Checking/PostInferenceChecks.fs | 12 +++--- src/Compiler/Driver/CompilerImports.fs | 18 +++++++++ src/Compiler/FSComp.txt | 2 + src/Compiler/Symbols/Exprs.fs | 8 ++-- src/Compiler/Symbols/Symbols.fs | 12 +++--- src/Compiler/TypedTree/TypedTree.fs | 38 ++++++++++++------- src/Compiler/TypedTree/TypedTree.fsi | 8 +++- src/Compiler/TypedTree/TypedTreeOps.fs | 18 ++++----- src/Compiler/TypedTree/TypedTreePickle.fs | 4 +- src/Compiler/xlf/FSComp.txt.cs.xlf | 10 +++++ src/Compiler/xlf/FSComp.txt.de.xlf | 10 +++++ src/Compiler/xlf/FSComp.txt.es.xlf | 10 +++++ src/Compiler/xlf/FSComp.txt.fr.xlf | 10 +++++ src/Compiler/xlf/FSComp.txt.it.xlf | 10 +++++ src/Compiler/xlf/FSComp.txt.ja.xlf | 10 +++++ src/Compiler/xlf/FSComp.txt.ko.xlf | 10 +++++ src/Compiler/xlf/FSComp.txt.pl.xlf | 10 +++++ src/Compiler/xlf/FSComp.txt.pt-BR.xlf | 10 +++++ src/Compiler/xlf/FSComp.txt.ru.xlf | 10 +++++ src/Compiler/xlf/FSComp.txt.tr.xlf | 10 +++++ src/Compiler/xlf/FSComp.txt.zh-Hans.xlf | 10 +++++ src/Compiler/xlf/FSComp.txt.zh-Hant.xlf | 10 +++++ .../ConstraintSolver/MemberConstraints.fs | 10 +++++ .../EnumTypes/E_NoMethodsOnEnums01.fs | 1 - 28 files changed, 240 insertions(+), 61 deletions(-) diff --git a/src/Compiler/Checking/CheckExpressions.fs b/src/Compiler/Checking/CheckExpressions.fs index 6f169d474a8..0fe7e428fc3 100644 --- a/src/Compiler/Checking/CheckExpressions.fs +++ b/src/Compiler/Checking/CheckExpressions.fs @@ -4076,7 +4076,8 @@ and TcConstraintWhereTyparSupportsMember cenv env newOk tpenv synSupportTys synM let g = cenv.g let traitInfo, tpenv = TcPseudoMemberSpec cenv newOk env synSupportTys tpenv synMemberSig m match traitInfo with - | TTrait(objTys, ".ctor", memberFlags, argTys, returnTy, _) when memberFlags.MemberKind = SynMemberKind.Constructor -> + | TTrait(tys=objTys; memberName=".ctor"; memberFlags=memberFlags; objAndArgTys=argTys; returnTyOpt=returnTy) + when memberFlags.MemberKind = SynMemberKind.Constructor -> match objTys, argTys with | [ty], [] when typeEquiv g ty (GetFSharpViewOfReturnType g returnTy) -> AddCxTypeMustSupportDefaultCtor env.DisplayEnv cenv.css m NoTrace ty @@ -4125,7 +4126,7 @@ and TcPseudoMemberSpec cenv newOk env synTypes tpenv synMemberSig m = let item = Item.OtherName (Some id, memberConstraintTy, None, None, id.idRange) CallNameResolutionSink cenv.tcSink (id.idRange, env.NameEnv, item, emptyTyparInst, ItemOccurence.Use, env.AccessRights) - TTrait(tys, logicalCompiledName, memberFlags, argTys, returnTy, ref None), tpenv + TTrait(tys, logicalCompiledName, memberFlags, argTys, returnTy, ref None, ref None), tpenv | _ -> error(Error(FSComp.SR.tcInvalidConstraint(), m)) @@ -8807,7 +8808,7 @@ and TcImplicitOpItemThen (cenv: cenv) overallTy env id sln tpenv mItem delayed = let memberFlags = StaticMemberFlags SynMemberKind.Member let logicalCompiledName = ComputeLogicalName id memberFlags - let traitInfo = TTrait(argTys, logicalCompiledName, memberFlags, argTys, Some retTy, sln) + let traitInfo = TTrait(argTys, logicalCompiledName, memberFlags, argTys, Some retTy, ref None, sln) let expr = Expr.Op (TOp.TraitCall traitInfo, [], ves, mItem) let expr = mkLambdas g mItem [] vs (expr, retTy) diff --git a/src/Compiler/Checking/ConstraintSolver.fs b/src/Compiler/Checking/ConstraintSolver.fs index 3c0f68c2859..1d6e40b55f5 100644 --- a/src/Compiler/Checking/ConstraintSolver.fs +++ b/src/Compiler/Checking/ConstraintSolver.fs @@ -1394,7 +1394,7 @@ and SolveDimensionlessNumericType (csenv: ConstraintSolverEnv) ndeep m2 trace ty /// /// 2. Some additional solutions are forced prior to generalization (permitWeakResolution= Yes or YesDuringCodeGen). See above and SolveMemberConstraint (csenv: ConstraintSolverEnv) ignoreUnresolvedOverload permitWeakResolution ndeep m2 trace traitInfo : OperationResult = trackErrors { - let (TTrait(supportTys, nm, memFlags, traitObjAndArgTys, retTy, sln)) = traitInfo + let (TTrait(supportTys, nm, memFlags, traitObjAndArgTys, retTy, source, sln)) = traitInfo // Do not re-solve if already solved if sln.Value.IsSome then return true else @@ -1411,8 +1411,8 @@ and SolveMemberConstraint (csenv: ConstraintSolverEnv) ignoreUnresolvedOverload let supportTys = ListSet.setify (typeAEquiv g aenv) supportTys // Rebuild the trait info after removing duplicates - let traitInfo = TTrait(supportTys, nm, memFlags, traitObjAndArgTys, retTy, sln) - let retTy = GetFSharpViewOfReturnType g retTy + let traitInfo = traitInfo.WithSupportTypes supportTys + let retTy = GetFSharpViewOfReturnType g retTy // Assert the object type if the constraint is for an instance member if memFlags.IsInstance then @@ -1754,8 +1754,11 @@ and SolveMemberConstraint (csenv: ConstraintSolverEnv) ignoreUnresolvedOverload if List.isSingleton supportTys then FSComp.SR.csTypeDoesNotSupportOperatorNullable(tyString, opName) else FSComp.SR.csTypesDoNotSupportOperatorNullable(tyString, opName) | _ -> - if List.isSingleton supportTys then FSComp.SR.csTypeDoesNotSupportOperator(tyString, opName) - else FSComp.SR.csTypesDoNotSupportOperator(tyString, opName) + match supportTys, source.Value with + | [_], Some s when s <> nm -> FSComp.SR.csTypeDoesNotSupportOperatorW(tyString, opName, s) + | [_], _ -> FSComp.SR.csTypeDoesNotSupportOperator(tyString, opName) + | _, Some s when s <> nm -> FSComp.SR.csTypesDoNotSupportOperatorW(tyString, opName, s) + | _, _ -> FSComp.SR.csTypesDoNotSupportOperator(tyString, opName) return! ErrorD(ConstraintSolverError(err, m, m2)) | _ -> @@ -1928,7 +1931,6 @@ and TransactMemberConstraintSolution traitInfo (trace: OptionalTrace) sln = /// Only consider overload resolution if canonicalizing or all the types are now nominal. /// That is, don't perform resolution if more nominal information may influence the set of available overloads and GetRelevantMethodsForTrait (csenv: ConstraintSolverEnv) (permitWeakResolution: PermitWeakResolution) nm traitInfo : (TType * MethInfo) list = - let (TTrait(_, _, memFlags, _, _, _)) = traitInfo let results = if permitWeakResolution.Permit || MemberConstraintSupportIsReadyForDeterminingOverloads csenv traitInfo then let m = csenv.m @@ -1938,7 +1940,7 @@ and GetRelevantMethodsForTrait (csenv: ConstraintSolverEnv) (permitWeakResolutio let minfos = [ for (supportTy, nominalTy) in nominalTys do let infos = - match memFlags.MemberKind with + match traitInfo.MemberFlags.MemberKind with | SynMemberKind.Constructor -> GetIntrinsicConstructorInfosOfType csenv.SolverState.InfoReader m nominalTy | _ -> @@ -1962,8 +1964,7 @@ and GetRelevantMethodsForTrait (csenv: ConstraintSolverEnv) (permitWeakResolutio // The trait name "op_Explicit" also covers "op_Implicit", so look for that one too. if nm = "op_Explicit" then - let (TTrait(supportTys, _, memFlags, argTys, retTy, soln)) = traitInfo - let traitInfo2 = TTrait(supportTys, "op_Implicit", memFlags, argTys, retTy, soln) + let traitInfo2 = traitInfo.WithMemberName "op_Implicit" results @ GetRelevantMethodsForTrait csenv permitWeakResolution "op_Implicit" traitInfo2 else results @@ -2020,7 +2021,7 @@ and SupportTypeOfMemberConstraintIsSolved (csenv: ConstraintSolverEnv) (traitInf /// Get all the unsolved typars (statically resolved or not) relevant to the member constraint and GetFreeTyparsOfMemberConstraint (csenv: ConstraintSolverEnv) traitInfo = - let (TTrait(supportTys, _, _, argTys, retTy, _)) = traitInfo + let (TTrait(tys=supportTys; objAndArgTys=argTys; returnTyOpt=retTy)) = traitInfo freeInTypesLeftToRightSkippingConstraints csenv.g (supportTys @ argTys @ Option.toList retTy) and MemberConstraintIsReadyForWeakResolution csenv traitInfo = @@ -2104,8 +2105,8 @@ and AddMemberConstraint (csenv: ConstraintSolverEnv) ndeep m2 (trace: OptionalTr and TraitsAreRelated (csenv: ConstraintSolverEnv) retry traitInfo1 traitInfo2 = let g = csenv.g - let (TTrait(tys1, nm1, memFlags1, argTys1, _, _)) = traitInfo1 - let (TTrait(tys2, nm2, memFlags2, argTys2, _, _)) = traitInfo2 + let (TTrait(tys=tys1; memberName=nm1; memberFlags=memFlags1; objAndArgTys=argTys1)) = traitInfo1 + let (TTrait(tys=tys2; memberName=nm2; memberFlags=memFlags2; objAndArgTys=argTys2)) = traitInfo2 memFlags1.IsInstance = memFlags2.IsInstance && nm1 = nm2 && // Multiple op_Explicit and op_Implicit constraints can exist for the same type variable. @@ -2130,8 +2131,8 @@ and EnforceConstraintConsistency (csenv: ConstraintSolverEnv) ndeep m2 trace ret match tpc1, tpc2 with | TyparConstraint.MayResolveMember(traitInfo1, _), TyparConstraint.MayResolveMember(traitInfo2, _) when TraitsAreRelated csenv retry traitInfo1 traitInfo2 -> - let (TTrait(tys1, _, _, argTys1, rty1, _)) = traitInfo1 - let (TTrait(tys2, _, _, argTys2, rty2, _)) = traitInfo2 + let (TTrait(tys=tys1; objAndArgTys=argTys1; returnTyOpt=rty1)) = traitInfo1 + let (TTrait(tys=tys2; objAndArgTys=argTys2; returnTyOpt=rty2)) = traitInfo2 if retry then match tys1, tys2 with | [ty1], [ty2] -> do! SolveTypeEqualsTypeKeepAbbrevs csenv ndeep m2 trace ty1 ty2 diff --git a/src/Compiler/Checking/FindUnsolved.fs b/src/Compiler/Checking/FindUnsolved.fs index cfc34649ae5..10eb7ab672c 100644 --- a/src/Compiler/Checking/FindUnsolved.fs +++ b/src/Compiler/Checking/FindUnsolved.fs @@ -167,7 +167,7 @@ and accOp cenv env (op, tyargs, args, m) = | _ -> () /// Walk a trait call, collecting type variables -and accTraitInfo cenv env (mFallback : range) (TTrait(tys, _nm, _, argTys, retTy, _sln)) = +and accTraitInfo cenv env (mFallback : range) (TTrait(tys=tys; objAndArgTys=argTys; returnTyOpt=retTy)) = argTys |> accTypeInst cenv env mFallback retTy |> Option.iter (accTy cenv env mFallback) tys |> List.iter (accTy cenv env mFallback) diff --git a/src/Compiler/Checking/NicePrint.fs b/src/Compiler/Checking/NicePrint.fs index d3d2ca9c590..34217f4b40d 100644 --- a/src/Compiler/Checking/NicePrint.fs +++ b/src/Compiler/Checking/NicePrint.fs @@ -823,7 +823,7 @@ module PrintTypes = and layoutTraitWithInfo denv env traitInfo = let g = denv.g - let (TTrait(tys, _, memFlags, _, _, _)) = traitInfo + let (TTrait(tys=tys;memberFlags=memFlags)) = traitInfo let nm = traitInfo.MemberDisplayNameCore let nameL = ConvertValLogicalNameToDisplayLayout false (tagMember >> wordL) nm if denv.shortConstraints then diff --git a/src/Compiler/Checking/PostInferenceChecks.fs b/src/Compiler/Checking/PostInferenceChecks.fs index c60fb146d54..e9dee56e748 100644 --- a/src/Compiler/Checking/PostInferenceChecks.fs +++ b/src/Compiler/Checking/PostInferenceChecks.fs @@ -346,7 +346,7 @@ let rec CheckTypeDeep (cenv: cenv) (visitTy, visitTyconRefOpt, visitAppTyOpt, vi | TType_var (tp, _) when tp.Solution.IsSome -> for cx in tp.Constraints do match cx with - | TyparConstraint.MayResolveMember(TTrait(_, _, _, _, _, soln), _) -> + | TyparConstraint.MayResolveMember(TTrait(solution=soln), _) -> match visitTraitSolutionOpt, soln.Value with | Some visitTraitSolution, Some sln -> visitTraitSolution sln | _ -> () @@ -432,11 +432,11 @@ and CheckTypeConstraintDeep cenv f g env x = | TyparConstraint.IsReferenceType _ | TyparConstraint.RequiresDefaultConstructor _ -> () -and CheckTraitInfoDeep cenv (_, _, _, visitTraitSolutionOpt, _ as f) g env (TTrait(tys, _, _, argTys, retTy, soln)) = - CheckTypesDeep cenv f g env tys - CheckTypesDeep cenv f g env argTys - Option.iter (CheckTypeDeep cenv f g env true ) retTy - match visitTraitSolutionOpt, soln.Value with +and CheckTraitInfoDeep cenv (_, _, _, visitTraitSolutionOpt, _ as f) g env traitInfo = + CheckTypesDeep cenv f g env traitInfo.SupportTypes + CheckTypesDeep cenv f g env traitInfo.CompiledObjectAndArgumentTypes + Option.iter (CheckTypeDeep cenv f g env true ) traitInfo.CompiledReturnType + match visitTraitSolutionOpt, traitInfo.Solution with | Some visitTraitSolution, Some sln -> visitTraitSolution sln | _ -> () diff --git a/src/Compiler/Driver/CompilerImports.fs b/src/Compiler/Driver/CompilerImports.fs index e828863c3a8..52663a77d14 100644 --- a/src/Compiler/Driver/CompilerImports.fs +++ b/src/Compiler/Driver/CompilerImports.fs @@ -377,6 +377,21 @@ let IsExe fileName = let ext = Path.GetExtension fileName String.Compare(ext, ".exe", StringComparison.OrdinalIgnoreCase) = 0 +let addConstraintSources(ia: ImportedAssembly) = + let contents = ia.FSharpViewOfMetadata.Contents + let addCxsToMember (v: Val) = + for typar in fst v.GeneralizedType do + for cx in typar.Constraints do + match cx with + | TyparConstraint.MayResolveMember(TTrait(source=source), _) -> + source.Value <- Some v.LogicalName + | _ -> () + let rec addCxsToModule (m: ModuleOrNamespaceType) = + for e in m.ModuleAndNamespaceDefinitions do + if e.IsModuleOrNamespace then addCxsToModule e.ModuleOrNamespaceType + for memb in m.AllValsAndMembers do addCxsToMember memb + addCxsToModule contents.ModuleOrNamespaceType + type TcConfig with member tcConfig.TryResolveLibWithDirectories(r: AssemblyReference) = @@ -2233,6 +2248,9 @@ and [] TcImports let _dllinfos, phase2s = results |> Array.choose id |> List.ofArray |> List.unzip fixupOrphanCcus () let ccuinfos = List.collect (fun phase2 -> phase2 ()) phase2s + if importsBase.IsSome then + importsBase.Value.CcuTable.Values |> Seq.iter addConstraintSources + ccuTable.Values |> Seq.iter addConstraintSources return ccuinfos } diff --git a/src/Compiler/FSComp.txt b/src/Compiler/FSComp.txt index d0fad76ab36..1b258825e00 100644 --- a/src/Compiler/FSComp.txt +++ b/src/Compiler/FSComp.txt @@ -314,7 +314,9 @@ csIndexArgumentMismatch,"This indexer expects %d arguments but is here given %d" csExpectTypeWithOperatorButGivenFunction,"Expecting a type supporting the operator '%s' but given a function type. You may be missing an argument to a function." csExpectTypeWithOperatorButGivenTuple,"Expecting a type supporting the operator '%s' but given a tuple type" csTypesDoNotSupportOperator,"None of the types '%s' support the operator '%s'" +csTypesDoNotSupportOperatorW,"None of the types '%s' support the operator '%s' as required by '%s'" csTypeDoesNotSupportOperator,"The type '%s' does not support the operator '%s'" +csTypeDoesNotSupportOperatorW,"The type '%s' does not support the operator '%s' as required by '%s'" csTypesDoNotSupportOperatorNullable,"None of the types '%s' support the operator '%s'. Consider opening the module 'Microsoft.FSharp.Linq.NullableOperators'." csTypeDoesNotSupportOperatorNullable,"The type '%s' does not support the operator '%s'. Consider opening the module 'Microsoft.FSharp.Linq.NullableOperators'." csTypeDoesNotSupportConversion,"The type '%s' does not support a conversion to the type '%s'" diff --git a/src/Compiler/Symbols/Exprs.fs b/src/Compiler/Symbols/Exprs.fs index 3aa8f1cbe5e..4d0b994f35b 100644 --- a/src/Compiler/Symbols/Exprs.fs +++ b/src/Compiler/Symbols/Exprs.fs @@ -899,12 +899,12 @@ module FSharpExprConvert = let typR = ConvType cenv (mkAppTy tycr tyargs) E.UnionCaseTag(ConvExpr cenv env arg1, typR) - | TOp.TraitCall (TTrait(tys, nm, memFlags, argTys, _retTy, _solution)), _, _ -> - let tysR = ConvTypes cenv tys + | TOp.TraitCall traitInfo, _, _ -> + let tysR = ConvTypes cenv traitInfo.SupportTypes let tyargsR = ConvTypes cenv tyargs - let argTysR = ConvTypes cenv argTys + let argTysR = ConvTypes cenv traitInfo.CompiledObjectAndArgumentTypes let argsR = ConvExprs cenv env args - E.TraitCall(tysR, nm, memFlags, argTysR, tyargsR, argsR) + E.TraitCall(tysR, traitInfo.MemberLogicalName, traitInfo.MemberFlags, argTysR, tyargsR, argsR) | TOp.RefAddrGet readonly, [ty], [e] -> let replExpr = mkRecdFieldGetAddrViaExprAddr(readonly, e, mkRefCellContentsRef g, [ty], m) diff --git a/src/Compiler/Symbols/Symbols.fs b/src/Compiler/Symbols/Symbols.fs index e405ded53e5..3286cbaa038 100644 --- a/src/Compiler/Symbols/Symbols.fs +++ b/src/Compiler/Symbols/Symbols.fs @@ -1461,18 +1461,18 @@ type FSharpGenericParameterMemberConstraint(cenv, info: TraitConstraintInfo) = (fun () -> Item.Trait(info)), (fun _ _ _ad -> true)) - let (TTrait(tys, nm, flags, atys, retTy, _)) = info member _.MemberSources = - tys |> List.map (fun ty -> FSharpType(cenv, ty)) |> makeReadOnlyCollection + info.SupportTypes |> List.map (fun ty -> FSharpType(cenv, ty)) |> makeReadOnlyCollection - member _.MemberName = nm + member _.MemberName = info.MemberLogicalName - member _.MemberIsStatic = not flags.IsInstance + member _.MemberIsStatic = not info.MemberFlags.IsInstance - member _.MemberArgumentTypes = atys |> List.map (fun ty -> FSharpType(cenv, ty)) |> makeReadOnlyCollection + member _.MemberArgumentTypes = + info.CompiledObjectAndArgumentTypes |> List.map (fun ty -> FSharpType(cenv, ty)) |> makeReadOnlyCollection member _.MemberReturnType = - match retTy with + match info.CompiledReturnType with | None -> FSharpType(cenv, cenv.g.unit_ty) | Some ty -> FSharpType(cenv, ty) override x.ToString() = "" diff --git a/src/Compiler/TypedTree/TypedTree.fs b/src/Compiler/TypedTree/TypedTree.fs index a0665d32212..2109361291e 100644 --- a/src/Compiler/TypedTree/TypedTree.fs +++ b/src/Compiler/TypedTree/TypedTree.fs @@ -2454,29 +2454,41 @@ type TraitWitnessInfo = type TraitConstraintInfo = /// Indicates the signature of a member constraint. Contains a mutable solution cell - /// to store the inferred solution of the constraint. - | TTrait of tys: TTypes * memberName: string * memberFlags: SynMemberFlags * objAndArgTys: TTypes * returnTyOpt: TType option * solution: TraitConstraintSln option ref + /// to store the inferred solution of the constraint. And a mutable source cell to store + /// the name of the type or member that defined the constraint. + | TTrait of + tys: TTypes * + memberName: string * + memberFlags: SynMemberFlags * + objAndArgTys: TTypes * + returnTyOpt: TType option * + source: string option ref * + solution: TraitConstraintSln option ref /// Get the types that may provide solutions for the traits - member x.SupportTypes = (let (TTrait(tys, _, _, _, _, _)) = x in tys) + member x.SupportTypes = (let (TTrait(tys = tys)) = x in tys) /// Get the logical member name associated with the member constraint. - member x.MemberLogicalName = (let (TTrait(_, nm, _, _, _, _)) = x in nm) + member x.MemberLogicalName = (let (TTrait(memberName = nm)) = x in nm) /// Get the member flags associated with the member constraint. - member x.MemberFlags = (let (TTrait(_, _, flags, _, _, _)) = x in flags) - - member x.CompiledObjectAndArgumentTypes = (let (TTrait(_, _, _, objAndArgTys, _, _)) = x in objAndArgTys) - - member x.WithMemberKind(kind) = (let (TTrait(a, b, c, d, e, f)) = x in TTrait(a, b, { c with MemberKind=kind }, d, e, f)) + member x.MemberFlags = (let (TTrait(memberFlags = flags)) = x in flags) + member x.CompiledObjectAndArgumentTypes = (let (TTrait(objAndArgTys = objAndArgTys)) = x in objAndArgTys) + /// Get the optional return type recorded in the member constraint. - member x.CompiledReturnType = (let (TTrait(_, _, _, _, retTy, _)) = x in retTy) - + member x.CompiledReturnType = (let (TTrait(returnTyOpt = retTy)) = x in retTy) + /// Get or set the solution of the member constraint during inference member x.Solution - with get() = (let (TTrait(_, _, _, _, _, sln)) = x in sln.Value) - and set v = (let (TTrait(_, _, _, _, _, sln)) = x in sln.Value <- v) + with get() = (let (TTrait(solution = sln)) = x in sln.Value) + and set v = (let (TTrait(solution = sln)) = x in sln.Value <- v) + + member x.WithMemberKind(kind) = (let (TTrait(a, b, c, d, e, f, g)) = x in TTrait(a, b, { c with MemberKind=kind }, d, e, f, g)) + + member x.WithSupportTypes(tys) = (let (TTrait(_, b, c, d, e, f, g)) = x in TTrait(tys, b, c, d, e, f, g)) + + member x.WithMemberName(name) = (let (TTrait(a, _, c, d, e, f, g)) = x in TTrait(a, name, c, d, e, f, g)) [] member x.DebugText = x.ToString() diff --git a/src/Compiler/TypedTree/TypedTree.fsi b/src/Compiler/TypedTree/TypedTree.fsi index 61674b35fa1..3eb47b5eb47 100644 --- a/src/Compiler/TypedTree/TypedTree.fsi +++ b/src/Compiler/TypedTree/TypedTree.fsi @@ -1678,13 +1678,15 @@ type TraitWitnessInfo = type TraitConstraintInfo = /// Indicates the signature of a member constraint. Contains a mutable solution cell - /// to store the inferred solution of the constraint. + /// to store the inferred solution of the constraint. And a mutable source cell to store + /// the name of the type or member that defined the constraint. | TTrait of tys: TTypes * memberName: string * memberFlags: Syntax.SynMemberFlags * objAndArgTys: TTypes * returnTyOpt: TType option * + source: string option ref * solution: TraitConstraintSln option ref override ToString: unit -> string @@ -1719,6 +1721,10 @@ type TraitConstraintInfo = /// the extension property MemberDisplayNameCore member WithMemberKind: SynMemberKind -> TraitConstraintInfo + member WithSupportTypes: TTypes -> TraitConstraintInfo + + member WithMemberName: string -> TraitConstraintInfo + /// Represents the solution of a member constraint during inference. [] type TraitConstraintSln = diff --git a/src/Compiler/TypedTree/TypedTreeOps.fs b/src/Compiler/TypedTree/TypedTreeOps.fs index 76e730eab6c..5192f604df4 100644 --- a/src/Compiler/TypedTree/TypedTreeOps.fs +++ b/src/Compiler/TypedTree/TypedTreeOps.fs @@ -261,7 +261,7 @@ and remapTyparConstraintsAux tyenv cs = | TyparConstraint.IsReferenceType _ | TyparConstraint.RequiresDefaultConstructor _ -> Some x) -and remapTraitInfo tyenv (TTrait(tys, nm, flags, argTys, retTy, slnCell)) = +and remapTraitInfo tyenv (TTrait(tys, nm, flags, argTys, retTy, source, slnCell)) = let slnCell = match slnCell.Value with | None -> None @@ -297,7 +297,7 @@ and remapTraitInfo tyenv (TTrait(tys, nm, flags, argTys, retTy, slnCell)) = // in the same way as types let newSlnCell = ref slnCell - TTrait(tysR, nm, flags, argTysR, retTyR, newSlnCell) + TTrait(tysR, nm, flags, argTysR, retTyR, source, newSlnCell) and bindTypars tps tyargs tpinst = match tps with @@ -960,8 +960,8 @@ type TypeEquivEnv with TypeEquivEnv.Empty.BindEquivTypars tps1 tps2 let rec traitsAEquivAux erasureFlag g aenv traitInfo1 traitInfo2 = - let (TTrait(tys1, nm, mf1, argTys, retTy, _)) = traitInfo1 - let (TTrait(tys2, nm2, mf2, argTys2, retTy2, _)) = traitInfo2 + let (TTrait(tys1, nm, mf1, argTys, retTy, _, _)) = traitInfo1 + let (TTrait(tys2, nm2, mf2, argTys2, retTy2, _, _)) = traitInfo2 mf1.IsInstance = mf2.IsInstance && nm = nm2 && ListSet.equals (typeAEquivAux erasureFlag g aenv) tys1 tys2 && @@ -2290,7 +2290,7 @@ and accFreeInTyparConstraint opts tpc acc = | TyparConstraint.IsUnmanaged _ | TyparConstraint.RequiresDefaultConstructor _ -> acc -and accFreeInTrait opts (TTrait(tys, _, _, argTys, retTy, sln)) acc = +and accFreeInTrait opts (TTrait(tys, _, _, argTys, retTy, _, sln)) acc = Option.foldBack (accFreeInTraitSln opts) sln.Value (accFreeInTypes opts tys (accFreeInTypes opts argTys @@ -2425,7 +2425,7 @@ and accFreeInTyparConstraintLeftToRight g cxFlag thruFlag acc tpc = | TyparConstraint.IsReferenceType _ | TyparConstraint.RequiresDefaultConstructor _ -> acc -and accFreeInTraitLeftToRight g cxFlag thruFlag acc (TTrait(tys, _, _, argTys, retTy, _)) = +and accFreeInTraitLeftToRight g cxFlag thruFlag acc (TTrait(tys, _, _, argTys, retTy, _, _)) = let acc = accFreeInTypesLeftToRight g cxFlag thruFlag acc tys let acc = accFreeInTypesLeftToRight g cxFlag thruFlag acc argTys let acc = Option.fold (accFreeInTypeLeftToRight g cxFlag thruFlag) acc retTy @@ -2632,7 +2632,7 @@ type TraitConstraintInfo with /// Get the key associated with the member constraint. member traitInfo.GetWitnessInfo() = - let (TTrait(tys, nm, memFlags, objAndArgTys, rty, _)) = traitInfo + let (TTrait(tys, nm, memFlags, objAndArgTys, rty, _, _)) = traitInfo TraitWitnessInfo(tys, nm, memFlags, objAndArgTys, rty) /// Get information about the trait constraints for a set of typars. @@ -4032,7 +4032,7 @@ module DebugPrint = and auxTraitL env (ttrait: TraitConstraintInfo) = #if DEBUG - let (TTrait(tys, nm, memFlags, argTys, retTy, _)) = ttrait + let (TTrait(tys, nm, memFlags, argTys, retTy, _, _)) = ttrait match global_g with | None -> wordL (tagText "") | Some g -> @@ -5365,7 +5365,7 @@ and accFreeInOp opts op acc = | TOp.Reraise -> accUsesRethrow true acc - | TOp.TraitCall (TTrait(tys, _, _, argTys, retTy, sln)) -> + | TOp.TraitCall (TTrait(tys, _, _, argTys, retTy, _, sln)) -> Option.foldBack (accFreeVarsInTraitSln opts) sln.Value (accFreeVarsInTys opts tys (accFreeVarsInTys opts argTys diff --git a/src/Compiler/TypedTree/TypedTreePickle.fs b/src/Compiler/TypedTree/TypedTreePickle.fs index b5b738f8ada..f2fd9887772 100644 --- a/src/Compiler/TypedTree/TypedTreePickle.fs +++ b/src/Compiler/TypedTree/TypedTreePickle.fs @@ -1437,7 +1437,7 @@ let p_trait_sln sln st = p_byte 7 st; p_tup4 p_ty (p_vref "trait") p_tys p_ty (a, b, c, d) st -let p_trait (TTrait(a, b, c, d, e, f)) st = +let p_trait (TTrait(a, b, c, d, e, _, f)) st = p_tup6 p_tys p_string p_MemberFlags p_tys (p_option p_ty) (p_option p_trait_sln) (a, b, c, d, e, f.Value) st let u_anonInfo_data st = @@ -1477,7 +1477,7 @@ let u_trait_sln st = let u_trait st = let a, b, c, d, e, f = u_tup6 u_tys u_string u_MemberFlags u_tys (u_option u_ty) (u_option u_trait_sln) st - TTrait (a, b, c, d, e, ref f) + TTrait (a, b, c, d, e, ref None, ref f) let p_rational q st = p_int32 (GetNumerator q) st; p_int32 (GetDenominator q) st diff --git a/src/Compiler/xlf/FSComp.txt.cs.xlf b/src/Compiler/xlf/FSComp.txt.cs.xlf index 07cccc56186..6bffcb8b263 100644 --- a/src/Compiler/xlf/FSComp.txt.cs.xlf +++ b/src/Compiler/xlf/FSComp.txt.cs.xlf @@ -187,6 +187,16 @@ Argument {0} neodpovídá + + The type '{0}' does not support the operator '{1}' as required by '{2}' + The type '{0}' does not support the operator '{1}' as required by '{2}' + + + + None of the types '{0}' support the operator '{1}' as required by '{2}' + None of the types '{0}' support the operator '{1}' as required by '{2}' + + The constraints 'unmanaged' and 'not struct' are inconsistent Omezení „unmanaged“ a „not struct“ jsou nekonzistentní diff --git a/src/Compiler/xlf/FSComp.txt.de.xlf b/src/Compiler/xlf/FSComp.txt.de.xlf index d9def2b9c6a..148b46012df 100644 --- a/src/Compiler/xlf/FSComp.txt.de.xlf +++ b/src/Compiler/xlf/FSComp.txt.de.xlf @@ -187,6 +187,16 @@ Das Argument "{0}" stimmt nicht überein. + + The type '{0}' does not support the operator '{1}' as required by '{2}' + The type '{0}' does not support the operator '{1}' as required by '{2}' + + + + None of the types '{0}' support the operator '{1}' as required by '{2}' + None of the types '{0}' support the operator '{1}' as required by '{2}' + + The constraints 'unmanaged' and 'not struct' are inconsistent Die Einschränkungen "unmanaged" und "not struct" sind nicht konsistent. diff --git a/src/Compiler/xlf/FSComp.txt.es.xlf b/src/Compiler/xlf/FSComp.txt.es.xlf index 6a6959dc583..3c0c24ca227 100644 --- a/src/Compiler/xlf/FSComp.txt.es.xlf +++ b/src/Compiler/xlf/FSComp.txt.es.xlf @@ -187,6 +187,16 @@ El argumento "{0}" no coincide. + + The type '{0}' does not support the operator '{1}' as required by '{2}' + The type '{0}' does not support the operator '{1}' as required by '{2}' + + + + None of the types '{0}' support the operator '{1}' as required by '{2}' + None of the types '{0}' support the operator '{1}' as required by '{2}' + + The constraints 'unmanaged' and 'not struct' are inconsistent Las restricciones “no administrado” y "no estructurado" son incoherentes diff --git a/src/Compiler/xlf/FSComp.txt.fr.xlf b/src/Compiler/xlf/FSComp.txt.fr.xlf index 8bf1b97e9bc..dc4da9aa1a5 100644 --- a/src/Compiler/xlf/FSComp.txt.fr.xlf +++ b/src/Compiler/xlf/FSComp.txt.fr.xlf @@ -187,6 +187,16 @@ L'argument '{0}' ne correspond pas + + The type '{0}' does not support the operator '{1}' as required by '{2}' + The type '{0}' does not support the operator '{1}' as required by '{2}' + + + + None of the types '{0}' support the operator '{1}' as required by '{2}' + None of the types '{0}' support the operator '{1}' as required by '{2}' + + The constraints 'unmanaged' and 'not struct' are inconsistent Les contraintes « non gérées » et « non structurées » sont incohérentes diff --git a/src/Compiler/xlf/FSComp.txt.it.xlf b/src/Compiler/xlf/FSComp.txt.it.xlf index 135dbc86cf4..b25d44d5af1 100644 --- a/src/Compiler/xlf/FSComp.txt.it.xlf +++ b/src/Compiler/xlf/FSComp.txt.it.xlf @@ -187,6 +187,16 @@ L'argomento '{0}' non corrisponde + + The type '{0}' does not support the operator '{1}' as required by '{2}' + The type '{0}' does not support the operator '{1}' as required by '{2}' + + + + None of the types '{0}' support the operator '{1}' as required by '{2}' + None of the types '{0}' support the operator '{1}' as required by '{2}' + + The constraints 'unmanaged' and 'not struct' are inconsistent I vincoli 'unmanaged' e 'not struct' sono incoerenti diff --git a/src/Compiler/xlf/FSComp.txt.ja.xlf b/src/Compiler/xlf/FSComp.txt.ja.xlf index c4e1d71a82f..c29eacc47e4 100644 --- a/src/Compiler/xlf/FSComp.txt.ja.xlf +++ b/src/Compiler/xlf/FSComp.txt.ja.xlf @@ -187,6 +187,16 @@ 引数 '{0}' が一致しません + + The type '{0}' does not support the operator '{1}' as required by '{2}' + The type '{0}' does not support the operator '{1}' as required by '{2}' + + + + None of the types '{0}' support the operator '{1}' as required by '{2}' + None of the types '{0}' support the operator '{1}' as required by '{2}' + + The constraints 'unmanaged' and 'not struct' are inconsistent 制約 'unmanaged' と 'not struct' が矛盾しています diff --git a/src/Compiler/xlf/FSComp.txt.ko.xlf b/src/Compiler/xlf/FSComp.txt.ko.xlf index 4751ad79ebc..54716b5ad95 100644 --- a/src/Compiler/xlf/FSComp.txt.ko.xlf +++ b/src/Compiler/xlf/FSComp.txt.ko.xlf @@ -187,6 +187,16 @@ '{0}' 인수가 일치하지 않습니다. + + The type '{0}' does not support the operator '{1}' as required by '{2}' + The type '{0}' does not support the operator '{1}' as required by '{2}' + + + + None of the types '{0}' support the operator '{1}' as required by '{2}' + None of the types '{0}' support the operator '{1}' as required by '{2}' + + The constraints 'unmanaged' and 'not struct' are inconsistent 제약 조건 'unmanaged' 및 'not struct'가 일치하지 않습니다. diff --git a/src/Compiler/xlf/FSComp.txt.pl.xlf b/src/Compiler/xlf/FSComp.txt.pl.xlf index 81d62979a4e..a0f5ef752f7 100644 --- a/src/Compiler/xlf/FSComp.txt.pl.xlf +++ b/src/Compiler/xlf/FSComp.txt.pl.xlf @@ -187,6 +187,16 @@ Argument „{0}” nie jest zgodny + + The type '{0}' does not support the operator '{1}' as required by '{2}' + The type '{0}' does not support the operator '{1}' as required by '{2}' + + + + None of the types '{0}' support the operator '{1}' as required by '{2}' + None of the types '{0}' support the operator '{1}' as required by '{2}' + + The constraints 'unmanaged' and 'not struct' are inconsistent Ograniczenia „unmanaged” i „not struct” są niespójne diff --git a/src/Compiler/xlf/FSComp.txt.pt-BR.xlf b/src/Compiler/xlf/FSComp.txt.pt-BR.xlf index 8cdbcdb29c4..5d8866002e5 100644 --- a/src/Compiler/xlf/FSComp.txt.pt-BR.xlf +++ b/src/Compiler/xlf/FSComp.txt.pt-BR.xlf @@ -187,6 +187,16 @@ O argumento '{0}' não corresponde + + The type '{0}' does not support the operator '{1}' as required by '{2}' + The type '{0}' does not support the operator '{1}' as required by '{2}' + + + + None of the types '{0}' support the operator '{1}' as required by '{2}' + None of the types '{0}' support the operator '{1}' as required by '{2}' + + The constraints 'unmanaged' and 'not struct' are inconsistent As restrições "unmanaged" e "not struct" são inconsistentes diff --git a/src/Compiler/xlf/FSComp.txt.ru.xlf b/src/Compiler/xlf/FSComp.txt.ru.xlf index 1319210fbc9..9df1f0e1413 100644 --- a/src/Compiler/xlf/FSComp.txt.ru.xlf +++ b/src/Compiler/xlf/FSComp.txt.ru.xlf @@ -187,6 +187,16 @@ Аргумент "{0}" не соответствует + + The type '{0}' does not support the operator '{1}' as required by '{2}' + The type '{0}' does not support the operator '{1}' as required by '{2}' + + + + None of the types '{0}' support the operator '{1}' as required by '{2}' + None of the types '{0}' support the operator '{1}' as required by '{2}' + + The constraints 'unmanaged' and 'not struct' are inconsistent Ограничения "unmanaged" и "not struct" несовместимы diff --git a/src/Compiler/xlf/FSComp.txt.tr.xlf b/src/Compiler/xlf/FSComp.txt.tr.xlf index d9143a0db5d..0fa0f656482 100644 --- a/src/Compiler/xlf/FSComp.txt.tr.xlf +++ b/src/Compiler/xlf/FSComp.txt.tr.xlf @@ -187,6 +187,16 @@ '{0}' bağımsız değişkeni eşleşmiyor + + The type '{0}' does not support the operator '{1}' as required by '{2}' + The type '{0}' does not support the operator '{1}' as required by '{2}' + + + + None of the types '{0}' support the operator '{1}' as required by '{2}' + None of the types '{0}' support the operator '{1}' as required by '{2}' + + The constraints 'unmanaged' and 'not struct' are inconsistent 'unmanaged' ve 'not struct' kısıtlamaları tutarsız diff --git a/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf b/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf index c62c1e73f6c..3b8ce2cf811 100644 --- a/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf +++ b/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf @@ -187,6 +187,16 @@ 参数 "{0}" 不匹配 + + The type '{0}' does not support the operator '{1}' as required by '{2}' + The type '{0}' does not support the operator '{1}' as required by '{2}' + + + + None of the types '{0}' support the operator '{1}' as required by '{2}' + None of the types '{0}' support the operator '{1}' as required by '{2}' + + The constraints 'unmanaged' and 'not struct' are inconsistent 约束 "unmanaged" 和 "not struct" 不一致 diff --git a/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf b/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf index 5f66fcae4ea..399662fe88b 100644 --- a/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf +++ b/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf @@ -187,6 +187,16 @@ 引數 '{0}' 不相符 + + The type '{0}' does not support the operator '{1}' as required by '{2}' + The type '{0}' does not support the operator '{1}' as required by '{2}' + + + + None of the types '{0}' support the operator '{1}' as required by '{2}' + None of the types '{0}' support the operator '{1}' as required by '{2}' + + The constraints 'unmanaged' and 'not struct' are inconsistent 條件約束 'unmanaged' 與 'not struct' 不一致 diff --git a/tests/FSharp.Compiler.ComponentTests/ConstraintSolver/MemberConstraints.fs b/tests/FSharp.Compiler.ComponentTests/ConstraintSolver/MemberConstraints.fs index 3bb1770b411..ee03683f742 100644 --- a/tests/FSharp.Compiler.ComponentTests/ConstraintSolver/MemberConstraints.fs +++ b/tests/FSharp.Compiler.ComponentTests/ConstraintSolver/MemberConstraints.fs @@ -74,3 +74,13 @@ type DataItem< ^input> with """ |> compile |> shouldSucceed + + [] + let ``Explain why type needs to support operator`` () = + FSharp """ +List.average [42] |> ignore +""" + |> typecheck + |> shouldFail + |> withSingleDiagnostic + (Error 1, Line 2, Col 15, Line 2, Col 17, "The type 'int' does not support the operator 'DivideByInt' as required by 'average'") diff --git a/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/EnumTypes/E_NoMethodsOnEnums01.fs b/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/EnumTypes/E_NoMethodsOnEnums01.fs index b4e05661698..f480258d91f 100644 --- a/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/EnumTypes/E_NoMethodsOnEnums01.fs +++ b/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/EnumTypes/E_NoMethodsOnEnums01.fs @@ -1,6 +1,5 @@ // #Regression #Conformance #ObjectOrientedTypes #Enums //Enumerations cannot have members$ -//The type 'Season' does not support the operator 'get_One'$ type Season = Spring=0 | Summer=1 | Autumn=2 | Winter=3 with From 05107ab976ed11dd3243b6ff88734f709001848f Mon Sep 17 00:00:00 2001 From: Martin521 <29605222+Martin521@users.noreply.github.com> Date: Mon, 11 Dec 2023 13:11:04 +0000 Subject: [PATCH 09/16] changed message text, added correct operator name --- src/Compiler/Checking/ConstraintSolver.fs | 14 +++++++---- src/Compiler/Driver/CompilerImports.fs | 17 ++++++++----- src/Compiler/FSComp.txt | 3 +-- src/Compiler/TypedTree/TypedTree.fsi | 2 +- src/Compiler/xlf/FSComp.txt.cs.xlf | 15 ++++-------- src/Compiler/xlf/FSComp.txt.de.xlf | 15 ++++-------- src/Compiler/xlf/FSComp.txt.es.xlf | 15 ++++-------- src/Compiler/xlf/FSComp.txt.fr.xlf | 15 ++++-------- src/Compiler/xlf/FSComp.txt.it.xlf | 15 ++++-------- src/Compiler/xlf/FSComp.txt.ja.xlf | 15 ++++-------- src/Compiler/xlf/FSComp.txt.ko.xlf | 15 ++++-------- src/Compiler/xlf/FSComp.txt.pl.xlf | 15 ++++-------- src/Compiler/xlf/FSComp.txt.pt-BR.xlf | 15 ++++-------- src/Compiler/xlf/FSComp.txt.ru.xlf | 15 ++++-------- src/Compiler/xlf/FSComp.txt.tr.xlf | 15 ++++-------- src/Compiler/xlf/FSComp.txt.zh-Hans.xlf | 15 ++++-------- src/Compiler/xlf/FSComp.txt.zh-Hant.xlf | 15 ++++-------- .../ConstraintSolver/MemberConstraints.fs | 24 +++++++++++++++++-- .../Libraries/Core/Operators/AbsTests.fs | 14 +++++------ tests/fsharp/typecheck/sigs/neg61.bsl | 2 +- 20 files changed, 118 insertions(+), 153 deletions(-) diff --git a/src/Compiler/Checking/ConstraintSolver.fs b/src/Compiler/Checking/ConstraintSolver.fs index 1d6e40b55f5..35f1fbc432c 100644 --- a/src/Compiler/Checking/ConstraintSolver.fs +++ b/src/Compiler/Checking/ConstraintSolver.fs @@ -1755,10 +1755,16 @@ and SolveMemberConstraint (csenv: ConstraintSolverEnv) ignoreUnresolvedOverload else FSComp.SR.csTypesDoNotSupportOperatorNullable(tyString, opName) | _ -> match supportTys, source.Value with - | [_], Some s when s <> nm -> FSComp.SR.csTypeDoesNotSupportOperatorW(tyString, opName, s) - | [_], _ -> FSComp.SR.csTypeDoesNotSupportOperator(tyString, opName) - | _, Some s when s <> nm -> FSComp.SR.csTypesDoNotSupportOperatorW(tyString, opName, s) - | _, _ -> FSComp.SR.csTypesDoNotSupportOperator(tyString, opName) + | [_], Some s when s.StartsWith("Operators.") -> + let opSource = s[10..] + if opSource = nm then FSComp.SR.csTypeDoesNotSupportOperator(tyString, opName) + else FSComp.SR.csTypeDoesNotSupportOperator(tyString, opSource) + | [_], Some s -> + FSComp.SR.csFunctionDoesNotSupportType(s, tyString, nm) + | [_], _ + -> FSComp.SR.csTypeDoesNotSupportOperator(tyString, opName) + | _, _ + -> FSComp.SR.csTypesDoNotSupportOperator(tyString, opName) return! ErrorD(ConstraintSolverError(err, m, m2)) | _ -> diff --git a/src/Compiler/Driver/CompilerImports.fs b/src/Compiler/Driver/CompilerImports.fs index 52663a77d14..d8d9ccd9866 100644 --- a/src/Compiler/Driver/CompilerImports.fs +++ b/src/Compiler/Driver/CompilerImports.fs @@ -379,18 +379,23 @@ let IsExe fileName = let addConstraintSources(ia: ImportedAssembly) = let contents = ia.FSharpViewOfMetadata.Contents - let addCxsToMember (v: Val) = + let addCxsToMember name (v: Val) = for typar in fst v.GeneralizedType do for cx in typar.Constraints do match cx with | TyparConstraint.MayResolveMember(TTrait(source=source), _) -> - source.Value <- Some v.LogicalName + source.Value <- Some name | _ -> () - let rec addCxsToModule (m: ModuleOrNamespaceType) = + let rec addCxsToModule name (m: ModuleOrNamespaceType) = for e in m.ModuleAndNamespaceDefinitions do - if e.IsModuleOrNamespace then addCxsToModule e.ModuleOrNamespaceType - for memb in m.AllValsAndMembers do addCxsToMember memb - addCxsToModule contents.ModuleOrNamespaceType + if e.IsModuleOrNamespace then + let mname = + if String.length name > 0 then name + "." + e.DisplayName + elif e.IsModule then e.DisplayName + else "" + addCxsToModule mname e.ModuleOrNamespaceType + for memb in m.AllValsAndMembers do addCxsToMember (name + "." + memb.LogicalName) memb + addCxsToModule "" contents.ModuleOrNamespaceType type TcConfig with diff --git a/src/Compiler/FSComp.txt b/src/Compiler/FSComp.txt index 1b258825e00..81669ae6c60 100644 --- a/src/Compiler/FSComp.txt +++ b/src/Compiler/FSComp.txt @@ -314,9 +314,8 @@ csIndexArgumentMismatch,"This indexer expects %d arguments but is here given %d" csExpectTypeWithOperatorButGivenFunction,"Expecting a type supporting the operator '%s' but given a function type. You may be missing an argument to a function." csExpectTypeWithOperatorButGivenTuple,"Expecting a type supporting the operator '%s' but given a tuple type" csTypesDoNotSupportOperator,"None of the types '%s' support the operator '%s'" -csTypesDoNotSupportOperatorW,"None of the types '%s' support the operator '%s' as required by '%s'" csTypeDoesNotSupportOperator,"The type '%s' does not support the operator '%s'" -csTypeDoesNotSupportOperatorW,"The type '%s' does not support the operator '%s' as required by '%s'" +csFunctionDoesNotSupportType,"'%s' does not support the type '%s', because the latter does not have a (real or built-in) member '%s'" csTypesDoNotSupportOperatorNullable,"None of the types '%s' support the operator '%s'. Consider opening the module 'Microsoft.FSharp.Linq.NullableOperators'." csTypeDoesNotSupportOperatorNullable,"The type '%s' does not support the operator '%s'. Consider opening the module 'Microsoft.FSharp.Linq.NullableOperators'." csTypeDoesNotSupportConversion,"The type '%s' does not support a conversion to the type '%s'" diff --git a/src/Compiler/TypedTree/TypedTree.fsi b/src/Compiler/TypedTree/TypedTree.fsi index 3eb47b5eb47..5e46bad2918 100644 --- a/src/Compiler/TypedTree/TypedTree.fsi +++ b/src/Compiler/TypedTree/TypedTree.fsi @@ -1335,7 +1335,7 @@ type ExceptionInfo = /// Represents the contents of of a module of namespace [] -type ModuleOrNamespaceType = +type ModuleOrNamespaceType = new: kind: ModuleOrNamespaceKind * vals: QueueList * entities: QueueList -> ModuleOrNamespaceType diff --git a/src/Compiler/xlf/FSComp.txt.cs.xlf b/src/Compiler/xlf/FSComp.txt.cs.xlf index 6bffcb8b263..c260b54e724 100644 --- a/src/Compiler/xlf/FSComp.txt.cs.xlf +++ b/src/Compiler/xlf/FSComp.txt.cs.xlf @@ -147,6 +147,11 @@ Dostupná přetížení:\n{0} + + '{0}' does not support the type '{1}', because the latter does not have a (real or built-in) member '{2}' + '{0}' does not support the type '{1}', because the latter does not have a (real or built-in) member '{2}' + + A generic construct requires that a generic type parameter be known as a struct or reference type. Consider adding a type annotation. Obecná konstrukce vyžaduje, aby byl parametr obecného typu známý jako typ struct nebo reference. Zvažte možnost přidat anotaci typu. @@ -187,16 +192,6 @@ Argument {0} neodpovídá - - The type '{0}' does not support the operator '{1}' as required by '{2}' - The type '{0}' does not support the operator '{1}' as required by '{2}' - - - - None of the types '{0}' support the operator '{1}' as required by '{2}' - None of the types '{0}' support the operator '{1}' as required by '{2}' - - The constraints 'unmanaged' and 'not struct' are inconsistent Omezení „unmanaged“ a „not struct“ jsou nekonzistentní diff --git a/src/Compiler/xlf/FSComp.txt.de.xlf b/src/Compiler/xlf/FSComp.txt.de.xlf index 148b46012df..8ca0c102dfb 100644 --- a/src/Compiler/xlf/FSComp.txt.de.xlf +++ b/src/Compiler/xlf/FSComp.txt.de.xlf @@ -147,6 +147,11 @@ Verfügbare Überladungen:\n{0} + + '{0}' does not support the type '{1}', because the latter does not have a (real or built-in) member '{2}' + '{0}' does not support the type '{1}', because the latter does not have a (real or built-in) member '{2}' + + A generic construct requires that a generic type parameter be known as a struct or reference type. Consider adding a type annotation. Für ein generisches Konstrukt muss ein generischer Typparameter als Struktur- oder Verweistyp bekannt sein. Erwägen Sie das Hinzufügen einer Typanmerkung. @@ -187,16 +192,6 @@ Das Argument "{0}" stimmt nicht überein. - - The type '{0}' does not support the operator '{1}' as required by '{2}' - The type '{0}' does not support the operator '{1}' as required by '{2}' - - - - None of the types '{0}' support the operator '{1}' as required by '{2}' - None of the types '{0}' support the operator '{1}' as required by '{2}' - - The constraints 'unmanaged' and 'not struct' are inconsistent Die Einschränkungen "unmanaged" und "not struct" sind nicht konsistent. diff --git a/src/Compiler/xlf/FSComp.txt.es.xlf b/src/Compiler/xlf/FSComp.txt.es.xlf index 3c0c24ca227..ea56c008fdb 100644 --- a/src/Compiler/xlf/FSComp.txt.es.xlf +++ b/src/Compiler/xlf/FSComp.txt.es.xlf @@ -147,6 +147,11 @@ Sobrecargas disponibles:\n{0} + + '{0}' does not support the type '{1}', because the latter does not have a (real or built-in) member '{2}' + '{0}' does not support the type '{1}', because the latter does not have a (real or built-in) member '{2}' + + A generic construct requires that a generic type parameter be known as a struct or reference type. Consider adding a type annotation. Una construcción genérica requiere que un parámetro de tipo genérico se conozca como tipo de referencia o estructura. Puede agregar una anotación de tipo. @@ -187,16 +192,6 @@ El argumento "{0}" no coincide. - - The type '{0}' does not support the operator '{1}' as required by '{2}' - The type '{0}' does not support the operator '{1}' as required by '{2}' - - - - None of the types '{0}' support the operator '{1}' as required by '{2}' - None of the types '{0}' support the operator '{1}' as required by '{2}' - - The constraints 'unmanaged' and 'not struct' are inconsistent Las restricciones “no administrado” y "no estructurado" son incoherentes diff --git a/src/Compiler/xlf/FSComp.txt.fr.xlf b/src/Compiler/xlf/FSComp.txt.fr.xlf index dc4da9aa1a5..3b19d0d1c6a 100644 --- a/src/Compiler/xlf/FSComp.txt.fr.xlf +++ b/src/Compiler/xlf/FSComp.txt.fr.xlf @@ -147,6 +147,11 @@ Surcharges disponibles :\n{0} + + '{0}' does not support the type '{1}', because the latter does not have a (real or built-in) member '{2}' + '{0}' does not support the type '{1}', because the latter does not have a (real or built-in) member '{2}' + + A generic construct requires that a generic type parameter be known as a struct or reference type. Consider adding a type annotation. L'utilisation d'une construction générique est possible uniquement si un paramètre de type générique est connu en tant que type struct ou type référence. Ajoutez une annotation de type. @@ -187,16 +192,6 @@ L'argument '{0}' ne correspond pas - - The type '{0}' does not support the operator '{1}' as required by '{2}' - The type '{0}' does not support the operator '{1}' as required by '{2}' - - - - None of the types '{0}' support the operator '{1}' as required by '{2}' - None of the types '{0}' support the operator '{1}' as required by '{2}' - - The constraints 'unmanaged' and 'not struct' are inconsistent Les contraintes « non gérées » et « non structurées » sont incohérentes diff --git a/src/Compiler/xlf/FSComp.txt.it.xlf b/src/Compiler/xlf/FSComp.txt.it.xlf index b25d44d5af1..d0f542b7d1d 100644 --- a/src/Compiler/xlf/FSComp.txt.it.xlf +++ b/src/Compiler/xlf/FSComp.txt.it.xlf @@ -147,6 +147,11 @@ Overload disponibili:\n{0} + + '{0}' does not support the type '{1}', because the latter does not have a (real or built-in) member '{2}' + '{0}' does not support the type '{1}', because the latter does not have a (real or built-in) member '{2}' + + A generic construct requires that a generic type parameter be known as a struct or reference type. Consider adding a type annotation. Un costrutto generico richiede che un parametro di tipo generico sia noto come tipo riferimento o struct. Provare ad aggiungere un'annotazione di tipo. @@ -187,16 +192,6 @@ L'argomento '{0}' non corrisponde - - The type '{0}' does not support the operator '{1}' as required by '{2}' - The type '{0}' does not support the operator '{1}' as required by '{2}' - - - - None of the types '{0}' support the operator '{1}' as required by '{2}' - None of the types '{0}' support the operator '{1}' as required by '{2}' - - The constraints 'unmanaged' and 'not struct' are inconsistent I vincoli 'unmanaged' e 'not struct' sono incoerenti diff --git a/src/Compiler/xlf/FSComp.txt.ja.xlf b/src/Compiler/xlf/FSComp.txt.ja.xlf index c29eacc47e4..404747cbece 100644 --- a/src/Compiler/xlf/FSComp.txt.ja.xlf +++ b/src/Compiler/xlf/FSComp.txt.ja.xlf @@ -147,6 +147,11 @@ 使用可能なオーバーロード:\n{0} + + '{0}' does not support the type '{1}', because the latter does not have a (real or built-in) member '{2}' + '{0}' does not support the type '{1}', because the latter does not have a (real or built-in) member '{2}' + + A generic construct requires that a generic type parameter be known as a struct or reference type. Consider adding a type annotation. ジェネリック コンストラクトでは、ジェネリック型パラメーターが構造体または参照型として認識されている必要があります。型の注釈の追加を検討してください。 @@ -187,16 +192,6 @@ 引数 '{0}' が一致しません - - The type '{0}' does not support the operator '{1}' as required by '{2}' - The type '{0}' does not support the operator '{1}' as required by '{2}' - - - - None of the types '{0}' support the operator '{1}' as required by '{2}' - None of the types '{0}' support the operator '{1}' as required by '{2}' - - The constraints 'unmanaged' and 'not struct' are inconsistent 制約 'unmanaged' と 'not struct' が矛盾しています diff --git a/src/Compiler/xlf/FSComp.txt.ko.xlf b/src/Compiler/xlf/FSComp.txt.ko.xlf index 54716b5ad95..678c87fb98b 100644 --- a/src/Compiler/xlf/FSComp.txt.ko.xlf +++ b/src/Compiler/xlf/FSComp.txt.ko.xlf @@ -147,6 +147,11 @@ 사용 가능한 오버로드:\n{0} + + '{0}' does not support the type '{1}', because the latter does not have a (real or built-in) member '{2}' + '{0}' does not support the type '{1}', because the latter does not have a (real or built-in) member '{2}' + + A generic construct requires that a generic type parameter be known as a struct or reference type. Consider adding a type annotation. 제네릭 구문을 사용하려면 구조체 또는 참조 형식의 제네릭 형식 매개 변수가 필요합니다. 형식 주석을 추가하세요. @@ -187,16 +192,6 @@ '{0}' 인수가 일치하지 않습니다. - - The type '{0}' does not support the operator '{1}' as required by '{2}' - The type '{0}' does not support the operator '{1}' as required by '{2}' - - - - None of the types '{0}' support the operator '{1}' as required by '{2}' - None of the types '{0}' support the operator '{1}' as required by '{2}' - - The constraints 'unmanaged' and 'not struct' are inconsistent 제약 조건 'unmanaged' 및 'not struct'가 일치하지 않습니다. diff --git a/src/Compiler/xlf/FSComp.txt.pl.xlf b/src/Compiler/xlf/FSComp.txt.pl.xlf index a0f5ef752f7..6cc2afe871e 100644 --- a/src/Compiler/xlf/FSComp.txt.pl.xlf +++ b/src/Compiler/xlf/FSComp.txt.pl.xlf @@ -147,6 +147,11 @@ Dostępne przeciążenia:\n{0} + + '{0}' does not support the type '{1}', because the latter does not have a (real or built-in) member '{2}' + '{0}' does not support the type '{1}', because the latter does not have a (real or built-in) member '{2}' + + A generic construct requires that a generic type parameter be known as a struct or reference type. Consider adding a type annotation. Konstrukcja ogólna wymaga, aby parametr typu ogólnego był znany jako struktura lub typ referencyjny. Rozważ dodanie adnotacji typu. @@ -187,16 +192,6 @@ Argument „{0}” nie jest zgodny - - The type '{0}' does not support the operator '{1}' as required by '{2}' - The type '{0}' does not support the operator '{1}' as required by '{2}' - - - - None of the types '{0}' support the operator '{1}' as required by '{2}' - None of the types '{0}' support the operator '{1}' as required by '{2}' - - The constraints 'unmanaged' and 'not struct' are inconsistent Ograniczenia „unmanaged” i „not struct” są niespójne diff --git a/src/Compiler/xlf/FSComp.txt.pt-BR.xlf b/src/Compiler/xlf/FSComp.txt.pt-BR.xlf index 5d8866002e5..40a52cc8d70 100644 --- a/src/Compiler/xlf/FSComp.txt.pt-BR.xlf +++ b/src/Compiler/xlf/FSComp.txt.pt-BR.xlf @@ -147,6 +147,11 @@ Sobrecargas disponíveis:\n{0} + + '{0}' does not support the type '{1}', because the latter does not have a (real or built-in) member '{2}' + '{0}' does not support the type '{1}', because the latter does not have a (real or built-in) member '{2}' + + A generic construct requires that a generic type parameter be known as a struct or reference type. Consider adding a type annotation. Um constructo genérico exige que um parâmetro de tipo genérico seja conhecido como um tipo de referência ou struct. Considere adicionar uma anotação de tipo. @@ -187,16 +192,6 @@ O argumento '{0}' não corresponde - - The type '{0}' does not support the operator '{1}' as required by '{2}' - The type '{0}' does not support the operator '{1}' as required by '{2}' - - - - None of the types '{0}' support the operator '{1}' as required by '{2}' - None of the types '{0}' support the operator '{1}' as required by '{2}' - - The constraints 'unmanaged' and 'not struct' are inconsistent As restrições "unmanaged" e "not struct" são inconsistentes diff --git a/src/Compiler/xlf/FSComp.txt.ru.xlf b/src/Compiler/xlf/FSComp.txt.ru.xlf index 9df1f0e1413..d7726ea254a 100644 --- a/src/Compiler/xlf/FSComp.txt.ru.xlf +++ b/src/Compiler/xlf/FSComp.txt.ru.xlf @@ -147,6 +147,11 @@ Доступные перегрузки:\n{0} + + '{0}' does not support the type '{1}', because the latter does not have a (real or built-in) member '{2}' + '{0}' does not support the type '{1}', because the latter does not have a (real or built-in) member '{2}' + + A generic construct requires that a generic type parameter be known as a struct or reference type. Consider adding a type annotation. В универсальной конструкции требуется использовать параметр универсального типа, известный как структура или ссылочный тип. Рекомендуется добавить заметку с типом. @@ -187,16 +192,6 @@ Аргумент "{0}" не соответствует - - The type '{0}' does not support the operator '{1}' as required by '{2}' - The type '{0}' does not support the operator '{1}' as required by '{2}' - - - - None of the types '{0}' support the operator '{1}' as required by '{2}' - None of the types '{0}' support the operator '{1}' as required by '{2}' - - The constraints 'unmanaged' and 'not struct' are inconsistent Ограничения "unmanaged" и "not struct" несовместимы diff --git a/src/Compiler/xlf/FSComp.txt.tr.xlf b/src/Compiler/xlf/FSComp.txt.tr.xlf index 0fa0f656482..ed7f5f72d09 100644 --- a/src/Compiler/xlf/FSComp.txt.tr.xlf +++ b/src/Compiler/xlf/FSComp.txt.tr.xlf @@ -147,6 +147,11 @@ Kullanılabilir aşırı yüklemeler:\n{0} + + '{0}' does not support the type '{1}', because the latter does not have a (real or built-in) member '{2}' + '{0}' does not support the type '{1}', because the latter does not have a (real or built-in) member '{2}' + + A generic construct requires that a generic type parameter be known as a struct or reference type. Consider adding a type annotation. Genel yapı, genel bir tür parametresinin yapı veya başvuru türü olarak bilinmesini gerektirir. Tür ek açıklaması eklemeyi düşünün. @@ -187,16 +192,6 @@ '{0}' bağımsız değişkeni eşleşmiyor - - The type '{0}' does not support the operator '{1}' as required by '{2}' - The type '{0}' does not support the operator '{1}' as required by '{2}' - - - - None of the types '{0}' support the operator '{1}' as required by '{2}' - None of the types '{0}' support the operator '{1}' as required by '{2}' - - The constraints 'unmanaged' and 'not struct' are inconsistent 'unmanaged' ve 'not struct' kısıtlamaları tutarsız diff --git a/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf b/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf index 3b8ce2cf811..f2689e02edc 100644 --- a/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf +++ b/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf @@ -147,6 +147,11 @@ 可用重载:\n{0} + + '{0}' does not support the type '{1}', because the latter does not have a (real or built-in) member '{2}' + '{0}' does not support the type '{1}', because the latter does not have a (real or built-in) member '{2}' + + A generic construct requires that a generic type parameter be known as a struct or reference type. Consider adding a type annotation. 泛型构造要求泛型类型参数被视为结构或引用类型。请考虑添加类型注释。 @@ -187,16 +192,6 @@ 参数 "{0}" 不匹配 - - The type '{0}' does not support the operator '{1}' as required by '{2}' - The type '{0}' does not support the operator '{1}' as required by '{2}' - - - - None of the types '{0}' support the operator '{1}' as required by '{2}' - None of the types '{0}' support the operator '{1}' as required by '{2}' - - The constraints 'unmanaged' and 'not struct' are inconsistent 约束 "unmanaged" 和 "not struct" 不一致 diff --git a/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf b/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf index 399662fe88b..0dd5ed3ff6b 100644 --- a/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf +++ b/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf @@ -147,6 +147,11 @@ 可用的多載:\n{0} + + '{0}' does not support the type '{1}', because the latter does not have a (real or built-in) member '{2}' + '{0}' does not support the type '{1}', because the latter does not have a (real or built-in) member '{2}' + + A generic construct requires that a generic type parameter be known as a struct or reference type. Consider adding a type annotation. 泛型建構要求泛型型別參數必須指定為結構或參考型別。請考慮新增型別註解。 @@ -187,16 +192,6 @@ 引數 '{0}' 不相符 - - The type '{0}' does not support the operator '{1}' as required by '{2}' - The type '{0}' does not support the operator '{1}' as required by '{2}' - - - - None of the types '{0}' support the operator '{1}' as required by '{2}' - None of the types '{0}' support the operator '{1}' as required by '{2}' - - The constraints 'unmanaged' and 'not struct' are inconsistent 條件約束 'unmanaged' 與 'not struct' 不一致 diff --git a/tests/FSharp.Compiler.ComponentTests/ConstraintSolver/MemberConstraints.fs b/tests/FSharp.Compiler.ComponentTests/ConstraintSolver/MemberConstraints.fs index ee03683f742..c155d2201e7 100644 --- a/tests/FSharp.Compiler.ComponentTests/ConstraintSolver/MemberConstraints.fs +++ b/tests/FSharp.Compiler.ComponentTests/ConstraintSolver/MemberConstraints.fs @@ -76,11 +76,31 @@ type DataItem< ^input> with |> shouldSucceed [] - let ``Explain why type needs to support operator`` () = + let ``Indirect constraint by operator`` () = FSharp """ List.average [42] |> ignore """ |> typecheck |> shouldFail |> withSingleDiagnostic - (Error 1, Line 2, Col 15, Line 2, Col 17, "The type 'int' does not support the operator 'DivideByInt' as required by 'average'") + (Error 1, Line 2, Col 15, Line 2, Col 17, "'List.average' does not support the type 'int', because the latter does not have a (real or built-in) member 'DivideByInt'") + + [] + let ``Direct constraint by named (pseudo) operator`` () = + FSharp """ +abs -1u |> ignore +""" + |> typecheck + |> shouldFail + |> withSingleDiagnostic + (Error 1, Line 2, Col 6, Line 2, Col 8, "The type 'uint32' does not support the operator 'abs'") + + [] + let ``Direct constraint by simple operator`` () = + FSharp """ +"" >>> 1 |> ignore +""" + |> typecheck + |> shouldFail + |> withSingleDiagnostic + (Error 1, Line 2, Col 1, Line 2, Col 3, "The type 'string' does not support the operator '>>>'") diff --git a/tests/fsharp/Compiler/Libraries/Core/Operators/AbsTests.fs b/tests/fsharp/Compiler/Libraries/Core/Operators/AbsTests.fs index ca2f753de4e..a6e07ba38e4 100644 --- a/tests/fsharp/Compiler/Libraries/Core/Operators/AbsTests.fs +++ b/tests/fsharp/Compiler/Libraries/Core/Operators/AbsTests.fs @@ -29,7 +29,7 @@ abs -1uy |> ignore FSharpDiagnosticSeverity.Error 1 (2, 6, 2, 9) - "The type 'byte' does not support the operator 'Abs'" + "The type 'byte' does not support the operator 'abs'" [] let ``Abs of uint16``() = @@ -40,7 +40,7 @@ abs -1us |> ignore FSharpDiagnosticSeverity.Error 1 (2, 6, 2, 9) - "The type 'uint16' does not support the operator 'Abs'" + "The type 'uint16' does not support the operator 'abs'" [] let ``Abs of uint32``() = @@ -51,7 +51,7 @@ abs -1ul |> ignore FSharpDiagnosticSeverity.Error 1 (2, 6, 2, 9) - "The type 'uint32' does not support the operator 'Abs'" + "The type 'uint32' does not support the operator 'abs'" CompilerAssert.TypeCheckSingleError """ @@ -60,7 +60,7 @@ abs -1u |> ignore FSharpDiagnosticSeverity.Error 1 (2, 6, 2, 8) - "The type 'uint32' does not support the operator 'Abs'" + "The type 'uint32' does not support the operator 'abs'" [] let ``Abs of unativeint``() = @@ -71,7 +71,7 @@ abs -1un |> ignore FSharpDiagnosticSeverity.Error 1 (2, 6, 2, 9) - "The type 'unativeint' does not support the operator 'Abs'" + "The type 'unativeint' does not support the operator 'abs'" [] let ``Abs of uint64``() = @@ -82,7 +82,7 @@ abs -1uL |> ignore FSharpDiagnosticSeverity.Error 1 (2, 6, 2, 9) - "The type 'uint64' does not support the operator 'Abs'" + "The type 'uint64' does not support the operator 'abs'" CompilerAssert.TypeCheckSingleError """ @@ -91,4 +91,4 @@ abs -1UL |> ignore FSharpDiagnosticSeverity.Error 1 (2, 6, 2, 9) - "The type 'uint64' does not support the operator 'Abs'" \ No newline at end of file + "The type 'uint64' does not support the operator 'abs'" \ No newline at end of file diff --git a/tests/fsharp/typecheck/sigs/neg61.bsl b/tests/fsharp/typecheck/sigs/neg61.bsl index b1ba15a77ad..e0b2fb5eafb 100644 --- a/tests/fsharp/typecheck/sigs/neg61.bsl +++ b/tests/fsharp/typecheck/sigs/neg61.bsl @@ -71,7 +71,7 @@ neg61.fs(111,13,111,24): typecheck error FS3144: 'return' and 'return!' may not neg61.fs(114,13,114,21): typecheck error FS3145: This is not a known query operator. Query operators are identifiers such as 'select', 'where', 'sortBy', 'thenBy', 'groupBy', 'groupValBy', 'join', 'groupJoin', 'sumBy' and 'averageBy', defined using corresponding methods on the 'QueryBuilder' type. -neg61.fs(114,22,114,23): typecheck error FS0001: The type 'int' does not support the operator 'Truncate' +neg61.fs(114,22,114,23): typecheck error FS0001: The type 'int' does not support the operator 'truncate' neg61.fs(133,17,133,20): typecheck error FS3147: This 'let' definition may not be used in a query. Only simple value definitions may be used in queries. From fcb0146cfd6a7cf3c079a40ac7a75b803ef4c932 Mon Sep 17 00:00:00 2001 From: Martin521 <29605222+Martin521@users.noreply.github.com> Date: Mon, 11 Dec 2023 13:42:22 +0000 Subject: [PATCH 10/16] formatting fixed; improved error message --- src/Compiler/FSComp.txt | 2 +- src/Compiler/TypedTree/TypedTree.fsi | 2 +- src/Compiler/xlf/FSComp.txt.cs.xlf | 4 ++-- src/Compiler/xlf/FSComp.txt.de.xlf | 4 ++-- src/Compiler/xlf/FSComp.txt.es.xlf | 4 ++-- src/Compiler/xlf/FSComp.txt.fr.xlf | 4 ++-- src/Compiler/xlf/FSComp.txt.it.xlf | 4 ++-- src/Compiler/xlf/FSComp.txt.ja.xlf | 4 ++-- src/Compiler/xlf/FSComp.txt.ko.xlf | 4 ++-- src/Compiler/xlf/FSComp.txt.pl.xlf | 4 ++-- src/Compiler/xlf/FSComp.txt.pt-BR.xlf | 4 ++-- src/Compiler/xlf/FSComp.txt.ru.xlf | 4 ++-- src/Compiler/xlf/FSComp.txt.tr.xlf | 4 ++-- src/Compiler/xlf/FSComp.txt.zh-Hans.xlf | 4 ++-- src/Compiler/xlf/FSComp.txt.zh-Hant.xlf | 4 ++-- .../ConstraintSolver/MemberConstraints.fs | 2 +- 16 files changed, 29 insertions(+), 29 deletions(-) diff --git a/src/Compiler/FSComp.txt b/src/Compiler/FSComp.txt index 81669ae6c60..71f06feb492 100644 --- a/src/Compiler/FSComp.txt +++ b/src/Compiler/FSComp.txt @@ -315,7 +315,7 @@ csExpectTypeWithOperatorButGivenFunction,"Expecting a type supporting the operat csExpectTypeWithOperatorButGivenTuple,"Expecting a type supporting the operator '%s' but given a tuple type" csTypesDoNotSupportOperator,"None of the types '%s' support the operator '%s'" csTypeDoesNotSupportOperator,"The type '%s' does not support the operator '%s'" -csFunctionDoesNotSupportType,"'%s' does not support the type '%s', because the latter does not have a (real or built-in) member '%s'" +csFunctionDoesNotSupportType,"'%s' does not support the type '%s', because the latter lacks the required (real or built-in) member '%s'" csTypesDoNotSupportOperatorNullable,"None of the types '%s' support the operator '%s'. Consider opening the module 'Microsoft.FSharp.Linq.NullableOperators'." csTypeDoesNotSupportOperatorNullable,"The type '%s' does not support the operator '%s'. Consider opening the module 'Microsoft.FSharp.Linq.NullableOperators'." csTypeDoesNotSupportConversion,"The type '%s' does not support a conversion to the type '%s'" diff --git a/src/Compiler/TypedTree/TypedTree.fsi b/src/Compiler/TypedTree/TypedTree.fsi index 5e46bad2918..3eb47b5eb47 100644 --- a/src/Compiler/TypedTree/TypedTree.fsi +++ b/src/Compiler/TypedTree/TypedTree.fsi @@ -1335,7 +1335,7 @@ type ExceptionInfo = /// Represents the contents of of a module of namespace [] -type ModuleOrNamespaceType = +type ModuleOrNamespaceType = new: kind: ModuleOrNamespaceKind * vals: QueueList * entities: QueueList -> ModuleOrNamespaceType diff --git a/src/Compiler/xlf/FSComp.txt.cs.xlf b/src/Compiler/xlf/FSComp.txt.cs.xlf index c260b54e724..efc6a457053 100644 --- a/src/Compiler/xlf/FSComp.txt.cs.xlf +++ b/src/Compiler/xlf/FSComp.txt.cs.xlf @@ -148,8 +148,8 @@ - '{0}' does not support the type '{1}', because the latter does not have a (real or built-in) member '{2}' - '{0}' does not support the type '{1}', because the latter does not have a (real or built-in) member '{2}' + '{0}' does not support the type '{1}', because the latter lacks the required (real or built-in) member '{2}' + '{0}' does not support the type '{1}', because the latter lacks the required (real or built-in) member '{2}' diff --git a/src/Compiler/xlf/FSComp.txt.de.xlf b/src/Compiler/xlf/FSComp.txt.de.xlf index 8ca0c102dfb..55d014103f7 100644 --- a/src/Compiler/xlf/FSComp.txt.de.xlf +++ b/src/Compiler/xlf/FSComp.txt.de.xlf @@ -148,8 +148,8 @@ - '{0}' does not support the type '{1}', because the latter does not have a (real or built-in) member '{2}' - '{0}' does not support the type '{1}', because the latter does not have a (real or built-in) member '{2}' + '{0}' does not support the type '{1}', because the latter lacks the required (real or built-in) member '{2}' + '{0}' does not support the type '{1}', because the latter lacks the required (real or built-in) member '{2}' diff --git a/src/Compiler/xlf/FSComp.txt.es.xlf b/src/Compiler/xlf/FSComp.txt.es.xlf index ea56c008fdb..fc34a22a2b5 100644 --- a/src/Compiler/xlf/FSComp.txt.es.xlf +++ b/src/Compiler/xlf/FSComp.txt.es.xlf @@ -148,8 +148,8 @@ - '{0}' does not support the type '{1}', because the latter does not have a (real or built-in) member '{2}' - '{0}' does not support the type '{1}', because the latter does not have a (real or built-in) member '{2}' + '{0}' does not support the type '{1}', because the latter lacks the required (real or built-in) member '{2}' + '{0}' does not support the type '{1}', because the latter lacks the required (real or built-in) member '{2}' diff --git a/src/Compiler/xlf/FSComp.txt.fr.xlf b/src/Compiler/xlf/FSComp.txt.fr.xlf index 3b19d0d1c6a..bee8c14e370 100644 --- a/src/Compiler/xlf/FSComp.txt.fr.xlf +++ b/src/Compiler/xlf/FSComp.txt.fr.xlf @@ -148,8 +148,8 @@ - '{0}' does not support the type '{1}', because the latter does not have a (real or built-in) member '{2}' - '{0}' does not support the type '{1}', because the latter does not have a (real or built-in) member '{2}' + '{0}' does not support the type '{1}', because the latter lacks the required (real or built-in) member '{2}' + '{0}' does not support the type '{1}', because the latter lacks the required (real or built-in) member '{2}' diff --git a/src/Compiler/xlf/FSComp.txt.it.xlf b/src/Compiler/xlf/FSComp.txt.it.xlf index d0f542b7d1d..1f76b69676f 100644 --- a/src/Compiler/xlf/FSComp.txt.it.xlf +++ b/src/Compiler/xlf/FSComp.txt.it.xlf @@ -148,8 +148,8 @@ - '{0}' does not support the type '{1}', because the latter does not have a (real or built-in) member '{2}' - '{0}' does not support the type '{1}', because the latter does not have a (real or built-in) member '{2}' + '{0}' does not support the type '{1}', because the latter lacks the required (real or built-in) member '{2}' + '{0}' does not support the type '{1}', because the latter lacks the required (real or built-in) member '{2}' diff --git a/src/Compiler/xlf/FSComp.txt.ja.xlf b/src/Compiler/xlf/FSComp.txt.ja.xlf index 404747cbece..2e2ca146411 100644 --- a/src/Compiler/xlf/FSComp.txt.ja.xlf +++ b/src/Compiler/xlf/FSComp.txt.ja.xlf @@ -148,8 +148,8 @@ - '{0}' does not support the type '{1}', because the latter does not have a (real or built-in) member '{2}' - '{0}' does not support the type '{1}', because the latter does not have a (real or built-in) member '{2}' + '{0}' does not support the type '{1}', because the latter lacks the required (real or built-in) member '{2}' + '{0}' does not support the type '{1}', because the latter lacks the required (real or built-in) member '{2}' diff --git a/src/Compiler/xlf/FSComp.txt.ko.xlf b/src/Compiler/xlf/FSComp.txt.ko.xlf index 678c87fb98b..487e8c04daf 100644 --- a/src/Compiler/xlf/FSComp.txt.ko.xlf +++ b/src/Compiler/xlf/FSComp.txt.ko.xlf @@ -148,8 +148,8 @@ - '{0}' does not support the type '{1}', because the latter does not have a (real or built-in) member '{2}' - '{0}' does not support the type '{1}', because the latter does not have a (real or built-in) member '{2}' + '{0}' does not support the type '{1}', because the latter lacks the required (real or built-in) member '{2}' + '{0}' does not support the type '{1}', because the latter lacks the required (real or built-in) member '{2}' diff --git a/src/Compiler/xlf/FSComp.txt.pl.xlf b/src/Compiler/xlf/FSComp.txt.pl.xlf index 6cc2afe871e..feaed3fbc04 100644 --- a/src/Compiler/xlf/FSComp.txt.pl.xlf +++ b/src/Compiler/xlf/FSComp.txt.pl.xlf @@ -148,8 +148,8 @@ - '{0}' does not support the type '{1}', because the latter does not have a (real or built-in) member '{2}' - '{0}' does not support the type '{1}', because the latter does not have a (real or built-in) member '{2}' + '{0}' does not support the type '{1}', because the latter lacks the required (real or built-in) member '{2}' + '{0}' does not support the type '{1}', because the latter lacks the required (real or built-in) member '{2}' diff --git a/src/Compiler/xlf/FSComp.txt.pt-BR.xlf b/src/Compiler/xlf/FSComp.txt.pt-BR.xlf index 40a52cc8d70..acd7f65c7fe 100644 --- a/src/Compiler/xlf/FSComp.txt.pt-BR.xlf +++ b/src/Compiler/xlf/FSComp.txt.pt-BR.xlf @@ -148,8 +148,8 @@ - '{0}' does not support the type '{1}', because the latter does not have a (real or built-in) member '{2}' - '{0}' does not support the type '{1}', because the latter does not have a (real or built-in) member '{2}' + '{0}' does not support the type '{1}', because the latter lacks the required (real or built-in) member '{2}' + '{0}' does not support the type '{1}', because the latter lacks the required (real or built-in) member '{2}' diff --git a/src/Compiler/xlf/FSComp.txt.ru.xlf b/src/Compiler/xlf/FSComp.txt.ru.xlf index d7726ea254a..cbab74e4310 100644 --- a/src/Compiler/xlf/FSComp.txt.ru.xlf +++ b/src/Compiler/xlf/FSComp.txt.ru.xlf @@ -148,8 +148,8 @@ - '{0}' does not support the type '{1}', because the latter does not have a (real or built-in) member '{2}' - '{0}' does not support the type '{1}', because the latter does not have a (real or built-in) member '{2}' + '{0}' does not support the type '{1}', because the latter lacks the required (real or built-in) member '{2}' + '{0}' does not support the type '{1}', because the latter lacks the required (real or built-in) member '{2}' diff --git a/src/Compiler/xlf/FSComp.txt.tr.xlf b/src/Compiler/xlf/FSComp.txt.tr.xlf index ed7f5f72d09..8874edf568e 100644 --- a/src/Compiler/xlf/FSComp.txt.tr.xlf +++ b/src/Compiler/xlf/FSComp.txt.tr.xlf @@ -148,8 +148,8 @@ - '{0}' does not support the type '{1}', because the latter does not have a (real or built-in) member '{2}' - '{0}' does not support the type '{1}', because the latter does not have a (real or built-in) member '{2}' + '{0}' does not support the type '{1}', because the latter lacks the required (real or built-in) member '{2}' + '{0}' does not support the type '{1}', because the latter lacks the required (real or built-in) member '{2}' diff --git a/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf b/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf index f2689e02edc..661c2d4b67b 100644 --- a/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf +++ b/src/Compiler/xlf/FSComp.txt.zh-Hans.xlf @@ -148,8 +148,8 @@ - '{0}' does not support the type '{1}', because the latter does not have a (real or built-in) member '{2}' - '{0}' does not support the type '{1}', because the latter does not have a (real or built-in) member '{2}' + '{0}' does not support the type '{1}', because the latter lacks the required (real or built-in) member '{2}' + '{0}' does not support the type '{1}', because the latter lacks the required (real or built-in) member '{2}' diff --git a/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf b/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf index 0dd5ed3ff6b..c60b10e6d57 100644 --- a/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf +++ b/src/Compiler/xlf/FSComp.txt.zh-Hant.xlf @@ -148,8 +148,8 @@ - '{0}' does not support the type '{1}', because the latter does not have a (real or built-in) member '{2}' - '{0}' does not support the type '{1}', because the latter does not have a (real or built-in) member '{2}' + '{0}' does not support the type '{1}', because the latter lacks the required (real or built-in) member '{2}' + '{0}' does not support the type '{1}', because the latter lacks the required (real or built-in) member '{2}' diff --git a/tests/FSharp.Compiler.ComponentTests/ConstraintSolver/MemberConstraints.fs b/tests/FSharp.Compiler.ComponentTests/ConstraintSolver/MemberConstraints.fs index c155d2201e7..2fd3db0b93a 100644 --- a/tests/FSharp.Compiler.ComponentTests/ConstraintSolver/MemberConstraints.fs +++ b/tests/FSharp.Compiler.ComponentTests/ConstraintSolver/MemberConstraints.fs @@ -83,7 +83,7 @@ List.average [42] |> ignore |> typecheck |> shouldFail |> withSingleDiagnostic - (Error 1, Line 2, Col 15, Line 2, Col 17, "'List.average' does not support the type 'int', because the latter does not have a (real or built-in) member 'DivideByInt'") + (Error 1, Line 2, Col 15, Line 2, Col 17, "'List.average' does not support the type 'int', because the latter lacks the required (real or built-in) member 'DivideByInt'") [] let ``Direct constraint by named (pseudo) operator`` () = From 51b3f238de2514bcd04589cb683109207daf58b5 Mon Sep 17 00:00:00 2001 From: Martin521 <29605222+Martin521@users.noreply.github.com> Date: Mon, 11 Dec 2023 14:26:19 +0000 Subject: [PATCH 11/16] fixed regression on enum test case --- .../EnumTypes/E_NoMethodsOnEnums01.fs | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/EnumTypes/E_NoMethodsOnEnums01.fs b/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/EnumTypes/E_NoMethodsOnEnums01.fs index f480258d91f..b4e05661698 100644 --- a/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/EnumTypes/E_NoMethodsOnEnums01.fs +++ b/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/EnumTypes/E_NoMethodsOnEnums01.fs @@ -1,5 +1,6 @@ // #Regression #Conformance #ObjectOrientedTypes #Enums //Enumerations cannot have members$ +//The type 'Season' does not support the operator 'get_One'$ type Season = Spring=0 | Summer=1 | Autumn=2 | Winter=3 with From 91b5c7ee18bf64ccc36c227f8cd8799cec1844af Mon Sep 17 00:00:00 2001 From: Martin521 <29605222+Martin521@users.noreply.github.com> Date: Mon, 11 Dec 2023 14:29:05 +0000 Subject: [PATCH 12/16] fixed expected error message in SignTests.fs --- .../fsharp/Compiler/Libraries/Core/Operators/SignTests.fs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/fsharp/Compiler/Libraries/Core/Operators/SignTests.fs b/tests/fsharp/Compiler/Libraries/Core/Operators/SignTests.fs index 2c67b1d1b8d..ca3edf8b377 100644 --- a/tests/fsharp/Compiler/Libraries/Core/Operators/SignTests.fs +++ b/tests/fsharp/Compiler/Libraries/Core/Operators/SignTests.fs @@ -45,7 +45,7 @@ sign 0uy |> ignore FSharpDiagnosticSeverity.Error 1 (2, 6, 2, 9) - "The type 'byte' does not support the operator 'get_Sign'" + "The type 'byte' does not support the operator 'sign'" [] let ``Sign of uint16``() = @@ -56,7 +56,7 @@ sign 0us |> ignore FSharpDiagnosticSeverity.Error 1 (2, 6, 2, 9) - "The type 'uint16' does not support the operator 'get_Sign'" + "The type 'uint16' does not support the operator 'sign'" [] let ``Sign of uint32``() = @@ -67,7 +67,7 @@ sign 0u |> ignore FSharpDiagnosticSeverity.Error 1 (2, 6, 2, 8) - "The type 'uint32' does not support the operator 'get_Sign'" + "The type 'uint32' does not support the operator 'sign'" [] let ``Sign of uint64``() = @@ -78,4 +78,4 @@ sign 0uL |> ignore FSharpDiagnosticSeverity.Error 1 (2, 6, 2, 9) - "The type 'uint64' does not support the operator 'get_Sign'" \ No newline at end of file + "The type 'uint64' does not support the operator 'sign'" \ No newline at end of file From 3bd121fa3a72d58102315deb0977eb72594c46d2 Mon Sep 17 00:00:00 2001 From: Martin521 <29605222+Martin521@users.noreply.github.com> Date: Mon, 11 Dec 2023 15:46:16 +0000 Subject: [PATCH 13/16] fixed changed expected message in E_NoMethodsOnEnums01 --- .../EnumTypes/E_NoMethodsOnEnums01.fs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/EnumTypes/E_NoMethodsOnEnums01.fs b/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/EnumTypes/E_NoMethodsOnEnums01.fs index b4e05661698..8b86f5e07c7 100644 --- a/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/EnumTypes/E_NoMethodsOnEnums01.fs +++ b/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/EnumTypes/E_NoMethodsOnEnums01.fs @@ -1,6 +1,6 @@ // #Regression #Conformance #ObjectOrientedTypes #Enums //Enumerations cannot have members$ -//The type 'Season' does not support the operator 'get_One'$ +//The type 'Season' does not support the operator 'get_Range'$ type Season = Spring=0 | Summer=1 | Autumn=2 | Winter=3 with From 0532bb026ea7b7cf4e56aca8066b09b12908964d Mon Sep 17 00:00:00 2001 From: Martin521 <29605222+Martin521@users.noreply.github.com> Date: Mon, 11 Dec 2023 16:39:22 +0000 Subject: [PATCH 14/16] Removed the last line of E_NoMethodsOnEnums01 since the second error it is introducing is not related to methods on enums and is difficult to verify. --- .../EnumTypes/E_NoMethodsOnEnums01.fs | 3 --- 1 file changed, 3 deletions(-) diff --git a/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/EnumTypes/E_NoMethodsOnEnums01.fs b/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/EnumTypes/E_NoMethodsOnEnums01.fs index 8b86f5e07c7..f1fb3a63888 100644 --- a/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/EnumTypes/E_NoMethodsOnEnums01.fs +++ b/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/EnumTypes/E_NoMethodsOnEnums01.fs @@ -1,6 +1,5 @@ // #Regression #Conformance #ObjectOrientedTypes #Enums //Enumerations cannot have members$ -//The type 'Season' does not support the operator 'get_Range'$ type Season = Spring=0 | Summer=1 | Autumn=2 | Winter=3 with @@ -8,5 +7,3 @@ type Season = Spring=0 | Summer=1 | Autumn=2 | Winter=3 let starti = Enum.to_int start let stopi = Enum.to_int stop { for i in starti .. stopi -> Enum.of_int i } - -printfn "%A" [Season.Spring .. Season.Autumn] From b55ec1046f4b6c85af620ec2b2cbbe2fdb0126e3 Mon Sep 17 00:00:00 2001 From: Martin521 <29605222+Martin521@users.noreply.github.com> Date: Mon, 11 Dec 2023 19:05:32 +0000 Subject: [PATCH 15/16] another detail needed to change in an expected result in a test --- .../EnumTypes/E_NoMethodsOnEnums01.fs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/EnumTypes/E_NoMethodsOnEnums01.fs b/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/EnumTypes/E_NoMethodsOnEnums01.fs index f1fb3a63888..dca7226146d 100644 --- a/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/EnumTypes/E_NoMethodsOnEnums01.fs +++ b/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/EnumTypes/E_NoMethodsOnEnums01.fs @@ -1,5 +1,5 @@ // #Regression #Conformance #ObjectOrientedTypes #Enums -//Enumerations cannot have members$ +//Enumerations cannot have members$ type Season = Spring=0 | Summer=1 | Autumn=2 | Winter=3 with From ae427e3eb721466523ea3b02acc63b10247a1a7e Mon Sep 17 00:00:00 2001 From: Martin521 <29605222+Martin521@users.noreply.github.com> Date: Mon, 11 Dec 2023 19:54:23 +0000 Subject: [PATCH 16/16] adding another test --- .../ConstraintSolver/MemberConstraints.fs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tests/FSharp.Compiler.ComponentTests/ConstraintSolver/MemberConstraints.fs b/tests/FSharp.Compiler.ComponentTests/ConstraintSolver/MemberConstraints.fs index 2fd3db0b93a..b3c33031acb 100644 --- a/tests/FSharp.Compiler.ComponentTests/ConstraintSolver/MemberConstraints.fs +++ b/tests/FSharp.Compiler.ComponentTests/ConstraintSolver/MemberConstraints.fs @@ -104,3 +104,13 @@ abs -1u |> ignore |> shouldFail |> withSingleDiagnostic (Error 1, Line 2, Col 1, Line 2, Col 3, "The type 'string' does not support the operator '>>>'") + + [] + let ``Direct constraint by pseudo operator`` () = + FSharp """ +ignore ["1" .. "42"] +""" + |> typecheck + |> shouldFail + |> withSingleDiagnostic + (Error 1, Line 2, Col 9, Line 2, Col 12, "The type 'string' does not support the operator 'op_Range'")