From da5a0cd69c64e0772960caee32f36b11bca1b498 Mon Sep 17 00:00:00 2001 From: Nick Fitzgerald Date: Thu, 7 Feb 2019 12:33:27 +0100 Subject: [PATCH 01/27] De-duplicate number formatting implementations for smaller code size Instead of inlining the same logic into every number formatting implementation, pull it out into a function that each of the number formatting impls call into. --- src/libcore/fmt/num.rs | 69 +++++++++++++++++++++++------------------- 1 file changed, 38 insertions(+), 31 deletions(-) diff --git a/src/libcore/fmt/num.rs b/src/libcore/fmt/num.rs index 3a812337bb111..31886748fa6c1 100644 --- a/src/libcore/fmt/num.rs +++ b/src/libcore/fmt/num.rs @@ -178,7 +178,8 @@ integer! { i32, u32 } integer! { i64, u64 } integer! { i128, u128 } -const DEC_DIGITS_LUT: &'static[u8] = + +static DEC_DIGITS_LUT: &[u8; 200] = b"0001020304050607080910111213141516171819\ 2021222324252627282930313233343536373839\ 4041424344454647484950515253545556575859\ @@ -186,18 +187,8 @@ const DEC_DIGITS_LUT: &'static[u8] = 8081828384858687888990919293949596979899"; macro_rules! impl_Display { - ($($t:ident),*: $conv_fn:ident) => ($( - #[stable(feature = "rust1", since = "1.0.0")] - impl fmt::Display for $t { - #[allow(unused_comparisons)] - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let is_nonnegative = *self >= 0; - let mut n = if is_nonnegative { - self.$conv_fn() - } else { - // convert the negative num to positive by summing 1 to it's 2 complement - (!self.$conv_fn()).wrapping_add(1) - }; + ($($t:ident),* as $u:ident via $conv_fn:ident named $name:ident) => { + fn $name(mut n: $u, is_nonnegative: bool, f: &mut fmt::Formatter) -> fmt::Result { let mut buf = uninitialized_array![u8; 39]; let mut curr = buf.len() as isize; let buf_ptr = MaybeUninit::first_ptr_mut(&mut buf); @@ -205,18 +196,18 @@ macro_rules! impl_Display { unsafe { // need at least 16 bits for the 4-characters-at-a-time to work. - if ::mem::size_of::<$t>() >= 2 { - // eagerly decode 4 characters at a time - while n >= 10000 { - let rem = (n % 10000) as isize; - n /= 10000; + assert!(::mem::size_of::<$u>() >= 2); + + // eagerly decode 4 characters at a time + while n >= 10000 { + let rem = (n % 10000) as isize; + n /= 10000; - let d1 = (rem / 100) << 1; - let d2 = (rem % 100) << 1; - curr -= 4; - ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2); - ptr::copy_nonoverlapping(lut_ptr.offset(d2), buf_ptr.offset(curr + 2), 2); - } + let d1 = (rem / 100) << 1; + let d2 = (rem % 100) << 1; + curr -= 4; + ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2); + ptr::copy_nonoverlapping(lut_ptr.offset(d2), buf_ptr.offset(curr + 2), 2); } // if we reach here numbers are <= 9999, so at most 4 chars long @@ -247,15 +238,31 @@ macro_rules! impl_Display { }; f.pad_integral(is_nonnegative, "", buf_slice) } - })*); + + $( + #[stable(feature = "rust1", since = "1.0.0")] + impl fmt::Display for $t { + #[allow(unused_comparisons)] + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let is_nonnegative = *self >= 0; + let n = if is_nonnegative { + self.$conv_fn() + } else { + // convert the negative num to positive by summing 1 to it's 2 complement + (!self.$conv_fn()).wrapping_add(1) + }; + $name(n, is_nonnegative, f) + } + })* + }; } -impl_Display!(i8, u8, i16, u16, i32, u32: to_u32); -impl_Display!(i64, u64: to_u64); -impl_Display!(i128, u128: to_u128); +impl_Display!(i8, u8, i16, u16, i32, u32 as u32 via to_u32 named fmt_u32); +impl_Display!(i64, u64 as u64 via to_u64 named fmt_u64); +impl_Display!(i128, u128 as u128 via to_u128 named fmt_u128); #[cfg(target_pointer_width = "16")] -impl_Display!(isize, usize: to_u16); +impl_Display!(isize, usize as u16 via to_u16 named fmt_usize); #[cfg(target_pointer_width = "32")] -impl_Display!(isize, usize: to_u32); +impl_Display!(isize, usize as u32 via to_u32 named fmt_usize); #[cfg(target_pointer_width = "64")] -impl_Display!(isize, usize: to_u64); +impl_Display!(isize, usize as u64 via to_u64 named fmt_usize); From ed2157a38f6ccdfe460f2f058f60a67daac6cc5a Mon Sep 17 00:00:00 2001 From: Nick Fitzgerald Date: Thu, 7 Feb 2019 13:02:27 +0100 Subject: [PATCH 02/27] De-duplicate write_prefix lambda in pad_integral For smaller code size. --- src/libcore/fmt/mod.rs | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index 530b2f52c0df2..dd95e3b4a7ce4 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -1153,38 +1153,46 @@ impl<'a> Formatter<'a> { sign = Some('+'); width += 1; } - let prefixed = self.alternate(); - if prefixed { + let prefix = if self.alternate() { width += prefix.chars().count(); - } + Some(prefix) + } else { + None + }; // Writes the sign if it exists, and then the prefix if it was requested - let write_prefix = |f: &mut Formatter| { + #[inline(never)] + fn write_prefix(f: &mut Formatter, sign: Option, prefix: Option<&str>) -> Result { if let Some(c) = sign { f.buf.write_char(c)?; } - if prefixed { f.buf.write_str(prefix) } - else { Ok(()) } - }; + if let Some(prefix) = prefix { + f.buf.write_str(prefix) + } else { + Ok(()) + } + } // The `width` field is more of a `min-width` parameter at this point. match self.width { // If there's no minimum length requirements then we can just // write the bytes. None => { - write_prefix(self)?; self.buf.write_str(buf) + write_prefix(self, sign, prefix)?; + self.buf.write_str(buf) } // Check if we're over the minimum width, if so then we can also // just write the bytes. Some(min) if width >= min => { - write_prefix(self)?; self.buf.write_str(buf) + write_prefix(self, sign, prefix)?; + self.buf.write_str(buf) } // The sign and prefix goes before the padding if the fill character // is zero Some(min) if self.sign_aware_zero_pad() => { self.fill = '0'; self.align = rt::v1::Alignment::Right; - write_prefix(self)?; + write_prefix(self, sign, prefix)?; self.with_padding(min - width, rt::v1::Alignment::Right, |f| { f.buf.write_str(buf) }) @@ -1192,7 +1200,8 @@ impl<'a> Formatter<'a> { // Otherwise, the sign and prefix goes after the padding Some(min) => { self.with_padding(min - width, rt::v1::Alignment::Right, |f| { - write_prefix(f)?; f.buf.write_str(buf) + write_prefix(f, sign, prefix)?; + f.buf.write_str(buf) }) } } From e633f152397545c2fd80795fc928ec555656b2ab Mon Sep 17 00:00:00 2001 From: Nick Fitzgerald Date: Thu, 7 Feb 2019 15:01:30 +0100 Subject: [PATCH 03/27] Un-monomorphize and inline formatting with padding The generic `F` in `with_padding` was causing a bunch of stuff to get inlined that otherwise needn't be, blowing up code size. --- src/libcore/fmt/mod.rs | 86 ++++++++++++++++++++++++++++-------------- 1 file changed, 57 insertions(+), 29 deletions(-) diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index dd95e3b4a7ce4..605779046ef51 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -1036,6 +1036,32 @@ pub fn write(output: &mut dyn Write, args: Arguments) -> Result { Ok(()) } +/// Padding after the end of something. Returned by `Formatter::padding`. +#[must_use = "don't forget to write the post padding"] +struct PostPadding { + fill: [u8; 4], + fill_len: u32, + padding: usize, +} + +impl PostPadding { + /// Safety relies on `fill[..fill_len]` being a valid UTF-8 char. + unsafe fn new(fill: [u8; 4], fill_len: u32, padding: usize) -> PostPadding { + PostPadding { fill, fill_len, padding } + } + + /// Write this post padding. + fn write(self, buf: &mut dyn Write) -> Result { + let fill = unsafe { + str::from_utf8_unchecked(&self.fill.get_unchecked(..self.fill_len as usize)) + }; + for _ in 0..self.padding { + buf.write_str(fill)?; + } + Ok(()) + } +} + impl<'a> Formatter<'a> { fn wrap_buf<'b, 'c, F>(&'b mut self, wrap: F) -> Formatter<'c> where 'b: 'c, F: FnOnce(&'b mut (dyn Write+'b)) -> &'c mut (dyn Write+'c) @@ -1193,16 +1219,16 @@ impl<'a> Formatter<'a> { self.fill = '0'; self.align = rt::v1::Alignment::Right; write_prefix(self, sign, prefix)?; - self.with_padding(min - width, rt::v1::Alignment::Right, |f| { - f.buf.write_str(buf) - }) + let post_padding = self.padding(min - width, rt::v1::Alignment::Right)?; + self.buf.write_str(buf)?; + post_padding.write(self.buf) } // Otherwise, the sign and prefix goes after the padding Some(min) => { - self.with_padding(min - width, rt::v1::Alignment::Right, |f| { - write_prefix(f, sign, prefix)?; - f.buf.write_str(buf) - }) + let post_padding = self.padding(min - width, rt::v1::Alignment::Right)?; + write_prefix(self, sign, prefix)?; + self.buf.write_str(buf)?; + post_padding.write(self.buf) } } } @@ -1273,19 +1299,21 @@ impl<'a> Formatter<'a> { // up the minimum width with the specified string + some alignment. Some(width) => { let align = rt::v1::Alignment::Left; - self.with_padding(width - s.chars().count(), align, |me| { - me.buf.write_str(s) - }) + let post_padding = self.padding(width - s.chars().count(), align)?; + self.buf.write_str(s)?; + post_padding.write(self.buf) } } } - /// Runs a callback, emitting the correct padding either before or - /// afterwards depending on whether right or left alignment is requested. - fn with_padding(&mut self, padding: usize, default: rt::v1::Alignment, - f: F) -> Result - where F: FnOnce(&mut Formatter) -> Result, - { + /// Write the pre-padding and return the unwritten post-padding. Callers are + /// responsible for ensuring post-padding is written after the thing that is + /// being padded. + fn padding( + &mut self, + padding: usize, + default: rt::v1::Alignment + ) -> result::Result { let align = match self.align { rt::v1::Alignment::Unknown => default, _ => self.align @@ -1299,19 +1327,19 @@ impl<'a> Formatter<'a> { }; let mut fill = [0; 4]; - let fill = self.fill.encode_utf8(&mut fill); - - for _ in 0..pre_pad { - self.buf.write_str(fill)?; - } + let fill_len = { + let fill = self.fill.encode_utf8(&mut fill); - f(self)?; + for _ in 0..pre_pad { + self.buf.write_str(fill)?; + } - for _ in 0..post_pad { - self.buf.write_str(fill)?; - } + fill.len() + }; - Ok(()) + Ok(unsafe { + PostPadding::new(fill, fill_len as u32, post_pad) + }) } /// Takes the formatted parts and applies the padding. @@ -1343,9 +1371,9 @@ impl<'a> Formatter<'a> { let ret = if width <= len { // no padding self.write_formatted_parts(&formatted) } else { - self.with_padding(width - len, align, |f| { - f.write_formatted_parts(&formatted) - }) + let post_padding = self.padding(width - len, align)?; + self.write_formatted_parts(&formatted)?; + post_padding.write(self.buf) }; self.fill = old_fill; self.align = old_align; From 05f0dee04a39912222f7237502e2230f0da1b551 Mon Sep 17 00:00:00 2001 From: varkor Date: Thu, 7 Feb 2019 16:38:23 +0100 Subject: [PATCH 04/27] Improve the error messages for missing stability attributes This makes the capitalisation consistent and provides more context (especially for missing top-level attributes). --- src/librustc/middle/stability.rs | 25 +++++++++++-------- src/test/ui/missing/missing-stability.rs | 4 +-- src/test/ui/missing/missing-stability.stderr | 6 ++--- .../missing-stability-attr-at-top-level.rs | 4 +++ ...missing-stability-attr-at-top-level.stderr | 11 ++++++++ .../stability-attribute-issue-43027.rs | 2 +- .../stability-attribute-issue-43027.stderr | 4 +-- .../stability-attribute-sanity-3.rs | 2 +- .../stability-attribute-sanity-3.stderr | 4 +-- 9 files changed, 41 insertions(+), 21 deletions(-) create mode 100644 src/test/ui/stability-attribute/missing-stability-attr-at-top-level.rs create mode 100644 src/test/ui/stability-attribute/missing-stability-attr-at-top-level.stderr diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs index 34c77d08f5a7e..1f7345dde8e8e 100644 --- a/src/librustc/middle/stability.rs +++ b/src/librustc/middle/stability.rs @@ -322,14 +322,17 @@ struct MissingStabilityAnnotations<'a, 'tcx: 'a> { } impl<'a, 'tcx: 'a> MissingStabilityAnnotations<'a, 'tcx> { - fn check_missing_stability(&self, id: NodeId, span: Span) { + fn check_missing_stability(&self, id: NodeId, span: Span, name: &str) { let hir_id = self.tcx.hir().node_to_hir_id(id); let stab = self.tcx.stability().local_stability(hir_id); let is_error = !self.tcx.sess.opts.test && stab.is_none() && self.access_levels.is_reachable(id); if is_error { - self.tcx.sess.span_err(span, "This node does not have a stability attribute"); + self.tcx.sess.span_err( + span, + &format!("{} has missing stability attribute", name), + ); } } } @@ -347,42 +350,44 @@ impl<'a, 'tcx> Visitor<'tcx> for MissingStabilityAnnotations<'a, 'tcx> { // optional. They inherit stability from their parents when unannotated. hir::ItemKind::Impl(.., None, _, _) | hir::ItemKind::ForeignMod(..) => {} - _ => self.check_missing_stability(i.id, i.span) + hir::ItemKind::Mod(..) => self.check_missing_stability(i.id, i.span, "module"), + + _ => self.check_missing_stability(i.id, i.span, "node") } intravisit::walk_item(self, i) } fn visit_trait_item(&mut self, ti: &'tcx hir::TraitItem) { - self.check_missing_stability(ti.id, ti.span); + self.check_missing_stability(ti.id, ti.span, "node"); intravisit::walk_trait_item(self, ti); } fn visit_impl_item(&mut self, ii: &'tcx hir::ImplItem) { let impl_def_id = self.tcx.hir().local_def_id(self.tcx.hir().get_parent(ii.id)); if self.tcx.impl_trait_ref(impl_def_id).is_none() { - self.check_missing_stability(ii.id, ii.span); + self.check_missing_stability(ii.id, ii.span, "node"); } intravisit::walk_impl_item(self, ii); } fn visit_variant(&mut self, var: &'tcx Variant, g: &'tcx Generics, item_id: NodeId) { - self.check_missing_stability(var.node.data.id(), var.span); + self.check_missing_stability(var.node.data.id(), var.span, "variant"); intravisit::walk_variant(self, var, g, item_id); } fn visit_struct_field(&mut self, s: &'tcx StructField) { - self.check_missing_stability(s.id, s.span); + self.check_missing_stability(s.id, s.span, "field"); intravisit::walk_struct_field(self, s); } fn visit_foreign_item(&mut self, i: &'tcx hir::ForeignItem) { - self.check_missing_stability(i.id, i.span); + self.check_missing_stability(i.id, i.span, "node"); intravisit::walk_foreign_item(self, i); } fn visit_macro_def(&mut self, md: &'tcx hir::MacroDef) { - self.check_missing_stability(md.id, md.span); + self.check_missing_stability(md.id, md.span, "macro"); } } @@ -867,7 +872,7 @@ pub fn check_unused_or_stable_features<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { tcx, access_levels, }; - missing.check_missing_stability(ast::CRATE_NODE_ID, krate.span); + missing.check_missing_stability(ast::CRATE_NODE_ID, krate.span, "crate"); intravisit::walk_crate(&mut missing, krate); krate.visit_all_item_likes(&mut missing.as_deep_visitor()); } diff --git a/src/test/ui/missing/missing-stability.rs b/src/test/ui/missing/missing-stability.rs index 86841706325f7..c7d721e836d1f 100644 --- a/src/test/ui/missing/missing-stability.rs +++ b/src/test/ui/missing/missing-stability.rs @@ -6,7 +6,7 @@ #![stable(feature = "stable_test_feature", since = "1.0.0")] pub fn unmarked() { - //~^ ERROR This node does not have a stability attribute + //~^ ERROR node has missing stability attribute () } @@ -20,5 +20,5 @@ pub mod foo { pub mod bar { // #[stable] is not inherited pub fn unmarked() {} - //~^ ERROR This node does not have a stability attribute + //~^ ERROR node has missing stability attribute } diff --git a/src/test/ui/missing/missing-stability.stderr b/src/test/ui/missing/missing-stability.stderr index e55bd00e2c673..bced3efd83da3 100644 --- a/src/test/ui/missing/missing-stability.stderr +++ b/src/test/ui/missing/missing-stability.stderr @@ -1,13 +1,13 @@ -error: This node does not have a stability attribute +error: node has missing stability attribute --> $DIR/missing-stability.rs:8:1 | LL | / pub fn unmarked() { -LL | | //~^ ERROR This node does not have a stability attribute +LL | | //~^ ERROR node has missing stability attribute LL | | () LL | | } | |_^ -error: This node does not have a stability attribute +error: node has missing stability attribute --> $DIR/missing-stability.rs:22:5 | LL | pub fn unmarked() {} diff --git a/src/test/ui/stability-attribute/missing-stability-attr-at-top-level.rs b/src/test/ui/stability-attribute/missing-stability-attr-at-top-level.rs new file mode 100644 index 0000000000000..8f750ae62f5e4 --- /dev/null +++ b/src/test/ui/stability-attribute/missing-stability-attr-at-top-level.rs @@ -0,0 +1,4 @@ +#![feature(staged_api)] +//~^ ERROR crate has missing stability attribute + +fn main() {} diff --git a/src/test/ui/stability-attribute/missing-stability-attr-at-top-level.stderr b/src/test/ui/stability-attribute/missing-stability-attr-at-top-level.stderr new file mode 100644 index 0000000000000..f674797694557 --- /dev/null +++ b/src/test/ui/stability-attribute/missing-stability-attr-at-top-level.stderr @@ -0,0 +1,11 @@ +error: crate has missing stability attribute + --> $DIR/missing-stability-attr-at-top-level.rs:1:1 + | +LL | / #![feature(staged_api)] +LL | | //~^ ERROR crate has missing stability attribute +LL | | +LL | | fn main() {} + | |____________^ + +error: aborting due to previous error + diff --git a/src/test/ui/stability-attribute/stability-attribute-issue-43027.rs b/src/test/ui/stability-attribute/stability-attribute-issue-43027.rs index 596a6eb6ed366..0b243bb52119b 100644 --- a/src/test/ui/stability-attribute/stability-attribute-issue-43027.rs +++ b/src/test/ui/stability-attribute/stability-attribute-issue-43027.rs @@ -2,7 +2,7 @@ #![stable(feature = "test", since = "0")] #[stable(feature = "test", since = "0")] -pub struct Reverse(pub T); //~ ERROR This node does not have a stability attribute +pub struct Reverse(pub T); //~ ERROR field has missing stability attribute fn main() { // Make sure the field is used to fill the stability cache diff --git a/src/test/ui/stability-attribute/stability-attribute-issue-43027.stderr b/src/test/ui/stability-attribute/stability-attribute-issue-43027.stderr index e123f42023324..7ffb4bb487a7b 100644 --- a/src/test/ui/stability-attribute/stability-attribute-issue-43027.stderr +++ b/src/test/ui/stability-attribute/stability-attribute-issue-43027.stderr @@ -1,7 +1,7 @@ -error: This node does not have a stability attribute +error: field has missing stability attribute --> $DIR/stability-attribute-issue-43027.rs:5:23 | -LL | pub struct Reverse(pub T); //~ ERROR This node does not have a stability attribute +LL | pub struct Reverse(pub T); //~ ERROR field has missing stability attribute | ^^^^^ error: aborting due to previous error diff --git a/src/test/ui/stability-attribute/stability-attribute-sanity-3.rs b/src/test/ui/stability-attribute/stability-attribute-sanity-3.rs index 0c132e8857550..13ef3d3f53d2b 100644 --- a/src/test/ui/stability-attribute/stability-attribute-sanity-3.rs +++ b/src/test/ui/stability-attribute/stability-attribute-sanity-3.rs @@ -5,7 +5,7 @@ #![stable(feature = "stable_test_feature", since = "1.0.0")] #[macro_export] -macro_rules! mac { //~ ERROR This node does not have a stability attribute +macro_rules! mac { //~ ERROR macro has missing stability attribute () => () } diff --git a/src/test/ui/stability-attribute/stability-attribute-sanity-3.stderr b/src/test/ui/stability-attribute/stability-attribute-sanity-3.stderr index d42dcc0c778a7..1c759d49b9947 100644 --- a/src/test/ui/stability-attribute/stability-attribute-sanity-3.stderr +++ b/src/test/ui/stability-attribute/stability-attribute-sanity-3.stderr @@ -1,7 +1,7 @@ -error: This node does not have a stability attribute +error: macro has missing stability attribute --> $DIR/stability-attribute-sanity-3.rs:8:1 | -LL | / macro_rules! mac { //~ ERROR This node does not have a stability attribute +LL | / macro_rules! mac { //~ ERROR macro has missing stability attribute LL | | () => () LL | | } | |_^ From c104b5c89767101a40ef173eb84d3aa1122e5e9a Mon Sep 17 00:00:00 2001 From: Nick Fitzgerald Date: Thu, 7 Feb 2019 15:44:52 +0100 Subject: [PATCH 05/27] Also de-duplicate 32- and 64-bit number formatting on wasm32 --- src/libcore/fmt/num.rs | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/src/libcore/fmt/num.rs b/src/libcore/fmt/num.rs index 31886748fa6c1..b9fa364037108 100644 --- a/src/libcore/fmt/num.rs +++ b/src/libcore/fmt/num.rs @@ -257,12 +257,22 @@ macro_rules! impl_Display { }; } -impl_Display!(i8, u8, i16, u16, i32, u32 as u32 via to_u32 named fmt_u32); -impl_Display!(i64, u64 as u64 via to_u64 named fmt_u64); +// Include wasm32 in here since it doesn't reflect the native pointer size, and +// often cares strongly about getting a smaller code size. +#[cfg(any(target_pointer_width = "64", target_arch = "wasm32"))] +mod imp { + use super::*; + impl_Display!( + i8, u8, i16, u16, i32, u32, i64, u64, usize, isize + as u64 via to_u64 named fmt_u64 + ); +} + +#[cfg(not(any(target_pointer_width = "64", target_arch = "wasm32")))] +mod imp { + use super::*; + impl_Display!(i8, u8, i16, u16, i32, u32, isize, usize as u32 via to_u32 named fmt_u32); + impl_Display!(i64, u64 as u64 via to_u64 named fmt_u64); +} + impl_Display!(i128, u128 as u128 via to_u128 named fmt_u128); -#[cfg(target_pointer_width = "16")] -impl_Display!(isize, usize as u16 via to_u16 named fmt_usize); -#[cfg(target_pointer_width = "32")] -impl_Display!(isize, usize as u32 via to_u32 named fmt_usize); -#[cfg(target_pointer_width = "64")] -impl_Display!(isize, usize as u64 via to_u64 named fmt_usize); From 05df9ff41537bab6586eea7ad9272eeb611e09e1 Mon Sep 17 00:00:00 2001 From: Nick Fitzgerald Date: Thu, 7 Feb 2019 17:05:23 +0100 Subject: [PATCH 06/27] Add a wasm code size test for stringifying numbers --- .../wasm-stringify-ints-small/Makefile | 10 +++++ .../run-make/wasm-stringify-ints-small/foo.rs | 39 +++++++++++++++++++ 2 files changed, 49 insertions(+) create mode 100644 src/test/run-make/wasm-stringify-ints-small/Makefile create mode 100755 src/test/run-make/wasm-stringify-ints-small/foo.rs diff --git a/src/test/run-make/wasm-stringify-ints-small/Makefile b/src/test/run-make/wasm-stringify-ints-small/Makefile new file mode 100644 index 0000000000000..18e47242f806b --- /dev/null +++ b/src/test/run-make/wasm-stringify-ints-small/Makefile @@ -0,0 +1,10 @@ +-include ../../run-make-fulldeps/tools.mk + +ifeq ($(TARGET),wasm32-unknown-unknown) +all: + $(RUSTC) foo.rs -C lto -O --target wasm32-unknown-unknown + wc -c < $(TMPDIR)/foo.wasm + [ "`wc -c < $(TMPDIR)/foo.wasm`" -lt "21000" ] +else +all: +endif diff --git a/src/test/run-make/wasm-stringify-ints-small/foo.rs b/src/test/run-make/wasm-stringify-ints-small/foo.rs new file mode 100755 index 0000000000000..6aa249aabeb93 --- /dev/null +++ b/src/test/run-make/wasm-stringify-ints-small/foo.rs @@ -0,0 +1,39 @@ +#![crate_type = "cdylib"] + +extern "C" { + fn observe(ptr: *const u8, len: usize); + + fn get_u8() -> u8; + fn get_i8() -> i8; + fn get_u16() -> u16; + fn get_i16() -> i16; + fn get_u32() -> u32; + fn get_i32() -> i32; + fn get_u64() -> u64; + fn get_i64() -> i64; + fn get_usize() -> usize; + fn get_isize() -> isize; +} + +macro_rules! stringify { + ( $($f:ident)* ) => { + $( + let s = $f().to_string(); + observe(s.as_ptr(), s.len()); + )* + }; +} + +#[no_mangle] +pub unsafe extern "C" fn foo() { + stringify!(get_u8); + stringify!(get_i8); + stringify!(get_u16); + stringify!(get_i16); + stringify!(get_u32); + stringify!(get_i32); + stringify!(get_u64); + stringify!(get_i64); + stringify!(get_usize); + stringify!(get_isize); +} From 8fea7054b9c77a7dcf242ce84cfc0a58d81a9c00 Mon Sep 17 00:00:00 2001 From: Nick Fitzgerald Date: Fri, 8 Feb 2019 10:02:24 +0100 Subject: [PATCH 07/27] Use write_char for writing padding characters Removes some unsafe *and* saves almost half a kilobyte of code size. --- src/libcore/fmt/mod.rs | 30 +++++-------------- .../wasm-stringify-ints-small/Makefile | 2 +- 2 files changed, 9 insertions(+), 23 deletions(-) diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index 605779046ef51..4c0eb1eeb5530 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -1039,24 +1039,19 @@ pub fn write(output: &mut dyn Write, args: Arguments) -> Result { /// Padding after the end of something. Returned by `Formatter::padding`. #[must_use = "don't forget to write the post padding"] struct PostPadding { - fill: [u8; 4], - fill_len: u32, + fill: char, padding: usize, } impl PostPadding { - /// Safety relies on `fill[..fill_len]` being a valid UTF-8 char. - unsafe fn new(fill: [u8; 4], fill_len: u32, padding: usize) -> PostPadding { - PostPadding { fill, fill_len, padding } + fn new(fill: char, padding: usize) -> PostPadding { + PostPadding { fill, padding } } /// Write this post padding. fn write(self, buf: &mut dyn Write) -> Result { - let fill = unsafe { - str::from_utf8_unchecked(&self.fill.get_unchecked(..self.fill_len as usize)) - }; for _ in 0..self.padding { - buf.write_str(fill)?; + buf.write_char(self.fill)?; } Ok(()) } @@ -1326,20 +1321,11 @@ impl<'a> Formatter<'a> { rt::v1::Alignment::Center => (padding / 2, (padding + 1) / 2), }; - let mut fill = [0; 4]; - let fill_len = { - let fill = self.fill.encode_utf8(&mut fill); - - for _ in 0..pre_pad { - self.buf.write_str(fill)?; - } - - fill.len() - }; + for _ in 0..pre_pad { + self.buf.write_char(self.fill)?; + } - Ok(unsafe { - PostPadding::new(fill, fill_len as u32, post_pad) - }) + Ok(PostPadding::new(self.fill, post_pad)) } /// Takes the formatted parts and applies the padding. diff --git a/src/test/run-make/wasm-stringify-ints-small/Makefile b/src/test/run-make/wasm-stringify-ints-small/Makefile index 18e47242f806b..26de6a0c68990 100644 --- a/src/test/run-make/wasm-stringify-ints-small/Makefile +++ b/src/test/run-make/wasm-stringify-ints-small/Makefile @@ -4,7 +4,7 @@ ifeq ($(TARGET),wasm32-unknown-unknown) all: $(RUSTC) foo.rs -C lto -O --target wasm32-unknown-unknown wc -c < $(TMPDIR)/foo.wasm - [ "`wc -c < $(TMPDIR)/foo.wasm`" -lt "21000" ] + [ "`wc -c < $(TMPDIR)/foo.wasm`" -lt "20500" ] else all: endif From f00f0e676887c8970858897836aa1e8a81d8aa60 Mon Sep 17 00:00:00 2001 From: Nick Fitzgerald Date: Fri, 8 Feb 2019 10:04:32 +0100 Subject: [PATCH 08/27] Don't shadow the provided `stringify!` macro in a wasm code size test case --- .../run-make/wasm-stringify-ints-small/foo.rs | 40 ++++++++----------- 1 file changed, 17 insertions(+), 23 deletions(-) mode change 100755 => 100644 src/test/run-make/wasm-stringify-ints-small/foo.rs diff --git a/src/test/run-make/wasm-stringify-ints-small/foo.rs b/src/test/run-make/wasm-stringify-ints-small/foo.rs old mode 100755 new mode 100644 index 6aa249aabeb93..7a947f013ad48 --- a/src/test/run-make/wasm-stringify-ints-small/foo.rs +++ b/src/test/run-make/wasm-stringify-ints-small/foo.rs @@ -2,22 +2,14 @@ extern "C" { fn observe(ptr: *const u8, len: usize); - - fn get_u8() -> u8; - fn get_i8() -> i8; - fn get_u16() -> u16; - fn get_i16() -> i16; - fn get_u32() -> u32; - fn get_i32() -> i32; - fn get_u64() -> u64; - fn get_i64() -> i64; - fn get_usize() -> usize; - fn get_isize() -> isize; } -macro_rules! stringify { - ( $($f:ident)* ) => { +macro_rules! s { + ( $( $f:ident -> $t:ty );* $(;)* ) => { $( + extern "C" { + fn $f() -> $t; + } let s = $f().to_string(); observe(s.as_ptr(), s.len()); )* @@ -26,14 +18,16 @@ macro_rules! stringify { #[no_mangle] pub unsafe extern "C" fn foo() { - stringify!(get_u8); - stringify!(get_i8); - stringify!(get_u16); - stringify!(get_i16); - stringify!(get_u32); - stringify!(get_i32); - stringify!(get_u64); - stringify!(get_i64); - stringify!(get_usize); - stringify!(get_isize); + s! { + get_u8 -> u8; + get_i8 -> i8; + get_u16 -> u16; + get_i16 -> i16; + get_u32 -> u32; + get_i32 -> i32; + get_u64 -> u64; + get_i64 -> i64; + get_usize -> usize; + get_isize -> isize; + } } From 03d4fd973aaa6dca0d1e756ecab5d4f17947337b Mon Sep 17 00:00:00 2001 From: varkor Date: Fri, 8 Feb 2019 14:30:13 +0100 Subject: [PATCH 09/27] Use descriptive variant name --- src/librustc/middle/stability.rs | 4 ++-- src/test/ui/missing/missing-stability.rs | 4 ++-- src/test/ui/missing/missing-stability.stderr | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs index 1f7345dde8e8e..45f53dee98582 100644 --- a/src/librustc/middle/stability.rs +++ b/src/librustc/middle/stability.rs @@ -352,7 +352,7 @@ impl<'a, 'tcx> Visitor<'tcx> for MissingStabilityAnnotations<'a, 'tcx> { hir::ItemKind::Mod(..) => self.check_missing_stability(i.id, i.span, "module"), - _ => self.check_missing_stability(i.id, i.span, "node") + _ => self.check_missing_stability(i.id, i.span, i.node.descriptive_variant()) } intravisit::walk_item(self, i) @@ -382,7 +382,7 @@ impl<'a, 'tcx> Visitor<'tcx> for MissingStabilityAnnotations<'a, 'tcx> { } fn visit_foreign_item(&mut self, i: &'tcx hir::ForeignItem) { - self.check_missing_stability(i.id, i.span, "node"); + self.check_missing_stability(i.id, i.span, i.node.descriptive_variant()); intravisit::walk_foreign_item(self, i); } diff --git a/src/test/ui/missing/missing-stability.rs b/src/test/ui/missing/missing-stability.rs index c7d721e836d1f..469c22fdb17d7 100644 --- a/src/test/ui/missing/missing-stability.rs +++ b/src/test/ui/missing/missing-stability.rs @@ -6,7 +6,7 @@ #![stable(feature = "stable_test_feature", since = "1.0.0")] pub fn unmarked() { - //~^ ERROR node has missing stability attribute + //~^ ERROR function has missing stability attribute () } @@ -20,5 +20,5 @@ pub mod foo { pub mod bar { // #[stable] is not inherited pub fn unmarked() {} - //~^ ERROR node has missing stability attribute + //~^ ERROR function has missing stability attribute } diff --git a/src/test/ui/missing/missing-stability.stderr b/src/test/ui/missing/missing-stability.stderr index bced3efd83da3..6c81f2bac5788 100644 --- a/src/test/ui/missing/missing-stability.stderr +++ b/src/test/ui/missing/missing-stability.stderr @@ -1,13 +1,13 @@ -error: node has missing stability attribute +error: function has missing stability attribute --> $DIR/missing-stability.rs:8:1 | LL | / pub fn unmarked() { -LL | | //~^ ERROR node has missing stability attribute +LL | | //~^ ERROR function has missing stability attribute LL | | () LL | | } | |_^ -error: node has missing stability attribute +error: function has missing stability attribute --> $DIR/missing-stability.rs:22:5 | LL | pub fn unmarked() {} From bb1eed0ec8537a09666978ad92d71ee1b5aba13b Mon Sep 17 00:00:00 2001 From: varkor Date: Fri, 8 Feb 2019 15:07:26 +0100 Subject: [PATCH 10/27] Correct descriptive item name for impl --- src/librustc/hir/mod.rs | 2 +- src/librustc/middle/stability.rs | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 3e7dd1432e1e3..d520acf950a23 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -2288,7 +2288,7 @@ impl ItemKind { ItemKind::Union(..) => "union", ItemKind::Trait(..) => "trait", ItemKind::TraitAlias(..) => "trait alias", - ItemKind::Impl(..) => "item", + ItemKind::Impl(..) => "impl", } } diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs index 45f53dee98582..04046fa3b00ab 100644 --- a/src/librustc/middle/stability.rs +++ b/src/librustc/middle/stability.rs @@ -350,8 +350,6 @@ impl<'a, 'tcx> Visitor<'tcx> for MissingStabilityAnnotations<'a, 'tcx> { // optional. They inherit stability from their parents when unannotated. hir::ItemKind::Impl(.., None, _, _) | hir::ItemKind::ForeignMod(..) => {} - hir::ItemKind::Mod(..) => self.check_missing_stability(i.id, i.span, "module"), - _ => self.check_missing_stability(i.id, i.span, i.node.descriptive_variant()) } @@ -359,14 +357,14 @@ impl<'a, 'tcx> Visitor<'tcx> for MissingStabilityAnnotations<'a, 'tcx> { } fn visit_trait_item(&mut self, ti: &'tcx hir::TraitItem) { - self.check_missing_stability(ti.id, ti.span, "node"); + self.check_missing_stability(ti.id, ti.span, "item"); intravisit::walk_trait_item(self, ti); } fn visit_impl_item(&mut self, ii: &'tcx hir::ImplItem) { let impl_def_id = self.tcx.hir().local_def_id(self.tcx.hir().get_parent(ii.id)); if self.tcx.impl_trait_ref(impl_def_id).is_none() { - self.check_missing_stability(ii.id, ii.span, "node"); + self.check_missing_stability(ii.id, ii.span, "item"); } intravisit::walk_impl_item(self, ii); } From 18089df7e8c5c3178049ce5ac3d0680d90aa97a4 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sun, 10 Feb 2019 15:44:24 +0000 Subject: [PATCH 11/27] Fix ICE and invalid filenames in MIR printing code --- src/librustc_mir/util/pretty.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/librustc_mir/util/pretty.rs b/src/librustc_mir/util/pretty.rs index 1357f8fe79a0d..8177de50776d6 100644 --- a/src/librustc_mir/util/pretty.rs +++ b/src/librustc_mir/util/pretty.rs @@ -197,7 +197,7 @@ fn dump_path( .chars() .filter_map(|c| match c { ' ' => None, - ':' => Some('_'), + ':' | '<' | '>' => Some('_'), c => Some(c) })); s @@ -603,7 +603,8 @@ fn write_mir_sig( match (descr, src.promoted) { (_, Some(i)) => write!(w, "{:?} in ", i)?, (Some(Def::StructCtor(..)), _) => write!(w, "struct ")?, - (Some(Def::Const(_)), _) => write!(w, "const ")?, + (Some(Def::Const(_)), _) + | (Some(Def::AssociatedConst(_)), _) => write!(w, "const ")?, (Some(Def::Static(_, /*is_mutbl*/false)), _) => write!(w, "static ")?, (Some(Def::Static(_, /*is_mutbl*/true)), _) => write!(w, "static mut ")?, (_, _) if is_function => write!(w, "fn ")?, From d7afd3ebfb490c3c3905812a93cbc08b6d45d26b Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sun, 10 Feb 2019 17:24:18 +0000 Subject: [PATCH 12/27] Add test for MIR printing changes --- src/test/mir-opt/unusual-item-types.rs | 66 ++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 src/test/mir-opt/unusual-item-types.rs diff --git a/src/test/mir-opt/unusual-item-types.rs b/src/test/mir-opt/unusual-item-types.rs new file mode 100644 index 0000000000000..fe85baa048e39 --- /dev/null +++ b/src/test/mir-opt/unusual-item-types.rs @@ -0,0 +1,66 @@ +// Test that we don't ICE when trying to dump MIR for unusual item types and +// that we don't create filenames containing `<` and `>` + +struct A; + +impl A { + const ASSOCIATED_CONSTANT: i32 = 2; +} + +enum E { + V = 5, +} + +fn main() { + let v = Vec::::new(); +} + +// END RUST SOURCE + +// START rustc.{{impl}}-ASSOCIATED_CONSTANT.mir_map.0.mir +// bb0: { +// _0 = const 2i32; +// return; +// } +// bb1: { +// resume; +// } +// END rustc.{{impl}}-ASSOCIATED_CONSTANT.mir_map.0.mir + +// START rustc.E-V-{{constant}}.mir_map.0.mir +// bb0: { +// _0 = const 5isize; +// return; +// } +// bb1: { +// resume; +// } +// END rustc.E-V-{{constant}}.mir_map.0.mir + +// START rustc.ptr-real_drop_in_place.std__vec__Vec_i32_.AddMovesForPackedDrops.before.mir +// bb0: { +// goto -> bb7; +// } +// bb1: { +// return; +// } +// bb2: { +// resume; +// } +// bb3: { +// goto -> bb1; +// } +// bb4: { +// goto -> bb2; +// } +// bb5: { +// drop(((*_1).0: alloc::raw_vec::RawVec)) -> bb4; +// } +// bb6: { +// drop(((*_1).0: alloc::raw_vec::RawVec)) -> [return: bb3, unwind: bb4]; +// } +// bb7: { +// _2 = &mut (*_1); +// _3 = const std::ops::Drop::drop(move _2) -> [return: bb6, unwind: bb5]; +// } +// END rustc.ptr-real_drop_in_place.std__vec__Vec_i32_.AddMovesForPackedDrops.before.mir From 3737d4d87db3961427f2548b19cb85f67602d741 Mon Sep 17 00:00:00 2001 From: varkor Date: Tue, 5 Feb 2019 22:50:44 +0100 Subject: [PATCH 13/27] Do not apply future deprecation warning for #[deprecated] --- src/librustc/middle/stability.rs | 28 +---- .../ui/deprecation/deprecation-in-future.rs | 4 +- .../deprecation/deprecation-in-future.stderr | 14 +-- src/test/ui/deprecation/deprecation-lint.rs | 5 +- .../ui/deprecation/deprecation-lint.stderr | 100 ++++++++++-------- 5 files changed, 67 insertions(+), 84 deletions(-) diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs index 34c77d08f5a7e..06bc7afc2fc2f 100644 --- a/src/librustc/middle/stability.rs +++ b/src/librustc/middle/stability.rs @@ -598,37 +598,11 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { // Deprecated attributes apply in-crate and cross-crate. if let Some(id) = id { if let Some(depr_entry) = self.lookup_deprecation_entry(def_id) { - // If the deprecation is scheduled for a future Rust - // version, then we should display no warning message. - let deprecated_in_future_version = if let Some(sym) = depr_entry.attr.since { - let since = sym.as_str(); - if !deprecation_in_effect(&since) { - Some(since) - } else { - None - } - } else { - None - }; - let parent_def_id = self.hir().local_def_id(self.hir().get_parent(id)); let skip = self.lookup_deprecation_entry(parent_def_id) .map_or(false, |parent_depr| parent_depr.same_origin(&depr_entry)); - if let Some(since) = deprecated_in_future_version { - let path = self.item_path_str(def_id); - let message = format!("use of item '{}' \ - that will be deprecated in future version {}", - path, - since); - - lint_deprecated(def_id, - id, - depr_entry.attr.note, - None, - &message, - lint::builtin::DEPRECATED_IN_FUTURE); - } else if !skip { + if !skip { let path = self.item_path_str(def_id); let message = format!("use of deprecated item '{}'", path); lint_deprecated(def_id, diff --git a/src/test/ui/deprecation/deprecation-in-future.rs b/src/test/ui/deprecation/deprecation-in-future.rs index c6c60177e9d0e..138d902621cbc 100644 --- a/src/test/ui/deprecation/deprecation-in-future.rs +++ b/src/test/ui/deprecation/deprecation-in-future.rs @@ -1,12 +1,14 @@ // ignore-tidy-linelength +// run-pass + #![deny(deprecated_in_future)] #[deprecated(since = "99.99.99", note = "text")] pub fn deprecated_future() {} fn test() { - deprecated_future(); //~ ERROR use of item 'deprecated_future' that will be deprecated in future version 99.99.99: text + deprecated_future(); // ok; deprecated_in_future only applies to rustc_deprecated } fn main() {} diff --git a/src/test/ui/deprecation/deprecation-in-future.stderr b/src/test/ui/deprecation/deprecation-in-future.stderr index 38392cf96084c..81d2461c1bd83 100644 --- a/src/test/ui/deprecation/deprecation-in-future.stderr +++ b/src/test/ui/deprecation/deprecation-in-future.stderr @@ -1,14 +1,8 @@ -error: use of item 'deprecated_future' that will be deprecated in future version 99.99.99: text - --> $DIR/deprecation-in-future.rs:9:5 +warning: use of deprecated item 'deprecated_future': text + --> $DIR/deprecation-in-future.rs:11:5 | -LL | deprecated_future(); //~ ERROR use of item 'deprecated_future' that will be deprecated in future version 99.99.99: text +LL | deprecated_future(); // ok; deprecated_in_future only applies to rustc_deprecated | ^^^^^^^^^^^^^^^^^ | -note: lint level defined here - --> $DIR/deprecation-in-future.rs:3:9 - | -LL | #![deny(deprecated_in_future)] - | ^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to previous error + = note: #[warn(deprecated)] on by default diff --git a/src/test/ui/deprecation/deprecation-lint.rs b/src/test/ui/deprecation/deprecation-lint.rs index 6b3e9a8ad8116..033d6eebbb219 100644 --- a/src/test/ui/deprecation/deprecation-lint.rs +++ b/src/test/ui/deprecation/deprecation-lint.rs @@ -261,8 +261,9 @@ mod this_crate { ::trait_deprecated_text(&foo); //~ ERROR use of deprecated item 'this_crate::Trait::trait_deprecated_text': text ::trait_deprecated_text(&foo); //~ ERROR use of deprecated item 'this_crate::Trait::trait_deprecated_text': text - deprecated_future(); // Fine; no error. - deprecated_future_text(); // Fine; no error. + // Future deprecations are only permitted for rustc_deprecated. + deprecated_future(); //~ ERROR use of deprecated item + deprecated_future_text(); //~ ERROR use of deprecated item let _ = DeprecatedStruct { //~^ ERROR use of deprecated item 'this_crate::DeprecatedStruct': text diff --git a/src/test/ui/deprecation/deprecation-lint.stderr b/src/test/ui/deprecation/deprecation-lint.stderr index 46875d0bf13ba..c48d06e86154d 100644 --- a/src/test/ui/deprecation/deprecation-lint.stderr +++ b/src/test/ui/deprecation/deprecation-lint.stderr @@ -214,128 +214,140 @@ error: use of deprecated item 'this_crate::Trait::trait_deprecated_text': text LL | ::trait_deprecated_text(&foo); //~ ERROR use of deprecated item 'this_crate::Trait::trait_deprecated_text': text | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +error: use of deprecated item 'this_crate::deprecated_future': text + --> $DIR/deprecation-lint.rs:265:9 + | +LL | deprecated_future(); //~ ERROR use of deprecated item + | ^^^^^^^^^^^^^^^^^ + +error: use of deprecated item 'this_crate::deprecated_future_text': text + --> $DIR/deprecation-lint.rs:266:9 + | +LL | deprecated_future_text(); //~ ERROR use of deprecated item + | ^^^^^^^^^^^^^^^^^^^^^^ + error: use of deprecated item 'this_crate::DeprecatedStruct': text - --> $DIR/deprecation-lint.rs:267:17 + --> $DIR/deprecation-lint.rs:268:17 | LL | let _ = DeprecatedStruct { | ^^^^^^^^^^^^^^^^ error: use of deprecated item 'this_crate::DeprecatedUnitStruct': text - --> $DIR/deprecation-lint.rs:272:17 + --> $DIR/deprecation-lint.rs:273:17 | LL | let _ = DeprecatedUnitStruct; //~ ERROR use of deprecated item 'this_crate::DeprecatedUnitStruct': text | ^^^^^^^^^^^^^^^^^^^^ error: use of deprecated item 'this_crate::Enum::DeprecatedVariant': text - --> $DIR/deprecation-lint.rs:274:17 + --> $DIR/deprecation-lint.rs:275:17 | LL | let _ = Enum::DeprecatedVariant; //~ ERROR use of deprecated item 'this_crate::Enum::DeprecatedVariant': text | ^^^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated item 'this_crate::DeprecatedTupleStruct': text - --> $DIR/deprecation-lint.rs:276:17 + --> $DIR/deprecation-lint.rs:277:17 | LL | let _ = DeprecatedTupleStruct (1); //~ ERROR use of deprecated item 'this_crate::DeprecatedTupleStruct': text | ^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated item 'this_crate::nested::DeprecatedStruct': text - --> $DIR/deprecation-lint.rs:278:17 + --> $DIR/deprecation-lint.rs:279:17 | LL | let _ = nested::DeprecatedStruct { | ^^^^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated item 'this_crate::nested::DeprecatedUnitStruct': text - --> $DIR/deprecation-lint.rs:283:17 + --> $DIR/deprecation-lint.rs:284:17 | LL | let _ = nested::DeprecatedUnitStruct; //~ ERROR use of deprecated item 'this_crate::nested::DeprecatedUnitStruct': text | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated item 'this_crate::nested::Enum::DeprecatedVariant': text - --> $DIR/deprecation-lint.rs:285:17 + --> $DIR/deprecation-lint.rs:286:17 | LL | let _ = nested::Enum::DeprecatedVariant; //~ ERROR use of deprecated item 'this_crate::nested::Enum::DeprecatedVariant': text | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated item 'this_crate::nested::DeprecatedTupleStruct': text - --> $DIR/deprecation-lint.rs:287:17 + --> $DIR/deprecation-lint.rs:288:17 | LL | let _ = nested::DeprecatedTupleStruct (1); //~ ERROR use of deprecated item 'this_crate::nested::DeprecatedTupleStruct': text | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated item 'this_crate::Trait::trait_deprecated': text - --> $DIR/deprecation-lint.rs:292:9 + --> $DIR/deprecation-lint.rs:293:9 | LL | Trait::trait_deprecated(&foo); //~ ERROR use of deprecated item 'this_crate::Trait::trait_deprecated' | ^^^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated item 'this_crate::Trait::trait_deprecated': text - --> $DIR/deprecation-lint.rs:294:9 + --> $DIR/deprecation-lint.rs:295:9 | LL | ::trait_deprecated(&foo); //~ ERROR use of deprecated item 'this_crate::Trait::trait_deprecated' | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated item 'this_crate::Trait::trait_deprecated_text': text - --> $DIR/deprecation-lint.rs:296:9 + --> $DIR/deprecation-lint.rs:297:9 | LL | Trait::trait_deprecated_text(&foo); //~ ERROR use of deprecated item 'this_crate::Trait::trait_deprecated_text': text | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated item 'this_crate::Trait::trait_deprecated_text': text - --> $DIR/deprecation-lint.rs:298:9 + --> $DIR/deprecation-lint.rs:299:9 | LL | ::trait_deprecated_text(&foo); //~ ERROR use of deprecated item 'this_crate::Trait::trait_deprecated_text': text | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated item 'this_crate::test_fn_closure_body::{{closure}}::bar' - --> $DIR/deprecation-lint.rs:316:13 + --> $DIR/deprecation-lint.rs:317:13 | LL | bar(); //~ ERROR use of deprecated item 'this_crate::test_fn_closure_body::{{closure}}::bar' | ^^^ error: use of deprecated item 'this_crate::DeprecatedTrait': text - --> $DIR/deprecation-lint.rs:335:10 + --> $DIR/deprecation-lint.rs:336:10 | LL | impl DeprecatedTrait for S { } //~ ERROR use of deprecated item 'this_crate::DeprecatedTrait': text | ^^^^^^^^^^^^^^^ error: use of deprecated item 'this_crate::DeprecatedTrait': text - --> $DIR/deprecation-lint.rs:337:24 + --> $DIR/deprecation-lint.rs:338:24 | LL | trait LocalTrait : DeprecatedTrait { } //~ ERROR use of deprecated item 'this_crate::DeprecatedTrait': text | ^^^^^^^^^^^^^^^ error: use of deprecated item 'this_crate2::Deprecated': text - --> $DIR/deprecation-lint.rs:389:17 + --> $DIR/deprecation-lint.rs:390:17 | LL | let x = Deprecated { | ^^^^^^^^^^ error: use of deprecated item 'this_crate2::Deprecated': text - --> $DIR/deprecation-lint.rs:398:13 + --> $DIR/deprecation-lint.rs:399:13 | LL | let Deprecated { | ^^^^^^^^^^ error: use of deprecated item 'this_crate2::Deprecated': text - --> $DIR/deprecation-lint.rs:404:13 + --> $DIR/deprecation-lint.rs:405:13 | LL | let Deprecated | ^^^^^^^^^^ error: use of deprecated item 'this_crate2::Deprecated2': text - --> $DIR/deprecation-lint.rs:409:17 + --> $DIR/deprecation-lint.rs:410:17 | LL | let x = Deprecated2(1, 2, 3); | ^^^^^^^^^^^ error: use of deprecated item 'this_crate2::Deprecated2': text - --> $DIR/deprecation-lint.rs:419:13 + --> $DIR/deprecation-lint.rs:420:13 | LL | let Deprecated2 | ^^^^^^^^^^^ error: use of deprecated item 'this_crate2::Deprecated2': text - --> $DIR/deprecation-lint.rs:428:13 + --> $DIR/deprecation-lint.rs:429:13 | LL | let Deprecated2 | ^^^^^^^^^^^ @@ -593,136 +605,136 @@ LL | ::trait_deprecated_text(&foo); //~ ERROR use of deprecated ite | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated item 'this_crate::DeprecatedStruct::i': text - --> $DIR/deprecation-lint.rs:269:13 + --> $DIR/deprecation-lint.rs:270:13 | LL | i: 0 //~ ERROR use of deprecated item 'this_crate::DeprecatedStruct::i': text | ^^^^ error: use of deprecated item 'this_crate::nested::DeprecatedStruct::i': text - --> $DIR/deprecation-lint.rs:280:13 + --> $DIR/deprecation-lint.rs:281:13 | LL | i: 0 //~ ERROR use of deprecated item 'this_crate::nested::DeprecatedStruct::i': text | ^^^^ error: use of deprecated item 'this_crate::Trait::trait_deprecated': text - --> $DIR/deprecation-lint.rs:291:13 + --> $DIR/deprecation-lint.rs:292:13 | LL | foo.trait_deprecated(); //~ ERROR use of deprecated item 'this_crate::Trait::trait_deprecated' | ^^^^^^^^^^^^^^^^ error: use of deprecated item 'this_crate::Trait::trait_deprecated': text - --> $DIR/deprecation-lint.rs:293:9 + --> $DIR/deprecation-lint.rs:294:9 | LL | ::trait_deprecated(&foo); //~ ERROR use of deprecated item 'this_crate::Trait::trait_deprecated' | ^^^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated item 'this_crate::Trait::trait_deprecated_text': text - --> $DIR/deprecation-lint.rs:295:13 + --> $DIR/deprecation-lint.rs:296:13 | LL | foo.trait_deprecated_text(); //~ ERROR use of deprecated item 'this_crate::Trait::trait_deprecated_text': text | ^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated item 'this_crate::Trait::trait_deprecated_text': text - --> $DIR/deprecation-lint.rs:297:9 + --> $DIR/deprecation-lint.rs:298:9 | LL | ::trait_deprecated_text(&foo); //~ ERROR use of deprecated item 'this_crate::Trait::trait_deprecated_text': text | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated item 'this_crate::Trait::trait_deprecated': text - --> $DIR/deprecation-lint.rs:302:13 + --> $DIR/deprecation-lint.rs:303:13 | LL | foo.trait_deprecated(); //~ ERROR use of deprecated item 'this_crate::Trait::trait_deprecated' | ^^^^^^^^^^^^^^^^ error: use of deprecated item 'this_crate::Trait::trait_deprecated_text': text - --> $DIR/deprecation-lint.rs:303:13 + --> $DIR/deprecation-lint.rs:304:13 | LL | foo.trait_deprecated_text(); //~ ERROR use of deprecated item 'this_crate::Trait::trait_deprecated_text': text | ^^^^^^^^^^^^^^^^^^^^^ error: use of deprecated item 'this_crate2::Stable::override2': text - --> $DIR/deprecation-lint.rs:362:13 + --> $DIR/deprecation-lint.rs:363:13 | LL | override2: 3, | ^^^^^^^^^^^^ error: use of deprecated item 'this_crate2::Stable::override2': text - --> $DIR/deprecation-lint.rs:366:17 + --> $DIR/deprecation-lint.rs:367:17 | LL | let _ = x.override2; | ^^^^^^^^^^^ error: use of deprecated item 'this_crate2::Stable::override2': text - --> $DIR/deprecation-lint.rs:370:13 + --> $DIR/deprecation-lint.rs:371:13 | LL | override2: _ | ^^^^^^^^^^^^ error: use of deprecated item 'this_crate2::Stable2::2': text - --> $DIR/deprecation-lint.rs:378:17 + --> $DIR/deprecation-lint.rs:379:17 | LL | let _ = x.2; | ^^^ error: use of deprecated item 'this_crate2::Stable2::2': text - --> $DIR/deprecation-lint.rs:383:20 + --> $DIR/deprecation-lint.rs:384:20 | LL | _) | ^ error: use of deprecated item 'this_crate2::Deprecated::inherit': text - --> $DIR/deprecation-lint.rs:391:13 + --> $DIR/deprecation-lint.rs:392:13 | LL | inherit: 1, | ^^^^^^^^^^ error: use of deprecated item 'this_crate2::Deprecated::inherit': text - --> $DIR/deprecation-lint.rs:395:17 + --> $DIR/deprecation-lint.rs:396:17 | LL | let _ = x.inherit; | ^^^^^^^^^ error: use of deprecated item 'this_crate2::Deprecated::inherit': text - --> $DIR/deprecation-lint.rs:400:13 + --> $DIR/deprecation-lint.rs:401:13 | LL | inherit: _, | ^^^^^^^^^^ error: use of deprecated item 'this_crate2::Deprecated2::0': text - --> $DIR/deprecation-lint.rs:412:17 + --> $DIR/deprecation-lint.rs:413:17 | LL | let _ = x.0; | ^^^ error: use of deprecated item 'this_crate2::Deprecated2::1': text - --> $DIR/deprecation-lint.rs:414:17 + --> $DIR/deprecation-lint.rs:415:17 | LL | let _ = x.1; | ^^^ error: use of deprecated item 'this_crate2::Deprecated2::2': text - --> $DIR/deprecation-lint.rs:416:17 + --> $DIR/deprecation-lint.rs:417:17 | LL | let _ = x.2; | ^^^ error: use of deprecated item 'this_crate2::Deprecated2::0': text - --> $DIR/deprecation-lint.rs:421:14 + --> $DIR/deprecation-lint.rs:422:14 | LL | (_, | ^ error: use of deprecated item 'this_crate2::Deprecated2::1': text - --> $DIR/deprecation-lint.rs:423:14 + --> $DIR/deprecation-lint.rs:424:14 | LL | _, | ^ error: use of deprecated item 'this_crate2::Deprecated2::2': text - --> $DIR/deprecation-lint.rs:425:14 + --> $DIR/deprecation-lint.rs:426:14 | LL | _) | ^ -error: aborting due to 120 previous errors +error: aborting due to 122 previous errors From 87cd09b94c00a07f2bd19366c71ac0c12579ee0e Mon Sep 17 00:00:00 2001 From: varkor Date: Tue, 5 Feb 2019 22:51:06 +0100 Subject: [PATCH 14/27] Don't display "Deprecated since" for non-rustc deprecated items --- src/librustdoc/html/render.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index a85ac19286af5..3de74491a330b 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -2845,8 +2845,10 @@ 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(Deprecation { since, note }) = &item.deprecation() { - let mut message = if let Some(since) = since { + if let Some(Deprecation { note, .. }) = &item.deprecation() { + // We display deprecation messages for #[deprecated] and #[rustc_deprecated] + // but only display the future-deprecation messages for #[rustc_deprecated]. + let mut message = if let Some(since) = item.stability.deprecation.since { if stability::deprecation_in_effect(since) { format!("Deprecated since {}", Escape(since)) } else { From 2a8a25be37f87dd21dfeeb3dd092d6530dbb5396 Mon Sep 17 00:00:00 2001 From: varkor Date: Tue, 5 Feb 2019 22:51:23 +0100 Subject: [PATCH 15/27] Display "Deprecation planned" in rustdoc for future rustc deprecations --- src/librustdoc/html/render.rs | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 3de74491a330b..00ee24e59c223 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -2817,7 +2817,17 @@ fn stability_tags(item: &clean::Item) -> String { // The trailing space after each tag is to space it properly against the rest of the docs. if item.deprecation().is_some() { - tags += &tag_html("deprecated", "Deprecated"); + let mut message = "Deprecated"; + if let Some(ref stab) = item.stability { + if let Some(ref depr) = stab.deprecation { + if let Some(ref since) = depr.since { + if !stability::deprecation_in_effect(&since) { + message = "Deprecation planned"; + } + } + } + } + tags += &tag_html("deprecated", message); } if let Some(stab) = item @@ -2848,15 +2858,18 @@ fn short_stability(item: &clean::Item, cx: &Context) -> Vec { if let Some(Deprecation { note, .. }) = &item.deprecation() { // We display deprecation messages for #[deprecated] and #[rustc_deprecated] // but only display the future-deprecation messages for #[rustc_deprecated]. - let mut message = if let Some(since) = item.stability.deprecation.since { - if stability::deprecation_in_effect(since) { - format!("Deprecated since {}", Escape(since)) - } else { - format!("Deprecating in {}", Escape(since)) + let mut message = String::from("Deprecated"); + if let Some(ref stab) = item.stability { + if let Some(ref depr) = stab.deprecation { + if let Some(ref since) = depr.since { + if stability::deprecation_in_effect(&since) { + message = format!("Deprecated since {}", Escape(&since)); + } else { + message = format!("Deprecating in {}", Escape(&since)); + } + } } - } else { - String::from("Deprecated") - }; + } if let Some(note) = note { let mut ids = cx.id_map.borrow_mut(); From 3dc660f1f58762ad2eff39d09f229dc36a40ca0c Mon Sep 17 00:00:00 2001 From: varkor Date: Wed, 6 Feb 2019 13:01:28 +0100 Subject: [PATCH 16/27] Update existing rustdoc test --- src/librustdoc/html/render.rs | 12 +++++++----- src/test/rustdoc/deprecated-future.rs | 2 +- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 00ee24e59c223..b98f4118614f4 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -2855,16 +2855,18 @@ 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(Deprecation { note, .. }) = &item.deprecation() { + if let Some(Deprecation { note, since }) = &item.deprecation() { // We display deprecation messages for #[deprecated] and #[rustc_deprecated] // but only display the future-deprecation messages for #[rustc_deprecated]. - let mut message = String::from("Deprecated"); + let mut message = if let Some(since) = since { + format!("Deprecated since {}", Escape(since)) + } else { + String::from("Deprecated") + }; if let Some(ref stab) = item.stability { if let Some(ref depr) = stab.deprecation { if let Some(ref since) = depr.since { - if stability::deprecation_in_effect(&since) { - message = format!("Deprecated since {}", Escape(&since)); - } else { + if !stability::deprecation_in_effect(&since) { message = format!("Deprecating in {}", Escape(&since)); } } diff --git a/src/test/rustdoc/deprecated-future.rs b/src/test/rustdoc/deprecated-future.rs index 383afe86cb405..015aade4c880f 100644 --- a/src/test/rustdoc/deprecated-future.rs +++ b/src/test/rustdoc/deprecated-future.rs @@ -1,6 +1,6 @@ #![feature(deprecated)] // @has deprecated_future/struct.S.html '//*[@class="stab deprecated"]' \ -// 'Deprecating in 99.99.99: effectively never' +// 'Deprecated since 99.99.99: effectively never' #[deprecated(since = "99.99.99", note = "effectively never")] pub struct S; From 01df8fe8ff4d57336ec84ac475988cc7403308a8 Mon Sep 17 00:00:00 2001 From: varkor Date: Wed, 6 Feb 2019 14:17:05 +0100 Subject: [PATCH 17/27] Add a rustdoc test for future rustc_deprecated attributes --- src/test/rustdoc/rustc_deprecated-future.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 src/test/rustdoc/rustc_deprecated-future.rs diff --git a/src/test/rustdoc/rustc_deprecated-future.rs b/src/test/rustdoc/rustc_deprecated-future.rs new file mode 100644 index 0000000000000..3133775706b8d --- /dev/null +++ b/src/test/rustdoc/rustc_deprecated-future.rs @@ -0,0 +1,11 @@ +#![feature(staged_api)] + +#![stable(feature = "rustc_deprecated-future-test", since = "1.0.0")] + +// @has rustc_deprecated_future/index.html '//*[@class="stab deprecated"]' \ +// 'Deprecation planned' +// @has rustc_deprecated_future/struct.S.html '//*[@class="stab deprecated"]' \ +// 'Deprecating in 99.99.99: effectively never' +#[rustc_deprecated(since = "99.99.99", reason = "effectively never")] +#[stable(feature = "rustc_deprecated-future-test", since = "1.0.0")] +pub struct S; From c8752415dc0775960accc5f6ae11be782910b3c6 Mon Sep 17 00:00:00 2001 From: varkor Date: Wed, 6 Feb 2019 14:17:27 +0100 Subject: [PATCH 18/27] Add rustdoc index page test for future deprecation attributes --- src/test/rustdoc/deprecated-future.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/test/rustdoc/deprecated-future.rs b/src/test/rustdoc/deprecated-future.rs index 015aade4c880f..c5248c52fb973 100644 --- a/src/test/rustdoc/deprecated-future.rs +++ b/src/test/rustdoc/deprecated-future.rs @@ -1,5 +1,7 @@ #![feature(deprecated)] +// @has deprecated_future/index.html '//*[@class="stab deprecated"]' \ +// 'Deprecated' // @has deprecated_future/struct.S.html '//*[@class="stab deprecated"]' \ // 'Deprecated since 99.99.99: effectively never' #[deprecated(since = "99.99.99", note = "effectively never")] From b5fa87076047207622a5fd6d3902e3ca58d0a9d6 Mon Sep 17 00:00:00 2001 From: varkor Date: Mon, 11 Feb 2019 12:16:50 +0100 Subject: [PATCH 19/27] Add a test for rustc_deprecated --- .../ui/deprecation/rustc_deprecation-in-future.rs | 15 +++++++++++++++ .../rustc_deprecation-in-future.stderr | 14 ++++++++++++++ 2 files changed, 29 insertions(+) create mode 100644 src/test/ui/deprecation/rustc_deprecation-in-future.rs create mode 100644 src/test/ui/deprecation/rustc_deprecation-in-future.stderr diff --git a/src/test/ui/deprecation/rustc_deprecation-in-future.rs b/src/test/ui/deprecation/rustc_deprecation-in-future.rs new file mode 100644 index 0000000000000..a19363c512950 --- /dev/null +++ b/src/test/ui/deprecation/rustc_deprecation-in-future.rs @@ -0,0 +1,15 @@ +// ignore-tidy-linelength + +#![deny(deprecated_in_future)] + +#![feature(staged_api)] + +#![stable(feature = "rustc_deprecation-in-future-test", since = "1.0.0")] + +#[rustc_deprecated(since = "99.99.99", reason = "effectively never")] +#[stable(feature = "rustc_deprecation-in-future-test", since = "1.0.0")] +pub struct S; + +fn main() { + let _ = S; //~ ERROR use of item 'S' that will be deprecated in future version 99.99.99: effectively never +} diff --git a/src/test/ui/deprecation/rustc_deprecation-in-future.stderr b/src/test/ui/deprecation/rustc_deprecation-in-future.stderr new file mode 100644 index 0000000000000..bd8ade16ec0e8 --- /dev/null +++ b/src/test/ui/deprecation/rustc_deprecation-in-future.stderr @@ -0,0 +1,14 @@ +error: use of item 'S' that will be deprecated in future version 99.99.99: effectively never + --> $DIR/rustc_deprecation-in-future.rs:14:13 + | +LL | let _ = S; //~ ERROR use of item 'S' that will be deprecated in future version 99.99.99: effectively never + | ^ + | +note: lint level defined here + --> $DIR/rustc_deprecation-in-future.rs:3:9 + | +LL | #![deny(deprecated_in_future)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + From 48b0c9da69965cd40d037cee42cf3093ed09c6ee Mon Sep 17 00:00:00 2001 From: David Wood Date: Mon, 11 Feb 2019 19:29:10 +0100 Subject: [PATCH 20/27] Only suggest imports if not imported. This commit modifies name resolution error reporting so that if a name is in scope and has been imported then we do not suggest importing it. This can occur when we add a label about constructors not being visible due to private fields. In these cases, we know that the struct/variant has been imported and we should silence any suggestions to import the struct/variant. --- src/librustc_resolve/error_reporting.rs | 10 +++++++++- src/librustc_resolve/lib.rs | 16 +++++++++++---- src/test/ui/issue-42944.rs | 19 ++++++++++++++++++ src/test/ui/issue-42944.stderr | 20 +++++++++++++++++++ .../ui/resolve/privacy-struct-ctor.stderr | 15 +++----------- 5 files changed, 63 insertions(+), 17 deletions(-) create mode 100644 src/test/ui/issue-42944.rs create mode 100644 src/test/ui/issue-42944.stderr diff --git a/src/librustc_resolve/error_reporting.rs b/src/librustc_resolve/error_reporting.rs index 8300e691bbea4..a6e27c0a1aee7 100644 --- a/src/librustc_resolve/error_reporting.rs +++ b/src/librustc_resolve/error_reporting.rs @@ -106,7 +106,15 @@ impl<'a> Resolver<'a> { // Try to lookup name in more relaxed fashion for better error reporting. let ident = path.last().unwrap().ident; - let candidates = self.lookup_import_candidates(ident, ns, is_expected); + let candidates = self.lookup_import_candidates(ident, ns, is_expected) + .drain(..) + .filter(|ImportSuggestion { did, .. }| { + match (did, def.and_then(|def| def.opt_def_id())) { + (Some(suggestion_did), Some(actual_did)) => *suggestion_did != actual_did, + _ => true, + } + }) + .collect::>(); if candidates.is_empty() && is_expected(Def::Enum(DefId::local(CRATE_DEF_INDEX))) { let enum_candidates = self.lookup_import_candidates(ident, ns, is_enum_variant); diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index ecbfcec3c5eb4..428d0bd4c2bf5 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -25,7 +25,7 @@ use rustc::hir::def::*; use rustc::hir::def::Namespace::*; use rustc::hir::def_id::{CRATE_DEF_INDEX, LOCAL_CRATE, DefId}; use rustc::hir::{Freevar, FreevarMap, TraitCandidate, TraitMap, GlobMap}; -use rustc::ty; +use rustc::ty::{self, DefIdTree}; use rustc::util::nodemap::{NodeMap, NodeSet, FxHashMap, FxHashSet, DefIdMap}; use rustc::{bug, span_bug}; @@ -93,6 +93,7 @@ enum ScopeSet { /// A free importable items suggested in case of resolution failure. struct ImportSuggestion { + did: Option, path: Path, } @@ -4392,7 +4393,8 @@ impl<'a> Resolver<'a> { // collect results based on the filter function if ident.name == lookup_ident.name && ns == namespace { - if filter_fn(name_binding.def()) { + let def = name_binding.def(); + if filter_fn(def) { // create the path let mut segms = path_segments.clone(); if lookup_ident.span.rust_2018() { @@ -4416,7 +4418,12 @@ impl<'a> Resolver<'a> { // declared as public (due to pruning, we don't explore // outside crate private modules => no need to check this) if !in_module_is_extern || name_binding.vis == ty::Visibility::Public { - candidates.push(ImportSuggestion { path }); + let did = match def { + Def::StructCtor(did, _) | Def::VariantCtor(did, _) => + self.parent(did), + _ => def.opt_def_id(), + }; + candidates.push(ImportSuggestion { did, path }); } } } @@ -4513,7 +4520,8 @@ impl<'a> Resolver<'a> { span: name_binding.span, segments: path_segments, }; - result = Some((module, ImportSuggestion { path })); + let did = module.def().and_then(|def| def.opt_def_id()); + result = Some((module, ImportSuggestion { did, path })); } else { // add the module to the lookup if seen_modules.insert(module.def_id().unwrap()) { diff --git a/src/test/ui/issue-42944.rs b/src/test/ui/issue-42944.rs new file mode 100644 index 0000000000000..9d746673f4dae --- /dev/null +++ b/src/test/ui/issue-42944.rs @@ -0,0 +1,19 @@ +mod foo { + pub struct B(()); +} + +mod bar { + use foo::B; + + fn foo() { + B(()); //~ ERROR expected function, found struct `B` [E0423] + } +} + +mod baz { + fn foo() { + B(()); //~ ERROR cannot find function `B` in this scope [E0425] + } +} + +fn main() {} diff --git a/src/test/ui/issue-42944.stderr b/src/test/ui/issue-42944.stderr new file mode 100644 index 0000000000000..43fd0ffb72439 --- /dev/null +++ b/src/test/ui/issue-42944.stderr @@ -0,0 +1,20 @@ +error[E0423]: expected function, found struct `B` + --> $DIR/issue-42944.rs:9:9 + | +LL | B(()); //~ ERROR expected function, found struct `B` [E0423] + | ^ constructor is not visible here due to private fields + +error[E0425]: cannot find function `B` in this scope + --> $DIR/issue-42944.rs:15:9 + | +LL | B(()); //~ ERROR cannot find function `B` in this scope [E0425] + | ^ not found in this scope +help: possible candidate is found in another module, you can import it into scope + | +LL | use foo::B; + | + +error: aborting due to 2 previous errors + +Some errors occurred: E0423, E0425. +For more information about an error, try `rustc --explain E0423`. diff --git a/src/test/ui/resolve/privacy-struct-ctor.stderr b/src/test/ui/resolve/privacy-struct-ctor.stderr index 44ecf6b97bf50..519e74d9f6315 100644 --- a/src/test/ui/resolve/privacy-struct-ctor.stderr +++ b/src/test/ui/resolve/privacy-struct-ctor.stderr @@ -2,25 +2,16 @@ error[E0423]: expected value, found struct `Z` --> $DIR/privacy-struct-ctor.rs:20:9 | LL | Z; - | ^ constructor is not visible here due to private fields -help: a tuple struct with a similar name exists - | -LL | S; | ^ -help: possible better candidate is found in another module, you can import it into scope - | -LL | use m::n::Z; - | + | | + | constructor is not visible here due to private fields + | help: a tuple struct with a similar name exists: `S` error[E0423]: expected value, found struct `S` --> $DIR/privacy-struct-ctor.rs:33:5 | LL | S; | ^ constructor is not visible here due to private fields -help: possible better candidate is found in another module, you can import it into scope - | -LL | use m::S; - | error[E0423]: expected value, found struct `S2` --> $DIR/privacy-struct-ctor.rs:38:5 From ddb6c4f8999f12edc2853e02082987234c11fbc5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Tue, 12 Feb 2019 02:10:02 +0100 Subject: [PATCH 21/27] Set the query in the ImplicitCtxt before trying to mark it green --- src/librustc/ty/query/plumbing.rs | 114 ++++++++++++++-------------- src/test/incremental/issue-54242.rs | 17 +++++ 2 files changed, 73 insertions(+), 58 deletions(-) create mode 100644 src/test/incremental/issue-54242.rs diff --git a/src/librustc/ty/query/plumbing.rs b/src/librustc/ty/query/plumbing.rs index f63fbd79825db..bfb7211f2ae04 100644 --- a/src/librustc/ty/query/plumbing.rs +++ b/src/librustc/ty/query/plumbing.rs @@ -188,40 +188,6 @@ impl<'a, 'tcx, Q: QueryDescription<'tcx>> JobOwner<'a, 'tcx, Q> { job.signal_complete(); } - - /// Executes a job by changing the ImplicitCtxt to point to the - /// new query job while it executes. It returns the diagnostics - /// captured during execution and the actual result. - #[inline(always)] - pub(super) fn start<'lcx, F, R>( - &self, - tcx: TyCtxt<'_, 'tcx, 'lcx>, - diagnostics: Option<&Lock>>, - compute: F) - -> R - where - F: for<'b> FnOnce(TyCtxt<'b, 'tcx, 'lcx>) -> R - { - // The TyCtxt stored in TLS has the same global interner lifetime - // as `tcx`, so we use `with_related_context` to relate the 'gcx lifetimes - // when accessing the ImplicitCtxt - tls::with_related_context(tcx, move |current_icx| { - // Update the ImplicitCtxt to point to our new query job - let new_icx = tls::ImplicitCtxt { - tcx: tcx.global_tcx(), - query: Some(self.job.clone()), - diagnostics, - layout_depth: current_icx.layout_depth, - task_deps: current_icx.task_deps, - }; - - // Use the ImplicitCtxt while we execute the query - tls::enter_context(&new_icx, |_| { - compute(tcx) - }) - }) - } - } #[inline(always)] @@ -265,6 +231,39 @@ pub(super) enum TryGetJob<'a, 'tcx: 'a, D: QueryDescription<'tcx> + 'a> { } impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { + /// Executes a job by changing the ImplicitCtxt to point to the + /// new query job while it executes. It returns the diagnostics + /// captured during execution and the actual result. + #[inline(always)] + pub(super) fn start_query( + self, + job: Lrc>, + diagnostics: Option<&Lock>>, + compute: F) + -> R + where + F: for<'b, 'lcx> FnOnce(TyCtxt<'b, 'gcx, 'lcx>) -> R + { + // The TyCtxt stored in TLS has the same global interner lifetime + // as `self`, so we use `with_related_context` to relate the 'gcx lifetimes + // when accessing the ImplicitCtxt + tls::with_related_context(self, move |current_icx| { + // Update the ImplicitCtxt to point to our new query job + let new_icx = tls::ImplicitCtxt { + tcx: self.global_tcx(), + query: Some(job), + diagnostics, + layout_depth: current_icx.layout_depth, + task_deps: current_icx.task_deps, + }; + + // Use the ImplicitCtxt while we execute the query + tls::enter_context(&new_icx, |_| { + compute(self.global_tcx()) + }) + }) + } + #[inline(never)] #[cold] pub(super) fn report_cycle( @@ -378,7 +377,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { self.sess.profiler(|p| p.start_query(Q::NAME, Q::CATEGORY)); let ((result, dep_node_index), diagnostics) = with_diagnostics(|diagnostics| { - job.start(self, diagnostics, |tcx| { + self.start_query(job.job.clone(), diagnostics, |tcx| { tcx.dep_graph.with_anon_task(dep_node.kind, || { Q::compute(tcx.global_tcx(), key) }) @@ -401,16 +400,23 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } if !dep_node.kind.is_input() { - if let Some((prev_dep_node_index, - dep_node_index)) = self.dep_graph.try_mark_green_and_read(self, - &dep_node) { - return Ok(self.load_from_disk_and_cache_in_memory::( - key, - job, - prev_dep_node_index, - dep_node_index, - &dep_node - )) + // The diagnostics for this query will be + // promoted to the current session during + // try_mark_green(), so we can ignore them here. + let loaded = self.start_query(job.job.clone(), None, |tcx| { + let marked = tcx.dep_graph.try_mark_green_and_read(tcx, &dep_node); + marked.map(|(prev_dep_node_index, dep_node_index)| { + (tcx.load_from_disk_and_cache_in_memory::( + key.clone(), + prev_dep_node_index, + dep_node_index, + &dep_node + ), dep_node_index) + }) + }); + if let Some((result, dep_node_index)) = loaded { + job.complete(&result, dep_node_index); + return Ok(result); } } @@ -422,7 +428,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { fn load_from_disk_and_cache_in_memory>( self, key: Q::Key, - job: JobOwner<'a, 'gcx, Q>, prev_dep_node_index: SerializedDepNodeIndex, dep_node_index: DepNodeIndex, dep_node: &DepNode @@ -461,15 +466,10 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { self.sess.profiler(|p| p.start_query(Q::NAME, Q::CATEGORY)); - // The diagnostics for this query have already been - // promoted to the current session during - // try_mark_green(), so we can ignore them here. - let result = job.start(self, None, |tcx| { - // The dep-graph for this computation is already in - // place - tcx.dep_graph.with_ignore(|| { - Q::compute(tcx, key) - }) + // The dep-graph for this computation is already in + // place + let result = self.dep_graph.with_ignore(|| { + Q::compute(self, key) }); self.sess.profiler(|p| p.end_query(Q::NAME, Q::CATEGORY)); @@ -486,8 +486,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { self.dep_graph.mark_loaded_from_cache(dep_node_index, true); } - job.complete(&result, dep_node_index); - result } @@ -540,7 +538,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { self.sess.profiler(|p| p.start_query(Q::NAME, Q::CATEGORY)); let ((result, dep_node_index), diagnostics) = with_diagnostics(|diagnostics| { - job.start(self, diagnostics, |tcx| { + self.start_query(job.job.clone(), diagnostics, |tcx| { if dep_node.kind.is_eval_always() { tcx.dep_graph.with_eval_always_task(dep_node, tcx, diff --git a/src/test/incremental/issue-54242.rs b/src/test/incremental/issue-54242.rs new file mode 100644 index 0000000000000..1c700d44dd80b --- /dev/null +++ b/src/test/incremental/issue-54242.rs @@ -0,0 +1,17 @@ +// revisions: rpass cfail + +trait Tr { + type Arr; + + const C: usize = 0; +} + +impl Tr for str { + #[cfg(rpass)] + type Arr = [u8; 8]; + #[cfg(cfail)] + type Arr = [u8; Self::C]; + //[cfail]~^ ERROR cycle detected when const-evaluating +} + +fn main() {} From 3a8448c3ff811d301c06bae6772b393d0236e363 Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Tue, 12 Feb 2019 11:40:36 +0100 Subject: [PATCH 22/27] Fix rustc_driver swallowing errors when compilation is stopped --- src/librustc_driver/driver.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index 6a23cadf87795..12cea3062885d 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -296,6 +296,11 @@ pub fn compile_input( (control.after_analysis.callback)(&mut state); }); + // Plugins like clippy and rust-semverver stop the analysis early, + // but want to still return an error if errors during the analysis + // happened: + tcx.sess.compile_status()?; + if control.after_analysis.stop == Compilation::Stop { return result.and_then(|_| Err(CompileIncomplete::Stopped)); } From eac43ccda4858e5415822a3a31bffb029cb0ed2b Mon Sep 17 00:00:00 2001 From: ljedrz Date: Mon, 4 Feb 2019 20:01:14 +0100 Subject: [PATCH 23/27] HirId-ify hir::BodyId --- src/librustc/hir/map/mod.rs | 29 +++++++-- src/librustc/hir/mod.rs | 6 +- src/librustc/ich/impls_hir.rs | 4 +- .../infer/error_reporting/need_type_info.rs | 2 +- src/librustc/infer/mod.rs | 5 +- src/librustc/infer/opaque_types/mod.rs | 4 +- src/librustc/infer/outlives/env.rs | 10 +-- src/librustc/infer/outlives/obligations.rs | 8 +-- src/librustc/traits/auto_trait.rs | 6 +- src/librustc/traits/mod.rs | 18 +++--- src/librustc/traits/query/outlives_bounds.rs | 4 +- src/librustc/ty/mod.rs | 16 ++--- src/librustc/ty/wf.rs | 10 +-- src/librustc_borrowck/borrowck/mod.rs | 2 +- src/librustc_mir/transform/qualify_consts.rs | 4 +- src/librustc_passes/rvalue_promotion.rs | 3 +- src/librustc_privacy/lib.rs | 3 +- .../implied_outlives_bounds.rs | 4 +- .../normalize_projection_ty.rs | 4 +- src/librustc_traits/type_op.rs | 4 +- src/librustc_typeck/astconv.rs | 6 +- src/librustc_typeck/check/autoderef.rs | 7 +- src/librustc_typeck/check/closure.rs | 2 +- src/librustc_typeck/check/compare_method.rs | 24 +++---- src/librustc_typeck/check/dropck.rs | 8 +-- src/librustc_typeck/check/intrinsic.rs | 2 +- src/librustc_typeck/check/method/probe.rs | 4 +- src/librustc_typeck/check/method/suggest.rs | 5 +- src/librustc_typeck/check/mod.rs | 15 +++-- src/librustc_typeck/check/regionck.rs | 64 +++++++++---------- src/librustc_typeck/check/wfcheck.rs | 9 +-- src/librustc_typeck/check/writeback.rs | 2 +- src/librustc_typeck/coherence/builtin.rs | 18 +++--- src/librustc_typeck/lib.rs | 8 +-- src/librustdoc/clean/mod.rs | 2 +- 35 files changed, 175 insertions(+), 147 deletions(-) diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index 692b7fd37d28d..b6cf4c1b84d0c 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -127,9 +127,9 @@ impl<'hir> Entry<'hir> { } } - fn is_body_owner(self, node_id: NodeId) -> bool { + fn is_body_owner(self, hir_id: HirId) -> bool { match self.associated_body() { - Some(b) => b.node_id == node_id, + Some(b) => b.hir_id == hir_id, None => false, } } @@ -438,7 +438,7 @@ impl<'hir> Map<'hir> { } pub fn body(&self, id: BodyId) -> &'hir Body { - self.read(id.node_id); + self.read_by_hir_id(id.hir_id); // N.B., intentionally bypass `self.forest.krate()` so that we // do not trigger a read of the whole krate here @@ -462,9 +462,10 @@ impl<'hir> Map<'hir> { /// Returns the `NodeId` that corresponds to the definition of /// which this is the body of, i.e., a `fn`, `const` or `static` /// item (possibly associated), a closure, or a `hir::AnonConst`. - pub fn body_owner(&self, BodyId { node_id }: BodyId) -> NodeId { + pub fn body_owner(&self, BodyId { hir_id }: BodyId) -> NodeId { + let node_id = self.hir_to_node_id(hir_id); let parent = self.get_parent_node(node_id); - assert!(self.map[parent.as_usize()].map_or(false, |e| e.is_body_owner(node_id))); + assert!(self.map[parent.as_usize()].map_or(false, |e| e.is_body_owner(hir_id))); parent } @@ -488,6 +489,12 @@ impl<'hir> Map<'hir> { } } + // FIXME(@ljedrz): replace the NodeId variant + pub fn maybe_body_owned_by_by_hir_id(&self, id: HirId) -> Option { + let node_id = self.hir_to_node_id(id); + self.maybe_body_owned_by(node_id) + } + /// Given a body owner's id, returns the `BodyId` associated with it. pub fn body_owned_by(&self, id: NodeId) -> BodyId { self.maybe_body_owned_by(id).unwrap_or_else(|| { @@ -521,6 +528,12 @@ impl<'hir> Map<'hir> { } } + // FIXME(@ljedrz): replace the NodeId variant + pub fn body_owner_kind_by_hir_id(&self, id: HirId) -> BodyOwnerKind { + let node_id = self.hir_to_node_id(id); + self.body_owner_kind(node_id) + } + pub fn ty_param_owner(&self, id: NodeId) -> NodeId { match self.get(id) { Node::Item(&Item { node: ItemKind::Trait(..), .. }) => id, @@ -837,6 +850,12 @@ impl<'hir> Map<'hir> { self.local_def_id(self.get_module_parent_node(id)) } + // FIXME(@ljedrz): replace the NodeId variant + pub fn get_module_parent_by_hir_id(&self, id: HirId) -> DefId { + let node_id = self.hir_to_node_id(id); + self.get_module_parent(node_id) + } + /// Returns the `NodeId` of `id`'s nearest module parent, or `id` itself if no /// module parent is in this map. pub fn get_module_parent_node(&self, id: NodeId) -> NodeId { diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index bf16ec0be83e7..139a4222f89de 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -72,7 +72,7 @@ pub mod print; /// the `local_id` part of the `HirId` changing, which is a very useful property in /// incremental compilation where we have to persist things through changes to /// the code base. -#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, PartialOrd, Ord)] pub struct HirId { pub owner: DefIndex, pub local_id: ItemLocalId, @@ -1234,7 +1234,7 @@ pub enum UnsafeSource { #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, RustcEncodable, RustcDecodable, Hash, Debug)] pub struct BodyId { - pub node_id: NodeId, + pub hir_id: HirId, } /// The body of a function, closure, or constant value. In the case of @@ -1268,7 +1268,7 @@ pub struct Body { impl Body { pub fn id(&self) -> BodyId { BodyId { - node_id: self.value.id + hir_id: self.value.hir_id, } } } diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs index 712fd360fbb6f..b10e893732597 100644 --- a/src/librustc/ich/impls_hir.rs +++ b/src/librustc/ich/impls_hir.rs @@ -989,8 +989,8 @@ impl<'a> ToStableHashKey> for hir::BodyId { fn to_stable_hash_key(&self, hcx: &StableHashingContext<'a>) -> (DefPathHash, hir::ItemLocalId) { - let hir::BodyId { node_id } = *self; - node_id.to_stable_hash_key(hcx) + let hir::BodyId { hir_id } = *self; + hir_id.to_stable_hash_key(hcx) } } diff --git a/src/librustc/infer/error_reporting/need_type_info.rs b/src/librustc/infer/error_reporting/need_type_info.rs index 0fbdbe15a3c54..9e0e48e474118 100644 --- a/src/librustc/infer/error_reporting/need_type_info.rs +++ b/src/librustc/infer/error_reporting/need_type_info.rs @@ -105,7 +105,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { }; if let Some(body_id) = body_id { - let expr = self.tcx.hir().expect_expr(body_id.node_id); + let expr = self.tcx.hir().expect_expr_by_hir_id(body_id.hir_id); local_visitor.visit_expr(expr); } diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index 8842308605825..a61771b2a4eea 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -7,6 +7,7 @@ pub use self::SubregionOrigin::*; pub use self::ValuePairs::*; pub use crate::ty::IntVarValue; +use crate::hir; use crate::hir::def_id::DefId; use crate::infer::canonical::{Canonical, CanonicalVarValues}; use crate::middle::free_region::RegionRelations; @@ -203,7 +204,7 @@ pub struct InferCtxt<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { // for each body-id in this map, which will process the // obligations within. This is expected to be done 'late enough' // that all type inference variables have been bound and so forth. - pub region_obligations: RefCell)>>, + pub region_obligations: RefCell)>>, /// What is the innermost universe we have created? Starts out as /// `UniverseIndex::root()` but grows from there as we enter @@ -1433,7 +1434,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { pub fn partially_normalize_associated_types_in( &self, span: Span, - body_id: ast::NodeId, + body_id: hir::HirId, param_env: ty::ParamEnv<'tcx>, value: &T, ) -> InferOk<'tcx, T> diff --git a/src/librustc/infer/opaque_types/mod.rs b/src/librustc/infer/opaque_types/mod.rs index 0e2c49a00dafe..1f81321d22d6e 100644 --- a/src/librustc/infer/opaque_types/mod.rs +++ b/src/librustc/infer/opaque_types/mod.rs @@ -98,7 +98,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { pub fn instantiate_opaque_types>( &self, parent_def_id: DefId, - body_id: ast::NodeId, + body_id: hir::HirId, param_env: ty::ParamEnv<'tcx>, value: &T, ) -> InferOk<'tcx, (T, OpaqueTypeMap<'tcx>)> { @@ -632,7 +632,7 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for ReverseMapper<'cx, 'gcx, 'tcx> struct Instantiator<'a, 'gcx: 'tcx, 'tcx: 'a> { infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, parent_def_id: DefId, - body_id: ast::NodeId, + body_id: hir::HirId, param_env: ty::ParamEnv<'tcx>, opaque_types: OpaqueTypeMap<'tcx>, obligations: Vec>, diff --git a/src/librustc/infer/outlives/env.rs b/src/librustc/infer/outlives/env.rs index 43afb60ee1731..39aa51a95f793 100644 --- a/src/librustc/infer/outlives/env.rs +++ b/src/librustc/infer/outlives/env.rs @@ -1,7 +1,7 @@ use crate::infer::outlives::free_region_map::FreeRegionMap; use crate::infer::{GenericKind, InferCtxt}; +use crate::hir; use rustc_data_structures::fx::FxHashMap; -use syntax::ast; use syntax_pos::Span; use crate::traits::query::outlives_bounds::{self, OutlivesBound}; use crate::ty::{self, Ty}; @@ -55,7 +55,7 @@ pub struct OutlivesEnvironment<'tcx> { // results when proving outlives obligations like `T: 'x` later // (e.g., if `T: 'x` must be proven within the body B1, then we // know it is true if either `'a: 'x` or `'b: 'x`). - region_bound_pairs_map: FxHashMap>, + region_bound_pairs_map: FxHashMap>, // Used to compute `region_bound_pairs_map`: contains the set of // in-scope region-bound pairs thus far. @@ -87,7 +87,7 @@ impl<'a, 'gcx: 'tcx, 'tcx: 'a> OutlivesEnvironment<'tcx> { } /// Borrows current value of the `region_bound_pairs`. - pub fn region_bound_pairs_map(&self) -> &FxHashMap> { + pub fn region_bound_pairs_map(&self) -> &FxHashMap> { &self.region_bound_pairs_map } @@ -162,7 +162,7 @@ impl<'a, 'gcx: 'tcx, 'tcx: 'a> OutlivesEnvironment<'tcx> { &mut self, infcx: &InferCtxt<'a, 'gcx, 'tcx>, fn_sig_tys: &[Ty<'tcx>], - body_id: ast::NodeId, + body_id: hir::HirId, span: Span, ) { debug!("add_implied_bounds()"); @@ -176,7 +176,7 @@ impl<'a, 'gcx: 'tcx, 'tcx: 'a> OutlivesEnvironment<'tcx> { } /// Save the current set of region-bound pairs under the given `body_id`. - pub fn save_implied_bounds(&mut self, body_id: ast::NodeId) { + pub fn save_implied_bounds(&mut self, body_id: hir::HirId) { let old = self.region_bound_pairs_map.insert( body_id, self.region_bound_pairs_accum.clone(), diff --git a/src/librustc/infer/outlives/obligations.rs b/src/librustc/infer/outlives/obligations.rs index c40fbfb25e422..bbda3d2fdbf84 100644 --- a/src/librustc/infer/outlives/obligations.rs +++ b/src/librustc/infer/outlives/obligations.rs @@ -63,7 +63,7 @@ use crate::infer::outlives::env::RegionBoundPairs; use crate::infer::outlives::verify::VerifyBoundCx; use crate::infer::{self, GenericKind, InferCtxt, RegionObligation, SubregionOrigin, VerifyBound}; use rustc_data_structures::fx::FxHashMap; -use syntax::ast; +use crate::hir; use crate::traits::ObligationCause; use crate::ty::outlives::Component; use crate::ty::{self, Region, Ty, TyCtxt, TypeFoldable}; @@ -76,7 +76,7 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> { /// information). pub fn register_region_obligation( &self, - body_id: ast::NodeId, + body_id: hir::HirId, obligation: RegionObligation<'tcx>, ) { debug!( @@ -110,7 +110,7 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> { } /// Trait queries just want to pass back type obligations "as is" - pub fn take_registered_region_obligations(&self) -> Vec<(ast::NodeId, RegionObligation<'tcx>)> { + pub fn take_registered_region_obligations(&self) -> Vec<(hir::HirId, RegionObligation<'tcx>)> { ::std::mem::replace(&mut *self.region_obligations.borrow_mut(), vec![]) } @@ -149,7 +149,7 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> { /// processed. pub fn process_registered_region_obligations( &self, - region_bound_pairs_map: &FxHashMap>, + region_bound_pairs_map: &FxHashMap>, implicit_region_bound: Option>, param_env: ty::ParamEnv<'tcx>, ) { diff --git a/src/librustc/traits/auto_trait.rs b/src/librustc/traits/auto_trait.rs index 012b9e5034cae..8957bbaa4ad7d 100644 --- a/src/librustc/traits/auto_trait.rs +++ b/src/librustc/traits/auto_trait.rs @@ -202,7 +202,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { full_env, ty, trait_did, - ObligationCause::misc(DUMMY_SP, ast::DUMMY_NODE_ID), + ObligationCause::misc(DUMMY_SP, hir::DUMMY_HIR_ID), ); fulfill.select_all_or_error(&infcx).unwrap_or_else(|e| { panic!( @@ -315,7 +315,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { user_env.caller_bounds.iter().cloned().collect(); let mut new_env = param_env.clone(); - let dummy_cause = ObligationCause::misc(DUMMY_SP, ast::DUMMY_NODE_ID); + let dummy_cause = ObligationCause::misc(DUMMY_SP, hir::DUMMY_HIR_ID); while let Some(pred) = predicates.pop_front() { infcx.clear_caches(); @@ -669,7 +669,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { select: &mut SelectionContext<'c, 'd, 'cx>, only_projections: bool, ) -> bool { - let dummy_cause = ObligationCause::misc(DUMMY_SP, ast::DUMMY_NODE_ID); + let dummy_cause = ObligationCause::misc(DUMMY_SP, hir::DUMMY_HIR_ID); for (obligation, mut predicate) in nested .map(|o| (o.clone(), o.predicate.clone())) diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index a32838f0e4c0c..459ff4db9e957 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -132,7 +132,7 @@ pub struct ObligationCause<'tcx> { /// (in particular, closures can add new assumptions). See the /// field `region_obligations` of the `FulfillmentContext` for more /// information. - pub body_id: ast::NodeId, + pub body_id: hir::HirId, pub code: ObligationCauseCode<'tcx> } @@ -654,7 +654,7 @@ pub fn type_known_to_meet_bound_modulo_regions<'a, 'gcx, 'tcx>( }; let obligation = Obligation { param_env, - cause: ObligationCause::misc(span, ast::DUMMY_NODE_ID), + cause: ObligationCause::misc(span, hir::DUMMY_HIR_ID), recursion_depth: 0, predicate: trait_ref.to_predicate(), }; @@ -677,7 +677,7 @@ pub fn type_known_to_meet_bound_modulo_regions<'a, 'gcx, 'tcx>( // We can use a dummy node-id here because we won't pay any mind // to region obligations that arise (there shouldn't really be any // anyhow). - let cause = ObligationCause::misc(span, ast::DUMMY_NODE_ID); + let cause = ObligationCause::misc(span, hir::DUMMY_HIR_ID); fulfill_cx.register_bound(infcx, param_env, ty, def_id, cause); @@ -1057,7 +1057,7 @@ impl<'tcx,O> Obligation<'tcx,O> { } pub fn misc(span: Span, - body_id: ast::NodeId, + body_id: hir::HirId, param_env: ty::ParamEnv<'tcx>, trait_ref: O) -> Obligation<'tcx, O> { @@ -1075,18 +1075,18 @@ impl<'tcx,O> Obligation<'tcx,O> { impl<'tcx> ObligationCause<'tcx> { #[inline] pub fn new(span: Span, - body_id: ast::NodeId, + body_id: hir::HirId, code: ObligationCauseCode<'tcx>) -> ObligationCause<'tcx> { - ObligationCause { span: span, body_id: body_id, code: code } + ObligationCause { span, body_id, code } } - pub fn misc(span: Span, body_id: ast::NodeId) -> ObligationCause<'tcx> { - ObligationCause { span: span, body_id: body_id, code: MiscObligation } + pub fn misc(span: Span, body_id: hir::HirId) -> ObligationCause<'tcx> { + ObligationCause { span, body_id, code: MiscObligation } } pub fn dummy() -> ObligationCause<'tcx> { - ObligationCause { span: DUMMY_SP, body_id: ast::CRATE_NODE_ID, code: MiscObligation } + ObligationCause { span: DUMMY_SP, body_id: hir::CRATE_HIR_ID, code: MiscObligation } } } diff --git a/src/librustc/traits/query/outlives_bounds.rs b/src/librustc/traits/query/outlives_bounds.rs index 6fe361d5adf6d..954de15905fb7 100644 --- a/src/librustc/traits/query/outlives_bounds.rs +++ b/src/librustc/traits/query/outlives_bounds.rs @@ -1,6 +1,6 @@ use crate::infer::InferCtxt; use crate::infer::canonical::OriginalQueryValues; -use syntax::ast; +use crate::hir; use syntax::source_map::Span; use crate::traits::{FulfillmentContext, ObligationCause, TraitEngine, TraitEngineExt}; use crate::traits::query::NoSolution; @@ -89,7 +89,7 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> { pub fn implied_outlives_bounds( &self, param_env: ty::ParamEnv<'tcx>, - body_id: ast::NodeId, + body_id: hir::HirId, ty: Ty<'tcx>, span: Span, ) -> Vec> { diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 70f72acad1fb6..1bb67b3ffaae8 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -39,7 +39,7 @@ use std::ops::Deref; use rustc_data_structures::sync::{self, Lrc, ParallelIterator, par_iter}; use std::slice; use std::{mem, ptr}; -use syntax::ast::{self, DUMMY_NODE_ID, Name, Ident, NodeId}; +use syntax::ast::{self, Name, Ident, NodeId}; use syntax::attr; use syntax::ext::hygiene::Mark; use syntax::symbol::{keywords, Symbol, LocalInternedString, InternedString}; @@ -2795,7 +2795,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { pub fn find_field_index(self, ident: Ident, variant: &VariantDef) -> Option { variant.fields.iter().position(|field| { - self.adjust_ident(ident, variant.did, DUMMY_NODE_ID).0 == field.ident.modern() + self.adjust_ident(ident, variant.did, hir::DUMMY_HIR_ID).0 == field.ident.modern() }) } @@ -3003,10 +3003,10 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { /// its supposed definition name (`def_name`). The method also needs `DefId` of the supposed /// definition's parent/scope to perform comparison. pub fn hygienic_eq(self, use_name: Ident, def_name: Ident, def_parent_def_id: DefId) -> bool { - self.adjust_ident(use_name, def_parent_def_id, DUMMY_NODE_ID).0 == def_name.modern() + self.adjust_ident(use_name, def_parent_def_id, hir::DUMMY_HIR_ID).0 == def_name.modern() } - pub fn adjust_ident(self, mut ident: Ident, scope: DefId, block: NodeId) -> (Ident, DefId) { + pub fn adjust_ident(self, mut ident: Ident, scope: DefId, block: hir::HirId) -> (Ident, DefId) { ident = ident.modern(); let target_expansion = match scope.krate { LOCAL_CRATE => self.hir().definitions().expansion_that_defined(scope.index), @@ -3015,8 +3015,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { let scope = match ident.span.adjust(target_expansion) { Some(actual_expansion) => self.hir().definitions().parent_module_of_macro_def(actual_expansion), - None if block == DUMMY_NODE_ID => DefId::local(CRATE_DEF_INDEX), // Dummy DefId - None => self.hir().get_module_parent(block), + None if block == hir::DUMMY_HIR_ID => DefId::local(CRATE_DEF_INDEX), // Dummy DefId + None => self.hir().get_module_parent_by_hir_id(block), }; (ident, scope) } @@ -3193,8 +3193,8 @@ fn param_env<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, if tcx.sess.opts.debugging_opts.chalk { Some(def_id) } else { None } ); - let body_id = tcx.hir().as_local_node_id(def_id).map_or(DUMMY_NODE_ID, |id| { - tcx.hir().maybe_body_owned_by(id).map_or(id, |body| body.node_id) + let body_id = tcx.hir().as_local_hir_id(def_id).map_or(hir::DUMMY_HIR_ID, |id| { + tcx.hir().maybe_body_owned_by_by_hir_id(id).map_or(id, |body| body.hir_id) }); let cause = traits::ObligationCause::misc(tcx.def_span(def_id), body_id); traits::normalize_param_env_or_error(tcx, def_id, unnormalized_env, cause) diff --git a/src/librustc/ty/wf.rs b/src/librustc/ty/wf.rs index ffb5471e34fbf..282bf1219fa5c 100644 --- a/src/librustc/ty/wf.rs +++ b/src/librustc/ty/wf.rs @@ -1,10 +1,10 @@ +use crate::hir; use crate::hir::def_id::DefId; use crate::infer::InferCtxt; use crate::ty::subst::Substs; use crate::traits; use crate::ty::{self, ToPredicate, Ty, TyCtxt, TypeFoldable}; use std::iter::once; -use syntax::ast; use syntax_pos::Span; use crate::middle::lang_items; @@ -16,7 +16,7 @@ use crate::middle::lang_items; /// say "$0 is WF if $0 is WF". pub fn obligations<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>, param_env: ty::ParamEnv<'tcx>, - body_id: ast::NodeId, + body_id: hir::HirId, ty: Ty<'tcx>, span: Span) -> Option>> @@ -42,7 +42,7 @@ pub fn obligations<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>, /// if `Bar: Eq`. pub fn trait_obligations<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>, param_env: ty::ParamEnv<'tcx>, - body_id: ast::NodeId, + body_id: hir::HirId, trait_ref: &ty::TraitRef<'tcx>, span: Span) -> Vec> @@ -54,7 +54,7 @@ pub fn trait_obligations<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>, pub fn predicate_obligations<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>, param_env: ty::ParamEnv<'tcx>, - body_id: ast::NodeId, + body_id: hir::HirId, predicate: &ty::Predicate<'tcx>, span: Span) -> Vec> @@ -103,7 +103,7 @@ pub fn predicate_obligations<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>, struct WfPredicates<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, param_env: ty::ParamEnv<'tcx>, - body_id: ast::NodeId, + body_id: hir::HirId, span: Span, out: Vec>, } diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs index 85c4ca7bd379e..307df16386639 100644 --- a/src/librustc_borrowck/borrowck/mod.rs +++ b/src/librustc_borrowck/borrowck/mod.rs @@ -404,7 +404,7 @@ fn closure_to_block(closure_id: LocalDefId, match tcx.hir().get(closure_id) { Node::Expr(expr) => match expr.node { hir::ExprKind::Closure(.., body_id, _, _) => { - body_id.node_id + tcx.hir().hir_to_node_id(body_id.hir_id) } _ => { bug!("encountered non-closure id: {}", closure_id) diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index a1a9e9baf1b2c..c593be4e67f45 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -1174,9 +1174,9 @@ impl MirPass for QualifyAndPromoteConstants { } let def_id = src.def_id(); - let id = tcx.hir().as_local_node_id(def_id).unwrap(); + let id = tcx.hir().as_local_hir_id(def_id).unwrap(); let mut const_promoted_temps = None; - let mode = match tcx.hir().body_owner_kind(id) { + let mode = match tcx.hir().body_owner_kind_by_hir_id(id) { hir::BodyOwnerKind::Closure => Mode::Fn, hir::BodyOwnerKind::Fn => { if tcx.is_const_fn(def_id) { diff --git a/src/librustc_passes/rvalue_promotion.rs b/src/librustc_passes/rvalue_promotion.rs index c00f38c7db6f3..20f31b3ebc173 100644 --- a/src/librustc_passes/rvalue_promotion.rs +++ b/src/librustc_passes/rvalue_promotion.rs @@ -56,8 +56,7 @@ fn const_is_rvalue_promotable_to_static<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let node_id = tcx.hir().as_local_node_id(def_id) .expect("rvalue_promotable_map invoked with non-local def-id"); let body_id = tcx.hir().body_owned_by(node_id); - let body_hir_id = tcx.hir().node_to_hir_id(body_id.node_id); - tcx.rvalue_promotable_map(def_id).contains(&body_hir_id.local_id) + tcx.rvalue_promotable_map(def_id).contains(&body_id.hir_id.local_id) } fn rvalue_promotable_map<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 0681d0d80b8c9..91651ad29dfa4 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -805,7 +805,8 @@ impl<'a, 'tcx> NamePrivacyVisitor<'a, 'tcx> { def: &'tcx ty::AdtDef, // definition of the struct or enum field: &'tcx ty::FieldDef) { // definition of the field let ident = Ident::new(keywords::Invalid.name(), use_ctxt); - let def_id = self.tcx.adjust_ident(ident, def.did, self.current_item).1; + let current_hir = self.tcx.hir().node_to_hir_id(self.current_item); + let def_id = self.tcx.adjust_ident(ident, def.did, current_hir).1; if !def.is_enum() && !field.vis.is_accessible_from(def_id, self.tcx) { struct_span_err!(self.tcx.sess, span, E0451, "field `{}` of {} `{}` is private", field.ident, def.variant_descr(), self.tcx.item_path_str(def.did)) diff --git a/src/librustc_traits/implied_outlives_bounds.rs b/src/librustc_traits/implied_outlives_bounds.rs index e4a032aaf7b18..dad45130062a4 100644 --- a/src/librustc_traits/implied_outlives_bounds.rs +++ b/src/librustc_traits/implied_outlives_bounds.rs @@ -1,6 +1,7 @@ //! Provider for the `implied_outlives_bounds` query. //! Do not call this query directory. See [`rustc::traits::query::implied_outlives_bounds`]. +use rustc::hir; use rustc::infer::InferCtxt; use rustc::infer::canonical::{self, Canonical}; use rustc::traits::{TraitEngine, TraitEngineExt}; @@ -11,7 +12,6 @@ use rustc::ty::outlives::Component; use rustc::ty::query::Providers; use rustc::ty::wf; use smallvec::{SmallVec, smallvec}; -use syntax::ast::DUMMY_NODE_ID; use syntax::source_map::DUMMY_SP; use rustc::traits::FulfillmentContext; @@ -65,7 +65,7 @@ fn compute_implied_outlives_bounds<'tcx>( // unresolved inference variables here anyway, but there might be // during typeck under some circumstances.) let obligations = - wf::obligations(infcx, param_env, DUMMY_NODE_ID, ty, DUMMY_SP).unwrap_or(vec![]); + wf::obligations(infcx, param_env, hir::DUMMY_HIR_ID, ty, DUMMY_SP).unwrap_or(vec![]); // N.B., all of these predicates *ought* to be easily proven // true. In fact, their correctness is (mostly) implied by diff --git a/src/librustc_traits/normalize_projection_ty.rs b/src/librustc_traits/normalize_projection_ty.rs index 6fe9e316cf36e..38f7a21e66c55 100644 --- a/src/librustc_traits/normalize_projection_ty.rs +++ b/src/librustc_traits/normalize_projection_ty.rs @@ -1,3 +1,4 @@ +use rustc::hir; use rustc::infer::canonical::{Canonical, QueryResponse}; use rustc::traits::query::{normalize::NormalizationResult, CanonicalProjectionGoal, NoSolution}; use rustc::traits::{self, ObligationCause, SelectionContext, TraitEngineExt}; @@ -5,7 +6,6 @@ use rustc::ty::query::Providers; use rustc::ty::{ParamEnvAnd, TyCtxt}; use rustc_data_structures::sync::Lrc; use std::sync::atomic::Ordering; -use syntax::ast::DUMMY_NODE_ID; use syntax_pos::DUMMY_SP; crate fn provide(p: &mut Providers<'_>) { @@ -34,7 +34,7 @@ fn normalize_projection_ty<'tcx>( value: goal, }| { let selcx = &mut SelectionContext::new(infcx); - let cause = ObligationCause::misc(DUMMY_SP, DUMMY_NODE_ID); + let cause = ObligationCause::misc(DUMMY_SP, hir::DUMMY_HIR_ID); let mut obligations = vec![]; let answer = traits::normalize_projection_type( selcx, diff --git a/src/librustc_traits/type_op.rs b/src/librustc_traits/type_op.rs index 3cc2f77187ac7..30fbdbdeb4433 100644 --- a/src/librustc_traits/type_op.rs +++ b/src/librustc_traits/type_op.rs @@ -1,6 +1,7 @@ use rustc::infer::at::ToTrace; use rustc::infer::canonical::{Canonical, QueryResponse}; use rustc::infer::InferCtxt; +use rustc::hir; use rustc::hir::def_id::DefId; use rustc::traits::query::type_op::ascribe_user_type::AscribeUserType; use rustc::traits::query::type_op::eq::Eq; @@ -18,7 +19,6 @@ use rustc::ty::{ }; use rustc_data_structures::sync::Lrc; use std::fmt; -use syntax::ast; use syntax_pos::DUMMY_SP; crate fn provide(p: &mut Providers<'_>) { @@ -71,7 +71,7 @@ impl AscribeUserTypeCx<'me, 'gcx, 'tcx> { self.infcx .partially_normalize_associated_types_in( DUMMY_SP, - ast::CRATE_NODE_ID, + hir::CRATE_HIR_ID, self.param_env, &value, ) diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 179350b95cb8e..23e9cd55cdce7 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -878,8 +878,9 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { binding.item_name, binding.span) }?; + let hir_ref_id = self.tcx().hir().node_to_hir_id(ref_id); let (assoc_ident, def_scope) = - tcx.adjust_ident(binding.item_name, candidate.def_id(), ref_id); + tcx.adjust_ident(binding.item_name, candidate.def_id(), hir_ref_id); let assoc_ty = tcx.associated_items(candidate.def_id()).find(|i| { i.kind == ty::AssociatedKind::Type && i.ident.modern() == assoc_ident }).expect("missing associated type"); @@ -1373,7 +1374,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { }; let trait_did = bound.def_id(); - let (assoc_ident, def_scope) = tcx.adjust_ident(assoc_ident, trait_did, ref_id); + let hir_ref_id = self.tcx().hir().node_to_hir_id(ref_id); + let (assoc_ident, def_scope) = tcx.adjust_ident(assoc_ident, trait_did, hir_ref_id); let item = tcx.associated_items(trait_did).find(|i| { Namespace::from(i.kind) == Namespace::Type && i.ident.modern() == assoc_ident diff --git a/src/librustc_typeck/check/autoderef.rs b/src/librustc_typeck/check/autoderef.rs index 35ac4f3957eb4..f863cfe1887db 100644 --- a/src/librustc_typeck/check/autoderef.rs +++ b/src/librustc_typeck/check/autoderef.rs @@ -1,6 +1,7 @@ use super::{FnCtxt, PlaceOp, Needs}; use super::method::MethodCallee; +use rustc::hir; use rustc::infer::{InferCtxt, InferOk}; use rustc::session::DiagnosticMessageId; use rustc::traits::{self, TraitEngine}; @@ -9,7 +10,7 @@ use rustc::ty::{ToPredicate, TypeFoldable}; use rustc::ty::adjustment::{Adjustment, Adjust, OverloadedDeref}; use syntax_pos::Span; -use syntax::ast::{self, Ident}; +use syntax::ast::Ident; use std::iter; @@ -21,7 +22,7 @@ enum AutoderefKind { pub struct Autoderef<'a, 'gcx: 'tcx, 'tcx: 'a> { infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, - body_id: ast::NodeId, + body_id: hir::HirId, param_env: ty::ParamEnv<'tcx>, steps: Vec<(Ty<'tcx>, AutoderefKind)>, cur_ty: Ty<'tcx>, @@ -87,7 +88,7 @@ impl<'a, 'gcx, 'tcx> Iterator for Autoderef<'a, 'gcx, 'tcx> { impl<'a, 'gcx, 'tcx> Autoderef<'a, 'gcx, 'tcx> { pub fn new(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, param_env: ty::ParamEnv<'tcx>, - body_id: ast::NodeId, + body_id: hir::HirId, span: Span, base_ty: Ty<'tcx>) -> Autoderef<'a, 'gcx, 'tcx> diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs index 93af07a4dd42c..722af8f0e778d 100644 --- a/src/librustc_typeck/check/closure.rs +++ b/src/librustc_typeck/check/closure.rs @@ -641,7 +641,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { .liberate_late_bound_regions(expr_def_id, &bound_sig); let liberated_sig = self.inh.normalize_associated_types_in( body.value.span, - body.value.id, + body.value.hir_id, self.param_env, &liberated_sig, ); diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs index 3b2d6d49fb2d2..05ca54df2984b 100644 --- a/src/librustc_typeck/check/compare_method.rs +++ b/src/librustc_typeck/check/compare_method.rs @@ -84,10 +84,11 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // `ObligationCause` (and the `FnCtxt`). This is what // `regionck_item` expects. let impl_m_node_id = tcx.hir().as_local_node_id(impl_m.def_id).unwrap(); + let impl_m_hir_id = tcx.hir().node_to_hir_id(impl_m_node_id); let cause = ObligationCause { span: impl_m_span, - body_id: impl_m_node_id, + body_id: impl_m_hir_id, code: ObligationCauseCode::CompareImplMethodObligation { item_name: impl_m.ident.name, impl_item_def_id: impl_m.def_id, @@ -205,7 +206,7 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // Construct trait parameter environment and then shift it into the placeholder viewpoint. // The key step here is to update the caller_bounds's predicates to be // the new hybrid bounds we computed. - let normalize_cause = traits::ObligationCause::misc(impl_m_span, impl_m_node_id); + let normalize_cause = traits::ObligationCause::misc(impl_m_span, impl_m_hir_id); let param_env = ty::ParamEnv::new( tcx.intern_predicates(&hybrid_preds.predicates), Reveal::UserFacing, @@ -262,7 +263,7 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ); let impl_sig = inh.normalize_associated_types_in(impl_m_span, - impl_m_node_id, + impl_m_hir_id, param_env, &impl_sig); let impl_fty = tcx.mk_fn_ptr(ty::Binder::bind(impl_sig)); @@ -275,7 +276,7 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, trait_sig.subst(tcx, trait_to_skol_substs); let trait_sig = inh.normalize_associated_types_in(impl_m_span, - impl_m_node_id, + impl_m_hir_id, param_env, &trait_sig); let trait_fty = tcx.mk_fn_ptr(ty::Binder::bind(trait_sig)); @@ -347,8 +348,8 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // Finally, resolve all regions. This catches wily misuses of // lifetime parameters. - let fcx = FnCtxt::new(&inh, param_env, impl_m_node_id); - fcx.regionck_item(impl_m_node_id, impl_m_span, &[]); + let fcx = FnCtxt::new(&inh, param_env, impl_m_hir_id); + fcx.regionck_item(impl_m_hir_id, impl_m_span, &[]); Ok(()) }) @@ -903,22 +904,23 @@ pub fn compare_const_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // Create a parameter environment that represents the implementation's // method. let impl_c_node_id = tcx.hir().as_local_node_id(impl_c.def_id).unwrap(); + let impl_c_hir_id = tcx.hir().node_to_hir_id(impl_c_node_id); // Compute placeholder form of impl and trait const tys. let impl_ty = tcx.type_of(impl_c.def_id); let trait_ty = tcx.type_of(trait_c.def_id).subst(tcx, trait_to_impl_substs); - let mut cause = ObligationCause::misc(impl_c_span, impl_c_node_id); + let mut cause = ObligationCause::misc(impl_c_span, impl_c_hir_id); // There is no "body" here, so just pass dummy id. let impl_ty = inh.normalize_associated_types_in(impl_c_span, - impl_c_node_id, + impl_c_hir_id, param_env, &impl_ty); debug!("compare_const_impl: impl_ty={:?}", impl_ty); let trait_ty = inh.normalize_associated_types_in(impl_c_span, - impl_c_node_id, + impl_c_hir_id, param_env, &trait_ty); @@ -973,7 +975,7 @@ pub fn compare_const_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, return; } - let fcx = FnCtxt::new(&inh, param_env, impl_c_node_id); - fcx.regionck_item(impl_c_node_id, impl_c_span, &[]); + let fcx = FnCtxt::new(&inh, param_env, impl_c_hir_id); + fcx.regionck_item(impl_c_hir_id, impl_c_span, &[]); }); } diff --git a/src/librustc_typeck/check/dropck.rs b/src/librustc_typeck/check/dropck.rs index 5c2608e36163b..ad74e78fecdcd 100644 --- a/src/librustc_typeck/check/dropck.rs +++ b/src/librustc_typeck/check/dropck.rs @@ -1,5 +1,6 @@ use crate::check::regionck::RegionCtxt; +use crate::hir; use crate::hir::def_id::DefId; use rustc::infer::outlives::env::OutlivesEnvironment; use rustc::infer::{self, InferOk, SuppressRegionErrors}; @@ -9,7 +10,6 @@ use rustc::ty::subst::{Subst, Substs, UnpackedKind}; use rustc::ty::{self, Ty, TyCtxt}; use crate::util::common::ErrorReported; -use syntax::ast; use syntax_pos::Span; /// This function confirms that the `Drop` implementation identified by @@ -70,7 +70,7 @@ fn ensure_drop_params_and_item_params_correspond<'a, 'tcx>( drop_impl_ty: Ty<'tcx>, self_type_did: DefId, ) -> Result<(), ErrorReported> { - let drop_impl_node_id = tcx.hir().as_local_node_id(drop_impl_did).unwrap(); + let drop_impl_hir_id = tcx.hir().as_local_hir_id(drop_impl_did).unwrap(); // check that the impl type can be made to match the trait type. @@ -85,7 +85,7 @@ fn ensure_drop_params_and_item_params_correspond<'a, 'tcx>( let fresh_impl_substs = infcx.fresh_substs_for_item(drop_impl_span, drop_impl_did); let fresh_impl_self_ty = drop_impl_ty.subst(tcx, fresh_impl_substs); - let cause = &ObligationCause::misc(drop_impl_span, drop_impl_node_id); + let cause = &ObligationCause::misc(drop_impl_span, drop_impl_hir_id); match infcx .at(cause, impl_param_env) .eq(named_type, fresh_impl_self_ty) @@ -291,7 +291,7 @@ pub fn check_safety_of_destructor_if_necessary<'a, 'gcx, 'tcx>( rcx: &mut RegionCtxt<'a, 'gcx, 'tcx>, ty: Ty<'tcx>, span: Span, - body_id: ast::NodeId, + body_id: hir::HirId, scope: region::Scope, ) -> Result<(), ErrorReported> { debug!("check_safety_of_destructor_if_necessary typ: {:?} scope: {:?}", diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs index 43513a83b6c89..fca9fa0829f72 100644 --- a/src/librustc_typeck/check/intrinsic.rs +++ b/src/librustc_typeck/check/intrinsic.rs @@ -58,7 +58,7 @@ fn equate_intrinsic_type<'a, 'tcx>( safety, abi ))); - let cause = ObligationCause::new(it.span, it.id, ObligationCauseCode::IntrinsicType); + let cause = ObligationCause::new(it.span, it.hir_id, ObligationCauseCode::IntrinsicType); require_same_types(tcx, &cause, tcx.mk_fn_ptr(tcx.fn_sig(def_id)), fty); } diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index fd93fea00bcf5..709177212ada7 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -401,7 +401,7 @@ fn method_autoderef_steps<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'gcx>, tcx.infer_ctxt().enter_with_canonical(DUMMY_SP, &goal, |ref infcx, goal, inference_vars| { let ParamEnvAnd { param_env, value: self_ty } = goal; - let mut autoderef = Autoderef::new(infcx, param_env, ast::DUMMY_NODE_ID, DUMMY_SP, self_ty) + let mut autoderef = Autoderef::new(infcx, param_env, hir::DUMMY_HIR_ID, DUMMY_SP, self_ty) .include_raw_pointers() .silence_errors(); let mut reached_raw_pointer = false; @@ -1183,7 +1183,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { stable_pick: &Pick, unstable_candidates: &[(&Candidate<'tcx>, Symbol)], ) { - let mut diag = self.tcx.struct_span_lint_node( + let mut diag = self.tcx.struct_span_lint_hir( lint::builtin::UNSTABLE_NAME_COLLISIONS, self.fcx.body_id, self.span, diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index aa6f73b29b4b5..66cc43439596f 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -346,7 +346,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { }; let field_ty = field.ty(tcx, substs); - let scope = self.tcx.hir().get_module_parent(self.body_id); + let scope = self.tcx.hir().get_module_parent_by_hir_id( + self.body_id); if field.vis.is_accessible_from(scope, self.tcx) { if self.is_fn_ty(&field_ty, span) { err.help(&format!("use `({0}.{1})(...)` if you \ @@ -499,7 +500,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { err: &mut DiagnosticBuilder, mut msg: String, candidates: Vec) { - let module_did = self.tcx.hir().get_module_parent(self.body_id); + let module_did = self.tcx.hir().get_module_parent_by_hir_id(self.body_id); let module_id = self.tcx.hir().as_local_node_id(module_did).unwrap(); let krate = self.tcx.hir().krate(); let (span, found_use) = UsePlacementFinder::check(self.tcx, krate, module_id); diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index acaa3d3966288..91e44a1588268 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -510,7 +510,7 @@ impl<'gcx, 'tcx> EnclosingBreakables<'gcx, 'tcx> { } pub struct FnCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { - body_id: ast::NodeId, + body_id: hir::HirId, /// The parameter environment used for proving trait obligations /// in this function. This can change when we descend into @@ -672,7 +672,7 @@ impl<'a, 'gcx, 'tcx> Inherited<'a, 'gcx, 'tcx> { fn normalize_associated_types_in(&self, span: Span, - body_id: ast::NodeId, + body_id: hir::HirId, param_env: ty::ParamEnv<'tcx>, value: &T) -> T where T : TypeFoldable<'tcx> @@ -861,14 +861,14 @@ fn typeck_tables_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, tcx.liberate_late_bound_regions(def_id, &fn_sig); let fn_sig = inh.normalize_associated_types_in(body.value.span, - body_id.node_id, + body_id.hir_id, param_env, &fn_sig); let fcx = check_fn(&inh, param_env, fn_sig, decl, id, body, None).0; fcx } else { - let fcx = FnCtxt::new(&inh, param_env, body.value.id); + let fcx = FnCtxt::new(&inh, param_env, body.value.hir_id); let expected_type = tcx.type_of(def_id); let expected_type = fcx.normalize_associated_types_in(body.value.span, &expected_type); fcx.require_type_is_sized(expected_type, body.value.span, traits::ConstSized); @@ -1062,7 +1062,7 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>, // Create the function context. This is either derived from scratch or, // in the case of closures, based on the outer context. - let mut fcx = FnCtxt::new(inherited, param_env, body.value.id); + let mut fcx = FnCtxt::new(inherited, param_env, body.value.hir_id); *fcx.ps.borrow_mut() = UnsafetyState::function(fn_sig.unsafety, fn_id); let declared_ret_ty = fn_sig.output(); @@ -1169,8 +1169,9 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>, let substs = fcx.tcx.mk_substs_trait(declared_ret_ty, &[]); let trait_ref = ty::TraitRef::new(term_id, substs); let return_ty_span = decl.output.span(); + let fn_hir_id = fcx.tcx.hir().node_to_hir_id(fn_id); let cause = traits::ObligationCause::new( - return_ty_span, fn_id, ObligationCauseCode::MainFunctionType); + return_ty_span, fn_hir_id, ObligationCauseCode::MainFunctionType); inherited.register_predicate( traits::Obligation::new( @@ -2022,7 +2023,7 @@ enum TupleArgumentsFlag { impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { pub fn new(inh: &'a Inherited<'a, 'gcx, 'tcx>, param_env: ty::ParamEnv<'tcx>, - body_id: ast::NodeId) + body_id: hir::HirId) -> FnCtxt<'a, 'gcx, 'tcx> { FnCtxt { body_id, diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index 79ade3bb5a65a..792f8eaacd290 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -112,7 +112,7 @@ macro_rules! ignore_err { impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { pub fn regionck_expr(&self, body: &'gcx hir::Body) { let subject = self.tcx.hir().body_owner_def_id(body.id()); - let id = body.value.id; + let id = body.value.hir_id; let mut rcx = RegionCtxt::new( self, RepeatingScope(id), @@ -138,9 +138,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { /// Region checking during the WF phase for items. `wf_tys` are the /// types from which we should derive implied bounds, if any. - pub fn regionck_item(&self, item_id: ast::NodeId, span: Span, wf_tys: &[Ty<'tcx>]) { + pub fn regionck_item(&self, item_id: hir::HirId, span: Span, wf_tys: &[Ty<'tcx>]) { debug!("regionck_item(item.id={:?}, wf_tys={:?})", item_id, wf_tys); - let subject = self.tcx.hir().local_def_id(item_id); + let subject = self.tcx.hir().local_def_id_from_hir_id(item_id); let mut rcx = RegionCtxt::new( self, RepeatingScope(item_id), @@ -166,18 +166,19 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { pub fn regionck_fn(&self, fn_id: ast::NodeId, body: &'gcx hir::Body) { debug!("regionck_fn(id={})", fn_id); let subject = self.tcx.hir().body_owner_def_id(body.id()); - let node_id = body.value.id; + let hir_id = body.value.hir_id; let mut rcx = RegionCtxt::new( self, - RepeatingScope(node_id), - node_id, + RepeatingScope(hir_id), + hir_id, Subject(subject), self.param_env, ); if self.err_count_since_creation() == 0 { + let fn_hir_id = self.tcx.hir().node_to_hir_id(fn_id); // regionck assumes typeck succeeded - rcx.visit_fn_body(fn_id, body, self.tcx.hir().span(fn_id)); + rcx.visit_fn_body(fn_hir_id, body, self.tcx.hir().span_by_hir_id(fn_hir_id)); } rcx.resolve_regions_and_report_errors(SuppressRegionErrors::when_nll_is_enabled(self.tcx)); @@ -201,13 +202,13 @@ pub struct RegionCtxt<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { outlives_environment: OutlivesEnvironment<'tcx>, // id of innermost fn body id - body_id: ast::NodeId, + body_id: hir::HirId, // call_site scope of innermost fn call_site_scope: Option, // id of innermost fn or loop - repeating_scope: ast::NodeId, + repeating_scope: hir::HirId, // id of AST node being analyzed (the subject of the analysis). subject_def_id: DefId, @@ -220,14 +221,14 @@ impl<'a, 'gcx, 'tcx> Deref for RegionCtxt<'a, 'gcx, 'tcx> { } } -pub struct RepeatingScope(ast::NodeId); +pub struct RepeatingScope(hir::HirId); pub struct Subject(DefId); impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { pub fn new( fcx: &'a FnCtxt<'a, 'gcx, 'tcx>, RepeatingScope(initial_repeating_scope): RepeatingScope, - initial_body_id: ast::NodeId, + initial_body_id: hir::HirId, Subject(subject): Subject, param_env: ty::ParamEnv<'tcx>, ) -> RegionCtxt<'a, 'gcx, 'tcx> { @@ -244,7 +245,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { } } - fn set_repeating_scope(&mut self, scope: ast::NodeId) -> ast::NodeId { + fn set_repeating_scope(&mut self, scope: hir::HirId) -> hir::HirId { mem::replace(&mut self.repeating_scope, scope) } @@ -301,15 +302,15 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { /// `intravisit::Visitor` impl below.) fn visit_fn_body( &mut self, - id: ast::NodeId, // the id of the fn itself + id: hir::HirId, // the id of the fn itself body: &'gcx hir::Body, span: Span, ) { // When we enter a function, we can derive - debug!("visit_fn_body(id={})", id); + debug!("visit_fn_body(id={:?})", id); let body_id = body.id(); - self.body_id = body_id.node_id; + self.body_id = body_id.hir_id; let call_site = region::Scope { id: body.value.hir_id.local_id, @@ -318,11 +319,10 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { self.call_site_scope = Some(call_site); let fn_sig = { - let fn_hir_id = self.tcx.hir().node_to_hir_id(id); - match self.tables.borrow().liberated_fn_sigs().get(fn_hir_id) { + match self.tables.borrow().liberated_fn_sigs().get(id) { Some(f) => f.clone(), None => { - bug!("No fn-sig entry for id={}", id); + bug!("No fn-sig entry for id={:?}", id); } } }; @@ -342,11 +342,11 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { self.outlives_environment.add_implied_bounds( self.fcx, &fn_sig_tys[..], - body_id.node_id, + body_id.hir_id, span, ); self.outlives_environment - .save_implied_bounds(body_id.node_id); + .save_implied_bounds(body_id.hir_id); self.link_fn_args( region::Scope { id: body.value.hir_id.local_id, @@ -355,7 +355,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { &body.arguments, ); self.visit_body(body); - self.visit_region_obligations(body_id.node_id); + self.visit_region_obligations(body_id.hir_id); let call_site_scope = self.call_site_scope.unwrap(); debug!( @@ -365,8 +365,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { ); let call_site_region = self.tcx.mk_region(ty::ReScope(call_site_scope)); - let body_hir_id = self.tcx.hir().node_to_hir_id(body_id.node_id); - self.type_of_node_must_outlive(infer::CallReturn(span), body_hir_id, call_site_region); + self.type_of_node_must_outlive(infer::CallReturn(span), body_id.hir_id, call_site_region); self.constrain_opaque_types( &self.fcx.opaque_types.borrow(), @@ -374,8 +373,8 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { ); } - fn visit_region_obligations(&mut self, node_id: ast::NodeId) { - debug!("visit_region_obligations: node_id={}", node_id); + fn visit_region_obligations(&mut self, hir_id: hir::HirId) { + debug!("visit_region_obligations: hir_id={:?}", hir_id); // region checking can introduce new pending obligations // which, when processed, might generate new region @@ -474,7 +473,8 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for RegionCtxt<'a, 'gcx, 'tcx> { let env_snapshot = self.outlives_environment.push_snapshot_pre_closure(); let body = self.tcx.hir().body(body_id); - self.visit_fn_body(id, body, span); + let hir_id = self.tcx.hir().node_to_hir_id(id); + self.visit_fn_body(hir_id, body, span); // Restore state from previous function. self.outlives_environment @@ -502,7 +502,7 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for RegionCtxt<'a, 'gcx, 'tcx> { fn visit_expr(&mut self, expr: &'gcx hir::Expr) { debug!( - "regionck::visit_expr(e={:?}, repeating_scope={})", + "regionck::visit_expr(e={:?}, repeating_scope={:?})", expr, self.repeating_scope ); @@ -555,7 +555,7 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for RegionCtxt<'a, 'gcx, 'tcx> { } debug!( - "regionck::visit_expr(e={:?}, repeating_scope={}) - visiting subexprs", + "regionck::visit_expr(e={:?}, repeating_scope={:?}) - visiting subexprs", expr, self.repeating_scope ); match expr.node { @@ -679,16 +679,16 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for RegionCtxt<'a, 'gcx, 'tcx> { } hir::ExprKind::Loop(ref body, _, _) => { - let repeating_scope = self.set_repeating_scope(body.id); + let repeating_scope = self.set_repeating_scope(body.hir_id); intravisit::walk_expr(self, expr); self.set_repeating_scope(repeating_scope); } hir::ExprKind::While(ref cond, ref body, _) => { - let repeating_scope = self.set_repeating_scope(cond.id); + let repeating_scope = self.set_repeating_scope(cond.hir_id); self.visit_expr(&cond); - self.set_repeating_scope(body.id); + self.set_repeating_scope(body.hir_id); self.visit_block(&body); self.set_repeating_scope(repeating_scope); @@ -758,7 +758,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { } fn check_expr_fn_block(&mut self, expr: &'gcx hir::Expr, body_id: hir::BodyId) { - let repeating_scope = self.set_repeating_scope(body_id.node_id); + let repeating_scope = self.set_repeating_scope(body_id.hir_id); intravisit::walk_expr(self, expr); self.set_repeating_scope(repeating_scope); } diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index 1489ebac748f1..86b2e0bfe8aef 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -22,7 +22,7 @@ use rustc::hir; /// `F: for<'b, 'tcx> where 'gcx: 'tcx FnOnce(FnCtxt<'b, 'gcx, 'tcx>)`. struct CheckWfFcxBuilder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { inherited: super::InheritedBuilder<'a, 'gcx, 'tcx>, - id: ast::NodeId, + id: hir::HirId, span: Span, param_env: ty::ParamEnv<'tcx>, } @@ -226,9 +226,10 @@ fn for_item<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'gcx>, item: &hir::Item) fn for_id<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'gcx>, id: ast::NodeId, span: Span) -> CheckWfFcxBuilder<'a, 'gcx, 'tcx> { let def_id = tcx.hir().local_def_id(id); + let hir_id = tcx.hir().node_to_hir_id(id); CheckWfFcxBuilder { inherited: Inherited::build(tcx, def_id), - id, + id: hir_id, span, param_env: tcx.param_env(def_id), } @@ -968,13 +969,13 @@ fn reject_shadowing_parameters(tcx: TyCtxt, def_id: DefId) { fn check_false_global_bounds<'a, 'gcx, 'tcx>( fcx: &FnCtxt<'a, 'gcx, 'tcx>, span: Span, - id: ast::NodeId) + id: hir::HirId) { use rustc::ty::TypeFoldable; let empty_env = ty::ParamEnv::empty(); - let def_id = fcx.tcx.hir().local_def_id(id); + let def_id = fcx.tcx.hir().local_def_id_from_hir_id(id); let predicates = fcx.tcx.predicates_of(def_id).predicates .iter() .map(|(p, _)| *p) diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index e02e70651d6c1..e68c50d752bd5 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -100,7 +100,7 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { body: &'gcx hir::Body, rustc_dump_user_substs: bool, ) -> WritebackCx<'cx, 'gcx, 'tcx> { - let owner = fcx.tcx.hir().definitions().node_to_hir_id(body.id().node_id); + let owner = body.id().hir_id; WritebackCx { fcx, diff --git a/src/librustc_typeck/coherence/builtin.rs b/src/librustc_typeck/coherence/builtin.rs index 3ec08f221f576..0996d1ff3b998 100644 --- a/src/librustc_typeck/coherence/builtin.rs +++ b/src/librustc_typeck/coherence/builtin.rs @@ -162,8 +162,8 @@ fn visit_implementation_of_dispatch_from_dyn<'a, 'tcx>( if impl_did.is_local() { let dispatch_from_dyn_trait = tcx.lang_items().dispatch_from_dyn_trait().unwrap(); - let impl_node_id = tcx.hir().as_local_node_id(impl_did).unwrap(); - let span = tcx.hir().span(impl_node_id); + let impl_hir_id = tcx.hir().as_local_hir_id(impl_did).unwrap(); + let span = tcx.hir().span_by_hir_id(impl_hir_id); let source = tcx.type_of(impl_did); assert!(!source.has_escaping_bound_vars()); @@ -185,7 +185,7 @@ fn visit_implementation_of_dispatch_from_dyn<'a, 'tcx>( }; tcx.infer_ctxt().enter(|infcx| { - let cause = ObligationCause::misc(span, impl_node_id); + let cause = ObligationCause::misc(span, impl_hir_id); use ty::TyKind::*; match (&source.sty, &target.sty) { @@ -332,7 +332,7 @@ pub fn coerce_unsized_info<'a, 'gcx>(gcx: TyCtxt<'a, 'gcx, 'gcx>, }); // this provider should only get invoked for local def-ids - let impl_node_id = gcx.hir().as_local_node_id(impl_did).unwrap_or_else(|| { + let impl_hir_id = gcx.hir().as_local_hir_id(impl_did).unwrap_or_else(|| { bug!("coerce_unsized_info: invoked for non-local def-id {:?}", impl_did) }); @@ -344,7 +344,7 @@ pub fn coerce_unsized_info<'a, 'gcx>(gcx: TyCtxt<'a, 'gcx, 'gcx>, source, target); - let span = gcx.hir().span(impl_node_id); + let span = gcx.hir().span_by_hir_id(impl_hir_id); let param_env = gcx.param_env(impl_did); assert!(!source.has_escaping_bound_vars()); @@ -355,7 +355,7 @@ pub fn coerce_unsized_info<'a, 'gcx>(gcx: TyCtxt<'a, 'gcx, 'gcx>, target); gcx.infer_ctxt().enter(|infcx| { - let cause = ObligationCause::misc(span, impl_node_id); + let cause = ObligationCause::misc(span, impl_hir_id); let check_mutbl = |mt_a: ty::TypeAndMut<'gcx>, mt_b: ty::TypeAndMut<'gcx>, mk_ptr: &dyn Fn(Ty<'gcx>) -> Ty<'gcx>| { @@ -481,11 +481,11 @@ pub fn coerce_unsized_info<'a, 'gcx>(gcx: TyCtxt<'a, 'gcx, 'gcx>, being coerced, none found"); return err_info; } else if diff_fields.len() > 1 { - let item = gcx.hir().expect_item(impl_node_id); + let item = gcx.hir().expect_item_by_hir_id(impl_hir_id); let span = if let ItemKind::Impl(.., Some(ref t), _, _) = item.node { t.path.span } else { - gcx.hir().span(impl_node_id) + gcx.hir().span_by_hir_id(impl_hir_id) }; let mut err = struct_span_err!(gcx.sess, @@ -527,7 +527,7 @@ pub fn coerce_unsized_info<'a, 'gcx>(gcx: TyCtxt<'a, 'gcx, 'gcx>, let mut fulfill_cx = TraitEngine::new(infcx.tcx); // Register an obligation for `A: Trait`. - let cause = traits::ObligationCause::misc(span, impl_node_id); + let cause = traits::ObligationCause::misc(span, impl_hir_id); let predicate = gcx.predicate_for_trait_def(param_env, cause, trait_def_id, diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index 931621fb53701..7055218577c5c 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -179,12 +179,12 @@ fn require_same_types<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } fn check_main_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, main_def_id: DefId) { - let main_id = tcx.hir().as_local_node_id(main_def_id).unwrap(); + let main_id = tcx.hir().as_local_hir_id(main_def_id).unwrap(); let main_span = tcx.def_span(main_def_id); let main_t = tcx.type_of(main_def_id); match main_t.sty { ty::FnDef(..) => { - if let Some(Node::Item(it)) = tcx.hir().find(main_id) { + if let Some(Node::Item(it)) = tcx.hir().find_by_hir_id(main_id) { if let hir::ItemKind::Fn(.., ref generics, _) = it.node { let mut error = false; if !generics.params.is_empty() { @@ -244,12 +244,12 @@ fn check_main_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, main_def_id: DefId) { } fn check_start_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, start_def_id: DefId) { - let start_id = tcx.hir().as_local_node_id(start_def_id).unwrap(); + let start_id = tcx.hir().as_local_hir_id(start_def_id).unwrap(); let start_span = tcx.def_span(start_def_id); let start_t = tcx.type_of(start_def_id); match start_t.sty { ty::FnDef(..) => { - if let Some(Node::Item(it)) = tcx.hir().find(start_id) { + if let Some(Node::Item(it)) = tcx.hir().find_by_hir_id(start_id) { if let hir::ItemKind::Fn(.., ref generics, _) = it.node { let mut error = false; if !generics.params.is_empty() { diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 8dab9efa36c62..d12b5021ca9fa 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -3830,7 +3830,7 @@ fn print_const(cx: &DocContext, n: ty::LazyConst) -> String { } fn print_const_expr(cx: &DocContext, body: hir::BodyId) -> String { - cx.tcx.hir().node_to_pretty_string(body.node_id) + cx.tcx.hir().hir_to_pretty_string(body.hir_id) } /// Given a type Path, resolve it to a Type using the TyCtxt From 15e4bd3bf460a4a943465534132a9d3eda5eb798 Mon Sep 17 00:00:00 2001 From: David Rheinsberg Date: Wed, 13 Feb 2019 11:50:09 +0100 Subject: [PATCH 24/27] target/uefi: clarify documentation This clarifies why FP-units are disabled on UEFI targets, as well as why we must opt into the NXCOMPAT feature. I did find some time to investigate why GRUB and friends disable FP on UEFI. The specification explicitly allows using MMX/SSE/AVX, but as it turns out it does not mandate enabling the instruction sets explicitly. Hence, any use of these instructions will trigger CPU exceptions, unless an application explicitly enables them (which is not an option, as these are global flags that better be controlled by the kernel/firmware). Furthermore, UEFI systems are allowed to mark any non-code page as non-executable. Hence, we must make sure to never place code on the stack or heap. So we better pass /NXCOMPAT to the linker for it to complain if it ever places code in non-code pages. Lastly, this fixes some typos in related comments. --- src/librustc_target/spec/uefi_base.rs | 7 ++++-- .../spec/x86_64_unknown_uefi.rs | 22 ++++++++++--------- 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/src/librustc_target/spec/uefi_base.rs b/src/librustc_target/spec/uefi_base.rs index 5078d500679d1..631966c09a498 100644 --- a/src/librustc_target/spec/uefi_base.rs +++ b/src/librustc_target/spec/uefi_base.rs @@ -5,7 +5,7 @@ // UEFI uses COFF/PE32+ format for binaries. All binaries must be statically linked. No dynamic // linker is supported. As native to COFF, binaries are position-dependent, but will be relocated // by the loader if the pre-chosen memory location is already in use. -// UEFI forbids running code on anything but the boot-CPU. Not interrupts are allowed other than +// UEFI forbids running code on anything but the boot-CPU. No interrupts are allowed other than // the timer-interrupt. Device-drivers are required to use polling-based models. Furthermore, all // code runs in the same environment, no process separation is supported. @@ -21,7 +21,10 @@ pub fn opts() -> TargetOptions { "/NOLOGO".to_string(), // UEFI is fully compatible to non-executable data pages. Tell the compiler that - // non-code sections can be marked as non-executable, including stack pages. + // non-code sections can be marked as non-executable, including stack pages. In fact, + // firmware might enforce this, so we better let the linker know about this, so it + // will fail if the compiler ever tries placing code on the stack (e.g., trampoline + // constructs and alike). "/NXCOMPAT".to_string(), // There is no runtime for UEFI targets, prevent them from being linked. UEFI targets diff --git a/src/librustc_target/spec/x86_64_unknown_uefi.rs b/src/librustc_target/spec/x86_64_unknown_uefi.rs index 9ac17a1693fb5..443479f55f04a 100644 --- a/src/librustc_target/spec/x86_64_unknown_uefi.rs +++ b/src/librustc_target/spec/x86_64_unknown_uefi.rs @@ -12,13 +12,15 @@ pub fn target() -> TargetResult { base.cpu = "x86-64".to_string(); base.max_atomic_width = Some(64); - // We disable MMX and SSE for now. UEFI does not prevent these from being used, but there have - // been reports to GRUB that some firmware does not initialize the FP exception handlers - // properly. Therefore, using FP coprocessors will end you up at random memory locations when - // you throw FP exceptions. - // To be safe, we disable them for now and force soft-float. This can be revisited when we - // have more test coverage. Disabling FP served GRUB well so far, so it should be good for us - // as well. + // We disable MMX and SSE for now, even though UEFI allows using them. Problem is, you have to + // enable these CPU features explicitly before their first use, otherwise their instructions + // will trigger an exception. Rust does not inject any code that enables AVX/MMX/SSE + // instruction sets, so this must be done by the firmware. However, existing firmware is known + // to leave these uninitialized, thus triggering exceptions if we make use of them. Which is + // why we avoid them and instead use soft-floats. This is also what GRUB and friends did so + // far. + // If you initialize FP units yourself, you can override these flags with custom linker + // arguments, thus giving you access to full MMX/SSE acceleration. base.features = "-mmx,-sse,+soft-float".to_string(); // UEFI systems run without a host OS, hence we cannot assume any code locality. We must tell @@ -26,9 +28,9 @@ pub fn target() -> TargetResult { // places no locality-restrictions, so it fits well here. base.code_model = Some("large".to_string()); - // UEFI mostly mirrors the calling-conventions used on windows. In case of x86-64 this means - // small structs will be returned as int. This shouldn't matter much, since the restrictions - // placed by the UEFI specifications forbid any ABI to return structures. + // UEFI mirrors the calling-conventions used on windows. In case of x86-64 this means small + // structs will be returned as int. This shouldn't matter much, since the restrictions placed + // by the UEFI specifications forbid any ABI to return structures. base.abi_return_struct_as_int = true; Ok(Target { From f2fe12a8ab85ab7e579bcc74246e6c7fea9f1015 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sat, 2 Feb 2019 19:00:02 +0100 Subject: [PATCH 25/27] libpanic_unwind => 2018 --- src/libpanic_unwind/Cargo.toml | 1 + src/libpanic_unwind/dwarf/eh.rs | 6 +++--- src/libpanic_unwind/emcc.rs | 2 +- src/libpanic_unwind/gcc.rs | 2 +- src/libpanic_unwind/lib.rs | 6 +++--- src/libpanic_unwind/seh.rs | 4 ++-- src/libpanic_unwind/seh64_gnu.rs | 4 ++-- 7 files changed, 13 insertions(+), 12 deletions(-) diff --git a/src/libpanic_unwind/Cargo.toml b/src/libpanic_unwind/Cargo.toml index c9fce621608a2..1b3901ac11a96 100644 --- a/src/libpanic_unwind/Cargo.toml +++ b/src/libpanic_unwind/Cargo.toml @@ -2,6 +2,7 @@ authors = ["The Rust Project Developers"] name = "panic_unwind" version = "0.0.0" +edition = "2018" [lib] path = "lib.rs" diff --git a/src/libpanic_unwind/dwarf/eh.rs b/src/libpanic_unwind/dwarf/eh.rs index ce24406b55642..07fa2971847f6 100644 --- a/src/libpanic_unwind/dwarf/eh.rs +++ b/src/libpanic_unwind/dwarf/eh.rs @@ -11,7 +11,7 @@ #![allow(non_upper_case_globals)] #![allow(unused)] -use dwarf::DwarfReader; +use crate::dwarf::DwarfReader; use core::mem; pub const DW_EH_PE_omit: u8 = 0xFF; @@ -51,7 +51,7 @@ pub enum EHAction { pub const USING_SJLJ_EXCEPTIONS: bool = cfg!(all(target_os = "ios", target_arch = "arm")); -pub unsafe fn find_eh_action(lsda: *const u8, context: &EHContext) +pub unsafe fn find_eh_action(lsda: *const u8, context: &EHContext<'_>) -> Result { if lsda.is_null() { @@ -145,7 +145,7 @@ fn round_up(unrounded: usize, align: usize) -> Result { } unsafe fn read_encoded_pointer(reader: &mut DwarfReader, - context: &EHContext, + context: &EHContext<'_>, encoding: u8) -> Result { if encoding == DW_EH_PE_omit { diff --git a/src/libpanic_unwind/emcc.rs b/src/libpanic_unwind/emcc.rs index 1f5ccfb0f1210..18e9006468ef3 100644 --- a/src/libpanic_unwind/emcc.rs +++ b/src/libpanic_unwind/emcc.rs @@ -10,10 +10,10 @@ use core::any::Any; use core::ptr; +use core::mem; use alloc::boxed::Box; use libc::{self, c_int}; use unwind as uw; -use core::mem; pub fn payload() -> *mut u8 { ptr::null_mut() diff --git a/src/libpanic_unwind/gcc.rs b/src/libpanic_unwind/gcc.rs index 607fe28e3f28d..e2b743b379704 100644 --- a/src/libpanic_unwind/gcc.rs +++ b/src/libpanic_unwind/gcc.rs @@ -52,7 +52,7 @@ use alloc::boxed::Box; use unwind as uw; use libc::{c_int, uintptr_t}; -use dwarf::eh::{self, EHContext, EHAction}; +use crate::dwarf::eh::{self, EHContext, EHAction}; #[repr(C)] struct Exception { diff --git a/src/libpanic_unwind/lib.rs b/src/libpanic_unwind/lib.rs index fa7a0916d429b..0369880a8d1a6 100644 --- a/src/libpanic_unwind/lib.rs +++ b/src/libpanic_unwind/lib.rs @@ -17,6 +17,8 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/", issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/")] +#![deny(rust_2018_idioms)] + #![feature(allocator_api)] #![feature(alloc)] #![feature(core_intrinsics)] @@ -32,8 +34,6 @@ #![panic_runtime] #![feature(panic_runtime)] -extern crate alloc; -extern crate libc; #[cfg(not(any(target_env = "msvc", all(windows, target_arch = "x86_64", target_env = "gnu"))))] extern crate unwind; @@ -87,7 +87,7 @@ pub unsafe extern "C" fn __rust_maybe_catch_panic(f: fn(*mut u8), vtable_ptr: *mut usize) -> u32 { let mut payload = imp::payload(); - if intrinsics::try(f, data, &mut payload as *mut _ as *mut _) == 0 { + if intrinsics::r#try(f, data, &mut payload as *mut _ as *mut _) == 0 { 0 } else { let obj = mem::transmute::<_, raw::TraitObject>(imp::cleanup(payload)); diff --git a/src/libpanic_unwind/seh.rs b/src/libpanic_unwind/seh.rs index f52d010815c5d..996fdb931eff2 100644 --- a/src/libpanic_unwind/seh.rs +++ b/src/libpanic_unwind/seh.rs @@ -52,7 +52,7 @@ use core::any::Any; use core::mem; use core::raw; -use windows as c; +use crate::windows as c; use libc::{c_int, c_uint}; // First up, a whole bunch of type definitions. There's a few platform-specific @@ -301,5 +301,5 @@ pub unsafe fn cleanup(payload: [u64; 2]) -> Box { #[lang = "eh_personality"] #[cfg(not(test))] fn rust_eh_personality() { - unsafe { ::core::intrinsics::abort() } + unsafe { core::intrinsics::abort() } } diff --git a/src/libpanic_unwind/seh64_gnu.rs b/src/libpanic_unwind/seh64_gnu.rs index 56ff6082190bc..457ffcd34f9c7 100644 --- a/src/libpanic_unwind/seh64_gnu.rs +++ b/src/libpanic_unwind/seh64_gnu.rs @@ -9,8 +9,8 @@ use alloc::boxed::Box; use core::any::Any; use core::intrinsics; use core::ptr; -use dwarf::eh::{EHContext, EHAction, find_eh_action}; -use windows as c; +use crate::dwarf::eh::{EHContext, EHAction, find_eh_action}; +use crate::windows as c; // Define our exception codes: // according to http://msdn.microsoft.com/en-us/library/het71c37(v=VS.80).aspx, From f9e9c9196a196e95d8f39aa57ed30857525be5e6 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Wed, 13 Feb 2019 00:07:22 +0100 Subject: [PATCH 26/27] libpanic_unwind => 2018: fix ICEs. --- src/librustc_typeck/check/method/suggest.rs | 5 ++--- src/librustdoc/visit_lib.rs | 8 +++++--- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index aa6f73b29b4b5..b3248018b5529 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -752,12 +752,11 @@ fn compute_all_traits<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Vec traits: &mut Vec, external_mods: &mut FxHashSet, def: Def) { - let def_id = def.def_id(); match def { - Def::Trait(..) => { + Def::Trait(def_id) => { traits.push(def_id); } - Def::Mod(..) => { + Def::Mod(def_id) => { if !external_mods.insert(def_id) { return; } diff --git a/src/librustdoc/visit_lib.rs b/src/librustdoc/visit_lib.rs index 7413a917f0563..bd5cae861e93b 100644 --- a/src/librustdoc/visit_lib.rs +++ b/src/librustdoc/visit_lib.rs @@ -60,9 +60,11 @@ impl<'a, 'tcx, 'rcx> LibEmbargoVisitor<'a, 'tcx, 'rcx> { } for item in self.cx.tcx.item_children(def_id).iter() { - if self.cx.tcx.def_key(item.def.def_id()).parent.map_or(false, |d| d == def_id.index) || - item.vis == Visibility::Public { - self.visit_item(item.def); + if let Some(def_id) = item.def.opt_def_id() { + if self.cx.tcx.def_key(def_id).parent.map_or(false, |d| d == def_id.index) || + item.vis == Visibility::Public { + self.visit_item(item.def); + } } } } From bb08499626d22504a6e212ead546e7ed5190c5e6 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Wed, 13 Feb 2019 18:08:53 +0100 Subject: [PATCH 27/27] libpanic_unwind => 2018: remove unused extern crate. --- src/libpanic_unwind/lib.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/libpanic_unwind/lib.rs b/src/libpanic_unwind/lib.rs index 0369880a8d1a6..9d3d8f6185bb3 100644 --- a/src/libpanic_unwind/lib.rs +++ b/src/libpanic_unwind/lib.rs @@ -34,9 +34,6 @@ #![panic_runtime] #![feature(panic_runtime)] -#[cfg(not(any(target_env = "msvc", all(windows, target_arch = "x86_64", target_env = "gnu"))))] -extern crate unwind; - use alloc::boxed::Box; use core::intrinsics; use core::mem;