From fbfa57bf307e3d47bd9d1d588c020f9946e77c16 Mon Sep 17 00:00:00 2001 From: Jared Parsons Date: Mon, 16 Feb 2015 08:05:30 -0800 Subject: [PATCH 1/2] Correctly handle duplicate WellKnownType values The WellKnownType enumeration contains several named items that have the same underlying value. Both First and Last share a value with an actual type entry in the enumeration. A ToString call on those values can return either the type name or First / Last, the runtime does not define which will happen. This comes into play in the static constructor of WellKnownTypes where we assert that the enumeration and s_metadataNames table stay in sync. The code already accounts for First being ambiguous but failed to for Last. This change removes the assumption for Last as well. It also expands out the assert as it was getting to difficult to follow when I added another level of ternary expressions into the mix. --- src/Compilers/Core/Portable/WellKnownTypes.cs | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/src/Compilers/Core/Portable/WellKnownTypes.cs b/src/Compilers/Core/Portable/WellKnownTypes.cs index 0eafe465fce7e..ebcc21eb78355 100644 --- a/src/Compilers/Core/Portable/WellKnownTypes.cs +++ b/src/Compilers/Core/Portable/WellKnownTypes.cs @@ -500,9 +500,29 @@ static WellKnownTypes() { var name = s_metadataNames[i]; var typeId = (WellKnownType)(i + WellKnownType.First); + +#if DEBUG + // Ensure the WellKnownType enumeration and s_metadataNames field stay in sync + + string typeIdName; + if (typeId == WellKnownType.First) + { + typeIdName = "System.Math"; + } + else if (typeId == WellKnownType.Last) + { + typeIdName = "System.IFormatProvider"; + } + else + { + typeIdName = typeId.ToString().Replace("__", "+").Replace('_', '.'); + } + Debug.Assert(name == "Microsoft.VisualBasic.CompilerServices.ObjectFlowControl+ForLoopControl" || name.IndexOf('`') > 0 // a generic type - || name == (typeId.ToString() == "First" ? "System.Math" : typeId.ToString().Replace("__", "+").Replace('_', '.'))); + || name == typeIdName); +#endif + s_nameToTypeIdMap.Add(name, typeId); } } From 230ba7bb70179edb2d20a4f33edbbfaf1a819b79 Mon Sep 17 00:00:00 2001 From: Jared Parsons Date: Mon, 16 Feb 2015 14:10:03 -0800 Subject: [PATCH 2/2] Refactor validation code to a new method This refactors the code which asserts the enum and name table are in sync into a new method. --- src/Compilers/Core/Portable/WellKnownTypes.cs | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/Compilers/Core/Portable/WellKnownTypes.cs b/src/Compilers/Core/Portable/WellKnownTypes.cs index ebcc21eb78355..5393c1242cc93 100644 --- a/src/Compilers/Core/Portable/WellKnownTypes.cs +++ b/src/Compilers/Core/Portable/WellKnownTypes.cs @@ -496,13 +496,23 @@ internal static class WellKnownTypes static WellKnownTypes() { + AssertEnumAndTableInSync(); + for (int i = 0; i < s_metadataNames.Length; i++) { var name = s_metadataNames[i]; var typeId = (WellKnownType)(i + WellKnownType.First); + s_nameToTypeIdMap.Add(name, typeId); + } + } -#if DEBUG - // Ensure the WellKnownType enumeration and s_metadataNames field stay in sync + [Conditional("DEBUG")] + private static void AssertEnumAndTableInSync() + { + for (int i = 0; i < s_metadataNames.Length; i++) + { + var name = s_metadataNames[i]; + var typeId = (WellKnownType)(i + WellKnownType.First); string typeIdName; if (typeId == WellKnownType.First) @@ -521,9 +531,6 @@ static WellKnownTypes() Debug.Assert(name == "Microsoft.VisualBasic.CompilerServices.ObjectFlowControl+ForLoopControl" || name.IndexOf('`') > 0 // a generic type || name == typeIdName); -#endif - - s_nameToTypeIdMap.Add(name, typeId); } }