diff --git a/src/Cargo.lock b/src/Cargo.lock index 40ec413c90a23..83e061d20bdaa 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -1441,6 +1441,11 @@ name = "pkg-config" version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "polonius-engine" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "precomputed-hash" version = "0.1.1" @@ -1763,6 +1768,7 @@ dependencies = [ "jobserver 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "polonius-engine 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "proc_macro 0.0.0", "rustc_apfloat 0.0.0", "rustc_data_structures 0.0.0", @@ -2135,6 +2141,7 @@ dependencies = [ "graphviz 0.0.0", "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "log_settings 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "polonius-engine 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc 0.0.0", "rustc_apfloat 0.0.0", "rustc_data_structures 0.0.0", @@ -3134,6 +3141,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum phf_generator 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "6b07ffcc532ccc85e3afc45865469bf5d9e4ef5bfcf9622e3cfe80c2d275ec03" "checksum phf_shared 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "07e24b0ca9643bdecd0632f2b3da6b1b89bbb0030e0b992afc1113b23a7bc2f2" "checksum pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "3a8b4c6b8165cd1a1cd4b9b120978131389f64bdaf456435caa41e630edba903" +"checksum polonius-engine 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6201ffe79e3da53bd065fbec2a9b391e5a0dc21038b39bb300612ddc658eb7ee" "checksum precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" "checksum pretty_assertions 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3a029430f0d744bc3d15dd474d591bed2402b645d024583082b9f63bb936dac6" "checksum proc-macro2 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "49b6a521dc81b643e9a51e0d1cf05df46d5a2f3c0280ea72bcb68276ba64a118" diff --git a/src/liballoc/fmt.rs b/src/liballoc/fmt.rs index b2c4582e8406f..a4e5373d90757 100644 --- a/src/liballoc/fmt.rs +++ b/src/liballoc/fmt.rs @@ -340,7 +340,8 @@ //! //! ## Fill/Alignment //! -//! The fill character is provided normally in conjunction with the `width` +//! The fill character is provided normally in conjunction with the +//! [`width`](#width) //! parameter. This indicates that if the value being formatted is smaller than //! `width` some extra characters will be printed around it. The extra //! characters are specified by `fill`, and the alignment can be one of the @@ -388,7 +389,8 @@ //! padding specified by fill/alignment will be used to take up the required //! space. //! -//! The default fill/alignment for non-numerics is a space and left-aligned. The +//! The default [fill/alignment](#fillalignment) for non-numerics is a space and +//! left-aligned. The //! defaults for numeric formatters is also a space but with right-alignment. If //! the `0` flag is specified for numerics, then the implicit fill character is //! `0`. diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index 5820fe58932c6..1dc0faa156d69 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -1202,6 +1202,23 @@ impl<'a> Formatter<'a> { /// is longer than this length /// /// Notably this function ignores the `flag` parameters. + /// + /// # Examples + /// + /// ``` + /// use std::fmt; + /// + /// struct Foo; + /// + /// impl fmt::Display for Foo { + /// fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + /// formatter.pad("Foo") + /// } + /// } + /// + /// assert_eq!(&format!("{:<4}", Foo), "Foo "); + /// assert_eq!(&format!("{:0>4}", Foo), "0Foo"); + /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn pad(&mut self, s: &str) -> Result { // Make sure there's a fast path up front @@ -1368,7 +1385,7 @@ impl<'a> Formatter<'a> { self.buf.write_str(data) } - /// Writes some formatted information into this instance + /// Writes some formatted information into this instance. #[stable(feature = "rust1", since = "1.0.0")] pub fn write_fmt(&mut self, fmt: Arguments) -> Result { write(self.buf, fmt) @@ -1381,11 +1398,69 @@ impl<'a> Formatter<'a> { or `sign_aware_zero_pad` methods instead")] pub fn flags(&self) -> u32 { self.flags } - /// Character used as 'fill' whenever there is alignment + /// Character used as 'fill' whenever there is alignment. + /// + /// # Examples + /// + /// ``` + /// use std::fmt; + /// + /// struct Foo; + /// + /// impl fmt::Display for Foo { + /// fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + /// let c = formatter.fill(); + /// if let Some(width) = formatter.width() { + /// for _ in 0..width { + /// write!(formatter, "{}", c)?; + /// } + /// Ok(()) + /// } else { + /// write!(formatter, "{}", c) + /// } + /// } + /// } + /// + /// // We set alignment to the left with ">". + /// assert_eq!(&format!("{:G>3}", Foo), "GGG"); + /// assert_eq!(&format!("{:t>6}", Foo), "tttttt"); + /// ``` #[stable(feature = "fmt_flags", since = "1.5.0")] pub fn fill(&self) -> char { self.fill } - /// Flag indicating what form of alignment was requested + /// Flag indicating what form of alignment was requested. + /// + /// # Examples + /// + /// ``` + /// #![feature(fmt_flags_align)] + /// + /// extern crate core; + /// + /// use std::fmt; + /// use core::fmt::Alignment; + /// + /// struct Foo; + /// + /// impl fmt::Display for Foo { + /// fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + /// let s = match formatter.align() { + /// Alignment::Left => "left", + /// Alignment::Right => "right", + /// Alignment::Center => "center", + /// Alignment::Unknown => "into the void", + /// }; + /// write!(formatter, "{}", s) + /// } + /// } + /// + /// fn main() { + /// assert_eq!(&format!("{:<}", Foo), "left"); + /// assert_eq!(&format!("{:>}", Foo), "right"); + /// assert_eq!(&format!("{:^}", Foo), "center"); + /// assert_eq!(&format!("{}", Foo), "into the void"); + /// } + /// ``` #[unstable(feature = "fmt_flags_align", reason = "method was just created", issue = "27726")] pub fn align(&self) -> Alignment { diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index 2e3f5cb65c926..95f13daf841ee 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -717,7 +717,7 @@ extern "rust-intrinsic" { /// Reinterprets the bits of a value of one type as another type. /// /// Both types must have the same size. Neither the original, nor the result, - /// may be an [invalid value](../../nomicon/meet-safe-and-unsafe.html). + /// may be an [invalid value](../../nomicon/what-unsafe-does.html). /// /// `transmute` is semantically equivalent to a bitwise move of one type /// into another. It copies the bits from the source value into the diff --git a/src/libproc_macro/lib.rs b/src/libproc_macro/lib.rs index bcab61680965a..35e2d6b23167e 100644 --- a/src/libproc_macro/lib.rs +++ b/src/libproc_macro/lib.rs @@ -93,7 +93,7 @@ impl !Sync for LexError {} impl TokenStream { /// Returns an empty `TokenStream` containing no token trees. #[unstable(feature = "proc_macro", issue = "38356")] - pub fn empty() -> TokenStream { + pub fn new() -> TokenStream { TokenStream(tokenstream::TokenStream::empty()) } diff --git a/src/libproc_macro/quote.rs b/src/libproc_macro/quote.rs index 390d4bc086825..c9d0bc1405fc0 100644 --- a/src/libproc_macro/quote.rs +++ b/src/libproc_macro/quote.rs @@ -71,7 +71,7 @@ macro_rules! quote_tree { } macro_rules! quote { - () => { TokenStream::empty() }; + () => { TokenStream::new() }; ($($t:tt)*) => { [$(quote_tree!($t),)*].iter() .cloned() @@ -104,7 +104,7 @@ impl Quote for Option { impl Quote for TokenStream { fn quote(self) -> TokenStream { if self.is_empty() { - return quote!(::TokenStream::empty()); + return quote!(::TokenStream::new()); } let mut after_dollar = false; let tokens = self.into_iter().filter_map(|tree| { diff --git a/src/librustc/Cargo.toml b/src/librustc/Cargo.toml index 42eccaec9d082..83cf4469f4d94 100644 --- a/src/librustc/Cargo.toml +++ b/src/librustc/Cargo.toml @@ -16,6 +16,7 @@ graphviz = { path = "../libgraphviz" } jobserver = "0.1" lazy_static = "1.0.0" log = { version = "0.4", features = ["release_max_level_info", "std"] } +polonius-engine = "0.1.1" proc_macro = { path = "../libproc_macro" } rustc_apfloat = { path = "../librustc_apfloat" } rustc_target = { path = "../librustc_target" } diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index d20cea8331fdd..d2dce2c7f69ba 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -82,10 +82,6 @@ pub struct LoweringContext<'a> { cstore: &'a CrateStore, - // As we walk the AST we must keep track of the current 'parent' def id (in - // the form of a DefIndex) so that if we create a new node which introduces - // a definition, then we can properly create the def id. - parent_def: Option, resolver: &'a mut Resolver, name_map: FxHashMap, @@ -205,7 +201,6 @@ pub fn lower_crate( crate_root: std_inject::injected_crate_name(), sess, cstore, - parent_def: None, resolver, name_map: FxHashMap(), items: BTreeMap::new(), @@ -885,22 +880,6 @@ impl<'a> LoweringContext<'a> { result } - fn with_parent_def(&mut self, parent_id: NodeId, f: F) -> T - where - F: FnOnce(&mut LoweringContext) -> T, - { - let old_def = self.parent_def; - self.parent_def = { - let defs = self.resolver.definitions(); - Some(defs.opt_def_index(parent_id).unwrap()) - }; - - let result = f(self); - - self.parent_def = old_def; - result - } - fn def_key(&mut self, id: DefId) -> DefKey { if id.is_local() { self.resolver.definitions().def_key(id.index) @@ -2461,74 +2440,72 @@ impl<'a> LoweringContext<'a> { } fn lower_trait_item(&mut self, i: &TraitItem) -> hir::TraitItem { - self.with_parent_def(i.id, |this| { - let LoweredNodeId { node_id, hir_id } = this.lower_node_id(i.id); - let trait_item_def_id = this.resolver.definitions().local_def_id(node_id); - - let (generics, node) = match i.node { - TraitItemKind::Const(ref ty, ref default) => ( - this.lower_generics(&i.generics, ImplTraitContext::Disallowed), - hir::TraitItemKind::Const( - this.lower_ty(ty, ImplTraitContext::Disallowed), - default - .as_ref() - .map(|x| this.lower_body(None, |this| this.lower_expr(x))), - ), + let LoweredNodeId { node_id, hir_id } = self.lower_node_id(i.id); + let trait_item_def_id = self.resolver.definitions().local_def_id(node_id); + + let (generics, node) = match i.node { + TraitItemKind::Const(ref ty, ref default) => ( + self.lower_generics(&i.generics, ImplTraitContext::Disallowed), + hir::TraitItemKind::Const( + self.lower_ty(ty, ImplTraitContext::Disallowed), + default + .as_ref() + .map(|x| self.lower_body(None, |this| this.lower_expr(x))), ), - TraitItemKind::Method(ref sig, None) => { - let names = this.lower_fn_args_to_names(&sig.decl); - this.add_in_band_defs( - &i.generics, - trait_item_def_id, - AnonymousLifetimeMode::PassThrough, - |this| { - hir::TraitItemKind::Method( - this.lower_method_sig(sig, trait_item_def_id, false), - hir::TraitMethod::Required(names), - ) - }, - ) - } - TraitItemKind::Method(ref sig, Some(ref body)) => { - let body_id = this.lower_body(Some(&sig.decl), |this| { - let body = this.lower_block(body, false); - this.expr_block(body, ThinVec::new()) - }); + ), + TraitItemKind::Method(ref sig, None) => { + let names = self.lower_fn_args_to_names(&sig.decl); + self.add_in_band_defs( + &i.generics, + trait_item_def_id, + AnonymousLifetimeMode::PassThrough, + |this| { + hir::TraitItemKind::Method( + this.lower_method_sig(sig, trait_item_def_id, false), + hir::TraitMethod::Required(names), + ) + }, + ) + } + TraitItemKind::Method(ref sig, Some(ref body)) => { + let body_id = self.lower_body(Some(&sig.decl), |this| { + let body = this.lower_block(body, false); + this.expr_block(body, ThinVec::new()) + }); - this.add_in_band_defs( - &i.generics, - trait_item_def_id, - AnonymousLifetimeMode::PassThrough, - |this| { - hir::TraitItemKind::Method( - this.lower_method_sig(sig, trait_item_def_id, false), - hir::TraitMethod::Provided(body_id), - ) - }, - ) - } - TraitItemKind::Type(ref bounds, ref default) => ( - this.lower_generics(&i.generics, ImplTraitContext::Disallowed), - hir::TraitItemKind::Type( - this.lower_bounds(bounds, ImplTraitContext::Disallowed), - default - .as_ref() - .map(|x| this.lower_ty(x, ImplTraitContext::Disallowed)), - ), + self.add_in_band_defs( + &i.generics, + trait_item_def_id, + AnonymousLifetimeMode::PassThrough, + |this| { + hir::TraitItemKind::Method( + this.lower_method_sig(sig, trait_item_def_id, false), + hir::TraitMethod::Provided(body_id), + ) + }, + ) + } + TraitItemKind::Type(ref bounds, ref default) => ( + self.lower_generics(&i.generics, ImplTraitContext::Disallowed), + hir::TraitItemKind::Type( + self.lower_bounds(bounds, ImplTraitContext::Disallowed), + default + .as_ref() + .map(|x| self.lower_ty(x, ImplTraitContext::Disallowed)), ), - TraitItemKind::Macro(..) => panic!("Shouldn't exist any more"), - }; + ), + TraitItemKind::Macro(..) => panic!("Shouldn't exist any more"), + }; - hir::TraitItem { - id: node_id, - hir_id, - name: this.lower_ident(i.ident), - attrs: this.lower_attrs(&i.attrs), - generics, - node, - span: i.span, - } - }) + hir::TraitItem { + id: node_id, + hir_id, + name: self.lower_ident(i.ident), + attrs: self.lower_attrs(&i.attrs), + generics, + node, + span: i.span, + } } fn lower_trait_item_ref(&mut self, i: &TraitItem) -> hir::TraitItemRef { @@ -2557,63 +2534,61 @@ impl<'a> LoweringContext<'a> { } fn lower_impl_item(&mut self, i: &ImplItem) -> hir::ImplItem { - self.with_parent_def(i.id, |this| { - let LoweredNodeId { node_id, hir_id } = this.lower_node_id(i.id); - let impl_item_def_id = this.resolver.definitions().local_def_id(node_id); + let LoweredNodeId { node_id, hir_id } = self.lower_node_id(i.id); + let impl_item_def_id = self.resolver.definitions().local_def_id(node_id); + + let (generics, node) = match i.node { + ImplItemKind::Const(ref ty, ref expr) => { + let body_id = self.lower_body(None, |this| this.lower_expr(expr)); + ( + self.lower_generics(&i.generics, ImplTraitContext::Disallowed), + hir::ImplItemKind::Const( + self.lower_ty(ty, ImplTraitContext::Disallowed), + body_id, + ), + ) + } + ImplItemKind::Method(ref sig, ref body) => { + let body_id = self.lower_body(Some(&sig.decl), |this| { + let body = this.lower_block(body, false); + this.expr_block(body, ThinVec::new()) + }); + let impl_trait_return_allow = !self.is_in_trait_impl; - let (generics, node) = match i.node { - ImplItemKind::Const(ref ty, ref expr) => { - let body_id = this.lower_body(None, |this| this.lower_expr(expr)); - ( - this.lower_generics(&i.generics, ImplTraitContext::Disallowed), - hir::ImplItemKind::Const( - this.lower_ty(ty, ImplTraitContext::Disallowed), + self.add_in_band_defs( + &i.generics, + impl_item_def_id, + AnonymousLifetimeMode::PassThrough, + |this| { + hir::ImplItemKind::Method( + this.lower_method_sig( + sig, + impl_item_def_id, + impl_trait_return_allow, + ), body_id, - ), - ) - } - ImplItemKind::Method(ref sig, ref body) => { - let body_id = this.lower_body(Some(&sig.decl), |this| { - let body = this.lower_block(body, false); - this.expr_block(body, ThinVec::new()) - }); - let impl_trait_return_allow = !this.is_in_trait_impl; - - this.add_in_band_defs( - &i.generics, - impl_item_def_id, - AnonymousLifetimeMode::PassThrough, - |this| { - hir::ImplItemKind::Method( - this.lower_method_sig( - sig, - impl_item_def_id, - impl_trait_return_allow, - ), - body_id, - ) - }, - ) - } - ImplItemKind::Type(ref ty) => ( - this.lower_generics(&i.generics, ImplTraitContext::Disallowed), - hir::ImplItemKind::Type(this.lower_ty(ty, ImplTraitContext::Disallowed)), - ), - ImplItemKind::Macro(..) => panic!("Shouldn't exist any more"), - }; - - hir::ImplItem { - id: node_id, - hir_id, - name: this.lower_ident(i.ident), - attrs: this.lower_attrs(&i.attrs), - generics, - vis: this.lower_visibility(&i.vis, None), - defaultness: this.lower_defaultness(i.defaultness, true /* [1] */), - node, - span: i.span, + ) + }, + ) } - }) + ImplItemKind::Type(ref ty) => ( + self.lower_generics(&i.generics, ImplTraitContext::Disallowed), + hir::ImplItemKind::Type(self.lower_ty(ty, ImplTraitContext::Disallowed)), + ), + ImplItemKind::Macro(..) => panic!("Shouldn't exist any more"), + }; + + hir::ImplItem { + id: node_id, + hir_id, + name: self.lower_ident(i.ident), + attrs: self.lower_attrs(&i.attrs), + generics, + vis: self.lower_visibility(&i.vis, None), + defaultness: self.lower_defaultness(i.defaultness, true /* [1] */), + node, + span: i.span, + } // [1] since `default impl` is not yet implemented, this is always true in impls } @@ -2689,9 +2664,7 @@ impl<'a> LoweringContext<'a> { return None; } - let node = self.with_parent_def(i.id, |this| { - this.lower_item_kind(i.id, &mut name, &attrs, &mut vis, &i.node) - }); + let node = self.lower_item_kind(i.id, &mut name, &attrs, &mut vis, &i.node); let LoweredNodeId { node_id, hir_id } = self.lower_node_id(i.id); @@ -2707,40 +2680,38 @@ impl<'a> LoweringContext<'a> { } fn lower_foreign_item(&mut self, i: &ForeignItem) -> hir::ForeignItem { - self.with_parent_def(i.id, |this| { - let node_id = this.lower_node_id(i.id).node_id; - let def_id = this.resolver.definitions().local_def_id(node_id); - hir::ForeignItem { - id: node_id, - name: i.ident.name, - attrs: this.lower_attrs(&i.attrs), - node: match i.node { - ForeignItemKind::Fn(ref fdec, ref generics) => { - let (generics, (fn_dec, fn_args)) = this.add_in_band_defs( - generics, - def_id, - AnonymousLifetimeMode::PassThrough, - |this| { - ( - // Disallow impl Trait in foreign items - this.lower_fn_decl(fdec, None, false), - this.lower_fn_args_to_names(fdec), - ) - }, - ); + let node_id = self.lower_node_id(i.id).node_id; + let def_id = self.resolver.definitions().local_def_id(node_id); + hir::ForeignItem { + id: node_id, + name: i.ident.name, + attrs: self.lower_attrs(&i.attrs), + node: match i.node { + ForeignItemKind::Fn(ref fdec, ref generics) => { + let (generics, (fn_dec, fn_args)) = self.add_in_band_defs( + generics, + def_id, + AnonymousLifetimeMode::PassThrough, + |this| { + ( + // Disallow impl Trait in foreign items + this.lower_fn_decl(fdec, None, false), + this.lower_fn_args_to_names(fdec), + ) + }, + ); - hir::ForeignItemFn(fn_dec, fn_args, generics) - } - ForeignItemKind::Static(ref t, m) => { - hir::ForeignItemStatic(this.lower_ty(t, ImplTraitContext::Disallowed), m) - } - ForeignItemKind::Ty => hir::ForeignItemType, - ForeignItemKind::Macro(_) => panic!("shouldn't exist here"), - }, - vis: this.lower_visibility(&i.vis, None), - span: i.span, - } - }) + hir::ForeignItemFn(fn_dec, fn_args, generics) + } + ForeignItemKind::Static(ref t, m) => { + hir::ForeignItemStatic(self.lower_ty(t, ImplTraitContext::Disallowed), m) + } + ForeignItemKind::Ty => hir::ForeignItemType, + ForeignItemKind::Macro(_) => panic!("shouldn't exist here"), + }, + vis: self.lower_visibility(&i.vis, None), + span: i.span, + } } fn lower_method_sig( @@ -3064,46 +3035,44 @@ impl<'a> LoweringContext<'a> { ), ExprKind::Closure(capture_clause, movability, ref decl, ref body, fn_decl_span) => { self.with_new_scopes(|this| { - this.with_parent_def(e.id, |this| { - let mut is_generator = false; - let body_id = this.lower_body(Some(decl), |this| { - let e = this.lower_expr(body); - is_generator = this.is_generator; - e - }); - let generator_option = if is_generator { - if !decl.inputs.is_empty() { - span_err!( - this.sess, - fn_decl_span, - E0628, - "generators cannot have explicit arguments" - ); - this.sess.abort_if_errors(); - } - Some(match movability { - Movability::Movable => hir::GeneratorMovability::Movable, - Movability::Static => hir::GeneratorMovability::Static, - }) - } else { - if movability == Movability::Static { - span_err!( - this.sess, - fn_decl_span, - E0906, - "closures cannot be static" - ); - } - None - }; - hir::ExprClosure( - this.lower_capture_clause(capture_clause), - this.lower_fn_decl(decl, None, false), - body_id, - fn_decl_span, - generator_option, - ) - }) + let mut is_generator = false; + let body_id = this.lower_body(Some(decl), |this| { + let e = this.lower_expr(body); + is_generator = this.is_generator; + e + }); + let generator_option = if is_generator { + if !decl.inputs.is_empty() { + span_err!( + this.sess, + fn_decl_span, + E0628, + "generators cannot have explicit arguments" + ); + this.sess.abort_if_errors(); + } + Some(match movability { + Movability::Movable => hir::GeneratorMovability::Movable, + Movability::Static => hir::GeneratorMovability::Static, + }) + } else { + if movability == Movability::Static { + span_err!( + this.sess, + fn_decl_span, + E0906, + "closures cannot be static" + ); + } + None + }; + hir::ExprClosure( + this.lower_capture_clause(capture_clause), + this.lower_fn_decl(decl, None, false), + body_id, + fn_decl_span, + generator_option, + ) }) } ExprKind::Block(ref blk, opt_label) => { diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index d138c6a85a0dd..486ea93588cc6 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -81,6 +81,7 @@ extern crate graphviz; #[macro_use] extern crate lazy_static; #[cfg(windows)] extern crate libc; +extern crate polonius_engine; extern crate rustc_target; #[macro_use] extern crate rustc_data_structures; extern crate serialize; diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 3347d47a4e81e..6fda152f9a118 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -14,6 +14,7 @@ use hir::def_id::DefId; use middle::const_val::ConstVal; use middle::region; +use polonius_engine::Atom; use rustc_data_structures::indexed_vec::Idx; use ty::subst::{Substs, Subst, Kind, UnpackedKind}; use ty::{self, AdtDef, TypeFlags, Ty, TyCtxt, TypeFoldable}; @@ -1169,6 +1170,24 @@ newtype_index!(RegionVid DEBUG_FORMAT = custom, }); +impl Atom for RegionVid { + fn index(self) -> usize { + Idx::index(self) + } +} + +impl From for RegionVid { + fn from(i: usize) -> RegionVid { + RegionVid::new(i) + } +} + +impl From for usize { + fn from(vid: RegionVid) -> usize { + Idx::index(vid) + } +} + #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)] pub enum InferTy { TyVar(TyVid), diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs index 91075ddcfa422..4d1d33e1325b8 100644 --- a/src/librustc_errors/emitter.rs +++ b/src/librustc_errors/emitter.rs @@ -1215,19 +1215,20 @@ impl EmitterWriter { let mut row_num = 2; for &(ref complete, ref parts) in suggestions.iter().take(MAX_SUGGESTIONS) { - let show_underline = parts.len() == 1 - && complete.lines().count() == 1 - && parts[0].snippet.trim() != complete.trim(); + // Only show underline if the suggestion spans a single line and doesn't cover the + // entirety of the code output. If you have multiple replacements in the same line + // of code, show the underline. + let show_underline = !(parts.len() == 1 + && parts[0].snippet.trim() == complete.trim()) + && complete.lines().count() == 1; let lines = cm.span_to_lines(parts[0].span).unwrap(); assert!(!lines.lines.is_empty()); - let span_start_pos = cm.lookup_char_pos(parts[0].span.lo()); - let line_start = span_start_pos.line; + let line_start = cm.lookup_char_pos(parts[0].span.lo()).line; draw_col_separator_no_space(&mut buffer, 1, max_line_num_len + 1); let mut line_pos = 0; - // Only show underline if there's a single suggestion and it is a single line let mut lines = complete.lines(); for line in lines.by_ref().take(MAX_HIGHLIGHT_LINES) { // Print the span column to avoid confusion @@ -1241,22 +1242,55 @@ impl EmitterWriter { line_pos += 1; row_num += 1; } + + // This offset and the ones below need to be signed to account for replacement code + // that is shorter than the original code. + let mut offset: isize = 0; // Only show an underline in the suggestions if the suggestion is not the // entirety of the code being shown and the displayed code is not multiline. if show_underline { draw_col_separator(&mut buffer, row_num, max_line_num_len + 1); - let start = parts[0].snippet.len() - parts[0].snippet.trim_left().len(); - // account for substitutions containing unicode characters - let sub_len = parts[0].snippet.trim().chars().fold(0, |acc, ch| { - acc + unicode_width::UnicodeWidthChar::width(ch).unwrap_or(0) - }); - let underline_start = span_start_pos.col_display + start; - let underline_end = span_start_pos.col_display + start + sub_len; - for p in underline_start..underline_end { - buffer.putc(row_num, - max_line_num_len + 3 + p, - '^', - Style::UnderlinePrimary); + for part in parts { + let span_start_pos = cm.lookup_char_pos(part.span.lo()).col_display; + let span_end_pos = cm.lookup_char_pos(part.span.hi()).col_display; + + // Do not underline the leading... + let start = part.snippet.len() + .saturating_sub(part.snippet.trim_left().len()); + // ...or trailing spaces. Account for substitutions containing unicode + // characters. + let sub_len = part.snippet.trim().chars().fold(0, |acc, ch| { + acc + unicode_width::UnicodeWidthChar::width(ch).unwrap_or(0) + }); + + let underline_start = (span_start_pos + start) as isize + offset; + let underline_end = (span_start_pos + start + sub_len) as isize + offset; + for p in underline_start..underline_end { + buffer.putc(row_num, + max_line_num_len + 3 + p as usize, + '^', + Style::UnderlinePrimary); + } + // underline removals too + if underline_start == underline_end { + for p in underline_start-1..underline_start+1 { + buffer.putc(row_num, + max_line_num_len + 3 + p as usize, + '-', + Style::UnderlineSecondary); + } + } + + // length of the code after substitution + let full_sub_len = part.snippet.chars().fold(0, |acc, ch| { + acc + unicode_width::UnicodeWidthChar::width(ch).unwrap_or(0) as isize + }); + + // length of the code to be substituted + let snippet_len = (span_end_pos - span_start_pos) as isize; + // For multiple substitutions, use the position *after* the previous + // substitutions have happened. + offset += full_sub_len - snippet_len; } row_num += 1; } diff --git a/src/librustc_mir/Cargo.toml b/src/librustc_mir/Cargo.toml index 62964745b6f9e..e88ff38ed7d34 100644 --- a/src/librustc_mir/Cargo.toml +++ b/src/librustc_mir/Cargo.toml @@ -14,6 +14,7 @@ bitflags = "1.0" graphviz = { path = "../libgraphviz" } log = "0.4" log_settings = "0.1.1" +polonius-engine = "0.1.1" rustc = { path = "../librustc" } rustc_target = { path = "../librustc_target" } rustc_data_structures = { path = "../librustc_data_structures" } diff --git a/src/librustc_mir/borrow_check/nll/facts.rs b/src/librustc_mir/borrow_check/nll/facts.rs index 2b2aadba7f92e..6cb8e64b9f5b4 100644 --- a/src/librustc_mir/borrow_check/nll/facts.rs +++ b/src/librustc_mir/borrow_check/nll/facts.rs @@ -10,41 +10,28 @@ use borrow_check::location::{LocationIndex, LocationTable}; use dataflow::indexes::BorrowIndex; +use polonius_engine::AllFacts as PoloniusAllFacts; +use polonius_engine::Atom; use rustc::ty::RegionVid; +use rustc_data_structures::indexed_vec::Idx; use std::error::Error; use std::fmt::Debug; use std::fs::{self, File}; use std::io::Write; use std::path::Path; -/// The "facts" which are the basis of the NLL borrow analysis. -#[derive(Default)] -crate struct AllFacts { - // `borrow_region(R, B, P)` -- the region R may refer to data from borrow B - // starting at the point P (this is usually the point *after* a borrow rvalue) - crate borrow_region: Vec<(RegionVid, BorrowIndex, LocationIndex)>, +crate type AllFacts = PoloniusAllFacts; - // universal_region(R) -- this is a "free region" within fn body - crate universal_region: Vec, - - // `cfg_edge(P,Q)` for each edge P -> Q in the control flow - crate cfg_edge: Vec<(LocationIndex, LocationIndex)>, - - // `killed(B,P)` when some prefix of the path borrowed at B is assigned at point P - crate killed: Vec<(BorrowIndex, LocationIndex)>, - - // `outlives(R1, R2, P)` when we require `R1@P: R2@P` - crate outlives: Vec<(RegionVid, RegionVid, LocationIndex)>, - - // `region_live_at(R, P)` when the region R appears in a live variable at P - crate region_live_at: Vec<(RegionVid, LocationIndex)>, - - // `invalidates(P, B)` when the borrow B is invalidated at point P - crate invalidates: Vec<(LocationIndex, BorrowIndex)>, +crate trait AllFactsExt { + fn write_to_dir( + &self, + dir: impl AsRef, + location_table: &LocationTable, + ) -> Result<(), Box>; } -impl AllFacts { - crate fn write_to_dir( +impl AllFactsExt for AllFacts { + fn write_to_dir( &self, dir: impl AsRef, location_table: &LocationTable, @@ -79,6 +66,42 @@ impl AllFacts { } } +impl Atom for BorrowIndex { + fn index(self) -> usize { + Idx::index(self) + } +} + +impl From for BorrowIndex { + fn from(i: usize) -> BorrowIndex { + BorrowIndex::new(i) + } +} + +impl From for usize { + fn from(vid: BorrowIndex) -> usize { + Idx::index(vid) + } +} + +impl Atom for LocationIndex { + fn index(self) -> usize { + Idx::index(self) + } +} + +impl From for LocationIndex { + fn from(i: usize) -> LocationIndex { + LocationIndex::new(i) + } +} + +impl From for usize { + fn from(vid: LocationIndex) -> usize { + Idx::index(vid) + } +} + struct FactWriter<'w> { location_table: &'w LocationTable, dir: &'w Path, diff --git a/src/librustc_mir/borrow_check/nll/mod.rs b/src/librustc_mir/borrow_check/nll/mod.rs index 04e23c6f041e8..a91789733a95e 100644 --- a/src/librustc_mir/borrow_check/nll/mod.rs +++ b/src/librustc_mir/borrow_check/nll/mod.rs @@ -10,6 +10,7 @@ use borrow_check::borrow_set::BorrowSet; use borrow_check::location::LocationTable; +use borrow_check::nll::facts::AllFactsExt; use dataflow::move_paths::MoveData; use dataflow::FlowAtLocation; use dataflow::MaybeInitializedPlaces; diff --git a/src/librustc_mir/dataflow/move_paths/mod.rs b/src/librustc_mir/dataflow/move_paths/mod.rs index 3a49e28f04187..610963af9e13c 100644 --- a/src/librustc_mir/dataflow/move_paths/mod.rs +++ b/src/librustc_mir/dataflow/move_paths/mod.rs @@ -34,7 +34,7 @@ pub(crate) mod indexes { macro_rules! new_index { ($Index:ident, $debug_name:expr) => { - #[derive(Copy, Clone, PartialEq, Eq, Hash)] + #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] pub struct $Index(NonZeroUsize); impl Idx for $Index { diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs index 3bf9453fb513c..ace4709ba1d64 100644 --- a/src/librustc_mir/lib.rs +++ b/src/librustc_mir/lib.rs @@ -39,6 +39,7 @@ extern crate arena; extern crate bitflags; #[macro_use] extern crate log; extern crate graphviz as dot; +extern crate polonius_engine; #[macro_use] extern crate rustc; #[macro_use] extern crate rustc_data_structures; diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs index d185bc6f300aa..808c134e99448 100644 --- a/src/librustc_typeck/check/compare_method.rs +++ b/src/librustc_typeck/check/compare_method.rs @@ -777,7 +777,7 @@ fn compare_synthetic_generics<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let new_generics_span = tcx .sess .codemap() - .generate_fn_name_span(impl_m.span)? + .generate_fn_name_span(impl_span)? .shrink_to_hi(); // in case there are generics, just replace them let generics_span = impl_m diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 70d299437a6e9..16695dcef8f71 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -3764,6 +3764,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } ctxt.may_break = true; + + // the type of a `break` is always `!`, since it diverges + tcx.types.never } else { // Otherwise, we failed to find the enclosing loop; // this can only happen if the `break` was not @@ -3784,10 +3787,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } } } + // There was an error, make typecheck fail + tcx.types.err } - // the type of a `break` is always `!`, since it diverges - tcx.types.never } hir::ExprAgain(_) => { tcx.types.never } hir::ExprRet(ref expr_opt) => { diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs index d1274a4090087..8da70f5717e71 100644 --- a/src/libstd/macros.rs +++ b/src/libstd/macros.rs @@ -364,7 +364,6 @@ pub mod builtin { /// /// let s = fmt::format(format_args!("hello {}", "world")); /// assert_eq!(s, format!("hello {}", "world")); - /// /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[macro_export] @@ -379,7 +378,7 @@ pub mod builtin { /// compile time, yielding an expression of type `&'static str`. /// /// If the environment variable is not defined, then a compilation error - /// will be emitted. To not emit a compile error, use the [`option_env!`] + /// will be emitted. To not emit a compile error, use the [`option_env!`] /// macro instead. /// /// [`option_env!`]: ../std/macro.option_env.html @@ -390,6 +389,20 @@ pub mod builtin { /// let path: &'static str = env!("PATH"); /// println!("the $PATH variable at the time of compiling was: {}", path); /// ``` + /// + /// You can customize the error message by passing a string as the second + /// parameter: + /// + /// ```compile_fail + /// let doc: &'static str = env!("documentation", "what's that?!"); + /// ``` + /// + /// If the `documentation` environment variable is not defined, you'll get + /// the following error: + /// + /// ```text + /// error: what's that?! + /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[macro_export] macro_rules! env { diff --git a/src/libstd/sync/once.rs b/src/libstd/sync/once.rs index 6fd8b6a5bbae4..7eb7be23128b3 100644 --- a/src/libstd/sync/once.rs +++ b/src/libstd/sync/once.rs @@ -73,16 +73,17 @@ use thread::{self, Thread}; /// A synchronization primitive which can be used to run a one-time global /// initialization. Useful for one-time initialization for FFI or related /// functionality. This type can only be constructed with the [`ONCE_INIT`] -/// value. +/// value or the equivalent [`Once::new`] constructor. /// /// [`ONCE_INIT`]: constant.ONCE_INIT.html +/// [`Once::new`]: struct.Once.html#method.new /// /// # Examples /// /// ``` -/// use std::sync::{Once, ONCE_INIT}; +/// use std::sync::Once; /// -/// static START: Once = ONCE_INIT; +/// static START: Once = Once::new(); /// /// START.call_once(|| { /// // run initialization here @@ -180,10 +181,10 @@ impl Once { /// # Examples /// /// ``` - /// use std::sync::{Once, ONCE_INIT}; + /// use std::sync::Once; /// /// static mut VAL: usize = 0; - /// static INIT: Once = ONCE_INIT; + /// static INIT: Once = Once::new(); /// /// // Accessing a `static mut` is unsafe much of the time, but if we do so /// // in a synchronized fashion (e.g. write once or read all) then we're @@ -248,10 +249,10 @@ impl Once { /// ``` /// #![feature(once_poison)] /// - /// use std::sync::{Once, ONCE_INIT}; + /// use std::sync::Once; /// use std::thread; /// - /// static INIT: Once = ONCE_INIT; + /// static INIT: Once = Once::new(); /// /// // poison the once /// let handle = thread::spawn(|| { @@ -431,10 +432,10 @@ impl OnceState { /// ``` /// #![feature(once_poison)] /// - /// use std::sync::{Once, ONCE_INIT}; + /// use std::sync::Once; /// use std::thread; /// - /// static INIT: Once = ONCE_INIT; + /// static INIT: Once = Once::new(); /// /// // poison the once /// let handle = thread::spawn(|| { @@ -452,9 +453,9 @@ impl OnceState { /// ``` /// #![feature(once_poison)] /// - /// use std::sync::{Once, ONCE_INIT}; + /// use std::sync::Once; /// - /// static INIT: Once = ONCE_INIT; + /// static INIT: Once = Once::new(); /// /// INIT.call_once_force(|state| { /// assert!(!state.poisoned()); diff --git a/src/test/compile-fail/issue-43162.rs b/src/test/compile-fail/issue-43162.rs index 8f4661299e9d0..b236283f75764 100644 --- a/src/test/compile-fail/issue-43162.rs +++ b/src/test/compile-fail/issue-43162.rs @@ -9,6 +9,7 @@ // except according to those terms. fn foo() -> bool { + //~^ ERROR E0308 break true; //~ ERROR E0268 } diff --git a/src/test/run-pass-fulldeps/proc-macro/auxiliary/modify-ast.rs b/src/test/run-pass-fulldeps/proc-macro/auxiliary/modify-ast.rs index fb50575579232..c37682220da33 100644 --- a/src/test/run-pass-fulldeps/proc-macro/auxiliary/modify-ast.rs +++ b/src/test/run-pass-fulldeps/proc-macro/auxiliary/modify-ast.rs @@ -26,7 +26,7 @@ pub fn assert1(_a: TokenStream, b: TokenStream) -> TokenStream { #[proc_macro_derive(Foo, attributes(foo))] pub fn assert2(a: TokenStream) -> TokenStream { assert_eq(a, "pub struct MyStructc { _a: i32, }".parse().unwrap()); - TokenStream::empty() + TokenStream::new() } fn assert_eq(a: TokenStream, b: TokenStream) { diff --git a/src/test/run-pass-fulldeps/proc-macro/auxiliary/not-joint.rs b/src/test/run-pass-fulldeps/proc-macro/auxiliary/not-joint.rs index 062a914534f13..a640fabe04fac 100644 --- a/src/test/run-pass-fulldeps/proc-macro/auxiliary/not-joint.rs +++ b/src/test/run-pass-fulldeps/proc-macro/auxiliary/not-joint.rs @@ -20,13 +20,13 @@ use proc_macro::*; #[proc_macro] pub fn tokens(input: TokenStream) -> TokenStream { assert_nothing_joint(input); - TokenStream::empty() + TokenStream::new() } #[proc_macro_attribute] pub fn nothing(_: TokenStream, input: TokenStream) -> TokenStream { assert_nothing_joint(input); - TokenStream::empty() + TokenStream::new() } fn assert_nothing_joint(s: TokenStream) { diff --git a/src/test/run-pass/weird-exprs.rs b/src/test/run-pass/weird-exprs.rs index ecb62b1888dd2..37ab2ea27150a 100644 --- a/src/test/run-pass/weird-exprs.rs +++ b/src/test/run-pass/weird-exprs.rs @@ -112,6 +112,12 @@ fn union() { union union<'union> { union: &'union union<'union>, } } +fn special_characters() { + let val = !((|(..):(_,_),__@_|__)((&*"\\",'🤔')/**/,{})=={&[..=..][..];})// + ; + assert!(!val); +} + pub fn main() { strange(); funny(); @@ -125,4 +131,5 @@ pub fn main() { you_eight(); fishy(); union(); + special_characters(); } diff --git a/src/test/ui-fulldeps/proc-macro/auxiliary/three-equals.rs b/src/test/ui-fulldeps/proc-macro/auxiliary/three-equals.rs index 8dfb9cb4fb751..5b8fcab0baaa7 100644 --- a/src/test/ui-fulldeps/proc-macro/auxiliary/three-equals.rs +++ b/src/test/ui-fulldeps/proc-macro/auxiliary/three-equals.rs @@ -50,7 +50,7 @@ fn parse(input: TokenStream) -> Result<(), Diagnostic> { pub fn three_equals(input: TokenStream) -> TokenStream { if let Err(diag) = parse(input) { diag.emit(); - return TokenStream::empty(); + return TokenStream::new(); } "3".parse().unwrap() diff --git a/src/test/ui/impl-trait/impl-generic-mismatch.stderr b/src/test/ui/impl-trait/impl-generic-mismatch.stderr index e133d825ba015..a5f1580b60d2f 100644 --- a/src/test/ui/impl-trait/impl-generic-mismatch.stderr +++ b/src/test/ui/impl-trait/impl-generic-mismatch.stderr @@ -9,7 +9,7 @@ LL | fn foo(&self, _: &U) { } help: try removing the generic parameter and using `impl Trait` instead | LL | fn foo(&self, _: &impl Debug) { } - | + | -- ^^^^^^^^^^ error[E0643]: method `bar` has incompatible signature for trait --> $DIR/impl-generic-mismatch.rs:27:23 @@ -21,12 +21,8 @@ LL | fn bar(&self, _: &impl Debug) { } | ^^^^^^^^^^ expected generic parameter, found `impl Trait` help: try changing the `impl Trait` argument to a generic parameter | -LL | fn bar(&self, _: &U); -LL | } -LL | -LL | impl Bar for () { -LL | fn bar(&self, _: &U) { } - | +LL | fn bar(&self, _: &U) { } + | ^^^^^^^^^^ ^ error[E0643]: method `hash` has incompatible signature for trait --> $DIR/impl-generic-mismatch.rs:38:33 diff --git a/src/test/ui/issue-50576.rs b/src/test/ui/issue-50576.rs new file mode 100644 index 0000000000000..b2032fb226bd1 --- /dev/null +++ b/src/test/ui/issue-50576.rs @@ -0,0 +1,16 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() { + |bool: [u8; break 'L]| 0; + //~^ ERROR [E0426] + //~| ERROR [E0268] + Vec::<[u8; break]>::new(); //~ ERROR [E0268] +} diff --git a/src/test/ui/issue-50576.stderr b/src/test/ui/issue-50576.stderr new file mode 100644 index 0000000000000..e661be2133900 --- /dev/null +++ b/src/test/ui/issue-50576.stderr @@ -0,0 +1,22 @@ +error[E0426]: use of undeclared label `'L` + --> $DIR/issue-50576.rs:12:23 + | +LL | |bool: [u8; break 'L]| 0; + | ^^ undeclared label `'L` + +error[E0268]: `break` outside of loop + --> $DIR/issue-50576.rs:12:17 + | +LL | |bool: [u8; break 'L]| 0; + | ^^^^^^^^ cannot break outside of a loop + +error[E0268]: `break` outside of loop + --> $DIR/issue-50576.rs:15:16 + | +LL | Vec::<[u8; break]>::new(); //~ ERROR [E0268] + | ^^^^^ cannot break outside of a loop + +error: aborting due to 3 previous errors + +Some errors occurred: E0268, E0426. +For more information about an error, try `rustc --explain E0268`. diff --git a/src/test/ui/issue-50581.rs b/src/test/ui/issue-50581.rs new file mode 100644 index 0000000000000..97b3f81eaf5fb --- /dev/null +++ b/src/test/ui/issue-50581.rs @@ -0,0 +1,13 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() { + |_: [u8; break]| (); //~ ERROR [E0268] +} diff --git a/src/test/ui/issue-50581.stderr b/src/test/ui/issue-50581.stderr new file mode 100644 index 0000000000000..38a87b1e78a1b --- /dev/null +++ b/src/test/ui/issue-50581.stderr @@ -0,0 +1,9 @@ +error[E0268]: `break` outside of loop + --> $DIR/issue-50581.rs:12:14 + | +LL | |_: [u8; break]| (); //~ ERROR [E0268] + | ^^^^^ cannot break outside of a loop + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0268`. diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index bcd6f4e67f436..86a600ddc2fa3 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -96,6 +96,7 @@ static WHITELIST: &'static [Crate] = &[ Crate("owning_ref"), Crate("parking_lot"), Crate("parking_lot_core"), + Crate("polonius-engine"), Crate("quick-error"), Crate("rand"), Crate("redox_syscall"),