diff --git a/mk/cfg/arm-apple-ios b/mk/cfg/arm-apple-ios
index 6a66ff46a363e..d1f1ee6f3bdb4 100644
--- a/mk/cfg/arm-apple-ios
+++ b/mk/cfg/arm-apple-ios
@@ -13,7 +13,7 @@ CFG_LIB_NAME_arm-apple-ios = lib$(1).a
 CFG_LIB_GLOB_arm-apple-ios = lib$(1)-*.a
 CFG_STATIC_LIB_NAME_arm-apple-ios=lib$(1).a
 CFG_LIB_DSYM_GLOB_arm-apple-ios = lib$(1)-*.a.dSYM
-CFG_CFLAGS_arm-apple-ios := -arch armv7 -mfpu=vfp3 $(CFG_IOS_FLAGS)
+CFG_JEMALLOC_CFLAGS_arm-apple-ios := -arch armv7 -mfpu=vfp3 $(CFG_IOS_FLAGS)
 CFG_GCCISH_CFLAGS_arm-apple-ios := -Wall -Werror -g -fPIC $(CFG_IOS_FLAGS) -mfpu=vfp3 -arch armv7
 CFG_GCCISH_CXXFLAGS_arm-apple-ios := -fno-rtti $(CFG_IOS_FLAGS) -I$(CFG_IOS_SDK)/usr/include/c++/4.2.1
 CFG_GCCISH_LINK_FLAGS_arm-apple-ios := -lpthread -syslibroot $(CFG_IOS_SDK) -Wl,-no_compact_unwind
diff --git a/mk/cfg/arm-linux-androideabi b/mk/cfg/arm-linux-androideabi
index e24a805b416e8..471220e2b6618 100644
--- a/mk/cfg/arm-linux-androideabi
+++ b/mk/cfg/arm-linux-androideabi
@@ -7,7 +7,7 @@ CFG_LIB_NAME_arm-linux-androideabi=lib$(1).so
 CFG_STATIC_LIB_NAME_arm-linux-androideabi=lib$(1).a
 CFG_LIB_GLOB_arm-linux-androideabi=lib$(1)-*.so
 CFG_LIB_DSYM_GLOB_arm-linux-androideabi=lib$(1)-*.dylib.dSYM
-CFG_CFLAGS_arm-linux-androideabi := -D__arm__ -DANDROID -D__ANDROID__ $(CFLAGS)
+CFG_JEMALLOC_CFLAGS_arm-linux-androideabi := -D__arm__ -DANDROID -D__ANDROID__ $(CFLAGS)
 CFG_GCCISH_CFLAGS_arm-linux-androideabi := -Wall -g -fPIC -D__arm__ -DANDROID -D__ANDROID__ $(CFLAGS)
 CFG_GCCISH_CXXFLAGS_arm-linux-androideabi := -fno-rtti $(CXXFLAGS)
 CFG_GCCISH_LINK_FLAGS_arm-linux-androideabi := -shared -fPIC -ldl -g -lm -lsupc++
diff --git a/mk/cfg/arm-unknown-linux-gnueabi b/mk/cfg/arm-unknown-linux-gnueabi
index 4b7b9ad87ca3a..b4c604b26bae0 100644
--- a/mk/cfg/arm-unknown-linux-gnueabi
+++ b/mk/cfg/arm-unknown-linux-gnueabi
@@ -8,7 +8,7 @@ CFG_LIB_NAME_arm-unknown-linux-gnueabi=lib$(1).so
 CFG_STATIC_LIB_NAME_arm-unknown-linux-gnueabi=lib$(1).a
 CFG_LIB_GLOB_arm-unknown-linux-gnueabi=lib$(1)-*.so
 CFG_LIB_DSYM_GLOB_arm-unknown-linux-gnueabi=lib$(1)-*.dylib.dSYM
-CFG_CFLAGS_arm-unknown-linux-gnueabi := -D__arm__ -mfpu=vfp $(CFLAGS)
+CFG_JEMALLOC_CFLAGS_arm-unknown-linux-gnueabi := -D__arm__ -mfpu=vfp $(CFLAGS)
 CFG_GCCISH_CFLAGS_arm-unknown-linux-gnueabi := -Wall -g -fPIC -D__arm__ -mfpu=vfp $(CFLAGS)
 CFG_GCCISH_CXXFLAGS_arm-unknown-linux-gnueabi := -fno-rtti $(CXXFLAGS)
 CFG_GCCISH_LINK_FLAGS_arm-unknown-linux-gnueabi := -shared -fPIC -g
diff --git a/mk/cfg/arm-unknown-linux-gnueabihf b/mk/cfg/arm-unknown-linux-gnueabihf
index 535dce6b9f3e4..4f02de0f6b5e6 100644
--- a/mk/cfg/arm-unknown-linux-gnueabihf
+++ b/mk/cfg/arm-unknown-linux-gnueabihf
@@ -8,7 +8,7 @@ CFG_LIB_NAME_arm-unknown-linux-gnueabihf=lib$(1).so
 CFG_STATIC_LIB_NAME_arm-unknown-linux-gnueabihf=lib$(1).a
 CFG_LIB_GLOB_arm-unknown-linux-gnueabihf=lib$(1)-*.so
 CFG_LIB_DSYM_GLOB_arm-unknown-linux-gnueabihf=lib$(1)-*.dylib.dSYM
-CFG_CFLAGS_arm-unknown-linux-gnueabihf := -D__arm__ $(CFLAGS)
+CFG_JEMALLOC_CFLAGS_arm-unknown-linux-gnueabihf := -D__arm__ $(CFLAGS)
 CFG_GCCISH_CFLAGS_arm-unknown-linux-gnueabihf := -Wall -g -fPIC -D__arm__ $(CFLAGS)
 CFG_GCCISH_CXXFLAGS_arm-unknown-linux-gnueabihf := -fno-rtti $(CXXFLAGS)
 CFG_GCCISH_LINK_FLAGS_arm-unknown-linux-gnueabihf := -shared -fPIC -g
diff --git a/mk/cfg/i386-apple-ios b/mk/cfg/i386-apple-ios
index 0e0d2724ddbc4..63eb590c6e4f6 100644
--- a/mk/cfg/i386-apple-ios
+++ b/mk/cfg/i386-apple-ios
@@ -13,7 +13,6 @@ CFG_LIB_NAME_i386-apple-ios = lib$(1).a
 CFG_LIB_GLOB_i386-apple-ios = lib$(1)-*.dylib
 CFG_STATIC_LIB_NAME_i386-apple-ios=lib$(1).a
 CFG_LIB_DSYM_GLOB_i386-apple-ios = lib$(1)-*.dylib.dSYM
-CFG_CFLAGS_i386-apple-ios = $(CFG_IOSSIM_FLAGS)
 CFG_GCCISH_CFLAGS_i386-apple-ios = -Wall -Werror -g -fPIC -m32 $(CFG_IOSSIM_FLAGS)
 CFG_GCCISH_CXXFLAGS_i386-apple-ios = -fno-rtti $(CFG_IOSSIM_FLAGS) -I$(CFG_IOSSIM_SDK)/usr/include/c++/4.2.1
 CFG_GCCISH_LINK_FLAGS_i386-apple-ios = -lpthread -Wl,-no_compact_unwind -m32 -Wl,-syslibroot $(CFG_IOSSIM_SDK)
@@ -30,5 +29,5 @@ CFG_PATH_MUNGE_i386-apple-ios = true
 CFG_LDPATH_i386-apple-ios =
 CFG_RUN_i386-apple-ios = $(2)
 CFG_RUN_TARG_i386-apple-ios = $(call CFG_RUN_i386-apple-ios,,$(2))
-CFG_JEMALLOC_CFLAGS_i386-apple-ios = -target i386-apple-ios -Wl,-syslibroot $(CFG_IOSSIM_SDK) -Wl,-no_compact_unwind
+CFG_JEMALLOC_CFLAGS_i386-apple-ios = $(CFG_IOSSIM_FLAGS) -target i386-apple-ios -Wl,-syslibroot $(CFG_IOSSIM_SDK) -Wl,-no_compact_unwind
 CFG_GNU_TRIPLE_i386-apple-ios := i386-apple-ios
diff --git a/mk/cfg/i686-apple-darwin b/mk/cfg/i686-apple-darwin
index 97ab0b31f6341..e935ce053e02a 100644
--- a/mk/cfg/i686-apple-darwin
+++ b/mk/cfg/i686-apple-darwin
@@ -7,7 +7,7 @@ CFG_LIB_NAME_i686-apple-darwin=lib$(1).dylib
 CFG_STATIC_LIB_NAME_i686-apple-darwin=lib$(1).a
 CFG_LIB_GLOB_i686-apple-darwin=lib$(1)-*.dylib
 CFG_LIB_DSYM_GLOB_i686-apple-darwin=lib$(1)-*.dylib.dSYM
-CFG_CFLAGS_i686-apple-darwin := -m32 -arch i386 $(CFLAGS)
+CFG_JEMALLOC_CFLAGS_i686-apple-darwin := -m32 -arch i386 $(CFLAGS)
 CFG_GCCISH_CFLAGS_i686-apple-darwin := -Wall -Werror -g -fPIC -m32 -arch i386 $(CFLAGS)
 CFG_GCCISH_CXXFLAGS_i686-apple-darwin := -fno-rtti $(CXXFLAGS)
 CFG_GCCISH_LINK_FLAGS_i686-apple-darwin := -dynamiclib -pthread  -framework CoreServices -m32
diff --git a/mk/cfg/i686-pc-windows-gnu b/mk/cfg/i686-pc-windows-gnu
index 52ed733e4434c..ecb405b76f010 100644
--- a/mk/cfg/i686-pc-windows-gnu
+++ b/mk/cfg/i686-pc-windows-gnu
@@ -8,7 +8,7 @@ CFG_LIB_NAME_i686-pc-windows-gnu=$(1).dll
 CFG_STATIC_LIB_NAME_i686-pc-windows-gnu=$(1).lib
 CFG_LIB_GLOB_i686-pc-windows-gnu=$(1)-*.dll
 CFG_LIB_DSYM_GLOB_i686-pc-windows-gnu=$(1)-*.dylib.dSYM
-CFG_CFLAGS_i686-pc-windows-gnu := -march=i686 -m32 -D_WIN32_WINNT=0x0600 $(CFLAGS)
+CFG_JEMALLOC_CFLAGS_i686-pc-windows-gnu := -march=i686 -m32 -D_WIN32_WINNT=0x0600 $(CFLAGS)
 CFG_GCCISH_CFLAGS_i686-pc-windows-gnu := -Wall -Werror -g -m32 -D_WIN32_WINNT=0x0600 $(CFLAGS)
 CFG_GCCISH_CXXFLAGS_i686-pc-windows-gnu := -fno-rtti $(CXXFLAGS)
 CFG_GCCISH_LINK_FLAGS_i686-pc-windows-gnu := -shared -g -m32
diff --git a/mk/cfg/i686-unknown-linux-gnu b/mk/cfg/i686-unknown-linux-gnu
index 76ed56d145b14..1cc9c143e8d47 100644
--- a/mk/cfg/i686-unknown-linux-gnu
+++ b/mk/cfg/i686-unknown-linux-gnu
@@ -7,7 +7,7 @@ CFG_LIB_NAME_i686-unknown-linux-gnu=lib$(1).so
 CFG_STATIC_LIB_NAME_i686-unknown-linux-gnu=lib$(1).a
 CFG_LIB_GLOB_i686-unknown-linux-gnu=lib$(1)-*.so
 CFG_LIB_DSYM_GLOB_i686-unknown-linux-gnu=lib$(1)-*.dylib.dSYM
-CFG_CFLAGS_i686-unknown-linux-gnu := -m32 $(CFLAGS)
+CFG_JEMALLOC_CFLAGS_i686-unknown-linux-gnu := -m32 $(CFLAGS)
 CFG_GCCISH_CFLAGS_i686-unknown-linux-gnu := -Wall -Werror -g -fPIC -m32 $(CFLAGS)
 CFG_GCCISH_CXXFLAGS_i686-unknown-linux-gnu := -fno-rtti $(CXXFLAGS)
 CFG_GCCISH_LINK_FLAGS_i686-unknown-linux-gnu := -shared -fPIC -ldl -pthread  -lrt -g -m32
diff --git a/mk/cfg/mips-unknown-linux-gnu b/mk/cfg/mips-unknown-linux-gnu
index 1caecec93d15d..c5d84966f8526 100644
--- a/mk/cfg/mips-unknown-linux-gnu
+++ b/mk/cfg/mips-unknown-linux-gnu
@@ -7,7 +7,7 @@ CFG_LIB_NAME_mips-unknown-linux-gnu=lib$(1).so
 CFG_STATIC_LIB_NAME_mips-unknown-linux-gnu=lib$(1).a
 CFG_LIB_GLOB_mips-unknown-linux-gnu=lib$(1)-*.so
 CFG_LIB_DSYM_GLOB_mips-unknown-linux-gnu=lib$(1)-*.dylib.dSYM
-CFG_CFLAGS_mips-unknown-linux-gnu := -mips32r2 -msoft-float -mabi=32 -mno-compact-eh $(CFLAGS)
+CFG_JEMALLOC_CFLAGS_mips-unknown-linux-gnu := -mips32r2 -msoft-float -mabi=32 -mno-compact-eh $(CFLAGS)
 CFG_GCCISH_CFLAGS_mips-unknown-linux-gnu := -Wall -g -fPIC -mips32r2 -msoft-float -mabi=32 -mno-compact-eh $(CFLAGS)
 CFG_GCCISH_CXXFLAGS_mips-unknown-linux-gnu := -fno-rtti $(CXXFLAGS)
 CFG_GCCISH_LINK_FLAGS_mips-unknown-linux-gnu := -shared -fPIC -g -mips32r2 -msoft-float -mabi=32
diff --git a/mk/cfg/mipsel-unknown-linux-gnu b/mk/cfg/mipsel-unknown-linux-gnu
index d761d5dd090c3..eb2f300abffd8 100644
--- a/mk/cfg/mipsel-unknown-linux-gnu
+++ b/mk/cfg/mipsel-unknown-linux-gnu
@@ -7,7 +7,7 @@ CFG_LIB_NAME_mipsel-unknown-linux-gnu=lib$(1).so
 CFG_STATIC_LIB_NAME_mipsel-unknown-linux-gnu=lib$(1).a
 CFG_LIB_GLOB_mipsel-unknown-linux-gnu=lib$(1)-*.so
 CFG_LIB_DSYM_GLOB_mipsel-unknown-linux-gnu=lib$(1)-*.dylib.dSYM
-CFG_CFLAGS_mipsel-unknown-linux-gnu := -mips32 -mabi=32 $(CFLAGS)
+CFG_JEMALLOC_CFLAGS_mipsel-unknown-linux-gnu := -mips32 -mabi=32 $(CFLAGS)
 CFG_GCCISH_CFLAGS_mipsel-unknown-linux-gnu := -Wall -g -fPIC -mips32 -mabi=32 $(CFLAGS)
 CFG_GCCISH_CXXFLAGS_mipsel-unknown-linux-gnu := -fno-rtti $(CXXFLAGS)
 CFG_GCCISH_LINK_FLAGS_mipsel-unknown-linux-gnu := -shared -fPIC -g -mips32
diff --git a/mk/cfg/x86_64-apple-darwin b/mk/cfg/x86_64-apple-darwin
index 5da7c928da9bc..dbd67542ab75a 100644
--- a/mk/cfg/x86_64-apple-darwin
+++ b/mk/cfg/x86_64-apple-darwin
@@ -7,7 +7,7 @@ CFG_LIB_NAME_x86_64-apple-darwin=lib$(1).dylib
 CFG_STATIC_LIB_NAME_x86_64-apple-darwin=lib$(1).a
 CFG_LIB_GLOB_x86_64-apple-darwin=lib$(1)-*.dylib
 CFG_LIB_DSYM_GLOB_x86_64-apple-darwin=lib$(1)-*.dylib.dSYM
-CFG_CFLAGS_x86_64-apple-darwin := -m64 -arch x86_64 $(CFLAGS)
+CFG_JEMALLOC_CFLAGS_x86_64-apple-darwin := -m64 -arch x86_64 $(CFLAGS)
 CFG_GCCISH_CFLAGS_x86_64-apple-darwin := -Wall -Werror -g -fPIC -m64 -arch x86_64 $(CFLAGS)
 CFG_GCCISH_CXXFLAGS_x86_64-apple-darwin := -fno-rtti $(CXXFLAGS)
 CFG_GCCISH_LINK_FLAGS_x86_64-apple-darwin := -dynamiclib -pthread  -framework CoreServices -m64
diff --git a/mk/cfg/x86_64-pc-windows-gnu b/mk/cfg/x86_64-pc-windows-gnu
index 14ebdf5c39091..a23e292c7bd5d 100644
--- a/mk/cfg/x86_64-pc-windows-gnu
+++ b/mk/cfg/x86_64-pc-windows-gnu
@@ -8,7 +8,7 @@ CFG_LIB_NAME_x86_64-pc-windows-gnu=$(1).dll
 CFG_STATIC_LIB_NAME_x86_64-pc-windows-gnu=$(1).lib
 CFG_LIB_GLOB_x86_64-pc-windows-gnu=$(1)-*.dll
 CFG_LIB_DSYM_GLOB_x86_64-pc-windows-gnu=$(1)-*.dylib.dSYM
-CFG_CFLAGS_x86_64-pc-windows-gnu := -m64 -D_WIN32_WINNT=0x0600 $(CFLAGS)
+CFG_JEMALLOC_CFLAGS_x86_64-pc-windows-gnu := -m64 -D_WIN32_WINNT=0x0600 $(CFLAGS)
 CFG_GCCISH_CFLAGS_x86_64-pc-windows-gnu := -Wall -Werror -g -m64 -D_WIN32_WINNT=0x0600 $(CFLAGS)
 CFG_GCCISH_CXXFLAGS_x86_64-pc-windows-gnu := -fno-rtti $(CXXFLAGS)
 CFG_GCCISH_LINK_FLAGS_x86_64-pc-windows-gnu := -shared -g -m64
diff --git a/mk/cfg/x86_64-unknown-dragonfly b/mk/cfg/x86_64-unknown-dragonfly
index 50928d3c20e21..05414c79dd78e 100644
--- a/mk/cfg/x86_64-unknown-dragonfly
+++ b/mk/cfg/x86_64-unknown-dragonfly
@@ -7,7 +7,7 @@ CFG_LIB_NAME_x86_64-unknown-dragonfly=lib$(1).so
 CFG_STATIC_LIB_NAME_x86_64-unknown-dragonfly=lib$(1).a
 CFG_LIB_GLOB_x86_64-unknown-dragonfly=lib$(1)-*.so
 CFG_LIB_DSYM_GLOB_x86_64-unknown-dragonfly=$(1)-*.dylib.dSYM
-CFG_CFLAGS_x86_64-unknown-dragonfly := -I/usr/include -I/usr/local/include $(CFLAGS)
+CFG_JEMALLOC_CFLAGS_x86_64-unknown-dragonfly := -I/usr/include -I/usr/local/include $(CFLAGS)
 CFG_GCCISH_CFLAGS_x86_64-unknown-dragonfly := -Wall -Werror -g -fPIC -I/usr/include -I/usr/local/include $(CFLAGS)
 CFG_GCCISH_LINK_FLAGS_x86_64-unknown-dragonfly := -shared -fPIC -g -pthread  -lrt
 CFG_GCCISH_DEF_FLAG_x86_64-unknown-dragonfly := -Wl,--export-dynamic,--dynamic-list=
diff --git a/mk/cfg/x86_64-unknown-freebsd b/mk/cfg/x86_64-unknown-freebsd
index 1926c9873b7f1..4e847ea78a717 100644
--- a/mk/cfg/x86_64-unknown-freebsd
+++ b/mk/cfg/x86_64-unknown-freebsd
@@ -7,7 +7,7 @@ CFG_LIB_NAME_x86_64-unknown-freebsd=lib$(1).so
 CFG_STATIC_LIB_NAME_x86_64-unknown-freebsd=lib$(1).a
 CFG_LIB_GLOB_x86_64-unknown-freebsd=lib$(1)-*.so
 CFG_LIB_DSYM_GLOB_x86_64-unknown-freebsd=$(1)-*.dylib.dSYM
-CFG_CFLAGS_x86_64-unknown-freebsd := -I/usr/local/include $(CFLAGS)
+CFG_JEMALLOC_CFLAGS_x86_64-unknown-freebsd := -I/usr/local/include $(CFLAGS)
 CFG_GCCISH_CFLAGS_x86_64-unknown-freebsd := -Wall -Werror -g -fPIC -I/usr/local/include $(CFLAGS)
 CFG_GCCISH_LINK_FLAGS_x86_64-unknown-freebsd := -shared -fPIC -g -pthread  -lrt
 CFG_GCCISH_DEF_FLAG_x86_64-unknown-freebsd := -Wl,--export-dynamic,--dynamic-list=
diff --git a/mk/cfg/x86_64-unknown-linux-gnu b/mk/cfg/x86_64-unknown-linux-gnu
index 5f165ade3a7cb..845f9c1c52d19 100644
--- a/mk/cfg/x86_64-unknown-linux-gnu
+++ b/mk/cfg/x86_64-unknown-linux-gnu
@@ -7,7 +7,7 @@ CFG_LIB_NAME_x86_64-unknown-linux-gnu=lib$(1).so
 CFG_STATIC_LIB_NAME_x86_64-unknown-linux-gnu=lib$(1).a
 CFG_LIB_GLOB_x86_64-unknown-linux-gnu=lib$(1)-*.so
 CFG_LIB_DSYM_GLOB_x86_64-unknown-linux-gnu=lib$(1)-*.dylib.dSYM
-CFG_CFLAGS_x86_64-unknown-linux-gnu := -m64
+CFG_JEMALLOC_CFLAGS_x86_64-unknown-linux-gnu := -m64
 CFG_GCCISH_CFLAGS_x86_64-unknown-linux-gnu := -Wall -Werror -g -fPIC -m64
 CFG_GCCISH_CXXFLAGS_x86_64-unknown-linux-gnu := -fno-rtti
 CFG_GCCISH_LINK_FLAGS_x86_64-unknown-linux-gnu := -shared -fPIC -ldl -pthread  -lrt -g -m64
diff --git a/mk/rt.mk b/mk/rt.mk
index 7204808c30a3b..a7d6a6e825fbc 100644
--- a/mk/rt.mk
+++ b/mk/rt.mk
@@ -177,11 +177,11 @@ $$(JEMALLOC_LOCAL_$(1)): $$(JEMALLOC_DEPS) $$(MKFILE_DEPS)
 	cd "$$(JEMALLOC_BUILD_DIR_$(1))"; "$(S)src/jemalloc/configure" \
 		$$(JEMALLOC_ARGS_$(1)) --with-jemalloc-prefix=je_ $(CFG_JEMALLOC_FLAGS) \
 		--build=$$(CFG_GNU_TRIPLE_$(CFG_BUILD)) --host=$$(CFG_GNU_TRIPLE_$(1)) \
-		CC="$$(CC_$(1))" \
+		CC="$$(CC_$(1)) $$(CFG_JEMALLOC_CFLAGS_$(1))" \
 		AR="$$(AR_$(1))" \
 		RANLIB="$$(AR_$(1)) s" \
 		CPPFLAGS="-I $(S)src/rt/" \
-		EXTRA_CFLAGS="$$(CFG_CFLAGS_$(1)) $$(CFG_JEMALLOC_CFLAGS_$(1)) -g1"
+		EXTRA_CFLAGS="-g1"
 	$$(Q)$$(MAKE) -C "$$(JEMALLOC_BUILD_DIR_$(1))" build_lib_static
 
 ifeq ($$(CFG_DISABLE_JEMALLOC),)
diff --git a/src/doc/reference.md b/src/doc/reference.md
index f31f28d6c08ce..171c39a4cbc39 100644
--- a/src/doc/reference.md
+++ b/src/doc/reference.md
@@ -304,8 +304,8 @@ r##"foo #"# bar"##;                // foo #"# bar
 #### Byte and byte string literals
 
 ```{.ebnf .gram}
-byte_lit : 'b' '\x27' byte_body '\x27' ;
-byte_string_lit : 'b' '"' string_body * '"' | 'b' 'r' raw_byte_string ;
+byte_lit : "b\x27" byte_body '\x27' ;
+byte_string_lit : "b\x22" string_body * '\x22' | "br" raw_byte_string ;
 
 byte_body : ascii_non_single_quote
           | '\x5c' [ '\x27' | common_escape ] ;
@@ -381,10 +381,10 @@ num_suffix : int_suffix | float_suffix ;
 
 int_suffix : 'u' int_suffix_size ?
            | 'i' int_suffix_size ? ;
-int_suffix_size : [ '8' | '1' '6' | '3' '2' | '6' '4' ] ;
+int_suffix_size : [ '8' | "16" | "32" | "64" ] ;
 
 float_suffix : [ exponent | '.' dec_lit exponent ? ] ? float_suffix_ty ? ;
-float_suffix_ty : 'f' [ '3' '2' | '6' '4' ] ;
+float_suffix_ty : 'f' [ "32" | "64" ] ;
 exponent : ['E' | 'e'] ['-' | '+' ] ? dec_lit ;
 dec_lit : [ dec_digit | '_' ] + ;
 ```
@@ -1862,7 +1862,7 @@ the namespace hierarchy as it normally would.
 ## Attributes
 
 ```{.ebnf .gram}
-attribute : '#' '!' ? '[' meta_item ']' ;
+attribute : "#!" ? '[' meta_item ']' ;
 meta_item : ident [ '=' literal
                   | '(' meta_seq ')' ] ? ;
 meta_seq : meta_item [ ',' meta_seq ] ? ;
diff --git a/src/grammar/verify.rs b/src/grammar/verify.rs
index a4641c40165ac..159a62f011072 100644
--- a/src/grammar/verify.rs
+++ b/src/grammar/verify.rs
@@ -178,7 +178,7 @@ fn parse_antlr_token(s: &str, tokens: &HashMap<String, Token>) -> TokenAndSpan {
     let toknum = m.name("toknum");
     let content = m.name("content");
 
-    let proto_tok = tokens.find_equiv(&toknum).expect(format!("didn't find token {} in the map",
+    let proto_tok = tokens.get(&toknum).expect(format!("didn't find token {} in the map",
                                                               toknum).as_slice());
 
     let nm = parse::token::intern(content);
diff --git a/src/libcollections/bit.rs b/src/libcollections/bit.rs
index 76b929746d653..0529bb8904ab9 100644
--- a/src/libcollections/bit.rs
+++ b/src/libcollections/bit.rs
@@ -283,7 +283,7 @@ impl Bitv {
         x != 0
     }
 
-    /// Sets the value of a bit at a index `i`.
+    /// Sets the value of a bit at an index `i`.
     ///
     /// # Panics
     ///
@@ -582,7 +582,7 @@ impl Bitv {
     ///
     /// # Panics
     ///
-    /// Panics if the the `Bitv` and slice are of different length.
+    /// Panics if the `Bitv` and slice are of different length.
     ///
     /// # Example
     ///
diff --git a/src/libcollections/btree/map.rs b/src/libcollections/btree/map.rs
index 0b6d9e356b910..adb9a9ae5bd3d 100644
--- a/src/libcollections/btree/map.rs
+++ b/src/libcollections/btree/map.rs
@@ -21,6 +21,7 @@ use core::prelude::*;
 
 use self::StackOp::*;
 use super::node::*;
+use core::borrow::BorrowFrom;
 use std::hash::{Writer, Hash};
 use core::default::Default;
 use core::{iter, fmt, mem};
@@ -56,7 +57,7 @@ use ring_buf::RingBuf;
 /// and possibly other factors. Using linear search, searching for a random element is expected
 /// to take O(B log<sub>B</sub>n) comparisons, which is generally worse than a BST. In practice,
 /// however, performance is excellent. `BTreeMap` is able to readily outperform `TreeMap` under
-/// many workloads, and is competetive where it doesn't. BTreeMap also generally *scales* better
+/// many workloads, and is competitive where it doesn't. BTreeMap also generally *scales* better
 /// than TreeMap, making it more appropriate for large datasets.
 ///
 /// However, `TreeMap` may still be more appropriate to use in many contexts. If elements are very
@@ -184,6 +185,9 @@ impl<K: Ord, V> BTreeMap<K, V> {
 
     /// Returns a reference to the value corresponding to the key.
     ///
+    /// The key may be any borrowed form of the map's key type, but the ordering
+    /// on the borrowed form *must* match the ordering on the key type.
+    ///
     /// # Example
     ///
     /// ```
@@ -195,7 +199,7 @@ impl<K: Ord, V> BTreeMap<K, V> {
     /// assert_eq!(map.get(&2), None);
     /// ```
     #[unstable = "matches collection reform specification, waiting for dust to settle"]
-    pub fn get(&self, key: &K) -> Option<&V> {
+    pub fn get<Sized? Q>(&self, key: &Q) -> Option<&V> where Q: BorrowFrom<K> + Ord {
         let mut cur_node = &self.root;
         loop {
             match cur_node.search(key) {
@@ -213,6 +217,9 @@ impl<K: Ord, V> BTreeMap<K, V> {
 
     /// Returns true if the map contains a value for the specified key.
     ///
+    /// The key may be any borrowed form of the map's key type, but the ordering
+    /// on the borrowed form *must* match the ordering on the key type.
+    ///
     /// # Example
     ///
     /// ```
@@ -224,7 +231,7 @@ impl<K: Ord, V> BTreeMap<K, V> {
     /// assert_eq!(map.contains_key(&2), false);
     /// ```
     #[unstable = "matches collection reform specification, waiting for dust to settle"]
-    pub fn contains_key(&self, key: &K) -> bool {
+    pub fn contains_key<Sized? Q>(&self, key: &Q) -> bool where Q: BorrowFrom<K> + Ord {
         self.get(key).is_some()
     }
 
@@ -236,6 +243,9 @@ impl<K: Ord, V> BTreeMap<K, V> {
 
     /// Returns a mutable reference to the value corresponding to the key.
     ///
+    /// The key may be any borrowed form of the map's key type, but the ordering
+    /// on the borrowed form *must* match the ordering on the key type.
+    ///
     /// # Example
     ///
     /// ```
@@ -251,7 +261,7 @@ impl<K: Ord, V> BTreeMap<K, V> {
     /// ```
     // See `get` for implementation notes, this is basically a copy-paste with mut's added
     #[unstable = "matches collection reform specification, waiting for dust to settle"]
-    pub fn get_mut(&mut self, key: &K) -> Option<&mut V> {
+    pub fn get_mut<Sized? Q>(&mut self, key: &Q) -> Option<&mut V> where Q: BorrowFrom<K> + Ord {
         // temp_node is a Borrowck hack for having a mutable value outlive a loop iteration
         let mut temp_node = &mut self.root;
         loop {
@@ -410,6 +420,9 @@ impl<K: Ord, V> BTreeMap<K, V> {
     /// Removes a key from the map, returning the value at the key if the key
     /// was previously in the map.
     ///
+    /// The key may be any borrowed form of the map's key type, but the ordering
+    /// on the borrowed form *must* match the ordering on the key type.
+    ///
     /// # Example
     ///
     /// ```
@@ -421,7 +434,7 @@ impl<K: Ord, V> BTreeMap<K, V> {
     /// assert_eq!(map.remove(&1), None);
     /// ```
     #[unstable = "matches collection reform specification, waiting for dust to settle"]
-    pub fn remove(&mut self, key: &K) -> Option<V> {
+    pub fn remove<Sized? Q>(&mut self, key: &Q) -> Option<V> where Q: BorrowFrom<K> + Ord {
         // See `swap` for a more thorough description of the stuff going on in here
         let mut stack = stack::PartialSearchStack::new(self);
         loop {
@@ -790,14 +803,18 @@ impl<K: Show, V: Show> Show for BTreeMap<K, V> {
     }
 }
 
-impl<K: Ord, V> Index<K, V> for BTreeMap<K, V> {
-    fn index(&self, key: &K) -> &V {
+impl<K: Ord, Sized? Q, V> Index<Q, V> for BTreeMap<K, V>
+    where Q: BorrowFrom<K> + Ord
+{
+    fn index(&self, key: &Q) -> &V {
         self.get(key).expect("no entry found for key")
     }
 }
 
-impl<K: Ord, V> IndexMut<K, V> for BTreeMap<K, V> {
-    fn index_mut(&mut self, key: &K) -> &mut V {
+impl<K: Ord, Sized? Q, V> IndexMut<Q, V> for BTreeMap<K, V>
+    where Q: BorrowFrom<K> + Ord
+{
+    fn index_mut(&mut self, key: &Q) -> &mut V {
         self.get_mut(key).expect("no entry found for key")
     }
 }
diff --git a/src/libcollections/btree/node.rs b/src/libcollections/btree/node.rs
index 6e9341231ad69..b40ff35cca1c6 100644
--- a/src/libcollections/btree/node.rs
+++ b/src/libcollections/btree/node.rs
@@ -19,6 +19,7 @@ use core::prelude::*;
 
 use core::{slice, mem, ptr};
 use core::iter::Zip;
+use core::borrow::BorrowFrom;
 
 use vec;
 use vec::Vec;
@@ -47,7 +48,7 @@ pub struct Node<K, V> {
     // theory, if we take full control of allocation like HashMap's RawTable does,
     // and restrict leaves to max size 256 (not unreasonable for a btree node) we can cut
     // this down to just (ptr, cap: u8, size: u8, is_leaf: bool). With generic
-    // integer arguments, cap can even move into the the type, reducing this just to
+    // integer arguments, cap can even move into the type, reducing this just to
     // (ptr, size, is_leaf). This could also have cache benefits for very small nodes, as keys
     // could bleed into edges and vals.
     //
@@ -73,19 +74,19 @@ impl<K: Ord, V> Node<K, V> {
     /// Searches for the given key in the node. If it finds an exact match,
     /// `Found` will be yielded with the matching index. If it doesn't find an exact match,
     /// `GoDown` will be yielded with the index of the subtree the key must lie in.
-    pub fn search(&self, key: &K) -> SearchResult {
+    pub fn search<Sized? Q>(&self, key: &Q) -> SearchResult where Q: BorrowFrom<K> + Ord {
         // FIXME(Gankro): Tune when to search linear or binary based on B (and maybe K/V).
         // For the B configured as of this writing (B = 6), binary search was *significantly*
         // worse for uints.
         self.search_linear(key)
     }
 
-    fn search_linear(&self, key: &K) -> SearchResult {
+    fn search_linear<Sized? Q>(&self, key: &Q) -> SearchResult where Q: BorrowFrom<K> + Ord {
         for (i, k) in self.keys.iter().enumerate() {
-            match k.cmp(key) {
-                Less => {},
+            match key.cmp(BorrowFrom::borrow_from(k)) {
+                Greater => {},
                 Equal => return Found(i),
-                Greater => return GoDown(i),
+                Less => return GoDown(i),
             }
         }
         GoDown(self.len())
diff --git a/src/libcollections/btree/set.rs b/src/libcollections/btree/set.rs
index 56edf7719bb22..64ae4f6a50867 100644
--- a/src/libcollections/btree/set.rs
+++ b/src/libcollections/btree/set.rs
@@ -15,6 +15,7 @@ use core::prelude::*;
 
 use btree_map::{BTreeMap, Keys, MoveEntries};
 use std::hash::Hash;
+use core::borrow::BorrowFrom;
 use core::default::Default;
 use core::{iter, fmt};
 use core::iter::Peekable;
@@ -167,6 +168,10 @@ impl<T: Ord> BTreeSet<T> {
 
     /// Returns `true` if the set contains a value.
     ///
+    /// The value may be any borrowed form of the set's value type,
+    /// but the ordering on the borrowed form *must* match the
+    /// ordering on the value type.
+    ///
     /// # Example
     ///
     /// ```
@@ -177,7 +182,7 @@ impl<T: Ord> BTreeSet<T> {
     /// assert_eq!(set.contains(&4), false);
     /// ```
     #[unstable = "matches collection reform specification, waiting for dust to settle"]
-    pub fn contains(&self, value: &T) -> bool {
+    pub fn contains<Sized? Q>(&self, value: &Q) -> bool where Q: BorrowFrom<T> + Ord {
         self.map.contains_key(value)
     }
 
@@ -291,6 +296,10 @@ impl<T: Ord> BTreeSet<T> {
     /// Removes a value from the set. Returns `true` if the value was
     /// present in the set.
     ///
+    /// The value may be any borrowed form of the set's value type,
+    /// but the ordering on the borrowed form *must* match the
+    /// ordering on the value type.
+    ///
     /// # Example
     ///
     /// ```
@@ -303,7 +312,7 @@ impl<T: Ord> BTreeSet<T> {
     /// assert_eq!(set.remove(&2), false);
     /// ```
     #[unstable = "matches collection reform specification, waiting for dust to settle"]
-    pub fn remove(&mut self, value: &T) -> bool {
+    pub fn remove<Sized? Q>(&mut self, value: &Q) -> bool where Q: BorrowFrom<T> + Ord {
         self.map.remove(value).is_some()
     }
 }
diff --git a/src/libcollections/slice.rs b/src/libcollections/slice.rs
index 000c3e08c677b..132a07af6b67b 100644
--- a/src/libcollections/slice.rs
+++ b/src/libcollections/slice.rs
@@ -89,6 +89,7 @@
 
 use self::Direction::*;
 use alloc::boxed::Box;
+use core::borrow::{BorrowFrom, BorrowFromMut};
 use core::cmp;
 use core::kinds::Sized;
 use core::mem::size_of;
@@ -647,6 +648,16 @@ impl<T> SliceAllocPrelude<T> for [T] {
     }
 }
 
+#[unstable = "trait is unstable"]
+impl<T> BorrowFrom<Vec<T>> for [T] {
+    fn borrow_from(owned: &Vec<T>) -> &[T] { owned[] }
+}
+
+#[unstable = "trait is unstable"]
+impl<T> BorrowFromMut<Vec<T>> for [T] {
+    fn borrow_from_mut(owned: &mut Vec<T>) -> &mut [T] { owned[mut] }
+}
+
 /// Unsafe operations
 pub mod raw {
     pub use core::slice::raw::{buf_as_slice, mut_buf_as_slice};
diff --git a/src/libcollections/str.rs b/src/libcollections/str.rs
index ae8e92fc6cb9d..aaa7da312f29a 100644
--- a/src/libcollections/str.rs
+++ b/src/libcollections/str.rs
@@ -54,7 +54,7 @@
 pub use self::MaybeOwned::*;
 use self::RecompositionState::*;
 use self::DecompositionType::*;
-
+use core::borrow::BorrowFrom;
 use core::default::Default;
 use core::fmt;
 use core::cmp;
@@ -604,6 +604,11 @@ impl<'a> fmt::Show for MaybeOwned<'a> {
     }
 }
 
+#[unstable = "trait is unstable"]
+impl BorrowFrom<String> for str {
+    fn borrow_from(owned: &String) -> &str { owned[] }
+}
+
 /// Unsafe string operations.
 pub mod raw {
     pub use core::str::raw::{from_utf8, c_str_to_static_slice, slice_bytes};
@@ -1258,13 +1263,13 @@ mod tests {
     #[test]
     fn test_slice_shift_char() {
         let data = "ประเทศไทย中";
-        assert_eq!(data.slice_shift_char(), (Some('ป'), "ระเทศไทย中"));
+        assert_eq!(data.slice_shift_char(), Some(('ป', "ระเทศไทย中")));
     }
 
     #[test]
     fn test_slice_shift_char_2() {
         let empty = "";
-        assert_eq!(empty.slice_shift_char(), (None, ""));
+        assert_eq!(empty.slice_shift_char(), None);
     }
 
     #[test]
diff --git a/src/libcollections/string.rs b/src/libcollections/string.rs
index c0c3af6d2d802..e6698542df238 100644
--- a/src/libcollections/string.rs
+++ b/src/libcollections/string.rs
@@ -549,7 +549,7 @@ impl String {
     ///
     /// # Warning
     ///
-    /// This is a O(n) operation as it requires copying every element in the
+    /// This is an O(n) operation as it requires copying every element in the
     /// buffer.
     ///
     /// # Panics
@@ -586,7 +586,7 @@ impl String {
     ///
     /// # Warning
     ///
-    /// This is a O(n) operation as it requires copying every element in the
+    /// This is an O(n) operation as it requires copying every element in the
     /// buffer.
     ///
     /// # Panics
diff --git a/src/libcollections/tree/map.rs b/src/libcollections/tree/map.rs
index 50bfeafc43e29..119268c27eeac 100644
--- a/src/libcollections/tree/map.rs
+++ b/src/libcollections/tree/map.rs
@@ -11,6 +11,8 @@
 use core::prelude::*;
 
 use alloc::boxed::Box;
+
+use core::borrow::BorrowFrom;
 use core::default::Default;
 use core::fmt;
 use core::fmt::Show;
@@ -188,16 +190,16 @@ impl<K: Ord, V> Default for TreeMap<K,V> {
     fn default() -> TreeMap<K, V> { TreeMap::new() }
 }
 
-impl<K: Ord, V> Index<K, V> for TreeMap<K, V> {
+impl<K: Ord, Sized? Q, V> Index<Q, V> for TreeMap<K, V> where Q: BorrowFrom<K> + Ord {
     #[inline]
-    fn index<'a>(&'a self, i: &K) -> &'a V {
+    fn index<'a>(&'a self, i: &Q) -> &'a V {
         self.get(i).expect("no entry found for key")
     }
 }
 
-impl<K: Ord, V> IndexMut<K, V> for TreeMap<K, V> {
+impl<K: Ord, Sized? Q, V> IndexMut<Q, V> for TreeMap<K, V> where Q: BorrowFrom<K> + Ord {
     #[inline]
-    fn index_mut<'a>(&'a mut self, i: &K) -> &'a mut V {
+    fn index_mut<'a>(&'a mut self, i: &Q) -> &'a mut V {
         self.get_mut(i).expect("no entry found for key")
     }
 }
@@ -446,6 +448,9 @@ impl<K: Ord, V> TreeMap<K, V> {
 
     /// Returns a reference to the value corresponding to the key.
     ///
+    /// The key may be any borrowed form of the map's key type, but the ordering
+    /// on the borrowed form *must* match the ordering on the key type.
+    ///
     /// # Example
     ///
     /// ```
@@ -458,12 +463,17 @@ impl<K: Ord, V> TreeMap<K, V> {
     /// ```
     #[inline]
     #[unstable = "matches collection reform specification, waiting for dust to settle"]
-    pub fn get(&self, key: &K) -> Option<&V> {
-        tree_find_with(&self.root, |k2| key.cmp(k2))
+    pub fn get<Sized? Q>(&self, key: &Q) -> Option<&V>
+        where Q: BorrowFrom<K> + Ord
+    {
+        tree_find_with(&self.root, |k2| key.cmp(BorrowFrom::borrow_from(k2)))
     }
 
     /// Returns true if the map contains a value for the specified key.
     ///
+    /// The key may be any borrowed form of the map's key type, but the ordering
+    /// on the borrowed form *must* match the ordering on the key type.
+    ///
     /// # Example
     ///
     /// ```
@@ -476,7 +486,9 @@ impl<K: Ord, V> TreeMap<K, V> {
     /// ```
     #[inline]
     #[unstable = "matches collection reform specification, waiting for dust to settle"]
-    pub fn contains_key(&self, key: &K) -> bool {
+    pub fn contains_key<Sized? Q>(&self, key: &Q) -> bool
+        where Q: BorrowFrom<K> + Ord
+    {
         self.get(key).is_some()
     }
 
@@ -488,6 +500,9 @@ impl<K: Ord, V> TreeMap<K, V> {
 
     /// Returns a mutable reference to the value corresponding to the key.
     ///
+    /// The key may be any borrowed form of the map's key type, but the ordering
+    /// on the borrowed form *must* match the ordering on the key type.
+    ///
     /// # Example
     ///
     /// ```
@@ -503,8 +518,10 @@ impl<K: Ord, V> TreeMap<K, V> {
     /// ```
     #[inline]
     #[unstable = "matches collection reform specification, waiting for dust to settle"]
-    pub fn get_mut(&mut self, key: &K) -> Option<&mut V> {
-        tree_find_with_mut(&mut self.root, |x| key.cmp(x))
+    pub fn get_mut<Sized? Q>(&mut self, key: &Q) -> Option<&mut V>
+        where Q: BorrowFrom<K> + Ord
+    {
+        tree_find_with_mut(&mut self.root, |x| key.cmp(BorrowFrom::borrow_from(x)))
     }
 
     /// Deprecated: Renamed to `insert`.
@@ -545,6 +562,9 @@ impl<K: Ord, V> TreeMap<K, V> {
     /// Removes a key from the map, returning the value at the key if the key
     /// was previously in the map.
     ///
+    /// The key may be any borrowed form of the map's key type, but the ordering
+    /// on the borrowed form *must* match the ordering on the key type.
+    ///
     /// # Example
     ///
     /// ```
@@ -556,7 +576,9 @@ impl<K: Ord, V> TreeMap<K, V> {
     /// assert_eq!(map.remove(&1), None);
     /// ```
     #[unstable = "matches collection reform specification, waiting for dust to settle"]
-    pub fn remove(&mut self, key: &K) -> Option<V> {
+    pub fn remove<Sized? Q>(&mut self, key: &Q) -> Option<V>
+        where Q: BorrowFrom<K> + Ord
+    {
         let ret = remove(&mut self.root, key);
         if ret.is_some() { self.length -= 1 }
         ret
@@ -589,6 +611,7 @@ impl<K, V> TreeMap<K, V> {
     /// assert_eq!((*ua.unwrap()).as_slice(), "Curl-Rust/0.1");
     /// ```
     #[inline]
+    #[experimental = "likely to be renamed, may be removed"]
     pub fn find_with(&self, f:|&K| -> Ordering) -> Option<&V> {
         tree_find_with(&self.root, f)
     }
@@ -613,6 +636,7 @@ impl<K, V> TreeMap<K, V> {
     /// assert_eq!(t.get(&"User-Agent"), Some(&new_ua));
     /// ```
     #[inline]
+    #[experimental = "likely to be renamed, may be removed"]
     pub fn find_with_mut<'a>(&'a mut self, f:|&K| -> Ordering) -> Option<&'a mut V> {
         tree_find_with_mut(&mut self.root, f)
     }
@@ -1168,10 +1192,11 @@ fn insert<K: Ord, V>(node: &mut Option<Box<TreeNode<K, V>>>,
     }
 }
 
-fn remove<K: Ord, V>(node: &mut Option<Box<TreeNode<K, V>>>,
-                          key: &K) -> Option<V> {
+fn remove<K, Sized? Q, V>(node: &mut Option<Box<TreeNode<K, V>>>, key: &Q) -> Option<V>
+    where K: Ord, Q: BorrowFrom<K> + Ord
+{
     fn heir_swap<K: Ord, V>(node: &mut Box<TreeNode<K, V>>,
-                                 child: &mut Option<Box<TreeNode<K, V>>>) {
+                            child: &mut Option<Box<TreeNode<K, V>>>) {
         // *could* be done without recursion, but it won't borrow check
         for x in child.iter_mut() {
             if x.right.is_some() {
@@ -1188,7 +1213,7 @@ fn remove<K: Ord, V>(node: &mut Option<Box<TreeNode<K, V>>>,
         return None; // bottom of tree
       }
       Some(ref mut save) => {
-        let (ret, rebalance) = match key.cmp(&save.key) {
+        let (ret, rebalance) = match key.cmp(BorrowFrom::borrow_from(&save.key)) {
           Less => (remove(&mut save.left, key), true),
           Greater => (remove(&mut save.right, key), true),
           Equal => {
@@ -1918,4 +1943,3 @@ mod bench {
         bench_iter(b, 100000);
     }
 }
-
diff --git a/src/libcollections/tree/mod.rs b/src/libcollections/tree/mod.rs
index ac8279c92feeb..20823a2affc7f 100644
--- a/src/libcollections/tree/mod.rs
+++ b/src/libcollections/tree/mod.rs
@@ -33,4 +33,4 @@
 //! ```
 
 pub mod map;
-pub mod set;
\ No newline at end of file
+pub mod set;
diff --git a/src/libcollections/tree/set.rs b/src/libcollections/tree/set.rs
index abfaeed7e7ed0..6988b929df689 100644
--- a/src/libcollections/tree/set.rs
+++ b/src/libcollections/tree/set.rs
@@ -10,6 +10,7 @@
 
 use core::prelude::*;
 
+use core::borrow::BorrowFrom;
 use core::default::Default;
 use core::fmt;
 use core::fmt::Show;
@@ -396,6 +397,10 @@ impl<T: Ord> TreeSet<T> {
 
     /// Returns `true` if the set contains a value.
     ///
+    /// The value may be any borrowed form of the set's value type,
+    /// but the ordering on the borrowed form *must* match the
+    /// ordering on the value type.
+    ///
     /// # Example
     ///
     /// ```
@@ -407,7 +412,9 @@ impl<T: Ord> TreeSet<T> {
     /// ```
     #[inline]
     #[unstable = "matches collection reform specification, waiting for dust to settle"]
-    pub fn contains(&self, value: &T) -> bool {
+    pub fn contains<Sized? Q>(&self, value: &Q) -> bool
+        where Q: Ord + BorrowFrom<T>
+    {
         self.map.contains_key(value)
     }
 
@@ -519,6 +526,10 @@ impl<T: Ord> TreeSet<T> {
     /// Removes a value from the set. Returns `true` if the value was
     /// present in the set.
     ///
+    /// The value may be any borrowed form of the set's value type,
+    /// but the ordering on the borrowed form *must* match the
+    /// ordering on the value type.
+    ///
     /// # Example
     ///
     /// ```
@@ -532,7 +543,11 @@ impl<T: Ord> TreeSet<T> {
     /// ```
     #[inline]
     #[unstable = "matches collection reform specification, waiting for dust to settle"]
-    pub fn remove(&mut self, value: &T) -> bool { self.map.remove(value).is_some() }
+    pub fn remove<Sized? Q>(&mut self, value: &Q) -> bool
+        where Q: Ord + BorrowFrom<T>
+    {
+        self.map.remove(value).is_some()
+    }
 }
 
 /// A lazy forward iterator over a set.
diff --git a/src/libcollections/trie/map.rs b/src/libcollections/trie/map.rs
index 8d1fb9e2a86af..672ddab4d87e0 100644
--- a/src/libcollections/trie/map.rs
+++ b/src/libcollections/trie/map.rs
@@ -1057,7 +1057,7 @@ impl<'a, T> VacantEntry<'a, T> {
             search_stack.map.root.count = temp;
             value_ref
         }
-        // Otherwise, find the predeccessor of the last stack node, and insert as normal.
+        // Otherwise, find the predecessor of the last stack node, and insert as normal.
         else {
             match *search_stack.get_ref(old_length - 2) {
                 Internal(box ref mut parent) => {
@@ -1741,7 +1741,7 @@ mod test {
                     // Update it to i^3 using the returned mutable reference.
                     *inserted_val = i * i * i;
                 },
-                _ => panic!("Non-existant key found.")
+                _ => panic!("Non-existent key found.")
             }
             assert_eq!(map.get(&i).unwrap(), &(i * i * i));
         }
diff --git a/src/libcollections/trie/mod.rs b/src/libcollections/trie/mod.rs
index f0f8f00a6a0db..9dcb182cd2675 100644
--- a/src/libcollections/trie/mod.rs
+++ b/src/libcollections/trie/mod.rs
@@ -17,4 +17,4 @@
 //! `TrieMap` is ordered.
 
 pub mod map;
-pub mod set;
\ No newline at end of file
+pub mod set;
diff --git a/src/libcore/array.rs b/src/libcore/array.rs
index 829605ce7cc1b..60765e82cb476 100644
--- a/src/libcore/array.rs
+++ b/src/libcore/array.rs
@@ -8,22 +8,36 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-/*!
- * Implementations of things like `Eq` for fixed-length arrays
- * up to a certain length. Eventually we should able to generalize
- * to all lengths.
- */
+//! Implementations of things like `Eq` for fixed-length arrays
+//! up to a certain length. Eventually we should able to generalize
+//! to all lengths.
 
-#![stable]
 #![experimental] // not yet reviewed
 
-use cmp::*;
-use option::{Option};
+use clone::Clone;
+use cmp::{PartialEq, Eq, PartialOrd, Ord, Ordering};
+use fmt;
+use kinds::Copy;
+use option::Option;
 
 // macro for implementing n-ary tuple functions and operations
 macro_rules! array_impls {
     ($($N:expr)+) => {
         $(
+            #[unstable = "waiting for Clone to stabilize"]
+            impl<T:Copy> Clone for [T, ..$N] {
+                fn clone(&self) -> [T, ..$N] {
+                    *self
+                }
+            }
+
+            #[unstable = "waiting for Show to stabilize"]
+            impl<T:fmt::Show> fmt::Show for [T, ..$N] {
+                fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+                    fmt::Show::fmt(&self[], f)
+                }
+            }
+
             #[unstable = "waiting for PartialEq to stabilize"]
             impl<T:PartialEq> PartialEq for [T, ..$N] {
                 #[inline]
diff --git a/src/libcore/borrow.rs b/src/libcore/borrow.rs
new file mode 100644
index 0000000000000..f0a14c02382ee
--- /dev/null
+++ b/src/libcore/borrow.rs
@@ -0,0 +1,127 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! A module for working with borrowed data.
+//!
+//! # The `BorrowFrom` traits
+//!
+//! In general, there may be several ways to "borrow" a piece of data.  The
+//! typical ways of borrowing a type `T` are `&T` (a shared borrow) and `&mut T`
+//! (a mutable borrow). But types like `Vec<T>` provide additional kinds of
+//! borrows: the borrowed slices `&[T]` and `&mut [T]`.
+//!
+//! When writing generic code, it is often desirable to abstract over all ways
+//! of borrowing data from a given type. That is the role of the `BorrowFrom`
+//! trait: if `T: BorrowFrom<U>`, then `&T` can be borrowed from `&U`.  A given
+//! type can be borrowed as multiple different types. In particular, `Vec<T>:
+//! BorrowFrom<Vec<T>>` and `[T]: BorrowFrom<Vec<T>>`.
+//!
+//! # The `ToOwned` trait
+//!
+//! Some types make it possible to go from borrowed to owned, usually by
+//! implementing the `Clone` trait. But `Clone` works only for going from `&T`
+//! to `T`. The `ToOwned` trait generalizes `Clone` to construct owned data
+//! from any borrow of a given type.
+//!
+//! # The `Cow` (clone-on-write) type
+//!
+//! The type `Cow` is a smart pointer providing clone-on-write functionality: it
+//! can enclose and provide immutable access to borrowed data, and clone the
+//! data lazily when mutation or ownership is required. The type is designed to
+//! work with general borrowed data via the `BorrowFrom` trait.
+//!
+//! `Cow` implements both `Deref` and `DerefMut`, which means that you can call
+//! methods directly on the data it encloses. The first time a mutable reference
+//! is required, the data will be cloned (via `to_owned`) if it is not
+//! already owned.
+
+#![unstable = "recently added as part of collections reform"]
+
+use clone::Clone;
+use kinds::Sized;
+use ops::Deref;
+use self::Cow::*;
+
+/// A trait for borrowing data.
+pub trait BorrowFrom<Sized? Owned> for Sized? {
+    /// Immutably borrow from an owned value.
+    fn borrow_from(owned: &Owned) -> &Self;
+}
+
+/// A trait for mutably borrowing data.
+pub trait BorrowFromMut<Sized? Owned> for Sized? : BorrowFrom<Owned> {
+    /// Mutably borrow from an owned value.
+    fn borrow_from_mut(owned: &mut Owned) -> &mut Self;
+}
+
+impl<Sized? T> BorrowFrom<T> for T {
+    fn borrow_from(owned: &T) -> &T { owned }
+}
+
+impl<Sized? T> BorrowFromMut<T> for T {
+    fn borrow_from_mut(owned: &mut T) -> &mut T { owned }
+}
+
+impl BorrowFrom<&'static str> for str {
+    fn borrow_from<'a>(owned: &'a &'static str) -> &'a str { &**owned }
+}
+
+/// A generalization of Clone to borrowed data.
+pub trait ToOwned<Owned> for Sized?: BorrowFrom<Owned> {
+    /// Create owned data from borrowed data, usually by copying.
+    fn to_owned(&self) -> Owned;
+}
+
+impl<T> ToOwned<T> for T where T: Clone {
+    fn to_owned(&self) -> T { self.clone() }
+}
+
+/// A clone-on-write smart pointer.
+pub enum Cow<'a, T, B: 'a> where B: ToOwned<T> {
+    /// Borrowed data.
+    Borrowed(&'a B),
+
+    /// Owned data.
+    Owned(T)
+}
+
+impl<'a, T, B> Cow<'a, T, B> where B: ToOwned<T> {
+    /// Acquire a mutable reference to the owned form of the data.
+    ///
+    /// Copies the data if it is not already owned.
+    pub fn to_mut(&mut self) -> &mut T {
+        match *self {
+            Borrowed(borrowed) => {
+                *self = Owned(borrowed.to_owned());
+                self.to_mut()
+            }
+            Owned(ref mut owned) => owned
+        }
+    }
+
+    /// Extract the owned data.
+    ///
+    /// Copies the data if it is not already owned.
+    pub fn into_owned(self) -> T {
+        match self {
+            Borrowed(borrowed) => borrowed.to_owned(),
+            Owned(owned) => owned
+        }
+    }
+}
+
+impl<'a, T, B> Deref<B> for Cow<'a, T, B> where B: ToOwned<T>  {
+    fn deref(&self) -> &B {
+        match *self {
+            Borrowed(borrowed) => borrowed,
+            Owned(ref owned) => BorrowFrom::borrow_from(owned)
+        }
+    }
+}
diff --git a/src/libcore/clone.rs b/src/libcore/clone.rs
index a495c780e02c0..d13daf0964a1a 100644
--- a/src/libcore/clone.rs
+++ b/src/libcore/clone.rs
@@ -23,6 +23,8 @@ the `clone` method.
 
 #![unstable]
 
+use kinds::Sized;
+
 /// A common trait for cloning an object.
 pub trait Clone {
     /// Returns a copy of the value.
@@ -40,24 +42,12 @@ pub trait Clone {
     }
 }
 
-impl<'a, T> Clone for &'a T {
+impl<'a, Sized? T> Clone for &'a T {
     /// Return a shallow copy of the reference.
     #[inline]
     fn clone(&self) -> &'a T { *self }
 }
 
-impl<'a, T> Clone for &'a [T] {
-    /// Return a shallow copy of the slice.
-    #[inline]
-    fn clone(&self) -> &'a [T] { *self }
-}
-
-impl<'a> Clone for &'a str {
-    /// Return a shallow copy of the slice.
-    #[inline]
-    fn clone(&self) -> &'a str { *self }
-}
-
 macro_rules! clone_impl(
     ($t:ty) => {
         impl Clone for $t {
diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs
index 9689f7cdd7114..5e3c74477d15c 100644
--- a/src/libcore/lib.rs
+++ b/src/libcore/lib.rs
@@ -108,6 +108,7 @@ pub mod default;
 pub mod any;
 pub mod atomic;
 pub mod bool;
+pub mod borrow;
 pub mod cell;
 pub mod char;
 pub mod panicking;
diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs
index 97b3554b1e1ba..937f73a326271 100644
--- a/src/libcore/mem.rs
+++ b/src/libcore/mem.rs
@@ -88,7 +88,7 @@ pub fn align_of_val<T>(_val: &T) -> uint {
 
 /// Create a value initialized to zero.
 ///
-/// This function is similar to allocating space for a a local variable and
+/// This function is similar to allocating space for a local variable and
 /// zeroing it out (an unsafe operation).
 ///
 /// Care must be taken when using this function, if the type `T` has a
diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs
index 800b0c1a9059f..a794897ce6bc8 100644
--- a/src/libcore/num/mod.rs
+++ b/src/libcore/num/mod.rs
@@ -198,7 +198,7 @@ pub trait Int
     /// ```
     fn swap_bytes(self) -> Self;
 
-    /// Convert a integer from big endian to the target's endianness.
+    /// Convert an integer from big endian to the target's endianness.
     ///
     /// On big endian this is a no-op. On little endian the bytes are swapped.
     ///
@@ -220,7 +220,7 @@ pub trait Int
         if cfg!(target_endian = "big") { x } else { x.swap_bytes() }
     }
 
-    /// Convert a integer from little endian to the target's endianness.
+    /// Convert an integer from little endian to the target's endianness.
     ///
     /// On little endian this is a no-op. On big endian the bytes are swapped.
     ///
@@ -1457,10 +1457,10 @@ macro_rules! from_str_radix_float_impl {
                 }
 
                 let (is_positive, src) =  match src.slice_shift_char() {
-                    (None, _)        => return None,
-                    (Some('-'), "")  => return None,
-                    (Some('-'), src) => (false, src),
-                    (Some(_), _)     => (true,  src),
+                    None             => return None,
+                    Some(('-', ""))  => return None,
+                    Some(('-', src)) => (false, src),
+                    Some((_, _))     => (true,  src),
                 };
 
                 // The significand to accumulate
@@ -1563,10 +1563,10 @@ macro_rules! from_str_radix_float_impl {
                         // Parse the exponent as decimal integer
                         let src = src[offset..];
                         let (is_positive, exp) = match src.slice_shift_char() {
-                            (Some('-'), src) => (false, from_str::<uint>(src)),
-                            (Some('+'), src) => (true,  from_str::<uint>(src)),
-                            (Some(_), _)     => (true,  from_str::<uint>(src)),
-                            (None, _)        => return None,
+                            Some(('-', src)) => (false, from_str::<uint>(src)),
+                            Some(('+', src)) => (true,  from_str::<uint>(src)),
+                            Some((_, _))     => (true,  from_str::<uint>(src)),
+                            None             => return None,
                         };
 
                         match (is_positive, exp) {
@@ -1606,7 +1606,7 @@ macro_rules! from_str_radix_int_impl {
                 let is_signed_ty = (0 as $T) > Int::min_value();
 
                 match src.slice_shift_char() {
-                    (Some('-'), src) if is_signed_ty => {
+                    Some(('-', src)) if is_signed_ty => {
                         // The number is negative
                         let mut result = 0;
                         for c in src.chars() {
@@ -1625,7 +1625,7 @@ macro_rules! from_str_radix_int_impl {
                         }
                         Some(result)
                     },
-                    (Some(_), _) => {
+                    Some((_, _)) => {
                         // The number is signed
                         let mut result = 0;
                         for c in src.chars() {
@@ -1644,7 +1644,7 @@ macro_rules! from_str_radix_int_impl {
                         }
                         Some(result)
                     },
-                    (None, _) => None,
+                    None => None,
                 }
             }
         }
diff --git a/src/libcore/ops.rs b/src/libcore/ops.rs
index 3a2e178d2ea0a..b4bf5351e597b 100644
--- a/src/libcore/ops.rs
+++ b/src/libcore/ops.rs
@@ -638,7 +638,7 @@ shr_impl!(uint u8 u16 u32 u64 int i8 i16 i32 i64)
  * ```
  */
 #[lang="index"]
-pub trait Index<Index, Sized? Result> for Sized? {
+pub trait Index<Sized? Index, Sized? Result> for Sized? {
     /// The method for the indexing (`Foo[Bar]`) operation
     fn index<'a>(&'a self, index: &Index) -> &'a Result;
 }
@@ -669,7 +669,7 @@ pub trait Index<Index, Sized? Result> for Sized? {
  * ```
  */
 #[lang="index_mut"]
-pub trait IndexMut<Index, Result> for Sized? {
+pub trait IndexMut<Sized? Index, Result> for Sized? {
     /// The method for the indexing (`Foo[Bar]`) operation
     fn index_mut<'a>(&'a mut self, index: &Index) -> &'a mut Result;
 }
diff --git a/src/libcore/str.rs b/src/libcore/str.rs
index bc30429c05c92..24f26b15f27ac 100644
--- a/src/libcore/str.rs
+++ b/src/libcore/str.rs
@@ -1811,21 +1811,21 @@ pub trait StrPrelude for Sized? {
     /// it. This does not allocate a new string; instead, it returns a
     /// slice that point one character beyond the character that was
     /// shifted. If the string does not contain any characters,
-    /// a tuple of None and an empty string is returned instead.
+    /// None is returned instead.
     ///
     /// # Example
     ///
     /// ```rust
     /// let s = "Löwe 老虎 Léopard";
-    /// let (c, s1) = s.slice_shift_char();
-    /// assert_eq!(c, Some('L'));
+    /// let (c, s1) = s.slice_shift_char().unwrap();
+    /// assert_eq!(c, 'L');
     /// assert_eq!(s1, "öwe 老虎 Léopard");
     ///
-    /// let (c, s2) = s1.slice_shift_char();
-    /// assert_eq!(c, Some('ö'));
+    /// let (c, s2) = s1.slice_shift_char().unwrap();
+    /// assert_eq!(c, 'ö');
     /// assert_eq!(s2, "we 老虎 Léopard");
     /// ```
-    fn slice_shift_char<'a>(&'a self) -> (Option<char>, &'a str);
+    fn slice_shift_char<'a>(&'a self) -> Option<(char, &'a str)>;
 
     /// Returns the byte offset of an inner slice relative to an enclosing outer slice.
     ///
@@ -2197,13 +2197,13 @@ impl StrPrelude for str {
     }
 
     #[inline]
-    fn slice_shift_char(&self) -> (Option<char>, &str) {
+    fn slice_shift_char(&self) -> Option<(char, &str)> {
         if self.is_empty() {
-            return (None, self);
+            None
         } else {
             let CharRange {ch, next} = self.char_range_at(0u);
             let next_s = unsafe { raw::slice_bytes(self, next, self.len()) };
-            return (Some(ch), next_s);
+            Some((ch, next_s))
         }
     }
 
diff --git a/src/libgraphviz/lib.rs b/src/libgraphviz/lib.rs
index eff5345e85e52..4478694367621 100644
--- a/src/libgraphviz/lib.rs
+++ b/src/libgraphviz/lib.rs
@@ -60,10 +60,10 @@ pub fn render_to<W:Writer>(output: &mut W) {
 }
 
 impl<'a> dot::Labeller<'a, Nd, Ed> for Edges {
-    fn graph_id(&'a self) -> dot::Id<'a> { dot::Id::new("example1") }
+    fn graph_id(&'a self) -> dot::Id<'a> { dot::Id::new("example1").unwrap() }
 
     fn node_id(&'a self, n: &Nd) -> dot::Id<'a> {
-        dot::Id::new(format!("N{}", *n))
+        dot::Id::new(format!("N{}", *n)).unwrap()
     }
 }
 
@@ -163,9 +163,9 @@ pub fn render_to<W:Writer>(output: &mut W) {
 }
 
 impl<'a> dot::Labeller<'a, Nd, Ed<'a>> for Graph {
-    fn graph_id(&'a self) -> dot::Id<'a> { dot::Id::new("example2") }
+    fn graph_id(&'a self) -> dot::Id<'a> { dot::Id::new("example2").unwrap() }
     fn node_id(&'a self, n: &Nd) -> dot::Id<'a> {
-        dot::Id::new(format!("N{}", n))
+        dot::Id::new(format!("N{}", n)).unwrap()
     }
     fn node_label<'a>(&'a self, n: &Nd) -> dot::LabelText<'a> {
         dot::LabelStr(str::Slice(self.nodes[*n].as_slice()))
@@ -219,9 +219,9 @@ pub fn render_to<W:Writer>(output: &mut W) {
 }
 
 impl<'a> dot::Labeller<'a, Nd<'a>, Ed<'a>> for Graph {
-    fn graph_id(&'a self) -> dot::Id<'a> { dot::Id::new("example3") }
+    fn graph_id(&'a self) -> dot::Id<'a> { dot::Id::new("example3").unwrap() }
     fn node_id(&'a self, n: &Nd<'a>) -> dot::Id<'a> {
-        dot::Id::new(format!("N{:u}", n.val0()))
+        dot::Id::new(format!("N{:u}", n.val0())).unwrap()
     }
     fn node_label<'a>(&'a self, n: &Nd<'a>) -> dot::LabelText<'a> {
         let &(i, _) = n;
@@ -354,14 +354,22 @@ impl<'a> Id<'a> {
     /// defined by the DOT language.  This function may change in the
     /// future to accept a broader subset, or the entirety, of DOT's
     /// `ID` format.)
-    pub fn new<Name:str::IntoMaybeOwned<'a>>(name: Name) -> Id<'a> {
+    ///
+    /// Passing an invalid string (containing spaces, brackets,
+    /// quotes, ...) will return an empty `Err` value.
+    pub fn new<Name:str::IntoMaybeOwned<'a>>(name: Name) -> Result<Id<'a>, ()> {
         let name = name.into_maybe_owned();
         {
             let mut chars = name.as_slice().chars();
-            assert!(is_letter_or_underscore(chars.next().unwrap()));
-            assert!(chars.all(is_constituent));
+            match chars.next() {
+                Some(c) if is_letter_or_underscore(c) => { ; },
+                _ => return Err(())
+            }
+            if !chars.all(is_constituent) {
+                return Err(());
+            }
         }
-        return Id{ name: name };
+        return Ok(Id{ name: name });
 
         fn is_letter_or_underscore(c: char) -> bool {
             in_range('a', c, 'z') || in_range('A', c, 'Z') || c == '_'
@@ -627,12 +635,12 @@ mod tests {
     }
 
     fn id_name<'a>(n: &Node) -> Id<'a> {
-        Id::new(format!("N{:u}", *n))
+        Id::new(format!("N{:u}", *n)).unwrap()
     }
 
     impl<'a> Labeller<'a, Node, &'a Edge> for LabelledGraph {
         fn graph_id(&'a self) -> Id<'a> {
-            Id::new(self.name.as_slice())
+            Id::new(self.name.as_slice()).unwrap()
         }
         fn node_id(&'a self, n: &Node) -> Id<'a> {
             id_name(n)
@@ -825,4 +833,22 @@ r#"digraph syntax_tree {
 }
 "#);
     }
+
+    #[test]
+    fn simple_id_construction() {
+        let id1 = Id::new("hello");
+        match id1 {
+            Ok(_) => {;},
+            Err(_) => panic!("'hello' is not a valid value for id anymore")
+        }
+    }
+
+    #[test]
+    fn badly_formatted_id() {
+        let id2 = Id::new("Weird { struct : ure } !!!");
+        match id2 {
+            Ok(_) => panic!("graphviz id suddenly allows spaces, brackets and stuff"),
+            Err(_) => {;}
+        }
+    }
 }
diff --git a/src/liblog/lib.rs b/src/liblog/lib.rs
index b626b66427df3..2e60ce31d5e5e 100644
--- a/src/liblog/lib.rs
+++ b/src/liblog/lib.rs
@@ -137,7 +137,7 @@
 //! includes 'foo'.
 //! * `info/f.o` turns on all info logging where the log message includes 'foo',
 //! 'f1o', 'fao', etc.
-//! * `hello=debug/foo*foo` turns on debug logging for 'hello' where the the log
+//! * `hello=debug/foo*foo` turns on debug logging for 'hello' where the log
 //! message includes 'foofoo' or 'fofoo' or 'fooooooofoo', etc.
 //! * `error,hello=warn/[0-9] scopes` turn on global error logging and also warn for
 //!  hello. In both cases the log message must include a single digit number
diff --git a/src/libregex/re.rs b/src/libregex/re.rs
index dbdb271874474..e70491a785c37 100644
--- a/src/libregex/re.rs
+++ b/src/libregex/re.rs
@@ -561,7 +561,7 @@ pub struct NoExpand<'t>(pub &'t str);
 /// Replacer describes types that can be used to replace matches in a string.
 pub trait Replacer {
     /// Returns a possibly owned string that is used to replace the match
-    /// corresponding the the `caps` capture group.
+    /// corresponding to the `caps` capture group.
     ///
     /// The `'a` lifetime refers to the lifetime of a borrowed string when
     /// a new owned string isn't needed (e.g., for `NoExpand`).
@@ -726,7 +726,7 @@ impl<'t> Captures<'t> {
         match self.named {
             None => "",
             Some(ref h) => {
-                match h.find_equiv(name) {
+                match h.get(name) {
                     None => "",
                     Some(i) => self.at(*i),
                 }
diff --git a/src/librustc/back/link.rs b/src/librustc/back/link.rs
index 97ab3209d28f8..766715ff25167 100644
--- a/src/librustc/back/link.rs
+++ b/src/librustc/back/link.rs
@@ -728,7 +728,9 @@ fn link_staticlib(sess: &Session, obj_filename: &Path, out_filename: &Path) {
     if sess.target.target.options.morestack {
         ab.add_native_library("morestack").unwrap();
     }
-    ab.add_native_library("compiler-rt").unwrap();
+    if !sess.target.target.options.no_compiler_rt {
+        ab.add_native_library("compiler-rt").unwrap();
+    }
 
     let crates = sess.cstore.get_used_crates(cstore::RequireStatic);
     let mut all_native_libs = vec![];
diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs
index 1792599783b2c..b5dafdb180766 100644
--- a/src/librustc/diagnostics.rs
+++ b/src/librustc/diagnostics.rs
@@ -143,5 +143,6 @@ register_diagnostics!(
     E0164,
     E0165,
     E0166,
-    E0167
+    E0167,
+    E0168
 )
diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs
index 4247d192d6d4c..df014eb1206aa 100644
--- a/src/librustc/lint/builtin.rs
+++ b/src/librustc/lint/builtin.rs
@@ -623,6 +623,7 @@ impl LintPass for UnusedAttributes {
             "link",
             "link_name",
             "link_section",
+            "linkage",
             "no_builtins",
             "no_mangle",
             "no_split_stack",
diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs
index 85cc413a1b801..aa6a021a210ef 100644
--- a/src/librustc/lint/context.rs
+++ b/src/librustc/lint/context.rs
@@ -165,7 +165,7 @@ impl LintStore {
     }
 
     fn register_renamed(&mut self, old_name: &str, new_name: &str) {
-        let target = match self.by_name.find_equiv(new_name) {
+        let target = match self.by_name.get(new_name) {
             Some(&Id(lint_id)) => lint_id.clone(),
             _ => panic!("invalid lint renaming of {} to {}", old_name, new_name)
         };
@@ -259,7 +259,7 @@ impl LintStore {
     fn find_lint(&self, lint_name: &str, sess: &Session, span: Option<Span>)
                  -> Option<LintId>
     {
-        match self.by_name.find_equiv(lint_name) {
+        match self.by_name.get(lint_name) {
             Some(&Id(lint_id)) => Some(lint_id),
             Some(&Renamed(ref new_name, lint_id)) => {
                 let warning = format!("lint {} has been renamed to {}",
@@ -282,7 +282,7 @@ impl LintStore {
                     match self.lint_groups.iter().map(|(&x, pair)| (x, pair.ref0().clone()))
                                                  .collect::<FnvHashMap<&'static str,
                                                                        Vec<LintId>>>()
-                                                 .find_equiv(lint_name.as_slice()) {
+                                                 .get(lint_name.as_slice()) {
                         Some(v) => {
                             v.iter()
                              .map(|lint_id: &LintId|
@@ -489,7 +489,7 @@ impl<'a, 'tcx> Context<'a, 'tcx> {
                     match self.lints.find_lint(lint_name.get(), &self.tcx.sess, Some(span)) {
                         Some(lint_id) => vec![(lint_id, level, span)],
                         None => {
-                            match self.lints.lint_groups.find_equiv(lint_name.get()) {
+                            match self.lints.lint_groups.get(lint_name.get()) {
                                 Some(&(ref v, _)) => v.iter()
                                                       .map(|lint_id: &LintId|
                                                            (*lint_id, level, span))
diff --git a/src/librustc/metadata/creader.rs b/src/librustc/metadata/creader.rs
index dbf0e4054085c..d9e7437216e80 100644
--- a/src/librustc/metadata/creader.rs
+++ b/src/librustc/metadata/creader.rs
@@ -242,6 +242,8 @@ fn visit_item(e: &Env, i: &ast::Item) {
                                     cstore::NativeFramework
                                 } else if k.equiv(&("framework")) {
                                     cstore::NativeFramework
+                                } else if k.equiv(&("dylib")) {
+                                    cstore::NativeUnknown
                                 } else {
                                     e.sess.span_err(m.span,
                                         format!("unknown kind: `{}`",
@@ -321,7 +323,7 @@ fn existing_match(e: &Env, name: &str,
         // `source` stores paths which are normalized which may be different
         // from the strings on the command line.
         let source = e.sess.cstore.get_used_crate_source(cnum).unwrap();
-        match e.sess.opts.externs.find_equiv(name) {
+        match e.sess.opts.externs.get(name) {
             Some(locs) => {
                 let found = locs.iter().any(|l| {
                     let l = fs::realpath(&Path::new(l.as_slice())).ok();
diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs
index 2af1f12a2cd82..e0110a81c179f 100644
--- a/src/librustc/metadata/decoder.rs
+++ b/src/librustc/metadata/decoder.rs
@@ -298,7 +298,7 @@ fn item_path(item_doc: rbml::Doc) -> Vec<ast_map::PathElem> {
 fn item_name(intr: &IdentInterner, item: rbml::Doc) -> ast::Name {
     let name = reader::get_doc(item, tag_paths_data_name);
     let string = name.as_str_slice();
-    match intr.find_equiv(string) {
+    match intr.find(string) {
         None => token::intern(string),
         Some(val) => val,
     }
@@ -1449,4 +1449,3 @@ pub fn is_associated_type(cdata: Cmd, id: ast::NodeId) -> bool {
         Some(item) => item_sort(item) == 't',
     }
 }
-
diff --git a/src/librustc/metadata/filesearch.rs b/src/librustc/metadata/filesearch.rs
index aeed829f8055b..f7d666e48150d 100644
--- a/src/librustc/metadata/filesearch.rs
+++ b/src/librustc/metadata/filesearch.rs
@@ -54,7 +54,7 @@ impl<'a> FileSearch<'a> {
         debug!("filesearch: searching lib path");
         let tlib_path = make_target_lib_path(self.sysroot,
                                     self.triple);
-        if !visited_dirs.contains_equiv(tlib_path.as_vec()) {
+        if !visited_dirs.contains(tlib_path.as_vec()) {
             match f(&tlib_path) {
                 FileMatches => found = true,
                 FileDoesntMatch => ()
@@ -69,9 +69,9 @@ impl<'a> FileSearch<'a> {
                 let tlib_path = make_rustpkg_lib_path(
                     self.sysroot, path, self.triple);
                 debug!("is {} in visited_dirs? {}", tlib_path.display(),
-                        visited_dirs.contains_equiv(&tlib_path.as_vec().to_vec()));
+                        visited_dirs.contains(&tlib_path.as_vec().to_vec()));
 
-                if !visited_dirs.contains_equiv(tlib_path.as_vec()) {
+                if !visited_dirs.contains(tlib_path.as_vec()) {
                     visited_dirs.insert(tlib_path.as_vec().to_vec());
                     // Don't keep searching the RUST_PATH if one match turns up --
                     // if we did, we'd get a "multiple matching crates" error
diff --git a/src/librustc/metadata/loader.rs b/src/librustc/metadata/loader.rs
index c3d92a19a2056..30bef248b4738 100644
--- a/src/librustc/metadata/loader.rs
+++ b/src/librustc/metadata/loader.rs
@@ -596,7 +596,7 @@ impl<'a> Context<'a> {
     }
 
     fn find_commandline_library(&mut self) -> Option<Library> {
-        let locs = match self.sess.opts.externs.find_equiv(self.crate_name) {
+        let locs = match self.sess.opts.externs.get(self.crate_name) {
             Some(s) => s,
             None => return None,
         };
diff --git a/src/librustc/middle/cfg/graphviz.rs b/src/librustc/middle/cfg/graphviz.rs
index 1feca05e4499d..78b3a1179ca59 100644
--- a/src/librustc/middle/cfg/graphviz.rs
+++ b/src/librustc/middle/cfg/graphviz.rs
@@ -50,10 +50,10 @@ fn replace_newline_with_backslash_l(s: String) -> String {
 }
 
 impl<'a, 'ast> dot::Labeller<'a, Node<'a>, Edge<'a>> for LabelledCFG<'a, 'ast> {
-    fn graph_id(&'a self) -> dot::Id<'a> { dot::Id::new(self.name.as_slice()) }
+    fn graph_id(&'a self) -> dot::Id<'a> { dot::Id::new(self.name.as_slice()).unwrap() }
 
     fn node_id(&'a self, &(i,_): &Node<'a>) -> dot::Id<'a> {
-        dot::Id::new(format!("N{:u}", i.node_id()))
+        dot::Id::new(format!("N{:u}", i.node_id())).unwrap()
     }
 
     fn node_label(&'a self, &(i, n): &Node<'a>) -> dot::LabelText<'a> {
diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs
index 4fe770a1e0fb3..ffc8a83e42eda 100644
--- a/src/librustc/middle/lang_items.rs
+++ b/src/librustc/middle/lang_items.rs
@@ -132,7 +132,7 @@ impl<'a, 'v> Visitor<'v> for LanguageItemCollector<'a> {
     fn visit_item(&mut self, item: &ast::Item) {
         match extract(item.attrs.as_slice()) {
             Some(value) => {
-                let item_index = self.item_refs.find_equiv(&value).map(|x| *x);
+                let item_index = self.item_refs.get(value.get()).map(|x| *x);
 
                 match item_index {
                     Some(item_index) => {
diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs
index 49bbfd0be479a..4d0474b68da85 100644
--- a/src/librustc/middle/stability.rs
+++ b/src/librustc/middle/stability.rs
@@ -79,14 +79,17 @@ impl<'v> Visitor<'v> for Annotator {
         }
     }
 
-    fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v FnDecl,
-                b: &'v Block, s: Span, _: NodeId) {
+    fn visit_fn(&mut self, fk: FnKind<'v>, _: &'v FnDecl,
+                _: &'v Block, _: Span, _: NodeId) {
         match fk {
             FkMethod(_, _, meth) => {
-                self.annotate(meth.id, &meth.attrs, |v| visit::walk_fn(v, fk, fd, b, s));
+                // Methods are not already annotated, so we annotate it
+                self.annotate(meth.id, &meth.attrs, |_| {});
             }
-            _ => visit::walk_fn(self, fk, fd, b, s)
+            _ => {}
         }
+        // Items defined in a function body have no reason to have
+        // a stability attribute, so we don't recurse.
     }
 
     fn visit_trait_item(&mut self, t: &TraitItem) {
diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs
index 9ab2f948f9da2..edd37294b6a69 100644
--- a/src/librustc/middle/traits/select.rs
+++ b/src/librustc/middle/traits/select.rs
@@ -351,7 +351,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         // matches this obligation, then we can assume that the
         // obligation is satisfied for now (still all other conditions
         // must be met of course). One obvious case this comes up is
-        // marker traits like `Send`. Think of a a linked list:
+        // marker traits like `Send`. Think of a linked list:
         //
         //    struct List<T> { data: T, next: Option<Box<List<T>>> {
         //
diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs
index b267d1d7f3e1e..c05e61023ed67 100644
--- a/src/librustc/middle/trans/base.rs
+++ b/src/librustc/middle/trans/base.rs
@@ -36,7 +36,7 @@ use driver::config::{NoDebugInfo, FullDebugInfo};
 use driver::driver::{CrateAnalysis, CrateTranslation, ModuleTranslation};
 use driver::session::Session;
 use lint;
-use llvm::{BasicBlockRef, ValueRef, Vector, get_param};
+use llvm::{BasicBlockRef, Linkage, ValueRef, Vector, get_param};
 use llvm;
 use metadata::{csearch, encoder, loader};
 use middle::astencode;
@@ -216,7 +216,7 @@ pub fn get_extern_fn(ccx: &CrateContext,
                      ty: Type,
                      output: ty::t)
                      -> ValueRef {
-    match externs.find_equiv(name) {
+    match externs.get(name) {
         Some(n) => return *n,
         None => {}
     }
@@ -226,7 +226,7 @@ pub fn get_extern_fn(ccx: &CrateContext,
 }
 
 fn get_extern_rust_fn(ccx: &CrateContext, fn_ty: ty::t, name: &str, did: ast::DefId) -> ValueRef {
-    match ccx.externs().borrow().find_equiv(name) {
+    match ccx.externs().borrow().get(name) {
         Some(n) => return *n,
         None => ()
     }
@@ -2137,6 +2137,32 @@ impl<'a, 'tcx, 'v> Visitor<'v> for TransItemVisitor<'a, 'tcx> {
     }
 }
 
+pub fn llvm_linkage_by_name(name: &str) -> Option<Linkage> {
+    // Use the names from src/llvm/docs/LangRef.rst here. Most types are only
+    // applicable to variable declarations and may not really make sense for
+    // Rust code in the first place but whitelist them anyway and trust that
+    // the user knows what s/he's doing. Who knows, unanticipated use cases
+    // may pop up in the future.
+    //
+    // ghost, dllimport, dllexport and linkonce_odr_autohide are not supported
+    // and don't have to be, LLVM treats them as no-ops.
+    match name {
+        "appending" => Some(llvm::AppendingLinkage),
+        "available_externally" => Some(llvm::AvailableExternallyLinkage),
+        "common" => Some(llvm::CommonLinkage),
+        "extern_weak" => Some(llvm::ExternalWeakLinkage),
+        "external" => Some(llvm::ExternalLinkage),
+        "internal" => Some(llvm::InternalLinkage),
+        "linkonce" => Some(llvm::LinkOnceAnyLinkage),
+        "linkonce_odr" => Some(llvm::LinkOnceODRLinkage),
+        "private" => Some(llvm::PrivateLinkage),
+        "weak" => Some(llvm::WeakAnyLinkage),
+        "weak_odr" => Some(llvm::WeakODRLinkage),
+        _ => None,
+    }
+}
+
+
 /// Enum describing the origin of an LLVM `Value`, for linkage purposes.
 pub enum ValueOrigin {
     /// The LLVM `Value` is in this context because the corresponding item was
@@ -2174,6 +2200,23 @@ pub fn update_linkage(ccx: &CrateContext,
         OriginalTranslation => {},
     }
 
+    match id {
+        Some(id) => {
+            let item = ccx.tcx().map.get(id);
+            if let ast_map::NodeItem(i) = item {
+                if let Some(name) =  attr::first_attr_value_str_by_name(i.attrs[], "linkage") {
+                    if let Some(linkage) = llvm_linkage_by_name(name.get()) {
+                        llvm::SetLinkage(llval, linkage);
+                    } else {
+                        ccx.sess().span_fatal(i.span, "invalid linkage specified");
+                    }
+                    return;
+                }
+            }
+        }
+        _ => {}
+    }
+
     match id {
         Some(id) if ccx.reachable().contains(&id) => {
             llvm::SetLinkage(llval, llvm::ExternalLinkage);
@@ -2983,7 +3026,7 @@ fn internalize_symbols(cx: &SharedCrateContext, reachable: &HashSet<String>) {
 
                 let name = CString::new(llvm::LLVMGetValueName(val), false);
                 if !declared.contains(&name) &&
-                   !reachable.contains_equiv(name.as_str().unwrap()) {
+                   !reachable.contains(name.as_str().unwrap()) {
                     llvm::SetLinkage(val, llvm::InternalLinkage);
                 }
             }
diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs
index eaff757679aa0..de8e80b02757b 100644
--- a/src/librustc/middle/trans/debuginfo.rs
+++ b/src/librustc/middle/trans/debuginfo.rs
@@ -1677,7 +1677,7 @@ fn declare_local(bcx: Block,
 }
 
 fn file_metadata(cx: &CrateContext, full_path: &str) -> DIFile {
-    match debug_context(cx).created_files.borrow().find_equiv(full_path) {
+    match debug_context(cx).created_files.borrow().get(full_path) {
         Some(file_metadata) => return *file_metadata,
         None => ()
     }
diff --git a/src/librustc/middle/trans/foreign.rs b/src/librustc/middle/trans/foreign.rs
index 1afb73b08f7b8..940319d050bea 100644
--- a/src/librustc/middle/trans/foreign.rs
+++ b/src/librustc/middle/trans/foreign.rs
@@ -10,10 +10,10 @@
 
 
 use back::{link};
-use llvm::{ValueRef, CallConv, Linkage, get_param};
+use llvm::{ValueRef, CallConv, get_param};
 use llvm;
 use middle::weak_lang_items;
-use middle::trans::base::push_ctxt;
+use middle::trans::base::{llvm_linkage_by_name, push_ctxt};
 use middle::trans::base;
 use middle::trans::build::*;
 use middle::trans::cabi;
@@ -101,31 +101,6 @@ pub fn llvm_calling_convention(ccx: &CrateContext,
     }
 }
 
-pub fn llvm_linkage_by_name(name: &str) -> Option<Linkage> {
-    // Use the names from src/llvm/docs/LangRef.rst here. Most types are only
-    // applicable to variable declarations and may not really make sense for
-    // Rust code in the first place but whitelist them anyway and trust that
-    // the user knows what s/he's doing. Who knows, unanticipated use cases
-    // may pop up in the future.
-    //
-    // ghost, dllimport, dllexport and linkonce_odr_autohide are not supported
-    // and don't have to be, LLVM treats them as no-ops.
-    match name {
-        "appending" => Some(llvm::AppendingLinkage),
-        "available_externally" => Some(llvm::AvailableExternallyLinkage),
-        "common" => Some(llvm::CommonLinkage),
-        "extern_weak" => Some(llvm::ExternalWeakLinkage),
-        "external" => Some(llvm::ExternalLinkage),
-        "internal" => Some(llvm::InternalLinkage),
-        "linkonce" => Some(llvm::LinkOnceAnyLinkage),
-        "linkonce_odr" => Some(llvm::LinkOnceODRLinkage),
-        "private" => Some(llvm::PrivateLinkage),
-        "weak" => Some(llvm::WeakAnyLinkage),
-        "weak_odr" => Some(llvm::WeakODRLinkage),
-        _ => None,
-    }
-}
-
 pub fn register_static(ccx: &CrateContext,
                        foreign_item: &ast::ForeignItem) -> ValueRef {
     let ty = ty::node_id_to_type(ccx.tcx(), foreign_item.id);
diff --git a/src/librustc/middle/trans/type_.rs b/src/librustc/middle/trans/type_.rs
index d6a2d0c86a111..69861290b8d0d 100644
--- a/src/librustc/middle/trans/type_.rs
+++ b/src/librustc/middle/trans/type_.rs
@@ -336,7 +336,7 @@ impl TypeNames {
     }
 
     pub fn find_type(&self, s: &str) -> Option<Type> {
-        self.named_types.borrow().find_equiv(s).map(|x| Type::from_ref(*x))
+        self.named_types.borrow().get(s).map(|x| Type::from_ref(*x))
     }
 
     pub fn type_to_string(&self, ty: Type) -> String {
diff --git a/src/librustc/middle/typeck/check/_match.rs b/src/librustc/middle/typeck/check/_match.rs
index 90c3d8c4f3f1d..a79edf28b3617 100644
--- a/src/librustc/middle/typeck/check/_match.rs
+++ b/src/librustc/middle/typeck/check/_match.rs
@@ -297,22 +297,38 @@ pub fn check_pat_struct(pcx: &pat_ctxt, pat: &ast::Pat,
     let tcx = pcx.fcx.ccx.tcx;
 
     let def = tcx.def_map.borrow()[pat.id].clone();
-    let def_type = ty::lookup_item_type(tcx, def.def_id());
-    let (enum_def_id, variant_def_id) = match ty::get(def_type.ty).sty {
-        ty::ty_struct(struct_def_id, _) =>
-            (struct_def_id, struct_def_id),
-        ty::ty_enum(enum_def_id, _) if def == def::DefVariant(enum_def_id, def.def_id(), true) =>
-            (enum_def_id, def.def_id()),
-        _ => {
+    let (enum_def_id, variant_def_id) = match def {
+        def::DefTrait(_) => {
             let name = pprust::path_to_string(path);
-            span_err!(tcx.sess, pat.span, E0163,
-                "`{}` does not name a struct or a struct variant", name);
+            span_err!(tcx.sess, pat.span, E0168,
+                "use of trait `{}` in a struct pattern", name);
             fcx.write_error(pat.id);
 
             for field in fields.iter() {
                 check_pat(pcx, &*field.node.pat, ty::mk_err());
             }
             return;
+        },
+        _ => {
+            let def_type = ty::lookup_item_type(tcx, def.def_id());
+            match ty::get(def_type.ty).sty {
+                ty::ty_struct(struct_def_id, _) =>
+                    (struct_def_id, struct_def_id),
+                ty::ty_enum(enum_def_id, _)
+                    if def == def::DefVariant(enum_def_id, def.def_id(), true) =>
+                    (enum_def_id, def.def_id()),
+                _ => {
+                    let name = pprust::path_to_string(path);
+                    span_err!(tcx.sess, pat.span, E0163,
+                        "`{}` does not name a struct or a struct variant", name);
+                    fcx.write_error(pat.id);
+
+                    for field in fields.iter() {
+                        check_pat(pcx, &*field.node.pat, ty::mk_err());
+                    }
+                    return;
+                }
+            }
         }
     };
 
diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs
index 1dd651481693f..8e9ac7095dae1 100644
--- a/src/librustdoc/html/render.rs
+++ b/src/librustdoc/html/render.rs
@@ -2122,7 +2122,7 @@ impl<'a> fmt::Show for Sidebar<'a> {
 
         fn block(w: &mut fmt::Formatter, short: &str, longty: &str,
                  cur: &clean::Item, cx: &Context) -> fmt::Result {
-            let items = match cx.sidebar.find_equiv(short) {
+            let items = match cx.sidebar.get(short) {
                 Some(items) => items.as_slice(),
                 None => return Ok(())
             };
diff --git a/src/libserialize/json.rs b/src/libserialize/json.rs
index 80238f6df415d..03e0452a4158d 100644
--- a/src/libserialize/json.rs
+++ b/src/libserialize/json.rs
@@ -901,7 +901,7 @@ impl Json {
     /// Otherwise, returns None.
     pub fn find<'a>(&'a self, key: &str) -> Option<&'a Json>{
         match self {
-            &Object(ref map) => map.find_with(|s| key.cmp(s.as_slice())),
+            &Object(ref map) => map.get(key),
             _ => None
         }
     }
@@ -926,7 +926,7 @@ impl Json {
     pub fn search<'a>(&'a self, key: &str) -> Option<&'a Json> {
         match self {
             &Object(ref map) => {
-                match map.find_with(|s| key.cmp(s.as_slice())) {
+                match map.get(key) {
                     Some(json_value) => Some(json_value),
                     None => {
                         for (_, v) in map.iter() {
diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs
index 0471d5e902c21..69375e8d4f84e 100644
--- a/src/libstd/collections/hash/map.rs
+++ b/src/libstd/collections/hash/map.rs
@@ -14,6 +14,7 @@ pub use self::Entry::*;
 use self::SearchResult::*;
 use self::VacantEntryState::*;
 
+use borrow::BorrowFrom;
 use clone::Clone;
 use cmp::{max, Eq, Equiv, PartialEq};
 use default::Default;
@@ -142,7 +143,7 @@ impl DefaultResizePolicy {
 // about the size of rust executables.
 //
 // Annotate exceedingly likely branches in `table::make_hash`
-// and `search_hashed_generic` to reduce instruction cache pressure
+// and `search_hashed` to reduce instruction cache pressure
 // and mispredictions once it becomes possible (blocked on issue #11092).
 //
 // Shrinking the table could simply reallocate in place after moving buckets
@@ -286,10 +287,10 @@ pub struct HashMap<K, V, H = RandomSipHasher> {
 }
 
 /// Search for a pre-hashed key.
-fn search_hashed_generic<K, V, M: Deref<RawTable<K, V>>>(table: M,
-                                                         hash: &SafeHash,
-                                                         is_match: |&K| -> bool)
-                                                         -> SearchResult<K, V, M> {
+fn search_hashed<K, V, M: Deref<RawTable<K, V>>>(table: M,
+                                                 hash: &SafeHash,
+                                                 is_match: |&K| -> bool)
+                                                 -> SearchResult<K, V, M> {
     let size = table.size();
     let mut probe = Bucket::new(table, hash);
     let ib = probe.index();
@@ -325,11 +326,6 @@ fn search_hashed_generic<K, V, M: Deref<RawTable<K, V>>>(table: M,
     TableRef(probe.into_table())
 }
 
-fn search_hashed<K: Eq, V, M: Deref<RawTable<K, V>>>(table: M, hash: &SafeHash, k: &K)
-                                                     -> SearchResult<K, V, M> {
-    search_hashed_generic(table, hash, |k_| *k == *k_)
-}
-
 fn pop_internal<K, V>(starting_bucket: FullBucketMut<K, V>) -> (K, V) {
     let (empty, retkey, retval) = starting_bucket.take();
     let mut gap = match empty.gap_peek() {
@@ -432,26 +428,32 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
     fn search_equiv<'a, Sized? Q: Hash<S> + Equiv<K>>(&'a self, q: &Q)
                     -> Option<FullBucketImm<'a, K, V>> {
         let hash = self.make_hash(q);
-        search_hashed_generic(&self.table, &hash, |k| q.equiv(k)).into_option()
+        search_hashed(&self.table, &hash, |k| q.equiv(k)).into_option()
     }
 
     fn search_equiv_mut<'a, Sized? Q: Hash<S> + Equiv<K>>(&'a mut self, q: &Q)
                     -> Option<FullBucketMut<'a, K, V>> {
         let hash = self.make_hash(q);
-        search_hashed_generic(&mut self.table, &hash, |k| q.equiv(k)).into_option()
+        search_hashed(&mut self.table, &hash, |k| q.equiv(k)).into_option()
     }
 
     /// Search for a key, yielding the index if it's found in the hashtable.
     /// If you already have the hash for the key lying around, use
     /// search_hashed.
-    fn search<'a>(&'a self, k: &K) -> Option<FullBucketImm<'a, K, V>> {
-        let hash = self.make_hash(k);
-        search_hashed(&self.table, &hash, k).into_option()
+    fn search<'a, Sized? Q>(&'a self, q: &Q) -> Option<FullBucketImm<'a, K, V>>
+        where Q: BorrowFrom<K> + Eq + Hash<S>
+    {
+        let hash = self.make_hash(q);
+        search_hashed(&self.table, &hash, |k| q.eq(BorrowFrom::borrow_from(k)))
+            .into_option()
     }
 
-    fn search_mut<'a>(&'a mut self, k: &K) -> Option<FullBucketMut<'a, K, V>> {
-        let hash = self.make_hash(k);
-        search_hashed(&mut self.table, &hash, k).into_option()
+    fn search_mut<'a, Sized? Q>(&'a mut self, q: &Q) -> Option<FullBucketMut<'a, K, V>>
+        where Q: BorrowFrom<K> + Eq + Hash<S>
+    {
+        let hash = self.make_hash(q);
+        search_hashed(&mut self.table, &hash, |k| q.eq(BorrowFrom::borrow_from(k)))
+            .into_option()
     }
 
     // The caller should ensure that invariants by Robin Hood Hashing hold.
@@ -748,18 +750,14 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
         }
     }
 
-    /// Return true if the map contains a value for the specified key,
-    /// using equivalence.
-    ///
-    /// See [pop_equiv](#method.pop_equiv) for an extended example.
+    /// Deprecated: use `contains_key` and `BorrowFrom` instead.
+    #[deprecated = "use contains_key and BorrowFrom instead"]
     pub fn contains_key_equiv<Sized? Q: Hash<S> + Equiv<K>>(&self, key: &Q) -> bool {
         self.search_equiv(key).is_some()
     }
 
-    /// Return the value corresponding to the key in the map, using
-    /// equivalence.
-    ///
-    /// See [pop_equiv](#method.pop_equiv) for an extended example.
+    /// Deprecated: use `get` and `BorrowFrom` instead.
+    #[deprecated = "use get and BorrowFrom instead"]
     pub fn find_equiv<'a, Sized? Q: Hash<S> + Equiv<K>>(&'a self, k: &Q) -> Option<&'a V> {
         match self.search_equiv(k) {
             None      => None,
@@ -770,52 +768,8 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
         }
     }
 
-    /// Remove an equivalent key from the map, returning the value at the
-    /// key if the key was previously in the map.
-    ///
-    /// # Example
-    ///
-    /// This is a slightly silly example where we define the number's
-    /// parity as the equivalence class. It is important that the
-    /// values hash the same, which is why we implement `Hash`.
-    ///
-    /// ```
-    /// use std::collections::HashMap;
-    /// use std::hash::Hash;
-    /// use std::hash::sip::SipState;
-    ///
-    /// #[deriving(Eq, PartialEq)]
-    /// struct EvenOrOdd {
-    ///     num: uint
-    /// };
-    ///
-    /// impl Hash for EvenOrOdd {
-    ///     fn hash(&self, state: &mut SipState) {
-    ///         let parity = self.num % 2;
-    ///         parity.hash(state);
-    ///     }
-    /// }
-    ///
-    /// impl Equiv<EvenOrOdd> for EvenOrOdd {
-    ///     fn equiv(&self, other: &EvenOrOdd) -> bool {
-    ///         self.num % 2 == other.num % 2
-    ///     }
-    /// }
-    ///
-    /// let mut map = HashMap::new();
-    /// map.insert(EvenOrOdd { num: 3 }, "foo");
-    ///
-    /// assert!(map.contains_key_equiv(&EvenOrOdd { num: 1 }));
-    /// assert!(!map.contains_key_equiv(&EvenOrOdd { num: 4 }));
-    ///
-    /// assert_eq!(map.find_equiv(&EvenOrOdd { num: 5 }), Some(&"foo"));
-    /// assert_eq!(map.find_equiv(&EvenOrOdd { num: 2 }), None);
-    ///
-    /// assert_eq!(map.pop_equiv(&EvenOrOdd { num: 1 }), Some("foo"));
-    /// assert_eq!(map.pop_equiv(&EvenOrOdd { num: 2 }), None);
-    ///
-    /// ```
-    #[experimental]
+    /// Deprecated: use `remove` and `BorrowFrom` instead.
+    #[deprecated = "use remove and BorrowFrom instead"]
     pub fn pop_equiv<Sized? Q:Hash<S> + Equiv<K>>(&mut self, k: &Q) -> Option<V> {
         if self.table.size() == 0 {
             return None
@@ -1036,6 +990,10 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
 
     /// Returns a reference to the value corresponding to the key.
     ///
+    /// The key may be any borrowed form of the map's key type, but
+    /// `Hash` and `Eq` on the borrowed form *must* match those for
+    /// the key type.
+    ///
     /// # Example
     ///
     /// ```
@@ -1047,7 +1005,9 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
     /// assert_eq!(map.get(&2), None);
     /// ```
     #[unstable = "matches collection reform specification, waiting for dust to settle"]
-    pub fn get(&self, k: &K) -> Option<&V> {
+    pub fn get<Sized? Q>(&self, k: &Q) -> Option<&V>
+        where Q: Hash<S> + Eq + BorrowFrom<K>
+    {
         self.search(k).map(|bucket| {
             let (_, v) = bucket.into_refs();
             v
@@ -1056,6 +1016,10 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
 
     /// Returns true if the map contains a value for the specified key.
     ///
+    /// The key may be any borrowed form of the map's key type, but
+    /// `Hash` and `Eq` on the borrowed form *must* match those for
+    /// the key type.
+    ///
     /// # Example
     ///
     /// ```
@@ -1067,7 +1031,9 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
     /// assert_eq!(map.contains_key(&2), false);
     /// ```
     #[unstable = "matches collection reform specification, waiting for dust to settle"]
-    pub fn contains_key(&self, k: &K) -> bool {
+    pub fn contains_key<Sized? Q>(&self, k: &Q) -> bool
+        where Q: Hash<S> + Eq + BorrowFrom<K>
+    {
         self.search(k).is_some()
     }
 
@@ -1079,6 +1045,10 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
 
     /// Returns a mutable reference to the value corresponding to the key.
     ///
+    /// The key may be any borrowed form of the map's key type, but
+    /// `Hash` and `Eq` on the borrowed form *must* match those for
+    /// the key type.
+    ///
     /// # Example
     ///
     /// ```
@@ -1093,7 +1063,9 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
     /// assert_eq!(map[1], "b");
     /// ```
     #[unstable = "matches collection reform specification, waiting for dust to settle"]
-    pub fn get_mut(&mut self, k: &K) -> Option<&mut V> {
+    pub fn get_mut<Sized? Q>(&mut self, k: &Q) -> Option<&mut V>
+        where Q: Hash<S> + Eq + BorrowFrom<K>
+    {
         match self.search_mut(k) {
             Some(bucket) => {
                 let (_, v) = bucket.into_mut_refs();
@@ -1147,6 +1119,10 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
     /// Removes a key from the map, returning the value at the key if the key
     /// was previously in the map.
     ///
+    /// The key may be any borrowed form of the map's key type, but
+    /// `Hash` and `Eq` on the borrowed form *must* match those for
+    /// the key type.
+    ///
     /// # Example
     ///
     /// ```
@@ -1158,7 +1134,9 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
     /// assert_eq!(map.remove(&1), None);
     /// ```
     #[unstable = "matches collection reform specification, waiting for dust to settle"]
-    pub fn remove(&mut self, k: &K) -> Option<V> {
+    pub fn remove<Sized? Q>(&mut self, k: &Q) -> Option<V>
+        where Q: Hash<S> + Eq + BorrowFrom<K>
+    {
         if self.table.size() == 0 {
             return None
         }
@@ -1271,16 +1249,20 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S> + Default> Default for HashMap<K, V, H>
     }
 }
 
-impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> Index<K, V> for HashMap<K, V, H> {
+impl<K: Hash<S> + Eq, Sized? Q, V, S, H: Hasher<S>> Index<Q, V> for HashMap<K, V, H>
+    where Q: BorrowFrom<K> + Hash<S> + Eq
+{
     #[inline]
-    fn index<'a>(&'a self, index: &K) -> &'a V {
+    fn index<'a>(&'a self, index: &Q) -> &'a V {
         self.get(index).expect("no entry found for key")
     }
 }
 
-impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> IndexMut<K, V> for HashMap<K, V, H> {
+impl<K: Hash<S> + Eq, Sized? Q, V, S, H: Hasher<S>> IndexMut<Q, V> for HashMap<K, V, H>
+    where Q: BorrowFrom<K> + Hash<S> + Eq
+{
     #[inline]
-    fn index_mut<'a>(&'a mut self, index: &K) -> &'a mut V {
+    fn index_mut<'a>(&'a mut self, index: &Q) -> &'a mut V {
         match self.get_mut(index) {
             Some(v) => v,
             None => panic!("no entry found for key")
@@ -1962,11 +1944,11 @@ mod test_map {
         m.insert("baz".to_string(), baz);
 
 
-        assert_eq!(m.find_equiv("foo"), Some(&foo));
-        assert_eq!(m.find_equiv("bar"), Some(&bar));
-        assert_eq!(m.find_equiv("baz"), Some(&baz));
+        assert_eq!(m.get("foo"), Some(&foo));
+        assert_eq!(m.get("bar"), Some(&bar));
+        assert_eq!(m.get("baz"), Some(&baz));
 
-        assert_eq!(m.find_equiv("qux"), None);
+        assert_eq!(m.get("qux"), None);
     }
 
     #[test]
diff --git a/src/libstd/collections/hash/set.rs b/src/libstd/collections/hash/set.rs
index 4326fae16fc91..2fbcb464358b3 100644
--- a/src/libstd/collections/hash/set.rs
+++ b/src/libstd/collections/hash/set.rs
@@ -10,6 +10,7 @@
 //
 // ignore-lexer-test FIXME #15883
 
+use borrow::BorrowFrom;
 use cmp::{Eq, Equiv, PartialEq};
 use core::kinds::Sized;
 use default::Default;
@@ -184,47 +185,9 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> {
         self.map.reserve(n)
     }
 
-    /// Returns true if the hash set contains a value equivalent to the
-    /// given query value.
-    ///
-    /// # Example
-    ///
-    /// This is a slightly silly example where we define the number's
-    /// parity as the equivalance class. It is important that the
-    /// values hash the same, which is why we implement `Hash`.
-    ///
-    /// ```
-    /// use std::collections::HashSet;
-    /// use std::hash::Hash;
-    /// use std::hash::sip::SipState;
-    ///
-    /// #[deriving(Eq, PartialEq)]
-    /// struct EvenOrOdd {
-    ///     num: uint
-    /// };
-    ///
-    /// impl Hash for EvenOrOdd {
-    ///     fn hash(&self, state: &mut SipState) {
-    ///         let parity = self.num % 2;
-    ///         parity.hash(state);
-    ///     }
-    /// }
-    ///
-    /// impl Equiv<EvenOrOdd> for EvenOrOdd {
-    ///     fn equiv(&self, other: &EvenOrOdd) -> bool {
-    ///         self.num % 2 == other.num % 2
-    ///     }
-    /// }
-    ///
-    /// let mut set = HashSet::new();
-    /// set.insert(EvenOrOdd { num: 3u });
-    ///
-    /// assert!(set.contains_equiv(&EvenOrOdd { num: 3u }));
-    /// assert!(set.contains_equiv(&EvenOrOdd { num: 5u }));
-    /// assert!(!set.contains_equiv(&EvenOrOdd { num: 4u }));
-    /// assert!(!set.contains_equiv(&EvenOrOdd { num: 2u }));
-    ///
-    /// ```
+    /// Deprecated: use `contains` and `BorrowFrom`.
+    #[deprecated = "use contains and BorrowFrom"]
+    #[allow(deprecated)]
     pub fn contains_equiv<Sized? Q: Hash<S> + Equiv<T>>(&self, value: &Q) -> bool {
       self.map.contains_key_equiv(value)
     }
@@ -427,6 +390,10 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> {
 
     /// Returns `true` if the set contains a value.
     ///
+    /// The value may be any borrowed form of the set's value type, but
+    /// `Hash` and `Eq` on the borrowed form *must* match those for
+    /// the value type.
+    ///
     /// # Example
     ///
     /// ```
@@ -437,7 +404,11 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> {
     /// assert_eq!(set.contains(&4), false);
     /// ```
     #[unstable = "matches collection reform specification, waiting for dust to settle"]
-    pub fn contains(&self, value: &T) -> bool { self.map.contains_key(value) }
+    pub fn contains<Sized? Q>(&self, value: &Q) -> bool
+        where Q: BorrowFrom<T> + Hash<S> + Eq
+    {
+        self.map.contains_key(value)
+    }
 
     /// Returns `true` if the set has no elements in common with `other`.
     /// This is equivalent to checking for an empty intersection.
@@ -527,6 +498,10 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> {
     /// Removes a value from the set. Returns `true` if the value was
     /// present in the set.
     ///
+    /// The value may be any borrowed form of the set's value type, but
+    /// `Hash` and `Eq` on the borrowed form *must* match those for
+    /// the value type.
+    ///
     /// # Example
     ///
     /// ```
@@ -539,7 +514,11 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> {
     /// assert_eq!(set.remove(&2), false);
     /// ```
     #[unstable = "matches collection reform specification, waiting for dust to settle"]
-    pub fn remove(&mut self, value: &T) -> bool { self.map.remove(value).is_some() }
+    pub fn remove<Sized? Q>(&mut self, value: &Q) -> bool
+        where Q: BorrowFrom<T> + Hash<S> + Eq
+    {
+        self.map.remove(value).is_some()
+    }
 }
 
 impl<T: Eq + Hash<S>, S, H: Hasher<S>> PartialEq for HashSet<T, H> {
diff --git a/src/libstd/collections/hash/table.rs b/src/libstd/collections/hash/table.rs
index 76e15f7375c01..f41ccea0aaf03 100644
--- a/src/libstd/collections/hash/table.rs
+++ b/src/libstd/collections/hash/table.rs
@@ -718,7 +718,7 @@ impl<'a, K, V> Iterator<RawBucket<K, V>> for RawBuckets<'a, K, V> {
 }
 
 /// An iterator that moves out buckets in reverse order. It leaves the table
-/// in an an inconsistent state and should only be used for dropping
+/// in an inconsistent state and should only be used for dropping
 /// the table's remaining entries. It's used in the implementation of Drop.
 struct RevMoveBuckets<'a, K, V> {
     raw: RawBucket<K, V>,
diff --git a/src/libstd/io/fs.rs b/src/libstd/io/fs.rs
index 3f39dda650aff..cd4141e045cb5 100644
--- a/src/libstd/io/fs.rs
+++ b/src/libstd/io/fs.rs
@@ -381,16 +381,8 @@ pub fn copy(from: &Path, to: &Path) -> IoResult<()> {
 
     let mut reader = try!(File::open(from));
     let mut writer = try!(File::create(to));
-    let mut buf = [0, ..io::DEFAULT_BUF_SIZE];
 
-    loop {
-        let amt = match reader.read(&mut buf) {
-            Ok(n) => n,
-            Err(ref e) if e.kind == io::EndOfFile => { break }
-            Err(e) => return update_err(Err(e), from, to)
-        };
-        try!(writer.write(buf[..amt]));
-    }
+    try!(update_err(super::util::copy(&mut reader, &mut writer), from, to));
 
     chmod(to, try!(update_err(from.stat(), from, to)).perm)
 }
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index 612613134d448..7f2a4c7e36569 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -141,6 +141,7 @@ extern crate rustrt;
 
 pub use core::any;
 pub use core::bool;
+pub use core::borrow;
 pub use core::cell;
 pub use core::clone;
 #[cfg(not(test))] pub use core::cmp;
diff --git a/src/libstd/os.rs b/src/libstd/os.rs
index f5aa2259f8d9c..be8e4695fa943 100644
--- a/src/libstd/os.rs
+++ b/src/libstd/os.rs
@@ -81,7 +81,7 @@ const BUF_BYTES : uint = 2048u;
 /// # Failure
 ///
 /// Fails if the current working directory value is invalid:
-/// Possibles cases:
+/// Possible cases:
 ///
 /// * Current directory does not exist.
 /// * There are insufficient permissions to access the current directory.
diff --git a/src/libstd/time/duration.rs b/src/libstd/time/duration.rs
index 83340c9faac22..39ca3128ccb2b 100644
--- a/src/libstd/time/duration.rs
+++ b/src/libstd/time/duration.rs
@@ -554,11 +554,4 @@ mod tests {
         assert_eq!(format!("{:30}", Duration::days(1) + Duration::milliseconds(2345)),
                    "P1DT2.345S".to_string());
     }
-
-    #[test]
-    fn span() {
-        use io::timer::sleep;
-        let dur = Duration::span(|| sleep(Duration::milliseconds(5)));
-        assert!(dur > Duration::milliseconds(1));
-    }
 }
diff --git a/src/libsyntax/diagnostics/registry.rs b/src/libsyntax/diagnostics/registry.rs
index 71d82a41f3868..4caef247aebc2 100644
--- a/src/libsyntax/diagnostics/registry.rs
+++ b/src/libsyntax/diagnostics/registry.rs
@@ -20,6 +20,6 @@ impl Registry {
     }
 
     pub fn find_description(&self, code: &str) -> Option<&'static str> {
-        self.descriptions.find_equiv(code).map(|desc| *desc)
+        self.descriptions.get(code).map(|desc| *desc)
     }
 }
diff --git a/src/libsyntax/ext/asm.rs b/src/libsyntax/ext/asm.rs
index 8027d9bfd8a8e..d04144ef26e59 100644
--- a/src/libsyntax/ext/asm.rs
+++ b/src/libsyntax/ext/asm.rs
@@ -97,8 +97,8 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
                     // cannot be shared with any other operand (usually when
                     // a register is clobbered early.)
                     let output = match constraint.get().slice_shift_char() {
-                        (Some('='), _) => None,
-                        (Some('+'), operand) => {
+                        Some(('=', _)) => None,
+                        Some(('+', operand)) => {
                             Some(token::intern_and_get_ident(format!(
                                         "={}",
                                         operand).as_slice()))
diff --git a/src/libsyntax/ext/format.rs b/src/libsyntax/ext/format.rs
index 9a9724de8fb70..f1b92b4d6bc1d 100644
--- a/src/libsyntax/ext/format.rs
+++ b/src/libsyntax/ext/format.rs
@@ -144,7 +144,7 @@ fn parse_args(ecx: &mut ExtCtxt, sp: Span, allow_method: bool,
             let name = interned_name.get();
             p.expect(&token::Eq);
             let e = p.parse_expr();
-            match names.find_equiv(name) {
+            match names.get(name) {
                 None => {}
                 Some(prev) => {
                     ecx.span_err(e.span,
@@ -366,7 +366,7 @@ impl<'a, 'b> Context<'a, 'b> {
                 self.ecx.expr_path(path)
             }
             parse::CountIsName(n) => {
-                let i = match self.name_positions.find_equiv(n) {
+                let i = match self.name_positions.get(n) {
                     Some(&i) => i,
                     None => 0, // error already emitted elsewhere
                 };
@@ -410,7 +410,7 @@ impl<'a, 'b> Context<'a, 'b> {
                     // Named arguments are converted to positional arguments at
                     // the end of the list of arguments
                     parse::ArgumentNamed(n) => {
-                        let i = match self.name_positions.find_equiv(n) {
+                        let i = match self.name_positions.get(n) {
                             Some(&i) => i,
                             None => 0, // error already emitted elsewhere
                         };
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index 0178566fb0621..0c31e9ae01d75 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -182,6 +182,10 @@ impl<'a, 'v> Visitor<'v> for Context<'a> {
                                   "`#[thread_local]` is an experimental feature, and does not \
                                   currently handle destructors. There is no corresponding \
                                   `#[task_local]` mapping to the task model");
+            } else if attr.name().equiv(&("linkage")) {
+                self.gate_feature("linkage", i.span,
+                                  "the `linkage` attribute is experimental \
+                                   and not portable across platforms")
             }
         }
         match i.node {
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 5c95c369f94a8..98479d65cbb2f 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -1232,7 +1232,8 @@ impl<'a> Parser<'a> {
     {
         if self.eat(&token::Lt) {
             if lifetime_defs.is_empty() {
-                self.warn("deprecated syntax, use `for` keyword now");
+                self.warn("deprecated syntax; use the `for` keyword now \
+                            (e.g. change `fn<'a>` to `for<'a> fn`)");
                 let lifetime_defs = self.parse_lifetime_defs();
                 self.expect_gt();
                 lifetime_defs
@@ -5178,7 +5179,15 @@ impl<'a> Parser<'a> {
             if self.eat(&token::OpenDelim(token::Brace)) {
                 // Parse a struct variant.
                 all_nullary = false;
-                kind = StructVariantKind(self.parse_struct_def());
+                let start_span = self.span;
+                let struct_def = self.parse_struct_def();
+                if struct_def.fields.len() == 0 {
+                    self.span_err(start_span,
+                        format!("unit-like struct variant should be written \
+                                 without braces, as `{},`",
+                                token::get_ident(ident)).as_slice());
+                }
+                kind = StructVariantKind(struct_def);
             } else if self.token == token::OpenDelim(token::Paren) {
                 all_nullary = false;
                 let arg_tys = self.parse_enum_variant_seq(
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index 390a5cc68d30b..81f3d977e13ff 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -1855,7 +1855,7 @@ impl<'a> State<'a> {
                 try!(self.commasep(Inconsistent, a.outputs.as_slice(),
                                    |s, &(ref co, ref o, is_rw)| {
                     match co.get().slice_shift_char() {
-                        (Some('='), operand) if is_rw => {
+                        Some(('=', operand)) if is_rw => {
                             try!(s.print_string(format!("+{}", operand).as_slice(),
                                                 ast::CookedStr))
                         }
diff --git a/src/libsyntax/util/interner.rs b/src/libsyntax/util/interner.rs
index 08ada3e443590..ede967bba25cd 100644
--- a/src/libsyntax/util/interner.rs
+++ b/src/libsyntax/util/interner.rs
@@ -14,9 +14,9 @@
 
 use ast::Name;
 
+use std::borrow::BorrowFrom;
 use std::collections::HashMap;
 use std::cell::RefCell;
-use std::cmp::Equiv;
 use std::fmt;
 use std::hash::Hash;
 use std::rc::Rc;
@@ -75,9 +75,10 @@ impl<T: Eq + Hash + Clone + 'static> Interner<T> {
         (*vect).len()
     }
 
-    pub fn find_equiv<Sized? Q: Hash + Equiv<T>>(&self, val: &Q) -> Option<Name> {
+    pub fn find<Sized? Q>(&self, val: &Q) -> Option<Name>
+    where Q: BorrowFrom<T> + Eq + Hash {
         let map = self.map.borrow();
-        match (*map).find_equiv(val) {
+        match (*map).get(val) {
             Some(v) => Some(*v),
             None => None,
         }
@@ -117,6 +118,12 @@ impl fmt::Show for RcStr {
     }
 }
 
+impl BorrowFrom<RcStr> for str {
+    fn borrow_from(owned: &RcStr) -> &str {
+        owned.string.as_slice()
+    }
+}
+
 impl RcStr {
     pub fn new(string: &str) -> RcStr {
         RcStr {
@@ -149,7 +156,7 @@ impl StrInterner {
 
     pub fn intern(&self, val: &str) -> Name {
         let mut map = self.map.borrow_mut();
-        match map.find_equiv(val) {
+        match map.get(val) {
             Some(&idx) => return idx,
             None => (),
         }
@@ -195,8 +202,9 @@ impl StrInterner {
         self.vect.borrow().len()
     }
 
-    pub fn find_equiv<Sized? Q:Hash + Equiv<RcStr>>(&self, val: &Q) -> Option<Name> {
-        match (*self.map.borrow()).find_equiv(val) {
+    pub fn find<Sized? Q>(&self, val: &Q) -> Option<Name>
+    where Q: BorrowFrom<RcStr> + Eq + Hash {
+        match (*self.map.borrow()).get(val) {
             Some(v) => Some(*v),
             None => None,
         }
diff --git a/src/libterm/terminfo/mod.rs b/src/libterm/terminfo/mod.rs
index 0b5092a64d0f3..c1393767c8adc 100644
--- a/src/libterm/terminfo/mod.rs
+++ b/src/libterm/terminfo/mod.rs
@@ -78,7 +78,7 @@ impl<T: Writer+Send> Terminal<T> for TerminfoTerminal<T> {
         if self.num_colors > color {
             let s = expand(self.ti
                                .strings
-                               .find_equiv("setaf")
+                               .get("setaf")
                                .unwrap()
                                .as_slice(),
                            &[Number(color as int)], &mut Variables::new());
@@ -95,7 +95,7 @@ impl<T: Writer+Send> Terminal<T> for TerminfoTerminal<T> {
         if self.num_colors > color {
             let s = expand(self.ti
                                .strings
-                               .find_equiv("setab")
+                               .get("setab")
                                .unwrap()
                                .as_slice(),
                            &[Number(color as int)], &mut Variables::new());
@@ -113,7 +113,7 @@ impl<T: Writer+Send> Terminal<T> for TerminfoTerminal<T> {
             attr::BackgroundColor(c) => self.bg(c),
             _ => {
                 let cap = cap_for_attr(attr);
-                let parm = self.ti.strings.find_equiv(cap);
+                let parm = self.ti.strings.get(cap);
                 if parm.is_some() {
                     let s = expand(parm.unwrap().as_slice(),
                                    &[],
@@ -135,19 +135,19 @@ impl<T: Writer+Send> Terminal<T> for TerminfoTerminal<T> {
             }
             _ => {
                 let cap = cap_for_attr(attr);
-                self.ti.strings.find_equiv(cap).is_some()
+                self.ti.strings.get(cap).is_some()
             }
         }
     }
 
     fn reset(&mut self) -> IoResult<()> {
-        let mut cap = self.ti.strings.find_equiv("sgr0");
+        let mut cap = self.ti.strings.get("sgr0");
         if cap.is_none() {
             // are there any terminals that have color/attrs and not sgr0?
             // Try falling back to sgr, then op
-            cap = self.ti.strings.find_equiv("sgr");
+            cap = self.ti.strings.get("sgr");
             if cap.is_none() {
-                cap = self.ti.strings.find_equiv("op");
+                cap = self.ti.strings.get("op");
             }
         }
         let s = cap.map_or(Err("can't find terminfo capability `sgr0`".to_string()), |op| {
@@ -202,9 +202,9 @@ impl<T: Writer+Send> TerminfoTerminal<T> {
         }
 
         let inf = ti.unwrap();
-        let nc = if inf.strings.find_equiv("setaf").is_some()
-                 && inf.strings.find_equiv("setab").is_some() {
-                     inf.numbers.find_equiv("colors").map_or(0, |&n| n)
+        let nc = if inf.strings.get("setaf").is_some()
+                 && inf.strings.get("setab").is_some() {
+                     inf.numbers.get("colors").map_or(0, |&n| n)
                  } else { 0 };
 
         return Some(box TerminfoTerminal {out: out,
diff --git a/src/test/bench/shootout-k-nucleotide-pipes.rs b/src/test/bench/shootout-k-nucleotide-pipes.rs
index e40c477ec66ef..e39cd743ad55a 100644
--- a/src/test/bench/shootout-k-nucleotide-pipes.rs
+++ b/src/test/bench/shootout-k-nucleotide-pipes.rs
@@ -76,7 +76,7 @@ fn sort_and_fmt(mm: &HashMap<Vec<u8> , uint>, total: uint) -> String {
 // given a map, search for the frequency of a pattern
 fn find(mm: &HashMap<Vec<u8> , uint>, key: String) -> uint {
    let key = key.into_ascii().as_slice().to_lowercase().into_string();
-   match mm.find_equiv(key.as_bytes()) {
+   match mm.get(key.as_bytes()) {
       option::None      => { return 0u; }
       option::Some(&num) => { return num; }
    }
diff --git a/src/test/compile-fail-fulldeps/issue-18986.rs b/src/test/compile-fail-fulldeps/issue-18986.rs
new file mode 100644
index 0000000000000..25d78c273e77a
--- /dev/null
+++ b/src/test/compile-fail-fulldeps/issue-18986.rs
@@ -0,0 +1,20 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:use_from_trait_xc.rs
+
+extern crate use_from_trait_xc;
+pub use use_from_trait_xc::Trait;
+
+fn main() {
+    match () {
+        Trait { x: 42u } => () //~ ERROR use of trait `Trait` in a struct pattern
+    }
+}
diff --git a/src/test/compile-fail/linkage4.rs b/src/test/compile-fail/linkage4.rs
new file mode 100644
index 0000000000000..8f68f3e553cd7
--- /dev/null
+++ b/src/test/compile-fail/linkage4.rs
@@ -0,0 +1,15 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#[linkage = "external"]
+static foo: int = 0;
+//~^ ERROR: the `linkage` attribute is experimental and not portable
+
+fn main() {}
diff --git a/src/test/compile-fail/lint-stability.rs b/src/test/compile-fail/lint-stability.rs
index 9e397ce9d8d13..8e1723ddab24c 100644
--- a/src/test/compile-fail/lint-stability.rs
+++ b/src/test/compile-fail/lint-stability.rs
@@ -459,6 +459,20 @@ mod this_crate {
         foo.trait_stable();
     }
 
+    #[deprecated]
+    fn test_fn_body() {
+        fn fn_in_body() {}
+        fn_in_body();
+    }
+
+    impl MethodTester {
+        #[deprecated]
+        fn test_method_body(&self) {
+            fn fn_in_body() {}
+            fn_in_body();
+        }
+    }
+
     #[deprecated]
     pub trait DeprecatedTrait {}
 
diff --git a/src/test/compile-fail/struct-variant-no-fields.rs b/src/test/compile-fail/struct-variant-no-fields.rs
new file mode 100644
index 0000000000000..41dbbeefc0a60
--- /dev/null
+++ b/src/test/compile-fail/struct-variant-no-fields.rs
@@ -0,0 +1,13 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+enum Foo {
+    Bar {} //~ ERROR unit-like struct variant should be written without braces, as `Bar,`
+}
diff --git a/src/test/run-make/linkage-attr-on-static/Makefile b/src/test/run-make/linkage-attr-on-static/Makefile
new file mode 100644
index 0000000000000..6bcde96335cff
--- /dev/null
+++ b/src/test/run-make/linkage-attr-on-static/Makefile
@@ -0,0 +1,8 @@
+-include ../tools.mk
+
+all:
+	$(CC) foo.c -c -o $(TMPDIR)/foo.o
+	$(AR) rcs $(TMPDIR)/libfoo.a $(TMPDIR)/foo.o
+	$(RUSTC) bar.rs -lfoo -L $(TMPDIR)
+	$(call RUN,bar) || exit 1
+
diff --git a/src/test/run-make/linkage-attr-on-static/bar.rs b/src/test/run-make/linkage-attr-on-static/bar.rs
new file mode 100644
index 0000000000000..6125421bdeb6c
--- /dev/null
+++ b/src/test/run-make/linkage-attr-on-static/bar.rs
@@ -0,0 +1,25 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(linkage)]
+
+#[no_mangle]
+#[linkage = "external"]
+static BAZ: i32 = 21;
+
+extern {
+    fn what() -> i32;
+}
+
+fn main() {
+    unsafe {
+        assert_eq!(what(), BAZ);
+    }
+}
diff --git a/src/test/run-make/linkage-attr-on-static/foo.c b/src/test/run-make/linkage-attr-on-static/foo.c
new file mode 100644
index 0000000000000..78a6934f57f76
--- /dev/null
+++ b/src/test/run-make/linkage-attr-on-static/foo.c
@@ -0,0 +1,7 @@
+#include <stdint.h>
+
+extern int32_t BAZ;
+
+int32_t what() {
+    return BAZ;
+}
diff --git a/src/test/run-pass/issue-19037.rs b/src/test/run-pass/issue-19037.rs
new file mode 100644
index 0000000000000..a6b5f4b874466
--- /dev/null
+++ b/src/test/run-pass/issue-19037.rs
@@ -0,0 +1,26 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+struct Str([u8]);
+
+#[deriving(Clone)]
+struct CharSplits<'a, Sep> {
+    string: &'a Str,
+    sep: Sep,
+    allow_trailing_empty: bool,
+    only_ascii: bool,
+    finished: bool,
+}
+
+fn clone(s: &Str) -> &Str {
+    Clone::clone(&s)
+}
+
+fn main() {}