"rustc",
"rustc_codegen_utils",
"rustc_data_structures",
+ "rustc_error_codes",
"rustc_errors",
"rustc_interface",
"rustc_lint",
"rustc_codegen_ssa",
"rustc_codegen_utils",
"rustc_data_structures",
- "rustc_error_codes",
"rustc_errors",
"rustc_incremental",
"rustc_lint",
-Subproject commit 75a5f9236c689a547fe207a10854f0775bce7937
+Subproject commit 934380b7cfceaaa4e1b9bb0de4a372f32725520b
/// Splits the collection into two at the given index.
///
- /// Returns a newly allocated `Self`. `self` contains elements `[0, at)`,
- /// and the returned `Self` contains elements `[at, len)`.
- ///
- /// Note that the capacity of `self` does not change.
+ /// Returns a newly allocated vector containing the elements in the range
+ /// `[at, len)`. After the call, the original vector will be left containing
+ /// the elements `[0, at)` with its previous capacity unchanged.
///
/// # Panics
///
+++ /dev/null
-/// Panics the current thread.
-///
-/// For details, see `std::macros`.
-#[macro_export]
-#[allow_internal_unstable(core_panic,
- // FIXME(anp, eddyb) `core_intrinsics` is used here to allow calling
- // the `caller_location` intrinsic, but once `#[track_caller]` is implemented,
- // `panicking::{panic, panic_fmt}` can use that instead of a `Location` argument.
- core_intrinsics,
-)]
-#[stable(feature = "core", since = "1.6.0")]
-macro_rules! panic {
- () => (
- $crate::panic!("explicit panic")
- );
- ($msg:expr) => (
- $crate::panicking::panic($msg, $crate::intrinsics::caller_location())
- );
- ($msg:expr,) => (
- $crate::panic!($msg)
- );
- ($fmt:expr, $($arg:tt)+) => (
- $crate::panicking::panic_fmt(
- $crate::format_args!($fmt, $($arg)+),
- $crate::intrinsics::caller_location(),
- )
- );
-}
-
-/// Asserts that two expressions are equal to each other (using [`PartialEq`]).
-///
-/// On panic, this macro will print the values of the expressions with their
-/// debug representations.
-///
-/// Like [`assert!`], this macro has a second form, where a custom
-/// panic message can be provided.
-///
-/// [`PartialEq`]: cmp/trait.PartialEq.html
-/// [`assert!`]: macro.assert.html
-///
-/// # Examples
-///
-/// ```
-/// let a = 3;
-/// let b = 1 + 2;
-/// assert_eq!(a, b);
-///
-/// assert_eq!(a, b, "we are testing addition with {} and {}", a, b);
-/// ```
-#[macro_export]
-#[stable(feature = "rust1", since = "1.0.0")]
-macro_rules! assert_eq {
- ($left:expr, $right:expr) => ({
- match (&$left, &$right) {
- (left_val, right_val) => {
- if !(*left_val == *right_val) {
- // The reborrows below are intentional. Without them, the stack slot for the
- // borrow is initialized even before the values are compared, leading to a
- // noticeable slow down.
- panic!(r#"assertion failed: `(left == right)`
- left: `{:?}`,
- right: `{:?}`"#, &*left_val, &*right_val)
- }
- }
- }
- });
- ($left:expr, $right:expr,) => ({
- $crate::assert_eq!($left, $right)
- });
- ($left:expr, $right:expr, $($arg:tt)+) => ({
- match (&($left), &($right)) {
- (left_val, right_val) => {
- if !(*left_val == *right_val) {
- // The reborrows below are intentional. Without them, the stack slot for the
- // borrow is initialized even before the values are compared, leading to a
- // noticeable slow down.
- panic!(r#"assertion failed: `(left == right)`
- left: `{:?}`,
- right: `{:?}`: {}"#, &*left_val, &*right_val,
- $crate::format_args!($($arg)+))
- }
- }
- }
- });
-}
-
-/// Asserts that two expressions are not equal to each other (using [`PartialEq`]).
-///
-/// On panic, this macro will print the values of the expressions with their
-/// debug representations.
-///
-/// Like [`assert!`], this macro has a second form, where a custom
-/// panic message can be provided.
-///
-/// [`PartialEq`]: cmp/trait.PartialEq.html
-/// [`assert!`]: macro.assert.html
-///
-/// # Examples
-///
-/// ```
-/// let a = 3;
-/// let b = 2;
-/// assert_ne!(a, b);
-///
-/// assert_ne!(a, b, "we are testing that the values are not equal");
-/// ```
-#[macro_export]
-#[stable(feature = "assert_ne", since = "1.13.0")]
-macro_rules! assert_ne {
- ($left:expr, $right:expr) => ({
- match (&$left, &$right) {
- (left_val, right_val) => {
- if *left_val == *right_val {
- // The reborrows below are intentional. Without them, the stack slot for the
- // borrow is initialized even before the values are compared, leading to a
- // noticeable slow down.
- panic!(r#"assertion failed: `(left != right)`
- left: `{:?}`,
- right: `{:?}`"#, &*left_val, &*right_val)
- }
- }
- }
- });
- ($left:expr, $right:expr,) => {
- $crate::assert_ne!($left, $right)
- };
- ($left:expr, $right:expr, $($arg:tt)+) => ({
- match (&($left), &($right)) {
- (left_val, right_val) => {
- if *left_val == *right_val {
- // The reborrows below are intentional. Without them, the stack slot for the
- // borrow is initialized even before the values are compared, leading to a
- // noticeable slow down.
- panic!(r#"assertion failed: `(left != right)`
- left: `{:?}`,
- right: `{:?}`: {}"#, &*left_val, &*right_val,
- $crate::format_args!($($arg)+))
- }
- }
- }
- });
-}
-
-/// Asserts that a boolean expression is `true` at runtime.
-///
-/// This will invoke the [`panic!`] macro if the provided expression cannot be
-/// evaluated to `true` at runtime.
-///
-/// Like [`assert!`], this macro also has a second version, where a custom panic
-/// message can be provided.
-///
-/// # Uses
-///
-/// Unlike [`assert!`], `debug_assert!` statements are only enabled in non
-/// optimized builds by default. An optimized build will not execute
-/// `debug_assert!` statements unless `-C debug-assertions` is passed to the
-/// compiler. This makes `debug_assert!` useful for checks that are too
-/// expensive to be present in a release build but may be helpful during
-/// development. The result of expanding `debug_assert!` is always type checked.
-///
-/// An unchecked assertion allows a program in an inconsistent state to keep
-/// running, which might have unexpected consequences but does not introduce
-/// unsafety as long as this only happens in safe code. The performance cost
-/// of assertions, is however, not measurable in general. Replacing [`assert!`]
-/// with `debug_assert!` is thus only encouraged after thorough profiling, and
-/// more importantly, only in safe code!
-///
-/// [`panic!`]: macro.panic.html
-/// [`assert!`]: macro.assert.html
-///
-/// # Examples
-///
-/// ```
-/// // the panic message for these assertions is the stringified value of the
-/// // expression given.
-/// debug_assert!(true);
-///
-/// fn some_expensive_computation() -> bool { true } // a very simple function
-/// debug_assert!(some_expensive_computation());
-///
-/// // assert with a custom message
-/// let x = true;
-/// debug_assert!(x, "x wasn't true!");
-///
-/// let a = 3; let b = 27;
-/// debug_assert!(a + b == 30, "a = {}, b = {}", a, b);
-/// ```
-#[macro_export]
-#[stable(feature = "rust1", since = "1.0.0")]
-macro_rules! debug_assert {
- ($($arg:tt)*) => (if $crate::cfg!(debug_assertions) { $crate::assert!($($arg)*); })
-}
-
-/// Asserts that two expressions are equal to each other.
-///
-/// On panic, this macro will print the values of the expressions with their
-/// debug representations.
-///
-/// Unlike [`assert_eq!`], `debug_assert_eq!` statements are only enabled in non
-/// optimized builds by default. An optimized build will not execute
-/// `debug_assert_eq!` statements unless `-C debug-assertions` is passed to the
-/// compiler. This makes `debug_assert_eq!` useful for checks that are too
-/// expensive to be present in a release build but may be helpful during
-/// development. The result of expanding `debug_assert_eq!` is always type checked.
-///
-/// [`assert_eq!`]: ../std/macro.assert_eq.html
-///
-/// # Examples
-///
-/// ```
-/// let a = 3;
-/// let b = 1 + 2;
-/// debug_assert_eq!(a, b);
-/// ```
-#[macro_export]
-#[stable(feature = "rust1", since = "1.0.0")]
-macro_rules! debug_assert_eq {
- ($($arg:tt)*) => (if $crate::cfg!(debug_assertions) { $crate::assert_eq!($($arg)*); })
-}
-
-/// Asserts that two expressions are not equal to each other.
-///
-/// On panic, this macro will print the values of the expressions with their
-/// debug representations.
-///
-/// Unlike [`assert_ne!`], `debug_assert_ne!` statements are only enabled in non
-/// optimized builds by default. An optimized build will not execute
-/// `debug_assert_ne!` statements unless `-C debug-assertions` is passed to the
-/// compiler. This makes `debug_assert_ne!` useful for checks that are too
-/// expensive to be present in a release build but may be helpful during
-/// development. The result of expanding `debug_assert_ne!` is always type checked.
-///
-/// [`assert_ne!`]: ../std/macro.assert_ne.html
-///
-/// # Examples
-///
-/// ```
-/// let a = 3;
-/// let b = 2;
-/// debug_assert_ne!(a, b);
-/// ```
-#[macro_export]
-#[stable(feature = "assert_ne", since = "1.13.0")]
-macro_rules! debug_assert_ne {
- ($($arg:tt)*) => (if $crate::cfg!(debug_assertions) { $crate::assert_ne!($($arg)*); })
-}
-
-/// Returns whether the given expression matches any of the given patterns.
-///
-/// Like in a `match` expression, the pattern can be optionally followed by `if`
-/// and a guard expression that has access to names bound by the pattern.
-///
-/// # Examples
-///
-/// ```
-/// #![feature(matches_macro)]
-///
-/// let foo = 'f';
-/// assert!(matches!(foo, 'A'..='Z' | 'a'..='z'));
-///
-/// let bar = Some(4);
-/// assert!(matches!(bar, Some(x) if x > 2));
-/// ```
-#[macro_export]
-#[unstable(feature = "matches_macro", issue = "65721")]
-macro_rules! matches {
- ($expression:expr, $( $pattern:pat )|+ $( if $guard: expr )?) => {
- match $expression {
- $( $pattern )|+ $( if $guard )? => true,
- _ => false
- }
- }
-}
-
-/// Unwraps a result or propagates its error.
-///
-/// The `?` operator was added to replace `try!` and should be used instead.
-/// Furthermore, `try` is a reserved word in Rust 2018, so if you must use
-/// it, you will need to use the [raw-identifier syntax][ris]: `r#try`.
-///
-/// [ris]: https://doc.rust-lang.org/nightly/rust-by-example/compatibility/raw_identifiers.html
-///
-/// `try!` matches the given [`Result`]. In case of the `Ok` variant, the
-/// expression has the value of the wrapped value.
-///
-/// In case of the `Err` variant, it retrieves the inner error. `try!` then
-/// performs conversion using `From`. This provides automatic conversion
-/// between specialized errors and more general ones. The resulting
-/// error is then immediately returned.
-///
-/// Because of the early return, `try!` can only be used in functions that
-/// return [`Result`].
-///
-/// [`Result`]: ../std/result/enum.Result.html
-///
-/// # Examples
-///
-/// ```
-/// use std::io;
-/// use std::fs::File;
-/// use std::io::prelude::*;
-///
-/// enum MyError {
-/// FileWriteError
-/// }
-///
-/// impl From<io::Error> for MyError {
-/// fn from(e: io::Error) -> MyError {
-/// MyError::FileWriteError
-/// }
-/// }
-///
-/// // The preferred method of quick returning Errors
-/// fn write_to_file_question() -> Result<(), MyError> {
-/// let mut file = File::create("my_best_friends.txt")?;
-/// file.write_all(b"This is a list of my best friends.")?;
-/// Ok(())
-/// }
-///
-/// // The previous method of quick returning Errors
-/// fn write_to_file_using_try() -> Result<(), MyError> {
-/// let mut file = r#try!(File::create("my_best_friends.txt"));
-/// r#try!(file.write_all(b"This is a list of my best friends."));
-/// Ok(())
-/// }
-///
-/// // This is equivalent to:
-/// fn write_to_file_using_match() -> Result<(), MyError> {
-/// let mut file = r#try!(File::create("my_best_friends.txt"));
-/// match file.write_all(b"This is a list of my best friends.") {
-/// Ok(v) => v,
-/// Err(e) => return Err(From::from(e)),
-/// }
-/// Ok(())
-/// }
-/// ```
-#[macro_export]
-#[stable(feature = "rust1", since = "1.0.0")]
-#[rustc_deprecated(since = "1.39.0", reason = "use the `?` operator instead")]
-#[doc(alias = "?")]
-macro_rules! r#try {
- ($expr:expr) => (match $expr {
- $crate::result::Result::Ok(val) => val,
- $crate::result::Result::Err(err) => {
- return $crate::result::Result::Err($crate::convert::From::from(err))
- }
- });
- ($expr:expr,) => ($crate::r#try!($expr));
-}
-
-/// Writes formatted data into a buffer.
-///
-/// This macro accepts a format string, a list of arguments, and a 'writer'. Arguments will be
-/// formatted according to the specified format string and the result will be passed to the writer.
-/// The writer may be any value with a `write_fmt` method; generally this comes from an
-/// implementation of either the [`std::fmt::Write`] or the [`std::io::Write`] trait. The macro
-/// returns whatever the `write_fmt` method returns; commonly a [`std::fmt::Result`], or an
-/// [`io::Result`].
-///
-/// See [`std::fmt`] for more information on the format string syntax.
-///
-/// [`std::fmt`]: ../std/fmt/index.html
-/// [`std::fmt::Write`]: ../std/fmt/trait.Write.html
-/// [`std::io::Write`]: ../std/io/trait.Write.html
-/// [`std::fmt::Result`]: ../std/fmt/type.Result.html
-/// [`io::Result`]: ../std/io/type.Result.html
-///
-/// # Examples
-///
-/// ```
-/// use std::io::Write;
-///
-/// fn main() -> std::io::Result<()> {
-/// let mut w = Vec::new();
-/// write!(&mut w, "test")?;
-/// write!(&mut w, "formatted {}", "arguments")?;
-///
-/// assert_eq!(w, b"testformatted arguments");
-/// Ok(())
-/// }
-/// ```
-///
-/// A module can import both `std::fmt::Write` and `std::io::Write` and call `write!` on objects
-/// implementing either, as objects do not typically implement both. However, the module must
-/// import the traits qualified so their names do not conflict:
-///
-/// ```
-/// use std::fmt::Write as FmtWrite;
-/// use std::io::Write as IoWrite;
-///
-/// fn main() -> Result<(), Box<dyn std::error::Error>> {
-/// let mut s = String::new();
-/// let mut v = Vec::new();
-///
-/// write!(&mut s, "{} {}", "abc", 123)?; // uses fmt::Write::write_fmt
-/// write!(&mut v, "s = {:?}", s)?; // uses io::Write::write_fmt
-/// assert_eq!(v, b"s = \"abc 123\"");
-/// Ok(())
-/// }
-/// ```
-///
-/// Note: This macro can be used in `no_std` setups as well.
-/// In a `no_std` setup you are responsible for the implementation details of the components.
-///
-/// ```no_run
-/// # extern crate core;
-/// use core::fmt::Write;
-///
-/// struct Example;
-///
-/// impl Write for Example {
-/// fn write_str(&mut self, _s: &str) -> core::fmt::Result {
-/// unimplemented!();
-/// }
-/// }
-///
-/// let mut m = Example{};
-/// write!(&mut m, "Hello World").expect("Not written");
-/// ```
-#[macro_export]
-#[stable(feature = "rust1", since = "1.0.0")]
-macro_rules! write {
- ($dst:expr, $($arg:tt)*) => ($dst.write_fmt($crate::format_args!($($arg)*)))
-}
-
-/// Write formatted data into a buffer, with a newline appended.
-///
-/// On all platforms, the newline is the LINE FEED character (`\n`/`U+000A`) alone
-/// (no additional CARRIAGE RETURN (`\r`/`U+000D`).
-///
-/// For more information, see [`write!`]. For information on the format string syntax, see
-/// [`std::fmt`].
-///
-/// [`write!`]: macro.write.html
-/// [`std::fmt`]: ../std/fmt/index.html
-///
-///
-/// # Examples
-///
-/// ```
-/// use std::io::{Write, Result};
-///
-/// fn main() -> Result<()> {
-/// let mut w = Vec::new();
-/// writeln!(&mut w)?;
-/// writeln!(&mut w, "test")?;
-/// writeln!(&mut w, "formatted {}", "arguments")?;
-///
-/// assert_eq!(&w[..], "\ntest\nformatted arguments\n".as_bytes());
-/// Ok(())
-/// }
-/// ```
-///
-/// A module can import both `std::fmt::Write` and `std::io::Write` and call `write!` on objects
-/// implementing either, as objects do not typically implement both. However, the module must
-/// import the traits qualified so their names do not conflict:
-///
-/// ```
-/// use std::fmt::Write as FmtWrite;
-/// use std::io::Write as IoWrite;
-///
-/// fn main() -> Result<(), Box<dyn std::error::Error>> {
-/// let mut s = String::new();
-/// let mut v = Vec::new();
-///
-/// writeln!(&mut s, "{} {}", "abc", 123)?; // uses fmt::Write::write_fmt
-/// writeln!(&mut v, "s = {:?}", s)?; // uses io::Write::write_fmt
-/// assert_eq!(v, b"s = \"abc 123\\n\"\n");
-/// Ok(())
-/// }
-/// ```
-#[macro_export]
-#[stable(feature = "rust1", since = "1.0.0")]
-#[allow_internal_unstable(format_args_nl)]
-macro_rules! writeln {
- ($dst:expr) => (
- $crate::write!($dst, "\n")
- );
- ($dst:expr,) => (
- $crate::writeln!($dst)
- );
- ($dst:expr, $($arg:tt)*) => (
- $dst.write_fmt($crate::format_args_nl!($($arg)*))
- );
-}
-
-/// Indicates unreachable code.
-///
-/// This is useful any time that the compiler can't determine that some code is unreachable. For
-/// example:
-///
-/// * Match arms with guard conditions.
-/// * Loops that dynamically terminate.
-/// * Iterators that dynamically terminate.
-///
-/// If the determination that the code is unreachable proves incorrect, the
-/// program immediately terminates with a [`panic!`].
-///
-/// The unsafe counterpart of this macro is the [`unreachable_unchecked`] function, which
-/// will cause undefined behavior if the code is reached.
-///
-/// [`panic!`]: ../std/macro.panic.html
-/// [`unreachable_unchecked`]: ../std/hint/fn.unreachable_unchecked.html
-/// [`std::hint`]: ../std/hint/index.html
-///
-/// # Panics
-///
-/// This will always [`panic!`]
-///
-/// [`panic!`]: ../std/macro.panic.html
-///
-/// # Examples
-///
-/// Match arms:
-///
-/// ```
-/// # #[allow(dead_code)]
-/// fn foo(x: Option<i32>) {
-/// match x {
-/// Some(n) if n >= 0 => println!("Some(Non-negative)"),
-/// Some(n) if n < 0 => println!("Some(Negative)"),
-/// Some(_) => unreachable!(), // compile error if commented out
-/// None => println!("None")
-/// }
-/// }
-/// ```
-///
-/// Iterators:
-///
-/// ```
-/// # #[allow(dead_code)]
-/// fn divide_by_three(x: u32) -> u32 { // one of the poorest implementations of x/3
-/// for i in 0.. {
-/// if 3*i < i { panic!("u32 overflow"); }
-/// if x < 3*i { return i-1; }
-/// }
-/// unreachable!();
-/// }
-/// ```
-#[macro_export]
-#[stable(feature = "rust1", since = "1.0.0")]
-macro_rules! unreachable {
- () => ({
- panic!("internal error: entered unreachable code")
- });
- ($msg:expr) => ({
- $crate::unreachable!("{}", $msg)
- });
- ($msg:expr,) => ({
- $crate::unreachable!($msg)
- });
- ($fmt:expr, $($arg:tt)*) => ({
- panic!($crate::concat!("internal error: entered unreachable code: ", $fmt), $($arg)*)
- });
-}
-
-/// Indicates unfinished code by panicking with a message of "not yet implemented".
-///
-/// This allows the your code to type-check, which is useful if you are prototyping or
-/// implementing a trait that requires multiple methods which you don't plan of using all of.
-///
-/// There is no difference between `unimplemented!` and `todo!` apart from the
-/// name.
-///
-/// # Panics
-///
-/// This will always [panic!](macro.panic.html) because `unimplemented!` is just a
-/// shorthand for `panic!` with a fixed, specific message.
-///
-/// Like `panic!`, this macro has a second form for displaying custom values.
-///
-/// # Examples
-///
-/// Here's an example of some in-progress code. We have a trait `Foo`:
-///
-/// ```
-/// trait Foo {
-/// fn bar(&self) -> u8;
-/// fn baz(&self);
-/// fn qux(&self) -> Result<u64, ()>;
-/// }
-/// ```
-///
-/// We want to implement `Foo` for 'MyStruct', but so far we only know how to
-/// implement the `bar()` function. `baz()` and `qux()` will still need to be defined
-/// in our implementation of `Foo`, but we can use `unimplemented!` in their definitions
-/// to allow our code to compile.
-///
-/// In the meantime, we want to have our program stop running once these
-/// unimplemented functions are reached.
-///
-/// ```
-/// # trait Foo {
-/// # fn bar(&self) -> u8;
-/// # fn baz(&self);
-/// # fn qux(&self) -> Result<u64, ()>;
-/// # }
-/// struct MyStruct;
-///
-/// impl Foo for MyStruct {
-/// fn bar(&self) -> u8 {
-/// 1 + 1
-/// }
-///
-/// fn baz(&self) {
-/// // We aren't sure how to even start writing baz yet,
-/// // so we have no logic here at all.
-/// // This will display "thread 'main' panicked at 'not yet implemented'".
-/// unimplemented!();
-/// }
-///
-/// fn qux(&self) -> Result<u64, ()> {
-/// let n = self.bar();
-/// // We have some logic here,
-/// // so we can use unimplemented! to display what we have so far.
-/// // This will display:
-/// // "thread 'main' panicked at 'not yet implemented: we need to divide by 2'".
-/// unimplemented!("we need to divide by {}", n);
-/// }
-/// }
-///
-/// fn main() {
-/// let s = MyStruct;
-/// s.bar();
-/// }
-/// ```
-#[macro_export]
-#[stable(feature = "rust1", since = "1.0.0")]
-macro_rules! unimplemented {
- () => (panic!("not yet implemented"));
- ($($arg:tt)+) => (panic!("not yet implemented: {}", $crate::format_args!($($arg)+)));
-}
-
-/// Indicates unfinished code.
-///
-/// This can be useful if you are prototyping and are just looking to have your
-/// code typecheck.
-///
-/// There is no difference between `unimplemented!` and `todo!` apart from the
-/// name.
-///
-/// # Panics
-///
-/// This will always [panic!](macro.panic.html)
-///
-/// # Examples
-///
-/// Here's an example of some in-progress code. We have a trait `Foo`:
-///
-/// ```
-/// trait Foo {
-/// fn bar(&self);
-/// fn baz(&self);
-/// }
-/// ```
-///
-/// We want to implement `Foo` on one of our types, but we also want to work on
-/// just `bar()` first. In order for our code to compile, we need to implement
-/// `baz()`, so we can use `todo!`:
-///
-/// ```
-/// # trait Foo {
-/// # fn bar(&self);
-/// # fn baz(&self);
-/// # }
-/// struct MyStruct;
-///
-/// impl Foo for MyStruct {
-/// fn bar(&self) {
-/// // implementation goes here
-/// }
-///
-/// fn baz(&self) {
-/// // let's not worry about implementing baz() for now
-/// todo!();
-/// }
-/// }
-///
-/// fn main() {
-/// let s = MyStruct;
-/// s.bar();
-///
-/// // we aren't even using baz() yet, so this is fine.
-/// }
-/// ```
-#[macro_export]
-#[stable(feature = "todo_macro", since = "1.39.0")]
-macro_rules! todo {
- () => (panic!("not yet implemented"));
- ($($arg:tt)+) => (panic!("not yet implemented: {}", $crate::format_args!($($arg)+)));
-}
-
-/// Definitions of built-in macros.
-///
-/// Most of the macro properties (stability, visibility, etc.) are taken from the source code here,
-/// with exception of expansion functions transforming macro inputs into outputs,
-/// those functions are provided by the compiler.
-pub(crate) mod builtin {
-
- /// Causes compilation to fail with the given error message when encountered.
- ///
- /// This macro should be used when a crate uses a conditional compilation strategy to provide
- /// better error messages for erroneous conditions. It's the compiler-level form of [`panic!`],
- /// but emits an error during *compilation* rather than at *runtime*.
- ///
- /// # Examples
- ///
- /// Two such examples are macros and `#[cfg]` environments.
- ///
- /// Emit better compiler error if a macro is passed invalid values. Without the final branch,
- /// the compiler would still emit an error, but the error's message would not mention the two
- /// valid values.
- ///
- /// ```compile_fail
- /// macro_rules! give_me_foo_or_bar {
- /// (foo) => {};
- /// (bar) => {};
- /// ($x:ident) => {
- /// compile_error!("This macro only accepts `foo` or `bar`");
- /// }
- /// }
- ///
- /// give_me_foo_or_bar!(neither);
- /// // ^ will fail at compile time with message "This macro only accepts `foo` or `bar`"
- /// ```
- ///
- /// Emit compiler error if one of a number of features isn't available.
- ///
- /// ```compile_fail
- /// #[cfg(not(any(feature = "foo", feature = "bar")))]
- /// compile_error!("Either feature \"foo\" or \"bar\" must be enabled for this crate.");
- /// ```
- ///
- /// [`panic!`]: ../std/macro.panic.html
- #[stable(feature = "compile_error_macro", since = "1.20.0")]
- #[rustc_builtin_macro]
- #[macro_export]
- macro_rules! compile_error {
- ($msg:expr) => ({ /* compiler built-in */ });
- ($msg:expr,) => ({ /* compiler built-in */ })
- }
-
- /// Constructs parameters for the other string-formatting macros.
- ///
- /// This macro functions by taking a formatting string literal containing
- /// `{}` for each additional argument passed. `format_args!` prepares the
- /// additional parameters to ensure the output can be interpreted as a string
- /// and canonicalizes the arguments into a single type. Any value that implements
- /// the [`Display`] trait can be passed to `format_args!`, as can any
- /// [`Debug`] implementation be passed to a `{:?}` within the formatting string.
- ///
- /// This macro produces a value of type [`fmt::Arguments`]. This value can be
- /// passed to the macros within [`std::fmt`] for performing useful redirection.
- /// All other formatting macros ([`format!`], [`write!`], [`println!`], etc) are
- /// proxied through this one. `format_args!`, unlike its derived macros, avoids
- /// heap allocations.
- ///
- /// You can use the [`fmt::Arguments`] value that `format_args!` returns
- /// in `Debug` and `Display` contexts as seen below. The example also shows
- /// that `Debug` and `Display` format to the same thing: the interpolated
- /// format string in `format_args!`.
- ///
- /// ```rust
- /// let debug = format!("{:?}", format_args!("{} foo {:?}", 1, 2));
- /// let display = format!("{}", format_args!("{} foo {:?}", 1, 2));
- /// assert_eq!("1 foo 2", display);
- /// assert_eq!(display, debug);
- /// ```
- ///
- /// For more information, see the documentation in [`std::fmt`].
- ///
- /// [`Display`]: ../std/fmt/trait.Display.html
- /// [`Debug`]: ../std/fmt/trait.Debug.html
- /// [`fmt::Arguments`]: ../std/fmt/struct.Arguments.html
- /// [`std::fmt`]: ../std/fmt/index.html
- /// [`format!`]: ../std/macro.format.html
- /// [`write!`]: ../std/macro.write.html
- /// [`println!`]: ../std/macro.println.html
- ///
- /// # Examples
- ///
- /// ```
- /// use std::fmt;
- ///
- /// let s = fmt::format(format_args!("hello {}", "world"));
- /// assert_eq!(s, format!("hello {}", "world"));
- /// ```
- #[stable(feature = "rust1", since = "1.0.0")]
- #[allow_internal_unstable(fmt_internals)]
- #[rustc_builtin_macro]
- #[macro_export]
- macro_rules! format_args {
- ($fmt:expr) => ({ /* compiler built-in */ });
- ($fmt:expr, $($args:tt)*) => ({ /* compiler built-in */ })
- }
-
- /// Same as `format_args`, but adds a newline in the end.
- #[unstable(feature = "format_args_nl", issue = "0",
- reason = "`format_args_nl` is only for internal \
- language use and is subject to change")]
- #[allow_internal_unstable(fmt_internals)]
- #[rustc_builtin_macro]
- #[macro_export]
- macro_rules! format_args_nl {
- ($fmt:expr) => ({ /* compiler built-in */ });
- ($fmt:expr, $($args:tt)*) => ({ /* compiler built-in */ })
- }
-
- /// Inspects an environment variable at compile time.
- ///
- /// This macro will expand to the value of the named environment variable at
- /// 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!`]
- /// macro instead.
- ///
- /// [`option_env!`]: ../std/macro.option_env.html
- ///
- /// # Examples
- ///
- /// ```
- /// 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")]
- #[rustc_builtin_macro]
- #[macro_export]
- macro_rules! env {
- ($name:expr) => ({ /* compiler built-in */ });
- ($name:expr,) => ({ /* compiler built-in */ })
- }
-
- /// Optionally inspects an environment variable at compile time.
- ///
- /// If the named environment variable is present at compile time, this will
- /// expand into an expression of type `Option<&'static str>` whose value is
- /// `Some` of the value of the environment variable. If the environment
- /// variable is not present, then this will expand to `None`. See
- /// [`Option<T>`][option] for more information on this type.
- ///
- /// A compile time error is never emitted when using this macro regardless
- /// of whether the environment variable is present or not.
- ///
- /// [option]: ../std/option/enum.Option.html
- ///
- /// # Examples
- ///
- /// ```
- /// let key: Option<&'static str> = option_env!("SECRET_KEY");
- /// println!("the secret key might be: {:?}", key);
- /// ```
- #[stable(feature = "rust1", since = "1.0.0")]
- #[rustc_builtin_macro]
- #[macro_export]
- macro_rules! option_env {
- ($name:expr) => ({ /* compiler built-in */ });
- ($name:expr,) => ({ /* compiler built-in */ })
- }
-
- /// Concatenates identifiers into one identifier.
- ///
- /// This macro takes any number of comma-separated identifiers, and
- /// concatenates them all into one, yielding an expression which is a new
- /// identifier. Note that hygiene makes it such that this macro cannot
- /// capture local variables. Also, as a general rule, macros are only
- /// allowed in item, statement or expression position. That means while
- /// you may use this macro for referring to existing variables, functions or
- /// modules etc, you cannot define a new one with it.
- ///
- /// # Examples
- ///
- /// ```
- /// #![feature(concat_idents)]
- ///
- /// # fn main() {
- /// fn foobar() -> u32 { 23 }
- ///
- /// let f = concat_idents!(foo, bar);
- /// println!("{}", f());
- ///
- /// // fn concat_idents!(new, fun, name) { } // not usable in this way!
- /// # }
- /// ```
- #[unstable(feature = "concat_idents", issue = "29599",
- reason = "`concat_idents` is not stable enough for use and is subject to change")]
- #[rustc_builtin_macro]
- #[macro_export]
- macro_rules! concat_idents {
- ($($e:ident),+) => ({ /* compiler built-in */ });
- ($($e:ident,)+) => ({ /* compiler built-in */ })
- }
-
- /// Concatenates literals into a static string slice.
- ///
- /// This macro takes any number of comma-separated literals, yielding an
- /// expression of type `&'static str` which represents all of the literals
- /// concatenated left-to-right.
- ///
- /// Integer and floating point literals are stringified in order to be
- /// concatenated.
- ///
- /// # Examples
- ///
- /// ```
- /// let s = concat!("test", 10, 'b', true);
- /// assert_eq!(s, "test10btrue");
- /// ```
- #[stable(feature = "rust1", since = "1.0.0")]
- #[rustc_builtin_macro]
- #[macro_export]
- macro_rules! concat {
- ($($e:expr),*) => ({ /* compiler built-in */ });
- ($($e:expr,)*) => ({ /* compiler built-in */ })
- }
-
- /// Expands to the line number on which it was invoked.
- ///
- /// With [`column!`] and [`file!`], these macros provide debugging information for
- /// developers about the location within the source.
- ///
- /// The expanded expression has type `u32` and is 1-based, so the first line
- /// in each file evaluates to 1, the second to 2, etc. This is consistent
- /// with error messages by common compilers or popular editors.
- /// The returned line is *not necessarily* the line of the `line!` invocation itself,
- /// but rather the first macro invocation leading up to the invocation
- /// of the `line!` macro.
- ///
- /// [`column!`]: macro.column.html
- /// [`file!`]: macro.file.html
- ///
- /// # Examples
- ///
- /// ```
- /// let current_line = line!();
- /// println!("defined on line: {}", current_line);
- /// ```
- #[stable(feature = "rust1", since = "1.0.0")]
- #[rustc_builtin_macro]
- #[macro_export]
- macro_rules! line { () => { /* compiler built-in */ } }
-
- /// Expands to the column number at which it was invoked.
- ///
- /// With [`line!`] and [`file!`], these macros provide debugging information for
- /// developers about the location within the source.
- ///
- /// The expanded expression has type `u32` and is 1-based, so the first column
- /// in each line evaluates to 1, the second to 2, etc. This is consistent
- /// with error messages by common compilers or popular editors.
- /// The returned column is *not necessarily* the line of the `column!` invocation itself,
- /// but rather the first macro invocation leading up to the invocation
- /// of the `column!` macro.
- ///
- /// [`line!`]: macro.line.html
- /// [`file!`]: macro.file.html
- ///
- /// # Examples
- ///
- /// ```
- /// let current_col = column!();
- /// println!("defined on column: {}", current_col);
- /// ```
- #[stable(feature = "rust1", since = "1.0.0")]
- #[rustc_builtin_macro]
- #[macro_export]
- macro_rules! column { () => { /* compiler built-in */ } }
-
- /// Expands to the file name in which it was invoked.
- ///
- /// With [`line!`] and [`column!`], these macros provide debugging information for
- /// developers about the location within the source.
- ///
- ///
- /// The expanded expression has type `&'static str`, and the returned file
- /// is not the invocation of the `file!` macro itself, but rather the
- /// first macro invocation leading up to the invocation of the `file!`
- /// macro.
- ///
- /// [`line!`]: macro.line.html
- /// [`column!`]: macro.column.html
- ///
- /// # Examples
- ///
- /// ```
- /// let this_file = file!();
- /// println!("defined in file: {}", this_file);
- /// ```
- #[stable(feature = "rust1", since = "1.0.0")]
- #[rustc_builtin_macro]
- #[macro_export]
- macro_rules! file { () => { /* compiler built-in */ } }
-
- /// Stringifies its arguments.
- ///
- /// This macro will yield an expression of type `&'static str` which is the
- /// stringification of all the tokens passed to the macro. No restrictions
- /// are placed on the syntax of the macro invocation itself.
- ///
- /// Note that the expanded results of the input tokens may change in the
- /// future. You should be careful if you rely on the output.
- ///
- /// # Examples
- ///
- /// ```
- /// let one_plus_one = stringify!(1 + 1);
- /// assert_eq!(one_plus_one, "1 + 1");
- /// ```
- #[stable(feature = "rust1", since = "1.0.0")]
- #[rustc_builtin_macro]
- #[macro_export]
- macro_rules! stringify { ($($t:tt)*) => { /* compiler built-in */ } }
-
- /// Includes a utf8-encoded file as a string.
- ///
- /// The file is located relative to the current file. (similarly to how
- /// modules are found)
- ///
- /// This macro will yield an expression of type `&'static str` which is the
- /// contents of the file.
- ///
- /// # Examples
- ///
- /// Assume there are two files in the same directory with the following
- /// contents:
- ///
- /// File 'spanish.in':
- ///
- /// ```text
- /// adiós
- /// ```
- ///
- /// File 'main.rs':
- ///
- /// ```ignore (cannot-doctest-external-file-dependency)
- /// fn main() {
- /// let my_str = include_str!("spanish.in");
- /// assert_eq!(my_str, "adiós\n");
- /// print!("{}", my_str);
- /// }
- /// ```
- ///
- /// Compiling 'main.rs' and running the resulting binary will print "adiós".
- #[stable(feature = "rust1", since = "1.0.0")]
- #[rustc_builtin_macro]
- #[macro_export]
- macro_rules! include_str {
- ($file:expr) => ({ /* compiler built-in */ });
- ($file:expr,) => ({ /* compiler built-in */ })
- }
-
- /// Includes a file as a reference to a byte array.
- ///
- /// The file is located relative to the current file. (similarly to how
- /// modules are found)
- ///
- /// This macro will yield an expression of type `&'static [u8; N]` which is
- /// the contents of the file.
- ///
- /// # Examples
- ///
- /// Assume there are two files in the same directory with the following
- /// contents:
- ///
- /// File 'spanish.in':
- ///
- /// ```text
- /// adiós
- /// ```
- ///
- /// File 'main.rs':
- ///
- /// ```ignore (cannot-doctest-external-file-dependency)
- /// fn main() {
- /// let bytes = include_bytes!("spanish.in");
- /// assert_eq!(bytes, b"adi\xc3\xb3s\n");
- /// print!("{}", String::from_utf8_lossy(bytes));
- /// }
- /// ```
- ///
- /// Compiling 'main.rs' and running the resulting binary will print "adiós".
- #[stable(feature = "rust1", since = "1.0.0")]
- #[rustc_builtin_macro]
- #[macro_export]
- macro_rules! include_bytes {
- ($file:expr) => ({ /* compiler built-in */ });
- ($file:expr,) => ({ /* compiler built-in */ })
- }
-
- /// Expands to a string that represents the current module path.
- ///
- /// The current module path can be thought of as the hierarchy of modules
- /// leading back up to the crate root. The first component of the path
- /// returned is the name of the crate currently being compiled.
- ///
- /// # Examples
- ///
- /// ```
- /// mod test {
- /// pub fn foo() {
- /// assert!(module_path!().ends_with("test"));
- /// }
- /// }
- ///
- /// test::foo();
- /// ```
- #[stable(feature = "rust1", since = "1.0.0")]
- #[rustc_builtin_macro]
- #[macro_export]
- macro_rules! module_path { () => { /* compiler built-in */ } }
-
- /// Evaluates boolean combinations of configuration flags at compile-time.
- ///
- /// In addition to the `#[cfg]` attribute, this macro is provided to allow
- /// boolean expression evaluation of configuration flags. This frequently
- /// leads to less duplicated code.
- ///
- /// The syntax given to this macro is the same syntax as the [`cfg`]
- /// attribute.
- ///
- /// [`cfg`]: ../reference/conditional-compilation.html#the-cfg-attribute
- ///
- /// # Examples
- ///
- /// ```
- /// let my_directory = if cfg!(windows) {
- /// "windows-specific-directory"
- /// } else {
- /// "unix-directory"
- /// };
- /// ```
- #[stable(feature = "rust1", since = "1.0.0")]
- #[rustc_builtin_macro]
- #[macro_export]
- macro_rules! cfg { ($($cfg:tt)*) => { /* compiler built-in */ } }
-
- /// Parses a file as an expression or an item according to the context.
- ///
- /// The file is located relative to the current file (similarly to how
- /// modules are found).
- ///
- /// Using this macro is often a bad idea, because if the file is
- /// parsed as an expression, it is going to be placed in the
- /// surrounding code unhygienically. This could result in variables
- /// or functions being different from what the file expected if
- /// there are variables or functions that have the same name in
- /// the current file.
- ///
- /// # Examples
- ///
- /// Assume there are two files in the same directory with the following
- /// contents:
- ///
- /// File 'monkeys.in':
- ///
- /// ```ignore (only-for-syntax-highlight)
- /// ['🙈', '🙊', '🙉']
- /// .iter()
- /// .cycle()
- /// .take(6)
- /// .collect::<String>()
- /// ```
- ///
- /// File 'main.rs':
- ///
- /// ```ignore (cannot-doctest-external-file-dependency)
- /// fn main() {
- /// let my_string = include!("monkeys.in");
- /// assert_eq!("🙈🙊🙉🙈🙊🙉", my_string);
- /// println!("{}", my_string);
- /// }
- /// ```
- ///
- /// Compiling 'main.rs' and running the resulting binary will print
- /// "🙈🙊🙉🙈🙊🙉".
- #[stable(feature = "rust1", since = "1.0.0")]
- #[rustc_builtin_macro]
- #[macro_export]
- macro_rules! include {
- ($file:expr) => ({ /* compiler built-in */ });
- ($file:expr,) => ({ /* compiler built-in */ })
- }
-
- /// Asserts that a boolean expression is `true` at runtime.
- ///
- /// This will invoke the [`panic!`] macro if the provided expression cannot be
- /// evaluated to `true` at runtime.
- ///
- /// # Uses
- ///
- /// Assertions are always checked in both debug and release builds, and cannot
- /// be disabled. See [`debug_assert!`] for assertions that are not enabled in
- /// release builds by default.
- ///
- /// Unsafe code relies on `assert!` to enforce run-time invariants that, if
- /// violated could lead to unsafety.
- ///
- /// Other use-cases of `assert!` include testing and enforcing run-time
- /// invariants in safe code (whose violation cannot result in unsafety).
- ///
- /// # Custom Messages
- ///
- /// This macro has a second form, where a custom panic message can
- /// be provided with or without arguments for formatting. See [`std::fmt`]
- /// for syntax for this form.
- ///
- /// [`panic!`]: macro.panic.html
- /// [`debug_assert!`]: macro.debug_assert.html
- /// [`std::fmt`]: ../std/fmt/index.html
- ///
- /// # Examples
- ///
- /// ```
- /// // the panic message for these assertions is the stringified value of the
- /// // expression given.
- /// assert!(true);
- ///
- /// fn some_computation() -> bool { true } // a very simple function
- ///
- /// assert!(some_computation());
- ///
- /// // assert with a custom message
- /// let x = true;
- /// assert!(x, "x wasn't true!");
- ///
- /// let a = 3; let b = 27;
- /// assert!(a + b == 30, "a = {}, b = {}", a, b);
- /// ```
- #[stable(feature = "rust1", since = "1.0.0")]
- #[rustc_builtin_macro]
- #[macro_export]
- macro_rules! assert {
- ($cond:expr) => ({ /* compiler built-in */ });
- ($cond:expr,) => ({ /* compiler built-in */ });
- ($cond:expr, $($arg:tt)+) => ({ /* compiler built-in */ })
- }
-
- /// Inline assembly.
- ///
- /// Read the [unstable book] for the usage.
- ///
- /// [unstable book]: ../unstable-book/library-features/asm.html
- #[unstable(feature = "asm", issue = "29722",
- reason = "inline assembly is not stable enough for use and is subject to change")]
- #[rustc_builtin_macro]
- #[macro_export]
- macro_rules! asm { ("assembly template"
- : $("output"(operand),)*
- : $("input"(operand),)*
- : $("clobbers",)*
- : $("options",)*) => { /* compiler built-in */ } }
-
- /// Module-level inline assembly.
- #[unstable(feature = "global_asm", issue = "35119",
- reason = "`global_asm!` is not stable enough for use and is subject to change")]
- #[rustc_builtin_macro]
- #[macro_export]
- macro_rules! global_asm { ("assembly") => { /* compiler built-in */ } }
-
- /// Prints passed tokens into the standard output.
- #[unstable(feature = "log_syntax", issue = "29598",
- reason = "`log_syntax!` is not stable enough for use and is subject to change")]
- #[rustc_builtin_macro]
- #[macro_export]
- macro_rules! log_syntax { ($($arg:tt)*) => { /* compiler built-in */ } }
-
- /// Enables or disables tracing functionality used for debugging other macros.
- #[unstable(feature = "trace_macros", issue = "29598",
- reason = "`trace_macros` is not stable enough for use and is subject to change")]
- #[rustc_builtin_macro]
- #[macro_export]
- macro_rules! trace_macros {
- (true) => ({ /* compiler built-in */ });
- (false) => ({ /* compiler built-in */ })
- }
-
- /// Attribute macro applied to a function to turn it into a unit test.
- #[stable(feature = "rust1", since = "1.0.0")]
- #[allow_internal_unstable(test, rustc_attrs)]
- #[rustc_builtin_macro]
- pub macro test($item:item) { /* compiler built-in */ }
-
- /// Attribute macro applied to a function to turn it into a benchmark test.
- #[unstable(soft, feature = "test", issue = "50297",
- reason = "`bench` is a part of custom test frameworks which are unstable")]
- #[allow_internal_unstable(test, rustc_attrs)]
- #[rustc_builtin_macro]
- pub macro bench($item:item) { /* compiler built-in */ }
-
- /// An implementation detail of the `#[test]` and `#[bench]` macros.
- #[unstable(feature = "custom_test_frameworks", issue = "50297",
- reason = "custom test frameworks are an unstable feature")]
- #[allow_internal_unstable(test, rustc_attrs)]
- #[rustc_builtin_macro]
- pub macro test_case($item:item) { /* compiler built-in */ }
-
- /// Attribute macro applied to a static to register it as a global allocator.
- #[stable(feature = "global_allocator", since = "1.28.0")]
- #[allow_internal_unstable(rustc_attrs)]
- #[rustc_builtin_macro]
- pub macro global_allocator($item:item) { /* compiler built-in */ }
-
- /// Unstable implementation detail of the `rustc` compiler, do not use.
- #[rustc_builtin_macro]
- #[stable(feature = "rust1", since = "1.0.0")]
- #[allow_internal_unstable(core_intrinsics, libstd_sys_internals)]
- pub macro RustcDecodable($item:item) { /* compiler built-in */ }
-
- /// Unstable implementation detail of the `rustc` compiler, do not use.
- #[rustc_builtin_macro]
- #[stable(feature = "rust1", since = "1.0.0")]
- #[allow_internal_unstable(core_intrinsics)]
- pub macro RustcEncodable($item:item) { /* compiler built-in */ }
-}
--- /dev/null
+#[doc(include = "panic.md")]
+#[macro_export]
+#[allow_internal_unstable(core_panic,
+ // FIXME(anp, eddyb) `core_intrinsics` is used here to allow calling
+ // the `caller_location` intrinsic, but once `#[track_caller]` is implemented,
+ // `panicking::{panic, panic_fmt}` can use that instead of a `Location` argument.
+ core_intrinsics,
+)]
+#[stable(feature = "core", since = "1.6.0")]
+macro_rules! panic {
+ () => (
+ $crate::panic!("explicit panic")
+ );
+ ($msg:expr) => (
+ $crate::panicking::panic($msg, $crate::intrinsics::caller_location())
+ );
+ ($msg:expr,) => (
+ $crate::panic!($msg)
+ );
+ ($fmt:expr, $($arg:tt)+) => (
+ $crate::panicking::panic_fmt(
+ $crate::format_args!($fmt, $($arg)+),
+ $crate::intrinsics::caller_location(),
+ )
+ );
+}
+
+/// Asserts that two expressions are equal to each other (using [`PartialEq`]).
+///
+/// On panic, this macro will print the values of the expressions with their
+/// debug representations.
+///
+/// Like [`assert!`], this macro has a second form, where a custom
+/// panic message can be provided.
+///
+/// [`PartialEq`]: cmp/trait.PartialEq.html
+/// [`assert!`]: macro.assert.html
+///
+/// # Examples
+///
+/// ```
+/// let a = 3;
+/// let b = 1 + 2;
+/// assert_eq!(a, b);
+///
+/// assert_eq!(a, b, "we are testing addition with {} and {}", a, b);
+/// ```
+#[macro_export]
+#[stable(feature = "rust1", since = "1.0.0")]
+macro_rules! assert_eq {
+ ($left:expr, $right:expr) => ({
+ match (&$left, &$right) {
+ (left_val, right_val) => {
+ if !(*left_val == *right_val) {
+ // The reborrows below are intentional. Without them, the stack slot for the
+ // borrow is initialized even before the values are compared, leading to a
+ // noticeable slow down.
+ panic!(r#"assertion failed: `(left == right)`
+ left: `{:?}`,
+ right: `{:?}`"#, &*left_val, &*right_val)
+ }
+ }
+ }
+ });
+ ($left:expr, $right:expr,) => ({
+ $crate::assert_eq!($left, $right)
+ });
+ ($left:expr, $right:expr, $($arg:tt)+) => ({
+ match (&($left), &($right)) {
+ (left_val, right_val) => {
+ if !(*left_val == *right_val) {
+ // The reborrows below are intentional. Without them, the stack slot for the
+ // borrow is initialized even before the values are compared, leading to a
+ // noticeable slow down.
+ panic!(r#"assertion failed: `(left == right)`
+ left: `{:?}`,
+ right: `{:?}`: {}"#, &*left_val, &*right_val,
+ $crate::format_args!($($arg)+))
+ }
+ }
+ }
+ });
+}
+
+/// Asserts that two expressions are not equal to each other (using [`PartialEq`]).
+///
+/// On panic, this macro will print the values of the expressions with their
+/// debug representations.
+///
+/// Like [`assert!`], this macro has a second form, where a custom
+/// panic message can be provided.
+///
+/// [`PartialEq`]: cmp/trait.PartialEq.html
+/// [`assert!`]: macro.assert.html
+///
+/// # Examples
+///
+/// ```
+/// let a = 3;
+/// let b = 2;
+/// assert_ne!(a, b);
+///
+/// assert_ne!(a, b, "we are testing that the values are not equal");
+/// ```
+#[macro_export]
+#[stable(feature = "assert_ne", since = "1.13.0")]
+macro_rules! assert_ne {
+ ($left:expr, $right:expr) => ({
+ match (&$left, &$right) {
+ (left_val, right_val) => {
+ if *left_val == *right_val {
+ // The reborrows below are intentional. Without them, the stack slot for the
+ // borrow is initialized even before the values are compared, leading to a
+ // noticeable slow down.
+ panic!(r#"assertion failed: `(left != right)`
+ left: `{:?}`,
+ right: `{:?}`"#, &*left_val, &*right_val)
+ }
+ }
+ }
+ });
+ ($left:expr, $right:expr,) => {
+ $crate::assert_ne!($left, $right)
+ };
+ ($left:expr, $right:expr, $($arg:tt)+) => ({
+ match (&($left), &($right)) {
+ (left_val, right_val) => {
+ if *left_val == *right_val {
+ // The reborrows below are intentional. Without them, the stack slot for the
+ // borrow is initialized even before the values are compared, leading to a
+ // noticeable slow down.
+ panic!(r#"assertion failed: `(left != right)`
+ left: `{:?}`,
+ right: `{:?}`: {}"#, &*left_val, &*right_val,
+ $crate::format_args!($($arg)+))
+ }
+ }
+ }
+ });
+}
+
+/// Asserts that a boolean expression is `true` at runtime.
+///
+/// This will invoke the [`panic!`] macro if the provided expression cannot be
+/// evaluated to `true` at runtime.
+///
+/// Like [`assert!`], this macro also has a second version, where a custom panic
+/// message can be provided.
+///
+/// # Uses
+///
+/// Unlike [`assert!`], `debug_assert!` statements are only enabled in non
+/// optimized builds by default. An optimized build will not execute
+/// `debug_assert!` statements unless `-C debug-assertions` is passed to the
+/// compiler. This makes `debug_assert!` useful for checks that are too
+/// expensive to be present in a release build but may be helpful during
+/// development. The result of expanding `debug_assert!` is always type checked.
+///
+/// An unchecked assertion allows a program in an inconsistent state to keep
+/// running, which might have unexpected consequences but does not introduce
+/// unsafety as long as this only happens in safe code. The performance cost
+/// of assertions, is however, not measurable in general. Replacing [`assert!`]
+/// with `debug_assert!` is thus only encouraged after thorough profiling, and
+/// more importantly, only in safe code!
+///
+/// [`panic!`]: macro.panic.html
+/// [`assert!`]: macro.assert.html
+///
+/// # Examples
+///
+/// ```
+/// // the panic message for these assertions is the stringified value of the
+/// // expression given.
+/// debug_assert!(true);
+///
+/// fn some_expensive_computation() -> bool { true } // a very simple function
+/// debug_assert!(some_expensive_computation());
+///
+/// // assert with a custom message
+/// let x = true;
+/// debug_assert!(x, "x wasn't true!");
+///
+/// let a = 3; let b = 27;
+/// debug_assert!(a + b == 30, "a = {}, b = {}", a, b);
+/// ```
+#[macro_export]
+#[stable(feature = "rust1", since = "1.0.0")]
+macro_rules! debug_assert {
+ ($($arg:tt)*) => (if $crate::cfg!(debug_assertions) { $crate::assert!($($arg)*); })
+}
+
+/// Asserts that two expressions are equal to each other.
+///
+/// On panic, this macro will print the values of the expressions with their
+/// debug representations.
+///
+/// Unlike [`assert_eq!`], `debug_assert_eq!` statements are only enabled in non
+/// optimized builds by default. An optimized build will not execute
+/// `debug_assert_eq!` statements unless `-C debug-assertions` is passed to the
+/// compiler. This makes `debug_assert_eq!` useful for checks that are too
+/// expensive to be present in a release build but may be helpful during
+/// development. The result of expanding `debug_assert_eq!` is always type checked.
+///
+/// [`assert_eq!`]: ../std/macro.assert_eq.html
+///
+/// # Examples
+///
+/// ```
+/// let a = 3;
+/// let b = 1 + 2;
+/// debug_assert_eq!(a, b);
+/// ```
+#[macro_export]
+#[stable(feature = "rust1", since = "1.0.0")]
+macro_rules! debug_assert_eq {
+ ($($arg:tt)*) => (if $crate::cfg!(debug_assertions) { $crate::assert_eq!($($arg)*); })
+}
+
+/// Asserts that two expressions are not equal to each other.
+///
+/// On panic, this macro will print the values of the expressions with their
+/// debug representations.
+///
+/// Unlike [`assert_ne!`], `debug_assert_ne!` statements are only enabled in non
+/// optimized builds by default. An optimized build will not execute
+/// `debug_assert_ne!` statements unless `-C debug-assertions` is passed to the
+/// compiler. This makes `debug_assert_ne!` useful for checks that are too
+/// expensive to be present in a release build but may be helpful during
+/// development. The result of expanding `debug_assert_ne!` is always type checked.
+///
+/// [`assert_ne!`]: ../std/macro.assert_ne.html
+///
+/// # Examples
+///
+/// ```
+/// let a = 3;
+/// let b = 2;
+/// debug_assert_ne!(a, b);
+/// ```
+#[macro_export]
+#[stable(feature = "assert_ne", since = "1.13.0")]
+macro_rules! debug_assert_ne {
+ ($($arg:tt)*) => (if $crate::cfg!(debug_assertions) { $crate::assert_ne!($($arg)*); })
+}
+
+/// Returns whether the given expression matches any of the given patterns.
+///
+/// Like in a `match` expression, the pattern can be optionally followed by `if`
+/// and a guard expression that has access to names bound by the pattern.
+///
+/// # Examples
+///
+/// ```
+/// #![feature(matches_macro)]
+///
+/// let foo = 'f';
+/// assert!(matches!(foo, 'A'..='Z' | 'a'..='z'));
+///
+/// let bar = Some(4);
+/// assert!(matches!(bar, Some(x) if x > 2));
+/// ```
+#[macro_export]
+#[unstable(feature = "matches_macro", issue = "65721")]
+macro_rules! matches {
+ ($expression:expr, $( $pattern:pat )|+ $( if $guard: expr )?) => {
+ match $expression {
+ $( $pattern )|+ $( if $guard )? => true,
+ _ => false
+ }
+ }
+}
+
+/// Unwraps a result or propagates its error.
+///
+/// The `?` operator was added to replace `try!` and should be used instead.
+/// Furthermore, `try` is a reserved word in Rust 2018, so if you must use
+/// it, you will need to use the [raw-identifier syntax][ris]: `r#try`.
+///
+/// [ris]: https://doc.rust-lang.org/nightly/rust-by-example/compatibility/raw_identifiers.html
+///
+/// `try!` matches the given [`Result`]. In case of the `Ok` variant, the
+/// expression has the value of the wrapped value.
+///
+/// In case of the `Err` variant, it retrieves the inner error. `try!` then
+/// performs conversion using `From`. This provides automatic conversion
+/// between specialized errors and more general ones. The resulting
+/// error is then immediately returned.
+///
+/// Because of the early return, `try!` can only be used in functions that
+/// return [`Result`].
+///
+/// [`Result`]: ../std/result/enum.Result.html
+///
+/// # Examples
+///
+/// ```
+/// use std::io;
+/// use std::fs::File;
+/// use std::io::prelude::*;
+///
+/// enum MyError {
+/// FileWriteError
+/// }
+///
+/// impl From<io::Error> for MyError {
+/// fn from(e: io::Error) -> MyError {
+/// MyError::FileWriteError
+/// }
+/// }
+///
+/// // The preferred method of quick returning Errors
+/// fn write_to_file_question() -> Result<(), MyError> {
+/// let mut file = File::create("my_best_friends.txt")?;
+/// file.write_all(b"This is a list of my best friends.")?;
+/// Ok(())
+/// }
+///
+/// // The previous method of quick returning Errors
+/// fn write_to_file_using_try() -> Result<(), MyError> {
+/// let mut file = r#try!(File::create("my_best_friends.txt"));
+/// r#try!(file.write_all(b"This is a list of my best friends."));
+/// Ok(())
+/// }
+///
+/// // This is equivalent to:
+/// fn write_to_file_using_match() -> Result<(), MyError> {
+/// let mut file = r#try!(File::create("my_best_friends.txt"));
+/// match file.write_all(b"This is a list of my best friends.") {
+/// Ok(v) => v,
+/// Err(e) => return Err(From::from(e)),
+/// }
+/// Ok(())
+/// }
+/// ```
+#[macro_export]
+#[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_deprecated(since = "1.39.0", reason = "use the `?` operator instead")]
+#[doc(alias = "?")]
+macro_rules! r#try {
+ ($expr:expr) => (match $expr {
+ $crate::result::Result::Ok(val) => val,
+ $crate::result::Result::Err(err) => {
+ return $crate::result::Result::Err($crate::convert::From::from(err))
+ }
+ });
+ ($expr:expr,) => ($crate::r#try!($expr));
+}
+
+/// Writes formatted data into a buffer.
+///
+/// This macro accepts a format string, a list of arguments, and a 'writer'. Arguments will be
+/// formatted according to the specified format string and the result will be passed to the writer.
+/// The writer may be any value with a `write_fmt` method; generally this comes from an
+/// implementation of either the [`std::fmt::Write`] or the [`std::io::Write`] trait. The macro
+/// returns whatever the `write_fmt` method returns; commonly a [`std::fmt::Result`], or an
+/// [`io::Result`].
+///
+/// See [`std::fmt`] for more information on the format string syntax.
+///
+/// [`std::fmt`]: ../std/fmt/index.html
+/// [`std::fmt::Write`]: ../std/fmt/trait.Write.html
+/// [`std::io::Write`]: ../std/io/trait.Write.html
+/// [`std::fmt::Result`]: ../std/fmt/type.Result.html
+/// [`io::Result`]: ../std/io/type.Result.html
+///
+/// # Examples
+///
+/// ```
+/// use std::io::Write;
+///
+/// fn main() -> std::io::Result<()> {
+/// let mut w = Vec::new();
+/// write!(&mut w, "test")?;
+/// write!(&mut w, "formatted {}", "arguments")?;
+///
+/// assert_eq!(w, b"testformatted arguments");
+/// Ok(())
+/// }
+/// ```
+///
+/// A module can import both `std::fmt::Write` and `std::io::Write` and call `write!` on objects
+/// implementing either, as objects do not typically implement both. However, the module must
+/// import the traits qualified so their names do not conflict:
+///
+/// ```
+/// use std::fmt::Write as FmtWrite;
+/// use std::io::Write as IoWrite;
+///
+/// fn main() -> Result<(), Box<dyn std::error::Error>> {
+/// let mut s = String::new();
+/// let mut v = Vec::new();
+///
+/// write!(&mut s, "{} {}", "abc", 123)?; // uses fmt::Write::write_fmt
+/// write!(&mut v, "s = {:?}", s)?; // uses io::Write::write_fmt
+/// assert_eq!(v, b"s = \"abc 123\"");
+/// Ok(())
+/// }
+/// ```
+///
+/// Note: This macro can be used in `no_std` setups as well.
+/// In a `no_std` setup you are responsible for the implementation details of the components.
+///
+/// ```no_run
+/// # extern crate core;
+/// use core::fmt::Write;
+///
+/// struct Example;
+///
+/// impl Write for Example {
+/// fn write_str(&mut self, _s: &str) -> core::fmt::Result {
+/// unimplemented!();
+/// }
+/// }
+///
+/// let mut m = Example{};
+/// write!(&mut m, "Hello World").expect("Not written");
+/// ```
+#[macro_export]
+#[stable(feature = "rust1", since = "1.0.0")]
+macro_rules! write {
+ ($dst:expr, $($arg:tt)*) => ($dst.write_fmt($crate::format_args!($($arg)*)))
+}
+
+/// Write formatted data into a buffer, with a newline appended.
+///
+/// On all platforms, the newline is the LINE FEED character (`\n`/`U+000A`) alone
+/// (no additional CARRIAGE RETURN (`\r`/`U+000D`).
+///
+/// For more information, see [`write!`]. For information on the format string syntax, see
+/// [`std::fmt`].
+///
+/// [`write!`]: macro.write.html
+/// [`std::fmt`]: ../std/fmt/index.html
+///
+///
+/// # Examples
+///
+/// ```
+/// use std::io::{Write, Result};
+///
+/// fn main() -> Result<()> {
+/// let mut w = Vec::new();
+/// writeln!(&mut w)?;
+/// writeln!(&mut w, "test")?;
+/// writeln!(&mut w, "formatted {}", "arguments")?;
+///
+/// assert_eq!(&w[..], "\ntest\nformatted arguments\n".as_bytes());
+/// Ok(())
+/// }
+/// ```
+///
+/// A module can import both `std::fmt::Write` and `std::io::Write` and call `write!` on objects
+/// implementing either, as objects do not typically implement both. However, the module must
+/// import the traits qualified so their names do not conflict:
+///
+/// ```
+/// use std::fmt::Write as FmtWrite;
+/// use std::io::Write as IoWrite;
+///
+/// fn main() -> Result<(), Box<dyn std::error::Error>> {
+/// let mut s = String::new();
+/// let mut v = Vec::new();
+///
+/// writeln!(&mut s, "{} {}", "abc", 123)?; // uses fmt::Write::write_fmt
+/// writeln!(&mut v, "s = {:?}", s)?; // uses io::Write::write_fmt
+/// assert_eq!(v, b"s = \"abc 123\\n\"\n");
+/// Ok(())
+/// }
+/// ```
+#[macro_export]
+#[stable(feature = "rust1", since = "1.0.0")]
+#[allow_internal_unstable(format_args_nl)]
+macro_rules! writeln {
+ ($dst:expr) => (
+ $crate::write!($dst, "\n")
+ );
+ ($dst:expr,) => (
+ $crate::writeln!($dst)
+ );
+ ($dst:expr, $($arg:tt)*) => (
+ $dst.write_fmt($crate::format_args_nl!($($arg)*))
+ );
+}
+
+/// Indicates unreachable code.
+///
+/// This is useful any time that the compiler can't determine that some code is unreachable. For
+/// example:
+///
+/// * Match arms with guard conditions.
+/// * Loops that dynamically terminate.
+/// * Iterators that dynamically terminate.
+///
+/// If the determination that the code is unreachable proves incorrect, the
+/// program immediately terminates with a [`panic!`].
+///
+/// The unsafe counterpart of this macro is the [`unreachable_unchecked`] function, which
+/// will cause undefined behavior if the code is reached.
+///
+/// [`panic!`]: ../std/macro.panic.html
+/// [`unreachable_unchecked`]: ../std/hint/fn.unreachable_unchecked.html
+/// [`std::hint`]: ../std/hint/index.html
+///
+/// # Panics
+///
+/// This will always [`panic!`]
+///
+/// [`panic!`]: ../std/macro.panic.html
+///
+/// # Examples
+///
+/// Match arms:
+///
+/// ```
+/// # #[allow(dead_code)]
+/// fn foo(x: Option<i32>) {
+/// match x {
+/// Some(n) if n >= 0 => println!("Some(Non-negative)"),
+/// Some(n) if n < 0 => println!("Some(Negative)"),
+/// Some(_) => unreachable!(), // compile error if commented out
+/// None => println!("None")
+/// }
+/// }
+/// ```
+///
+/// Iterators:
+///
+/// ```
+/// # #[allow(dead_code)]
+/// fn divide_by_three(x: u32) -> u32 { // one of the poorest implementations of x/3
+/// for i in 0.. {
+/// if 3*i < i { panic!("u32 overflow"); }
+/// if x < 3*i { return i-1; }
+/// }
+/// unreachable!();
+/// }
+/// ```
+#[macro_export]
+#[stable(feature = "rust1", since = "1.0.0")]
+macro_rules! unreachable {
+ () => ({
+ panic!("internal error: entered unreachable code")
+ });
+ ($msg:expr) => ({
+ $crate::unreachable!("{}", $msg)
+ });
+ ($msg:expr,) => ({
+ $crate::unreachable!($msg)
+ });
+ ($fmt:expr, $($arg:tt)*) => ({
+ panic!($crate::concat!("internal error: entered unreachable code: ", $fmt), $($arg)*)
+ });
+}
+
+/// Indicates unfinished code by panicking with a message of "not yet implemented".
+///
+/// This allows the your code to type-check, which is useful if you are prototyping or
+/// implementing a trait that requires multiple methods which you don't plan of using all of.
+///
+/// There is no difference between `unimplemented!` and `todo!` apart from the
+/// name.
+///
+/// # Panics
+///
+/// This will always [panic!](macro.panic.html) because `unimplemented!` is just a
+/// shorthand for `panic!` with a fixed, specific message.
+///
+/// Like `panic!`, this macro has a second form for displaying custom values.
+///
+/// # Examples
+///
+/// Here's an example of some in-progress code. We have a trait `Foo`:
+///
+/// ```
+/// trait Foo {
+/// fn bar(&self) -> u8;
+/// fn baz(&self);
+/// fn qux(&self) -> Result<u64, ()>;
+/// }
+/// ```
+///
+/// We want to implement `Foo` for 'MyStruct', but so far we only know how to
+/// implement the `bar()` function. `baz()` and `qux()` will still need to be defined
+/// in our implementation of `Foo`, but we can use `unimplemented!` in their definitions
+/// to allow our code to compile.
+///
+/// In the meantime, we want to have our program stop running once these
+/// unimplemented functions are reached.
+///
+/// ```
+/// # trait Foo {
+/// # fn bar(&self) -> u8;
+/// # fn baz(&self);
+/// # fn qux(&self) -> Result<u64, ()>;
+/// # }
+/// struct MyStruct;
+///
+/// impl Foo for MyStruct {
+/// fn bar(&self) -> u8 {
+/// 1 + 1
+/// }
+///
+/// fn baz(&self) {
+/// // We aren't sure how to even start writing baz yet,
+/// // so we have no logic here at all.
+/// // This will display "thread 'main' panicked at 'not yet implemented'".
+/// unimplemented!();
+/// }
+///
+/// fn qux(&self) -> Result<u64, ()> {
+/// let n = self.bar();
+/// // We have some logic here,
+/// // so we can use unimplemented! to display what we have so far.
+/// // This will display:
+/// // "thread 'main' panicked at 'not yet implemented: we need to divide by 2'".
+/// unimplemented!("we need to divide by {}", n);
+/// }
+/// }
+///
+/// fn main() {
+/// let s = MyStruct;
+/// s.bar();
+/// }
+/// ```
+#[macro_export]
+#[stable(feature = "rust1", since = "1.0.0")]
+macro_rules! unimplemented {
+ () => (panic!("not yet implemented"));
+ ($($arg:tt)+) => (panic!("not yet implemented: {}", $crate::format_args!($($arg)+)));
+}
+
+/// Indicates unfinished code.
+///
+/// This can be useful if you are prototyping and are just looking to have your
+/// code typecheck.
+///
+/// There is no difference between `unimplemented!` and `todo!` apart from the
+/// name.
+///
+/// # Panics
+///
+/// This will always [panic!](macro.panic.html)
+///
+/// # Examples
+///
+/// Here's an example of some in-progress code. We have a trait `Foo`:
+///
+/// ```
+/// trait Foo {
+/// fn bar(&self);
+/// fn baz(&self);
+/// }
+/// ```
+///
+/// We want to implement `Foo` on one of our types, but we also want to work on
+/// just `bar()` first. In order for our code to compile, we need to implement
+/// `baz()`, so we can use `todo!`:
+///
+/// ```
+/// # trait Foo {
+/// # fn bar(&self);
+/// # fn baz(&self);
+/// # }
+/// struct MyStruct;
+///
+/// impl Foo for MyStruct {
+/// fn bar(&self) {
+/// // implementation goes here
+/// }
+///
+/// fn baz(&self) {
+/// // let's not worry about implementing baz() for now
+/// todo!();
+/// }
+/// }
+///
+/// fn main() {
+/// let s = MyStruct;
+/// s.bar();
+///
+/// // we aren't even using baz() yet, so this is fine.
+/// }
+/// ```
+#[macro_export]
+#[stable(feature = "todo_macro", since = "1.39.0")]
+macro_rules! todo {
+ () => (panic!("not yet implemented"));
+ ($($arg:tt)+) => (panic!("not yet implemented: {}", $crate::format_args!($($arg)+)));
+}
+
+/// Definitions of built-in macros.
+///
+/// Most of the macro properties (stability, visibility, etc.) are taken from the source code here,
+/// with exception of expansion functions transforming macro inputs into outputs,
+/// those functions are provided by the compiler.
+pub(crate) mod builtin {
+
+ /// Causes compilation to fail with the given error message when encountered.
+ ///
+ /// This macro should be used when a crate uses a conditional compilation strategy to provide
+ /// better error messages for erroneous conditions. It's the compiler-level form of [`panic!`],
+ /// but emits an error during *compilation* rather than at *runtime*.
+ ///
+ /// # Examples
+ ///
+ /// Two such examples are macros and `#[cfg]` environments.
+ ///
+ /// Emit better compiler error if a macro is passed invalid values. Without the final branch,
+ /// the compiler would still emit an error, but the error's message would not mention the two
+ /// valid values.
+ ///
+ /// ```compile_fail
+ /// macro_rules! give_me_foo_or_bar {
+ /// (foo) => {};
+ /// (bar) => {};
+ /// ($x:ident) => {
+ /// compile_error!("This macro only accepts `foo` or `bar`");
+ /// }
+ /// }
+ ///
+ /// give_me_foo_or_bar!(neither);
+ /// // ^ will fail at compile time with message "This macro only accepts `foo` or `bar`"
+ /// ```
+ ///
+ /// Emit compiler error if one of a number of features isn't available.
+ ///
+ /// ```compile_fail
+ /// #[cfg(not(any(feature = "foo", feature = "bar")))]
+ /// compile_error!("Either feature \"foo\" or \"bar\" must be enabled for this crate.");
+ /// ```
+ ///
+ /// [`panic!`]: ../std/macro.panic.html
+ #[stable(feature = "compile_error_macro", since = "1.20.0")]
+ #[rustc_builtin_macro]
+ #[macro_export]
+ macro_rules! compile_error {
+ ($msg:expr) => ({ /* compiler built-in */ });
+ ($msg:expr,) => ({ /* compiler built-in */ })
+ }
+
+ /// Constructs parameters for the other string-formatting macros.
+ ///
+ /// This macro functions by taking a formatting string literal containing
+ /// `{}` for each additional argument passed. `format_args!` prepares the
+ /// additional parameters to ensure the output can be interpreted as a string
+ /// and canonicalizes the arguments into a single type. Any value that implements
+ /// the [`Display`] trait can be passed to `format_args!`, as can any
+ /// [`Debug`] implementation be passed to a `{:?}` within the formatting string.
+ ///
+ /// This macro produces a value of type [`fmt::Arguments`]. This value can be
+ /// passed to the macros within [`std::fmt`] for performing useful redirection.
+ /// All other formatting macros ([`format!`], [`write!`], [`println!`], etc) are
+ /// proxied through this one. `format_args!`, unlike its derived macros, avoids
+ /// heap allocations.
+ ///
+ /// You can use the [`fmt::Arguments`] value that `format_args!` returns
+ /// in `Debug` and `Display` contexts as seen below. The example also shows
+ /// that `Debug` and `Display` format to the same thing: the interpolated
+ /// format string in `format_args!`.
+ ///
+ /// ```rust
+ /// let debug = format!("{:?}", format_args!("{} foo {:?}", 1, 2));
+ /// let display = format!("{}", format_args!("{} foo {:?}", 1, 2));
+ /// assert_eq!("1 foo 2", display);
+ /// assert_eq!(display, debug);
+ /// ```
+ ///
+ /// For more information, see the documentation in [`std::fmt`].
+ ///
+ /// [`Display`]: ../std/fmt/trait.Display.html
+ /// [`Debug`]: ../std/fmt/trait.Debug.html
+ /// [`fmt::Arguments`]: ../std/fmt/struct.Arguments.html
+ /// [`std::fmt`]: ../std/fmt/index.html
+ /// [`format!`]: ../std/macro.format.html
+ /// [`write!`]: ../std/macro.write.html
+ /// [`println!`]: ../std/macro.println.html
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::fmt;
+ ///
+ /// let s = fmt::format(format_args!("hello {}", "world"));
+ /// assert_eq!(s, format!("hello {}", "world"));
+ /// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
+ #[allow_internal_unstable(fmt_internals)]
+ #[rustc_builtin_macro]
+ #[macro_export]
+ macro_rules! format_args {
+ ($fmt:expr) => ({ /* compiler built-in */ });
+ ($fmt:expr, $($args:tt)*) => ({ /* compiler built-in */ })
+ }
+
+ /// Same as `format_args`, but adds a newline in the end.
+ #[unstable(feature = "format_args_nl", issue = "0",
+ reason = "`format_args_nl` is only for internal \
+ language use and is subject to change")]
+ #[allow_internal_unstable(fmt_internals)]
+ #[rustc_builtin_macro]
+ #[macro_export]
+ macro_rules! format_args_nl {
+ ($fmt:expr) => ({ /* compiler built-in */ });
+ ($fmt:expr, $($args:tt)*) => ({ /* compiler built-in */ })
+ }
+
+ /// Inspects an environment variable at compile time.
+ ///
+ /// This macro will expand to the value of the named environment variable at
+ /// 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!`]
+ /// macro instead.
+ ///
+ /// [`option_env!`]: ../std/macro.option_env.html
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// 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")]
+ #[rustc_builtin_macro]
+ #[macro_export]
+ macro_rules! env {
+ ($name:expr) => ({ /* compiler built-in */ });
+ ($name:expr,) => ({ /* compiler built-in */ })
+ }
+
+ /// Optionally inspects an environment variable at compile time.
+ ///
+ /// If the named environment variable is present at compile time, this will
+ /// expand into an expression of type `Option<&'static str>` whose value is
+ /// `Some` of the value of the environment variable. If the environment
+ /// variable is not present, then this will expand to `None`. See
+ /// [`Option<T>`][option] for more information on this type.
+ ///
+ /// A compile time error is never emitted when using this macro regardless
+ /// of whether the environment variable is present or not.
+ ///
+ /// [option]: ../std/option/enum.Option.html
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// let key: Option<&'static str> = option_env!("SECRET_KEY");
+ /// println!("the secret key might be: {:?}", key);
+ /// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
+ #[rustc_builtin_macro]
+ #[macro_export]
+ macro_rules! option_env {
+ ($name:expr) => ({ /* compiler built-in */ });
+ ($name:expr,) => ({ /* compiler built-in */ })
+ }
+
+ /// Concatenates identifiers into one identifier.
+ ///
+ /// This macro takes any number of comma-separated identifiers, and
+ /// concatenates them all into one, yielding an expression which is a new
+ /// identifier. Note that hygiene makes it such that this macro cannot
+ /// capture local variables. Also, as a general rule, macros are only
+ /// allowed in item, statement or expression position. That means while
+ /// you may use this macro for referring to existing variables, functions or
+ /// modules etc, you cannot define a new one with it.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(concat_idents)]
+ ///
+ /// # fn main() {
+ /// fn foobar() -> u32 { 23 }
+ ///
+ /// let f = concat_idents!(foo, bar);
+ /// println!("{}", f());
+ ///
+ /// // fn concat_idents!(new, fun, name) { } // not usable in this way!
+ /// # }
+ /// ```
+ #[unstable(feature = "concat_idents", issue = "29599",
+ reason = "`concat_idents` is not stable enough for use and is subject to change")]
+ #[rustc_builtin_macro]
+ #[macro_export]
+ macro_rules! concat_idents {
+ ($($e:ident),+) => ({ /* compiler built-in */ });
+ ($($e:ident,)+) => ({ /* compiler built-in */ })
+ }
+
+ /// Concatenates literals into a static string slice.
+ ///
+ /// This macro takes any number of comma-separated literals, yielding an
+ /// expression of type `&'static str` which represents all of the literals
+ /// concatenated left-to-right.
+ ///
+ /// Integer and floating point literals are stringified in order to be
+ /// concatenated.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// let s = concat!("test", 10, 'b', true);
+ /// assert_eq!(s, "test10btrue");
+ /// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
+ #[rustc_builtin_macro]
+ #[macro_export]
+ macro_rules! concat {
+ ($($e:expr),*) => ({ /* compiler built-in */ });
+ ($($e:expr,)*) => ({ /* compiler built-in */ })
+ }
+
+ /// Expands to the line number on which it was invoked.
+ ///
+ /// With [`column!`] and [`file!`], these macros provide debugging information for
+ /// developers about the location within the source.
+ ///
+ /// The expanded expression has type `u32` and is 1-based, so the first line
+ /// in each file evaluates to 1, the second to 2, etc. This is consistent
+ /// with error messages by common compilers or popular editors.
+ /// The returned line is *not necessarily* the line of the `line!` invocation itself,
+ /// but rather the first macro invocation leading up to the invocation
+ /// of the `line!` macro.
+ ///
+ /// [`column!`]: macro.column.html
+ /// [`file!`]: macro.file.html
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// let current_line = line!();
+ /// println!("defined on line: {}", current_line);
+ /// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
+ #[rustc_builtin_macro]
+ #[macro_export]
+ macro_rules! line { () => { /* compiler built-in */ } }
+
+ /// Expands to the column number at which it was invoked.
+ ///
+ /// With [`line!`] and [`file!`], these macros provide debugging information for
+ /// developers about the location within the source.
+ ///
+ /// The expanded expression has type `u32` and is 1-based, so the first column
+ /// in each line evaluates to 1, the second to 2, etc. This is consistent
+ /// with error messages by common compilers or popular editors.
+ /// The returned column is *not necessarily* the line of the `column!` invocation itself,
+ /// but rather the first macro invocation leading up to the invocation
+ /// of the `column!` macro.
+ ///
+ /// [`line!`]: macro.line.html
+ /// [`file!`]: macro.file.html
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// let current_col = column!();
+ /// println!("defined on column: {}", current_col);
+ /// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
+ #[rustc_builtin_macro]
+ #[macro_export]
+ macro_rules! column { () => { /* compiler built-in */ } }
+
+ /// Expands to the file name in which it was invoked.
+ ///
+ /// With [`line!`] and [`column!`], these macros provide debugging information for
+ /// developers about the location within the source.
+ ///
+ ///
+ /// The expanded expression has type `&'static str`, and the returned file
+ /// is not the invocation of the `file!` macro itself, but rather the
+ /// first macro invocation leading up to the invocation of the `file!`
+ /// macro.
+ ///
+ /// [`line!`]: macro.line.html
+ /// [`column!`]: macro.column.html
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// let this_file = file!();
+ /// println!("defined in file: {}", this_file);
+ /// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
+ #[rustc_builtin_macro]
+ #[macro_export]
+ macro_rules! file { () => { /* compiler built-in */ } }
+
+ /// Stringifies its arguments.
+ ///
+ /// This macro will yield an expression of type `&'static str` which is the
+ /// stringification of all the tokens passed to the macro. No restrictions
+ /// are placed on the syntax of the macro invocation itself.
+ ///
+ /// Note that the expanded results of the input tokens may change in the
+ /// future. You should be careful if you rely on the output.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// let one_plus_one = stringify!(1 + 1);
+ /// assert_eq!(one_plus_one, "1 + 1");
+ /// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
+ #[rustc_builtin_macro]
+ #[macro_export]
+ macro_rules! stringify { ($($t:tt)*) => { /* compiler built-in */ } }
+
+ /// Includes a utf8-encoded file as a string.
+ ///
+ /// The file is located relative to the current file. (similarly to how
+ /// modules are found)
+ ///
+ /// This macro will yield an expression of type `&'static str` which is the
+ /// contents of the file.
+ ///
+ /// # Examples
+ ///
+ /// Assume there are two files in the same directory with the following
+ /// contents:
+ ///
+ /// File 'spanish.in':
+ ///
+ /// ```text
+ /// adiós
+ /// ```
+ ///
+ /// File 'main.rs':
+ ///
+ /// ```ignore (cannot-doctest-external-file-dependency)
+ /// fn main() {
+ /// let my_str = include_str!("spanish.in");
+ /// assert_eq!(my_str, "adiós\n");
+ /// print!("{}", my_str);
+ /// }
+ /// ```
+ ///
+ /// Compiling 'main.rs' and running the resulting binary will print "adiós".
+ #[stable(feature = "rust1", since = "1.0.0")]
+ #[rustc_builtin_macro]
+ #[macro_export]
+ macro_rules! include_str {
+ ($file:expr) => ({ /* compiler built-in */ });
+ ($file:expr,) => ({ /* compiler built-in */ })
+ }
+
+ /// Includes a file as a reference to a byte array.
+ ///
+ /// The file is located relative to the current file. (similarly to how
+ /// modules are found)
+ ///
+ /// This macro will yield an expression of type `&'static [u8; N]` which is
+ /// the contents of the file.
+ ///
+ /// # Examples
+ ///
+ /// Assume there are two files in the same directory with the following
+ /// contents:
+ ///
+ /// File 'spanish.in':
+ ///
+ /// ```text
+ /// adiós
+ /// ```
+ ///
+ /// File 'main.rs':
+ ///
+ /// ```ignore (cannot-doctest-external-file-dependency)
+ /// fn main() {
+ /// let bytes = include_bytes!("spanish.in");
+ /// assert_eq!(bytes, b"adi\xc3\xb3s\n");
+ /// print!("{}", String::from_utf8_lossy(bytes));
+ /// }
+ /// ```
+ ///
+ /// Compiling 'main.rs' and running the resulting binary will print "adiós".
+ #[stable(feature = "rust1", since = "1.0.0")]
+ #[rustc_builtin_macro]
+ #[macro_export]
+ macro_rules! include_bytes {
+ ($file:expr) => ({ /* compiler built-in */ });
+ ($file:expr,) => ({ /* compiler built-in */ })
+ }
+
+ /// Expands to a string that represents the current module path.
+ ///
+ /// The current module path can be thought of as the hierarchy of modules
+ /// leading back up to the crate root. The first component of the path
+ /// returned is the name of the crate currently being compiled.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// mod test {
+ /// pub fn foo() {
+ /// assert!(module_path!().ends_with("test"));
+ /// }
+ /// }
+ ///
+ /// test::foo();
+ /// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
+ #[rustc_builtin_macro]
+ #[macro_export]
+ macro_rules! module_path { () => { /* compiler built-in */ } }
+
+ /// Evaluates boolean combinations of configuration flags at compile-time.
+ ///
+ /// In addition to the `#[cfg]` attribute, this macro is provided to allow
+ /// boolean expression evaluation of configuration flags. This frequently
+ /// leads to less duplicated code.
+ ///
+ /// The syntax given to this macro is the same syntax as the [`cfg`]
+ /// attribute.
+ ///
+ /// [`cfg`]: ../reference/conditional-compilation.html#the-cfg-attribute
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// let my_directory = if cfg!(windows) {
+ /// "windows-specific-directory"
+ /// } else {
+ /// "unix-directory"
+ /// };
+ /// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
+ #[rustc_builtin_macro]
+ #[macro_export]
+ macro_rules! cfg { ($($cfg:tt)*) => { /* compiler built-in */ } }
+
+ /// Parses a file as an expression or an item according to the context.
+ ///
+ /// The file is located relative to the current file (similarly to how
+ /// modules are found).
+ ///
+ /// Using this macro is often a bad idea, because if the file is
+ /// parsed as an expression, it is going to be placed in the
+ /// surrounding code unhygienically. This could result in variables
+ /// or functions being different from what the file expected if
+ /// there are variables or functions that have the same name in
+ /// the current file.
+ ///
+ /// # Examples
+ ///
+ /// Assume there are two files in the same directory with the following
+ /// contents:
+ ///
+ /// File 'monkeys.in':
+ ///
+ /// ```ignore (only-for-syntax-highlight)
+ /// ['🙈', '🙊', '🙉']
+ /// .iter()
+ /// .cycle()
+ /// .take(6)
+ /// .collect::<String>()
+ /// ```
+ ///
+ /// File 'main.rs':
+ ///
+ /// ```ignore (cannot-doctest-external-file-dependency)
+ /// fn main() {
+ /// let my_string = include!("monkeys.in");
+ /// assert_eq!("🙈🙊🙉🙈🙊🙉", my_string);
+ /// println!("{}", my_string);
+ /// }
+ /// ```
+ ///
+ /// Compiling 'main.rs' and running the resulting binary will print
+ /// "🙈🙊🙉🙈🙊🙉".
+ #[stable(feature = "rust1", since = "1.0.0")]
+ #[rustc_builtin_macro]
+ #[macro_export]
+ macro_rules! include {
+ ($file:expr) => ({ /* compiler built-in */ });
+ ($file:expr,) => ({ /* compiler built-in */ })
+ }
+
+ /// Asserts that a boolean expression is `true` at runtime.
+ ///
+ /// This will invoke the [`panic!`] macro if the provided expression cannot be
+ /// evaluated to `true` at runtime.
+ ///
+ /// # Uses
+ ///
+ /// Assertions are always checked in both debug and release builds, and cannot
+ /// be disabled. See [`debug_assert!`] for assertions that are not enabled in
+ /// release builds by default.
+ ///
+ /// Unsafe code relies on `assert!` to enforce run-time invariants that, if
+ /// violated could lead to unsafety.
+ ///
+ /// Other use-cases of `assert!` include testing and enforcing run-time
+ /// invariants in safe code (whose violation cannot result in unsafety).
+ ///
+ /// # Custom Messages
+ ///
+ /// This macro has a second form, where a custom panic message can
+ /// be provided with or without arguments for formatting. See [`std::fmt`]
+ /// for syntax for this form.
+ ///
+ /// [`panic!`]: macro.panic.html
+ /// [`debug_assert!`]: macro.debug_assert.html
+ /// [`std::fmt`]: ../std/fmt/index.html
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// // the panic message for these assertions is the stringified value of the
+ /// // expression given.
+ /// assert!(true);
+ ///
+ /// fn some_computation() -> bool { true } // a very simple function
+ ///
+ /// assert!(some_computation());
+ ///
+ /// // assert with a custom message
+ /// let x = true;
+ /// assert!(x, "x wasn't true!");
+ ///
+ /// let a = 3; let b = 27;
+ /// assert!(a + b == 30, "a = {}, b = {}", a, b);
+ /// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
+ #[rustc_builtin_macro]
+ #[macro_export]
+ macro_rules! assert {
+ ($cond:expr) => ({ /* compiler built-in */ });
+ ($cond:expr,) => ({ /* compiler built-in */ });
+ ($cond:expr, $($arg:tt)+) => ({ /* compiler built-in */ })
+ }
+
+ /// Inline assembly.
+ ///
+ /// Read the [unstable book] for the usage.
+ ///
+ /// [unstable book]: ../unstable-book/library-features/asm.html
+ #[unstable(feature = "asm", issue = "29722",
+ reason = "inline assembly is not stable enough for use and is subject to change")]
+ #[rustc_builtin_macro]
+ #[macro_export]
+ macro_rules! asm { ("assembly template"
+ : $("output"(operand),)*
+ : $("input"(operand),)*
+ : $("clobbers",)*
+ : $("options",)*) => { /* compiler built-in */ } }
+
+ /// Module-level inline assembly.
+ #[unstable(feature = "global_asm", issue = "35119",
+ reason = "`global_asm!` is not stable enough for use and is subject to change")]
+ #[rustc_builtin_macro]
+ #[macro_export]
+ macro_rules! global_asm { ("assembly") => { /* compiler built-in */ } }
+
+ /// Prints passed tokens into the standard output.
+ #[unstable(feature = "log_syntax", issue = "29598",
+ reason = "`log_syntax!` is not stable enough for use and is subject to change")]
+ #[rustc_builtin_macro]
+ #[macro_export]
+ macro_rules! log_syntax { ($($arg:tt)*) => { /* compiler built-in */ } }
+
+ /// Enables or disables tracing functionality used for debugging other macros.
+ #[unstable(feature = "trace_macros", issue = "29598",
+ reason = "`trace_macros` is not stable enough for use and is subject to change")]
+ #[rustc_builtin_macro]
+ #[macro_export]
+ macro_rules! trace_macros {
+ (true) => ({ /* compiler built-in */ });
+ (false) => ({ /* compiler built-in */ })
+ }
+
+ /// Attribute macro applied to a function to turn it into a unit test.
+ #[stable(feature = "rust1", since = "1.0.0")]
+ #[allow_internal_unstable(test, rustc_attrs)]
+ #[rustc_builtin_macro]
+ pub macro test($item:item) { /* compiler built-in */ }
+
+ /// Attribute macro applied to a function to turn it into a benchmark test.
+ #[unstable(soft, feature = "test", issue = "50297",
+ reason = "`bench` is a part of custom test frameworks which are unstable")]
+ #[allow_internal_unstable(test, rustc_attrs)]
+ #[rustc_builtin_macro]
+ pub macro bench($item:item) { /* compiler built-in */ }
+
+ /// An implementation detail of the `#[test]` and `#[bench]` macros.
+ #[unstable(feature = "custom_test_frameworks", issue = "50297",
+ reason = "custom test frameworks are an unstable feature")]
+ #[allow_internal_unstable(test, rustc_attrs)]
+ #[rustc_builtin_macro]
+ pub macro test_case($item:item) { /* compiler built-in */ }
+
+ /// Attribute macro applied to a static to register it as a global allocator.
+ #[stable(feature = "global_allocator", since = "1.28.0")]
+ #[allow_internal_unstable(rustc_attrs)]
+ #[rustc_builtin_macro]
+ pub macro global_allocator($item:item) { /* compiler built-in */ }
+
+ /// Unstable implementation detail of the `rustc` compiler, do not use.
+ #[rustc_builtin_macro]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ #[allow_internal_unstable(core_intrinsics, libstd_sys_internals)]
+ pub macro RustcDecodable($item:item) { /* compiler built-in */ }
+
+ /// Unstable implementation detail of the `rustc` compiler, do not use.
+ #[rustc_builtin_macro]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ #[allow_internal_unstable(core_intrinsics)]
+ pub macro RustcEncodable($item:item) { /* compiler built-in */ }
+}
--- /dev/null
+Panics the current thread.
+
+This allows a program to terminate immediately and provide feedback
+to the caller of the program. `panic!` should be used when a program reaches
+an unrecoverable state.
+
+This macro is the perfect way to assert conditions in example code and in
+tests. `panic!` is closely tied with the `unwrap` method of both [`Option`]
+and [`Result`][runwrap] enums. Both implementations call `panic!` when they are set
+to None or Err variants.
+
+This macro is used to inject panic into a Rust thread, causing the thread to
+panic entirely. Each thread's panic can be reaped as the `Box<Any>` type,
+and the single-argument form of the `panic!` macro will be the value which
+is transmitted.
+
+[`Result`] enum is often a better solution for recovering from errors than
+using the `panic!` macro. This macro should be used to avoid proceeding using
+incorrect values, such as from external sources. Detailed information about
+error handling is found in the [book].
+
+The multi-argument form of this macro panics with a string and has the
+[`format!`] syntax for building a string.
+
+See also the macro [`compile_error!`], for raising errors during compilation.
+
+[runwrap]: ../std/result/enum.Result.html#method.unwrap
+[`Option`]: ../std/option/enum.Option.html#method.unwrap
+[`Result`]: ../std/result/enum.Result.html
+[`format!`]: ../std/macro.format.html
+[`compile_error!`]: ../std/macro.compile_error.html
+[book]: ../book/ch09-00-error-handling.html
+
+# Current implementation
+
+If the main thread panics it will terminate all your threads and end your
+program with code `101`.
+
+# Examples
+
+```should_panic
+# #![allow(unreachable_code)]
+panic!();
+panic!("this is a terrible mistake!");
+panic!(4); // panic with the value of 4 to be collected elsewhere
+panic!("this is a {} {message}", "fancy", message = "message");
+```
if #[cfg(miri)] {
#[path = "miri.rs"]
mod imp;
- // On MSVC we need the SEH lang items as well...
- // This should match the conditions of the `seh.rs` import below.
- #[cfg(all(target_env = "msvc", not(target_arch = "aarch64")))]
- #[allow(unused)]
- mod seh;
} else if #[cfg(target_os = "emscripten")] {
#[path = "emcc.rs"]
mod imp;
+#![allow(nonstandard_style)]
+
use core::any::Any;
use alloc::boxed::Box;
Box::from_raw(ptr)
}
-
// This is required by the compiler to exist (e.g., it's a lang item),
// but is never used by Miri. Therefore, we just use a stub here
#[lang = "eh_personality"]
fn rust_eh_personality() {
unsafe { core::intrinsics::abort() }
}
+
+// The rest is required on *some* targets to exist (specifically, MSVC targets that use SEH).
+// We just add it on all targets. Copied from `seh.rs`.
+#[repr(C)]
+pub struct _TypeDescriptor {
+ pub pVFTable: *const u8,
+ pub spare: *mut u8,
+ pub name: [u8; 11],
+}
+
+const TYPE_NAME: [u8; 11] = *b"rust_panic\0";
+
+#[cfg_attr(not(test), lang = "eh_catch_typeinfo")]
+static mut TYPE_DESCRIPTOR: _TypeDescriptor = _TypeDescriptor {
+ pVFTable: core::ptr::null(),
+ spare: core::ptr::null_mut(),
+ name: TYPE_NAME,
+};
DeriveHelper,
/// Single-segment custom attribute registered with `#[register_attr]`.
Registered,
- /// Single-segment custom attribute registered by a legacy plugin (`register_attribute`).
- LegacyPluginHelper,
}
#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, HashStable)]
NonMacroAttrKind::Tool => "tool attribute",
NonMacroAttrKind::DeriveHelper => "derive helper attribute",
NonMacroAttrKind::Registered => "explicitly registered attribute",
- NonMacroAttrKind::LegacyPluginHelper => "legacy plugin helper attribute",
}
}
pub fn is_used(self) -> bool {
match self {
NonMacroAttrKind::Tool | NonMacroAttrKind::DeriveHelper => true,
- NonMacroAttrKind::Builtin | NonMacroAttrKind::Registered |
- NonMacroAttrKind::LegacyPluginHelper => false,
+ NonMacroAttrKind::Builtin | NonMacroAttrKind::Registered => false,
}
}
}
ImplTraitContext::disallowed(),
),
unsafety: f.unsafety,
- abi: this.lower_abi(f.abi),
+ abi: this.lower_extern(f.ext),
decl: this.lower_fn_decl(&f.decl, None, false, None),
param_names: this.lower_fn_params_to_names(&f.decl),
}))
fn lower_foreign_mod(&mut self, fm: &ForeignMod) -> hir::ForeignMod {
hir::ForeignMod {
- abi: self.lower_abi(fm.abi),
+ abi: fm.abi.map_or(abi::Abi::C, |abi| self.lower_abi(abi)),
items: fm.items
.iter()
.map(|x| self.lower_foreign_item(x))
unsafety: h.unsafety,
asyncness: self.lower_asyncness(h.asyncness.node),
constness: h.constness.node,
- abi: self.lower_abi(h.abi),
+ abi: self.lower_extern(h.ext),
}
}
- pub(super) fn lower_abi(&mut self, abi: Abi) -> abi::Abi {
- abi::lookup(&abi.symbol.as_str()).unwrap_or_else(|| {
+ pub(super) fn lower_abi(&mut self, abi: StrLit) -> abi::Abi {
+ abi::lookup(&abi.symbol_unescaped.as_str()).unwrap_or_else(|| {
self.error_on_invalid_abi(abi);
abi::Abi::Rust
})
}
- fn error_on_invalid_abi(&self, abi: Abi) {
+ pub(super) fn lower_extern(&mut self, ext: Extern) -> abi::Abi {
+ match ext {
+ Extern::None => abi::Abi::Rust,
+ Extern::Implicit => abi::Abi::C,
+ Extern::Explicit(abi) => self.lower_abi(abi),
+ }
+ }
+
+ fn error_on_invalid_abi(&self, abi: StrLit) {
struct_span_err!(
self.sess,
abi.span,
use errors::emitter::HumanReadableErrorType;
use errors::annotate_snippet_emitter_writer::{AnnotateSnippetEmitterWriter};
use syntax::edition::Edition;
-use syntax::feature_gate::{self, AttributeType};
+use syntax::feature_gate;
use errors::json::JsonEmitter;
use syntax::source_map;
use syntax::sess::{ParseSess, ProcessCfgMod};
-use syntax::symbol::Symbol;
use syntax_pos::{MultiSpan, Span};
use rustc_target::spec::{PanicStrategy, RelroLevel, Target, TargetTriple};
/// in order to avoid redundantly verbose output (Issue #24690, #44953).
pub one_time_diagnostics: Lock<FxHashSet<(DiagnosticMessageId, Option<Span>, String)>>,
pub plugin_llvm_passes: OneThread<RefCell<Vec<String>>>,
- pub plugin_attributes: Lock<Vec<(Symbol, AttributeType)>>,
pub crate_types: Once<Vec<config::CrateType>>,
/// The `crate_disambiguator` is constructed out of all the `-C metadata`
/// arguments passed to the compiler. Its value together with the crate-name
let external_macro_backtrace = sopts.debugging_opts.external_macro_backtrace;
- let emitter = match diagnostics_output {
- DiagnosticOutput::Default => default_emitter(&sopts, registry, &source_map, None),
- DiagnosticOutput::Raw(write) => {
- default_emitter(&sopts, registry, &source_map, Some(write))
- }
+ let write_dest = match diagnostics_output {
+ DiagnosticOutput::Default => None,
+ DiagnosticOutput::Raw(write) => Some(write),
};
+ let emitter = default_emitter(&sopts, registry, &source_map, write_dest);
let diagnostic_handler = errors::Handler::with_emitter_and_flags(
emitter,
working_dir,
one_time_diagnostics: Default::default(),
plugin_llvm_passes: OneThread::new(RefCell::new(Vec::new())),
- plugin_attributes: Lock::new(Vec::new()),
crate_types: Once::new(),
crate_disambiguator: Once::new(),
features: Once::new(),
rustc_plugin_impl = { path = "../librustc_plugin" }
rustc_save_analysis = { path = "../librustc_save_analysis" }
rustc_codegen_utils = { path = "../librustc_codegen_utils" }
+rustc_error_codes = { path = "../librustc_error_codes" }
rustc_interface = { path = "../librustc_interface" }
rustc_serialize = { path = "../libserialize", package = "serialize" }
rustc_resolve = { path = "../librustc_resolve" }
use rustc::util::common::{set_time_depth, time, print_time_passes_entry, ErrorReported};
use rustc_metadata::locator;
use rustc_codegen_utils::codegen_backend::CodegenBackend;
-use errors::PResult;
+use errors::{PResult, registry::Registry};
use rustc_interface::interface;
use rustc_interface::util::get_codegen_sysroot;
use rustc_data_structures::sync::SeqCst;
}
}
+pub fn diagnostics_registry() -> Registry {
+ Registry::new(&rustc_error_codes::DIAGNOSTICS)
+}
+
// Parse args and run the compiler. This is the primary entry point for rustc.
// See comments on CompilerCalls below for details about the callbacks argument.
// The FileLoader provides a way to load files from sources other than the file system.
lint_caps: Default::default(),
register_lints: None,
override_queries: None,
+ registry: diagnostics_registry(),
};
callbacks.config(&mut config);
config
};
if let Some(ref code) = matches.opt_str("explain") {
- handle_explain(code, sopts.error_format);
+ handle_explain(diagnostics_registry(), code, sopts.error_format);
return Ok(());
}
lint_caps: Default::default(),
register_lints: None,
override_queries: None,
+ registry: diagnostics_registry(),
};
callbacks.config(&mut config);
}
}
-fn handle_explain(code: &str,
- output: ErrorOutputType) {
- let descriptions = rustc_interface::util::diagnostics_registry();
+fn handle_explain(registry: Registry, code: &str, output: ErrorOutputType) {
let normalised = if code.starts_with("E") {
code.to_string()
} else {
format!("E{0:0>4}", code)
};
- match descriptions.find_description(&normalised) {
+ match registry.find_description(&normalised) {
Some(ref description) => {
let mut is_in_code_block = false;
let mut text = String::new();
// Error messages' format must follow the RFC 1567 available here:
// https://github.com/rust-lang/rfcs/pull/1567
-crate::register_diagnostics! {
-
+register_diagnostics! {
E0001: include_str!("./error_codes/E0001.md"),
E0002: include_str!("./error_codes/E0002.md"),
E0004: include_str!("./error_codes/E0004.md"),
-//! This library is used to gather all error codes into one place. The goal
-//! being to make their maintenance easier.
+//! This library is used to gather all error codes into one place,
+//! the goal being to make their maintenance easier.
-#[macro_export]
macro_rules! register_diagnostics {
- ($($ecode:ident: $message:expr,)*) => (
- $crate::register_diagnostics!{$($ecode:$message,)* ;}
- );
-
($($ecode:ident: $message:expr,)* ; $($code:ident,)*) => (
pub static DIAGNOSTICS: &[(&str, &str)] = &[
$( (stringify!($ecode), $message), )*
];
$(
- pub const $ecode: &str = $message;
+ pub const $ecode: () = ();
)*
$(
pub const $code: () = ();
rustc_plugin = { path = "../librustc_plugin", package = "rustc_plugin_impl" }
rustc_privacy = { path = "../librustc_privacy" }
rustc_resolve = { path = "../librustc_resolve" }
-rustc_error_codes = { path = "../librustc_error_codes" }
tempfile = "3.0.5"
once_cell = "1"
use rustc_data_structures::OnDrop;
use rustc_data_structures::sync::Lrc;
use rustc_data_structures::fx::{FxHashSet, FxHashMap};
+use rustc_errors::registry::Registry;
use rustc_parse::new_parser_from_source_str;
use rustc::ty;
use std::path::PathBuf;
/// The second parameter is local providers and the third parameter is external providers.
pub override_queries:
Option<fn(&Session, &mut ty::query::Providers<'_>, &mut ty::query::Providers<'_>)>,
+
+ /// Registry of diagnostics codes.
+ pub registry: Registry,
}
-pub fn run_compiler_in_existing_thread_pool<F, R>(config: Config, f: F) -> R
-where
- F: FnOnce(&Compiler) -> R,
-{
+pub fn run_compiler_in_existing_thread_pool<R>(
+ config: Config,
+ f: impl FnOnce(&Compiler) -> R,
+) -> R {
+ let registry = &config.registry;
let (sess, codegen_backend, source_map) = util::create_session(
config.opts,
config.crate_cfg,
config.file_loader,
config.input_path.clone(),
config.lint_caps,
+ registry.clone(),
);
let compiler = Compiler {
};
let _sess_abort_error = OnDrop(|| {
- compiler.sess.diagnostic().print_error_count(&util::diagnostics_registry());
+ compiler.sess.diagnostic().print_error_count(registry);
});
f(&compiler)
}
-pub fn run_compiler<F, R>(mut config: Config, f: F) -> R
-where
- F: FnOnce(&Compiler) -> R + Send,
- R: Send,
-{
+pub fn run_compiler<R: Send>(mut config: Config, f: impl FnOnce(&Compiler) -> R + Send) -> R {
let stderr = config.stderr.take();
util::spawn_thread_pool(
config.opts.edition,
)
}
-pub fn default_thread_pool<F, R>(edition: edition::Edition, f: F) -> R
-where
- F: FnOnce() -> R + Send,
- R: Send,
-{
+pub fn default_thread_pool<R: Send>(edition: edition::Edition, f: impl FnOnce() -> R + Send) -> R {
// the 1 here is duplicating code in config.opts.debugging_opts.threads
// which also defaults to 1; it ultimately doesn't matter as the default
// isn't threaded, and just ignores this parameter
}
});
- let Registry {
- syntax_exts,
- llvm_passes,
- attributes,
- ..
- } = registry;
-
+ let Registry { syntax_exts, llvm_passes, .. } = registry;
*sess.plugin_llvm_passes.borrow_mut() = llvm_passes;
- *sess.plugin_attributes.borrow_mut() = attributes;
Ok((krate, PluginInfo { syntax_exts }, Lrc::new(lint_store)))
}
use rustc_errors::registry::Registry;
use rustc_metadata::dynamic_lib::DynamicLibrary;
use rustc_resolve::{self, Resolver};
-use rustc_error_codes;
use std::env;
use std::env::consts::{DLL_PREFIX, DLL_SUFFIX};
use std::io::{self, Write};
#[cfg(not(parallel_compiler))]
use std::{thread, panic};
-pub fn diagnostics_registry() -> Registry {
- let mut all_errors = Vec::new();
- all_errors.extend_from_slice(&rustc_error_codes::DIAGNOSTICS);
- // FIXME: need to figure out a way to get these back in here
- // all_errors.extend_from_slice(get_codegen_backend(sess).diagnostics());
-
- Registry::new(&all_errors)
-}
-
/// Adds `target_feature = "..."` cfgs for a variety of platform
/// specific features (SSE, NEON etc.).
///
file_loader: Option<Box<dyn FileLoader + Send + Sync + 'static>>,
input_path: Option<PathBuf>,
lint_caps: FxHashMap<lint::LintId, lint::Level>,
+ descriptions: Registry,
) -> (Lrc<Session>, Lrc<Box<dyn CodegenBackend>>, Lrc<SourceMap>) {
- let descriptions = diagnostics_registry();
-
let loader = file_loader.unwrap_or(box RealFileLoader);
let source_map = Lrc::new(SourceMap::with_file_loader(
loader,
}
}
- let plugin_attributes = cx.sess().plugin_attributes.borrow();
- for &(name, ty) in plugin_attributes.iter() {
- if ty == AttributeType::Whitelisted && attr.check_name(name) {
- debug!("{:?} (plugin attr) is whitelisted with ty {:?}", name, ty);
- break;
- }
- }
-
- let name = attr.name_or_empty();
if !attr::is_used(attr) {
debug!("emitting warning for: {:?}", attr);
cx.span_lint(UNUSED_ATTRIBUTES, attr.span, "unused attribute");
// Is it a builtin attribute that must be used at the crate level?
- let known_crate = attr_info.map(|&&(_, ty, ..)| {
- ty == AttributeType::CrateLevel
- }).unwrap_or(false);
-
- // Has a plugin registered this attribute as one that must be used at
- // the crate level?
- let plugin_crate = plugin_attributes.iter()
- .find(|&&(x, t)| name == x && AttributeType::CrateLevel == t)
- .is_some();
- if known_crate || plugin_crate {
+ if attr_info.map_or(false, |(_, ty, ..)| ty == &AttributeType::CrateLevel) {
let msg = match attr.style {
ast::AttrStyle::Outer => {
"crate-level attribute should be an inner attribute: add an exclamation \
use rustc_data_structures::fx::FxHashMap;
use rustc_index::vec::IndexVec;
use rustc::ty::layout::{
- LayoutOf, TyLayout, LayoutError, HasTyCtxt, TargetDataLayout, HasDataLayout,
+ LayoutOf, TyLayout, LayoutError, HasTyCtxt, TargetDataLayout, HasDataLayout, Size,
};
use crate::rustc::ty::subst::Subst;
use crate::const_eval::error_to_const_error;
use crate::transform::{MirPass, MirSource};
+/// The maximum number of bytes that we'll allocate space for a return value.
+const MAX_ALLOC_LIMIT: u64 = 1024;
+
pub struct ConstProp;
impl<'tcx> MirPass<'tcx> for ConstProp {
ecx
.layout_of(body.return_ty().subst(tcx, substs))
.ok()
- // Don't bother allocating memory for ZST types which have no values.
- .filter(|ret_layout| !ret_layout.is_zst())
+ // Don't bother allocating memory for ZST types which have no values
+ // or for large values.
+ .filter(|ret_layout| !ret_layout.is_zst() &&
+ ret_layout.size < Size::from_bytes(MAX_ALLOC_LIMIT))
.map(|ret_layout| ecx.allocate(ret_layout, MemoryKind::Stack));
ecx.push_stack_frame(
) -> Option<()> {
let span = source_info.span;
+ // #66397: Don't try to eval into large places as that can cause an OOM
+ if place_layout.size >= Size::from_bytes(MAX_ALLOC_LIMIT) {
+ return None;
+ }
+
let overflow_check = self.tcx.sess.overflow_checks();
// Perform any special handling for specific Rvalue types.
macro_rules! parse_lit {
() => {
- match self.parse_lit() {
- Ok(literal) => {
+ match self.parse_opt_lit() {
+ Some(literal) => {
hi = self.prev_span;
ex = ExprKind::Lit(literal);
}
- Err(mut err) => {
- err.cancel();
+ None => {
return Err(self.expected_expression_found());
}
}
self.maybe_recover_from_bad_qpath(expr, true)
}
- /// Matches `lit = true | false | token_lit`.
+ /// Returns a string literal if the next token is a string literal.
+ /// In case of error returns `Some(lit)` if the next token is a literal with a wrong kind,
+ /// and returns `None` if the next token is not literal at all.
+ pub fn parse_str_lit(&mut self) -> Result<ast::StrLit, Option<Lit>> {
+ match self.parse_opt_lit() {
+ Some(lit) => match lit.kind {
+ ast::LitKind::Str(symbol_unescaped, style) => Ok(ast::StrLit {
+ style,
+ symbol: lit.token.symbol,
+ suffix: lit.token.suffix,
+ span: lit.span,
+ symbol_unescaped,
+ }),
+ _ => Err(Some(lit)),
+ }
+ None => Err(None),
+ }
+ }
+
pub(super) fn parse_lit(&mut self) -> PResult<'a, Lit> {
+ self.parse_opt_lit().ok_or_else(|| {
+ let msg = format!("unexpected token: {}", self.this_token_descr());
+ self.span_fatal(self.token.span, &msg)
+ })
+ }
+
+ /// Matches `lit = true | false | token_lit`.
+ /// Returns `None` if the next token is not a literal.
+ pub(super) fn parse_opt_lit(&mut self) -> Option<Lit> {
let mut recovered = None;
if self.token == token::Dot {
- // Attempt to recover `.4` as `0.4`.
+ // Attempt to recover `.4` as `0.4`. We don't currently have any syntax where
+ // dot would follow an optional literal, so we do this unconditionally.
recovered = self.look_ahead(1, |next_token| {
if let token::Literal(token::Lit { kind: token::Integer, symbol, suffix })
= next_token.kind {
match Lit::from_token(token) {
Ok(lit) => {
self.bump();
- Ok(lit)
+ Some(lit)
}
Err(LitError::NotLiteral) => {
- let msg = format!("unexpected token: {}", self.this_token_descr());
- Err(self.span_fatal(token.span, &msg))
+ None
}
Err(err) => {
let span = token.span;
_ => unreachable!(),
};
self.bump();
- self.error_literal_from_token(err, lit, span);
+ self.report_lit_error(err, lit, span);
// Pack possible quotes and prefixes from the original literal into
// the error literal's symbol so they can be pretty-printed faithfully.
let suffixless_lit = token::Lit::new(lit.kind, lit.symbol, None);
let symbol = Symbol::intern(&suffixless_lit.to_string());
let lit = token::Lit::new(token::Err, symbol, lit.suffix);
- Lit::from_lit_token(lit, span).map_err(|_| unreachable!())
+ Some(Lit::from_lit_token(lit, span).unwrap_or_else(|_| unreachable!()))
}
}
}
- fn error_literal_from_token(&self, err: LitError, lit: token::Lit, span: Span) {
+ fn report_lit_error(&self, err: LitError, lit: token::Lit, span: Span) {
// Checks if `s` looks like i32 or u1234 etc.
fn looks_like_width_suffix(first_chars: &[char], s: &str) -> bool {
s.len() > 1
use crate::maybe_whole;
-use syntax::ast::{self, Abi, DUMMY_NODE_ID, Ident, Attribute, AttrKind, AttrStyle, AnonConst, Item};
+use syntax::ast::{self, DUMMY_NODE_ID, Ident, Attribute, AttrKind, AttrStyle, AnonConst, Item};
use syntax::ast::{ItemKind, ImplItem, ImplItemKind, TraitItem, TraitItemKind, UseTree, UseTreeKind};
-use syntax::ast::{PathSegment, IsAuto, Constness, IsAsync, Unsafety, Defaultness};
+use syntax::ast::{PathSegment, IsAuto, Constness, IsAsync, Unsafety, Defaultness, Extern, StrLit};
use syntax::ast::{Visibility, VisibilityKind, Mutability, FnHeader, ForeignItem, ForeignItemKind};
use syntax::ast::{Ty, TyKind, Generics, TraitRef, EnumDef, VariantData, StructField};
use syntax::ast::{Mac, MacDelimiter, Block, BindingMode, FnDecl, FnSig, SelfKind, Param};
return Ok(Some(self.parse_item_extern_crate(lo, vis, attrs)?));
}
- let abi = self.parse_opt_abi()?;
+ let abi = self.parse_abi();
if self.eat_keyword(kw::Fn) {
// EXTERN FUNCTION ITEM
unsafety: Unsafety::Normal,
asyncness: respan(fn_span, IsAsync::NotAsync),
constness: respan(fn_span, Constness::NotConst),
- abi,
+ ext: Extern::from_abi(abi),
};
return self.parse_item_fn(lo, vis, attrs, header);
} else if self.check(&token::OpenDelim(token::Brace)) {
if self.check_keyword(kw::Extern) {
self.sess.gated_spans.gate(sym::const_extern_fn, lo.to(self.token.span));
}
- let abi = self.parse_extern_abi()?;
+ let ext = self.parse_extern()?;
self.bump(); // `fn`
let header = FnHeader {
unsafety,
asyncness: respan(const_span, IsAsync::NotAsync),
constness: respan(const_span, Constness::Const),
- abi,
+ ext,
};
return self.parse_item_fn(lo, vis, attrs, header);
}
unsafety,
asyncness,
constness: respan(fn_span, Constness::NotConst),
- abi: Abi::new(sym::Rust, fn_span),
+ ext: Extern::None,
};
return self.parse_item_fn(lo, vis, attrs, header);
}
unsafety: Unsafety::Normal,
asyncness: respan(fn_span, IsAsync::NotAsync),
constness: respan(fn_span, Constness::NotConst),
- abi: Abi::new(sym::Rust, fn_span),
+ ext: Extern::None,
};
return self.parse_item_fn(lo, vis, attrs, header);
}
self.bump(); // `unsafe`
// `{` is also expected after `unsafe`; in case of error, include it in the diagnostic.
self.check(&token::OpenDelim(token::Brace));
- let abi = self.parse_extern_abi()?;
+ let ext = self.parse_extern()?;
self.expect_keyword(kw::Fn)?;
let fn_span = self.prev_span;
let header = FnHeader {
unsafety: Unsafety::Unsafe,
asyncness: respan(fn_span, IsAsync::NotAsync),
constness: respan(fn_span, Constness::NotConst),
- abi,
+ ext,
};
return self.parse_item_fn(lo, vis, attrs, header);
}
fn parse_item_foreign_mod(
&mut self,
lo: Span,
- abi: Abi,
+ abi: Option<StrLit>,
visibility: Visibility,
mut attrs: Vec<Attribute>,
extern_sp: Span,
attrs: Vec<Attribute>,
header: FnHeader,
) -> PResult<'a, Option<P<Item>>> {
+ let is_c_abi = match header.ext {
+ ast::Extern::None => false,
+ ast::Extern::Implicit => true,
+ ast::Extern::Explicit(abi) => abi.symbol_unescaped == sym::C,
+ };
let (ident, decl, generics) = self.parse_fn_sig(ParamCfg {
is_self_allowed: false,
- allow_c_variadic: header.abi.symbol == sym::C && header.unsafety == Unsafety::Unsafe,
+ // FIXME: Parsing should not depend on ABI or unsafety and
+ // the variadic parameter should always be parsed.
+ allow_c_variadic: is_c_abi && header.unsafety == Unsafety::Unsafe,
is_name_required: |_| true,
})?;
let (inner_attrs, body) = self.parse_inner_attrs_and_block()?;
}
let asyncness = respan(self.prev_span, asyncness);
let unsafety = self.parse_unsafety();
- let (constness, unsafety, abi) = if is_const_fn {
- (respan(const_span, Constness::Const), unsafety, Abi::default())
+ let (constness, unsafety, ext) = if is_const_fn {
+ (respan(const_span, Constness::Const), unsafety, Extern::None)
} else {
- let abi = self.parse_extern_abi()?;
- (respan(self.prev_span, Constness::NotConst), unsafety, abi)
+ let ext = self.parse_extern()?;
+ (respan(self.prev_span, Constness::NotConst), unsafety, ext)
};
if !self.eat_keyword(kw::Fn) {
// It is possible for `expect_one_of` to recover given the contents of
// account for this.
if !self.expect_one_of(&[], &[])? { unreachable!() }
}
- Ok(FnHeader { constness, unsafety, asyncness, abi })
+ Ok(FnHeader { constness, unsafety, asyncness, ext })
}
/// Parse the "signature", including the identifier, parameters, and generics of a function.
use crate::lexer::UnmatchedBrace;
use syntax::ast::{
- self, Abi, DUMMY_NODE_ID, AttrStyle, Attribute, CrateSugar, Ident,
- IsAsync, MacDelimiter, Mutability, StrStyle, Visibility, VisibilityKind, Unsafety,
+ self, DUMMY_NODE_ID, AttrStyle, Attribute, CrateSugar, Extern, Ident, StrLit,
+ IsAsync, MacDelimiter, Mutability, Visibility, VisibilityKind, Unsafety,
};
use syntax::print::pprust;
}
/// Parses `extern string_literal?`.
- /// If `extern` is not found, the Rust ABI is used.
- /// If `extern` is found and a `string_literal` does not follow, the C ABI is used.
- fn parse_extern_abi(&mut self) -> PResult<'a, Abi> {
+ fn parse_extern(&mut self) -> PResult<'a, Extern> {
Ok(if self.eat_keyword(kw::Extern) {
- self.parse_opt_abi()?
+ Extern::from_abi(self.parse_abi())
} else {
- Abi::default()
+ Extern::None
})
}
/// Parses a string literal as an ABI spec.
- /// If one is not found, the "C" ABI is used.
- fn parse_opt_abi(&mut self) -> PResult<'a, Abi> {
- let span = if self.token.can_begin_literal_or_bool() {
- let ast::Lit { span, kind, .. } = self.parse_lit()?;
- match kind {
- ast::LitKind::Str(symbol, _) => return Ok(Abi::new(symbol, span)),
- ast::LitKind::Err(_) => {}
+ fn parse_abi(&mut self) -> Option<StrLit> {
+ match self.parse_str_lit() {
+ Ok(str_lit) => Some(str_lit),
+ Err(Some(lit)) => match lit.kind {
+ ast::LitKind::Err(_) => None,
_ => {
- self.struct_span_err(span, "non-string ABI literal")
+ self.struct_span_err(lit.span, "non-string ABI literal")
.span_suggestion(
- span,
+ lit.span,
"specify the ABI with a string literal",
"\"C\"".to_string(),
Applicability::MaybeIncorrect,
)
.emit();
+ None
}
}
- span
- } else {
- self.prev_span
- };
- Ok(Abi::new(sym::C, span))
+ Err(None) => None,
+ }
}
/// We are parsing `async fn`. If we are on Rust 2015, emit an error.
self.look_ahead(1, |t| *t == token::OpenDelim(token::Brace) ||
*t == token::BinOp(token::Star))
}
-
- fn parse_optional_str(&mut self) -> Option<(Symbol, ast::StrStyle, Option<ast::Name>)> {
- let ret = match self.token.kind {
- token::Literal(token::Lit { kind: token::Str, symbol, suffix }) =>
- (symbol, ast::StrStyle::Cooked, suffix),
- token::Literal(token::Lit { kind: token::StrRaw(n), symbol, suffix }) =>
- (symbol, ast::StrStyle::Raw(n), suffix),
- _ => return None
- };
- self.bump();
- Some(ret)
- }
-
- pub fn parse_str(&mut self) -> PResult<'a, (Symbol, StrStyle)> {
- match self.parse_optional_str() {
- Some((s, style, suf)) => {
- let sp = self.prev_span;
- self.expect_no_suffix(sp, "a string literal", suf);
- Ok((s, style))
- }
- _ => {
- let msg = "expected string literal";
- let mut err = self.fatal(msg);
- err.span_label(self.token.span, msg);
- Err(err)
- }
- }
- }
}
crate fn make_unclosed_delims_error(
*/
let unsafety = self.parse_unsafety();
- let abi = self.parse_extern_abi()?;
+ let ext = self.parse_extern()?;
self.expect_keyword(kw::Fn)?;
let cfg = ParamCfg {
is_self_allowed: false,
};
let decl = self.parse_fn_decl(cfg, false)?;
Ok(TyKind::BareFn(P(BareFnTy {
- abi,
+ ext,
unsafety,
generic_params,
decl,
fn visit_struct_field(&mut self, field: &'tcx hir::StructField) {
if self.should_warn_about_field(&field) {
- self.warn_dead_code(field.hir_id, field.span, field.ident.name, "field", "used");
+ self.warn_dead_code(field.hir_id, field.span, field.ident.name, "field", "read");
}
intravisit::walk_struct_field(self, field);
}
use syntax_expand::base::MacroExpanderFn;
use syntax::symbol::Symbol;
use syntax::ast;
-use syntax::feature_gate::AttributeType;
use syntax_pos::Span;
use std::borrow::ToOwned;
#[doc(hidden)]
pub llvm_passes: Vec<String>,
-
- #[doc(hidden)]
- pub attributes: Vec<(Symbol, AttributeType)>,
}
impl<'a> Registry<'a> {
krate_span,
syntax_exts: vec![],
llvm_passes: vec![],
- attributes: vec![],
}
}
pub fn register_llvm_pass(&mut self, name: &str) {
self.llvm_passes.push(name.to_owned());
}
-
- /// Register an attribute with an attribute type.
- ///
- /// `Whitelisted` attributes will additionally not trigger the `unused_attribute`
- /// lint. `CrateLevel` attributes will not be allowed on anything other than a crate.
- pub fn register_attribute(&mut self, name: Symbol, ty: AttributeType) {
- self.attributes.push((name, ty));
- }
}
let mut suggestions = Vec::new();
self.visit_scopes(scope_set, parent_scope, ident, |this, scope, use_prelude, _| {
match scope {
- Scope::DeriveHelpers => {
+ Scope::DeriveHelpers(expn_id) => {
+ let res = Res::NonMacroAttr(NonMacroAttrKind::DeriveHelper);
+ if filter_fn(res) {
+ suggestions.extend(this.helper_attrs.get(&expn_id)
+ .into_iter().flatten().map(|ident| {
+ TypoSuggestion::from_res(ident.name, res)
+ }));
+ }
+ }
+ Scope::DeriveHelpersCompat => {
let res = Res::NonMacroAttr(NonMacroAttrKind::DeriveHelper);
if filter_fn(res) {
for derive in parent_scope.derives {
}));
}
}
- Scope::LegacyPluginHelpers => {
- let res = Res::NonMacroAttr(NonMacroAttrKind::LegacyPluginHelper);
- if filter_fn(res) {
- let plugin_attributes = this.session.plugin_attributes.borrow();
- suggestions.extend(plugin_attributes.iter().map(|(name, _)| {
- TypoSuggestion::from_res(*name, res)
- }));
- }
- }
Scope::ExternPrelude => {
suggestions.extend(this.extern_prelude.iter().filter_map(|(ident, _)| {
let res = Res::Def(DefKind::Mod, DefId::local(CRATE_DEF_INDEX));
use syntax::source_map::Spanned;
use syntax::visit::{self, Visitor};
use syntax_expand::base::SyntaxExtension;
-use syntax_pos::hygiene::{MacroKind, ExpnId, Transparency, SyntaxContext};
+use syntax_pos::hygiene::{MacroKind, ExpnId, ExpnKind, Transparency, SyntaxContext};
use syntax_pos::{Span, DUMMY_SP};
use errors::{Applicability, DiagnosticBuilder};
/// but not for late resolution yet.
#[derive(Clone, Copy)]
enum Scope<'a> {
- DeriveHelpers,
+ DeriveHelpers(ExpnId),
+ DeriveHelpersCompat,
MacroRules(LegacyScope<'a>),
CrateRoot,
Module(Module<'a>),
RegisteredAttrs,
MacroUsePrelude,
BuiltinAttrs,
- LegacyPluginHelpers,
ExternPrelude,
ToolPrelude,
StdLibPrelude,
/// Legacy scopes *produced* by expanding the macro invocations,
/// include all the `macro_rules` items and other invocations generated by them.
output_legacy_scopes: FxHashMap<ExpnId, LegacyScope<'a>>,
+ /// Helper attributes that are in scope for the given expansion.
+ helper_attrs: FxHashMap<ExpnId, Vec<Ident>>,
/// Avoid duplicated errors for "name already defined".
name_already_seen: FxHashMap<Name, Span>,
non_macro_attrs: [non_macro_attr(false), non_macro_attr(true)],
invocation_parent_scopes,
output_legacy_scopes: Default::default(),
+ helper_attrs: Default::default(),
macro_defs,
local_macro_def_scopes: FxHashMap::default(),
name_already_seen: FxHashMap::default(),
// 4b. "Standard library prelude" part implemented through `macro-use` (closed, controlled).
// 4c. Standard library prelude (de-facto closed, controlled).
// 6. Language prelude: builtin attributes (closed, controlled).
- // 4-6. Legacy plugin helpers (open, not controlled). Similar to derive helpers,
- // but introduced by legacy plugins using `register_attribute`. Priority is somewhere
- // in prelude, not sure where exactly (creates ambiguities with any other prelude names).
let rust_2015 = ident.span.rust_2015();
- let (ns, is_absolute_path) = match scope_set {
- ScopeSet::All(ns, _) => (ns, false),
- ScopeSet::AbsolutePath(ns) => (ns, true),
- ScopeSet::Macro(_) => (MacroNS, false),
+ let (ns, macro_kind, is_absolute_path) = match scope_set {
+ ScopeSet::All(ns, _) => (ns, None, false),
+ ScopeSet::AbsolutePath(ns) => (ns, None, true),
+ ScopeSet::Macro(macro_kind) => (MacroNS, Some(macro_kind), false),
};
// Jump out of trait or enum modules, they do not act as scopes.
let module = parent_scope.module.nearest_item_scope();
let mut scope = match ns {
_ if is_absolute_path => Scope::CrateRoot,
TypeNS | ValueNS => Scope::Module(module),
- MacroNS => Scope::DeriveHelpers,
+ MacroNS => Scope::DeriveHelpers(parent_scope.expansion),
};
let mut ident = ident.modern();
let mut use_prelude = !module.no_implicit_prelude;
loop {
let visit = match scope {
- Scope::DeriveHelpers => true,
+ // Derive helpers are not in scope when resolving derives in the same container.
+ Scope::DeriveHelpers(expn_id) =>
+ !(expn_id == parent_scope.expansion && macro_kind == Some(MacroKind::Derive)),
+ Scope::DeriveHelpersCompat => true,
Scope::MacroRules(..) => true,
Scope::CrateRoot => true,
Scope::Module(..) => true,
Scope::RegisteredAttrs => use_prelude,
Scope::MacroUsePrelude => use_prelude || rust_2015,
Scope::BuiltinAttrs => true,
- Scope::LegacyPluginHelpers => use_prelude || rust_2015,
Scope::ExternPrelude => use_prelude || is_absolute_path,
Scope::ToolPrelude => use_prelude,
Scope::StdLibPrelude => use_prelude || ns == MacroNS,
}
scope = match scope {
- Scope::DeriveHelpers =>
+ Scope::DeriveHelpers(expn_id) if expn_id != ExpnId::root() => {
+ // Derive helpers are not visible to code generated by bang or derive macros.
+ let expn_data = expn_id.expn_data();
+ match expn_data.kind {
+ ExpnKind::Root |
+ ExpnKind::Macro(MacroKind::Bang, _) |
+ ExpnKind::Macro(MacroKind::Derive, _) => Scope::DeriveHelpersCompat,
+ _ => Scope::DeriveHelpers(expn_data.parent),
+ }
+ }
+ Scope::DeriveHelpers(..) => Scope::DeriveHelpersCompat,
+ Scope::DeriveHelpersCompat =>
Scope::MacroRules(parent_scope.legacy),
Scope::MacroRules(legacy_scope) => match legacy_scope {
LegacyScope::Binding(binding) => Scope::MacroRules(
}
Scope::RegisteredAttrs => Scope::MacroUsePrelude,
Scope::MacroUsePrelude => Scope::StdLibPrelude,
- Scope::BuiltinAttrs => Scope::LegacyPluginHelpers,
- Scope::LegacyPluginHelpers => break, // nowhere else to search
+ Scope::BuiltinAttrs => break, // nowhere else to search
Scope::ExternPrelude if is_absolute_path => break,
Scope::ExternPrelude => Scope::ToolPrelude,
Scope::ToolPrelude => Scope::StdLibPrelude,
// - Derives in the container need to know whether one of them is a built-in `Copy`.
// FIXME: Try to avoid repeated resolutions for derives here and in expansion.
let mut exts = Vec::new();
+ let mut helper_attrs = Vec::new();
for path in derives {
exts.push(match self.resolve_macro_path(
path, Some(MacroKind::Derive), &parent_scope, true, force
) {
- Ok((Some(ext), _)) => ext,
+ Ok((Some(ext), _)) => {
+ let span = path.segments.last().unwrap().ident.span.modern();
+ helper_attrs.extend(
+ ext.helper_attrs.iter().map(|name| Ident::new(*name, span))
+ );
+ if ext.is_derive_copy {
+ self.add_derive_copy(invoc_id);
+ }
+ ext
+ }
Ok(_) | Err(Determinacy::Determined) => self.dummy_ext(MacroKind::Derive),
Err(Determinacy::Undetermined) => return Err(Indeterminate),
})
}
+ self.helper_attrs.insert(invoc_id, helper_attrs);
return Ok(InvocationRes::DeriveContainer(exts));
}
};
Flags::empty(),
));
let result = match scope {
- Scope::DeriveHelpers => {
+ Scope::DeriveHelpers(expn_id) => {
+ if let Some(attr) = this.helper_attrs.get(&expn_id).and_then(|attrs| {
+ attrs.iter().rfind(|i| ident == **i)
+ }) {
+ let binding = (Res::NonMacroAttr(NonMacroAttrKind::DeriveHelper),
+ ty::Visibility::Public, attr.span, expn_id)
+ .to_name_binding(this.arenas);
+ Ok((binding, Flags::empty()))
+ } else {
+ Err(Determinacy::Determined)
+ }
+ }
+ Scope::DeriveHelpersCompat => {
let mut result = Err(Determinacy::Determined);
for derive in parent_scope.derives {
let parent_scope = &ParentScope { derives: &[], ..*parent_scope };
} else {
Err(Determinacy::Determined)
}
- Scope::LegacyPluginHelpers => if this.session.plugin_attributes.borrow().iter()
- .any(|(name, _)| ident.name == *name) {
- let res = Res::NonMacroAttr(NonMacroAttrKind::LegacyPluginHelper);
- ok(res, DUMMY_SP, this.arenas)
- } else {
- Err(Determinacy::Determined)
- }
Scope::ExternPrelude => match this.extern_prelude_get(ident, !record_used) {
Some(binding) => Ok((binding, Flags::empty())),
None => Err(Determinacy::determined(
use rls_data::{SigElement, Signature};
use rustc::hir::def::{Res, DefKind};
-use syntax::ast::{self, NodeId};
+use syntax::ast::{self, Extern, NodeId};
use syntax::print::pprust;
-use syntax_pos::sym;
pub fn item_signature(item: &ast::Item, scx: &SaveContext<'_, '_>) -> Option<Signature> {
if !scx.config.signatures {
}
}
-fn push_abi(text: &mut String, abi: ast::Abi) {
- if abi.symbol != sym::Rust {
- text.push_str(&format!("extern \"{}\" ", abi.symbol));
+fn push_extern(text: &mut String, ext: Extern) {
+ match ext {
+ Extern::None => {}
+ Extern::Implicit => text.push_str("extern "),
+ Extern::Explicit(abi) => text.push_str(&format!("extern \"{}\" ", abi.symbol)),
}
}
if f.unsafety == ast::Unsafety::Unsafe {
text.push_str("unsafe ");
}
- push_abi(&mut text, f.abi);
+ push_extern(&mut text, f.ext);
text.push_str("fn(");
let mut defs = vec![];
if header.unsafety == ast::Unsafety::Unsafe {
text.push_str("unsafe ");
}
- push_abi(&mut text, header.abi);
+ push_extern(&mut text, header.ext);
text.push_str("fn ");
let mut sig = name_and_generics(text, offset, generics, self.id, self.ident, scx)?;
if m.header.unsafety == ast::Unsafety::Unsafe {
text.push_str("unsafe ");
}
- push_abi(&mut text, m.header.abi);
+ push_extern(&mut text, m.header.ext);
text.push_str("fn ");
let mut sig = name_and_generics(text, 0, generics, id, ident, scx)?;
use errors::json::JsonEmitter;
use syntax::symbol::sym;
use syntax_pos::DUMMY_SP;
-use errors;
use errors::emitter::{Emitter, EmitterWriter};
use std::cell::RefCell;
lint_caps,
register_lints: None,
override_queries: None,
+ registry: rustc_driver::diagnostics_registry(),
};
interface::run_compiler_in_existing_thread_pool(config, |compiler| {
extern crate env_logger;
extern crate rustc;
extern crate rustc_data_structures;
-extern crate rustc_index;
extern crate rustc_driver;
+extern crate rustc_error_codes;
+extern crate rustc_index;
extern crate rustc_resolve;
extern crate rustc_lint;
extern crate rustc_interface;
lint_caps: Default::default(),
register_lints: None,
override_queries: None,
+ registry: rustc_driver::diagnostics_registry(),
};
let mut test_args = options.test_args.clone();
/// look like this:
///
/// ```rust
-/// const WORDS: &str = "hello rust!";
+/// const WORDS: &'static str = "hello rust!";
/// ```
///
/// Thanks to static lifetime elision, you usually don't have to explicitly use 'static:
//! library. Each macro is available for use when linking against the standard
//! library.
-/// Panics the current thread.
-///
-/// This allows a program to terminate immediately and provide feedback
-/// to the caller of the program. `panic!` should be used when a program reaches
-/// an unrecoverable state.
-///
-/// This macro is the perfect way to assert conditions in example code and in
-/// tests. `panic!` is closely tied with the `unwrap` method of both [`Option`]
-/// and [`Result`][runwrap] enums. Both implementations call `panic!` when they are set
-/// to None or Err variants.
-///
-/// This macro is used to inject panic into a Rust thread, causing the thread to
-/// panic entirely. Each thread's panic can be reaped as the `Box<Any>` type,
-/// and the single-argument form of the `panic!` macro will be the value which
-/// is transmitted.
-///
-/// [`Result`] enum is often a better solution for recovering from errors than
-/// using the `panic!` macro. This macro should be used to avoid proceeding using
-/// incorrect values, such as from external sources. Detailed information about
-/// error handling is found in the [book].
-///
-/// The multi-argument form of this macro panics with a string and has the
-/// [`format!`] syntax for building a string.
-///
-/// See also the macro [`compile_error!`], for raising errors during compilation.
-///
-/// [runwrap]: ../std/result/enum.Result.html#method.unwrap
-/// [`Option`]: ../std/option/enum.Option.html#method.unwrap
-/// [`Result`]: ../std/result/enum.Result.html
-/// [`format!`]: ../std/macro.format.html
-/// [`compile_error!`]: ../std/macro.compile_error.html
-/// [book]: ../book/ch09-00-error-handling.html
-///
-/// # Current implementation
-///
-/// If the main thread panics it will terminate all your threads and end your
-/// program with code `101`.
-///
-/// # Examples
-///
-/// ```should_panic
-/// # #![allow(unreachable_code)]
-/// panic!();
-/// panic!("this is a terrible mistake!");
-/// panic!(4); // panic with the value of 4 to be collected elsewhere
-/// panic!("this is a {} {message}", "fancy", message = "message");
-/// ```
+#[doc(include = "../libcore/macros/panic.md")]
#[macro_export]
#[stable(feature = "rust1", since = "1.0.0")]
#[allow_internal_unstable(libstd_sys_internals)]
pub span: Span,
}
+/// Same as `Lit`, but restricted to string literals.
+#[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug)]
+pub struct StrLit {
+ /// The original literal token as written in source code.
+ pub style: StrStyle,
+ pub symbol: Symbol,
+ pub suffix: Option<Symbol>,
+ pub span: Span,
+ /// The unescaped "semantic" representation of the literal lowered from the original token.
+ /// FIXME: Remove this and only create the semantic representation during lowering to HIR.
+ pub symbol_unescaped: Symbol,
+}
+
+impl StrLit {
+ crate fn as_lit(&self) -> Lit {
+ let token_kind = match self.style {
+ StrStyle::Cooked => token::Str,
+ StrStyle::Raw(n) => token::StrRaw(n),
+ };
+ Lit {
+ token: token::Lit::new(token_kind, self.symbol, self.suffix),
+ span: self.span,
+ kind: LitKind::Str(self.symbol_unescaped, self.style),
+ }
+ }
+}
+
// Clippy uses Hash and PartialEq
/// Type of the integer literal based on provided suffix.
#[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug, Hash, PartialEq)]
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
pub struct BareFnTy {
pub unsafety: Unsafety,
- pub abi: Abi,
+ pub ext: Extern,
pub generic_params: Vec<GenericParam>,
pub decl: P<FnDecl>,
}
/// E.g., `extern { .. }` or `extern C { .. }`.
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
pub struct ForeignMod {
- pub abi: Abi,
+ pub abi: Option<StrLit>,
pub items: Vec<ForeignItem>,
}
}
}
-/// A reference to an ABI.
-///
-/// In AST our notion of an ABI is still syntactic unlike in `rustc_target::spec::abi::Abi`.
-#[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug, PartialEq)]
-pub struct Abi {
- pub symbol: Symbol,
- pub span: Span,
-}
-
-impl Abi {
- pub fn new(symbol: Symbol, span: Span) -> Self {
- Self { symbol, span }
- }
+/// `extern` qualifier on a function item or function type.
+#[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug)]
+pub enum Extern {
+ None,
+ Implicit,
+ Explicit(StrLit),
}
-impl Default for Abi {
- fn default() -> Self {
- Self::new(sym::Rust, DUMMY_SP)
+impl Extern {
+ pub fn from_abi(abi: Option<StrLit>) -> Extern {
+ abi.map_or(Extern::Implicit, Extern::Explicit)
}
}
pub unsafety: Unsafety,
pub asyncness: Spanned<IsAsync>,
pub constness: Spanned<Constness>,
- pub abi: Abi,
+ pub ext: Extern,
}
impl Default for FnHeader {
unsafety: Unsafety::Normal,
asyncness: dummy_spanned(IsAsync::NotAsync),
constness: dummy_spanned(Constness::NotConst),
- abi: Abi::default(),
+ ext: Extern::None,
}
}
}
break
}
- let meta = attr.meta().unwrap();
+ let meta = match attr.meta() {
+ Some(meta) => meta,
+ None => continue,
+ };
depr = match &meta.kind {
MetaItemKind::Word => Some(Deprecation { since: None, note: None }),
MetaItemKind::NameValue(..) => {
}
impl<'a> PostExpansionVisitor<'a> {
- fn check_abi(&self, abi: ast::Abi) {
- let ast::Abi { symbol, span } = abi;
+ fn check_abi(&self, abi: ast::StrLit) {
+ let ast::StrLit { symbol_unescaped, span, .. } = abi;
- match &*symbol.as_str() {
+ match &*symbol_unescaped.as_str() {
// Stable
"Rust" |
"C" |
}
}
+ fn check_extern(&self, ext: ast::Extern) {
+ if let ast::Extern::Explicit(abi) = ext {
+ self.check_abi(abi);
+ }
+ }
+
fn maybe_report_invalid_custom_discriminants(&self, variants: &[ast::Variant]) {
let has_fields = variants.iter().any(|variant| match variant.data {
VariantData::Tuple(..) | VariantData::Struct(..) => true,
fn visit_item(&mut self, i: &'a ast::Item) {
match i.kind {
ast::ItemKind::ForeignMod(ref foreign_module) => {
- self.check_abi(foreign_module.abi);
+ if let Some(abi) = foreign_module.abi {
+ self.check_abi(abi);
+ }
}
ast::ItemKind::Fn(..) => {
fn visit_ty(&mut self, ty: &'a ast::Ty) {
match ty.kind {
ast::TyKind::BareFn(ref bare_fn_ty) => {
- self.check_abi(bare_fn_ty.abi);
+ self.check_extern(bare_fn_ty.ext);
}
ast::TyKind::Never => {
gate_feature_post!(&self, never_type, ty.span,
// Stability of const fn methods are covered in
// `visit_trait_item` and `visit_impl_item` below; this is
// because default methods don't pass through this point.
- self.check_abi(header.abi);
+ self.check_extern(header.ext);
}
if fn_decl.c_variadic() {
match ti.kind {
ast::TraitItemKind::Method(ref sig, ref block) => {
if block.is_none() {
- self.check_abi(sig.header.abi);
+ self.check_extern(sig.header.ext);
}
if sig.decl.c_variadic() {
gate_feature_post!(&self, c_variadic, ti.span,
vis.visit_mt(mt);
}
TyKind::BareFn(bft) => {
- let BareFnTy { unsafety: _, abi: _, generic_params, decl } = bft.deref_mut();
+ let BareFnTy { unsafety: _, ext: _, generic_params, decl } = bft.deref_mut();
generic_params.flat_map_in_place(|param| vis.flat_map_generic_param(param));
vis.visit_fn_decl(decl);
}
}
pub fn noop_visit_fn_header<T: MutVisitor>(header: &mut FnHeader, vis: &mut T) {
- let FnHeader { unsafety: _, asyncness, constness: _, abi: _ } = header;
+ let FnHeader { unsafety: _, asyncness, constness: _, ext: _ } = header;
vis.visit_asyncness(&mut asyncness.node);
}
self.pclose();
}
ast::TyKind::BareFn(ref f) => {
- self.print_ty_fn(f.abi,
+ self.print_ty_fn(f.ext,
f.unsafety,
&f.decl,
None,
}
ast::ItemKind::ForeignMod(ref nmod) => {
self.head("extern");
- self.print_abi(nmod.abi);
+ if let Some(abi) = nmod.abi {
+ self.print_literal(&abi.as_lit());
+ self.nbsp();
+ }
self.bopen();
self.print_foreign_mod(nmod, &item.attrs);
self.bclose(item.span);
}
crate fn print_ty_fn(&mut self,
- abi: ast::Abi,
+ ext: ast::Extern,
unsafety: ast::Unsafety,
decl: &ast::FnDecl,
name: Option<ast::Ident>,
span: syntax_pos::DUMMY_SP,
};
self.print_fn(decl,
- ast::FnHeader { unsafety, abi, ..ast::FnHeader::default() },
+ ast::FnHeader { unsafety, ext, ..ast::FnHeader::default() },
name,
&generics,
&source_map::dummy_spanned(ast::VisibilityKind::Inherited));
self.print_asyncness(header.asyncness.node);
self.print_unsafety(header.unsafety);
- if header.abi.symbol != sym::Rust {
- self.word_nbsp("extern");
- self.print_abi(header.abi);
+ match header.ext {
+ ast::Extern::None => {}
+ ast::Extern::Implicit => {
+ self.word_nbsp("extern");
+ }
+ ast::Extern::Explicit(abi) => {
+ self.word_nbsp("extern");
+ self.print_literal(&abi.as_lit());
+ self.nbsp();
+ }
}
self.s.word("fn")
}
- fn print_abi(&mut self, abi: ast::Abi) {
- self.word_nbsp(format!("\"{}\"", abi.symbol));
- }
-
crate fn print_unsafety(&mut self, s: ast::Unsafety) {
match s {
ast::Unsafety::Normal => {},
use crate::base::*;
-use crate::proc_macro::{collect_derives, MarkAttrs};
+use crate::proc_macro::collect_derives;
use crate::hygiene::{ExpnId, SyntaxContext, ExpnData, ExpnKind};
use crate::mbe::macro_rules::annotate_err_with_kind;
use crate::placeholders::{placeholder, PlaceholderExpander};
let fragment = self.expand_invoc(invoc, &ext.kind);
self.collect_invocations(fragment, &[])
}
- InvocationRes::DeriveContainer(exts) => {
+ InvocationRes::DeriveContainer(_exts) => {
+ // FIXME: Consider using the derive resolutions (`_exts`) immediately,
+ // instead of enqueuing the derives to be resolved again later.
let (derives, item) = match invoc.kind {
InvocationKind::DeriveContainer { derives, item } => (derives, item),
_ => unreachable!(),
let mut item = self.fully_configure(item);
item.visit_attrs(|attrs| attrs.retain(|a| !a.has_name(sym::derive)));
- let mut helper_attrs = Vec::new();
- let mut has_copy = false;
- for ext in exts {
- helper_attrs.extend(&ext.helper_attrs);
- has_copy |= ext.is_derive_copy;
- }
- // Mark derive helpers inside this item as known and used.
- // FIXME: This is a hack, derive helpers should be integrated with regular name
- // resolution instead. For example, helpers introduced by a derive container
- // can be in scope for all code produced by that container's expansion.
- item.visit_with(&mut MarkAttrs(&helper_attrs));
- if has_copy {
- self.cx.resolver.add_derive_copy(invoc.expansion_data.id);
- }
let mut derive_placeholders = Vec::with_capacity(derives.len());
invocations.reserve(derives.len());
use crate::base::{self, *};
use crate::proc_macro_server;
-use syntax::ast::{self, ItemKind, Attribute, Mac};
-use syntax::attr::{mark_used, mark_known};
+use syntax::ast::{self, ItemKind};
use syntax::errors::{Applicability, FatalError};
use syntax::symbol::sym;
use syntax::token;
use syntax::tokenstream::{self, TokenStream};
-use syntax::visit::Visitor;
use rustc_data_structures::sync::Lrc;
use syntax_pos::{Span, DUMMY_SP};
}
}
-crate struct MarkAttrs<'a>(crate &'a [ast::Name]);
-
-impl<'a> Visitor<'a> for MarkAttrs<'a> {
- fn visit_attribute(&mut self, attr: &Attribute) {
- if let Some(ident) = attr.ident() {
- if self.0.contains(&ident.name) {
- mark_used(attr);
- mark_known(attr);
- }
- }
- }
-
- fn visit_mac(&mut self, _mac: &Mac) {}
-}
-
crate fn collect_derives(cx: &mut ExtCtxt<'_>, attrs: &mut Vec<ast::Attribute>) -> Vec<ast::Path> {
let mut result = Vec::new();
attrs.retain(|attr| {
//
use State::*;
+use errors::{DiagnosticBuilder, PResult};
use rustc_data_structures::thin_vec::ThinVec;
-
-use errors::DiagnosticBuilder;
-
-use syntax::ast;
-use syntax_expand::base::{self, *};
-use syntax::token::{self, Token};
+use rustc_parse::parser::Parser;
+use syntax_expand::base::*;
+use syntax_pos::Span;
+use syntax::{span_err, struct_span_err};
+use syntax::ast::{self, AsmDialect};
use syntax::ptr::P;
use syntax::symbol::{kw, sym, Symbol};
-use syntax::ast::AsmDialect;
-use syntax_pos::Span;
+use syntax::token::{self, Token};
use syntax::tokenstream::{self, TokenStream};
-use syntax::{span_err, struct_span_err};
use rustc_error_codes::*;
pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt<'_>,
sp: Span,
tts: TokenStream)
- -> Box<dyn base::MacResult + 'cx> {
+ -> Box<dyn MacResult + 'cx> {
let mut inline_asm = match parse_inline_asm(cx, sp, tts) {
Ok(Some(inline_asm)) => inline_asm,
Ok(None) => return DummyResult::any(sp),
}))
}
+fn parse_asm_str<'a>(p: &mut Parser<'a>) -> PResult<'a, Symbol> {
+ match p.parse_str_lit() {
+ Ok(str_lit) => Ok(str_lit.symbol_unescaped),
+ Err(opt_lit) => {
+ let span = opt_lit.map_or(p.token.span, |lit| lit.span);
+ let mut err = p.sess.span_diagnostic.struct_span_err(span, "expected string literal");
+ err.span_label(span, "not a string literal");
+ Err(err)
+ }
+ }
+}
+
fn parse_inline_asm<'a>(
cx: &mut ExtCtxt<'a>,
sp: Span,
p.eat(&token::Comma);
}
- let (constraint, _) = p.parse_str()?;
+ let constraint = parse_asm_str(&mut p)?;
let span = p.prev_span;
p.eat(&token::Comma);
}
- let (constraint, _) = p.parse_str()?;
+ let constraint = parse_asm_str(&mut p)?;
if constraint.as_str().starts_with("=") {
span_err!(cx, p.prev_span, E0662,
p.eat(&token::Comma);
}
- let (s, _) = p.parse_str()?;
+ let s = parse_asm_str(&mut p)?;
if OPTIONS.iter().any(|&opt| s == opt) {
cx.span_warn(p.prev_span, "expected a clobber, found an option");
}
}
Options => {
- let (option, _) = p.parse_str()?;
+ let option = parse_asm_str(&mut p)?;
if option == sym::volatile {
// Indicates that the inline assembly has side effects
use std::vec;
use rustc_data_structures::thin_vec::ThinVec;
-use syntax::ast::{self, Abi, BinOpKind, EnumDef, Expr, Generics, Ident, PatKind};
+use syntax::ast::{self, BinOpKind, EnumDef, Expr, Generics, Ident, PatKind};
use syntax::ast::{VariantData, GenericParamKind, GenericArg};
use syntax::attr;
use syntax::source_map::respan;
self,
type_ident,
generics,
- sym::Rust,
explicit_self,
tys,
body)
self,
type_ident,
generics,
- sym::Rust,
explicit_self,
tys,
body)
trait_: &TraitDef<'_>,
type_ident: Ident,
generics: &Generics,
- abi: Symbol,
explicit_self: Option<ast::ExplicitSelf>,
arg_types: Vec<(Ident, P<ast::Ty>)>,
body: P<Expr>)
let sig = ast::FnSig {
header: ast::FnHeader {
unsafety,
- abi: Abi::new(abi, trait_lo_sp),
+ ext: ast::Extern::None,
..ast::FnHeader::default()
},
decl: fn_decl,
rust_2018_preview,
rust_begin_unwind,
rustc,
- Rust,
RustcDecodable,
RustcEncodable,
rustc_allocator,
extern crate rustc;
extern crate rustc_interface;
-extern crate rustc_driver as _;
+extern crate rustc_driver;
extern crate syntax;
use rustc::session::DiagnosticOutput;
lint_caps: Default::default(),
register_lints: None,
override_queries: None,
+ registry: rustc_driver::diagnostics_registry(),
};
interface::run_compiler(config, |compiler| {
#[plugin_registrar]
pub fn plugin_registrar(reg: &mut Registry) {
- reg.register_attribute(Symbol::intern("foo"), AttributeType::Normal);
- reg.register_attribute(Symbol::intern("bar"), AttributeType::CrateLevel);
- reg.register_attribute(Symbol::intern("baz"), AttributeType::Whitelisted);
reg.register_syntax_extension(
Symbol::intern("mac"), SyntaxExtension::dummy_bang(reg.sess.edition())
);
extern crate rustc;
extern crate rustc_driver;
extern crate syntax;
-extern crate syntax_expand;
use rustc_driver::plugin::Registry;
-use syntax::attr;
-use syntax_expand::base::*;
-use syntax::feature_gate::AttributeType::Whitelisted;
-use syntax::symbol::Symbol;
-
-use rustc::hir;
-use rustc::hir::intravisit;
-use hir::Node;
+use rustc::hir::{self, intravisit, Node};
use rustc::lint::{LateContext, LintPass, LintArray, LateLintPass, LintContext};
+use syntax::print::pprust;
use syntax::source_map;
#[plugin_registrar]
pub fn plugin_registrar(reg: &mut Registry) {
reg.lint_store.register_lints(&[&MISSING_WHITELISTED_ATTR]);
reg.lint_store.register_late_pass(|| box MissingWhitelistedAttrPass);
- reg.register_attribute(Symbol::intern("whitelisted_attr"), Whitelisted);
}
declare_lint! {
_ => cx.tcx.hir().expect_item(cx.tcx.hir().get_parent_item(id)),
};
- if !attr::contains_name(&item.attrs, Symbol::intern("whitelisted_attr")) {
+ let whitelisted = |attr| pprust::attribute_to_string(attr).contains("whitelisted_attr");
+ if !item.attrs.iter().any(whitelisted) {
cx.span_lint(MISSING_WHITELISTED_ATTR, span,
"Missing 'whitelisted_attr' attribute");
}
// aux-build:issue-40001-plugin.rs
// ignore-stage1
-#![feature(plugin)]
+#![feature(plugin, register_tool)]
#![plugin(issue_40001_plugin)] //~ WARNING compiler plugins are deprecated
+#![register_tool(plugin)]
-#[whitelisted_attr]
+#[plugin::whitelisted_attr]
fn main() {}
+++ /dev/null
-// aux-build:attr-plugin-test.rs
-// ignore-stage1
-
-#![feature(plugin)]
-#![plugin(attr_plugin_test)]
-//~^ WARN use of deprecated attribute `plugin`
-#![deny(unused_attributes)]
-
-#[baz]
-fn baz() { } // no error
-
-#[foo]
-pub fn main() {
- //~^^ ERROR unused
- #[bar]
- fn inner() {}
- //~^^ ERROR crate
- //~^^^ ERROR unused
- baz();
- inner();
-}
+++ /dev/null
-warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675
- --> $DIR/plugin-attr-register-deny.rs:5:1
- |
-LL | #![plugin(attr_plugin_test)]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: may be removed in a future compiler version
- |
- = note: `#[warn(deprecated)]` on by default
-
-error: unused attribute
- --> $DIR/plugin-attr-register-deny.rs:15:5
- |
-LL | #[bar]
- | ^^^^^^
- |
-note: lint level defined here
- --> $DIR/plugin-attr-register-deny.rs:7:9
- |
-LL | #![deny(unused_attributes)]
- | ^^^^^^^^^^^^^^^^^
-
-error: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
- --> $DIR/plugin-attr-register-deny.rs:15:5
- |
-LL | #[bar]
- | ^^^^^^
-
-error: unused attribute
- --> $DIR/plugin-attr-register-deny.rs:12:1
- |
-LL | #[foo]
- | ^^^^^^
-
-error: aborting due to 3 previous errors
-
--- /dev/null
+// build-pass
+// only-x86_64
+
+#![feature(asm)]
+
+fn main() {
+ unsafe {
+ // "nop" :: "r"(x) : "eax" : "volatile"
+ let x = 10;
+ asm!("\x6Eop" :: "\x72"(x) : "\x65ax" : "\x76olatile");
+ }
+}
--> $DIR/asm-parse-errors.rs:5:18
|
LL | asm!("nop" : struct);
- | ^^^^^^ expected string literal
+ | ^^^^^^ not a string literal
error: expected string literal
--> $DIR/asm-parse-errors.rs:6:30
|
LL | asm!("mov %eax, $$0x2" : struct);
- | ^^^^^^ expected string literal
+ | ^^^^^^ not a string literal
error: expected `(`, found keyword `struct`
--> $DIR/asm-parse-errors.rs:7:39
--> $DIR/asm-parse-errors.rs:9:44
|
LL | asm!("in %dx, %al" : "={al}"(result) : struct);
- | ^^^^^^ expected string literal
+ | ^^^^^^ not a string literal
error: expected `(`, found keyword `struct`
--> $DIR/asm-parse-errors.rs:10:51
--> $DIR/asm-parse-errors.rs:12:36
|
LL | asm!("mov $$0x200, %eax" : : : struct);
- | ^^^^^^ expected string literal
+ | ^^^^^^ not a string literal
error: expected string literal
--> $DIR/asm-parse-errors.rs:13:45
|
LL | asm!("mov eax, 2" : "={eax}"(foo) : : : struct);
- | ^^^^^^ expected string literal
+ | ^^^^^^ not a string literal
error: inline assembly must be a string literal
--> $DIR/asm-parse-errors.rs:14:10
--- /dev/null
+// check-pass
+// only-x86_64
+
+// Checks that the compiler does not actually try to allocate 4 TB during compilation and OOM crash.
+
+fn foo() -> [u8; 4 * 1024 * 1024 * 1024 * 1024] {
+ unimplemented!()
+}
+
+fn main() {
+ foo();
+}
--- /dev/null
+// check-pass
+// only-x86_64
+
+// Checks that the compiler does not actually try to allocate 4 TB during compilation and OOM crash.
+
+fn main() {
+ [0; 4 * 1024 * 1024 * 1024 * 1024];
+}
--- /dev/null
+// The original problem in #66340 was that `find_deprecation_generic`
+// called `attr.meta().unwrap()` under the assumption that the attribute
+// was a well-formed `MetaItem`.
+
+fn main() {
+ foo()
+}
+
+#[deprecated(note = test)]
+//~^ ERROR expected unsuffixed literal or identifier, found `test`
+fn foo() {}
--- /dev/null
+error: expected unsuffixed literal or identifier, found `test`
+ --> $DIR/issue-66340-deprecated-attr-non-meta-grammar.rs:9:21
+ |
+LL | #[deprecated(note = test)]
+ | ^^^^
+
+error: aborting due to previous error
+
struct Foo {
x: usize,
- b: bool, //~ ERROR: field is never used
+ b: bool, //~ ERROR: field is never read
}
fn field_read(f: Foo) -> usize {
I, //~ ERROR variant is never constructed
J {
a: String,
- b: i32, //~ ERROR field is never used
- c: i32, //~ ERROR field is never used
+ b: i32, //~ ERROR field is never read
+ c: i32, //~ ERROR field is never read
},
K //~ ERROR variant is never constructed
}
struct Bar {
- x: usize, //~ ERROR: field is never used
+ x: usize, //~ ERROR: field is never read
b: bool,
- c: bool, //~ ERROR: field is never used
+ c: bool, //~ ERROR: field is never read
_guard: ()
}
-error: field is never used: `b`
+error: field is never read: `b`
--> $DIR/lint-dead-code-4.rs:7:5
|
LL | b: bool,
LL | I,
| ^
-error: field is never used: `b`
+error: field is never read: `b`
--> $DIR/lint-dead-code-4.rs:39:9
|
LL | b: i32,
| ^^^^^^
-error: field is never used: `c`
+error: field is never read: `c`
--> $DIR/lint-dead-code-4.rs:40:9
|
LL | c: i32,
LL | K
| ^
-error: field is never used: `x`
+error: field is never read: `x`
--> $DIR/lint-dead-code-4.rs:61:5
|
LL | x: usize,
| ^^^^^^^^
-error: field is never used: `c`
+error: field is never read: `c`
--> $DIR/lint-dead-code-4.rs:63:5
|
LL | c: bool,
--- /dev/null
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+use proc_macro::*;
+
+#[proc_macro_derive(GenHelperUse)]
+pub fn derive_a(_: TokenStream) -> TokenStream {
+ "
+ #[empty_helper]
+ struct Uwu;
+ ".parse().unwrap()
+}
+// edition:2018
// aux-build:test-macros.rs
+// aux-build:derive-helper-shadowing.rs
#[macro_use]
extern crate test_macros;
+#[macro_use]
+extern crate derive_helper_shadowing;
use test_macros::empty_attr as empty_helper;
+macro_rules! gen_helper_use {
+ () => {
+ #[empty_helper] //~ ERROR cannot find attribute `empty_helper` in this scope
+ struct W;
+ }
+}
+
#[empty_helper] //~ ERROR `empty_helper` is ambiguous
#[derive(Empty)]
struct S {
- // FIXME No ambiguity, attributes in non-macro positions are not resolved properly
- #[empty_helper]
+ #[empty_helper] //~ ERROR `empty_helper` is ambiguous
field: [u8; {
- // FIXME No ambiguity, derive helpers are not put into scope for non-attributes
- use empty_helper;
+ use empty_helper; //~ ERROR `empty_helper` is ambiguous
- // FIXME No ambiguity, derive helpers are not put into scope for inner items
- #[empty_helper]
+ #[empty_helper] //~ ERROR `empty_helper` is ambiguous
struct U;
mod inner {
- // FIXME No ambiguity, attributes in non-macro positions are not resolved properly
+ // OK, no ambiguity, the non-helper attribute is not in scope here, only the helper.
#[empty_helper]
struct V;
+
+ gen_helper_use!();
+
+ #[derive(GenHelperUse)] //~ ERROR cannot find attribute `empty_helper` in this scope
+ struct Owo;
+
+ use empty_helper as renamed;
+ #[renamed] //~ ERROR cannot use a derive helper attribute through an import
+ struct Wow;
}
0
}]
}
+// OK, no ambiguity, only the non-helper attribute is in scope.
+#[empty_helper]
+struct Z;
+
fn main() {
let s = S { field: [] };
}
+error: cannot use a derive helper attribute through an import
+ --> $DIR/derive-helper-shadowing.rs:40:15
+ |
+LL | #[renamed]
+ | ^^^^^^^
+ |
+note: the derive helper attribute imported here
+ --> $DIR/derive-helper-shadowing.rs:39:17
+ |
+LL | use empty_helper as renamed;
+ | ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: cannot find attribute `empty_helper` in this scope
+ --> $DIR/derive-helper-shadowing.rs:36:22
+ |
+LL | #[derive(GenHelperUse)]
+ | ^^^^^^^^^^^^
+
+error: cannot find attribute `empty_helper` in this scope
+ --> $DIR/derive-helper-shadowing.rs:14:11
+ |
+LL | #[empty_helper]
+ | ^^^^^^^^^^^^
+...
+LL | gen_helper_use!();
+ | ------------------ in this macro invocation
+
+error[E0659]: `empty_helper` is ambiguous (name vs any other name during import resolution)
+ --> $DIR/derive-helper-shadowing.rs:24:13
+ |
+LL | use empty_helper;
+ | ^^^^^^^^^^^^ ambiguous name
+ |
+note: `empty_helper` could refer to the derive helper attribute defined here
+ --> $DIR/derive-helper-shadowing.rs:20:10
+ |
+LL | #[derive(Empty)]
+ | ^^^^^
+note: `empty_helper` could also refer to the attribute macro imported here
+ --> $DIR/derive-helper-shadowing.rs:10:5
+ |
+LL | use test_macros::empty_attr as empty_helper;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = help: use `crate::empty_helper` to refer to this attribute macro unambiguously
+
error[E0659]: `empty_helper` is ambiguous (derive helper attribute vs any other name)
- --> $DIR/derive-helper-shadowing.rs:8:3
+ --> $DIR/derive-helper-shadowing.rs:19:3
|
LL | #[empty_helper]
| ^^^^^^^^^^^^ ambiguous name
|
note: `empty_helper` could refer to the derive helper attribute defined here
- --> $DIR/derive-helper-shadowing.rs:9:10
+ --> $DIR/derive-helper-shadowing.rs:20:10
+ |
+LL | #[derive(Empty)]
+ | ^^^^^
+note: `empty_helper` could also refer to the attribute macro imported here
+ --> $DIR/derive-helper-shadowing.rs:10:5
+ |
+LL | use test_macros::empty_attr as empty_helper;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = help: use `crate::empty_helper` to refer to this attribute macro unambiguously
+
+error[E0659]: `empty_helper` is ambiguous (derive helper attribute vs any other name)
+ --> $DIR/derive-helper-shadowing.rs:22:7
+ |
+LL | #[empty_helper]
+ | ^^^^^^^^^^^^ ambiguous name
+ |
+note: `empty_helper` could refer to the derive helper attribute defined here
+ --> $DIR/derive-helper-shadowing.rs:20:10
+ |
+LL | #[derive(Empty)]
+ | ^^^^^
+note: `empty_helper` could also refer to the attribute macro imported here
+ --> $DIR/derive-helper-shadowing.rs:10:5
+ |
+LL | use test_macros::empty_attr as empty_helper;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = help: use `crate::empty_helper` to refer to this attribute macro unambiguously
+
+error[E0659]: `empty_helper` is ambiguous (derive helper attribute vs any other name)
+ --> $DIR/derive-helper-shadowing.rs:26:11
+ |
+LL | #[empty_helper]
+ | ^^^^^^^^^^^^ ambiguous name
+ |
+note: `empty_helper` could refer to the derive helper attribute defined here
+ --> $DIR/derive-helper-shadowing.rs:20:10
|
LL | #[derive(Empty)]
| ^^^^^
note: `empty_helper` could also refer to the attribute macro imported here
- --> $DIR/derive-helper-shadowing.rs:6:5
+ --> $DIR/derive-helper-shadowing.rs:10:5
|
LL | use test_macros::empty_attr as empty_helper;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= help: use `crate::empty_helper` to refer to this attribute macro unambiguously
-error: aborting due to previous error
+error: aborting due to 7 previous errors
For more information about this error, try `rustc --explain E0659`.
-//~ ERROR mismatched types
-// aux-build:test-macros.rs
-
// For each of these, we should get the appropriate type mismatch error message,
// and the function should be echoed.
+// aux-build:test-macros.rs
+
#[macro_use]
extern crate test_macros;
let y = Foo { a: 10, b: 10isize }; //~ ERROR has no field named `b`
}
-// FIXME: This doesn't work at the moment. See the one below. The pretty-printer
-// injects a "C" between `extern` and `fn` which causes a "probably_eq"
-// `TokenStream` mismatch. The lack of `"C"` should be preserved in the AST.
#[recollect_attr]
extern fn bar() {
- 0
+ 0 //~ ERROR mismatched types
}
#[recollect_attr]
0 //~ ERROR mismatched types
}
+#[recollect_attr]
+extern "Rust" fn rust_abi() {
+ 0 //~ ERROR mismatched types
+}
+
+#[recollect_attr]
+extern "\x43" fn c_abi_escaped() {
+ 0 //~ ERROR mismatched types
+}
+
fn main() {}
error[E0308]: mismatched types
- |
- = note: expected type `()`
- found type `{integer}`
-
-error[E0308]: mismatched types
- --> $DIR/span-preservation.rs:12:20
+ --> $DIR/span-preservation.rs:11:20
|
LL | let x: usize = "hello";
| ^^^^^^^ expected usize, found reference
found type `&'static str`
error[E0308]: mismatched types
- --> $DIR/span-preservation.rs:18:29
+ --> $DIR/span-preservation.rs:17:29
|
LL | fn b(x: Option<isize>) -> usize {
| ----- expected `usize` because of return type
| ^ expected usize, found isize
error[E0308]: mismatched types
- --> $DIR/span-preservation.rs:34:22
+ --> $DIR/span-preservation.rs:33:22
|
LL | let x = Foo { a: 10isize };
| ^^^^^^^ expected usize, found isize
error[E0560]: struct `c::Foo` has no field named `b`
- --> $DIR/span-preservation.rs:35:26
+ --> $DIR/span-preservation.rs:34:26
|
LL | let y = Foo { a: 10, b: 10isize };
| ^ `c::Foo` does not have this field
= note: available fields are: `a`
error[E0308]: mismatched types
- --> $DIR/span-preservation.rs:48:5
+ --> $DIR/span-preservation.rs:39:5
+ |
+LL | extern fn bar() {
+ | - possibly return type missing here?
+LL | 0
+ | ^ expected (), found integer
+ |
+ = note: expected type `()`
+ found type `{integer}`
+
+error[E0308]: mismatched types
+ --> $DIR/span-preservation.rs:44:5
|
LL | extern "C" fn baz() {
| - possibly return type missing here?
= note: expected type `()`
found type `{integer}`
-error: aborting due to 6 previous errors
+error[E0308]: mismatched types
+ --> $DIR/span-preservation.rs:49:5
+ |
+LL | extern "Rust" fn rust_abi() {
+ | - possibly return type missing here?
+LL | 0
+ | ^ expected (), found integer
+ |
+ = note: expected type `()`
+ found type `{integer}`
+
+error[E0308]: mismatched types
+ --> $DIR/span-preservation.rs:54:5
+ |
+LL | extern "\x43" fn c_abi_escaped() {
+ | - possibly return type missing here?
+LL | 0
+ | ^ expected (), found integer
+ |
+ = note: expected type `()`
+ found type `{integer}`
+
+error: aborting due to 8 previous errors
Some errors have detailed explanations: E0308, E0560.
For more information about an error, try `rustc --explain E0308`.
union U1 {
a: u8, // should not be reported
b: u8, // should not be reported
- c: u8, //~ ERROR field is never used
+ c: u8, //~ ERROR field is never read
}
union U2 {
- a: u8, //~ ERROR field is never used
+ a: u8, //~ ERROR field is never read
b: u8, // should not be reported
c: u8, // should not be reported
}
-union NoDropLike { a: u8 } //~ ERROR field is never used
+union NoDropLike { a: u8 } //~ ERROR field is never read
union U {
a: u8, // should not be reported
b: u8, // should not be reported
- c: u8, //~ ERROR field is never used
+ c: u8, //~ ERROR field is never read
}
type A = U;
-error: field is never used: `c`
+error: field is never read: `c`
--> $DIR/union-fields-1.rs:6:5
|
LL | c: u8,
LL | #![deny(dead_code)]
| ^^^^^^^^^
-error: field is never used: `a`
+error: field is never read: `a`
--> $DIR/union-fields-1.rs:9:5
|
LL | a: u8,
| ^^^^^
-error: field is never used: `a`
+error: field is never read: `a`
--> $DIR/union-fields-1.rs:13:20
|
LL | union NoDropLike { a: u8 }
| ^^^^^
-error: field is never used: `c`
+error: field is never read: `c`
--> $DIR/union-fields-1.rs:18:5
|
LL | c: u8,
union Foo {
x: usize,
- b: bool, //~ ERROR: field is never used
+ b: bool, //~ ERROR: field is never read
_unused: u16,
}
-error: field is never used: `b`
+error: field is never read: `b`
--> $DIR/union-lint-dead-code.rs:5:5
|
LL | b: bool,