From bbec2c54edd347b084734d01826675ae2dffc636 Mon Sep 17 00:00:00 2001 From: Brian Leibig Date: Tue, 25 Feb 2014 08:47:58 -0800 Subject: [PATCH 01/19] Add new target 'make dist-osx' to create a .pkg installer for OS X --- mk/dist.mk | 34 +++++++++++++++++++++++++++++++++- src/etc/pkg/Distribution.xml | 22 ++++++++++++++++++++++ 2 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 src/etc/pkg/Distribution.xml diff --git a/mk/dist.mk b/mk/dist.mk index 1a4d7a278437f..0eb0365a59976 100644 --- a/mk/dist.mk +++ b/mk/dist.mk @@ -12,6 +12,10 @@ PKG_ICO = $(S)src/etc/pkg/rust-logo.ico PKG_EXE = $(PKG_DIR)-install.exe endif +ifeq ($(CFG_OSTYPE), apple-darwin) +PKG_OSX = $(PKG_DIR).pkg +endif + PKG_GITMODULES := $(S)src/libuv $(S)src/llvm $(S)src/gyp $(S)src/compiler-rt PKG_FILES := \ @@ -41,10 +45,10 @@ PKG_FILES := \ UNROOTED_PKG_FILES := $(patsubst $(S)%,./%,$(PKG_FILES)) -ifdef CFG_ISCC LICENSE.txt: $(S)COPYRIGHT $(S)LICENSE-APACHE $(S)LICENSE-MIT cat $^ > $@ +ifdef CFG_ISCC %.iss: $(S)src/etc/pkg/%.iss cp $< $@ @@ -124,3 +128,31 @@ distcheck: $(PKG_TAR) @echo ----------------------------------------------- endif + +ifeq ($(CFG_OSTYPE), apple-darwin) + +dist-prepare-osx: PREPARE_HOST=$(CFG_BUILD) +dist-prepare-osx: PREPARE_TARGETS=$(CFG_BUILD) +dist-prepare-osx: PREPARE_DEST_DIR=pkgroot +dist-prepare-osx: PREPARE_STAGE=2 +dist-prepare-osx: PREPARE_DIR_CMD=$(DEFAULT_PREPARE_DIR_CMD) +dist-prepare-osx: PREPARE_BIN_CMD=$(DEFAULT_PREPARE_BIN_CMD) +dist-prepare-osx: PREPARE_LIB_CMD=$(DEFAULT_PREPARE_LIB_CMD) +dist-prepare-osx: PREPARE_MAN_CMD=$(DEFAULT_PREPARE_MAN_CMD) +dist-prepare-osx: prepare-base + +$(PKG_OSX): Distribution.xml LICENSE.txt dist-prepare-osx + @$(call E, making OS X pkg) + $(Q)pkgbuild --identifier org.rust-lang.rust --root pkgroot rust.pkg + $(Q)productbuild --distribution Distribution.xml --resources . $(PKG_OSX) + $(Q)rm -rf pkgroot rust.pkg + +dist-osx: $(PKG_OSX) + +distcheck-osx: $(PKG_OSX) + @echo + @echo ----------------------------------------------- + @echo $(PKG_OSX) ready for distribution + @echo ----------------------------------------------- + +endif diff --git a/src/etc/pkg/Distribution.xml b/src/etc/pkg/Distribution.xml new file mode 100644 index 0000000000000..9c2e5d6588433 --- /dev/null +++ b/src/etc/pkg/Distribution.xml @@ -0,0 +1,22 @@ + + + Rust + + + + + + + + + + + + + + + + + + rust.pkg + From 4d4ccb5d81362999ab9dc9534b507340995ad0ac Mon Sep 17 00:00:00 2001 From: Brian Leibig Date: Wed, 26 Feb 2014 08:59:58 -0800 Subject: [PATCH 02/19] Make OS X installer build from /tmp/dist/pkgroot, and have it be part of the 'make dist' target --- mk/dist.mk | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/mk/dist.mk b/mk/dist.mk index 0eb0365a59976..17afeaae37732 100644 --- a/mk/dist.mk +++ b/mk/dist.mk @@ -107,7 +107,7 @@ distcheck: dist else -dist: $(PKG_TAR) +dist: $(PKG_TAR) $(PKG_OSX) distcheck: $(PKG_TAR) $(Q)rm -Rf dist @@ -133,7 +133,7 @@ ifeq ($(CFG_OSTYPE), apple-darwin) dist-prepare-osx: PREPARE_HOST=$(CFG_BUILD) dist-prepare-osx: PREPARE_TARGETS=$(CFG_BUILD) -dist-prepare-osx: PREPARE_DEST_DIR=pkgroot +dist-prepare-osx: PREPARE_DEST_DIR=tmp/dist/pkgroot dist-prepare-osx: PREPARE_STAGE=2 dist-prepare-osx: PREPARE_DIR_CMD=$(DEFAULT_PREPARE_DIR_CMD) dist-prepare-osx: PREPARE_BIN_CMD=$(DEFAULT_PREPARE_BIN_CMD) @@ -143,9 +143,9 @@ dist-prepare-osx: prepare-base $(PKG_OSX): Distribution.xml LICENSE.txt dist-prepare-osx @$(call E, making OS X pkg) - $(Q)pkgbuild --identifier org.rust-lang.rust --root pkgroot rust.pkg + $(Q)pkgbuild --identifier org.rust-lang.rust --root tmp/dist/pkgroot rust.pkg $(Q)productbuild --distribution Distribution.xml --resources . $(PKG_OSX) - $(Q)rm -rf pkgroot rust.pkg + $(Q)rm -rf tmp rust.pkg dist-osx: $(PKG_OSX) From cdc5729ea2dc98f83c9a88ce7aa0f52ba5a606e6 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 26 Feb 2014 08:52:08 -0800 Subject: [PATCH 03/19] rustc: Move local native libs back in link-args With linkers on unix systems, libraries on the right of the command line are used to resolve symbols in those on the left of the command line. This means that arguments must have a right-to-left dependency chain (things on the left depend on things on the right). This is currently done by ordering the linker arguments as 1. Local object 2. Local native libraries 3. Upstream rust libraries 4. Upstream native libraries This commit swaps the order of 2 and 3 so upstream rust libraries have access to local native libraries. It has been seen that some upstream crates don't specify the library that they link to because the name varies per platform (e.g. lua/glfw/etc). This commit enables building these libraries by allowing the upstream rust crate to have access to local native libraries. I believe that the failure mode for this scheme is when an upstream rust crate depends on a symbol in an upstream library which is then redefined in a local library. This failure mode is incredibly uncommon, and the failure mode also varies per platform (OSX behaves differently), so I believe that a change like this is fine to make. Closes #12446 --- src/librustc/back/link.rs | 35 +++++++++++++++++++++++++- src/test/run-make/issue-12446/Makefile | 6 +++++ src/test/run-make/issue-12446/bar.rs | 18 +++++++++++++ src/test/run-make/issue-12446/foo.c | 1 + src/test/run-make/issue-12446/foo.rs | 19 ++++++++++++++ 5 files changed, 78 insertions(+), 1 deletion(-) create mode 100644 src/test/run-make/issue-12446/Makefile create mode 100644 src/test/run-make/issue-12446/bar.rs create mode 100644 src/test/run-make/issue-12446/foo.c create mode 100644 src/test/run-make/issue-12446/foo.rs diff --git a/src/librustc/back/link.rs b/src/librustc/back/link.rs index bfc7fdb14666f..33d3a1c67f2e2 100644 --- a/src/librustc/back/link.rs +++ b/src/librustc/back/link.rs @@ -1132,8 +1132,41 @@ fn link_args(sess: Session, args.push(~"-Wl,--allow-multiple-definition"); } - add_local_native_libraries(&mut args, sess); + // Take careful note of the ordering of the arguments we pass to the linker + // here. Linkers will assume that things on the left depend on things to the + // right. Things on the right cannot depend on things on the left. This is + // all formally implemented in terms of resolving symbols (libs on the right + // resolve unknown symbols of libs on the left, but not vice versa). + // + // For this reason, we have organized the arguments we pass to the linker as + // such: + // + // 1. The local object that LLVM just generated + // 2. Upstream rust libraries + // 3. Local native libraries + // 4. Upstream native libraries + // + // This is generally fairly natural, but some may expect 2 and 3 to be + // swapped. The reason that all native libraries are put last is that it's + // not recommended for a native library to depend on a symbol from a rust + // crate. If this is the case then a staticlib crate is recommended, solving + // the problem. + // + // Additionally, it is occasionally the case that upstream rust libraries + // depend on a local native library. In the case of libraries such as + // lua/glfw/etc the name of the library isn't the same across all platforms, + // so only the consumer crate of a library knows the actual name. This means + // that downstream crates will provide the #[link] attribute which upstream + // crates will depend on. Hence local native libraries are after out + // upstream rust crates. + // + // In theory this means that a symbol in an upstream native library will be + // shadowed by a local native library when it wouldn't have been before, but + // this kind of behavior is pretty platform specific and generally not + // recommended anyway, so I don't think we're shooting ourself in the foot + // much with that. add_upstream_rust_crates(&mut args, sess, dylib, tmpdir); + add_local_native_libraries(&mut args, sess); add_upstream_native_libraries(&mut args, sess); // # Telling the linker what we're doing diff --git a/src/test/run-make/issue-12446/Makefile b/src/test/run-make/issue-12446/Makefile new file mode 100644 index 0000000000000..e864ee0058c7e --- /dev/null +++ b/src/test/run-make/issue-12446/Makefile @@ -0,0 +1,6 @@ +-include ../tools.mk + +all: $(call STATICLIB,foo) + $(RUSTC) foo.rs + $(RUSTC) bar.rs + $(call RUN,bar) diff --git a/src/test/run-make/issue-12446/bar.rs b/src/test/run-make/issue-12446/bar.rs new file mode 100644 index 0000000000000..cd41058744d5a --- /dev/null +++ b/src/test/run-make/issue-12446/bar.rs @@ -0,0 +1,18 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +extern crate foo; + +#[link(name = "foo")] +extern {} + +fn main() { + foo::foo(); +} diff --git a/src/test/run-make/issue-12446/foo.c b/src/test/run-make/issue-12446/foo.c new file mode 100644 index 0000000000000..a58cd8bb7c98f --- /dev/null +++ b/src/test/run-make/issue-12446/foo.c @@ -0,0 +1 @@ +void some_c_symbol() {} diff --git a/src/test/run-make/issue-12446/foo.rs b/src/test/run-make/issue-12446/foo.rs new file mode 100644 index 0000000000000..f16dd5e1d5c30 --- /dev/null +++ b/src/test/run-make/issue-12446/foo.rs @@ -0,0 +1,19 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[crate_type = "rlib"]; + +extern { + fn some_c_symbol(); +} + +pub fn foo() { + unsafe { some_c_symbol() } +} From e3a251a41021ae0f8c0d97235d9da9d38e0d9f4a Mon Sep 17 00:00:00 2001 From: Felix Crux Date: Wed, 26 Feb 2014 20:27:30 -0500 Subject: [PATCH 04/19] Provide a more helpful error for tests that fail due to noexec The rustdoc tests create and execute a file in a temporary directory. By default on UNIX-like platforms this is in `/tmp`, which some users mount with the `noexec` option. In those cases, the tests fail in a mysterious way. This change adds a note that suggests what the problem might be, if the error looks like it could have been caused by the `noexec` setup. Closes #12558 --- src/librustdoc/test.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index ae22d9c84dccc..ab90b27a0dee3 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -9,6 +9,7 @@ // except according to those terms. use std::cell::RefCell; +use std::io; use std::io::Process; use std::local_data; use std::os; @@ -128,7 +129,10 @@ fn runtest(test: &str, cratename: &str, libs: HashSet, should_fail: bool) let exe = outdir.path().join("rust_out"); let out = Process::output(exe.as_str().unwrap(), []); match out { - Err(e) => fail!("couldn't run the test: {}", e), + Err(e) => fail!("couldn't run the test: {}{}", e, + if e.kind == io::PermissionDenied { + " - maybe your tempdir is mounted with noexec?" + } else { "" }), Ok(out) => { if should_fail && out.status.success() { fail!("test executable succeeded when it should have failed"); From c5fbc5048b805c57671582d70083240617b75c31 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Wed, 26 Feb 2014 02:54:10 -0800 Subject: [PATCH 05/19] rustc: Remove codemap and reachable from metadata encoder --- src/librustc/metadata/encoder.rs | 16 +--------------- src/librustc/middle/trans/base.rs | 2 -- 2 files changed, 1 insertion(+), 17 deletions(-) diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index 733d1de27dea2..285a7411270ff 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -40,7 +40,6 @@ use syntax::ast_util::*; use syntax::ast_util; use syntax::attr::AttrMetaMethods; use syntax::attr; -use syntax::codemap; use syntax::diagnostic::SpanHandler; use syntax::parse::token::InternedString; use syntax::parse::token::special_idents; @@ -73,8 +72,6 @@ pub struct EncodeParams<'a> { link_meta: &'a LinkMeta, cstore: @cstore::CStore, encode_inlined_item: EncodeInlinedItem<'a>, - reachable: @RefCell>, - codemap: @codemap::CodeMap, } struct Stats { @@ -104,13 +101,6 @@ pub struct EncodeContext<'a> { cstore: &'a cstore::CStore, encode_inlined_item: EncodeInlinedItem<'a>, type_abbrevs: abbrev_map, - reachable: @RefCell>, - codemap: @codemap::CodeMap, -} - -pub fn reachable(ecx: &EncodeContext, id: NodeId) -> bool { - let reachable = ecx.reachable.borrow(); - reachable.get().contains(&id) } fn encode_name(ebml_w: &mut writer::Encoder, name: Name) { @@ -1630,7 +1620,7 @@ impl<'a, 'b> Visitor<()> for MacroDefVisitor<'a, 'b> { fn visit_item(&mut self, item: &Item, _: ()) { match item.node { ItemMac(..) => { - let def = self.ecx.codemap.span_to_snippet(item.span) + let def = self.ecx.tcx.sess.codemap.span_to_snippet(item.span) .expect("Unable to find source for macro"); self.ebml_w.start_tag(tag_macro_def); self.ebml_w.wr_str(def); @@ -1796,9 +1786,7 @@ fn encode_metadata_inner(wr: &mut MemWriter, parms: EncodeParams, krate: &Crate) cstore, encode_inlined_item, link_meta, - reachable, non_inlineable_statics, - codemap, .. } = parms; let type_abbrevs = @RefCell::new(HashMap::new()); @@ -1814,8 +1802,6 @@ fn encode_metadata_inner(wr: &mut MemWriter, parms: EncodeParams, krate: &Crate) cstore: cstore, encode_inlined_item: encode_inlined_item, type_abbrevs: type_abbrevs, - reachable: reachable, - codemap: codemap, }; let mut ebml_w = writer::Encoder(wr); diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index 5df6c231b5c23..6a7694b2b81a1 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -2552,8 +2552,6 @@ pub fn crate_ctxt_to_encode_parms<'r>(cx: &'r CrateContext, ie: encoder::EncodeI link_meta: link_meta, cstore: cx.sess.cstore, encode_inlined_item: ie, - reachable: cx.reachable, - codemap: cx.sess.codemap, } } From 37f6564a8498cedd88b230abde3da1e75c6e4fd1 Mon Sep 17 00:00:00 2001 From: Chris Morgan Date: Thu, 27 Feb 2014 16:30:28 +1100 Subject: [PATCH 06/19] Fix syntax::ext::deriving{,::*} docs formatting. The most significant fix is for `syntax::ext::deriving::encodable`, where one of the blocks of code, auspiciously containing `` (recall that Markdown allows arbitrary HTML to be contained inside it), was not formatted as a code block, with a fun but messy effect. --- src/libsyntax/ext/deriving/decodable.rs | 2 +- src/libsyntax/ext/deriving/encodable.rs | 17 +++++++++-------- src/libsyntax/ext/deriving/generic.rs | 9 +++++---- src/libsyntax/ext/deriving/mod.rs | 4 ++-- 4 files changed, 17 insertions(+), 15 deletions(-) diff --git a/src/libsyntax/ext/deriving/decodable.rs b/src/libsyntax/ext/deriving/decodable.rs index 623e8ef766c69..7aaa66cbfb5de 100644 --- a/src/libsyntax/ext/deriving/decodable.rs +++ b/src/libsyntax/ext/deriving/decodable.rs @@ -9,7 +9,7 @@ // except according to those terms. /*! -The compiler code necessary for #[deriving(Decodable)]. See +The compiler code necessary for `#[deriving(Decodable)]`. See encodable.rs for more. */ diff --git a/src/libsyntax/ext/deriving/encodable.rs b/src/libsyntax/ext/deriving/encodable.rs index 2bc661ff27a45..ae23013b7ccc6 100644 --- a/src/libsyntax/ext/deriving/encodable.rs +++ b/src/libsyntax/ext/deriving/encodable.rs @@ -10,20 +10,20 @@ /*! -The compiler code necessary to implement the #[deriving(Encodable)] -(and Decodable, in decodable.rs) extension. The idea here is that -type-defining items may be tagged with #[deriving(Encodable, -Decodable)]. +The compiler code necessary to implement the `#[deriving(Encodable)]` +(and `Decodable`, in decodable.rs) extension. The idea here is that +type-defining items may be tagged with `#[deriving(Encodable, Decodable)]`. For example, a type like: ```ignore - #[deriving(Encodable, Decodable)] - struct Node {id: uint} +#[deriving(Encodable, Decodable)] +struct Node { id: uint } ``` would generate two implementations like: +```ignore impl Encodable for Node { fn encode(&self, s: &S) { s.emit_struct("Node", 1, || { @@ -41,13 +41,14 @@ impl Decodable for node_id { }) } } +``` Other interesting scenarios are whe the item has type parameters or references other non-built-in types. A type definition like: ```ignore - #[deriving(Encodable, Decodable)] - struct spanned {node: T, span: Span} +#[deriving(Encodable, Decodable)] +struct spanned { node: T, span: Span } ``` would yield functions like: diff --git a/src/libsyntax/ext/deriving/generic.rs b/src/libsyntax/ext/deriving/generic.rs index ded80295320f0..24d4efb1b0e68 100644 --- a/src/libsyntax/ext/deriving/generic.rs +++ b/src/libsyntax/ext/deriving/generic.rs @@ -16,6 +16,7 @@ access to the fields of the 4 different sorts of structs and enum variants, as well as creating the method and impl ast instances. Supported features (fairly exhaustive): + - Methods taking any number of parameters of any type, and returning any type, other than vectors, bottom and closures. - Generating `impl`s for types with type parameters and lifetimes @@ -59,7 +60,7 @@ associated with. It is only not `None` when the associated field has an identifier in the source code. For example, the `x`s in the following snippet -~~~notrust +```rust struct A { x : int } struct B(int); @@ -68,7 +69,7 @@ enum C { C0(int), C1 { x: int } } -~~~ +``` The `int`s in `B` and `C0` don't have an identifier, so the `Option`s would be `None` for them. @@ -83,7 +84,7 @@ variants, it is represented as a count of 0. The following simplified `Eq` is used for in-code examples: -~~~notrust +```rust trait Eq { fn eq(&self, other: &Self); } @@ -92,7 +93,7 @@ impl Eq for int { *self == *other } } -~~~ +``` Some examples of the values of `SubstructureFields` follow, using the above `Eq`, `A`, `B` and `C`. diff --git a/src/libsyntax/ext/deriving/mod.rs b/src/libsyntax/ext/deriving/mod.rs index 9c823449d2141..28f039f081812 100644 --- a/src/libsyntax/ext/deriving/mod.rs +++ b/src/libsyntax/ext/deriving/mod.rs @@ -9,10 +9,10 @@ // except according to those terms. /*! -The compiler code necessary to implement the #[deriving] extensions. +The compiler code necessary to implement the `#[deriving]` extensions. -FIXME (#2810)--Hygiene. Search for "__" strings (in other files too). +FIXME (#2810): hygiene. Search for "__" strings (in other files too). We also assume "extra" is the standard library, and "std" is the core library. From e0088ef80b541b1cd2f99bd03765853f2df7ed44 Mon Sep 17 00:00:00 2001 From: Chris Morgan Date: Thu, 27 Feb 2014 16:45:48 +1100 Subject: [PATCH 07/19] Highlight the `mod` in `extern mod x;` as Error. Just like the bare keyword `crate` is highlighted as Error (a little dubious, actually, given macros), `mod` is invalid after `extern`: it's obsolete syntax. --- src/etc/vim/syntax/rust.vim | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/etc/vim/syntax/rust.vim b/src/etc/vim/syntax/rust.vim index 837a87879b026..34d9b534c5c80 100644 --- a/src/etc/vim/syntax/rust.vim +++ b/src/etc/vim/syntax/rust.vim @@ -19,7 +19,7 @@ syn keyword rustOperator as syn match rustAssert "\ Date: Thu, 27 Feb 2014 16:50:35 +1100 Subject: [PATCH 08/19] Downgrade `do` to a reserved keyword in Vim. This means it gets highlighted as Error by default. --- src/etc/vim/syntax/rust.vim | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/etc/vim/syntax/rust.vim b/src/etc/vim/syntax/rust.vim index 34d9b534c5c80..673b4d3d1b219 100644 --- a/src/etc/vim/syntax/rust.vim +++ b/src/etc/vim/syntax/rust.vim @@ -18,7 +18,7 @@ syn keyword rustOperator as syn match rustAssert "\ Date: Thu, 27 Feb 2014 16:51:20 +1100 Subject: [PATCH 09/19] Update prelude items in Vim syntax. --- src/etc/vim/syntax/rust.vim | 29 +++++++++-------------------- 1 file changed, 9 insertions(+), 20 deletions(-) diff --git a/src/etc/vim/syntax/rust.vim b/src/etc/vim/syntax/rust.vim index 673b4d3d1b219..7e0b6d99d2474 100644 --- a/src/etc/vim/syntax/rust.vim +++ b/src/etc/vim/syntax/rust.vim @@ -52,8 +52,7 @@ syn keyword rustType f64 i8 i16 i32 i64 str Self " to make it easy to update. " Core operators {{{3 -syn keyword rustTrait Sized -syn keyword rustTrait Freeze Send +syn keyword rustTrait Freeze Pod Send Sized syn keyword rustTrait Add Sub Mul Div Rem Neg Not syn keyword rustTrait BitAnd BitOr BitXor syn keyword rustTrait Drop @@ -64,32 +63,25 @@ syn keyword rustEnum Result syn keyword rustEnumVariant Ok Err " Functions {{{3 -"syn keyword rustFunction print println -"syn keyword rustFunction range "syn keyword rustFunction from_str +"syn keyword rustFunction range +"syn keyword rustFunction drop " Types and traits {{{3 syn keyword rustTrait Any AnyOwnExt AnyRefExt AnyMutRefExt syn keyword rustTrait Ascii AsciiCast OwnedAsciiCast AsciiStr IntoBytes -syn keyword rustTrait Bool syn keyword rustTrait ToCStr syn keyword rustTrait Char syn keyword rustTrait Clone DeepClone syn keyword rustTrait Eq Ord TotalEq TotalOrd Ordering Equiv syn keyword rustEnumVariant Less Equal Greater syn keyword rustTrait Container Mutable Map MutableMap Set MutableSet -syn keyword rustTrait Default -syn keyword rustTrait Hash -syn keyword rustTrait FromStr syn keyword rustTrait FromIterator Extendable syn keyword rustTrait Iterator DoubleEndedIterator RandomAccessIterator CloneableIterator syn keyword rustTrait OrdIterator MutableDoubleEndedIterator ExactSize - -syn keyword rustTrait Algebraic Trigonometric Exponential Hyperbolic -syn keyword rustTrait Bitwise Bounded Fractional -syn keyword rustTrait Num NumCast CheckedAdd CheckedSub CheckedMul CheckedDiv -syn keyword rustTrait Orderable Signed Unsigned Round -syn keyword rustTrait Primitive Int Float ToStrRadix ToPrimitive FromPrimitive +syn keyword rustTrait Num NumCast CheckedAdd CheckedSub CheckedMul +syn keyword rustTrait Signed Unsigned Round +syn keyword rustTrait Primitive Int Float ToPrimitive FromPrimitive syn keyword rustTrait GenericPath Path PosixPath WindowsPath syn keyword rustTrait RawPtr syn keyword rustTrait Buffer Writer Reader Seek @@ -99,20 +91,17 @@ syn keyword rustTrait Tuple1 Tuple2 Tuple3 Tuple4 syn keyword rustTrait Tuple5 Tuple6 Tuple7 Tuple8 syn keyword rustTrait Tuple9 Tuple10 Tuple11 Tuple12 syn keyword rustTrait ImmutableEqVector ImmutableTotalOrdVector ImmutableCloneableVector -syn keyword rustTrait OwnedVector OwnedCloneableVector OwnedEqVector MutableVector +syn keyword rustTrait OwnedVector OwnedCloneableVector OwnedEqVector +syn keyword rustTrait MutableVector MutableTotalOrdVector syn keyword rustTrait Vector VectorVector CloneableVector ImmutableVector "syn keyword rustFunction stream -syn keyword rustTrait Port Chan GenericChan GenericSmartChan GenericPort Peekable +syn keyword rustTrait Port Chan "syn keyword rustFunction spawn syn keyword rustSelf self syn keyword rustBoolean true false -syn keyword rustConstant Some None " option -syn keyword rustConstant Ok Err " result -syn keyword rustConstant Less Equal Greater " Ordering - " Other syntax {{{2 " If foo::bar changes to foo.bar, change this ("::" to "\."). From 879ac436890ca8f810b9b8275e4e0ec488f9c5d5 Mon Sep 17 00:00:00 2001 From: Chris Morgan Date: Thu, 27 Feb 2014 16:54:54 +1100 Subject: [PATCH 10/19] Fix Vim section movements for standard Rust style. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit (Expressed another way: make `[[` et al. work with the curly brace at the end of a line as is standard Rust style, not just at the start is it is by default in Vim, from K&R style.) This came out of #11492, where a simpler but less effective technique was initially proposed; some discussion of the techniques, ways and means can be found there. There are still a few caveats: - Operator-pending mode behaves differently to the standard behaviour: if inside curly braces, it should delete up to and including the closing of the outermost curly brace (that doesn't seem to me consistent with documented behaviour, but it's what it does). Actual behaviour (the more logical and consistent, in my opinion): up to the start of the next outermost curly brace. - With folding enabled (`set fdm=syntax`), `[[` and `]]` do not behave as they should: the default behaviour treats an entire closed fold as one line for these purposes while this code does not (I explicitly `set nofoldenable` in the function—the side-effects are worse with folds enabled), leading to unexpected behaviour, the worst of which is `[[` and/or `]]` not working in visual mode on a closed fold (visual mode keeps it at the extreme end of the region line of the folded region, so it's always going back to the opening line of that fold and immediately being shoved back to the end by visual mode). - `[[` and `]]` are operating inside comments, whereas the standard behaviour skips comments. - The viewport position is sometimes changed when it should not be necessary. --- src/etc/vim/ftplugin/rust.vim | 55 +++++++++++++++++++++++++++++++++-- 1 file changed, 53 insertions(+), 2 deletions(-) diff --git a/src/etc/vim/ftplugin/rust.vim b/src/etc/vim/ftplugin/rust.vim index 281a63ef40ae4..b70cda9b998c4 100644 --- a/src/etc/vim/ftplugin/rust.vim +++ b/src/etc/vim/ftplugin/rust.vim @@ -1,7 +1,7 @@ " Vim syntax file " Language: Rust " Maintainer: Chris Morgan -" Last Change: 2013 Jul 10 +" Last Change: 2014 Feb 27 if exists("b:did_ftplugin") finish @@ -42,4 +42,55 @@ if exists("g:loaded_delimitMate") let b:delimitMate_excluded_regions = delimitMate#Get("excluded_regions") . ',rustLifetimeCandidate,rustGenericLifetimeCandidate' endif -let b:undo_ftplugin = "setlocal formatoptions< comments< commentstring< includeexpr< suffixesadd< | if exists('b:rust_original_delimitMate_excluded_regions') | let b:delimitMate_excluded_regions = b:rust_original_delimitMate_excluded_regions | unlet b:rust_original_delimitMate_excluded_regions | elseif exists('b:delimitMate_excluded_regions') | unlet b:delimitMate_excluded_regions | endif" +" Bind motion commands to support hanging indents +nnoremap [[ :call Rust_Jump('n', 'Back') +nnoremap ]] :call Rust_Jump('n', 'Forward') +xnoremap [[ :call Rust_Jump('v', 'Back') +xnoremap ]] :call Rust_Jump('v', 'Forward') +onoremap [[ :call Rust_Jump('o', 'Back') +onoremap ]] :call Rust_Jump('o', 'Forward') + +let b:undo_ftplugin = " + \setlocal formatoptions< comments< commentstring< includeexpr< suffixesadd< + \|if exists('b:rust_original_delimitMate_excluded_regions') + \|let b:delimitMate_excluded_regions = b:rust_original_delimitMate_excluded_regions + \|unlet b:rust_original_delimitMate_excluded_regions + \|elseif exists('b:delimitMate_excluded_regions') + \|unlet b:delimitMate_excluded_regions + \|endif + \|nunmap [[ + \|nunmap ]] + \|xunmap [[ + \|xunmap ]] + \|ounmap [[ + \|ounmap ]] + \" + +if exists('*Rust_Jump') | finish | endif + +function! Rust_Jump(mode, function) range + let cnt = v:count1 + normal! m' + if a:mode ==# 'v' + norm! gv + endif + let foldenable = &foldenable + set nofoldenable + while cnt > 0 + execute "call Rust_Jump_" . a:function . "()" + let cnt = cnt - 1 + endwhile + let &foldenable = foldenable +endfunction + +function! Rust_Jump_Back() + call search('{', 'b') + keepjumps normal! w99[{ +endfunction + +function! Rust_Jump_Forward() + normal! j0 + call search('{', 'b') + keepjumps normal! w99[{% + call search('{') +endfunction From 498a6060ef949f303bdc7d5fc5ef4de88ce0d3ed Mon Sep 17 00:00:00 2001 From: Chris Morgan Date: Thu, 27 Feb 2014 17:02:51 +1100 Subject: [PATCH 11/19] Update Vim syntax file last change date. --- src/etc/vim/syntax/rust.vim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/etc/vim/syntax/rust.vim b/src/etc/vim/syntax/rust.vim index 7e0b6d99d2474..cc158bb44af37 100644 --- a/src/etc/vim/syntax/rust.vim +++ b/src/etc/vim/syntax/rust.vim @@ -3,7 +3,7 @@ " Maintainer: Patrick Walton " Maintainer: Ben Blum " Maintainer: Chris Morgan -" Last Change: 2014 Feb 14 +" Last Change: 2014 Feb 27 if version < 600 syntax clear From af38726d8e5f9d0cdd6167d0d918bf86138833ce Mon Sep 17 00:00:00 2001 From: Kevin Ballard Date: Thu, 27 Feb 2014 00:19:27 -0800 Subject: [PATCH 12/19] path: clean up some lint warnings and an obsolete comment Get rid of the unnecessary parenthesies that crept into some macros. Remove a FIXME that was already fixed. Fix a comment that wasn't rendering correctly in rustdoc. --- src/libstd/path/windows.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/libstd/path/windows.rs b/src/libstd/path/windows.rs index 10834aec64c94..bf437875b8449 100644 --- a/src/libstd/path/windows.rs +++ b/src/libstd/path/windows.rs @@ -865,7 +865,7 @@ pub fn prefix(path: &Path) -> Option { path.prefix } -/// Returns whether the Path's prefix is a verbatim prefix, i.e. \\?\ +/// Returns whether the Path's prefix is a verbatim prefix, i.e. `\\?\` #[inline] pub fn is_verbatim(path: &Path) -> bool { prefix_is_verbatim(path.prefix) @@ -926,7 +926,6 @@ pub enum PathPrefix { DiskPrefix } -// FIXME (#8169): Make private once visibility is fixed fn parse_prefix<'a>(mut path: &'a str) -> Option { if path.starts_with("\\\\") { // \\ From ea0bd40d9b03542d5b9b5bb8f84fecc274a10b82 Mon Sep 17 00:00:00 2001 From: Kevin Ballard Date: Thu, 27 Feb 2014 00:25:43 -0800 Subject: [PATCH 13/19] path: Implement windows::make_non_verbatim() make_non_verbatim() takes a WindowsPath and returns a new one that does not use the \\?\ verbatim prefix, if possible. --- src/libstd/path/windows.rs | 66 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/src/libstd/path/windows.rs b/src/libstd/path/windows.rs index bf437875b8449..864cdebe1a090 100644 --- a/src/libstd/path/windows.rs +++ b/src/libstd/path/windows.rs @@ -871,6 +871,38 @@ pub fn is_verbatim(path: &Path) -> bool { prefix_is_verbatim(path.prefix) } +/// Returns the non-verbatim equivalent of the input path, if possible. +/// If the input path is a device namespace path, None is returned. +/// If the input path is not verbatim, it is returned as-is. +/// If the input path is verbatim, but the same path can be expressed as +/// non-verbatim, the non-verbatim version is returned. +/// Otherwise, None is returned. +pub fn make_non_verbatim(path: &Path) -> Option { + let new_path = match path.prefix { + Some(VerbatimPrefix(_)) | Some(DeviceNSPrefix(_)) => return None, + Some(UNCPrefix(_,_)) | Some(DiskPrefix) | None => return Some(path.clone()), + Some(VerbatimDiskPrefix) => { + // \\?\D:\ + Path::new(path.repr.slice_from(4)) + } + Some(VerbatimUNCPrefix(_,_)) => { + // \\?\UNC\server\share + Path::new(format!(r"\\{}", path.repr.slice_from(7))) + } + }; + if new_path.prefix.is_none() { + // \\?\UNC\server is a VerbatimUNCPrefix + // but \\server is nothing + return None; + } + // now ensure normalization didn't change anything + if path.repr.slice_from(path.prefix_len()) == new_path.repr.slice_from(new_path.prefix_len()) { + Some(new_path) + } else { + None + } +} + /// The standard path separator character pub static SEP: char = '\\'; /// The standard path separator byte @@ -2284,4 +2316,38 @@ mod tests { t!(s: ".", [b!(".")]); // since this is really a wrapper around str_components, those tests suffice } + + #[test] + fn test_make_non_verbatim() { + macro_rules! t( + ($path:expr, $exp:expr) => ( + { + let path = Path::new($path); + let exp: Option<&str> = $exp; + let exp = exp.map(|s| Path::new(s)); + assert_eq!(make_non_verbatim(&path), exp); + } + ) + ) + + t!(r"\a\b\c", Some(r"\a\b\c")); + t!(r"a\b\c", Some(r"a\b\c")); + t!(r"C:\a\b\c", Some(r"C:\a\b\c")); + t!(r"C:a\b\c", Some(r"C:a\b\c")); + t!(r"\\server\share\foo", Some(r"\\server\share\foo")); + t!(r"\\.\foo", None); + t!(r"\\?\foo", None); + t!(r"\\?\C:", None); + t!(r"\\?\C:foo", None); + t!(r"\\?\C:\", Some(r"C:\")); + t!(r"\\?\C:\foo", Some(r"C:\foo")); + t!(r"\\?\C:\foo\bar\baz", Some(r"C:\foo\bar\baz")); + t!(r"\\?\C:\foo\.\bar\baz", None); + t!(r"\\?\C:\foo\bar\..\baz", None); + t!(r"\\?\C:\foo\bar\..", None); + t!(r"\\?\UNC\server\share\foo", Some(r"\\server\share\foo")); + t!(r"\\?\UNC\server\share", Some(r"\\server\share")); + t!(r"\\?\UNC\server", None); + t!(r"\\?\UNC\server\", None); + } } From 231832d83579b4ed0268a70e53af806a7c53e53f Mon Sep 17 00:00:00 2001 From: Chris Morgan Date: Thu, 27 Feb 2014 22:34:08 +1100 Subject: [PATCH 14/19] Improve the ctags function regular expression. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Before it would only catch lines starting `fn` or `pub fn`. Now it can cope with: - attributes (e.g. `#[test] fn`) - external functions (e.g. `extern fn`, `extern "C" fn`) - unsafe functions (e.g. `unsafe fn`) … and any correct combination of these (e.g. `#[test] extern "C" unsafe fn`). --- src/etc/ctags.rust | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/etc/ctags.rust b/src/etc/ctags.rust index f0fab3347d163..b42edf7579a64 100644 --- a/src/etc/ctags.rust +++ b/src/etc/ctags.rust @@ -1,6 +1,6 @@ --langdef=Rust --langmap=Rust:.rs ---regex-Rust=/^[ \t]*(pub[ \t]+)?fn[ \t]+([a-zA-Z0-9_]+)/\2/f,functions,function definitions/ +--regex-Rust=/^[ \t]*(#\[[^\]]\][ \t]*)*(pub[ \t]+)?(extern[ \t]+)?("[^"]+"[ \t]+)?(unsafe[ \t]+)?fn[ \t]+([a-zA-Z0-9_]+)/\6/f,functions,function definitions/ --regex-Rust=/^[ \t]*(pub[ \t]+)?type[ \t]+([a-zA-Z0-9_]+)/\2/T,types,type definitions/ --regex-Rust=/^[ \t]*(pub[ \t]+)?enum[ \t]+([a-zA-Z0-9_]+)/\2/g,enum,enumeration names/ --regex-Rust=/^[ \t]*(pub[ \t]+)?struct[ \t]+([a-zA-Z0-9_]+)/\2/s,structure names/ From d028079b88df0c642aefe4de4e338e4df14f3cd3 Mon Sep 17 00:00:00 2001 From: Axel Viala Date: Sat, 22 Feb 2014 17:54:21 +0100 Subject: [PATCH 15/19] Documentation : Tutorial improvement... Refactoring examples on implementation of generics for linked list. Fixing typo of 'Note's for coherancy. Adding internal links inside the tutorial example with traits, generics etc... --- src/doc/tutorial.md | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/doc/tutorial.md b/src/doc/tutorial.md index 670ad5800c6a7..1c33d17ec66d2 100644 --- a/src/doc/tutorial.md +++ b/src/doc/tutorial.md @@ -133,6 +133,8 @@ fn main() { println!("hello?"); } ~~~~ +> ***Note:*** *Macros* are explained in the [Syntax extensions +> (3.4)](#syntax-extensions) section. If the Rust compiler was installed successfully, running `rustc hello.rs` will produce an executable called `hello` (or `hello.exe` on @@ -1059,7 +1061,7 @@ box, while the owner holds onto a pointer to it: list -> | Cons | 1 | ~ | -> | Cons | 2 | ~ | -> | Cons | 3 | ~ | -> | Nil | +--------------+ +--------------+ +--------------+ +--------------+ -> Note: the above diagram shows the logical contents of the enum. The actual +> ***Note:*** the above diagram shows the logical contents of the enum. The actual > memory layout of the enum may vary. For example, for the `List` enum shown > above, Rust guarantees that there will be no enum tag field in the actual > structure. See the language reference for more details. @@ -1114,7 +1116,7 @@ let z = x; // no new memory allocated, `x` can no longer be used ~~~~ The `clone` method is provided by the `Clone` trait, and can be derived for -our `List` type. Traits will be explained in detail later. +our `List` type. Traits will be explained in detail [later](#traits). ~~~{.ignore} #[deriving(Clone)] @@ -1207,8 +1209,8 @@ let ys = Cons(5, ~Cons(10, ~Nil)); assert!(eq(&xs, &ys)); ~~~ -Note that Rust doesn't guarantee [tail-call](http://en.wikipedia.org/wiki/Tail_call) optimization, -but LLVM is able to handle a simple case like this with optimizations enabled. +> ***Note:*** Rust doesn't guarantee [tail-call](http://en.wikipedia.org/wiki/Tail_call) optimization, +> but LLVM is able to handle a simple case like this with optimizations enabled. ## Lists of other types @@ -1218,6 +1220,9 @@ element type. The `u32` in the previous definition can be substituted with a type parameter: +> ***Note:*** The following code introduces generics, which are explained in a +> [dedicated section](#generics). + ~~~ enum List { Cons(T, ~List), @@ -1336,9 +1341,13 @@ impl Eq for List { let xs = Cons(5, ~Cons(10, ~Nil)); let ys = Cons(5, ~Cons(10, ~Nil)); +// The methods below are part of the Eq trait, +// which we implemented on our linked list. assert!(xs.eq(&ys)); -assert!(xs == ys); assert!(!xs.ne(&ys)); + +// The Eq trait also allows us to use the shorthand infix operators. +assert!(xs == ys); assert!(!(xs != ys)); ~~~ From 1bcd8252ee22ea4f153de812e9bf83e3cfe4f8e0 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Thu, 27 Feb 2014 14:16:31 +0100 Subject: [PATCH 16/19] Minor modifications to Axel's tutorial improvements (see also #12472). --- src/doc/tutorial.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/doc/tutorial.md b/src/doc/tutorial.md index 1c33d17ec66d2..339e5552d7f6d 100644 --- a/src/doc/tutorial.md +++ b/src/doc/tutorial.md @@ -133,8 +133,10 @@ fn main() { println!("hello?"); } ~~~~ -> ***Note:*** *Macros* are explained in the [Syntax extensions -> (3.4)](#syntax-extensions) section. +> ***Note:*** An identifier followed by an exclamation point, like +> `println!`, is a macro invocation. Macros are explained +> [later](#syntax-extensions); for now just remember to include the +> exclamation point. If the Rust compiler was installed successfully, running `rustc hello.rs` will produce an executable called `hello` (or `hello.exe` on @@ -1347,8 +1349,8 @@ assert!(xs.eq(&ys)); assert!(!xs.ne(&ys)); // The Eq trait also allows us to use the shorthand infix operators. -assert!(xs == ys); -assert!(!(xs != ys)); +assert!(xs == ys); // `xs == ys` is short for `xs.eq(&ys)` +assert!(!(xs != ys)); // `xs != ys` is short for `xs.ne(&ys)` ~~~ # More on boxes From 98782bb5c9b0196cd10e3cfaf07cd02c6fe9f2f3 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Sun, 23 Feb 2014 21:30:18 -0800 Subject: [PATCH 17/19] std: Export the select! macro Mark it as #[experimental] for now. In theory this attribute will be read in the future. I believe that the implementation is solid enough for general use, although I would not be surprised if there were bugs in it still. I think that it's at the point now where public usage of it will start to uncover hopefully the last few remaining bugs. Closes #12044 --- src/libstd/comm/select.rs | 16 -------------- src/libstd/macros.rs | 44 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 16 deletions(-) diff --git a/src/libstd/comm/select.rs b/src/libstd/comm/select.rs index 02066086ad773..75e7265705a77 100644 --- a/src/libstd/comm/select.rs +++ b/src/libstd/comm/select.rs @@ -58,22 +58,6 @@ use rt::task::{Task, BlockedTask}; use super::Port; use uint; -macro_rules! select { - ( - $($name:pat = $port:ident.$meth:ident() => $code:expr),+ - ) => ({ - use std::comm::Select; - let sel = Select::new(); - $( let mut $port = sel.handle(&$port); )+ - unsafe { - $( $port.add(); )+ - } - let ret = sel.wait(); - $( if ret == $port.id() { let $name = $port.$meth(); $code } else )+ - { unreachable!() } - }) -} - /// The "port set" of the select interface. This structure is used to manage a /// set of ports which are being selected over. pub struct Select { diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs index 490f2c9b198d2..e16d944fb4628 100644 --- a/src/libstd/macros.rs +++ b/src/libstd/macros.rs @@ -368,3 +368,47 @@ macro_rules! vec( }) ) + +/// A macro to select an event from a number of ports. +/// +/// This macro is used to wait for the first event to occur on a number of +/// ports. It places no restrictions on the types of ports given to this macro, +/// this can be viewed as a heterogeneous select. +/// +/// # Example +/// +/// ``` +/// let (p1, c1) = Chan::new(); +/// let (p2, c2) = Chan::new(); +/// # fn long_running_task() {} +/// # fn calculate_the_answer() -> int { 42 } +/// +/// spawn(proc() { long_running_task(); c1.send(()) }); +/// spawn(proc() { c2.send(calculate_the_answer()) }); +/// +/// select! ( +/// () = p1.recv() => println!("the long running task finished first"), +/// answer = p2.recv() => { +/// println!("the answer was: {}", answer); +/// } +/// ) +/// ``` +/// +/// For more information about select, see the `std::comm::Select` structure. +#[macro_export] +#[experimental] +macro_rules! select { + ( + $($name:pat = $port:ident.$meth:ident() => $code:expr),+ + ) => ({ + use std::comm::Select; + let sel = Select::new(); + $( let mut $port = sel.handle(&$port); )+ + unsafe { + $( $port.add(); )+ + } + let ret = sel.wait(); + $( if ret == $port.id() { let $name = $port.$meth(); $code } else )+ + { unreachable!() } + }) +} From 53a3f281158bf584361ad63400ba0b4a88472b23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micka=C3=ABl=20Delahaye?= Date: Thu, 27 Feb 2014 21:00:23 +0100 Subject: [PATCH 18/19] Fix typo in doc of Binary trait in std::fmt --- src/libstd/fmt/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstd/fmt/mod.rs b/src/libstd/fmt/mod.rs index 5c0838fadca46..bdc1aa75c9419 100644 --- a/src/libstd/fmt/mod.rs +++ b/src/libstd/fmt/mod.rs @@ -580,7 +580,7 @@ pub trait Unsigned { fn fmt(&self, &mut Formatter) -> Result; } /// Format trait for the `o` character #[allow(missing_doc)] pub trait Octal { fn fmt(&self, &mut Formatter) -> Result; } -/// Format trait for the `b` character +/// Format trait for the `t` character #[allow(missing_doc)] pub trait Binary { fn fmt(&self, &mut Formatter) -> Result; } /// Format trait for the `x` character From a8d57a26dfe1c8e44e9af1923c900f147d13889b Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 28 Feb 2014 12:53:36 +1300 Subject: [PATCH 19/19] Fix bytepos_to_file_charpos. Make bytepos_to_charpos relative to the start of the filemap rather than its previous behaviour which was to be realtive to the start of the codemap, but ignoring multi-byte chars in earlier filemaps. Rename to bytepos_to_file_charpos. Add tests for multi-byte chars. --- src/libsyntax/codemap.rs | 62 +++++++++++++++++++++++++++++++++------- 1 file changed, 52 insertions(+), 10 deletions(-) diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs index 79ccc8df0f3fe..7b70e14e802e2 100644 --- a/src/libsyntax/codemap.rs +++ b/src/libsyntax/codemap.rs @@ -420,10 +420,10 @@ impl CodeMap { fn lookup_pos(&self, pos: BytePos) -> Loc { let FileMapAndLine {fm: f, line: a} = self.lookup_line(pos); let line = a + 1u; // Line numbers start at 1 - let chpos = self.bytepos_to_charpos(pos); + let chpos = self.bytepos_to_file_charpos(pos); let lines = f.lines.borrow(); let linebpos = lines.get()[a]; - let linechpos = self.bytepos_to_charpos(linebpos); + let linechpos = self.bytepos_to_file_charpos(linebpos); debug!("codemap: byte pos {:?} is on the line at byte pos {:?}", pos, linebpos); debug!("codemap: char pos {:?} is on the line at char pos {:?}", @@ -446,8 +446,8 @@ impl CodeMap { return FileMapAndBytePos {fm: fm, pos: offset}; } - // Converts an absolute BytePos to a CharPos relative to the codemap. - fn bytepos_to_charpos(&self, bpos: BytePos) -> CharPos { + // Converts an absolute BytePos to a CharPos relative to the filemap. + fn bytepos_to_file_charpos(&self, bpos: BytePos) -> CharPos { debug!("codemap: converting {:?} to char pos", bpos); let idx = self.lookup_filemap_idx(bpos); let files = self.files.borrow(); @@ -471,7 +471,8 @@ impl CodeMap { } } - CharPos(bpos.to_uint() - total_extra_bytes) + assert!(map.start_pos.to_uint() + total_extra_bytes <= bpos.to_uint()); + CharPos(bpos.to_uint() - map.start_pos.to_uint() - total_extra_bytes) } } @@ -501,7 +502,7 @@ mod test { fm.next_line(BytePos(2)); } - fn init_code_map() ->CodeMap { + fn init_code_map() -> CodeMap { let cm = CodeMap::new(); let fm1 = cm.new_filemap(~"blork.rs",~"first line.\nsecond line"); let fm2 = cm.new_filemap(~"empty.rs",~""); @@ -532,14 +533,14 @@ mod test { #[test] fn t4() { - // Test bytepos_to_charpos + // Test bytepos_to_file_charpos let cm = init_code_map(); - let cp1 = cm.bytepos_to_charpos(BytePos(22)); + let cp1 = cm.bytepos_to_file_charpos(BytePos(22)); assert_eq!(cp1, CharPos(22)); - let cp2 = cm.bytepos_to_charpos(BytePos(23)); - assert_eq!(cp2, CharPos(23)); + let cp2 = cm.bytepos_to_file_charpos(BytePos(23)); + assert_eq!(cp2, CharPos(0)); } #[test] @@ -557,4 +558,45 @@ mod test { assert_eq!(loc2.line, 1); assert_eq!(loc2.col, CharPos(0)); } + + fn init_code_map_mbc() -> CodeMap { + let cm = CodeMap::new(); + // € is a three byte utf8 char. + let fm1 = cm.new_filemap(~"blork.rs",~"fir€st €€€€ line.\nsecond line"); + let fm2 = cm.new_filemap(~"blork2.rs",~"first line€€.\n€ second line"); + + fm1.next_line(BytePos(0)); + fm1.next_line(BytePos(22)); + fm2.next_line(BytePos(39)); + fm2.next_line(BytePos(57)); + + fm1.record_multibyte_char(BytePos(3), 3); + fm1.record_multibyte_char(BytePos(9), 3); + fm1.record_multibyte_char(BytePos(12), 3); + fm1.record_multibyte_char(BytePos(15), 3); + fm1.record_multibyte_char(BytePos(18), 3); + fm2.record_multibyte_char(BytePos(49), 3); + fm2.record_multibyte_char(BytePos(52), 3); + fm2.record_multibyte_char(BytePos(57), 3); + + cm + } + + #[test] + fn t6() { + // Test bytepos_to_file_charpos in the presence of multi-byte chars + let cm = init_code_map_mbc(); + + let cp1 = cm.bytepos_to_file_charpos(BytePos(3)); + assert_eq!(cp1, CharPos(3)); + + let cp2 = cm.bytepos_to_file_charpos(BytePos(6)); + assert_eq!(cp2, CharPos(4)); + + let cp3 = cm.bytepos_to_file_charpos(BytePos(55)); + assert_eq!(cp3, CharPos(12)); + + let cp4 = cm.bytepos_to_file_charpos(BytePos(60)); + assert_eq!(cp4, CharPos(15)); + } }