From 130751d662fadcdd43d6d2e71dfad161af3d3e20 Mon Sep 17 00:00:00 2001 From: Steffen Forkmann Date: Fri, 29 Jan 2016 10:12:21 +0100 Subject: [PATCH 1/2] Implementing basic nameof and typenameof operators --- src/fsharp/FSComp.txt | 2 + .../FSharp.Core.Unittests.fsproj | 1 + .../Microsoft.FSharp.Core/NameOfTests.fs | 248 ++++++++++++++++++ .../SurfaceArea.Silverlight.2.0.fs | 2 + .../SurfaceArea.net20.fs | 2 + .../SurfaceArea.net40.fs | 2 + .../SurfaceArea.portable259.fs | 2 + .../SurfaceArea.portable47.fs | 2 + .../SurfaceArea.portable7.fs | 2 + .../SurfaceArea.portable78.fs | 2 + src/fsharp/FSharp.Core/prim-types.fs | 6 + src/fsharp/FSharp.Core/prim-types.fsi | 9 + src/fsharp/Optimizer.fs | 33 ++- src/fsharp/PostInferenceChecks.fs | 35 ++- src/fsharp/PostInferenceChecks.fsi | 1 + src/fsharp/TastOps.fs | 12 + src/fsharp/TastOps.fsi | 1 + src/fsharp/TcGlobals.fs | 10 + .../NameOf/E_NameOfAdditionExpr.fs | 7 + .../NameOf/E_NameOfAppliedFunction.fs | 8 + .../NameOf/E_NameOfAsAFunction.fs | 7 + .../NameOf/E_NameOfDictLookup.fs | 8 + .../NameOf/E_NameOfIntConst.fs | 7 + .../NameOf/E_NameOfIntegerAppliedFunction.fs | 8 + .../E_NameOfParameterAppliedFunction.fs | 9 + .../E_NameOfPartiallyAppliedFunction.fs | 8 + .../NameOf/E_NameOfStringConst.fs | 7 + .../NameOf/E_NameOfWithPipe.fs | 7 + .../DataExpressions/NameOf/env.lst | 10 + tests/fsharpqa/Source/test.lst | 1 + 30 files changed, 456 insertions(+), 3 deletions(-) create mode 100644 src/fsharp/FSharp.Core.Unittests/FSharp.Core/Microsoft.FSharp.Core/NameOfTests.fs create mode 100644 tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/NameOf/E_NameOfAdditionExpr.fs create mode 100644 tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/NameOf/E_NameOfAppliedFunction.fs create mode 100644 tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/NameOf/E_NameOfAsAFunction.fs create mode 100644 tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/NameOf/E_NameOfDictLookup.fs create mode 100644 tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/NameOf/E_NameOfIntConst.fs create mode 100644 tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/NameOf/E_NameOfIntegerAppliedFunction.fs create mode 100644 tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/NameOf/E_NameOfParameterAppliedFunction.fs create mode 100644 tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/NameOf/E_NameOfPartiallyAppliedFunction.fs create mode 100644 tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/NameOf/E_NameOfStringConst.fs create mode 100644 tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/NameOf/E_NameOfWithPipe.fs create mode 100644 tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/NameOf/env.lst diff --git a/src/fsharp/FSComp.txt b/src/fsharp/FSComp.txt index 5bbff5d3ffa..5bebaef7422 100644 --- a/src/fsharp/FSComp.txt +++ b/src/fsharp/FSComp.txt @@ -1307,3 +1307,5 @@ estApplyStaticArgumentsForMethodNotImplemented,"A type provider implemented GetS 3201,tcModuleAbbrevFirstInMutRec,"In a recursive declaration group, module abbreviations must come after all 'open' declarations and before other declarations" 3202,tcUnsupportedMutRecDecl,"This declaration is not supported in recursive declaration groups" 3203,parsInvalidUseOfRec,"Invalid use of 'rec' keyword" +3204,expressionHasNoName,"This expression does not have a name." +3205,nameofNotPermitted,"The nameof operator is not allowed in this position." diff --git a/src/fsharp/FSharp.Core.Unittests/FSharp.Core.Unittests.fsproj b/src/fsharp/FSharp.Core.Unittests/FSharp.Core.Unittests.fsproj index 83ed633defa..e0e3765a40b 100644 --- a/src/fsharp/FSharp.Core.Unittests/FSharp.Core.Unittests.fsproj +++ b/src/fsharp/FSharp.Core.Unittests/FSharp.Core.Unittests.fsproj @@ -120,6 +120,7 @@ + diff --git a/src/fsharp/FSharp.Core.Unittests/FSharp.Core/Microsoft.FSharp.Core/NameOfTests.fs b/src/fsharp/FSharp.Core.Unittests/FSharp.Core/Microsoft.FSharp.Core/NameOfTests.fs new file mode 100644 index 00000000000..1c82fc8ef04 --- /dev/null +++ b/src/fsharp/FSharp.Core.Unittests/FSharp.Core/Microsoft.FSharp.Core/NameOfTests.fs @@ -0,0 +1,248 @@ +// Copyright (c) Microsoft Open Technologies, Inc. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +namespace FSharp.Core.Unittests +open System +open NUnit.Framework + +[] +type BasicNameOfTests() = + let localConstant = 23 + member this.MemberMethod() = 0 + member this.MemberProperty = this.MemberMethod() + static member StaticMethod() = 0 + static member StaticProperty = BasicNameOfTests.StaticMethod() + + [] + member this.``local variable name lookup`` () = + let a = 0 + let result = nameof a + Assert.AreEqual("a",result) + Assert.AreEqual("result",nameof result) + + [] + member this.``local int function name`` () = + let myFunction x = 0 * x + let b = nameof myFunction + Assert.AreEqual("myFunction",b) + + [] + member this.``local curried function name`` () = + let curriedFunction x y = x * y + let b = nameof curriedFunction + Assert.AreEqual("curriedFunction",b) + + [] + member this.``local tupled function name`` () = + let tupledFunction(x,y) = x * y + let b = nameof tupledFunction + Assert.AreEqual("tupledFunction",b) + + [] + member this.``local unit function name`` () = + let myFunction() = 1 + let b = nameof(myFunction) + Assert.AreEqual("myFunction",b) + + [] + member this.``local function parameter name`` () = + let myFunction parameter1 = nameof parameter1 + + Assert.AreEqual("parameter1",myFunction "x") + + [] + member this.``can get name from inside a local function (needs to be let rec)`` () = + let rec myLocalFunction x = + let z = 2 * x + nameof myLocalFunction + " " + z.ToString() + + Assert.AreEqual("myLocalFunction 46",myLocalFunction 23) + Assert.AreEqual("myLocalFunction 50",myLocalFunction 25) + + [] + member this.CanGetNameFromInsideAMember () = + let b = nameof(this.CanGetNameFromInsideAMember) + Assert.AreEqual("CanGetNameFromInsideAMember",b) + + [] + member this.``member function name`` () = + let b = nameof(this.MemberMethod) + Assert.AreEqual("MemberMethod",b) + + [] + member this.``member function which is defined below`` () = + let b = nameof(this.MemberMethodDefinedBelow) + Assert.AreEqual("MemberMethodDefinedBelow",b) + + member this.MemberMethodDefinedBelow(x,y) = x * y + + [] + member this.``static member function name`` () = + let b = nameof(BasicNameOfTests.StaticMethod) + Assert.AreEqual("StaticMethod",b) + + [] + member this.``class member lookup`` () = + let b = nameof(localConstant) + Assert.AreEqual("localConstant",b) + + [] + member this.``member property name`` () = + let b = nameof(this.MemberProperty) + Assert.AreEqual("MemberProperty",b) + + [] + member this.``static property name`` () = + let b = nameof(BasicNameOfTests.StaticProperty) + Assert.AreEqual("StaticProperty",b) + + member this.get_XYZ() = 1 + + [] + member this.``member method starting with get_`` () = + let b = nameof(this.get_XYZ) + Assert.AreEqual("get_XYZ",b) + + static member get_SXYZ() = 1 + + [] + member this.``static method starting with get_`` () = + let b = nameof(BasicNameOfTests.get_SXYZ) + Assert.AreEqual("get_SXYZ",b) + + [] + member this.``nameof local property with encapsulated name`` () = + let ``local property with encapsulated name and %.f`` = 0 + let b = nameof(``local property with encapsulated name and %.f``) + Assert.AreEqual("local property with encapsulated name and %.f",b) + +[] +type MethodGroupTests() = + member this.MethodGroup() = () + member this.MethodGroup(i:int) = () + + [] + member this.``method group name lookup`` () = + let b = nameof(this.MethodGroup) + Assert.AreEqual("MethodGroup",b) + +[] +type FrameworkMethodTests() = + [] + member this.``library function name`` () = + let b = nameof(List.map) + Assert.AreEqual("Map",b) + + [] + member this.``static class function name`` () = + let b = nameof(Tuple.Create) + Assert.AreEqual("Create",b) + +type CustomUnionType = +| OptionA of string +| OptionB of int * string + +[] +type NameOfOperatorForTypes() = + [] + member this.``use typenameof on Int32`` () = + let b = typenameof + Assert.AreEqual("System.Int32",b) + + [] + member this.``use typenameof on a custom type`` () = + let b = typenameof + Assert.AreEqual("FSharp.Core.Unittests.NameOfOperatorForTypes",b) + + [] + member this.``use typenameof on a custom union type`` () = + let b = typenameof + Assert.AreEqual("FSharp.Core.Unittests.CustomUnionType",b) +// +// [] +// member this.``use typenameof on a custom union case`` () = +// let b = typenameof +// Assert.AreEqual("FSharp.Core.Unittests.CustomUnionType.OptionB",b) + + [] + member this.``use typenameof on List`` () = + let b = typenameof> + Assert.AreEqual("System.Collections.Generic.List`1",b) + + [] + member this.``use typenameof on generic List`` () = + let b = typenameof> + Assert.AreEqual("System.Collections.Generic.List`1",b) + + + +[] +type OperatorNameTests() = + + [] + member this.``lookup name of typeof operator`` () = + let b = nameof(typeof) + Assert.AreEqual("TypeOf",b) + + [] + member this.``lookup name of + operator`` () = + let b = nameof(+) + Assert.AreEqual("op_Addition",b) + + [] + member this.``lookup name of |> operator`` () = + let a = nameof(|>) + Assert.AreEqual("op_PipeRight",a) + let b = nameof(op_PipeRight) + Assert.AreEqual("op_PipeRight",b) + + [] + member this.``lookup name of nameof operator`` () = + let b = nameof(nameof) + Assert.AreEqual("NameOf",b) + +[] +type PatternMatchingOfOperatorNameTests() = + member this.Method1(i:int) = () + + [] + member this.``use it as a match case guard`` () = + match "Method1" with + | x when x = nameof(this.Method1) -> () + | _ -> Assert.Fail("not expected") + +[] +type NameOfOperatorInQuotations() = + [] + member this.``use it in a quotation`` () = + let q = + <@ + let f(x:int) = nameof x + f 20 + @> + () + +[] +type NameOfOperatorForGenerics() = + [] + member this.``use it in a generic function`` () = + let fullyGeneric x = x + let b = nameof(fullyGeneric) + Assert.AreEqual("fullyGeneric",b) + +[] +type UserDefinedNameOfTests() = + [] + member this.``userdefined nameof should shadow the operator`` () = + let nameof x = "test" + x.ToString() + + let y = nameof 1 + Assert.AreEqual("test1",y) + +type Person = + { Name : string + Age : int } + member __.Update(fld : string, value : obj) = + match fld with + | x when x = nameof __.Name -> { __ with Name = string value } + | x when x = nameof __.Age -> { __ with Age = value :?> int } + | _ -> __ \ No newline at end of file diff --git a/src/fsharp/FSharp.Core.Unittests/SurfaceArea.Silverlight.2.0.fs b/src/fsharp/FSharp.Core.Unittests/SurfaceArea.Silverlight.2.0.fs index 3d933f40517..eb3eed957e9 100644 --- a/src/fsharp/FSharp.Core.Unittests/SurfaceArea.Silverlight.2.0.fs +++ b/src/fsharp/FSharp.Core.Unittests/SurfaceArea.Silverlight.2.0.fs @@ -2197,8 +2197,10 @@ Microsoft.FSharp.Core.Operators: System.IO.TextReader ConsoleIn[T]() Microsoft.FSharp.Core.Operators: System.IO.TextWriter ConsoleError[T]() Microsoft.FSharp.Core.Operators: System.IO.TextWriter ConsoleOut[T]() Microsoft.FSharp.Core.Operators: System.Object Box[T](T) +Microsoft.FSharp.Core.Operators: System.String NameOf[T](T) Microsoft.FSharp.Core.Operators: System.String ToString() Microsoft.FSharp.Core.Operators: System.String ToString[T](T) +Microsoft.FSharp.Core.Operators: System.String TypeNameOf[T]() Microsoft.FSharp.Core.Operators: System.String op_Concatenate(System.String, System.String) Microsoft.FSharp.Core.Operators: System.Tuple`2[TKey,TValue] KeyValuePattern[TKey,TValue](System.Collections.Generic.KeyValuePair`2[TKey,TValue]) Microsoft.FSharp.Core.Operators: System.Type GetType() diff --git a/src/fsharp/FSharp.Core.Unittests/SurfaceArea.net20.fs b/src/fsharp/FSharp.Core.Unittests/SurfaceArea.net20.fs index c8caf782564..e6c4c706130 100644 --- a/src/fsharp/FSharp.Core.Unittests/SurfaceArea.net20.fs +++ b/src/fsharp/FSharp.Core.Unittests/SurfaceArea.net20.fs @@ -2438,8 +2438,10 @@ Microsoft.FSharp.Core.Operators: System.Object Box[T](T)" + Microsoft.FSharp.Core.Operators: System.RuntimeMethodHandle MethodHandleOf[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult])" + #endif @" +Microsoft.FSharp.Core.Operators: System.String NameOf[T](T) Microsoft.FSharp.Core.Operators: System.String ToString() Microsoft.FSharp.Core.Operators: System.String ToString[T](T) +Microsoft.FSharp.Core.Operators: System.String TypeNameOf[T]() Microsoft.FSharp.Core.Operators: System.String op_Concatenate(System.String, System.String) Microsoft.FSharp.Core.Operators: System.Tuple`2[TKey,TValue] KeyValuePattern[TKey,TValue](System.Collections.Generic.KeyValuePair`2[TKey,TValue]) Microsoft.FSharp.Core.Operators: System.Type GetType() diff --git a/src/fsharp/FSharp.Core.Unittests/SurfaceArea.net40.fs b/src/fsharp/FSharp.Core.Unittests/SurfaceArea.net40.fs index 6879946205f..f22e36ce3ee 100644 --- a/src/fsharp/FSharp.Core.Unittests/SurfaceArea.net40.fs +++ b/src/fsharp/FSharp.Core.Unittests/SurfaceArea.net40.fs @@ -2602,8 +2602,10 @@ Microsoft.FSharp.Core.Operators: System.Object Box[T](T)" + Microsoft.FSharp.Core.Operators: System.RuntimeMethodHandle MethodHandleOf[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult])" + #endif @" +Microsoft.FSharp.Core.Operators: System.String NameOf[T](T) Microsoft.FSharp.Core.Operators: System.String ToString() Microsoft.FSharp.Core.Operators: System.String ToString[T](T) +Microsoft.FSharp.Core.Operators: System.String TypeNameOf[T]() Microsoft.FSharp.Core.Operators: System.String op_Concatenate(System.String, System.String) Microsoft.FSharp.Core.Operators: System.Tuple`2[TKey,TValue] KeyValuePattern[TKey,TValue](System.Collections.Generic.KeyValuePair`2[TKey,TValue]) Microsoft.FSharp.Core.Operators: System.Type GetType() diff --git a/src/fsharp/FSharp.Core.Unittests/SurfaceArea.portable259.fs b/src/fsharp/FSharp.Core.Unittests/SurfaceArea.portable259.fs index 2102f9d951d..0f554627561 100644 --- a/src/fsharp/FSharp.Core.Unittests/SurfaceArea.portable259.fs +++ b/src/fsharp/FSharp.Core.Unittests/SurfaceArea.portable259.fs @@ -2574,8 +2574,10 @@ Microsoft.FSharp.Core.Operators: System.Object Box[T](T)" + Microsoft.FSharp.Core.Operators: System.RuntimeMethodHandle MethodHandleOf[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult])" + #endif @" +Microsoft.FSharp.Core.Operators: System.String NameOf[T](T) Microsoft.FSharp.Core.Operators: System.String ToString() Microsoft.FSharp.Core.Operators: System.String ToString[T](T) +Microsoft.FSharp.Core.Operators: System.String TypeNameOf[T]() Microsoft.FSharp.Core.Operators: System.String op_Concatenate(System.String, System.String) Microsoft.FSharp.Core.Operators: System.Tuple`2[TKey,TValue] KeyValuePattern[TKey,TValue](System.Collections.Generic.KeyValuePair`2[TKey,TValue]) Microsoft.FSharp.Core.Operators: System.Type GetType() diff --git a/src/fsharp/FSharp.Core.Unittests/SurfaceArea.portable47.fs b/src/fsharp/FSharp.Core.Unittests/SurfaceArea.portable47.fs index 856107f69f2..b3d6e1d4db6 100644 --- a/src/fsharp/FSharp.Core.Unittests/SurfaceArea.portable47.fs +++ b/src/fsharp/FSharp.Core.Unittests/SurfaceArea.portable47.fs @@ -2576,8 +2576,10 @@ Microsoft.FSharp.Core.Operators: System.Object Box[T](T)" + Microsoft.FSharp.Core.Operators: System.RuntimeMethodHandle MethodHandleOf[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult])" + #endif @" +Microsoft.FSharp.Core.Operators: System.String NameOf[T](T) Microsoft.FSharp.Core.Operators: System.String ToString() Microsoft.FSharp.Core.Operators: System.String ToString[T](T) +Microsoft.FSharp.Core.Operators: System.String TypeNameOf[T]() Microsoft.FSharp.Core.Operators: System.String op_Concatenate(System.String, System.String) Microsoft.FSharp.Core.Operators: System.Tuple`2[TKey,TValue] KeyValuePattern[TKey,TValue](System.Collections.Generic.KeyValuePair`2[TKey,TValue]) Microsoft.FSharp.Core.Operators: System.Type GetType() diff --git a/src/fsharp/FSharp.Core.Unittests/SurfaceArea.portable7.fs b/src/fsharp/FSharp.Core.Unittests/SurfaceArea.portable7.fs index 745df1359bf..60fe06e203a 100644 --- a/src/fsharp/FSharp.Core.Unittests/SurfaceArea.portable7.fs +++ b/src/fsharp/FSharp.Core.Unittests/SurfaceArea.portable7.fs @@ -2587,8 +2587,10 @@ Microsoft.FSharp.Core.Operators: System.Object Box[T](T)" + Microsoft.FSharp.Core.Operators: System.RuntimeMethodHandle MethodHandleOf[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult])" + #endif @" +Microsoft.FSharp.Core.Operators: System.String NameOf[T](T) Microsoft.FSharp.Core.Operators: System.String ToString() Microsoft.FSharp.Core.Operators: System.String ToString[T](T) +Microsoft.FSharp.Core.Operators: System.String TypeNameOf[T]() Microsoft.FSharp.Core.Operators: System.String op_Concatenate(System.String, System.String) Microsoft.FSharp.Core.Operators: System.Tuple`2[TKey,TValue] KeyValuePattern[TKey,TValue](System.Collections.Generic.KeyValuePair`2[TKey,TValue]) Microsoft.FSharp.Core.Operators: System.Type GetType() diff --git a/src/fsharp/FSharp.Core.Unittests/SurfaceArea.portable78.fs b/src/fsharp/FSharp.Core.Unittests/SurfaceArea.portable78.fs index 72df723cf36..1c9fc1d346b 100644 --- a/src/fsharp/FSharp.Core.Unittests/SurfaceArea.portable78.fs +++ b/src/fsharp/FSharp.Core.Unittests/SurfaceArea.portable78.fs @@ -2574,8 +2574,10 @@ Microsoft.FSharp.Core.Operators: System.Object Box[T](T)" + Microsoft.FSharp.Core.Operators: System.RuntimeMethodHandle MethodHandleOf[T,TResult](Microsoft.FSharp.Core.FSharpFunc`2[T,TResult])" + #endif @" +Microsoft.FSharp.Core.Operators: System.String NameOf[T](T) Microsoft.FSharp.Core.Operators: System.String ToString() Microsoft.FSharp.Core.Operators: System.String ToString[T](T) +Microsoft.FSharp.Core.Operators: System.String TypeNameOf[T]() Microsoft.FSharp.Core.Operators: System.String op_Concatenate(System.String, System.String) Microsoft.FSharp.Core.Operators: System.Tuple`2[TKey,TValue] KeyValuePattern[TKey,TValue](System.Collections.Generic.KeyValuePair`2[TKey,TValue]) Microsoft.FSharp.Core.Operators: System.Type GetType() diff --git a/src/fsharp/FSharp.Core/prim-types.fs b/src/fsharp/FSharp.Core/prim-types.fs index 8ff1a91732b..72fb0444119 100644 --- a/src/fsharp/FSharp.Core/prim-types.fs +++ b/src/fsharp/FSharp.Core/prim-types.fs @@ -4753,6 +4753,12 @@ namespace Microsoft.FSharp.Core [] let inline typeof<'T> = BasicInlinedOperations.typeof<'T> + [] + let inline typenameof<'T> : string = raise (Exception "may not call directly, should always be optimized away") + + [] + let inline nameof (_: 'T) : string = raise (Exception "may not call directly, should always be optimized away") + [] let methodhandleof (_call: ('T -> 'TResult)) : System.RuntimeMethodHandle = raise (Exception "may not call directly, should always be optimized away") diff --git a/src/fsharp/FSharp.Core/prim-types.fsi b/src/fsharp/FSharp.Core/prim-types.fsi index d3202b3aeee..0653e9be9ac 100644 --- a/src/fsharp/FSharp.Core/prim-types.fsi +++ b/src/fsharp/FSharp.Core/prim-types.fsi @@ -2306,6 +2306,15 @@ namespace Microsoft.FSharp.Core [] val inline typeof<'T> : System.Type + /// Returns the name of the given static type. + [] + [] + val inline typenameof<'T> : string + + /// Returns the name of the given symbol. + [] + val inline nameof : 'T -> string + /// An internal, library-only compiler intrinsic for compile-time /// generation of a RuntimeMethodHandle. [] diff --git a/src/fsharp/Optimizer.fs b/src/fsharp/Optimizer.fs index 186113ed2a2..3830c15a843 100644 --- a/src/fsharp/Optimizer.fs +++ b/src/fsharp/Optimizer.fs @@ -1219,7 +1219,7 @@ let AbstractAndRemapModulInfo msg g m (repackage,hidden) info = info //------------------------------------------------------------------------- -// Misc helerps +// Misc helpers //------------------------------------------------------------------------- // Mark some variables (the ones we introduce via abstractBigTargets) as don't-eliminate @@ -2542,6 +2542,37 @@ and TryDevirtualizeApplication cenv env (f,tyargs,args,m) = MightMakeCriticalTailcall = false; Info=UnknownValue}) + // Analyze the name of the given symbol and rewrite AST to constant string expression with the name + | Expr.Val(vref,_,_),_,_ when valRefEq cenv.g vref cenv.g.nameof_vref -> + PostTypeCheckSemanticChecks.tryExtractNameOf args + |> Option.map (fun name -> + Expr.Const(Const.String name, m, cenv.g.string_ty), + { TotalSize = 1 + FunctionSize = 1 + HasEffect = false + MightMakeCriticalTailcall = false + Info = UnknownValue }) + // Analyze the name of the given type and rewrite AST to constant string expression with the name + | Expr.Val(vref,_,_),_,_ when valRefEq cenv.g vref cenv.g.typenameof_vref -> + match tyargs with + | (typeName:TType):: _ -> + let name = + match typeName with + | TType_forall (_tps,ty) -> ty.ToString() + | TType_app (tcref, _) -> tcref.CompiledRepresentationForNamedType.FullName + | TType_tuple tinst -> "(" + String.concat "," (List.map string tinst) + ")" + | TType_fun (d,r) -> "(" + string d + " -> " + string r + ")" + | TType_ucase (uc,_) -> uc.CaseName + | TType_var tp -> tp.DisplayName + | TType_measure ms -> sprintf "%A" ms + + Some(Expr.Const(Const.String name, m, cenv.g.string_ty), + { TotalSize = 1 + FunctionSize = 1 + HasEffect = false + MightMakeCriticalTailcall = false + Info = UnknownValue }) + | _ -> None | _ -> None /// Attempt to inline an application of a known value at callsites diff --git a/src/fsharp/PostInferenceChecks.fs b/src/fsharp/PostInferenceChecks.fs index d9ea90e1715..e5e829dda3b 100644 --- a/src/fsharp/PostInferenceChecks.fs +++ b/src/fsharp/PostInferenceChecks.fs @@ -459,6 +459,27 @@ let CheckMultipleInterfaceInstantiations cenv interfaces m = | Some (typ1,typ2) -> errorR(Error(FSComp.SR.chkMultipleGenericInterfaceInstantiations((NicePrint.minimalStringOfType cenv.denv typ1), (NicePrint.minimalStringOfType cenv.denv typ2)),m)) +// tries to extract the name of an expression +let tryExtractNameOf args = + match args with + | [Expr.Val(r,_,_)] -> Some(r.CompiledName) + | [Expr.App(Expr.Val(r,_,_),_,_,Expr.Const(constant,_,_)::_,_)] -> + if r.CompiledName.StartsWith("get_") && constant = Const.Unit then // TODO: We need a better way to find static property getters + Some(r.CompiledName.Substring(4)) + else + None // the function was applied + | [Expr.App(Expr.Val(r,_,_),_,_,[],_)] -> Some(r.CompiledName) + | [Expr.App(Expr.Val(r,_,_),_,_,_,_)] -> + if r.CompiledName.StartsWith("get_") then // TODO: We need a better way to find member property getters + Some(r.CompiledName.Substring(4)) + else + None // the function was applied + | [Expr.Let(_,Expr.Val(r,_,_),_,_)] -> Some(r.CompiledName) + | [Expr.Let(_,Expr.Lambda(_,_,_,_,Expr.App(Expr.Val(r,_,_),_,_,_,_),_,_),_,_)] -> Some(r.CompiledName) + | [Expr.Lambda(_,_,_,_,Expr.App(Expr.Val(r,_,_),_,_,_,_),_,_)] -> Some(r.CompiledName) + | [Expr.Op(TOp.ValFieldGet(r),_,_,_)] -> Some(r.FieldName) + | [Expr.Lambda(_,_,_,_,Expr.Op(TOp.ILCall(_,_,_,_,_,_,_,r,_,_,_),_,_,_),_,_)] -> Some(r.Name) + | _ -> None let rec CheckExpr (cenv:cenv) (env:env) expr = CheckExprInContext cenv env expr GeneralContext @@ -489,8 +510,18 @@ and CheckExprInContext (cenv:cenv) (env:env) expr (context:ByrefCallContext) = BindVal cenv bind.Var CheckExpr cenv env body | Expr.Const (_,m,ty) -> - CheckTypePermitByrefs cenv env m ty - + CheckTypePermitByrefs cenv env m ty + + | Expr.App(Expr.Val (v,_,_),_,_,args,m) -> + if cenv.reportErrors then + if valRefEq cenv.g v cenv.g.nameof_vref && tryExtractNameOf args = None then + errorR(Error(FSComp.SR.expressionHasNoName(), m)) + match args with + | [_;Expr.App(Expr.Val (v,_,_),_,_,args,m)] -> + if valRefEq cenv.g v cenv.g.nameof_vref && tryExtractNameOf args = None then + errorR(Error(FSComp.SR.nameofNotPermitted(), m)) + | _ -> () + | Expr.Val (v,vFlags,m) -> if cenv.reportErrors then if v.BaseOrThisInfo = BaseVal then diff --git a/src/fsharp/PostInferenceChecks.fsi b/src/fsharp/PostInferenceChecks.fsi index b647dd2cc0a..e25cfed7f96 100644 --- a/src/fsharp/PostInferenceChecks.fsi +++ b/src/fsharp/PostInferenceChecks.fsi @@ -10,3 +10,4 @@ open Microsoft.FSharp.Compiler.InfoReader val testFlagMemberBody : bool ref val CheckTopImpl : TcGlobals * Import.ImportMap * bool * InfoReader * Tast.CompilationPath list * Tast.CcuThunk * Tastops.DisplayEnv * Tast.ModuleOrNamespaceExprWithSig * Tast.Attribs * (bool * bool) -> bool +val tryExtractNameOf : Microsoft.FSharp.Compiler.Tast.Expr list -> string option diff --git a/src/fsharp/TastOps.fs b/src/fsharp/TastOps.fs index 57320d2205e..a4ee75800d2 100755 --- a/src/fsharp/TastOps.fs +++ b/src/fsharp/TastOps.fs @@ -2761,6 +2761,11 @@ let isTypeOfValRef g vref = // There is an internal version of typeof defined in prim-types.fs that needs to be detected || (g.compilingFslib && vref.LogicalName = "typeof") +let isTypeNameOfValRef g vref = + valRefEq g vref g.typenameof_vref + // There is an internal version of typenameof defined in prim-types.fs that needs to be detected + || (g.compilingFslib && vref.LogicalName = "typenameof") + let isSizeOfValRef g vref = valRefEq g vref g.sizeof_vref // There is an internal version of typeof defined in prim-types.fs that needs to be detected @@ -2781,6 +2786,11 @@ let (|TypeOfExpr|_|) g expr = | Expr.App(Expr.Val(vref,_,_),_,[ty],[],_) when isTypeOfValRef g vref -> Some ty | _ -> None +let (|TypeNameOfExpr|_|) g expr = + match expr with + | Expr.App(Expr.Val(vref,_,_),_,[ty],[],_) when isTypeNameOfValRef g vref -> Some ty + | _ -> None + let (|SizeOfExpr|_|) g expr = match expr with | Expr.App(Expr.Val(vref,_,_),_,[ty],[],_) when isSizeOfValRef g vref -> Some ty @@ -5911,6 +5921,7 @@ let mkCallUnbox g m ty e1 = mkApps g (typedExprForIntrinsic g let mkCallUnboxFast g m ty e1 = mkApps g (typedExprForIntrinsic g m g.unbox_fast_info, [[ty]], [ e1 ], m) let mkCallTypeTest g m ty e1 = mkApps g (typedExprForIntrinsic g m g.istype_info, [[ty]], [ e1 ], m) let mkCallTypeOf g m ty = mkApps g (typedExprForIntrinsic g m g.typeof_info, [[ty]], [ ], m) +let mkCallTypeNameOf g m ty = mkApps g (typedExprForIntrinsic g m g.typenameof_info, [[ty]], [ ], m) let mkCallTypeDefOf g m ty = mkApps g (typedExprForIntrinsic g m g.typedefof_info, [[ty]], [ ], m) @@ -7568,6 +7579,7 @@ let IsSimpleSyntacticConstantExpr g inputExpr = | Expr.Op (TOp.UnionCase _,_,[],_) // Nullary union cases | UncheckedDefaultOfExpr g _ | SizeOfExpr g _ + | TypeNameOfExpr g _ | TypeOfExpr g _ -> true // All others are not simple constant expressions | _ -> false diff --git a/src/fsharp/TastOps.fsi b/src/fsharp/TastOps.fsi index e4719f1b86f..43aaaffa650 100755 --- a/src/fsharp/TastOps.fsi +++ b/src/fsharp/TastOps.fsi @@ -1137,6 +1137,7 @@ val mkCallTypeTest : TcGlobals -> range -> TType -> Expr -> Expr val canUseTypeTestFast : TcGlobals -> TType -> bool val mkCallTypeOf : TcGlobals -> range -> TType -> Expr +val mkCallTypeNameOf : TcGlobals -> range -> TType -> Expr val mkCallTypeDefOf : TcGlobals -> range -> TType -> Expr val mkCallCreateInstance : TcGlobals -> range -> TType -> Expr diff --git a/src/fsharp/TcGlobals.fs b/src/fsharp/TcGlobals.fs index a02124d5e42..821f7ddf5da 100755 --- a/src/fsharp/TcGlobals.fs +++ b/src/fsharp/TcGlobals.fs @@ -403,6 +403,10 @@ type public TcGlobals = reraise_vref : ValRef typeof_info : IntrinsicValRef typeof_vref : ValRef + nameof_info : IntrinsicValRef + nameof_vref : ValRef + typenameof_info : IntrinsicValRef + typenameof_vref : ValRef methodhandleof_info : IntrinsicValRef methodhandleof_vref : ValRef sizeof_vref : ValRef @@ -929,6 +933,8 @@ let mkTcGlobals (compilingFslib,sysCcu,ilg,fslibCcu,directoryToResolveRelativePa let reraise_info = makeIntrinsicValRef(fslib_MFOperators_nleref, "reraise" ,None ,Some "Reraise",[vara], ([[unit_ty]],varaTy)) let typeof_info = makeIntrinsicValRef(fslib_MFOperators_nleref, "typeof" ,None ,Some "TypeOf" ,[vara], ([],system_Type_typ)) + let typenameof_info = makeIntrinsicValRef(fslib_MFOperators_nleref, "typenameof" ,None ,Some "TypeNameOf" ,[vara], ([],string_ty)) + let nameof_info = makeIntrinsicValRef(fslib_MFOperators_nleref, "nameof" ,None ,Some "NameOf" ,[vara], ([[varaTy]],string_ty)) let methodhandleof_info = makeIntrinsicValRef(fslib_MFOperators_nleref, "methodhandleof" ,None ,Some "MethodHandleOf",[vara;varb],([[varaTy --> varbTy]],system_RuntimeMethodHandle_typ)) let sizeof_info = makeIntrinsicValRef(fslib_MFOperators_nleref, "sizeof" ,None ,Some "SizeOf" ,[vara], ([],int_ty)) let unchecked_defaultof_info = makeIntrinsicValRef(fslib_MFOperatorsUnchecked_nleref, "defaultof" ,None ,Some "DefaultOf",[vara], ([],varaTy)) @@ -1383,6 +1389,10 @@ let mkTcGlobals (compilingFslib,sysCcu,ilg,fslibCcu,directoryToResolveRelativePa reraise_vref = ValRefForIntrinsic reraise_info methodhandleof_info = methodhandleof_info methodhandleof_vref = ValRefForIntrinsic methodhandleof_info + nameof_info = nameof_info + nameof_vref = ValRefForIntrinsic nameof_info + typenameof_info = typenameof_info + typenameof_vref = ValRefForIntrinsic typenameof_info typeof_info = typeof_info typeof_vref = ValRefForIntrinsic typeof_info sizeof_vref = ValRefForIntrinsic sizeof_info diff --git a/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/NameOf/E_NameOfAdditionExpr.fs b/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/NameOf/E_NameOfAdditionExpr.fs new file mode 100644 index 00000000000..64c41f78e31 --- /dev/null +++ b/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/NameOf/E_NameOfAdditionExpr.fs @@ -0,0 +1,7 @@ +// #Regression #Conformance #DataExpressions +// Verify that nameof doesn't work on const string +//This expression does not have a name. + +let x = nameof(1+2) + +exit 0 diff --git a/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/NameOf/E_NameOfAppliedFunction.fs b/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/NameOf/E_NameOfAppliedFunction.fs new file mode 100644 index 00000000000..3a812478a88 --- /dev/null +++ b/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/NameOf/E_NameOfAppliedFunction.fs @@ -0,0 +1,8 @@ +// #Regression #Conformance #DataExpressions +// Verify that nameof doesn't work on applied functions +//This expression does not have a name. + +let f() = 1 +let x = nameof(f()) + +exit 0 \ No newline at end of file diff --git a/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/NameOf/E_NameOfAsAFunction.fs b/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/NameOf/E_NameOfAsAFunction.fs new file mode 100644 index 00000000000..6411781236d --- /dev/null +++ b/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/NameOf/E_NameOfAsAFunction.fs @@ -0,0 +1,7 @@ +// #Regression #Conformance #DataExpressions +// Verify that nameof can't be used as a function. +//This expression does not have a name. + +let f = nameof + +exit 0 diff --git a/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/NameOf/E_NameOfDictLookup.fs b/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/NameOf/E_NameOfDictLookup.fs new file mode 100644 index 00000000000..ff9915209f2 --- /dev/null +++ b/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/NameOf/E_NameOfDictLookup.fs @@ -0,0 +1,8 @@ +// #Regression #Conformance #DataExpressions +// Verify that nameof doesn't work on dictionary lookup +//This expression does not have a name. + +let dict = new System.Collections.Generic.Dictionary() +let b = nameof(dict.[2]) + +exit 0 diff --git a/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/NameOf/E_NameOfIntConst.fs b/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/NameOf/E_NameOfIntConst.fs new file mode 100644 index 00000000000..89aa6ae3b11 --- /dev/null +++ b/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/NameOf/E_NameOfIntConst.fs @@ -0,0 +1,7 @@ +// #Regression #Conformance #DataExpressions +// Verify that nameof doesn't work on const int +//This expression does not have a name. + +let x = nameof 1 + +exit 0 diff --git a/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/NameOf/E_NameOfIntegerAppliedFunction.fs b/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/NameOf/E_NameOfIntegerAppliedFunction.fs new file mode 100644 index 00000000000..099ed0ad53b --- /dev/null +++ b/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/NameOf/E_NameOfIntegerAppliedFunction.fs @@ -0,0 +1,8 @@ +// #Regression #Conformance #DataExpressions +// Verify that nameof doesn't work on applied functions +//This expression does not have a name. + +let f x = 1 * x +let x = nameof(f 2) + +exit 0 diff --git a/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/NameOf/E_NameOfParameterAppliedFunction.fs b/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/NameOf/E_NameOfParameterAppliedFunction.fs new file mode 100644 index 00000000000..ad3f9772ebc --- /dev/null +++ b/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/NameOf/E_NameOfParameterAppliedFunction.fs @@ -0,0 +1,9 @@ +// #Regression #Conformance #DataExpressions +// Verify that nameof doesn't work on applied functions +//This expression does not have a name. + +let f x y = x y +let z x = 1 * x +let b = nameof(f z 1) + +exit 0 diff --git a/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/NameOf/E_NameOfPartiallyAppliedFunction.fs b/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/NameOf/E_NameOfPartiallyAppliedFunction.fs new file mode 100644 index 00000000000..3aa6244c078 --- /dev/null +++ b/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/NameOf/E_NameOfPartiallyAppliedFunction.fs @@ -0,0 +1,8 @@ +// #Regression #Conformance #DataExpressions +// Verify that nameof doesn't work on partially applied functions +//This expression does not have a name. + +let f x y = y * x +let x = nameof(f 2) + +exit 0 diff --git a/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/NameOf/E_NameOfStringConst.fs b/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/NameOf/E_NameOfStringConst.fs new file mode 100644 index 00000000000..b225f8ea628 --- /dev/null +++ b/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/NameOf/E_NameOfStringConst.fs @@ -0,0 +1,7 @@ +// #Regression #Conformance #DataExpressions +// Verify that nameof doesn't work on const string +//This expression does not have a name. + +let x = nameof "string" + +exit 0 diff --git a/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/NameOf/E_NameOfWithPipe.fs b/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/NameOf/E_NameOfWithPipe.fs new file mode 100644 index 00000000000..7973767fbc4 --- /dev/null +++ b/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/NameOf/E_NameOfWithPipe.fs @@ -0,0 +1,7 @@ +// #Regression #Conformance #DataExpressions +// Verify that nameof can't be used as a function. +//The nameof operator is not allowed in this position. + +let curriedFunction x y = x * y +let b = curriedFunction |> nameof +exit 0 diff --git a/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/NameOf/env.lst b/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/NameOf/env.lst new file mode 100644 index 00000000000..4b62ea892e7 --- /dev/null +++ b/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/NameOf/env.lst @@ -0,0 +1,10 @@ + SOURCE=E_NameOfIntConst.fs # E_NameOfIntConst.fs + SOURCE=E_NameOfStringConst.fs # E_NameOfStringConst.fs + SOURCE=E_NameOfAppliedFunction.fs # E_NameOfAppliedFunction.fs + SOURCE=E_NameOfIntegerAppliedFunction.fs # E_NameOfIntegerAppliedFunction.fs + SOURCE=E_NameOfPartiallyAppliedFunction.fs # E_NameOfPartiallyAppliedFunction.fs + SOURCE=E_NameOfDictLookup.fs # E_NameOfDictLookup.fs + SOURCE=E_NameOfAdditionExpr.fs # E_NameOfAdditionExpr.fs + SOURCE=E_NameOfParameterAppliedFunction.fs # E_NameOfParameterAppliedFunction.fs + SOURCE=E_NameOfAsAFunction.fs # E_NameOfAsAFunction.fs + SOURCE=E_NameOfWithPipe.fs # E_NameOfWithPipe.fs diff --git a/tests/fsharpqa/Source/test.lst b/tests/fsharpqa/Source/test.lst index b9391dc0801..7b3b1a46e8a 100644 --- a/tests/fsharpqa/Source/test.lst +++ b/tests/fsharpqa/Source/test.lst @@ -236,6 +236,7 @@ Conformance08 Conformance\UnitsOfMeasure\Parenthesis Conformance08 Conformance\UnitsOfMeasure\Parsing Conformance08 Conformance\UnitsOfMeasure\TypeChecker Conformance08 Conformance\UnitsOfMeasure\WithOOP +Conformance08 Conformance\Expressions\DataExpressions\NameOf Misc01 ClrFx\PseudoCustomAttributes\AssemblyAlgorithmId Misc01 ClrFx\PseudoCustomAttributes\AssemblyConfiguration From bd88baba7dbf97b554e541c9e3c0af85b8ceb6de Mon Sep 17 00:00:00 2001 From: Steffen Forkmann Date: Fri, 3 Jun 2016 10:09:23 +0200 Subject: [PATCH 2/2] Apply feedback --- src/fsharp/Optimizer.fs | 26 +++++++++---------- src/fsharp/PostInferenceChecks.fs | 11 +++++--- .../NameOf/E_NameOfAdditionExpr.fs | 2 +- .../NameOf/E_NameOfAppliedFunction.fs | 2 +- .../NameOf/E_NameOfAsAFunction.fs | 2 +- .../NameOf/E_NameOfDictLookup.fs | 2 +- .../NameOf/E_NameOfIntConst.fs | 2 +- .../NameOf/E_NameOfIntegerAppliedFunction.fs | 2 +- .../E_NameOfParameterAppliedFunction.fs | 2 +- .../E_NameOfPartiallyAppliedFunction.fs | 2 +- .../NameOf/E_NameOfStringConst.fs | 2 +- .../NameOf/E_NameOfWithPipe.fs | 2 +- 12 files changed, 30 insertions(+), 27 deletions(-) diff --git a/src/fsharp/Optimizer.fs b/src/fsharp/Optimizer.fs index 3830c15a843..989d26c7d8b 100644 --- a/src/fsharp/Optimizer.fs +++ b/src/fsharp/Optimizer.fs @@ -2345,8 +2345,17 @@ and DevirtualizeApplication cenv env (vref:ValRef) ty tyargs args m = let transformedExpr = wrap (MakeApplicationAndBetaReduce cenv.g (exprForValRef m vref,vref.Type,(if isNil tyargs then [] else [tyargs]),args,m)) OptimizeExpr cenv env transformedExpr - - + +and GetNameFromTypeName tcGlobals m typeName = + match stripTyEqns tcGlobals typeName with + | TType_app (tcref, _) -> tcref.CompiledRepresentationForNamedType.FullName + | TType_forall _ -> errorR(Error(FSComp.SR.expressionHasNoName(), m)); "" + | TType_tuple _ -> errorR(Error(FSComp.SR.expressionHasNoName(), m)); "" + | TType_fun _ -> errorR(Error(FSComp.SR.expressionHasNoName(), m)); "" + | TType_ucase _ -> errorR(Error(FSComp.SR.expressionHasNoName(), m)); "" + | TType_var tp -> tp.DisplayName + | TType_measure ms -> sprintf "%A" ms + and TryDevirtualizeApplication cenv env (f,tyargs,args,m) = match f,tyargs,args with @@ -2555,17 +2564,8 @@ and TryDevirtualizeApplication cenv env (f,tyargs,args,m) = // Analyze the name of the given type and rewrite AST to constant string expression with the name | Expr.Val(vref,_,_),_,_ when valRefEq cenv.g vref cenv.g.typenameof_vref -> match tyargs with - | (typeName:TType):: _ -> - let name = - match typeName with - | TType_forall (_tps,ty) -> ty.ToString() - | TType_app (tcref, _) -> tcref.CompiledRepresentationForNamedType.FullName - | TType_tuple tinst -> "(" + String.concat "," (List.map string tinst) + ")" - | TType_fun (d,r) -> "(" + string d + " -> " + string r + ")" - | TType_ucase (uc,_) -> uc.CaseName - | TType_var tp -> tp.DisplayName - | TType_measure ms -> sprintf "%A" ms - + | typeName:: _ -> + let name = GetNameFromTypeName cenv.g m typeName Some(Expr.Const(Const.String name, m, cenv.g.string_ty), { TotalSize = 1 FunctionSize = 1 diff --git a/src/fsharp/PostInferenceChecks.fs b/src/fsharp/PostInferenceChecks.fs index e5e829dda3b..261023316ec 100644 --- a/src/fsharp/PostInferenceChecks.fs +++ b/src/fsharp/PostInferenceChecks.fs @@ -464,10 +464,13 @@ let tryExtractNameOf args = match args with | [Expr.Val(r,_,_)] -> Some(r.CompiledName) | [Expr.App(Expr.Val(r,_,_),_,_,Expr.Const(constant,_,_)::_,_)] -> - if r.CompiledName.StartsWith("get_") && constant = Const.Unit then // TODO: We need a better way to find static property getters - Some(r.CompiledName.Substring(4)) - else - None // the function was applied + match constant with + | Const.Unit -> + if r.CompiledName.StartsWith("get_") then // TODO: We need a better way to find static property getters + Some(r.CompiledName.Substring(4)) + else + None // the function was applied + | _ -> None | [Expr.App(Expr.Val(r,_,_),_,_,[],_)] -> Some(r.CompiledName) | [Expr.App(Expr.Val(r,_,_),_,_,_,_)] -> if r.CompiledName.StartsWith("get_") then // TODO: We need a better way to find member property getters diff --git a/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/NameOf/E_NameOfAdditionExpr.fs b/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/NameOf/E_NameOfAdditionExpr.fs index 64c41f78e31..f71add7dd74 100644 --- a/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/NameOf/E_NameOfAdditionExpr.fs +++ b/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/NameOf/E_NameOfAdditionExpr.fs @@ -1,6 +1,6 @@ // #Regression #Conformance #DataExpressions // Verify that nameof doesn't work on const string -//This expression does not have a name. +//This expression does not have a name. let x = nameof(1+2) diff --git a/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/NameOf/E_NameOfAppliedFunction.fs b/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/NameOf/E_NameOfAppliedFunction.fs index 3a812478a88..6663899751e 100644 --- a/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/NameOf/E_NameOfAppliedFunction.fs +++ b/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/NameOf/E_NameOfAppliedFunction.fs @@ -1,6 +1,6 @@ // #Regression #Conformance #DataExpressions // Verify that nameof doesn't work on applied functions -//This expression does not have a name. +//This expression does not have a name. let f() = 1 let x = nameof(f()) diff --git a/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/NameOf/E_NameOfAsAFunction.fs b/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/NameOf/E_NameOfAsAFunction.fs index 6411781236d..f7e104cfe64 100644 --- a/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/NameOf/E_NameOfAsAFunction.fs +++ b/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/NameOf/E_NameOfAsAFunction.fs @@ -1,6 +1,6 @@ // #Regression #Conformance #DataExpressions // Verify that nameof can't be used as a function. -//This expression does not have a name. +//This expression does not have a name. let f = nameof diff --git a/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/NameOf/E_NameOfDictLookup.fs b/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/NameOf/E_NameOfDictLookup.fs index ff9915209f2..761b23cb3ea 100644 --- a/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/NameOf/E_NameOfDictLookup.fs +++ b/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/NameOf/E_NameOfDictLookup.fs @@ -1,6 +1,6 @@ // #Regression #Conformance #DataExpressions // Verify that nameof doesn't work on dictionary lookup -//This expression does not have a name. +//This expression does not have a name. let dict = new System.Collections.Generic.Dictionary() let b = nameof(dict.[2]) diff --git a/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/NameOf/E_NameOfIntConst.fs b/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/NameOf/E_NameOfIntConst.fs index 89aa6ae3b11..a5144348e05 100644 --- a/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/NameOf/E_NameOfIntConst.fs +++ b/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/NameOf/E_NameOfIntConst.fs @@ -1,6 +1,6 @@ // #Regression #Conformance #DataExpressions // Verify that nameof doesn't work on const int -//This expression does not have a name. +//This expression does not have a name. let x = nameof 1 diff --git a/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/NameOf/E_NameOfIntegerAppliedFunction.fs b/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/NameOf/E_NameOfIntegerAppliedFunction.fs index 099ed0ad53b..7fe241fe86f 100644 --- a/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/NameOf/E_NameOfIntegerAppliedFunction.fs +++ b/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/NameOf/E_NameOfIntegerAppliedFunction.fs @@ -1,6 +1,6 @@ // #Regression #Conformance #DataExpressions // Verify that nameof doesn't work on applied functions -//This expression does not have a name. +//This expression does not have a name. let f x = 1 * x let x = nameof(f 2) diff --git a/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/NameOf/E_NameOfParameterAppliedFunction.fs b/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/NameOf/E_NameOfParameterAppliedFunction.fs index ad3f9772ebc..5f24456195c 100644 --- a/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/NameOf/E_NameOfParameterAppliedFunction.fs +++ b/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/NameOf/E_NameOfParameterAppliedFunction.fs @@ -1,6 +1,6 @@ // #Regression #Conformance #DataExpressions // Verify that nameof doesn't work on applied functions -//This expression does not have a name. +//This expression does not have a name. let f x y = x y let z x = 1 * x diff --git a/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/NameOf/E_NameOfPartiallyAppliedFunction.fs b/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/NameOf/E_NameOfPartiallyAppliedFunction.fs index 3aa6244c078..4a572a983f3 100644 --- a/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/NameOf/E_NameOfPartiallyAppliedFunction.fs +++ b/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/NameOf/E_NameOfPartiallyAppliedFunction.fs @@ -1,6 +1,6 @@ // #Regression #Conformance #DataExpressions // Verify that nameof doesn't work on partially applied functions -//This expression does not have a name. +//This expression does not have a name. let f x y = y * x let x = nameof(f 2) diff --git a/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/NameOf/E_NameOfStringConst.fs b/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/NameOf/E_NameOfStringConst.fs index b225f8ea628..b30f702b1ae 100644 --- a/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/NameOf/E_NameOfStringConst.fs +++ b/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/NameOf/E_NameOfStringConst.fs @@ -1,6 +1,6 @@ // #Regression #Conformance #DataExpressions // Verify that nameof doesn't work on const string -//This expression does not have a name. +//This expression does not have a name. let x = nameof "string" diff --git a/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/NameOf/E_NameOfWithPipe.fs b/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/NameOf/E_NameOfWithPipe.fs index 7973767fbc4..f959420f99f 100644 --- a/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/NameOf/E_NameOfWithPipe.fs +++ b/tests/fsharpqa/Source/Conformance/Expressions/DataExpressions/NameOf/E_NameOfWithPipe.fs @@ -1,6 +1,6 @@ // #Regression #Conformance #DataExpressions // Verify that nameof can't be used as a function. -//The nameof operator is not allowed in this position. +//The nameof operator is not allowed in this position. let curriedFunction x y = x * y let b = curriedFunction |> nameof