From 1059a86b8f2762ada09b5e8250a84b069e6a37c8 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Fri, 21 Feb 2020 15:47:27 -0500 Subject: [PATCH 1/9] 1.41.1 release --- RELEASES.md | 12 +++++++++++- src/bootstrap/channel.rs | 33 +++++++++++++++------------------ 2 files changed, 26 insertions(+), 19 deletions(-) diff --git a/RELEASES.md b/RELEASES.md index c30ad289cfafb..26d6e2012f15a 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1,3 +1,13 @@ +Version 1.41.1 (2020-02-27) +=========================== + +* [Always check types of static items][69145] +* [Always check lifetime bounds of `Copy` impls][69145] +* [Fix miscompilation in callers of `Layout::repeat`][69225] + +[69225]: https://github.com/rust-lang/rust/issues/69225 +[69145]: https://github.com/rust-lang/rust/pull/69145 + Version 1.41.0 (2020-01-30) =========================== @@ -208,7 +218,7 @@ Compatibility Notes - [Using `#[inline]` on function prototypes and consts now emits a warning under `unused_attribute` lint.][65294] Using `#[inline]` anywhere else inside traits or `extern` blocks now correctly emits a hard error. - + [65294]: https://github.com/rust-lang/rust/pull/65294/ [66103]: https://github.com/rust-lang/rust/pull/66103/ [65843]: https://github.com/rust-lang/rust/pull/65843/ diff --git a/src/bootstrap/channel.rs b/src/bootstrap/channel.rs index b17ee098ff62a..d265b6eb2d810 100644 --- a/src/bootstrap/channel.rs +++ b/src/bootstrap/channel.rs @@ -13,7 +13,7 @@ use build_helper::output; use crate::Build; // The version number -pub const CFG_RELEASE_NUM: &str = "1.41.0"; +pub const CFG_RELEASE_NUM: &str = "1.41.1"; pub struct GitInfo { inner: Option, @@ -29,31 +29,28 @@ impl GitInfo { pub fn new(ignore_git: bool, dir: &Path) -> GitInfo { // See if this even begins to look like a git dir if ignore_git || !dir.join(".git").exists() { - return GitInfo { inner: None } + return GitInfo { inner: None }; } // Make sure git commands work - match Command::new("git") - .arg("rev-parse") - .current_dir(dir) - .output() - { + match Command::new("git").arg("rev-parse").current_dir(dir).output() { Ok(ref out) if out.status.success() => {} _ => return GitInfo { inner: None }, } // Ok, let's scrape some info - let ver_date = output(Command::new("git").current_dir(dir) - .arg("log").arg("-1") - .arg("--date=short") - .arg("--pretty=format:%cd")); - let ver_hash = output(Command::new("git").current_dir(dir) - .arg("rev-parse").arg("HEAD")); - let short_ver_hash = output(Command::new("git") - .current_dir(dir) - .arg("rev-parse") - .arg("--short=9") - .arg("HEAD")); + let ver_date = output( + Command::new("git") + .current_dir(dir) + .arg("log") + .arg("-1") + .arg("--date=short") + .arg("--pretty=format:%cd"), + ); + let ver_hash = output(Command::new("git").current_dir(dir).arg("rev-parse").arg("HEAD")); + let short_ver_hash = output( + Command::new("git").current_dir(dir).arg("rev-parse").arg("--short=9").arg("HEAD"), + ); GitInfo { inner: Some(Info { commit_date: ver_date.trim().to_string(), From 00b07c65f6a10138c92ac74e4d5c384f145dff1f Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Fri, 21 Feb 2020 16:10:27 -0500 Subject: [PATCH 2/9] rustfmt relevant files --- src/librustc/hir/map/blocks.rs | 132 ++-- src/librustc/hir/map/collector.rs | 180 +++-- src/librustc/hir/map/definitions.rs | 183 ++--- src/librustc/hir/map/hir_id_validator.rs | 106 +-- src/librustc/hir/map/mod.rs | 834 ++++++++++------------- src/librustc_mir/interpret/validity.rs | 252 +++---- 6 files changed, 783 insertions(+), 904 deletions(-) diff --git a/src/librustc/hir/map/blocks.rs b/src/librustc/hir/map/blocks.rs index 8f9f398326237..ff793fd861b3a 100644 --- a/src/librustc/hir/map/blocks.rs +++ b/src/librustc/hir/map/blocks.rs @@ -12,9 +12,9 @@ //! for the `Code` associated with a particular NodeId. use crate::hir as ast; +use crate::hir::intravisit::FnKind; use crate::hir::map; use crate::hir::{Expr, FnDecl, Node}; -use crate::hir::intravisit::FnKind; use syntax::ast::{Attribute, Ident}; use syntax_pos::Span; @@ -29,11 +29,15 @@ use syntax_pos::Span; /// /// To construct one, use the `Code::from_node` function. #[derive(Copy, Clone, Debug)] -pub struct FnLikeNode<'a> { node: Node<'a> } +pub struct FnLikeNode<'a> { + node: Node<'a>, +} /// MaybeFnLike wraps a method that indicates if an object /// corresponds to some FnLikeNode. -trait MaybeFnLike { fn is_fn_like(&self) -> bool; } +trait MaybeFnLike { + fn is_fn_like(&self) -> bool; +} impl MaybeFnLike for ast::Item { fn is_fn_like(&self) -> bool { @@ -96,7 +100,7 @@ impl<'a> Code<'a> { Code::from_node(map, map.get_parent_node(id)) } map::Node::Expr(expr) => Some(Code::Expr(expr)), - node => FnLikeNode::from_node(node).map(Code::FnLike) + node => FnLikeNode::from_node(node).map(Code::FnLike), } } } @@ -104,15 +108,15 @@ impl<'a> Code<'a> { /// These are all the components one can extract from a fn item for /// use when implementing FnLikeNode operations. struct ItemFnParts<'a> { - ident: Ident, - decl: &'a ast::FnDecl, - header: ast::FnHeader, - vis: &'a ast::Visibility, + ident: Ident, + decl: &'a ast::FnDecl, + header: ast::FnHeader, + vis: &'a ast::Visibility, generics: &'a ast::Generics, - body: ast::BodyId, - id: ast::HirId, - span: Span, - attrs: &'a [Attribute], + body: ast::BodyId, + id: ast::HirId, + span: Span, + attrs: &'a [Attribute], } /// These are all the components one can extract from a closure expr @@ -127,13 +131,7 @@ struct ClosureParts<'a> { impl<'a> ClosureParts<'a> { fn new(d: &'a FnDecl, b: ast::BodyId, id: ast::HirId, s: Span, attrs: &'a [Attribute]) -> Self { - ClosureParts { - decl: d, - body: b, - id, - span: s, - attrs, - } + ClosureParts { decl: d, body: b, id, span: s, attrs } } } @@ -145,33 +143,41 @@ impl<'a> FnLikeNode<'a> { map::Node::TraitItem(tm) => tm.is_fn_like(), map::Node::ImplItem(it) => it.is_fn_like(), map::Node::Expr(e) => e.is_fn_like(), - _ => false + _ => false, }; fn_like.then_some(FnLikeNode { node }) } pub fn body(self) -> ast::BodyId { - self.handle(|i: ItemFnParts<'a>| i.body, - |_, _, _: &'a ast::FnSig, _, body: ast::BodyId, _, _| body, - |c: ClosureParts<'a>| c.body) + self.handle( + |i: ItemFnParts<'a>| i.body, + |_, _, _: &'a ast::FnSig, _, body: ast::BodyId, _, _| body, + |c: ClosureParts<'a>| c.body, + ) } pub fn decl(self) -> &'a FnDecl { - self.handle(|i: ItemFnParts<'a>| &*i.decl, - |_, _, sig: &'a ast::FnSig, _, _, _, _| &sig.decl, - |c: ClosureParts<'a>| c.decl) + self.handle( + |i: ItemFnParts<'a>| &*i.decl, + |_, _, sig: &'a ast::FnSig, _, _, _, _| &sig.decl, + |c: ClosureParts<'a>| c.decl, + ) } pub fn span(self) -> Span { - self.handle(|i: ItemFnParts<'_>| i.span, - |_, _, _: &'a ast::FnSig, _, _, span, _| span, - |c: ClosureParts<'_>| c.span) + self.handle( + |i: ItemFnParts<'_>| i.span, + |_, _, _: &'a ast::FnSig, _, _, span, _| span, + |c: ClosureParts<'_>| c.span, + ) } pub fn id(self) -> ast::HirId { - self.handle(|i: ItemFnParts<'_>| i.id, - |id, _, _: &'a ast::FnSig, _, _, _, _| id, - |c: ClosureParts<'_>| c.id) + self.handle( + |i: ItemFnParts<'_>| i.id, + |id, _, _: &'a ast::FnSig, _, _, _, _| id, + |c: ClosureParts<'_>| c.id, + ) } pub fn constness(self) -> ast::Constness { @@ -190,41 +196,40 @@ impl<'a> FnLikeNode<'a> { let item = |p: ItemFnParts<'a>| -> FnKind<'a> { FnKind::ItemFn(p.ident, p.generics, p.header, p.vis, p.attrs) }; - let closure = |c: ClosureParts<'a>| { - FnKind::Closure(c.attrs) - }; + let closure = |c: ClosureParts<'a>| FnKind::Closure(c.attrs); let method = |_, ident: Ident, sig: &'a ast::FnSig, vis, _, _, attrs| { FnKind::Method(ident, sig, vis, attrs) }; self.handle(item, method, closure) } - fn handle(self, item_fn: I, method: M, closure: C) -> A where + fn handle(self, item_fn: I, method: M, closure: C) -> A + where I: FnOnce(ItemFnParts<'a>) -> A, - M: FnOnce(ast::HirId, - Ident, - &'a ast::FnSig, - Option<&'a ast::Visibility>, - ast::BodyId, - Span, - &'a [Attribute]) - -> A, + M: FnOnce( + ast::HirId, + Ident, + &'a ast::FnSig, + Option<&'a ast::Visibility>, + ast::BodyId, + Span, + &'a [Attribute], + ) -> A, C: FnOnce(ClosureParts<'a>) -> A, { match self.node { map::Node::Item(i) => match i.kind { - ast::ItemKind::Fn(ref sig, ref generics, block) => - item_fn(ItemFnParts { - id: i.hir_id, - ident: i.ident, - decl: &sig.decl, - body: block, - vis: &i.vis, - span: i.span, - attrs: &i.attrs, - header: sig.header, - generics, - }), + ast::ItemKind::Fn(ref sig, ref generics, block) => item_fn(ItemFnParts { + id: i.hir_id, + ident: i.ident, + decl: &sig.decl, + body: block, + vis: &i.vis, + span: i.span, + attrs: &i.attrs, + header: sig.header, + generics, + }), _ => bug!("item FnLikeNode that is not fn-like"), }, map::Node::TraitItem(ti) => match ti.kind { @@ -233,17 +238,16 @@ impl<'a> FnLikeNode<'a> { } _ => bug!("trait method FnLikeNode that is not fn-like"), }, - map::Node::ImplItem(ii) => { - match ii.kind { - ast::ImplItemKind::Method(ref sig, body) => { - method(ii.hir_id, ii.ident, sig, Some(&ii.vis), body, ii.span, &ii.attrs) - } - _ => bug!("impl method FnLikeNode that is not fn-like") + map::Node::ImplItem(ii) => match ii.kind { + ast::ImplItemKind::Method(ref sig, body) => { + method(ii.hir_id, ii.ident, sig, Some(&ii.vis), body, ii.span, &ii.attrs) } + _ => bug!("impl method FnLikeNode that is not fn-like"), }, map::Node::Expr(e) => match e.kind { - ast::ExprKind::Closure(_, ref decl, block, _fn_decl_span, _gen) => - closure(ClosureParts::new(&decl, block, e.hir_id, e.span, &e.attrs)), + ast::ExprKind::Closure(_, ref decl, block, _fn_decl_span, _gen) => { + closure(ClosureParts::new(&decl, block, e.hir_id, e.span, &e.attrs)) + } _ => bug!("expr FnLikeNode that is not fn-like"), }, _ => bug!("other FnLikeNode that is not fn-like"), diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs index b0fa844c81881..76aa186696db5 100644 --- a/src/librustc/hir/map/collector.rs +++ b/src/librustc/hir/map/collector.rs @@ -1,20 +1,20 @@ use super::*; use crate::dep_graph::{DepGraph, DepKind, DepNodeIndex}; use crate::hir; +use crate::hir::def_id::{CrateNum, LOCAL_CRATE}; +use crate::hir::intravisit::{NestedVisitorMap, Visitor}; use crate::hir::map::HirEntryMap; -use crate::hir::def_id::{LOCAL_CRATE, CrateNum}; -use crate::hir::intravisit::{Visitor, NestedVisitorMap}; -use rustc_data_structures::svh::Svh; -use rustc_index::vec::IndexVec; use crate::ich::Fingerprint; use crate::middle::cstore::CrateStore; use crate::session::CrateDisambiguator; use crate::session::Session; use crate::util::nodemap::FxHashMap; +use rustc_data_structures::svh::Svh; +use rustc_index::vec::IndexVec; +use std::iter::repeat; use syntax::ast::NodeId; use syntax::source_map::SourceMap; use syntax_pos::Span; -use std::iter::repeat; use crate::ich::StableHashingContext; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; @@ -82,11 +82,13 @@ fn alloc_hir_dep_nodes( where I: for<'a> HashStable>, { - let sig = dep_graph.input_task( - def_path_hash.to_dep_node(DepKind::Hir), - &mut *hcx, - HirItemLike { item_like: &item_like, hash_bodies: false }, - ).1; + let sig = dep_graph + .input_task( + def_path_hash.to_dep_node(DepKind::Hir), + &mut *hcx, + HirItemLike { item_like: &item_like, hash_bodies: false }, + ) + .1; let (full, hash) = input_dep_node_and_hash( dep_graph, hcx, @@ -98,13 +100,14 @@ where } impl<'a, 'hir> NodeCollector<'a, 'hir> { - pub(super) fn root(sess: &'a Session, - krate: &'hir Crate, - dep_graph: &'a DepGraph, - definitions: &'a definitions::Definitions, - hir_to_node_id: &'a FxHashMap, - mut hcx: StableHashingContext<'a>) - -> NodeCollector<'a, 'hir> { + pub(super) fn root( + sess: &'a Session, + krate: &'hir Crate, + dep_graph: &'a DepGraph, + definitions: &'a definitions::Definitions, + hir_to_node_id: &'a FxHashMap, + mut hcx: StableHashingContext<'a>, + ) -> NodeCollector<'a, 'hir> { let root_mod_def_path_hash = definitions.def_path_hash(CRATE_DEF_INDEX); let mut hir_body_nodes = Vec::new(); @@ -161,36 +164,43 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { hcx, hir_body_nodes, }; - collector.insert_entry(hir::CRATE_HIR_ID, Entry { - parent: hir::CRATE_HIR_ID, - dep_node: root_mod_sig_dep_index, - node: Node::Crate, - }); + collector.insert_entry( + hir::CRATE_HIR_ID, + Entry { + parent: hir::CRATE_HIR_ID, + dep_node: root_mod_sig_dep_index, + node: Node::Crate, + }, + ); collector } - pub(super) fn finalize_and_compute_crate_hash(mut self, - crate_disambiguator: CrateDisambiguator, - cstore: &dyn CrateStore, - commandline_args_hash: u64) - -> (HirEntryMap<'hir>, Svh) - { + pub(super) fn finalize_and_compute_crate_hash( + mut self, + crate_disambiguator: CrateDisambiguator, + cstore: &dyn CrateStore, + commandline_args_hash: u64, + ) -> (HirEntryMap<'hir>, Svh) { self.hir_body_nodes.sort_unstable_by_key(|bn| bn.0); - let node_hashes = self - .hir_body_nodes - .iter() - .fold(Fingerprint::ZERO, |combined_fingerprint, &(def_path_hash, fingerprint)| { + let node_hashes = self.hir_body_nodes.iter().fold( + Fingerprint::ZERO, + |combined_fingerprint, &(def_path_hash, fingerprint)| { combined_fingerprint.combine(def_path_hash.0.combine(fingerprint)) - }); + }, + ); - let mut upstream_crates: Vec<_> = cstore.crates_untracked().iter().map(|&cnum| { - let name = cstore.crate_name_untracked(cnum); - let disambiguator = cstore.crate_disambiguator_untracked(cnum).to_fingerprint(); - let hash = cstore.crate_hash_untracked(cnum); - (name, disambiguator, hash) - }).collect(); + let mut upstream_crates: Vec<_> = cstore + .crates_untracked() + .iter() + .map(|&cnum| { + let name = cstore.crate_name_untracked(cnum); + let disambiguator = cstore.crate_disambiguator_untracked(cnum).to_fingerprint(); + let hash = cstore.crate_hash_untracked(cnum); + (name, disambiguator, hash) + }) + .collect(); upstream_crates.sort_unstable_by_key(|&(name, dis, _)| (name.as_str(), dis)); @@ -211,7 +221,7 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { let crate_hash_input = ( ((node_hashes, upstream_crates), source_file_names), - (commandline_args_hash, crate_disambiguator.to_fingerprint()) + (commandline_args_hash, crate_disambiguator.to_fingerprint()), ); let (_, crate_hash) = input_dep_node_and_hash( @@ -255,10 +265,8 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { if hir_id.owner != self.current_dep_node_owner { let node_str = match self.definitions.opt_def_index(node_id) { - Some(def_index) => { - self.definitions.def_path(def_index).to_string_no_crate() - } - None => format!("{:?}", node) + Some(def_index) => self.definitions.def_path(def_index).to_string_no_crate(), + None => format!("{:?}", node), }; let forgot_str = if hir_id == crate::hir::DUMMY_HIR_ID { @@ -273,9 +281,7 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { current_dep_node_owner={} ({:?}), hir_id.owner={} ({:?}){}", self.source_map.span_to_string(span), node_str, - self.definitions - .def_path(self.current_dep_node_owner) - .to_string_no_crate(), + self.definitions.def_path(self.current_dep_node_owner).to_string_no_crate(), self.current_dep_node_owner, self.definitions.def_path(hir_id.owner).to_string_no_crate(), hir_id.owner, @@ -287,22 +293,22 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { self.insert_entry(hir_id, entry); } - fn with_parent( - &mut self, - parent_node_id: HirId, - f: F, - ) { + fn with_parent(&mut self, parent_node_id: HirId, f: F) { let parent_node = self.parent_node; self.parent_node = parent_node_id; f(self); self.parent_node = parent_node; } - fn with_dep_node_owner HashStable>, - F: FnOnce(&mut Self)>(&mut self, - dep_node_owner: DefIndex, - item_like: &T, - f: F) { + fn with_dep_node_owner< + T: for<'b> HashStable>, + F: FnOnce(&mut Self), + >( + &mut self, + dep_node_owner: DefIndex, + item_like: &T, + f: F, + ) { let prev_owner = self.current_dep_node_owner; let prev_signature_dep_index = self.current_signature_dep_index; let prev_full_dep_index = self.current_full_dep_index; @@ -369,8 +375,10 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { fn visit_item(&mut self, i: &'hir Item) { debug!("visit_item: {:?}", i); - debug_assert_eq!(i.hir_id.owner, - self.definitions.opt_def_index(self.hir_to_node_id[&i.hir_id]).unwrap()); + debug_assert_eq!( + i.hir_id.owner, + self.definitions.opt_def_index(self.hir_to_node_id[&i.hir_id]).unwrap() + ); self.with_dep_node_owner(i.hir_id.owner, i, |this| { this.insert(i.span, i.hir_id, Node::Item(i)); this.with_parent(i.hir_id, |this| { @@ -399,8 +407,10 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { } fn visit_trait_item(&mut self, ti: &'hir TraitItem) { - debug_assert_eq!(ti.hir_id.owner, - self.definitions.opt_def_index(self.hir_to_node_id[&ti.hir_id]).unwrap()); + debug_assert_eq!( + ti.hir_id.owner, + self.definitions.opt_def_index(self.hir_to_node_id[&ti.hir_id]).unwrap() + ); self.with_dep_node_owner(ti.hir_id.owner, ti, |this| { this.insert(ti.span, ti.hir_id, Node::TraitItem(ti)); @@ -411,8 +421,10 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { } fn visit_impl_item(&mut self, ii: &'hir ImplItem) { - debug_assert_eq!(ii.hir_id.owner, - self.definitions.opt_def_index(self.hir_to_node_id[&ii.hir_id]).unwrap()); + debug_assert_eq!( + ii.hir_id.owner, + self.definitions.opt_def_index(self.hir_to_node_id[&ii.hir_id]).unwrap() + ); self.with_dep_node_owner(ii.hir_id.owner, ii, |this| { this.insert(ii.span, ii.hir_id, Node::ImplItem(ii)); @@ -423,11 +435,8 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { } fn visit_pat(&mut self, pat: &'hir Pat) { - let node = if let PatKind::Binding(..) = pat.kind { - Node::Binding(pat) - } else { - Node::Pat(pat) - }; + let node = + if let PatKind::Binding(..) = pat.kind { Node::Binding(pat) } else { Node::Pat(pat) }; self.insert(pat.span, pat.hir_id, node); self.with_parent(pat.hir_id, |this| { @@ -492,8 +501,14 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { }); } - fn visit_fn(&mut self, fk: intravisit::FnKind<'hir>, fd: &'hir FnDecl, - b: BodyId, s: Span, id: HirId) { + fn visit_fn( + &mut self, + fk: intravisit::FnKind<'hir>, + fd: &'hir FnDecl, + b: BodyId, + s: Span, + id: HirId, + ) { assert_eq!(self.parent_node, id); intravisit::walk_fn(self, fk, fd, b, s, id); } @@ -507,9 +522,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { fn visit_local(&mut self, l: &'hir Local) { self.insert(l.span, l.hir_id, Node::Local(l)); - self.with_parent(l.hir_id, |this| { - intravisit::walk_local(this, l) - }) + self.with_parent(l.hir_id, |this| intravisit::walk_local(this, l)) } fn visit_lifetime(&mut self, lifetime: &'hir Lifetime) { @@ -518,9 +531,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { fn visit_vis(&mut self, visibility: &'hir Visibility) { match visibility.node { - VisibilityKind::Public | - VisibilityKind::Crate(_) | - VisibilityKind::Inherited => {} + VisibilityKind::Public | VisibilityKind::Crate(_) | VisibilityKind::Inherited => {} VisibilityKind::Restricted { hir_id, .. } => { self.insert(visibility.span, hir_id, Node::Visibility(visibility)); self.with_parent(hir_id, |this| { @@ -560,13 +571,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { fn visit_trait_item_ref(&mut self, ii: &'hir TraitItemRef) { // Do not visit the duplicate information in TraitItemRef. We want to // map the actual nodes, not the duplicate ones in the *Ref. - let TraitItemRef { - id, - ident: _, - kind: _, - span: _, - defaultness: _, - } = *ii; + let TraitItemRef { id, ident: _, kind: _, span: _, defaultness: _ } = *ii; self.visit_nested_trait_item(id); } @@ -574,14 +579,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { fn visit_impl_item_ref(&mut self, ii: &'hir ImplItemRef) { // Do not visit the duplicate information in ImplItemRef. We want to // map the actual nodes, not the duplicate ones in the *Ref. - let ImplItemRef { - id, - ident: _, - kind: _, - span: _, - vis: _, - defaultness: _, - } = *ii; + let ImplItemRef { id, ident: _, kind: _, span: _, vis: _, defaultness: _ } = *ii; self.visit_nested_impl_item(id); } diff --git a/src/librustc/hir/map/definitions.rs b/src/librustc/hir/map/definitions.rs index 91b4971cd92be..1ba0e993f0bce 100644 --- a/src/librustc/hir/map/definitions.rs +++ b/src/librustc/hir/map/definitions.rs @@ -5,20 +5,20 @@ //! expressions) that are mostly just leftovers. use crate::hir; -use crate::hir::def_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE, CRATE_DEF_INDEX}; +use crate::hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE}; use crate::ich::Fingerprint; use crate::session::CrateDisambiguator; use crate::util::nodemap::NodeMap; use rustc_data_structures::fx::FxHashMap; -use rustc_index::vec::{IndexVec}; use rustc_data_structures::stable_hasher::StableHasher; +use rustc_index::vec::IndexVec; use std::borrow::Borrow; use std::fmt::Write; use std::hash::Hash; use syntax::ast; -use syntax_pos::symbol::{Symbol, sym}; use syntax_pos::hygiene::ExpnId; +use syntax_pos::symbol::{sym, Symbol}; use syntax_pos::Span; /// The `DefPathTable` maps `DefIndex`es to `DefKey`s and vice versa. @@ -32,10 +32,7 @@ pub struct DefPathTable { } impl DefPathTable { - fn allocate(&mut self, - key: DefKey, - def_path_hash: DefPathHash) - -> DefIndex { + fn allocate(&mut self, key: DefKey, def_path_hash: DefPathHash) -> DefIndex { let index = { let index = DefIndex::from(self.index_to_key.len()); debug!("DefPathTable::insert() - {:?} <-> {:?}", key, index); @@ -63,21 +60,11 @@ impl DefPathTable { hash } - pub fn add_def_path_hashes_to(&self, - cnum: CrateNum, - out: &mut FxHashMap) { - out.extend( - self.def_path_hashes - .iter() - .enumerate() - .map(|(index, &hash)| { - let def_id = DefId { - krate: cnum, - index: DefIndex::from(index), - }; - (hash, def_id) - }) - ); + pub fn add_def_path_hashes_to(&self, cnum: CrateNum, out: &mut FxHashMap) { + out.extend(self.def_path_hashes.iter().enumerate().map(|(index, &hash)| { + let def_id = DefId { krate: cnum, index: DefIndex::from(index) }; + (hash, def_id) + })); } pub fn size(&self) -> usize { @@ -129,10 +116,7 @@ impl DefKey { 0u8.hash(&mut hasher); parent_hash.hash(&mut hasher); - let DisambiguatedDefPathData { - ref data, - disambiguator, - } = self.disambiguated_data; + let DisambiguatedDefPathData { ref data, disambiguator } = self.disambiguated_data; ::std::mem::discriminant(data).hash(&mut hasher); if let Some(name) = data.get_opt_name() { @@ -146,9 +130,10 @@ impl DefKey { DefPathHash(hasher.finish()) } - fn root_parent_stable_hash(crate_name: &str, - crate_disambiguator: CrateDisambiguator) - -> DefPathHash { + fn root_parent_stable_hash( + crate_name: &str, + crate_disambiguator: CrateDisambiguator, + ) -> DefPathHash { let mut hasher = StableHasher::new(); // Disambiguate this from a regular `DefPath` hash; see `compute_stable_hash()` above. 1u8.hash(&mut hasher); @@ -167,7 +152,7 @@ impl DefKey { #[derive(Copy, Clone, PartialEq, Debug, RustcEncodable, RustcDecodable)] pub struct DisambiguatedDefPathData { pub data: DefPathData, - pub disambiguator: u32 + pub disambiguator: u32, } #[derive(Clone, Debug, RustcEncodable, RustcDecodable)] @@ -184,10 +169,9 @@ impl DefPath { self.krate == LOCAL_CRATE } - pub fn make(krate: CrateNum, - start_index: DefIndex, - mut get_key: FN) -> DefPath - where FN: FnMut(DefIndex) -> DefKey + pub fn make(krate: CrateNum, start_index: DefIndex, mut get_key: FN) -> DefPath + where + FN: FnMut(DefIndex) -> DefKey, { let mut data = vec![]; let mut index = Some(start_index); @@ -218,11 +202,7 @@ impl DefPath { let mut s = String::with_capacity(self.data.len() * 16); for component in &self.data { - write!(s, - "::{}[{}]", - component.data.as_symbol(), - component.disambiguator) - .unwrap(); + write!(s, "::{}[{}]", component.data.as_symbol(), component.disambiguator).unwrap(); } s @@ -231,7 +211,8 @@ impl DefPath { /// Returns a filename-friendly string for the `DefPath`, with the /// crate-prefix. pub fn to_string_friendly(&self, crate_imported_name: F) -> String - where F: FnOnce(CrateNum) -> Symbol + where + F: FnOnce(CrateNum) -> Symbol, { let crate_name_str = crate_imported_name(self.krate).as_str(); let mut s = String::with_capacity(crate_name_str.len() + self.data.len() * 16); @@ -242,11 +223,7 @@ impl DefPath { if component.disambiguator == 0 { write!(s, "::{}", component.data.as_symbol()).unwrap(); } else { - write!(s, - "{}[{}]", - component.data.as_symbol(), - component.disambiguator) - .unwrap(); + write!(s, "{}[{}]", component.data.as_symbol(), component.disambiguator).unwrap(); } } @@ -266,11 +243,7 @@ impl DefPath { if component.disambiguator == 0 { write!(s, "{}", component.data.as_symbol()).unwrap(); } else { - write!(s, - "{}[{}]", - component.data.as_symbol(), - component.disambiguator) - .unwrap(); + write!(s, "{}[{}]", component.data.as_symbol(), component.disambiguator).unwrap(); } } s @@ -281,14 +254,12 @@ impl DefPath { pub enum DefPathData { // Root: these should only be used for the root nodes, because // they are treated specially by the `def_path` function. - /// The crate root (marker). CrateRoot, // Catch-all for random `DefId` things like `DUMMY_NODE_ID`. Misc, // Different kinds of items and item-like things: - /// An impl. Impl, /// Something in the type namespace. @@ -303,7 +274,6 @@ pub enum DefPathData { ClosureExpr, // Subportions of items: - /// Implicit constructor for a unit or tuple-like struct or enum variant. Ctor, /// A constant expression (see `{ast,hir}::AnonConst`). @@ -312,8 +282,19 @@ pub enum DefPathData { ImplTrait, } -#[derive(Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Debug, - RustcEncodable, RustcDecodable, HashStable)] +#[derive( + Copy, + Clone, + Hash, + PartialEq, + Eq, + PartialOrd, + Ord, + Debug, + RustcEncodable, + RustcDecodable, + HashStable, +)] pub struct DefPathHash(pub Fingerprint); impl Borrow for DefPathHash { @@ -381,11 +362,7 @@ impl Definitions { pub fn as_local_hir_id(&self, def_id: DefId) -> Option { if def_id.krate == LOCAL_CRATE { let hir_id = self.def_index_to_hir_id(def_id.index); - if hir_id != hir::DUMMY_HIR_ID { - Some(hir_id) - } else { - None - } + if hir_id != hir::DUMMY_HIR_ID { Some(hir_id) } else { None } } else { None } @@ -414,20 +391,20 @@ impl Definitions { } /// Adds a root definition (no parent) and a few other reserved definitions. - pub fn create_root_def(&mut self, - crate_name: &str, - crate_disambiguator: CrateDisambiguator) - -> DefIndex { + pub fn create_root_def( + &mut self, + crate_name: &str, + crate_disambiguator: CrateDisambiguator, + ) -> DefIndex { let key = DefKey { parent: None, disambiguated_data: DisambiguatedDefPathData { data: DefPathData::CrateRoot, - disambiguator: 0 - } + disambiguator: 0, + }, }; - let parent_hash = DefKey::root_parent_stable_hash(crate_name, - crate_disambiguator); + let parent_hash = DefKey::root_parent_stable_hash(crate_name, crate_disambiguator); let def_path_hash = key.compute_stable_hash(parent_hash); // Create the definition. @@ -442,21 +419,26 @@ impl Definitions { } /// Adds a definition with a parent definition. - pub fn create_def_with_parent(&mut self, - parent: DefIndex, - node_id: ast::NodeId, - data: DefPathData, - expn_id: ExpnId, - span: Span) - -> DefIndex { - debug!("create_def_with_parent(parent={:?}, node_id={:?}, data={:?})", - parent, node_id, data); - - assert!(!self.node_to_def_index.contains_key(&node_id), - "adding a def'n for node-id {:?} and data {:?} but a previous def'n exists: {:?}", - node_id, - data, - self.table.def_key(self.node_to_def_index[&node_id])); + pub fn create_def_with_parent( + &mut self, + parent: DefIndex, + node_id: ast::NodeId, + data: DefPathData, + expn_id: ExpnId, + span: Span, + ) -> DefIndex { + debug!( + "create_def_with_parent(parent={:?}, node_id={:?}, data={:?})", + parent, node_id, data + ); + + assert!( + !self.node_to_def_index.contains_key(&node_id), + "adding a def'n for node-id {:?} and data {:?} but a previous def'n exists: {:?}", + node_id, + data, + self.table.def_key(self.node_to_def_index[&node_id]) + ); // The root node must be created with `create_root_def()`. assert!(data != DefPathData::CrateRoot); @@ -471,9 +453,7 @@ impl Definitions { let key = DefKey { parent: Some(parent), - disambiguated_data: DisambiguatedDefPathData { - data, disambiguator - } + disambiguated_data: DisambiguatedDefPathData { data, disambiguator }, }; let parent_hash = self.table.def_path_hash(parent); @@ -508,10 +488,11 @@ impl Definitions { /// Initializes the `ast::NodeId` to `HirId` mapping once it has been generated during /// AST to HIR lowering. - pub fn init_node_id_to_hir_id_mapping(&mut self, - mapping: IndexVec) { - assert!(self.node_to_hir_id.is_empty(), - "trying to initialize `NodeId` -> `HirId` mapping twice"); + pub fn init_node_id_to_hir_id_mapping(&mut self, mapping: IndexVec) { + assert!( + self.node_to_hir_id.is_empty(), + "trying to initialize `NodeId` -> `HirId` mapping twice" + ); self.node_to_hir_id = mapping; } @@ -550,30 +531,16 @@ impl DefPathData { pub fn get_opt_name(&self) -> Option { use self::DefPathData::*; match *self { - TypeNs(name) | - ValueNs(name) | - MacroNs(name) | - LifetimeNs(name) => Some(name), - - Impl | - CrateRoot | - Misc | - ClosureExpr | - Ctor | - AnonConst | - ImplTrait => None + TypeNs(name) | ValueNs(name) | MacroNs(name) | LifetimeNs(name) => Some(name), + + Impl | CrateRoot | Misc | ClosureExpr | Ctor | AnonConst | ImplTrait => None, } } pub fn as_symbol(&self) -> Symbol { use self::DefPathData::*; match *self { - TypeNs(name) | - ValueNs(name) | - MacroNs(name) | - LifetimeNs(name) => { - name - } + TypeNs(name) | ValueNs(name) | MacroNs(name) | LifetimeNs(name) => name, // Note that this does not show up in user print-outs. CrateRoot => sym::double_braced_crate, Impl => sym::double_braced_impl, diff --git a/src/librustc/hir/map/hir_id_validator.rs b/src/librustc/hir/map/hir_id_validator.rs index b66c2ce1178a4..78889bf5543ff 100644 --- a/src/librustc/hir/map/hir_id_validator.rs +++ b/src/librustc/hir/map/hir_id_validator.rs @@ -1,8 +1,8 @@ use crate::hir::def_id::{DefId, DefIndex, CRATE_DEF_INDEX}; -use crate::hir::{self, intravisit, HirId, ItemLocalId}; use crate::hir::itemlikevisit::ItemLikeVisitor; +use crate::hir::{self, intravisit, HirId, ItemLocalId}; use rustc_data_structures::fx::FxHashSet; -use rustc_data_structures::sync::{Lock, ParallelIterator, par_iter}; +use rustc_data_structures::sync::{par_iter, Lock, ParallelIterator}; pub fn check_crate(hir_map: &hir::map::Map<'_>) { hir_map.dep_graph.assert_ignored(); @@ -11,18 +11,16 @@ pub fn check_crate(hir_map: &hir::map::Map<'_>) { par_iter(&hir_map.krate().modules).for_each(|(module_id, _)| { let local_def_id = hir_map.local_def_id(*module_id); - hir_map.visit_item_likes_in_module(local_def_id, &mut OuterVisitor { - hir_map, - errors: &errors, - }); + hir_map.visit_item_likes_in_module( + local_def_id, + &mut OuterVisitor { hir_map, errors: &errors }, + ); }); let errors = errors.into_inner(); if !errors.is_empty() { - let message = errors - .iter() - .fold(String::new(), |s1, s2| s1 + "\n" + s2); + let message = errors.iter().fold(String::new(), |s1, s2| s1 + "\n" + s2); bug!("{}", message); } } @@ -40,9 +38,7 @@ struct OuterVisitor<'a, 'hir> { } impl<'a, 'hir> OuterVisitor<'a, 'hir> { - fn new_inner_visitor(&self, - hir_map: &'a hir::map::Map<'hir>) - -> HirIdValidator<'a, 'hir> { + fn new_inner_visitor(&self, hir_map: &'a hir::map::Map<'hir>) -> HirIdValidator<'a, 'hir> { HirIdValidator { hir_map, owner_def_index: None, @@ -76,9 +72,7 @@ impl<'a, 'hir> HirIdValidator<'a, 'hir> { self.errors.lock().push(f()); } - fn check)>(&mut self, - hir_id: HirId, - walk: F) { + fn check)>(&mut self, hir_id: HirId, walk: F) { assert!(self.owner_def_index.is_none()); let owner_def_index = self.hir_map.local_def_id(hir_id).index; self.owner_def_index = Some(owner_def_index); @@ -89,55 +83,54 @@ impl<'a, 'hir> HirIdValidator<'a, 'hir> { } // There's always at least one entry for the owning item itself - let max = self.hir_ids_seen - .iter() - .map(|local_id| local_id.as_usize()) - .max() - .expect("owning item has no entry"); + let max = self + .hir_ids_seen + .iter() + .map(|local_id| local_id.as_usize()) + .max() + .expect("owning item has no entry"); if max != self.hir_ids_seen.len() - 1 { // Collect the missing ItemLocalIds - let missing: Vec<_> = (0 ..= max as u32) - .filter(|&i| !self.hir_ids_seen.contains(&ItemLocalId::from_u32(i))) - .collect(); + let missing: Vec<_> = (0..=max as u32) + .filter(|&i| !self.hir_ids_seen.contains(&ItemLocalId::from_u32(i))) + .collect(); // Try to map those to something more useful let mut missing_items = Vec::with_capacity(missing.len()); for local_id in missing { - let hir_id = HirId { - owner: owner_def_index, - local_id: ItemLocalId::from_u32(local_id), - }; + let hir_id = + HirId { owner: owner_def_index, local_id: ItemLocalId::from_u32(local_id) }; trace!("missing hir id {:#?}", hir_id); - missing_items.push(format!("[local_id: {}, node:{}]", - local_id, - self.hir_map.node_to_string(hir_id))); + missing_items.push(format!( + "[local_id: {}, node:{}]", + local_id, + self.hir_map.node_to_string(hir_id) + )); } - self.error(|| format!( - "ItemLocalIds not assigned densely in {}. \ + self.error(|| { + format!( + "ItemLocalIds not assigned densely in {}. \ Max ItemLocalId = {}, missing IDs = {:?}; seens IDs = {:?}", - self.hir_map.def_path(DefId::local(owner_def_index)).to_string_no_crate(), - max, - missing_items, - self.hir_ids_seen - .iter() - .map(|&local_id| HirId { - owner: owner_def_index, - local_id, - }) - .map(|h| format!("({:?} {})", h, self.hir_map.node_to_string(h))) - .collect::>())); + self.hir_map.def_path(DefId::local(owner_def_index)).to_string_no_crate(), + max, + missing_items, + self.hir_ids_seen + .iter() + .map(|&local_id| HirId { owner: owner_def_index, local_id }) + .map(|h| format!("({:?} {})", h, self.hir_map.node_to_string(h))) + .collect::>() + ) + }); } } } impl<'a, 'hir> intravisit::Visitor<'hir> for HirIdValidator<'a, 'hir> { - - fn nested_visit_map<'this>(&'this mut self) - -> intravisit::NestedVisitorMap<'this, 'hir> { + fn nested_visit_map<'this>(&'this mut self) -> intravisit::NestedVisitorMap<'this, 'hir> { intravisit::NestedVisitorMap::OnlyBodies(self.hir_map) } @@ -145,17 +138,24 @@ impl<'a, 'hir> intravisit::Visitor<'hir> for HirIdValidator<'a, 'hir> { let owner = self.owner_def_index.expect("no owner_def_index"); if hir_id == hir::DUMMY_HIR_ID { - self.error(|| format!("HirIdValidator: HirId {:?} is invalid", - self.hir_map.node_to_string(hir_id))); + self.error(|| { + format!( + "HirIdValidator: HirId {:?} is invalid", + self.hir_map.node_to_string(hir_id) + ) + }); return; } if owner != hir_id.owner { - self.error(|| format!( - "HirIdValidator: The recorded owner of {} is {} instead of {}", - self.hir_map.node_to_string(hir_id), - self.hir_map.def_path(DefId::local(hir_id.owner)).to_string_no_crate(), - self.hir_map.def_path(DefId::local(owner)).to_string_no_crate())); + self.error(|| { + format!( + "HirIdValidator: The recorded owner of {} is {} instead of {}", + self.hir_map.node_to_string(hir_id), + self.hir_map.def_path(DefId::local(hir_id.owner)).to_string_no_crate(), + self.hir_map.def_path(DefId::local(owner)).to_string_no_crate() + ) + }); } self.hir_ids_seen.insert(hir_id.local_id); diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index 69e772697f846..7cfdfb9e4f528 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -1,22 +1,22 @@ use self::collector::NodeCollector; pub use self::definitions::{ - Definitions, DefKey, DefPath, DefPathData, DisambiguatedDefPathData, DefPathHash + DefKey, DefPath, DefPathData, DefPathHash, Definitions, DisambiguatedDefPathData, }; -use crate::dep_graph::{DepGraph, DepNode, DepKind, DepNodeIndex}; -use crate::hir::*; -use crate::hir::DefKind; -use crate::hir::def_id::{CRATE_DEF_INDEX, DefId, LocalDefId}; +use crate::dep_graph::{DepGraph, DepKind, DepNode, DepNodeIndex}; +use crate::hir::def_id::{DefId, LocalDefId, CRATE_DEF_INDEX}; use crate::hir::itemlikevisit::ItemLikeVisitor; use crate::hir::print::Nested; +use crate::hir::DefKind; +use crate::hir::*; use crate::middle::cstore::CrateStoreDyn; use crate::ty::query::Providers; -use crate::util::nodemap::FxHashMap; use crate::util::common::time; +use crate::util::nodemap::FxHashMap; -use rustc_target::spec::abi::Abi; use rustc_data_structures::svh::Svh; use rustc_index::vec::IndexVec; +use rustc_target::spec::abi::Abi; use syntax::ast::{self, Name, NodeId}; use syntax::source_map::Spanned; use syntax_pos::hygiene::MacroKind; @@ -45,33 +45,25 @@ impl<'hir> Entry<'hir> { fn fn_decl(&self) -> Option<&'hir FnDecl> { match self.node { - Node::Item(ref item) => { - match item.kind { - ItemKind::Fn(ref sig, _, _) => Some(&sig.decl), - _ => None, - } - } + Node::Item(ref item) => match item.kind { + ItemKind::Fn(ref sig, _, _) => Some(&sig.decl), + _ => None, + }, - Node::TraitItem(ref item) => { - match item.kind { - TraitItemKind::Method(ref sig, _) => Some(&sig.decl), - _ => None - } - } + Node::TraitItem(ref item) => match item.kind { + TraitItemKind::Method(ref sig, _) => Some(&sig.decl), + _ => None, + }, - Node::ImplItem(ref item) => { - match item.kind { - ImplItemKind::Method(ref sig, _) => Some(&sig.decl), - _ => None, - } - } + Node::ImplItem(ref item) => match item.kind { + ImplItemKind::Method(ref sig, _) => Some(&sig.decl), + _ => None, + }, - Node::Expr(ref expr) => { - match expr.kind { - ExprKind::Closure(_, ref fn_decl, ..) => Some(fn_decl), - _ => None, - } - } + Node::Expr(ref expr) => match expr.kind { + ExprKind::Closure(_, ref fn_decl, ..) => Some(fn_decl), + _ => None, + }, _ => None, } @@ -79,26 +71,20 @@ impl<'hir> Entry<'hir> { fn fn_sig(&self) -> Option<&'hir FnSig> { match &self.node { - Node::Item(item) => { - match &item.kind { - ItemKind::Fn(sig, _, _) => Some(sig), - _ => None, - } - } + Node::Item(item) => match &item.kind { + ItemKind::Fn(sig, _, _) => Some(sig), + _ => None, + }, - Node::TraitItem(item) => { - match &item.kind { - TraitItemKind::Method(sig, _) => Some(sig), - _ => None - } - } + Node::TraitItem(item) => match &item.kind { + TraitItemKind::Method(sig, _) => Some(sig), + _ => None, + }, - Node::ImplItem(item) => { - match &item.kind { - ImplItemKind::Method(sig, _) => Some(sig), - _ => None, - } - } + Node::ImplItem(item) => match &item.kind { + ImplItemKind::Method(sig, _) => Some(sig), + _ => None, + }, _ => None, } @@ -106,41 +92,32 @@ impl<'hir> Entry<'hir> { fn associated_body(self) -> Option { match self.node { - Node::Item(item) => { - match item.kind { - ItemKind::Const(_, body) | - ItemKind::Static(.., body) | - ItemKind::Fn(.., body) => Some(body), - _ => None, + Node::Item(item) => match item.kind { + ItemKind::Const(_, body) | ItemKind::Static(.., body) | ItemKind::Fn(.., body) => { + Some(body) } - } + _ => None, + }, - Node::TraitItem(item) => { - match item.kind { - TraitItemKind::Const(_, Some(body)) | - TraitItemKind::Method(_, TraitMethod::Provided(body)) => Some(body), - _ => None - } - } + Node::TraitItem(item) => match item.kind { + TraitItemKind::Const(_, Some(body)) + | TraitItemKind::Method(_, TraitMethod::Provided(body)) => Some(body), + _ => None, + }, - Node::ImplItem(item) => { - match item.kind { - ImplItemKind::Const(_, body) | - ImplItemKind::Method(_, body) => Some(body), - _ => None, - } - } + Node::ImplItem(item) => match item.kind { + ImplItemKind::Const(_, body) | ImplItemKind::Method(_, body) => Some(body), + _ => None, + }, Node::AnonConst(constant) => Some(constant.body), - Node::Expr(expr) => { - match expr.kind { - ExprKind::Closure(.., body, _, _) => Some(body), - _ => None, - } - } + Node::Expr(expr) => match expr.kind { + ExprKind::Closure(.., body, _, _) => Some(body), + _ => None, + }, - _ => None + _ => None, } } @@ -160,10 +137,7 @@ pub struct Forest { impl Forest { pub fn new(krate: Crate, dep_graph: &DepGraph) -> Forest { - Forest { - krate, - dep_graph: dep_graph.clone(), - } + Forest { krate, dep_graph: dep_graph.clone() } } pub fn krate(&self) -> &Crate { @@ -213,10 +187,7 @@ struct ParentHirIterator<'map> { impl<'map> ParentHirIterator<'map> { fn new(current_id: HirId, map: &'map Map<'map>) -> ParentHirIterator<'map> { - ParentHirIterator { - current_id, - map, - } + ParentHirIterator { current_id, map } } } @@ -227,7 +198,8 @@ impl<'map> Iterator for ParentHirIterator<'map> { if self.current_id == CRATE_HIR_ID { return None; } - loop { // There are nodes that do not have entries, so we need to skip them. + loop { + // There are nodes that do not have entries, so we need to skip them. let parent_id = self.map.get_parent_node(self.current_id); if parent_id == self.current_id { @@ -277,9 +249,7 @@ impl<'hir> Map<'hir> { } pub fn def_path_from_hir_id(&self, id: HirId) -> Option { - self.opt_local_def_id(id).map(|def_id| { - self.def_path(def_id) - }) + self.opt_local_def_id(id).map(|def_id| self.def_path(def_id)) } pub fn def_path(&self, def_id: DefId) -> DefPath { @@ -291,16 +261,22 @@ impl<'hir> Map<'hir> { pub fn local_def_id_from_node_id(&self, node: NodeId) -> DefId { self.opt_local_def_id_from_node_id(node).unwrap_or_else(|| { let hir_id = self.node_to_hir_id(node); - bug!("local_def_id_from_node_id: no entry for `{}`, which has a map of `{:?}`", - node, self.find_entry(hir_id)) + bug!( + "local_def_id_from_node_id: no entry for `{}`, which has a map of `{:?}`", + node, + self.find_entry(hir_id) + ) }) } #[inline] pub fn local_def_id(&self, hir_id: HirId) -> DefId { self.opt_local_def_id(hir_id).unwrap_or_else(|| { - bug!("local_def_id: no entry for `{:?}`, which has a map of `{:?}`", - hir_id, self.find_entry(hir_id)) + bug!( + "local_def_id: no entry for `{:?}`, which has a map of `{:?}`", + hir_id, + self.find_entry(hir_id) + ) }) } @@ -346,55 +322,43 @@ impl<'hir> Map<'hir> { } pub fn def_kind(&self, hir_id: HirId) -> Option { - let node = if let Some(node) = self.find(hir_id) { - node - } else { - return None - }; + let node = if let Some(node) = self.find(hir_id) { node } else { return None }; Some(match node { - Node::Item(item) => { - match item.kind { - ItemKind::Static(..) => DefKind::Static, - ItemKind::Const(..) => DefKind::Const, - ItemKind::Fn(..) => DefKind::Fn, - ItemKind::Mod(..) => DefKind::Mod, - ItemKind::OpaqueTy(..) => DefKind::OpaqueTy, - ItemKind::TyAlias(..) => DefKind::TyAlias, - ItemKind::Enum(..) => DefKind::Enum, - ItemKind::Struct(..) => DefKind::Struct, - ItemKind::Union(..) => DefKind::Union, - ItemKind::Trait(..) => DefKind::Trait, - ItemKind::TraitAlias(..) => DefKind::TraitAlias, - ItemKind::ExternCrate(_) | - ItemKind::Use(..) | - ItemKind::ForeignMod(..) | - ItemKind::GlobalAsm(..) | - ItemKind::Impl(..) => return None, - } - } - Node::ForeignItem(item) => { - match item.kind { - ForeignItemKind::Fn(..) => DefKind::Fn, - ForeignItemKind::Static(..) => DefKind::Static, - ForeignItemKind::Type => DefKind::ForeignTy, - } - } - Node::TraitItem(item) => { - match item.kind { - TraitItemKind::Const(..) => DefKind::AssocConst, - TraitItemKind::Method(..) => DefKind::Method, - TraitItemKind::Type(..) => DefKind::AssocTy, - } - } - Node::ImplItem(item) => { - match item.kind { - ImplItemKind::Const(..) => DefKind::AssocConst, - ImplItemKind::Method(..) => DefKind::Method, - ImplItemKind::TyAlias(..) => DefKind::AssocTy, - ImplItemKind::OpaqueTy(..) => DefKind::AssocOpaqueTy, - } - } + Node::Item(item) => match item.kind { + ItemKind::Static(..) => DefKind::Static, + ItemKind::Const(..) => DefKind::Const, + ItemKind::Fn(..) => DefKind::Fn, + ItemKind::Mod(..) => DefKind::Mod, + ItemKind::OpaqueTy(..) => DefKind::OpaqueTy, + ItemKind::TyAlias(..) => DefKind::TyAlias, + ItemKind::Enum(..) => DefKind::Enum, + ItemKind::Struct(..) => DefKind::Struct, + ItemKind::Union(..) => DefKind::Union, + ItemKind::Trait(..) => DefKind::Trait, + ItemKind::TraitAlias(..) => DefKind::TraitAlias, + ItemKind::ExternCrate(_) + | ItemKind::Use(..) + | ItemKind::ForeignMod(..) + | ItemKind::GlobalAsm(..) + | ItemKind::Impl(..) => return None, + }, + Node::ForeignItem(item) => match item.kind { + ForeignItemKind::Fn(..) => DefKind::Fn, + ForeignItemKind::Static(..) => DefKind::Static, + ForeignItemKind::Type => DefKind::ForeignTy, + }, + Node::TraitItem(item) => match item.kind { + TraitItemKind::Const(..) => DefKind::AssocConst, + TraitItemKind::Method(..) => DefKind::Method, + TraitItemKind::Type(..) => DefKind::AssocTy, + }, + Node::ImplItem(item) => match item.kind { + ImplItemKind::Const(..) => DefKind::AssocConst, + ImplItemKind::Method(..) => DefKind::Method, + ImplItemKind::TyAlias(..) => DefKind::AssocTy, + ImplItemKind::OpaqueTy(..) => DefKind::AssocOpaqueTy, + }, Node::Variant(_) => DefKind::Variant, Node::Ctor(variant_data) => { // FIXME(eddyb) is this even possible, if we have a `Node::Ctor`? @@ -408,30 +372,28 @@ impl<'hir> Map<'hir> { }; DefKind::Ctor(ctor_of, def::CtorKind::from_hir(variant_data)) } - Node::AnonConst(_) | - Node::Field(_) | - Node::Expr(_) | - Node::Stmt(_) | - Node::PathSegment(_) | - Node::Ty(_) | - Node::TraitRef(_) | - Node::Pat(_) | - Node::Binding(_) | - Node::Local(_) | - Node::Param(_) | - Node::Arm(_) | - Node::Lifetime(_) | - Node::Visibility(_) | - Node::Block(_) | - Node::Crate => return None, + Node::AnonConst(_) + | Node::Field(_) + | Node::Expr(_) + | Node::Stmt(_) + | Node::PathSegment(_) + | Node::Ty(_) + | Node::TraitRef(_) + | Node::Pat(_) + | Node::Binding(_) + | Node::Local(_) + | Node::Param(_) + | Node::Arm(_) + | Node::Lifetime(_) + | Node::Visibility(_) + | Node::Block(_) + | Node::Crate => return None, Node::MacroDef(_) => DefKind::Macro(MacroKind::Bang), - Node::GenericParam(param) => { - match param.kind { - GenericParamKind::Lifetime { .. } => return None, - GenericParamKind::Type { .. } => DefKind::TyParam, - GenericParamKind::Const { .. } => DefKind::ConstParam, - } - } + Node::GenericParam(param) => match param.kind { + GenericParamKind::Lifetime { .. } => return None, + GenericParamKind::Type { .. } => DefKind::TyParam, + GenericParamKind::Const { .. } => DefKind::ConstParam, + }, }) } @@ -515,48 +477,43 @@ impl<'hir> Map<'hir> { /// Given a body owner's id, returns the `BodyId` associated with it. pub fn body_owned_by(&self, id: HirId) -> BodyId { self.maybe_body_owned_by(id).unwrap_or_else(|| { - span_bug!(self.span(id), "body_owned_by: {} has no associated body", - self.node_to_string(id)); + span_bug!( + self.span(id), + "body_owned_by: {} has no associated body", + self.node_to_string(id) + ); }) } pub fn body_owner_kind(&self, id: HirId) -> BodyOwnerKind { match self.get(id) { - Node::Item(&Item { kind: ItemKind::Const(..), .. }) | - Node::TraitItem(&TraitItem { kind: TraitItemKind::Const(..), .. }) | - Node::ImplItem(&ImplItem { kind: ImplItemKind::Const(..), .. }) | - Node::AnonConst(_) => { - BodyOwnerKind::Const - } - Node::Ctor(..) | - Node::Item(&Item { kind: ItemKind::Fn(..), .. }) | - Node::TraitItem(&TraitItem { kind: TraitItemKind::Method(..), .. }) | - Node::ImplItem(&ImplItem { kind: ImplItemKind::Method(..), .. }) => { - BodyOwnerKind::Fn - } - Node::Item(&Item { kind: ItemKind::Static(_, m, _), .. }) => { - BodyOwnerKind::Static(m) - } - Node::Expr(&Expr { kind: ExprKind::Closure(..), .. }) => { - BodyOwnerKind::Closure - } + Node::Item(&Item { kind: ItemKind::Const(..), .. }) + | Node::TraitItem(&TraitItem { kind: TraitItemKind::Const(..), .. }) + | Node::ImplItem(&ImplItem { kind: ImplItemKind::Const(..), .. }) + | Node::AnonConst(_) => BodyOwnerKind::Const, + Node::Ctor(..) + | Node::Item(&Item { kind: ItemKind::Fn(..), .. }) + | Node::TraitItem(&TraitItem { kind: TraitItemKind::Method(..), .. }) + | Node::ImplItem(&ImplItem { kind: ImplItemKind::Method(..), .. }) => BodyOwnerKind::Fn, + Node::Item(&Item { kind: ItemKind::Static(_, m, _), .. }) => BodyOwnerKind::Static(m), + Node::Expr(&Expr { kind: ExprKind::Closure(..), .. }) => BodyOwnerKind::Closure, node => bug!("{:#?} is not a body node", node), } } pub fn ty_param_owner(&self, id: HirId) -> HirId { match self.get(id) { - Node::Item(&Item { kind: ItemKind::Trait(..), .. }) | - Node::Item(&Item { kind: ItemKind::TraitAlias(..), .. }) => id, + Node::Item(&Item { kind: ItemKind::Trait(..), .. }) + | Node::Item(&Item { kind: ItemKind::TraitAlias(..), .. }) => id, Node::GenericParam(_) => self.get_parent_node(id), - _ => bug!("ty_param_owner: {} not a type parameter", self.node_to_string(id)) + _ => bug!("ty_param_owner: {} not a type parameter", self.node_to_string(id)), } } pub fn ty_param_name(&self, id: HirId) -> Name { match self.get(id) { - Node::Item(&Item { kind: ItemKind::Trait(..), .. }) | - Node::Item(&Item { kind: ItemKind::TraitAlias(..), .. }) => kw::SelfUpper, + Node::Item(&Item { kind: ItemKind::Trait(..), .. }) + | Node::Item(&Item { kind: ItemKind::TraitAlias(..), .. }) => kw::SelfUpper, Node::GenericParam(param) => param.name.ident().name, _ => bug!("ty_param_name: {} not a type parameter", self.node_to_string(id)), } @@ -584,18 +541,15 @@ impl<'hir> Map<'hir> { let hir_id = self.as_local_hir_id(module).unwrap(); self.read(hir_id); match self.find_entry(hir_id).unwrap().node { - Node::Item(&Item { - span, - kind: ItemKind::Mod(ref m), - .. - }) => (m, span, hir_id), + Node::Item(&Item { span, kind: ItemKind::Mod(ref m), .. }) => (m, span, hir_id), Node::Crate => (&self.forest.krate.module, self.forest.krate.span, hir_id), node => panic!("not a module: {:?}", node), } } pub fn visit_item_likes_in_module(&self, module: DefId, visitor: &mut V) - where V: ItemLikeVisitor<'hir> + where + V: ItemLikeVisitor<'hir>, { let hir_id = self.as_local_hir_id(module).unwrap(); @@ -623,8 +577,7 @@ impl<'hir> Map<'hir> { /// Retrieves the `Node` corresponding to `id`, panicking if it cannot be found. pub fn get(&self, id: HirId) -> Node<'hir> { // read recorded by `find` - self.find(id).unwrap_or_else(|| - bug!("couldn't find hir id {} in the HIR map", id)) + self.find(id).unwrap_or_else(|| bug!("couldn't find hir id {} in the HIR map", id)) } pub fn get_if_local(&self, id: DefId) -> Option> { @@ -632,37 +585,29 @@ impl<'hir> Map<'hir> { } pub fn get_generics(&self, id: DefId) -> Option<&'hir Generics> { - self.get_if_local(id).and_then(|node| { - match node { - Node::ImplItem(ref impl_item) => Some(&impl_item.generics), - Node::TraitItem(ref trait_item) => Some(&trait_item.generics), - Node::Item(ref item) => { - match item.kind { - ItemKind::Fn(_, ref generics, _) | - ItemKind::TyAlias(_, ref generics) | - ItemKind::Enum(_, ref generics) | - ItemKind::Struct(_, ref generics) | - ItemKind::Union(_, ref generics) | - ItemKind::Trait(_, _, ref generics, ..) | - ItemKind::TraitAlias(ref generics, _) | - ItemKind::Impl(_, _, _, ref generics, ..) => Some(generics), - _ => None, - } - } + self.get_if_local(id).and_then(|node| match node { + Node::ImplItem(ref impl_item) => Some(&impl_item.generics), + Node::TraitItem(ref trait_item) => Some(&trait_item.generics), + Node::Item(ref item) => match item.kind { + ItemKind::Fn(_, ref generics, _) + | ItemKind::TyAlias(_, ref generics) + | ItemKind::Enum(_, ref generics) + | ItemKind::Struct(_, ref generics) + | ItemKind::Union(_, ref generics) + | ItemKind::Trait(_, _, ref generics, ..) + | ItemKind::TraitAlias(ref generics, _) + | ItemKind::Impl(_, _, _, ref generics, ..) => Some(generics), _ => None, - } + }, + _ => None, }) } /// Retrieves the `Node` corresponding to `id`, returning `None` if cannot be found. pub fn find(&self, hir_id: HirId) -> Option> { - let result = self.find_entry(hir_id).and_then(|entry| { - if let Node::Crate = entry.node { - None - } else { - Some(entry.node) - } - }); + let result = self + .find_entry(hir_id) + .and_then(|entry| if let Node::Crate = entry.node { None } else { Some(entry.node) }); if result.is_some() { self.read(hir_id); } @@ -686,9 +631,7 @@ impl<'hir> Map<'hir> { self.dep_graph.read(def_path_hash.to_dep_node(DepKind::HirBody)); } - self.find_entry(hir_id) - .and_then(|x| x.parent_node()) - .unwrap_or(hir_id) + self.find_entry(hir_id).and_then(|x| x.parent_node()).unwrap_or(hir_id) } /// Checks if the node is an argument. An argument is a local variable whose @@ -699,15 +642,11 @@ impl<'hir> Map<'hir> { _ => return false, } match self.find(self.get_parent_node(id)) { - Some(Node::Item(_)) | - Some(Node::TraitItem(_)) | - Some(Node::ImplItem(_)) => true, - Some(Node::Expr(e)) => { - match e.kind { - ExprKind::Closure(..) => true, - _ => false, - } - } + Some(Node::Item(_)) | Some(Node::TraitItem(_)) | Some(Node::ImplItem(_)) => true, + Some(Node::Expr(e)) => match e.kind { + ExprKind::Closure(..) => true, + _ => false, + }, _ => false, } } @@ -717,27 +656,14 @@ impl<'hir> Map<'hir> { pub fn is_const_context(&self, hir_id: HirId) -> bool { let parent_id = self.get_parent_item(hir_id); match self.get(parent_id) { - Node::Item(&Item { - kind: ItemKind::Const(..), - .. - }) - | Node::TraitItem(&TraitItem { - kind: TraitItemKind::Const(..), - .. - }) - | Node::ImplItem(&ImplItem { - kind: ImplItemKind::Const(..), - .. - }) + Node::Item(&Item { kind: ItemKind::Const(..), .. }) + | Node::TraitItem(&TraitItem { kind: TraitItemKind::Const(..), .. }) + | Node::ImplItem(&ImplItem { kind: ImplItemKind::Const(..), .. }) | Node::AnonConst(_) - | Node::Item(&Item { - kind: ItemKind::Static(..), - .. - }) => true, - Node::Item(&Item { - kind: ItemKind::Fn(ref sig, ..), - .. - }) => sig.header.constness == Constness::Const, + | Node::Item(&Item { kind: ItemKind::Static(..), .. }) => true, + Node::Item(&Item { kind: ItemKind::Fn(ref sig, ..), .. }) => { + sig.header.constness == Constness::Const + } _ => false, } } @@ -745,8 +671,8 @@ impl<'hir> Map<'hir> { /// Wether `hir_id` corresponds to a `mod` or a crate. pub fn is_hir_id_module(&self, hir_id: HirId) -> bool { match self.lookup(hir_id) { - Some(Entry { node: Node::Item(Item { kind: ItemKind::Mod(_), .. }), .. }) | - Some(Entry { node: Node::Crate, .. }) => true, + Some(Entry { node: Node::Item(Item { kind: ItemKind::Mod(_), .. }), .. }) + | Some(Entry { node: Node::Crate, .. }) => true, _ => false, } } @@ -797,11 +723,11 @@ impl<'hir> Map<'hir> { } } match node { - Node::Item(_) | - Node::ForeignItem(_) | - Node::TraitItem(_) | - Node::Expr(Expr { kind: ExprKind::Closure(..), ..}) | - Node::ImplItem(_) => return Some(hir_id), + Node::Item(_) + | Node::ForeignItem(_) + | Node::TraitItem(_) + | Node::Expr(Expr { kind: ExprKind::Closure(..), .. }) + | Node::ImplItem(_) => return Some(hir_id), Node::Expr(ref expr) => { match expr.kind { // Ignore `return`s on the first iteration @@ -823,11 +749,11 @@ impl<'hir> Map<'hir> { pub fn get_parent_item(&self, hir_id: HirId) -> HirId { for (hir_id, node) in ParentHirIterator::new(hir_id, &self) { match node { - Node::Crate | - Node::Item(_) | - Node::ForeignItem(_) | - Node::TraitItem(_) | - Node::ImplItem(_) => return hir_id, + Node::Crate + | Node::Item(_) + | Node::ForeignItem(_) + | Node::TraitItem(_) + | Node::ImplItem(_) => return hir_id, _ => {} } } @@ -859,10 +785,9 @@ impl<'hir> Map<'hir> { pub fn get_match_if_cause(&self, hir_id: HirId) -> Option<&Expr> { for (_, node) in ParentHirIterator::new(hir_id, &self) { match node { - Node::Item(_) | - Node::ForeignItem(_) | - Node::TraitItem(_) | - Node::ImplItem(_) => break, + Node::Item(_) | Node::ForeignItem(_) | Node::TraitItem(_) | Node::ImplItem(_) => { + break; + } Node::Expr(expr) => match expr.kind { ExprKind::Match(_, _, _) => return Some(expr), _ => {} @@ -870,7 +795,7 @@ impl<'hir> Map<'hir> { Node::Stmt(stmt) => match stmt.kind { StmtKind::Local(_) => break, _ => {} - } + }, _ => {} } } @@ -881,35 +806,27 @@ impl<'hir> Map<'hir> { pub fn get_enclosing_scope(&self, hir_id: HirId) -> Option { for (hir_id, node) in ParentHirIterator::new(hir_id, &self) { if match node { - Node::Item(i) => { - match i.kind { - ItemKind::Fn(..) - | ItemKind::Mod(..) - | ItemKind::Enum(..) - | ItemKind::Struct(..) - | ItemKind::Union(..) - | ItemKind::Trait(..) - | ItemKind::Impl(..) => true, - _ => false, - } + Node::Item(i) => match i.kind { + ItemKind::Fn(..) + | ItemKind::Mod(..) + | ItemKind::Enum(..) + | ItemKind::Struct(..) + | ItemKind::Union(..) + | ItemKind::Trait(..) + | ItemKind::Impl(..) => true, + _ => false, }, - Node::ForeignItem(fi) => { - match fi.kind { - ForeignItemKind::Fn(..) => true, - _ => false, - } + Node::ForeignItem(fi) => match fi.kind { + ForeignItemKind::Fn(..) => true, + _ => false, }, - Node::TraitItem(ti) => { - match ti.kind { - TraitItemKind::Method(..) => true, - _ => false, - } + Node::TraitItem(ti) => match ti.kind { + TraitItemKind::Method(..) => true, + _ => false, }, - Node::ImplItem(ii) => { - match ii.kind { - ImplItemKind::Method(..) => true, - _ => false, - } + Node::ImplItem(ii) => match ii.kind { + ImplItemKind::Method(..) => true, + _ => false, }, Node::Block(_) => true, _ => false, @@ -929,12 +846,10 @@ impl<'hir> Map<'hir> { return CRATE_HIR_ID; } match self.get(scope) { - Node::Item(i) => { - match i.kind { - ItemKind::OpaqueTy(OpaqueTy { impl_trait_fn: None, .. }) => {} - _ => break, - } - } + Node::Item(i) => match i.kind { + ItemKind::OpaqueTy(OpaqueTy { impl_trait_fn: None, .. }) => {} + _ => break, + }, Node::Block(_) => {} _ => break, } @@ -950,7 +865,8 @@ impl<'hir> Map<'hir> { let parent = self.get_parent_item(hir_id); if let Some(entry) = self.find_entry(parent) { if let Entry { - node: Node::Item(Item { kind: ItemKind::ForeignMod(ref nm), .. }), .. } = entry + node: Node::Item(Item { kind: ItemKind::ForeignMod(ref nm), .. }), .. + } = entry { self.read(hir_id); // reveals some of the content of a node return nm.abi; @@ -960,38 +876,38 @@ impl<'hir> Map<'hir> { } pub fn expect_item(&self, id: HirId) -> &'hir Item { - match self.find(id) { // read recorded by `find` + match self.find(id) { + // read recorded by `find` Some(Node::Item(item)) => item, - _ => bug!("expected item, found {}", self.node_to_string(id)) + _ => bug!("expected item, found {}", self.node_to_string(id)), } } pub fn expect_impl_item(&self, id: HirId) -> &'hir ImplItem { match self.find(id) { Some(Node::ImplItem(item)) => item, - _ => bug!("expected impl item, found {}", self.node_to_string(id)) + _ => bug!("expected impl item, found {}", self.node_to_string(id)), } } pub fn expect_trait_item(&self, id: HirId) -> &'hir TraitItem { match self.find(id) { Some(Node::TraitItem(item)) => item, - _ => bug!("expected trait item, found {}", self.node_to_string(id)) + _ => bug!("expected trait item, found {}", self.node_to_string(id)), } } pub fn expect_variant_data(&self, id: HirId) -> &'hir VariantData { match self.find(id) { - Some(Node::Item(i)) => { - match i.kind { - ItemKind::Struct(ref struct_def, _) | - ItemKind::Union(ref struct_def, _) => struct_def, - _ => bug!("struct ID bound to non-struct {}", self.node_to_string(id)) + Some(Node::Item(i)) => match i.kind { + ItemKind::Struct(ref struct_def, _) | ItemKind::Union(ref struct_def, _) => { + struct_def } - } + _ => bug!("struct ID bound to non-struct {}", self.node_to_string(id)), + }, Some(Node::Variant(variant)) => &variant.data, Some(Node::Ctor(data)) => data, - _ => bug!("expected struct or variant, found {}", self.node_to_string(id)) + _ => bug!("expected struct or variant, found {}", self.node_to_string(id)), } } @@ -1005,14 +921,15 @@ impl<'hir> Map<'hir> { pub fn expect_foreign_item(&self, id: HirId) -> &'hir ForeignItem { match self.find(id) { Some(Node::ForeignItem(item)) => item, - _ => bug!("expected foreign item, found {}", self.node_to_string(id)) + _ => bug!("expected foreign item, found {}", self.node_to_string(id)), } } pub fn expect_expr(&self, id: HirId) -> &'hir Expr { - match self.find(id) { // read recorded by find + match self.find(id) { + // read recorded by find Some(Node::Expr(expr)) => expr, - _ => bug!("expected expr, found {}", self.node_to_string(id)) + _ => bug!("expected expr, found {}", self.node_to_string(id)), } } @@ -1060,7 +977,7 @@ impl<'hir> Map<'hir> { // the struct/variant definition. Some(Node::Ctor(..)) => return self.attrs(self.get_parent_item(id)), Some(Node::Crate) => Some(&self.forest.krate.attrs[..]), - _ => None + _ => None, }; attrs.unwrap_or(&[]) } @@ -1073,13 +990,12 @@ impl<'hir> Map<'hir> { // local maps and their index given that they exist. self.map.iter_enumerated().flat_map(move |(owner, local_map)| { // Iterate over each valid entry in the local map. - local_map.iter_enumerated().filter_map(move |(i, entry)| entry.map(move |_| { - // Reconstruct the `HirId` based on the 3 indices we used to find it. - HirId { - owner, - local_id: i, - } - })) + local_map.iter_enumerated().filter_map(move |(i, entry)| { + entry.map(move |_| { + // Reconstruct the `HirId` based on the 3 indices we used to find it. + HirId { owner, local_id: i } + }) + }) }) } @@ -1090,17 +1006,19 @@ impl<'hir> Map<'hir> { /// the iterator will produce node id's for items with paths /// such as `foo::bar::quux`, `bar::quux`, `other::bar::quux`, and /// any other such items it can find in the map. - pub fn nodes_matching_suffix<'a>(&'a self, parts: &'a [String]) - -> impl Iterator + 'a { + pub fn nodes_matching_suffix<'a>( + &'a self, + parts: &'a [String], + ) -> impl Iterator + 'a { let nodes = NodesMatchingSuffix { map: self, item_name: parts.last().unwrap(), in_which: &parts[..parts.len() - 1], }; - self.all_ids().filter(move |hir| nodes.matches_suffix(*hir)).map(move |hir| { - self.hir_to_node_id(hir) - }) + self.all_ids() + .filter(move |hir| nodes.matches_suffix(*hir)) + .map(move |hir| self.hir_to_node_id(hir)) } pub fn span(&self, hir_id: HirId) -> Span { @@ -1123,17 +1041,16 @@ impl<'hir> Map<'hir> { Some(Node::Pat(pat)) => pat.span, Some(Node::Arm(arm)) => arm.span, Some(Node::Block(block)) => block.span, - Some(Node::Ctor(..)) => match self.find( - self.get_parent_node(hir_id)) - { + Some(Node::Ctor(..)) => match self.find(self.get_parent_node(hir_id)) { Some(Node::Item(item)) => item.span, Some(Node::Variant(variant)) => variant.span, _ => unreachable!(), - } + }, Some(Node::Lifetime(lifetime)) => lifetime.span, Some(Node::GenericParam(param)) => param.span, Some(Node::Visibility(&Spanned { - node: VisibilityKind::Restricted { ref path, .. }, .. + node: VisibilityKind::Restricted { ref path, .. }, + .. })) => path.span, Some(Node::Visibility(v)) => bug!("unexpected Visibility {:?}", v), Some(Node::Local(local)) => local.span, @@ -1205,11 +1122,13 @@ impl<'a> NodesMatchingSuffix<'a> { loop { if let Node::Item(item) = map.find(id)? { if item_is_mod(&item) { - return Some((id, item.ident.name)) + return Some((id, item.ident.name)); } } let parent = map.get_parent_item(id); - if parent == id { return None } + if parent == id { + return None; + } id = parent; } @@ -1246,44 +1165,74 @@ trait Named { fn name(&self) -> Name; } -impl Named for Spanned { fn name(&self) -> Name { self.node.name() } } +impl Named for Spanned { + fn name(&self) -> Name { + self.node.name() + } +} -impl Named for Item { fn name(&self) -> Name { self.ident.name } } -impl Named for ForeignItem { fn name(&self) -> Name { self.ident.name } } -impl Named for Variant { fn name(&self) -> Name { self.ident.name } } -impl Named for StructField { fn name(&self) -> Name { self.ident.name } } -impl Named for TraitItem { fn name(&self) -> Name { self.ident.name } } -impl Named for ImplItem { fn name(&self) -> Name { self.ident.name } } +impl Named for Item { + fn name(&self) -> Name { + self.ident.name + } +} +impl Named for ForeignItem { + fn name(&self) -> Name { + self.ident.name + } +} +impl Named for Variant { + fn name(&self) -> Name { + self.ident.name + } +} +impl Named for StructField { + fn name(&self) -> Name { + self.ident.name + } +} +impl Named for TraitItem { + fn name(&self) -> Name { + self.ident.name + } +} +impl Named for ImplItem { + fn name(&self) -> Name { + self.ident.name + } +} -pub fn map_crate<'hir>(sess: &crate::session::Session, - cstore: &CrateStoreDyn, - forest: &'hir Forest, - definitions: Definitions) - -> Map<'hir> { +pub fn map_crate<'hir>( + sess: &crate::session::Session, + cstore: &CrateStoreDyn, + forest: &'hir Forest, + definitions: Definitions, +) -> Map<'hir> { let _prof_timer = sess.prof.generic_activity("build_hir_map"); // Build the reverse mapping of `node_to_hir_id`. - let hir_to_node_id = definitions.node_to_hir_id.iter_enumerated() - .map(|(node_id, &hir_id)| (hir_id, node_id)).collect(); + let hir_to_node_id = definitions + .node_to_hir_id + .iter_enumerated() + .map(|(node_id, &hir_id)| (hir_id, node_id)) + .collect(); let (map, crate_hash) = { let hcx = crate::ich::StableHashingContext::new(sess, &forest.krate, &definitions, cstore); - let mut collector = NodeCollector::root(sess, - &forest.krate, - &forest.dep_graph, - &definitions, - &hir_to_node_id, - hcx); + let mut collector = NodeCollector::root( + sess, + &forest.krate, + &forest.dep_graph, + &definitions, + &hir_to_node_id, + hcx, + ); intravisit::walk_crate(&mut collector, &forest.krate); let crate_disambiguator = sess.local_crate_disambiguator(); let cmdline_args = sess.opts.dep_tracking_hash(); - collector.finalize_and_compute_crate_hash( - crate_disambiguator, - cstore, - cmdline_args - ) + collector.finalize_and_compute_crate_hash(crate_disambiguator, cstore, cmdline_args) }; let map = Map { @@ -1311,7 +1260,7 @@ impl<'hir> print::PpAnn for Map<'hir> { Nested::TraitItem(id) => state.print_trait_item(self.trait_item(id)), Nested::ImplItem(id) => state.print_impl_item(self.impl_item(id)), Nested::Body(id) => state.print_expr(&self.body(id).value), - Nested::BodyParamPat(id, i) => state.print_pat(&self.body(id).params[i].pat) + Nested::BodyParamPat(id, i) => state.print_pat(&self.body(id).params[i].pat), } } } @@ -1319,39 +1268,38 @@ impl<'hir> print::PpAnn for Map<'hir> { impl<'a> print::State<'a> { pub fn print_node(&mut self, node: Node<'_>) { match node { - Node::Param(a) => self.print_param(&a), - Node::Item(a) => self.print_item(&a), - Node::ForeignItem(a) => self.print_foreign_item(&a), - Node::TraitItem(a) => self.print_trait_item(a), - Node::ImplItem(a) => self.print_impl_item(a), - Node::Variant(a) => self.print_variant(&a), - Node::AnonConst(a) => self.print_anon_const(&a), - Node::Expr(a) => self.print_expr(&a), - Node::Stmt(a) => self.print_stmt(&a), - Node::PathSegment(a) => self.print_path_segment(&a), - Node::Ty(a) => self.print_type(&a), - Node::TraitRef(a) => self.print_trait_ref(&a), - Node::Binding(a) | - Node::Pat(a) => self.print_pat(&a), - Node::Arm(a) => self.print_arm(&a), - Node::Block(a) => { + Node::Param(a) => self.print_param(&a), + Node::Item(a) => self.print_item(&a), + Node::ForeignItem(a) => self.print_foreign_item(&a), + Node::TraitItem(a) => self.print_trait_item(a), + Node::ImplItem(a) => self.print_impl_item(a), + Node::Variant(a) => self.print_variant(&a), + Node::AnonConst(a) => self.print_anon_const(&a), + Node::Expr(a) => self.print_expr(&a), + Node::Stmt(a) => self.print_stmt(&a), + Node::PathSegment(a) => self.print_path_segment(&a), + Node::Ty(a) => self.print_type(&a), + Node::TraitRef(a) => self.print_trait_ref(&a), + Node::Binding(a) | Node::Pat(a) => self.print_pat(&a), + Node::Arm(a) => self.print_arm(&a), + Node::Block(a) => { // Containing cbox, will be closed by print-block at `}`. self.cbox(print::INDENT_UNIT); // Head-ibox, will be closed by print-block after `{`. self.ibox(0); self.print_block(&a) } - Node::Lifetime(a) => self.print_lifetime(&a), - Node::Visibility(a) => self.print_visibility(&a), + Node::Lifetime(a) => self.print_lifetime(&a), + Node::Visibility(a) => self.print_visibility(&a), Node::GenericParam(_) => bug!("cannot print Node::GenericParam"), - Node::Field(_) => bug!("cannot print StructField"), + Node::Field(_) => bug!("cannot print StructField"), // These cases do not carry enough information in the // `hir_map` to reconstruct their full structure for pretty // printing. - Node::Ctor(..) => bug!("cannot print isolated Ctor"), - Node::Local(a) => self.print_local_decl(&a), - Node::MacroDef(_) => bug!("cannot print MacroDef"), - Node::Crate => bug!("cannot print Crate"), + Node::Ctor(..) => bug!("cannot print isolated Ctor"), + Node::Local(a) => self.print_local_decl(&a), + Node::MacroDef(_) => bug!("cannot print MacroDef"), + Node::Crate => bug!("cannot print Crate"), } } } @@ -1368,9 +1316,11 @@ fn hir_id_to_string(map: &Map<'_>, id: HirId, include_id: bool) -> String { let def_id = map.local_def_id(id); tcx.def_path_str(def_id) } else if let Some(path) = map.def_path_from_hir_id(id) { - path.data.into_iter().map(|elem| { - elem.data.to_string() - }).collect::>().join("::") + path.data + .into_iter() + .map(|elem| elem.data.to_string()) + .collect::>() + .join("::") } else { String::from("") } @@ -1399,25 +1349,19 @@ fn hir_id_to_string(map: &Map<'_>, id: HirId, include_id: bool) -> String { }; format!("{} {}{}", item_str, path_str(), id_str) } - Some(Node::ForeignItem(_)) => { - format!("foreign item {}{}", path_str(), id_str) - } - Some(Node::ImplItem(ii)) => { - match ii.kind { - ImplItemKind::Const(..) => { - format!("assoc const {} in {}{}", ii.ident, path_str(), id_str) - } - ImplItemKind::Method(..) => { - format!("method {} in {}{}", ii.ident, path_str(), id_str) - } - ImplItemKind::TyAlias(_) => { - format!("assoc type {} in {}{}", ii.ident, path_str(), id_str) - } - ImplItemKind::OpaqueTy(_) => { - format!("assoc opaque type {} in {}{}", ii.ident, path_str(), id_str) - } + Some(Node::ForeignItem(_)) => format!("foreign item {}{}", path_str(), id_str), + Some(Node::ImplItem(ii)) => match ii.kind { + ImplItemKind::Const(..) => { + format!("assoc const {} in {}{}", ii.ident, path_str(), id_str) } - } + ImplItemKind::Method(..) => format!("method {} in {}{}", ii.ident, path_str(), id_str), + ImplItemKind::TyAlias(_) => { + format!("assoc type {} in {}{}", ii.ident, path_str(), id_str) + } + ImplItemKind::OpaqueTy(_) => { + format!("assoc opaque type {} in {}{}", ii.ident, path_str(), id_str) + } + }, Some(Node::TraitItem(ti)) => { let kind = match ti.kind { TraitItemKind::Const(..) => "assoc constant", @@ -1428,66 +1372,30 @@ fn hir_id_to_string(map: &Map<'_>, id: HirId, include_id: bool) -> String { format!("{} {} in {}{}", kind, ti.ident, path_str(), id_str) } Some(Node::Variant(ref variant)) => { - format!("variant {} in {}{}", - variant.ident, - path_str(), id_str) + format!("variant {} in {}{}", variant.ident, path_str(), id_str) } Some(Node::Field(ref field)) => { - format!("field {} in {}{}", - field.ident, - path_str(), id_str) - } - Some(Node::AnonConst(_)) => { - format!("const {}{}", map.hir_to_pretty_string(id), id_str) - } - Some(Node::Expr(_)) => { - format!("expr {}{}", map.hir_to_pretty_string(id), id_str) - } - Some(Node::Stmt(_)) => { - format!("stmt {}{}", map.hir_to_pretty_string(id), id_str) + format!("field {} in {}{}", field.ident, path_str(), id_str) } + Some(Node::AnonConst(_)) => format!("const {}{}", map.hir_to_pretty_string(id), id_str), + Some(Node::Expr(_)) => format!("expr {}{}", map.hir_to_pretty_string(id), id_str), + Some(Node::Stmt(_)) => format!("stmt {}{}", map.hir_to_pretty_string(id), id_str), Some(Node::PathSegment(_)) => { format!("path segment {}{}", map.hir_to_pretty_string(id), id_str) } - Some(Node::Ty(_)) => { - format!("type {}{}", map.hir_to_pretty_string(id), id_str) - } - Some(Node::TraitRef(_)) => { - format!("trait_ref {}{}", map.hir_to_pretty_string(id), id_str) - } - Some(Node::Binding(_)) => { - format!("local {}{}", map.hir_to_pretty_string(id), id_str) - } - Some(Node::Pat(_)) => { - format!("pat {}{}", map.hir_to_pretty_string(id), id_str) - } - Some(Node::Param(_)) => { - format!("param {}{}", map.hir_to_pretty_string(id), id_str) - } - Some(Node::Arm(_)) => { - format!("arm {}{}", map.hir_to_pretty_string(id), id_str) - } - Some(Node::Block(_)) => { - format!("block {}{}", map.hir_to_pretty_string(id), id_str) - } - Some(Node::Local(_)) => { - format!("local {}{}", map.hir_to_pretty_string(id), id_str) - } - Some(Node::Ctor(..)) => { - format!("ctor {}{}", path_str(), id_str) - } - Some(Node::Lifetime(_)) => { - format!("lifetime {}{}", map.hir_to_pretty_string(id), id_str) - } - Some(Node::GenericParam(ref param)) => { - format!("generic_param {:?}{}", param, id_str) - } - Some(Node::Visibility(ref vis)) => { - format!("visibility {:?}{}", vis, id_str) - } - Some(Node::MacroDef(_)) => { - format!("macro {}{}", path_str(), id_str) - } + Some(Node::Ty(_)) => format!("type {}{}", map.hir_to_pretty_string(id), id_str), + Some(Node::TraitRef(_)) => format!("trait_ref {}{}", map.hir_to_pretty_string(id), id_str), + Some(Node::Binding(_)) => format!("local {}{}", map.hir_to_pretty_string(id), id_str), + Some(Node::Pat(_)) => format!("pat {}{}", map.hir_to_pretty_string(id), id_str), + Some(Node::Param(_)) => format!("param {}{}", map.hir_to_pretty_string(id), id_str), + Some(Node::Arm(_)) => format!("arm {}{}", map.hir_to_pretty_string(id), id_str), + Some(Node::Block(_)) => format!("block {}{}", map.hir_to_pretty_string(id), id_str), + Some(Node::Local(_)) => format!("local {}{}", map.hir_to_pretty_string(id), id_str), + Some(Node::Ctor(..)) => format!("ctor {}{}", path_str(), id_str), + Some(Node::Lifetime(_)) => format!("lifetime {}{}", map.hir_to_pretty_string(id), id_str), + Some(Node::GenericParam(ref param)) => format!("generic_param {:?}{}", param, id_str), + Some(Node::Visibility(ref vis)) => format!("visibility {:?}{}", vis, id_str), + Some(Node::MacroDef(_)) => format!("macro {}{}", path_str(), id_str), Some(Node::Crate) => String::from("root_crate"), None => format!("unknown node{}", id_str), } @@ -1498,9 +1406,7 @@ pub fn provide(providers: &mut Providers<'_>) { if let Some(hir_id) = tcx.hir().as_local_hir_id(def_id) { tcx.hir().def_kind(hir_id) } else { - bug!("calling local def_kind query provider for upstream DefId: {:?}", - def_id - ); + bug!("calling local def_kind query provider for upstream DefId: {:?}", def_id); } }; } diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs index 1dbcfe5588e48..df8cb5d692b15 100644 --- a/src/librustc_mir/interpret/validity.rs +++ b/src/librustc_mir/interpret/validity.rs @@ -7,17 +7,17 @@ use std::fmt::Write; use std::ops::RangeInclusive; -use syntax_pos::symbol::{sym, Symbol}; use rustc::hir; -use rustc::ty::layout::{self, TyLayout, LayoutOf, VariantIdx}; use rustc::ty; +use rustc::ty::layout::{self, LayoutOf, TyLayout, VariantIdx}; use rustc_data_structures::fx::FxHashSet; +use syntax_pos::symbol::{sym, Symbol}; use std::hash::Hash; use super::{ - GlobalAlloc, InterpResult, CheckInAllocMsg, - Scalar, OpTy, Machine, InterpCx, ValueVisitor, MPlaceTy, + CheckInAllocMsg, GlobalAlloc, InterpCx, InterpResult, MPlaceTy, Machine, OpTy, Scalar, + ValueVisitor, }; macro_rules! throw_validation_failure { @@ -83,16 +83,11 @@ pub struct RefTracking { impl RefTracking { pub fn empty() -> Self { - RefTracking { - seen: FxHashSet::default(), - todo: vec![], - } + RefTracking { seen: FxHashSet::default(), todo: vec![] } } pub fn new(op: T) -> Self { - let mut ref_tracking_for_consts = RefTracking { - seen: FxHashSet::default(), - todo: vec![(op, PATH::default())], - }; + let mut ref_tracking_for_consts = + RefTracking { seen: FxHashSet::default(), todo: vec![(op, PATH::default())] }; ref_tracking_for_consts.seen.insert(op); ref_tracking_for_consts } @@ -120,14 +115,17 @@ fn write_path(out: &mut String, path: &Vec) { TupleElem(idx) => write!(out, ".{}", idx), ArrayElem(idx) => write!(out, "[{}]", idx), Deref => - // This does not match Rust syntax, but it is more readable for long paths -- and - // some of the other items here also are not Rust syntax. Actually we can't - // even use the usual syntax because we are just showing the projections, - // not the root. - write!(out, "."), + // This does not match Rust syntax, but it is more readable for long paths -- and + // some of the other items here also are not Rust syntax. Actually we can't + // even use the usual syntax because we are just showing the projections, + // not the root. + { + write!(out, ".") + } Tag => write!(out, "."), DynDowncast => write!(out, "."), - }.unwrap() + } + .unwrap() } } @@ -168,19 +166,13 @@ struct ValidityVisitor<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> { /// starts must not be changed! `visit_fields` and `visit_array` rely on /// this stack discipline. path: Vec, - ref_tracking_for_consts: Option<&'rt mut RefTracking< - MPlaceTy<'tcx, M::PointerTag>, - Vec, - >>, + ref_tracking_for_consts: + Option<&'rt mut RefTracking, Vec>>, ecx: &'rt InterpCx<'mir, 'tcx, M>, } impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, 'tcx, M> { - fn aggregate_field_path_elem( - &mut self, - layout: TyLayout<'tcx>, - field: usize, - ) -> PathElem { + fn aggregate_field_path_elem(&mut self, layout: TyLayout<'tcx>, field: usize) -> PathElem { match layout.ty.kind { // generators and closures. ty::Closure(def_id, _) | ty::Generator(def_id, _, _) => { @@ -215,8 +207,10 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, 'tcx, M // we might be projecting *to* a variant, or to a field *in*a variant. match layout.variants { layout::Variants::Single { index } => - // Inside a variant - PathElem::Field(def.variants[index].fields[field].ident.name), + // Inside a variant + { + PathElem::Field(def.variants[index].fields[field].ident.name) + } _ => bug!(), } } @@ -262,21 +256,30 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, 'tcx, M try_validation!( self.ecx.memory.check_ptr_access( vtable, - 3*self.ecx.tcx.data_layout.pointer_size, // drop, size, align + 3 * self.ecx.tcx.data_layout.pointer_size, // drop, size, align self.ecx.tcx.data_layout.pointer_align.abi, ), "dangling or unaligned vtable pointer in wide pointer or too small vtable", self.path ); - try_validation!(self.ecx.read_drop_type_from_vtable(vtable), - "invalid drop fn in vtable", self.path); - try_validation!(self.ecx.read_size_and_align_from_vtable(vtable), - "invalid size or align in vtable", self.path); + try_validation!( + self.ecx.read_drop_type_from_vtable(vtable), + "invalid drop fn in vtable", + self.path + ); + try_validation!( + self.ecx.read_size_and_align_from_vtable(vtable), + "invalid size or align in vtable", + self.path + ); // FIXME: More checks for the vtable. } ty::Slice(..) | ty::Str => { - let _len = try_validation!(meta.unwrap().to_machine_usize(self.ecx), - "non-integer slice length in wide pointer", self.path); + let _len = try_validation!( + meta.unwrap().to_machine_usize(self.ecx), + "non-integer slice length in wide pointer", + self.path + ); // We do not check that `len * elem_size <= isize::MAX`: // that is only required for references, and there it falls out of the // "dereferenceable" check performed by Stacked Borrows. @@ -284,8 +287,7 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, 'tcx, M ty::Foreign(..) => { // Unsized, but not wide. } - _ => - bug!("Unexpected unsized type tail: {:?}", tail), + _ => bug!("Unexpected unsized type tail: {:?}", tail), } Ok(()) @@ -307,7 +309,7 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M> &mut self, old_op: OpTy<'tcx, M::PointerTag>, field: usize, - new_op: OpTy<'tcx, M::PointerTag> + new_op: OpTy<'tcx, M::PointerTag>, ) -> InterpResult<'tcx> { let elem = self.aggregate_field_path_elem(old_op.layout, field); self.visit_elem(new_op, elem) @@ -318,7 +320,7 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M> &mut self, old_op: OpTy<'tcx, M::PointerTag>, variant_id: VariantIdx, - new_op: OpTy<'tcx, M::PointerTag> + new_op: OpTy<'tcx, M::PointerTag>, ) -> InterpResult<'tcx> { let name = match old_op.layout.ty.kind { ty::Adt(adt, _) => PathElem::Variant(adt.variants[variant_id].ident.name), @@ -330,42 +332,36 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M> } #[inline] - fn visit_value(&mut self, op: OpTy<'tcx, M::PointerTag>) -> InterpResult<'tcx> - { + fn visit_value(&mut self, op: OpTy<'tcx, M::PointerTag>) -> InterpResult<'tcx> { trace!("visit_value: {:?}, {:?}", *op, op.layout); // Translate some possible errors to something nicer. match self.walk_value(op) { Ok(()) => Ok(()), Err(err) => match err.kind { - err_ub!(InvalidDiscriminant(val)) => - throw_validation_failure!( - val, self.path, "a valid enum discriminant" - ), - err_unsup!(ReadPointerAsBytes) => - throw_validation_failure!( - "a pointer", self.path, "plain (non-pointer) bytes" - ), + err_ub!(InvalidDiscriminant(val)) => { + throw_validation_failure!(val, self.path, "a valid enum discriminant") + } + err_unsup!(ReadPointerAsBytes) => { + throw_validation_failure!("a pointer", self.path, "plain (non-pointer) bytes") + } _ => Err(err), - } + }, } } - fn visit_primitive(&mut self, value: OpTy<'tcx, M::PointerTag>) -> InterpResult<'tcx> - { + fn visit_primitive(&mut self, value: OpTy<'tcx, M::PointerTag>) -> InterpResult<'tcx> { let value = self.ecx.read_immediate(value)?; // Go over all the primitive types let ty = value.layout.ty; match ty.kind { ty::Bool => { let value = value.to_scalar_or_undef(); - try_validation!(value.to_bool(), - value, self.path, "a boolean"); - }, + try_validation!(value.to_bool(), value, self.path, "a boolean"); + } ty::Char => { let value = value.to_scalar_or_undef(); - try_validation!(value.to_char(), - value, self.path, "a valid unicode codepoint"); - }, + try_validation!(value.to_char(), value, self.path, "a valid unicode codepoint"); + } ty::Float(_) | ty::Int(_) | ty::Uint(_) => { // NOTE: Keep this in sync with the array optimization for int/float // types below! @@ -373,8 +369,12 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M> let value = value.to_scalar_or_undef(); if self.ref_tracking_for_consts.is_some() { // Integers/floats in CTFE: Must be scalar bits, pointers are dangerous - try_validation!(value.to_bits(size), - value, self.path, "initialized plain (non-pointer) bytes"); + try_validation!( + value.to_bits(size), + value, + self.path, + "initialized plain (non-pointer) bytes" + ); } else { // At run-time, for now, we accept *anything* for these types, including // undef. We should fix that, but let's start low. @@ -383,8 +383,8 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M> ty::RawPtr(..) => { // We are conservative with undef for integers, but try to // actually enforce our current rules for raw pointers. - let place = try_validation!(self.ecx.ref_to_mplace(value), - "undefined pointer", self.path); + let place = + try_validation!(self.ecx.ref_to_mplace(value), "undefined pointer", self.path); if place.layout.is_unsized() { self.check_wide_ptr_meta(place.meta, place.layout)?; } @@ -392,25 +392,25 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M> _ if ty.is_box() || ty.is_region_ptr() => { // Handle wide pointers. // Check metadata early, for better diagnostics - let place = try_validation!(self.ecx.ref_to_mplace(value), - "undefined pointer", self.path); + let place = + try_validation!(self.ecx.ref_to_mplace(value), "undefined pointer", self.path); if place.layout.is_unsized() { self.check_wide_ptr_meta(place.meta, place.layout)?; } // Make sure this is dereferenceable and all. - let (size, align) = self.ecx.size_and_align_of(place.meta, place.layout)? + let (size, align) = self + .ecx + .size_and_align_of(place.meta, place.layout)? // for the purpose of validity, consider foreign types to have // alignment and size determined by the layout (size will be 0, // alignment should take attributes into account). .unwrap_or_else(|| (place.layout.size, place.layout.align.abi)); - let ptr: Option<_> = match - self.ecx.memory.check_ptr_access_align( - place.ptr, - size, - Some(align), - CheckInAllocMsg::InboundsTest, - ) - { + let ptr: Option<_> = match self.ecx.memory.check_ptr_access_align( + place.ptr, + size, + Some(align), + CheckInAllocMsg::InboundsTest, + ) { Ok(ptr) => ptr, Err(err) => { info!( @@ -418,28 +418,35 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M> place.ptr, size, align ); match err.kind { - err_unsup!(InvalidNullPointerUsage) => - throw_validation_failure!("NULL reference", self.path), - err_unsup!(AlignmentCheckFailed { required, has }) => - throw_validation_failure!(format_args!("unaligned reference \ - (required {} byte alignment but found {})", - required.bytes(), has.bytes()), self.path), - err_unsup!(ReadBytesAsPointer) => - throw_validation_failure!( - "dangling reference (created from integer)", - self.path - ), - _ => + err_unsup!(InvalidNullPointerUsage) => { + throw_validation_failure!("NULL reference", self.path) + } + err_unsup!(AlignmentCheckFailed { required, has }) => { throw_validation_failure!( - "dangling reference (not entirely in bounds)", + format_args!( + "unaligned reference \ + (required {} byte alignment but found {})", + required.bytes(), + has.bytes() + ), self.path - ), + ) + } + err_unsup!(ReadBytesAsPointer) => throw_validation_failure!( + "dangling reference (created from integer)", + self.path + ), + _ => throw_validation_failure!( + "dangling reference (not entirely in bounds)", + self.path + ), } } }; // Recursive checking if let Some(ref mut ref_tracking) = self.ref_tracking_for_consts { - if let Some(ptr) = ptr { // not a ZST + if let Some(ptr) = ptr { + // not a ZST // Skip validation entirely for some external statics let alloc_kind = self.ecx.tcx.alloc_map.lock().get(ptr.alloc_id); if let Some(GlobalAlloc::Static(did)) = alloc_kind { @@ -457,8 +464,7 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M> // Normalize before handing `place` to tracking because that will // check for duplicates. let place = if size.bytes() > 0 { - self.ecx.force_mplace_ptr(place) - .expect("we already bounds-checked") + self.ecx.force_mplace_ptr(place).expect("we already bounds-checked") } else { place }; @@ -477,18 +483,19 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M> let value = value.to_scalar_or_undef(); let _fn = try_validation!( value.not_undef().and_then(|ptr| self.ecx.memory.get_fn(ptr)), - value, self.path, "a function pointer" + value, + self.path, + "a function pointer" ); // FIXME: Check if the signature matches } // This should be all the primitive types - _ => bug!("Unexpected primitive type {}", value.layout.ty) + _ => bug!("Unexpected primitive type {}", value.layout.ty), } Ok(()) } - fn visit_uninhabited(&mut self) -> InterpResult<'tcx> - { + fn visit_uninhabited(&mut self) -> InterpResult<'tcx> { throw_validation_failure!("a value of an uninhabited type", self.path) } @@ -509,13 +516,11 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M> return Ok(()); } // At least one value is excluded. Get the bits. - let value = try_validation!(value.not_undef(), + let value = try_validation!( + value.not_undef(), value, self.path, - format_args!( - "something {}", - wrapping_range_format(&layout.valid_range, max_hi), - ) + format_args!("something {}", wrapping_range_format(&layout.valid_range, max_hi),) ); let bits = match value.to_bits_or_ptr(op.layout.size, self.ecx) { Err(ptr) => { @@ -545,8 +550,7 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M> ) } } - Ok(data) => - data + Ok(data) => data, }; // Now compare. This is slightly subtle because this is a special "wrap-around" range. if wrapping_range_contains(&layout.valid_range, bits) { @@ -563,22 +567,27 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M> fn visit_aggregate( &mut self, op: OpTy<'tcx, M::PointerTag>, - fields: impl Iterator>, + fields: impl Iterator>, ) -> InterpResult<'tcx> { match op.layout.ty.kind { ty::Str => { let mplace = op.assert_mem_place(); // strings are never immediate - try_validation!(self.ecx.read_str(mplace), - "uninitialized or non-UTF-8 data in str", self.path); + try_validation!( + self.ecx.read_str(mplace), + "uninitialized or non-UTF-8 data in str", + self.path + ); } - ty::Array(tys, ..) | ty::Slice(tys) if { - // This optimization applies only for integer and floating point types - // (i.e., types that can hold arbitrary bytes). - match tys.kind { - ty::Int(..) | ty::Uint(..) | ty::Float(..) => true, - _ => false, - } - } => { + ty::Array(tys, ..) | ty::Slice(tys) + if { + // This optimization applies only for integer and floating point types + // (i.e., types that can hold arbitrary bytes). + match tys.kind { + ty::Int(..) | ty::Uint(..) | ty::Float(..) => true, + _ => false, + } + } => + { // Optimized handling for arrays of integer/float type. // bailing out for zsts is ok, since the array element type can only be int/float @@ -617,7 +626,7 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M> /*allow_ptr_and_undef*/ self.ref_tracking_for_consts.is_none(), ) { // In the happy case, we needn't check anything else. - Ok(()) => {}, + Ok(()) => {} // Some error happened, try to provide a more detailed description. Err(err) => { // For some errors we might be able to provide extra information @@ -630,7 +639,7 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M> self.path.push(PathElem::ArrayElem(i)); throw_validation_failure!("undefined bytes", self.path) - }, + } // Other errors shouldn't be possible _ => return Err(err), } @@ -658,19 +667,14 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { &self, op: OpTy<'tcx, M::PointerTag>, path: Vec, - ref_tracking_for_consts: Option<&mut RefTracking< - MPlaceTy<'tcx, M::PointerTag>, - Vec, - >>, + ref_tracking_for_consts: Option< + &mut RefTracking, Vec>, + >, ) -> InterpResult<'tcx> { trace!("validate_operand: {:?}, {:?}", *op, op.layout.ty); // Construct a visitor - let mut visitor = ValidityVisitor { - path, - ref_tracking_for_consts, - ecx: self, - }; + let mut visitor = ValidityVisitor { path, ref_tracking_for_consts, ecx: self }; // Try to cast to ptr *once* instead of all the time. let op = self.force_op_ptr(op).unwrap_or(op); From aaa142a3962f92a1056047c6ca5ea2f12981d1ed Mon Sep 17 00:00:00 2001 From: Sebastian Hahn Date: Mon, 17 Feb 2020 18:55:41 +0100 Subject: [PATCH 3/9] Revert "Remove `checked_add` in `Layout::repeat`" This fixes a a segfault in safe code, a stable regression. Reported in \#69225. This reverts commit a983e0590a43ed8b0f60417828efd4e79b51f494. Also adds a test for the expected behaviour. --- src/libcore/alloc.rs | 13 ++++---- ...issue-69225-layout-repeated-checked-add.rs | 31 +++++++++++++++++++ 2 files changed, 38 insertions(+), 6 deletions(-) create mode 100644 src/test/ui/issues/issue-69225-layout-repeated-checked-add.rs diff --git a/src/libcore/alloc.rs b/src/libcore/alloc.rs index 71517ffb0065e..227b725de1a1e 100644 --- a/src/libcore/alloc.rs +++ b/src/libcore/alloc.rs @@ -240,13 +240,14 @@ impl Layout { #[unstable(feature = "alloc_layout_extra", issue = "55724")] #[inline] pub fn repeat(&self, n: usize) -> Result<(Self, usize), LayoutErr> { - // This cannot overflow. Quoting from the invariant of Layout: - // > `size`, when rounded up to the nearest multiple of `align`, - // > must not overflow (i.e., the rounded value must be less than - // > `usize::MAX`) - let padded_size = self.size() + self.padding_needed_for(self.align()); - let alloc_size = padded_size.checked_mul(n) + // Warning, removing the checked_add here led to segfaults in #67174. Further + // analysis in #69225 seems to indicate that this is an LTO-related + // miscompilation, so #67174 might be able to be reapplied in the future. + let padded_size = self + .size() + .checked_add(self.padding_needed_for(self.align())) .ok_or(LayoutErr { private: () })?; + let alloc_size = padded_size.checked_mul(n).ok_or(LayoutErr { private: () })?; unsafe { // self.align is already known to be valid and alloc_size has been diff --git a/src/test/ui/issues/issue-69225-layout-repeated-checked-add.rs b/src/test/ui/issues/issue-69225-layout-repeated-checked-add.rs new file mode 100644 index 0000000000000..7f43e4d1a51f8 --- /dev/null +++ b/src/test/ui/issues/issue-69225-layout-repeated-checked-add.rs @@ -0,0 +1,31 @@ +// Ensure we appropriately error instead of overflowing a calculation when creating a new Alloc +// Layout + +// run-fail +// compile-flags: -C opt-level=3 +// error-pattern: index out of bounds: the len is 0 but the index is 16777216 +// ignore-wasm no panic or subprocess support +// ignore-emscripten no panic or subprocess support + +fn do_test(x: usize) { + let arr = vec![vec![0u8; 3]]; + + let mut z = Vec::new(); + for arr_ref in arr { + for y in 0..x { + for _ in 0..1 { + z.extend(std::iter::repeat(0).take(x)); + let a = y * x; + let b = (y + 1) * x - 1; + let slice = &arr_ref[a..b]; + eprintln!("{} {} {} {}", a, b, arr_ref.len(), slice.len()); + eprintln!("{:?}", slice[1 << 24]); + } + } + } +} + +fn main() { + do_test(1); + do_test(2); +} From a978a9723ef6aeeef0acf707b7232eb1c4debfb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 14 Feb 2020 17:49:16 -0800 Subject: [PATCH 4/9] Do not ICE when encountering `yield` inside `async` block --- src/librustc/hir/map/hir_id_validator.rs | 4 ++-- src/librustc/hir/map/mod.rs | 2 +- src/test/ui/generator/async-generator-issue-67158.rs | 6 ++++++ src/test/ui/generator/async-generator-issue-67158.stderr | 9 +++++++++ 4 files changed, 18 insertions(+), 3 deletions(-) create mode 100644 src/test/ui/generator/async-generator-issue-67158.rs create mode 100644 src/test/ui/generator/async-generator-issue-67158.stderr diff --git a/src/librustc/hir/map/hir_id_validator.rs b/src/librustc/hir/map/hir_id_validator.rs index 78889bf5543ff..b68e195f295f8 100644 --- a/src/librustc/hir/map/hir_id_validator.rs +++ b/src/librustc/hir/map/hir_id_validator.rs @@ -4,7 +4,7 @@ use crate::hir::{self, intravisit, HirId, ItemLocalId}; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::sync::{par_iter, Lock, ParallelIterator}; -pub fn check_crate(hir_map: &hir::map::Map<'_>) { +pub fn check_crate(hir_map: &hir::map::Map<'_>, sess: &rustc_session::Session) { hir_map.dep_graph.assert_ignored(); let errors = Lock::new(Vec::new()); @@ -21,7 +21,7 @@ pub fn check_crate(hir_map: &hir::map::Map<'_>) { if !errors.is_empty() { let message = errors.iter().fold(String::new(), |s1, s2| s1 + "\n" + s2); - bug!("{}", message); + sess.delay_span_bug(syntax_pos::DUMMY_SP, &message); } } diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index 7cfdfb9e4f528..8cd12ead65b79 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -1245,7 +1245,7 @@ pub fn map_crate<'hir>( }; time(sess, "validate HIR map", || { - hir_id_validator::check_crate(&map); + hir_id_validator::check_crate(&map, sess); }); map diff --git a/src/test/ui/generator/async-generator-issue-67158.rs b/src/test/ui/generator/async-generator-issue-67158.rs new file mode 100644 index 0000000000000..8125a7a9bb664 --- /dev/null +++ b/src/test/ui/generator/async-generator-issue-67158.rs @@ -0,0 +1,6 @@ +#![feature(generators)] +// edition:2018 +// Regression test for #67158. +fn main() { + async { yield print!(":C") }; //~ ERROR `async` generators are not yet supported +} diff --git a/src/test/ui/generator/async-generator-issue-67158.stderr b/src/test/ui/generator/async-generator-issue-67158.stderr new file mode 100644 index 0000000000000..7270d188e8b88 --- /dev/null +++ b/src/test/ui/generator/async-generator-issue-67158.stderr @@ -0,0 +1,9 @@ +error[E0727]: `async` generators are not yet supported + --> $DIR/async-generator-issue-67158.rs:5:13 + | +LL | async { yield print!(":C") }; + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0727`. From bb392dc052fa5598ac59b6a0b2ebbdfbc8df259d Mon Sep 17 00:00:00 2001 From: Michael Burge Date: Tue, 28 Jan 2020 10:57:03 -0800 Subject: [PATCH 5/9] Correct ICE caused by macros generating invalid spans. --- src/librustc_errors/emitter.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs index 779081993a16f..6fa2a747fd3af 100644 --- a/src/librustc_errors/emitter.rs +++ b/src/librustc_errors/emitter.rs @@ -19,6 +19,7 @@ use crate::{ pluralize, CodeSuggestion, Diagnostic, DiagnosticId, Level, SubDiagnostic, SuggestionStyle, }; +use log::*; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::Lrc; use std::borrow::Cow; @@ -2097,7 +2098,13 @@ impl<'a> Drop for WritableDst<'a> { /// Whether the original and suggested code are visually similar enough to warrant extra wording. pub fn is_case_difference(sm: &SourceMap, suggested: &str, sp: Span) -> bool { // FIXME: this should probably be extended to also account for `FO0` → `FOO` and unicode. - let found = sm.span_to_snippet(sp).unwrap(); + let found = match sm.span_to_snippet(sp) { + Ok(snippet) => snippet, + Err(e) => { + warn!("Invalid span {:?}. Err={:?}", sp, e); + return false; + } + }; let ascii_confusables = &['c', 'f', 'i', 'k', 'o', 's', 'u', 'v', 'w', 'x', 'y', 'z']; // All the chars that differ in capitalization are confusable (above): let confusable = found From 2427a4970dbd6a1acd6f4dc6a5b5b1fa3285b9e3 Mon Sep 17 00:00:00 2001 From: Kornel Date: Tue, 28 Jan 2020 15:53:21 +0000 Subject: [PATCH 6/9] Demonstrate final build-override syntax --- RELEASES.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/RELEASES.md b/RELEASES.md index 26d6e2012f15a..3e06f23c59a39 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -72,9 +72,9 @@ Cargo - [Cargo.lock now uses a more git friendly format that should help to reduce merge conflicts.][cargo/7579] - [You can now override specific dependencies's build settings][cargo/7591] E.g. - `[profile.dev.overrides.image] opt-level = 2` sets the `image` crate's + `[profile.dev.package.image] opt-level = 2` sets the `image` crate's optimisation level to `2` for debug builds. You can also use - `[profile..build_overrides]` to override build scripts and + `[profile..build-override]` to override build scripts and their dependencies. Misc From c5b841cee229d4d29307b4cb9c8bdc778f7190f0 Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Fri, 27 Dec 2019 14:33:22 -0500 Subject: [PATCH 7/9] Resolve long compile times when evaluating always valid constants This extends the existing logic which skips validating every integer or floating point number type to also skip validating empty structs because they are also trivially valid. Fixes #67539 --- src/librustc_mir/interpret/validity.rs | 15 ++++-- .../const-eval/validate_uninhabited_zsts.rs | 24 +++++++++ .../validate_uninhabited_zsts.stderr | 52 +++++++++++++++++++ src/test/ui/consts/huge-values.rs | 11 ++++ 4 files changed, 99 insertions(+), 3 deletions(-) create mode 100644 src/test/ui/consts/const-eval/validate_uninhabited_zsts.rs create mode 100644 src/test/ui/consts/const-eval/validate_uninhabited_zsts.stderr create mode 100644 src/test/ui/consts/huge-values.rs diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs index df8cb5d692b15..448a2765fd3e0 100644 --- a/src/librustc_mir/interpret/validity.rs +++ b/src/librustc_mir/interpret/validity.rs @@ -580,10 +580,19 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M> } ty::Array(tys, ..) | ty::Slice(tys) if { - // This optimization applies only for integer and floating point types - // (i.e., types that can hold arbitrary bytes). + // This optimization applies for types that can hold arbitrary bytes (such as + // integer and floating point types) or for structs or tuples with no fields. + // FIXME(wesleywiser) This logic could be extended further to arbitrary structs + // or tuples made up of integer/floating point types or inhabited ZSTs with no + // padding. match tys.kind { ty::Int(..) | ty::Uint(..) | ty::Float(..) => true, + ty::Tuple(tys) if tys.len() == 0 => true, + ty::Adt(adt_def, _) + if adt_def.is_struct() && adt_def.all_fields().next().is_none() => + { + true + } _ => false, } } => @@ -609,7 +618,7 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M> // Size is not 0, get a pointer. let ptr = self.ecx.force_ptr(mplace.ptr)?; - // This is the optimization: we just check the entire range at once. + // Optimization: we just check the entire range at once. // NOTE: Keep this in sync with the handling of integer and float // types above, in `visit_primitive`. // In run-time mode, we accept pointers in here. This is actually more diff --git a/src/test/ui/consts/const-eval/validate_uninhabited_zsts.rs b/src/test/ui/consts/const-eval/validate_uninhabited_zsts.rs new file mode 100644 index 0000000000000..f18e00fd633ea --- /dev/null +++ b/src/test/ui/consts/const-eval/validate_uninhabited_zsts.rs @@ -0,0 +1,24 @@ +#![feature(const_fn)] +#![feature(const_transmute)] + +const fn foo() -> ! { + unsafe { std::mem::transmute(()) } + //~^ WARN any use of this value will cause an error [const_err] + //~| WARN the type `!` does not permit zero-initialization [invalid_value] +} + +#[derive(Clone, Copy)] +enum Empty { } + +#[warn(const_err)] +const FOO: [Empty; 3] = [foo(); 3]; + +#[warn(const_err)] +const BAR: [Empty; 3] = [unsafe { std::mem::transmute(()) }; 3]; +//~^ ERROR it is undefined behavior to use this value +//~| WARN the type `Empty` does not permit zero-initialization + +fn main() { + FOO; + BAR; +} diff --git a/src/test/ui/consts/const-eval/validate_uninhabited_zsts.stderr b/src/test/ui/consts/const-eval/validate_uninhabited_zsts.stderr new file mode 100644 index 0000000000000..bde7f2536fac1 --- /dev/null +++ b/src/test/ui/consts/const-eval/validate_uninhabited_zsts.stderr @@ -0,0 +1,52 @@ +warning: any use of this value will cause an error + --> $DIR/validate_uninhabited_zsts.rs:5:14 + | +LL | unsafe { std::mem::transmute(()) } + | ^^^^^^^^^^^^^^^^^^^^^^^ + | | + | entering unreachable code + | inside call to `foo` at $DIR/validate_uninhabited_zsts.rs:14:26 +... +LL | const FOO: [Empty; 3] = [foo(); 3]; + | ----------------------------------- + | +note: lint level defined here + --> $DIR/validate_uninhabited_zsts.rs:13:8 + | +LL | #[warn(const_err)] + | ^^^^^^^^^ + +error[E0080]: it is undefined behavior to use this value + --> $DIR/validate_uninhabited_zsts.rs:17:1 + | +LL | const BAR: [Empty; 3] = [unsafe { std::mem::transmute(()) }; 3]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of an uninhabited type + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + +warning: the type `!` does not permit zero-initialization + --> $DIR/validate_uninhabited_zsts.rs:5:14 + | +LL | unsafe { std::mem::transmute(()) } + | ^^^^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | + = note: `#[warn(invalid_value)]` on by default + = note: The never type (`!`) has no valid value + +warning: the type `Empty` does not permit zero-initialization + --> $DIR/validate_uninhabited_zsts.rs:17:35 + | +LL | const BAR: [Empty; 3] = [unsafe { std::mem::transmute(()) }; 3]; + | ^^^^^^^^^^^^^^^^^^^^^^^ + | | + | this code causes undefined behavior when executed + | help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done + | + = note: 0-variant enums have no valid value + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/consts/huge-values.rs b/src/test/ui/consts/huge-values.rs new file mode 100644 index 0000000000000..ab09922d7614a --- /dev/null +++ b/src/test/ui/consts/huge-values.rs @@ -0,0 +1,11 @@ +// build-pass +// ignore-32bit + +#[derive(Clone, Copy)] +struct Foo; + +fn main() { + let _ = [(); 4_000_000_000]; + let _ = [0u8; 4_000_000_000]; + let _ = [Foo; 4_000_000_000]; +} From 6195b6024577f4755403e079c5d076cfff8c898b Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Thu, 13 Feb 2020 20:29:03 +0000 Subject: [PATCH 8/9] Check `Copy` lifetimes bounds when copying from a projection --- .../borrow_check/type_check/mod.rs | 78 +++++++++---------- ...not-ignore-lifetime-bounds-in-copy-proj.rs | 12 +++ ...ignore-lifetime-bounds-in-copy-proj.stderr | 14 ++++ 3 files changed, 64 insertions(+), 40 deletions(-) create mode 100644 src/test/ui/nll/do-not-ignore-lifetime-bounds-in-copy-proj.rs create mode 100644 src/test/ui/nll/do-not-ignore-lifetime-bounds-in-copy-proj.stderr diff --git a/src/librustc_mir/borrow_check/type_check/mod.rs b/src/librustc_mir/borrow_check/type_check/mod.rs index 663536bc2b4b6..d2958321b5534 100644 --- a/src/librustc_mir/borrow_check/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/type_check/mod.rs @@ -497,46 +497,6 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { } }; - if place.projection.is_empty() { - if let PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) = context { - let is_promoted = match place.as_ref() { - PlaceRef { - base: &PlaceBase::Static(box Static { - kind: StaticKind::Promoted(..), - .. - }), - projection: &[], - } => true, - _ => false, - }; - - if !is_promoted { - let tcx = self.tcx(); - let trait_ref = ty::TraitRef { - def_id: tcx.lang_items().copy_trait().unwrap(), - substs: tcx.mk_substs_trait(place_ty.ty, &[]), - }; - - // To have a `Copy` operand, the type `T` of the - // value must be `Copy`. Note that we prove that `T: Copy`, - // rather than using the `is_copy_modulo_regions` - // test. This is important because - // `is_copy_modulo_regions` ignores the resulting region - // obligations and assumes they pass. This can result in - // bounds from `Copy` impls being unsoundly ignored (e.g., - // #29149). Note that we decide to use `Copy` before knowing - // whether the bounds fully apply: in effect, the rule is - // that if a value of some type could implement `Copy`, then - // it must. - self.cx.prove_trait_ref( - trait_ref, - location.to_locations(), - ConstraintCategory::CopyBound, - ); - } - } - } - for elem in place.projection.iter() { if place_ty.variant_index.is_none() { if place_ty.ty.references_error() { @@ -547,6 +507,44 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { place_ty = self.sanitize_projection(place_ty, elem, place, location) } + if let PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) = context { + let is_promoted = match place.as_ref() { + PlaceRef { + base: &PlaceBase::Static(box Static { + kind: StaticKind::Promoted(..), + .. + }), + projection: &[], + } => true, + _ => false, + }; + + if !is_promoted { + let tcx = self.tcx(); + let trait_ref = ty::TraitRef { + def_id: tcx.lang_items().copy_trait().unwrap(), + substs: tcx.mk_substs_trait(place_ty.ty, &[]), + }; + + // To have a `Copy` operand, the type `T` of the + // value must be `Copy`. Note that we prove that `T: Copy`, + // rather than using the `is_copy_modulo_regions` + // test. This is important because + // `is_copy_modulo_regions` ignores the resulting region + // obligations and assumes they pass. This can result in + // bounds from `Copy` impls being unsoundly ignored (e.g., + // #29149). Note that we decide to use `Copy` before knowing + // whether the bounds fully apply: in effect, the rule is + // that if a value of some type could implement `Copy`, then + // it must. + self.cx.prove_trait_ref( + trait_ref, + location.to_locations(), + ConstraintCategory::CopyBound, + ); + } + } + place_ty } diff --git a/src/test/ui/nll/do-not-ignore-lifetime-bounds-in-copy-proj.rs b/src/test/ui/nll/do-not-ignore-lifetime-bounds-in-copy-proj.rs new file mode 100644 index 0000000000000..96c8719468f27 --- /dev/null +++ b/src/test/ui/nll/do-not-ignore-lifetime-bounds-in-copy-proj.rs @@ -0,0 +1,12 @@ +// Test that the 'static bound from the Copy impl is respected. Regression test for #29149. + +#[derive(Clone)] +struct Foo<'a>(&'a u32); +impl Copy for Foo<'static> {} + +fn main() { + let s = 2; + let a = (Foo(&s),); //~ ERROR `s` does not live long enough [E0597] + drop(a.0); + drop(a.0); +} diff --git a/src/test/ui/nll/do-not-ignore-lifetime-bounds-in-copy-proj.stderr b/src/test/ui/nll/do-not-ignore-lifetime-bounds-in-copy-proj.stderr new file mode 100644 index 0000000000000..65be3b37e0e3b --- /dev/null +++ b/src/test/ui/nll/do-not-ignore-lifetime-bounds-in-copy-proj.stderr @@ -0,0 +1,14 @@ +error[E0597]: `s` does not live long enough + --> $DIR/do-not-ignore-lifetime-bounds-in-copy-proj.rs:9:18 + | +LL | let a = (Foo(&s),); + | ^^ borrowed value does not live long enough +LL | drop(a.0); + | --- copying this value requires that `s` is borrowed for `'static` +LL | drop(a.0); +LL | } + | - `s` dropped here while still borrowed + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. From 8f92102486d85e1247f72286a99f0e1bcd77e0dc Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Thu, 13 Feb 2020 20:29:30 +0000 Subject: [PATCH 9/9] Check types of statics in MIR typeck --- .../borrow_check/type_check/mod.rs | 21 +++++++++++-- src/test/ui/nll/issue-69114-static-mut-ty.rs | 30 +++++++++++++++++++ .../ui/nll/issue-69114-static-mut-ty.stderr | 27 +++++++++++++++++ src/test/ui/nll/issue-69114-static-ty.rs | 9 ++++++ src/test/ui/nll/issue-69114-static-ty.stderr | 15 ++++++++++ 5 files changed, 99 insertions(+), 3 deletions(-) create mode 100644 src/test/ui/nll/issue-69114-static-mut-ty.rs create mode 100644 src/test/ui/nll/issue-69114-static-mut-ty.stderr create mode 100644 src/test/ui/nll/issue-69114-static-ty.rs create mode 100644 src/test/ui/nll/issue-69114-static-ty.stderr diff --git a/src/librustc_mir/borrow_check/type_check/mod.rs b/src/librustc_mir/borrow_check/type_check/mod.rs index d2958321b5534..b48f45b2090e0 100644 --- a/src/librustc_mir/borrow_check/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/type_check/mod.rs @@ -326,12 +326,15 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> { ); } } else { + let tcx = self.tcx(); if let ty::ConstKind::Unevaluated(def_id, substs) = constant.literal.val { if let Err(terr) = self.cx.fully_perform_op( location.to_locations(), ConstraintCategory::Boring, self.cx.param_env.and(type_op::ascribe_user_type::AscribeUserType::new( - constant.literal.ty, def_id, UserSubsts { substs, user_self_ty: None }, + constant.literal.ty, + def_id, + UserSubsts { substs, user_self_ty: None }, )), ) { span_mirbug!( @@ -342,10 +345,22 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> { terr ); } + } else if let Some(static_def_id) = constant.check_static_ptr(tcx) { + let unnormalized_ty = tcx.type_of(static_def_id); + let locations = location.to_locations(); + let normalized_ty = self.cx.normalize(unnormalized_ty, locations); + let literal_ty = constant.literal.ty.builtin_deref(true).unwrap().ty; + + if let Err(terr) = self.cx.eq_types( + normalized_ty, + literal_ty, + locations, + ConstraintCategory::Boring, + ) { + span_mirbug!(self, constant, "bad static type {:?} ({:?})", constant, terr); + } } if let ty::FnDef(def_id, substs) = constant.literal.ty.kind { - let tcx = self.tcx(); - let instantiated_predicates = tcx .predicates_of(def_id) .instantiate(tcx, substs); diff --git a/src/test/ui/nll/issue-69114-static-mut-ty.rs b/src/test/ui/nll/issue-69114-static-mut-ty.rs new file mode 100644 index 0000000000000..ce37da053e371 --- /dev/null +++ b/src/test/ui/nll/issue-69114-static-mut-ty.rs @@ -0,0 +1,30 @@ +// Check that borrowck ensures that `static mut` items have the expected type. + +static FOO: u8 = 42; +static mut BAR: &'static u8 = &FOO; +static mut BAR_ELIDED: &u8 = &FOO; + +fn main() { + unsafe { + println!("{} {}", BAR, BAR_ELIDED); + set_bar(); + set_bar_elided(); + println!("{} {}", BAR, BAR_ELIDED); + } +} + +fn set_bar() { + let n = 42; + unsafe { + BAR = &n; + //~^ ERROR does not live long enough + } +} + +fn set_bar_elided() { + let n = 42; + unsafe { + BAR_ELIDED = &n; + //~^ ERROR does not live long enough + } +} diff --git a/src/test/ui/nll/issue-69114-static-mut-ty.stderr b/src/test/ui/nll/issue-69114-static-mut-ty.stderr new file mode 100644 index 0000000000000..5e55cb502caa9 --- /dev/null +++ b/src/test/ui/nll/issue-69114-static-mut-ty.stderr @@ -0,0 +1,27 @@ +error[E0597]: `n` does not live long enough + --> $DIR/issue-69114-static-mut-ty.rs:19:15 + | +LL | BAR = &n; + | ------^^ + | | | + | | borrowed value does not live long enough + | assignment requires that `n` is borrowed for `'static` +... +LL | } + | - `n` dropped here while still borrowed + +error[E0597]: `n` does not live long enough + --> $DIR/issue-69114-static-mut-ty.rs:27:22 + | +LL | BAR_ELIDED = &n; + | -------------^^ + | | | + | | borrowed value does not live long enough + | assignment requires that `n` is borrowed for `'static` +... +LL | } + | - `n` dropped here while still borrowed + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/nll/issue-69114-static-ty.rs b/src/test/ui/nll/issue-69114-static-ty.rs new file mode 100644 index 0000000000000..3318433a1c56f --- /dev/null +++ b/src/test/ui/nll/issue-69114-static-ty.rs @@ -0,0 +1,9 @@ +// Check that borrowck ensures that `static` items have the expected type. + +static FOO: &'static (dyn Fn(&'static u8) + Send + Sync) = &drop; + +fn main() { + let n = 42; + FOO(&n); + //~^ ERROR does not live long enough +} diff --git a/src/test/ui/nll/issue-69114-static-ty.stderr b/src/test/ui/nll/issue-69114-static-ty.stderr new file mode 100644 index 0000000000000..0815e74b5537d --- /dev/null +++ b/src/test/ui/nll/issue-69114-static-ty.stderr @@ -0,0 +1,15 @@ +error[E0597]: `n` does not live long enough + --> $DIR/issue-69114-static-ty.rs:7:9 + | +LL | FOO(&n); + | ----^^- + | | | + | | borrowed value does not live long enough + | argument requires that `n` is borrowed for `'static` +LL | +LL | } + | - `n` dropped here while still borrowed + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`.