use crate::string::ToString;
use crate::vec::Vec;
+ // We shouldn't add inline attribute to this since this is used in
+ // `vec!` macro mostly and causes perf regression. See #71204 for
+ // discussion and perf results.
pub fn into_vec<T>(b: Box<[T]>) -> Vec<T> {
unsafe {
let len = b.len();
pub mod comments;
pub mod lev_distance;
pub mod literal;
- pub mod map_in_place;
pub mod parser;
}
use crate::ptr::P;
use crate::token::{self, Token};
use crate::tokenstream::*;
-use crate::util::map_in_place::MapInPlace;
+use rustc_data_structures::map_in_place::MapInPlace;
use rustc_data_structures::sync::Lrc;
use rustc_span::source_map::{respan, Spanned};
use rustc_span::Span;
+++ /dev/null
-// FIXME(Centril): Move to rustc_data_structures.
-
-use smallvec::{Array, SmallVec};
-use std::ptr;
-
-pub trait MapInPlace<T>: Sized {
- fn map_in_place<F>(&mut self, mut f: F)
- where
- F: FnMut(T) -> T,
- {
- self.flat_map_in_place(|e| Some(f(e)))
- }
-
- fn flat_map_in_place<F, I>(&mut self, f: F)
- where
- F: FnMut(T) -> I,
- I: IntoIterator<Item = T>;
-}
-
-impl<T> MapInPlace<T> for Vec<T> {
- fn flat_map_in_place<F, I>(&mut self, mut f: F)
- where
- F: FnMut(T) -> I,
- I: IntoIterator<Item = T>,
- {
- let mut read_i = 0;
- let mut write_i = 0;
- unsafe {
- let mut old_len = self.len();
- self.set_len(0); // make sure we just leak elements in case of panic
-
- while read_i < old_len {
- // move the read_i'th item out of the vector and map it
- // to an iterator
- let e = ptr::read(self.get_unchecked(read_i));
- let iter = f(e).into_iter();
- read_i += 1;
-
- for e in iter {
- if write_i < read_i {
- ptr::write(self.get_unchecked_mut(write_i), e);
- write_i += 1;
- } else {
- // If this is reached we ran out of space
- // in the middle of the vector.
- // However, the vector is in a valid state here,
- // so we just do a somewhat inefficient insert.
- self.set_len(old_len);
- self.insert(write_i, e);
-
- old_len = self.len();
- self.set_len(0);
-
- read_i += 1;
- write_i += 1;
- }
- }
- }
-
- // write_i tracks the number of actually written new items.
- self.set_len(write_i);
- }
- }
-}
-
-impl<T, A: Array<Item = T>> MapInPlace<T> for SmallVec<A> {
- fn flat_map_in_place<F, I>(&mut self, mut f: F)
- where
- F: FnMut(T) -> I,
- I: IntoIterator<Item = T>,
- {
- let mut read_i = 0;
- let mut write_i = 0;
- unsafe {
- let mut old_len = self.len();
- self.set_len(0); // make sure we just leak elements in case of panic
-
- while read_i < old_len {
- // move the read_i'th item out of the vector and map it
- // to an iterator
- let e = ptr::read(self.get_unchecked(read_i));
- let iter = f(e).into_iter();
- read_i += 1;
-
- for e in iter {
- if write_i < read_i {
- ptr::write(self.get_unchecked_mut(write_i), e);
- write_i += 1;
- } else {
- // If this is reached we ran out of space
- // in the middle of the vector.
- // However, the vector is in a valid state here,
- // so we just do a somewhat inefficient insert.
- self.set_len(old_len);
- self.insert(write_i, e);
-
- old_len = self.len();
- self.set_len(0);
-
- read_i += 1;
- write_i += 1;
- }
- }
- }
-
- // write_i tracks the number of actually written new items.
- self.set_len(write_i);
- }
- }
-}
use rustc_ast::ast::{self, BinOpKind, EnumDef, Expr, Generics, Ident, PatKind};
use rustc_ast::ast::{GenericArg, GenericParamKind, VariantData};
use rustc_ast::ptr::P;
-use rustc_ast::util::map_in_place::MapInPlace;
use rustc_attr as attr;
+use rustc_data_structures::map_in_place::MapInPlace;
use rustc_expand::base::{Annotatable, ExtCtxt};
use rustc_session::parse::ParseSess;
use rustc_span::source_map::respan;
pub mod graph;
pub mod jobserver;
pub mod macros;
+pub mod map_in_place;
pub mod obligation_forest;
pub mod owning_ref;
pub mod ptr_key;
--- /dev/null
+use smallvec::{Array, SmallVec};
+use std::ptr;
+
+pub trait MapInPlace<T>: Sized {
+ fn map_in_place<F>(&mut self, mut f: F)
+ where
+ F: FnMut(T) -> T,
+ {
+ self.flat_map_in_place(|e| Some(f(e)))
+ }
+
+ fn flat_map_in_place<F, I>(&mut self, f: F)
+ where
+ F: FnMut(T) -> I,
+ I: IntoIterator<Item = T>;
+}
+
+impl<T> MapInPlace<T> for Vec<T> {
+ fn flat_map_in_place<F, I>(&mut self, mut f: F)
+ where
+ F: FnMut(T) -> I,
+ I: IntoIterator<Item = T>,
+ {
+ let mut read_i = 0;
+ let mut write_i = 0;
+ unsafe {
+ let mut old_len = self.len();
+ self.set_len(0); // make sure we just leak elements in case of panic
+
+ while read_i < old_len {
+ // move the read_i'th item out of the vector and map it
+ // to an iterator
+ let e = ptr::read(self.get_unchecked(read_i));
+ let iter = f(e).into_iter();
+ read_i += 1;
+
+ for e in iter {
+ if write_i < read_i {
+ ptr::write(self.get_unchecked_mut(write_i), e);
+ write_i += 1;
+ } else {
+ // If this is reached we ran out of space
+ // in the middle of the vector.
+ // However, the vector is in a valid state here,
+ // so we just do a somewhat inefficient insert.
+ self.set_len(old_len);
+ self.insert(write_i, e);
+
+ old_len = self.len();
+ self.set_len(0);
+
+ read_i += 1;
+ write_i += 1;
+ }
+ }
+ }
+
+ // write_i tracks the number of actually written new items.
+ self.set_len(write_i);
+ }
+ }
+}
+
+impl<T, A: Array<Item = T>> MapInPlace<T> for SmallVec<A> {
+ fn flat_map_in_place<F, I>(&mut self, mut f: F)
+ where
+ F: FnMut(T) -> I,
+ I: IntoIterator<Item = T>,
+ {
+ let mut read_i = 0;
+ let mut write_i = 0;
+ unsafe {
+ let mut old_len = self.len();
+ self.set_len(0); // make sure we just leak elements in case of panic
+
+ while read_i < old_len {
+ // move the read_i'th item out of the vector and map it
+ // to an iterator
+ let e = ptr::read(self.get_unchecked(read_i));
+ let iter = f(e).into_iter();
+ read_i += 1;
+
+ for e in iter {
+ if write_i < read_i {
+ ptr::write(self.get_unchecked_mut(write_i), e);
+ write_i += 1;
+ } else {
+ // If this is reached we ran out of space
+ // in the middle of the vector.
+ // However, the vector is in a valid state here,
+ // so we just do a somewhat inefficient insert.
+ self.set_len(old_len);
+ self.insert(write_i, e);
+
+ old_len = self.len();
+ self.set_len(0);
+
+ read_i += 1;
+ write_i += 1;
+ }
+ }
+ }
+
+ // write_i tracks the number of actually written new items.
+ self.set_len(write_i);
+ }
+ }
+}
use rustc_ast::attr::HasAttrs;
use rustc_ast::mut_visit::*;
use rustc_ast::ptr::P;
-use rustc_ast::util::map_in_place::MapInPlace;
use rustc_attr as attr;
use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::map_in_place::MapInPlace;
use rustc_errors::{error_code, struct_span_err, Applicability, Handler};
use rustc_feature::{Feature, Features, State as FeatureState};
use rustc_feature::{
use rustc_ast::ptr::P;
use rustc_ast::token;
use rustc_ast::tokenstream::TokenStream;
-use rustc_ast::util::map_in_place::MapInPlace;
use rustc_ast::visit::{self, AssocCtxt, Visitor};
use rustc_ast_pretty::pprust;
use rustc_attr::{self as attr, is_builtin_attr, HasAttrs};
+use rustc_data_structures::map_in_place::MapInPlace;
use rustc_errors::{Applicability, PResult};
use rustc_feature::Features;
use rustc_parse::parser::Parser;
}
fn inject_profiler_runtime(&mut self) {
- if self.sess.opts.debugging_opts.profile || self.sess.opts.cg.profile_generate.enabled() {
+ if (self.sess.opts.debugging_opts.profile || self.sess.opts.cg.profile_generate.enabled())
+ && !self.sess.opts.debugging_opts.no_profiler_runtime
+ {
info!("loading profiler");
let name = Symbol::intern("profiler_builtins");
///
/// This function would create a label like this:
///
- /// ```
+ /// ```text
/// | fn foo(x: &u32) { .. }
/// ------- fully elaborated type of `x` is `&'1 u32`
/// ```
/// elaborated type, returning something like `'1`. Result looks
/// like:
///
- /// ```
+ /// ```text
/// | fn foo(x: &u32) { .. }
/// ------- fully elaborated type of `x` is `&'1 u32`
/// ```
/// that has no type annotation.
/// For example, we might produce an annotation like this:
///
- /// ```
+ /// ```text
/// | foo(|a, b| b)
/// | - -
/// | | |
/// that contains the anonymous reference we want to give a name
/// to. For example, we might produce an annotation like this:
///
- /// ```
+ /// ```text
/// | fn a<T>(items: &[T]) -> Box<dyn Iterator<Item = &T>> {
/// | - let's call the lifetime of this reference `'1`
/// ```
/// fully elaborated type, returning something like `'1`. Result
/// looks like:
///
- /// ```
+ /// ```text
/// | let x = Some(&22);
/// - fully elaborated type of `x` is `Option<&'1 u32>`
/// ```
pub use self::qualifs::Qualif;
-pub mod ops;
+mod ops;
pub mod qualifs;
mod resolver;
pub mod validation;
#[derive(Debug)]
pub struct HeapAllocation;
impl NonConstOp for HeapAllocation {
- const IS_SUPPORTED_IN_MIRI: bool = false;
-
fn emit_error(&self, item: &Item<'_, '_>, span: Span) {
let mut err = struct_span_err!(
item.tcx.sess,
/// Keep in mind that given that `outer_op.is_comparison()` holds and comparison ops are left
/// associative we can infer that we have:
///
+ /// ```text
/// outer_op
/// / \
/// inner_op r2
/// / \
/// l1 r1
+ /// ```
pub(super) fn check_no_chained_comparison(
&mut self,
inner_op: &Expr,
impl<'a> Parser<'a> {
/// Parses bounds of a lifetime parameter `BOUND + BOUND + BOUND`, possibly with trailing `+`.
///
- /// ```
+ /// ```text
/// BOUND = LT_BOUND (e.g., `'a`)
/// ```
fn parse_lt_param_bounds(&mut self) -> GenericBounds {
/// Parses a `UseTree`.
///
- /// ```
+ /// ```text
/// USE_TREE = [`::`] `*` |
/// [`::`] `{` USE_TREE_LIST `}` |
/// PATH `::` `*` |
/// Parses a `UseTreeKind::Nested(list)`.
///
- /// ```
+ /// ```text
/// USE_TREE_LIST = Ø | (USE_TREE `,`)* USE_TREE [`,`]
/// ```
fn parse_use_tree_list(&mut self) -> PResult<'a, Vec<(UseTree, ast::NodeId)>> {
/// Suggest a missing `self::` if that resolves to an correct module.
///
- /// ```
+ /// ```text
/// |
/// LL | use foo::Bar;
/// | ^^^ did you mean `self::foo`?
/// Suggests a missing `super::` if that resolves to an correct module.
///
- /// ```
+ /// ```text
/// |
/// LL | use foo::Bar;
/// | ^^^ did you mean `super::foo`?
/// Suggests a missing external crate name if that resolves to an correct module.
///
- /// ```
+ /// ```text
/// |
/// LL | use foobar::Baz;
/// | ^^^^^^ did you mean `baz::foobar`?
let output_types = parse_output_types(&debugging_opts, matches, error_format);
let mut cg = build_codegen_options(matches, error_format);
- let (disable_thinlto, codegen_units) = should_override_cgus_and_disable_thinlto(
+ let (disable_thinlto, mut codegen_units) = should_override_cgus_and_disable_thinlto(
&output_types,
matches,
error_format,
"can't instrument with gcov profiling when compiling incrementally",
);
}
+ if debugging_opts.profile {
+ match codegen_units {
+ Some(1) => {}
+ None => codegen_units = Some(1),
+ Some(_) => early_error(
+ error_format,
+ "can't instrument with gcov profiling with multiple codegen units",
+ ),
+ }
+ }
if cg.profile_generate.enabled() && cg.profile_use.is_some() {
early_error(
"extra arguments to prepend to the linker invocation (space separated)"),
profile: bool = (false, parse_bool, [TRACKED],
"insert profiling code"),
+ no_profiler_runtime: bool = (false, parse_bool, [TRACKED],
+ "don't automatically inject the profiler_builtins crate"),
relro_level: Option<RelroLevel> = (None, parse_relro_level, [TRACKED],
"choose which RELRO level to use"),
nll_facts: bool = (false, parse_bool, [UNTRACKED],
/// Adds an async-await specific note to the diagnostic when the future does not implement
/// an auto trait because of a captured type.
///
- /// ```ignore (diagnostic)
+ /// ```text
/// note: future does not implement `Qux` as this value is used across an await
/// --> $DIR/issue-64130-3-other.rs:17:5
/// |
/// When the diagnostic does not implement `Send` or `Sync` specifically, then the diagnostic
/// is "replaced" with a different message and a more specific error.
///
- /// ```ignore (diagnostic)
+ /// ```text
/// error: future cannot be sent between threads safely
/// --> $DIR/issue-64130-2-send.rs:21:5
/// |
/// This helper takes a *converted* parameter type (`param_ty`)
/// and an *unconverted* list of bounds:
///
- /// ```
+ /// ```text
/// fn foo<T: Debug>
/// ^ ^^^^^ `ast_bounds` parameter, in HIR form
/// |
/// representations). These lists of bounds occur in many places in
/// Rust's syntax:
///
-/// ```
+/// ```text
/// trait Foo: Bar + Baz { }
/// ^^^^^^^^^ supertrait list bounding the `Self` type parameter
///
--- /dev/null
+// compile-flags: -Zunleash-the-miri-inside-of-you
+#![feature(const_mut_refs, box_syntax)]
+#![deny(const_err)]
+
+use std::mem::ManuallyDrop;
+
+fn main() {}
+
+static TEST_BAD: &mut i32 = {
+ &mut *(box 0)
+ //~^ WARN skipping const check
+ //~| ERROR could not evaluate static initializer
+ //~| NOTE heap allocations
+};
--- /dev/null
+warning: skipping const checks
+ --> $DIR/box.rs:10:11
+ |
+LL | &mut *(box 0)
+ | ^^^^^^^
+
+error[E0080]: could not evaluate static initializer
+ --> $DIR/box.rs:10:11
+ |
+LL | &mut *(box 0)
+ | ^^^^^^^ "heap allocations via `box` keyword" needs an rfc before being allowed inside constants
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0080`.