From 5f3431691dd2b2b2b3c48ad5bfa6ca782a9a6d09 Mon Sep 17 00:00:00 2001 From: Andy Russell Date: Thu, 13 Dec 2018 23:28:54 -0500 Subject: [PATCH 01/84] simplify deprecation and stability rendering --- src/librustdoc/clean/mod.rs | 48 +++++---- src/librustdoc/html/render.rs | 182 +++++++++++++++----------------- src/test/rustdoc/deprecated.rs | 22 ++++ src/test/rustdoc/issue-27759.rs | 8 +- src/test/rustdoc/issue-32374.rs | 10 +- 5 files changed, 141 insertions(+), 129 deletions(-) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 1e33ec8c37661..7ac718ed730bc 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -478,7 +478,7 @@ impl Item { classes.push("unstable"); } - if !s.deprecated_since.is_empty() { + if s.deprecation.is_some() { classes.push("deprecated"); } @@ -503,6 +503,15 @@ impl Item { pub fn type_(&self) -> ItemType { ItemType::from(self) } + + /// Returns the info in the item's `#[deprecated]` or `#[rustc_deprecated]` attributes. + /// + /// If the item is not deprecated, returns `None`. + pub fn deprecation(&self) -> Option<&Deprecation> { + self.deprecation + .as_ref() + .or_else(|| self.stability.as_ref().and_then(|s| s.deprecation.as_ref())) + } } #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] @@ -3838,40 +3847,37 @@ impl Clean for doctree::ProcMacro { #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct Stability { pub level: stability::StabilityLevel, - pub feature: String, + pub feature: Option, pub since: String, - pub deprecated_since: String, - pub deprecated_reason: String, - pub unstable_reason: String, - pub issue: Option + pub deprecation: Option, + pub unstable_reason: Option, + pub issue: Option, } #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct Deprecation { - pub since: String, - pub note: String, + pub since: Option, + pub note: Option, } impl Clean for attr::Stability { fn clean(&self, _: &DocContext) -> Stability { Stability { level: stability::StabilityLevel::from_attr_level(&self.level), - feature: self.feature.to_string(), + feature: Some(self.feature.to_string()).filter(|f| !f.is_empty()), since: match self.level { attr::Stable {ref since} => since.to_string(), _ => String::new(), }, - deprecated_since: match self.rustc_depr { - Some(attr::RustcDeprecation {ref since, ..}) => since.to_string(), - _=> String::new(), - }, - deprecated_reason: match self.rustc_depr { - Some(ref depr) => depr.reason.to_string(), - _ => String::new(), - }, + deprecation: self.rustc_depr.as_ref().map(|d| { + Deprecation { + note: Some(d.reason.to_string()).filter(|r| !r.is_empty()), + since: Some(d.since.to_string()).filter(|d| !d.is_empty()), + } + }), unstable_reason: match self.level { - attr::Unstable { reason: Some(ref reason), .. } => reason.to_string(), - _ => String::new(), + attr::Unstable { reason: Some(ref reason), .. } => Some(reason.to_string()), + _ => None, }, issue: match self.level { attr::Unstable {issue, ..} => Some(issue), @@ -3890,8 +3896,8 @@ impl<'a> Clean for &'a attr::Stability { impl Clean for attr::Deprecation { fn clean(&self, _: &DocContext) -> Deprecation { Deprecation { - since: self.since.as_ref().map_or(String::new(), |s| s.to_string()), - note: self.note.as_ref().map_or(String::new(), |s| s.to_string()), + since: self.since.map(|s| s.to_string()).filter(|s| !s.is_empty()), + note: self.note.map(|n| n.to_string()).filter(|n| !n.is_empty()), } } } diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 8d7942a14669c..689054da39d01 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -65,7 +65,7 @@ use rustc::hir; use rustc::util::nodemap::{FxHashMap, FxHashSet}; use rustc_data_structures::flock; -use clean::{self, AttributesExt, GetDefId, SelfTy, Mutability}; +use clean::{self, AttributesExt, Deprecation, GetDefId, SelfTy, Mutability}; use config::RenderOptions; use doctree; use fold::DocFolder; @@ -2449,7 +2449,7 @@ fn document_full(w: &mut fmt::Formatter, item: &clean::Item, fn document_stability(w: &mut fmt::Formatter, cx: &Context, item: &clean::Item, is_hidden: bool) -> fmt::Result { - let stabilities = short_stability(item, cx, true); + let stabilities = short_stability(item, cx); if !stabilities.is_empty() { write!(w, "
", if is_hidden { " hidden" } else { "" })?; for stability in stabilities { @@ -2642,18 +2642,6 @@ fn item_module(w: &mut fmt::Formatter, cx: &Context, _ => { if myitem.name.is_none() { continue } - let stabilities = short_stability(myitem, cx, false); - - let stab_docs = if !stabilities.is_empty() { - stabilities.iter() - .map(|s| format!("[{}]", s)) - .collect::>() - .as_slice() - .join(" ") - } else { - String::new() - }; - let unsafety_flag = match myitem.inner { clean::FunctionItem(ref func) | clean::ForeignFunctionItem(ref func) if func.header.unsafety == hir::Unsafety::Unsafe => { @@ -2674,11 +2662,11 @@ fn item_module(w: &mut fmt::Formatter, cx: &Context, \ {name}{unsafety_flag}\ - {stab_docs}{docs}\ + {stab_tags}{docs}\ \ ", name = *myitem.name.as_ref().unwrap(), - stab_docs = stab_docs, + stab_tags = stability_tags(myitem), docs = MarkdownSummaryLine(doc_value, &myitem.links()), class = myitem.type_(), add = add, @@ -2705,101 +2693,99 @@ fn item_module(w: &mut fmt::Formatter, cx: &Context, Ok(()) } -fn short_stability(item: &clean::Item, cx: &Context, show_reason: bool) -> Vec { +/// Render the stability and deprecation tags that are displayed in the item's summary at the +/// module level. +fn stability_tags(item: &clean::Item) -> String { + let mut tags = String::new(); + + // The trailing space after each tag is to space it properly against the rest of the docs. + if item.deprecation().is_some() { + tags.push_str("[
Deprecated
] "); + } + + if item + .stability + .as_ref() + .filter(|s| s.level == stability::Unstable) + .is_some() + { + tags.push_str("[
Experimental
] "); + } + + if let Some(ref cfg) = item.attrs.cfg { + tags.push_str(&format!( + "[
{}
] ", + cfg.render_short_html() + )); + } + + tags +} + +/// Render the stability and/or deprecation warning that is displayed at the top of the item's +/// documentation. +fn short_stability(item: &clean::Item, cx: &Context) -> Vec { let mut stability = vec![]; let error_codes = ErrorCodes::from(UnstableFeatures::from_environment().is_nightly_build()); - if let Some(stab) = item.stability.as_ref() { - let deprecated_reason = if show_reason && !stab.deprecated_reason.is_empty() { - format!(": {}", stab.deprecated_reason) + if let Some(Deprecation { since, note }) = &item.deprecation() { + let mut message = if let Some(since) = since { + if stability::deprecation_in_effect(since) { + format!("Deprecated since {}", Escape(since)) + } else { + format!("Deprecating in {}", Escape(since)) + } } else { - String::new() + String::from("Deprecated") }; - if !stab.deprecated_since.is_empty() { - let since = if show_reason { - format!(" since {}", Escape(&stab.deprecated_since)) - } else { - String::new() - }; + + if let Some(note) = note { let mut ids = cx.id_map.borrow_mut(); - let html = MarkdownHtml(&deprecated_reason, RefCell::new(&mut ids), error_codes); - let text = if stability::deprecation_in_effect(&stab.deprecated_since) { - format!("Deprecated{}{}", since, html) - } else { - format!("Deprecating in {}{}", Escape(&stab.deprecated_since), html) - }; - stability.push(format!("
{}
", text)) - }; + let html = MarkdownHtml(¬e, RefCell::new(&mut ids), error_codes); + message.push_str(&format!(": {}", html)); + } + stability.push(format!("
{}
", message)); + } - if stab.level == stability::Unstable { - if show_reason { - let unstable_extra = match (!stab.feature.is_empty(), - &cx.shared.issue_tracker_base_url, - stab.issue) { - (true, &Some(ref tracker_url), Some(issue_no)) if issue_no > 0 => - format!(" ({} #{})", - Escape(&stab.feature), tracker_url, issue_no, issue_no), - (false, &Some(ref tracker_url), Some(issue_no)) if issue_no > 0 => - format!(" (#{})", Escape(&tracker_url), issue_no, - issue_no), - (true, ..) => - format!(" ({})", Escape(&stab.feature)), - _ => String::new(), - }; - if stab.unstable_reason.is_empty() { - stability.push(format!("
\ - 🔬 \ - This is a nightly-only experimental API. {}\ -
", - unstable_extra)); - } else { - let mut ids = cx.id_map.borrow_mut(); - let text = format!("🔬 \ - This is a nightly-only experimental API. {}\ - {}", - unstable_extra, - MarkdownHtml( - &stab.unstable_reason, - RefCell::new(&mut ids), - error_codes)); - stability.push(format!("
{}
", - text)); - } - } else { - stability.push("
Experimental
".to_string()) + if let Some(stab) = item + .stability + .as_ref() + .filter(|stab| stab.level == stability::Unstable) + { + let mut message = String::from( + "🔬 This is a nightly-only experimental API.", + ); + + if let Some(feature) = stab.feature.as_ref() { + let mut feature = format!("{}", Escape(&feature)); + if let (Some(url), Some(issue)) = (&cx.shared.issue_tracker_base_url, stab.issue) { + feature.push_str(&format!( + " #{issue}", + url = url, + issue = issue + )); } - }; - } else if let Some(depr) = item.deprecation.as_ref() { - let note = if show_reason && !depr.note.is_empty() { - format!(": {}", depr.note) - } else { - String::new() - }; - let since = if show_reason && !depr.since.is_empty() { - format!(" since {}", Escape(&depr.since)) - } else { - String::new() - }; - let mut ids = cx.id_map.borrow_mut(); - let text = if stability::deprecation_in_effect(&depr.since) { - format!("Deprecated{}{}", - since, - MarkdownHtml(¬e, RefCell::new(&mut ids), error_codes)) - } else { - format!("Deprecating in {}{}", - Escape(&depr.since), - MarkdownHtml(¬e, RefCell::new(&mut ids), error_codes)) - }; - stability.push(format!("
{}
", text)) + message.push_str(&format!(" ({})", feature)); + } + + if let Some(unstable_reason) = &stab.unstable_reason { + let mut ids = cx.id_map.borrow_mut(); + message = format!( + "
{}{}
", + message, + MarkdownHtml(&unstable_reason, RefCell::new(&mut ids), error_codes) + ); + } + + stability.push(format!("
{}
", message)) } if let Some(ref cfg) = item.attrs.cfg { - stability.push(format!("
{}
", if show_reason { + stability.push(format!( + "
{}
", cfg.render_long_html() - } else { - cfg.render_short_html() - })); + )); } stability diff --git a/src/test/rustdoc/deprecated.rs b/src/test/rustdoc/deprecated.rs index 744304a62c216..63447ad169002 100644 --- a/src/test/rustdoc/deprecated.rs +++ b/src/test/rustdoc/deprecated.rs @@ -10,7 +10,29 @@ #![feature(deprecated)] +// @matches deprecated/index.html '//*[@class="docblock-short"]' \ +// '^\[Deprecated\] Deprecated docs' // @has deprecated/struct.S.html '//*[@class="stab deprecated"]' \ // 'Deprecated since 1.0.0: text' +/// Deprecated docs #[deprecated(since = "1.0.0", note = "text")] pub struct S; + +// @matches deprecated/index.html '//*[@class="docblock-short"]' '^Docs' +/// Docs +pub struct T; + +// @matches deprecated/struct.U.html '//*[@class="stab deprecated"]' \ +// 'Deprecated since 1.0.0$' +#[deprecated(since = "1.0.0")] +pub struct U; + +// @matches deprecated/struct.V.html '//*[@class="stab deprecated"]' \ +// 'Deprecated: text$' +#[deprecated(note = "text")] +pub struct V; + +// @matches deprecated/struct.W.html '//*[@class="stab deprecated"]' \ +// 'Deprecated$' +#[deprecated] +pub struct W; diff --git a/src/test/rustdoc/issue-27759.rs b/src/test/rustdoc/issue-27759.rs index e82e93230aa07..4723b04a078be 100644 --- a/src/test/rustdoc/issue-27759.rs +++ b/src/test/rustdoc/issue-27759.rs @@ -14,13 +14,11 @@ #![unstable(feature="test", issue="27759")] // @has issue_27759/unstable/index.html -// @has - 'test ' -// @has - '#27759' +// @has - 'test #27759' #[unstable(feature="test", issue="27759")] pub mod unstable { // @has issue_27759/unstable/fn.issue.html - // @has - 'test_function ' - // @has - '#1234567890' - #[unstable(feature="test_function", issue="1234567890")] + // @has - 'test_function #12345' + #[unstable(feature="test_function", issue="12345")] pub fn issue() {} } diff --git a/src/test/rustdoc/issue-32374.rs b/src/test/rustdoc/issue-32374.rs index 6d1f8bc1cf9ba..34423d0176d2d 100644 --- a/src/test/rustdoc/issue-32374.rs +++ b/src/test/rustdoc/issue-32374.rs @@ -13,15 +13,15 @@ #![unstable(feature="test", issue = "32374")] -// @has issue_32374/index.html '//*[@class="docblock-short"]' \ -// '[Deprecated] [Experimental]' +// @matches issue_32374/index.html '//*[@class="docblock-short"]' \ +// '^\[Deprecated\] \[Experimental\] Docs' // @has issue_32374/struct.T.html '//*[@class="stab deprecated"]' \ // 'Deprecated since 1.0.0: text' -// @has - 'test ' -// @has - '#32374' +// @has - 'test #32374' // @matches issue_32374/struct.T.html '//*[@class="stab unstable"]' \ -// '🔬 This is a nightly-only experimental API. \(test #32374\)$' +// '🔬 This is a nightly-only experimental API. \(test #32374\)$' +/// Docs #[rustc_deprecated(since = "1.0.0", reason = "text")] #[unstable(feature = "test", issue = "32374")] pub struct T; From 1bdd6cad02470c268a8af21fbb07443e9d5647ac Mon Sep 17 00:00:00 2001 From: csmoe Date: Sat, 15 Dec 2018 12:53:41 +0800 Subject: [PATCH 02/84] retrieve ty info from place_ty --- .../borrow_check/error_reporting.rs | 74 +++++++------------ 1 file changed, 28 insertions(+), 46 deletions(-) diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs index 598c2f810beb7..2d790c2a361ce 100644 --- a/src/librustc_mir/borrow_check/error_reporting.rs +++ b/src/librustc_mir/borrow_check/error_reporting.rs @@ -191,38 +191,36 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { ); } - if let Some(ty) = self.retrieve_type_for_place(used_place) { - let needs_note = match ty.sty { - ty::Closure(id, _) => { - let tables = self.infcx.tcx.typeck_tables_of(id); - let node_id = self.infcx.tcx.hir().as_local_node_id(id).unwrap(); - let hir_id = self.infcx.tcx.hir().node_to_hir_id(node_id); - - tables.closure_kind_origins().get(hir_id).is_none() - } - _ => true, - }; + let ty = used_place.ty(self.mir, self.infcx.tcx).to_ty(self.infcx.tcx); + let needs_note = match ty.sty { + ty::Closure(id, _) => { + let tables = self.infcx.tcx.typeck_tables_of(id); + let node_id = self.infcx.tcx.hir().as_local_node_id(id).unwrap(); + let hir_id = self.infcx.tcx.hir().node_to_hir_id(node_id); - if needs_note { - let mpi = self.move_data.moves[move_out_indices[0]].path; - let place = &self.move_data.move_paths[mpi].place; - - if let Some(ty) = self.retrieve_type_for_place(place) { - let note_msg = match self.describe_place_with_options( - place, - IncludingDowncast(true), - ) { - Some(name) => format!("`{}`", name), - None => "value".to_owned(), - }; - - err.note(&format!( - "move occurs because {} has type `{}`, \ - which does not implement the `Copy` trait", - note_msg, ty - )); - } + tables.closure_kind_origins().get(hir_id).is_none() } + _ => true, + }; + + if needs_note { + let mpi = self.move_data.moves[move_out_indices[0]].path; + let place = &self.move_data.move_paths[mpi].place; + + let ty = place.ty(self.mir, self.infcx.tcx).to_ty(self.infcx.tcx); + let note_msg = match self.describe_place_with_options( + place, + IncludingDowncast(true), + ) { + Some(name) => format!("`{}`", name), + None => "value".to_owned(), + }; + + err.note(&format!( + "move occurs because {} has type `{}`, \ + which does not implement the `Copy` trait", + note_msg, ty + )); } if let Some((_, mut old_err)) = self.move_error_reported @@ -1673,22 +1671,6 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { } } - /// Retrieve type of a place for the current MIR representation - fn retrieve_type_for_place(&self, place: &Place<'tcx>) -> Option { - match place { - Place::Local(local) => { - let local = &self.mir.local_decls[*local]; - Some(local.ty) - } - Place::Promoted(ref prom) => Some(prom.1), - Place::Static(ref st) => Some(st.ty), - Place::Projection(ref proj) => match proj.elem { - ProjectionElem::Field(_, ty) => Some(ty), - _ => None, - }, - } - } - /// Check if a place is a thread-local static. pub fn is_place_thread_local(&self, place: &Place<'tcx>) -> bool { if let Place::Static(statik) = place { From 7f9883d79e517741dd3531688d026b1fa4a2a0ad Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Sat, 15 Dec 2018 02:34:10 -0800 Subject: [PATCH 03/84] Add unstable VecDeque::rotate_{left|right} --- src/liballoc/collections/vec_deque.rs | 102 ++++++++++++++++++++++++++ 1 file changed, 102 insertions(+) diff --git a/src/liballoc/collections/vec_deque.rs b/src/liballoc/collections/vec_deque.rs index 0c5926fbaf1dc..954a1c8becf15 100644 --- a/src/liballoc/collections/vec_deque.rs +++ b/src/liballoc/collections/vec_deque.rs @@ -1927,6 +1927,108 @@ impl VecDeque { self.truncate(new_len); } } + + /// Rotates the double-ended queue `mid` places to the left. + /// + /// Equivalently, + /// - Rotates item `mid` into the first position. + /// - Pops the first `mid` items and pushes them to the end. + /// - Rotates `len() - mid` places to the right. + /// + /// # Panics + /// + /// If `mid` is greater than `len()`. Note that `mid == len()` + /// does _not_ panic and is a no-op rotation. + /// + /// # Complexity + /// + /// Takes `O(min(mid, len() - mid))` time and no extra space. + /// + /// # Examples + /// + /// ``` + /// #![feature(vecdeque_rotate)] + /// + /// use std::collections::VecDeque; + /// + /// let mut buf: VecDeque<_> = (0..10).collect(); + /// + /// buf.rotate_left(3); + /// assert_eq!(buf, [3, 4, 5, 6, 7, 8, 9, 0, 1, 2]); + /// + /// for i in 1..10 { + /// assert_eq!(i * 3 % 10, buf[0]); + /// buf.rotate_left(3); + /// } + /// assert_eq!(buf, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]); + /// ``` + #[unstable(feature = "vecdeque_rotate", issue = "56686")] + pub fn rotate_left(&mut self, mid: usize) { + assert!(mid <= self.len()); + let k = self.len() - mid; + if mid <= k { + unsafe { self.rotate_left_inner(mid) } + } else { + unsafe { self.rotate_right_inner(k) } + } + } + + /// Rotates the double-ended queue `k` places to the right. + /// + /// Equivalently, + /// - Rotates the first item into position `k`. + /// - Pops the last `k` items and pushes them to the front. + /// - Rotates `len() - k` places to the left. + /// + /// # Panics + /// + /// If `k` is greater than `len()`. Note that `k == len()` + /// does _not_ panic and is a no-op rotation. + /// + /// # Complexity + /// + /// Takes `O(min(k, len() - k))` time and no extra space. + /// + /// # Examples + /// + /// ``` + /// #![feature(vecdeque_rotate)] + /// + /// use std::collections::VecDeque; + /// + /// let mut buf: VecDeque<_> = (0..10).collect(); + /// + /// buf.rotate_right(3); + /// assert_eq!(buf, [7, 8, 9, 0, 1, 2, 3, 4, 5, 6]); + /// + /// for i in 1..10 { + /// assert_eq!(0, buf[i * 3 % 10]); + /// buf.rotate_right(3); + /// } + /// assert_eq!(buf, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]); + /// ``` + #[unstable(feature = "vecdeque_rotate", issue = "56686")] + pub fn rotate_right(&mut self, k: usize) { + assert!(k <= self.len()); + let mid = self.len() - k; + if k <= mid { + unsafe { self.rotate_right_inner(k) } + } else { + unsafe { self.rotate_left_inner(mid) } + } + } + + unsafe fn rotate_left_inner(&mut self, mid: usize) { + self.wrap_copy(self.head, self.tail, mid); + self.head = self.wrap_add(self.head, mid); + self.tail = self.wrap_add(self.tail, mid); + } + + unsafe fn rotate_right_inner(&mut self, k: usize) { + self.head = self.wrap_sub(self.head, k); + self.tail = self.wrap_sub(self.tail, k); + self.wrap_copy(self.tail, self.head, k); + } } impl VecDeque { From 9ca2902a69711f32f13e0595784422398f81eac4 Mon Sep 17 00:00:00 2001 From: csmoe Date: Sat, 15 Dec 2018 19:00:04 +0800 Subject: [PATCH 04/84] update test --- .../ui/borrowck/borrowck-move-out-from-array.mir.stderr | 4 ++++ src/test/ui/borrowck/two-phase-nonrecv-autoref.nll.stderr | 4 ++++ .../issues/issue-27282-move-match-input-into-guard.stderr | 2 ++ src/test/ui/use/use-after-move-self.rs | 3 ++- src/test/ui/use/use-after-move-self.stderr | 6 +++--- 5 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/test/ui/borrowck/borrowck-move-out-from-array.mir.stderr b/src/test/ui/borrowck/borrowck-move-out-from-array.mir.stderr index d67b63b5aa71a..d19c23dce5f5f 100644 --- a/src/test/ui/borrowck/borrowck-move-out-from-array.mir.stderr +++ b/src/test/ui/borrowck/borrowck-move-out-from-array.mir.stderr @@ -5,6 +5,8 @@ LL | let [_, _x] = a; | -- value moved here LL | let [.., _y] = a; //[ast]~ ERROR [E0382] | ^^ value used here after move + | + = note: move occurs because `a[..]` has type `std::boxed::Box`, which does not implement the `Copy` trait error[E0382]: use of moved value: `a[..]` --> $DIR/borrowck-move-out-from-array.rs:27:10 @@ -13,6 +15,8 @@ LL | let [_x, _] = a; | -- value moved here LL | let [_y..] = a; //[ast]~ ERROR [E0382] | ^^ value used here after move + | + = note: move occurs because `a[..]` has type `std::boxed::Box`, which does not implement the `Copy` trait error: aborting due to 2 previous errors diff --git a/src/test/ui/borrowck/two-phase-nonrecv-autoref.nll.stderr b/src/test/ui/borrowck/two-phase-nonrecv-autoref.nll.stderr index a272d2cf019a7..564783d3492f0 100644 --- a/src/test/ui/borrowck/two-phase-nonrecv-autoref.nll.stderr +++ b/src/test/ui/borrowck/two-phase-nonrecv-autoref.nll.stderr @@ -14,6 +14,8 @@ LL | f(f(10)); | - ^ value used here after move | | | value moved here + | + = note: move occurs because `*f` has type `F`, which does not implement the `Copy` trait error[E0499]: cannot borrow `*f` as mutable more than once at a time --> $DIR/two-phase-nonrecv-autoref.rs:86:11 @@ -43,6 +45,8 @@ LL | f(f(10)); | - ^ value used here after move | | | value moved here + | + = note: move occurs because `*f` has type `dyn std::ops::FnOnce(i32) -> i32`, which does not implement the `Copy` trait error[E0502]: cannot borrow `a` as immutable because it is also borrowed as mutable --> $DIR/two-phase-nonrecv-autoref.rs:139:27 diff --git a/src/test/ui/issues/issue-27282-move-match-input-into-guard.stderr b/src/test/ui/issues/issue-27282-move-match-input-into-guard.stderr index 5f3b07bd1e8b8..fa05e85c464b0 100644 --- a/src/test/ui/issues/issue-27282-move-match-input-into-guard.stderr +++ b/src/test/ui/issues/issue-27282-move-match-input-into-guard.stderr @@ -8,6 +8,8 @@ LL | _ if { (|| { let bar = b; *bar = false; })(); LL | false } => { }, LL | &mut true => { println!("You might think we should get here"); }, | ^^^^ value used here after move + | + = note: move occurs because `b` has type `&mut bool`, which does not implement the `Copy` trait error: aborting due to previous error diff --git a/src/test/ui/use/use-after-move-self.rs b/src/test/ui/use/use-after-move-self.rs index e9ffb26aba5b7..d762c74283229 100644 --- a/src/test/ui/use/use-after-move-self.rs +++ b/src/test/ui/use/use-after-move-self.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +//compile-flags: -Z borrowck=mir #![feature(box_syntax)] struct S { @@ -17,7 +18,7 @@ struct S { impl S { pub fn foo(self) -> isize { self.bar(); - return *self.x; //~ ERROR use of moved value: `*self.x` + return *self.x; //~ ERROR use of moved value: `self` } pub fn bar(self) {} diff --git a/src/test/ui/use/use-after-move-self.stderr b/src/test/ui/use/use-after-move-self.stderr index 7273602aadc4b..1902dd9c06ce7 100644 --- a/src/test/ui/use/use-after-move-self.stderr +++ b/src/test/ui/use/use-after-move-self.stderr @@ -1,9 +1,9 @@ -error[E0382]: use of moved value: `*self.x` - --> $DIR/use-after-move-self.rs:20:16 +error[E0382]: use of moved value: `self` + --> $DIR/use-after-move-self.rs:21:16 | LL | self.bar(); | ---- value moved here -LL | return *self.x; //~ ERROR use of moved value: `*self.x` +LL | return *self.x; //~ ERROR use of moved value: `self` | ^^^^^^^ value used here after move | = note: move occurs because `self` has type `S`, which does not implement the `Copy` trait From c4fa1d2c4739acf03a0df991d1c28f725c2ba20f Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Sat, 15 Dec 2018 23:45:37 +0200 Subject: [PATCH 05/84] stop treating trait objects from #[fundamental] traits as fundamental Fixes #56503. --- src/librustc/traits/coherence.rs | 7 +++---- .../auxiliary/coherence_fundamental_trait_lib.rs | 7 +++++++ .../coherence-fundamental-trait-objects.rs | 15 +++++++++++++++ .../coherence-fundamental-trait-objects.stderr | 12 ++++++++++++ 4 files changed, 37 insertions(+), 4 deletions(-) create mode 100644 src/test/ui/coherence/auxiliary/coherence_fundamental_trait_lib.rs create mode 100644 src/test/ui/coherence/coherence-fundamental-trait-objects.rs create mode 100644 src/test/ui/coherence/coherence-fundamental-trait-objects.stderr diff --git a/src/librustc/traits/coherence.rs b/src/librustc/traits/coherence.rs index f10f523e2b487..0f8bc8518f2fe 100644 --- a/src/librustc/traits/coherence.rs +++ b/src/librustc/traits/coherence.rs @@ -393,7 +393,7 @@ fn uncovered_tys<'tcx>(tcx: TyCtxt<'_, '_, '_>, ty: Ty<'tcx>, in_crate: InCrate) -> Vec> { if ty_is_local_constructor(ty, in_crate) { vec![] - } else if fundamental_ty(tcx, ty) { + } else if fundamental_ty(ty) { ty.walk_shallow() .flat_map(|t| uncovered_tys(tcx, t, in_crate)) .collect() @@ -411,14 +411,13 @@ fn is_possibly_remote_type(ty: Ty<'_>, _in_crate: InCrate) -> bool { fn ty_is_local(tcx: TyCtxt<'_, '_, '_>, ty: Ty<'_>, in_crate: InCrate) -> bool { ty_is_local_constructor(ty, in_crate) || - fundamental_ty(tcx, ty) && ty.walk_shallow().any(|t| ty_is_local(tcx, t, in_crate)) + fundamental_ty(ty) && ty.walk_shallow().any(|t| ty_is_local(tcx, t, in_crate)) } -fn fundamental_ty(tcx: TyCtxt<'_, '_, '_>, ty: Ty<'_>) -> bool { +fn fundamental_ty(ty: Ty<'_>) -> bool { match ty.sty { ty::Ref(..) => true, ty::Adt(def, _) => def.is_fundamental(), - ty::Dynamic(ref data, ..) => tcx.has_attr(data.principal().def_id(), "fundamental"), _ => false } } diff --git a/src/test/ui/coherence/auxiliary/coherence_fundamental_trait_lib.rs b/src/test/ui/coherence/auxiliary/coherence_fundamental_trait_lib.rs new file mode 100644 index 0000000000000..21aaea479631c --- /dev/null +++ b/src/test/ui/coherence/auxiliary/coherence_fundamental_trait_lib.rs @@ -0,0 +1,7 @@ +#![crate_type = "rlib"] +#![feature(fundamental)] + +pub trait Misc {} + +#[fundamental] +pub trait Fundamental {} diff --git a/src/test/ui/coherence/coherence-fundamental-trait-objects.rs b/src/test/ui/coherence/coherence-fundamental-trait-objects.rs new file mode 100644 index 0000000000000..dd127bf7f4bff --- /dev/null +++ b/src/test/ui/coherence/coherence-fundamental-trait-objects.rs @@ -0,0 +1,15 @@ +// Check that trait objects from #[fundamental] traits are not +// treated as #[fundamental] types - the 2 meanings of #[fundamental] +// are distinct. + +// aux-build:coherence_fundamental_trait_lib.rs + +extern crate coherence_fundamental_trait_lib; + +use coherence_fundamental_trait_lib::{Fundamental, Misc}; + +pub struct Local; +impl Misc for dyn Fundamental {} +//~^ ERROR E0117 + +fn main() {} diff --git a/src/test/ui/coherence/coherence-fundamental-trait-objects.stderr b/src/test/ui/coherence/coherence-fundamental-trait-objects.stderr new file mode 100644 index 0000000000000..cefcac2c51795 --- /dev/null +++ b/src/test/ui/coherence/coherence-fundamental-trait-objects.stderr @@ -0,0 +1,12 @@ +error[E0117]: only traits defined in the current crate can be implemented for arbitrary types + --> $DIR/coherence-fundamental-trait-objects.rs:12:1 + | +LL | impl Misc for dyn Fundamental {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate + | + = note: the impl does not reference any types defined in this crate + = note: define and implement a trait or new type instead + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0117`. From 08155314889e9c9b4cb0e35c117cc4ba93c29388 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Sat, 15 Dec 2018 16:33:23 -0800 Subject: [PATCH 06/84] Add a note about why the unsafe is sound --- src/liballoc/collections/vec_deque.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/liballoc/collections/vec_deque.rs b/src/liballoc/collections/vec_deque.rs index 954a1c8becf15..5171ca254e486 100644 --- a/src/liballoc/collections/vec_deque.rs +++ b/src/liballoc/collections/vec_deque.rs @@ -2018,13 +2018,23 @@ impl VecDeque { } } + // Safety: the following two methods require that the rotation amount + // be less than half the length of the deque. + // + // `wrap_copy` requres that `min(x, cap() - x) + copy_len <= cap()`, + // but than `min` is never more than half the capacity, regardless of x, + // so it's sound to call here because we're calling with something + // less than half the length, which is never above half the capacity. + unsafe fn rotate_left_inner(&mut self, mid: usize) { + debug_assert!(mid * 2 <= self.len()); self.wrap_copy(self.head, self.tail, mid); self.head = self.wrap_add(self.head, mid); self.tail = self.wrap_add(self.tail, mid); } unsafe fn rotate_right_inner(&mut self, k: usize) { + debug_assert!(k * 2 <= self.len()); self.head = self.wrap_sub(self.head, k); self.tail = self.wrap_sub(self.tail, k); self.wrap_copy(self.tail, self.head, k); From bf4a98463d2717ba590492b3161ce0ac926cdd0a Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 16 Dec 2018 02:35:39 +0100 Subject: [PATCH 07/84] Reduce search-index.js size --- Cargo.lock | 12 ++++++------ src/librustdoc/Cargo.toml | 2 +- src/librustdoc/html/render.rs | 5 ++++- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d22a91073394a..cecaa4fc60e4e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1334,7 +1334,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "minifier" -version = "0.0.20" +version = "0.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "macro-utils 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1813,7 +1813,7 @@ name = "rand_chacha" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1835,7 +1835,7 @@ name = "rand_hc" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1860,7 +1860,7 @@ name = "rand_xorshift" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2682,7 +2682,7 @@ dependencies = [ name = "rustdoc" version = "0.0.0" dependencies = [ - "minifier 0.0.20 (registry+https://github.com/rust-lang/crates.io-index)", + "minifier 0.0.21 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", "pulldown-cmark 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "tempfile 3.0.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3497,7 +3497,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum memchr 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0a3eb002f0535929f1199681417029ebea04aadc0c7a4224b46be99c7f5d6a16" "checksum memmap 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e2ffa2c986de11a9df78620c01eeaaf27d94d3ff02bf81bfcca953102dd0c6ff" "checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3" -"checksum minifier 0.0.20 (registry+https://github.com/rust-lang/crates.io-index)" = "96c269bb45c39b333392b2b18ad71760b34ac65666591386b0e959ed58b3f474" +"checksum minifier 0.0.21 (registry+https://github.com/rust-lang/crates.io-index)" = "9707d0ff1b828cba09c4bb27d5c3dceb6f49bd46f700042343bea350a131bf4f" "checksum miniz-sys 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "0300eafb20369952951699b68243ab4334f4b10a88f411c221d444b36c40e649" "checksum miniz_oxide 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5ad30a47319c16cde58d0314f5d98202a80c9083b5f61178457403dfb14e509c" "checksum miniz_oxide_c_api 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "28edaef377517fd9fe3e085c37d892ce7acd1fbeab9239c5a36eec352d8a8b7e" diff --git a/src/librustdoc/Cargo.toml b/src/librustdoc/Cargo.toml index 8bac007b748ac..bc6447d74f1b2 100644 --- a/src/librustdoc/Cargo.toml +++ b/src/librustdoc/Cargo.toml @@ -9,6 +9,6 @@ path = "lib.rs" [dependencies] pulldown-cmark = { version = "0.1.2", default-features = false } -minifier = "0.0.20" +minifier = "0.0.21" tempfile = "3" parking_lot = "0.6.4" diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index c9f3aa011a1d4..2ad9292fb8442 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -1221,7 +1221,10 @@ fn write_minify_replacer(dst: &mut W, -> io::Result<()> { if enable_minification { writeln!(dst, "{}", - minifier::js::minify_and_replace_keywords(contents, keywords_to_replace)) + minifier::js::minify_and_replace_keywords(contents, keywords_to_replace) + .apply(minifier::js::clean_tokens) + .apply(minifier::js::aggregate_strings) + .to_string()) } else { writeln!(dst, "{}", contents) } From fba23d01d16db8b83b2415bc538d2a850fcf24da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Sun, 16 Dec 2018 19:59:42 +0100 Subject: [PATCH 08/84] Disable field reordering for repr(int). --- src/librustc/ty/mod.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index a1fc949137dde..634df0194b08f 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -2059,9 +2059,10 @@ impl ReprOptions { } /// Returns `true` if this `#[repr()]` should inhibit struct field reordering - /// optimizations, such as with repr(C) or repr(packed(1)). + /// optimizations, such as with repr(C), repr(packed(1)), or repr(). pub fn inhibit_struct_field_reordering_opt(&self) -> bool { - !(self.flags & ReprFlags::IS_UNOPTIMISABLE).is_empty() || (self.pack == 1) + self.flags.intersects(ReprFlags::IS_UNOPTIMISABLE) || self.pack == 1 || + self.int.is_some() } /// Returns true if this `#[repr()]` should inhibit union abi optimisations From d84bdba72888a42a67c1771b0a62f8517c8964cb Mon Sep 17 00:00:00 2001 From: Peter Todd Date: Fri, 7 Dec 2018 19:54:16 -0500 Subject: [PATCH 09/84] Add test to check order of repr(int) enum fields RFC #2195 specifies that a repr(int) enum such as: #[repr(u8)] enum MyEnum { B { x: u8, y: i16, z: u8 }, } has a layout that is equivalent to: #[repr(C)] enum MyEnumVariantB { tag: u8, x: u8, y: i16, z: u8 }, However this isn't actually implemented, with the actual layout being roughly equivalent to: union MyEnumPayload { B { x: u8, y: i16, z: u8 }, } #[repr(packed)] struct MyEnum { tag: u8, payload: MyEnumPayload, } Thus the variant payload is *not* subject to repr(C) ordering rules, and gets re-ordered as `{ x: u8, z: u8, z: i16 }` The existing tests added in pull-req #45688 fail to catch this as the repr(C) ordering just happens to match the current Rust ordering in this case; adding a third field reveals the problem. --- .../enum-non-c-like-repr-c-and-int.rs | 18 ++++++++++-------- .../structs-enums/enum-non-c-like-repr-c.rs | 18 ++++++++++-------- .../structs-enums/enum-non-c-like-repr-int.rs | 18 ++++++++++-------- 3 files changed, 30 insertions(+), 24 deletions(-) diff --git a/src/test/run-pass/structs-enums/enum-non-c-like-repr-c-and-int.rs b/src/test/run-pass/structs-enums/enum-non-c-like-repr-c-and-int.rs index 14eac687ecf96..f59f100653fbb 100644 --- a/src/test/run-pass/structs-enums/enum-non-c-like-repr-c-and-int.rs +++ b/src/test/run-pass/structs-enums/enum-non-c-like-repr-c-and-int.rs @@ -20,11 +20,12 @@ use std::mem; #[repr(C, u8)] #[derive(Copy, Clone, Eq, PartialEq, Debug)] enum MyEnum { - A(u32), // Single primitive value - B { x: u8, y: i16 }, // Composite, and the offset of `y` depends on tag being internal - C, // Empty - D(Option), // Contains an enum - E(Duration), // Contains a struct + A(u32), // Single primitive value + B { x: u8, y: i16, z: u8 }, // Composite, and the offsets of `y` and `z` + // depend on tag being internal + C, // Empty + D(Option), // Contains an enum + E(Duration), // Contains a struct } #[repr(C)] @@ -44,14 +45,14 @@ union MyEnumPayload { #[repr(u8)] #[derive(Copy, Clone)] enum MyEnumTag { A, B, C, D, E } #[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantA(u32); -#[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantB {x: u8, y: i16 } +#[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantB {x: u8, y: i16, z: u8 } #[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantD(Option); #[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantE(Duration); fn main() { let result: Vec> = vec![ Ok(MyEnum::A(17)), - Ok(MyEnum::B { x: 206, y: 1145 }), + Ok(MyEnum::B { x: 206, y: 1145, z: 78 }), Ok(MyEnum::C), Err(()), Ok(MyEnum::D(Some(407))), @@ -63,7 +64,7 @@ fn main() { // Binary serialized version of the above (little-endian) let input: Vec = vec![ 0, 17, 0, 0, 0, - 1, 206, 121, 4, + 1, 206, 121, 4, 78, 2, 8, /* invalid tag value */ 3, 0, 151, 1, 0, 0, @@ -112,6 +113,7 @@ fn parse_my_enum<'a>(dest: &'a mut MyEnum, buf: &mut &[u8]) -> Result<(), ()> { MyEnumTag::B => { dest.payload.B.x = read_u8(buf)?; dest.payload.B.y = read_u16_le(buf)? as i16; + dest.payload.B.z = read_u8(buf)?; } MyEnumTag::C => { /* do nothing */ diff --git a/src/test/run-pass/structs-enums/enum-non-c-like-repr-c.rs b/src/test/run-pass/structs-enums/enum-non-c-like-repr-c.rs index 80c4339af9d6f..e88b91ab6c3f1 100644 --- a/src/test/run-pass/structs-enums/enum-non-c-like-repr-c.rs +++ b/src/test/run-pass/structs-enums/enum-non-c-like-repr-c.rs @@ -20,11 +20,12 @@ use std::mem; #[repr(C)] #[derive(Copy, Clone, Eq, PartialEq, Debug)] enum MyEnum { - A(u32), // Single primitive value - B { x: u8, y: i16 }, // Composite, and the offset of `y` depends on tag being internal - C, // Empty - D(Option), // Contains an enum - E(Duration), // Contains a struct + A(u32), // Single primitive value + B { x: u8, y: i16, z: u8 }, // Composite, and the offset of `y` and `z` + // depend on tag being internal + C, // Empty + D(Option), // Contains an enum + E(Duration), // Contains a struct } #[repr(C)] @@ -44,14 +45,14 @@ union MyEnumPayload { #[repr(C)] #[derive(Copy, Clone)] enum MyEnumTag { A, B, C, D, E } #[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantA(u32); -#[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantB {x: u8, y: i16 } +#[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantB {x: u8, y: i16, z: u8 } #[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantD(Option); #[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantE(Duration); fn main() { let result: Vec> = vec![ Ok(MyEnum::A(17)), - Ok(MyEnum::B { x: 206, y: 1145 }), + Ok(MyEnum::B { x: 206, y: 1145, z: 78 }), Ok(MyEnum::C), Err(()), Ok(MyEnum::D(Some(407))), @@ -63,7 +64,7 @@ fn main() { // Binary serialized version of the above (little-endian) let input: Vec = vec![ 0, 17, 0, 0, 0, - 1, 206, 121, 4, + 1, 206, 121, 4, 78, 2, 8, /* invalid tag value */ 3, 0, 151, 1, 0, 0, @@ -112,6 +113,7 @@ fn parse_my_enum<'a>(dest: &'a mut MyEnum, buf: &mut &[u8]) -> Result<(), ()> { MyEnumTag::B => { dest.payload.B.x = read_u8(buf)?; dest.payload.B.y = read_u16_le(buf)? as i16; + dest.payload.B.z = read_u8(buf)?; } MyEnumTag::C => { /* do nothing */ diff --git a/src/test/run-pass/structs-enums/enum-non-c-like-repr-int.rs b/src/test/run-pass/structs-enums/enum-non-c-like-repr-int.rs index 4c1fe8db1cda5..d862c0c72c2d8 100644 --- a/src/test/run-pass/structs-enums/enum-non-c-like-repr-int.rs +++ b/src/test/run-pass/structs-enums/enum-non-c-like-repr-int.rs @@ -20,11 +20,12 @@ use std::mem; #[repr(u8)] #[derive(Copy, Clone, Eq, PartialEq, Debug)] enum MyEnum { - A(u32), // Single primitive value - B { x: u8, y: i16 }, // Composite, and the offset of `y` depends on tag being internal - C, // Empty - D(Option), // Contains an enum - E(Duration), // Contains a struct + A(u32), // Single primitive value + B { x: u8, y: i16, z: u8 }, // Composite, and the offset of `y` and `z` + // depend on tag being internal + C, // Empty + D(Option), // Contains an enum + E(Duration), // Contains a struct } #[allow(non_snake_case)] @@ -39,7 +40,7 @@ union MyEnumRepr { #[repr(u8)] #[derive(Copy, Clone)] enum MyEnumTag { A, B, C, D, E } #[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantA(MyEnumTag, u32); -#[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantB { tag: MyEnumTag, x: u8, y: i16 } +#[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantB { tag: MyEnumTag, x: u8, y: i16, z: u8 } #[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantC(MyEnumTag); #[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantD(MyEnumTag, Option); #[repr(C)] #[derive(Copy, Clone)] struct MyEnumVariantE(MyEnumTag, Duration); @@ -47,7 +48,7 @@ union MyEnumRepr { fn main() { let result: Vec> = vec![ Ok(MyEnum::A(17)), - Ok(MyEnum::B { x: 206, y: 1145 }), + Ok(MyEnum::B { x: 206, y: 1145, z: 78 }), Ok(MyEnum::C), Err(()), Ok(MyEnum::D(Some(407))), @@ -59,7 +60,7 @@ fn main() { // Binary serialized version of the above (little-endian) let input: Vec = vec![ 0, 17, 0, 0, 0, - 1, 206, 121, 4, + 1, 206, 121, 4, 78, 2, 8, /* invalid tag value */ 3, 0, 151, 1, 0, 0, @@ -108,6 +109,7 @@ fn parse_my_enum<'a>(dest: &'a mut MyEnum, buf: &mut &[u8]) -> Result<(), ()> { MyEnumTag::B => { dest.B.x = read_u8(buf)?; dest.B.y = read_u16_le(buf)? as i16; + dest.B.z = read_u8(buf)?; } MyEnumTag::C => { /* do nothing */ From bbce189046fa84c1fb3d310920ab6bd536562a47 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Sun, 16 Dec 2018 12:11:19 -0800 Subject: [PATCH 10/84] rustc: Update Clang used to build LLVM on LInux This commit updates from LLVM 7.0.0 to git revisions of clang/llvm/lld to build LLVM on our dist builders for Linux. The goal of this is to fix #56849 by picking up a fix [1] in LLD. Closes #56849 [1]: https://github.com/llvm-mirror/lld/commit/3be4e82db78b46a8ca349b2b799dec620a6f159f --- .../docker/dist-x86_64-linux/build-clang.sh | 31 +++++++++---------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/src/ci/docker/dist-x86_64-linux/build-clang.sh b/src/ci/docker/dist-x86_64-linux/build-clang.sh index 2762f0bf7ec74..a7a8719b5357e 100755 --- a/src/ci/docker/dist-x86_64-linux/build-clang.sh +++ b/src/ci/docker/dist-x86_64-linux/build-clang.sh @@ -13,31 +13,28 @@ set -ex source shared.sh -LLVM=7.0.0 +# Currently these commits are all tip-of-tree as of 2018-12-16, used to pick up +# a fix for rust-lang/rust#56849 +LLVM=032b00a5404865765cda7db3039f39d54964d8b0 +LLD=3e4aa4e8671523321af51449e0569f455ef3ad43 +CLANG=a6b9739069763243020f4ea6fe586bc135fde1f9 mkdir clang cd clang -curl https://releases.llvm.org/$LLVM/llvm-$LLVM.src.tar.xz | \ - xz -d | \ - tar xf - - -cd llvm-$LLVM.src +curl -L https://github.com/llvm-mirror/llvm/archive/$LLVM.tar.gz | \ + tar xzf - --strip-components=1 mkdir -p tools/clang - -curl https://releases.llvm.org/$LLVM/cfe-$LLVM.src.tar.xz | \ - xz -d | \ - tar xf - -C tools/clang --strip-components=1 +curl -L https://github.com/llvm-mirror/clang/archive/$CLANG.tar.gz | \ + tar xzf - --strip-components=1 -C tools/clang mkdir -p tools/lld +curl -L https://github.com/llvm-mirror/lld/archive/$LLD.tar.gz | \ + tar zxf - --strip-components=1 -C tools/lld -curl https://releases.llvm.org/$LLVM/lld-$LLVM.src.tar.xz | \ - xz -d | \ - tar xf - -C tools/lld --strip-components=1 - -mkdir ../clang-build -cd ../clang-build +mkdir clang-build +cd clang-build # For whatever reason the default set of include paths for clang is different # than that of gcc. As a result we need to manually include our sysroot's @@ -55,7 +52,7 @@ INC="$INC:/rustroot/lib/gcc/x86_64-unknown-linux-gnu/4.8.5/include-fixed" INC="$INC:/usr/include" hide_output \ - cmake ../llvm-$LLVM.src \ + cmake .. \ -DCMAKE_C_COMPILER=/rustroot/bin/gcc \ -DCMAKE_CXX_COMPILER=/rustroot/bin/g++ \ -DCMAKE_BUILD_TYPE=Release \ From 37c356188147cbdfd36ed8077edcab97e0a6f1cf Mon Sep 17 00:00:00 2001 From: csmoe Date: Mon, 17 Dec 2018 19:41:48 +0800 Subject: [PATCH 11/84] describe index with accurate _ --- src/librustc_mir/borrow_check/error_reporting.rs | 2 +- .../borrowck/borrowck-describe-lvalue.mir.stderr | 2 +- src/test/ui/borrowck/borrowck-describe-lvalue.rs | 2 +- .../borrowck-vec-pattern-move-tail.cmp.stderr | 6 +++--- .../borrowck/borrowck-vec-pattern-move-tail.rs | 2 +- src/test/ui/issues/issue-46604.mir.stderr | 2 +- src/test/ui/nll/drop-no-may-dangle.rs | 4 ++-- src/test/ui/nll/drop-no-may-dangle.stderr | 16 ++++++++-------- 8 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs index 2d790c2a361ce..9826b4dbe5f86 100644 --- a/src/librustc_mir/borrow_check/error_reporting.rs +++ b/src/librustc_mir/borrow_check/error_reporting.rs @@ -1566,7 +1566,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { )?; buf.push_str("["); if self.append_local_to_string(index, buf).is_err() { - buf.push_str(".."); + buf.push_str("_"); } buf.push_str("]"); } diff --git a/src/test/ui/borrowck/borrowck-describe-lvalue.mir.stderr b/src/test/ui/borrowck/borrowck-describe-lvalue.mir.stderr index 5721c52ba2172..606c0e0b5c2a3 100644 --- a/src/test/ui/borrowck/borrowck-describe-lvalue.mir.stderr +++ b/src/test/ui/borrowck/borrowck-describe-lvalue.mir.stderr @@ -316,7 +316,7 @@ LL | v[0].y; LL | drop(x); | - borrow later used here -error[E0503]: cannot use `v[..].y` because it was mutably borrowed +error[E0503]: cannot use `v[_].y` because it was mutably borrowed --> $DIR/borrowck-describe-lvalue.rs:271:9 | LL | let x = &mut v; diff --git a/src/test/ui/borrowck/borrowck-describe-lvalue.rs b/src/test/ui/borrowck/borrowck-describe-lvalue.rs index 649de888ab0a2..c73fd27f9ff2a 100644 --- a/src/test/ui/borrowck/borrowck-describe-lvalue.rs +++ b/src/test/ui/borrowck/borrowck-describe-lvalue.rs @@ -270,7 +270,7 @@ fn main() { let x = &mut v; v[0].y; //[ast]~^ ERROR cannot use `v[..].y` because it was mutably borrowed - //[mir]~^^ ERROR cannot use `v[..].y` because it was mutably borrowed + //[mir]~^^ ERROR cannot use `v[_].y` because it was mutably borrowed //[mir]~| ERROR cannot use `*v` because it was mutably borrowed drop(x); } diff --git a/src/test/ui/borrowck/borrowck-vec-pattern-move-tail.cmp.stderr b/src/test/ui/borrowck/borrowck-vec-pattern-move-tail.cmp.stderr index a6aa9cd6d2a13..6192b1389bef6 100644 --- a/src/test/ui/borrowck/borrowck-vec-pattern-move-tail.cmp.stderr +++ b/src/test/ui/borrowck/borrowck-vec-pattern-move-tail.cmp.stderr @@ -7,14 +7,14 @@ LL | [1, 2, ref tail..] => tail, LL | a[2] = 0; //[ast]~ ERROR cannot assign to `a[..]` because it is borrowed | ^^^^^^^^ assignment to borrowed `a[..]` occurs here -error[E0506]: cannot assign to `a[..]` because it is borrowed (Mir) +error[E0506]: cannot assign to `a[_]` because it is borrowed (Mir) --> $DIR/borrowck-vec-pattern-move-tail.rs:24:5 | LL | [1, 2, ref tail..] => tail, - | -------- borrow of `a[..]` occurs here + | -------- borrow of `a[_]` occurs here ... LL | a[2] = 0; //[ast]~ ERROR cannot assign to `a[..]` because it is borrowed - | ^^^^^^^^ assignment to borrowed `a[..]` occurs here + | ^^^^^^^^ assignment to borrowed `a[_]` occurs here ... LL | println!("t[0]: {}", t[0]); | ---- borrow later used here diff --git a/src/test/ui/borrowck/borrowck-vec-pattern-move-tail.rs b/src/test/ui/borrowck/borrowck-vec-pattern-move-tail.rs index 94877b27d5888..48b5af01705ae 100644 --- a/src/test/ui/borrowck/borrowck-vec-pattern-move-tail.rs +++ b/src/test/ui/borrowck/borrowck-vec-pattern-move-tail.rs @@ -23,7 +23,7 @@ fn main() { println!("t[0]: {}", t[0]); a[2] = 0; //[ast]~ ERROR cannot assign to `a[..]` because it is borrowed //[cmp]~^ ERROR cannot assign to `a[..]` because it is borrowed (Ast) - //[cmp]~| ERROR cannot assign to `a[..]` because it is borrowed (Mir) + //[cmp]~| ERROR cannot assign to `a[_]` because it is borrowed (Mir) println!("t[0]: {}", t[0]); t[0]; } diff --git a/src/test/ui/issues/issue-46604.mir.stderr b/src/test/ui/issues/issue-46604.mir.stderr index a4ee0d4e2a3a9..3ad0f256ed7e1 100644 --- a/src/test/ui/issues/issue-46604.mir.stderr +++ b/src/test/ui/issues/issue-46604.mir.stderr @@ -4,7 +4,7 @@ error[E0017]: references in statics may only refer to immutable values LL | static buf: &mut [u8] = &mut [1u8,2,3,4,5,7]; //[ast]~ ERROR E0017 | ^^^^^^^^^^^^^^^^^^^^ statics require immutable values -error[E0594]: cannot assign to `buf[..]`, as `buf` is an immutable static item +error[E0594]: cannot assign to `buf[_]`, as `buf` is an immutable static item --> $DIR/issue-46604.rs:20:5 | LL | buf[0]=2; //[ast]~ ERROR E0389 diff --git a/src/test/ui/nll/drop-no-may-dangle.rs b/src/test/ui/nll/drop-no-may-dangle.rs index 513609316311a..fce4ad904f137 100644 --- a/src/test/ui/nll/drop-no-may-dangle.rs +++ b/src/test/ui/nll/drop-no-may-dangle.rs @@ -27,10 +27,10 @@ fn main() { use_x(*p.value); } else { use_x(22); - v[0] += 1; //~ ERROR cannot assign to `v[..]` because it is borrowed + v[0] += 1; //~ ERROR cannot assign to `v[_]` because it is borrowed } - v[0] += 1; //~ ERROR cannot assign to `v[..]` because it is borrowed + v[0] += 1; //~ ERROR cannot assign to `v[_]` because it is borrowed } struct WrapMayNotDangle { diff --git a/src/test/ui/nll/drop-no-may-dangle.stderr b/src/test/ui/nll/drop-no-may-dangle.stderr index 60862d0f22952..0c1d0b29d2c8b 100644 --- a/src/test/ui/nll/drop-no-may-dangle.stderr +++ b/src/test/ui/nll/drop-no-may-dangle.stderr @@ -1,23 +1,23 @@ -error[E0506]: cannot assign to `v[..]` because it is borrowed +error[E0506]: cannot assign to `v[_]` because it is borrowed --> $DIR/drop-no-may-dangle.rs:30:9 | LL | let p: WrapMayNotDangle<&usize> = WrapMayNotDangle { value: &v[0] }; - | ----- borrow of `v[..]` occurs here + | ----- borrow of `v[_]` occurs here ... -LL | v[0] += 1; //~ ERROR cannot assign to `v[..]` because it is borrowed - | ^^^^^^^^^ assignment to borrowed `v[..]` occurs here +LL | v[0] += 1; //~ ERROR cannot assign to `v[_]` because it is borrowed + | ^^^^^^^^^ assignment to borrowed `v[_]` occurs here ... LL | } | - borrow might be used here, when `p` is dropped and runs the `Drop` code for type `WrapMayNotDangle` -error[E0506]: cannot assign to `v[..]` because it is borrowed +error[E0506]: cannot assign to `v[_]` because it is borrowed --> $DIR/drop-no-may-dangle.rs:33:5 | LL | let p: WrapMayNotDangle<&usize> = WrapMayNotDangle { value: &v[0] }; - | ----- borrow of `v[..]` occurs here + | ----- borrow of `v[_]` occurs here ... -LL | v[0] += 1; //~ ERROR cannot assign to `v[..]` because it is borrowed - | ^^^^^^^^^ assignment to borrowed `v[..]` occurs here +LL | v[0] += 1; //~ ERROR cannot assign to `v[_]` because it is borrowed + | ^^^^^^^^^ assignment to borrowed `v[_]` occurs here LL | } | - borrow might be used here, when `p` is dropped and runs the `Drop` code for type `WrapMayNotDangle` From e38e954a0d249f88d0a55504f70d6055e865a931 Mon Sep 17 00:00:00 2001 From: Shotaro Yamada Date: Mon, 17 Dec 2018 15:57:38 +0900 Subject: [PATCH 12/84] Simplify MIR generation for logical ops --- src/librustc_mir/build/expr/into.rs | 53 +++++++++++++---------------- 1 file changed, 23 insertions(+), 30 deletions(-) diff --git a/src/librustc_mir/build/expr/into.rs b/src/librustc_mir/build/expr/into.rs index 0e7305e076ede..a26b0055a048c 100644 --- a/src/librustc_mir/build/expr/into.rs +++ b/src/librustc_mir/build/expr/into.rs @@ -126,18 +126,17 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { ExprKind::LogicalOp { op, lhs, rhs } => { // And: // - // [block: If(lhs)] -true-> [else_block: If(rhs)] -true-> [true_block] - // | | (false) - // +----------false-----------+------------------> [false_block] + // [block: If(lhs)] -true-> [else_block: dest = (rhs)] + // | (false) + // [shortcurcuit_block: dest = false] // // Or: // - // [block: If(lhs)] -false-> [else_block: If(rhs)] -true-> [true_block] - // | (true) | (false) - // [true_block] [false_block] + // [block: If(lhs)] -false-> [else_block: dest = (rhs)] + // | (true) + // [shortcurcuit_block: dest = true] - let (true_block, false_block, mut else_block, join_block) = ( - this.cfg.start_new_block(), + let (shortcircuit_block, mut else_block, join_block) = ( this.cfg.start_new_block(), this.cfg.start_new_block(), this.cfg.start_new_block(), @@ -145,47 +144,41 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { let lhs = unpack!(block = this.as_local_operand(block, lhs)); let blocks = match op { - LogicalOp::And => (else_block, false_block), - LogicalOp::Or => (true_block, else_block), + LogicalOp::And => (else_block, shortcircuit_block), + LogicalOp::Or => (shortcircuit_block, else_block), }; let term = TerminatorKind::if_(this.hir.tcx(), lhs, blocks.0, blocks.1); this.cfg.terminate(block, source_info, term); - let rhs = unpack!(else_block = this.as_local_operand(else_block, rhs)); - let term = TerminatorKind::if_(this.hir.tcx(), rhs, true_block, false_block); - this.cfg.terminate(else_block, source_info, term); - this.cfg.push_assign_constant( - true_block, + shortcircuit_block, source_info, destination, Constant { span: expr_span, ty: this.hir.bool_ty(), user_ty: None, - literal: this.hir.true_literal(), + literal: match op { + LogicalOp::And => this.hir.false_literal(), + LogicalOp::Or => this.hir.true_literal(), + }, }, ); - - this.cfg.push_assign_constant( - false_block, + this.cfg.terminate( + shortcircuit_block, source_info, - destination, - Constant { - span: expr_span, - ty: this.hir.bool_ty(), - user_ty: None, - literal: this.hir.false_literal(), - }, + TerminatorKind::Goto { target: join_block }, ); - this.cfg.terminate( - true_block, + let rhs = unpack!(else_block = this.as_local_operand(else_block, rhs)); + this.cfg.push_assign( + else_block, source_info, - TerminatorKind::Goto { target: join_block }, + destination, + Rvalue::Use(rhs), ); this.cfg.terminate( - false_block, + else_block, source_info, TerminatorKind::Goto { target: join_block }, ); From 3e7a4ca2f1d576a4a23e8c541cb5c0c420b108de Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Mon, 17 Dec 2018 16:47:26 +0100 Subject: [PATCH 13/84] Remove a wrong multiplier on relocation offset computation --- src/librustc_mir/interpret/memory.rs | 8 ++++---- src/test/ui/consts/promoted_regression.rs | 9 +++++++++ 2 files changed, 13 insertions(+), 4 deletions(-) create mode 100644 src/test/ui/consts/promoted_regression.rs diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index 420fe26426321..65347a02be0c7 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -707,10 +707,10 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { new_relocations.extend( relocations .iter() - .map(|&(offset, reloc)| { - (offset + dest.offset - src.offset + (i * size * relocations.len() as u64), - reloc) - }) + .map(|&(offset, reloc)| ( + offset + dest.offset - src.offset + (i * size), + reloc, + )) ); } diff --git a/src/test/ui/consts/promoted_regression.rs b/src/test/ui/consts/promoted_regression.rs new file mode 100644 index 0000000000000..68b9a20ecf90b --- /dev/null +++ b/src/test/ui/consts/promoted_regression.rs @@ -0,0 +1,9 @@ +// compile-pass + +fn main() { + let _ = &[("", ""); 3]; +} + +const FOO: &[(&str, &str)] = &[("", ""); 3]; +const BAR: &[(&str, &str); 5] = &[("", ""); 5]; +const BAA: &[[&str; 12]; 11] = &[[""; 12]; 11]; From e7e17f9d1b008a1f06ad8b4ef06c443b4b879bc4 Mon Sep 17 00:00:00 2001 From: Dan Robertson Date: Mon, 17 Dec 2018 03:17:59 +0000 Subject: [PATCH 14/84] static eval: Do not ICE on layout size overflow Layout size overflow and typeck eval errors are reported. Trigger a bug only when the eval error is strictly labeled as TooGeneric. --- src/librustc_mir/const_eval.rs | 12 ++++++++---- src/test/ui/issues/issue-56762.rs | 18 ++++++++++++++++++ src/test/ui/issues/issue-56762.stderr | 4 ++++ 3 files changed, 30 insertions(+), 4 deletions(-) create mode 100644 src/test/ui/issues/issue-56762.rs create mode 100644 src/test/ui/issues/issue-56762.stderr diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs index 248c5d2db4917..d5bc83aba7b99 100644 --- a/src/librustc_mir/const_eval.rs +++ b/src/librustc_mir/const_eval.rs @@ -692,12 +692,16 @@ pub fn const_eval_raw_provider<'a, 'tcx>( let err = error_to_const_error(&ecx, error); // errors in statics are always emitted as fatal errors if tcx.is_static(def_id).is_some() { - let err = err.report_as_error(ecx.tcx, "could not evaluate static initializer"); - // check that a static never produces `TooGeneric` + let reported_err = err.report_as_error(ecx.tcx, + "could not evaluate static initializer"); + // Ensure that if the above error was either `TooGeneric` or `Reported` + // an error must be reported. if tcx.sess.err_count() == 0 { - span_bug!(ecx.tcx.span, "static eval failure didn't emit an error: {:#?}", err); + tcx.sess.delay_span_bug(err.span, + &format!("static eval failure did not emit an error: {:#?}", + reported_err)); } - err + reported_err } else if def_id.is_local() { // constant defined in this crate, we can figure out a lint level! match tcx.describe_def(def_id) { diff --git a/src/test/ui/issues/issue-56762.rs b/src/test/ui/issues/issue-56762.rs new file mode 100644 index 0000000000000..97b66b2c7c923 --- /dev/null +++ b/src/test/ui/issues/issue-56762.rs @@ -0,0 +1,18 @@ +// only-x86_64 +const HUGE_SIZE: usize = !0usize / 8; + + +pub struct TooBigArray { + arr: [u8; HUGE_SIZE], +} + +impl TooBigArray { + pub const fn new() -> Self { + TooBigArray { arr: [0x00; HUGE_SIZE], } + } +} + +static MY_TOO_BIG_ARRAY_1: TooBigArray = TooBigArray::new(); +static MY_TOO_BIG_ARRAY_2: [u8; HUGE_SIZE] = [0x00; HUGE_SIZE]; + +fn main() { } diff --git a/src/test/ui/issues/issue-56762.stderr b/src/test/ui/issues/issue-56762.stderr new file mode 100644 index 0000000000000..83d5dc62e6161 --- /dev/null +++ b/src/test/ui/issues/issue-56762.stderr @@ -0,0 +1,4 @@ +error: the type `[u8; 2305843009213693951]` is too big for the current architecture + +error: aborting due to previous error + From 6130fc884bc1dff9bb835894a7bb2042c110b011 Mon Sep 17 00:00:00 2001 From: Clar Fon Date: Mon, 17 Dec 2018 17:16:39 -0500 Subject: [PATCH 15/84] Add --progress to git submodule commands --- src/bootstrap/bootstrap.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index d143dffb24be5..09c87fdd1a84c 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -678,10 +678,10 @@ def update_submodule(self, module, checked_out, recorded_submodules): print("Updating submodule", module) - run(["git", "submodule", "-q", "sync", module], + run(["git", "submodule", "-q", "sync", "--progress", module], cwd=self.rust_root, verbose=self.verbose) run(["git", "submodule", "update", - "--init", "--recursive", module], + "--init", "--recursive", "--progress", module], cwd=self.rust_root, verbose=self.verbose) run(["git", "reset", "-q", "--hard"], cwd=module_path, verbose=self.verbose) From e36b62873fb6787d521fbc4e0bd89915e28ed0f1 Mon Sep 17 00:00:00 2001 From: Nicole Mazzuca Date: Mon, 17 Dec 2018 16:41:48 -0800 Subject: [PATCH 16/84] rename div_euc -> div_euclid, and mod_euc -> rem_euclid logic is written up in https://github.com/rust-lang/rust/issues/49048 Also, update the documentation slightly --- src/libcore/num/mod.rs | 172 ++++++++++++++++------------ src/libcore/tests/num/int_macros.rs | 4 +- src/libcore/tests/num/mod.rs | 26 ++--- src/libstd/f32.rs | 30 ++--- src/libstd/f64.rs | 30 ++--- 5 files changed, 141 insertions(+), 121 deletions(-) diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index f1df1f2856ed6..cedee1c8e5f99 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -673,7 +673,7 @@ $EndFeature, " } doc_comment! { - concat!("Checked Euclidean division. Computes `self.div_euc(rhs)`, + concat!("Checked Euclidean division. Computes `self.div_euclid(rhs)`, returning `None` if `rhs == 0` or the division results in overflow. # Examples @@ -683,17 +683,17 @@ Basic usage: ``` #![feature(euclidean_division)] assert_eq!((", stringify!($SelfT), -"::min_value() + 1).checked_div_euc(-1), Some(", stringify!($Max), ")); -assert_eq!(", stringify!($SelfT), "::min_value().checked_div_euc(-1), None); -assert_eq!((1", stringify!($SelfT), ").checked_div_euc(0), None); +"::min_value() + 1).checked_div_euclid(-1), Some(", stringify!($Max), ")); +assert_eq!(", stringify!($SelfT), "::min_value().checked_div_euclid(-1), None); +assert_eq!((1", stringify!($SelfT), ").checked_div_euclid(0), None); ```"), #[unstable(feature = "euclidean_division", issue = "49048")] #[inline] - pub fn checked_div_euc(self, rhs: Self) -> Option { + pub fn checked_div_euclid(self, rhs: Self) -> Option { if rhs == 0 || (self == Self::min_value() && rhs == -1) { None } else { - Some(self.div_euc(rhs)) + Some(self.div_euclid(rhs)) } } } @@ -726,8 +726,8 @@ $EndFeature, " } doc_comment! { - concat!("Checked Euclidean modulo. Computes `self.mod_euc(rhs)`, returning `None` if -`rhs == 0` or the division results in overflow. + concat!("Checked Euclidean remainder. Computes `self.rem_euclid(rhs)`, returning `None` +if `rhs == 0` or the division results in overflow. # Examples @@ -737,17 +737,17 @@ Basic usage: #![feature(euclidean_division)] use std::", stringify!($SelfT), "; -assert_eq!(5", stringify!($SelfT), ".checked_mod_euc(2), Some(1)); -assert_eq!(5", stringify!($SelfT), ".checked_mod_euc(0), None); -assert_eq!(", stringify!($SelfT), "::MIN.checked_mod_euc(-1), None); +assert_eq!(5", stringify!($SelfT), ".checked_rem_euclid(2), Some(1)); +assert_eq!(5", stringify!($SelfT), ".checked_rem_euclid(0), None); +assert_eq!(", stringify!($SelfT), "::MIN.checked_rem_euclid(-1), None); ```"), #[unstable(feature = "euclidean_division", issue = "49048")] #[inline] - pub fn checked_mod_euc(self, rhs: Self) -> Option { + pub fn checked_rem_euclid(self, rhs: Self) -> Option { if rhs == 0 || (self == Self::min_value() && rhs == -1) { None } else { - Some(self.mod_euc(rhs)) + Some(self.rem_euclid(rhs)) } } } @@ -1089,7 +1089,7 @@ $EndFeature, " } doc_comment! { - concat!("Wrapping Euclidean division. Computes `self.div_euc(rhs)`, + concat!("Wrapping Euclidean division. Computes `self.div_euclid(rhs)`, wrapping around at the boundary of the type. Wrapping will only occur in `MIN / -1` on a signed type (where `MIN` is the negative minimal value @@ -1106,13 +1106,13 @@ Basic usage: ``` #![feature(euclidean_division)] -assert_eq!(100", stringify!($SelfT), ".wrapping_div_euc(10), 10); -assert_eq!((-128i8).wrapping_div_euc(-1), -128); +assert_eq!(100", stringify!($SelfT), ".wrapping_div_euclid(10), 10); +assert_eq!((-128i8).wrapping_div_euclid(-1), -128); ```"), #[unstable(feature = "euclidean_division", issue = "49048")] #[inline] - pub fn wrapping_div_euc(self, rhs: Self) -> Self { - self.overflowing_div_euc(rhs).0 + pub fn wrapping_div_euclid(self, rhs: Self) -> Self { + self.overflowing_div_euclid(rhs).0 } } @@ -1145,8 +1145,8 @@ $EndFeature, " } doc_comment! { - concat!("Wrapping Euclidean modulo. Computes `self.mod_euc(rhs)`, wrapping around at the -boundary of the type. + concat!("Wrapping Euclidean remainder. Computes `self.rem_euclid(rhs)`, wrapping around +at the boundary of the type. Wrapping will only occur in `MIN % -1` on a signed type (where `MIN` is the negative minimal value for the type). In this case, this method returns 0. @@ -1161,13 +1161,13 @@ Basic usage: ``` #![feature(euclidean_division)] -assert_eq!(100", stringify!($SelfT), ".wrapping_mod_euc(10), 0); -assert_eq!((-128i8).wrapping_mod_euc(-1), 0); +assert_eq!(100", stringify!($SelfT), ".wrapping_rem_euclid(10), 0); +assert_eq!((-128i8).wrapping_rem_euclid(-1), 0); ```"), #[unstable(feature = "euclidean_division", issue = "49048")] #[inline] - pub fn wrapping_mod_euc(self, rhs: Self) -> Self { - self.overflowing_mod_euc(rhs).0 + pub fn wrapping_rem_euclid(self, rhs: Self) -> Self { + self.overflowing_rem_euclid(rhs).0 } } @@ -1442,7 +1442,7 @@ $EndFeature, " } doc_comment! { - concat!("Calculates the quotient of Euclidean division `self.div_euc(rhs)`. + concat!("Calculates the quotient of Euclidean division `self.div_euclid(rhs)`. Returns a tuple of the divisor along with a boolean indicating whether an arithmetic overflow would occur. If an overflow would occur then `self` is returned. @@ -1459,17 +1459,17 @@ Basic usage: #![feature(euclidean_division)] use std::", stringify!($SelfT), "; -assert_eq!(5", stringify!($SelfT), ".overflowing_div_euc(2), (2, false)); -assert_eq!(", stringify!($SelfT), "::MIN.overflowing_div_euc(-1), (", stringify!($SelfT), +assert_eq!(5", stringify!($SelfT), ".overflowing_div_euclid(2), (2, false)); +assert_eq!(", stringify!($SelfT), "::MIN.overflowing_div_euclid(-1), (", stringify!($SelfT), "::MIN, true)); ```"), #[inline] #[unstable(feature = "euclidean_division", issue = "49048")] - pub fn overflowing_div_euc(self, rhs: Self) -> (Self, bool) { + pub fn overflowing_div_euclid(self, rhs: Self) -> (Self, bool) { if self == Self::min_value() && rhs == -1 { (self, true) } else { - (self.div_euc(rhs), false) + (self.div_euclid(rhs), false) } } } @@ -1508,7 +1508,7 @@ $EndFeature, " doc_comment! { - concat!("Calculates the remainder `self.mod_euc(rhs)` by Euclidean division. + concat!("Overflowing Euclidean remainder. Calculates `self.rem_euclid(rhs)`. Returns a tuple of the remainder after dividing along with a boolean indicating whether an arithmetic overflow would occur. If an overflow would occur then 0 is returned. @@ -1525,16 +1525,16 @@ Basic usage: #![feature(euclidean_division)] use std::", stringify!($SelfT), "; -assert_eq!(5", stringify!($SelfT), ".overflowing_mod_euc(2), (1, false)); -assert_eq!(", stringify!($SelfT), "::MIN.overflowing_mod_euc(-1), (0, true)); +assert_eq!(5", stringify!($SelfT), ".overflowing_rem_euclid(2), (1, false)); +assert_eq!(", stringify!($SelfT), "::MIN.overflowing_rem_euclid(-1), (0, true)); ```"), #[unstable(feature = "euclidean_division", issue = "49048")] #[inline] - pub fn overflowing_mod_euc(self, rhs: Self) -> (Self, bool) { + pub fn overflowing_rem_euclid(self, rhs: Self) -> (Self, bool) { if self == Self::min_value() && rhs == -1 { (0, true) } else { - (self.mod_euc(rhs), false) + (self.rem_euclid(rhs), false) } } } @@ -1739,9 +1739,13 @@ $EndFeature, " doc_comment! { concat!("Calculates the quotient of Euclidean division of `self` by `rhs`. -This computes the integer `n` such that `self = n * rhs + self.mod_euc(rhs)`. +This computes the integer `n` such that `self = n * rhs + self.rem_euclid(rhs)`, +with the `0 <= self.rem_euclid(rhs) < rhs`. + In other words, the result is `self / rhs` rounded to the integer `n` such that `self >= n * rhs`. +If `self > 0`, this is equal to round towards zero (the default in Rust); +if `self < 0`, this is equal to round towards +/- infinity. # Panics @@ -1756,15 +1760,15 @@ Basic usage: let a: ", stringify!($SelfT), " = 7; // or any other integer type let b = 4; -assert_eq!(a.div_euc(b), 1); // 7 >= 4 * 1 -assert_eq!(a.div_euc(-b), -1); // 7 >= -4 * -1 -assert_eq!((-a).div_euc(b), -2); // -7 >= 4 * -2 -assert_eq!((-a).div_euc(-b), 2); // -7 >= -4 * 2 +assert_eq!(a.div_euclid(b), 1); // 7 >= 4 * 1 +assert_eq!(a.div_euclid(-b), -1); // 7 >= -4 * -1 +assert_eq!((-a).div_euclid(b), -2); // -7 >= 4 * -2 +assert_eq!((-a).div_euclid(-b), 2); // -7 >= -4 * 2 ```"), #[unstable(feature = "euclidean_division", issue = "49048")] #[inline] #[rustc_inherit_overflow_checks] - pub fn div_euc(self, rhs: Self) -> Self { + pub fn div_euclid(self, rhs: Self) -> Self { let q = self / rhs; if self % rhs < 0 { return if rhs > 0 { q - 1 } else { q + 1 } @@ -1775,9 +1779,9 @@ assert_eq!((-a).div_euc(-b), 2); // -7 >= -4 * 2 doc_comment! { - concat!("Calculates the remainder `self mod rhs` by Euclidean division. + concat!("Calculates the least nonnegative remainder of `self (mod rhs)`. -In particular, the result `n` satisfies `0 <= n < rhs.abs()`. +This is done as if by the euclidean division algorithm. # Panics @@ -1792,15 +1796,15 @@ Basic usage: let a: ", stringify!($SelfT), " = 7; // or any other integer type let b = 4; -assert_eq!(a.mod_euc(b), 3); -assert_eq!((-a).mod_euc(b), 1); -assert_eq!(a.mod_euc(-b), 3); -assert_eq!((-a).mod_euc(-b), 1); +assert_eq!(a.rem_euclid(b), 3); +assert_eq!((-a).rem_euclid(b), 1); +assert_eq!(a.rem_euclid(-b), 3); +assert_eq!((-a).rem_euclid(-b), 1); ```"), #[unstable(feature = "euclidean_division", issue = "49048")] #[inline] #[rustc_inherit_overflow_checks] - pub fn mod_euc(self, rhs: Self) -> Self { + pub fn rem_euclid(self, rhs: Self) -> Self { let r = self % rhs; if r < 0 { if rhs < 0 { @@ -2611,7 +2615,7 @@ assert_eq!(1", stringify!($SelfT), ".checked_div(0), None);", $EndFeature, " } doc_comment! { - concat!("Checked Euclidean division. Computes `self.div_euc(rhs)`, returning `None` + concat!("Checked Euclidean division. Computes `self.div_euclid(rhs)`, returning `None` if `rhs == 0`. # Examples @@ -2620,16 +2624,16 @@ Basic usage: ``` #![feature(euclidean_division)] -assert_eq!(128", stringify!($SelfT), ".checked_div(2), Some(64)); -assert_eq!(1", stringify!($SelfT), ".checked_div_euc(0), None); +assert_eq!(128", stringify!($SelfT), ".checked_div_euclid(2), Some(64)); +assert_eq!(1", stringify!($SelfT), ".checked_div_euclid(0), None); ```"), #[unstable(feature = "euclidean_division", issue = "49048")] #[inline] - pub fn checked_div_euc(self, rhs: Self) -> Option { + pub fn checked_div_euclid(self, rhs: Self) -> Option { if rhs == 0 { None } else { - Some(self.div_euc(rhs)) + Some(self.div_euclid(rhs)) } } } @@ -2659,7 +2663,7 @@ assert_eq!(5", stringify!($SelfT), ".checked_rem(0), None);", $EndFeature, " } doc_comment! { - concat!("Checked Euclidean modulo. Computes `self.mod_euc(rhs)`, returning `None` + concat!("Checked Euclidean modulo. Computes `self.rem_euclid(rhs)`, returning `None` if `rhs == 0`. # Examples @@ -2668,16 +2672,16 @@ Basic usage: ``` #![feature(euclidean_division)] -assert_eq!(5", stringify!($SelfT), ".checked_mod_euc(2), Some(1)); -assert_eq!(5", stringify!($SelfT), ".checked_mod_euc(0), None); +assert_eq!(5", stringify!($SelfT), ".checked_rem_euclid(2), Some(1)); +assert_eq!(5", stringify!($SelfT), ".checked_rem_euclid(0), None); ```"), #[unstable(feature = "euclidean_division", issue = "49048")] #[inline] - pub fn checked_mod_euc(self, rhs: Self) -> Option { + pub fn checked_rem_euclid(self, rhs: Self) -> Option { if rhs == 0 { None } else { - Some(self.mod_euc(rhs)) + Some(self.rem_euclid(rhs)) } } } @@ -2965,11 +2969,14 @@ Basic usage: } doc_comment! { - concat!("Wrapping Euclidean division. Computes `self.div_euc(rhs)`. + concat!("Wrapping Euclidean division. Computes `self.div_euclid(rhs)`. Wrapped division on unsigned types is just normal division. There's no way wrapping could ever happen. This function exists, so that all operations are accounted for in the wrapping operations. +Since, for the positive integers, all common +definitions of division are equal, this +is exactly equal to `self.wrapping_div(rhs)`. # Examples @@ -2977,11 +2984,11 @@ Basic usage: ``` #![feature(euclidean_division)] -assert_eq!(100", stringify!($SelfT), ".wrapping_div_euc(10), 10); +assert_eq!(100", stringify!($SelfT), ".wrapping_div_euclid(10), 10); ```"), #[unstable(feature = "euclidean_division", issue = "49048")] #[inline] - pub fn wrapping_div_euc(self, rhs: Self) -> Self { + pub fn wrapping_div_euclid(self, rhs: Self) -> Self { self / rhs } } @@ -3009,12 +3016,15 @@ Basic usage: } doc_comment! { - concat!("Wrapping Euclidean modulo. Computes `self.mod_euc(rhs)`. + concat!("Wrapping Euclidean modulo. Computes `self.rem_euclid(rhs)`. Wrapped modulo calculation on unsigned types is just the regular remainder calculation. There's no way wrapping could ever happen. This function exists, so that all operations are accounted for in the wrapping operations. +Since, for the positive integers, all common +definitions of division are equal, this +is exactly equal to `self.wrapping_rem(rhs)`. # Examples @@ -3022,11 +3032,11 @@ Basic usage: ``` #![feature(euclidean_division)] -assert_eq!(100", stringify!($SelfT), ".wrapping_mod_euc(10), 0); +assert_eq!(100", stringify!($SelfT), ".wrapping_rem_euclid(10), 0); ```"), #[unstable(feature = "euclidean_division", issue = "49048")] #[inline] - pub fn wrapping_mod_euc(self, rhs: Self) -> Self { + pub fn wrapping_rem_euclid(self, rhs: Self) -> Self { self % rhs } } @@ -3270,12 +3280,15 @@ Basic usage } doc_comment! { - concat!("Calculates the quotient of Euclidean division `self.div_euc(rhs)`. + concat!("Calculates the quotient of Euclidean division `self.div_euclid(rhs)`. Returns a tuple of the divisor along with a boolean indicating whether an arithmetic overflow would occur. Note that for unsigned integers overflow never occurs, so the second value is always `false`. +Since, for the positive integers, all common +definitions of division are equal, this +is exactly equal to `self.overflowing_div(rhs)`. # Panics @@ -3287,11 +3300,11 @@ Basic usage ``` #![feature(euclidean_division)] -assert_eq!(5", stringify!($SelfT), ".overflowing_div_euc(2), (2, false)); +assert_eq!(5", stringify!($SelfT), ".overflowing_div_euclid(2), (2, false)); ```"), #[inline] #[unstable(feature = "euclidean_division", issue = "49048")] - pub fn overflowing_div_euc(self, rhs: Self) -> (Self, bool) { + pub fn overflowing_div_euclid(self, rhs: Self) -> (Self, bool) { (self / rhs, false) } } @@ -3323,12 +3336,15 @@ Basic usage } doc_comment! { - concat!("Calculates the remainder `self.mod_euc(rhs)` by Euclidean division. + concat!("Calculates the remainder `self.rem_euclid(rhs)` as if by Euclidean division. Returns a tuple of the modulo after dividing along with a boolean indicating whether an arithmetic overflow would occur. Note that for unsigned integers overflow never occurs, so the second value is always `false`. +Since, for the positive integers, all common +definitions of division are equal, this operation +is exactly equal to `self.overflowing_rem(rhs)`. # Panics @@ -3340,11 +3356,11 @@ Basic usage ``` #![feature(euclidean_division)] -assert_eq!(5", stringify!($SelfT), ".overflowing_mod_euc(2), (1, false)); +assert_eq!(5", stringify!($SelfT), ".overflowing_rem_euclid(2), (1, false)); ```"), #[inline] #[unstable(feature = "euclidean_division", issue = "49048")] - pub fn overflowing_mod_euc(self, rhs: Self) -> (Self, bool) { + pub fn overflowing_rem_euclid(self, rhs: Self) -> (Self, bool) { (self % rhs, false) } } @@ -3511,7 +3527,9 @@ Basic usage: doc_comment! { concat!("Performs Euclidean division. -For unsigned types, this is just the same as `self / rhs`. +Since, for the positive integers, all common +definitions of division are equal, this +is exactly equal to `self / rhs`. # Examples @@ -3519,21 +3537,23 @@ Basic usage: ``` #![feature(euclidean_division)] -assert_eq!(7", stringify!($SelfT), ".div_euc(4), 1); // or any other integer type +assert_eq!(7", stringify!($SelfT), ".div_euclid(4), 1); // or any other integer type ```"), #[unstable(feature = "euclidean_division", issue = "49048")] #[inline] #[rustc_inherit_overflow_checks] - pub fn div_euc(self, rhs: Self) -> Self { + pub fn div_euclid(self, rhs: Self) -> Self { self / rhs } } doc_comment! { - concat!("Calculates the remainder `self mod rhs` by Euclidean division. + concat!("Calculates the least remainder of `self (mod rhs)`. -For unsigned types, this is just the same as `self % rhs`. +Since, for the positive integers, all common +definitions of division are equal, this +is exactly equal to `self % rhs`. # Examples @@ -3541,12 +3561,12 @@ Basic usage: ``` #![feature(euclidean_division)] -assert_eq!(7", stringify!($SelfT), ".mod_euc(4), 3); // or any other integer type +assert_eq!(7", stringify!($SelfT), ".rem_euclid(4), 3); // or any other integer type ```"), #[unstable(feature = "euclidean_division", issue = "49048")] #[inline] #[rustc_inherit_overflow_checks] - pub fn mod_euc(self, rhs: Self) -> Self { + pub fn rem_euclid(self, rhs: Self) -> Self { self % rhs } } diff --git a/src/libcore/tests/num/int_macros.rs b/src/libcore/tests/num/int_macros.rs index 71d2e7945389b..577847b3c8282 100644 --- a/src/libcore/tests/num/int_macros.rs +++ b/src/libcore/tests/num/int_macros.rs @@ -31,8 +31,8 @@ mod tests { } #[test] - fn test_mod_euc() { - assert!((-1 as $T).mod_euc(MIN) == MAX); + fn test_mod_euclid() { + assert!((-1 as $T).mod_euclid(MIN) == MAX); } #[test] diff --git a/src/libcore/tests/num/mod.rs b/src/libcore/tests/num/mod.rs index 0928f7560e175..e1648db5e8ed2 100644 --- a/src/libcore/tests/num/mod.rs +++ b/src/libcore/tests/num/mod.rs @@ -694,23 +694,23 @@ macro_rules! test_float { assert!(($nan as $fty).max($nan).is_nan()); } #[test] - fn mod_euc() { + fn rem_euclid() { let a: $fty = 42.0; - assert!($inf.mod_euc(a).is_nan()); - assert_eq!(a.mod_euc($inf), a); - assert!(a.mod_euc($nan).is_nan()); - assert!($inf.mod_euc($inf).is_nan()); - assert!($inf.mod_euc($nan).is_nan()); - assert!($nan.mod_euc($inf).is_nan()); + assert!($inf.rem_euclid(a).is_nan()); + assert_eq!(a.rem_euclid($inf), a); + assert!(a.rem_euclid($nan).is_nan()); + assert!($inf.rem_euclid($inf).is_nan()); + assert!($inf.rem_euclid($nan).is_nan()); + assert!($nan.rem_euclid($inf).is_nan()); } #[test] - fn div_euc() { + fn div_euclid() { let a: $fty = 42.0; - assert_eq!(a.div_euc($inf), 0.0); - assert!(a.div_euc($nan).is_nan()); - assert!($inf.div_euc($inf).is_nan()); - assert!($inf.div_euc($nan).is_nan()); - assert!($nan.div_euc($inf).is_nan()); + assert_eq!(a.div_euclid($inf), 0.0); + assert!(a.div_euclid($nan).is_nan()); + assert!($inf.div_euclid($inf).is_nan()); + assert!($inf.div_euclid($nan).is_nan()); + assert!($nan.div_euclid($inf).is_nan()); } } } } diff --git a/src/libstd/f32.rs b/src/libstd/f32.rs index d0dd4d4adcb98..209343444a0b5 100644 --- a/src/libstd/f32.rs +++ b/src/libstd/f32.rs @@ -253,10 +253,10 @@ impl f32 { unsafe { intrinsics::fmaf32(self, a, b) } } - /// Calculates Euclidean division, the matching method for `mod_euc`. + /// Calculates Euclidean division, the matching method for `rem_euclid`. /// /// This computes the integer `n` such that - /// `self = n * rhs + self.mod_euc(rhs)`. + /// `self = n * rhs + self.rem_euclid(rhs)`. /// In other words, the result is `self / rhs` rounded to the integer `n` /// such that `self >= n * rhs`. /// @@ -266,14 +266,14 @@ impl f32 { /// #![feature(euclidean_division)] /// let a: f32 = 7.0; /// let b = 4.0; - /// assert_eq!(a.div_euc(b), 1.0); // 7.0 > 4.0 * 1.0 - /// assert_eq!((-a).div_euc(b), -2.0); // -7.0 >= 4.0 * -2.0 - /// assert_eq!(a.div_euc(-b), -1.0); // 7.0 >= -4.0 * -1.0 - /// assert_eq!((-a).div_euc(-b), 2.0); // -7.0 >= -4.0 * 2.0 + /// assert_eq!(a.div_euclid(b), 1.0); // 7.0 > 4.0 * 1.0 + /// assert_eq!((-a).div_euclid(b), -2.0); // -7.0 >= 4.0 * -2.0 + /// assert_eq!(a.div_euclid(-b), -1.0); // 7.0 >= -4.0 * -1.0 + /// assert_eq!((-a).div_euclid(-b), 2.0); // -7.0 >= -4.0 * 2.0 /// ``` #[inline] #[unstable(feature = "euclidean_division", issue = "49048")] - pub fn div_euc(self, rhs: f32) -> f32 { + pub fn div_euclid(self, rhs: f32) -> f32 { let q = (self / rhs).trunc(); if self % rhs < 0.0 { return if rhs > 0.0 { q - 1.0 } else { q + 1.0 } @@ -281,7 +281,7 @@ impl f32 { q } - /// Calculates the Euclidean modulo (self mod rhs), which is never negative. + /// Calculates the least nonnegative remainder of `self (mod rhs)`. /// /// In particular, the return value `r` satisfies `0.0 <= r < rhs.abs()` in /// most cases. However, due to a floating point round-off error it can @@ -289,7 +289,7 @@ impl f32 { /// `self` is much smaller than `rhs.abs()` in magnitude and `self < 0.0`. /// This result is not an element of the function's codomain, but it is the /// closest floating point number in the real numbers and thus fulfills the - /// property `self == self.div_euc(rhs) * rhs + self.mod_euc(rhs)` + /// property `self == self.div_euclid(rhs) * rhs + self.rem_euclid(rhs)` /// approximatively. /// /// # Examples @@ -298,16 +298,16 @@ impl f32 { /// #![feature(euclidean_division)] /// let a: f32 = 7.0; /// let b = 4.0; - /// assert_eq!(a.mod_euc(b), 3.0); - /// assert_eq!((-a).mod_euc(b), 1.0); - /// assert_eq!(a.mod_euc(-b), 3.0); - /// assert_eq!((-a).mod_euc(-b), 1.0); + /// assert_eq!(a.rem_euclid(b), 3.0); + /// assert_eq!((-a).rem_euclid(b), 1.0); + /// assert_eq!(a.rem_euclid(-b), 3.0); + /// assert_eq!((-a).rem_euclid(-b), 1.0); /// // limitation due to round-off error - /// assert!((-std::f32::EPSILON).mod_euc(3.0) != 0.0); + /// assert!((-std::f32::EPSILON).rem_euclid(3.0) != 0.0); /// ``` #[inline] #[unstable(feature = "euclidean_division", issue = "49048")] - pub fn mod_euc(self, rhs: f32) -> f32 { + pub fn rem_euclid(self, rhs: f32) -> f32 { let r = self % rhs; if r < 0.0 { r + rhs.abs() diff --git a/src/libstd/f64.rs b/src/libstd/f64.rs index 9e627ec204291..b73a67ed9d8a0 100644 --- a/src/libstd/f64.rs +++ b/src/libstd/f64.rs @@ -229,10 +229,10 @@ impl f64 { unsafe { intrinsics::fmaf64(self, a, b) } } - /// Calculates Euclidean division, the matching method for `mod_euc`. + /// Calculates Euclidean division, the matching method for `rem_euclid`. /// /// This computes the integer `n` such that - /// `self = n * rhs + self.mod_euc(rhs)`. + /// `self = n * rhs + self.rem_euclid(rhs)`. /// In other words, the result is `self / rhs` rounded to the integer `n` /// such that `self >= n * rhs`. /// @@ -242,14 +242,14 @@ impl f64 { /// #![feature(euclidean_division)] /// let a: f64 = 7.0; /// let b = 4.0; - /// assert_eq!(a.div_euc(b), 1.0); // 7.0 > 4.0 * 1.0 - /// assert_eq!((-a).div_euc(b), -2.0); // -7.0 >= 4.0 * -2.0 - /// assert_eq!(a.div_euc(-b), -1.0); // 7.0 >= -4.0 * -1.0 - /// assert_eq!((-a).div_euc(-b), 2.0); // -7.0 >= -4.0 * 2.0 + /// assert_eq!(a.div_euclid(b), 1.0); // 7.0 > 4.0 * 1.0 + /// assert_eq!((-a).div_euclid(b), -2.0); // -7.0 >= 4.0 * -2.0 + /// assert_eq!(a.div_euclid(-b), -1.0); // 7.0 >= -4.0 * -1.0 + /// assert_eq!((-a).div_euclid(-b), 2.0); // -7.0 >= -4.0 * 2.0 /// ``` #[inline] #[unstable(feature = "euclidean_division", issue = "49048")] - pub fn div_euc(self, rhs: f64) -> f64 { + pub fn div_euclid(self, rhs: f64) -> f64 { let q = (self / rhs).trunc(); if self % rhs < 0.0 { return if rhs > 0.0 { q - 1.0 } else { q + 1.0 } @@ -257,7 +257,7 @@ impl f64 { q } - /// Calculates the Euclidean modulo (self mod rhs), which is never negative. + /// Calculates the least nonnegative remainder of `self (mod rhs)`. /// /// In particular, the return value `r` satisfies `0.0 <= r < rhs.abs()` in /// most cases. However, due to a floating point round-off error it can @@ -265,7 +265,7 @@ impl f64 { /// `self` is much smaller than `rhs.abs()` in magnitude and `self < 0.0`. /// This result is not an element of the function's codomain, but it is the /// closest floating point number in the real numbers and thus fulfills the - /// property `self == self.div_euc(rhs) * rhs + self.mod_euc(rhs)` + /// property `self == self.div_euclid(rhs) * rhs + self.rem_euclid(rhs)` /// approximatively. /// /// # Examples @@ -274,16 +274,16 @@ impl f64 { /// #![feature(euclidean_division)] /// let a: f64 = 7.0; /// let b = 4.0; - /// assert_eq!(a.mod_euc(b), 3.0); - /// assert_eq!((-a).mod_euc(b), 1.0); - /// assert_eq!(a.mod_euc(-b), 3.0); - /// assert_eq!((-a).mod_euc(-b), 1.0); + /// assert_eq!(a.rem_euclid(b), 3.0); + /// assert_eq!((-a).rem_euclid(b), 1.0); + /// assert_eq!(a.rem_euclid(-b), 3.0); + /// assert_eq!((-a).rem_euclid(-b), 1.0); /// // limitation due to round-off error - /// assert!((-std::f64::EPSILON).mod_euc(3.0) != 0.0); + /// assert!((-std::f64::EPSILON).rem_euclid(3.0) != 0.0); /// ``` #[inline] #[unstable(feature = "euclidean_division", issue = "49048")] - pub fn mod_euc(self, rhs: f64) -> f64 { + pub fn rem_euclid(self, rhs: f64) -> f64 { let r = self % rhs; if r < 0.0 { r + rhs.abs() From 82e55c1bdcf0a20a2652152447160414a9cd57d7 Mon Sep 17 00:00:00 2001 From: Andy Russell Date: Mon, 17 Dec 2018 21:10:24 -0500 Subject: [PATCH 17/84] deny intra-doc link resolution failures in libstd --- src/liballoc/lib.rs | 2 ++ src/liballoc/rc.rs | 5 ++++- src/liballoc/sync.rs | 5 ++++- src/libcore/lib.rs | 1 + src/libcore/mem.rs | 3 +++ src/libcore/slice/mod.rs | 2 ++ src/libstd/io/buffered.rs | 5 ++++- src/libstd/io/error.rs | 3 +++ src/libstd/lib.rs | 1 + 9 files changed, 24 insertions(+), 3 deletions(-) diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index abacc62c8562b..31a4aeeab4be8 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -72,6 +72,8 @@ test(no_crate_inject, attr(allow(unused_variables), deny(warnings))))] #![no_std] #![needs_allocator] + +#![deny(intra_doc_link_resolution_failure)] #![deny(missing_debug_implementations)] #![cfg_attr(not(test), feature(fn_traits))] diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index 52ad30c411a10..37204bc20c272 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -840,6 +840,8 @@ unsafe impl<#[may_dangle] T: ?Sized> Drop for Rc { /// drop(foo); // Doesn't print anything /// drop(foo2); // Prints "dropped!" /// ``` + /// + /// [`Weak`]: ../../std/rc/struct.Weak.html fn drop(&mut self) { unsafe { self.dec_strong(); @@ -1381,9 +1383,10 @@ impl fmt::Debug for Weak { #[stable(feature = "downgraded_weak", since = "1.10.0")] impl Default for Weak { /// Constructs a new `Weak`, allocating memory for `T` without initializing - /// it. Calling [`upgrade`][Weak::upgrade] on the return value always gives [`None`]. + /// it. Calling [`upgrade`] on the return value always gives [`None`]. /// /// [`None`]: ../../std/option/enum.Option.html + /// [`upgrade`]: ../../std/rc/struct.Weak.html#method.upgrade /// /// # Examples /// diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs index 111459d12a4df..5f72b232c64ce 100644 --- a/src/liballoc/sync.rs +++ b/src/liballoc/sync.rs @@ -952,6 +952,8 @@ unsafe impl<#[may_dangle] T: ?Sized> Drop for Arc { /// drop(foo); // Doesn't print anything /// drop(foo2); // Prints "dropped!" /// ``` + /// + /// [`Weak`]: ../../std/sync/struct.Weak.html #[inline] fn drop(&mut self) { // Because `fetch_sub` is already atomic, we do not need to synchronize @@ -1219,10 +1221,11 @@ impl Clone for Weak { #[stable(feature = "downgraded_weak", since = "1.10.0")] impl Default for Weak { /// Constructs a new `Weak`, without allocating memory. - /// Calling [`upgrade`][Weak::upgrade] on the return value always + /// Calling [`upgrade`] on the return value always /// gives [`None`]. /// /// [`None`]: ../../std/option/enum.Option.html#variant.None + /// [`upgrade`]: ../../std/sync/struct.Weak.html#method.upgrade /// /// # Examples /// diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index a51674fbfc71a..258f499d44481 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -71,6 +71,7 @@ #![no_core] #![deny(missing_docs)] +#![deny(intra_doc_link_resolution_failure)] #![deny(missing_debug_implementations)] #![feature(allow_internal_unstable)] diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index afd9fcb1fba84..0cde23cde40f1 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -984,6 +984,9 @@ impl ManuallyDrop { /// /// This function semantically moves out the contained value without preventing further usage. /// It is up to the user of this method to ensure that this container is not used again. + /// + /// [`ManuallyDrop::drop`]: #method.drop + /// [`ManuallyDrop::into_inner`]: #method.into_inner #[must_use = "if you don't need the value, you can use `ManuallyDrop::drop` instead"] #[unstable(feature = "manually_drop_take", issue = "55422")] #[inline] diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index 59c11b273293f..193061457b5cd 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -877,6 +877,7 @@ impl [T] { /// assert_eq!(iter.remainder(), &['l']); /// ``` /// + /// [`chunks`]: #method.chunks /// [`rchunks`]: #method.rchunks /// [`chunks_exact`]: #method.chunks_exact #[stable(feature = "rchunks", since = "1.31.0")] @@ -921,6 +922,7 @@ impl [T] { /// assert_eq!(v, &[0, 2, 2, 1, 1]); /// ``` /// + /// [`chunks_mut`]: #method.chunks_mut /// [`rchunks_mut`]: #method.rchunks_mut /// [`chunks_exact_mut`]: #method.chunks_exact_mut #[stable(feature = "rchunks", since = "1.31.0")] diff --git a/src/libstd/io/buffered.rs b/src/libstd/io/buffered.rs index 7ede050da6c45..7aaf89cd0ff71 100644 --- a/src/libstd/io/buffered.rs +++ b/src/libstd/io/buffered.rs @@ -294,7 +294,7 @@ impl Seek for BufReader { /// `.into_inner()` immediately after a seek yields the underlying reader /// at the same position. /// - /// To seek without discarding the internal buffer, use [`Seek::seek_relative`]. + /// To seek without discarding the internal buffer, use [`BufReader::seek_relative`]. /// /// See [`std::io::Seek`] for more details. /// @@ -303,6 +303,9 @@ impl Seek for BufReader { /// seeks will be performed instead of one. If the second seek returns /// `Err`, the underlying reader will be left at the same position it would /// have if you called `seek` with `SeekFrom::Current(0)`. + /// + /// [`BufReader::seek_relative`]: struct.BufReader.html#method.seek_relative + /// [`std::io::Seek`]: trait.Seek.html fn seek(&mut self, pos: SeekFrom) -> io::Result { let result: u64; if let SeekFrom::Current(n) = pos { diff --git a/src/libstd/io/error.rs b/src/libstd/io/error.rs index d3844ebe19e4b..324852355b0d6 100644 --- a/src/libstd/io/error.rs +++ b/src/libstd/io/error.rs @@ -225,6 +225,9 @@ impl From for Error { /// let error = Error::from(not_found); /// assert_eq!("entity not found", format!("{}", error)); /// ``` + /// + /// [`ErrorKind`]: ../../std/io/enum.ErrorKind.html + /// [`Error`]: ../../std/io/struct.Error.html #[inline] fn from(kind: ErrorKind) -> Error { Error { diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index ead38f2112687..13de55a6a542f 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -222,6 +222,7 @@ #![no_std] #![deny(missing_docs)] +#![deny(intra_doc_link_resolution_failure)] #![deny(missing_debug_implementations)] // Tell the compiler to link to either panic_abort or panic_unwind From de39aea91cdbaecb330ff666f63d27bbe7c109a2 Mon Sep 17 00:00:00 2001 From: Nicole Mazzuca Date: Mon, 17 Dec 2018 20:21:21 -0800 Subject: [PATCH 18/84] fix tests --- src/libcore/tests/num/int_macros.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libcore/tests/num/int_macros.rs b/src/libcore/tests/num/int_macros.rs index 577847b3c8282..8b04f84007fa7 100644 --- a/src/libcore/tests/num/int_macros.rs +++ b/src/libcore/tests/num/int_macros.rs @@ -31,8 +31,8 @@ mod tests { } #[test] - fn test_mod_euclid() { - assert!((-1 as $T).mod_euclid(MIN) == MAX); + fn test_rem_euclid() { + assert!((-1 as $T).rem_euclid(MIN) == MAX); } #[test] From 50eb5f6137719a7e8fdd270e90af0d734d002c5d Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Tue, 18 Dec 2018 10:08:37 +0100 Subject: [PATCH 19/84] Explain the math --- src/librustc_mir/interpret/memory.rs | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index 65347a02be0c7..77a5f5d7b3a84 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -707,10 +707,15 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { new_relocations.extend( relocations .iter() - .map(|&(offset, reloc)| ( - offset + dest.offset - src.offset + (i * size), - reloc, - )) + .map(|&(offset, reloc)| { + // compute offset for current repetition + let dest_offset = dest.offset + (i * size); + ( + // shift offsets from source allocation to destination allocation + offset + dest_offset - src.offset, + reloc, + ) + }) ); } From f7314456d03d2bfed188baf3a988c77b40864dc8 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Tue, 18 Dec 2018 15:52:32 +0100 Subject: [PATCH 20/84] Mark tuple structs as live if their constructors are used --- src/librustc/hir/mod.rs | 2 +- src/librustc/middle/dead.rs | 80 ++++++++++----------- src/test/ui/dead-code-tuple-struct-field.rs | 22 ++++++ 3 files changed, 61 insertions(+), 43 deletions(-) create mode 100644 src/test/ui/dead-code-tuple-struct-field.rs diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 156d55b9e2fe6..3f5b614df9dc2 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -2119,7 +2119,7 @@ impl StructField { /// Id of the whole enum lives in `Item`. /// /// For structs: `NodeId` represents an Id of the structure's constructor, so it is not actually -/// used for `Struct`-structs (but still presents). Structures don't have an analogue of "Id of +/// used for `Struct`-structs (but still present). Structures don't have an analogue of "Id of /// the variant itself" from enum variants. /// Id of the whole struct lives in `Item`. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs index 934d7c12be552..d2175c28309b1 100644 --- a/src/librustc/middle/dead.rs +++ b/src/librustc/middle/dead.rs @@ -25,6 +25,8 @@ use middle::privacy; use ty::{self, TyCtxt}; use util::nodemap::FxHashSet; +use rustc_data_structures::fx::FxHashMap; + use syntax::{ast, source_map}; use syntax::attr; use syntax_pos; @@ -55,12 +57,15 @@ struct MarkSymbolVisitor<'a, 'tcx: 'a> { in_pat: bool, inherited_pub_visibility: bool, ignore_variant_stack: Vec, + // maps from tuple struct constructors to tuple struct items + struct_constructors: FxHashMap, } impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> { fn check_def_id(&mut self, def_id: DefId) { if let Some(node_id) = self.tcx.hir().as_local_node_id(def_id) { - if should_explore(self.tcx, node_id) { + if should_explore(self.tcx, node_id) || + self.struct_constructors.contains_key(&node_id) { self.worklist.push(node_id); } self.live_symbols.insert(node_id); @@ -137,19 +142,23 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> { continue } - if let Some(ref node) = self.tcx.hir().find(id) { + // in the case of tuple struct constructors we want to check the item, not the generated + // tuple struct constructor function + let id = self.struct_constructors.get(&id).cloned().unwrap_or(id); + + if let Some(node) = self.tcx.hir().find(id) { self.live_symbols.insert(id); self.visit_node(node); } } } - fn visit_node(&mut self, node: &Node<'tcx>) { + fn visit_node(&mut self, node: Node<'tcx>) { let had_repr_c = self.repr_has_repr_c; self.repr_has_repr_c = false; let had_inherited_pub_visibility = self.inherited_pub_visibility; self.inherited_pub_visibility = false; - match *node { + match node { Node::Item(item) => { match item.node { hir::ItemKind::Struct(..) | hir::ItemKind::Union(..) => { @@ -337,6 +346,8 @@ struct LifeSeeder<'k, 'tcx: 'k> { worklist: Vec, krate: &'k hir::Crate, tcx: TyCtxt<'k, 'tcx, 'tcx>, + // see `MarkSymbolVisitor::struct_constructors` + struct_constructors: FxHashMap, } impl<'v, 'k, 'tcx> ItemLikeVisitor<'v> for LifeSeeder<'k, 'tcx> { @@ -379,6 +390,9 @@ impl<'v, 'k, 'tcx> ItemLikeVisitor<'v> for LifeSeeder<'k, 'tcx> { } } } + hir::ItemKind::Struct(ref variant_data, _) => { + self.struct_constructors.insert(variant_data.id(), item.id); + } _ => () } } @@ -392,11 +406,11 @@ impl<'v, 'k, 'tcx> ItemLikeVisitor<'v> for LifeSeeder<'k, 'tcx> { } } -fn create_and_seed_worklist<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - access_levels: &privacy::AccessLevels, - krate: &hir::Crate) - -> Vec -{ +fn create_and_seed_worklist<'a, 'tcx>( + tcx: TyCtxt<'a, 'tcx, 'tcx>, + access_levels: &privacy::AccessLevels, + krate: &hir::Crate, +) -> (Vec, FxHashMap) { let worklist = access_levels.map.iter().filter_map(|(&id, level)| { if level >= &privacy::AccessLevel::Reachable { Some(id) @@ -413,17 +427,18 @@ fn create_and_seed_worklist<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, worklist, krate, tcx, + struct_constructors: Default::default(), }; krate.visit_all_item_likes(&mut life_seeder); - return life_seeder.worklist; + (life_seeder.worklist, life_seeder.struct_constructors) } fn find_live<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, access_levels: &privacy::AccessLevels, krate: &hir::Crate) -> FxHashSet { - let worklist = create_and_seed_worklist(tcx, access_levels, krate); + let (worklist, struct_constructors) = create_and_seed_worklist(tcx, access_levels, krate); let mut symbol_visitor = MarkSymbolVisitor { worklist, tcx, @@ -433,20 +448,12 @@ fn find_live<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, in_pat: false, inherited_pub_visibility: false, ignore_variant_stack: vec![], + struct_constructors, }; symbol_visitor.mark_live_symbols(); symbol_visitor.live_symbols } -fn get_struct_ctor_id(item: &hir::Item) -> Option { - match item.node { - hir::ItemKind::Struct(ref struct_def, _) if !struct_def.is_struct() => { - Some(struct_def.id()) - } - _ => None - } -} - struct DeadVisitor<'a, 'tcx: 'a> { tcx: TyCtxt<'a, 'tcx, 'tcx>, live_symbols: FxHashSet, @@ -464,46 +471,35 @@ impl<'a, 'tcx> DeadVisitor<'a, 'tcx> { | hir::ItemKind::Union(..) => true, _ => false }; - let ctor_id = get_struct_ctor_id(item); - should_warn && !self.symbol_is_live(item.id, ctor_id) + should_warn && !self.symbol_is_live(item.id) } fn should_warn_about_field(&mut self, field: &hir::StructField) -> bool { let field_type = self.tcx.type_of(self.tcx.hir().local_def_id(field.id)); !field.is_positional() - && !self.symbol_is_live(field.id, None) + && !self.symbol_is_live(field.id) && !field_type.is_phantom_data() && !has_allow_dead_code_or_lang_attr(self.tcx, field.id, &field.attrs) } fn should_warn_about_variant(&mut self, variant: &hir::VariantKind) -> bool { - !self.symbol_is_live(variant.data.id(), None) + !self.symbol_is_live(variant.data.id()) && !has_allow_dead_code_or_lang_attr(self.tcx, variant.data.id(), &variant.attrs) } fn should_warn_about_foreign_item(&mut self, fi: &hir::ForeignItem) -> bool { - !self.symbol_is_live(fi.id, None) + !self.symbol_is_live(fi.id) && !has_allow_dead_code_or_lang_attr(self.tcx, fi.id, &fi.attrs) } // id := node id of an item's definition. - // ctor_id := `Some` if the item is a struct_ctor (tuple struct), - // `None` otherwise. - // If the item is a struct_ctor, then either its `id` or - // `ctor_id` (unwrapped) is in the live_symbols set. More specifically, - // DefMap maps the ExprKind::Path of a struct_ctor to the node referred by - // `ctor_id`. On the other hand, in a statement like - // `type = ;` where refers to a struct_ctor, - // DefMap maps to `id` instead. - fn symbol_is_live(&mut self, - id: ast::NodeId, - ctor_id: Option) - -> bool { - if self.live_symbols.contains(&id) - || ctor_id.map_or(false, |ctor| self.live_symbols.contains(&ctor)) - { + fn symbol_is_live( + &mut self, + id: ast::NodeId, + ) -> bool { + if self.live_symbols.contains(&id) { return true; } // If it's a type whose items are live, then it's live, too. @@ -611,7 +607,7 @@ impl<'a, 'tcx> Visitor<'tcx> for DeadVisitor<'a, 'tcx> { fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem) { match impl_item.node { hir::ImplItemKind::Const(_, body_id) => { - if !self.symbol_is_live(impl_item.id, None) { + if !self.symbol_is_live(impl_item.id) { self.warn_dead_code(impl_item.id, impl_item.span, impl_item.ident.name, @@ -621,7 +617,7 @@ impl<'a, 'tcx> Visitor<'tcx> for DeadVisitor<'a, 'tcx> { self.visit_nested_body(body_id) } hir::ImplItemKind::Method(_, body_id) => { - if !self.symbol_is_live(impl_item.id, None) { + if !self.symbol_is_live(impl_item.id) { let span = self.tcx.sess.source_map().def_span(impl_item.span); self.warn_dead_code(impl_item.id, span, impl_item.ident.name, "method", "used"); } diff --git a/src/test/ui/dead-code-tuple-struct-field.rs b/src/test/ui/dead-code-tuple-struct-field.rs new file mode 100644 index 0000000000000..f4989fa1037d3 --- /dev/null +++ b/src/test/ui/dead-code-tuple-struct-field.rs @@ -0,0 +1,22 @@ +// 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. + +// compile-pass + +#![deny(dead_code)] + +const LEN: usize = 4; + +#[derive(Debug)] +struct Wrapper([u8; LEN]); + +fn main() { + println!("{:?}", Wrapper([0, 1, 2, 3])); +} From fe918927b1329c11205a8fb54e6c7b34e414b1f3 Mon Sep 17 00:00:00 2001 From: Taylor Cramer Date: Mon, 17 Dec 2018 17:19:32 -0800 Subject: [PATCH 21/84] Update Pin API to match the one proposed for stabilization Remove pin::Unpin reexport and add Unpin to the prelude. Change Pin associated functions to methods. Rename get_mut_unchecked_ to get_unchecked_mut Remove impl Unpin for Pin Mark Pin repr(transparent) --- src/libcore/future/future.rs | 2 +- src/libcore/option.rs | 2 +- src/libcore/pin.rs | 33 ++++++++++++++------------------- src/libcore/prelude/v1.rs | 2 +- src/libstd/future.rs | 2 +- 5 files changed, 18 insertions(+), 23 deletions(-) diff --git a/src/libcore/future/future.rs b/src/libcore/future/future.rs index 5dee1d6dd3a39..da3aa8449bafb 100644 --- a/src/libcore/future/future.rs +++ b/src/libcore/future/future.rs @@ -120,7 +120,7 @@ impl<'a, F: ?Sized + Future + Unpin> Future for &'a mut F { impl

Future for Pin

where - P: ops::DerefMut, + P: Unpin + ops::DerefMut, P::Target: Future, { type Output = <

::Target as Future>::Output; diff --git a/src/libcore/option.rs b/src/libcore/option.rs index 44d632ece055c..0d7ddfc20b6d3 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -285,7 +285,7 @@ impl Option { #[unstable(feature = "pin", issue = "49150")] pub fn as_pin_mut<'a>(self: Pin<&'a mut Option>) -> Option> { unsafe { - Pin::get_mut_unchecked(self).as_mut().map(|x| Pin::new_unchecked(x)) + Pin::get_unchecked_mut(self).as_mut().map(|x| Pin::new_unchecked(x)) } } diff --git a/src/libcore/pin.rs b/src/libcore/pin.rs index 0ad6e8c7c1c7d..71636e3361254 100644 --- a/src/libcore/pin.rs +++ b/src/libcore/pin.rs @@ -100,12 +100,9 @@ #![unstable(feature = "pin", issue = "49150")] use fmt; -use marker::Sized; +use marker::{Sized, Unpin}; use ops::{Deref, DerefMut, CoerceUnsized, DispatchFromDyn}; -#[doc(inline)] -pub use marker::Unpin; - /// A pinned pointer. /// /// This is a wrapper around a kind of pointer which makes that pointer "pin" its @@ -121,6 +118,7 @@ pub use marker::Unpin; // cannot move the value behind `pointer`. #[unstable(feature = "pin", issue = "49150")] #[fundamental] +#[repr(transparent)] #[derive(Copy, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)] pub struct Pin

{ pointer: P, @@ -200,10 +198,10 @@ impl<'a, T: ?Sized> Pin<&'a T> { /// because it is one of the fields of that value), and also that you do /// not move out of the argument you receive to the interior function. #[unstable(feature = "pin", issue = "49150")] - pub unsafe fn map_unchecked(this: Pin<&'a T>, func: F) -> Pin<&'a U> where + pub unsafe fn map_unchecked(self: Pin<&'a T>, func: F) -> Pin<&'a U> where F: FnOnce(&T) -> &U, { - let pointer = &*this.pointer; + let pointer = &*self.pointer; let new_pointer = func(pointer); Pin::new_unchecked(new_pointer) } @@ -217,8 +215,8 @@ impl<'a, T: ?Sized> Pin<&'a T> { /// with the same lifetime as the original `Pin`. #[unstable(feature = "pin", issue = "49150")] #[inline(always)] - pub fn get_ref(this: Pin<&'a T>) -> &'a T { - this.pointer + pub fn get_ref(self: Pin<&'a T>) -> &'a T { + self.pointer } } @@ -226,8 +224,8 @@ impl<'a, T: ?Sized> Pin<&'a mut T> { /// Convert this `Pin<&mut T>` into a `Pin<&T>` with the same lifetime. #[unstable(feature = "pin", issue = "49150")] #[inline(always)] - pub fn into_ref(this: Pin<&'a mut T>) -> Pin<&'a T> { - Pin { pointer: this.pointer } + pub fn into_ref(self: Pin<&'a mut T>) -> Pin<&'a T> { + Pin { pointer: self.pointer } } /// Get a mutable reference to the data inside of this `Pin`. @@ -241,10 +239,10 @@ impl<'a, T: ?Sized> Pin<&'a mut T> { /// with the same lifetime as the original `Pin`. #[unstable(feature = "pin", issue = "49150")] #[inline(always)] - pub fn get_mut(this: Pin<&'a mut T>) -> &'a mut T + pub fn get_mut(self: Pin<&'a mut T>) -> &'a mut T where T: Unpin, { - this.pointer + self.pointer } /// Get a mutable reference to the data inside of this `Pin`. @@ -259,8 +257,8 @@ impl<'a, T: ?Sized> Pin<&'a mut T> { /// instead. #[unstable(feature = "pin", issue = "49150")] #[inline(always)] - pub unsafe fn get_mut_unchecked(this: Pin<&'a mut T>) -> &'a mut T { - this.pointer + pub unsafe fn get_unchecked_mut(self: Pin<&'a mut T>) -> &'a mut T { + self.pointer } /// Construct a new pin by mapping the interior value. @@ -275,10 +273,10 @@ impl<'a, T: ?Sized> Pin<&'a mut T> { /// because it is one of the fields of that value), and also that you do /// not move out of the argument you receive to the interior function. #[unstable(feature = "pin", issue = "49150")] - pub unsafe fn map_unchecked_mut(this: Pin<&'a mut T>, func: F) -> Pin<&'a mut U> where + pub unsafe fn map_unchecked_mut(self: Pin<&'a mut T>, func: F) -> Pin<&'a mut U> where F: FnOnce(&mut T) -> &mut U, { - let pointer = Pin::get_mut_unchecked(this); + let pointer = Pin::get_unchecked_mut(self); let new_pointer = func(pointer); Pin::new_unchecked(new_pointer) } @@ -339,6 +337,3 @@ impl<'a, P, U> DispatchFromDyn> for Pin

where P: DispatchFromDyn, {} - -#[unstable(feature = "pin", issue = "49150")] -impl

Unpin for Pin

{} diff --git a/src/libcore/prelude/v1.rs b/src/libcore/prelude/v1.rs index 45f629a64424c..a1e6034b20821 100644 --- a/src/libcore/prelude/v1.rs +++ b/src/libcore/prelude/v1.rs @@ -19,7 +19,7 @@ // Re-exported core operators #[stable(feature = "core_prelude", since = "1.4.0")] #[doc(no_inline)] -pub use marker::{Copy, Send, Sized, Sync}; +pub use marker::{Copy, Send, Sized, Sync, Unpin}; #[stable(feature = "core_prelude", since = "1.4.0")] #[doc(no_inline)] pub use ops::{Drop, Fn, FnMut, FnOnce}; diff --git a/src/libstd/future.rs b/src/libstd/future.rs index d5e6cab948b8f..3379be79186ef 100644 --- a/src/libstd/future.rs +++ b/src/libstd/future.rs @@ -43,7 +43,7 @@ impl> !Unpin for GenFuture {} impl> Future for GenFuture { type Output = T::Return; fn poll(self: Pin<&mut Self>, lw: &LocalWaker) -> Poll { - set_task_waker(lw, || match unsafe { Pin::get_mut_unchecked(self).0.resume() } { + set_task_waker(lw, || match unsafe { Pin::get_unchecked_mut(self).0.resume() } { GeneratorState::Yielded(()) => Poll::Pending, GeneratorState::Complete(x) => Poll::Ready(x), }) From 987a5e4c435a0de64f6db264be7b3ac125fb0200 Mon Sep 17 00:00:00 2001 From: Taylor Cramer Date: Mon, 17 Dec 2018 18:14:07 -0800 Subject: [PATCH 22/84] Stabilize Pin --- src/liballoc/boxed.rs | 6 +-- src/liballoc/lib.rs | 1 - src/liballoc/rc.rs | 4 +- src/liballoc/sync.rs | 4 +- src/libcore/marker.rs | 10 ++--- src/libcore/option.rs | 4 +- src/libcore/pin.rs | 40 +++++++++---------- src/libstd/lib.rs | 3 +- .../compile-fail/must_use-in-stdlib-traits.rs | 2 +- .../arbitrary_self_types_stdlib_pointers.rs | 1 - src/test/run-pass/async-await.rs | 2 +- src/test/run-pass/futures-api.rs | 2 +- 12 files changed, 38 insertions(+), 41 deletions(-) diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 83adcce5c742c..c8bbe4807a25a 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -109,7 +109,7 @@ impl Box { box x } - #[unstable(feature = "pin", issue = "49150")] + #[stable(feature = "pin", since = "1.33.0")] #[inline(always)] pub fn pinned(x: T) -> Pin> { (box x).into() @@ -444,7 +444,7 @@ impl From for Box { } } -#[unstable(feature = "pin", issue = "49150")] +#[stable(feature = "pin", since = "1.33.0")] impl From> for Pin> { fn from(boxed: Box) -> Self { // It's not possible to move or replace the insides of a `Pin>` @@ -808,7 +808,7 @@ impl AsMut for Box { * implementation of `Unpin` (where `T: Unpin`) would be valid/safe, and * could have a method to project a Pin from it. */ -#[unstable(feature = "pin", issue = "49150")] +#[stable(feature = "pin", since = "1.33.0")] impl Unpin for Box { } #[unstable(feature = "generator_trait", issue = "43122")] diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index abacc62c8562b..071153060e9b6 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -100,7 +100,6 @@ #![feature(nll)] #![feature(optin_builtin_traits)] #![feature(pattern)] -#![feature(pin)] #![feature(ptr_internals)] #![feature(ptr_offset_from)] #![feature(rustc_attrs)] diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index 52ad30c411a10..875fcc7fb9744 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -325,7 +325,7 @@ impl Rc { } } - #[unstable(feature = "pin", issue = "49150")] + #[stable(feature = "pin", since = "1.33.0")] pub fn pinned(value: T) -> Pin> { unsafe { Pin::new_unchecked(Rc::new(value)) } } @@ -1890,5 +1890,5 @@ impl AsRef for Rc { } } -#[unstable(feature = "pin", issue = "49150")] +#[stable(feature = "pin", since = "1.33.0")] impl Unpin for Rc { } diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs index 111459d12a4df..c4f770eff7fc9 100644 --- a/src/liballoc/sync.rs +++ b/src/liballoc/sync.rs @@ -303,7 +303,7 @@ impl Arc { Arc { ptr: Box::into_raw_non_null(x), phantom: PhantomData } } - #[unstable(feature = "pin", issue = "49150")] + #[stable(feature = "pin", since = "1.33.0")] pub fn pinned(data: T) -> Pin> { unsafe { Pin::new_unchecked(Arc::new(data)) } } @@ -2004,5 +2004,5 @@ impl AsRef for Arc { } } -#[unstable(feature = "pin", issue = "49150")] +#[stable(feature = "pin", since = "1.33.0")] impl Unpin for Arc { } diff --git a/src/libcore/marker.rs b/src/libcore/marker.rs index d3d16127ed5fe..181623f4932ee 100644 --- a/src/libcore/marker.rs +++ b/src/libcore/marker.rs @@ -637,23 +637,23 @@ unsafe impl Freeze for &mut T {} /// [`replace`]: ../../std/mem/fn.replace.html /// [`Pin`]: ../pin/struct.Pin.html /// [`pin module`]: ../../std/pin/index.html -#[unstable(feature = "pin", issue = "49150")] +#[stable(feature = "pin", since = "1.33.0")] pub auto trait Unpin {} /// A marker type which does not implement `Unpin`. /// /// If a type contains a `PhantomPinned`, it will not implement `Unpin` by default. -#[unstable(feature = "pin", issue = "49150")] +#[stable(feature = "pin", since = "1.33.0")] #[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] pub struct PhantomPinned; -#[unstable(feature = "pin", issue = "49150")] +#[stable(feature = "pin", since = "1.33.0")] impl !Unpin for PhantomPinned {} -#[unstable(feature = "pin", issue = "49150")] +#[stable(feature = "pin", since = "1.33.0")] impl<'a, T: ?Sized + 'a> Unpin for &'a T {} -#[unstable(feature = "pin", issue = "49150")] +#[stable(feature = "pin", since = "1.33.0")] impl<'a, T: ?Sized + 'a> Unpin for &'a mut T {} /// Implementations of `Copy` for primitive types. diff --git a/src/libcore/option.rs b/src/libcore/option.rs index 0d7ddfc20b6d3..2f248d5276c77 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -273,7 +273,7 @@ impl Option { /// Converts from `Pin<&Option>` to `Option>` #[inline] - #[unstable(feature = "pin", issue = "49150")] + #[stable(feature = "pin", since = "1.33.0")] pub fn as_pin_ref<'a>(self: Pin<&'a Option>) -> Option> { unsafe { Pin::get_ref(self).as_ref().map(|x| Pin::new_unchecked(x)) @@ -282,7 +282,7 @@ impl Option { /// Converts from `Pin<&mut Option>` to `Option>` #[inline] - #[unstable(feature = "pin", issue = "49150")] + #[stable(feature = "pin", since = "1.33.0")] pub fn as_pin_mut<'a>(self: Pin<&'a mut Option>) -> Option> { unsafe { Pin::get_unchecked_mut(self).as_mut().map(|x| Pin::new_unchecked(x)) diff --git a/src/libcore/pin.rs b/src/libcore/pin.rs index 71636e3361254..3f2eb0b6110b9 100644 --- a/src/libcore/pin.rs +++ b/src/libcore/pin.rs @@ -97,7 +97,7 @@ //! // std::mem::swap(&mut *still_unmoved, &mut *new_unmoved); //! ``` -#![unstable(feature = "pin", issue = "49150")] +#![stable(feature = "pin", since = "1.33.0")] use fmt; use marker::{Sized, Unpin}; @@ -116,7 +116,7 @@ use ops::{Deref, DerefMut, CoerceUnsized, DispatchFromDyn}; // // Note: the derives below are allowed because they all only use `&P`, so they // cannot move the value behind `pointer`. -#[unstable(feature = "pin", issue = "49150")] +#[stable(feature = "pin", since = "1.33.0")] #[fundamental] #[repr(transparent)] #[derive(Copy, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)] @@ -130,7 +130,7 @@ where { /// Construct a new `Pin` around a pointer to some data of a type that /// implements `Unpin`. - #[unstable(feature = "pin", issue = "49150")] + #[stable(feature = "pin", since = "1.33.0")] #[inline(always)] pub fn new(pointer: P) -> Pin

{ // Safety: the value pointed to is `Unpin`, and so has no requirements @@ -152,14 +152,14 @@ impl Pin

{ /// /// If `pointer` dereferences to an `Unpin` type, `Pin::new` should be used /// instead. - #[unstable(feature = "pin", issue = "49150")] + #[stable(feature = "pin", since = "1.33.0")] #[inline(always)] pub unsafe fn new_unchecked(pointer: P) -> Pin

{ Pin { pointer } } /// Get a pinned shared reference from this pinned pointer. - #[unstable(feature = "pin", issue = "49150")] + #[stable(feature = "pin", since = "1.33.0")] #[inline(always)] pub fn as_ref(self: &Pin

) -> Pin<&P::Target> { unsafe { Pin::new_unchecked(&*self.pointer) } @@ -168,14 +168,14 @@ impl Pin

{ impl Pin

{ /// Get a pinned mutable reference from this pinned pointer. - #[unstable(feature = "pin", issue = "49150")] + #[stable(feature = "pin", since = "1.33.0")] #[inline(always)] pub fn as_mut(self: &mut Pin

) -> Pin<&mut P::Target> { unsafe { Pin::new_unchecked(&mut *self.pointer) } } /// Assign a new value to the memory behind the pinned reference. - #[unstable(feature = "pin", issue = "49150")] + #[stable(feature = "pin", since = "1.33.0")] #[inline(always)] pub fn set(mut self: Pin

, value: P::Target) where @@ -197,7 +197,7 @@ impl<'a, T: ?Sized> Pin<&'a T> { /// will not move so long as the argument value does not move (for example, /// because it is one of the fields of that value), and also that you do /// not move out of the argument you receive to the interior function. - #[unstable(feature = "pin", issue = "49150")] + #[stable(feature = "pin", since = "1.33.0")] pub unsafe fn map_unchecked(self: Pin<&'a T>, func: F) -> Pin<&'a U> where F: FnOnce(&T) -> &U, { @@ -213,7 +213,7 @@ impl<'a, T: ?Sized> Pin<&'a T> { /// that lives for as long as the borrow of the `Pin`, not the lifetime of /// the `Pin` itself. This method allows turning the `Pin` into a reference /// with the same lifetime as the original `Pin`. - #[unstable(feature = "pin", issue = "49150")] + #[stable(feature = "pin", since = "1.33.0")] #[inline(always)] pub fn get_ref(self: Pin<&'a T>) -> &'a T { self.pointer @@ -222,7 +222,7 @@ impl<'a, T: ?Sized> Pin<&'a T> { impl<'a, T: ?Sized> Pin<&'a mut T> { /// Convert this `Pin<&mut T>` into a `Pin<&T>` with the same lifetime. - #[unstable(feature = "pin", issue = "49150")] + #[stable(feature = "pin", since = "1.33.0")] #[inline(always)] pub fn into_ref(self: Pin<&'a mut T>) -> Pin<&'a T> { Pin { pointer: self.pointer } @@ -237,7 +237,7 @@ impl<'a, T: ?Sized> Pin<&'a mut T> { /// that lives for as long as the borrow of the `Pin`, not the lifetime of /// the `Pin` itself. This method allows turning the `Pin` into a reference /// with the same lifetime as the original `Pin`. - #[unstable(feature = "pin", issue = "49150")] + #[stable(feature = "pin", since = "1.33.0")] #[inline(always)] pub fn get_mut(self: Pin<&'a mut T>) -> &'a mut T where T: Unpin, @@ -255,7 +255,7 @@ impl<'a, T: ?Sized> Pin<&'a mut T> { /// /// If the underlying data is `Unpin`, `Pin::get_mut` should be used /// instead. - #[unstable(feature = "pin", issue = "49150")] + #[stable(feature = "pin", since = "1.33.0")] #[inline(always)] pub unsafe fn get_unchecked_mut(self: Pin<&'a mut T>) -> &'a mut T { self.pointer @@ -272,7 +272,7 @@ impl<'a, T: ?Sized> Pin<&'a mut T> { /// will not move so long as the argument value does not move (for example, /// because it is one of the fields of that value), and also that you do /// not move out of the argument you receive to the interior function. - #[unstable(feature = "pin", issue = "49150")] + #[stable(feature = "pin", since = "1.33.0")] pub unsafe fn map_unchecked_mut(self: Pin<&'a mut T>, func: F) -> Pin<&'a mut U> where F: FnOnce(&mut T) -> &mut U, { @@ -282,7 +282,7 @@ impl<'a, T: ?Sized> Pin<&'a mut T> { } } -#[unstable(feature = "pin", issue = "49150")] +#[stable(feature = "pin", since = "1.33.0")] impl Deref for Pin

{ type Target = P::Target; fn deref(&self) -> &P::Target { @@ -290,7 +290,7 @@ impl Deref for Pin

{ } } -#[unstable(feature = "pin", issue = "49150")] +#[stable(feature = "pin", since = "1.33.0")] impl DerefMut for Pin

where P::Target: Unpin @@ -300,21 +300,21 @@ where } } -#[unstable(feature = "pin", issue = "49150")] +#[stable(feature = "pin", since = "1.33.0")] impl fmt::Debug for Pin

{ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Debug::fmt(&self.pointer, f) } } -#[unstable(feature = "pin", issue = "49150")] +#[stable(feature = "pin", since = "1.33.0")] impl fmt::Display for Pin

{ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(&self.pointer, f) } } -#[unstable(feature = "pin", issue = "49150")] +#[stable(feature = "pin", since = "1.33.0")] impl fmt::Pointer for Pin

{ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Pointer::fmt(&self.pointer, f) @@ -326,13 +326,13 @@ impl fmt::Pointer for Pin

{ // `Deref` is unsound. Any such impl would probably be unsound // for other reasons, though, so we just need to take care not to allow such // impls to land in std. -#[unstable(feature = "pin", issue = "49150")] +#[stable(feature = "pin", since = "1.33.0")] impl CoerceUnsized> for Pin

where P: CoerceUnsized, {} -#[unstable(feature = "pin", issue = "49150")] +#[stable(feature = "pin", since = "1.33.0")] impl<'a, P, U> DispatchFromDyn> for Pin

where P: DispatchFromDyn, diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index ead38f2112687..77c64dcff9feb 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -280,7 +280,6 @@ #![feature(optin_builtin_traits)] #![feature(panic_internals)] #![feature(panic_unwind)] -#![feature(pin)] #![feature(prelude_import)] #![feature(ptr_internals)] #![feature(raw)] @@ -432,7 +431,7 @@ pub use alloc_crate::borrow; pub use alloc_crate::fmt; #[stable(feature = "rust1", since = "1.0.0")] pub use alloc_crate::format; -#[unstable(feature = "pin", issue = "49150")] +#[stable(feature = "pin", since = "1.33.0")] pub use core::pin; #[stable(feature = "rust1", since = "1.0.0")] pub use alloc_crate::slice; diff --git a/src/test/compile-fail/must_use-in-stdlib-traits.rs b/src/test/compile-fail/must_use-in-stdlib-traits.rs index 4bb5c59722ad1..7e446fdaeaf41 100644 --- a/src/test/compile-fail/must_use-in-stdlib-traits.rs +++ b/src/test/compile-fail/must_use-in-stdlib-traits.rs @@ -1,5 +1,5 @@ #![deny(unused_must_use)] -#![feature(futures_api, pin, arbitrary_self_types)] +#![feature(arbitrary_self_types, futures_api)] use std::iter::Iterator; use std::future::Future; diff --git a/src/test/run-pass/arbitrary_self_types_stdlib_pointers.rs b/src/test/run-pass/arbitrary_self_types_stdlib_pointers.rs index 80a7ce9691126..3f5d96dd42a39 100644 --- a/src/test/run-pass/arbitrary_self_types_stdlib_pointers.rs +++ b/src/test/run-pass/arbitrary_self_types_stdlib_pointers.rs @@ -9,7 +9,6 @@ // except according to those terms. #![feature(arbitrary_self_types)] -#![feature(pin)] #![feature(rustc_attrs)] use std::{ diff --git a/src/test/run-pass/async-await.rs b/src/test/run-pass/async-await.rs index 59da758035466..996709fa86c33 100644 --- a/src/test/run-pass/async-await.rs +++ b/src/test/run-pass/async-await.rs @@ -10,7 +10,7 @@ // edition:2018 -#![feature(arbitrary_self_types, async_await, await_macro, futures_api, pin)] +#![feature(arbitrary_self_types, async_await, await_macro, futures_api)] use std::pin::Pin; use std::future::Future; diff --git a/src/test/run-pass/futures-api.rs b/src/test/run-pass/futures-api.rs index 18865e4a07622..ac67488924993 100644 --- a/src/test/run-pass/futures-api.rs +++ b/src/test/run-pass/futures-api.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(arbitrary_self_types, futures_api, pin)] +#![feature(arbitrary_self_types, futures_api)] #![allow(unused)] use std::future::Future; From 80059df0caa60da98f8eb69fe0852fe30f2f70d6 Mon Sep 17 00:00:00 2001 From: Taylor Cramer Date: Tue, 18 Dec 2018 10:20:53 -0800 Subject: [PATCH 23/84] Pin stabilization: fix doctests --- src/libcore/marker.rs | 1 - src/libcore/pin.rs | 4 +--- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/src/libcore/marker.rs b/src/libcore/marker.rs index 181623f4932ee..74055a4f8a9b0 100644 --- a/src/libcore/marker.rs +++ b/src/libcore/marker.rs @@ -621,7 +621,6 @@ unsafe impl Freeze for &mut T {} /// So this, for example, can only be done on types implementing `Unpin`: /// /// ```rust -/// #![feature(pin)] /// use std::mem::replace; /// use std::pin::Pin; /// diff --git a/src/libcore/pin.rs b/src/libcore/pin.rs index 3f2eb0b6110b9..be40e5da5e910 100644 --- a/src/libcore/pin.rs +++ b/src/libcore/pin.rs @@ -43,8 +43,6 @@ //! # Examples //! //! ```rust -//! #![feature(pin)] -//! //! use std::pin::Pin; //! use std::marker::PhantomPinned; //! use std::ptr::NonNull; @@ -78,7 +76,7 @@ //! // we know this is safe because modifying a field doesn't move the whole struct //! unsafe { //! let mut_ref: Pin<&mut Self> = Pin::as_mut(&mut boxed); -//! Pin::get_mut_unchecked(mut_ref).slice = slice; +//! Pin::get_unchecked_mut(mut_ref).slice = slice; //! } //! boxed //! } From 9229488089727b816ed19dcfbcaa07531c91535c Mon Sep 17 00:00:00 2001 From: Taylor Cramer Date: Tue, 18 Dec 2018 10:25:02 -0800 Subject: [PATCH 24/84] Rename Box/Arc/Rc::pinned to ::pin --- src/liballoc/boxed.rs | 4 +++- src/liballoc/rc.rs | 4 +++- src/liballoc/sync.rs | 4 +++- src/libcore/pin.rs | 2 +- src/test/run-pass/async-await.rs | 2 +- 5 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index c8bbe4807a25a..a51bd9aa4c7b8 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -109,9 +109,11 @@ impl Box { box x } + /// Constructs a new `Pin>`. If `T` does not implement `Unpin`, then + /// `x` will be pinned in memory and unable to be moved. #[stable(feature = "pin", since = "1.33.0")] #[inline(always)] - pub fn pinned(x: T) -> Pin> { + pub fn pin(x: T) -> Pin> { (box x).into() } } diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index 875fcc7fb9744..f4ef8a627eb45 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -325,8 +325,10 @@ impl Rc { } } + /// Constructs a new `Pin>`. If `T` does not implement `Unpin`, then + /// `value` will be pinned in memory and unable to be moved. #[stable(feature = "pin", since = "1.33.0")] - pub fn pinned(value: T) -> Pin> { + pub fn pin(value: T) -> Pin> { unsafe { Pin::new_unchecked(Rc::new(value)) } } diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs index c4f770eff7fc9..f2c474da0d427 100644 --- a/src/liballoc/sync.rs +++ b/src/liballoc/sync.rs @@ -303,8 +303,10 @@ impl Arc { Arc { ptr: Box::into_raw_non_null(x), phantom: PhantomData } } + /// Constructs a new `Pin>`. If `T` does not implement `Unpin`, then + /// `data` will be pinned in memory and unable to be moved. #[stable(feature = "pin", since = "1.33.0")] - pub fn pinned(data: T) -> Pin> { + pub fn pin(data: T) -> Pin> { unsafe { Pin::new_unchecked(Arc::new(data)) } } diff --git a/src/libcore/pin.rs b/src/libcore/pin.rs index be40e5da5e910..38ea96cec5d93 100644 --- a/src/libcore/pin.rs +++ b/src/libcore/pin.rs @@ -70,7 +70,7 @@ //! slice: NonNull::dangling(), //! _pin: PhantomPinned, //! }; -//! let mut boxed = Box::pinned(res); +//! let mut boxed = Box::pin(res); //! //! let slice = NonNull::from(&boxed.data); //! // we know this is safe because modifying a field doesn't move the whole struct diff --git a/src/test/run-pass/async-await.rs b/src/test/run-pass/async-await.rs index 996709fa86c33..d9eb801a20668 100644 --- a/src/test/run-pass/async-await.rs +++ b/src/test/run-pass/async-await.rs @@ -138,7 +138,7 @@ where F: FnOnce(u8) -> Fut, Fut: Future, { - let mut fut = Box::pinned(f(9)); + let mut fut = Box::pin(f(9)); let counter = Arc::new(Counter { wakes: AtomicUsize::new(0) }); let waker = local_waker_from_nonlocal(counter.clone()); assert_eq!(0, counter.wakes.load(atomic::Ordering::SeqCst)); From 46a4ff6333302ddd5e291c63f529556cde6c131f Mon Sep 17 00:00:00 2001 From: Taylor Cramer Date: Tue, 18 Dec 2018 14:23:24 -0800 Subject: [PATCH 25/84] Fix Unpin docs link --- src/libcore/pin.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/pin.rs b/src/libcore/pin.rs index 38ea96cec5d93..930e51ce41ed6 100644 --- a/src/libcore/pin.rs +++ b/src/libcore/pin.rs @@ -36,7 +36,7 @@ //! are always freely movable, even if the data they point to isn't. //! //! [`Pin`]: struct.Pin.html -//! [`Unpin`]: trait.Unpin.html +//! [`Unpin`]: ../../std/marker/trait.Unpin.html //! [`swap`]: ../../std/mem/fn.swap.html //! [`Box`]: ../../std/boxed/struct.Box.html //! From 3d8a066fa1558134a6f40d91def67bd4366ead31 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 19 Dec 2018 00:51:37 +0100 Subject: [PATCH 26/84] Replace current crate's searchIndex when regenerating --- src/librustdoc/html/render.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index c9f3aa011a1d4..fb559305fb7d4 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -964,7 +964,7 @@ themePicker.onblur = handleThemeButtonsBlur; .collect::>() .join(","))); } - all_aliases.push(format!("ALIASES['{}'] = {{{}}};", krate.name, output)); + all_aliases.push(format!("ALIASES[\"{}\"] = {{{}}};", krate.name, output)); all_aliases.sort(); try_err!(writeln!(&mut w, "var ALIASES = {{}};"), &dst); for aliases in &all_aliases { @@ -1038,7 +1038,7 @@ themePicker.onblur = handleThemeButtonsBlur; let dst = cx.dst.join("source-files.js"); let (mut all_sources, _krates) = try_err!(collect(&dst, &krate.name, "sourcesIndex"), &dst); - all_sources.push(format!("sourcesIndex['{}'] = {};", + all_sources.push(format!("sourcesIndex[\"{}\"] = {};", &krate.name, hierarchy.to_json_string())); all_sources.sort(); From 00bd306e0d060fc737d670e9aacd2789d3103785 Mon Sep 17 00:00:00 2001 From: William Brown Date: Wed, 19 Dec 2018 11:32:56 +1000 Subject: [PATCH 27/84] Extend documentation for mem uninit to discuss partial allocation of the values --- src/libcore/mem.rs | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index afd9fcb1fba84..7e4e83999c1a3 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -530,6 +530,12 @@ pub unsafe fn zeroed() -> T { /// it goes out of scope (and therefore would be dropped). Note that this /// includes a `panic` occurring and unwinding the stack suddenly. /// +/// If you partially initialize an array, you may need to use +/// [`ptr::drop_in_place`][drop_in_place] to remove the set you have created +/// followed by [`mem::forget`][mem_forget] to prevent drop running on the +/// array. If a partially allocated array is dropped this may lead to +/// undefined behaviour. +/// /// # Examples /// /// Here's how to safely initialize an array of [`Vec`]s. @@ -583,11 +589,47 @@ pub unsafe fn zeroed() -> T { /// println!("{:?}", &data[0]); /// ``` /// +/// This example shows how to handle partially allocated arrays, which could +/// be found in low-level datastructures. +/// +/// ``` +/// use std::mem; +/// use std::ptr; +/// +/// // Count the number of elements we have assigned. +/// let mut data_len: usize = 0; +/// let mut data: [String; 1000]; +/// +/// unsafe { +/// data = mem::uninitialized(); +/// +/// for elem in &mut data[0..500] { +/// ptr::write(elem, String::from("hello")); +/// data_len += 1; +/// } +/// +/// // For each item in the array, drop if we allocated it. +/// for i in &mut data[0..data_len] { +/// ptr::drop_in_place(i); +/// } +/// } +/// // Forget the data. If this is allowed to drop, you may see a crash such as: +/// // 'mem_uninit_test(2457,0x7fffb55dd380) malloc: *** error for object 0x7ff3b8402920: pointer being freed was not allocated' +/// mem::forget(data); +/// ``` +/// +/// An alternate strategy is to use [`mem::zeroed`][mem_zeroed] with ptr +/// comparison. This is a very error prone strategy and may only be relevant +/// for FFI. +/// /// [`Vec`]: ../../std/vec/struct.Vec.html /// [`vec!`]: ../../std/macro.vec.html /// [`Clone`]: ../../std/clone/trait.Clone.html /// [ub]: ../../reference/behavior-considered-undefined.html /// [write]: ../ptr/fn.write.html +/// [drop_in_place]: ../ptr/fn.drop_in_place.html +/// [mem_zeroed]: fn.zeroed.html +/// [mem_forget]: fn.forget.html /// [copy]: ../intrinsics/fn.copy.html /// [copy_no]: ../intrinsics/fn.copy_nonoverlapping.html /// [`Drop`]: ../ops/trait.Drop.html From 0829d0c0e480a3729dcfe4f28f5969277dc8f646 Mon Sep 17 00:00:00 2001 From: William Brown Date: Wed, 19 Dec 2018 12:40:57 +1000 Subject: [PATCH 28/84] Updates based on comment --- src/libcore/mem.rs | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index 7e4e83999c1a3..7492cf4c5ed32 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -531,9 +531,9 @@ pub unsafe fn zeroed() -> T { /// includes a `panic` occurring and unwinding the stack suddenly. /// /// If you partially initialize an array, you may need to use -/// [`ptr::drop_in_place`][drop_in_place] to remove the set you have created -/// followed by [`mem::forget`][mem_forget] to prevent drop running on the -/// array. If a partially allocated array is dropped this may lead to +/// [`ptr::drop_in_place`][drop_in_place] to remove the elements you have fully +/// initialized followed by [`mem::forget`][mem_forget] to prevent drop running +/// on the array. If a partially allocated array is dropped this will lead to /// undefined behaviour. /// /// # Examples @@ -589,7 +589,7 @@ pub unsafe fn zeroed() -> T { /// println!("{:?}", &data[0]); /// ``` /// -/// This example shows how to handle partially allocated arrays, which could +/// This example shows how to handle partially initialized arrays, which could /// be found in low-level datastructures. /// /// ``` @@ -618,10 +618,6 @@ pub unsafe fn zeroed() -> T { /// mem::forget(data); /// ``` /// -/// An alternate strategy is to use [`mem::zeroed`][mem_zeroed] with ptr -/// comparison. This is a very error prone strategy and may only be relevant -/// for FFI. -/// /// [`Vec`]: ../../std/vec/struct.Vec.html /// [`vec!`]: ../../std/macro.vec.html /// [`Clone`]: ../../std/clone/trait.Clone.html From 3773ae26a0cf7b6806602e7994087d3a3f37c3cb Mon Sep 17 00:00:00 2001 From: Niv Kaminer Date: Mon, 17 Dec 2018 17:28:03 +0200 Subject: [PATCH 29/84] FIXME(45827) remove comment since errors are reported --- .../propagate-approximated-shorter-to-static-no-bound.rs | 3 --- ...propagate-approximated-shorter-to-static-no-bound.stderr | 6 +++--- .../propagate-approximated-shorter-to-static-wrong-bound.rs | 3 --- ...pagate-approximated-shorter-to-static-wrong-bound.stderr | 6 +++--- 4 files changed, 6 insertions(+), 12 deletions(-) diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.rs b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.rs index 4bef6cf8cd160..76105afb13e6e 100644 --- a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.rs +++ b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.rs @@ -12,9 +12,6 @@ // approximate the shorter end-point (`'y`) to with `'static`. This is // because `'y` is higher-ranked but we know of no relations to other // regions. Note that `'static` shows up in the stderr output as `'0`. -// -// FIXME(#45827) Because of shortcomings in the MIR type checker, -// these errors are not (yet) reported. // compile-flags:-Zborrowck=mir -Zverbose diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr index f22dbdba934e8..2b0474332d6e8 100644 --- a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr @@ -1,5 +1,5 @@ note: External requirements - --> $DIR/propagate-approximated-shorter-to-static-no-bound.rs:45:47 + --> $DIR/propagate-approximated-shorter-to-static-no-bound.rs:42:47 | LL | establish_relationships(&cell_a, &cell_b, |_outlives, x, y| { | _______________________________________________^ @@ -20,7 +20,7 @@ LL | | }); = note: where '_#1r: '_#0r note: No external requirements - --> $DIR/propagate-approximated-shorter-to-static-no-bound.rs:44:1 + --> $DIR/propagate-approximated-shorter-to-static-no-bound.rs:41:1 | LL | / fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) { LL | | establish_relationships(&cell_a, &cell_b, |_outlives, x, y| { @@ -34,7 +34,7 @@ LL | | } = note: defining type: DefId(0/0:6 ~ propagate_approximated_shorter_to_static_no_bound[317d]::supply[0]) with substs [] error[E0521]: borrowed data escapes outside of function - --> $DIR/propagate-approximated-shorter-to-static-no-bound.rs:45:5 + --> $DIR/propagate-approximated-shorter-to-static-no-bound.rs:42:5 | LL | fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) { | ------ `cell_a` is a reference that is only valid in the function body diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.rs b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.rs index 05e9818b91e56..79bd029411e5a 100644 --- a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.rs +++ b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.rs @@ -13,9 +13,6 @@ // because `'y` is higher-ranked but we know of only irrelevant // relations to other regions. Note that `'static` shows up in the // stderr output as `'0`. -// -// FIXME(#45827) Because of shortcomings in the MIR type checker, -// these errors are not (yet) reported. // compile-flags:-Zborrowck=mir -Zverbose diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr index 2b1cb5a30ceda..f76787c8d7d16 100644 --- a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr @@ -1,5 +1,5 @@ note: External requirements - --> $DIR/propagate-approximated-shorter-to-static-wrong-bound.rs:48:47 + --> $DIR/propagate-approximated-shorter-to-static-wrong-bound.rs:45:47 | LL | establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| { | _______________________________________________^ @@ -20,7 +20,7 @@ LL | | }); = note: where '_#1r: '_#0r note: No external requirements - --> $DIR/propagate-approximated-shorter-to-static-wrong-bound.rs:47:1 + --> $DIR/propagate-approximated-shorter-to-static-wrong-bound.rs:44:1 | LL | / fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) { LL | | establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| { @@ -34,7 +34,7 @@ LL | | } = note: defining type: DefId(0/0:6 ~ propagate_approximated_shorter_to_static_wrong_bound[317d]::supply[0]) with substs [] error[E0521]: borrowed data escapes outside of function - --> $DIR/propagate-approximated-shorter-to-static-wrong-bound.rs:48:5 + --> $DIR/propagate-approximated-shorter-to-static-wrong-bound.rs:45:5 | LL | fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) { | ------ `cell_a` is a reference that is only valid in the function body From cf329d5978a9d09f8d4df4afa360823167c8ea5d Mon Sep 17 00:00:00 2001 From: Niv Kaminer Date: Mon, 17 Dec 2018 17:31:27 +0200 Subject: [PATCH 30/84] FIXME(49821) remove fixme since a tip about let binding is given --- src/test/ui/issues/issue-36082.ast.stderr | 2 +- src/test/ui/issues/issue-36082.mir.stderr | 2 +- src/test/ui/issues/issue-36082.rs | 2 -- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/test/ui/issues/issue-36082.ast.stderr b/src/test/ui/issues/issue-36082.ast.stderr index b79958de5cb36..720a11bfe44d0 100644 --- a/src/test/ui/issues/issue-36082.ast.stderr +++ b/src/test/ui/issues/issue-36082.ast.stderr @@ -1,5 +1,5 @@ error[E0597]: borrowed value does not live long enough - --> $DIR/issue-36082.rs:23:19 + --> $DIR/issue-36082.rs:21:19 | LL | let val: &_ = x.borrow().0; | ^^^^^^^^^^ - temporary value dropped here while still borrowed diff --git a/src/test/ui/issues/issue-36082.mir.stderr b/src/test/ui/issues/issue-36082.mir.stderr index 7fa7cee0aec1e..4a6fa787d31b9 100644 --- a/src/test/ui/issues/issue-36082.mir.stderr +++ b/src/test/ui/issues/issue-36082.mir.stderr @@ -1,5 +1,5 @@ error[E0716]: temporary value dropped while borrowed - --> $DIR/issue-36082.rs:23:19 + --> $DIR/issue-36082.rs:21:19 | LL | let val: &_ = x.borrow().0; | ^^^^^^^^^^ - temporary value is freed at the end of this statement diff --git a/src/test/ui/issues/issue-36082.rs b/src/test/ui/issues/issue-36082.rs index b8a498a4dc85c..c8b92bba6e7ff 100644 --- a/src/test/ui/issues/issue-36082.rs +++ b/src/test/ui/issues/issue-36082.rs @@ -11,8 +11,6 @@ // revisions: ast mir //[mir]compile-flags: -Z borrowck=mir -// FIXME(#49821) -- No tip about using a let binding - use std::cell::RefCell; fn main() { From 7092fca98465457c7512e313d52a5f92797942da Mon Sep 17 00:00:00 2001 From: Niv Kaminer Date: Mon, 17 Dec 2018 18:21:00 +0200 Subject: [PATCH 31/84] FIXME(44217) remove fixme because the allocator logic was removed, but platform specific code remains --- src/tools/tidy/src/pal.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/tidy/src/pal.rs b/src/tools/tidy/src/pal.rs index acf72022c60ed..da5d1a3eaa4a7 100644 --- a/src/tools/tidy/src/pal.rs +++ b/src/tools/tidy/src/pal.rs @@ -58,7 +58,7 @@ const EXCEPTION_PATHS: &[&str] = &[ "src/rtstartup", // Not sure what to do about this. magic stuff for mingw // temporary exceptions - "src/libstd/lib.rs", // FIXME(#44217) + "src/libstd/lib.rs", "src/libstd/path.rs", "src/libstd/f32.rs", "src/libstd/f64.rs", From cc568e7be1ee6fea6e594f8ecd34d4fe05610e8b Mon Sep 17 00:00:00 2001 From: Niv Kaminer Date: Mon, 17 Dec 2018 18:34:04 +0200 Subject: [PATCH 32/84] FIXME(49824) remove fixme because there is no free region error anymore --- src/test/ui/borrowck/borrowck-describe-lvalue.ast.stderr | 4 ++-- src/test/ui/borrowck/borrowck-describe-lvalue.mir.stderr | 6 +++--- src/test/ui/borrowck/borrowck-describe-lvalue.rs | 1 - 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/test/ui/borrowck/borrowck-describe-lvalue.ast.stderr b/src/test/ui/borrowck/borrowck-describe-lvalue.ast.stderr index bc6385ffd920b..c028b2c486812 100644 --- a/src/test/ui/borrowck/borrowck-describe-lvalue.ast.stderr +++ b/src/test/ui/borrowck/borrowck-describe-lvalue.ast.stderr @@ -220,7 +220,7 @@ LL | }; | - first borrow ends here error[E0499]: cannot borrow `**x` as mutable more than once at a time - --> $DIR/borrowck-describe-lvalue.rs:307:25 + --> $DIR/borrowck-describe-lvalue.rs:306:25 | LL | let y = &mut x; | - first mutable borrow occurs here @@ -231,7 +231,7 @@ LL | } | - first borrow ends here error[E0382]: use of moved value: `x` - --> $DIR/borrowck-describe-lvalue.rs:318:22 + --> $DIR/borrowck-describe-lvalue.rs:317:22 | LL | drop(x); | - value moved here diff --git a/src/test/ui/borrowck/borrowck-describe-lvalue.mir.stderr b/src/test/ui/borrowck/borrowck-describe-lvalue.mir.stderr index 5721c52ba2172..69855cc984195 100644 --- a/src/test/ui/borrowck/borrowck-describe-lvalue.mir.stderr +++ b/src/test/ui/borrowck/borrowck-describe-lvalue.mir.stderr @@ -10,7 +10,7 @@ LL | *y = 1; | ------ first borrow later used here error[E0499]: cannot borrow `x` as mutable more than once at a time - --> $DIR/borrowck-describe-lvalue.rs:307:20 + --> $DIR/borrowck-describe-lvalue.rs:306:20 | LL | let y = &mut x; | ------ first mutable borrow occurs here @@ -21,7 +21,7 @@ LL | *y = 1; | ------ first borrow later used here error: captured variable cannot escape `FnMut` closure body - --> $DIR/borrowck-describe-lvalue.rs:305:16 + --> $DIR/borrowck-describe-lvalue.rs:304:16 | LL | || { | - inferred to be a `FnMut` closure @@ -362,7 +362,7 @@ LL | drop(x); | - mutable borrow later used here error[E0382]: use of moved value: `x` - --> $DIR/borrowck-describe-lvalue.rs:318:22 + --> $DIR/borrowck-describe-lvalue.rs:317:22 | LL | drop(x); | - value moved here diff --git a/src/test/ui/borrowck/borrowck-describe-lvalue.rs b/src/test/ui/borrowck/borrowck-describe-lvalue.rs index 649de888ab0a2..29f29f106dff6 100644 --- a/src/test/ui/borrowck/borrowck-describe-lvalue.rs +++ b/src/test/ui/borrowck/borrowck-describe-lvalue.rs @@ -299,7 +299,6 @@ fn main() { } // Field from upvar nested { - // FIXME(#49824) -- the free region error below should probably not be there let mut x = 0; || { || { //[mir]~ ERROR captured variable cannot escape `FnMut` closure body From e06b81e029c8e37a4b5e153e85977022b0167f9e Mon Sep 17 00:00:00 2001 From: Niv Kaminer Date: Mon, 17 Dec 2018 18:38:42 +0200 Subject: [PATCH 33/84] FIXME(21232) update fixme to point to the open issue about accepting partial initialization --- src/test/ui/borrowck/assign_mutable_fields.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/ui/borrowck/assign_mutable_fields.rs b/src/test/ui/borrowck/assign_mutable_fields.rs index 4e41f44ef5bb3..1b9ecbeafe422 100644 --- a/src/test/ui/borrowck/assign_mutable_fields.rs +++ b/src/test/ui/borrowck/assign_mutable_fields.rs @@ -12,7 +12,7 @@ // var, but we do not permit you to use the complete var afterwards. // We hope to fix this at some point. // -// FIXME(#21232) +// FIXME(#54987) fn assign_both_fields_and_use() { let mut x: (u32, u32); From aedbe9a9634fdd821ed317557b06993b554d89a1 Mon Sep 17 00:00:00 2001 From: Niv Kaminer Date: Mon, 17 Dec 2018 20:38:50 +0200 Subject: [PATCH 34/84] FIXME(31702) remove fixme, move auxiliaries to the right place and fix hr_lifetime_in_assoc_type warning --- src/test/run-pass/{ => issues}/auxiliary/issue-31702-1.rs | 0 src/test/run-pass/{ => issues}/auxiliary/issue-31702-2.rs | 2 +- src/test/run-pass/issues/issue-31702.rs | 5 ----- 3 files changed, 1 insertion(+), 6 deletions(-) rename src/test/run-pass/{ => issues}/auxiliary/issue-31702-1.rs (100%) rename src/test/run-pass/{ => issues}/auxiliary/issue-31702-2.rs (94%) diff --git a/src/test/run-pass/auxiliary/issue-31702-1.rs b/src/test/run-pass/issues/auxiliary/issue-31702-1.rs similarity index 100% rename from src/test/run-pass/auxiliary/issue-31702-1.rs rename to src/test/run-pass/issues/auxiliary/issue-31702-1.rs diff --git a/src/test/run-pass/auxiliary/issue-31702-2.rs b/src/test/run-pass/issues/auxiliary/issue-31702-2.rs similarity index 94% rename from src/test/run-pass/auxiliary/issue-31702-2.rs rename to src/test/run-pass/issues/auxiliary/issue-31702-2.rs index c5b1bc6dfb08d..ae8743b62ee05 100644 --- a/src/test/run-pass/auxiliary/issue-31702-2.rs +++ b/src/test/run-pass/issues/auxiliary/issue-31702-2.rs @@ -16,7 +16,7 @@ use std::collections::HashMap; use issue_31702_1::U256; pub struct Ethash { - engine_params: for<'a> fn() -> Option<&'a Vec>, + engine_params: fn() -> Option<&'static Vec>, u256_params: HashMap, } diff --git a/src/test/run-pass/issues/issue-31702.rs b/src/test/run-pass/issues/issue-31702.rs index 8ce06e8d34339..4011d12ad961b 100644 --- a/src/test/run-pass/issues/issue-31702.rs +++ b/src/test/run-pass/issues/issue-31702.rs @@ -11,11 +11,6 @@ // run-pass // aux-build:issue-31702-1.rs // aux-build:issue-31702-2.rs -// ignore-test: FIXME(#31702) when this test was added it was thought that the -// accompanying llvm update would fix it, but -// unfortunately it appears that was not the case. In -// the interest of not deleting the test, though, -// this is just tagged with ignore-test // this test is actually entirely in the linked library crates From b1db8f8833e004889454f9a09287ed4efa28ddf7 Mon Sep 17 00:00:00 2001 From: Niv Kaminer Date: Tue, 18 Dec 2018 11:27:31 +0200 Subject: [PATCH 35/84] FIXME(45992) remove fixme since the lint is being tested --- src/test/run-pass/impl-trait/lifetimes.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/test/run-pass/impl-trait/lifetimes.rs b/src/test/run-pass/impl-trait/lifetimes.rs index e5a98962ff3ab..920fe07c91496 100644 --- a/src/test/run-pass/impl-trait/lifetimes.rs +++ b/src/test/run-pass/impl-trait/lifetimes.rs @@ -41,7 +41,6 @@ impl<'a> SingleRegionTrait<'a> for &'a u32 {} struct SingleRegionStruct<'a>(&'a u32); fn simple_type_hrtb<'b>() -> impl for<'a> SingleRegionTrait<'a> { 5 } -// FIXME(cramertj) add test after #45992 lands to ensure lint is triggered fn elision_single_region_trait(x: &u32) -> impl SingleRegionTrait { x } fn elision_single_region_struct(x: SingleRegionStruct) -> impl Into { x } From 5d7fad35eb66bcd128b8897dd8c84e75c1aa142d Mon Sep 17 00:00:00 2001 From: Niv Kaminer Date: Tue, 18 Dec 2018 12:29:30 +0200 Subject: [PATCH 36/84] FIXME(47184) update fixmes to point to issues specific to them --- src/librustc_mir/build/matches/test.rs | 2 +- src/librustc_mir/hair/pattern/mod.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustc_mir/build/matches/test.rs b/src/librustc_mir/build/matches/test.rs index c8dec6d0b9764..69706924dc966 100644 --- a/src/librustc_mir/build/matches/test.rs +++ b/src/librustc_mir/build/matches/test.rs @@ -347,7 +347,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { span: test.span, ty: mty, - // FIXME(#47184): This constant comes from user + // FIXME(#54571): This constant comes from user // input (a constant in a pattern). Are // there forms where users can add type // annotations here? For example, an diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs index f78a70f6a25f4..0324bfb892e45 100644 --- a/src/librustc_mir/hair/pattern/mod.rs +++ b/src/librustc_mir/hair/pattern/mod.rs @@ -83,7 +83,7 @@ impl<'tcx> PatternTypeProjections<'tcx> { } pub(crate) fn ref_binding(&self) -> Self { - // FIXME(#47184): ignore for now + // FIXME(#55401): ignore for now PatternTypeProjections { contents: vec![] } } From 86808249b4bc213540d41989c7c12df48021593d Mon Sep 17 00:00:00 2001 From: Niv Kaminer Date: Tue, 18 Dec 2018 15:38:43 +0200 Subject: [PATCH 37/84] FIXME(2665) remove fixme since the c files are included by the testsuite --- src/test/auxiliary/rust_test_helpers.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/test/auxiliary/rust_test_helpers.c b/src/test/auxiliary/rust_test_helpers.c index 2a14b3da7b7d0..feb51557ec648 100644 --- a/src/test/auxiliary/rust_test_helpers.c +++ b/src/test/auxiliary/rust_test_helpers.c @@ -163,11 +163,7 @@ rust_get_null_ptr() { return 0; } -/* Debug helpers strictly to verify ABI conformance. - * - * FIXME (#2665): move these into a testcase when the testsuite - * understands how to have explicit C files included. - */ +// Debug helpers strictly to verify ABI conformance. struct quad { uint64_t a; From 1aaad19418aef16b2e7688e36016b729ac2538ae Mon Sep 17 00:00:00 2001 From: Niv Kaminer Date: Tue, 18 Dec 2018 19:08:11 +0200 Subject: [PATCH 38/84] FIXME(RFC1868) point the fixme to the tracking issue --- src/librustdoc/clean/cfg.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/librustdoc/clean/cfg.rs b/src/librustdoc/clean/cfg.rs index 847786d123efc..e70284e4948ec 100644 --- a/src/librustdoc/clean/cfg.rs +++ b/src/librustdoc/clean/cfg.rs @@ -10,7 +10,8 @@ //! Representation of a `#[doc(cfg(...))]` attribute. -// FIXME: Once RFC #1868 is implemented, switch to use those structures instead. +// FIXME: Once the portability lint RFC is implemented (see tracking issue #41619), +// switch to use those structures instead. use std::mem; use std::fmt::{self, Write}; From 897c18235a28e9470badd4a3e93a0641dd9c2865 Mon Sep 17 00:00:00 2001 From: Niv Kaminer Date: Tue, 18 Dec 2018 20:58:15 +0200 Subject: [PATCH 39/84] FIXME(52456) remove fixme and combine all extern items in one block --- src/librustc_codegen_llvm/llvm/ffi.rs | 32 +++++---------------------- 1 file changed, 6 insertions(+), 26 deletions(-) diff --git a/src/librustc_codegen_llvm/llvm/ffi.rs b/src/librustc_codegen_llvm/llvm/ffi.rs index 4732db88ec1cb..5c59439fdfb6f 100644 --- a/src/librustc_codegen_llvm/llvm/ffi.rs +++ b/src/librustc_codegen_llvm/llvm/ffi.rs @@ -1601,15 +1601,12 @@ extern "C" { -> &'a Value; pub fn LLVMRustDIBuilderCreateOpDeref() -> i64; pub fn LLVMRustDIBuilderCreateOpPlusUconst() -> i64; -} -#[allow(improper_ctypes)] // FIXME(#52456) needed for RustString. -extern "C" { + #[allow(improper_ctypes)] pub fn LLVMRustWriteTypeToString(Type: &Type, s: &RustString); + #[allow(improper_ctypes)] pub fn LLVMRustWriteValueToString(value_ref: &Value, s: &RustString); -} -extern "C" { pub fn LLVMIsAConstantInt(value_ref: &Value) -> Option<&Value>; pub fn LLVMIsAConstantFP(value_ref: &Value) -> Option<&Value>; @@ -1687,21 +1684,15 @@ extern "C" { pub fn LLVMRustDestroyArchive(AR: &'static mut Archive); pub fn LLVMRustGetSectionName(SI: &SectionIterator, data: &mut *const c_char) -> size_t; -} -#[allow(improper_ctypes)] // FIXME(#52456) needed for RustString. -extern "C" { + #[allow(improper_ctypes)] pub fn LLVMRustWriteTwineToString(T: &Twine, s: &RustString); -} -extern "C" { pub fn LLVMContextSetDiagnosticHandler(C: &Context, Handler: DiagnosticHandler, DiagnosticContext: *mut c_void); -} -#[allow(improper_ctypes)] // FIXME(#52456) needed for RustString. -extern "C" { + #[allow(improper_ctypes)] pub fn LLVMRustUnpackOptimizationDiagnostic(DI: &'a DiagnosticInfo, pass_name_out: &RustString, function_out: &mut Option<&'a Value>, @@ -1709,34 +1700,23 @@ extern "C" { loc_column_out: &mut c_uint, loc_filename_out: &RustString, message_out: &RustString); -} -extern "C" { pub fn LLVMRustUnpackInlineAsmDiagnostic(DI: &'a DiagnosticInfo, cookie_out: &mut c_uint, message_out: &mut Option<&'a Twine>, instruction_out: &mut Option<&'a Value>); -} -#[allow(improper_ctypes)] // FIXME(#52456) needed for RustString. -extern "C" { + #[allow(improper_ctypes)] pub fn LLVMRustWriteDiagnosticInfoToString(DI: &DiagnosticInfo, s: &RustString); -} - -extern "C" { pub fn LLVMRustGetDiagInfoKind(DI: &DiagnosticInfo) -> DiagnosticKind; pub fn LLVMRustSetInlineAsmDiagnosticHandler(C: &Context, H: InlineAsmDiagHandler, CX: *mut c_void); -} -#[allow(improper_ctypes)] // FIXME(#52456) needed for RustString. -extern "C" { + #[allow(improper_ctypes)] pub fn LLVMRustWriteSMDiagnosticToString(d: &SMDiagnostic, s: &RustString); -} -extern "C" { pub fn LLVMRustWriteArchive(Dst: *const c_char, NumMembers: size_t, Members: *const &RustArchiveMember, From d88d319a5d9d8f339d9d0fde71bb3b9979c9093b Mon Sep 17 00:00:00 2001 From: Niv Kaminer Date: Tue, 18 Dec 2018 22:47:13 +0200 Subject: [PATCH 40/84] FIXME(53451) remove fixme and unnecessary pubs --- src/libproc_macro/bridge/client.rs | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/src/libproc_macro/bridge/client.rs b/src/libproc_macro/bridge/client.rs index f5e12713e4e72..d6c2848b03433 100644 --- a/src/libproc_macro/bridge/client.rs +++ b/src/libproc_macro/bridge/client.rs @@ -25,8 +25,7 @@ macro_rules! define_handles { } impl HandleCounters { - // FIXME(#53451) public to work around `Cannot create local mono-item` ICE. - pub extern "C" fn get() -> &'static Self { + extern "C" fn get() -> &'static Self { static COUNTERS: HandleCounters = HandleCounters { $($oty: AtomicUsize::new(1),)* $($ity: AtomicUsize::new(1),)* @@ -345,9 +344,7 @@ pub struct Client { pub(super) f: F, } -// FIXME(#53451) public to work around `Cannot create local mono-item` ICE, -// affecting not only the function itself, but also the `BridgeState` `thread_local!`. -pub extern "C" fn __run_expand1( +extern "C" fn run_expand1( mut bridge: Bridge, f: fn(::TokenStream) -> ::TokenStream, ) -> Buffer { @@ -392,15 +389,13 @@ impl Client ::TokenStream> { pub const fn expand1(f: fn(::TokenStream) -> ::TokenStream) -> Self { Client { get_handle_counters: HandleCounters::get, - run: __run_expand1, + run: run_expand1, f, } } } -// FIXME(#53451) public to work around `Cannot create local mono-item` ICE, -// affecting not only the function itself, but also the `BridgeState` `thread_local!`. -pub extern "C" fn __run_expand2( +extern "C" fn run_expand2( mut bridge: Bridge, f: fn(::TokenStream, ::TokenStream) -> ::TokenStream, ) -> Buffer { @@ -446,7 +441,7 @@ impl Client ::TokenStream> { pub const fn expand2(f: fn(::TokenStream, ::TokenStream) -> ::TokenStream) -> Self { Client { get_handle_counters: HandleCounters::get, - run: __run_expand2, + run: run_expand2, f, } } From cbe9abb78cd6c1b8c74b78110b8c92c1f0984ba0 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Wed, 19 Dec 2018 00:38:15 -0800 Subject: [PATCH 41/84] Add more VecDeque::rotate_{left|right} tests --- src/liballoc/tests/lib.rs | 3 +- src/liballoc/tests/vec_deque.rs | 134 ++++++++++++++++++++++++++++++++ 2 files changed, 136 insertions(+), 1 deletion(-) diff --git a/src/liballoc/tests/lib.rs b/src/liballoc/tests/lib.rs index e514a8a69c020..146abd1b7508a 100644 --- a/src/liballoc/tests/lib.rs +++ b/src/liballoc/tests/lib.rs @@ -13,11 +13,12 @@ #![feature(drain_filter)] #![feature(exact_size_is_empty)] #![feature(pattern)] +#![feature(repeat_generic_slice)] #![feature(slice_sort_by_cached_key)] #![feature(str_escape)] #![feature(try_reserve)] #![feature(unboxed_closures)] -#![feature(repeat_generic_slice)] +#![feature(vecdeque_rotate)] extern crate core; extern crate rand; diff --git a/src/liballoc/tests/vec_deque.rs b/src/liballoc/tests/vec_deque.rs index 1f2a7211c657b..c8a6d86413ad6 100644 --- a/src/liballoc/tests/vec_deque.rs +++ b/src/liballoc/tests/vec_deque.rs @@ -1309,3 +1309,137 @@ fn test_try_reserve_exact() { } } + +#[test] +fn test_rotate_nop() { + let mut v: VecDeque<_> = (0..10).collect(); + assert_unchanged(&v); + + v.rotate_left(0); + assert_unchanged(&v); + + v.rotate_left(10); + assert_unchanged(&v); + + v.rotate_right(0); + assert_unchanged(&v); + + v.rotate_right(10); + assert_unchanged(&v); + + v.rotate_left(3); + v.rotate_right(3); + assert_unchanged(&v); + + v.rotate_right(3); + v.rotate_left(3); + assert_unchanged(&v); + + v.rotate_left(6); + v.rotate_right(6); + assert_unchanged(&v); + + v.rotate_right(6); + v.rotate_left(6); + assert_unchanged(&v); + + v.rotate_left(3); + v.rotate_left(7); + assert_unchanged(&v); + + v.rotate_right(4); + v.rotate_right(6); + assert_unchanged(&v); + + v.rotate_left(1); + v.rotate_left(2); + v.rotate_left(3); + v.rotate_left(4); + assert_unchanged(&v); + + v.rotate_right(1); + v.rotate_right(2); + v.rotate_right(3); + v.rotate_right(4); + assert_unchanged(&v); + + fn assert_unchanged(v: &VecDeque) { + assert_eq!(v, &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]); + } +} + +#[test] +fn test_rotate_left_parts() { + let mut v: VecDeque<_> = (1..=7).collect(); + v.rotate_left(2); + assert_eq!(v.as_slices(), (&[3, 4, 5, 6, 7, 1][..], &[2][..])); + v.rotate_left(2); + assert_eq!(v.as_slices(), (&[5, 6, 7, 1][..], &[2, 3, 4][..])); + v.rotate_left(2); + assert_eq!(v.as_slices(), (&[7, 1][..], &[2, 3, 4, 5, 6][..])); + v.rotate_left(2); + assert_eq!(v.as_slices(), (&[2, 3, 4, 5, 6, 7, 1][..], &[][..])); + v.rotate_left(2); + assert_eq!(v.as_slices(), (&[4, 5, 6, 7, 1, 2][..], &[3][..])); + v.rotate_left(2); + assert_eq!(v.as_slices(), (&[6, 7, 1, 2][..], &[3, 4, 5][..])); + v.rotate_left(2); + assert_eq!(v.as_slices(), (&[1, 2][..], &[3, 4, 5, 6, 7][..])); +} + +#[test] +fn test_rotate_right_parts() { + let mut v: VecDeque<_> = (1..=7).collect(); + v.rotate_right(2); + assert_eq!(v.as_slices(), (&[6, 7][..], &[1, 2, 3, 4, 5][..])); + v.rotate_right(2); + assert_eq!(v.as_slices(), (&[4, 5, 6, 7][..], &[1, 2, 3][..])); + v.rotate_right(2); + assert_eq!(v.as_slices(), (&[2, 3, 4, 5, 6, 7][..], &[1][..])); + v.rotate_right(2); + assert_eq!(v.as_slices(), (&[7, 1, 2, 3, 4, 5, 6][..], &[][..])); + v.rotate_right(2); + assert_eq!(v.as_slices(), (&[5, 6][..], &[7, 1, 2, 3, 4][..])); + v.rotate_right(2); + assert_eq!(v.as_slices(), (&[3, 4, 5, 6][..], &[7, 1, 2][..])); + v.rotate_right(2); + assert_eq!(v.as_slices(), (&[1, 2, 3, 4, 5, 6][..], &[7][..])); +} + +#[test] +fn test_rotate_left_random() { + let shifts = [ + 6, 1, 0, 11, 12, 1, 11, 7, 9, 3, 6, 1, + 4, 0, 5, 1, 3, 1, 12, 8, 3, 1, 11, 11, + 9, 4, 12, 3, 12, 9, 11, 1, 7, 9, 7, 2, + ]; + let n = 12; + let mut v: VecDeque<_> = (0..n).collect(); + let mut total_shift = 0; + for shift in shifts.iter().cloned() { + v.rotate_left(shift); + total_shift += shift; + for i in 0..n { + assert_eq!(v[i], (i + total_shift) % n); + } + } +} + +#[test] +fn test_rotate_right_random() { + let shifts = [ + 6, 1, 0, 11, 12, 1, 11, 7, 9, 3, 6, 1, + 4, 0, 5, 1, 3, 1, 12, 8, 3, 1, 11, 11, + 9, 4, 12, 3, 12, 9, 11, 1, 7, 9, 7, 2, + ]; + let n = 12; + let mut v: VecDeque<_> = (0..n).collect(); + let mut total_shift = 0; + for shift in shifts.iter().cloned() { + v.rotate_right(shift); + total_shift += shift; + for i in 0..n { + assert_eq!(v[(i + total_shift) % n], i); + } + } +} From 957a9c7c666801019478f1ff1535d8395127fa6f Mon Sep 17 00:00:00 2001 From: Niv Kaminer Date: Wed, 19 Dec 2018 10:54:35 +0200 Subject: [PATCH 42/84] Revert "FIXME(53451) remove fixme and unnecessary pubs" This reverts commit d88d319a5d9d8f339d9d0fde71bb3b9979c9093b. --- src/libproc_macro/bridge/client.rs | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/libproc_macro/bridge/client.rs b/src/libproc_macro/bridge/client.rs index d6c2848b03433..f5e12713e4e72 100644 --- a/src/libproc_macro/bridge/client.rs +++ b/src/libproc_macro/bridge/client.rs @@ -25,7 +25,8 @@ macro_rules! define_handles { } impl HandleCounters { - extern "C" fn get() -> &'static Self { + // FIXME(#53451) public to work around `Cannot create local mono-item` ICE. + pub extern "C" fn get() -> &'static Self { static COUNTERS: HandleCounters = HandleCounters { $($oty: AtomicUsize::new(1),)* $($ity: AtomicUsize::new(1),)* @@ -344,7 +345,9 @@ pub struct Client { pub(super) f: F, } -extern "C" fn run_expand1( +// FIXME(#53451) public to work around `Cannot create local mono-item` ICE, +// affecting not only the function itself, but also the `BridgeState` `thread_local!`. +pub extern "C" fn __run_expand1( mut bridge: Bridge, f: fn(::TokenStream) -> ::TokenStream, ) -> Buffer { @@ -389,13 +392,15 @@ impl Client ::TokenStream> { pub const fn expand1(f: fn(::TokenStream) -> ::TokenStream) -> Self { Client { get_handle_counters: HandleCounters::get, - run: run_expand1, + run: __run_expand1, f, } } } -extern "C" fn run_expand2( +// FIXME(#53451) public to work around `Cannot create local mono-item` ICE, +// affecting not only the function itself, but also the `BridgeState` `thread_local!`. +pub extern "C" fn __run_expand2( mut bridge: Bridge, f: fn(::TokenStream, ::TokenStream) -> ::TokenStream, ) -> Buffer { @@ -441,7 +446,7 @@ impl Client ::TokenStream> { pub const fn expand2(f: fn(::TokenStream, ::TokenStream) -> ::TokenStream) -> Self { Client { get_handle_counters: HandleCounters::get, - run: run_expand2, + run: __run_expand2, f, } } From b2d8040e6f89318c0ca7f5512ca31f8311b14a36 Mon Sep 17 00:00:00 2001 From: William Brown Date: Wed, 19 Dec 2018 19:09:54 +1000 Subject: [PATCH 43/84] Fix tidy error --- src/libcore/mem.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index 7492cf4c5ed32..9d1f5ce403570 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -614,7 +614,8 @@ pub unsafe fn zeroed() -> T { /// } /// } /// // Forget the data. If this is allowed to drop, you may see a crash such as: -/// // 'mem_uninit_test(2457,0x7fffb55dd380) malloc: *** error for object 0x7ff3b8402920: pointer being freed was not allocated' +/// // 'mem_uninit_test(2457,0x7fffb55dd380) malloc: *** error for object +/// // 0x7ff3b8402920: pointer being freed was not allocated' /// mem::forget(data); /// ``` /// From 202904b3f7a7d2563e6808b8d8d530768c949a99 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 19 Dec 2018 10:10:39 +0100 Subject: [PATCH 44/84] make basic CTFE tracing available on release builds --- src/librustc_mir/interpret/eval_context.rs | 8 ++++---- src/librustc_mir/interpret/step.rs | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index d36d530fe78b2..8ae0345e07a34 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -422,7 +422,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc return_to_block: StackPopCleanup, ) -> EvalResult<'tcx> { if self.stack.len() > 1 { // FIXME should be "> 0", printing topmost frame crashes rustc... - debug!("PAUSING({}) {}", self.cur_frame(), self.frame().instance); + info!("PAUSING({}) {}", self.cur_frame(), self.frame().instance); } ::log_settings::settings().indentation += 1; @@ -491,7 +491,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc } if self.stack.len() > 1 { // FIXME no check should be needed, but some instances ICE - debug!("ENTERING({}) {}", self.cur_frame(), self.frame().instance); + info!("ENTERING({}) {}", self.cur_frame(), self.frame().instance); } if self.stack.len() > self.tcx.sess.const_eval_stack_frame_limit { @@ -503,7 +503,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc pub(super) fn pop_stack_frame(&mut self) -> EvalResult<'tcx> { if self.stack.len() > 1 { // FIXME no check should be needed, but some instances ICE - debug!("LEAVING({}) {}", self.cur_frame(), self.frame().instance); + info!("LEAVING({}) {}", self.cur_frame(), self.frame().instance); } ::log_settings::settings().indentation -= 1; let frame = self.stack.pop().expect( @@ -557,7 +557,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc } if self.stack.len() > 1 { // FIXME should be "> 0", printing topmost frame crashes rustc... - debug!("CONTINUING({}) {}", self.cur_frame(), self.frame().instance); + info!("CONTINUING({}) {}", self.cur_frame(), self.frame().instance); } Ok(()) diff --git a/src/librustc_mir/interpret/step.rs b/src/librustc_mir/interpret/step.rs index a6835e4f16738..0b3f5b2678c7f 100644 --- a/src/librustc_mir/interpret/step.rs +++ b/src/librustc_mir/interpret/step.rs @@ -81,7 +81,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> } fn statement(&mut self, stmt: &mir::Statement<'tcx>) -> EvalResult<'tcx> { - debug!("{:?}", stmt); + info!("{:?}", stmt); use rustc::mir::StatementKind::*; @@ -293,7 +293,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> } fn terminator(&mut self, terminator: &mir::Terminator<'tcx>) -> EvalResult<'tcx> { - debug!("{:?}", terminator.kind); + info!("{:?}", terminator.kind); self.tcx.span = terminator.source_info.span; self.memory.tcx.span = terminator.source_info.span; @@ -303,7 +303,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> if !self.stack.is_empty() { // This should change *something* debug_assert!(self.cur_frame() != old_stack || self.frame().block != old_bb); - debug!("// {:?}", self.frame().block); + info!("// {:?}", self.frame().block); } Ok(()) } From 885cf2a2afd6da270287cfc3bfa651ac737d0378 Mon Sep 17 00:00:00 2001 From: Vardhan Thigle Date: Fri, 14 Dec 2018 18:38:15 +0530 Subject: [PATCH 45/84] Adding unwinding support for x86_64_fortanix_unknown_sgx target. --- src/libpanic_unwind/lib.rs | 2 +- .../spec/x86_64_fortanix_unknown_sgx.rs | 46 +++--- src/libstd/sys/sgx/abi/entry.S | 8 + src/libstd/sys/sgx/rwlock.rs | 137 +++++++++++++++++- src/libunwind/lib.rs | 5 +- 5 files changed, 168 insertions(+), 30 deletions(-) diff --git a/src/libpanic_unwind/lib.rs b/src/libpanic_unwind/lib.rs index 49f8a429126b7..cfe671c626bcf 100644 --- a/src/libpanic_unwind/lib.rs +++ b/src/libpanic_unwind/lib.rs @@ -62,7 +62,7 @@ cfg_if! { if #[cfg(target_os = "emscripten")] { #[path = "emcc.rs"] mod imp; - } else if #[cfg(any(target_arch = "wasm32", target_env = "sgx"))] { + } else if #[cfg(target_arch = "wasm32")] { #[path = "dummy.rs"] mod imp; } else if #[cfg(all(target_env = "msvc", target_arch = "aarch64"))] { diff --git a/src/librustc_target/spec/x86_64_fortanix_unknown_sgx.rs b/src/librustc_target/spec/x86_64_fortanix_unknown_sgx.rs index 5b6d8abc5ef3e..6a6aab2bea366 100644 --- a/src/librustc_target/spec/x86_64_fortanix_unknown_sgx.rs +++ b/src/librustc_target/spec/x86_64_fortanix_unknown_sgx.rs @@ -10,28 +10,29 @@ use std::iter; -use super::{LinkerFlavor, Target, TargetOptions, PanicStrategy}; +use super::{LinkerFlavor, PanicStrategy, Target, TargetOptions}; pub fn target() -> Result { const PRE_LINK_ARGS: &[&str] = &[ "-Wl,--as-needed", "-Wl,-z,noexecstack", "-m64", - "-fuse-ld=gold", - "-nostdlib", - "-shared", - "-Wl,-e,sgx_entry", - "-Wl,-Bstatic", - "-Wl,--gc-sections", - "-Wl,-z,text", - "-Wl,-z,norelro", - "-Wl,--rosegment", - "-Wl,--no-undefined", - "-Wl,--error-unresolved-symbols", - "-Wl,--no-undefined-version", - "-Wl,-Bsymbolic", - "-Wl,--export-dynamic", + "-fuse-ld=gold", + "-nostdlib", + "-shared", + "-Wl,-e,sgx_entry", + "-Wl,-Bstatic", + "-Wl,--gc-sections", + "-Wl,-z,text", + "-Wl,-z,norelro", + "-Wl,--rosegment", + "-Wl,--no-undefined", + "-Wl,--error-unresolved-symbols", + "-Wl,--no-undefined-version", + "-Wl,-Bsymbolic", + "-Wl,--export-dynamic", ]; + const EXPORT_SYMBOLS: &[&str] = &[ "sgx_entry", "HEAP_BASE", @@ -41,19 +42,26 @@ pub fn target() -> Result { "ENCLAVE_SIZE", "CFGDATA_BASE", "DEBUG", + "EH_FRM_HDR_BASE", + "EH_FRM_HDR_SIZE", + "TEXT_BASE", + "TEXT_SIZE", ]; let opts = TargetOptions { dynamic_linking: false, executables: true, linker_is_gnu: true, max_atomic_width: Some(64), - panic_strategy: PanicStrategy::Abort, + panic_strategy: PanicStrategy::Unwind, cpu: "x86-64".into(), features: "+rdrnd,+rdseed".into(), position_independent_executables: true, - pre_link_args: iter::once( - (LinkerFlavor::Gcc, PRE_LINK_ARGS.iter().cloned().map(String::from).collect()) - ).collect(), + pre_link_args: iter::once(( + LinkerFlavor::Gcc, + PRE_LINK_ARGS.iter().cloned().map(String::from).collect(), + )) + .collect(), + post_link_objects: vec!["libunwind.a".into()], override_export_symbols: Some(EXPORT_SYMBOLS.iter().cloned().map(String::from).collect()), ..Default::default() }; diff --git a/src/libstd/sys/sgx/abi/entry.S b/src/libstd/sys/sgx/abi/entry.S index 4d5cc02e11e2c..49ede0674ce42 100644 --- a/src/libstd/sys/sgx/abi/entry.S +++ b/src/libstd/sys/sgx/abi/entry.S @@ -56,6 +56,14 @@ IMAGE_BASE: globvar CFGDATA_BASE 8 /* Non-zero if debugging is enabled, zero otherwise */ globvar DEBUG 1 + /* The base address (relative to enclave start) of the enclave text section */ + globvar TEXT_BASE 8 + /* The size in bytes of enclacve text section */ + globvar TEXT_SIZE 8 + /* The base address (relative to enclave start) of the enclave EH_FRM_HDR section */ + globvar EH_FRM_HDR_BASE 8 + /* The size in bytes of enclacve EH_FRM_HDR section */ + globvar EH_FRM_HDR_SIZE 8 .Lreentry_panic_msg: .asciz "Re-entered panicked enclave!" diff --git a/src/libstd/sys/sgx/rwlock.rs b/src/libstd/sys/sgx/rwlock.rs index a1551dbb53b2d..d1af98bd4f525 100644 --- a/src/libstd/sys/sgx/rwlock.rs +++ b/src/libstd/sys/sgx/rwlock.rs @@ -9,14 +9,25 @@ // except according to those terms. use num::NonZeroUsize; +use slice; +use str; -use super::waitqueue::{WaitVariable, WaitQueue, SpinMutex, NotifiedTcs, try_lock_or_false}; +use super::waitqueue::{ + try_lock_or_false, NotifiedTcs, SpinMutex, SpinMutexGuard, WaitQueue, WaitVariable, +}; +use mem; pub struct RWLock { readers: SpinMutex>>, writer: SpinMutex>, } +// Below is to check at compile time, that RWLock has size of 128 bytes. +#[allow(dead_code)] +unsafe fn rw_lock_size_assert(r: RWLock) { + mem::transmute::(r); +} + //unsafe impl Send for RWLock {} //unsafe impl Sync for RWLock {} // FIXME @@ -24,7 +35,7 @@ impl RWLock { pub const fn new() -> RWLock { RWLock { readers: SpinMutex::new(WaitVariable::new(None)), - writer: SpinMutex::new(WaitVariable::new(false)) + writer: SpinMutex::new(WaitVariable::new(false)), } } @@ -89,9 +100,11 @@ impl RWLock { } #[inline] - pub unsafe fn read_unlock(&self) { - let mut rguard = self.readers.lock(); - let wguard = self.writer.lock(); + unsafe fn __read_unlock( + &self, + mut rguard: SpinMutexGuard>>, + wguard: SpinMutexGuard>, + ) { *rguard.lock_var_mut() = NonZeroUsize::new(rguard.lock_var().unwrap().get() - 1); if rguard.lock_var().is_some() { // There are other active readers @@ -107,9 +120,18 @@ impl RWLock { } #[inline] - pub unsafe fn write_unlock(&self) { + pub unsafe fn read_unlock(&self) { let rguard = self.readers.lock(); let wguard = self.writer.lock(); + self.__read_unlock(rguard, wguard); + } + + #[inline] + unsafe fn __write_unlock( + &self, + rguard: SpinMutexGuard>>, + wguard: SpinMutexGuard>, + ) { if let Err(mut wguard) = WaitQueue::notify_one(wguard) { // No writers waiting, release the write lock *wguard.lock_var_mut() = false; @@ -128,6 +150,109 @@ impl RWLock { } } + #[inline] + pub unsafe fn write_unlock(&self) { + let rguard = self.readers.lock(); + let wguard = self.writer.lock(); + self.__write_unlock(rguard, wguard); + } + + #[inline] + unsafe fn unlock(&self) { + let rguard = self.readers.lock(); + let wguard = self.writer.lock(); + if *wguard.lock_var() == true { + self.__write_unlock(rguard, wguard); + } else { + self.__read_unlock(rguard, wguard); + } + } + #[inline] pub unsafe fn destroy(&self) {} } + +const EINVAL: i32 = 22; + +#[no_mangle] +pub unsafe extern "C" fn __rust_rwlock_rdlock(p: *mut RWLock) -> i32 { + if p.is_null() { + return EINVAL; + } + (*p).read(); + return 0; +} + +#[no_mangle] +pub unsafe extern "C" fn __rust_rwlock_wrlock(p: *mut RWLock) -> i32 { + if p.is_null() { + return EINVAL; + } + (*p).write(); + return 0; +} +#[no_mangle] +pub unsafe extern "C" fn __rust_rwlock_unlock(p: *mut RWLock) -> i32 { + if p.is_null() { + return EINVAL; + } + (*p).unlock(); + return 0; +} + +#[no_mangle] +pub unsafe extern "C" fn __rust_print_err(m: *mut u8, s: i32) { + if s < 0 { + return; + } + let buf = slice::from_raw_parts(m as *const u8, s as _); + if let Ok(s) = str::from_utf8(&buf[..buf.iter().position(|&b| b == 0).unwrap_or(buf.len())]) { + eprint!("{}", s); + } +} + +#[no_mangle] +pub unsafe extern "C" fn __rust_abort() { + ::sys::abort_internal(); +} + +#[cfg(test)] +mod tests { + + use super::*; + use core::array::FixedSizeArray; + use mem::MaybeUninit; + use {mem, ptr}; + + // The below test verifies that the bytes of initialized RWLock are the ones + // we use in libunwind. + // If they change we need to update src/UnwindRustSgx.h in libunwind. + #[test] + fn test_c_rwlock_initializer() { + const RWLOCK_INIT: &[u8] = &[ + 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + ]; + + let mut init = MaybeUninit::::zeroed(); + init.set(RWLock::new()); + assert_eq!( + mem::transmute::<_, [u8; 128]>(init.into_inner()).as_slice(), + RWLOCK_INIT + ); + } +} diff --git a/src/libunwind/lib.rs b/src/libunwind/lib.rs index eb53332ab3302..954eb9d6d03ba 100644 --- a/src/libunwind/lib.rs +++ b/src/libunwind/lib.rs @@ -26,10 +26,7 @@ mod macros; cfg_if! { if #[cfg(target_env = "msvc")] { // no extra unwinder support needed - } else if #[cfg(any( - all(target_arch = "wasm32", not(target_os = "emscripten")), - target_env = "sgx" - ))] { + } else if #[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))] { // no unwinder on the system! } else { extern crate libc; From 81a45e20385009db9b964be3ed18801477f0a3dc Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 19 Dec 2018 14:11:01 +0100 Subject: [PATCH 46/84] miri: allocation is infallible --- src/librustc_mir/const_eval.rs | 6 +++--- src/librustc_mir/interpret/machine.rs | 2 +- src/librustc_mir/interpret/memory.rs | 10 +++++----- src/librustc_mir/interpret/operand.rs | 2 +- src/librustc_mir/interpret/place.rs | 12 ++++++------ src/librustc_mir/interpret/traits.rs | 2 +- src/librustc_mir/transform/const_prop.rs | 2 +- 7 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs index 248c5d2db4917..6e0f1c8b80c32 100644 --- a/src/librustc_mir/const_eval.rs +++ b/src/librustc_mir/const_eval.rs @@ -187,7 +187,7 @@ fn eval_body_using_ecx<'mir, 'tcx>( } let layout = ecx.layout_of(mir.return_ty().subst(tcx, cid.instance.substs))?; assert!(!layout.is_unsized()); - let ret = ecx.allocate(layout, MemoryKind::Stack)?; + let ret = ecx.allocate(layout, MemoryKind::Stack); let name = ty::tls::with(|tcx| tcx.item_path_str(cid.instance.def_id())); let prom = cid.promoted.map_or(String::new(), |p| format!("::promoted[{:?}]", p)); @@ -490,8 +490,8 @@ impl<'a, 'mir, 'tcx> interpret::Machine<'a, 'mir, 'tcx> _ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>, ptr: Pointer, _kind: MemoryKind, - ) -> EvalResult<'tcx, Pointer> { - Ok(ptr) + ) -> Pointer { + ptr } #[inline(always)] diff --git a/src/librustc_mir/interpret/machine.rs b/src/librustc_mir/interpret/machine.rs index 4c7aa887045c7..74b633d67956e 100644 --- a/src/librustc_mir/interpret/machine.rs +++ b/src/librustc_mir/interpret/machine.rs @@ -185,7 +185,7 @@ pub trait Machine<'a, 'mir, 'tcx>: Sized { ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>, ptr: Pointer, kind: MemoryKind, - ) -> EvalResult<'tcx, Pointer>; + ) -> Pointer; /// Executed when evaluating the `*` operator: Following a reference. /// This has the chance to adjust the tag. It should not change anything else! diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index 420fe26426321..ddecdd44347f6 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -131,10 +131,10 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { &mut self, alloc: Allocation, kind: MemoryKind, - ) -> EvalResult<'tcx, AllocId> { + ) -> AllocId { let id = self.tcx.alloc_map.lock().reserve(); self.alloc_map.insert(id, (kind, alloc)); - Ok(id) + id } pub fn allocate( @@ -142,9 +142,9 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { size: Size, align: Align, kind: MemoryKind, - ) -> EvalResult<'tcx, Pointer> { + ) -> Pointer { let extra = AllocationExtra::memory_allocated(size, &self.extra); - Ok(Pointer::from(self.allocate_with(Allocation::undef(size, align, extra), kind)?)) + Pointer::from(self.allocate_with(Allocation::undef(size, align, extra), kind)) } pub fn reallocate( @@ -162,7 +162,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { // For simplicities' sake, we implement reallocate as "alloc, copy, dealloc". // This happens so rarely, the perf advantage is outweighed by the maintenance cost. - let new_ptr = self.allocate(new_size, new_align, kind)?; + let new_ptr = self.allocate(new_size, new_align, kind); self.copy( ptr.into(), old_align, diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs index 83ceadada65ce..7143d66ad9246 100644 --- a/src/librustc_mir/interpret/operand.rs +++ b/src/librustc_mir/interpret/operand.rs @@ -382,7 +382,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> _ => { trace!("Forcing allocation for local of type {:?}", layout.ty); Operand::Indirect( - *self.allocate(layout, MemoryKind::Stack)? + *self.allocate(layout, MemoryKind::Stack) ) } }) diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs index bae670bf2b4b3..e316b54f8ca7d 100644 --- a/src/librustc_mir/interpret/place.rs +++ b/src/librustc_mir/interpret/place.rs @@ -911,7 +911,7 @@ where // that might e.g., be an inner field of a struct with `Scalar` layout, // that has different alignment than the outer field. let local_layout = self.layout_of_local(&self.stack[frame], local)?; - let ptr = self.allocate(local_layout, MemoryKind::Stack)?; + let ptr = self.allocate(local_layout, MemoryKind::Stack); // We don't have to validate as we can assume the local // was already valid for its type. self.write_immediate_to_mplace_no_validate(value, ptr)?; @@ -933,15 +933,15 @@ where &mut self, layout: TyLayout<'tcx>, kind: MemoryKind, - ) -> EvalResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> { + ) -> MPlaceTy<'tcx, M::PointerTag> { if layout.is_unsized() { assert!(self.tcx.features().unsized_locals, "cannot alloc memory for unsized type"); // FIXME: What should we do here? We should definitely also tag! - Ok(MPlaceTy::dangling(layout, self)) + MPlaceTy::dangling(layout, self) } else { - let ptr = self.memory.allocate(layout.size, layout.align.abi, kind)?; - let ptr = M::tag_new_allocation(self, ptr, kind)?; - Ok(MPlaceTy::from_aligned_ptr(ptr, layout)) + let ptr = self.memory.allocate(layout.size, layout.align.abi, kind); + let ptr = M::tag_new_allocation(self, ptr, kind); + MPlaceTy::from_aligned_ptr(ptr, layout) } } diff --git a/src/librustc_mir/interpret/traits.rs b/src/librustc_mir/interpret/traits.rs index bda585b8eda34..22936a9b0a0cf 100644 --- a/src/librustc_mir/interpret/traits.rs +++ b/src/librustc_mir/interpret/traits.rs @@ -54,7 +54,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> ptr_size * (3 + methods.len() as u64), ptr_align, MemoryKind::Vtable, - )?.with_default_tag(); + ).with_default_tag(); let tcx = &*self.tcx; let drop = ::monomorphize::resolve_drop_in_place(*tcx, ty); diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index acae03f7f94f5..cfa899eb5a62a 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -346,7 +346,7 @@ impl<'a, 'mir, 'tcx> ConstPropagator<'a, 'mir, 'tcx> { Rvalue::Cast(kind, ref operand, _) => { let (op, span) = self.eval_operand(operand, source_info)?; self.use_ecx(source_info, |this| { - let dest = this.ecx.allocate(place_layout, MemoryKind::Stack)?; + let dest = this.ecx.allocate(place_layout, MemoryKind::Stack); this.ecx.cast(op, kind, dest.into())?; Ok((dest.into(), span)) }) From 818ed6935dc10f450f5c230b19465b1a323b07ea Mon Sep 17 00:00:00 2001 From: ljedrz Date: Wed, 19 Dec 2018 16:39:01 +0100 Subject: [PATCH 47/84] dropck: simplify common patterns --- src/librustc/traits/query/dropck_outlives.rs | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/librustc/traits/query/dropck_outlives.rs b/src/librustc/traits/query/dropck_outlives.rs index b8bf0fcc15307..b993dd6080bb6 100644 --- a/src/librustc/traits/query/dropck_outlives.rs +++ b/src/librustc/traits/query/dropck_outlives.rs @@ -55,8 +55,8 @@ impl<'cx, 'gcx, 'tcx> At<'cx, 'gcx, 'tcx> { let c_ty = self.infcx.canonicalize_query(&self.param_env.and(ty), &mut orig_values); let span = self.cause.span; debug!("c_ty = {:?}", c_ty); - match &gcx.dropck_outlives(c_ty) { - Ok(result) if result.is_proven() => { + if let Ok(result) = &gcx.dropck_outlives(c_ty) { + if result.is_proven() { if let Ok(InferOk { value, obligations }) = self.infcx.instantiate_query_response_and_region_obligations( self.cause, @@ -72,8 +72,6 @@ impl<'cx, 'gcx, 'tcx> At<'cx, 'gcx, 'tcx> { }; } } - - _ => { /* fallthrough to error-handling code below */ } } // Errors and ambiuity in dropck occur in two cases: @@ -82,10 +80,11 @@ impl<'cx, 'gcx, 'tcx> At<'cx, 'gcx, 'tcx> { // Either of these should have created an error before. tcx.sess .delay_span_bug(span, "dtorck encountered internal error"); - return InferOk { + + InferOk { value: vec![], obligations: vec![], - }; + } } } @@ -102,7 +101,7 @@ impl<'tcx> DropckOutlivesResult<'tcx> { span: Span, ty: Ty<'tcx>, ) { - for overflow_ty in self.overflows.iter().take(1) { + if let Some(overflow_ty) = self.overflows.iter().next() { let mut err = struct_span_err!( tcx.sess, span, From ae3f6b015ec3f76e2d784fe7cb23b8bbb91faa43 Mon Sep 17 00:00:00 2001 From: ljedrz Date: Wed, 19 Dec 2018 16:41:15 +0100 Subject: [PATCH 48/84] dropck: remove unnecessary call to cloned() --- src/librustc/traits/query/dropck_outlives.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc/traits/query/dropck_outlives.rs b/src/librustc/traits/query/dropck_outlives.rs index b993dd6080bb6..f506c47371c92 100644 --- a/src/librustc/traits/query/dropck_outlives.rs +++ b/src/librustc/traits/query/dropck_outlives.rs @@ -227,7 +227,7 @@ pub fn trivial_dropck_outlives<'tcx>(tcx: TyCtxt<'_, '_, 'tcx>, ty: Ty<'tcx>) -> // (T1..Tn) and closures have same properties as T1..Tn -- // check if *any* of those are trivial. - ty::Tuple(ref tys) => tys.iter().cloned().all(|t| trivial_dropck_outlives(tcx, t)), + ty::Tuple(ref tys) => tys.iter().all(|t| trivial_dropck_outlives(tcx, t)), ty::Closure(def_id, ref substs) => substs .upvar_tys(def_id, tcx) .all(|t| trivial_dropck_outlives(tcx, t)), From 7eb67c2503eb01079f41a5d176485d9a85a9bb2d Mon Sep 17 00:00:00 2001 From: John Paul Adrian Glaubitz Date: Wed, 19 Dec 2018 17:52:27 +0100 Subject: [PATCH 49/84] test: Ignore ui/target-feature-gate on powerpc and powerpc64(le) --- src/test/ui/target-feature-gate.rs | 3 +++ src/test/ui/target-feature-gate.stderr | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/test/ui/target-feature-gate.rs b/src/test/ui/target-feature-gate.rs index 4207a3285c48c..9a82f2b05325f 100644 --- a/src/test/ui/target-feature-gate.rs +++ b/src/test/ui/target-feature-gate.rs @@ -14,6 +14,9 @@ // ignore-emscripten // ignore-mips // ignore-mips64 +// ignore-powerpc +// ignore-powerpc64 +// ignore-powerpc64le // gate-test-sse4a_target_feature // gate-test-powerpc_target_feature // gate-test-avx512_target_feature diff --git a/src/test/ui/target-feature-gate.stderr b/src/test/ui/target-feature-gate.stderr index 54589536010ae..d7c2eb8c5f0a7 100644 --- a/src/test/ui/target-feature-gate.stderr +++ b/src/test/ui/target-feature-gate.stderr @@ -1,5 +1,5 @@ error[E0658]: the target feature `avx512bw` is currently unstable (see issue #44839) - --> $DIR/target-feature-gate.rs:31:18 + --> $DIR/target-feature-gate.rs:34:18 | LL | #[target_feature(enable = "avx512bw")] | ^^^^^^^^^^^^^^^^^^^ From a153d485fe9fbd0dd4f16c0dfa29bf5d75cd63df Mon Sep 17 00:00:00 2001 From: John Paul Adrian Glaubitz Date: Wed, 19 Dec 2018 17:53:03 +0100 Subject: [PATCH 50/84] test: Ignore ui/target-feature-gate on sparc and sparc64 --- src/test/ui/target-feature-gate.rs | 2 ++ src/test/ui/target-feature-gate.stderr | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/test/ui/target-feature-gate.rs b/src/test/ui/target-feature-gate.rs index 9a82f2b05325f..cb0938b861c05 100644 --- a/src/test/ui/target-feature-gate.rs +++ b/src/test/ui/target-feature-gate.rs @@ -17,6 +17,8 @@ // ignore-powerpc // ignore-powerpc64 // ignore-powerpc64le +// ignore-sparc +// ignore-sparc64 // gate-test-sse4a_target_feature // gate-test-powerpc_target_feature // gate-test-avx512_target_feature diff --git a/src/test/ui/target-feature-gate.stderr b/src/test/ui/target-feature-gate.stderr index d7c2eb8c5f0a7..d7154324d12fe 100644 --- a/src/test/ui/target-feature-gate.stderr +++ b/src/test/ui/target-feature-gate.stderr @@ -1,5 +1,5 @@ error[E0658]: the target feature `avx512bw` is currently unstable (see issue #44839) - --> $DIR/target-feature-gate.rs:34:18 + --> $DIR/target-feature-gate.rs:36:18 | LL | #[target_feature(enable = "avx512bw")] | ^^^^^^^^^^^^^^^^^^^ From 036ce5cdc4a2cd5c0bdfaa83ed3ce64644bbdcde Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Wed, 19 Dec 2018 19:41:22 +0100 Subject: [PATCH 51/84] Fix compiletest `trim` deprecation warnings --- src/tools/compiletest/src/header.rs | 10 +++++----- src/tools/compiletest/src/runtest.rs | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index 8b3023e63dfb4..4e25e3a77110a 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -205,7 +205,7 @@ impl EarlyProps { fn ignore_lldb(config: &Config, line: &str) -> bool { if let Some(ref actual_version) = config.lldb_version { if line.starts_with("min-lldb-version") { - let min_version = line.trim_right() + let min_version = line.trim_end() .rsplit(' ') .next() .expect("Malformed lldb version directive"); @@ -228,7 +228,7 @@ impl EarlyProps { } if let Some(ref actual_version) = config.llvm_version { if line.starts_with("min-llvm-version") { - let min_version = line.trim_right() + let min_version = line.trim_end() .rsplit(' ') .next() .expect("Malformed llvm version directive"); @@ -236,7 +236,7 @@ impl EarlyProps { // version &actual_version[..] < min_version } else if line.starts_with("min-system-llvm-version") { - let min_version = line.trim_right() + let min_version = line.trim_end() .rsplit(' ') .next() .expect("Malformed llvm version directive"); @@ -573,14 +573,14 @@ fn iter_header(testfile: &Path, cfg: Option<&str>, it: &mut dyn FnMut(&str)) { None => false, }; if matches { - it(ln[(close_brace + 1)..].trim_left()); + it(ln[(close_brace + 1)..].trim_start()); } } else { panic!("malformed condition directive: expected `{}foo]`, found `{}`", comment_with_brace, ln) } } else if ln.starts_with(comment) { - it(ln[comment.len() ..].trim_left()); + it(ln[comment.len() ..].trim_start()); } } return; diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 45527a7cce535..cddaf93b67132 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -1079,7 +1079,7 @@ impl<'test> TestCx<'test> { match line { Ok(line) => { let line = if line.starts_with("//") { - line[2..].trim_left() + line[2..].trim_start() } else { line.as_str() }; @@ -2143,8 +2143,8 @@ impl<'test> TestCx<'test> { .lines() .enumerate() .filter_map(|(line_nb, line)| { - if (line.trim_left().starts_with("pub mod ") - || line.trim_left().starts_with("mod ")) + if (line.trim_start().starts_with("pub mod ") + || line.trim_start().starts_with("mod ")) && line.ends_with(';') { if let Some(ref mut other_files) = other_files { @@ -2153,7 +2153,7 @@ impl<'test> TestCx<'test> { None } else { let sline = line.split("///").last().unwrap_or(""); - let line = sline.trim_left(); + let line = sline.trim_start(); if line.starts_with("```") { if ignore { ignore = false; @@ -3284,7 +3284,7 @@ fn normalize_mir_line(line: &str) -> String { fn nocomment_mir_line(line: &str) -> &str { if let Some(idx) = line.find("//") { let (l, _) = line.split_at(idx); - l.trim_right() + l.trim_end() } else { line } From 0e72c80afe9024ea7824579cd12c428264bb4783 Mon Sep 17 00:00:00 2001 From: Niv Kaminer Date: Mon, 17 Dec 2018 23:45:26 +0200 Subject: [PATCH 52/84] FIXME(9639) remove fixme and accept non-utf8 paths in compiletest --- src/tools/compiletest/src/runtest.rs | 36 ++++++++++++++-------------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 45527a7cce535..8c6e97893fb43 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -27,7 +27,7 @@ use util::{logv, PathBufExt}; use std::collections::hash_map::DefaultHasher; use std::collections::{HashMap, HashSet, VecDeque}; use std::env; -use std::ffi::OsString; +use std::ffi::{OsStr, OsString}; use std::fmt; use std::fs::{self, create_dir_all, File}; use std::hash::{Hash, Hasher}; @@ -760,13 +760,13 @@ impl<'test> TestCx<'test> { } drop(stdout); - let debugger_script = self.make_out_name("debugger.script"); - // FIXME (#9639): This needs to handle non-utf8 paths - let debugger_opts = vec![ - "-quiet".to_owned(), - "-batch".to_owned(), - "-nx".to_owned(), - format!("-command={}", debugger_script.to_str().unwrap()), + let mut debugger_script = OsString::from("-command="); + debugger_script.push(self.make_out_name("debugger.script")); + let debugger_opts: &[&OsStr] = &[ + "-quiet".as_ref(), + "-batch".as_ref(), + "-nx".as_ref(), + &debugger_script, ]; let gdb_path = self.config.gdb.as_ref().unwrap(); @@ -775,12 +775,12 @@ impl<'test> TestCx<'test> { stdout, stderr, } = Command::new(&gdb_path) - .args(&debugger_opts) + .args(debugger_opts) .output() .expect(&format!("failed to exec `{:?}`", gdb_path)); let cmdline = { let mut gdb = Command::new(&format!("{}-gdb", self.config.target)); - gdb.args(&debugger_opts); + gdb.args(debugger_opts); let cmdline = self.make_cmdline(&gdb, ""); logv(self.config, format!("executing {}", cmdline)); cmdline @@ -868,18 +868,18 @@ impl<'test> TestCx<'test> { debug!("script_str = {}", script_str); self.dump_output_file(&script_str, "debugger.script"); - let debugger_script = self.make_out_name("debugger.script"); + let mut debugger_script = OsString::from("-command="); + debugger_script.push(self.make_out_name("debugger.script")); - // FIXME (#9639): This needs to handle non-utf8 paths - let debugger_opts = vec![ - "-quiet".to_owned(), - "-batch".to_owned(), - "-nx".to_owned(), - format!("-command={}", debugger_script.to_str().unwrap()), + let debugger_opts: &[&OsStr] = &[ + "-quiet".as_ref(), + "-batch".as_ref(), + "-nx".as_ref(), + &debugger_script, ]; let mut gdb = Command::new(self.config.gdb.as_ref().unwrap()); - gdb.args(&debugger_opts) + gdb.args(debugger_opts) .env("PYTHONPATH", rust_pp_module_abs_path); debugger_run_result = self.compose_and_run( From 7894717e91ec8a01681bc38ca2273b91037e1ece Mon Sep 17 00:00:00 2001 From: Niv Kaminer Date: Wed, 19 Dec 2018 19:03:05 +0200 Subject: [PATCH 53/84] FIXME(9639) remove fixme and accept non-utf8 paths in librustdoc --- src/librustdoc/html/render.rs | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 46002c089cf9f..6da1471c6a687 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -1232,10 +1232,8 @@ fn write_minify_replacer(dst: &mut W, /// static HTML tree. Each component in the cleaned path will be passed as an /// argument to `f`. The very last component of the path (ie the file name) will /// be passed to `f` if `keep_filename` is true, and ignored otherwise. -// FIXME (#9639): The closure should deal with &[u8] instead of &str -// FIXME (#9639): This is too conservative, rejecting non-UTF-8 paths fn clean_srcpath(src_root: &Path, p: &Path, keep_filename: bool, mut f: F) where - F: FnMut(&str), + F: FnMut(&OsStr), { // make it relative, if possible let p = p.strip_prefix(src_root).unwrap_or(p); @@ -1248,8 +1246,8 @@ fn clean_srcpath(src_root: &Path, p: &Path, keep_filename: bool, mut f: F) wh } match c { - Component::ParentDir => f("up"), - Component::Normal(c) => f(c.to_str().unwrap()), + Component::ParentDir => f("up".as_ref()), + Component::Normal(c) => f(c), _ => continue, } } @@ -1348,7 +1346,7 @@ impl<'a> SourceCollector<'a> { cur.push(component); fs::create_dir_all(&cur).unwrap(); root_path.push_str("../"); - href.push_str(component); + href.push_str(&component.to_string_lossy()); href.push('/'); }); let mut fname = p.file_name() @@ -2227,7 +2225,7 @@ impl<'a> Item<'a> { }; clean_srcpath(&src_root, file, false, |component| { - path.push_str(component); + path.push_str(&component.to_string_lossy()); path.push('/'); }); let mut fname = file.file_name().expect("source has no filename") From 90726e1ac17a91d07ca5749ade718239f439d1bd Mon Sep 17 00:00:00 2001 From: Andy Russell Date: Wed, 19 Dec 2018 13:51:52 -0500 Subject: [PATCH 54/84] suggest similar lint names for unknown lints --- src/librustc/lint/context.rs | 30 ++++++++++++++----- src/librustc/lint/levels.rs | 27 +++++++---------- src/test/ui/lint/lint-unknown-lint-cmdline.rs | 7 +++-- .../ui/lint/lint-unknown-lint-cmdline.stderr | 7 ++++- src/test/ui/lint/lint-unknown-lint.rs | 12 ++++++-- src/test/ui/lint/lint-unknown-lint.stderr | 29 ++++++++---------- src/test/ui/lint/not_found.stderr | 4 +-- 7 files changed, 69 insertions(+), 47 deletions(-) diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index 449f8e0a2db67..131dedb988832 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -42,11 +42,12 @@ use util::nodemap::FxHashMap; use std::default::Default as StdDefault; use syntax::ast; use syntax::edition; -use syntax_pos::{MultiSpan, Span, symbol::LocalInternedString}; +use syntax_pos::{MultiSpan, Span, symbol::{LocalInternedString, Symbol}}; use errors::DiagnosticBuilder; use hir; use hir::def_id::LOCAL_CRATE; use hir::intravisit as hir_visit; +use syntax::util::lev_distance::find_best_match_for_name; use syntax::visit as ast_visit; /// Information about the registered lints. @@ -139,8 +140,8 @@ struct LintGroup { pub enum CheckLintNameResult<'a> { Ok(&'a [LintId]), - /// Lint doesn't exist - NoLint, + /// Lint doesn't exist. Potentially contains a suggestion for a correct lint name. + NoLint(Option), /// The lint is either renamed or removed. This is the warning /// message, and an optional new name (`None` if removed). Warning(String, Option), @@ -359,8 +360,14 @@ impl LintStore { CheckLintNameResult::Warning(ref msg, _) => { Some(sess.struct_warn(msg)) }, - CheckLintNameResult::NoLint => { - Some(struct_err!(sess, E0602, "unknown lint: `{}`", lint_name)) + CheckLintNameResult::NoLint(suggestion) => { + let mut err = struct_err!(sess, E0602, "unknown lint: `{}`", lint_name); + + if let Some(suggestion) = suggestion { + err.help(&format!("did you mean: `{}`", suggestion)); + } + + Some(err) } CheckLintNameResult::Tool(result) => match result { Err((Some(_), new_name)) => Some(sess.struct_warn(&format!( @@ -464,7 +471,16 @@ impl LintStore { match self.by_name.get(&complete_name) { None => match self.lint_groups.get(&*complete_name) { // Now we are sure, that this lint exists nowhere - None => CheckLintNameResult::NoLint, + None => { + let symbols = self.by_name.keys() + .map(|name| Symbol::intern(&name)) + .collect::>(); + + let suggestion = + find_best_match_for_name(symbols.iter(), &lint_name.to_lowercase(), None); + + CheckLintNameResult::NoLint(suggestion) + } Some(LintGroup { lint_ids, depr, .. }) => { // Reaching this would be weird, but let's cover this case anyway if let Some(LintAlias { name, silent }) = depr { @@ -484,7 +500,7 @@ impl LintStore { Some(&Id(ref id)) => { CheckLintNameResult::Tool(Err((Some(slice::from_ref(id)), complete_name))) } - _ => CheckLintNameResult::NoLint, + _ => CheckLintNameResult::NoLint(None), } } } diff --git a/src/librustc/lint/levels.rs b/src/librustc/lint/levels.rs index 06e3e0bab4f10..9ab8e89df72e6 100644 --- a/src/librustc/lint/levels.rs +++ b/src/librustc/lint/levels.rs @@ -385,7 +385,7 @@ impl<'a> LintLevelsBuilder<'a> { } err.emit(); } - CheckLintNameResult::NoLint => { + CheckLintNameResult::NoLint(suggestion) => { let lint = builtin::UNKNOWN_LINTS; let (level, src) = self.sets.get_lint_level(lint, self.cur, @@ -398,22 +398,17 @@ impl<'a> LintLevelsBuilder<'a> { src, Some(li.span.into()), &msg); - if name.as_str().chars().any(|c| c.is_uppercase()) { - let name_lower = name.as_str().to_lowercase().to_string(); - if let CheckLintNameResult::NoLint = - store.check_lint_name(&name_lower, tool_name) { - db.emit(); - } else { - db.span_suggestion_with_applicability( - li.span, - "lowercase the lint name", - name_lower, - Applicability::MachineApplicable - ).emit(); - } - } else { - db.emit(); + + if let Some(suggestion) = suggestion { + db.span_suggestion_with_applicability( + li.span, + "did you mean", + suggestion.to_string(), + Applicability::MachineApplicable, + ); } + + db.emit(); } } } diff --git a/src/test/ui/lint/lint-unknown-lint-cmdline.rs b/src/test/ui/lint/lint-unknown-lint-cmdline.rs index 0c41959f8a710..33fb46dce6e38 100644 --- a/src/test/ui/lint/lint-unknown-lint-cmdline.rs +++ b/src/test/ui/lint/lint-unknown-lint-cmdline.rs @@ -8,9 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags:-D bogus +// compile-flags:-D bogus -D dead_cod -// error-pattern:unknown lint +// error-pattern:unknown lint: `bogus` // error-pattern:requested on the command line with `-D bogus` +// error-pattern:unknown lint: `dead_cod` +// error-pattern:requested on the command line with `-D dead_cod` +// error-pattern:did you mean: `dead_code` fn main() { } diff --git a/src/test/ui/lint/lint-unknown-lint-cmdline.stderr b/src/test/ui/lint/lint-unknown-lint-cmdline.stderr index 8636004102618..58fdae3333ca1 100644 --- a/src/test/ui/lint/lint-unknown-lint-cmdline.stderr +++ b/src/test/ui/lint/lint-unknown-lint-cmdline.stderr @@ -2,6 +2,11 @@ error[E0602]: unknown lint: `bogus` | = note: requested on the command line with `-D bogus` -error: aborting due to previous error +error[E0602]: unknown lint: `dead_cod` + | + = help: did you mean: `dead_code` + = note: requested on the command line with `-D dead_cod` + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0602`. diff --git a/src/test/ui/lint/lint-unknown-lint.rs b/src/test/ui/lint/lint-unknown-lint.rs index 2de8d849d1915..5d3fd0f19721f 100644 --- a/src/test/ui/lint/lint-unknown-lint.rs +++ b/src/test/ui/lint/lint-unknown-lint.rs @@ -8,6 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![allow(not_a_real_lint)] //~ WARN unknown lint -#![deny(unused)] -fn main() { let unused = (); } //~ ERROR unused variable +#![deny(unknown_lints)] + +#![allow(not_a_real_lint)] //~ ERROR unknown lint + +#![deny(dead_cod)] //~ ERROR unknown lint + //~| HELP did you mean + //~| SUGGESTION dead_code + +fn main() {} diff --git a/src/test/ui/lint/lint-unknown-lint.stderr b/src/test/ui/lint/lint-unknown-lint.stderr index b398a2f3690fb..6fc2da39a7c60 100644 --- a/src/test/ui/lint/lint-unknown-lint.stderr +++ b/src/test/ui/lint/lint-unknown-lint.stderr @@ -1,23 +1,20 @@ -warning: unknown lint: `not_a_real_lint` - --> $DIR/lint-unknown-lint.rs:11:10 +error: unknown lint: `not_a_real_lint` + --> $DIR/lint-unknown-lint.rs:13:10 | -LL | #![allow(not_a_real_lint)] //~ WARN unknown lint +LL | #![allow(not_a_real_lint)] //~ ERROR unknown lint | ^^^^^^^^^^^^^^^ | - = note: #[warn(unknown_lints)] on by default - -error: unused variable: `unused` - --> $DIR/lint-unknown-lint.rs:13:17 - | -LL | fn main() { let unused = (); } //~ ERROR unused variable - | ^^^^^^ help: consider using `_unused` instead - | note: lint level defined here - --> $DIR/lint-unknown-lint.rs:12:9 + --> $DIR/lint-unknown-lint.rs:11:9 + | +LL | #![deny(unknown_lints)] + | ^^^^^^^^^^^^^ + +error: unknown lint: `dead_cod` + --> $DIR/lint-unknown-lint.rs:15:9 | -LL | #![deny(unused)] - | ^^^^^^ - = note: #[deny(unused_variables)] implied by #[deny(unused)] +LL | #![deny(dead_cod)] //~ ERROR unknown lint + | ^^^^^^^^ help: did you mean: `dead_code` -error: aborting due to previous error +error: aborting due to 2 previous errors diff --git a/src/test/ui/lint/not_found.stderr b/src/test/ui/lint/not_found.stderr index 603b5410444cd..dedbc829913a5 100644 --- a/src/test/ui/lint/not_found.stderr +++ b/src/test/ui/lint/not_found.stderr @@ -10,11 +10,11 @@ warning: unknown lint: `DEAD_CODE` --> $DIR/not_found.rs:18:8 | LL | #[warn(DEAD_CODE)] - | ^^^^^^^^^ help: lowercase the lint name: `dead_code` + | ^^^^^^^^^ help: did you mean: `dead_code` warning: unknown lint: `Warnings` --> $DIR/not_found.rs:20:8 | LL | #[deny(Warnings)] - | ^^^^^^^^ help: lowercase the lint name: `warnings` + | ^^^^^^^^ help: did you mean: `warnings` From e7c5146c5d801c020f13c81b8b550f465c33d03a Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 20 Dec 2018 09:50:14 +1100 Subject: [PATCH 55/84] Remove `TokenStream::JointTree`. This is done by adding a new `IsJoint` field to `TokenStream::Tree`, which simplifies a lot of `match` statements. And likewise for `CursorKind`. The commit also adds a new method `TokenTree:stream()` which can replace a choice between `.into()` and `.joint()`. --- src/libsyntax/parse/lexer/tokentrees.rs | 5 +- src/libsyntax/tokenstream.rs | 93 +++++++++++-------------- src/libsyntax_ext/proc_macro_server.rs | 8 +-- 3 files changed, 46 insertions(+), 60 deletions(-) diff --git a/src/libsyntax/parse/lexer/tokentrees.rs b/src/libsyntax/parse/lexer/tokentrees.rs index 0906c25cab361..72abcb03410ec 100644 --- a/src/libsyntax/parse/lexer/tokentrees.rs +++ b/src/libsyntax/parse/lexer/tokentrees.rs @@ -11,7 +11,7 @@ use print::pprust::token_to_string; use parse::lexer::StringReader; use parse::{token, PResult}; -use tokenstream::{DelimSpan, TokenStream, TokenTree}; +use tokenstream::{DelimSpan, IsJoint::*, TokenStream, TokenTree}; impl<'a> StringReader<'a> { // Parse a stream of tokens into a list of `TokenTree`s, up to an `Eof`. @@ -178,8 +178,7 @@ impl<'a> StringReader<'a> { let raw = self.span_src_raw; self.real_token(); let is_joint = raw.hi() == self.span_src_raw.lo() && token::is_op(&self.token); - - Ok(if is_joint { tt.joint() } else { tt.into() }) + Ok(TokenStream::Tree(tt, if is_joint { Joint } else { NonJoint })) } } } diff --git a/src/libsyntax/tokenstream.rs b/src/libsyntax/tokenstream.rs index c11ef33f931d8..620035413a553 100644 --- a/src/libsyntax/tokenstream.rs +++ b/src/libsyntax/tokenstream.rs @@ -123,7 +123,7 @@ impl TokenTree { } pub fn joint(self) -> TokenStream { - TokenStream::JointTree(self) + TokenStream::Tree(self, Joint) } /// Returns the opening delimiter as a token tree. @@ -156,8 +156,7 @@ impl TokenTree { #[derive(Clone, Debug)] pub enum TokenStream { Empty, - Tree(TokenTree), - JointTree(TokenTree), + Tree(TokenTree, IsJoint), Stream(Lrc>), } @@ -165,6 +164,14 @@ pub enum TokenStream { #[cfg(target_arch = "x86_64")] static_assert!(MEM_SIZE_OF_TOKEN_STREAM: mem::size_of::() == 32); +#[derive(Clone, Copy, Debug, PartialEq)] +pub enum IsJoint { + Joint, + NonJoint +} + +use self::IsJoint::*; + impl TokenStream { /// Given a `TokenStream` with a `Stream` of only two arguments, return a new `TokenStream` /// separating the two arguments with a comma for diagnostic suggestions. @@ -176,16 +183,16 @@ impl TokenStream { while let Some((pos, ts)) = iter.next() { if let Some((_, next)) = iter.peek() { let sp = match (&ts, &next) { - (TokenStream::Tree(TokenTree::Token(_, token::Token::Comma)), _) | - (_, TokenStream::Tree(TokenTree::Token(_, token::Token::Comma))) => { - continue; - } - (TokenStream::Tree(TokenTree::Token(sp, _)), _) => *sp, - (TokenStream::Tree(TokenTree::Delimited(sp, ..)), _) => sp.entire(), + (TokenStream::Tree(TokenTree::Token(_, token::Token::Comma), NonJoint), _) | + (_, TokenStream::Tree(TokenTree::Token(_, token::Token::Comma), NonJoint)) + => continue, + (TokenStream::Tree(TokenTree::Token(sp, _), NonJoint), _) => *sp, + (TokenStream::Tree(TokenTree::Delimited(sp, ..), NonJoint), _) => + sp.entire(), _ => continue, }; let sp = sp.shrink_to_hi(); - let comma = TokenStream::Tree(TokenTree::Token(sp, token::Comma)); + let comma = TokenStream::Tree(TokenTree::Token(sp, token::Comma), NonJoint); suggestion = Some((pos, comma, sp)); } } @@ -204,7 +211,7 @@ impl TokenStream { impl From for TokenStream { fn from(tt: TokenTree) -> TokenStream { - TokenStream::Tree(tt) + TokenStream::Tree(tt, NonJoint) } } @@ -232,7 +239,7 @@ impl Extend for TokenStream { vec.reserve(iter.size_hint().0); vec } - TokenStream::Tree(_) | TokenStream::JointTree(_) => { + TokenStream::Tree(..) => { let mut vec = Vec::new(); vec.reserve(1 + iter.size_hint().0); vec.push(this); @@ -367,8 +374,7 @@ impl TokenStream { /// Returns true if the token tree is a joint operation w.r.t. `proc_macro::TokenNode`. pub fn as_tree(self) -> (TokenTree, bool /* joint? */) { match self { - TokenStream::Tree(tree) => (tree, false), - TokenStream::JointTree(tree) => (tree, true), + TokenStream::Tree(tree, is_joint) => (tree, is_joint == Joint), _ => unreachable!(), } } @@ -379,8 +385,7 @@ impl TokenStream { let mut i = 0; while let Some(stream) = trees.next_as_stream() { result.push(match stream { - TokenStream::Tree(tree) => f(i, tree).into(), - TokenStream::JointTree(tree) => f(i, tree).joint(), + TokenStream::Tree(tree, is_joint) => TokenStream::Tree(f(i, tree), is_joint), _ => unreachable!() }); i += 1; @@ -393,27 +398,25 @@ impl TokenStream { let mut result = Vec::new(); while let Some(stream) = trees.next_as_stream() { result.push(match stream { - TokenStream::Tree(tree) => f(tree).into(), - TokenStream::JointTree(tree) => f(tree).joint(), + TokenStream::Tree(tree, is_joint) => TokenStream::Tree(f(tree), is_joint), _ => unreachable!() }); } TokenStream::new(result) } - fn first_tree_and_joint(&self) -> Option<(TokenTree, bool)> { + fn first_tree_and_joint(&self) -> Option<(TokenTree, IsJoint)> { match self { TokenStream::Empty => None, - TokenStream::Tree(ref tree) => Some((tree.clone(), false)), - TokenStream::JointTree(ref tree) => Some((tree.clone(), true)), + TokenStream::Tree(ref tree, is_joint) => Some((tree.clone(), *is_joint)), TokenStream::Stream(ref stream) => stream.first().unwrap().first_tree_and_joint(), } } fn last_tree_if_joint(&self) -> Option { match self { - TokenStream::Empty | TokenStream::Tree(..) => None, - TokenStream::JointTree(ref tree) => Some(tree.clone()), + TokenStream::Empty | TokenStream::Tree(_, NonJoint) => None, + TokenStream::Tree(ref tree, Joint) => Some(tree.clone()), TokenStream::Stream(ref stream) => stream.last().unwrap().last_tree_if_joint(), } } @@ -437,11 +440,7 @@ impl TokenStreamBuilder { self.push_all_but_last_tree(&last_stream); let glued_span = last_span.to(span); let glued_tt = TokenTree::Token(glued_span, glued_tok); - let glued_tokenstream = if is_joint { - glued_tt.joint() - } else { - glued_tt.into() - }; + let glued_tokenstream = TokenStream::Tree(glued_tt, is_joint); self.0.push(glued_tokenstream); self.push_all_but_first_tree(&stream); return @@ -491,8 +490,7 @@ pub struct Cursor(CursorKind); #[derive(Clone)] enum CursorKind { Empty, - Tree(TokenTree, bool /* consumed? */), - JointTree(TokenTree, bool /* consumed? */), + Tree(TokenTree, IsJoint, bool /* consumed? */), Stream(StreamCursor), } @@ -514,9 +512,9 @@ impl StreamCursor { self.index += 1; let next = self.stream[self.index - 1].clone(); match next { - TokenStream::Tree(..) | TokenStream::JointTree(..) => return Some(next), - TokenStream::Stream(stream) => self.insert(stream), TokenStream::Empty => {} + TokenStream::Tree(..) => return Some(next), + TokenStream::Stream(stream) => self.insert(stream), } } else if let Some((stream, index)) = self.stack.pop() { self.stream = stream; @@ -538,7 +536,7 @@ impl Iterator for Cursor { fn next(&mut self) -> Option { self.next_as_stream().map(|stream| match stream { - TokenStream::Tree(tree) | TokenStream::JointTree(tree) => tree, + TokenStream::Tree(tree, _) => tree, _ => unreachable!() }) } @@ -548,18 +546,15 @@ impl Cursor { fn new(stream: TokenStream) -> Self { Cursor(match stream { TokenStream::Empty => CursorKind::Empty, - TokenStream::Tree(tree) => CursorKind::Tree(tree, false), - TokenStream::JointTree(tree) => CursorKind::JointTree(tree, false), + TokenStream::Tree(tree, is_joint) => CursorKind::Tree(tree, is_joint, false), TokenStream::Stream(stream) => CursorKind::Stream(StreamCursor::new(stream)), }) } pub fn next_as_stream(&mut self) -> Option { let (stream, consumed) = match self.0 { - CursorKind::Tree(ref tree, ref mut consumed @ false) => - (tree.clone().into(), consumed), - CursorKind::JointTree(ref tree, ref mut consumed @ false) => - (tree.clone().joint(), consumed), + CursorKind::Tree(ref tree, ref is_joint, ref mut consumed @ false) => + (TokenStream::Tree(tree.clone(), *is_joint), consumed), CursorKind::Stream(ref mut cursor) => return cursor.next_as_stream(), _ => return None, }; @@ -572,7 +567,7 @@ impl Cursor { match self.0 { _ if stream.is_empty() => return, CursorKind::Empty => *self = stream.trees(), - CursorKind::Tree(_, consumed) | CursorKind::JointTree(_, consumed) => { + CursorKind::Tree(_, _, consumed) => { *self = TokenStream::new(vec![self.original_stream(), stream]).trees(); if consumed { self.next(); @@ -587,8 +582,8 @@ impl Cursor { pub fn original_stream(&self) -> TokenStream { match self.0 { CursorKind::Empty => TokenStream::empty(), - CursorKind::Tree(ref tree, _) => tree.clone().into(), - CursorKind::JointTree(ref tree, _) => tree.clone().joint(), + CursorKind::Tree(ref tree, ref is_joint, _) => + TokenStream::Tree(tree.clone(), *is_joint), CursorKind::Stream(ref cursor) => TokenStream::Stream( cursor.stack.get(0).cloned().map(|(stream, _)| stream) .unwrap_or_else(|| cursor.stream.clone()) @@ -600,9 +595,8 @@ impl Cursor { fn look_ahead(streams: &[TokenStream], mut n: usize) -> Result { for stream in streams { n = match stream { - TokenStream::Tree(ref tree) | TokenStream::JointTree(ref tree) - if n == 0 => return Ok(tree.clone()), - TokenStream::Tree(..) | TokenStream::JointTree(..) => n - 1, + TokenStream::Tree(ref tree, _) if n == 0 => return Ok(tree.clone()), + TokenStream::Tree(..) => n - 1, TokenStream::Stream(ref stream) => match look_ahead(stream, n) { Ok(tree) => return Ok(tree), Err(n) => n, @@ -615,10 +609,8 @@ impl Cursor { match self.0 { CursorKind::Empty | - CursorKind::Tree(_, true) | - CursorKind::JointTree(_, true) => Err(n), - CursorKind::Tree(ref tree, false) | - CursorKind::JointTree(ref tree, false) => look_ahead(&[tree.clone().into()], n), + CursorKind::Tree(_, _, true) => Err(n), + CursorKind::Tree(ref tree, _, false) => look_ahead(&[tree.clone().into()], n), CursorKind::Stream(ref cursor) => { look_ahead(&cursor.stream[cursor.index ..], n).or_else(|mut n| { for &(ref stream, index) in cursor.stack.iter().rev() { @@ -651,8 +643,7 @@ impl From for ThinTokenStream { fn from(stream: TokenStream) -> ThinTokenStream { ThinTokenStream(match stream { TokenStream::Empty => None, - TokenStream::Tree(tree) => Some(Lrc::new(vec![tree.into()])), - TokenStream::JointTree(tree) => Some(Lrc::new(vec![tree.joint()])), + TokenStream::Tree(..) => Some(Lrc::new(vec![stream])), TokenStream::Stream(stream) => Some(stream), }) } diff --git a/src/libsyntax_ext/proc_macro_server.rs b/src/libsyntax_ext/proc_macro_server.rs index a04d6c92b7817..fa41022b7b675 100644 --- a/src/libsyntax_ext/proc_macro_server.rs +++ b/src/libsyntax_ext/proc_macro_server.rs @@ -21,7 +21,7 @@ use syntax::ast; use syntax::ext::base::ExtCtxt; use syntax::parse::lexer::comments; use syntax::parse::{self, token, ParseSess}; -use syntax::tokenstream::{self, DelimSpan, TokenStream}; +use syntax::tokenstream::{self, DelimSpan, IsJoint::*, TokenStream}; use syntax_pos::hygiene::{SyntaxContext, Transparency}; use syntax_pos::symbol::{keywords, Symbol}; use syntax_pos::{BytePos, FileName, MultiSpan, Pos, SourceFile, Span}; @@ -297,11 +297,7 @@ impl ToInternal for TokenTree { }; let tree = tokenstream::TokenTree::Token(span, token); - if joint { - tree.joint() - } else { - tree.into() - } + TokenStream::Tree(tree, if joint { Joint } else { NonJoint }) } } From 7b6cf6e87b5d0d54687dd56a803d3a86f1994182 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Wed, 19 Dec 2018 22:00:25 -0800 Subject: [PATCH 56/84] Stabilize Vec(Deque)::resize_with Closes #41758 --- src/liballoc/collections/vec_deque.rs | 4 +--- src/liballoc/vec.rs | 4 +--- src/librustc_data_structures/lib.rs | 1 - 3 files changed, 2 insertions(+), 7 deletions(-) diff --git a/src/liballoc/collections/vec_deque.rs b/src/liballoc/collections/vec_deque.rs index 0c5926fbaf1dc..99b1ad8d6e297 100644 --- a/src/liballoc/collections/vec_deque.rs +++ b/src/liballoc/collections/vec_deque.rs @@ -1897,8 +1897,6 @@ impl VecDeque { /// # Examples /// /// ``` - /// #![feature(vec_resize_with)] - /// /// use std::collections::VecDeque; /// /// let mut buf = VecDeque::new(); @@ -1917,7 +1915,7 @@ impl VecDeque { /// buf.resize_with(5, || { state += 1; state }); /// assert_eq!(buf, [5, 10, 101, 102, 103]); /// ``` - #[unstable(feature = "vec_resize_with", issue = "41758")] + #[stable(feature = "vec_resize_with", since = "1.33.0")] pub fn resize_with(&mut self, new_len: usize, generator: impl FnMut()->T) { let len = self.len(); diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index 63af69dda1dce..b78e71331a97f 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -1241,8 +1241,6 @@ impl Vec { /// # Examples /// /// ``` - /// #![feature(vec_resize_with)] - /// /// let mut vec = vec![1, 2, 3]; /// vec.resize_with(5, Default::default); /// assert_eq!(vec, [1, 2, 3, 0, 0]); @@ -1255,7 +1253,7 @@ impl Vec { /// /// [`resize`]: #method.resize /// [`Clone`]: ../../std/clone/trait.Clone.html - #[unstable(feature = "vec_resize_with", issue = "41758")] + #[stable(feature = "vec_resize_with", since = "1.33.0")] pub fn resize_with(&mut self, new_len: usize, f: F) where F: FnMut() -> T { diff --git a/src/librustc_data_structures/lib.rs b/src/librustc_data_structures/lib.rs index bc2b8f1d6523e..9e29b2798d860 100644 --- a/src/librustc_data_structures/lib.rs +++ b/src/librustc_data_structures/lib.rs @@ -28,7 +28,6 @@ #![feature(optin_builtin_traits)] #![feature(nll)] #![feature(allow_internal_unstable)] -#![feature(vec_resize_with)] #![feature(hash_raw_entry)] #![feature(stmt_expr_attributes)] #![feature(core_intrinsics)] From fb18ddaaaa8eeec29bf6fc8684cfceccaa09e064 Mon Sep 17 00:00:00 2001 From: Clar Fon Date: Thu, 13 Dec 2018 23:26:09 -0500 Subject: [PATCH 57/84] Add DoubleEndedIterator::nth_back --- src/libcore/iter/mod.rs | 6 +++ src/libcore/iter/traits.rs | 79 +++++++++++++++++++++++++++++++++++--- src/libcore/tests/iter.rs | 27 +++++++++++++ src/libcore/tests/lib.rs | 1 + 4 files changed, 107 insertions(+), 6 deletions(-) diff --git a/src/libcore/iter/mod.rs b/src/libcore/iter/mod.rs index aa23d49672a0b..e493a3804376f 100644 --- a/src/libcore/iter/mod.rs +++ b/src/libcore/iter/mod.rs @@ -429,6 +429,9 @@ impl Iterator for Rev where I: DoubleEndedIterator { #[inline] fn size_hint(&self) -> (usize, Option) { self.iter.size_hint() } + #[inline] + fn nth(&mut self, n: usize) -> Option<::Item> { self.iter.nth_back(n) } + fn try_fold(&mut self, init: B, f: F) -> R where Self: Sized, F: FnMut(B, Self::Item) -> R, R: Try { @@ -461,6 +464,9 @@ impl DoubleEndedIterator for Rev where I: DoubleEndedIterator { #[inline] fn next_back(&mut self) -> Option<::Item> { self.iter.next() } + #[inline] + fn nth_back(&mut self, n: usize) -> Option<::Item> { self.iter.nth(n) } + fn try_rfold(&mut self, init: B, f: F) -> R where Self: Sized, F: FnMut(B, Self::Item) -> R, R: Try { diff --git a/src/libcore/iter/traits.rs b/src/libcore/iter/traits.rs index 45e5b614db3e0..727a60e359694 100644 --- a/src/libcore/iter/traits.rs +++ b/src/libcore/iter/traits.rs @@ -427,6 +427,62 @@ pub trait DoubleEndedIterator: Iterator { #[stable(feature = "rust1", since = "1.0.0")] fn next_back(&mut self) -> Option; + /// Returns the `n`th element from the end of the iterator. + /// + /// This is essentially the reversed version of [`nth`]. Although like most indexing + /// operations, the count starts from zero, so `nth_back(0)` returns the first value fro + /// the end, `nth_back(1)` the second, and so on. + /// + /// Note that all elements between the end and the returned element will be + /// consumed, including the returned element. This also means that calling + /// `nth_back(0)` multiple times on the same iterator will return different + /// elements. + /// + /// `nth_back()` will return [`None`] if `n` is greater than or equal to the length of the + /// iterator. + /// + /// [`None`]: ../../std/option/enum.Option.html#variant.None + /// [`nth`]: ../../std/iter/trait.Iterator.html#method.nth + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(iter_nth_back)] + /// let a = [1, 2, 3]; + /// assert_eq!(a.iter().nth_back(2), Some(&1)); + /// ``` + /// + /// Calling `nth_back()` multiple times doesn't rewind the iterator: + /// + /// ``` + /// #![feature(iter_nth_back)] + /// let a = [1, 2, 3]; + /// + /// let mut iter = a.iter(); + /// + /// assert_eq!(iter.nth_back(1), Some(&2)); + /// assert_eq!(iter.nth_back(1), None); + /// ``` + /// + /// Returning `None` if there are less than `n + 1` elements: + /// + /// ``` + /// #![feature(iter_nth_back)] + /// let a = [1, 2, 3]; + /// assert_eq!(a.iter().nth_back(10), None); + /// ``` + #[inline] + #[unstable(feature = "iter_nth_back", issue = "56995")] + fn nth_back(&mut self, mut n: usize) -> Option { + for x in self.rev() { + if n == 0 { return Some(x) } + n -= 1; + } + None + } + /// This is the reverse version of [`try_fold()`]: it takes elements /// starting from the back of the iterator. /// @@ -461,8 +517,11 @@ pub trait DoubleEndedIterator: Iterator { /// ``` #[inline] #[stable(feature = "iterator_try_fold", since = "1.27.0")] - fn try_rfold(&mut self, init: B, mut f: F) -> R where - Self: Sized, F: FnMut(B, Self::Item) -> R, R: Try + fn try_rfold(&mut self, init: B, mut f: F) -> R + where + Self: Sized, + F: FnMut(B, Self::Item) -> R, + R: Try { let mut accum = init; while let Some(x) = self.next_back() { @@ -524,8 +583,10 @@ pub trait DoubleEndedIterator: Iterator { /// ``` #[inline] #[stable(feature = "iter_rfold", since = "1.27.0")] - fn rfold(mut self, accum: B, mut f: F) -> B where - Self: Sized, F: FnMut(B, Self::Item) -> B, + fn rfold(mut self, accum: B, mut f: F) -> B + where + Self: Sized, + F: FnMut(B, Self::Item) -> B, { self.try_rfold(accum, move |acc, x| Ok::(f(acc, x))).unwrap() } @@ -574,7 +635,8 @@ pub trait DoubleEndedIterator: Iterator { /// ``` #[inline] #[stable(feature = "iter_rfind", since = "1.27.0")] - fn rfind

(&mut self, mut predicate: P) -> Option where + fn rfind

(&mut self, mut predicate: P) -> Option + where Self: Sized, P: FnMut(&Self::Item) -> bool { @@ -587,7 +649,12 @@ pub trait DoubleEndedIterator: Iterator { #[stable(feature = "rust1", since = "1.0.0")] impl<'a, I: DoubleEndedIterator + ?Sized> DoubleEndedIterator for &'a mut I { - fn next_back(&mut self) -> Option { (**self).next_back() } + fn next_back(&mut self) -> Option { + (**self).next_back() + } + fn nth_back(&mut self, n: usize) -> Option { + (**self).nth_back(n) + } } /// An iterator that knows its exact length. diff --git a/src/libcore/tests/iter.rs b/src/libcore/tests/iter.rs index 00b4aa4fa2d7a..b5633333d0170 100644 --- a/src/libcore/tests/iter.rs +++ b/src/libcore/tests/iter.rs @@ -1016,6 +1016,33 @@ fn test_iterator_nth() { assert_eq!(v.iter().nth(v.len()), None); } +#[test] +fn test_iterator_nth_back() { + let v: &[_] = &[0, 1, 2, 3, 4]; + for i in 0..v.len() { + assert_eq!(v.iter().nth_back(i).unwrap(), &v[v.len() - 1 - i]); + } + assert_eq!(v.iter().nth_back(v.len()), None); +} + +#[test] +fn test_iterator_rev_nth_back() { + let v: &[_] = &[0, 1, 2, 3, 4]; + for i in 0..v.len() { + assert_eq!(v.iter().rev().nth_back(i).unwrap(), &v[i]); + } + assert_eq!(v.iter().rev().nth_back(v.len()), None); +} + +#[test] +fn test_iterator_rev_nth() { + let v: &[_] = &[0, 1, 2, 3, 4]; + for i in 0..v.len() { + assert_eq!(v.iter().rev().nth(i).unwrap(), &v[v.len() - 1 - i]); + } + assert_eq!(v.iter().rev().nth(v.len()), None); +} + #[test] fn test_iterator_last() { let v: &[_] = &[0, 1, 2, 3, 4]; diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs index 7d62b4fa90f20..2377a4733678d 100644 --- a/src/libcore/tests/lib.rs +++ b/src/libcore/tests/lib.rs @@ -19,6 +19,7 @@ #![feature(flt2dec)] #![feature(fmt_internals)] #![feature(hashmap_internals)] +#![feature(iter_nth_back)] #![feature(iter_unfold)] #![feature(pattern)] #![feature(range_is_empty)] From 66bb34c3ab254d19623315d9d71695c3acb4e826 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Thu, 20 Dec 2018 01:34:31 -0800 Subject: [PATCH 58/84] Update src/libcore/num/mod.rs Co-Authored-By: ubsan --- src/libcore/num/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index cedee1c8e5f99..cd8adfdd1fd26 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -1781,7 +1781,7 @@ assert_eq!((-a).div_euclid(-b), 2); // -7 >= -4 * 2 doc_comment! { concat!("Calculates the least nonnegative remainder of `self (mod rhs)`. -This is done as if by the euclidean division algorithm. +This is done as if by the Euclidean division algorithm. # Panics From 455bc95317ddb3f8d528d0220bfde7f7a7286463 Mon Sep 17 00:00:00 2001 From: Nicole Mazzuca Date: Thu, 20 Dec 2018 01:37:20 -0800 Subject: [PATCH 59/84] fix nits --- src/libcore/num/mod.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index cd8adfdd1fd26..7ffb81901c619 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -1740,7 +1740,7 @@ $EndFeature, " concat!("Calculates the quotient of Euclidean division of `self` by `rhs`. This computes the integer `n` such that `self = n * rhs + self.rem_euclid(rhs)`, -with the `0 <= self.rem_euclid(rhs) < rhs`. +with `0 <= self.rem_euclid(rhs) < rhs`. In other words, the result is `self / rhs` rounded to the integer `n` such that `self >= n * rhs`. @@ -1781,7 +1781,9 @@ assert_eq!((-a).div_euclid(-b), 2); // -7 >= -4 * 2 doc_comment! { concat!("Calculates the least nonnegative remainder of `self (mod rhs)`. -This is done as if by the Euclidean division algorithm. +This is done as if by the Euclidean division algorithm -- given +`r = self.rem_euclid(rhs)`, `self = rhs * self.div_euclid(rhs) + r`, and +`0 <= r < abs(rhs)`. # Panics From 405d8b0bb3d749e3baad25f68455873b66b219be Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Thu, 20 Dec 2018 14:31:40 +0100 Subject: [PATCH 60/84] Copyrite --- src/test/ui/dead-code-tuple-struct-field.rs | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/test/ui/dead-code-tuple-struct-field.rs b/src/test/ui/dead-code-tuple-struct-field.rs index f4989fa1037d3..496ce4fb378ae 100644 --- a/src/test/ui/dead-code-tuple-struct-field.rs +++ b/src/test/ui/dead-code-tuple-struct-field.rs @@ -1,13 +1,3 @@ -// 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. - // compile-pass #![deny(dead_code)] From 0b0a00cc0551b7f525515e4e53bc0a11bd1b2ebd Mon Sep 17 00:00:00 2001 From: QuietMisdreavus Date: Thu, 20 Dec 2018 10:18:45 -0600 Subject: [PATCH 61/84] new --static-root-path flag for controlling static file locations --- src/doc/rustdoc/src/unstable-features.md | 15 +++++++++ src/librustdoc/config.rs | 5 +++ src/librustdoc/html/layout.rs | 39 +++++++++++++++--------- src/librustdoc/html/render.rs | 9 ++++++ src/librustdoc/lib.rs | 8 +++++ src/test/rustdoc/static-root-path.rs | 18 +++++++++++ 6 files changed, 80 insertions(+), 14 deletions(-) create mode 100644 src/test/rustdoc/static-root-path.rs diff --git a/src/doc/rustdoc/src/unstable-features.md b/src/doc/rustdoc/src/unstable-features.md index 43cdab27e9dae..905b06465340a 100644 --- a/src/doc/rustdoc/src/unstable-features.md +++ b/src/doc/rustdoc/src/unstable-features.md @@ -402,3 +402,18 @@ Using `index-page` option enables `enable-index-page` option as well. ### `--enable-index-page`: generate a default index page for docs This feature allows the generation of a default index-page which lists the generated crates. + +### `--static-root-path`: control how static files are loaded in HTML output + +Using this flag looks like this: + +```bash +$ rustdoc src/lib.rs -Z unstable-options --static-root-path '/cache/' +``` + +This flag controls how rustdoc links to its static files on HTML pages. If you're hosting a lot of +crates' docs generated by the same version of rustdoc, you can use this flag to cache rustdoc's CSS, +JavaScript, and font files in a single location, rather than duplicating it once per "doc root" +(grouping of crate docs generated into the same output directory, like with `cargo doc`). Per-crate +files like the search index will still load from the documentation root, but anything that gets +renamed with `--resource-suffix` will load from the given path. diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index b421f07ddafa2..f9a46fe362e3c 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -181,6 +181,9 @@ pub struct RenderOptions { /// A file to use as the index page at the root of the output directory. Overrides /// `enable_index_page` to be true if set. pub index_page: Option, + /// An optional path to use as the location of static files. If not set, uses combinations of + /// `../` to reach the documentation root. + pub static_root_path: Option, // Options specific to reading standalone Markdown files @@ -433,6 +436,7 @@ impl Options { let markdown_playground_url = matches.opt_str("markdown-playground-url"); let crate_version = matches.opt_str("crate-version"); let enable_index_page = matches.opt_present("enable-index-page") || index_page.is_some(); + let static_root_path = matches.opt_str("static-root-path"); let (lint_opts, describe_lints, lint_cap) = get_cmd_lint_options(matches, error_format); @@ -471,6 +475,7 @@ impl Options { enable_minification, enable_index_page, index_page, + static_root_path, markdown_no_toc, markdown_css, markdown_playground_url, diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs index 37ff693bdf167..1ead428ff498c 100644 --- a/src/librustdoc/html/layout.rs +++ b/src/librustdoc/html/layout.rs @@ -26,6 +26,7 @@ pub struct Page<'a> { pub title: &'a str, pub css_class: &'a str, pub root_path: &'a str, + pub static_root_path: Option<&'a str>, pub description: &'a str, pub keywords: &'a str, pub resource_suffix: &'a str, @@ -36,6 +37,7 @@ pub fn render( css_file_extension: bool, themes: &[PathBuf], extra_scripts: &[&str]) -> io::Result<()> { + let static_root_path = page.static_root_path.unwrap_or(page.root_path); write!(dst, "\ \ @@ -46,20 +48,20 @@ pub fn render( \ \ {title}\ - \ - \ + \ {themes}\ - \ - \ + \ - \ - \ + \ + \ {css_extension}\ {favicon}\ {in_header}\ \ \ \ @@ -77,11 +79,13 @@ pub fn render( \

\ \
\
\ - \ + \
\ \ @@ -157,19 +163,22 @@ pub fn render( window.currentCrate = \"{krate}\";\ \ \ - \ + \ {extra_scripts}\ \ \ ", css_extension = if css_file_extension { - format!("", - root_path = page.root_path, + format!("", + static_root_path = static_root_path, suffix=page.resource_suffix) } else { String::new() }, content = *t, + static_root_path = static_root_path, root_path = page.root_path, css_class = page.css_class, logo = if layout.logo.is_empty() { @@ -197,11 +206,13 @@ pub fn render( .filter_map(|t| t.file_stem()) .filter_map(|t| t.to_str()) .map(|t| format!(r#""#, - page.root_path, + static_root_path, t, page.resource_suffix)) .collect::(), suffix=page.resource_suffix, + // TODO: break out a separate `static_extra_scripts` that uses `static_root_path` instead, + // then leave `source-files.js` here and move `source-script.js` to the static version extra_scripts=extra_scripts.iter().map(|e| { format!("", root_path=page.root_path, diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 46002c089cf9f..a4e71a1833322 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -140,6 +140,9 @@ struct SharedContext { /// Suffix to be added on resource files (if suffix is "-v2" then "light.css" becomes /// "light-v2.css"). pub resource_suffix: String, + /// Optional path string to be used to load static files on output pages. If not set, uses + /// combinations of `../` to reach the documentation root. + pub static_root_path: Option, } impl SharedContext { @@ -506,6 +509,7 @@ pub fn run(mut krate: clean::Crate, extension_css, extern_html_root_urls, resource_suffix, + static_root_path, .. } = options; @@ -533,6 +537,7 @@ pub fn run(mut krate: clean::Crate, sort_modules_alphabetically, themes, resource_suffix, + static_root_path, }; // If user passed in `--playground-url` arg, we fill in crate name here @@ -1080,6 +1085,7 @@ themePicker.onblur = handleThemeButtonsBlur; title: "Index of crates", css_class: "mod", root_path: "./", + static_root_path: cx.shared.static_root_path.deref(), description: "List of crates", keywords: BASIC_KEYWORDS, resource_suffix: &cx.shared.resource_suffix, @@ -1366,6 +1372,7 @@ impl<'a> SourceCollector<'a> { title: &title, css_class: "source", root_path: &root_path, + static_root_path: self.scx.static_root_path.deref(), description: &desc, keywords: BASIC_KEYWORDS, resource_suffix: &self.scx.resource_suffix, @@ -1956,6 +1963,7 @@ impl Context { title: "List of all items in this crate", css_class: "mod", root_path: "../", + static_root_path: self.shared.static_root_path.deref(), description: "List of all items in this crate", keywords: BASIC_KEYWORDS, resource_suffix: &self.shared.resource_suffix, @@ -2035,6 +2043,7 @@ impl Context { let page = layout::Page { css_class: tyname, root_path: &self.root_path(), + static_root_path: self.shared.static_root_path.deref(), title: &title, description: &desc, keywords: &keywords, diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index b0045e41f5057..4f59f67e94f98 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -25,6 +25,7 @@ #![feature(crate_visibility_modifier)] #![feature(const_fn)] #![feature(drain_filter)] +#![feature(inner_deref)] #![recursion_limit="256"] @@ -338,6 +339,13 @@ fn opts() -> Vec { "enable-index-page", "To enable generation of the index page") }), + unstable("static-root-path", |o| { + o.optopt("", + "static-root-path", + "Path string to force loading static files from in output pages. \ + If not set, uses combinations of '../' to reach the documentation root.", + "PATH") + }), ] } diff --git a/src/test/rustdoc/static-root-path.rs b/src/test/rustdoc/static-root-path.rs new file mode 100644 index 0000000000000..9307b501585fc --- /dev/null +++ b/src/test/rustdoc/static-root-path.rs @@ -0,0 +1,18 @@ +// Copyright 2018 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. + +// compile-flags:-Z unstable-options --static-root-path /cache/ + +// @has static_root_path/struct.SomeStruct.html +// @matches - '"/cache/main\.js"' +// @!matches - '"\.\./main\.js"' +// @matches - '"\.\./search-index\.js"' +// @!matches - '"/cache/search-index\.js"' +pub struct SomeStruct; From 8dc8d7ac512b831705da9bf7ef4601fdc6adcb25 Mon Sep 17 00:00:00 2001 From: QuietMisdreavus Date: Thu, 20 Dec 2018 10:57:03 -0600 Subject: [PATCH 62/84] split extra_scripts to handle root_path shenanigans --- src/librustdoc/html/layout.rs | 14 ++++++++++---- src/librustdoc/html/render.rs | 19 +++++++++++++------ src/test/rustdoc/static-root-path.rs | 6 ++++++ 3 files changed, 29 insertions(+), 10 deletions(-) diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs index 1ead428ff498c..d8a57bc93fd6c 100644 --- a/src/librustdoc/html/layout.rs +++ b/src/librustdoc/html/layout.rs @@ -30,11 +30,13 @@ pub struct Page<'a> { pub description: &'a str, pub keywords: &'a str, pub resource_suffix: &'a str, + pub extra_scripts: &'a [&'a str], + pub static_extra_scripts: &'a [&'a str], } pub fn render( dst: &mut dyn io::Write, layout: &Layout, page: &Page, sidebar: &S, t: &T, - css_file_extension: bool, themes: &[PathBuf], extra_scripts: &[&str]) + css_file_extension: bool, themes: &[PathBuf]) -> io::Result<()> { let static_root_path = page.static_root_path.unwrap_or(page.root_path); @@ -164,6 +166,7 @@ pub fn render( \ \ \ + {static_extra_scripts}\ {extra_scripts}\ \ \ @@ -211,9 +214,12 @@ pub fn render( page.resource_suffix)) .collect::(), suffix=page.resource_suffix, - // TODO: break out a separate `static_extra_scripts` that uses `static_root_path` instead, - // then leave `source-files.js` here and move `source-script.js` to the static version - extra_scripts=extra_scripts.iter().map(|e| { + static_extra_scripts=page.static_extra_scripts.iter().map(|e| { + format!("", + static_root_path=static_root_path, + extra_script=e) + }).collect::(), + extra_scripts=page.extra_scripts.iter().map(|e| { format!("", root_path=page.root_path, extra_script=e) diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index a4e71a1833322..d171d74744508 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -1089,6 +1089,8 @@ themePicker.onblur = handleThemeButtonsBlur; description: "List of crates", keywords: BASIC_KEYWORDS, resource_suffix: &cx.shared.resource_suffix, + extra_scripts: &[], + static_extra_scripts: &[], }; krates.push(krate.name.clone()); krates.sort(); @@ -1107,7 +1109,7 @@ themePicker.onblur = handleThemeButtonsBlur; try_err!(layout::render(&mut w, &cx.shared.layout, &page, &(""), &content, cx.shared.css_file_extension.is_some(), - &cx.shared.themes, &[]), &dst); + &cx.shared.themes), &dst); try_err!(w.flush(), &dst); } } @@ -1376,12 +1378,13 @@ impl<'a> SourceCollector<'a> { description: &desc, keywords: BASIC_KEYWORDS, resource_suffix: &self.scx.resource_suffix, + extra_scripts: &["source-files"], + static_extra_scripts: &[&format!("source-script{}", self.scx.resource_suffix)], }; layout::render(&mut w, &self.scx.layout, &page, &(""), &Source(contents), self.scx.css_file_extension.is_some(), - &self.scx.themes, &["source-files", - &format!("source-script{}", page.resource_suffix)])?; + &self.scx.themes)?; w.flush()?; self.scx.local_sources.insert(p.clone(), href); Ok(()) @@ -1967,6 +1970,8 @@ impl Context { description: "List of all items in this crate", keywords: BASIC_KEYWORDS, resource_suffix: &self.shared.resource_suffix, + extra_scripts: &[], + static_extra_scripts: &[], }; let sidebar = if let Some(ref version) = cache().crate_version { format!("

Crate {}

\ @@ -1981,7 +1986,7 @@ impl Context { try_err!(layout::render(&mut w, &self.shared.layout, &page, &sidebar, &all, self.shared.css_file_extension.is_some(), - &self.shared.themes, &[]), + &self.shared.themes), &final_file); // Generating settings page. @@ -2001,7 +2006,7 @@ impl Context { try_err!(layout::render(&mut w, &layout, &page, &sidebar, &settings, self.shared.css_file_extension.is_some(), - &themes, &[]), + &themes), &settings_file); Ok(()) @@ -2048,6 +2053,8 @@ impl Context { description: &desc, keywords: &keywords, resource_suffix: &self.shared.resource_suffix, + extra_scripts: &[], + static_extra_scripts: &[], }; { @@ -2060,7 +2067,7 @@ impl Context { &Sidebar{ cx: self, item: it }, &Item{ cx: self, item: it }, self.shared.css_file_extension.is_some(), - &self.shared.themes, &[])?; + &self.shared.themes)?; } else { let mut url = self.root_path(); if let Some(&(ref names, ty)) = cache().paths.get(&it.def_id) { diff --git a/src/test/rustdoc/static-root-path.rs b/src/test/rustdoc/static-root-path.rs index 9307b501585fc..7df3fee336583 100644 --- a/src/test/rustdoc/static-root-path.rs +++ b/src/test/rustdoc/static-root-path.rs @@ -16,3 +16,9 @@ // @matches - '"\.\./search-index\.js"' // @!matches - '"/cache/search-index\.js"' pub struct SomeStruct; + +// @has src/static_root_path/static-root-path.rs.html +// @matches - '"/cache/source-script\.js"' +// @!matches - '"\.\./\.\./source-script\.js"' +// @matches - '"\.\./\.\./source-files.js"' +// @!matches - '"/cache/source-files\.js"' From 8d393bf797c378bddc757cf18c59728b180ef2ba Mon Sep 17 00:00:00 2001 From: Andy Russell Date: Wed, 12 Dec 2018 22:51:04 -0500 Subject: [PATCH 63/84] display rustc_private APIs as "Internal" --- src/librustdoc/html/render.rs | 38 +++++++++++++++++---- src/librustdoc/html/static/rustdoc.css | 2 +- src/librustdoc/html/static/themes/dark.css | 5 +++ src/librustdoc/html/static/themes/light.css | 5 +++ src/test/rustdoc/internal.rs | 10 ++++++ 5 files changed, 52 insertions(+), 8 deletions(-) create mode 100644 src/test/rustdoc/internal.rs diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 689054da39d01..397eeb7433f90 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -2703,13 +2703,16 @@ fn stability_tags(item: &clean::Item) -> String { tags.push_str("[
Deprecated
] "); } - if item + if let Some(stab) = item .stability .as_ref() .filter(|s| s.level == stability::Unstable) - .is_some() { - tags.push_str("[
Experimental
] "); + if stab.feature.as_ref().map(|s| &**s) == Some("rustc_private") { + tags.push_str("[
Internal
] "); + } else { + tags.push_str("[
Experimental
] "); + } } if let Some(ref cfg) = item.attrs.cfg { @@ -2752,9 +2755,14 @@ fn short_stability(item: &clean::Item, cx: &Context) -> Vec { .as_ref() .filter(|stab| stab.level == stability::Unstable) { - let mut message = String::from( - "🔬 This is a nightly-only experimental API.", - ); + let is_rustc_private = stab.feature.as_ref().map(|s| &**s) == Some("rustc_private"); + + let mut message = if is_rustc_private { + "⚙️ This is an internal compiler API." + } else { + "🔬 This is a nightly-only experimental API." + } + .to_owned(); if let Some(feature) = stab.feature.as_ref() { let mut feature = format!("{}", Escape(&feature)); @@ -2770,6 +2778,17 @@ fn short_stability(item: &clean::Item, cx: &Context) -> Vec { } if let Some(unstable_reason) = &stab.unstable_reason { + // Provide a more informative message than the compiler help. + let unstable_reason = if is_rustc_private { + "This crate is being loaded from the sysroot, a permanently unstable location \ + for private compiler dependencies. It is not intended for general use. Prefer \ + using a public version of this crate from \ + [crates.io](https://crates.io) via [`Cargo.toml`]\ + (https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html)." + } else { + unstable_reason + }; + let mut ids = cx.id_map.borrow_mut(); message = format!( "
{}{}
", @@ -2778,7 +2797,12 @@ fn short_stability(item: &clean::Item, cx: &Context) -> Vec { ); } - stability.push(format!("
{}
", message)) + let class = if is_rustc_private { + "internal" + } else { + "unstable" + }; + stability.push(format!("
{}
", class, message)); } if let Some(ref cfg) = item.attrs.cfg { diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css index cd5a8a739d16d..b1648fbb1bc3e 100644 --- a/src/librustdoc/html/static/rustdoc.css +++ b/src/librustdoc/html/static/rustdoc.css @@ -765,7 +765,7 @@ body.blur > :not(#help) { display: list-item; } -.stab .microscope { +.stab .emoji { font-size: 1.5em; } diff --git a/src/librustdoc/html/static/themes/dark.css b/src/librustdoc/html/static/themes/dark.css index 2cd1a8580890c..be3ffed2b2659 100644 --- a/src/librustdoc/html/static/themes/dark.css +++ b/src/librustdoc/html/static/themes/dark.css @@ -174,6 +174,10 @@ a { color: #D2991D; } +.stab.internal a { + color: #304FFE; +} + a.test-arrow { color: #dedede; } @@ -199,6 +203,7 @@ a.test-arrow { } .stab.unstable { background: #FFF5D6; border-color: #FFC600; color: #404040; } +.stab.internal { background: #FFB9B3; border-color: #B71C1C; color: #404040; } .stab.deprecated { background: #F3DFFF; border-color: #7F0087; color: #404040; } .stab.portability { background: #C4ECFF; border-color: #7BA5DB; color: #404040; } diff --git a/src/librustdoc/html/static/themes/light.css b/src/librustdoc/html/static/themes/light.css index 4cf35f64d19a4..4ae10492ae6b2 100644 --- a/src/librustdoc/html/static/themes/light.css +++ b/src/librustdoc/html/static/themes/light.css @@ -174,6 +174,10 @@ a { color: #3873AD; } +.stab.internal a { + color: #304FFE; +} + a.test-arrow { color: #f5f5f5; } @@ -200,6 +204,7 @@ a.test-arrow { } .stab.unstable { background: #FFF5D6; border-color: #FFC600; } +.stab.internal { background: #FFB9B3; border-color: #B71C1C; } .stab.deprecated { background: #F3DFFF; border-color: #7F0087; } .stab.portability { background: #C4ECFF; border-color: #7BA5DB; } diff --git a/src/test/rustdoc/internal.rs b/src/test/rustdoc/internal.rs new file mode 100644 index 0000000000000..ba58da138a8c0 --- /dev/null +++ b/src/test/rustdoc/internal.rs @@ -0,0 +1,10 @@ +// compile-flags: -Z force-unstable-if-unmarked + +// @matches internal/index.html '//*[@class="docblock-short"]' \ +// '^\[Internal\] Docs' +// @has internal/struct.S.html '//*[@class="stab internal"]' \ +// 'This is an internal compiler API. (rustc_private)' +/// Docs +pub struct S; + +fn main() {} From 49f5106447ab873b8c743dafa2f8b1d387c1a263 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Mon, 17 Dec 2018 04:57:32 +0300 Subject: [PATCH 64/84] AST/HIR: Introduce `ExprKind::Err` for better error recovery in the front-end --- src/librustc/cfg/construct.rs | 3 ++- src/librustc/hir/intravisit.rs | 1 + src/librustc/hir/lowering.rs | 2 ++ src/librustc/hir/mod.rs | 7 ++++++- src/librustc/hir/print.rs | 9 ++++++++- src/librustc/ich/impls_hir.rs | 3 ++- src/librustc/middle/expr_use_visitor.rs | 3 ++- src/librustc/middle/liveness.rs | 6 ++++-- src/librustc/middle/mem_categorization.rs | 2 +- src/librustc_mir/hair/cx/expr.rs | 1 + src/librustc_passes/rvalue_promotion.rs | 3 ++- src/librustc_typeck/check/mod.rs | 3 +++ src/libsyntax/ast.rs | 4 ++++ src/libsyntax/fold.rs | 1 + src/libsyntax/print/pprust.rs | 9 ++++++++- src/libsyntax/util/parser.rs | 4 +++- src/libsyntax/visit.rs | 1 + 17 files changed, 51 insertions(+), 11 deletions(-) diff --git a/src/librustc/cfg/construct.rs b/src/librustc/cfg/construct.rs index c5d6ce24c5df4..0900c818ef6c6 100644 --- a/src/librustc/cfg/construct.rs +++ b/src/librustc/cfg/construct.rs @@ -402,7 +402,8 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { hir::ExprKind::Closure(..) | hir::ExprKind::Lit(..) | - hir::ExprKind::Path(_) => { + hir::ExprKind::Path(_) | + hir::ExprKind::Err => { self.straightline(expr, pred, None::.iter()) } } diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs index f7e2c7036f6f8..db94a48b9b1d7 100644 --- a/src/librustc/hir/intravisit.rs +++ b/src/librustc/hir/intravisit.rs @@ -1109,6 +1109,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) { ExprKind::Yield(ref subexpression) => { visitor.visit_expr(subexpression); } + ExprKind::Err => {} } } diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 6958801d865bf..7fc68af35fe26 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -4127,6 +4127,8 @@ impl<'a> LoweringContext<'a> { hir::ExprKind::Yield(P(expr)) } + ExprKind::Err => hir::ExprKind::Err, + // Desugar `ExprIfLet` // from: `if let = []` ExprKind::IfLet(ref pats, ref sub_expr, ref body, ref else_opt) => { diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 156d55b9e2fe6..90c18c748789f 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -1372,6 +1372,7 @@ impl Expr { ExprKind::Struct(..) => ExprPrecedence::Struct, ExprKind::Repeat(..) => ExprPrecedence::Repeat, ExprKind::Yield(..) => ExprPrecedence::Yield, + ExprKind::Err => ExprPrecedence::Err, } } @@ -1422,7 +1423,8 @@ impl Expr { ExprKind::AddrOf(..) | ExprKind::Binary(..) | ExprKind::Yield(..) | - ExprKind::Cast(..) => { + ExprKind::Cast(..) | + ExprKind::Err => { false } } @@ -1535,6 +1537,9 @@ pub enum ExprKind { /// A suspension point for generators. This is `yield ` in Rust. Yield(P), + + /// Placeholder for an expression that wasn't syntactically well formed in some way. + Err, } /// Optionally `Self`-qualified value/type path or associated extension. diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs index 5c6845181afd1..93194870a4a1e 100644 --- a/src/librustc/hir/print.rs +++ b/src/librustc/hir/print.rs @@ -440,7 +440,9 @@ impl<'a> State<'a> { self.s.word("_")?; } hir::TyKind::Err => { - self.s.word("?")?; + self.popen()?; + self.s.word("/*ERROR*/")?; + self.pclose()?; } } self.end() @@ -1550,6 +1552,11 @@ impl<'a> State<'a> { self.word_space("yield")?; self.print_expr_maybe_paren(&expr, parser::PREC_JUMP)?; } + hir::ExprKind::Err => { + self.popen()?; + self.s.word("/*ERROR*/")?; + self.pclose()?; + } } self.ann.post(self, AnnNode::Expr(expr))?; self.end() diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs index ae0d78d2958ad..8a48563a6c5d0 100644 --- a/src/librustc/ich/impls_hir.rs +++ b/src/librustc/ich/impls_hir.rs @@ -602,7 +602,8 @@ impl_stable_hash_for!(enum hir::ExprKind { InlineAsm(asm, inputs, outputs), Struct(path, fields, base), Repeat(val, times), - Yield(val) + Yield(val), + Err }); impl_stable_hash_for!(enum hir::LocalSource { diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index f1bc37d03e5a1..02ae4737eaacb 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -489,7 +489,8 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { } hir::ExprKind::Continue(..) | - hir::ExprKind::Lit(..) => {} + hir::ExprKind::Lit(..) | + hir::ExprKind::Err => {} hir::ExprKind::Loop(ref blk, _, _) => { self.walk_block(&blk); diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index 31a75bd106e2c..b05c86cf7fcdb 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -525,6 +525,7 @@ fn visit_expr<'a, 'tcx>(ir: &mut IrMaps<'a, 'tcx>, expr: &'tcx Expr) { hir::ExprKind::Box(..) | hir::ExprKind::Yield(..) | hir::ExprKind::Type(..) | + hir::ExprKind::Err | hir::ExprKind::Path(hir::QPath::TypeRelative(..)) => { intravisit::walk_expr(ir, expr); } @@ -1264,7 +1265,8 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { self.propagate_through_exprs(inputs, succ) } - hir::ExprKind::Lit(..) | hir::ExprKind::Path(hir::QPath::TypeRelative(..)) => { + hir::ExprKind::Lit(..) | hir::ExprKind::Err | + hir::ExprKind::Path(hir::QPath::TypeRelative(..)) => { succ } @@ -1531,7 +1533,7 @@ fn check_expr<'a, 'tcx>(this: &mut Liveness<'a, 'tcx>, expr: &'tcx Expr) { hir::ExprKind::Block(..) | hir::ExprKind::AddrOf(..) | hir::ExprKind::Struct(..) | hir::ExprKind::Repeat(..) | hir::ExprKind::Closure(..) | hir::ExprKind::Path(_) | hir::ExprKind::Yield(..) | - hir::ExprKind::Box(..) | hir::ExprKind::Type(..) => { + hir::ExprKind::Box(..) | hir::ExprKind::Type(..) | hir::ExprKind::Err => { intravisit::walk_expr(this, expr); } } diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index a04914e977493..bd1817fff5399 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -697,7 +697,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { hir::ExprKind::Block(..) | hir::ExprKind::Loop(..) | hir::ExprKind::Match(..) | hir::ExprKind::Lit(..) | hir::ExprKind::Break(..) | hir::ExprKind::Continue(..) | hir::ExprKind::Struct(..) | hir::ExprKind::Repeat(..) | - hir::ExprKind::InlineAsm(..) | hir::ExprKind::Box(..) => { + hir::ExprKind::InlineAsm(..) | hir::ExprKind::Box(..) | hir::ExprKind::Err => { Ok(self.cat_rvalue_node(expr.hir_id, expr.span, expr_ty)) } } diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index f93dbce97b54a..5a8ffb8059840 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -790,6 +790,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, hir::ExprKind::Tup(ref fields) => ExprKind::Tuple { fields: fields.to_ref() }, hir::ExprKind::Yield(ref v) => ExprKind::Yield { value: v.to_ref() }, + hir::ExprKind::Err => unreachable!(), }; Expr { diff --git a/src/librustc_passes/rvalue_promotion.rs b/src/librustc_passes/rvalue_promotion.rs index bfe8b677a5e80..2f0fbe477754f 100644 --- a/src/librustc_passes/rvalue_promotion.rs +++ b/src/librustc_passes/rvalue_promotion.rs @@ -459,7 +459,8 @@ fn check_expr_kind<'a, 'tcx>( struct_result } - hir::ExprKind::Lit(_) => Promotable, + hir::ExprKind::Lit(_) | + hir::ExprKind::Err => Promotable, hir::ExprKind::AddrOf(_, ref expr) | hir::ExprKind::Repeat(ref expr, _) => { diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index d45f8fd6de8d9..2c50be15d6f86 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -4498,6 +4498,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } tcx.mk_unit() } + hir::ExprKind::Err => { + tcx.types.err + } } } diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 0792b2dc49c27..50c9e14068ab6 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -1011,6 +1011,7 @@ impl Expr { ExprKind::Paren(..) => ExprPrecedence::Paren, ExprKind::Try(..) => ExprPrecedence::Try, ExprKind::Yield(..) => ExprPrecedence::Yield, + ExprKind::Err => ExprPrecedence::Err, } } } @@ -1170,6 +1171,9 @@ pub enum ExprKind { /// A `yield`, with an optional value to be yielded. Yield(Option>), + + /// Placeholder for an expression that wasn't syntactically well formed in some way. + Err, } /// The explicit `Self` type in a "qualified path". The actual diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index ecb0245263853..b05039329967d 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -1377,6 +1377,7 @@ pub fn noop_fold_expr(Expr {id, node, span, attrs}: Expr, folder: &mu ExprKind::Yield(ex) => ExprKind::Yield(ex.map(|x| folder.fold_expr(x))), ExprKind::Try(ex) => ExprKind::Try(folder.fold_expr(ex)), ExprKind::TryBlock(body) => ExprKind::TryBlock(folder.fold_block(body)), + ExprKind::Err => ExprKind::Err, }, id: folder.new_id(id), span: folder.new_span(span), diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 5e7707f4e5c3c..3c4a051b85880 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -1103,7 +1103,9 @@ impl<'a> State<'a> { self.s.word("_")?; } ast::TyKind::Err => { - self.s.word("?")?; + self.popen()?; + self.s.word("/*ERROR*/")?; + self.pclose()?; } ast::TyKind::ImplicitSelf => { self.s.word("Self")?; @@ -2401,6 +2403,11 @@ impl<'a> State<'a> { self.s.space()?; self.print_block_with_attrs(blk, attrs)? } + ast::ExprKind::Err => { + self.popen()?; + self.s.word("/*ERROR*/")?; + self.pclose()? + } } self.ann.post(self, AnnNode::Expr(expr))?; self.end() diff --git a/src/libsyntax/util/parser.rs b/src/libsyntax/util/parser.rs index b7cd2acf8a591..5a6a6f05fd756 100644 --- a/src/libsyntax/util/parser.rs +++ b/src/libsyntax/util/parser.rs @@ -276,6 +276,7 @@ pub enum ExprPrecedence { TryBlock, Struct, Async, + Err, } impl ExprPrecedence { @@ -334,7 +335,8 @@ impl ExprPrecedence { ExprPrecedence::Block | ExprPrecedence::TryBlock | ExprPrecedence::Async | - ExprPrecedence::Struct => PREC_PAREN, + ExprPrecedence::Struct | + ExprPrecedence::Err => PREC_PAREN, } } } diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 6747598f3753f..e30fef6ba51fc 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -812,6 +812,7 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) { ExprKind::TryBlock(ref body) => { visitor.visit_block(body) } + ExprKind::Err => {} } visitor.visit_expr_post(expression) From cc2b08d3172a03e2bc33bd2f432e17b3423bc53f Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 16 Dec 2018 20:23:27 +0300 Subject: [PATCH 65/84] Do not abort compilation if expansion produces errors Fix a number of uncovered deficiencies in diagnostics --- src/librustc_driver/driver.rs | 10 -- src/librustc_passes/ast_validation.rs | 30 ------ src/librustc_resolve/lib.rs | 7 +- src/librustc_resolve/macros.rs | 31 ++++-- src/libsyntax/ext/base.rs | 9 +- src/libsyntax/ext/expand.rs | 16 ++-- src/libsyntax/feature_gate.rs | 19 ++-- src/libsyntax_ext/deriving/default.rs | 4 +- src/libsyntax_ext/format.rs | 4 +- .../cfg-attr-invalid-predicate.rs | 2 + .../cfg-attr-syntax-validation.rs | 2 + .../auxiliary/extern_macro_crate.rs | 2 +- .../derive-on-trait-item-or-impl-item.rs | 2 + .../derive-on-trait-item-or-impl-item.stderr | 2 +- src/test/ui/did_you_mean/issue-40396.rs | 19 +++- src/test/ui/did_you_mean/issue-40396.stderr | 95 ++++++++++++++++--- .../edition-keywords-2015-2015-parsing.rs | 6 ++ .../edition-keywords-2015-2015-parsing.stderr | 4 +- .../edition-keywords-2015-2018-expansion.rs | 2 + .../edition-keywords-2015-2018-parsing.rs | 6 ++ .../edition-keywords-2015-2018-parsing.stderr | 4 +- .../edition-keywords-2018-2018-expansion.rs | 2 + .../issue-43106-gating-of-derive-2.rs | 2 + .../issue-43106-gating-of-derive.rs | 2 + .../feature-gate-cfg-target-has-atomic.rs | 2 + .../feature-gate-cfg-target-has-atomic.stderr | 36 +++---- .../feature-gate-macros_in_extern.rs | 2 + .../feature-gates/feature-gate-rustc-attrs.rs | 4 +- .../feature-gate-rustc-attrs.stderr | 2 +- src/test/ui/issues/issue-10536.rs | 7 +- src/test/ui/issues/issue-10536.stderr | 27 +++++- src/test/ui/issues/issue-11692-1.rs | 1 + src/test/ui/issues/issue-11692-1.stderr | 8 +- src/test/ui/issues/issue-11692-2.rs | 1 + src/test/ui/issues/issue-11692-2.stderr | 10 +- src/test/ui/issues/issue-32950.rs | 1 + src/test/ui/issues/issue-32950.stderr | 9 +- src/test/ui/issues/issue-33571.rs | 2 + src/test/ui/issues/issue-35677.rs | 2 + src/test/ui/issues/issue-35677.stderr | 9 +- src/test/ui/issues/issue-36617.rs | 2 + src/test/ui/issues/issue-43023.rs | 2 + src/test/ui/issues/issue-46438.rs | 2 +- src/test/ui/issues/issue-49074.rs | 2 +- src/test/ui/issues/issue-49074.stderr | 10 +- src/test/ui/issues/issue-51279.rs | 1 + src/test/ui/issues/issue-51279.stderr | 11 ++- src/test/ui/issues/issue-55796.rs | 2 + src/test/ui/issues/issue-55796.stderr | 9 +- src/test/ui/issues/issue-6596-1.rs | 1 + src/test/ui/issues/issue-6596-1.stderr | 12 ++- src/test/ui/issues/issue-6596-2.rs | 1 + src/test/ui/macro_backtrace/main.rs | 2 + .../macros/macro-comma-behavior.core.stderr | 8 +- .../ui/malformed/malformed-derive-entry.rs | 2 + .../runtime-depend-on-needs-runtime.rs | 2 + .../runtime-depend-on-needs-runtime.stderr | 7 +- src/test/ui/parser/macro/pub-item-macro.rs | 2 +- .../ui/parser/macro/pub-item-macro.stderr | 9 +- src/test/ui/proc-macro/issue-41211.rs | 1 + src/test/ui/proc-macro/issue-41211.stderr | 8 +- src/test/ui/proc-macro/lifetimes.rs | 2 + src/test/ui/proc-macro/more-gates.rs | 2 + src/test/ui/proc-macro/more-gates.stderr | 10 +- src/test/ui/proc-macro/parent-source-spans.rs | 3 + .../ui/proc-macro/parent-source-spans.stderr | 54 ++++++++--- .../ui/proc-macro/proc-macro-attributes.rs | 9 +- .../proc-macro/proc-macro-attributes.stderr | 79 ++++++++++++++- src/test/ui/quote-with-interpolated.rs | 7 +- src/test/ui/quote-with-interpolated.stderr | 33 ++++++- .../ui/reserved/reserved-attr-on-macro.rs | 5 +- .../ui/reserved/reserved-attr-on-macro.stderr | 12 ++- src/test/ui/self/self_type_keyword.rs | 1 + src/test/ui/self/self_type_keyword.stderr | 27 ++++-- src/test/ui/span/issue-36530.rs | 2 + src/test/ui/span/macro-ty-params.rs | 4 +- src/test/ui/span/macro-ty-params.stderr | 26 ++--- src/test/ui/span/visibility-ty-params.rs | 1 + src/test/ui/span/visibility-ty-params.stderr | 13 ++- .../ui/tuple/tuple-struct-fields/test2.rs | 4 +- .../ui/tuple/tuple-struct-fields/test2.stderr | 11 ++- .../ui/tuple/tuple-struct-fields/test3.rs | 4 +- .../ui/tuple/tuple-struct-fields/test3.stderr | 11 ++- 83 files changed, 598 insertions(+), 223 deletions(-) diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index 55e052882ea5b..43fc91ea4827f 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -997,7 +997,6 @@ where }; let mut ecx = ExtCtxt::new(&sess.parse_sess, cfg, &mut resolver); - let err_count = ecx.parse_sess.span_diagnostic.err_count(); // Expand macros now! let krate = time(sess, "expand crate", || { @@ -1023,9 +1022,6 @@ where let msg = "missing fragment specifier"; sess.buffer_lint(lint, ast::CRATE_NODE_ID, span, msg); } - if ecx.parse_sess.span_diagnostic.err_count() - ecx.resolve_err_count > err_count { - ecx.parse_sess.span_diagnostic.abort_if_errors(); - } if cfg!(windows) { env::set_var("PATH", &old_path); } @@ -1129,12 +1125,6 @@ where }) })?; - // Unresolved macros might be due to mistyped `#[macro_use]`, - // so abort after checking for unknown attributes. (#49074) - if resolver.found_unresolved_macro { - sess.diagnostic().abort_if_errors(); - } - // Lower ast -> hir. // First, we need to collect the dep_graph. let dep_graph = match future_dep_graph { diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs index 9a35721e3e1c4..259888412a98d 100644 --- a/src/librustc_passes/ast_validation.rs +++ b/src/librustc_passes/ast_validation.rs @@ -288,25 +288,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> { visit::walk_ty(self, ty) } - fn visit_use_tree(&mut self, use_tree: &'a UseTree, id: NodeId, _nested: bool) { - // Check if the path in this `use` is not generic, such as `use foo::bar;` While this - // can't happen normally thanks to the parser, a generic might sneak in if the `use` is - // built using a macro. - // - // macro_use foo { - // ($p:path) => { use $p; } - // } - // foo!(bar::baz); - use_tree.prefix.segments.iter().find(|segment| { - segment.args.is_some() - }).map(|segment| { - self.err_handler().span_err(segment.args.as_ref().unwrap().span(), - "generic arguments in import path"); - }); - - visit::walk_use_tree(self, use_tree, id); - } - fn visit_label(&mut self, label: &'a Label) { self.check_label(label.ident); visit::walk_label(self, label); @@ -443,17 +424,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> { visit::walk_foreign_item(self, fi) } - fn visit_vis(&mut self, vis: &'a Visibility) { - if let VisibilityKind::Restricted { ref path, .. } = vis.node { - path.segments.iter().find(|segment| segment.args.is_some()).map(|segment| { - self.err_handler().span_err(segment.args.as_ref().unwrap().span(), - "generic arguments in visibility path"); - }); - } - - visit::walk_vis(self, vis) - } - fn visit_generics(&mut self, generics: &'a Generics) { let mut seen_non_lifetime_param = false; let mut seen_default = None; diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 794e5741d62ca..c1d4ea281809b 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -1584,7 +1584,6 @@ pub struct Resolver<'a> { macro_map: FxHashMap>, macro_defs: FxHashMap, local_macro_def_scopes: FxHashMap>, - pub found_unresolved_macro: bool, /// List of crate local macros that we need to warn about as being unused. /// Right now this only includes macro_rules! macros, and macros 2.0. @@ -1919,7 +1918,6 @@ impl<'a> Resolver<'a> { name_already_seen: FxHashMap::default(), potentially_unused_imports: Vec::new(), struct_constructors: Default::default(), - found_unresolved_macro: false, unused_macros: FxHashSet::default(), current_type_ascription: Vec::new(), injected_crate: None, @@ -2032,8 +2030,10 @@ impl<'a> Resolver<'a> { record_used_id: Option, path_span: Span) -> Option> { - let record_used = record_used_id.is_some(); assert!(ns == TypeNS || ns == ValueNS); + if ident.name == keywords::Invalid.name() { + return Some(LexicalScopeBinding::Def(Def::Err)); + } if ns == TypeNS { ident.span = if ident.name == keywords::SelfUpper.name() { // FIXME(jseyfried) improve `Self` hygiene @@ -2046,6 +2046,7 @@ impl<'a> Resolver<'a> { } // Walk backwards up the ribs in scope. + let record_used = record_used_id.is_some(); let mut module = self.graph_root; for i in (0 .. self.ribs[ns].len()).rev() { if let Some(def) = self.ribs[ns][i].bindings.get(&ident).cloned() { diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 81633c8f57f9e..1bdcf4577fef1 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -192,7 +192,14 @@ impl<'a> base::Resolver for Resolver<'a> { }; let parent_scope = self.invoc_parent_scope(invoc_id, derives_in_scope); - let (def, ext) = self.resolve_macro_to_def(path, kind, &parent_scope, true, force)?; + let (def, ext) = match self.resolve_macro_to_def(path, kind, &parent_scope, true, force) { + Ok((def, ext)) => (def, ext), + Err(Determinacy::Determined) if kind == MacroKind::Attr => { + // Replace unresolved attributes with used inert attributes for better recovery. + return Ok(Some(self.get_macro(Def::NonMacroAttr(NonMacroAttrKind::Tool)))); + } + Err(determinacy) => return Err(determinacy), + }; if let Def::Macro(def_id, _) = def { if after_derive { @@ -347,7 +354,6 @@ impl<'a> Resolver<'a> { } PathResult::Indeterminate if !force => return Err(Determinacy::Undetermined), PathResult::NonModule(..) | PathResult::Indeterminate | PathResult::Failed(..) => { - self.found_unresolved_macro = true; Err(Determinacy::Determined) } PathResult::Module(..) => unreachable!(), @@ -363,10 +369,8 @@ impl<'a> Resolver<'a> { let binding = self.early_resolve_ident_in_lexical_scope( path[0].ident, ScopeSet::Macro(kind), parent_scope, false, force, path_span ); - match binding { - Ok(..) => {} - Err(Determinacy::Determined) => self.found_unresolved_macro = true, - Err(Determinacy::Undetermined) => return Err(Determinacy::Undetermined), + if let Err(Determinacy::Undetermined) = binding { + return Err(Determinacy::Undetermined); } if trace { @@ -868,14 +872,23 @@ impl<'a> Resolver<'a> { pub fn finalize_current_module_macro_resolutions(&mut self) { let module = self.current_module; - let check_consistency = |this: &mut Self, path: &[Segment], span, - kind: MacroKind, initial_def, def| { + let check_consistency = |this: &mut Self, path: &[Segment], span, kind: MacroKind, + initial_def: Option, def: Def| { if let Some(initial_def) = initial_def { if def != initial_def && def != Def::Err && this.ambiguity_errors.is_empty() { // Make sure compilation does not succeed if preferred macro resolution // has changed after the macro had been expanded. In theory all such // situations should be reported as ambiguity errors, so this is a bug. - span_bug!(span, "inconsistent resolution for a macro"); + if initial_def == Def::NonMacroAttr(NonMacroAttrKind::Custom) { + // Yeah, legacy custom attributes are implemented using forced resolution + // (which is a best effort error recovery tool, basically), so we can't + // promise their resolution won't change later. + let msg = format!("inconsistent resolution for a macro: first {}, then {}", + initial_def.kind_name(), def.kind_name()); + this.session.span_err(span, &msg); + } else { + span_bug!(span, "inconsistent resolution for a macro"); + } } } else { // It's possible that the macro was unresolved (indeterminate) and silently diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index b807a65f6aed6..ad4824dc5dfae 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -12,7 +12,7 @@ pub use self::SyntaxExtension::*; use ast::{self, Attribute, Name, PatKind, MetaItem}; use attr::HasAttrs; -use source_map::{self, SourceMap, Spanned, respan}; +use source_map::{SourceMap, Spanned, respan}; use syntax_pos::{Span, MultiSpan, DUMMY_SP}; use edition::Edition; use errors::{DiagnosticBuilder, DiagnosticId}; @@ -491,7 +491,7 @@ impl DummyResult { pub fn raw_expr(sp: Span) -> P { P(ast::Expr { id: ast::DUMMY_NODE_ID, - node: ast::ExprKind::Lit(source_map::respan(sp, ast::LitKind::Bool(false))), + node: ast::ExprKind::Err, span: sp, attrs: ThinVec::new(), }) @@ -506,10 +506,11 @@ impl DummyResult { } } + /// A plain dummy type. pub fn raw_ty(sp: Span) -> P { P(ast::Ty { id: ast::DUMMY_NODE_ID, - node: ast::TyKind::Infer, + node: ast::TyKind::Err, span: sp }) } @@ -806,7 +807,6 @@ pub struct ExtCtxt<'a> { pub ecfg: expand::ExpansionConfig<'a>, pub root_path: PathBuf, pub resolver: &'a mut dyn Resolver, - pub resolve_err_count: usize, pub current_expansion: ExpansionData, pub expansions: FxHashMap>, } @@ -821,7 +821,6 @@ impl<'a> ExtCtxt<'a> { ecfg, root_path: PathBuf::new(), resolver, - resolve_err_count: 0, current_expansion: ExpansionData { mark: Mark::root(), depth: 0, diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 57ccc3e981720..299f23927bf8d 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -354,8 +354,10 @@ impl<'a, 'b> MacroExpander<'a, 'b> { // FIXME(jseyfried): Refactor out the following logic let (expanded_fragment, new_invocations) = if let Some(ext) = ext { if let Some(ext) = ext { - let dummy = invoc.fragment_kind.dummy(invoc.span()).unwrap(); - let fragment = self.expand_invoc(invoc, &*ext).unwrap_or(dummy); + let (invoc_fragment_kind, invoc_span) = (invoc.fragment_kind, invoc.span()); + let fragment = self.expand_invoc(invoc, &*ext).unwrap_or_else(|| { + invoc_fragment_kind.dummy(invoc_span).unwrap() + }); self.collect_invocations(fragment, &[]) } else if let InvocationKind::Attr { attr: None, traits, item, .. } = invoc.kind { if !item.derive_allowed() { @@ -441,9 +443,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { fn resolve_imports(&mut self) { if self.monotonic { - let err_count = self.cx.parse_sess.span_diagnostic.err_count(); self.cx.resolver.resolve_imports(); - self.cx.resolve_err_count += self.cx.parse_sess.span_diagnostic.err_count() - err_count; } } @@ -467,11 +467,9 @@ impl<'a, 'b> MacroExpander<'a, 'b> { }; if self.monotonic { - let err_count = self.cx.parse_sess.span_diagnostic.err_count(); - let mark = self.cx.current_expansion.mark; - self.cx.resolver.visit_ast_fragment_with_placeholders(mark, &fragment_with_placeholders, - derives); - self.cx.resolve_err_count += self.cx.parse_sess.span_diagnostic.err_count() - err_count; + self.cx.resolver.visit_ast_fragment_with_placeholders( + self.cx.current_expansion.mark, &fragment_with_placeholders, derives + ); } (fragment_with_placeholders, invocations) diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 844f49fe842b7..8a3f0ed68c449 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -1284,16 +1284,15 @@ impl<'a> Context<'a> { return; } } - if name.starts_with("rustc_") { - gate_feature!(self, rustc_attrs, attr.span, - "unless otherwise specified, attributes \ - with the prefix `rustc_` \ - are reserved for internal compiler diagnostics"); - } else if !attr::is_known(attr) { - // Only run the custom attribute lint during regular feature gate - // checking. Macro gating runs before the plugin attributes are - // registered, so we skip this in that case. - if !is_macro { + if !attr::is_known(attr) { + if name.starts_with("rustc_") { + let msg = "unless otherwise specified, attributes with the prefix `rustc_` \ + are reserved for internal compiler diagnostics"; + gate_feature!(self, rustc_attrs, attr.span, msg); + } else if !is_macro { + // Only run the custom attribute lint during regular feature gate + // checking. Macro gating runs before the plugin attributes are + // registered, so we skip this in that case. let msg = format!("The attribute `{}` is currently unknown to the compiler and \ may have meaning added to it in the future", attr.path); gate_feature!(self, custom_attribute, attr.span, &msg); diff --git a/src/libsyntax_ext/deriving/default.rs b/src/libsyntax_ext/deriving/default.rs index adbc5828b8fb8..e0c4fa405e6d9 100644 --- a/src/libsyntax_ext/deriving/default.rs +++ b/src/libsyntax_ext/deriving/default.rs @@ -13,7 +13,7 @@ use deriving::generic::*; use deriving::generic::ty::*; use syntax::ast::{Expr, MetaItem}; -use syntax::ext::base::{Annotatable, ExtCtxt}; +use syntax::ext::base::{Annotatable, DummyResult, ExtCtxt}; use syntax::ext::build::AstBuilder; use syntax::ptr::P; use syntax::symbol::Symbol; @@ -79,7 +79,7 @@ fn default_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructur span_err!(cx, trait_span, E0665, "`Default` cannot be derived for enums, only structs"); // let compilation continue - cx.expr_usize(trait_span, 0) + DummyResult::raw_expr(trait_span) } _ => cx.span_bug(trait_span, "Non-static method in `derive(Default)`"), }; diff --git a/src/libsyntax_ext/format.rs b/src/libsyntax_ext/format.rs index 41799eede9e86..79241fb6aa74f 100644 --- a/src/libsyntax_ext/format.rs +++ b/src/libsyntax_ext/format.rs @@ -676,7 +676,7 @@ impl<'a, 'b> Context<'a, 'b> { "X" => "UpperHex", _ => { ecx.span_err(sp, &format!("unknown format trait `{}`", *tyname)); - "Dummy" + return DummyResult::raw_expr(sp); } } } @@ -723,7 +723,7 @@ pub fn expand_format_args_nl<'cx>( sp, feature_gate::GateIssue::Language, feature_gate::EXPLAIN_FORMAT_ARGS_NL); - return base::DummyResult::expr(sp); + return DummyResult::expr(sp); } sp = sp.apply_mark(ecx.current_expansion.mark); match parse_args(ecx, sp, tts) { diff --git a/src/test/ui/conditional-compilation/cfg-attr-invalid-predicate.rs b/src/test/ui/conditional-compilation/cfg-attr-invalid-predicate.rs index 09fe6cec49c2e..a16568f5ffabe 100644 --- a/src/test/ui/conditional-compilation/cfg-attr-invalid-predicate.rs +++ b/src/test/ui/conditional-compilation/cfg-attr-invalid-predicate.rs @@ -9,4 +9,6 @@ // except according to those terms. #[cfg(foo(bar))] //~ ERROR invalid predicate `foo` +fn check() {} + fn main() {} diff --git a/src/test/ui/conditional-compilation/cfg-attr-syntax-validation.rs b/src/test/ui/conditional-compilation/cfg-attr-syntax-validation.rs index 83e162e08712f..c7e1b4435e49b 100644 --- a/src/test/ui/conditional-compilation/cfg-attr-syntax-validation.rs +++ b/src/test/ui/conditional-compilation/cfg-attr-syntax-validation.rs @@ -33,3 +33,5 @@ macro_rules! generate_s10 { } generate_s10!(concat!("nonexistent")); + +fn main() {} diff --git a/src/test/ui/cross/cross-crate-macro-backtrace/auxiliary/extern_macro_crate.rs b/src/test/ui/cross/cross-crate-macro-backtrace/auxiliary/extern_macro_crate.rs index 598e9f0f53aee..782e830eb4634 100644 --- a/src/test/ui/cross/cross-crate-macro-backtrace/auxiliary/extern_macro_crate.rs +++ b/src/test/ui/cross/cross-crate-macro-backtrace/auxiliary/extern_macro_crate.rs @@ -14,7 +14,7 @@ pub fn print(_args: std::fmt::Arguments) {} #[macro_export] macro_rules! myprint { - ($($arg:tt)*) => (print(format_args!($($arg)*))); + ($($arg:tt)*) => ($crate::print(format_args!($($arg)*))); } #[macro_export] diff --git a/src/test/ui/derives/derive-on-trait-item-or-impl-item.rs b/src/test/ui/derives/derive-on-trait-item-or-impl-item.rs index 9ff1c14f54c6e..f3a23f6888ab3 100644 --- a/src/test/ui/derives/derive-on-trait-item-or-impl-item.rs +++ b/src/test/ui/derives/derive-on-trait-item-or-impl-item.rs @@ -14,6 +14,8 @@ trait Foo { type Bar; } +struct Bar; + impl Bar { #[derive(Clone)] //~^ ERROR `derive` may only be applied to structs, enums and unions diff --git a/src/test/ui/derives/derive-on-trait-item-or-impl-item.stderr b/src/test/ui/derives/derive-on-trait-item-or-impl-item.stderr index 8246889b620be..29db68d94b076 100644 --- a/src/test/ui/derives/derive-on-trait-item-or-impl-item.stderr +++ b/src/test/ui/derives/derive-on-trait-item-or-impl-item.stderr @@ -5,7 +5,7 @@ LL | #[derive(Clone)] | ^^^^^^^^^^^^^^^^ error: `derive` may only be applied to structs, enums and unions - --> $DIR/derive-on-trait-item-or-impl-item.rs:18:5 + --> $DIR/derive-on-trait-item-or-impl-item.rs:20:5 | LL | #[derive(Clone)] | ^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/did_you_mean/issue-40396.rs b/src/test/ui/did_you_mean/issue-40396.rs index eb62dc5408494..6b4283c65ac28 100644 --- a/src/test/ui/did_you_mean/issue-40396.rs +++ b/src/test/ui/did_you_mean/issue-40396.rs @@ -9,16 +9,29 @@ // except according to those terms. fn foo() { - println!("{:?}", (0..13).collect>()); //~ ERROR chained comparison + (0..13).collect>(); + //~^ ERROR chained comparison + //~| ERROR expected value, found struct `Vec` + //~| ERROR expected value, found builtin type `i32` + //~| ERROR attempted to take value of method `collect` } fn bar() { - println!("{:?}", Vec::new()); //~ ERROR chained comparison + Vec::new(); + //~^ ERROR chained comparison + //~| ERROR expected value, found struct `Vec` + //~| ERROR expected value, found builtin type `i32` + //~| ERROR cannot find function `new` in the crate root } fn qux() { - println!("{:?}", (0..13).collect()); //~ ERROR chained comparison + (0..13).collect(); //~^ ERROR chained comparison + //~| ERROR chained comparison + //~| ERROR expected value, found struct `Vec` + //~| ERROR expected value, found builtin type `i32` + //~| ERROR attempted to take value of method `collect` + //~| ERROR mismatched types } fn main() {} diff --git a/src/test/ui/did_you_mean/issue-40396.stderr b/src/test/ui/did_you_mean/issue-40396.stderr index 219fd45665a94..22f1acbea6c97 100644 --- a/src/test/ui/did_you_mean/issue-40396.stderr +++ b/src/test/ui/did_you_mean/issue-40396.stderr @@ -1,38 +1,107 @@ error: chained comparison operators require parentheses - --> $DIR/issue-40396.rs:12:37 + --> $DIR/issue-40396.rs:12:20 | -LL | println!("{:?}", (0..13).collect>()); //~ ERROR chained comparison - | ^^^^^^^^ +LL | (0..13).collect>(); + | ^^^^^^^^ | = help: use `::<...>` instead of `<...>` if you meant to specify type arguments = help: or use `(...)` if you meant to specify fn arguments error: chained comparison operators require parentheses - --> $DIR/issue-40396.rs:16:25 + --> $DIR/issue-40396.rs:20:8 | -LL | println!("{:?}", Vec::new()); //~ ERROR chained comparison - | ^^^^^^^ +LL | Vec::new(); + | ^^^^^^^ | = help: use `::<...>` instead of `<...>` if you meant to specify type arguments = help: or use `(...)` if you meant to specify fn arguments error: chained comparison operators require parentheses - --> $DIR/issue-40396.rs:20:37 + --> $DIR/issue-40396.rs:28:20 | -LL | println!("{:?}", (0..13).collect()); //~ ERROR chained comparison - | ^^^^^^^^ +LL | (0..13).collect(); + | ^^^^^^^^ | = help: use `::<...>` instead of `<...>` if you meant to specify type arguments = help: or use `(...)` if you meant to specify fn arguments error: chained comparison operators require parentheses - --> $DIR/issue-40396.rs:20:41 + --> $DIR/issue-40396.rs:28:24 | -LL | println!("{:?}", (0..13).collect()); //~ ERROR chained comparison - | ^^^^^^ +LL | (0..13).collect(); + | ^^^^^^ | = help: use `::<...>` instead of `<...>` if you meant to specify type arguments = help: or use `(...)` if you meant to specify fn arguments -error: aborting due to 4 previous errors +error[E0423]: expected value, found struct `Vec` + --> $DIR/issue-40396.rs:12:21 + | +LL | (0..13).collect>(); + | ^^^ did you mean `Vec { /* fields */ }`? + +error[E0423]: expected value, found builtin type `i32` + --> $DIR/issue-40396.rs:12:25 + | +LL | (0..13).collect>(); + | ^^^ not a value + +error[E0423]: expected value, found struct `Vec` + --> $DIR/issue-40396.rs:20:5 + | +LL | Vec::new(); + | ^^^ did you mean `Vec { /* fields */ }`? + +error[E0423]: expected value, found builtin type `i32` + --> $DIR/issue-40396.rs:20:9 + | +LL | Vec::new(); + | ^^^ not a value + +error[E0425]: cannot find function `new` in the crate root + --> $DIR/issue-40396.rs:20:15 + | +LL | Vec::new(); + | ^^^ not found in the crate root + +error[E0423]: expected value, found struct `Vec` + --> $DIR/issue-40396.rs:28:21 + | +LL | (0..13).collect(); + | ^^^ did you mean `Vec { /* fields */ }`? + +error[E0423]: expected value, found builtin type `i32` + --> $DIR/issue-40396.rs:28:25 + | +LL | (0..13).collect(); + | ^^^ not a value + +error[E0615]: attempted to take value of method `collect` on type `std::ops::Range<{integer}>` + --> $DIR/issue-40396.rs:12:13 + | +LL | (0..13).collect>(); + | ^^^^^^^ + | + = help: maybe a `()` to call it is missing? + +error[E0615]: attempted to take value of method `collect` on type `std::ops::Range<{integer}>` + --> $DIR/issue-40396.rs:28:13 + | +LL | (0..13).collect(); + | ^^^^^^^ + | + = help: maybe a `()` to call it is missing? + +error[E0308]: mismatched types + --> $DIR/issue-40396.rs:28:29 + | +LL | (0..13).collect(); + | ^^ expected bool, found () + | + = note: expected type `bool` + found type `()` + +error: aborting due to 14 previous errors +Some errors occurred: E0308, E0423, E0425, E0615. +For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/editions/edition-keywords-2015-2015-parsing.rs b/src/test/ui/editions/edition-keywords-2015-2015-parsing.rs index bdb190c748ace..02bb1077b8661 100644 --- a/src/test/ui/editions/edition-keywords-2015-2015-parsing.rs +++ b/src/test/ui/editions/edition-keywords-2015-2015-parsing.rs @@ -14,6 +14,10 @@ #[macro_use] extern crate edition_kw_macro_2015; +mod module { + pub fn async() {} +} + pub fn check_async() { let mut async = 1; // OK let mut r#async = 1; // OK @@ -28,3 +32,5 @@ pub fn check_async() { module::async(); // OK module::r#async(); // OK } + +fn main() {} diff --git a/src/test/ui/editions/edition-keywords-2015-2015-parsing.stderr b/src/test/ui/editions/edition-keywords-2015-2015-parsing.stderr index 8bf8c3c356030..f8f112941bb85 100644 --- a/src/test/ui/editions/edition-keywords-2015-2015-parsing.stderr +++ b/src/test/ui/editions/edition-keywords-2015-2015-parsing.stderr @@ -1,11 +1,11 @@ error: no rules expected the token `r#async` - --> $DIR/edition-keywords-2015-2015-parsing.rs:22:31 + --> $DIR/edition-keywords-2015-2015-parsing.rs:26:31 | LL | r#async = consumes_async!(r#async); //~ ERROR no rules expected the token `r#async` | ^^^^^^^ no rules expected this token in macro call error: no rules expected the token `async` - --> $DIR/edition-keywords-2015-2015-parsing.rs:23:35 + --> $DIR/edition-keywords-2015-2015-parsing.rs:27:35 | LL | r#async = consumes_async_raw!(async); //~ ERROR no rules expected the token `async` | ^^^^^ no rules expected this token in macro call diff --git a/src/test/ui/editions/edition-keywords-2015-2018-expansion.rs b/src/test/ui/editions/edition-keywords-2015-2018-expansion.rs index 291fd0285e57c..249519d55a75b 100644 --- a/src/test/ui/editions/edition-keywords-2015-2018-expansion.rs +++ b/src/test/ui/editions/edition-keywords-2015-2018-expansion.rs @@ -20,3 +20,5 @@ mod one_async { mod two_async { produces_async_raw! {} // OK } + +fn main() {} diff --git a/src/test/ui/editions/edition-keywords-2015-2018-parsing.rs b/src/test/ui/editions/edition-keywords-2015-2018-parsing.rs index 1b7bfb530596a..492dd62a6c3da 100644 --- a/src/test/ui/editions/edition-keywords-2015-2018-parsing.rs +++ b/src/test/ui/editions/edition-keywords-2015-2018-parsing.rs @@ -14,6 +14,10 @@ #[macro_use] extern crate edition_kw_macro_2018; +mod module { + pub fn async() {} +} + pub fn check_async() { let mut async = 1; // OK let mut r#async = 1; // OK @@ -28,3 +32,5 @@ pub fn check_async() { module::async(); // OK module::r#async(); // OK } + +fn main() {} diff --git a/src/test/ui/editions/edition-keywords-2015-2018-parsing.stderr b/src/test/ui/editions/edition-keywords-2015-2018-parsing.stderr index 77622548bce93..5b71507430258 100644 --- a/src/test/ui/editions/edition-keywords-2015-2018-parsing.stderr +++ b/src/test/ui/editions/edition-keywords-2015-2018-parsing.stderr @@ -1,11 +1,11 @@ error: no rules expected the token `r#async` - --> $DIR/edition-keywords-2015-2018-parsing.rs:22:31 + --> $DIR/edition-keywords-2015-2018-parsing.rs:26:31 | LL | r#async = consumes_async!(r#async); //~ ERROR no rules expected the token `r#async` | ^^^^^^^ no rules expected this token in macro call error: no rules expected the token `async` - --> $DIR/edition-keywords-2015-2018-parsing.rs:23:35 + --> $DIR/edition-keywords-2015-2018-parsing.rs:27:35 | LL | r#async = consumes_async_raw!(async); //~ ERROR no rules expected the token `async` | ^^^^^ no rules expected this token in macro call diff --git a/src/test/ui/editions/edition-keywords-2018-2018-expansion.rs b/src/test/ui/editions/edition-keywords-2018-2018-expansion.rs index 81bef913ac6ca..ad9c7ca1e87a8 100644 --- a/src/test/ui/editions/edition-keywords-2018-2018-expansion.rs +++ b/src/test/ui/editions/edition-keywords-2018-2018-expansion.rs @@ -20,3 +20,5 @@ mod one_async { mod two_async { produces_async_raw! {} // OK } + +fn main() {} diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-derive-2.rs b/src/test/ui/feature-gate/issue-43106-gating-of-derive-2.rs index 2dbc6cb140db3..96c96b2010469 100644 --- a/src/test/ui/feature-gate/issue-43106-gating-of-derive-2.rs +++ b/src/test/ui/feature-gate/issue-43106-gating-of-derive-2.rs @@ -23,3 +23,5 @@ mod derive { //~^ ERROR cannot find derive macro `x3300` in this scope struct S; } + +fn main() {} diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-derive.rs b/src/test/ui/feature-gate/issue-43106-gating-of-derive.rs index e5293ebb94ddc..88cad6bc501f4 100644 --- a/src/test/ui/feature-gate/issue-43106-gating-of-derive.rs +++ b/src/test/ui/feature-gate/issue-43106-gating-of-derive.rs @@ -41,3 +41,5 @@ mod derive { //~^ ERROR `derive` may only be applied to structs, enums and unions impl S { } } + +fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-cfg-target-has-atomic.rs b/src/test/ui/feature-gates/feature-gate-cfg-target-has-atomic.rs index 6b70c1ea294c5..e4413f449ef13 100644 --- a/src/test/ui/feature-gates/feature-gate-cfg-target-has-atomic.rs +++ b/src/test/ui/feature-gates/feature-gate-cfg-target-has-atomic.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(intrinsics, lang_items, no_core)] + #![crate_type="rlib"] #![no_core] diff --git a/src/test/ui/feature-gates/feature-gate-cfg-target-has-atomic.stderr b/src/test/ui/feature-gates/feature-gate-cfg-target-has-atomic.stderr index 81f20112a12ff..a042f2f6948f4 100644 --- a/src/test/ui/feature-gates/feature-gate-cfg-target-has-atomic.stderr +++ b/src/test/ui/feature-gates/feature-gate-cfg-target-has-atomic.stderr @@ -1,5 +1,5 @@ error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976) - --> $DIR/feature-gate-cfg-target-has-atomic.rs:23:7 + --> $DIR/feature-gate-cfg-target-has-atomic.rs:25:7 | LL | #[cfg(target_has_atomic = "8")] | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,7 +7,7 @@ LL | #[cfg(target_has_atomic = "8")] = help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976) - --> $DIR/feature-gate-cfg-target-has-atomic.rs:29:7 + --> $DIR/feature-gate-cfg-target-has-atomic.rs:31:7 | LL | #[cfg(target_has_atomic = "8")] | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -15,7 +15,7 @@ LL | #[cfg(target_has_atomic = "8")] = help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976) - --> $DIR/feature-gate-cfg-target-has-atomic.rs:34:7 + --> $DIR/feature-gate-cfg-target-has-atomic.rs:36:7 | LL | #[cfg(target_has_atomic = "16")] | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -23,7 +23,7 @@ LL | #[cfg(target_has_atomic = "16")] = help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976) - --> $DIR/feature-gate-cfg-target-has-atomic.rs:39:7 + --> $DIR/feature-gate-cfg-target-has-atomic.rs:41:7 | LL | #[cfg(target_has_atomic = "16")] | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -31,7 +31,7 @@ LL | #[cfg(target_has_atomic = "16")] = help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976) - --> $DIR/feature-gate-cfg-target-has-atomic.rs:44:7 + --> $DIR/feature-gate-cfg-target-has-atomic.rs:46:7 | LL | #[cfg(target_has_atomic = "32")] | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -39,7 +39,7 @@ LL | #[cfg(target_has_atomic = "32")] = help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976) - --> $DIR/feature-gate-cfg-target-has-atomic.rs:49:7 + --> $DIR/feature-gate-cfg-target-has-atomic.rs:51:7 | LL | #[cfg(target_has_atomic = "32")] | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -47,7 +47,7 @@ LL | #[cfg(target_has_atomic = "32")] = help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976) - --> $DIR/feature-gate-cfg-target-has-atomic.rs:54:7 + --> $DIR/feature-gate-cfg-target-has-atomic.rs:56:7 | LL | #[cfg(target_has_atomic = "64")] | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -55,7 +55,7 @@ LL | #[cfg(target_has_atomic = "64")] = help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976) - --> $DIR/feature-gate-cfg-target-has-atomic.rs:59:7 + --> $DIR/feature-gate-cfg-target-has-atomic.rs:61:7 | LL | #[cfg(target_has_atomic = "64")] | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -63,7 +63,7 @@ LL | #[cfg(target_has_atomic = "64")] = help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976) - --> $DIR/feature-gate-cfg-target-has-atomic.rs:64:7 + --> $DIR/feature-gate-cfg-target-has-atomic.rs:66:7 | LL | #[cfg(target_has_atomic = "128")] | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -71,7 +71,7 @@ LL | #[cfg(target_has_atomic = "128")] = help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976) - --> $DIR/feature-gate-cfg-target-has-atomic.rs:69:7 + --> $DIR/feature-gate-cfg-target-has-atomic.rs:71:7 | LL | #[cfg(target_has_atomic = "128")] | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -79,7 +79,7 @@ LL | #[cfg(target_has_atomic = "128")] = help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976) - --> $DIR/feature-gate-cfg-target-has-atomic.rs:74:7 + --> $DIR/feature-gate-cfg-target-has-atomic.rs:76:7 | LL | #[cfg(target_has_atomic = "ptr")] | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -87,7 +87,7 @@ LL | #[cfg(target_has_atomic = "ptr")] = help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976) - --> $DIR/feature-gate-cfg-target-has-atomic.rs:79:7 + --> $DIR/feature-gate-cfg-target-has-atomic.rs:81:7 | LL | #[cfg(target_has_atomic = "ptr")] | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -95,7 +95,7 @@ LL | #[cfg(target_has_atomic = "ptr")] = help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976) - --> $DIR/feature-gate-cfg-target-has-atomic.rs:86:10 + --> $DIR/feature-gate-cfg-target-has-atomic.rs:88:10 | LL | cfg!(target_has_atomic = "8"); | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -103,7 +103,7 @@ LL | cfg!(target_has_atomic = "8"); = help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976) - --> $DIR/feature-gate-cfg-target-has-atomic.rs:88:10 + --> $DIR/feature-gate-cfg-target-has-atomic.rs:90:10 | LL | cfg!(target_has_atomic = "16"); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -111,7 +111,7 @@ LL | cfg!(target_has_atomic = "16"); = help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976) - --> $DIR/feature-gate-cfg-target-has-atomic.rs:90:10 + --> $DIR/feature-gate-cfg-target-has-atomic.rs:92:10 | LL | cfg!(target_has_atomic = "32"); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -119,7 +119,7 @@ LL | cfg!(target_has_atomic = "32"); = help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976) - --> $DIR/feature-gate-cfg-target-has-atomic.rs:92:10 + --> $DIR/feature-gate-cfg-target-has-atomic.rs:94:10 | LL | cfg!(target_has_atomic = "64"); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -127,7 +127,7 @@ LL | cfg!(target_has_atomic = "64"); = help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976) - --> $DIR/feature-gate-cfg-target-has-atomic.rs:94:10 + --> $DIR/feature-gate-cfg-target-has-atomic.rs:96:10 | LL | cfg!(target_has_atomic = "128"); | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -135,7 +135,7 @@ LL | cfg!(target_has_atomic = "128"); = help: add #![feature(cfg_target_has_atomic)] to the crate attributes to enable error[E0658]: `cfg(target_has_atomic)` is experimental and subject to change (see issue #32976) - --> $DIR/feature-gate-cfg-target-has-atomic.rs:96:10 + --> $DIR/feature-gate-cfg-target-has-atomic.rs:98:10 | LL | cfg!(target_has_atomic = "ptr"); | ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/feature-gates/feature-gate-macros_in_extern.rs b/src/test/ui/feature-gates/feature-gate-macros_in_extern.rs index 77080e3c348f9..8fe67c14e7f29 100644 --- a/src/test/ui/feature-gates/feature-gate-macros_in_extern.rs +++ b/src/test/ui/feature-gates/feature-gate-macros_in_extern.rs @@ -33,3 +33,5 @@ extern { emits_nothing!(); //~^ ERROR macro invocations in `extern {}` blocks are experimental } + +fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-rustc-attrs.rs b/src/test/ui/feature-gates/feature-gate-rustc-attrs.rs index 99bc51b69c6cb..7a2bfdf7f7584 100644 --- a/src/test/ui/feature-gates/feature-gate-rustc-attrs.rs +++ b/src/test/ui/feature-gates/feature-gate-rustc-attrs.rs @@ -8,11 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// ignore-tidy-linelength - // Test that `#[rustc_*]` attributes are gated by `rustc_attrs` feature gate. #[rustc_foo] -//~^ ERROR unless otherwise specified, attributes with the prefix `rustc_` are reserved for internal compiler diagnostics +//~^ ERROR unless otherwise specified, attributes with the prefix `rustc_` are reserved fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-rustc-attrs.stderr b/src/test/ui/feature-gates/feature-gate-rustc-attrs.stderr index 882549c1eafba..40708baaaefbf 100644 --- a/src/test/ui/feature-gates/feature-gate-rustc-attrs.stderr +++ b/src/test/ui/feature-gates/feature-gate-rustc-attrs.stderr @@ -1,5 +1,5 @@ error[E0658]: unless otherwise specified, attributes with the prefix `rustc_` are reserved for internal compiler diagnostics (see issue #29642) - --> $DIR/feature-gate-rustc-attrs.rs:15:3 + --> $DIR/feature-gate-rustc-attrs.rs:13:3 | LL | #[rustc_foo] | ^^^^^^^^^ diff --git a/src/test/ui/issues/issue-10536.rs b/src/test/ui/issues/issue-10536.rs index 2b71fb5c67f7a..0976d9abf14ed 100644 --- a/src/test/ui/issues/issue-10536.rs +++ b/src/test/ui/issues/issue-10536.rs @@ -11,8 +11,6 @@ // We only want to assert that this doesn't ICE, we don't particularly care // about whether it nor it fails to compile. -// error-pattern: - macro_rules! foo{ () => {{ macro_rules! bar{() => (())} @@ -25,9 +23,12 @@ pub fn main() { assert!({one! two()}); //~^ ERROR macros that expand to items must either be surrounded with braces or followed by a + //~| ERROR cannot find macro `one!` in this scope + //~| ERROR mismatched types // regardless of whether nested macro_rules works, the following should at // least throw a conventional error. assert!({one! two}); - //~^ ERROR expected + //~^ ERROR expected `(` or `{`, found `}` + //~| ERROR cannot apply unary operator `!` to type `!` } diff --git a/src/test/ui/issues/issue-10536.stderr b/src/test/ui/issues/issue-10536.stderr index ba404d0dd3f63..bf3a6fadd9909 100644 --- a/src/test/ui/issues/issue-10536.stderr +++ b/src/test/ui/issues/issue-10536.stderr @@ -1,5 +1,5 @@ error: macros that expand to items must either be surrounded with braces or followed by a semicolon - --> $DIR/issue-10536.rs:26:22 + --> $DIR/issue-10536.rs:24:22 | LL | assert!({one! two()}); | ^^ @@ -10,5 +10,28 @@ error: expected `(` or `{`, found `}` LL | assert!({one! two}); | ^ expected `(` or `{` -error: aborting due to 2 previous errors +error: cannot find macro `one!` in this scope + --> $DIR/issue-10536.rs:24:14 + | +LL | assert!({one! two()}); + | ^^^ + +error[E0308]: mismatched types + --> $DIR/issue-10536.rs:24:13 + | +LL | assert!({one! two()}); + | ^^^^^^^^^^^^ expected bool, found () + | + = note: expected type `bool` + found type `()` + +error[E0600]: cannot apply unary operator `!` to type `!` + --> $DIR/issue-10536.rs:31:5 + | +LL | assert!({one! two}); + | ^^^^^^^^^^^^^^^^^^^^ cannot apply unary operator `!` + +error: aborting due to 5 previous errors +Some errors occurred: E0308, E0600. +For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/issues/issue-11692-1.rs b/src/test/ui/issues/issue-11692-1.rs index ff6009da72fd9..da766d441b6b9 100644 --- a/src/test/ui/issues/issue-11692-1.rs +++ b/src/test/ui/issues/issue-11692-1.rs @@ -11,4 +11,5 @@ fn main() { print!(testo!()); //~^ ERROR: format argument must be a string literal + //~| ERROR: cannot find macro `testo!` in this scope } diff --git a/src/test/ui/issues/issue-11692-1.stderr b/src/test/ui/issues/issue-11692-1.stderr index 61ff455d16ca5..f068531485fa5 100644 --- a/src/test/ui/issues/issue-11692-1.stderr +++ b/src/test/ui/issues/issue-11692-1.stderr @@ -8,5 +8,11 @@ help: you might be missing a string literal to format with LL | print!("{}", testo!()); | ^^^^^ -error: aborting due to previous error +error: cannot find macro `testo!` in this scope + --> $DIR/issue-11692-1.rs:12:12 + | +LL | print!(testo!()); + | ^^^^^ + +error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-11692-2.rs b/src/test/ui/issues/issue-11692-2.rs index a4b8b48384d7a..34c14a66445dc 100644 --- a/src/test/ui/issues/issue-11692-2.rs +++ b/src/test/ui/issues/issue-11692-2.rs @@ -10,4 +10,5 @@ fn main() { concat!(test!()); //~ ERROR cannot find macro `test!` in this scope + //~| ERROR expected a literal } diff --git a/src/test/ui/issues/issue-11692-2.stderr b/src/test/ui/issues/issue-11692-2.stderr index 85f600dbff24e..4b4f95d2fb2e7 100644 --- a/src/test/ui/issues/issue-11692-2.stderr +++ b/src/test/ui/issues/issue-11692-2.stderr @@ -1,8 +1,16 @@ +error: expected a literal + --> $DIR/issue-11692-2.rs:12:13 + | +LL | concat!(test!()); //~ ERROR cannot find macro `test!` in this scope + | ^^^^^^^ + | + = note: only literals (like `"foo"`, `42` and `3.14`) can be passed to `concat!()` + error: cannot find macro `test!` in this scope --> $DIR/issue-11692-2.rs:12:13 | LL | concat!(test!()); //~ ERROR cannot find macro `test!` in this scope | ^^^^ -error: aborting due to previous error +error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-32950.rs b/src/test/ui/issues/issue-32950.rs index 4e5cdd50b2a95..622bb4ca989f9 100644 --- a/src/test/ui/issues/issue-32950.rs +++ b/src/test/ui/issues/issue-32950.rs @@ -13,6 +13,7 @@ #[derive(Debug)] struct Baz( concat_idents!(Foo, Bar) //~ ERROR `derive` cannot be used on items with type macros + //~^ ERROR cannot find type `FooBar` in this scope ); fn main() {} diff --git a/src/test/ui/issues/issue-32950.stderr b/src/test/ui/issues/issue-32950.stderr index 0363bf05f0080..b0e5deba21319 100644 --- a/src/test/ui/issues/issue-32950.stderr +++ b/src/test/ui/issues/issue-32950.stderr @@ -4,5 +4,12 @@ error: `derive` cannot be used on items with type macros LL | concat_idents!(Foo, Bar) //~ ERROR `derive` cannot be used on items with type macros | ^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error[E0412]: cannot find type `FooBar` in this scope + --> $DIR/issue-32950.rs:15:5 + | +LL | concat_idents!(Foo, Bar) //~ ERROR `derive` cannot be used on items with type macros + | ^^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope + +error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0412`. diff --git a/src/test/ui/issues/issue-33571.rs b/src/test/ui/issues/issue-33571.rs index 5dfc41c8f4a48..f91cf407a6590 100644 --- a/src/test/ui/issues/issue-33571.rs +++ b/src/test/ui/issues/issue-33571.rs @@ -12,3 +12,5 @@ Sync, //~ ERROR this unsafe trait should be implemented explicitly Copy)] enum Foo {} + +fn main() {} diff --git a/src/test/ui/issues/issue-35677.rs b/src/test/ui/issues/issue-35677.rs index 46d3f7e4af00b..71e2125ffd2cc 100644 --- a/src/test/ui/issues/issue-35677.rs +++ b/src/test/ui/issues/issue-35677.rs @@ -3,3 +3,5 @@ fn intersect_map(this: &mut HashMap, other: HashMap) -> bool { this.drain() //~^ ERROR no method named } + +fn main() {} diff --git a/src/test/ui/issues/issue-35677.stderr b/src/test/ui/issues/issue-35677.stderr index dca096b93f5f3..61ddb75b3b52c 100644 --- a/src/test/ui/issues/issue-35677.stderr +++ b/src/test/ui/issues/issue-35677.stderr @@ -1,7 +1,3 @@ -error[E0601]: `main` function not found in crate `issue_35677` - | - = note: consider adding a `main` function to `$DIR/issue-35677.rs` - error[E0599]: no method named `drain` found for type `&mut std::collections::HashMap` in the current scope --> $DIR/issue-35677.rs:3:10 | @@ -12,7 +8,6 @@ LL | this.drain() `K : std::cmp::Eq` `K : std::hash::Hash` -error: aborting due to 2 previous errors +error: aborting due to previous error -Some errors occurred: E0599, E0601. -For more information about an error, try `rustc --explain E0599`. +For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/issues/issue-36617.rs b/src/test/ui/issues/issue-36617.rs index 9f5eeb1a45dc8..d3ae783a3dcd9 100644 --- a/src/test/ui/issues/issue-36617.rs +++ b/src/test/ui/issues/issue-36617.rs @@ -9,3 +9,5 @@ // except according to those terms. #![derive(Copy)] //~ ERROR `derive` may only be applied to structs, enums and unions + +fn main() {} diff --git a/src/test/ui/issues/issue-43023.rs b/src/test/ui/issues/issue-43023.rs index 6a5f7a1136aaa..0084ace803ccc 100644 --- a/src/test/ui/issues/issue-43023.rs +++ b/src/test/ui/issues/issue-43023.rs @@ -26,3 +26,5 @@ trait Tr2 { #[derive(Debug)] //~ ERROR `derive` may only be applied to structs, enums and unions type F; } + +fn main() {} diff --git a/src/test/ui/issues/issue-46438.rs b/src/test/ui/issues/issue-46438.rs index d84b58133853f..6676f2b808ccc 100644 --- a/src/test/ui/issues/issue-46438.rs +++ b/src/test/ui/issues/issue-46438.rs @@ -14,7 +14,7 @@ macro_rules! m { } } -trait Trait {} +trait Tr {} m!(Tr); diff --git a/src/test/ui/issues/issue-49074.rs b/src/test/ui/issues/issue-49074.rs index d255fac5427b6..9ff04c3b80b57 100644 --- a/src/test/ui/issues/issue-49074.rs +++ b/src/test/ui/issues/issue-49074.rs @@ -19,5 +19,5 @@ mod foo { } fn main() { - bar!(); + bar!(); //~ ERROR cannot find macro `bar!` in this scope } diff --git a/src/test/ui/issues/issue-49074.stderr b/src/test/ui/issues/issue-49074.stderr index 6c9d1eac35684..e32cb23f66527 100644 --- a/src/test/ui/issues/issue-49074.stderr +++ b/src/test/ui/issues/issue-49074.stderr @@ -6,6 +6,14 @@ LL | #[marco_use] // typo | = help: add #![feature(custom_attribute)] to the crate attributes to enable -error: aborting due to previous error +error: cannot find macro `bar!` in this scope + --> $DIR/issue-49074.rs:22:4 + | +LL | bar!(); //~ ERROR cannot find macro `bar!` in this scope + | ^^^ + | + = help: have you added the `#[macro_use]` on the module/import? + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/issues/issue-51279.rs b/src/test/ui/issues/issue-51279.rs index 4639d73e44d3d..7088c1a8bb8fa 100644 --- a/src/test/ui/issues/issue-51279.rs +++ b/src/test/ui/issues/issue-51279.rs @@ -32,3 +32,4 @@ unsafe impl<#[cfg_attr(none, may_dangle)] T> Drop for M { type Z<#[ignored] 'a, #[cfg(none)] T> = X<'a, T>; //~^ ERROR #[cfg] cannot be applied on a generic parameter +//~| ERROR attribute `ignored` is currently unknown to the compiler diff --git a/src/test/ui/issues/issue-51279.stderr b/src/test/ui/issues/issue-51279.stderr index 38d5a5acc50fe..3485d8f27f25d 100644 --- a/src/test/ui/issues/issue-51279.stderr +++ b/src/test/ui/issues/issue-51279.stderr @@ -46,5 +46,14 @@ error: #[cfg] cannot be applied on a generic parameter LL | type Z<#[ignored] 'a, #[cfg(none)] T> = X<'a, T>; | ^^^^^^^^^^^^ -error: aborting due to 8 previous errors +error[E0658]: The attribute `ignored` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642) + --> $DIR/issue-51279.rs:33:8 + | +LL | type Z<#[ignored] 'a, #[cfg(none)] T> = X<'a, T>; + | ^^^^^^^^^^ + | + = help: add #![feature(custom_attribute)] to the crate attributes to enable + +error: aborting due to 9 previous errors +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/issues/issue-55796.rs b/src/test/ui/issues/issue-55796.rs index a172f6a7bfad1..efdea5c9b1e16 100644 --- a/src/test/ui/issues/issue-55796.rs +++ b/src/test/ui/issues/issue-55796.rs @@ -22,3 +22,5 @@ pub trait Graph<'a> { //~^ ERROR cannot infer } } + +fn main() {} diff --git a/src/test/ui/issues/issue-55796.stderr b/src/test/ui/issues/issue-55796.stderr index f8ca0727efb7e..c05f8b85d0e98 100644 --- a/src/test/ui/issues/issue-55796.stderr +++ b/src/test/ui/issues/issue-55796.stderr @@ -1,7 +1,3 @@ -error[E0601]: `main` function not found in crate `issue_55796` - | - = note: consider adding a `main` function to `$DIR/issue-55796.rs` - error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements --> $DIR/issue-55796.rs:16:9 | @@ -44,7 +40,6 @@ LL | Box::new(self.in_edges(u).map(|e| e.target())) expected std::boxed::Box<(dyn std::iter::Iterator>::Node> + 'static)> found std::boxed::Box>::Node>> -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors -Some errors occurred: E0495, E0601. -For more information about an error, try `rustc --explain E0495`. +For more information about this error, try `rustc --explain E0495`. diff --git a/src/test/ui/issues/issue-6596-1.rs b/src/test/ui/issues/issue-6596-1.rs index ce8a3a80e1f84..457f129f2d505 100644 --- a/src/test/ui/issues/issue-6596-1.rs +++ b/src/test/ui/issues/issue-6596-1.rs @@ -13,6 +13,7 @@ macro_rules! e { ($inp:ident) => ( $nonexistent //~^ ERROR unknown macro variable `nonexistent` + //~| ERROR cannot find value `nonexistent` in this scope ); } diff --git a/src/test/ui/issues/issue-6596-1.stderr b/src/test/ui/issues/issue-6596-1.stderr index b7055ab19d0c5..2a682348386f9 100644 --- a/src/test/ui/issues/issue-6596-1.stderr +++ b/src/test/ui/issues/issue-6596-1.stderr @@ -7,5 +7,15 @@ LL | $nonexistent LL | e!(foo); | -------- in this macro invocation -error: aborting due to previous error +error[E0425]: cannot find value `nonexistent` in this scope + --> $DIR/issue-6596-1.rs:14:9 + | +LL | $nonexistent + | ^^^^^^^^^^^^ not found in this scope +... +LL | e!(foo); + | -------- in this macro invocation + +error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0425`. diff --git a/src/test/ui/issues/issue-6596-2.rs b/src/test/ui/issues/issue-6596-2.rs index 3e18de6178a63..9e8d937e8ab6f 100644 --- a/src/test/ui/issues/issue-6596-2.rs +++ b/src/test/ui/issues/issue-6596-2.rs @@ -19,5 +19,6 @@ macro_rules! g { } fn main() { + let foo = 0; g!(foo); } diff --git a/src/test/ui/macro_backtrace/main.rs b/src/test/ui/macro_backtrace/main.rs index 72a5c0d5e3728..ba8de550e5492 100644 --- a/src/test/ui/macro_backtrace/main.rs +++ b/src/test/ui/macro_backtrace/main.rs @@ -22,6 +22,8 @@ macro_rules! pong { //~| ERROR expected one of //~| ERROR expected one of +struct syntax; + fn main() { pong!(); ping!(); diff --git a/src/test/ui/macros/macro-comma-behavior.core.stderr b/src/test/ui/macros/macro-comma-behavior.core.stderr index 5ff31f050790e..fccada76d15e4 100644 --- a/src/test/ui/macros/macro-comma-behavior.core.stderr +++ b/src/test/ui/macros/macro-comma-behavior.core.stderr @@ -40,5 +40,11 @@ error: 1 positional argument in format string, but no arguments were given LL | write!(f, "{}",)?; | ^^ -error: aborting due to 7 previous errors +error: `#[panic_handler]` function required, but not found + +error: language item required, but not found: `eh_personality` + +error: language item required, but not found: `eh_unwind_resume` + +error: aborting due to 10 previous errors diff --git a/src/test/ui/malformed/malformed-derive-entry.rs b/src/test/ui/malformed/malformed-derive-entry.rs index ac000628f2b04..80e49fe7eeb91 100644 --- a/src/test/ui/malformed/malformed-derive-entry.rs +++ b/src/test/ui/malformed/malformed-derive-entry.rs @@ -23,3 +23,5 @@ struct Test3; #[derive] //~^ WARNING empty trait list struct Test4; + +fn main() {} diff --git a/src/test/ui/panic-runtime/runtime-depend-on-needs-runtime.rs b/src/test/ui/panic-runtime/runtime-depend-on-needs-runtime.rs index 7cfdacbd983c1..db932a45b455d 100644 --- a/src/test/ui/panic-runtime/runtime-depend-on-needs-runtime.rs +++ b/src/test/ui/panic-runtime/runtime-depend-on-needs-runtime.rs @@ -13,3 +13,5 @@ // error-pattern:cannot depend on a crate that needs a panic runtime extern crate depends; + +fn main() {} diff --git a/src/test/ui/panic-runtime/runtime-depend-on-needs-runtime.stderr b/src/test/ui/panic-runtime/runtime-depend-on-needs-runtime.stderr index 0e68c9b806d1d..27e27dda5effe 100644 --- a/src/test/ui/panic-runtime/runtime-depend-on-needs-runtime.stderr +++ b/src/test/ui/panic-runtime/runtime-depend-on-needs-runtime.stderr @@ -1,9 +1,4 @@ error: the crate `depends` cannot depend on a crate that needs a panic runtime, but it depends on `needs_panic_runtime` -error[E0601]: `main` function not found in crate `runtime_depend_on_needs_runtime` - | - = note: consider adding a `main` function to `$DIR/runtime-depend-on-needs-runtime.rs` +error: aborting due to previous error -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0601`. diff --git a/src/test/ui/parser/macro/pub-item-macro.rs b/src/test/ui/parser/macro/pub-item-macro.rs index 8809e9a257ddb..1bc7d7b255c88 100644 --- a/src/test/ui/parser/macro/pub-item-macro.rs +++ b/src/test/ui/parser/macro/pub-item-macro.rs @@ -24,5 +24,5 @@ mod foo { } fn main() { - let y: u32 = foo::x; + let y: u32 = foo::x; //~ ERROR static `x` is private } diff --git a/src/test/ui/parser/macro/pub-item-macro.stderr b/src/test/ui/parser/macro/pub-item-macro.stderr index f55ba469ab435..99e29a08581f6 100644 --- a/src/test/ui/parser/macro/pub-item-macro.stderr +++ b/src/test/ui/parser/macro/pub-item-macro.stderr @@ -9,5 +9,12 @@ LL | pub_x!(); | = help: try adjusting the macro to put `pub` inside the invocation -error: aborting due to previous error +error[E0603]: static `x` is private + --> $DIR/pub-item-macro.rs:27:23 + | +LL | let y: u32 = foo::x; //~ ERROR static `x` is private + | ^ + +error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0603`. diff --git a/src/test/ui/proc-macro/issue-41211.rs b/src/test/ui/proc-macro/issue-41211.rs index e0922c452b5fb..6c7e2efef6889 100644 --- a/src/test/ui/proc-macro/issue-41211.rs +++ b/src/test/ui/proc-macro/issue-41211.rs @@ -17,6 +17,7 @@ #![emit_unchanged] //~^ ERROR attribute `emit_unchanged` is currently unknown to the compiler +//~| ERROR inconsistent resolution for a macro: first custom attribute, then attribute macro extern crate issue_41211; use issue_41211::emit_unchanged; diff --git a/src/test/ui/proc-macro/issue-41211.stderr b/src/test/ui/proc-macro/issue-41211.stderr index ba5fad432b7ab..b2893edeccd1a 100644 --- a/src/test/ui/proc-macro/issue-41211.stderr +++ b/src/test/ui/proc-macro/issue-41211.stderr @@ -6,6 +6,12 @@ LL | #![emit_unchanged] | = help: add #![feature(custom_attribute)] to the crate attributes to enable -error: aborting due to previous error +error: inconsistent resolution for a macro: first custom attribute, then attribute macro + --> $DIR/issue-41211.rs:18:4 + | +LL | #![emit_unchanged] + | ^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/proc-macro/lifetimes.rs b/src/test/ui/proc-macro/lifetimes.rs index ff6464a7a3a70..c375d134b804c 100644 --- a/src/test/ui/proc-macro/lifetimes.rs +++ b/src/test/ui/proc-macro/lifetimes.rs @@ -17,3 +17,5 @@ extern crate lifetimes; use lifetimes::*; type A = single_quote_alone!(); //~ ERROR expected type, found `'` + +fn main() {} diff --git a/src/test/ui/proc-macro/more-gates.rs b/src/test/ui/proc-macro/more-gates.rs index 4c038179544ff..096fc871eec5c 100644 --- a/src/test/ui/proc-macro/more-gates.rs +++ b/src/test/ui/proc-macro/more-gates.rs @@ -10,6 +10,8 @@ // aux-build:more-gates.rs +#![feature(decl_macro)] + extern crate more_gates as foo; use foo::*; diff --git a/src/test/ui/proc-macro/more-gates.stderr b/src/test/ui/proc-macro/more-gates.stderr index d5f30d5817c93..a0db4143018cc 100644 --- a/src/test/ui/proc-macro/more-gates.stderr +++ b/src/test/ui/proc-macro/more-gates.stderr @@ -1,5 +1,5 @@ error[E0658]: procedural macros cannot expand to macro definitions (see issue #54727) - --> $DIR/more-gates.rs:17:1 + --> $DIR/more-gates.rs:19:1 | LL | #[attr2mac1] | ^^^^^^^^^^^^ @@ -7,7 +7,7 @@ LL | #[attr2mac1] = help: add #![feature(proc_macro_hygiene)] to the crate attributes to enable error[E0658]: procedural macros cannot expand to macro definitions (see issue #54727) - --> $DIR/more-gates.rs:20:1 + --> $DIR/more-gates.rs:22:1 | LL | #[attr2mac2] | ^^^^^^^^^^^^ @@ -15,7 +15,7 @@ LL | #[attr2mac2] = help: add #![feature(proc_macro_hygiene)] to the crate attributes to enable error[E0658]: procedural macros cannot expand to macro definitions (see issue #54727) - --> $DIR/more-gates.rs:24:1 + --> $DIR/more-gates.rs:26:1 | LL | mac2mac1!(); //~ ERROR: cannot expand to macro definitions | ^^^^^^^^^^^^ @@ -23,7 +23,7 @@ LL | mac2mac1!(); //~ ERROR: cannot expand to macro definitions = help: add #![feature(proc_macro_hygiene)] to the crate attributes to enable error[E0658]: procedural macros cannot expand to macro definitions (see issue #54727) - --> $DIR/more-gates.rs:25:1 + --> $DIR/more-gates.rs:27:1 | LL | mac2mac2!(); //~ ERROR: cannot expand to macro definitions | ^^^^^^^^^^^^ @@ -31,7 +31,7 @@ LL | mac2mac2!(); //~ ERROR: cannot expand to macro definitions = help: add #![feature(proc_macro_hygiene)] to the crate attributes to enable error[E0658]: procedural macros cannot expand to macro definitions (see issue #54727) - --> $DIR/more-gates.rs:27:1 + --> $DIR/more-gates.rs:29:1 | LL | tricky!(); | ^^^^^^^^^^ diff --git a/src/test/ui/proc-macro/parent-source-spans.rs b/src/test/ui/proc-macro/parent-source-spans.rs index 8f8e22ba1c34d..1989e726dea02 100644 --- a/src/test/ui/proc-macro/parent-source-spans.rs +++ b/src/test/ui/proc-macro/parent-source-spans.rs @@ -38,6 +38,9 @@ macro three($($tokens:tt)*) { macro four($($tokens:tt)*) { parent_source_spans!($($tokens)*); + //~^ ERROR cannot find value `ok` in this scope + //~| ERROR cannot find value `ok` in this scope + //~| ERROR cannot find value `ok` in this scope } fn main() { diff --git a/src/test/ui/proc-macro/parent-source-spans.stderr b/src/test/ui/proc-macro/parent-source-spans.stderr index 0442c4f6ce71f..1d7ae0780356b 100644 --- a/src/test/ui/proc-macro/parent-source-spans.stderr +++ b/src/test/ui/proc-macro/parent-source-spans.stderr @@ -35,25 +35,25 @@ LL | one!("hello", "world"); | ----------------------- in this macro invocation error: first grandparent: "hello" - --> $DIR/parent-source-spans.rs:44:5 + --> $DIR/parent-source-spans.rs:47:5 | LL | one!("hello", "world"); | ^^^^^^^^^^^^^^^^^^^^^^^ error: second grandparent: "world" - --> $DIR/parent-source-spans.rs:44:5 + --> $DIR/parent-source-spans.rs:47:5 | LL | one!("hello", "world"); | ^^^^^^^^^^^^^^^^^^^^^^^ error: first source: "hello" - --> $DIR/parent-source-spans.rs:44:5 + --> $DIR/parent-source-spans.rs:47:5 | LL | one!("hello", "world"); | ^^^^^^^^^^^^^^^^^^^^^^^ error: second source: "world" - --> $DIR/parent-source-spans.rs:44:5 + --> $DIR/parent-source-spans.rs:47:5 | LL | one!("hello", "world"); | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -77,52 +77,80 @@ LL | two!("yay", "rust"); | -------------------- in this macro invocation error: first parent: "yay" - --> $DIR/parent-source-spans.rs:50:5 + --> $DIR/parent-source-spans.rs:53:5 | LL | two!("yay", "rust"); | ^^^^^^^^^^^^^^^^^^^^ error: second parent: "rust" - --> $DIR/parent-source-spans.rs:50:5 + --> $DIR/parent-source-spans.rs:53:5 | LL | two!("yay", "rust"); | ^^^^^^^^^^^^^^^^^^^^ error: first source: "yay" - --> $DIR/parent-source-spans.rs:50:5 + --> $DIR/parent-source-spans.rs:53:5 | LL | two!("yay", "rust"); | ^^^^^^^^^^^^^^^^^^^^ error: second source: "rust" - --> $DIR/parent-source-spans.rs:50:5 + --> $DIR/parent-source-spans.rs:53:5 | LL | two!("yay", "rust"); | ^^^^^^^^^^^^^^^^^^^^ error: first final: "hip" - --> $DIR/parent-source-spans.rs:56:12 + --> $DIR/parent-source-spans.rs:59:12 | LL | three!("hip", "hop"); | ^^^^^ error: second final: "hop" - --> $DIR/parent-source-spans.rs:56:19 + --> $DIR/parent-source-spans.rs:59:19 | LL | three!("hip", "hop"); | ^^^^^ error: first source: "hip" - --> $DIR/parent-source-spans.rs:56:12 + --> $DIR/parent-source-spans.rs:59:12 | LL | three!("hip", "hop"); | ^^^^^ error: second source: "hop" - --> $DIR/parent-source-spans.rs:56:19 + --> $DIR/parent-source-spans.rs:59:19 | LL | three!("hip", "hop"); | ^^^^^ -error: aborting due to 18 previous errors +error[E0425]: cannot find value `ok` in this scope + --> $DIR/parent-source-spans.rs:40:5 + | +LL | parent_source_spans!($($tokens)*); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ did you mean `Ok`? +... +LL | one!("hello", "world"); + | ----------------------- in this macro invocation + +error[E0425]: cannot find value `ok` in this scope + --> $DIR/parent-source-spans.rs:40:5 + | +LL | parent_source_spans!($($tokens)*); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ did you mean `Ok`? +... +LL | two!("yay", "rust"); + | -------------------- in this macro invocation + +error[E0425]: cannot find value `ok` in this scope + --> $DIR/parent-source-spans.rs:40:5 + | +LL | parent_source_spans!($($tokens)*); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ did you mean `Ok`? +... +LL | three!("hip", "hop"); + | --------------------- in this macro invocation + +error: aborting due to 21 previous errors +For more information about this error, try `rustc --explain E0425`. diff --git a/src/test/ui/proc-macro/proc-macro-attributes.rs b/src/test/ui/proc-macro/proc-macro-attributes.rs index 6e52411500e22..1814752ac1779 100644 --- a/src/test/ui/proc-macro/proc-macro-attributes.rs +++ b/src/test/ui/proc-macro/proc-macro-attributes.rs @@ -13,11 +13,12 @@ #[macro_use] extern crate derive_b; -#[B] +#[B] //~ ERROR `B` is ambiguous #[C] //~ ERROR attribute `C` is currently unknown to the compiler -#[B(D)] -#[B(E = "foo")] -#[B(arbitrary tokens)] +#[B(D)] //~ ERROR `B` is ambiguous +#[B(E = "foo")] //~ ERROR `B` is ambiguous +#[B(arbitrary tokens)] //~ ERROR `B` is ambiguous + //~^ ERROR expected one of `(`, `)`, `,`, `::`, or `=`, found `tokens` #[derive(B)] struct B; diff --git a/src/test/ui/proc-macro/proc-macro-attributes.stderr b/src/test/ui/proc-macro/proc-macro-attributes.stderr index a1289c6356ae6..57f3a5f5ca66c 100644 --- a/src/test/ui/proc-macro/proc-macro-attributes.stderr +++ b/src/test/ui/proc-macro/proc-macro-attributes.stderr @@ -6,6 +6,81 @@ LL | #[C] //~ ERROR attribute `C` is currently unknown to the compiler | = help: add #![feature(custom_attribute)] to the crate attributes to enable -error: aborting due to previous error +error[E0659]: `B` is ambiguous (derive helper attribute vs any other name) + --> $DIR/proc-macro-attributes.rs:16:3 + | +LL | #[B] //~ ERROR `B` is ambiguous + | ^ ambiguous name + | +note: `B` could refer to the derive helper attribute defined here + --> $DIR/proc-macro-attributes.rs:22:10 + | +LL | #[derive(B)] + | ^ +note: `B` could also refer to the derive macro imported here + --> $DIR/proc-macro-attributes.rs:13:1 + | +LL | #[macro_use] + | ^^^^^^^^^^^^ + +error[E0659]: `B` is ambiguous (derive helper attribute vs any other name) + --> $DIR/proc-macro-attributes.rs:18:3 + | +LL | #[B(D)] //~ ERROR `B` is ambiguous + | ^ ambiguous name + | +note: `B` could refer to the derive helper attribute defined here + --> $DIR/proc-macro-attributes.rs:22:10 + | +LL | #[derive(B)] + | ^ +note: `B` could also refer to the derive macro imported here + --> $DIR/proc-macro-attributes.rs:13:1 + | +LL | #[macro_use] + | ^^^^^^^^^^^^ + +error[E0659]: `B` is ambiguous (derive helper attribute vs any other name) + --> $DIR/proc-macro-attributes.rs:19:3 + | +LL | #[B(E = "foo")] //~ ERROR `B` is ambiguous + | ^ ambiguous name + | +note: `B` could refer to the derive helper attribute defined here + --> $DIR/proc-macro-attributes.rs:22:10 + | +LL | #[derive(B)] + | ^ +note: `B` could also refer to the derive macro imported here + --> $DIR/proc-macro-attributes.rs:13:1 + | +LL | #[macro_use] + | ^^^^^^^^^^^^ + +error[E0659]: `B` is ambiguous (derive helper attribute vs any other name) + --> $DIR/proc-macro-attributes.rs:20:3 + | +LL | #[B(arbitrary tokens)] //~ ERROR `B` is ambiguous + | ^ ambiguous name + | +note: `B` could refer to the derive helper attribute defined here + --> $DIR/proc-macro-attributes.rs:22:10 + | +LL | #[derive(B)] + | ^ +note: `B` could also refer to the derive macro imported here + --> $DIR/proc-macro-attributes.rs:13:1 + | +LL | #[macro_use] + | ^^^^^^^^^^^^ + +error: expected one of `(`, `)`, `,`, `::`, or `=`, found `tokens` + --> $DIR/proc-macro-attributes.rs:20:15 + | +LL | #[B(arbitrary tokens)] //~ ERROR `B` is ambiguous + | ^^^^^^ expected one of `(`, `)`, `,`, `::`, or `=` here + +error: aborting due to 6 previous errors -For more information about this error, try `rustc --explain E0658`. +Some errors occurred: E0658, E0659. +For more information about an error, try `rustc --explain E0658`. diff --git a/src/test/ui/quote-with-interpolated.rs b/src/test/ui/quote-with-interpolated.rs index 1fafb1c7a1b94..0def0b1d7a99e 100644 --- a/src/test/ui/quote-with-interpolated.rs +++ b/src/test/ui/quote-with-interpolated.rs @@ -12,7 +12,12 @@ fn main() { macro_rules! foo { ($bar:expr) => { - quote_expr!(cx, $bar) //~ ERROR quote! with interpolated token + quote_expr!(cx, $bar) + //~^ ERROR quote! with interpolated token + //~| ERROR failed to resolve: maybe a missing `extern crate syntax;`? + //~| ERROR failed to resolve: maybe a missing `extern crate syntax;`? + //~| ERROR cannot find value `cx` in this scope + //~| ERROR cannot find function `new_parser_from_tts` in this scope } } foo!(bar); diff --git a/src/test/ui/quote-with-interpolated.stderr b/src/test/ui/quote-with-interpolated.stderr index 10b3fc0a9ae80..f96c3c56e5383 100644 --- a/src/test/ui/quote-with-interpolated.stderr +++ b/src/test/ui/quote-with-interpolated.stderr @@ -1,11 +1,40 @@ error: quote! with interpolated token --> $DIR/quote-with-interpolated.rs:15:29 | -LL | quote_expr!(cx, $bar) //~ ERROR quote! with interpolated token +LL | quote_expr!(cx, $bar) | ^^^^ ... LL | foo!(bar); | ---------- in this macro invocation -error: aborting due to previous error +error[E0433]: failed to resolve: maybe a missing `extern crate syntax;`? + --> $DIR/quote-with-interpolated.rs:15:13 + | +LL | quote_expr!(cx, $bar) + | ^^^^^^^^^^^^^^^^^^^^^ maybe a missing `extern crate syntax;`? + +error[E0433]: failed to resolve: maybe a missing `extern crate syntax;`? + --> $DIR/quote-with-interpolated.rs:15:29 + | +LL | quote_expr!(cx, $bar) + | ^^^^ maybe a missing `extern crate syntax;`? + +error[E0425]: cannot find value `cx` in this scope + --> $DIR/quote-with-interpolated.rs:15:25 + | +LL | quote_expr!(cx, $bar) + | ^^ not found in this scope +... +LL | foo!(bar); + | ---------- in this macro invocation + +error[E0425]: cannot find function `new_parser_from_tts` in this scope + --> $DIR/quote-with-interpolated.rs:15:13 + | +LL | quote_expr!(cx, $bar) + | ^^^^^^^^^^^^^^^^^^^^^ not found in this scope + +error: aborting due to 5 previous errors +Some errors occurred: E0425, E0433. +For more information about an error, try `rustc --explain E0425`. diff --git a/src/test/ui/reserved/reserved-attr-on-macro.rs b/src/test/ui/reserved/reserved-attr-on-macro.rs index db8f82a70e103..a267daaefef8a 100644 --- a/src/test/ui/reserved/reserved-attr-on-macro.rs +++ b/src/test/ui/reserved/reserved-attr-on-macro.rs @@ -8,11 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#[rustc_attribute_should_be_reserved] //~ ERROR attributes with the prefix `rustc_` are reserved +#[rustc_attribute_should_be_reserved] +//~^ ERROR unless otherwise specified, attributes with the prefix `rustc_` are reserved macro_rules! foo { () => (()); } fn main() { - foo!(); + foo!(); //~ ERROR cannot determine resolution for the macro `foo` } diff --git a/src/test/ui/reserved/reserved-attr-on-macro.stderr b/src/test/ui/reserved/reserved-attr-on-macro.stderr index efcd1ec67d7e9..9766dcb2e8f86 100644 --- a/src/test/ui/reserved/reserved-attr-on-macro.stderr +++ b/src/test/ui/reserved/reserved-attr-on-macro.stderr @@ -1,11 +1,19 @@ error[E0658]: unless otherwise specified, attributes with the prefix `rustc_` are reserved for internal compiler diagnostics (see issue #29642) --> $DIR/reserved-attr-on-macro.rs:11:3 | -LL | #[rustc_attribute_should_be_reserved] //~ ERROR attributes with the prefix `rustc_` are reserved +LL | #[rustc_attribute_should_be_reserved] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: add #![feature(rustc_attrs)] to the crate attributes to enable -error: aborting due to previous error +error: cannot determine resolution for the macro `foo` + --> $DIR/reserved-attr-on-macro.rs:18:5 + | +LL | foo!(); //~ ERROR cannot determine resolution for the macro `foo` + | ^^^ + | + = note: import resolution is stuck, try simplifying macro imports + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/self/self_type_keyword.rs b/src/test/ui/self/self_type_keyword.rs index 20d2e2ca9cfa1..783179334aae8 100644 --- a/src/test/ui/self/self_type_keyword.rs +++ b/src/test/ui/self/self_type_keyword.rs @@ -17,6 +17,7 @@ mod foo { struct Bar<'Self>; //~^ ERROR lifetimes cannot use keyword names +//~| ERROR parameter `'Self` is never used struct Foo; diff --git a/src/test/ui/self/self_type_keyword.stderr b/src/test/ui/self/self_type_keyword.stderr index 4a7b9a6ce2cee..d4d986902a938 100644 --- a/src/test/ui/self/self_type_keyword.stderr +++ b/src/test/ui/self/self_type_keyword.stderr @@ -5,43 +5,43 @@ LL | struct Self; | ^^^^ expected identifier, found keyword error: expected identifier, found keyword `Self` - --> $DIR/self_type_keyword.rs:25:13 + --> $DIR/self_type_keyword.rs:26:13 | LL | ref Self => (), | ^^^^ expected identifier, found keyword error: expected identifier, found keyword `Self` - --> $DIR/self_type_keyword.rs:27:13 + --> $DIR/self_type_keyword.rs:28:13 | LL | mut Self => (), | ^^^^ expected identifier, found keyword error: expected identifier, found keyword `Self` - --> $DIR/self_type_keyword.rs:29:17 + --> $DIR/self_type_keyword.rs:30:17 | LL | ref mut Self => (), | ^^^^ expected identifier, found keyword error: expected identifier, found keyword `Self` - --> $DIR/self_type_keyword.rs:33:15 + --> $DIR/self_type_keyword.rs:34:15 | LL | Foo { Self } => (), | ^^^^ expected identifier, found keyword error: expected identifier, found keyword `Self` - --> $DIR/self_type_keyword.rs:39:26 + --> $DIR/self_type_keyword.rs:40:26 | LL | extern crate core as Self; | ^^^^ expected identifier, found keyword error: expected identifier, found keyword `Self` - --> $DIR/self_type_keyword.rs:44:32 + --> $DIR/self_type_keyword.rs:45:32 | LL | use std::option::Option as Self; | ^^^^ expected identifier, found keyword error: expected identifier, found keyword `Self` - --> $DIR/self_type_keyword.rs:49:11 + --> $DIR/self_type_keyword.rs:50:11 | LL | trait Self {} | ^^^^ expected identifier, found keyword @@ -53,10 +53,19 @@ LL | struct Bar<'Self>; | ^^^^^ error: cannot find macro `Self!` in this scope - --> $DIR/self_type_keyword.rs:31:9 + --> $DIR/self_type_keyword.rs:32:9 | LL | Self!() => (), | ^^^^ -error: aborting due to 10 previous errors +error[E0392]: parameter `'Self` is never used + --> $DIR/self_type_keyword.rs:18:12 + | +LL | struct Bar<'Self>; + | ^^^^^ unused type parameter + | + = help: consider removing `'Self` or using a marker such as `std::marker::PhantomData` + +error: aborting due to 11 previous errors +For more information about this error, try `rustc --explain E0392`. diff --git a/src/test/ui/span/issue-36530.rs b/src/test/ui/span/issue-36530.rs index fbe1535caaed2..01d89c0f86870 100644 --- a/src/test/ui/span/issue-36530.rs +++ b/src/test/ui/span/issue-36530.rs @@ -15,3 +15,5 @@ mod foo { #![foo] //~ ERROR is currently unknown to the compiler //~| ERROR non-builtin inner attributes are unstable } + +fn main() {} diff --git a/src/test/ui/span/macro-ty-params.rs b/src/test/ui/span/macro-ty-params.rs index 5d93b1266a4ae..b18de6fba9da8 100644 --- a/src/test/ui/span/macro-ty-params.rs +++ b/src/test/ui/span/macro-ty-params.rs @@ -14,9 +14,11 @@ macro_rules! m { } } +macro_rules! foo { () => () } + fn main() { foo::!(); //~ ERROR generic arguments in macro path foo::<>!(); //~ ERROR generic arguments in macro path - m!(MyTrait<>); //~ ERROR generic arguments in macro path + m!(Default<>); //~ ERROR generic arguments in macro path //~^ ERROR unexpected generic arguments in path } diff --git a/src/test/ui/span/macro-ty-params.stderr b/src/test/ui/span/macro-ty-params.stderr index 8a40556a6cd0e..3aa619a031280 100644 --- a/src/test/ui/span/macro-ty-params.stderr +++ b/src/test/ui/span/macro-ty-params.stderr @@ -1,26 +1,26 @@ -error: unexpected generic arguments in path +error: generic arguments in macro path --> $DIR/macro-ty-params.rs:20:8 | -LL | m!(MyTrait<>); //~ ERROR generic arguments in macro path - | ^^^^^^^^^ +LL | foo::!(); //~ ERROR generic arguments in macro path + | ^^^^^ error: generic arguments in macro path - --> $DIR/macro-ty-params.rs:20:15 + --> $DIR/macro-ty-params.rs:21:8 | -LL | m!(MyTrait<>); //~ ERROR generic arguments in macro path - | ^^ +LL | foo::<>!(); //~ ERROR generic arguments in macro path + | ^^^^ -error: generic arguments in macro path - --> $DIR/macro-ty-params.rs:18:8 +error: unexpected generic arguments in path + --> $DIR/macro-ty-params.rs:22:8 | -LL | foo::!(); //~ ERROR generic arguments in macro path - | ^^^^^ +LL | m!(Default<>); //~ ERROR generic arguments in macro path + | ^^^^^^^^^ error: generic arguments in macro path - --> $DIR/macro-ty-params.rs:19:8 + --> $DIR/macro-ty-params.rs:22:15 | -LL | foo::<>!(); //~ ERROR generic arguments in macro path - | ^^^^ +LL | m!(Default<>); //~ ERROR generic arguments in macro path + | ^^ error: aborting due to 4 previous errors diff --git a/src/test/ui/span/visibility-ty-params.rs b/src/test/ui/span/visibility-ty-params.rs index 5df28971e9942..932b4a4c6ec42 100644 --- a/src/test/ui/span/visibility-ty-params.rs +++ b/src/test/ui/span/visibility-ty-params.rs @@ -14,6 +14,7 @@ macro_rules! m { struct S(T); m!{ S } //~ ERROR unexpected generic arguments in path + //~| ERROR expected module, found struct `S` mod m { m!{ m<> } //~ ERROR unexpected generic arguments in path diff --git a/src/test/ui/span/visibility-ty-params.stderr b/src/test/ui/span/visibility-ty-params.stderr index 7719bd48c85bb..8f861e02aa509 100644 --- a/src/test/ui/span/visibility-ty-params.stderr +++ b/src/test/ui/span/visibility-ty-params.stderr @@ -5,10 +5,19 @@ LL | m!{ S } //~ ERROR unexpected generic arguments in path | ^^^^^ error: unexpected generic arguments in path - --> $DIR/visibility-ty-params.rs:19:9 + --> $DIR/visibility-ty-params.rs:20:9 | LL | m!{ m<> } //~ ERROR unexpected generic arguments in path | ^^^ -error: aborting due to 2 previous errors +error[E0577]: expected module, found struct `S` + --> $DIR/visibility-ty-params.rs:16:5 + | +LL | m!{ S } //~ ERROR unexpected generic arguments in path + | -^^^^ + | | + | did you mean `m`? + +error: aborting due to 3 previous errors +For more information about this error, try `rustc --explain E0577`. diff --git a/src/test/ui/tuple/tuple-struct-fields/test2.rs b/src/test/ui/tuple/tuple-struct-fields/test2.rs index eead027cb1351..db4d2fa59cc0f 100644 --- a/src/test/ui/tuple/tuple-struct-fields/test2.rs +++ b/src/test/ui/tuple/tuple-struct-fields/test2.rs @@ -18,5 +18,7 @@ macro_rules! define_struct { } mod foo { - define_struct! { (foo) } + define_struct! { (foo) } //~ ERROR cannot find type `foo` in this scope } + +fn main() {} diff --git a/src/test/ui/tuple/tuple-struct-fields/test2.stderr b/src/test/ui/tuple/tuple-struct-fields/test2.stderr index 983e74772ac69..cb79a51b6d8c6 100644 --- a/src/test/ui/tuple/tuple-struct-fields/test2.stderr +++ b/src/test/ui/tuple/tuple-struct-fields/test2.stderr @@ -4,8 +4,15 @@ error: expected one of `)` or `,`, found `(` LL | struct S3(pub $t ()); | ^ expected one of `)` or `,` here ... -LL | define_struct! { (foo) } +LL | define_struct! { (foo) } //~ ERROR cannot find type `foo` in this scope | ------------------------ in this macro invocation -error: aborting due to previous error +error[E0412]: cannot find type `foo` in this scope + --> $DIR/test2.rs:21:23 + | +LL | define_struct! { (foo) } //~ ERROR cannot find type `foo` in this scope + | ^^^ not found in this scope + +error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0412`. diff --git a/src/test/ui/tuple/tuple-struct-fields/test3.rs b/src/test/ui/tuple/tuple-struct-fields/test3.rs index d666c8abd3c95..c5702866fe41e 100644 --- a/src/test/ui/tuple/tuple-struct-fields/test3.rs +++ b/src/test/ui/tuple/tuple-struct-fields/test3.rs @@ -18,5 +18,7 @@ macro_rules! define_struct { } mod foo { - define_struct! { foo } + define_struct! { foo } //~ ERROR cannot find type `foo` in this scope } + +fn main() {} diff --git a/src/test/ui/tuple/tuple-struct-fields/test3.stderr b/src/test/ui/tuple/tuple-struct-fields/test3.stderr index 6738595b99798..a0ac82917f153 100644 --- a/src/test/ui/tuple/tuple-struct-fields/test3.stderr +++ b/src/test/ui/tuple/tuple-struct-fields/test3.stderr @@ -4,8 +4,15 @@ error: expected one of `)` or `,`, found `(` LL | struct S3(pub($t) ()); | ^ expected one of `)` or `,` here ... -LL | define_struct! { foo } +LL | define_struct! { foo } //~ ERROR cannot find type `foo` in this scope | ---------------------- in this macro invocation -error: aborting due to previous error +error[E0412]: cannot find type `foo` in this scope + --> $DIR/test3.rs:21:22 + | +LL | define_struct! { foo } //~ ERROR cannot find type `foo` in this scope + | ^^^ not found in this scope + +error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0412`. From 577427e0be62552e4d4520d4c57066ca812648e0 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Thu, 20 Dec 2018 02:33:56 +0300 Subject: [PATCH 66/84] Get rid of `Block::recovered` --- src/librustc/hir/lowering.rs | 3 --- src/librustc/hir/mod.rs | 5 ----- src/librustc/ich/impls_hir.rs | 1 - src/librustc_driver/pretty.rs | 6 ++---- src/librustc_typeck/check/mod.rs | 7 +------ src/libsyntax/ast.rs | 1 - src/libsyntax/ext/build.rs | 1 - src/libsyntax/fold.rs | 3 +-- src/libsyntax/parse/parser.rs | 12 ++++++------ src/libsyntax_ext/deriving/mod.rs | 1 - src/test/run-pass-fulldeps/pprust-expr-roundtrip.rs | 1 - src/test/ui/issues/issue-10536.rs | 1 - src/test/ui/issues/issue-10536.stderr | 11 ++--------- 13 files changed, 12 insertions(+), 41 deletions(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 7fc68af35fe26..83e56b56c6c61 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -2719,7 +2719,6 @@ impl<'a> LoweringContext<'a> { rules: self.lower_block_check_mode(&b.rules), span: b.span, targeted_by_break, - recovered: b.recovered, }) } @@ -3791,7 +3790,6 @@ impl<'a> LoweringContext<'a> { rules: hir::DefaultBlock, span, targeted_by_break: false, - recovered: blk.recovered, }); P(self.expr_block(blk, ThinVec::new())) } @@ -4833,7 +4831,6 @@ impl<'a> LoweringContext<'a> { rules: hir::DefaultBlock, span, targeted_by_break: false, - recovered: false, } } diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 90c18c748789f..b23ed69201e14 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -817,11 +817,6 @@ pub struct Block { /// break out of this block early. /// Used by `'label: {}` blocks and by `catch` statements. pub targeted_by_break: bool, - /// If true, don't emit return value type errors as the parser had - /// to recover from a parse error so this block will not have an - /// appropriate type. A parse error will have been emitted so the - /// compilation will never succeed if this is true. - pub recovered: bool, } #[derive(Clone, RustcEncodable, RustcDecodable)] diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs index 8a48563a6c5d0..cd8360678b50c 100644 --- a/src/librustc/ich/impls_hir.rs +++ b/src/librustc/ich/impls_hir.rs @@ -420,7 +420,6 @@ impl_stable_hash_for!(struct hir::Block { rules, span, targeted_by_break, - recovered, }); impl_stable_hash_for!(struct hir::Pat { diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs index bc991016bbee5..551244f7fe227 100644 --- a/src/librustc_driver/pretty.rs +++ b/src/librustc_driver/pretty.rs @@ -751,7 +751,6 @@ impl<'a> fold::Folder for ReplaceBodyWithLoop<'a> { fn fold_block(&mut self, b: P) -> P { fn stmt_to_block(rules: ast::BlockCheckMode, - recovered: bool, s: Option, sess: &Session) -> ast::Block { ast::Block { @@ -759,7 +758,6 @@ impl<'a> fold::Folder for ReplaceBodyWithLoop<'a> { rules, id: sess.next_node_id(), span: syntax_pos::DUMMY_SP, - recovered, } } @@ -778,7 +776,7 @@ impl<'a> fold::Folder for ReplaceBodyWithLoop<'a> { } } - let empty_block = stmt_to_block(BlockCheckMode::Default, false, None, self.sess); + let empty_block = stmt_to_block(BlockCheckMode::Default, None, self.sess); let loop_expr = P(ast::Expr { node: ast::ExprKind::Loop(P(empty_block), None), id: self.sess.next_node_id(), @@ -819,7 +817,7 @@ impl<'a> fold::Folder for ReplaceBodyWithLoop<'a> { old_blocks.push(new_block); } - stmt_to_block(b.rules, b.recovered, Some(loop_stmt), self.sess) + stmt_to_block(b.rules, Some(loop_stmt), self.sess) } else { //push `loop {}` onto the end of our fresh block and yield that new_block.stmts.push(loop_stmt); diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 2c50be15d6f86..22efa2381b145 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -4757,12 +4757,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // // #41425 -- label the implicit `()` as being the // "found type" here, rather than the "expected type". - // - // #44579 -- if the block was recovered during parsing, - // the type would be nonsensical and it is not worth it - // to perform the type check, so we avoid generating the - // diagnostic output. - if !self.diverges.get().always() && !blk.recovered { + if !self.diverges.get().always() { coerce.coerce_forced_unit(self, &self.misc(blk.span), &mut |err| { if let Some(expected_ty) = expected.only_has_type(self) { self.consider_hint_about_removing_semicolon(blk, diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 50c9e14068ab6..46d12a1706564 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -454,7 +454,6 @@ pub struct Block { /// Distinguishes between `unsafe { ... }` and `{ ... }` pub rules: BlockCheckMode, pub span: Span, - pub recovered: bool, } #[derive(Clone, RustcEncodable, RustcDecodable)] diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index 5770f6bb8a28c..b1673a807e304 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -597,7 +597,6 @@ impl<'a> AstBuilder for ExtCtxt<'a> { id: ast::DUMMY_NODE_ID, rules: BlockCheckMode::Default, span, - recovered: false, }) } diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index b05039329967d..df13ff6e6c81e 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -902,12 +902,11 @@ fn noop_fold_bounds(bounds: GenericBounds, folder: &mut T) } pub fn noop_fold_block(b: P, folder: &mut T) -> P { - b.map(|Block {id, stmts, rules, span, recovered}| Block { + b.map(|Block {id, stmts, rules, span}| Block { id: folder.new_id(id), stmts: stmts.move_flat_map(|s| folder.fold_stmt(s).into_iter()), rules, span: folder.new_span(span), - recovered, }) } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 5a51b629826dd..9c16d2d7a3596 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -42,6 +42,7 @@ use ast::{UseTree, UseTreeKind}; use ast::{BinOpKind, UnOp}; use ast::{RangeEnd, RangeSyntax}; use {ast, attr}; +use ext::base::DummyResult; use source_map::{self, SourceMap, Spanned, respan}; use syntax_pos::{self, Span, MultiSpan, BytePos, FileName}; use errors::{self, Applicability, DiagnosticBuilder, DiagnosticId}; @@ -4976,16 +4977,16 @@ impl<'a> Parser<'a> { /// Precondition: already parsed the '{'. fn parse_block_tail(&mut self, lo: Span, s: BlockCheckMode) -> PResult<'a, P> { let mut stmts = vec![]; - let mut recovered = false; - while !self.eat(&token::CloseDelim(token::Brace)) { let stmt = match self.parse_full_stmt(false) { Err(mut err) => { err.emit(); self.recover_stmt_(SemiColonMode::Ignore, BlockMode::Ignore); - self.eat(&token::CloseDelim(token::Brace)); - recovered = true; - break; + Some(Stmt { + id: ast::DUMMY_NODE_ID, + node: StmtKind::Expr(DummyResult::raw_expr(self.span)), + span: self.span, + }) } Ok(stmt) => stmt, }; @@ -5003,7 +5004,6 @@ impl<'a> Parser<'a> { id: ast::DUMMY_NODE_ID, rules: s, span: lo.to(self.prev_span), - recovered, })) } diff --git a/src/libsyntax_ext/deriving/mod.rs b/src/libsyntax_ext/deriving/mod.rs index ae47a028bc386..292743e0798a7 100644 --- a/src/libsyntax_ext/deriving/mod.rs +++ b/src/libsyntax_ext/deriving/mod.rs @@ -163,6 +163,5 @@ fn call_intrinsic(cx: &ExtCtxt, id: ast::DUMMY_NODE_ID, rules: ast::BlockCheckMode::Unsafe(ast::CompilerGenerated), span, - recovered: false, })) } diff --git a/src/test/run-pass-fulldeps/pprust-expr-roundtrip.rs b/src/test/run-pass-fulldeps/pprust-expr-roundtrip.rs index 854063a2984b4..323c8f95e8c81 100644 --- a/src/test/run-pass-fulldeps/pprust-expr-roundtrip.rs +++ b/src/test/run-pass-fulldeps/pprust-expr-roundtrip.rs @@ -115,7 +115,6 @@ fn iter_exprs(depth: usize, f: &mut FnMut(P)) { id: DUMMY_NODE_ID, rules: BlockCheckMode::Default, span: DUMMY_SP, - recovered: false, }); iter_exprs(depth - 1, &mut |e| g(ExprKind::If(e, block.clone(), None))); }, diff --git a/src/test/ui/issues/issue-10536.rs b/src/test/ui/issues/issue-10536.rs index 0976d9abf14ed..2bfc2e16334d7 100644 --- a/src/test/ui/issues/issue-10536.rs +++ b/src/test/ui/issues/issue-10536.rs @@ -30,5 +30,4 @@ pub fn main() { // least throw a conventional error. assert!({one! two}); //~^ ERROR expected `(` or `{`, found `}` - //~| ERROR cannot apply unary operator `!` to type `!` } diff --git a/src/test/ui/issues/issue-10536.stderr b/src/test/ui/issues/issue-10536.stderr index bf3a6fadd9909..f80f024dcb23f 100644 --- a/src/test/ui/issues/issue-10536.stderr +++ b/src/test/ui/issues/issue-10536.stderr @@ -25,13 +25,6 @@ LL | assert!({one! two()}); = note: expected type `bool` found type `()` -error[E0600]: cannot apply unary operator `!` to type `!` - --> $DIR/issue-10536.rs:31:5 - | -LL | assert!({one! two}); - | ^^^^^^^^^^^^^^^^^^^^ cannot apply unary operator `!` - -error: aborting due to 5 previous errors +error: aborting due to 4 previous errors -Some errors occurred: E0308, E0600. -For more information about an error, try `rustc --explain E0308`. +For more information about this error, try `rustc --explain E0308`. From a053ae20a9bdabae38ad2d1a9f109ab96e02070f Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Thu, 20 Dec 2018 03:57:48 +0300 Subject: [PATCH 67/84] Fix `trace_macros` and `log_syntax` --- src/libsyntax/ext/base.rs | 30 ++++++++++++++++----------- src/libsyntax/parse/parser.rs | 2 +- src/libsyntax_ext/deriving/default.rs | 2 +- src/libsyntax_ext/format.rs | 6 +++--- src/libsyntax_ext/log_syntax.rs | 2 +- src/libsyntax_ext/trace_macros.rs | 2 +- 6 files changed, 25 insertions(+), 19 deletions(-) diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index ad4824dc5dfae..5adb9868e238f 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -466,7 +466,8 @@ impl MacResult for MacEager { #[derive(Copy, Clone)] pub struct DummyResult { expr_only: bool, - span: Span + is_error: bool, + span: Span, } impl DummyResult { @@ -474,8 +475,13 @@ impl DummyResult { /// /// Use this as a return value after hitting any errors and /// calling `span_err`. - pub fn any(sp: Span) -> Box { - Box::new(DummyResult { expr_only: false, span: sp }) + pub fn any(span: Span) -> Box { + Box::new(DummyResult { expr_only: false, is_error: true, span }) + } + + /// Same as `any`, but must be a valid fragment, not error. + pub fn any_valid(span: Span) -> Box { + Box::new(DummyResult { expr_only: false, is_error: false, span }) } /// Create a default MacResult that can only be an expression. @@ -483,15 +489,15 @@ impl DummyResult { /// Use this for macros that must expand to an expression, so even /// if an error is encountered internally, the user will receive /// an error that they also used it in the wrong place. - pub fn expr(sp: Span) -> Box { - Box::new(DummyResult { expr_only: true, span: sp }) + pub fn expr(span: Span) -> Box { + Box::new(DummyResult { expr_only: true, is_error: true, span }) } /// A plain dummy expression. - pub fn raw_expr(sp: Span) -> P { + pub fn raw_expr(sp: Span, is_error: bool) -> P { P(ast::Expr { id: ast::DUMMY_NODE_ID, - node: ast::ExprKind::Err, + node: if is_error { ast::ExprKind::Err } else { ast::ExprKind::Tup(Vec::new()) }, span: sp, attrs: ThinVec::new(), }) @@ -507,10 +513,10 @@ impl DummyResult { } /// A plain dummy type. - pub fn raw_ty(sp: Span) -> P { + pub fn raw_ty(sp: Span, is_error: bool) -> P { P(ast::Ty { id: ast::DUMMY_NODE_ID, - node: ast::TyKind::Err, + node: if is_error { ast::TyKind::Err } else { ast::TyKind::Tup(Vec::new()) }, span: sp }) } @@ -518,7 +524,7 @@ impl DummyResult { impl MacResult for DummyResult { fn make_expr(self: Box) -> Option> { - Some(DummyResult::raw_expr(self.span)) + Some(DummyResult::raw_expr(self.span, self.is_error)) } fn make_pat(self: Box) -> Option> { @@ -561,13 +567,13 @@ impl MacResult for DummyResult { fn make_stmts(self: Box) -> Option> { Some(smallvec![ast::Stmt { id: ast::DUMMY_NODE_ID, - node: ast::StmtKind::Expr(DummyResult::raw_expr(self.span)), + node: ast::StmtKind::Expr(DummyResult::raw_expr(self.span, self.is_error)), span: self.span, }]) } fn make_ty(self: Box) -> Option> { - Some(DummyResult::raw_ty(self.span)) + Some(DummyResult::raw_ty(self.span, self.is_error)) } } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 9c16d2d7a3596..4e994dd67c882 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -4984,7 +4984,7 @@ impl<'a> Parser<'a> { self.recover_stmt_(SemiColonMode::Ignore, BlockMode::Ignore); Some(Stmt { id: ast::DUMMY_NODE_ID, - node: StmtKind::Expr(DummyResult::raw_expr(self.span)), + node: StmtKind::Expr(DummyResult::raw_expr(self.span, true)), span: self.span, }) } diff --git a/src/libsyntax_ext/deriving/default.rs b/src/libsyntax_ext/deriving/default.rs index e0c4fa405e6d9..53a3ecda0d5c0 100644 --- a/src/libsyntax_ext/deriving/default.rs +++ b/src/libsyntax_ext/deriving/default.rs @@ -79,7 +79,7 @@ fn default_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructur span_err!(cx, trait_span, E0665, "`Default` cannot be derived for enums, only structs"); // let compilation continue - DummyResult::raw_expr(trait_span) + DummyResult::raw_expr(trait_span, true) } _ => cx.span_bug(trait_span, "Non-static method in `derive(Default)`"), }; diff --git a/src/libsyntax_ext/format.rs b/src/libsyntax_ext/format.rs index 79241fb6aa74f..621dc3ed98bed 100644 --- a/src/libsyntax_ext/format.rs +++ b/src/libsyntax_ext/format.rs @@ -676,7 +676,7 @@ impl<'a, 'b> Context<'a, 'b> { "X" => "UpperHex", _ => { ecx.span_err(sp, &format!("unknown format trait `{}`", *tyname)); - return DummyResult::raw_expr(sp); + return DummyResult::raw_expr(sp, true); } } } @@ -771,7 +771,7 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, Applicability::MaybeIncorrect, ); err.emit(); - return DummyResult::raw_expr(sp); + return DummyResult::raw_expr(sp, true); } }; @@ -806,7 +806,7 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, e.note(¬e); } e.emit(); - return DummyResult::raw_expr(sp); + return DummyResult::raw_expr(sp, true); } let arg_spans = parser.arg_places.iter() diff --git a/src/libsyntax_ext/log_syntax.rs b/src/libsyntax_ext/log_syntax.rs index 7b76b1e891468..41f520d4fcebb 100644 --- a/src/libsyntax_ext/log_syntax.rs +++ b/src/libsyntax_ext/log_syntax.rs @@ -30,5 +30,5 @@ pub fn expand_syntax_ext<'cx>(cx: &'cx mut base::ExtCtxt, println!("{}", print::pprust::tts_to_string(tts)); // any so that `log_syntax` can be invoked as an expression and item. - base::DummyResult::any(sp) + base::DummyResult::any_valid(sp) } diff --git a/src/libsyntax_ext/trace_macros.rs b/src/libsyntax_ext/trace_macros.rs index 256b525b8bea6..0fd2ebddb2549 100644 --- a/src/libsyntax_ext/trace_macros.rs +++ b/src/libsyntax_ext/trace_macros.rs @@ -38,5 +38,5 @@ pub fn expand_trace_macros(cx: &mut ExtCtxt, _ => cx.span_err(sp, "trace_macros! accepts only `true` or `false`"), } - base::DummyResult::any(sp) + base::DummyResult::any_valid(sp) } From db24d8e8e25192703eb8f2ad6864207e92979443 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Fri, 21 Dec 2018 00:30:35 +0100 Subject: [PATCH 68/84] Enable emission of alignment attrs for pointer params Instead disable creation of assumptions during inlining using an LLVM opt flag. The -Z arg-align-attributes option which previously controlled this behavior is removed. --- src/librustc/session/config.rs | 2 -- src/librustc_codegen_llvm/abi.rs | 6 ----- src/librustc_codegen_llvm/llvm_util.rs | 4 ++++ src/test/codegen/function-arguments.rs | 32 +++++++++++++------------- 4 files changed, 20 insertions(+), 24 deletions(-) diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index b58d80e24857d..8bb3fc1295205 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -1271,8 +1271,6 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, "set the MIR optimization level (0-3, default: 1)"), mutable_noalias: Option = (None, parse_opt_bool, [TRACKED], "emit noalias metadata for mutable references (default: yes on LLVM >= 6)"), - arg_align_attributes: bool = (false, parse_bool, [TRACKED], - "emit align metadata for reference arguments"), dump_mir: Option = (None, parse_opt_string, [UNTRACKED], "dump MIR state to file. `val` is used to select which passes and functions to dump. For example: diff --git a/src/librustc_codegen_llvm/abi.rs b/src/librustc_codegen_llvm/abi.rs index b8954dee794f7..71b75525a5aa1 100644 --- a/src/librustc_codegen_llvm/abi.rs +++ b/src/librustc_codegen_llvm/abi.rs @@ -489,12 +489,6 @@ impl<'tcx> FnTypeExt<'tcx> for FnType<'tcx, Ty<'tcx>> { attrs.pointee_size = pointee.size; attrs.pointee_align = Some(pointee.align); - // HACK(eddyb) LLVM inserts `llvm.assume` calls when inlining functions - // with align attributes, and those calls later block optimizations. - if !is_return && !cx.tcx.sess.opts.debugging_opts.arg_align_attributes { - attrs.pointee_align = None; - } - // `Box` pointer parameters never alias because ownership is transferred // `&mut` pointer parameters never alias other parameters, // or mutable global data diff --git a/src/librustc_codegen_llvm/llvm_util.rs b/src/librustc_codegen_llvm/llvm_util.rs index 82b1d7e8b40e4..090ff83ecc1a8 100644 --- a/src/librustc_codegen_llvm/llvm_util.rs +++ b/src/librustc_codegen_llvm/llvm_util.rs @@ -74,6 +74,10 @@ unsafe fn configure_llvm(sess: &Session) { add("-mergefunc-use-aliases"); } + // HACK(eddyb) LLVM inserts `llvm.assume` calls to preserve align attributes + // during inlining. Unfortunately these may block other optimizations. + add("-preserve-alignment-assumptions-during-inlining=false"); + for arg in &sess.opts.cg.llvm_args { add(&(*arg)); } diff --git a/src/test/codegen/function-arguments.rs b/src/test/codegen/function-arguments.rs index 52bdb1b103afd..69632c9c82b70 100644 --- a/src/test/codegen/function-arguments.rs +++ b/src/test/codegen/function-arguments.rs @@ -28,37 +28,37 @@ pub fn boolean(x: bool) -> bool { x } -// CHECK: @readonly_borrow(i32* noalias readonly dereferenceable(4) %arg0) +// CHECK: @readonly_borrow(i32* noalias readonly align 4 dereferenceable(4) %arg0) // FIXME #25759 This should also have `nocapture` #[no_mangle] pub fn readonly_borrow(_: &i32) { } -// CHECK: @static_borrow(i32* noalias readonly dereferenceable(4) %arg0) +// CHECK: @static_borrow(i32* noalias readonly align 4 dereferenceable(4) %arg0) // static borrow may be captured #[no_mangle] pub fn static_borrow(_: &'static i32) { } -// CHECK: @named_borrow(i32* noalias readonly dereferenceable(4) %arg0) +// CHECK: @named_borrow(i32* noalias readonly align 4 dereferenceable(4) %arg0) // borrow with named lifetime may be captured #[no_mangle] pub fn named_borrow<'r>(_: &'r i32) { } -// CHECK: @unsafe_borrow(i16* dereferenceable(2) %arg0) +// CHECK: @unsafe_borrow(i16* align 2 dereferenceable(2) %arg0) // unsafe interior means this isn't actually readonly and there may be aliases ... #[no_mangle] pub fn unsafe_borrow(_: &UnsafeInner) { } -// CHECK: @mutable_unsafe_borrow(i16* dereferenceable(2) %arg0) +// CHECK: @mutable_unsafe_borrow(i16* align 2 dereferenceable(2) %arg0) // ... unless this is a mutable borrow, those never alias #[no_mangle] pub fn mutable_unsafe_borrow(_: &mut UnsafeInner) { } -// CHECK: @mutable_borrow(i32* dereferenceable(4) %arg0) +// CHECK: @mutable_borrow(i32* align 4 dereferenceable(4) %arg0) // FIXME #25759 This should also have `nocapture` #[no_mangle] pub fn mutable_borrow(_: &mut i32) { @@ -69,13 +69,13 @@ pub fn mutable_borrow(_: &mut i32) { pub fn indirect_struct(_: S) { } -// CHECK: @borrowed_struct(%S* noalias readonly dereferenceable(32) %arg0) +// CHECK: @borrowed_struct(%S* noalias readonly align 4 dereferenceable(32) %arg0) // FIXME #25759 This should also have `nocapture` #[no_mangle] pub fn borrowed_struct(_: &S) { } -// CHECK: noalias align 4 dereferenceable(4) i32* @_box(i32* noalias dereferenceable(4) %x) +// CHECK: noalias align 4 dereferenceable(4) i32* @_box(i32* noalias align 4 dereferenceable(4) %x) #[no_mangle] pub fn _box(x: Box) -> Box { x @@ -95,48 +95,48 @@ pub fn struct_return() -> S { pub fn helper(_: usize) { } -// CHECK: @slice([0 x i8]* noalias nonnull readonly %arg0.0, [[USIZE]] %arg0.1) +// CHECK: @slice([0 x i8]* noalias nonnull readonly align 1 %arg0.0, [[USIZE]] %arg0.1) // FIXME #25759 This should also have `nocapture` #[no_mangle] pub fn slice(_: &[u8]) { } -// CHECK: @mutable_slice([0 x i8]* nonnull %arg0.0, [[USIZE]] %arg0.1) +// CHECK: @mutable_slice([0 x i8]* nonnull align 1 %arg0.0, [[USIZE]] %arg0.1) // FIXME #25759 This should also have `nocapture` #[no_mangle] pub fn mutable_slice(_: &mut [u8]) { } -// CHECK: @unsafe_slice([0 x i16]* nonnull %arg0.0, [[USIZE]] %arg0.1) +// CHECK: @unsafe_slice([0 x i16]* nonnull align 2 %arg0.0, [[USIZE]] %arg0.1) // unsafe interior means this isn't actually readonly and there may be aliases ... #[no_mangle] pub fn unsafe_slice(_: &[UnsafeInner]) { } -// CHECK: @str([0 x i8]* noalias nonnull readonly %arg0.0, [[USIZE]] %arg0.1) +// CHECK: @str([0 x i8]* noalias nonnull readonly align 1 %arg0.0, [[USIZE]] %arg0.1) // FIXME #25759 This should also have `nocapture` #[no_mangle] pub fn str(_: &[u8]) { } -// CHECK: @trait_borrow({}* nonnull %arg0.0, [3 x [[USIZE]]]* noalias readonly dereferenceable({{.*}}) %arg0.1) +// CHECK: @trait_borrow({}* nonnull align 1 %arg0.0, [3 x [[USIZE]]]* noalias readonly align {{.*}} dereferenceable({{.*}}) %arg0.1) // FIXME #25759 This should also have `nocapture` #[no_mangle] pub fn trait_borrow(_: &Drop) { } -// CHECK: @trait_box({}* noalias nonnull, [3 x [[USIZE]]]* noalias readonly dereferenceable({{.*}})) +// CHECK: @trait_box({}* noalias nonnull align 1, [3 x [[USIZE]]]* noalias readonly align {{.*}} dereferenceable({{.*}})) #[no_mangle] pub fn trait_box(_: Box) { } -// CHECK: { i8*, i8* } @trait_option(i8* noalias %x.0, i8* %x.1) +// CHECK: { i8*, i8* } @trait_option(i8* noalias align 1 %x.0, i8* %x.1) #[no_mangle] pub fn trait_option(x: Option>) -> Option> { x } -// CHECK: { [0 x i16]*, [[USIZE]] } @return_slice([0 x i16]* noalias nonnull readonly %x.0, [[USIZE]] %x.1) +// CHECK: { [0 x i16]*, [[USIZE]] } @return_slice([0 x i16]* noalias nonnull readonly align 2 %x.0, [[USIZE]] %x.1) #[no_mangle] pub fn return_slice(x: &[u16]) -> &[u16] { x From 29f3d7b47b2e43216f09229ef64cab47a59c4c96 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Fri, 21 Dec 2018 01:47:03 +0300 Subject: [PATCH 69/84] Make sure feature gate errors are recoverable --- src/librustc/lint/levels.rs | 6 ++-- src/librustc_typeck/collect.rs | 1 - src/libsyntax/ext/expand.rs | 1 - src/libsyntax_ext/asm.rs | 1 - src/libsyntax_ext/concat_idents.rs | 1 - src/libsyntax_ext/format.rs | 1 - src/libsyntax_ext/global_asm.rs | 1 - src/libsyntax_ext/log_syntax.rs | 1 - src/libsyntax_ext/test_case.rs | 2 -- src/libsyntax_ext/trace_macros.rs | 1 - .../ui/feature-gates/feature-gate-asm2.rs | 2 +- .../ui/feature-gates/feature-gate-asm2.stderr | 6 ++-- .../feature-gate-concat_idents2.rs | 1 + .../feature-gate-concat_idents2.stderr | 11 ++++-- .../feature-gate-log_syntax.stdout | 1 + .../feature-gates/feature-gate-log_syntax2.rs | 2 +- .../feature-gate-log_syntax2.stderr | 6 ++-- .../feature-gate-log_syntax2.stdout | 1 + src/test/ui/trace_macros-gate.rs | 12 ++----- src/test/ui/trace_macros-gate.stderr | 36 +++++-------------- 20 files changed, 34 insertions(+), 60 deletions(-) create mode 100644 src/test/ui/feature-gates/feature-gate-log_syntax.stdout create mode 100644 src/test/ui/feature-gates/feature-gate-log_syntax2.stdout diff --git a/src/librustc/lint/levels.rs b/src/librustc/lint/levels.rs index 06e3e0bab4f10..0eaab349fdb26 100644 --- a/src/librustc/lint/levels.rs +++ b/src/librustc/lint/levels.rs @@ -232,14 +232,13 @@ impl<'a> LintLevelsBuilder<'a> { match item.node { ast::MetaItemKind::Word => {} // actual lint names handled later ast::MetaItemKind::NameValue(ref name_value) => { - let gate_reasons = !self.sess.features_untracked().lint_reasons; if item.ident == "reason" { // found reason, reslice meta list to exclude it metas = &metas[0..metas.len()-1]; // FIXME (#55112): issue unused-attributes lint if we thereby // don't have any lint names (`#[level(reason = "foo")]`) if let ast::LitKind::Str(rationale, _) = name_value.node { - if gate_reasons { + if !self.sess.features_untracked().lint_reasons { feature_gate::emit_feature_err( &self.sess.parse_sess, "lint_reasons", @@ -247,9 +246,8 @@ impl<'a> LintLevelsBuilder<'a> { feature_gate::GateIssue::Language, "lint reasons are experimental" ); - } else { - reason = Some(rationale); } + reason = Some(rationale); } else { let mut err = bad_attr(name_value.span); err.help("reason must be a string literal"); diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index a4eafee36d1a1..5e70c7be1fef1 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -2220,7 +2220,6 @@ fn from_target_feature( feature_gate::GateIssue::Language, &format!("the target feature `{}` is currently unstable", feature), ); - return None; } Some(Symbol::intern(feature)) })); diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 299f23927bf8d..d2320af11dcf8 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -732,7 +732,6 @@ impl<'a, 'b> MacroExpander<'a, 'b> { emit_feature_err(this.cx.parse_sess, &*feature.as_str(), span, GateIssue::Library(Some(issue)), &explain); this.cx.trace_macros_diag(); - return Err(kind.dummy(span)); } } diff --git a/src/libsyntax_ext/asm.rs b/src/libsyntax_ext/asm.rs index 2ff9fb487c4f2..3e9a1a9228bed 100644 --- a/src/libsyntax_ext/asm.rs +++ b/src/libsyntax_ext/asm.rs @@ -59,7 +59,6 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt, sp, feature_gate::GateIssue::Language, feature_gate::EXPLAIN_ASM); - return DummyResult::expr(sp); } // Split the tts before the first colon, to avoid `asm!("x": y)` being diff --git a/src/libsyntax_ext/concat_idents.rs b/src/libsyntax_ext/concat_idents.rs index c8cc11e43545a..aee969fd23122 100644 --- a/src/libsyntax_ext/concat_idents.rs +++ b/src/libsyntax_ext/concat_idents.rs @@ -30,7 +30,6 @@ pub fn expand_syntax_ext<'cx>(cx: &'cx mut ExtCtxt, sp, feature_gate::GateIssue::Language, feature_gate::EXPLAIN_CONCAT_IDENTS); - return base::DummyResult::expr(sp); } if tts.is_empty() { diff --git a/src/libsyntax_ext/format.rs b/src/libsyntax_ext/format.rs index 621dc3ed98bed..0199ac4d1304e 100644 --- a/src/libsyntax_ext/format.rs +++ b/src/libsyntax_ext/format.rs @@ -723,7 +723,6 @@ pub fn expand_format_args_nl<'cx>( sp, feature_gate::GateIssue::Language, feature_gate::EXPLAIN_FORMAT_ARGS_NL); - return DummyResult::expr(sp); } sp = sp.apply_mark(ecx.current_expansion.mark); match parse_args(ecx, sp, tts) { diff --git a/src/libsyntax_ext/global_asm.rs b/src/libsyntax_ext/global_asm.rs index 000bede7348a5..c7fa233c16334 100644 --- a/src/libsyntax_ext/global_asm.rs +++ b/src/libsyntax_ext/global_asm.rs @@ -39,7 +39,6 @@ pub fn expand_global_asm<'cx>(cx: &'cx mut ExtCtxt, sp, feature_gate::GateIssue::Language, feature_gate::EXPLAIN_GLOBAL_ASM); - return DummyResult::any(sp); } let mut p = cx.new_parser_from_tts(tts); diff --git a/src/libsyntax_ext/log_syntax.rs b/src/libsyntax_ext/log_syntax.rs index 41f520d4fcebb..6e5c4ebd2078a 100644 --- a/src/libsyntax_ext/log_syntax.rs +++ b/src/libsyntax_ext/log_syntax.rs @@ -24,7 +24,6 @@ pub fn expand_syntax_ext<'cx>(cx: &'cx mut base::ExtCtxt, sp, feature_gate::GateIssue::Language, feature_gate::EXPLAIN_LOG_SYNTAX); - return base::DummyResult::any(sp); } println!("{}", print::pprust::tts_to_string(tts)); diff --git a/src/libsyntax_ext/test_case.rs b/src/libsyntax_ext/test_case.rs index 0128db7dd78d7..51fee8e2e6e2a 100644 --- a/src/libsyntax_ext/test_case.rs +++ b/src/libsyntax_ext/test_case.rs @@ -39,8 +39,6 @@ pub fn expand( attr_sp, feature_gate::GateIssue::Language, feature_gate::EXPLAIN_CUSTOM_TEST_FRAMEWORKS); - - return vec![anno_item]; } if !ecx.ecfg.should_test { return vec![]; } diff --git a/src/libsyntax_ext/trace_macros.rs b/src/libsyntax_ext/trace_macros.rs index 0fd2ebddb2549..4d30c41d9c9d6 100644 --- a/src/libsyntax_ext/trace_macros.rs +++ b/src/libsyntax_ext/trace_macros.rs @@ -25,7 +25,6 @@ pub fn expand_trace_macros(cx: &mut ExtCtxt, sp, feature_gate::GateIssue::Language, feature_gate::EXPLAIN_TRACE_MACROS); - return base::DummyResult::any(sp); } match (tt.len(), tt.first()) { diff --git a/src/test/ui/feature-gates/feature-gate-asm2.rs b/src/test/ui/feature-gates/feature-gate-asm2.rs index 222190de9fe9c..5291b0e2fb63a 100644 --- a/src/test/ui/feature-gates/feature-gate-asm2.rs +++ b/src/test/ui/feature-gates/feature-gate-asm2.rs @@ -12,6 +12,6 @@ fn main() { unsafe { - println!("{}", asm!("")); //~ ERROR inline assembly is not stable + println!("{:?}", asm!("")); //~ ERROR inline assembly is not stable } } diff --git a/src/test/ui/feature-gates/feature-gate-asm2.stderr b/src/test/ui/feature-gates/feature-gate-asm2.stderr index a0e881a3b99ae..36f0e71f72b5a 100644 --- a/src/test/ui/feature-gates/feature-gate-asm2.stderr +++ b/src/test/ui/feature-gates/feature-gate-asm2.stderr @@ -1,8 +1,8 @@ error[E0658]: inline assembly is not stable enough for use and is subject to change (see issue #29722) - --> $DIR/feature-gate-asm2.rs:15:24 + --> $DIR/feature-gate-asm2.rs:15:26 | -LL | println!("{}", asm!("")); //~ ERROR inline assembly is not stable - | ^^^^^^^^ +LL | println!("{:?}", asm!("")); //~ ERROR inline assembly is not stable + | ^^^^^^^^ | = help: add #![feature(asm)] to the crate attributes to enable diff --git a/src/test/ui/feature-gates/feature-gate-concat_idents2.rs b/src/test/ui/feature-gates/feature-gate-concat_idents2.rs index af288a9790440..b8fe82057146c 100644 --- a/src/test/ui/feature-gates/feature-gate-concat_idents2.rs +++ b/src/test/ui/feature-gates/feature-gate-concat_idents2.rs @@ -12,4 +12,5 @@ fn main() { concat_idents!(a, b); //~ ERROR `concat_idents` is not stable enough + //~| ERROR cannot find value `ab` in this scope } diff --git a/src/test/ui/feature-gates/feature-gate-concat_idents2.stderr b/src/test/ui/feature-gates/feature-gate-concat_idents2.stderr index 9312a6f5b3618..d7fcf0cc59158 100644 --- a/src/test/ui/feature-gates/feature-gate-concat_idents2.stderr +++ b/src/test/ui/feature-gates/feature-gate-concat_idents2.stderr @@ -6,6 +6,13 @@ LL | concat_idents!(a, b); //~ ERROR `concat_idents` is not stable enough | = help: add #![feature(concat_idents)] to the crate attributes to enable -error: aborting due to previous error +error[E0425]: cannot find value `ab` in this scope + --> $DIR/feature-gate-concat_idents2.rs:14:5 + | +LL | concat_idents!(a, b); //~ ERROR `concat_idents` is not stable enough + | ^^^^^^^^^^^^^^^^^^^^^ not found in this scope + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0658`. +Some errors occurred: E0425, E0658. +For more information about an error, try `rustc --explain E0425`. diff --git a/src/test/ui/feature-gates/feature-gate-log_syntax.stdout b/src/test/ui/feature-gates/feature-gate-log_syntax.stdout new file mode 100644 index 0000000000000..8b137891791fe --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-log_syntax.stdout @@ -0,0 +1 @@ + diff --git a/src/test/ui/feature-gates/feature-gate-log_syntax2.rs b/src/test/ui/feature-gates/feature-gate-log_syntax2.rs index dcbe7eefee52c..d60e447322fd7 100644 --- a/src/test/ui/feature-gates/feature-gate-log_syntax2.rs +++ b/src/test/ui/feature-gates/feature-gate-log_syntax2.rs @@ -11,5 +11,5 @@ // gate-test-log_syntax fn main() { - println!("{}", log_syntax!()); //~ ERROR `log_syntax!` is not stable + println!("{:?}", log_syntax!()); //~ ERROR `log_syntax!` is not stable } diff --git a/src/test/ui/feature-gates/feature-gate-log_syntax2.stderr b/src/test/ui/feature-gates/feature-gate-log_syntax2.stderr index 19e7de1a824ff..90c7a66a5b6a2 100644 --- a/src/test/ui/feature-gates/feature-gate-log_syntax2.stderr +++ b/src/test/ui/feature-gates/feature-gate-log_syntax2.stderr @@ -1,8 +1,8 @@ error[E0658]: `log_syntax!` is not stable enough for use and is subject to change (see issue #29598) - --> $DIR/feature-gate-log_syntax2.rs:14:20 + --> $DIR/feature-gate-log_syntax2.rs:14:22 | -LL | println!("{}", log_syntax!()); //~ ERROR `log_syntax!` is not stable - | ^^^^^^^^^^^^^ +LL | println!("{:?}", log_syntax!()); //~ ERROR `log_syntax!` is not stable + | ^^^^^^^^^^^^^ | = help: add #![feature(log_syntax)] to the crate attributes to enable diff --git a/src/test/ui/feature-gates/feature-gate-log_syntax2.stdout b/src/test/ui/feature-gates/feature-gate-log_syntax2.stdout new file mode 100644 index 0000000000000..8b137891791fe --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-log_syntax2.stdout @@ -0,0 +1 @@ + diff --git a/src/test/ui/trace_macros-gate.rs b/src/test/ui/trace_macros-gate.rs index d4a7c4ed0e0f9..c358ac0d48580 100644 --- a/src/test/ui/trace_macros-gate.rs +++ b/src/test/ui/trace_macros-gate.rs @@ -12,15 +12,9 @@ fn main() { trace_macros!(); //~ ERROR `trace_macros` is not stable - trace_macros!(1); //~ ERROR `trace_macros` is not stable - trace_macros!(ident); //~ ERROR `trace_macros` is not stable - trace_macros!(for); //~ ERROR `trace_macros` is not stable - trace_macros!(true,); //~ ERROR `trace_macros` is not stable - trace_macros!(false 1); //~ ERROR `trace_macros` is not stable - - // Errors are signalled early for the above, before expansion. - // See trace_macros-gate2 and trace_macros-gate3. for examples - // of the below being caught. + //~| ERROR trace_macros! accepts only `true` or `false` + trace_macros!(true); //~ ERROR `trace_macros` is not stable + trace_macros!(false); //~ ERROR `trace_macros` is not stable macro_rules! expando { ($x: ident) => { trace_macros!($x) } //~ ERROR `trace_macros` is not stable diff --git a/src/test/ui/trace_macros-gate.stderr b/src/test/ui/trace_macros-gate.stderr index ed92e1227baf5..a6960f47a266d 100644 --- a/src/test/ui/trace_macros-gate.stderr +++ b/src/test/ui/trace_macros-gate.stderr @@ -6,48 +6,30 @@ LL | trace_macros!(); //~ ERROR `trace_macros` is not stable | = help: add #![feature(trace_macros)] to the crate attributes to enable -error[E0658]: `trace_macros` is not stable enough for use and is subject to change (see issue #29598) - --> $DIR/trace_macros-gate.rs:15:5 - | -LL | trace_macros!(1); //~ ERROR `trace_macros` is not stable - | ^^^^^^^^^^^^^^^^^ +error: trace_macros! accepts only `true` or `false` + --> $DIR/trace_macros-gate.rs:14:5 | - = help: add #![feature(trace_macros)] to the crate attributes to enable +LL | trace_macros!(); //~ ERROR `trace_macros` is not stable + | ^^^^^^^^^^^^^^^^ error[E0658]: `trace_macros` is not stable enough for use and is subject to change (see issue #29598) --> $DIR/trace_macros-gate.rs:16:5 | -LL | trace_macros!(ident); //~ ERROR `trace_macros` is not stable - | ^^^^^^^^^^^^^^^^^^^^^ +LL | trace_macros!(true); //~ ERROR `trace_macros` is not stable + | ^^^^^^^^^^^^^^^^^^^^ | = help: add #![feature(trace_macros)] to the crate attributes to enable error[E0658]: `trace_macros` is not stable enough for use and is subject to change (see issue #29598) --> $DIR/trace_macros-gate.rs:17:5 | -LL | trace_macros!(for); //~ ERROR `trace_macros` is not stable - | ^^^^^^^^^^^^^^^^^^^ - | - = help: add #![feature(trace_macros)] to the crate attributes to enable - -error[E0658]: `trace_macros` is not stable enough for use and is subject to change (see issue #29598) - --> $DIR/trace_macros-gate.rs:18:5 - | -LL | trace_macros!(true,); //~ ERROR `trace_macros` is not stable +LL | trace_macros!(false); //~ ERROR `trace_macros` is not stable | ^^^^^^^^^^^^^^^^^^^^^ | = help: add #![feature(trace_macros)] to the crate attributes to enable error[E0658]: `trace_macros` is not stable enough for use and is subject to change (see issue #29598) - --> $DIR/trace_macros-gate.rs:19:5 - | -LL | trace_macros!(false 1); //~ ERROR `trace_macros` is not stable - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: add #![feature(trace_macros)] to the crate attributes to enable - -error[E0658]: `trace_macros` is not stable enough for use and is subject to change (see issue #29598) - --> $DIR/trace_macros-gate.rs:26:26 + --> $DIR/trace_macros-gate.rs:20:26 | LL | ($x: ident) => { trace_macros!($x) } //~ ERROR `trace_macros` is not stable | ^^^^^^^^^^^^^^^^^ @@ -57,6 +39,6 @@ LL | expando!(true); | = help: add #![feature(trace_macros)] to the crate attributes to enable -error: aborting due to 7 previous errors +error: aborting due to 5 previous errors For more information about this error, try `rustc --explain E0658`. From 4a6aa363ccc41e92f8a6c395031c1745f063e464 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Fri, 21 Dec 2018 02:58:55 +0300 Subject: [PATCH 70/84] Address review comments and CI failures --- src/librustc_resolve/macros.rs | 2 +- src/libsyntax/parse/parser.rs | 1 + src/test/ui/issues/issue-6596-1.rs | 1 - src/test/ui/issues/issue-6596-1.stderr | 12 +---------- src/test/ui/issues/issue-6596-2.rs | 1 - src/test/ui/issues/issue-6596-2.stderr | 11 +--------- .../macros/macro-comma-behavior.core.stderr | 18 ++++++++--------- src/test/ui/macros/macro-comma-behavior.rs | 2 ++ .../ui/macros/macro-comma-behavior.std.stderr | 20 +++++++++---------- 9 files changed, 24 insertions(+), 44 deletions(-) diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 1bdcf4577fef1..64a5f1e3b6fb4 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -196,7 +196,7 @@ impl<'a> base::Resolver for Resolver<'a> { Ok((def, ext)) => (def, ext), Err(Determinacy::Determined) if kind == MacroKind::Attr => { // Replace unresolved attributes with used inert attributes for better recovery. - return Ok(Some(self.get_macro(Def::NonMacroAttr(NonMacroAttrKind::Tool)))); + return Ok(Some(Lrc::new(SyntaxExtension::NonMacroAttr { mark_used: true }))); } Err(determinacy) => return Err(determinacy), }; diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 4e994dd67c882..99014964aa52c 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -2881,6 +2881,7 @@ impl<'a> Parser<'a> { let mut err = self.fatal(&format!("unknown macro variable `{}`", name)); err.span_label(self.span, "unknown macro variable"); err.emit(); + self.bump(); return } token::Interpolated(ref nt) => { diff --git a/src/test/ui/issues/issue-6596-1.rs b/src/test/ui/issues/issue-6596-1.rs index 457f129f2d505..ce8a3a80e1f84 100644 --- a/src/test/ui/issues/issue-6596-1.rs +++ b/src/test/ui/issues/issue-6596-1.rs @@ -13,7 +13,6 @@ macro_rules! e { ($inp:ident) => ( $nonexistent //~^ ERROR unknown macro variable `nonexistent` - //~| ERROR cannot find value `nonexistent` in this scope ); } diff --git a/src/test/ui/issues/issue-6596-1.stderr b/src/test/ui/issues/issue-6596-1.stderr index 2a682348386f9..b7055ab19d0c5 100644 --- a/src/test/ui/issues/issue-6596-1.stderr +++ b/src/test/ui/issues/issue-6596-1.stderr @@ -7,15 +7,5 @@ LL | $nonexistent LL | e!(foo); | -------- in this macro invocation -error[E0425]: cannot find value `nonexistent` in this scope - --> $DIR/issue-6596-1.rs:14:9 - | -LL | $nonexistent - | ^^^^^^^^^^^^ not found in this scope -... -LL | e!(foo); - | -------- in this macro invocation - -error: aborting due to 2 previous errors +error: aborting due to previous error -For more information about this error, try `rustc --explain E0425`. diff --git a/src/test/ui/issues/issue-6596-2.rs b/src/test/ui/issues/issue-6596-2.rs index 9e8d937e8ab6f..5eaa187756eda 100644 --- a/src/test/ui/issues/issue-6596-2.rs +++ b/src/test/ui/issues/issue-6596-2.rs @@ -14,7 +14,6 @@ macro_rules! g { ($inp:ident) => ( { $inp $nonexistent } //~^ ERROR unknown macro variable `nonexistent` - //~| ERROR expected one of ); } diff --git a/src/test/ui/issues/issue-6596-2.stderr b/src/test/ui/issues/issue-6596-2.stderr index f2ed17f35e697..273654f2ae224 100644 --- a/src/test/ui/issues/issue-6596-2.stderr +++ b/src/test/ui/issues/issue-6596-2.stderr @@ -7,14 +7,5 @@ LL | { $inp $nonexistent } LL | g!(foo); | -------- in this macro invocation -error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `nonexistent` - --> $DIR/issue-6596-2.rs:15:16 - | -LL | { $inp $nonexistent } - | ^^^^^^^^^^^^ expected one of 8 possible tokens here -... -LL | g!(foo); - | -------- in this macro invocation - -error: aborting due to 2 previous errors +error: aborting due to previous error diff --git a/src/test/ui/macros/macro-comma-behavior.core.stderr b/src/test/ui/macros/macro-comma-behavior.core.stderr index fccada76d15e4..b7c8c6f394504 100644 --- a/src/test/ui/macros/macro-comma-behavior.core.stderr +++ b/src/test/ui/macros/macro-comma-behavior.core.stderr @@ -1,41 +1,41 @@ error: 1 positional argument in format string, but no arguments were given - --> $DIR/macro-comma-behavior.rs:27:23 + --> $DIR/macro-comma-behavior.rs:29:23 | LL | assert_eq!(1, 1, "{}",); | ^^ error: 1 positional argument in format string, but no arguments were given - --> $DIR/macro-comma-behavior.rs:30:23 + --> $DIR/macro-comma-behavior.rs:32:23 | LL | assert_ne!(1, 2, "{}",); | ^^ error: 1 positional argument in format string, but no arguments were given - --> $DIR/macro-comma-behavior.rs:36:29 + --> $DIR/macro-comma-behavior.rs:38:29 | LL | debug_assert_eq!(1, 1, "{}",); | ^^ error: 1 positional argument in format string, but no arguments were given - --> $DIR/macro-comma-behavior.rs:39:29 + --> $DIR/macro-comma-behavior.rs:41:29 | LL | debug_assert_ne!(1, 2, "{}",); | ^^ error: 1 positional argument in format string, but no arguments were given - --> $DIR/macro-comma-behavior.rs:60:19 + --> $DIR/macro-comma-behavior.rs:62:19 | LL | format_args!("{}",); | ^^ error: 1 positional argument in format string, but no arguments were given - --> $DIR/macro-comma-behavior.rs:78:21 + --> $DIR/macro-comma-behavior.rs:80:21 | LL | unimplemented!("{}",); | ^^ error: 1 positional argument in format string, but no arguments were given - --> $DIR/macro-comma-behavior.rs:87:24 + --> $DIR/macro-comma-behavior.rs:89:24 | LL | write!(f, "{}",)?; | ^^ @@ -44,7 +44,5 @@ error: `#[panic_handler]` function required, but not found error: language item required, but not found: `eh_personality` -error: language item required, but not found: `eh_unwind_resume` - -error: aborting due to 10 previous errors +error: aborting due to 9 previous errors diff --git a/src/test/ui/macros/macro-comma-behavior.rs b/src/test/ui/macros/macro-comma-behavior.rs index 620e57b463d1a..e130b4b349aaa 100644 --- a/src/test/ui/macros/macro-comma-behavior.rs +++ b/src/test/ui/macros/macro-comma-behavior.rs @@ -13,10 +13,12 @@ // compile-flags: -C debug_assertions=yes // revisions: std core +#![feature(lang_items)] #![cfg_attr(core, no_std)] #[cfg(std)] use std::fmt; #[cfg(core)] use core::fmt; +#[cfg(core)] #[lang = "eh_unwind_resume"] fn eh_unwind_resume() {} // (see documentation of the similarly-named test in run-pass) fn to_format_or_not_to_format() { diff --git a/src/test/ui/macros/macro-comma-behavior.std.stderr b/src/test/ui/macros/macro-comma-behavior.std.stderr index a87271ed026f9..6c508c6af03c4 100644 --- a/src/test/ui/macros/macro-comma-behavior.std.stderr +++ b/src/test/ui/macros/macro-comma-behavior.std.stderr @@ -1,59 +1,59 @@ error: 1 positional argument in format string, but no arguments were given - --> $DIR/macro-comma-behavior.rs:27:23 + --> $DIR/macro-comma-behavior.rs:29:23 | LL | assert_eq!(1, 1, "{}",); | ^^ error: 1 positional argument in format string, but no arguments were given - --> $DIR/macro-comma-behavior.rs:30:23 + --> $DIR/macro-comma-behavior.rs:32:23 | LL | assert_ne!(1, 2, "{}",); | ^^ error: 1 positional argument in format string, but no arguments were given - --> $DIR/macro-comma-behavior.rs:36:29 + --> $DIR/macro-comma-behavior.rs:38:29 | LL | debug_assert_eq!(1, 1, "{}",); | ^^ error: 1 positional argument in format string, but no arguments were given - --> $DIR/macro-comma-behavior.rs:39:29 + --> $DIR/macro-comma-behavior.rs:41:29 | LL | debug_assert_ne!(1, 2, "{}",); | ^^ error: 1 positional argument in format string, but no arguments were given - --> $DIR/macro-comma-behavior.rs:44:18 + --> $DIR/macro-comma-behavior.rs:46:18 | LL | eprint!("{}",); | ^^ error: 1 positional argument in format string, but no arguments were given - --> $DIR/macro-comma-behavior.rs:56:18 + --> $DIR/macro-comma-behavior.rs:58:18 | LL | format!("{}",); | ^^ error: 1 positional argument in format string, but no arguments were given - --> $DIR/macro-comma-behavior.rs:60:19 + --> $DIR/macro-comma-behavior.rs:62:19 | LL | format_args!("{}",); | ^^ error: 1 positional argument in format string, but no arguments were given - --> $DIR/macro-comma-behavior.rs:67:17 + --> $DIR/macro-comma-behavior.rs:69:17 | LL | print!("{}",); | ^^ error: 1 positional argument in format string, but no arguments were given - --> $DIR/macro-comma-behavior.rs:78:21 + --> $DIR/macro-comma-behavior.rs:80:21 | LL | unimplemented!("{}",); | ^^ error: 1 positional argument in format string, but no arguments were given - --> $DIR/macro-comma-behavior.rs:87:24 + --> $DIR/macro-comma-behavior.rs:89:24 | LL | write!(f, "{}",)?; | ^^ From edd08e020cb1269a0f171e0502d8bc166c78e58b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Fri, 7 Dec 2018 00:56:19 +0100 Subject: [PATCH 71/84] Optimize away a move --- src/librustc/ty/query/plumbing.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/librustc/ty/query/plumbing.rs b/src/librustc/ty/query/plumbing.rs index a73b92ed713ec..3f90f072ddbdf 100644 --- a/src/librustc/ty/query/plumbing.rs +++ b/src/librustc/ty/query/plumbing.rs @@ -136,11 +136,14 @@ impl<'a, 'tcx, Q: QueryDescription<'tcx>> JobOwner<'a, 'tcx, Q> { Entry::Vacant(entry) => { // No job entry for this query. Return a new one to be started later return tls::with_related_context(tcx, |icx| { + // Create the `parent` variable before `info`. This allows LLVM + // to elide the move of `info` + let parent = icx.query.clone(); let info = QueryInfo { span, query: Q::query(key.clone()), }; - let job = Lrc::new(QueryJob::new(info, icx.query.clone())); + let job = Lrc::new(QueryJob::new(info, parent)); let owner = JobOwner { cache, job: job.clone(), From 86e63ba1b207d0479aeb00acc8cf1d52f2f19353 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Fri, 7 Dec 2018 04:34:37 +0100 Subject: [PATCH 72/84] Remove QueryResult --- src/librustc/ty/query/job.rs | 9 -------- src/librustc/ty/query/plumbing.rs | 37 ++++++++++++------------------- 2 files changed, 14 insertions(+), 32 deletions(-) diff --git a/src/librustc/ty/query/job.rs b/src/librustc/ty/query/job.rs index 6e513d68f60f5..0faf6b5a58fa1 100644 --- a/src/librustc/ty/query/job.rs +++ b/src/librustc/ty/query/job.rs @@ -40,15 +40,6 @@ use { rustc_data_structures::stable_hasher::{StableHasherResult, StableHasher, HashStable}, }; -/// Indicates the state of a query for a given key in a query map -pub(super) enum QueryResult<'tcx> { - /// An already executing query. The query job can be used to await for its completion - Started(Lrc>), - - /// The query panicked. Queries trying to wait on this will raise a fatal error / silently panic - Poisoned, -} - /// A span and a query key #[derive(Clone, Debug)] pub struct QueryInfo<'tcx> { diff --git a/src/librustc/ty/query/plumbing.rs b/src/librustc/ty/query/plumbing.rs index a73b92ed713ec..188aa7339c4ed 100644 --- a/src/librustc/ty/query/plumbing.rs +++ b/src/librustc/ty/query/plumbing.rs @@ -16,12 +16,11 @@ use dep_graph::{DepNodeIndex, DepNode, DepKind, DepNodeColor}; use errors::DiagnosticBuilder; use errors::Level; use errors::Diagnostic; -use errors::FatalError; use ty::tls; use ty::{TyCtxt}; use ty::query::Query; use ty::query::config::{QueryConfig, QueryDescription}; -use ty::query::job::{QueryJob, QueryResult, QueryInfo}; +use ty::query::job::{QueryJob, QueryInfo}; use ty::item_path; use util::common::{profq_msg, ProfileQueriesMsg, QueryMsg}; @@ -35,8 +34,12 @@ use syntax_pos::Span; use syntax::source_map::DUMMY_SP; pub struct QueryCache<'tcx, D: QueryConfig<'tcx> + ?Sized> { + /// Completed queries have their result stored here pub(super) results: FxHashMap>, - pub(super) active: FxHashMap>, + + /// Queries under execution will have an entry in this map. + /// The query job inside can be used to await for completion of queries. + pub(super) active: FxHashMap>>, } pub(super) struct QueryValue { @@ -127,12 +130,7 @@ impl<'a, 'tcx, Q: QueryDescription<'tcx>> JobOwner<'a, 'tcx, Q> { return TryGetJob::JobCompleted(result); } let job = match lock.active.entry((*key).clone()) { - Entry::Occupied(entry) => { - match *entry.get() { - QueryResult::Started(ref job) => job.clone(), - QueryResult::Poisoned => FatalError.raise(), - } - } + Entry::Occupied(entry) => entry.get().clone(), Entry::Vacant(entry) => { // No job entry for this query. Return a new one to be started later return tls::with_related_context(tcx, |icx| { @@ -146,7 +144,7 @@ impl<'a, 'tcx, Q: QueryDescription<'tcx>> JobOwner<'a, 'tcx, Q> { job: job.clone(), key: (*key).clone(), }; - entry.insert(QueryResult::Started(job)); + entry.insert(job); TryGetJob::NotYetStarted(owner) }) } @@ -228,10 +226,11 @@ impl<'a, 'tcx, Q: QueryDescription<'tcx>> JobOwner<'a, 'tcx, Q> { impl<'a, 'tcx, Q: QueryDescription<'tcx>> Drop for JobOwner<'a, 'tcx, Q> { fn drop(&mut self) { - // Poison the query so jobs waiting on it panic - self.cache.borrow_mut().active.insert(self.key.clone(), QueryResult::Poisoned); - // Also signal the completion of the job, so waiters - // will continue execution + // This job failed to execute due to a panic. + // Remove it from the list of active queries + self.cache.borrow_mut().active.remove(&self.key); + // Signal that the job not longer executes, so the waiters will continue execution. + // The waiters will try to execute the query which may result in them panicking too. self.job.signal_complete(); } } @@ -706,8 +705,6 @@ macro_rules! define_queries_inner { [$($modifiers:tt)*] fn $name:ident: $node:ident($K:ty) -> $V:ty,)*) => { use std::mem; - #[cfg(parallel_queries)] - use ty::query::job::QueryResult; use rustc_data_structures::sync::Lock; use { rustc_data_structures::stable_hasher::HashStable, @@ -744,13 +741,7 @@ macro_rules! define_queries_inner { // deadlock handler, and this shouldn't be locked $( jobs.extend( - self.$name.try_lock().unwrap().active.values().filter_map(|v| - if let QueryResult::Started(ref job) = *v { - Some(job.clone()) - } else { - None - } - ) + self.$name.try_lock().unwrap().active.values().cloned() ); )* From f8e508cde4854cc4da4333a33696f0e67d366d78 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Mon, 17 Dec 2018 14:20:42 +0100 Subject: [PATCH 73/84] Fix a recently introduces regression --- src/librustc_mir/transform/qualify_consts.rs | 2 +- .../consts/static_mut_containing_mut_ref.rs | 7 +++++++ .../consts/static_mut_containing_mut_ref2.rs | 8 ++++++++ .../static_mut_containing_mut_ref2.stderr | 9 +++++++++ src/test/ui/write-to-static-mut-in-static.rs | 4 ++-- .../ui/write-to-static-mut-in-static.stderr | 20 ++++++++++++++++--- 6 files changed, 44 insertions(+), 6 deletions(-) create mode 100644 src/test/ui/consts/static_mut_containing_mut_ref.rs create mode 100644 src/test/ui/consts/static_mut_containing_mut_ref2.rs create mode 100644 src/test/ui/consts/static_mut_containing_mut_ref2.stderr diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index b854f029e5106..646a671d4a2ce 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -518,7 +518,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { // Only allow statics (not consts) to refer to other statics. if self.mode == Mode::Static || self.mode == Mode::StaticMut { - if context.is_mutating_use() { + if self.mode == Mode::Static && context.is_mutating_use() { // this is not strictly necessary as miri will also bail out // For interior mutability we can't really catch this statically as that // goes through raw pointers and intermediate temporaries, so miri has diff --git a/src/test/ui/consts/static_mut_containing_mut_ref.rs b/src/test/ui/consts/static_mut_containing_mut_ref.rs new file mode 100644 index 0000000000000..27e1a111163b1 --- /dev/null +++ b/src/test/ui/consts/static_mut_containing_mut_ref.rs @@ -0,0 +1,7 @@ +// compile-pass + +static mut STDERR_BUFFER_SPACE: [u8; 42] = [0u8; 42]; + +pub static mut STDERR_BUFFER: *mut [u8] = unsafe { &mut STDERR_BUFFER_SPACE }; + +fn main() {} diff --git a/src/test/ui/consts/static_mut_containing_mut_ref2.rs b/src/test/ui/consts/static_mut_containing_mut_ref2.rs new file mode 100644 index 0000000000000..aa9bfb4aeab2d --- /dev/null +++ b/src/test/ui/consts/static_mut_containing_mut_ref2.rs @@ -0,0 +1,8 @@ +#![feature(const_let)] + +static mut STDERR_BUFFER_SPACE: u8 = 0; + +pub static mut STDERR_BUFFER: () = unsafe { *(&mut STDERR_BUFFER_SPACE) = 42; }; +//~^ references in statics may only refer to immutable values + +fn main() {} diff --git a/src/test/ui/consts/static_mut_containing_mut_ref2.stderr b/src/test/ui/consts/static_mut_containing_mut_ref2.stderr new file mode 100644 index 0000000000000..72923431c90ed --- /dev/null +++ b/src/test/ui/consts/static_mut_containing_mut_ref2.stderr @@ -0,0 +1,9 @@ +error[E0017]: references in statics may only refer to immutable values + --> $DIR/static_mut_containing_mut_ref2.rs:5:46 + | +LL | pub static mut STDERR_BUFFER: () = unsafe { *(&mut STDERR_BUFFER_SPACE) = 42; }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ statics require immutable values + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0017`. diff --git a/src/test/ui/write-to-static-mut-in-static.rs b/src/test/ui/write-to-static-mut-in-static.rs index 191f09b54ee73..983b5d48e60fc 100644 --- a/src/test/ui/write-to-static-mut-in-static.rs +++ b/src/test/ui/write-to-static-mut-in-static.rs @@ -12,10 +12,10 @@ pub static mut A: u32 = 0; pub static mut B: () = unsafe { A = 1; }; -//~^ ERROR cannot mutate statics in the initializer of another static +//~^ ERROR could not evaluate static initializer pub static mut C: u32 = unsafe { C = 1; 0 }; -//~^ ERROR cannot mutate statics in the initializer of another static +//~^ ERROR cycle detected pub static D: u32 = D; diff --git a/src/test/ui/write-to-static-mut-in-static.stderr b/src/test/ui/write-to-static-mut-in-static.stderr index 673a71b4642f3..335f849fb2472 100644 --- a/src/test/ui/write-to-static-mut-in-static.stderr +++ b/src/test/ui/write-to-static-mut-in-static.stderr @@ -1,14 +1,28 @@ -error: cannot mutate statics in the initializer of another static +error[E0080]: could not evaluate static initializer --> $DIR/write-to-static-mut-in-static.rs:14:33 | LL | pub static mut B: () = unsafe { A = 1; }; - | ^^^^^ + | ^^^^^ tried to modify a static's initial value from another static's initializer -error: cannot mutate statics in the initializer of another static +error[E0391]: cycle detected when const-evaluating `C` --> $DIR/write-to-static-mut-in-static.rs:17:34 | LL | pub static mut C: u32 = unsafe { C = 1; 0 }; | ^^^^^ + | +note: ...which requires const-evaluating `C`... + --> $DIR/write-to-static-mut-in-static.rs:17:1 + | +LL | pub static mut C: u32 = unsafe { C = 1; 0 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: ...which again requires const-evaluating `C`, completing the cycle +note: cycle used when const-evaluating + checking `C` + --> $DIR/write-to-static-mut-in-static.rs:17:1 + | +LL | pub static mut C: u32 = unsafe { C = 1; 0 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors +Some errors occurred: E0080, E0391. +For more information about an error, try `rustc --explain E0080`. From b9d74fc3ceec744ac6dbfb6b0d8d1003b54668e8 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Mon, 17 Dec 2018 14:36:10 +0100 Subject: [PATCH 74/84] Also test projections --- src/test/ui/consts/static_mut_containing_mut_ref2.rs | 2 +- src/test/ui/consts/static_mut_containing_mut_ref3.rs | 8 ++++++++ src/test/ui/consts/static_mut_containing_mut_ref3.stderr | 9 +++++++++ 3 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/consts/static_mut_containing_mut_ref3.rs create mode 100644 src/test/ui/consts/static_mut_containing_mut_ref3.stderr diff --git a/src/test/ui/consts/static_mut_containing_mut_ref2.rs b/src/test/ui/consts/static_mut_containing_mut_ref2.rs index aa9bfb4aeab2d..aeb69b2652cbf 100644 --- a/src/test/ui/consts/static_mut_containing_mut_ref2.rs +++ b/src/test/ui/consts/static_mut_containing_mut_ref2.rs @@ -3,6 +3,6 @@ static mut STDERR_BUFFER_SPACE: u8 = 0; pub static mut STDERR_BUFFER: () = unsafe { *(&mut STDERR_BUFFER_SPACE) = 42; }; -//~^ references in statics may only refer to immutable values +//~^ ERROR references in statics may only refer to immutable values fn main() {} diff --git a/src/test/ui/consts/static_mut_containing_mut_ref3.rs b/src/test/ui/consts/static_mut_containing_mut_ref3.rs new file mode 100644 index 0000000000000..0bc7faa9afdec --- /dev/null +++ b/src/test/ui/consts/static_mut_containing_mut_ref3.rs @@ -0,0 +1,8 @@ +#![feature(const_let)] + +static mut FOO: (u8, u8) = (42, 43); + +static mut BAR: () = unsafe { FOO.0 = 99; }; +//~^ ERROR could not evaluate static initializer + +fn main() {} diff --git a/src/test/ui/consts/static_mut_containing_mut_ref3.stderr b/src/test/ui/consts/static_mut_containing_mut_ref3.stderr new file mode 100644 index 0000000000000..cae53c6fee9dd --- /dev/null +++ b/src/test/ui/consts/static_mut_containing_mut_ref3.stderr @@ -0,0 +1,9 @@ +error[E0080]: could not evaluate static initializer + --> $DIR/static_mut_containing_mut_ref3.rs:5:31 + | +LL | static mut BAR: () = unsafe { FOO.0 = 99; }; + | ^^^^^^^^^^ tried to modify a static's initial value from another static's initializer + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. From 3414be0b3eb6192c13865e794817de396eeccd4b Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 21 Dec 2018 11:33:29 +0100 Subject: [PATCH 75/84] fix deprecation warnings in liballoc benches --- Cargo.lock | 1 + src/liballoc/Cargo.toml | 1 + src/liballoc/benches/btree/map.rs | 4 ++-- src/liballoc/benches/lib.rs | 1 + src/liballoc/benches/slice.rs | 3 ++- src/liballoc/benches/str.rs | 8 ++++---- 6 files changed, 11 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7e03474565d85..06d01ab78f3a8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -18,6 +18,7 @@ dependencies = [ "compiler_builtins 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "core 0.0.0", "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_xorshift 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] diff --git a/src/liballoc/Cargo.toml b/src/liballoc/Cargo.toml index b2eb3566c04a7..861c7cecb8879 100644 --- a/src/liballoc/Cargo.toml +++ b/src/liballoc/Cargo.toml @@ -15,6 +15,7 @@ compiler_builtins = { version = "0.1.0", features = ['rustc-dep-of-std'] } [dev-dependencies] rand = "0.6" +rand_xorshift = "0.1" [[test]] name = "collectionstests" diff --git a/src/liballoc/benches/btree/map.rs b/src/liballoc/benches/btree/map.rs index 20b9091a07bfc..6e2b5e06b7a91 100644 --- a/src/liballoc/benches/btree/map.rs +++ b/src/liballoc/benches/btree/map.rs @@ -12,7 +12,7 @@ use std::iter::Iterator; use std::vec::Vec; use std::collections::BTreeMap; -use rand::{Rng, thread_rng}; +use rand::{Rng, seq::SliceRandom, thread_rng}; use test::{Bencher, black_box}; macro_rules! map_insert_rand_bench { @@ -78,7 +78,7 @@ macro_rules! map_find_rand_bench { map.insert(k, k); } - rng.shuffle(&mut keys); + keys.shuffle(&mut rng); // measure let mut i = 0; diff --git a/src/liballoc/benches/lib.rs b/src/liballoc/benches/lib.rs index b4f4fd74f3a39..9502a7dc3c075 100644 --- a/src/liballoc/benches/lib.rs +++ b/src/liballoc/benches/lib.rs @@ -13,6 +13,7 @@ #![feature(test)] extern crate rand; +extern crate rand_xorshift; extern crate test; mod btree; diff --git a/src/liballoc/benches/slice.rs b/src/liballoc/benches/slice.rs index 490320f57cbf7..fc58899406332 100644 --- a/src/liballoc/benches/slice.rs +++ b/src/liballoc/benches/slice.rs @@ -12,8 +12,9 @@ use rand::{thread_rng}; use std::mem; use std::ptr; -use rand::{Rng, SeedableRng, XorShiftRng}; +use rand::{Rng, SeedableRng}; use rand::distributions::{Standard, Alphanumeric}; +use rand_xorshift::XorShiftRng; use test::{Bencher, black_box}; #[bench] diff --git a/src/liballoc/benches/str.rs b/src/liballoc/benches/str.rs index 38c94d4d8b5f3..c5e1576d24e26 100644 --- a/src/liballoc/benches/str.rs +++ b/src/liballoc/benches/str.rs @@ -274,11 +274,11 @@ make_test!(split_a_str, s, s.split("a").count()); make_test!(trim_ascii_char, s, { s.trim_matches(|c: char| c.is_ascii()) }); -make_test!(trim_left_ascii_char, s, { - s.trim_left_matches(|c: char| c.is_ascii()) +make_test!(trim_start_ascii_char, s, { + s.trim_start_matches(|c: char| c.is_ascii()) }); -make_test!(trim_right_ascii_char, s, { - s.trim_right_matches(|c: char| c.is_ascii()) +make_test!(trim_end_ascii_char, s, { + s.trim_end_matches(|c: char| c.is_ascii()) }); make_test!(find_underscore_char, s, s.find('_')); From 4f30a24e42137149373311f20525ac52cff44d94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Wed, 5 Dec 2018 18:59:48 +0100 Subject: [PATCH 76/84] Inline tweaks --- src/librustc/ty/context.rs | 10 ++++++++++ src/librustc/ty/query/plumbing.rs | 3 +++ src/librustc_data_structures/lib.rs | 2 ++ src/libserialize/opaque.rs | 1 + src/libstd/collections/hash/table.rs | 3 +++ 5 files changed, 19 insertions(+) diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 04d96e362a465..9883752da0b69 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -1926,6 +1926,7 @@ pub mod tls { /// to `value` during the call to `f`. It is restored to its previous value after. /// This is used to set the pointer to the new ImplicitCtxt. #[cfg(parallel_queries)] + #[inline] fn set_tlv R, R>(value: usize, f: F) -> R { rayon_core::tlv::with(value, f) } @@ -1933,6 +1934,7 @@ pub mod tls { /// Gets Rayon's thread local variable which is preserved for Rayon jobs. /// This is used to get the pointer to the current ImplicitCtxt. #[cfg(parallel_queries)] + #[inline] fn get_tlv() -> usize { rayon_core::tlv::get() } @@ -1945,6 +1947,7 @@ pub mod tls { /// It is restored to its previous value after. /// This is used to set the pointer to the new ImplicitCtxt. #[cfg(not(parallel_queries))] + #[inline] fn set_tlv R, R>(value: usize, f: F) -> R { let old = get_tlv(); let _reset = OnDrop(move || TLV.with(|tlv| tlv.set(old))); @@ -2009,6 +2012,7 @@ pub mod tls { } /// Sets `context` as the new current ImplicitCtxt for the duration of the function `f` + #[inline] pub fn enter_context<'a, 'gcx: 'tcx, 'tcx, F, R>(context: &ImplicitCtxt<'a, 'gcx, 'tcx>, f: F) -> R where F: FnOnce(&ImplicitCtxt<'a, 'gcx, 'tcx>) -> R @@ -2080,6 +2084,7 @@ pub mod tls { } /// Allows access to the current ImplicitCtxt in a closure if one is available + #[inline] pub fn with_context_opt(f: F) -> R where F: for<'a, 'gcx, 'tcx> FnOnce(Option<&ImplicitCtxt<'a, 'gcx, 'tcx>>) -> R { @@ -2097,6 +2102,7 @@ pub mod tls { /// Allows access to the current ImplicitCtxt. /// Panics if there is no ImplicitCtxt available + #[inline] pub fn with_context(f: F) -> R where F: for<'a, 'gcx, 'tcx> FnOnce(&ImplicitCtxt<'a, 'gcx, 'tcx>) -> R { @@ -2108,6 +2114,7 @@ pub mod tls { /// with the same 'gcx lifetime as the TyCtxt passed in. /// This will panic if you pass it a TyCtxt which has a different global interner from /// the current ImplicitCtxt's tcx field. + #[inline] pub fn with_related_context<'a, 'gcx, 'tcx1, F, R>(tcx: TyCtxt<'a, 'gcx, 'tcx1>, f: F) -> R where F: for<'b, 'tcx2> FnOnce(&ImplicitCtxt<'b, 'gcx, 'tcx2>) -> R { @@ -2126,6 +2133,7 @@ pub mod tls { /// is given an ImplicitCtxt with the same 'tcx and 'gcx lifetimes as the TyCtxt passed in. /// This will panic if you pass it a TyCtxt which has a different global interner or /// a different local interner from the current ImplicitCtxt's tcx field. + #[inline] pub fn with_fully_related_context<'a, 'gcx, 'tcx, F, R>(tcx: TyCtxt<'a, 'gcx, 'tcx>, f: F) -> R where F: for<'b> FnOnce(&ImplicitCtxt<'b, 'gcx, 'tcx>) -> R { @@ -2143,6 +2151,7 @@ pub mod tls { /// Allows access to the TyCtxt in the current ImplicitCtxt. /// Panics if there is no ImplicitCtxt available + #[inline] pub fn with(f: F) -> R where F: for<'a, 'gcx, 'tcx> FnOnce(TyCtxt<'a, 'gcx, 'tcx>) -> R { @@ -2151,6 +2160,7 @@ pub mod tls { /// Allows access to the TyCtxt in the current ImplicitCtxt. /// The closure is passed None if there is no ImplicitCtxt available + #[inline] pub fn with_opt(f: F) -> R where F: for<'a, 'gcx, 'tcx> FnOnce(Option>) -> R { diff --git a/src/librustc/ty/query/plumbing.rs b/src/librustc/ty/query/plumbing.rs index a73b92ed713ec..549f0e94d70ea 100644 --- a/src/librustc/ty/query/plumbing.rs +++ b/src/librustc/ty/query/plumbing.rs @@ -171,6 +171,7 @@ impl<'a, 'tcx, Q: QueryDescription<'tcx>> JobOwner<'a, 'tcx, Q> { /// Completes the query by updating the query cache with the `result`, /// signals the waiter and forgets the JobOwner, so it won't poison the query + #[inline(always)] pub(super) fn complete(self, result: &Q::Value, dep_node_index: DepNodeIndex) { // We can move out of `self` here because we `mem::forget` it below let key = unsafe { ptr::read(&self.key) }; @@ -227,6 +228,8 @@ impl<'a, 'tcx, Q: QueryDescription<'tcx>> JobOwner<'a, 'tcx, Q> { } impl<'a, 'tcx, Q: QueryDescription<'tcx>> Drop for JobOwner<'a, 'tcx, Q> { + #[inline(never)] + #[cold] fn drop(&mut self) { // Poison the query so jobs waiting on it panic self.cache.borrow_mut().active.insert(self.key.clone(), QueryResult::Poisoned); diff --git a/src/librustc_data_structures/lib.rs b/src/librustc_data_structures/lib.rs index bc2b8f1d6523e..9d0201a9e38b1 100644 --- a/src/librustc_data_structures/lib.rs +++ b/src/librustc_data_structures/lib.rs @@ -113,12 +113,14 @@ pub struct OnDrop(pub F); impl OnDrop { /// Forgets the function which prevents it from running. /// Ensure that the function owns no memory, otherwise it will be leaked. + #[inline] pub fn disable(self) { std::mem::forget(self); } } impl Drop for OnDrop { + #[inline] fn drop(&mut self) { (self.0)(); } diff --git a/src/libserialize/opaque.rs b/src/libserialize/opaque.rs index 4ce80bc36a080..3eb7bc14a927f 100644 --- a/src/libserialize/opaque.rs +++ b/src/libserialize/opaque.rs @@ -172,6 +172,7 @@ pub struct Decoder<'a> { } impl<'a> Decoder<'a> { + #[inline] pub fn new(data: &'a [u8], position: usize) -> Decoder<'a> { Decoder { data, diff --git a/src/libstd/collections/hash/table.rs b/src/libstd/collections/hash/table.rs index 479e6dccb90dd..7195175db28a6 100644 --- a/src/libstd/collections/hash/table.rs +++ b/src/libstd/collections/hash/table.rs @@ -740,6 +740,7 @@ impl RawTable { } } + #[inline] fn new_internal( capacity: usize, fallibility: Fallibility, @@ -755,12 +756,14 @@ impl RawTable { /// Tries to create a new raw table from a given capacity. If it cannot allocate, /// it returns with AllocErr. + #[inline] pub fn try_new(capacity: usize) -> Result, CollectionAllocErr> { Self::new_internal(capacity, Fallible) } /// Creates a new raw table from a given capacity. All buckets are /// initially empty. + #[inline] pub fn new(capacity: usize) -> RawTable { match Self::new_internal(capacity, Infallible) { Err(CollectionAllocErr::CapacityOverflow) => panic!("capacity overflow"), From 6ed596ebe245df1a8de8a609222c8e217508f6dd Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Fri, 21 Dec 2018 13:39:45 +0100 Subject: [PATCH 77/84] Update tests to changes on master --- src/test/ui/consts/static_mut_containing_mut_ref2.rs | 1 + .../ui/consts/static_mut_containing_mut_ref2.stderr | 11 +++++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/test/ui/consts/static_mut_containing_mut_ref2.rs b/src/test/ui/consts/static_mut_containing_mut_ref2.rs index aeb69b2652cbf..4180b1e295ab0 100644 --- a/src/test/ui/consts/static_mut_containing_mut_ref2.rs +++ b/src/test/ui/consts/static_mut_containing_mut_ref2.rs @@ -4,5 +4,6 @@ static mut STDERR_BUFFER_SPACE: u8 = 0; pub static mut STDERR_BUFFER: () = unsafe { *(&mut STDERR_BUFFER_SPACE) = 42; }; //~^ ERROR references in statics may only refer to immutable values +//~| ERROR static contains unimplemented expression type fn main() {} diff --git a/src/test/ui/consts/static_mut_containing_mut_ref2.stderr b/src/test/ui/consts/static_mut_containing_mut_ref2.stderr index 72923431c90ed..f0ae1545056b7 100644 --- a/src/test/ui/consts/static_mut_containing_mut_ref2.stderr +++ b/src/test/ui/consts/static_mut_containing_mut_ref2.stderr @@ -4,6 +4,13 @@ error[E0017]: references in statics may only refer to immutable values LL | pub static mut STDERR_BUFFER: () = unsafe { *(&mut STDERR_BUFFER_SPACE) = 42; }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ statics require immutable values -error: aborting due to previous error +error[E0019]: static contains unimplemented expression type + --> $DIR/static_mut_containing_mut_ref2.rs:5:45 + | +LL | pub static mut STDERR_BUFFER: () = unsafe { *(&mut STDERR_BUFFER_SPACE) = 42; }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0017`. +Some errors occurred: E0017, E0019. +For more information about an error, try `rustc --explain E0017`. From 8c40aedb8fdc9b97013f8484498a71bada06c4dc Mon Sep 17 00:00:00 2001 From: Otavio Salvador Date: Fri, 21 Dec 2018 11:33:59 -0200 Subject: [PATCH 78/84] Fix feature gate to point to 1.32.0 for `path_from_str` When the feature has been added back (#55148) the feature gate has not been adjusted accordingly. We have it enabled for 1.32.0, currently in Beta, so adjust it. Refs: #44431. Signed-off-by: Otavio Salvador --- src/libstd/path.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstd/path.rs b/src/libstd/path.rs index b882442dd2f4e..df05eb7d6042d 100644 --- a/src/libstd/path.rs +++ b/src/libstd/path.rs @@ -1461,7 +1461,7 @@ impl From for PathBuf { } } -#[stable(feature = "path_from_str", since = "1.26.0")] +#[stable(feature = "path_from_str", since = "1.32.0")] impl FromStr for PathBuf { type Err = ParseError; From 87c8cdd8efb60a9a4b57e5b959bc56d36ea511b5 Mon Sep 17 00:00:00 2001 From: Taylor Cramer Date: Fri, 21 Dec 2018 10:18:38 -0800 Subject: [PATCH 79/84] Stabilize #[repr(packed(N))] --- src/libsyntax/feature_gate.rs | 12 ++--------- src/test/codegen/packed.rs | 1 - src/test/run-pass/issues/issue-48159.rs | 1 - src/test/run-pass/packed/auxiliary/packed.rs | 2 -- .../packed/packed-struct-borrow-element.rs | 2 -- .../packed/packed-struct-generic-size.rs | 3 --- .../packed/packed-struct-generic-size.stderr | 12 +++++------ .../run-pass/packed/packed-struct-match.rs | 1 - .../run-pass/packed/packed-struct-size.rs | 3 --- src/test/run-pass/packed/packed-struct-vec.rs | 1 - .../packed/packed-tuple-struct-size.rs | 2 -- .../run-pass/structs-enums/align-struct.rs | 1 - src/test/run-pass/union/union-packed.rs | 1 - src/test/ui/conflicting-repr-hints.rs | 1 - src/test/ui/conflicting-repr-hints.stderr | 20 +++++++++---------- .../feature-gates/feature-gate-repr_packed.rs | 18 ----------------- .../feature-gate-repr_packed.stderr | 19 ------------------ src/test/ui/print_type_sizes/packed.rs | 1 - 18 files changed, 18 insertions(+), 83 deletions(-) delete mode 100644 src/test/ui/feature-gates/feature-gate-repr_packed.rs delete mode 100644 src/test/ui/feature-gates/feature-gate-repr_packed.stderr diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 844f49fe842b7..db84703afde5d 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -397,9 +397,6 @@ declare_features! ( // Multiple patterns with `|` in `if let` and `while let`. (active, if_while_or_patterns, "1.26.0", Some(48215), None), - // Allows `#[repr(packed)]` attribute on structs. - (active, repr_packed, "1.26.0", Some(33158), None), - // Allows macro invocations in `extern {}` blocks. (active, macros_in_extern, "1.27.0", Some(49476), None), @@ -695,6 +692,8 @@ declare_features! ( (accepted, self_in_typedefs, "1.32.0", Some(49303), None), // `use path as _;` and `extern crate c as _;` (accepted, underscore_imports, "1.33.0", Some(48216), None), + // Allows `#[repr(packed(N))]` attribute on structs. + (accepted, repr_packed, "1.33.0", Some(33158), None), ); // If you change this, please modify `src/doc/unstable-book` as well. You must @@ -1588,13 +1587,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { gate_feature_post!(&self, repr_simd, attr.span, "SIMD types are experimental and possibly buggy"); } - if let Some((name, _)) = item.name_value_literal() { - if name == "packed" { - gate_feature_post!(&self, repr_packed, attr.span, - "the `#[repr(packed(n))]` attribute \ - is experimental"); - } - } } } } diff --git a/src/test/codegen/packed.rs b/src/test/codegen/packed.rs index b50f5b6f16fed..fb6507fd22a4b 100644 --- a/src/test/codegen/packed.rs +++ b/src/test/codegen/packed.rs @@ -13,7 +13,6 @@ // min-llvm-version 7.0 #![crate_type = "lib"] -#![feature(repr_packed)] #[repr(packed)] pub struct Packed1 { diff --git a/src/test/run-pass/issues/issue-48159.rs b/src/test/run-pass/issues/issue-48159.rs index 2f625747b2591..0d5b211bca9b6 100644 --- a/src/test/run-pass/issues/issue-48159.rs +++ b/src/test/run-pass/issues/issue-48159.rs @@ -9,7 +9,6 @@ // except according to those terms. // run-pass -#![feature(repr_packed)] #![allow(non_camel_case_types)] use std::mem; diff --git a/src/test/run-pass/packed/auxiliary/packed.rs b/src/test/run-pass/packed/auxiliary/packed.rs index 828be41cd4157..6884c360e4a58 100644 --- a/src/test/run-pass/packed/auxiliary/packed.rs +++ b/src/test/run-pass/packed/auxiliary/packed.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(repr_packed)] - #[repr(packed)] pub struct P1S5 { a: u8, diff --git a/src/test/run-pass/packed/packed-struct-borrow-element.rs b/src/test/run-pass/packed/packed-struct-borrow-element.rs index 69969ba640fb0..87c26c597f58f 100644 --- a/src/test/run-pass/packed/packed-struct-borrow-element.rs +++ b/src/test/run-pass/packed/packed-struct-borrow-element.rs @@ -12,8 +12,6 @@ #![allow(dead_code)] // ignore-emscripten weird assertion? -#![feature(repr_packed)] - #[repr(packed)] struct Foo1 { bar: u8, diff --git a/src/test/run-pass/packed/packed-struct-generic-size.rs b/src/test/run-pass/packed/packed-struct-generic-size.rs index 58cd5505ffc29..9608ff4ec0e92 100644 --- a/src/test/run-pass/packed/packed-struct-generic-size.rs +++ b/src/test/run-pass/packed/packed-struct-generic-size.rs @@ -10,11 +10,8 @@ // run-pass #![allow(dead_code)] -#![allow(stable_features)] #![allow(unused_comparisons)] -#![feature(repr_packed)] - use std::mem; #[repr(packed)] diff --git a/src/test/run-pass/packed/packed-struct-generic-size.stderr b/src/test/run-pass/packed/packed-struct-generic-size.stderr index 994ea7c44fbe4..672952f6e9f3b 100644 --- a/src/test/run-pass/packed/packed-struct-generic-size.stderr +++ b/src/test/run-pass/packed/packed-struct-generic-size.stderr @@ -1,35 +1,35 @@ warning: unnecessary path disambiguator - --> $DIR/packed-struct-generic-size.rs:49:14 + --> $DIR/packed-struct-generic-size.rs:46:14 | LL | check!(P1::, 1, 3); | ^^ try removing `::` warning: unnecessary path disambiguator - --> $DIR/packed-struct-generic-size.rs:50:14 + --> $DIR/packed-struct-generic-size.rs:47:14 | LL | check!(P1::, 1, 11); | ^^ try removing `::` warning: unnecessary path disambiguator - --> $DIR/packed-struct-generic-size.rs:52:14 + --> $DIR/packed-struct-generic-size.rs:49:14 | LL | check!(P2::, 1, 3); | ^^ try removing `::` warning: unnecessary path disambiguator - --> $DIR/packed-struct-generic-size.rs:53:14 + --> $DIR/packed-struct-generic-size.rs:50:14 | LL | check!(P2::, 2, 12); | ^^ try removing `::` warning: unnecessary path disambiguator - --> $DIR/packed-struct-generic-size.rs:55:15 + --> $DIR/packed-struct-generic-size.rs:52:15 | LL | check!(P4C::, 1, 3); | ^^ try removing `::` warning: unnecessary path disambiguator - --> $DIR/packed-struct-generic-size.rs:56:15 + --> $DIR/packed-struct-generic-size.rs:53:15 | LL | check!(P4C::, 4, 12); | ^^ try removing `::` diff --git a/src/test/run-pass/packed/packed-struct-match.rs b/src/test/run-pass/packed/packed-struct-match.rs index e349a4e7f5414..21ef55e5a42f5 100644 --- a/src/test/run-pass/packed/packed-struct-match.rs +++ b/src/test/run-pass/packed/packed-struct-match.rs @@ -9,7 +9,6 @@ // except according to those terms. // run-pass -#![feature(repr_packed)] #[repr(packed)] struct Foo1 { diff --git a/src/test/run-pass/packed/packed-struct-size.rs b/src/test/run-pass/packed/packed-struct-size.rs index 27e07b87ff417..d6a236ffc6d68 100644 --- a/src/test/run-pass/packed/packed-struct-size.rs +++ b/src/test/run-pass/packed/packed-struct-size.rs @@ -13,9 +13,6 @@ #![allow(non_camel_case_types)] #![allow(non_upper_case_globals)] -#![feature(repr_packed)] - - use std::mem; #[repr(packed)] diff --git a/src/test/run-pass/packed/packed-struct-vec.rs b/src/test/run-pass/packed/packed-struct-vec.rs index d64bfe0033b94..6fd24479c1959 100644 --- a/src/test/run-pass/packed/packed-struct-vec.rs +++ b/src/test/run-pass/packed/packed-struct-vec.rs @@ -9,7 +9,6 @@ // except according to those terms. // run-pass -#![feature(repr_packed)] use std::fmt; use std::mem; diff --git a/src/test/run-pass/packed/packed-tuple-struct-size.rs b/src/test/run-pass/packed/packed-tuple-struct-size.rs index 011ff4c20f4a8..8b18bd33c74d9 100644 --- a/src/test/run-pass/packed/packed-tuple-struct-size.rs +++ b/src/test/run-pass/packed/packed-tuple-struct-size.rs @@ -12,8 +12,6 @@ #![allow(dead_code)] #![allow(non_camel_case_types)] -#![feature(repr_packed)] - use std::mem; #[repr(packed)] diff --git a/src/test/run-pass/structs-enums/align-struct.rs b/src/test/run-pass/structs-enums/align-struct.rs index a0d05a6d0d2c1..109d5b75590df 100644 --- a/src/test/run-pass/structs-enums/align-struct.rs +++ b/src/test/run-pass/structs-enums/align-struct.rs @@ -11,7 +11,6 @@ // run-pass #![allow(dead_code)] #![feature(box_syntax)] -#![feature(repr_packed)] use std::mem; diff --git a/src/test/run-pass/union/union-packed.rs b/src/test/run-pass/union/union-packed.rs index a6aef9046eeb2..4c9e06a395c05 100644 --- a/src/test/run-pass/union/union-packed.rs +++ b/src/test/run-pass/union/union-packed.rs @@ -13,7 +13,6 @@ #![allow(non_snake_case)] #![feature(untagged_unions)] -#![feature(repr_packed)] use std::mem::{size_of, size_of_val, align_of, align_of_val}; diff --git a/src/test/ui/conflicting-repr-hints.rs b/src/test/ui/conflicting-repr-hints.rs index 426f60c6b098c..f16bd1003f934 100644 --- a/src/test/ui/conflicting-repr-hints.rs +++ b/src/test/ui/conflicting-repr-hints.rs @@ -9,7 +9,6 @@ // except according to those terms. #![allow(dead_code)] -#![feature(repr_packed)] #[repr(C)] enum A { A } diff --git a/src/test/ui/conflicting-repr-hints.stderr b/src/test/ui/conflicting-repr-hints.stderr index 7a4e5a5488ad3..01b72d93823cc 100644 --- a/src/test/ui/conflicting-repr-hints.stderr +++ b/src/test/ui/conflicting-repr-hints.stderr @@ -1,47 +1,47 @@ warning[E0566]: conflicting representation hints - --> $DIR/conflicting-repr-hints.rs:20:8 + --> $DIR/conflicting-repr-hints.rs:19:8 | LL | #[repr(C, u64)] //~ WARNING conflicting representation hints | ^ ^^^ warning[E0566]: conflicting representation hints - --> $DIR/conflicting-repr-hints.rs:23:8 + --> $DIR/conflicting-repr-hints.rs:22:8 | LL | #[repr(u32, u64)] //~ WARNING conflicting representation hints | ^^^ ^^^ error[E0587]: type has conflicting packed and align representation hints - --> $DIR/conflicting-repr-hints.rs:30:1 + --> $DIR/conflicting-repr-hints.rs:29:1 | LL | struct F(i32); //~ ERROR type has conflicting packed and align representation hints | ^^^^^^^^^^^^^^ error[E0587]: type has conflicting packed and align representation hints - --> $DIR/conflicting-repr-hints.rs:34:1 + --> $DIR/conflicting-repr-hints.rs:33:1 | LL | struct G(i32); //~ ERROR type has conflicting packed and align representation hints | ^^^^^^^^^^^^^^ error[E0587]: type has conflicting packed and align representation hints - --> $DIR/conflicting-repr-hints.rs:38:1 + --> $DIR/conflicting-repr-hints.rs:37:1 | LL | struct H(i32); //~ ERROR type has conflicting packed and align representation hints | ^^^^^^^^^^^^^^ error[E0634]: type has conflicting packed representation hints - --> $DIR/conflicting-repr-hints.rs:41:1 + --> $DIR/conflicting-repr-hints.rs:40:1 | LL | struct I(i32); //~ ERROR type has conflicting packed representation hints | ^^^^^^^^^^^^^^ error[E0634]: type has conflicting packed representation hints - --> $DIR/conflicting-repr-hints.rs:45:1 + --> $DIR/conflicting-repr-hints.rs:44:1 | LL | struct J(i32); //~ ERROR type has conflicting packed representation hints | ^^^^^^^^^^^^^^ error[E0587]: type has conflicting packed and align representation hints - --> $DIR/conflicting-repr-hints.rs:51:1 + --> $DIR/conflicting-repr-hints.rs:50:1 | LL | / union X { //~ ERROR type has conflicting packed and align representation hints LL | | i: i32 @@ -49,7 +49,7 @@ LL | | } | |_^ error[E0587]: type has conflicting packed and align representation hints - --> $DIR/conflicting-repr-hints.rs:57:1 + --> $DIR/conflicting-repr-hints.rs:56:1 | LL | / union Y { //~ ERROR type has conflicting packed and align representation hints LL | | i: i32 @@ -57,7 +57,7 @@ LL | | } | |_^ error[E0587]: type has conflicting packed and align representation hints - --> $DIR/conflicting-repr-hints.rs:63:1 + --> $DIR/conflicting-repr-hints.rs:62:1 | LL | / union Z { //~ ERROR type has conflicting packed and align representation hints LL | | i: i32 diff --git a/src/test/ui/feature-gates/feature-gate-repr_packed.rs b/src/test/ui/feature-gates/feature-gate-repr_packed.rs deleted file mode 100644 index 65e3be288fdf7..0000000000000 --- a/src/test/ui/feature-gates/feature-gate-repr_packed.rs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2018 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. - -#[repr(packed(1))] //~ error: the `#[repr(packed(n))]` attribute is experimental -struct Foo(u64); - -#[repr(C)] -#[repr(packed(1))] //~ error: the `#[repr(packed(n))]` attribute is experimental -struct Bar(u64); - -fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-repr_packed.stderr b/src/test/ui/feature-gates/feature-gate-repr_packed.stderr deleted file mode 100644 index ed89a3f6b3169..0000000000000 --- a/src/test/ui/feature-gates/feature-gate-repr_packed.stderr +++ /dev/null @@ -1,19 +0,0 @@ -error[E0658]: the `#[repr(packed(n))]` attribute is experimental (see issue #33158) - --> $DIR/feature-gate-repr_packed.rs:11:1 - | -LL | #[repr(packed(1))] //~ error: the `#[repr(packed(n))]` attribute is experimental - | ^^^^^^^^^^^^^^^^^^ - | - = help: add #![feature(repr_packed)] to the crate attributes to enable - -error[E0658]: the `#[repr(packed(n))]` attribute is experimental (see issue #33158) - --> $DIR/feature-gate-repr_packed.rs:15:1 - | -LL | #[repr(packed(1))] //~ error: the `#[repr(packed(n))]` attribute is experimental - | ^^^^^^^^^^^^^^^^^^ - | - = help: add #![feature(repr_packed)] to the crate attributes to enable - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/print_type_sizes/packed.rs b/src/test/ui/print_type_sizes/packed.rs index bc11146aa8516..9ff794178fcfa 100644 --- a/src/test/ui/print_type_sizes/packed.rs +++ b/src/test/ui/print_type_sizes/packed.rs @@ -21,7 +21,6 @@ #![allow(dead_code)] #![feature(start)] -#![feature(repr_packed)] #[derive(Default)] #[repr(packed)] From e5e19d960815a66d9094a817319ca92c7ed13872 Mon Sep 17 00:00:00 2001 From: Taylor Cramer Date: Fri, 21 Dec 2018 10:37:55 -0800 Subject: [PATCH 80/84] Remove unstable-book repr-packed entry --- .../unstable-book/src/language-features/repr-packed.md | 8 -------- 1 file changed, 8 deletions(-) delete mode 100644 src/doc/unstable-book/src/language-features/repr-packed.md diff --git a/src/doc/unstable-book/src/language-features/repr-packed.md b/src/doc/unstable-book/src/language-features/repr-packed.md deleted file mode 100644 index 2dd763d04b0ab..0000000000000 --- a/src/doc/unstable-book/src/language-features/repr-packed.md +++ /dev/null @@ -1,8 +0,0 @@ -# `repr_packed` - -The tracking issue for this feature is [#33158] - -[#33158]: https://github.com/rust-lang/rust/issues/33158 - ------------------------- - From 51e4c1f320fe8fd4b00574430d285b62d10ee93b Mon Sep 17 00:00:00 2001 From: Ryan Marcus Date: Fri, 21 Dec 2018 14:50:25 -0500 Subject: [PATCH 81/84] Fixed typo in HashMap documentation Previously "with a custom type as key", now "with a custom key type" --- src/libstd/collections/hash/map.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index 55a1a75d049e9..9c994d29202ee 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -354,7 +354,7 @@ const DISPLACEMENT_THRESHOLD: usize = 128; /// *stat += random_stat_buff(); /// ``` /// -/// The easiest way to use `HashMap` with a custom type as key is to derive [`Eq`] and [`Hash`]. +/// The easiest way to use `HashMap` with a custom key type is to derive [`Eq`] and [`Hash`]. /// We must also derive [`PartialEq`]. /// /// [`Eq`]: ../../std/cmp/trait.Eq.html From 34dc5c8980e428a306f9af09b9e3002e0e9f443e Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Fri, 21 Dec 2018 21:25:32 +0100 Subject: [PATCH 82/84] macro_literal_matcher was stabilized in 1.32; not 1.32. --- src/libsyntax/feature_gate.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 844f49fe842b7..3fe827a2a089f 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -684,7 +684,7 @@ declare_features! ( // `extern crate foo as bar;` puts `bar` into extern prelude. (accepted, extern_crate_item_prelude, "1.31.0", Some(55599), None), // Allows use of the `:literal` macro fragment specifier (RFC 1576). - (accepted, macro_literal_matcher, "1.31.0", Some(35625), None), + (accepted, macro_literal_matcher, "1.32.0", Some(35625), None), // Integer match exhaustiveness checking (RFC 2591) (accepted, exhaustive_integer_patterns, "1.32.0", Some(50907), None), // Use `?` as the Kleene "at most one" operator. From 0203a1cc3139d053ea40d8b89c70ea9c361c837a Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Fri, 21 Dec 2018 21:27:04 +0100 Subject: [PATCH 83/84] exhaustive_integer_patterns slipped 1.32; stabilized in 1.33. --- src/libsyntax/feature_gate.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 3fe827a2a089f..ddb1355ee567e 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -685,14 +685,14 @@ declare_features! ( (accepted, extern_crate_item_prelude, "1.31.0", Some(55599), None), // Allows use of the `:literal` macro fragment specifier (RFC 1576). (accepted, macro_literal_matcher, "1.32.0", Some(35625), None), - // Integer match exhaustiveness checking (RFC 2591) - (accepted, exhaustive_integer_patterns, "1.32.0", Some(50907), None), // Use `?` as the Kleene "at most one" operator. (accepted, macro_at_most_once_rep, "1.32.0", Some(48075), None), // `Self` struct constructor (RFC 2302) (accepted, self_struct_ctor, "1.32.0", Some(51994), None), // `Self` in type definitions (RFC 2300) (accepted, self_in_typedefs, "1.32.0", Some(49303), None), + // Integer match exhaustiveness checking (RFC 2591) + (accepted, exhaustive_integer_patterns, "1.33.0", Some(50907), None), // `use path as _;` and `extern crate c as _;` (accepted, underscore_imports, "1.33.0", Some(48216), None), ); From 097d39d8ecb2d8aa828393c66e85716081188793 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Fri, 21 Dec 2018 23:12:15 +0100 Subject: [PATCH 84/84] Fix alignment for array indexing We need to reduce the alignment with the used offset. If the offset isn't known, we need to reduce with the element size to support arbitrary offsets. --- src/librustc_codegen_ssa/mir/place.rs | 13 ++++++-- src/librustc_codegen_ssa/mir/rvalue.rs | 3 +- src/test/codegen/issue-56927.rs | 44 ++++++++++++++++++++++++++ src/test/codegen/packed.rs | 36 +++++++++++++++++++++ 4 files changed, 93 insertions(+), 3 deletions(-) create mode 100644 src/test/codegen/issue-56927.rs diff --git a/src/librustc_codegen_ssa/mir/place.rs b/src/librustc_codegen_ssa/mir/place.rs index 90aa9f6cbc763..5fad4a24b262e 100644 --- a/src/librustc_codegen_ssa/mir/place.rs +++ b/src/librustc_codegen_ssa/mir/place.rs @@ -335,11 +335,20 @@ impl<'a, 'tcx: 'a, V: CodegenObject> PlaceRef<'tcx, V> { bx: &mut Bx, llindex: V ) -> Self { + // Statically compute the offset if we can, otherwise just use the element size, + // as this will yield the lowest alignment. + let layout = self.layout.field(bx, 0); + let offset = if bx.is_const_integral(llindex) { + layout.size.checked_mul(bx.const_to_uint(llindex), bx).unwrap_or(layout.size) + } else { + layout.size + }; + PlaceRef { llval: bx.inbounds_gep(self.llval, &[bx.cx().const_usize(0), llindex]), llextra: None, - layout: self.layout.field(bx.cx(), 0), - align: self.align + layout, + align: self.align.restrict_for_offset(offset), } } diff --git a/src/librustc_codegen_ssa/mir/rvalue.rs b/src/librustc_codegen_ssa/mir/rvalue.rs index c932ffd1c1bda..052342dd7597b 100644 --- a/src/librustc_codegen_ssa/mir/rvalue.rs +++ b/src/librustc_codegen_ssa/mir/rvalue.rs @@ -131,8 +131,9 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let keep_going = header_bx.icmp(IntPredicate::IntNE, current, end); header_bx.cond_br(keep_going, body_bx.llbb(), next_bx.llbb()); + let align = dest.align.restrict_for_offset(dest.layout.field(bx.cx(), 0).size); cg_elem.val.store(&mut body_bx, - PlaceRef::new_sized(current, cg_elem.layout, dest.align)); + PlaceRef::new_sized(current, cg_elem.layout, align)); let next = body_bx.inbounds_gep(current, &[bx.cx().const_usize(1)]); body_bx.br(header_bx.llbb()); diff --git a/src/test/codegen/issue-56927.rs b/src/test/codegen/issue-56927.rs new file mode 100644 index 0000000000000..0544ff86aacfa --- /dev/null +++ b/src/test/codegen/issue-56927.rs @@ -0,0 +1,44 @@ +// compile-flags: -C no-prepopulate-passes + +#![crate_type="rlib"] +use std::usize; + +#[repr(align(16))] +pub struct S { + arr: [u32; 4], +} + +// CHECK-LABEL: @test1 +// CHECK: store i32 0, i32* %{{.+}}, align 16 +// CHECK: store i32 1, i32* %{{.+}}, align 4 +// CHECK: store i32 2, i32* %{{.+}}, align 8 +// CHECK: store i32 3, i32* %{{.+}}, align 4 +#[no_mangle] +pub fn test1(s: &mut S) { + s.arr[0] = 0; + s.arr[1] = 1; + s.arr[2] = 2; + s.arr[3] = 3; +} + +// CHECK-LABEL: @test2 +// CHECK: store i32 4, i32* %{{.+}}, align 4 +#[allow(const_err)] +#[no_mangle] +pub fn test2(s: &mut S) { + s.arr[usize::MAX / 4 + 1] = 4; +} + +// CHECK-LABEL: @test3 +// CHECK: store i32 5, i32* %{{.+}}, align 4 +#[no_mangle] +pub fn test3(s: &mut S, i: usize) { + s.arr[i] = 5; +} + +// CHECK-LABEL: @test4 +// CHECK: store i32 6, i32* %{{.+}}, align 4 +#[no_mangle] +pub fn test4(s: &mut S) { + s.arr = [6; 4]; +} diff --git a/src/test/codegen/packed.rs b/src/test/codegen/packed.rs index b50f5b6f16fed..e60051de559b5 100644 --- a/src/test/codegen/packed.rs +++ b/src/test/codegen/packed.rs @@ -84,6 +84,42 @@ pub fn call_pkd2(f: fn() -> Array) -> BigPacked2 { BigPacked2 { dealign: 0, data: f() } } +// CHECK-LABEL: @write_packed_array1 +// CHECK: store i32 0, i32* %{{.+}}, align 1 +// CHECK: store i32 1, i32* %{{.+}}, align 1 +// CHECK: store i32 2, i32* %{{.+}}, align 1 +#[no_mangle] +pub fn write_packed_array1(p: &mut BigPacked1) { + p.data.0[0] = 0; + p.data.0[1] = 1; + p.data.0[2] = 2; +} + +// CHECK-LABEL: @write_packed_array2 +// CHECK: store i32 0, i32* %{{.+}}, align 2 +// CHECK: store i32 1, i32* %{{.+}}, align 2 +// CHECK: store i32 2, i32* %{{.+}}, align 2 +#[no_mangle] +pub fn write_packed_array2(p: &mut BigPacked2) { + p.data.0[0] = 0; + p.data.0[1] = 1; + p.data.0[2] = 2; +} + +// CHECK-LABEL: @repeat_packed_array1 +// CHECK: store i32 42, i32* %{{.+}}, align 1 +#[no_mangle] +pub fn repeat_packed_array1(p: &mut BigPacked1) { + p.data.0 = [42; 8]; +} + +// CHECK-LABEL: @repeat_packed_array2 +// CHECK: store i32 42, i32* %{{.+}}, align 2 +#[no_mangle] +pub fn repeat_packed_array2(p: &mut BigPacked2) { + p.data.0 = [42; 8]; +} + #[repr(packed)] #[derive(Copy, Clone)] pub struct Packed1Pair(u8, u32);