You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucenenet.apache.org by ni...@apache.org on 2018/06/14 23:59:50 UTC

[1/2] lucenenet git commit: BUG: Fixed list comparison to include a check for count (without it an empty list on one side returns true)

Repository: lucenenet
Updated Branches:
  refs/heads/master a3a12967b -> 199fab066


BUG: Fixed list comparison to include a check for count (without it an empty list on one side returns true)


Project: http://git-wip-us.apache.org/repos/asf/lucenenet/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucenenet/commit/a66190d8
Tree: http://git-wip-us.apache.org/repos/asf/lucenenet/tree/a66190d8
Diff: http://git-wip-us.apache.org/repos/asf/lucenenet/diff/a66190d8

Branch: refs/heads/master
Commit: a66190d8a3b9694b6f0dab3946bebcd920c415c5
Parents: a3a1296
Author: Shad Storhaug <sh...@shadstorhaug.com>
Authored: Sun Nov 26 03:04:32 2017 +0700
Committer: Shad Storhaug <sh...@shadstorhaug.com>
Committed: Sun Nov 26 03:11:18 2017 +0700

----------------------------------------------------------------------
 src/Lucene.Net/Support/Collections.cs | 4 ++++
 1 file changed, 4 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucenenet/blob/a66190d8/src/Lucene.Net/Support/Collections.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net/Support/Collections.cs b/src/Lucene.Net/Support/Collections.cs
index 3ded8e3..76adb23 100644
--- a/src/Lucene.Net/Support/Collections.cs
+++ b/src/Lucene.Net/Support/Collections.cs
@@ -279,6 +279,10 @@ namespace Lucene.Net.Support
                 return false;
             }
 
+            if (listA.Count != listB.Count)
+            {
+                return false;
+            }
 
             using (IEnumerator<T> eA = listA.GetEnumerator())
             {


[2/2] lucenenet git commit: BUG: LUCENENET-602. Added Lucene.Net.Support.EqualityComparer implementation to fix incomplete support for value types with generics on MONO AOT platforms. Added missing constructor overload to Lucene.Net.Facet.Taxonomy.LRU

Posted by ni...@apache.org.
BUG: LUCENENET-602. Added Lucene.Net.Support.EqualityComparer<T> implementation to fix incomplete support for value types with generics on MONO AOT platforms. Added missing constructor overload to Lucene.Net.Facet.Taxonomy.LRUHashMap so the issue can be worked around using a custom IEqualityComparer<T> implementation if desired. Fixed inconsistencies with optimized C5 EqualityComparer, which was not being used in all of the C5-derived classes.


Project: http://git-wip-us.apache.org/repos/asf/lucenenet/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucenenet/commit/199fab06
Tree: http://git-wip-us.apache.org/repos/asf/lucenenet/tree/199fab06
Diff: http://git-wip-us.apache.org/repos/asf/lucenenet/diff/199fab06

Branch: refs/heads/master
Commit: 199fab0660b9a20508e6f1b86882441f0ec654e8
Parents: a66190d
Author: Shad Storhaug <sh...@shadstorhaug.com>
Authored: Fri Jun 15 06:43:37 2018 +0700
Committer: Shad Storhaug <sh...@shadstorhaug.com>
Committed: Fri Jun 15 06:43:37 2018 +0700

----------------------------------------------------------------------
 .../Analysis/Util/CharArrayMap.cs               |   2 +-
 .../Directory/DirectoryTaxonomyReader.cs        |   8 +-
 src/Lucene.Net.Facet/Taxonomy/LRUHashMap.cs     |  32 ++++-
 src/Lucene.Net.Tests/Support/C5/Events.cs       |   2 +-
 src/Lucene.Net.Tests/Support/C5/HashBag.cs      |   2 +-
 src/Lucene.Net.Tests/Support/TestLurchTable.cs  |  18 +--
 src/Lucene.Net.Tests/Support/TestTreeSet.cs     |  14 +--
 src/Lucene.Net/Search/LiveFieldValues.cs        |   9 +-
 src/Lucene.Net/Support/C5.Support.cs            |   4 +-
 .../Compatibility/ConcurrentDictionary.cs       |   2 +-
 src/Lucene.Net/Support/EqualityComparer.cs      | 124 +++++++++++++++++++
 src/Lucene.Net/Support/HashMap.cs               |   7 +-
 src/Lucene.Net/Support/LinkedHashMap.cs         |   2 +-
 src/Lucene.Net/Support/LurchTable.cs            |  43 ++++---
 src/Lucene.Net/Support/TreeDictionary.cs        |   2 +-
 src/Lucene.Net/Support/TreeSet.cs               |   2 +-
 src/Lucene.Net/Util/Fst/FST.cs                  |   8 +-
 src/Lucene.Net/Util/PriorityQueue.cs            |   2 +-
 18 files changed, 225 insertions(+), 58 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucenenet/blob/199fab06/src/Lucene.Net.Analysis.Common/Analysis/Util/CharArrayMap.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Analysis.Common/Analysis/Util/CharArrayMap.cs b/src/Lucene.Net.Analysis.Common/Analysis/Util/CharArrayMap.cs
index cfe5625..c642bc8 100644
--- a/src/Lucene.Net.Analysis.Common/Analysis/Util/CharArrayMap.cs
+++ b/src/Lucene.Net.Analysis.Common/Analysis/Util/CharArrayMap.cs
@@ -764,7 +764,7 @@ namespace Lucene.Net.Analysis.Util
                 if (!this.ContainsKey(iter.Current.Key))
                     return false;
 
-                if (!EqualityComparer<TValue>.Default.Equals(this[iter.Current.Key], iter.Current.Value))
+                if (!Support.EqualityComparer<TValue>.Default.Equals(this[iter.Current.Key], iter.Current.Value))
                     return false;
             }
 

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/199fab06/src/Lucene.Net.Facet/Taxonomy/Directory/DirectoryTaxonomyReader.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Facet/Taxonomy/Directory/DirectoryTaxonomyReader.cs b/src/Lucene.Net.Facet/Taxonomy/Directory/DirectoryTaxonomyReader.cs
index 994b644..13a5feb 100644
--- a/src/Lucene.Net.Facet/Taxonomy/Directory/DirectoryTaxonomyReader.cs
+++ b/src/Lucene.Net.Facet/Taxonomy/Directory/DirectoryTaxonomyReader.cs
@@ -1,4 +1,5 @@
-using System;
+using Lucene.Net.Support;
+using System;
 using System.Collections.Generic;
 using System.IO;
 using System.Text;
@@ -22,7 +23,6 @@ namespace Lucene.Net.Facet.Taxonomy.Directory
      * limitations under the License.
      */
 
-    using Lucene.Net.Facet.Taxonomy;
     using BytesRef = Lucene.Net.Util.BytesRef;
     using Directory = Lucene.Net.Store.Directory;
     using DirectoryReader = Lucene.Net.Index.DirectoryReader;
@@ -83,8 +83,8 @@ namespace Lucene.Net.Facet.Taxonomy.Directory
             this.taxoEpoch = taxoWriter == null ? -1 : taxoWriter.TaxonomyEpoch;
 
             // use the same instance of the cache, note the protective code in getOrdinal and getPath
-            this.ordinalCache = ordinalCache == null ? new LRUHashMap<FacetLabel, Int32Class>(DEFAULT_CACHE_VALUE) : ordinalCache;
-            this.categoryCache = categoryCache == null ? new LRUHashMap<int, FacetLabel>(DEFAULT_CACHE_VALUE) : categoryCache;
+            this.ordinalCache = ordinalCache ?? new LRUHashMap<FacetLabel, Int32Class>(DEFAULT_CACHE_VALUE);
+            this.categoryCache = categoryCache ?? new LRUHashMap<int, FacetLabel>(DEFAULT_CACHE_VALUE);
 
             this.taxoArrays = taxoArrays != null ? new TaxonomyIndexArrays(indexReader, taxoArrays) : null;
         }

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/199fab06/src/Lucene.Net.Facet/Taxonomy/LRUHashMap.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Facet/Taxonomy/LRUHashMap.cs b/src/Lucene.Net.Facet/Taxonomy/LRUHashMap.cs
index f38c8d2..bd449b9 100644
--- a/src/Lucene.Net.Facet/Taxonomy/LRUHashMap.cs
+++ b/src/Lucene.Net.Facet/Taxonomy/LRUHashMap.cs
@@ -50,7 +50,7 @@ namespace Lucene.Net.Facet.Taxonomy
         /// The maximum size (in number of entries) to which the map can grow
         /// before the least recently used entries start being removed.
         /// <para/>
-        /// Setting maxSize to a very large value, like <see cref="int.MaxValue"/>
+        /// Setting <paramref name="limit"/> to a very large value, like <see cref="int.MaxValue"/>
         /// is allowed, but is less efficient than
         /// using <see cref="Support.HashMap{TKey, TValue}"/> or 
         /// <see cref="Dictionary{TKey, TValue}"/> because our class needs
@@ -59,8 +59,36 @@ namespace Lucene.Net.Facet.Taxonomy
         /// maximum size.
         /// </param>
         public LRUHashMap(int limit)
+            : this(limit, null)
         {
-            cache = new LurchTable<TKey, TValue>(LurchTableOrder.Access, limit);
+        }
+
+        /// <summary>
+        /// Create a new hash map with a bounded size and with least recently
+        /// used entries removed.
+        /// <para/>
+        /// LUCENENET specific overload to allow passing in custom <see cref="IEqualityComparer{T}"/>. 
+        /// See LUCENENET-602.
+        /// </summary>
+        /// <param name="limit">
+        /// The maximum size (in number of entries) to which the map can grow
+        /// before the least recently used entries start being removed.
+        /// <para/>
+        /// Setting <paramref name="limit"/> to a very large value, like <see cref="int.MaxValue"/>
+        /// is allowed, but is less efficient than
+        /// using <see cref="Support.HashMap{TKey, TValue}"/> or 
+        /// <see cref="Dictionary{TKey, TValue}"/> because our class needs
+        /// to keep track of the use order (via an additional doubly-linked
+        /// list) which is not used when the map's size is always below the
+        /// maximum size.
+        /// </param>
+        /// <param name="comparer">
+        /// The <see cref="IEqualityComparer{TKey}"/> implementation to use when comparing keys, 
+        /// or <c>null</c> to use the default <see cref="IEqualityComparer{TKey}"/> for the type of the key.
+        /// </param>
+        public LRUHashMap(int limit, IEqualityComparer<TKey> comparer)
+        {
+            cache = new LurchTable<TKey, TValue>(LurchTableOrder.Access, limit, comparer);
         }
 
         /// <summary>

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/199fab06/src/Lucene.Net.Tests/Support/C5/Events.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/Support/C5/Events.cs b/src/Lucene.Net.Tests/Support/C5/Events.cs
index f0f5082..c3e982d 100644
--- a/src/Lucene.Net.Tests/Support/C5/Events.cs
+++ b/src/Lucene.Net.Tests/Support/C5/Events.cs
@@ -38,7 +38,7 @@ namespace Lucene.Net.Support.Templates.Events
         {
             this.collection = list;
             listenTo = testSpec;
-            seen = new CollectionEventList<TItem>(EqualityComparer<TItem>.Default, memoryType);
+            seen = new CollectionEventList<TItem>(C5.EqualityComparer<TItem>.Default, memoryType);
         }
 
         public SCG.IEnumerable<EventTypeEnum> SpecsBasic

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/199fab06/src/Lucene.Net.Tests/Support/C5/HashBag.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/Support/C5/HashBag.cs b/src/Lucene.Net.Tests/Support/C5/HashBag.cs
index 288198a..9b46e63 100644
--- a/src/Lucene.Net.Tests/Support/C5/HashBag.cs
+++ b/src/Lucene.Net.Tests/Support/C5/HashBag.cs
@@ -50,7 +50,7 @@ namespace Lucene.Net.Support.C5
         /// <summary>
         /// Create a hash bag with the default item equalityComparer.
         /// </summary>
-		public HashBag(MemoryType memoryType = MemoryType.Normal) : this(EqualityComparer<T>.Default, memoryType) { }
+		public HashBag(MemoryType memoryType = MemoryType.Normal) : this(C5.EqualityComparer<T>.Default, memoryType) { }
 
         /// <summary>
         /// Create a hash bag with an external item equalityComparer.

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/199fab06/src/Lucene.Net.Tests/Support/TestLurchTable.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/Support/TestLurchTable.cs b/src/Lucene.Net.Tests/Support/TestLurchTable.cs
index 47c22a7..af38e5c 100644
--- a/src/Lucene.Net.Tests/Support/TestLurchTable.cs
+++ b/src/Lucene.Net.Tests/Support/TestLurchTable.cs
@@ -180,7 +180,7 @@ namespace Lucene.Net.Support
         {
             //multiple of prime will produce hash collision, thus testing removal of non-first elements
             const int prime = 1103;
-            var test = new LurchTable<int, string>(LurchTableOrder.Access, 3, prime, 10, 10, EqualityComparer<int>.Default);
+            var test = new LurchTable<int, string>(LurchTableOrder.Access, 3, prime, 10, 10, Support.EqualityComparer<int>.Default);
             test[1 * prime] = "a";
             test[2 * prime] = "b";
             test[3 * prime] = "c";
@@ -207,7 +207,7 @@ namespace Lucene.Net.Support
         public void TestCrudEvents()
         {
             var recorder = new RecordEvents<int, string>();
-            var test = new LurchTable<int, string>(LurchTableOrder.Access, 3, 1103, 10, 10, EqualityComparer<int>.Default);
+            var test = new LurchTable<int, string>(LurchTableOrder.Access, 3, 1103, 10, 10, Support.EqualityComparer<int>.Default);
             test.ItemAdded += recorder.ItemAdded;
             test.ItemUpdated += recorder.ItemUpdated;
             test.ItemRemoved += recorder.ItemRemoved;
@@ -247,7 +247,7 @@ namespace Lucene.Net.Support
         {
             //multiple of prime will produce hash collision, thus testing removal of non-first elements
             const int prime = 1103;
-            var test = new LurchTable<int, string>(LurchTableOrder.Access, 10, prime, 10, 10, EqualityComparer<int>.Default);
+            var test = new LurchTable<int, string>(LurchTableOrder.Access, 10, prime, 10, 10, Support.EqualityComparer<int>.Default);
             test[1 * prime] = "a";
             test[2 * prime] = "b";
             test[3 * prime] = "c";
@@ -487,8 +487,8 @@ namespace Lucene.Net.Support
             var keys = new List<int>();
             foreach (var kv in sample)
                 keys.Add(kv.Key);
-            VerifyCollection(EqualityComparer<int>.Default, keys.AsReadOnly(), items.Keys);
-            VerifyCollection(EqualityComparer<int>.Default, keys.AsReadOnly(), dict.Keys);
+            VerifyCollection(Support.EqualityComparer<int>.Default, keys.AsReadOnly(), items.Keys);
+            VerifyCollection(Support.EqualityComparer<int>.Default, keys.AsReadOnly(), dict.Keys);
         }
 
         [Test, LuceneNetSpecific]
@@ -500,8 +500,8 @@ namespace Lucene.Net.Support
             var values = new List<string>();
             foreach (var kv in sample)
                 values.Add(kv.Value);
-            VerifyCollection(EqualityComparer<string>.Default, values.AsReadOnly(), items.Values);
-            VerifyCollection(EqualityComparer<string>.Default, values.AsReadOnly(), dict.Values);
+            VerifyCollection(Support.EqualityComparer<string>.Default, values.AsReadOnly(), items.Values);
+            VerifyCollection(Support.EqualityComparer<string>.Default, values.AsReadOnly(), dict.Values);
         }
 
         [Test]
@@ -518,8 +518,8 @@ namespace Lucene.Net.Support
 
         class KeyValueEquality<TKey, TValue> : IEqualityComparer<KeyValuePair<TKey, TValue>>
         {
-            IEqualityComparer<TKey> KeyComparer = EqualityComparer<TKey>.Default;
-            IEqualityComparer<TValue> ValueComparer = EqualityComparer<TValue>.Default;
+            IEqualityComparer<TKey> KeyComparer = Support.EqualityComparer<TKey>.Default;
+            IEqualityComparer<TValue> ValueComparer = Support.EqualityComparer<TValue>.Default;
             public bool Equals(KeyValuePair<TKey, TValue> x, KeyValuePair<TKey, TValue> y)
             {
                 return KeyComparer.Equals(x.Key, y.Key) && ValueComparer.Equals(x.Value, y.Value);

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/199fab06/src/Lucene.Net.Tests/Support/TestTreeSet.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/Support/TestTreeSet.cs b/src/Lucene.Net.Tests/Support/TestTreeSet.cs
index 448e27c..56f88cf 100644
--- a/src/Lucene.Net.Tests/Support/TestTreeSet.cs
+++ b/src/Lucene.Net.Tests/Support/TestTreeSet.cs
@@ -416,7 +416,7 @@ namespace Lucene.Net.Support.RBTreeSet
         [Test, LuceneNetSpecific]
         public void NullEqualityComparerinConstructor3()
         {
-            Assert.Throws<NullReferenceException>(() => new TreeSet<int>(null, EqualityComparer<int>.Default));
+            Assert.Throws<NullReferenceException>(() => new TreeSet<int>(null, Support.EqualityComparer<int>.Default));
         }
 
         [Test, LuceneNetSpecific]
@@ -2784,9 +2784,9 @@ namespace Lucene.Net.Support.RBTreeSet
             [SetUp]
             public void Init()
             {
-                dit = new TreeSet<int>(SCG.Comparer<int>.Default, EqualityComparer<int>.Default);
-                dat = new TreeSet<int>(SCG.Comparer<int>.Default, EqualityComparer<int>.Default);
-                dut = new TreeSet<int>(new RevIC(), EqualityComparer<int>.Default);
+                dit = new TreeSet<int>(SCG.Comparer<int>.Default, Support.EqualityComparer<int>.Default);
+                dat = new TreeSet<int>(SCG.Comparer<int>.Default, Support.EqualityComparer<int>.Default);
+                dut = new TreeSet<int>(new RevIC(), Support.EqualityComparer<int>.Default);
             }
 
 
@@ -2880,9 +2880,9 @@ namespace Lucene.Net.Support.RBTreeSet
             [SetUp]
             public void Init()
             {
-                dit = new TreeSet<int>(SCG.Comparer<int>.Default, EqualityComparer<int>.Default);
-                dat = new TreeSet<int>(SCG.Comparer<int>.Default, EqualityComparer<int>.Default);
-                dut = new TreeSet<int>(new RevIC(), EqualityComparer<int>.Default);
+                dit = new TreeSet<int>(SCG.Comparer<int>.Default, Support.EqualityComparer<int>.Default);
+                dat = new TreeSet<int>(SCG.Comparer<int>.Default, Support.EqualityComparer<int>.Default);
+                dut = new TreeSet<int>(new RevIC(), Support.EqualityComparer<int>.Default);
             }
 
 

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/199fab06/src/Lucene.Net/Search/LiveFieldValues.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net/Search/LiveFieldValues.cs b/src/Lucene.Net/Search/LiveFieldValues.cs
index 6f2ab6f..43603a3 100644
--- a/src/Lucene.Net/Search/LiveFieldValues.cs
+++ b/src/Lucene.Net/Search/LiveFieldValues.cs
@@ -114,26 +114,27 @@ namespace Lucene.Net.Search
             // First try to get the "live" value:
             T value;
             current.TryGetValue(id, out value);
-            if (EqualityComparer<T>.Default.Equals(value, missingValue))
+            var comparer = Support.EqualityComparer<T>.Default;
+            if (comparer.Equals(value, missingValue))
             {
                 // Deleted but the deletion is not yet reflected in
                 // the reader:
                 return default(T);
             }
-            else if (!EqualityComparer<T>.Default.Equals(value, default(T)))
+            else if (!comparer.Equals(value, default(T)))
             {
                 return value;
             }
             else
             {
                 old.TryGetValue(id, out value);
-                if (EqualityComparer<T>.Default.Equals(value, missingValue))
+                if (comparer.Equals(value, missingValue))
                 {
                     // Deleted but the deletion is not yet reflected in
                     // the reader:
                     return default(T);
                 }
-                else if (!EqualityComparer<T>.Default.Equals(value, default(T)))
+                else if (!comparer.Equals(value, default(T)))
                 {
                     return value;
                 }

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/199fab06/src/Lucene.Net/Support/C5.Support.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net/Support/C5.Support.cs b/src/Lucene.Net/Support/C5.Support.cs
index fc80bbc..9789d88 100644
--- a/src/Lucene.Net/Support/C5.Support.cs
+++ b/src/Lucene.Net/Support/C5.Support.cs
@@ -3967,7 +3967,7 @@ namespace Lucene.Net.Support.C5
         /// <item><description>If the actual generic argument T implements 
         /// <see cref="T:C5.ICollection`1"/> for some value W of its generic parameter T,
         /// the equalityComparer will be <see cref="T:C5.UnsequencedCollectionEqualityComparer`2"/></description></item>
-        /// <item><description>Otherwise the SCG.EqualityComparer&lt;T&gt;.Default is returned</description></item>
+        /// <item><description>Otherwise the Support.EqualityComparer&lt;T&gt;.Default is returned</description></item>
         /// </list>   
         /// </summary>
         /// <value>The comparer</value>
@@ -4005,7 +4005,7 @@ namespace Lucene.Net.Support.C5
                     return CreateAndCache(UnsequencedCollectionEqualityComparer.MakeGenericType(new[] { type, icollection.GetGenericArguments()[0] }));
                 }
 
-                return _default = SCG.EqualityComparer<T>.Default;
+                return _default = Support.EqualityComparer<T>.Default;
             }
         }
 

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/199fab06/src/Lucene.Net/Support/Compatibility/ConcurrentDictionary.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net/Support/Compatibility/ConcurrentDictionary.cs b/src/Lucene.Net/Support/Compatibility/ConcurrentDictionary.cs
index 58f6dd8..22f1531 100644
--- a/src/Lucene.Net/Support/Compatibility/ConcurrentDictionary.cs
+++ b/src/Lucene.Net/Support/Compatibility/ConcurrentDictionary.cs
@@ -45,7 +45,7 @@ namespace System.Collections.Concurrent
         { }
 
         public ConcurrentDictionary(int capacity)
-            : this(capacity, EqualityComparer<TKey>.Default)
+            : this(capacity, Support.EqualityComparer<TKey>.Default)
         { }
 
         public ConcurrentDictionary(int capacity, IEqualityComparer<TKey> comparer)

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/199fab06/src/Lucene.Net/Support/EqualityComparer.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net/Support/EqualityComparer.cs b/src/Lucene.Net/Support/EqualityComparer.cs
new file mode 100644
index 0000000..6ea40cb
--- /dev/null
+++ b/src/Lucene.Net/Support/EqualityComparer.cs
@@ -0,0 +1,124 @@
+using System.Collections.Generic;
+using System.Reflection;
+
+namespace Lucene.Net.Support
+{
+    /*
+	 * Licensed to the Apache Software Foundation (ASF) under one or more
+	 * contributor license agreements.  See the NOTICE file distributed with
+	 * this work for additional information regarding copyright ownership.
+	 * The ASF licenses this file to You under the Apache License, Version 2.0
+	 * (the "License"); you may not use this file except in compliance with
+	 * the License.  You may obtain a copy of the License at
+	 *
+	 *     http://www.apache.org/licenses/LICENSE-2.0
+	 *
+	 * Unless required by applicable law or agreed to in writing, software
+	 * distributed under the License is distributed on an "AS IS" BASIS,
+	 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+	 * See the License for the specific language governing permissions and
+	 * limitations under the License.
+	 */
+
+    /// <summary>
+    /// <see cref="IEqualityComparer{T}"/> to patch value type support for generics in MONO AOT.
+    /// Value types for generics in this environment at the time of this writing is
+    /// not supported, but is currently under development and eventually should be.
+    /// <para/>
+    /// This class can be used to patch the behavior when using MONO AOT, at the cost
+    /// of throwing an exception to reliably detect when generic types are not supported.
+    /// See <a href=""></a>
+    /// <para/>
+    /// See LUCENENET-602.
+    /// </summary>
+    /// <typeparam name="T">The type of objects to compare.</typeparam>
+    public sealed class EqualityComparer<T>
+    {
+        private static readonly bool IsValueType = typeof(T).GetTypeInfo().IsValueType;
+
+        /// <summary>
+        /// Returns a default equality comparer for the type specified by the generic argument.
+        /// <para/>
+        /// LUCENENET specific constant that is used for the comparer
+        /// rather than creating a custom <see cref="IEqualityComparer{T}"/> for value types.
+        /// See LUCENENET-602.
+        /// </summary>
+        public static System.Collections.Generic.EqualityComparer<T> Default { get; } = CreateComparer();
+
+        private static System.Collections.Generic.EqualityComparer<T> CreateComparer()
+        {
+            if (!EqualityComparerConstants.ValueTypesSupported.HasValue)
+            {
+                if (EqualityComparerConstants.ValueTypesSupported == true)
+                {
+                    return System.Collections.Generic.EqualityComparer<T>.Default;
+                }
+                else
+                {
+                    return IsValueType ?
+                        new ValueTypeEqualityComparer() :
+                        System.Collections.Generic.EqualityComparer<T>.Default;
+                }
+            }
+
+            // We test for an exception the first time this is called on this runtime instance,
+            // and store it in the ValueTypesSupported property (called once for any value type).
+            // This is not currently supported under MONO AOT compilation, but is under development,
+            // so eventually the catch path will be unreachable.
+            try
+            {
+                var result = System.Collections.Generic.EqualityComparer<T>.Default;
+                EqualityComparerConstants.ValueTypesSupported = true;
+                return result;
+            }
+            catch when (IsValueType)
+            {
+                EqualityComparerConstants.ValueTypesSupported = false;
+                return new ValueTypeEqualityComparer();
+            }
+        }
+
+        /// <summary>
+        /// Comparer for any .NET value type.
+        /// <para/>
+        /// In some platforms, such as Xamarin iOS, the implementation of <see cref="System.Collections.Generic.EqualityComparer{T}.Default"/> doesn't
+        /// work for value types. This class is used to provide equality comparers in cases where value types are required.
+        /// </summary>
+        internal class ValueTypeEqualityComparer : System.Collections.Generic.EqualityComparer<T> // where T : struct
+        {
+            /// <summary>
+            /// Determines whether two objects of type T are equal.
+            /// </summary>
+            /// <param name="x">The first value type to compare.</param>
+            /// <param name="y">The second value type to compare.</param>
+            /// <returns><c>true</c> if the specified objects are equal; otherwise, <c>false</c>.</returns>
+            public override bool Equals(T x, T y)
+            {
+                if (x != null)
+                {
+                    if (y != null) return x.Equals(y);
+                    return false;
+                }
+                if (y != null) return false;
+                return true;
+            }
+
+            /// <summary>
+            /// Serves as the default hash function.
+            /// <para/>
+            /// This is the same as calling obj.GetHashCode().
+            /// </summary>
+            /// <param name="obj">The object for which to get a hash code.</param>
+            /// <returns>A hash code for the specified object.</returns>
+            public override int GetHashCode(T obj)
+            {
+                return obj == null ? 0 : obj.GetHashCode();
+            }
+        }
+    }
+
+    internal class EqualityComparerConstants
+    {
+        public static bool? ValueTypesSupported { get; set; } = null;
+    }
+}

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/199fab06/src/Lucene.Net/Support/HashMap.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net/Support/HashMap.cs b/src/Lucene.Net/Support/HashMap.cs
index 6a293c3..65ba883 100644
--- a/src/Lucene.Net/Support/HashMap.cs
+++ b/src/Lucene.Net/Support/HashMap.cs
@@ -95,7 +95,7 @@ namespace Lucene.Net.Support
         }
 
         public HashMap(int initialCapacity)
-            : this(initialCapacity, EqualityComparer<TKey>.Default)
+            : this(initialCapacity, Support.EqualityComparer<TKey>.Default)
         {
         }
 
@@ -115,7 +115,8 @@ namespace Lucene.Net.Support
 
         internal HashMap(IDictionary<TKey, TValue> wrappedDict, IEqualityComparer<TKey> comparer)
         {
-            _comparer = EqualityComparer<TKey>.Default;
+            // LUCENENET TODO: Is this a bug? Shouldn't we be using the passed in comparer if non-null?
+            _comparer = /* comparer ?? */ Support.EqualityComparer<TKey>.Default;
             _dict = wrappedDict;
             _hasNullValue = false;
 
@@ -260,7 +261,7 @@ namespace Lucene.Net.Support
         {
             if (!_isValueType && _comparer.Equals(item.Key, default(TKey)))
             {
-                return _hasNullValue && EqualityComparer<TValue>.Default.Equals(item.Value, _nullValue);
+                return _hasNullValue && Support.EqualityComparer<TValue>.Default.Equals(item.Value, _nullValue);
             }
 
             return _dict.Contains(item);

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/199fab06/src/Lucene.Net/Support/LinkedHashMap.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net/Support/LinkedHashMap.cs b/src/Lucene.Net/Support/LinkedHashMap.cs
index e3d9c94..dbc5d3b 100644
--- a/src/Lucene.Net/Support/LinkedHashMap.cs
+++ b/src/Lucene.Net/Support/LinkedHashMap.cs
@@ -199,7 +199,7 @@ namespace Lucene.Net.Support
         private bool TryGetNode(TKey key, TValue value, out LinkedListNode<KeyValuePair<TKey, TValue>> node)
         {
             LinkedListNode<KeyValuePair<TKey, TValue>> n;
-            if (dict.TryGetValue(key, out n) && EqualityComparer<TValue>.Default.Equals(value, n.Value.Value))
+            if (dict.TryGetValue(key, out n) && Support.EqualityComparer<TValue>.Default.Equals(value, n.Value.Value))
             {
                 node = n;
                 return true;

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/199fab06/src/Lucene.Net/Support/LurchTable.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net/Support/LurchTable.cs b/src/Lucene.Net/Support/LurchTable.cs
index 71379c8..47d251f 100644
--- a/src/Lucene.Net/Support/LurchTable.cs
+++ b/src/Lucene.Net/Support/LurchTable.cs
@@ -75,35 +75,48 @@ namespace Lucene.Net.Support
         private int _used, _count;
         private int _allocNext, _freeVersion;
 
-        /// <summary>Creates a LurchTable that can store up to (capacity) items efficiently.</summary>
+
+
+        /// <summary>Creates a LurchTable that can store up to <paramref name="capacity"/> items efficiently.</summary>
+        /// <param name="capacity">The initial allowable number of items before allocation of more memory</param>
         public LurchTable(int capacity)
-            : this(LurchTableOrder.None, int.MaxValue, capacity >> 1, capacity >> 4, capacity >> 8, EqualityComparer<TKey>.Default) { }
+            : this(LurchTableOrder.None, int.MaxValue, capacity >> 1, capacity >> 4, capacity >> 8, null) { }
 
-        /// <summary>Creates a LurchTable that can store up to (capacity) items efficiently.</summary>
+        /// <summary>Creates a LurchTable that can store up to <paramref name="capacity"/> items efficiently.</summary>
+        /// <param name="capacity">The initial allowable number of items before allocation of more memory</param>
+        /// <param name="ordering">The type of linking for the items</param>
         public LurchTable(int capacity, LurchTableOrder ordering)
-            : this(ordering, int.MaxValue, capacity >> 1, capacity >> 4, capacity >> 8, EqualityComparer<TKey>.Default) { }
+            : this(ordering, int.MaxValue, capacity >> 1, capacity >> 4, capacity >> 8, null) { }
 
-        /// <summary>Creates a LurchTable that can store up to (capacity) items efficiently.</summary>
+        /// <summary>Creates a LurchTable that can store up to <paramref name="capacity"/> items efficiently.</summary>
+        /// <param name="capacity">The initial allowable number of items before allocation of more memory</param>
+        /// <param name="ordering">The type of linking for the items</param>
+        /// <param name="comparer">The element hash generator for keys, or <c>null</c> to use <see cref="Support.EqualityComparer{TKey}.Default"/></param>
         public LurchTable(int capacity, LurchTableOrder ordering, IEqualityComparer<TKey> comparer)
             : this(ordering, int.MaxValue, capacity >> 1, capacity >> 4, capacity >> 8, comparer) { }
 
-        /// <summary>Creates a LurchTable that orders items by (ordering) and removes items once the specified (limit) is reached.</summary>
+        /// <summary>Creates a LurchTable that orders items by <paramref name="ordering"/> and removes items once the specified <paramref name="limit"/> is reached.</summary>
+        /// <param name="ordering">The type of linking for the items</param>
+        /// <param name="limit">The maximum allowable number of items, or int.MaxValue for unlimited</param>
         public LurchTable(LurchTableOrder ordering, int limit)
-            : this(ordering, limit, limit >> 1, limit >> 4, limit >> 8, EqualityComparer<TKey>.Default) { }
+            : this(ordering, limit, limit >> 1, limit >> 4, limit >> 8, null) { }
 
-        /// <summary>Creates a LurchTable that orders items by (ordering) and removes items once the specified (limit) is reached.</summary>
+        /// <summary>Creates a LurchTable that orders items by <paramref name="ordering"/> and removes items once the specified <paramref name="limit"/> is reached.</summary>
+        /// <param name="ordering">The type of linking for the items</param>
+        /// <param name="limit">The maximum allowable number of items, or int.MaxValue for unlimited</param>
+        /// <param name="comparer">The element hash generator for keys, or <c>null</c> to use <see cref="Support.EqualityComparer{TKey}.Default"/></param>
         public LurchTable(LurchTableOrder ordering, int limit, IEqualityComparer<TKey> comparer)
             : this(ordering, limit, limit >> 1, limit >> 4, limit >> 8, comparer) { }
 
         /// <summary>
-        /// Creates a LurchTable that orders items by (ordering) and removes items once the specified (limit) is reached.
+        /// Creates a LurchTable that orders items by <paramref name="ordering"/> and removes items once the specified <paramref name="limit"/> is reached.
         /// </summary>
         /// <param name="ordering">The type of linking for the items</param>
         /// <param name="limit">The maximum allowable number of items, or int.MaxValue for unlimited</param>
         /// <param name="hashSize">The number of hash buckets to use for the collection, usually 1/2 estimated capacity</param>
         /// <param name="allocSize">The number of entries to allocate at a time, usually 1/16 estimated capacity</param>
         /// <param name="lockSize">The number of concurrency locks to preallocate, usually 1/256 estimated capacity</param>
-        /// <param name="comparer">The element hash generator for keys</param>
+        /// <param name="comparer">The element hash generator for keys, or <c>null</c> to use <see cref="Support.EqualityComparer{TKey}.Default"/></param>
         public LurchTable(LurchTableOrder ordering, int limit, int hashSize, int allocSize, int lockSize, IEqualityComparer<TKey> comparer)
         {
             if (limit <= 0)
@@ -112,7 +125,7 @@ namespace Lucene.Net.Support
                 throw new ArgumentOutOfRangeException("ordering");
 
             _limit = limit <= 0 ? int.MaxValue : limit;
-            _comparer = comparer;
+            _comparer = comparer ?? Support.EqualityComparer<TKey>.Default;
             _ordering = ordering;
 
             allocSize = (int)Math.Min((long)allocSize + OverAlloc, 0x3fffffff);
@@ -457,7 +470,7 @@ namespace Lucene.Net.Support
         {
             TValue test;
             if (TryGetValue(item.Key, out test))
-                return EqualityComparer<TValue>.Default.Equals(item.Value, test);
+                return Support.EqualityComparer<TValue>.Default.Equals(item.Value, test);
             return false;
         }
 
@@ -754,7 +767,7 @@ namespace Lucene.Net.Support
             /// </summary>
             public bool Contains(TValue value)
             {
-                var comparer = EqualityComparer<TValue>.Default;
+                var comparer = Support.EqualityComparer<TValue>.Default;
                 foreach (var item in _owner)
                 {
                     if (comparer.Equals(item.Value, value))
@@ -1413,7 +1426,7 @@ namespace Lucene.Net.Support
             {
                 Value = value;
 
-                if (_hasTestValue && !EqualityComparer<TValue>.Default.Equals(_testValue, value))
+                if (_hasTestValue && !Support.EqualityComparer<TValue>.Default.Equals(_testValue, value))
                     return false;
                 if (Condition != null && !Condition(key, value))
                     return false;
@@ -1508,7 +1521,7 @@ namespace Lucene.Net.Support
             }
             public bool UpdateValue(TKey key, ref TValue value)
             {
-                if (_hasTestValue && !EqualityComparer<TValue>.Default.Equals(_testValue, value))
+                if (_hasTestValue && !Support.EqualityComparer<TValue>.Default.Equals(_testValue, value))
                     return false;
 
                 value = Value;

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/199fab06/src/Lucene.Net/Support/TreeDictionary.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net/Support/TreeDictionary.cs b/src/Lucene.Net/Support/TreeDictionary.cs
index f1b50f1..fe43a57 100644
--- a/src/Lucene.Net/Support/TreeDictionary.cs
+++ b/src/Lucene.Net/Support/TreeDictionary.cs
@@ -40,7 +40,7 @@ namespace Lucene.Net.Support
         /// Create a red-black tree dictionary using the natural comparer for keys.
         /// <exception cref="ArgumentException"/> if the key type K is not comparable.
         /// </summary>
-		public TreeDictionary(MemoryType memoryType = MemoryType.Normal) : this(SCG.Comparer<K>.Default, EqualityComparer<K>.Default, memoryType) { }
+		public TreeDictionary(MemoryType memoryType = MemoryType.Normal) : this(SCG.Comparer<K>.Default, C5.EqualityComparer<K>.Default, memoryType) { }
 
         /// <summary>
         /// Create a red-black tree dictionary using an external comparer for keys.

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/199fab06/src/Lucene.Net/Support/TreeSet.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net/Support/TreeSet.cs b/src/Lucene.Net/Support/TreeSet.cs
index 559477f..f0d78c7 100644
--- a/src/Lucene.Net/Support/TreeSet.cs
+++ b/src/Lucene.Net/Support/TreeSet.cs
@@ -228,7 +228,7 @@ namespace Lucene.Net.Support
         /// </summary>
         /// <exception cref="NotComparableException">If <code>T</code> is not comparable.
         /// </exception>
-		public TreeSet(MemoryType memoryType = MemoryType.Normal) : this(SCG.Comparer<T>.Default, EqualityComparer<T>.Default, memoryType) { }
+		public TreeSet(MemoryType memoryType = MemoryType.Normal) : this(SCG.Comparer<T>.Default, C5.EqualityComparer<T>.Default, memoryType) { }
 
 
         /// <summary>

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/199fab06/src/Lucene.Net/Util/Fst/FST.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net/Util/Fst/FST.cs b/src/Lucene.Net/Util/Fst/FST.cs
index 8982395..c4053fd 100644
--- a/src/Lucene.Net/Util/Fst/FST.cs
+++ b/src/Lucene.Net/Util/Fst/FST.cs
@@ -362,7 +362,7 @@ namespace Lucene.Net.Util.Fst
             {
                 throw new InvalidOperationException("already finished");
             }
-            if (newStartNode == FST.FINAL_END_NODE && !EqualityComparer<T>.Default.Equals(emptyOutput, default(T)))
+            if (newStartNode == FST.FINAL_END_NODE && !Support.EqualityComparer<T>.Default.Equals(emptyOutput, default(T)))
             {
                 newStartNode = 0;
             }
@@ -514,7 +514,7 @@ namespace Lucene.Net.Util.Fst
             }
             // TODO: really we should encode this as an arc, arriving
             // to the root node, instead of special casing here:
-            if (!EqualityComparer<T>.Default.Equals(emptyOutput, default(T)))
+            if (!Support.EqualityComparer<T>.Default.Equals(emptyOutput, default(T)))
             {
                 // Accepts empty string
                 @out.WriteByte(1);
@@ -875,7 +875,7 @@ namespace Lucene.Net.Util.Fst
         /// </summary>
         public FST.Arc<T> GetFirstArc(FST.Arc<T> arc)
         {
-            if (!EqualityComparer<T>.Default.Equals(emptyOutput, default(T)))
+            if (!Support.EqualityComparer<T>.Default.Equals(emptyOutput, default(T)))
             {
                 arc.Flags = FST.BIT_FINAL_ARC | FST.BIT_LAST_ARC;
                 arc.NextFinalOutput = emptyOutput;
@@ -2053,7 +2053,7 @@ namespace Lucene.Net.Util.Fst
             fst.startNode = newNodeAddress.Get((int)startNode);
             //System.out.println("new startNode=" + fst.startNode + " old startNode=" + startNode);
 
-            if (!EqualityComparer<T>.Default.Equals(emptyOutput, default(T)))
+            if (!Support.EqualityComparer<T>.Default.Equals(emptyOutput, default(T)))
             {
                 fst.EmptyOutput = emptyOutput;
             }

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/199fab06/src/Lucene.Net/Util/PriorityQueue.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net/Util/PriorityQueue.cs b/src/Lucene.Net/Util/PriorityQueue.cs
index 36d5be5..391dd4f 100644
--- a/src/Lucene.Net/Util/PriorityQueue.cs
+++ b/src/Lucene.Net/Util/PriorityQueue.cs
@@ -88,7 +88,7 @@ namespace Lucene.Net.Util
             {
                 // If sentinel objects are supported, populate the queue with them
                 T sentinel = GetSentinelObject();
-                if (!EqualityComparer<T>.Default.Equals(sentinel, default(T)))
+                if (!Support.EqualityComparer<T>.Default.Equals(sentinel, default(T)))
                 {
                     heap[1] = sentinel;
                     for (int i = 2; i < heap.Length; i++)