diff --git a/src/main/java/leon/codegen/runtime/LeonCodeGenRuntimeHashing.java b/src/main/java/leon/codegen/runtime/LeonCodeGenRuntimeHashing.java
new file mode 100644
index 0000000000000000000000000000000000000000..5a919af148faf32bffaa6b5bbc3c44d10f3ed72e
--- /dev/null
+++ b/src/main/java/leon/codegen/runtime/LeonCodeGenRuntimeHashing.java
@@ -0,0 +1,43 @@
+package leon.codegen.runtime;
+
+// MurmurHash3, reproduced from std. Scala lib.
+public final class LeonCodeGenRuntimeHashing {
+  public static final int seqHash(Object[] elements, int seed) {
+    // I feel good about this line.
+    int h = avalanche(seed ^ 0xcafebabe);
+    int sz = elements.length;
+    if(sz == 0) return h;
+    for(int i = 0; i < sz; i++) {
+      h = mix(h, elements[i].hashCode());
+    }
+    return finalizeHash(h, sz);
+  }
+
+  private static final int mix(int hash, int data) {
+    int h = mixLast(hash, data);
+    h = Integer.rotateLeft(h, 13);
+    return h * 5 + 0xe6546b64;
+  }
+
+  private static final int mixLast(int hash, int data) {
+    int k = data;
+    k *= 0xcc9e2d51;
+    k  = Integer.rotateLeft(k, 15);
+    k *= 0x1b873593;
+    return hash ^ k;
+  }
+
+  private static final int finalizeHash(int hash, int length) {
+    return avalanche(hash ^ length);
+  }
+
+  private static final int avalanche(int hash) {
+    int h = hash;
+    h ^= h >>> 16;
+    h *= 0x85ebca6b;
+    h ^= h >>> 13;
+    h *= 0xc2b2ae35;
+    h ^= h >>> 16;
+    return h;
+  }
+}
diff --git a/src/main/java/leon/codegen/runtime/Map.java b/src/main/java/leon/codegen/runtime/Map.java
index cd9c2eb6aa428f762193b112640085d177913ee2..514a3e1b46a6c9f5364803bafb40fab3150cea8d 100644
--- a/src/main/java/leon/codegen/runtime/Map.java
+++ b/src/main/java/leon/codegen/runtime/Map.java
@@ -4,22 +4,22 @@ package leon.codegen.runtime;
 
 import java.util.Arrays;
 import java.util.Iterator;
-import java.util.TreeMap;
+import java.util.HashMap;
 
 /** If someone wants to make it an efficient implementation of immutable
  *  maps, go ahead. */
 public final class Map {
-  private final TreeMap<Object,Object> _underlying;
+  private final HashMap<Object,Object> _underlying;
 
-  protected final TreeMap<Object,Object> underlying() {
+  protected final HashMap<Object,Object> underlying() {
     return _underlying;
   }
 
   public Map() {
-    _underlying = new TreeMap<Object,Object>();
+    _underlying = new HashMap<Object,Object>();
   }
 
-  private Map(TreeMap<Object,Object> u) {
+  private Map(HashMap<Object,Object> u) {
     _underlying = u;
   }
 
@@ -49,7 +49,7 @@ public final class Map {
   }
 
   public Map union(Map s) {
-    TreeMap<Object,Object> n = new TreeMap<Object,Object>(_underlying);
+    HashMap<Object,Object> n = new HashMap<Object,Object>(_underlying);
     n.putAll(s.underlying());
     return new Map(n);
   }
diff --git a/src/main/java/leon/codegen/runtime/Set.java b/src/main/java/leon/codegen/runtime/Set.java
index f271679532f17817a347cabd4381f169f06d00cb..2bd466af8f8b437507c7d6e0c333dd13721e631f 100644
--- a/src/main/java/leon/codegen/runtime/Set.java
+++ b/src/main/java/leon/codegen/runtime/Set.java
@@ -4,23 +4,23 @@ package leon.codegen.runtime;
 
 import java.util.Arrays;
 import java.util.Iterator;
-import java.util.TreeSet;
+import java.util.HashSet;
 
 /** If someone wants to make it an efficient implementation of immutable
  *  sets, go ahead. */
 public final class Set {
-  private final TreeSet<Object> _underlying;
+  private final HashSet<Object> _underlying;
 
-  protected final TreeSet<Object> underlying() {
+  protected final HashSet<Object> underlying() {
     return _underlying;
   }
 
   public Set() {
-    _underlying = new TreeSet<Object>();
+    _underlying = new HashSet<Object>();
   }
 
   public Set(Object[] elements) {
-    _underlying = new TreeSet<Object>(Arrays.asList(elements));
+    _underlying = new HashSet<Object>(Arrays.asList(elements));
   }
 
   // Uses mutation! Useful at building time.
@@ -32,7 +32,7 @@ public final class Set {
     return _underlying.iterator();
   }
 
-  private Set(TreeSet<Object> u) {
+  private Set(HashSet<Object> u) {
     _underlying = u;
   }
 
@@ -54,13 +54,13 @@ public final class Set {
   }
 
   public Set union(Set s) {
-    TreeSet<Object> n = new TreeSet<Object>(_underlying);
+    HashSet<Object> n = new HashSet<Object>(_underlying);
     n.addAll(s.underlying());
     return new Set(n);
   }
 
   public Set intersect(Set s) {
-    TreeSet<Object> n = new TreeSet<Object>();
+    HashSet<Object> n = new HashSet<Object>();
     for(Object o : _underlying) {
       if(s.underlying().contains(o)) {
         n.add(o);
@@ -70,7 +70,7 @@ public final class Set {
   }
 
   public Set minus(Set s) {
-    TreeSet<Object> n = new TreeSet<Object>(_underlying);
+    HashSet<Object> n = new HashSet<Object>(_underlying);
     for(Object o : s.underlying()) {
       n.remove(o);
     }
diff --git a/src/main/java/leon/codegen/runtime/Tuple.java b/src/main/java/leon/codegen/runtime/Tuple.java
index 958a2340fc31b6789812adaacc8752b24e6631fb..ea1e0880559ee7084a1f3ff9c7295aed42955958 100644
--- a/src/main/java/leon/codegen/runtime/Tuple.java
+++ b/src/main/java/leon/codegen/runtime/Tuple.java
@@ -32,8 +32,18 @@ public final class Tuple {
     Tuple other = (Tuple)that;
     if(other.getArity() != this.getArity()) return false;
     for(int i = 0; i < this.getArity(); i++) {
-        if(other.get(i) != this.get(i)) return false;
+        if(!other.get(i).equals(this.get(i))) return false;
     }
     return true; 
   }
+
+  private int _hash = 0;
+  @Override
+  final public int hashCode() {
+    if(_hash != 0) return _hash;
+    int seed = (new String("Tuple" + getArity())).hashCode();
+    int h = LeonCodeGenRuntimeHashing.seqHash(elements, seed);
+    _hash = h;
+    return h;
+  }
 }
diff --git a/src/main/scala/leon/codegen/CodeGeneration.scala b/src/main/scala/leon/codegen/CodeGeneration.scala
index 80d55ab9eef90931627ac82d1fd8ff3dd775899d..5752b140b825bde0da19e4fe059322e00be8f16c 100644
--- a/src/main/scala/leon/codegen/CodeGeneration.scala
+++ b/src/main/scala/leon/codegen/CodeGeneration.scala
@@ -25,6 +25,7 @@ object CodeGeneration {
   private val CaseClassClass = "leon/codegen/runtime/CaseClass"
   private val ErrorClass     = "leon/codegen/runtime/LeonCodeGenRuntimeException"
   private val ImpossibleEvaluationClass = "leon/codegen/runtime/LeonCodeGenEvaluationException"
+  private val HashingClass   = "leon/codegen/runtime/LeonCodeGenRuntimeHashing"
 
   def defToJVMName(p : Program, d : Definition) : String = "Leon$CodeGen$" + d.id.uniqueName
 
@@ -645,6 +646,8 @@ object CodeGeneration {
 
     // definition of hashcode
     locally {
+      val hashFieldName = "$leon$hashCode"
+      cf.addField("I", hashFieldName).setFlags((FIELD_ACC_PRIVATE).asInstanceOf[U2])
       val hmh = cf.addMethod("I", "hashCode", "")
       hmh.setFlags((
         METHOD_ACC_PUBLIC |
@@ -652,8 +655,20 @@ object CodeGeneration {
       ).asInstanceOf[U2])
 
       val hch = hmh.codeHandler
-      // TODO FIXME. Look at Scala for inspiration.
-      hch << Ldc(42) << IRETURN
+      
+      val wasNotCached = hch.getFreshLabel("wasNotCached")
+
+      hch << ALoad(0) << GetField(cName, hashFieldName, "I") << DUP
+      hch << IfEq(wasNotCached)
+      hch << IRETURN
+      hch << Label(wasNotCached) << POP
+      hch << ALoad(0) << InvokeVirtual(cName, "productElements", "()[Ljava/lang/Object;")
+      hch << ALoad(0) << InvokeVirtual(cName, "productName", "()Ljava/lang/String;")
+      hch << InvokeVirtual("java/lang/String", "hashCode", "()I")
+      hch << InvokeStatic(HashingClass, "seqHash", "([Ljava/lang/Object;I)I") << DUP
+      hch << ALoad(0) << SWAP << PutField(cName, hashFieldName, "I") 
+      hch << IRETURN
+      
       hch.freeze
     }
 
diff --git a/src/test/scala/leon/test/evaluators/EvaluatorsTests.scala b/src/test/scala/leon/test/evaluators/EvaluatorsTests.scala
index 6cd6d9a88c96915eb1c2c7e90d1ef34209e5dd01..cda418e96a4b5c80f718622365f6253696e8eb7a 100644
--- a/src/test/scala/leon/test/evaluators/EvaluatorsTests.scala
+++ b/src/test/scala/leon/test/evaluators/EvaluatorsTests.scala
@@ -407,6 +407,28 @@ class EvaluatorsTests extends FunSuite {
     }
   }
 
+  test("Sets and maps of structures") {
+    val p = """|object Program {
+               |  case class MyPair(x : Int, y : Boolean)
+               |
+               |  def buildPairCC(x : Int, y : Boolean) : MyPair = MyPair(x,y)
+               |  def mkSingletonCC(p : MyPair) : Set[MyPair] = Set(p)
+               |  def containsCC(s : Set[MyPair], p : MyPair) : Boolean = s.contains(p)
+               |
+               |  def buildPairT(x : Int, y : Boolean) : (Int,Boolean) = (x,y)
+               |  def mkSingletonT(p : (Int,Boolean)) : Set[(Int,Boolean)] = Set(p)
+               |  def containsT(s : Set[(Int,Boolean)], p : (Int,Boolean)) : Boolean = s.contains(p)
+               |}""".stripMargin
+
+    implicit val progs = parseString(p)
+    val evaluators = prepareEvaluators
+
+    for(e <- evaluators) {
+      checkComp(e, mkCall("containsCC", mkCall("mkSingletonCC", mkCall("buildPairCC", IL(42), T)), mkCall("buildPairCC", IL(42), T)), T)
+      checkComp(e, mkCall("containsT", mkCall("mkSingletonT", mkCall("buildPairT", IL(42), T)), mkCall("buildPairT", IL(42), T)), T)
+    }
+  }
+
   test("Misc") {
     val p = """|object Program {
                |  import leon.Utils._