Auto merge of #51082 - kennytm:rollup, r=kennytm

Rollup of 11 pull requests

Successful merges:

 - #50987 (Underline multiple suggested replacements in the same line)
 - #51014 (Add documentation about env! second argument)
 - #51034 (Remove unused lowering field and method)
 - #51047 (Use AllFacts from polonius-engine)
 - #51048 (Add more missing examples for Formatter)
 - #51056 (Mention and use `Once::new` instead of `ONCE_INIT`)
 - #51059 (What does an expression look like, that consists only of special characters?)
 - #51065 (Update nomicon link in transmute docs)
 - #51067 (Add inner links in documentation)
 - #51070 (Fail typecheck if we encounter a bogus break)
 - #51073 (Rename TokenStream::empty to TokenStream::new)

Failed merges:
This commit is contained in:
bors 2018-05-26 12:03:28 +00:00
commit 7a0e6a837f
31 changed files with 514 additions and 297 deletions

View File

@ -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"

View File

@ -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`.

View File

@ -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 {

View File

@ -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

View File

@ -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())
}

View File

@ -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<T: Quote> Quote for Option<T> {
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| {

View File

@ -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" }

View File

@ -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<DefIndex>,
resolver: &'a mut Resolver,
name_map: FxHashMap<Ident, Name>,
@ -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<T, F>(&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 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) => (
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 (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())
});
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)),
),
),
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,
),
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())
});
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"),
};
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 = 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),
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,
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;
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::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) => {

View File

@ -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;

View File

@ -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<usize> for RegionVid {
fn from(i: usize) -> RegionVid {
RegionVid::new(i)
}
}
impl From<RegionVid> 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),

View File

@ -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;
}

View File

@ -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" }

View File

@ -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<RegionVid, BorrowIndex, LocationIndex>;
// universal_region(R) -- this is a "free region" within fn body
crate universal_region: Vec<RegionVid>,
// `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<Path>,
location_table: &LocationTable,
) -> Result<(), Box<dyn Error>>;
}
impl AllFacts {
crate fn write_to_dir(
impl AllFactsExt for AllFacts {
fn write_to_dir(
&self,
dir: impl AsRef<Path>,
location_table: &LocationTable,
@ -79,6 +66,42 @@ impl AllFacts {
}
}
impl Atom for BorrowIndex {
fn index(self) -> usize {
Idx::index(self)
}
}
impl From<usize> for BorrowIndex {
fn from(i: usize) -> BorrowIndex {
BorrowIndex::new(i)
}
}
impl From<BorrowIndex> for usize {
fn from(vid: BorrowIndex) -> usize {
Idx::index(vid)
}
}
impl Atom for LocationIndex {
fn index(self) -> usize {
Idx::index(self)
}
}
impl From<usize> for LocationIndex {
fn from(i: usize) -> LocationIndex {
LocationIndex::new(i)
}
}
impl From<LocationIndex> for usize {
fn from(vid: LocationIndex) -> usize {
Idx::index(vid)
}
}
struct FactWriter<'w> {
location_table: &'w LocationTable,
dir: &'w Path,

View File

@ -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;

View File

@ -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 {

View File

@ -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;

View File

@ -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

View File

@ -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) => {

View File

@ -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 {

View File

@ -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());

View File

@ -9,6 +9,7 @@
// except according to those terms.
fn foo() -> bool {
//~^ ERROR E0308
break true; //~ ERROR E0268
}

View File

@ -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) {

View File

@ -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) {

View File

@ -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();
}

View File

@ -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()

View File

@ -9,7 +9,7 @@ LL | fn foo<U: Debug>(&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<U: Debug><U: Debug>(&self, _: &U);
LL | }
LL |
LL | impl Bar for () {
LL | fn bar(&self, _: &U) { }
|
LL | fn bar<U: Debug>(&self, _: &U) { }
| ^^^^^^^^^^ ^
error[E0643]: method `hash` has incompatible signature for trait
--> $DIR/impl-generic-mismatch.rs:38:33

View File

@ -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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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]
}

View File

@ -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`.

View File

@ -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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
fn main() {
|_: [u8; break]| (); //~ ERROR [E0268]
}

View File

@ -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`.

View File

@ -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"),