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:
commit
7a0e6a837f
31 changed files with 514 additions and 297 deletions
|
@ -1441,6 +1441,11 @@ name = "pkg-config"
|
||||||
version = "0.3.9"
|
version = "0.3.9"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
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]]
|
[[package]]
|
||||||
name = "precomputed-hash"
|
name = "precomputed-hash"
|
||||||
version = "0.1.1"
|
version = "0.1.1"
|
||||||
|
@ -1763,6 +1768,7 @@ dependencies = [
|
||||||
"jobserver 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
"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)",
|
"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)",
|
"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",
|
"proc_macro 0.0.0",
|
||||||
"rustc_apfloat 0.0.0",
|
"rustc_apfloat 0.0.0",
|
||||||
"rustc_data_structures 0.0.0",
|
"rustc_data_structures 0.0.0",
|
||||||
|
@ -2135,6 +2141,7 @@ dependencies = [
|
||||||
"graphviz 0.0.0",
|
"graphviz 0.0.0",
|
||||||
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"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)",
|
"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 0.0.0",
|
||||||
"rustc_apfloat 0.0.0",
|
"rustc_apfloat 0.0.0",
|
||||||
"rustc_data_structures 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_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 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 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 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 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"
|
"checksum proc-macro2 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "49b6a521dc81b643e9a51e0d1cf05df46d5a2f3c0280ea72bcb68276ba64a118"
|
||||||
|
|
|
@ -340,7 +340,8 @@
|
||||||
//!
|
//!
|
||||||
//! ## Fill/Alignment
|
//! ## 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
|
//! parameter. This indicates that if the value being formatted is smaller than
|
||||||
//! `width` some extra characters will be printed around it. The extra
|
//! `width` some extra characters will be printed around it. The extra
|
||||||
//! characters are specified by `fill`, and the alignment can be one of the
|
//! 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
|
//! padding specified by fill/alignment will be used to take up the required
|
||||||
//! space.
|
//! 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
|
//! 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
|
//! the `0` flag is specified for numerics, then the implicit fill character is
|
||||||
//! `0`.
|
//! `0`.
|
||||||
|
|
|
@ -1202,6 +1202,23 @@ impl<'a> Formatter<'a> {
|
||||||
/// is longer than this length
|
/// is longer than this length
|
||||||
///
|
///
|
||||||
/// Notably this function ignores the `flag` parameters.
|
/// 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")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub fn pad(&mut self, s: &str) -> Result {
|
pub fn pad(&mut self, s: &str) -> Result {
|
||||||
// Make sure there's a fast path up front
|
// Make sure there's a fast path up front
|
||||||
|
@ -1368,7 +1385,7 @@ impl<'a> Formatter<'a> {
|
||||||
self.buf.write_str(data)
|
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")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub fn write_fmt(&mut self, fmt: Arguments) -> Result {
|
pub fn write_fmt(&mut self, fmt: Arguments) -> Result {
|
||||||
write(self.buf, fmt)
|
write(self.buf, fmt)
|
||||||
|
@ -1381,11 +1398,69 @@ impl<'a> Formatter<'a> {
|
||||||
or `sign_aware_zero_pad` methods instead")]
|
or `sign_aware_zero_pad` methods instead")]
|
||||||
pub fn flags(&self) -> u32 { self.flags }
|
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")]
|
#[stable(feature = "fmt_flags", since = "1.5.0")]
|
||||||
pub fn fill(&self) -> char { self.fill }
|
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",
|
#[unstable(feature = "fmt_flags_align", reason = "method was just created",
|
||||||
issue = "27726")]
|
issue = "27726")]
|
||||||
pub fn align(&self) -> Alignment {
|
pub fn align(&self) -> Alignment {
|
||||||
|
|
|
@ -717,7 +717,7 @@ extern "rust-intrinsic" {
|
||||||
/// Reinterprets the bits of a value of one type as another type.
|
/// 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,
|
/// 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
|
/// `transmute` is semantically equivalent to a bitwise move of one type
|
||||||
/// into another. It copies the bits from the source value into the
|
/// into another. It copies the bits from the source value into the
|
||||||
|
|
|
@ -93,7 +93,7 @@ impl !Sync for LexError {}
|
||||||
impl TokenStream {
|
impl TokenStream {
|
||||||
/// Returns an empty `TokenStream` containing no token trees.
|
/// Returns an empty `TokenStream` containing no token trees.
|
||||||
#[unstable(feature = "proc_macro", issue = "38356")]
|
#[unstable(feature = "proc_macro", issue = "38356")]
|
||||||
pub fn empty() -> TokenStream {
|
pub fn new() -> TokenStream {
|
||||||
TokenStream(tokenstream::TokenStream::empty())
|
TokenStream(tokenstream::TokenStream::empty())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -71,7 +71,7 @@ macro_rules! quote_tree {
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! quote {
|
macro_rules! quote {
|
||||||
() => { TokenStream::empty() };
|
() => { TokenStream::new() };
|
||||||
($($t:tt)*) => {
|
($($t:tt)*) => {
|
||||||
[$(quote_tree!($t),)*].iter()
|
[$(quote_tree!($t),)*].iter()
|
||||||
.cloned()
|
.cloned()
|
||||||
|
@ -104,7 +104,7 @@ impl<T: Quote> Quote for Option<T> {
|
||||||
impl Quote for TokenStream {
|
impl Quote for TokenStream {
|
||||||
fn quote(self) -> TokenStream {
|
fn quote(self) -> TokenStream {
|
||||||
if self.is_empty() {
|
if self.is_empty() {
|
||||||
return quote!(::TokenStream::empty());
|
return quote!(::TokenStream::new());
|
||||||
}
|
}
|
||||||
let mut after_dollar = false;
|
let mut after_dollar = false;
|
||||||
let tokens = self.into_iter().filter_map(|tree| {
|
let tokens = self.into_iter().filter_map(|tree| {
|
||||||
|
|
|
@ -16,6 +16,7 @@ graphviz = { path = "../libgraphviz" }
|
||||||
jobserver = "0.1"
|
jobserver = "0.1"
|
||||||
lazy_static = "1.0.0"
|
lazy_static = "1.0.0"
|
||||||
log = { version = "0.4", features = ["release_max_level_info", "std"] }
|
log = { version = "0.4", features = ["release_max_level_info", "std"] }
|
||||||
|
polonius-engine = "0.1.1"
|
||||||
proc_macro = { path = "../libproc_macro" }
|
proc_macro = { path = "../libproc_macro" }
|
||||||
rustc_apfloat = { path = "../librustc_apfloat" }
|
rustc_apfloat = { path = "../librustc_apfloat" }
|
||||||
rustc_target = { path = "../librustc_target" }
|
rustc_target = { path = "../librustc_target" }
|
||||||
|
|
|
@ -82,10 +82,6 @@ pub struct LoweringContext<'a> {
|
||||||
|
|
||||||
cstore: &'a CrateStore,
|
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,
|
resolver: &'a mut Resolver,
|
||||||
name_map: FxHashMap<Ident, Name>,
|
name_map: FxHashMap<Ident, Name>,
|
||||||
|
|
||||||
|
@ -205,7 +201,6 @@ pub fn lower_crate(
|
||||||
crate_root: std_inject::injected_crate_name(),
|
crate_root: std_inject::injected_crate_name(),
|
||||||
sess,
|
sess,
|
||||||
cstore,
|
cstore,
|
||||||
parent_def: None,
|
|
||||||
resolver,
|
resolver,
|
||||||
name_map: FxHashMap(),
|
name_map: FxHashMap(),
|
||||||
items: BTreeMap::new(),
|
items: BTreeMap::new(),
|
||||||
|
@ -885,22 +880,6 @@ impl<'a> LoweringContext<'a> {
|
||||||
result
|
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 {
|
fn def_key(&mut self, id: DefId) -> DefKey {
|
||||||
if id.is_local() {
|
if id.is_local() {
|
||||||
self.resolver.definitions().def_key(id.index)
|
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 {
|
fn lower_trait_item(&mut self, i: &TraitItem) -> hir::TraitItem {
|
||||||
self.with_parent_def(i.id, |this| {
|
let LoweredNodeId { node_id, hir_id } = self.lower_node_id(i.id);
|
||||||
let LoweredNodeId { node_id, hir_id } = this.lower_node_id(i.id);
|
let trait_item_def_id = self.resolver.definitions().local_def_id(node_id);
|
||||||
let trait_item_def_id = this.resolver.definitions().local_def_id(node_id);
|
|
||||||
|
|
||||||
let (generics, node) = match i.node {
|
let (generics, node) = match i.node {
|
||||||
TraitItemKind::Const(ref ty, ref default) => (
|
TraitItemKind::Const(ref ty, ref default) => (
|
||||||
this.lower_generics(&i.generics, ImplTraitContext::Disallowed),
|
self.lower_generics(&i.generics, ImplTraitContext::Disallowed),
|
||||||
hir::TraitItemKind::Const(
|
hir::TraitItemKind::Const(
|
||||||
this.lower_ty(ty, ImplTraitContext::Disallowed),
|
self.lower_ty(ty, ImplTraitContext::Disallowed),
|
||||||
default
|
default
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|x| this.lower_body(None, |this| this.lower_expr(x))),
|
.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);
|
TraitItemKind::Method(ref sig, None) => {
|
||||||
this.add_in_band_defs(
|
let names = self.lower_fn_args_to_names(&sig.decl);
|
||||||
&i.generics,
|
self.add_in_band_defs(
|
||||||
trait_item_def_id,
|
&i.generics,
|
||||||
AnonymousLifetimeMode::PassThrough,
|
trait_item_def_id,
|
||||||
|this| {
|
AnonymousLifetimeMode::PassThrough,
|
||||||
hir::TraitItemKind::Method(
|
|this| {
|
||||||
this.lower_method_sig(sig, trait_item_def_id, false),
|
hir::TraitItemKind::Method(
|
||||||
hir::TraitMethod::Required(names),
|
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, 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 {
|
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 {
|
fn lower_impl_item(&mut self, i: &ImplItem) -> hir::ImplItem {
|
||||||
self.with_parent_def(i.id, |this| {
|
let LoweredNodeId { node_id, hir_id } = self.lower_node_id(i.id);
|
||||||
let LoweredNodeId { node_id, hir_id } = this.lower_node_id(i.id);
|
let impl_item_def_id = self.resolver.definitions().local_def_id(node_id);
|
||||||
let impl_item_def_id = this.resolver.definitions().local_def_id(node_id);
|
|
||||||
|
|
||||||
let (generics, node) = match i.node {
|
let (generics, node) = match i.node {
|
||||||
ImplItemKind::Const(ref ty, ref expr) => {
|
ImplItemKind::Const(ref ty, ref expr) => {
|
||||||
let body_id = this.lower_body(None, |this| this.lower_expr(expr));
|
let body_id = self.lower_body(None, |this| this.lower_expr(expr));
|
||||||
(
|
(
|
||||||
this.lower_generics(&i.generics, ImplTraitContext::Disallowed),
|
self.lower_generics(&i.generics, ImplTraitContext::Disallowed),
|
||||||
hir::ImplItemKind::Const(
|
hir::ImplItemKind::Const(
|
||||||
this.lower_ty(ty, ImplTraitContext::Disallowed),
|
self.lower_ty(ty, ImplTraitContext::Disallowed),
|
||||||
body_id,
|
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::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
|
// [1] since `default impl` is not yet implemented, this is always true in impls
|
||||||
}
|
}
|
||||||
|
@ -2689,9 +2664,7 @@ impl<'a> LoweringContext<'a> {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
let node = self.with_parent_def(i.id, |this| {
|
let node = self.lower_item_kind(i.id, &mut name, &attrs, &mut vis, &i.node);
|
||||||
this.lower_item_kind(i.id, &mut name, &attrs, &mut vis, &i.node)
|
|
||||||
});
|
|
||||||
|
|
||||||
let LoweredNodeId { node_id, hir_id } = self.lower_node_id(i.id);
|
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 {
|
fn lower_foreign_item(&mut self, i: &ForeignItem) -> hir::ForeignItem {
|
||||||
self.with_parent_def(i.id, |this| {
|
let node_id = self.lower_node_id(i.id).node_id;
|
||||||
let node_id = this.lower_node_id(i.id).node_id;
|
let def_id = self.resolver.definitions().local_def_id(node_id);
|
||||||
let def_id = this.resolver.definitions().local_def_id(node_id);
|
hir::ForeignItem {
|
||||||
hir::ForeignItem {
|
id: node_id,
|
||||||
id: node_id,
|
name: i.ident.name,
|
||||||
name: i.ident.name,
|
attrs: self.lower_attrs(&i.attrs),
|
||||||
attrs: this.lower_attrs(&i.attrs),
|
node: match i.node {
|
||||||
node: match i.node {
|
ForeignItemKind::Fn(ref fdec, ref generics) => {
|
||||||
ForeignItemKind::Fn(ref fdec, ref generics) => {
|
let (generics, (fn_dec, fn_args)) = self.add_in_band_defs(
|
||||||
let (generics, (fn_dec, fn_args)) = this.add_in_band_defs(
|
generics,
|
||||||
generics,
|
def_id,
|
||||||
def_id,
|
AnonymousLifetimeMode::PassThrough,
|
||||||
AnonymousLifetimeMode::PassThrough,
|
|this| {
|
||||||
|this| {
|
(
|
||||||
(
|
// Disallow impl Trait in foreign items
|
||||||
// Disallow impl Trait in foreign items
|
this.lower_fn_decl(fdec, None, false),
|
||||||
this.lower_fn_decl(fdec, None, false),
|
this.lower_fn_args_to_names(fdec),
|
||||||
this.lower_fn_args_to_names(fdec),
|
)
|
||||||
)
|
},
|
||||||
},
|
);
|
||||||
);
|
|
||||||
|
|
||||||
hir::ForeignItemFn(fn_dec, fn_args, generics)
|
hir::ForeignItemFn(fn_dec, fn_args, generics)
|
||||||
}
|
}
|
||||||
ForeignItemKind::Static(ref t, m) => {
|
ForeignItemKind::Static(ref t, m) => {
|
||||||
hir::ForeignItemStatic(this.lower_ty(t, ImplTraitContext::Disallowed), m)
|
hir::ForeignItemStatic(self.lower_ty(t, ImplTraitContext::Disallowed), m)
|
||||||
}
|
}
|
||||||
ForeignItemKind::Ty => hir::ForeignItemType,
|
ForeignItemKind::Ty => hir::ForeignItemType,
|
||||||
ForeignItemKind::Macro(_) => panic!("shouldn't exist here"),
|
ForeignItemKind::Macro(_) => panic!("shouldn't exist here"),
|
||||||
},
|
},
|
||||||
vis: this.lower_visibility(&i.vis, None),
|
vis: self.lower_visibility(&i.vis, None),
|
||||||
span: i.span,
|
span: i.span,
|
||||||
}
|
}
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lower_method_sig(
|
fn lower_method_sig(
|
||||||
|
@ -3064,46 +3035,44 @@ impl<'a> LoweringContext<'a> {
|
||||||
),
|
),
|
||||||
ExprKind::Closure(capture_clause, movability, ref decl, ref body, fn_decl_span) => {
|
ExprKind::Closure(capture_clause, movability, ref decl, ref body, fn_decl_span) => {
|
||||||
self.with_new_scopes(|this| {
|
self.with_new_scopes(|this| {
|
||||||
this.with_parent_def(e.id, |this| {
|
let mut is_generator = false;
|
||||||
let mut is_generator = false;
|
let body_id = this.lower_body(Some(decl), |this| {
|
||||||
let body_id = this.lower_body(Some(decl), |this| {
|
let e = this.lower_expr(body);
|
||||||
let e = this.lower_expr(body);
|
is_generator = this.is_generator;
|
||||||
is_generator = this.is_generator;
|
e
|
||||||
e
|
});
|
||||||
});
|
let generator_option = if is_generator {
|
||||||
let generator_option = if is_generator {
|
if !decl.inputs.is_empty() {
|
||||||
if !decl.inputs.is_empty() {
|
span_err!(
|
||||||
span_err!(
|
this.sess,
|
||||||
this.sess,
|
fn_decl_span,
|
||||||
fn_decl_span,
|
E0628,
|
||||||
E0628,
|
"generators cannot have explicit arguments"
|
||||||
"generators cannot have explicit arguments"
|
);
|
||||||
);
|
this.sess.abort_if_errors();
|
||||||
this.sess.abort_if_errors();
|
}
|
||||||
}
|
Some(match movability {
|
||||||
Some(match movability {
|
Movability::Movable => hir::GeneratorMovability::Movable,
|
||||||
Movability::Movable => hir::GeneratorMovability::Movable,
|
Movability::Static => hir::GeneratorMovability::Static,
|
||||||
Movability::Static => hir::GeneratorMovability::Static,
|
})
|
||||||
})
|
} else {
|
||||||
} else {
|
if movability == Movability::Static {
|
||||||
if movability == Movability::Static {
|
span_err!(
|
||||||
span_err!(
|
this.sess,
|
||||||
this.sess,
|
fn_decl_span,
|
||||||
fn_decl_span,
|
E0906,
|
||||||
E0906,
|
"closures cannot be static"
|
||||||
"closures cannot be static"
|
);
|
||||||
);
|
}
|
||||||
}
|
None
|
||||||
None
|
};
|
||||||
};
|
hir::ExprClosure(
|
||||||
hir::ExprClosure(
|
this.lower_capture_clause(capture_clause),
|
||||||
this.lower_capture_clause(capture_clause),
|
this.lower_fn_decl(decl, None, false),
|
||||||
this.lower_fn_decl(decl, None, false),
|
body_id,
|
||||||
body_id,
|
fn_decl_span,
|
||||||
fn_decl_span,
|
generator_option,
|
||||||
generator_option,
|
)
|
||||||
)
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
ExprKind::Block(ref blk, opt_label) => {
|
ExprKind::Block(ref blk, opt_label) => {
|
||||||
|
|
|
@ -81,6 +81,7 @@ extern crate graphviz;
|
||||||
#[macro_use] extern crate lazy_static;
|
#[macro_use] extern crate lazy_static;
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
extern crate libc;
|
extern crate libc;
|
||||||
|
extern crate polonius_engine;
|
||||||
extern crate rustc_target;
|
extern crate rustc_target;
|
||||||
#[macro_use] extern crate rustc_data_structures;
|
#[macro_use] extern crate rustc_data_structures;
|
||||||
extern crate serialize;
|
extern crate serialize;
|
||||||
|
|
|
@ -14,6 +14,7 @@ use hir::def_id::DefId;
|
||||||
|
|
||||||
use middle::const_val::ConstVal;
|
use middle::const_val::ConstVal;
|
||||||
use middle::region;
|
use middle::region;
|
||||||
|
use polonius_engine::Atom;
|
||||||
use rustc_data_structures::indexed_vec::Idx;
|
use rustc_data_structures::indexed_vec::Idx;
|
||||||
use ty::subst::{Substs, Subst, Kind, UnpackedKind};
|
use ty::subst::{Substs, Subst, Kind, UnpackedKind};
|
||||||
use ty::{self, AdtDef, TypeFlags, Ty, TyCtxt, TypeFoldable};
|
use ty::{self, AdtDef, TypeFlags, Ty, TyCtxt, TypeFoldable};
|
||||||
|
@ -1169,6 +1170,24 @@ newtype_index!(RegionVid
|
||||||
DEBUG_FORMAT = custom,
|
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)]
|
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
|
||||||
pub enum InferTy {
|
pub enum InferTy {
|
||||||
TyVar(TyVid),
|
TyVar(TyVid),
|
||||||
|
|
|
@ -1215,19 +1215,20 @@ impl EmitterWriter {
|
||||||
|
|
||||||
let mut row_num = 2;
|
let mut row_num = 2;
|
||||||
for &(ref complete, ref parts) in suggestions.iter().take(MAX_SUGGESTIONS) {
|
for &(ref complete, ref parts) in suggestions.iter().take(MAX_SUGGESTIONS) {
|
||||||
let show_underline = parts.len() == 1
|
// Only show underline if the suggestion spans a single line and doesn't cover the
|
||||||
&& complete.lines().count() == 1
|
// entirety of the code output. If you have multiple replacements in the same line
|
||||||
&& parts[0].snippet.trim() != complete.trim();
|
// 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();
|
let lines = cm.span_to_lines(parts[0].span).unwrap();
|
||||||
|
|
||||||
assert!(!lines.lines.is_empty());
|
assert!(!lines.lines.is_empty());
|
||||||
|
|
||||||
let span_start_pos = cm.lookup_char_pos(parts[0].span.lo());
|
let line_start = cm.lookup_char_pos(parts[0].span.lo()).line;
|
||||||
let line_start = span_start_pos.line;
|
|
||||||
draw_col_separator_no_space(&mut buffer, 1, max_line_num_len + 1);
|
draw_col_separator_no_space(&mut buffer, 1, max_line_num_len + 1);
|
||||||
let mut line_pos = 0;
|
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();
|
let mut lines = complete.lines();
|
||||||
for line in lines.by_ref().take(MAX_HIGHLIGHT_LINES) {
|
for line in lines.by_ref().take(MAX_HIGHLIGHT_LINES) {
|
||||||
// Print the span column to avoid confusion
|
// Print the span column to avoid confusion
|
||||||
|
@ -1241,22 +1242,55 @@ impl EmitterWriter {
|
||||||
line_pos += 1;
|
line_pos += 1;
|
||||||
row_num += 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
|
// 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.
|
// entirety of the code being shown and the displayed code is not multiline.
|
||||||
if show_underline {
|
if show_underline {
|
||||||
draw_col_separator(&mut buffer, row_num, max_line_num_len + 1);
|
draw_col_separator(&mut buffer, row_num, max_line_num_len + 1);
|
||||||
let start = parts[0].snippet.len() - parts[0].snippet.trim_left().len();
|
for part in parts {
|
||||||
// account for substitutions containing unicode characters
|
let span_start_pos = cm.lookup_char_pos(part.span.lo()).col_display;
|
||||||
let sub_len = parts[0].snippet.trim().chars().fold(0, |acc, ch| {
|
let span_end_pos = cm.lookup_char_pos(part.span.hi()).col_display;
|
||||||
acc + unicode_width::UnicodeWidthChar::width(ch).unwrap_or(0)
|
|
||||||
});
|
// Do not underline the leading...
|
||||||
let underline_start = span_start_pos.col_display + start;
|
let start = part.snippet.len()
|
||||||
let underline_end = span_start_pos.col_display + start + sub_len;
|
.saturating_sub(part.snippet.trim_left().len());
|
||||||
for p in underline_start..underline_end {
|
// ...or trailing spaces. Account for substitutions containing unicode
|
||||||
buffer.putc(row_num,
|
// characters.
|
||||||
max_line_num_len + 3 + p,
|
let sub_len = part.snippet.trim().chars().fold(0, |acc, ch| {
|
||||||
'^',
|
acc + unicode_width::UnicodeWidthChar::width(ch).unwrap_or(0)
|
||||||
Style::UnderlinePrimary);
|
});
|
||||||
|
|
||||||
|
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;
|
row_num += 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,7 @@ bitflags = "1.0"
|
||||||
graphviz = { path = "../libgraphviz" }
|
graphviz = { path = "../libgraphviz" }
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
log_settings = "0.1.1"
|
log_settings = "0.1.1"
|
||||||
|
polonius-engine = "0.1.1"
|
||||||
rustc = { path = "../librustc" }
|
rustc = { path = "../librustc" }
|
||||||
rustc_target = { path = "../librustc_target" }
|
rustc_target = { path = "../librustc_target" }
|
||||||
rustc_data_structures = { path = "../librustc_data_structures" }
|
rustc_data_structures = { path = "../librustc_data_structures" }
|
||||||
|
|
|
@ -10,41 +10,28 @@
|
||||||
|
|
||||||
use borrow_check::location::{LocationIndex, LocationTable};
|
use borrow_check::location::{LocationIndex, LocationTable};
|
||||||
use dataflow::indexes::BorrowIndex;
|
use dataflow::indexes::BorrowIndex;
|
||||||
|
use polonius_engine::AllFacts as PoloniusAllFacts;
|
||||||
|
use polonius_engine::Atom;
|
||||||
use rustc::ty::RegionVid;
|
use rustc::ty::RegionVid;
|
||||||
|
use rustc_data_structures::indexed_vec::Idx;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
use std::fs::{self, File};
|
use std::fs::{self, File};
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
/// The "facts" which are the basis of the NLL borrow analysis.
|
crate type AllFacts = PoloniusAllFacts<RegionVid, BorrowIndex, LocationIndex>;
|
||||||
#[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)>,
|
|
||||||
|
|
||||||
// universal_region(R) -- this is a "free region" within fn body
|
crate trait AllFactsExt {
|
||||||
crate universal_region: Vec<RegionVid>,
|
fn write_to_dir(
|
||||||
|
&self,
|
||||||
// `cfg_edge(P,Q)` for each edge P -> Q in the control flow
|
dir: impl AsRef<Path>,
|
||||||
crate cfg_edge: Vec<(LocationIndex, LocationIndex)>,
|
location_table: &LocationTable,
|
||||||
|
) -> Result<(), Box<dyn Error>>;
|
||||||
// `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)>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AllFacts {
|
impl AllFactsExt for AllFacts {
|
||||||
crate fn write_to_dir(
|
fn write_to_dir(
|
||||||
&self,
|
&self,
|
||||||
dir: impl AsRef<Path>,
|
dir: impl AsRef<Path>,
|
||||||
location_table: &LocationTable,
|
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> {
|
struct FactWriter<'w> {
|
||||||
location_table: &'w LocationTable,
|
location_table: &'w LocationTable,
|
||||||
dir: &'w Path,
|
dir: &'w Path,
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
|
|
||||||
use borrow_check::borrow_set::BorrowSet;
|
use borrow_check::borrow_set::BorrowSet;
|
||||||
use borrow_check::location::LocationTable;
|
use borrow_check::location::LocationTable;
|
||||||
|
use borrow_check::nll::facts::AllFactsExt;
|
||||||
use dataflow::move_paths::MoveData;
|
use dataflow::move_paths::MoveData;
|
||||||
use dataflow::FlowAtLocation;
|
use dataflow::FlowAtLocation;
|
||||||
use dataflow::MaybeInitializedPlaces;
|
use dataflow::MaybeInitializedPlaces;
|
||||||
|
|
|
@ -34,7 +34,7 @@ pub(crate) mod indexes {
|
||||||
|
|
||||||
macro_rules! new_index {
|
macro_rules! new_index {
|
||||||
($Index:ident, $debug_name:expr) => {
|
($Index:ident, $debug_name:expr) => {
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
|
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
||||||
pub struct $Index(NonZeroUsize);
|
pub struct $Index(NonZeroUsize);
|
||||||
|
|
||||||
impl Idx for $Index {
|
impl Idx for $Index {
|
||||||
|
|
|
@ -39,6 +39,7 @@ extern crate arena;
|
||||||
extern crate bitflags;
|
extern crate bitflags;
|
||||||
#[macro_use] extern crate log;
|
#[macro_use] extern crate log;
|
||||||
extern crate graphviz as dot;
|
extern crate graphviz as dot;
|
||||||
|
extern crate polonius_engine;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate rustc;
|
extern crate rustc;
|
||||||
#[macro_use] extern crate rustc_data_structures;
|
#[macro_use] extern crate rustc_data_structures;
|
||||||
|
|
|
@ -777,7 +777,7 @@ fn compare_synthetic_generics<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
let new_generics_span = tcx
|
let new_generics_span = tcx
|
||||||
.sess
|
.sess
|
||||||
.codemap()
|
.codemap()
|
||||||
.generate_fn_name_span(impl_m.span)?
|
.generate_fn_name_span(impl_span)?
|
||||||
.shrink_to_hi();
|
.shrink_to_hi();
|
||||||
// in case there are generics, just replace them
|
// in case there are generics, just replace them
|
||||||
let generics_span = impl_m
|
let generics_span = impl_m
|
||||||
|
|
|
@ -3764,6 +3764,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
ctxt.may_break = true;
|
ctxt.may_break = true;
|
||||||
|
|
||||||
|
// the type of a `break` is always `!`, since it diverges
|
||||||
|
tcx.types.never
|
||||||
} else {
|
} else {
|
||||||
// Otherwise, we failed to find the enclosing loop;
|
// Otherwise, we failed to find the enclosing loop;
|
||||||
// this can only happen if the `break` was not
|
// 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::ExprAgain(_) => { tcx.types.never }
|
||||||
hir::ExprRet(ref expr_opt) => {
|
hir::ExprRet(ref expr_opt) => {
|
||||||
|
|
|
@ -364,7 +364,6 @@ pub mod builtin {
|
||||||
///
|
///
|
||||||
/// let s = fmt::format(format_args!("hello {}", "world"));
|
/// let s = fmt::format(format_args!("hello {}", "world"));
|
||||||
/// assert_eq!(s, format!("hello {}", "world"));
|
/// assert_eq!(s, format!("hello {}", "world"));
|
||||||
///
|
|
||||||
/// ```
|
/// ```
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
|
@ -379,7 +378,7 @@ pub mod builtin {
|
||||||
/// compile time, yielding an expression of type `&'static str`.
|
/// compile time, yielding an expression of type `&'static str`.
|
||||||
///
|
///
|
||||||
/// If the environment variable is not defined, then a compilation error
|
/// 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.
|
/// macro instead.
|
||||||
///
|
///
|
||||||
/// [`option_env!`]: ../std/macro.option_env.html
|
/// [`option_env!`]: ../std/macro.option_env.html
|
||||||
|
@ -390,6 +389,20 @@ pub mod builtin {
|
||||||
/// let path: &'static str = env!("PATH");
|
/// let path: &'static str = env!("PATH");
|
||||||
/// println!("the $PATH variable at the time of compiling was: {}", 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")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! env {
|
macro_rules! env {
|
||||||
|
|
|
@ -73,16 +73,17 @@ use thread::{self, Thread};
|
||||||
/// A synchronization primitive which can be used to run a one-time global
|
/// A synchronization primitive which can be used to run a one-time global
|
||||||
/// initialization. Useful for one-time initialization for FFI or related
|
/// initialization. Useful for one-time initialization for FFI or related
|
||||||
/// functionality. This type can only be constructed with the [`ONCE_INIT`]
|
/// 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_INIT`]: constant.ONCE_INIT.html
|
||||||
|
/// [`Once::new`]: struct.Once.html#method.new
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use std::sync::{Once, ONCE_INIT};
|
/// use std::sync::Once;
|
||||||
///
|
///
|
||||||
/// static START: Once = ONCE_INIT;
|
/// static START: Once = Once::new();
|
||||||
///
|
///
|
||||||
/// START.call_once(|| {
|
/// START.call_once(|| {
|
||||||
/// // run initialization here
|
/// // run initialization here
|
||||||
|
@ -180,10 +181,10 @@ impl Once {
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use std::sync::{Once, ONCE_INIT};
|
/// use std::sync::Once;
|
||||||
///
|
///
|
||||||
/// static mut VAL: usize = 0;
|
/// 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
|
/// // 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
|
/// // in a synchronized fashion (e.g. write once or read all) then we're
|
||||||
|
@ -248,10 +249,10 @@ impl Once {
|
||||||
/// ```
|
/// ```
|
||||||
/// #![feature(once_poison)]
|
/// #![feature(once_poison)]
|
||||||
///
|
///
|
||||||
/// use std::sync::{Once, ONCE_INIT};
|
/// use std::sync::Once;
|
||||||
/// use std::thread;
|
/// use std::thread;
|
||||||
///
|
///
|
||||||
/// static INIT: Once = ONCE_INIT;
|
/// static INIT: Once = Once::new();
|
||||||
///
|
///
|
||||||
/// // poison the once
|
/// // poison the once
|
||||||
/// let handle = thread::spawn(|| {
|
/// let handle = thread::spawn(|| {
|
||||||
|
@ -431,10 +432,10 @@ impl OnceState {
|
||||||
/// ```
|
/// ```
|
||||||
/// #![feature(once_poison)]
|
/// #![feature(once_poison)]
|
||||||
///
|
///
|
||||||
/// use std::sync::{Once, ONCE_INIT};
|
/// use std::sync::Once;
|
||||||
/// use std::thread;
|
/// use std::thread;
|
||||||
///
|
///
|
||||||
/// static INIT: Once = ONCE_INIT;
|
/// static INIT: Once = Once::new();
|
||||||
///
|
///
|
||||||
/// // poison the once
|
/// // poison the once
|
||||||
/// let handle = thread::spawn(|| {
|
/// let handle = thread::spawn(|| {
|
||||||
|
@ -452,9 +453,9 @@ impl OnceState {
|
||||||
/// ```
|
/// ```
|
||||||
/// #![feature(once_poison)]
|
/// #![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| {
|
/// INIT.call_once_force(|state| {
|
||||||
/// assert!(!state.poisoned());
|
/// assert!(!state.poisoned());
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
fn foo() -> bool {
|
fn foo() -> bool {
|
||||||
|
//~^ ERROR E0308
|
||||||
break true; //~ ERROR E0268
|
break true; //~ ERROR E0268
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,7 @@ pub fn assert1(_a: TokenStream, b: TokenStream) -> TokenStream {
|
||||||
#[proc_macro_derive(Foo, attributes(foo))]
|
#[proc_macro_derive(Foo, attributes(foo))]
|
||||||
pub fn assert2(a: TokenStream) -> TokenStream {
|
pub fn assert2(a: TokenStream) -> TokenStream {
|
||||||
assert_eq(a, "pub struct MyStructc { _a: i32, }".parse().unwrap());
|
assert_eq(a, "pub struct MyStructc { _a: i32, }".parse().unwrap());
|
||||||
TokenStream::empty()
|
TokenStream::new()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn assert_eq(a: TokenStream, b: TokenStream) {
|
fn assert_eq(a: TokenStream, b: TokenStream) {
|
||||||
|
|
|
@ -20,13 +20,13 @@ use proc_macro::*;
|
||||||
#[proc_macro]
|
#[proc_macro]
|
||||||
pub fn tokens(input: TokenStream) -> TokenStream {
|
pub fn tokens(input: TokenStream) -> TokenStream {
|
||||||
assert_nothing_joint(input);
|
assert_nothing_joint(input);
|
||||||
TokenStream::empty()
|
TokenStream::new()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[proc_macro_attribute]
|
#[proc_macro_attribute]
|
||||||
pub fn nothing(_: TokenStream, input: TokenStream) -> TokenStream {
|
pub fn nothing(_: TokenStream, input: TokenStream) -> TokenStream {
|
||||||
assert_nothing_joint(input);
|
assert_nothing_joint(input);
|
||||||
TokenStream::empty()
|
TokenStream::new()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn assert_nothing_joint(s: TokenStream) {
|
fn assert_nothing_joint(s: TokenStream) {
|
||||||
|
|
|
@ -112,6 +112,12 @@ fn union() {
|
||||||
union union<'union> { union: &'union union<'union>, }
|
union union<'union> { union: &'union union<'union>, }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn special_characters() {
|
||||||
|
let val = !((|(..):(_,_),__@_|__)((&*"\\",'🤔')/**/,{})=={&[..=..][..];})//
|
||||||
|
;
|
||||||
|
assert!(!val);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn main() {
|
pub fn main() {
|
||||||
strange();
|
strange();
|
||||||
funny();
|
funny();
|
||||||
|
@ -125,4 +131,5 @@ pub fn main() {
|
||||||
you_eight();
|
you_eight();
|
||||||
fishy();
|
fishy();
|
||||||
union();
|
union();
|
||||||
|
special_characters();
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,7 +50,7 @@ fn parse(input: TokenStream) -> Result<(), Diagnostic> {
|
||||||
pub fn three_equals(input: TokenStream) -> TokenStream {
|
pub fn three_equals(input: TokenStream) -> TokenStream {
|
||||||
if let Err(diag) = parse(input) {
|
if let Err(diag) = parse(input) {
|
||||||
diag.emit();
|
diag.emit();
|
||||||
return TokenStream::empty();
|
return TokenStream::new();
|
||||||
}
|
}
|
||||||
|
|
||||||
"3".parse().unwrap()
|
"3".parse().unwrap()
|
||||||
|
|
|
@ -9,7 +9,7 @@ LL | fn foo<U: Debug>(&self, _: &U) { }
|
||||||
help: try removing the generic parameter and using `impl Trait` instead
|
help: try removing the generic parameter and using `impl Trait` instead
|
||||||
|
|
|
|
||||||
LL | fn foo(&self, _: &impl Debug) { }
|
LL | fn foo(&self, _: &impl Debug) { }
|
||||||
|
|
| -- ^^^^^^^^^^
|
||||||
|
|
||||||
error[E0643]: method `bar` has incompatible signature for trait
|
error[E0643]: method `bar` has incompatible signature for trait
|
||||||
--> $DIR/impl-generic-mismatch.rs:27:23
|
--> $DIR/impl-generic-mismatch.rs:27:23
|
||||||
|
@ -21,12 +21,8 @@ LL | fn bar(&self, _: &impl Debug) { }
|
||||||
| ^^^^^^^^^^ expected generic parameter, found `impl Trait`
|
| ^^^^^^^^^^ expected generic parameter, found `impl Trait`
|
||||||
help: try changing the `impl Trait` argument to a generic parameter
|
help: try changing the `impl Trait` argument to a generic parameter
|
||||||
|
|
|
|
||||||
LL | fn bar<U: Debug><U: Debug>(&self, _: &U);
|
LL | fn bar<U: Debug>(&self, _: &U) { }
|
||||||
LL | }
|
| ^^^^^^^^^^ ^
|
||||||
LL |
|
|
||||||
LL | impl Bar for () {
|
|
||||||
LL | fn bar(&self, _: &U) { }
|
|
||||||
|
|
|
||||||
|
|
||||||
error[E0643]: method `hash` has incompatible signature for trait
|
error[E0643]: method `hash` has incompatible signature for trait
|
||||||
--> $DIR/impl-generic-mismatch.rs:38:33
|
--> $DIR/impl-generic-mismatch.rs:38:33
|
||||||
|
|
16
src/test/ui/issue-50576.rs
Normal file
16
src/test/ui/issue-50576.rs
Normal 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]
|
||||||
|
}
|
22
src/test/ui/issue-50576.stderr
Normal file
22
src/test/ui/issue-50576.stderr
Normal 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`.
|
13
src/test/ui/issue-50581.rs
Normal file
13
src/test/ui/issue-50581.rs
Normal 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]
|
||||||
|
}
|
9
src/test/ui/issue-50581.stderr
Normal file
9
src/test/ui/issue-50581.stderr
Normal 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`.
|
|
@ -96,6 +96,7 @@ static WHITELIST: &'static [Crate] = &[
|
||||||
Crate("owning_ref"),
|
Crate("owning_ref"),
|
||||||
Crate("parking_lot"),
|
Crate("parking_lot"),
|
||||||
Crate("parking_lot_core"),
|
Crate("parking_lot_core"),
|
||||||
|
Crate("polonius-engine"),
|
||||||
Crate("quick-error"),
|
Crate("quick-error"),
|
||||||
Crate("rand"),
|
Crate("rand"),
|
||||||
Crate("redox_syscall"),
|
Crate("redox_syscall"),
|
||||||
|
|
Loading…
Add table
Reference in a new issue