Fixed issue #1564: The set implementation should special-case PyUnicode instead of PyString
I moved the unicode_eq to stringlib/eq.h to keep the function static and possible inline for setobject.c and dictobject.h. I also removed the unused _PyString_Eq method. If it's required in the future it can be added to eq.h
diff --git a/Objects/setobject.c b/Objects/setobject.c
index f22268e..cd63968 100644
--- a/Objects/setobject.c
+++ b/Objects/setobject.c
@@ -9,6 +9,7 @@
 
 #include "Python.h"
 #include "structmember.h"
+#include "stringlib/eq.h"
 
 /* Set a key error with the specified argument, wrapping it in a
  * tuple automatically so that tuple keys are not unpacked as the
@@ -55,6 +56,7 @@
 static PySetObject *free_sets[MAXFREESETS];
 static int num_free_sets = 0;
 
+
 /*
 The basic lookup function used by all operations.
 This is based on Algorithm D from Knuth Vol. 3, Sec. 6.4.
@@ -144,12 +146,12 @@
 }
 
 /*
- * Hacked up version of set_lookkey which can assume keys are always strings;
- * This means we can always use _PyString_Eq directly and not have to check to
+ * Hacked up version of set_lookkey which can assume keys are always unicode;
+ * This means we can always use unicode_eq directly and not have to check to
  * see if the comparison altered the table.
  */
 static setentry *
-set_lookkey_string(PySetObject *so, PyObject *key, register long hash)
+set_lookkey_unicode(PySetObject *so, PyObject *key, register long hash)
 {
 	register Py_ssize_t i;
 	register size_t perturb;
@@ -158,11 +160,11 @@
 	setentry *table = so->table;
 	register setentry *entry;
 
-	/* Make sure this function doesn't have to handle non-string keys,
+	/* Make sure this function doesn't have to handle non-unicode keys,
 	   including subclasses of str; e.g., one reason to subclass
 	   strings is to override __eq__, and for speed we don't cater to
 	   that here. */
-	if (!PyString_CheckExact(key)) {
+	if (!PyUnicode_CheckExact(key)) {
 		so->lookup = set_lookkey;
 		return set_lookkey(so, key, hash);
 	}
@@ -173,7 +175,7 @@
 	if (entry->key == dummy)
 		freeslot = entry;
 	else {
-		if (entry->hash == hash && _PyString_Eq(entry->key, key))
+		if (entry->hash == hash && unicode_eq(entry->key, key))
 			return entry;
 		freeslot = NULL;
 	}
@@ -188,7 +190,7 @@
 		if (entry->key == key
 		    || (entry->hash == hash
 			&& entry->key != dummy
-			&& _PyString_Eq(entry->key, key)))
+			&& unicode_eq(entry->key, key)))
 			return entry;
 		if (entry->key == dummy && freeslot == NULL)
 			freeslot = entry;
@@ -375,8 +377,8 @@
 	register long hash;
 	register Py_ssize_t n_used;
 
-	if (!PyString_CheckExact(key) ||
-	    (hash = ((PyStringObject *) key)->ob_shash) == -1) {
+	if (!PyUnicode_CheckExact(key) ||
+	    (hash = ((PyUnicodeObject *) key)->hash) == -1) {
 		hash = PyObject_Hash(key);
 		if (hash == -1)
 			return -1;
@@ -422,8 +424,9 @@
 	PyObject *old_key;
 
 	assert (PyAnySet_Check(so));
-	if (!PyString_CheckExact(key) ||
-	    (hash = ((PyStringObject *) key)->ob_shash) == -1) {
+
+	if (!PyUnicode_CheckExact(key) ||
+	    (hash = ((PyUnicodeObject *) key)->hash) == -1) {
 		hash = PyObject_Hash(key);
 		if (hash == -1)
 			return -1;
@@ -668,8 +671,8 @@
 	long hash;
 	setentry *entry;
 
-	if (!PyString_CheckExact(key) ||
-	    (hash = ((PyStringObject *) key)->ob_shash) == -1) {
+	if (!PyUnicode_CheckExact(key) ||
+	    (hash = ((PyUnicodeObject *) key)->hash) == -1) {
 		hash = PyObject_Hash(key);
 		if (hash == -1)
 			return -1;
@@ -989,7 +992,7 @@
 		INIT_NONZERO_SET_SLOTS(so);
 	}
 
-	so->lookup = set_lookkey_string;
+	so->lookup = set_lookkey_unicode;
 	so->weakreflist = NULL;
 
 	if (iterable != NULL) {
@@ -1352,7 +1355,7 @@
 	while ((key = PyIter_Next(it)) != NULL) {
 		int rv;
 		setentry entry;
-		long hash = PyObject_Hash(key);
+		long hash = PyObject_Hash(key);;
 
 		if (hash == -1) {
 			Py_DECREF(key);