diff --git a/RELEASES.md b/RELEASES.md index a50b6b0e271bb..7053900056b34 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1,10 +1,10 @@ -Version 1.1.0 (July 2015) -======================== +Version 1.1.0 (June 2015) +========================= -* NNNN changes, numerous bugfixes +* ~850 changes, numerous bugfixes -Libraries ---------- +Highlights +---------- * The [`std::fs` module has been expanded][fs-expand] to expand the set of functionality exposed: @@ -13,8 +13,103 @@ Libraries * A `symlink_metadata` function has been added. * The `fs::Metadata` structure now lowers to its OS counterpart, providing access to all underlying information. +* The compiler contains extended explanations of many errors. When it + emits such an error it also suggests using the `--explain` flag to + read the extended explanations, which are also [cataloged on the web + site][err]. +* Thanks to multiple [improvements][sk] to [type checking][pre], as + well as other work, the time to bootstrap the compiler decreased by + 32%. + +Libraries +--------- + +* The `str::split_whitespace` method splits a string on unicode + whitespace boundaries. +* On both Windows and Unix, new extension traits provide conversion of + I/O types to and from the underlying system handles. On Unix, these + traits are [`FrowRawFd`] and [`AsRawFd`], on Windows `FromRawHandle` + and `AsRawHandle`. These are implemented for `File`, `TcpStream`, + `TcpListener`, and `UpdSocket`. Further implementations for + `std::process` will be stabilized later. +* On Unix, [`std::os::unix::symlink`] creates symlinks. On + Windows, symlinks can be created with + `std::os::windows::symlink_dir` and + `std::os::windows::symlink_file`. +* The `mpsc::Receiver` type can now be converted into an iterator with + `into_iter` on the [`IntoIterator`] trait. +* `Ipv4Addr` can be created from `u32` with the `From` + implementation of the [`From`] trait. +* The `Debug` implementation for `RangeFull` [creates output that is + more consistent with other implementations][rf]. +* [`Debug` is implemented for `File`][file]. +* The `Default` implementation for `Arc` [no longer requires `Sync + + Send`][arc]. +* [The `Iterator` methods `count`, `nth`, and `last` have been + overridden for slices to have O(1) performance instead of O(n)][si]. +* Incorrect handling of paths on Windows has been improved in both the + compiler and the standard library. +* [`AtomicPtr` gained a `Default` implementation][ap]. +* In accordance with Rust's policy on arithmetic overflow `abs` now + [panics on overflow when debug assertions are enabled][abs]. +* The [`Cloned`] iterator, which was accidentally left unstable for + 1.0 [has been stabilized][c]. +* The [`Incoming`] iterator, which iterates over incoming TCP + connections, and which was accidentally unnamable in 1.0, [is now + properly exported][inc]. +* [`BinaryHeap`] no longer corrupts itself [when functions called by + `sift_up` or `sift_down` panic][bh]. +* The [`split_off`] method of `LinkedList` [no longer corrupts + the list in certain scenarios][ll]. + +Misc +---- -[fs-expand]: https://github.com/rust-lang/rust/pull/25844 +* Type checking performance [has improved notably][sk] with + [multiple improvements][pre]. +* The compiler [suggests code changes][ch] for more errors. +* rustc and it's build system have experimental support for [building + toolchains against MUSL][m] instead of glibc on Linux. +* The compiler defines the `target_env` cfg value, which is used for + distinguishing toolchains that are otherwise for the same + platform. Presently this is set to `gnu` for common GNU Linux + targets and for MinGW targets, and `musl` for MUSL Linux targets. +* The [`cargo rustc`][crc] command invokes a build with custom flags + to rustc. +* [Android executables are always position independent][pie]. +* [The `drop_with_repr_extern` lint warns about mixing `repr(C)` + with `Drop`][drop]. + +[`split_whitespace`]: http://doc.rust-lang.org/nightly/std/primitive.str.html#method.split_whitespace +[`Iterator::cloned`]: http://doc.rust-lang.org/nightly/core/iter/trait.Iterator.html#method.cloned +[`FromRawFd`]: http://doc.rust-lang.org/nightly/std/os/unix/io/trait.FromRawFd.html +[`AsRawFd`]: http://doc.rust-lang.org/nightly/std/os/unix/io/trait.AsRawFd.html +[`std::os::unix::symlink`]: http://doc.rust-lang.org/nightly/std/os/unix/fs/fn.symlink.html +[`IntoIterator`]: http://doc.rust-lang.org/nightly/std/iter/trait.IntoIterator.html +[`From`]: http://doc.rust-lang.org/nightly/std/convert/trait.From.html +[rf]: https://github.com/rust-lang/rust/pull/24491 +[err]: http://doc.rust-lang.org/error-index.html +[sk]: https://github.com/rust-lang/rust/pull/24615 +[pre]: https://github.com/rust-lang/rust/pull/25323 +[file]: https://github.com/rust-lang/rust/pull/24598 +[ch]: https://github.com/rust-lang/rust/pull/24683 +[arc]: https://github.com/rust-lang/rust/pull/24695 +[si]: https://github.com/rust-lang/rust/pull/24701 +[ap]: https://github.com/rust-lang/rust/pull/24834 +[m]: https://github.com/rust-lang/rust/pull/24777 +[fs]: https://github.com/rust-lang/rfcs/blob/master/text/1044-io-fs-2.1.md +[crc]: https://github.com/rust-lang/cargo/pull/1568 +[pie]: https://github.com/rust-lang/rust/pull/24953 +[abs]: https://github.com/rust-lang/rust/pull/25441 +[c]: https://github.com/rust-lang/rust/pull/25496 +[`Cloned`]: http://doc.rust-lang.org/nightly/std/iter/struct.Cloned.html +[`Incoming`]: http://doc.rust-lang.org/nightly/std/net/struct.Incoming.html +[inc]: https://github.com/rust-lang/rust/pull/25522 +[bh]: https://github.com/rust-lang/rust/pull/25856 +[`BinaryHeap`]: http://doc.rust-lang.org/nightly/std/collections/struct.BinaryHeap.html +[ll]: https://github.com/rust-lang/rust/pull/26022 +[`split_off`]: http://doc.rust-lang.org/nightly/collections/linked_list/struct.LinkedList.html#method.split_off +[drop]: https://github.com/rust-lang/rust/pull/24935 Version 1.0.0 (May 2015) ======================== diff --git a/src/librustc_trans/trans/cleanup.rs b/src/librustc_trans/trans/cleanup.rs index d23543924dd39..9133004dfeff1 100644 --- a/src/librustc_trans/trans/cleanup.rs +++ b/src/librustc_trans/trans/cleanup.rs @@ -954,8 +954,15 @@ impl<'blk, 'tcx> CleanupScope<'blk, 'tcx> { } } + /// Manipulate cleanup scope for call arguments. Conceptually, each + /// argument to a call is an lvalue, and performing the call moves each + /// of the arguments into a new rvalue (which gets cleaned up by the + /// callee). As an optimization, instead of actually performing all of + /// those moves, trans just manipulates the cleanup scope to obtain the + /// same effect. pub fn drop_non_lifetime_clean(&mut self) { self.cleanups.retain(|c| c.is_lifetime_end()); + self.clear_cached_exits(); } } diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs index c692babfacc44..ef9b14739a5ed 100644 --- a/src/libsyntax/codemap.rs +++ b/src/libsyntax/codemap.rs @@ -17,7 +17,7 @@ //! within the CodeMap, which upon request can be converted to line and column //! information, source code snippets, etc. -pub use self::MacroFormat::*; +pub use self::ExpnFormat::*; use std::cell::RefCell; use std::ops::{Add, Sub}; @@ -226,17 +226,17 @@ pub struct FileMapAndBytePos { pub fm: Rc, pub pos: BytePos } // _____________________________________________________________________________ -// MacroFormat, NameAndSpan, ExpnInfo, ExpnId +// ExpnFormat, NameAndSpan, ExpnInfo, ExpnId // -/// The syntax with which a macro was invoked. -#[derive(Clone, Copy, Hash, Debug)] -pub enum MacroFormat { +/// The source of expansion. +#[derive(Clone, Copy, Hash, Debug, PartialEq, Eq)] +pub enum ExpnFormat { /// e.g. #[derive(...)] MacroAttribute, /// e.g. `format!()` MacroBang, - /// Expansion performed by the compiler (libsyntax::expand). + /// Syntax sugar expansion performed by the compiler (libsyntax::expand). CompilerExpansion, } @@ -246,7 +246,7 @@ pub struct NameAndSpan { /// with this Span. pub name: String, /// The format with which the macro was invoked. - pub format: MacroFormat, + pub format: ExpnFormat, /// Whether the macro is allowed to use #[unstable]/feature-gated /// features internally without forcing the whole crate to opt-in /// to them. @@ -257,11 +257,11 @@ pub struct NameAndSpan { pub span: Option } -/// Extra information for tracking macro expansion of spans +/// Extra information for tracking spans of macro and syntax sugar expansion #[derive(Hash, Debug)] pub struct ExpnInfo { - /// The location of the actual macro invocation, e.g. `let x = - /// foo!();` + /// The location of the actual macro invocation or syntax sugar , e.g. + /// `let x = foo!();` or `if let Some(y) = x {}` /// /// This may recursively refer to other macro invocations, e.g. if /// `foo!()` invoked `bar!()` internally, and there was an @@ -270,12 +270,7 @@ pub struct ExpnInfo { /// call_site span would have its own ExpnInfo, with the call_site /// pointing to the `foo!` invocation. pub call_site: Span, - /// Information about the macro and its definition. - /// - /// The `callee` of the inner expression in the `call_site` - /// example would point to the `macro_rules! bar { ... }` and that - /// of the `bar!()` invocation would point to the `macro_rules! - /// foo { ... }`. + /// Information about the expansion. pub callee: NameAndSpan } @@ -633,7 +628,39 @@ impl CodeMap { /// Lookup source information about a BytePos pub fn lookup_char_pos(&self, pos: BytePos) -> Loc { - self.lookup_pos(pos) + let FileMapAndLine {fm: f, line: a} = self.lookup_line(pos); + let line = a + 1; // Line numbers start at 1 + let chpos = self.bytepos_to_file_charpos(pos); + let linebpos = (*f.lines.borrow())[a]; + let linechpos = self.bytepos_to_file_charpos(linebpos); + debug!("byte pos {:?} is on the line at byte pos {:?}", + pos, linebpos); + debug!("char pos {:?} is on the line at char pos {:?}", + chpos, linechpos); + debug!("byte is on line: {}", line); + assert!(chpos >= linechpos); + Loc { + file: f, + line: line, + col: chpos - linechpos + } + } + + fn lookup_line(&self, pos: BytePos) -> FileMapAndLine { + let idx = self.lookup_filemap_idx(pos); + + let files = self.files.borrow(); + let f = (*files)[idx].clone(); + let mut a = 0; + { + let lines = f.lines.borrow(); + let mut b = lines.len(); + while b - a > 1 { + let m = (a + b) / 2; + if (*lines)[m] > pos { b = m; } else { a = m; } + } + } + FileMapAndLine {fm: f, line: a} } pub fn lookup_char_pos_adj(&self, pos: BytePos) -> LocWithOpt { @@ -833,42 +860,6 @@ impl CodeMap { return a; } - fn lookup_line(&self, pos: BytePos) -> FileMapAndLine { - let idx = self.lookup_filemap_idx(pos); - - let files = self.files.borrow(); - let f = (*files)[idx].clone(); - let mut a = 0; - { - let lines = f.lines.borrow(); - let mut b = lines.len(); - while b - a > 1 { - let m = (a + b) / 2; - if (*lines)[m] > pos { b = m; } else { a = m; } - } - } - FileMapAndLine {fm: f, line: a} - } - - fn lookup_pos(&self, pos: BytePos) -> Loc { - let FileMapAndLine {fm: f, line: a} = self.lookup_line(pos); - let line = a + 1; // Line numbers start at 1 - let chpos = self.bytepos_to_file_charpos(pos); - let linebpos = (*f.lines.borrow())[a]; - let linechpos = self.bytepos_to_file_charpos(linebpos); - debug!("byte pos {:?} is on the line at byte pos {:?}", - pos, linebpos); - debug!("char pos {:?} is on the line at char pos {:?}", - chpos, linechpos); - debug!("byte is on line: {}", line); - assert!(chpos >= linechpos); - Loc { - file: f, - line: line, - col: chpos - linechpos - } - } - pub fn record_expansion(&self, expn_info: ExpnInfo) -> ExpnId { let mut expansions = self.expansions.borrow_mut(); expansions.push(expn_info); diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 2ecefef51045e..9f3abfcb08b58 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -13,7 +13,7 @@ pub use self::SyntaxExtension::*; use ast; use ast::Name; use codemap; -use codemap::{CodeMap, Span, ExpnId, ExpnInfo, NO_EXPANSION}; +use codemap::{CodeMap, Span, ExpnId, ExpnInfo, NO_EXPANSION, CompilerExpansion}; use ext; use ext::expand; use ext::tt::macro_rules; @@ -658,6 +658,8 @@ impl<'a> ExtCtxt<'a> { }) } pub fn backtrace(&self) -> ExpnId { self.backtrace } + + /// Original span that caused the current exapnsion to happen. pub fn original_span(&self) -> Span { let mut expn_id = self.backtrace; let mut call_site = None; @@ -672,26 +674,31 @@ impl<'a> ExtCtxt<'a> { } call_site.expect("missing expansion backtrace") } - pub fn original_span_in_file(&self) -> Span { + + /// Returns span for the macro which originally caused the current expansion to happen. + /// + /// Stops backtracing at include! boundary. + pub fn expansion_cause(&self) -> Span { let mut expn_id = self.backtrace; - let mut call_site = None; + let mut last_macro = None; loop { - let expn_info = self.codemap().with_expn_info(expn_id, |ei| { - ei.map(|ei| (ei.call_site, ei.callee.name == "include")) - }); - match expn_info { - None => break, - Some((cs, is_include)) => { - if is_include { - // Don't recurse into file using "include!". - break; + if self.codemap().with_expn_info(expn_id, |info| { + info.map_or(None, |i| { + if i.callee.name == "include" { + // Stop going up the backtrace once include! is encountered + return None; } - call_site = Some(cs); - expn_id = cs.expn_id; - } + expn_id = i.call_site.expn_id; + if i.callee.format != CompilerExpansion { + last_macro = Some(i.call_site) + } + return Some(()); + }) + }).is_none() { + break } } - call_site.expect("missing expansion backtrace") + last_macro.expect("missing expansion backtrace") } pub fn mod_push(&mut self, i: ast::Ident) { self.mod_path.push(i); } diff --git a/src/libsyntax/ext/source_util.rs b/src/libsyntax/ext/source_util.rs index 08bb4ca106486..3866f5534c2eb 100644 --- a/src/libsyntax/ext/source_util.rs +++ b/src/libsyntax/ext/source_util.rs @@ -34,7 +34,7 @@ pub fn expand_line(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) -> Box { base::check_zero_tts(cx, sp, tts, "line!"); - let topmost = cx.original_span_in_file(); + let topmost = cx.expansion_cause(); let loc = cx.codemap().lookup_char_pos(topmost.lo); base::MacEager::expr(cx.expr_u32(topmost, loc.line as u32)) @@ -45,7 +45,7 @@ pub fn expand_column(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) -> Box { base::check_zero_tts(cx, sp, tts, "column!"); - let topmost = cx.original_span_in_file(); + let topmost = cx.expansion_cause(); let loc = cx.codemap().lookup_char_pos(topmost.lo); base::MacEager::expr(cx.expr_u32(topmost, loc.col.to_usize() as u32)) @@ -58,7 +58,7 @@ pub fn expand_file(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) -> Box { base::check_zero_tts(cx, sp, tts, "file!"); - let topmost = cx.original_span_in_file(); + let topmost = cx.expansion_cause(); let loc = cx.codemap().lookup_char_pos(topmost.lo); let filename = token::intern_and_get_ident(&loc.file.name); base::MacEager::expr(cx.expr_str(topmost, filename)) diff --git a/src/test/run-pass/issue-25089.rs b/src/test/run-pass/issue-25089.rs new file mode 100644 index 0000000000000..b619d1dd4488c --- /dev/null +++ b/src/test/run-pass/issue-25089.rs @@ -0,0 +1,40 @@ +// Copyright 2015 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. + +use std::thread; + +struct Foo(i32); + +impl Drop for Foo { + fn drop(&mut self) { + static mut DROPPED: bool = false; + unsafe { + assert!(!DROPPED); + DROPPED = true; + } + } +} + +struct Empty; + +fn empty() -> Empty { Empty } + +fn should_panic(_: Foo, _: Empty) { + panic!("test panic"); +} + +fn test() { + should_panic(Foo(1), empty()); +} + +fn main() { + let ret = thread::spawn(test).join(); + assert!(ret.is_err()); +} diff --git a/src/test/run-pass/issue-26322.rs b/src/test/run-pass/issue-26322.rs new file mode 100644 index 0000000000000..766d1ce25d1ed --- /dev/null +++ b/src/test/run-pass/issue-26322.rs @@ -0,0 +1,36 @@ +// Copyright 2015 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. + +macro_rules! columnline { + () => ( + (column!(), line!()) + ) +} + +macro_rules! indirectcolumnline { + () => ( + (||{ columnline!() })() + ) +} + +fn main() { + let closure = || { + columnline!() + }; + let iflet = if let Some(_) = Some(0) { + columnline!() + } else { (0, 0) }; + let cl = columnline!(); + assert_eq!(closure(), (8, 25)); + assert_eq!(iflet, (8, 28)); + assert_eq!(cl, (13, 30)); + let indirect = indirectcolumnline!(); + assert_eq!(indirect, (19, 34)); +}