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() {}