diff --git a/src/libsyntax_pos/span_encoding.rs b/src/libsyntax_pos/span_encoding.rs
index b23e40ce7a9..bf9a832519a 100644
--- a/src/libsyntax_pos/span_encoding.rs
+++ b/src/libsyntax_pos/span_encoding.rs
@@ -19,16 +19,37 @@ use hygiene::SyntaxContext;
 
 use rustc_data_structures::fx::FxHashMap;
 use std::cell::RefCell;
+use std::hash::{Hash, Hasher};
 
 /// A compressed span.
 /// Contains either fields of `SpanData` inline if they are small, or index into span interner.
 /// The primary goal of `Span` is to be as small as possible and fit into other structures
 /// (that's why it uses `packed` as well). Decoding speed is the second priority.
 /// See `SpanData` for the info on span fields in decoded representation.
-#[derive(Clone, Copy, PartialEq, Eq, Hash)]
 #[repr(packed)]
 pub struct Span(u32);
 
+impl Copy for Span {}
+impl Clone for Span {
+    fn clone(&self) -> Span {
+        *self
+    }
+}
+impl PartialEq for Span {
+    fn eq(&self, other: &Span) -> bool {
+        let a = self.0;
+        let b = other.0;
+        a == b
+    }
+}
+impl Eq for Span {}
+impl Hash for Span {
+    fn hash<H: Hasher>(&self, state: &mut H) {
+        let a = self.0;
+        a.hash(state)
+    }
+}
+
 /// Dummy span, both position and length are zero, syntax context is zero as well.
 /// This span is kept inline and encoded with format 0.
 pub const DUMMY_SP: Span = Span(0);