mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 23:04:33 +00:00
Auto merge of #69879 - Centril:rollup-ryea91j, r=Centril
Rollup of 10 pull requests Successful merges: - #69475 (Remove the `no_force` query attribute) - #69514 (Remove spotlight) - #69677 (rustc_metadata: Give decoder access to whole crate store) - #69714 (Make PlaceRef take just one lifetime) - #69799 (Allow ZSTs in `AllocRef`) - #69817 (test(patterns): add patterns feature tests to borrowck test suite) - #69836 (Check if output is immediate value) - #69847 (clean up E0393 explanation) - #69861 (Add note about localization to std::fmt docs) - #69877 (Vec::new is const stable in 1.39 not 1.32) Failed merges: r? @ghost
This commit is contained in:
commit
dd155df0a6
@ -138,27 +138,6 @@ Book][unstable-doc-cfg] and [its tracking issue][issue-doc-cfg].
|
||||
[unstable-doc-cfg]: ../unstable-book/language-features/doc-cfg.html
|
||||
[issue-doc-cfg]: https://github.com/rust-lang/rust/issues/43781
|
||||
|
||||
### Adding your trait to the "Important Traits" dialog
|
||||
|
||||
Rustdoc keeps a list of a few traits that are believed to be "fundamental" to a given type when
|
||||
implemented on it. These traits are intended to be the primary interface for their types, and are
|
||||
often the only thing available to be documented on their types. For this reason, Rustdoc will track
|
||||
when a given type implements one of these traits and call special attention to it when a function
|
||||
returns one of these types. This is the "Important Traits" dialog, visible as a circle-i button next
|
||||
to the function, which, when clicked, shows the dialog.
|
||||
|
||||
In the standard library, the traits that qualify for inclusion are `Iterator`, `io::Read`, and
|
||||
`io::Write`. However, rather than being implemented as a hard-coded list, these traits have a
|
||||
special marker attribute on them: `#[doc(spotlight)]`. This means that you could apply this
|
||||
attribute to your own trait to include it in the "Important Traits" dialog in documentation.
|
||||
|
||||
The `#[doc(spotlight)]` attribute currently requires the `#![feature(doc_spotlight)]` feature gate.
|
||||
For more information, see [its chapter in the Unstable Book][unstable-spotlight] and [its tracking
|
||||
issue][issue-spotlight].
|
||||
|
||||
[unstable-spotlight]: ../unstable-book/language-features/doc-spotlight.html
|
||||
[issue-spotlight]: https://github.com/rust-lang/rust/issues/45040
|
||||
|
||||
### Exclude certain dependencies from documentation
|
||||
|
||||
The standard library uses several dependencies which, in turn, use several types and traits from the
|
||||
|
@ -1,30 +0,0 @@
|
||||
# `doc_spotlight`
|
||||
|
||||
The tracking issue for this feature is: [#45040]
|
||||
|
||||
The `doc_spotlight` feature allows the use of the `spotlight` parameter to the `#[doc]` attribute,
|
||||
to "spotlight" a specific trait on the return values of functions. Adding a `#[doc(spotlight)]`
|
||||
attribute to a trait definition will make rustdoc print extra information for functions which return
|
||||
a type that implements that trait. This attribute is applied to the `Iterator`, `io::Read`, and
|
||||
`io::Write` traits in the standard library.
|
||||
|
||||
You can do this on your own traits, like this:
|
||||
|
||||
```
|
||||
#![feature(doc_spotlight)]
|
||||
|
||||
#[doc(spotlight)]
|
||||
pub trait MyTrait {}
|
||||
|
||||
pub struct MyStruct;
|
||||
impl MyTrait for MyStruct {}
|
||||
|
||||
/// The docs for this function will have an extra line about `MyStruct` implementing `MyTrait`,
|
||||
/// without having to write that yourself!
|
||||
pub fn my_fn() -> MyStruct { MyStruct }
|
||||
```
|
||||
|
||||
This feature was originally implemented in PR [#45039].
|
||||
|
||||
[#45040]: https://github.com/rust-lang/rust/issues/45040
|
||||
[#45039]: https://github.com/rust-lang/rust/pull/45039
|
@ -165,13 +165,19 @@ pub unsafe fn alloc_zeroed(layout: Layout) -> *mut u8 {
|
||||
#[unstable(feature = "allocator_api", issue = "32838")]
|
||||
unsafe impl AllocRef for Global {
|
||||
#[inline]
|
||||
unsafe fn alloc(&mut self, layout: Layout) -> Result<(NonNull<u8>, usize), AllocErr> {
|
||||
NonNull::new(alloc(layout)).ok_or(AllocErr).map(|p| (p, layout.size()))
|
||||
fn alloc(&mut self, layout: Layout) -> Result<(NonNull<u8>, usize), AllocErr> {
|
||||
if layout.size() == 0 {
|
||||
Ok((layout.dangling(), 0))
|
||||
} else {
|
||||
unsafe { NonNull::new(alloc(layout)).ok_or(AllocErr).map(|p| (p, layout.size())) }
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn dealloc(&mut self, ptr: NonNull<u8>, layout: Layout) {
|
||||
dealloc(ptr.as_ptr(), layout)
|
||||
if layout.size() != 0 {
|
||||
dealloc(ptr.as_ptr(), layout)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@ -181,12 +187,28 @@ unsafe impl AllocRef for Global {
|
||||
layout: Layout,
|
||||
new_size: usize,
|
||||
) -> Result<(NonNull<u8>, usize), AllocErr> {
|
||||
NonNull::new(realloc(ptr.as_ptr(), layout, new_size)).ok_or(AllocErr).map(|p| (p, new_size))
|
||||
match (layout.size(), new_size) {
|
||||
(0, 0) => Ok((layout.dangling(), 0)),
|
||||
(0, _) => self.alloc(Layout::from_size_align_unchecked(new_size, layout.align())),
|
||||
(_, 0) => {
|
||||
self.dealloc(ptr, layout);
|
||||
Ok((layout.dangling(), 0))
|
||||
}
|
||||
(_, _) => NonNull::new(realloc(ptr.as_ptr(), layout, new_size))
|
||||
.ok_or(AllocErr)
|
||||
.map(|p| (p, new_size)),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn alloc_zeroed(&mut self, layout: Layout) -> Result<(NonNull<u8>, usize), AllocErr> {
|
||||
NonNull::new(alloc_zeroed(layout)).ok_or(AllocErr).map(|p| (p, layout.size()))
|
||||
fn alloc_zeroed(&mut self, layout: Layout) -> Result<(NonNull<u8>, usize), AllocErr> {
|
||||
if layout.size() == 0 {
|
||||
Ok((layout.dangling(), 0))
|
||||
} else {
|
||||
unsafe {
|
||||
NonNull::new(alloc_zeroed(layout)).ok_or(AllocErr).map(|p| (p, layout.size()))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -247,6 +247,21 @@
|
||||
//! Hello, ` 123` has 3 right-aligned characters
|
||||
//! ```
|
||||
//!
|
||||
//! ## Localization
|
||||
//!
|
||||
//! In some programming languages, the behavior of string formatting functions
|
||||
//! depends on the operating system's locale setting. The format functions
|
||||
//! provided by Rust's standard library do not have any concept of locale, and
|
||||
//! will produce the same results on all systems regardless of user
|
||||
//! configuration.
|
||||
//!
|
||||
//! For example, the following code will always print `1.5` even if the system
|
||||
//! locale uses a decimal separator other than a dot.
|
||||
//!
|
||||
//! ```
|
||||
//! println!("The value is {}", 1.5);
|
||||
//! ```
|
||||
//!
|
||||
//! # Escaping
|
||||
//!
|
||||
//! The literal characters `{` and `}` may be included in a string by preceding
|
||||
|
@ -73,30 +73,28 @@ impl<T, A: AllocRef> RawVec<T, A> {
|
||||
}
|
||||
|
||||
fn allocate_in(mut capacity: usize, zeroed: bool, mut a: A) -> Self {
|
||||
unsafe {
|
||||
let elem_size = mem::size_of::<T>();
|
||||
let elem_size = mem::size_of::<T>();
|
||||
|
||||
let alloc_size = capacity.checked_mul(elem_size).unwrap_or_else(|| capacity_overflow());
|
||||
alloc_guard(alloc_size).unwrap_or_else(|_| capacity_overflow());
|
||||
let alloc_size = capacity.checked_mul(elem_size).unwrap_or_else(|| capacity_overflow());
|
||||
alloc_guard(alloc_size).unwrap_or_else(|_| capacity_overflow());
|
||||
|
||||
// Handles ZSTs and `capacity == 0` alike.
|
||||
let ptr = if alloc_size == 0 {
|
||||
NonNull::<T>::dangling()
|
||||
} else {
|
||||
let align = mem::align_of::<T>();
|
||||
let layout = Layout::from_size_align(alloc_size, align).unwrap();
|
||||
let result = if zeroed { a.alloc_zeroed(layout) } else { a.alloc(layout) };
|
||||
match result {
|
||||
Ok((ptr, size)) => {
|
||||
capacity = size / elem_size;
|
||||
ptr.cast()
|
||||
}
|
||||
Err(_) => handle_alloc_error(layout),
|
||||
// Handles ZSTs and `capacity == 0` alike.
|
||||
let ptr = if alloc_size == 0 {
|
||||
NonNull::<T>::dangling()
|
||||
} else {
|
||||
let align = mem::align_of::<T>();
|
||||
let layout = Layout::from_size_align(alloc_size, align).unwrap();
|
||||
let result = if zeroed { a.alloc_zeroed(layout) } else { a.alloc(layout) };
|
||||
match result {
|
||||
Ok((ptr, size)) => {
|
||||
capacity = size / elem_size;
|
||||
ptr.cast()
|
||||
}
|
||||
};
|
||||
Err(_) => handle_alloc_error(layout),
|
||||
}
|
||||
};
|
||||
|
||||
RawVec { ptr: ptr.into(), cap: capacity, a }
|
||||
}
|
||||
RawVec { ptr: ptr.into(), cap: capacity, a }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -20,7 +20,7 @@ fn allocator_param() {
|
||||
fuel: usize,
|
||||
}
|
||||
unsafe impl AllocRef for BoundedAlloc {
|
||||
unsafe fn alloc(&mut self, layout: Layout) -> Result<(NonNull<u8>, usize), AllocErr> {
|
||||
fn alloc(&mut self, layout: Layout) -> Result<(NonNull<u8>, usize), AllocErr> {
|
||||
let size = layout.size();
|
||||
if size > self.fuel {
|
||||
return Err(AllocErr);
|
||||
|
@ -317,7 +317,7 @@ impl<T> Vec<T> {
|
||||
/// let mut vec: Vec<i32> = Vec::new();
|
||||
/// ```
|
||||
#[inline]
|
||||
#[rustc_const_stable(feature = "const_vec_new", since = "1.32.0")]
|
||||
#[rustc_const_stable(feature = "const_vec_new", since = "1.39.0")]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub const fn new() -> Vec<T> {
|
||||
Vec { buf: RawVec::NEW, len: 0 }
|
||||
|
@ -606,20 +606,11 @@ pub unsafe trait GlobalAlloc {
|
||||
/// method (`dealloc`) or by being passed to a reallocation method
|
||||
/// (see above) that returns `Ok`.
|
||||
///
|
||||
/// A note regarding zero-sized types and zero-sized layouts: many
|
||||
/// methods in the `AllocRef` trait state that allocation requests
|
||||
/// must be non-zero size, or else undefined behavior can result.
|
||||
///
|
||||
/// * If an `AllocRef` implementation chooses to return `Ok` in this
|
||||
/// case (i.e., the pointer denotes a zero-sized inaccessible block)
|
||||
/// then that returned pointer must be considered "currently
|
||||
/// allocated". On such an allocator, *all* methods that take
|
||||
/// currently-allocated pointers as inputs must accept these
|
||||
/// zero-sized pointers, *without* causing undefined behavior.
|
||||
///
|
||||
/// * In other words, if a zero-sized pointer can flow out of an
|
||||
/// allocator, then that allocator must likewise accept that pointer
|
||||
/// flowing back into its deallocation and reallocation methods.
|
||||
/// Unlike [`GlobalAlloc`], zero-sized allocations are allowed in
|
||||
/// `AllocRef`. If an underlying allocator does not support this (like
|
||||
/// jemalloc) or return a null pointer (such as `libc::malloc`), this case
|
||||
/// must be caught. In this case [`Layout::dangling()`] can be used to
|
||||
/// create a dangling, but aligned `NonNull<u8>`.
|
||||
///
|
||||
/// Some of the methods require that a layout *fit* a memory block.
|
||||
/// What it means for a layout to "fit" a memory block means (or
|
||||
@ -649,6 +640,9 @@ pub unsafe trait GlobalAlloc {
|
||||
/// * if an allocator does not support overallocating, it is fine to
|
||||
/// simply return `layout.size()` as the allocated size.
|
||||
///
|
||||
/// [`GlobalAlloc`]: self::GlobalAlloc
|
||||
/// [`Layout::dangling()`]: self::Layout::dangling
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The `AllocRef` trait is an `unsafe` trait for a number of reasons, and
|
||||
@ -669,14 +663,6 @@ pub unsafe trait GlobalAlloc {
|
||||
/// the future.
|
||||
#[unstable(feature = "allocator_api", issue = "32838")]
|
||||
pub unsafe trait AllocRef {
|
||||
// (Note: some existing allocators have unspecified but well-defined
|
||||
// behavior in response to a zero size allocation request ;
|
||||
// e.g., in C, `malloc` of 0 will either return a null pointer or a
|
||||
// unique pointer, but will not have arbitrary undefined
|
||||
// behavior.
|
||||
// However in jemalloc for example,
|
||||
// `mallocx(0)` is documented as undefined behavior.)
|
||||
|
||||
/// On success, returns a pointer meeting the size and alignment
|
||||
/// guarantees of `layout` and the actual size of the allocated block,
|
||||
/// which must be greater than or equal to `layout.size()`.
|
||||
@ -690,15 +676,6 @@ pub unsafe trait AllocRef {
|
||||
/// behavior, e.g., to ensure initialization to particular sets of
|
||||
/// bit patterns.)
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// This function is unsafe because undefined behavior can result
|
||||
/// if the caller does not ensure that `layout` has non-zero size.
|
||||
///
|
||||
/// (Extension subtraits might provide more specific bounds on
|
||||
/// behavior, e.g., guarantee a sentinel address or a null pointer
|
||||
/// in response to a zero-size allocation request.)
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// Returning `Err` indicates that either memory is exhausted or
|
||||
@ -716,7 +693,7 @@ pub unsafe trait AllocRef {
|
||||
/// rather than directly invoking `panic!` or similar.
|
||||
///
|
||||
/// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
|
||||
unsafe fn alloc(&mut self, layout: Layout) -> Result<(NonNull<u8>, usize), AllocErr>;
|
||||
fn alloc(&mut self, layout: Layout) -> Result<(NonNull<u8>, usize), AllocErr>;
|
||||
|
||||
/// Deallocate the memory referenced by `ptr`.
|
||||
///
|
||||
@ -738,10 +715,6 @@ pub unsafe trait AllocRef {
|
||||
/// Behaves like `alloc`, but also ensures that the contents
|
||||
/// are set to zero before being returned.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// This function is unsafe for the same reasons that `alloc` is.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// Returning `Err` indicates that either memory is exhausted or
|
||||
@ -753,17 +726,17 @@ pub unsafe trait AllocRef {
|
||||
/// rather than directly invoking `panic!` or similar.
|
||||
///
|
||||
/// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
|
||||
unsafe fn alloc_zeroed(&mut self, layout: Layout) -> Result<(NonNull<u8>, usize), AllocErr> {
|
||||
fn alloc_zeroed(&mut self, layout: Layout) -> Result<(NonNull<u8>, usize), AllocErr> {
|
||||
let size = layout.size();
|
||||
let result = self.alloc(layout);
|
||||
if let Ok((p, _)) = result {
|
||||
ptr::write_bytes(p.as_ptr(), 0, size);
|
||||
unsafe { ptr::write_bytes(p.as_ptr(), 0, size) }
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
// == METHODS FOR MEMORY REUSE ==
|
||||
// realloc. alloc_excess, realloc_excess
|
||||
// realloc, realloc_zeroed, grow_in_place, grow_in_place_zeroed, shrink_in_place
|
||||
|
||||
/// Returns a pointer suitable for holding data described by
|
||||
/// a new layout with `layout`’s alignment and a size given
|
||||
@ -793,8 +766,6 @@ pub unsafe trait AllocRef {
|
||||
/// * `layout` must *fit* the `ptr` (see above). (The `new_size`
|
||||
/// argument need not fit it.)
|
||||
///
|
||||
/// * `new_size` must be greater than zero.
|
||||
///
|
||||
/// * `new_size`, when rounded up to the nearest multiple of `layout.align()`,
|
||||
/// must not overflow (i.e., the rounded value must be less than `usize::MAX`).
|
||||
///
|
||||
@ -1009,8 +980,7 @@ pub unsafe trait AllocRef {
|
||||
/// * `layout` must *fit* the `ptr` (see above); note the
|
||||
/// `new_size` argument need not fit it,
|
||||
///
|
||||
/// * `new_size` must not be greater than `layout.size()`
|
||||
/// (and must be greater than zero),
|
||||
/// * `new_size` must not be greater than `layout.size()`,
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
|
@ -24,7 +24,6 @@ use crate::task::{Context, Poll};
|
||||
/// `.await` the value.
|
||||
///
|
||||
/// [`Waker`]: ../task/struct.Waker.html
|
||||
#[doc(spotlight)]
|
||||
#[must_use = "futures do nothing unless you `.await` or poll them"]
|
||||
#[stable(feature = "futures_api", since = "1.36.0")]
|
||||
#[lang = "future_trait"]
|
||||
|
@ -92,7 +92,6 @@ fn _assert_is_object_safe(_: &dyn Iterator<Item = ()>) {}
|
||||
label = "`{Self}` is not an iterator",
|
||||
message = "`{Self}` is not an iterator"
|
||||
)]
|
||||
#[doc(spotlight)]
|
||||
#[must_use = "iterators are lazy and do nothing unless consumed"]
|
||||
pub trait Iterator {
|
||||
/// The type of the elements being iterated over.
|
||||
|
@ -90,7 +90,6 @@
|
||||
#![feature(custom_inner_attributes)]
|
||||
#![feature(decl_macro)]
|
||||
#![feature(doc_cfg)]
|
||||
#![feature(doc_spotlight)]
|
||||
#![feature(extern_types)]
|
||||
#![feature(fundamental)]
|
||||
#![feature(intrinsics)]
|
||||
|
@ -360,33 +360,9 @@ rustc_dep_node_append!([define_dep_nodes!][ <'tcx>
|
||||
[anon] TraitSelect,
|
||||
|
||||
[] CompileCodegenUnit(Symbol),
|
||||
|
||||
[eval_always] Analysis(CrateNum),
|
||||
]);
|
||||
|
||||
pub trait RecoverKey<'tcx>: Sized {
|
||||
fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self>;
|
||||
}
|
||||
|
||||
impl RecoverKey<'tcx> for CrateNum {
|
||||
fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> {
|
||||
dep_node.extract_def_id(tcx).map(|id| id.krate)
|
||||
}
|
||||
}
|
||||
|
||||
impl RecoverKey<'tcx> for DefId {
|
||||
fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> {
|
||||
dep_node.extract_def_id(tcx)
|
||||
}
|
||||
}
|
||||
|
||||
impl RecoverKey<'tcx> for DefIndex {
|
||||
fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> {
|
||||
dep_node.extract_def_id(tcx).map(|id| id.index)
|
||||
}
|
||||
}
|
||||
|
||||
trait DepNodeParams<'tcx>: fmt::Debug {
|
||||
pub(crate) trait DepNodeParams<'tcx>: fmt::Debug + Sized {
|
||||
const CAN_RECONSTRUCT_QUERY_KEY: bool;
|
||||
|
||||
/// This method turns the parameters of a DepNodeConstructor into an opaque
|
||||
@ -400,6 +376,14 @@ trait DepNodeParams<'tcx>: fmt::Debug {
|
||||
fn to_debug_str(&self, _: TyCtxt<'tcx>) -> String {
|
||||
format!("{:?}", self)
|
||||
}
|
||||
|
||||
/// This method tries to recover the query key from the given `DepNode`,
|
||||
/// something which is needed when forcing `DepNode`s during red-green
|
||||
/// evaluation. The query system will only call this method if
|
||||
/// `CAN_RECONSTRUCT_QUERY_KEY` is `true`.
|
||||
/// It is always valid to return `None` here, in which case incremental
|
||||
/// compilation will treat the query as having changed instead of forcing it.
|
||||
fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self>;
|
||||
}
|
||||
|
||||
impl<'tcx, T> DepNodeParams<'tcx> for T
|
||||
@ -420,6 +404,10 @@ where
|
||||
default fn to_debug_str(&self, _: TyCtxt<'tcx>) -> String {
|
||||
format!("{:?}", *self)
|
||||
}
|
||||
|
||||
default fn recover(_: TyCtxt<'tcx>, _: &DepNode) -> Option<Self> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> DepNodeParams<'tcx> for DefId {
|
||||
@ -432,6 +420,10 @@ impl<'tcx> DepNodeParams<'tcx> for DefId {
|
||||
fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String {
|
||||
tcx.def_path_str(*self)
|
||||
}
|
||||
|
||||
fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> {
|
||||
dep_node.extract_def_id(tcx)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> DepNodeParams<'tcx> for DefIndex {
|
||||
@ -444,6 +436,10 @@ impl<'tcx> DepNodeParams<'tcx> for DefIndex {
|
||||
fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String {
|
||||
tcx.def_path_str(DefId::local(*self))
|
||||
}
|
||||
|
||||
fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> {
|
||||
dep_node.extract_def_id(tcx).map(|id| id.index)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> DepNodeParams<'tcx> for CrateNum {
|
||||
@ -457,6 +453,10 @@ impl<'tcx> DepNodeParams<'tcx> for CrateNum {
|
||||
fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String {
|
||||
tcx.crate_name(*self).to_string()
|
||||
}
|
||||
|
||||
fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> {
|
||||
dep_node.extract_def_id(tcx).map(|id| id.krate)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> DepNodeParams<'tcx> for (DefId, DefId) {
|
||||
|
@ -6,7 +6,8 @@ mod query;
|
||||
mod safe;
|
||||
mod serialized;
|
||||
|
||||
pub use self::dep_node::{label_strs, DepConstructor, DepKind, DepNode, RecoverKey, WorkProductId};
|
||||
pub(crate) use self::dep_node::DepNodeParams;
|
||||
pub use self::dep_node::{label_strs, DepConstructor, DepKind, DepNode, WorkProductId};
|
||||
pub use self::graph::WorkProductFileKind;
|
||||
pub use self::graph::{hash_result, DepGraph, DepNodeColor, DepNodeIndex, TaskDeps, WorkProduct};
|
||||
pub use self::prev::PreviousDepGraph;
|
||||
|
@ -1827,9 +1827,9 @@ rustc_index::newtype_index! {
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct PlaceRef<'a, 'tcx> {
|
||||
pub struct PlaceRef<'tcx> {
|
||||
pub local: Local,
|
||||
pub projection: &'a [PlaceElem<'tcx>],
|
||||
pub projection: &'tcx [PlaceElem<'tcx>],
|
||||
}
|
||||
|
||||
impl<'tcx> Place<'tcx> {
|
||||
@ -1864,7 +1864,7 @@ impl<'tcx> Place<'tcx> {
|
||||
self.as_ref().as_local()
|
||||
}
|
||||
|
||||
pub fn as_ref(&self) -> PlaceRef<'_, 'tcx> {
|
||||
pub fn as_ref(&self) -> PlaceRef<'tcx> {
|
||||
PlaceRef { local: self.local, projection: &self.projection }
|
||||
}
|
||||
}
|
||||
@ -1875,7 +1875,7 @@ impl From<Local> for Place<'_> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> PlaceRef<'a, 'tcx> {
|
||||
impl<'tcx> PlaceRef<'tcx> {
|
||||
/// Finds the innermost `Local` from this `Place`, *if* it is either a local itself or
|
||||
/// a single deref of a local.
|
||||
//
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::dep_graph::{DepKind, DepNode, RecoverKey, SerializedDepNodeIndex};
|
||||
use crate::dep_graph::SerializedDepNodeIndex;
|
||||
use crate::mir;
|
||||
use crate::mir::interpret::{GlobalId, LitToConstInput};
|
||||
use crate::traits;
|
||||
@ -60,6 +60,11 @@ rustc_queries! {
|
||||
cache_on_disk_if { key.is_local() }
|
||||
}
|
||||
|
||||
query analysis(key: CrateNum) -> Result<(), ErrorReported> {
|
||||
eval_always
|
||||
desc { "running analysis passes on this crate" }
|
||||
}
|
||||
|
||||
/// Maps from the `DefId` of an item (trait/struct/enum/fn) to its
|
||||
/// associated generics.
|
||||
query generics_of(key: DefId) -> &'tcx ty::Generics {
|
||||
@ -195,7 +200,6 @@ rustc_queries! {
|
||||
// queries). Making it anonymous avoids hashing the result, which
|
||||
// may save a bit of time.
|
||||
anon
|
||||
no_force
|
||||
desc { "erasing regions from `{:?}`", ty }
|
||||
}
|
||||
|
||||
@ -204,7 +208,6 @@ rustc_queries! {
|
||||
}
|
||||
|
||||
query program_clauses_for_env(_: traits::Environment<'tcx>) -> Clauses<'tcx> {
|
||||
no_force
|
||||
desc { "generating chalk-style clauses for environment" }
|
||||
}
|
||||
|
||||
@ -247,7 +250,6 @@ rustc_queries! {
|
||||
/// To avoid cycles within the predicates of a single item we compute
|
||||
/// per-type-parameter predicates for resolving `T::AssocTy`.
|
||||
query type_param_predicates(key: (DefId, DefId)) -> ty::GenericPredicates<'tcx> {
|
||||
no_force
|
||||
desc { |tcx| "computing the bounds for type parameter `{}`", {
|
||||
let id = tcx.hir().as_local_hir_id(key.1).unwrap();
|
||||
tcx.hir().ty_param_name(id)
|
||||
@ -503,7 +505,6 @@ rustc_queries! {
|
||||
/// form to be used outside of const eval.
|
||||
query const_eval_raw(key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>)
|
||||
-> ConstEvalRawResult<'tcx> {
|
||||
no_force
|
||||
desc { |tcx|
|
||||
"const-evaluating `{}`",
|
||||
tcx.def_path_str(key.value.instance.def.def_id())
|
||||
@ -520,7 +521,6 @@ rustc_queries! {
|
||||
/// `tcx.const_eval_resolve`, `tcx.const_eval_instance`, or `tcx.const_eval_global_id`.
|
||||
query const_eval_validated(key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>)
|
||||
-> ConstEvalResult<'tcx> {
|
||||
no_force
|
||||
desc { |tcx|
|
||||
"const-evaluating + checking `{}`",
|
||||
tcx.def_path_str(key.value.instance.def.def_id())
|
||||
@ -535,7 +535,6 @@ rustc_queries! {
|
||||
query const_field(
|
||||
key: ty::ParamEnvAnd<'tcx, (&'tcx ty::Const<'tcx>, mir::Field)>
|
||||
) -> ConstValue<'tcx> {
|
||||
no_force
|
||||
desc { "extract field of const" }
|
||||
}
|
||||
|
||||
@ -544,19 +543,16 @@ rustc_queries! {
|
||||
query destructure_const(
|
||||
key: ty::ParamEnvAnd<'tcx, &'tcx ty::Const<'tcx>>
|
||||
) -> mir::DestructuredConst<'tcx> {
|
||||
no_force
|
||||
desc { "destructure constant" }
|
||||
}
|
||||
|
||||
query const_caller_location(key: (rustc_span::Symbol, u32, u32)) -> ConstValue<'tcx> {
|
||||
no_force
|
||||
desc { "get a &core::panic::Location referring to a span" }
|
||||
}
|
||||
|
||||
query lit_to_const(
|
||||
key: LitToConstInput<'tcx>
|
||||
) -> Result<&'tcx ty::Const<'tcx>, LitToConstError> {
|
||||
no_force
|
||||
desc { "converting literal to const" }
|
||||
}
|
||||
}
|
||||
@ -587,7 +583,6 @@ rustc_queries! {
|
||||
query region_scope_tree(_: DefId) -> &'tcx region::ScopeTree {}
|
||||
|
||||
query mir_shims(key: ty::InstanceDef<'tcx>) -> &'tcx mir::BodyAndCache<'tcx> {
|
||||
no_force
|
||||
desc { |tcx| "generating MIR shim for `{}`", tcx.def_path_str(key.def_id()) }
|
||||
}
|
||||
|
||||
@ -595,7 +590,6 @@ rustc_queries! {
|
||||
/// given instance from the local crate. In particular, it will also
|
||||
/// look up the correct symbol name of instances from upstream crates.
|
||||
query symbol_name(key: ty::Instance<'tcx>) -> ty::SymbolName {
|
||||
no_force
|
||||
desc { "computing the symbol for `{}`", key }
|
||||
cache_on_disk_if { true }
|
||||
}
|
||||
@ -642,7 +636,6 @@ rustc_queries! {
|
||||
Other {
|
||||
query vtable_methods(key: ty::PolyTraitRef<'tcx>)
|
||||
-> &'tcx [Option<(DefId, SubstsRef<'tcx>)>] {
|
||||
no_force
|
||||
desc { |tcx| "finding all methods for trait {}", tcx.def_path_str(key.def_id()) }
|
||||
}
|
||||
}
|
||||
@ -651,7 +644,6 @@ rustc_queries! {
|
||||
query codegen_fulfill_obligation(
|
||||
key: (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>)
|
||||
) -> Option<Vtable<'tcx, ()>> {
|
||||
no_force
|
||||
cache_on_disk_if { true }
|
||||
desc { |tcx|
|
||||
"checking if `{}` fulfills its obligations",
|
||||
@ -683,22 +675,18 @@ rustc_queries! {
|
||||
/// Trait selection queries. These are best used by invoking `ty.is_copy_modulo_regions()`,
|
||||
/// `ty.is_copy()`, etc, since that will prune the environment where possible.
|
||||
query is_copy_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
|
||||
no_force
|
||||
desc { "computing whether `{}` is `Copy`", env.value }
|
||||
}
|
||||
/// Query backing `TyS::is_sized`.
|
||||
query is_sized_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
|
||||
no_force
|
||||
desc { "computing whether `{}` is `Sized`", env.value }
|
||||
}
|
||||
/// Query backing `TyS::is_freeze`.
|
||||
query is_freeze_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
|
||||
no_force
|
||||
desc { "computing whether `{}` is freeze", env.value }
|
||||
}
|
||||
/// Query backing `TyS::needs_drop`.
|
||||
query needs_drop_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
|
||||
no_force
|
||||
desc { "computing whether `{}` needs drop", env.value }
|
||||
}
|
||||
|
||||
@ -712,7 +700,6 @@ rustc_queries! {
|
||||
query layout_raw(
|
||||
env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>
|
||||
) -> Result<&'tcx ty::layout::LayoutDetails, ty::layout::LayoutError<'tcx>> {
|
||||
no_force
|
||||
desc { "computing layout of `{}`", env.value }
|
||||
}
|
||||
}
|
||||
@ -768,7 +755,6 @@ rustc_queries! {
|
||||
|
||||
TypeChecking {
|
||||
query specializes(_: (DefId, DefId)) -> bool {
|
||||
no_force
|
||||
desc { "computing whether impls specialize one another" }
|
||||
}
|
||||
query in_scope_traits_map(_: DefIndex)
|
||||
@ -853,7 +839,6 @@ rustc_queries! {
|
||||
/// (like `Clone::clone` for example).
|
||||
query upstream_drop_glue_for(substs: SubstsRef<'tcx>) -> Option<CrateNum> {
|
||||
desc { "available upstream drop-glue for `{:?}`", substs }
|
||||
no_force
|
||||
}
|
||||
}
|
||||
|
||||
@ -898,7 +883,6 @@ rustc_queries! {
|
||||
TypeChecking {
|
||||
query implementations_of_trait(_: (CrateNum, DefId))
|
||||
-> &'tcx [DefId] {
|
||||
no_force
|
||||
desc { "looking up implementations of a trait in a crate" }
|
||||
}
|
||||
query all_trait_implementations(_: CrateNum)
|
||||
@ -1065,7 +1049,6 @@ rustc_queries! {
|
||||
}
|
||||
query is_codegened_item(_: DefId) -> bool {}
|
||||
query codegen_unit(_: Symbol) -> Arc<CodegenUnit<'tcx>> {
|
||||
no_force
|
||||
desc { "codegen_unit" }
|
||||
}
|
||||
query backend_optimization_level(_: CrateNum) -> OptLevel {
|
||||
@ -1088,7 +1071,6 @@ rustc_queries! {
|
||||
&'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, NormalizationResult<'tcx>>>,
|
||||
NoSolution,
|
||||
> {
|
||||
no_force
|
||||
desc { "normalizing `{:?}`", goal }
|
||||
}
|
||||
|
||||
@ -1096,7 +1078,6 @@ rustc_queries! {
|
||||
query normalize_ty_after_erasing_regions(
|
||||
goal: ParamEnvAnd<'tcx, Ty<'tcx>>
|
||||
) -> Ty<'tcx> {
|
||||
no_force
|
||||
desc { "normalizing `{:?}`", goal }
|
||||
}
|
||||
|
||||
@ -1106,7 +1087,6 @@ rustc_queries! {
|
||||
&'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, Vec<OutlivesBound<'tcx>>>>,
|
||||
NoSolution,
|
||||
> {
|
||||
no_force
|
||||
desc { "computing implied outlives bounds for `{:?}`", goal }
|
||||
}
|
||||
|
||||
@ -1117,7 +1097,6 @@ rustc_queries! {
|
||||
&'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, DropckOutlivesResult<'tcx>>>,
|
||||
NoSolution,
|
||||
> {
|
||||
no_force
|
||||
desc { "computing dropck types for `{:?}`", goal }
|
||||
}
|
||||
|
||||
@ -1126,7 +1105,6 @@ rustc_queries! {
|
||||
query evaluate_obligation(
|
||||
goal: CanonicalPredicateGoal<'tcx>
|
||||
) -> Result<traits::EvaluationResult, traits::OverflowError> {
|
||||
no_force
|
||||
desc { "evaluating trait selection obligation `{}`", goal.value.value }
|
||||
}
|
||||
|
||||
@ -1137,7 +1115,6 @@ rustc_queries! {
|
||||
&'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, ()>>,
|
||||
NoSolution,
|
||||
> {
|
||||
no_force
|
||||
desc { "evaluating `type_op_ascribe_user_type` `{:?}`", goal }
|
||||
}
|
||||
|
||||
@ -1148,7 +1125,6 @@ rustc_queries! {
|
||||
&'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, ()>>,
|
||||
NoSolution,
|
||||
> {
|
||||
no_force
|
||||
desc { "evaluating `type_op_eq` `{:?}`", goal }
|
||||
}
|
||||
|
||||
@ -1159,7 +1135,6 @@ rustc_queries! {
|
||||
&'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, ()>>,
|
||||
NoSolution,
|
||||
> {
|
||||
no_force
|
||||
desc { "evaluating `type_op_subtype` `{:?}`", goal }
|
||||
}
|
||||
|
||||
@ -1170,7 +1145,6 @@ rustc_queries! {
|
||||
&'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, ()>>,
|
||||
NoSolution,
|
||||
> {
|
||||
no_force
|
||||
desc { "evaluating `type_op_prove_predicate` `{:?}`", goal }
|
||||
}
|
||||
|
||||
@ -1181,7 +1155,6 @@ rustc_queries! {
|
||||
&'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, Ty<'tcx>>>,
|
||||
NoSolution,
|
||||
> {
|
||||
no_force
|
||||
desc { "normalizing `{:?}`", goal }
|
||||
}
|
||||
|
||||
@ -1192,7 +1165,6 @@ rustc_queries! {
|
||||
&'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, ty::Predicate<'tcx>>>,
|
||||
NoSolution,
|
||||
> {
|
||||
no_force
|
||||
desc { "normalizing `{:?}`", goal }
|
||||
}
|
||||
|
||||
@ -1203,7 +1175,6 @@ rustc_queries! {
|
||||
&'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, ty::PolyFnSig<'tcx>>>,
|
||||
NoSolution,
|
||||
> {
|
||||
no_force
|
||||
desc { "normalizing `{:?}`", goal }
|
||||
}
|
||||
|
||||
@ -1214,12 +1185,10 @@ rustc_queries! {
|
||||
&'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, ty::FnSig<'tcx>>>,
|
||||
NoSolution,
|
||||
> {
|
||||
no_force
|
||||
desc { "normalizing `{:?}`", goal }
|
||||
}
|
||||
|
||||
query substitute_normalize_and_test_predicates(key: (DefId, SubstsRef<'tcx>)) -> bool {
|
||||
no_force
|
||||
desc { |tcx|
|
||||
"testing substituted normalized predicates:`{}`",
|
||||
tcx.def_path_str(key.0)
|
||||
@ -1229,7 +1198,6 @@ rustc_queries! {
|
||||
query method_autoderef_steps(
|
||||
goal: CanonicalTyGoal<'tcx>
|
||||
) -> MethodAutoderefStepsResult<'tcx> {
|
||||
no_force
|
||||
desc { "computing autoderef types for `{:?}`", goal }
|
||||
}
|
||||
}
|
||||
@ -1243,7 +1211,6 @@ rustc_queries! {
|
||||
// Get an estimate of the size of an InstanceDef based on its MIR for CGU partitioning.
|
||||
query instance_def_size_estimate(def: ty::InstanceDef<'tcx>)
|
||||
-> usize {
|
||||
no_force
|
||||
desc { |tcx| "estimating size for `{}`", tcx.def_path_str(def.def_id()) }
|
||||
}
|
||||
|
||||
|
@ -2,11 +2,10 @@ use crate::dep_graph::SerializedDepNodeIndex;
|
||||
use crate::dep_graph::{DepKind, DepNode};
|
||||
use crate::ty::query::caches::QueryCache;
|
||||
use crate::ty::query::plumbing::CycleError;
|
||||
use crate::ty::query::queries;
|
||||
use crate::ty::query::{Query, QueryState};
|
||||
use crate::ty::TyCtxt;
|
||||
use rustc_data_structures::profiling::ProfileCategory;
|
||||
use rustc_hir::def_id::{CrateNum, DefId};
|
||||
use rustc_hir::def_id::DefId;
|
||||
|
||||
use crate::ich::StableHashingContext;
|
||||
use rustc_data_structures::fingerprint::Fingerprint;
|
||||
@ -87,9 +86,3 @@ where
|
||||
bug!("QueryDescription::load_from_disk() called for an unsupported query.")
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription<'tcx> for queries::analysis<'tcx> {
|
||||
fn describe(_tcx: TyCtxt<'_>, _: CrateNum) -> Cow<'static, str> {
|
||||
"running analysis passes on this crate".into()
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::dep_graph::{self, DepConstructor, DepNode};
|
||||
use crate::dep_graph::{self, DepConstructor, DepNode, DepNodeParams};
|
||||
use crate::hir::exports::Export;
|
||||
use crate::infer::canonical::{self, Canonical};
|
||||
use crate::lint::LintLevelMap;
|
||||
@ -60,8 +60,8 @@ use std::sync::Arc;
|
||||
|
||||
#[macro_use]
|
||||
mod plumbing;
|
||||
pub use self::plumbing::CycleError;
|
||||
use self::plumbing::*;
|
||||
pub use self::plumbing::{force_from_dep_node, CycleError};
|
||||
|
||||
mod stats;
|
||||
pub use self::stats::print_stats;
|
||||
@ -104,9 +104,105 @@ pub use self::profiling_support::{IntoSelfProfilingString, QueryKeyStringBuilder
|
||||
// Queries marked with `fatal_cycle` do not need the latter implementation,
|
||||
// as they will raise an fatal error on query cycles instead.
|
||||
|
||||
rustc_query_append! { [define_queries!][ <'tcx>
|
||||
Other {
|
||||
/// Runs analysis passes on the crate.
|
||||
[eval_always] fn analysis: Analysis(CrateNum) -> Result<(), ErrorReported>,
|
||||
},
|
||||
]}
|
||||
rustc_query_append! { [define_queries!][<'tcx>] }
|
||||
|
||||
/// The red/green evaluation system will try to mark a specific DepNode in the
|
||||
/// dependency graph as green by recursively trying to mark the dependencies of
|
||||
/// that `DepNode` as green. While doing so, it will sometimes encounter a `DepNode`
|
||||
/// where we don't know if it is red or green and we therefore actually have
|
||||
/// to recompute its value in order to find out. Since the only piece of
|
||||
/// information that we have at that point is the `DepNode` we are trying to
|
||||
/// re-evaluate, we need some way to re-run a query from just that. This is what
|
||||
/// `force_from_dep_node()` implements.
|
||||
///
|
||||
/// In the general case, a `DepNode` consists of a `DepKind` and an opaque
|
||||
/// GUID/fingerprint that will uniquely identify the node. This GUID/fingerprint
|
||||
/// is usually constructed by computing a stable hash of the query-key that the
|
||||
/// `DepNode` corresponds to. Consequently, it is not in general possible to go
|
||||
/// back from hash to query-key (since hash functions are not reversible). For
|
||||
/// this reason `force_from_dep_node()` is expected to fail from time to time
|
||||
/// because we just cannot find out, from the `DepNode` alone, what the
|
||||
/// corresponding query-key is and therefore cannot re-run the query.
|
||||
///
|
||||
/// The system deals with this case letting `try_mark_green` fail which forces
|
||||
/// the root query to be re-evaluated.
|
||||
///
|
||||
/// Now, if `force_from_dep_node()` would always fail, it would be pretty useless.
|
||||
/// Fortunately, we can use some contextual information that will allow us to
|
||||
/// reconstruct query-keys for certain kinds of `DepNode`s. In particular, we
|
||||
/// enforce by construction that the GUID/fingerprint of certain `DepNode`s is a
|
||||
/// valid `DefPathHash`. Since we also always build a huge table that maps every
|
||||
/// `DefPathHash` in the current codebase to the corresponding `DefId`, we have
|
||||
/// everything we need to re-run the query.
|
||||
///
|
||||
/// Take the `mir_validated` query as an example. Like many other queries, it
|
||||
/// just has a single parameter: the `DefId` of the item it will compute the
|
||||
/// validated MIR for. Now, when we call `force_from_dep_node()` on a `DepNode`
|
||||
/// with kind `MirValidated`, we know that the GUID/fingerprint of the `DepNode`
|
||||
/// is actually a `DefPathHash`, and can therefore just look up the corresponding
|
||||
/// `DefId` in `tcx.def_path_hash_to_def_id`.
|
||||
///
|
||||
/// When you implement a new query, it will likely have a corresponding new
|
||||
/// `DepKind`, and you'll have to support it here in `force_from_dep_node()`. As
|
||||
/// a rule of thumb, if your query takes a `DefId` or `DefIndex` as sole parameter,
|
||||
/// then `force_from_dep_node()` should not fail for it. Otherwise, you can just
|
||||
/// add it to the "We don't have enough information to reconstruct..." group in
|
||||
/// the match below.
|
||||
pub fn force_from_dep_node<'tcx>(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> bool {
|
||||
use crate::dep_graph::DepKind;
|
||||
|
||||
// We must avoid ever having to call `force_from_dep_node()` for a
|
||||
// `DepNode::codegen_unit`:
|
||||
// Since we cannot reconstruct the query key of a `DepNode::codegen_unit`, we
|
||||
// would always end up having to evaluate the first caller of the
|
||||
// `codegen_unit` query that *is* reconstructible. This might very well be
|
||||
// the `compile_codegen_unit` query, thus re-codegenning the whole CGU just
|
||||
// to re-trigger calling the `codegen_unit` query with the right key. At
|
||||
// that point we would already have re-done all the work we are trying to
|
||||
// avoid doing in the first place.
|
||||
// The solution is simple: Just explicitly call the `codegen_unit` query for
|
||||
// each CGU, right after partitioning. This way `try_mark_green` will always
|
||||
// hit the cache instead of having to go through `force_from_dep_node`.
|
||||
// This assertion makes sure, we actually keep applying the solution above.
|
||||
debug_assert!(
|
||||
dep_node.kind != DepKind::codegen_unit,
|
||||
"calling force_from_dep_node() on DepKind::codegen_unit"
|
||||
);
|
||||
|
||||
if !dep_node.kind.can_reconstruct_query_key() {
|
||||
return false;
|
||||
}
|
||||
|
||||
rustc_dep_node_force!([dep_node, tcx]
|
||||
// These are inputs that are expected to be pre-allocated and that
|
||||
// should therefore always be red or green already.
|
||||
DepKind::AllLocalTraitImpls |
|
||||
DepKind::CrateMetadata |
|
||||
DepKind::HirBody |
|
||||
DepKind::Hir |
|
||||
|
||||
// These are anonymous nodes.
|
||||
DepKind::TraitSelect |
|
||||
|
||||
// We don't have enough information to reconstruct the query key of
|
||||
// these.
|
||||
DepKind::CompileCodegenUnit => {
|
||||
bug!("force_from_dep_node: encountered {:?}", dep_node)
|
||||
}
|
||||
);
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
impl DepNode {
|
||||
/// Check whether the query invocation corresponding to the given
|
||||
/// DepNode is eligible for on-disk-caching. If so, this is method
|
||||
/// will execute the query corresponding to the given DepNode.
|
||||
/// Also, as a sanity check, it expects that the corresponding query
|
||||
/// invocation has been marked as green already.
|
||||
pub fn try_load_from_on_disk_cache<'tcx>(&self, tcx: TyCtxt<'tcx>) {
|
||||
use crate::dep_graph::DepKind;
|
||||
|
||||
rustc_dep_node_try_load_from_on_disk_cache!(self, tcx)
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
//! generate the actual methods on tcx which find and execute the provider,
|
||||
//! manage the caches, and so forth.
|
||||
|
||||
use crate::dep_graph::{DepKind, DepNode, DepNodeIndex, SerializedDepNodeIndex};
|
||||
use crate::dep_graph::{DepNode, DepNodeIndex, SerializedDepNodeIndex};
|
||||
use crate::ty::query::caches::QueryCache;
|
||||
use crate::ty::query::config::{QueryAccessors, QueryDescription};
|
||||
use crate::ty::query::job::{QueryInfo, QueryJob, QueryJobId, QueryShardJobId};
|
||||
@ -720,7 +720,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn force_query<Q: QueryDescription<'tcx> + 'tcx>(
|
||||
pub(super) fn force_query<Q: QueryDescription<'tcx> + 'tcx>(
|
||||
self,
|
||||
key: Q::Key,
|
||||
span: Span,
|
||||
@ -1162,105 +1162,3 @@ macro_rules! define_provider_struct {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// The red/green evaluation system will try to mark a specific DepNode in the
|
||||
/// dependency graph as green by recursively trying to mark the dependencies of
|
||||
/// that `DepNode` as green. While doing so, it will sometimes encounter a `DepNode`
|
||||
/// where we don't know if it is red or green and we therefore actually have
|
||||
/// to recompute its value in order to find out. Since the only piece of
|
||||
/// information that we have at that point is the `DepNode` we are trying to
|
||||
/// re-evaluate, we need some way to re-run a query from just that. This is what
|
||||
/// `force_from_dep_node()` implements.
|
||||
///
|
||||
/// In the general case, a `DepNode` consists of a `DepKind` and an opaque
|
||||
/// GUID/fingerprint that will uniquely identify the node. This GUID/fingerprint
|
||||
/// is usually constructed by computing a stable hash of the query-key that the
|
||||
/// `DepNode` corresponds to. Consequently, it is not in general possible to go
|
||||
/// back from hash to query-key (since hash functions are not reversible). For
|
||||
/// this reason `force_from_dep_node()` is expected to fail from time to time
|
||||
/// because we just cannot find out, from the `DepNode` alone, what the
|
||||
/// corresponding query-key is and therefore cannot re-run the query.
|
||||
///
|
||||
/// The system deals with this case letting `try_mark_green` fail which forces
|
||||
/// the root query to be re-evaluated.
|
||||
///
|
||||
/// Now, if `force_from_dep_node()` would always fail, it would be pretty useless.
|
||||
/// Fortunately, we can use some contextual information that will allow us to
|
||||
/// reconstruct query-keys for certain kinds of `DepNode`s. In particular, we
|
||||
/// enforce by construction that the GUID/fingerprint of certain `DepNode`s is a
|
||||
/// valid `DefPathHash`. Since we also always build a huge table that maps every
|
||||
/// `DefPathHash` in the current codebase to the corresponding `DefId`, we have
|
||||
/// everything we need to re-run the query.
|
||||
///
|
||||
/// Take the `mir_validated` query as an example. Like many other queries, it
|
||||
/// just has a single parameter: the `DefId` of the item it will compute the
|
||||
/// validated MIR for. Now, when we call `force_from_dep_node()` on a `DepNode`
|
||||
/// with kind `MirValidated`, we know that the GUID/fingerprint of the `DepNode`
|
||||
/// is actually a `DefPathHash`, and can therefore just look up the corresponding
|
||||
/// `DefId` in `tcx.def_path_hash_to_def_id`.
|
||||
///
|
||||
/// When you implement a new query, it will likely have a corresponding new
|
||||
/// `DepKind`, and you'll have to support it here in `force_from_dep_node()`. As
|
||||
/// a rule of thumb, if your query takes a `DefId` or `DefIndex` as sole parameter,
|
||||
/// then `force_from_dep_node()` should not fail for it. Otherwise, you can just
|
||||
/// add it to the "We don't have enough information to reconstruct..." group in
|
||||
/// the match below.
|
||||
pub fn force_from_dep_node(tcx: TyCtxt<'_>, dep_node: &DepNode) -> bool {
|
||||
use crate::dep_graph::RecoverKey;
|
||||
|
||||
// We must avoid ever having to call `force_from_dep_node()` for a
|
||||
// `DepNode::codegen_unit`:
|
||||
// Since we cannot reconstruct the query key of a `DepNode::codegen_unit`, we
|
||||
// would always end up having to evaluate the first caller of the
|
||||
// `codegen_unit` query that *is* reconstructible. This might very well be
|
||||
// the `compile_codegen_unit` query, thus re-codegenning the whole CGU just
|
||||
// to re-trigger calling the `codegen_unit` query with the right key. At
|
||||
// that point we would already have re-done all the work we are trying to
|
||||
// avoid doing in the first place.
|
||||
// The solution is simple: Just explicitly call the `codegen_unit` query for
|
||||
// each CGU, right after partitioning. This way `try_mark_green` will always
|
||||
// hit the cache instead of having to go through `force_from_dep_node`.
|
||||
// This assertion makes sure, we actually keep applying the solution above.
|
||||
debug_assert!(
|
||||
dep_node.kind != DepKind::codegen_unit,
|
||||
"calling force_from_dep_node() on DepKind::codegen_unit"
|
||||
);
|
||||
|
||||
if !dep_node.kind.can_reconstruct_query_key() {
|
||||
return false;
|
||||
}
|
||||
|
||||
rustc_dep_node_force!([dep_node, tcx]
|
||||
// These are inputs that are expected to be pre-allocated and that
|
||||
// should therefore always be red or green already.
|
||||
DepKind::AllLocalTraitImpls |
|
||||
DepKind::CrateMetadata |
|
||||
DepKind::HirBody |
|
||||
DepKind::Hir |
|
||||
|
||||
// These are anonymous nodes.
|
||||
DepKind::TraitSelect |
|
||||
|
||||
// We don't have enough information to reconstruct the query key of
|
||||
// these.
|
||||
DepKind::CompileCodegenUnit => {
|
||||
bug!("force_from_dep_node: encountered {:?}", dep_node)
|
||||
}
|
||||
|
||||
DepKind::Analysis => {
|
||||
let def_id = if let Some(def_id) = dep_node.extract_def_id(tcx) {
|
||||
def_id
|
||||
} else {
|
||||
// Return from the whole function.
|
||||
return false
|
||||
};
|
||||
tcx.force_query::<crate::ty::query::queries::analysis<'_>>(
|
||||
def_id.krate,
|
||||
DUMMY_SP,
|
||||
*dep_node
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
true
|
||||
}
|
||||
|
@ -245,7 +245,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
|
||||
include => external_doc
|
||||
cfg => doc_cfg
|
||||
masked => doc_masked
|
||||
spotlight => doc_spotlight
|
||||
alias => doc_alias
|
||||
keyword => doc_keyword
|
||||
);
|
||||
|
@ -29,11 +29,17 @@ impl AsmBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> {
|
||||
let mut indirect_outputs = vec![];
|
||||
for (i, (out, &place)) in ia.outputs.iter().zip(&outputs).enumerate() {
|
||||
if out.is_rw {
|
||||
inputs.push(self.load_operand(place).immediate());
|
||||
let operand = self.load_operand(place);
|
||||
if let OperandValue::Immediate(_) = operand.val {
|
||||
inputs.push(operand.immediate());
|
||||
}
|
||||
ext_constraints.push(i.to_string());
|
||||
}
|
||||
if out.is_indirect {
|
||||
indirect_outputs.push(self.load_operand(place).immediate());
|
||||
let operand = self.load_operand(place);
|
||||
if let OperandValue::Immediate(_) = operand.val {
|
||||
indirect_outputs.push(operand.immediate());
|
||||
}
|
||||
} else {
|
||||
output_types.push(place.layout.llvm_type(self.cx()));
|
||||
}
|
||||
|
@ -97,7 +97,7 @@ impl<Bx: BuilderMethods<'a, 'tcx>> LocalAnalyzer<'mir, 'a, 'tcx, Bx> {
|
||||
|
||||
fn process_place(
|
||||
&mut self,
|
||||
place_ref: &mir::PlaceRef<'_, 'tcx>,
|
||||
place_ref: &mir::PlaceRef<'tcx>,
|
||||
context: PlaceContext,
|
||||
location: Location,
|
||||
) {
|
||||
|
@ -364,7 +364,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||
fn maybe_codegen_consume_direct(
|
||||
&mut self,
|
||||
bx: &mut Bx,
|
||||
place_ref: mir::PlaceRef<'_, 'tcx>,
|
||||
place_ref: mir::PlaceRef<'tcx>,
|
||||
) -> Option<OperandRef<'tcx, Bx::Value>> {
|
||||
debug!("maybe_codegen_consume_direct(place_ref={:?})", place_ref);
|
||||
|
||||
@ -408,7 +408,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||
pub fn codegen_consume(
|
||||
&mut self,
|
||||
bx: &mut Bx,
|
||||
place_ref: mir::PlaceRef<'_, 'tcx>,
|
||||
place_ref: mir::PlaceRef<'tcx>,
|
||||
) -> OperandRef<'tcx, Bx::Value> {
|
||||
debug!("codegen_consume(place_ref={:?})", place_ref);
|
||||
|
||||
|
@ -408,7 +408,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||
pub fn codegen_place(
|
||||
&mut self,
|
||||
bx: &mut Bx,
|
||||
place_ref: mir::PlaceRef<'_, 'tcx>,
|
||||
place_ref: mir::PlaceRef<'tcx>,
|
||||
) -> PlaceRef<'tcx, Bx::Value> {
|
||||
debug!("codegen_place(place_ref={:?})", place_ref);
|
||||
let cx = self.cx;
|
||||
@ -497,7 +497,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||
result
|
||||
}
|
||||
|
||||
pub fn monomorphized_place_ty(&self, place_ref: mir::PlaceRef<'_, 'tcx>) -> Ty<'tcx> {
|
||||
pub fn monomorphized_place_ty(&self, place_ref: mir::PlaceRef<'tcx>) -> Ty<'tcx> {
|
||||
let tcx = self.cx.tcx();
|
||||
let place_ty = mir::Place::ty_from(place_ref.local, place_ref.projection, *self.mir, tcx);
|
||||
self.monomorphize(&place_ty.ty)
|
||||
|
@ -1,5 +1,6 @@
|
||||
A type parameter which references `Self` in its default value was not specified.
|
||||
Example of erroneous code:
|
||||
|
||||
Erroneous code example:
|
||||
|
||||
```compile_fail,E0393
|
||||
trait A<T=Self> {}
|
||||
|
@ -360,9 +360,6 @@ declare_features! (
|
||||
/// Allows `#[doc(masked)]`.
|
||||
(active, doc_masked, "1.21.0", Some(44027), None),
|
||||
|
||||
/// Allows `#[doc(spotlight)]`.
|
||||
(active, doc_spotlight, "1.22.0", Some(45040), None),
|
||||
|
||||
/// Allows `#[doc(include = "some-file")]`.
|
||||
(active, external_doc, "1.22.0", Some(44732), None),
|
||||
|
||||
|
@ -51,9 +51,6 @@ enum QueryModifier {
|
||||
/// Don't hash the result, instead just mark a query red if it runs
|
||||
NoHash,
|
||||
|
||||
/// Don't force the query
|
||||
NoForce,
|
||||
|
||||
/// Generate a dep node based on the dependencies of the query
|
||||
Anon,
|
||||
|
||||
@ -118,8 +115,6 @@ impl Parse for QueryModifier {
|
||||
Ok(QueryModifier::CycleDelayBug)
|
||||
} else if modifier == "no_hash" {
|
||||
Ok(QueryModifier::NoHash)
|
||||
} else if modifier == "no_force" {
|
||||
Ok(QueryModifier::NoForce)
|
||||
} else if modifier == "anon" {
|
||||
Ok(QueryModifier::Anon)
|
||||
} else if modifier == "eval_always" {
|
||||
@ -222,9 +217,6 @@ struct QueryModifiers {
|
||||
/// Don't hash the result, instead just mark a query red if it runs
|
||||
no_hash: bool,
|
||||
|
||||
/// Don't force the query
|
||||
no_force: bool,
|
||||
|
||||
/// Generate a dep node based on the dependencies of the query
|
||||
anon: bool,
|
||||
|
||||
@ -241,7 +233,6 @@ fn process_modifiers(query: &mut Query) -> QueryModifiers {
|
||||
let mut fatal_cycle = false;
|
||||
let mut cycle_delay_bug = false;
|
||||
let mut no_hash = false;
|
||||
let mut no_force = false;
|
||||
let mut anon = false;
|
||||
let mut eval_always = false;
|
||||
for modifier in query.modifiers.0.drain(..) {
|
||||
@ -288,12 +279,6 @@ fn process_modifiers(query: &mut Query) -> QueryModifiers {
|
||||
}
|
||||
no_hash = true;
|
||||
}
|
||||
QueryModifier::NoForce => {
|
||||
if no_force {
|
||||
panic!("duplicate modifier `no_force` for query `{}`", query.name);
|
||||
}
|
||||
no_force = true;
|
||||
}
|
||||
QueryModifier::Anon => {
|
||||
if anon {
|
||||
panic!("duplicate modifier `anon` for query `{}`", query.name);
|
||||
@ -316,7 +301,6 @@ fn process_modifiers(query: &mut Query) -> QueryModifiers {
|
||||
fatal_cycle,
|
||||
cycle_delay_bug,
|
||||
no_hash,
|
||||
no_force,
|
||||
anon,
|
||||
eval_always,
|
||||
}
|
||||
@ -425,7 +409,6 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream {
|
||||
let mut dep_node_def_stream = quote! {};
|
||||
let mut dep_node_force_stream = quote! {};
|
||||
let mut try_load_from_on_disk_cache_stream = quote! {};
|
||||
let mut no_force_queries = Vec::new();
|
||||
let mut cached_queries = quote! {};
|
||||
|
||||
for group in groups.0 {
|
||||
@ -444,19 +427,19 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream {
|
||||
cached_queries.extend(quote! {
|
||||
#name,
|
||||
});
|
||||
}
|
||||
|
||||
if modifiers.cache.is_some() && !modifiers.no_force {
|
||||
try_load_from_on_disk_cache_stream.extend(quote! {
|
||||
DepKind::#name => {
|
||||
debug_assert!(tcx.dep_graph
|
||||
.node_color(self)
|
||||
.map(|c| c.is_green())
|
||||
.unwrap_or(false));
|
||||
if <#arg as DepNodeParams>::CAN_RECONSTRUCT_QUERY_KEY {
|
||||
debug_assert!($tcx.dep_graph
|
||||
.node_color($dep_node)
|
||||
.map(|c| c.is_green())
|
||||
.unwrap_or(false));
|
||||
|
||||
let key = RecoverKey::recover(tcx, self).unwrap();
|
||||
if queries::#name::cache_on_disk(tcx, key, None) {
|
||||
let _ = tcx.#name(key);
|
||||
let key = <#arg as DepNodeParams>::recover($tcx, $dep_node).unwrap();
|
||||
if queries::#name::cache_on_disk($tcx, key, None) {
|
||||
let _ = $tcx.#name(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -501,24 +484,21 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream {
|
||||
[#attribute_stream] #name(#arg),
|
||||
});
|
||||
|
||||
if modifiers.no_force {
|
||||
no_force_queries.push(name.clone());
|
||||
} else {
|
||||
// Add a match arm to force the query given the dep node
|
||||
dep_node_force_stream.extend(quote! {
|
||||
DepKind::#name => {
|
||||
if let Some(key) = RecoverKey::recover($tcx, $dep_node) {
|
||||
// Add a match arm to force the query given the dep node
|
||||
dep_node_force_stream.extend(quote! {
|
||||
DepKind::#name => {
|
||||
if <#arg as DepNodeParams>::CAN_RECONSTRUCT_QUERY_KEY {
|
||||
if let Some(key) = <#arg as DepNodeParams>::recover($tcx, $dep_node) {
|
||||
$tcx.force_query::<crate::ty::query::queries::#name<'_>>(
|
||||
key,
|
||||
DUMMY_SP,
|
||||
*$dep_node
|
||||
);
|
||||
} else {
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
add_query_description_impl(&query, modifiers, &mut query_description_stream);
|
||||
}
|
||||
@ -528,12 +508,6 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream {
|
||||
});
|
||||
}
|
||||
|
||||
// Add an arm for the no force queries to panic when trying to force them
|
||||
for query in no_force_queries {
|
||||
dep_node_force_stream.extend(quote! {
|
||||
DepKind::#query |
|
||||
});
|
||||
}
|
||||
dep_node_force_stream.extend(quote! {
|
||||
DepKind::Null => {
|
||||
bug!("Cannot force dep node: {:?}", $dep_node)
|
||||
@ -577,14 +551,9 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream {
|
||||
|
||||
#query_description_stream
|
||||
|
||||
impl DepNode {
|
||||
/// Check whether the query invocation corresponding to the given
|
||||
/// DepNode is eligible for on-disk-caching. If so, this is method
|
||||
/// will execute the query corresponding to the given DepNode.
|
||||
/// Also, as a sanity check, it expects that the corresponding query
|
||||
/// invocation has been marked as green already.
|
||||
pub fn try_load_from_on_disk_cache(&self, tcx: TyCtxt<'_>) {
|
||||
match self.kind {
|
||||
macro_rules! rustc_dep_node_try_load_from_on_disk_cache {
|
||||
($dep_node:expr, $tcx:expr) => {
|
||||
match $dep_node.kind {
|
||||
#try_load_from_on_disk_cache_stream
|
||||
_ => (),
|
||||
}
|
||||
|
@ -76,6 +76,21 @@ impl<'a> LoadError<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
/// A reference to `CrateMetadata` that can also give access to whole crate store when necessary.
|
||||
#[derive(Clone, Copy)]
|
||||
crate struct CrateMetadataRef<'a> {
|
||||
pub cdata: &'a CrateMetadata,
|
||||
pub cstore: &'a CStore,
|
||||
}
|
||||
|
||||
impl std::ops::Deref for CrateMetadataRef<'_> {
|
||||
type Target = CrateMetadata;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
self.cdata
|
||||
}
|
||||
}
|
||||
|
||||
fn dump_crates(cstore: &CStore) {
|
||||
info!("resolved crates:");
|
||||
cstore.iter_crate_data(|cnum, data| {
|
||||
@ -100,10 +115,11 @@ impl CStore {
|
||||
CrateNum::new(self.metas.len() - 1)
|
||||
}
|
||||
|
||||
crate fn get_crate_data(&self, cnum: CrateNum) -> &CrateMetadata {
|
||||
self.metas[cnum]
|
||||
crate fn get_crate_data(&self, cnum: CrateNum) -> CrateMetadataRef<'_> {
|
||||
let cdata = self.metas[cnum]
|
||||
.as_ref()
|
||||
.unwrap_or_else(|| panic!("Failed to get crate data for {:?}", cnum))
|
||||
.unwrap_or_else(|| panic!("Failed to get crate data for {:?}", cnum));
|
||||
CrateMetadataRef { cdata, cstore: self }
|
||||
}
|
||||
|
||||
fn set_crate_data(&mut self, cnum: CrateNum, data: CrateMetadata) {
|
||||
@ -217,7 +233,7 @@ impl<'a> CrateLoader<'a> {
|
||||
// We're also sure to compare *paths*, not actual byte slices. The
|
||||
// `source` stores paths which are normalized which may be different
|
||||
// from the strings on the command line.
|
||||
let source = self.cstore.get_crate_data(cnum).source();
|
||||
let source = self.cstore.get_crate_data(cnum).cdata.source();
|
||||
if let Some(entry) = self.sess.opts.externs.get(&name.as_str()) {
|
||||
// Only use `--extern crate_name=path` here, not `--extern crate_name`.
|
||||
if let Some(mut files) = entry.files() {
|
||||
|
@ -1,5 +1,6 @@
|
||||
// Decoding metadata from a single crate's metadata
|
||||
|
||||
use crate::creader::CrateMetadataRef;
|
||||
use crate::rmeta::table::{FixedSizeEncoding, Table};
|
||||
use crate::rmeta::*;
|
||||
|
||||
@ -125,7 +126,7 @@ struct ImportedSourceFile {
|
||||
|
||||
pub(super) struct DecodeContext<'a, 'tcx> {
|
||||
opaque: opaque::Decoder<'a>,
|
||||
cdata: Option<&'a CrateMetadata>,
|
||||
cdata: Option<CrateMetadataRef<'a>>,
|
||||
sess: Option<&'tcx Session>,
|
||||
tcx: Option<TyCtxt<'tcx>>,
|
||||
|
||||
@ -141,7 +142,7 @@ pub(super) struct DecodeContext<'a, 'tcx> {
|
||||
/// Abstract over the various ways one can create metadata decoders.
|
||||
pub(super) trait Metadata<'a, 'tcx>: Copy {
|
||||
fn raw_bytes(self) -> &'a [u8];
|
||||
fn cdata(self) -> Option<&'a CrateMetadata> {
|
||||
fn cdata(self) -> Option<CrateMetadataRef<'a>> {
|
||||
None
|
||||
}
|
||||
fn sess(self) -> Option<&'tcx Session> {
|
||||
@ -162,7 +163,7 @@ pub(super) trait Metadata<'a, 'tcx>: Copy {
|
||||
lazy_state: LazyState::NoNode,
|
||||
alloc_decoding_session: self
|
||||
.cdata()
|
||||
.map(|cdata| cdata.alloc_decoding_state.new_decoding_session()),
|
||||
.map(|cdata| cdata.cdata.alloc_decoding_state.new_decoding_session()),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -185,33 +186,33 @@ impl<'a, 'tcx> Metadata<'a, 'tcx> for (&'a MetadataBlob, &'tcx Session) {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> Metadata<'a, 'tcx> for &'a CrateMetadata {
|
||||
impl<'a, 'tcx> Metadata<'a, 'tcx> for &'a CrateMetadataRef<'a> {
|
||||
fn raw_bytes(self) -> &'a [u8] {
|
||||
self.blob.raw_bytes()
|
||||
}
|
||||
fn cdata(self) -> Option<&'a CrateMetadata> {
|
||||
Some(self)
|
||||
fn cdata(self) -> Option<CrateMetadataRef<'a>> {
|
||||
Some(*self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> Metadata<'a, 'tcx> for (&'a CrateMetadata, &'tcx Session) {
|
||||
impl<'a, 'tcx> Metadata<'a, 'tcx> for (&'a CrateMetadataRef<'a>, &'tcx Session) {
|
||||
fn raw_bytes(self) -> &'a [u8] {
|
||||
self.0.raw_bytes()
|
||||
}
|
||||
fn cdata(self) -> Option<&'a CrateMetadata> {
|
||||
Some(self.0)
|
||||
fn cdata(self) -> Option<CrateMetadataRef<'a>> {
|
||||
Some(*self.0)
|
||||
}
|
||||
fn sess(self) -> Option<&'tcx Session> {
|
||||
Some(&self.1)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> Metadata<'a, 'tcx> for (&'a CrateMetadata, TyCtxt<'tcx>) {
|
||||
impl<'a, 'tcx> Metadata<'a, 'tcx> for (&'a CrateMetadataRef<'a>, TyCtxt<'tcx>) {
|
||||
fn raw_bytes(self) -> &'a [u8] {
|
||||
self.0.raw_bytes()
|
||||
}
|
||||
fn cdata(self) -> Option<&'a CrateMetadata> {
|
||||
Some(self.0)
|
||||
fn cdata(self) -> Option<CrateMetadataRef<'a>> {
|
||||
Some(*self.0)
|
||||
}
|
||||
fn tcx(self) -> Option<TyCtxt<'tcx>> {
|
||||
Some(self.1)
|
||||
@ -242,7 +243,7 @@ impl<'a, 'tcx> DecodeContext<'a, 'tcx> {
|
||||
self.tcx.expect("missing TyCtxt in DecodeContext")
|
||||
}
|
||||
|
||||
fn cdata(&self) -> &'a CrateMetadata {
|
||||
fn cdata(&self) -> CrateMetadataRef<'a> {
|
||||
self.cdata.expect("missing CrateMetadata in DecodeContext")
|
||||
}
|
||||
|
||||
@ -558,50 +559,7 @@ impl CrateRoot<'_> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> CrateMetadata {
|
||||
crate fn new(
|
||||
sess: &Session,
|
||||
blob: MetadataBlob,
|
||||
root: CrateRoot<'static>,
|
||||
raw_proc_macros: Option<&'static [ProcMacro]>,
|
||||
cnum: CrateNum,
|
||||
cnum_map: CrateNumMap,
|
||||
dep_kind: DepKind,
|
||||
source: CrateSource,
|
||||
private_dep: bool,
|
||||
host_hash: Option<Svh>,
|
||||
) -> CrateMetadata {
|
||||
let def_path_table = record_time(&sess.perf_stats.decode_def_path_tables_time, || {
|
||||
root.def_path_table.decode((&blob, sess))
|
||||
});
|
||||
let trait_impls = root
|
||||
.impls
|
||||
.decode((&blob, sess))
|
||||
.map(|trait_impls| (trait_impls.trait_id, trait_impls.impls))
|
||||
.collect();
|
||||
let alloc_decoding_state =
|
||||
AllocDecodingState::new(root.interpret_alloc_index.decode(&blob).collect());
|
||||
let dependencies = Lock::new(cnum_map.iter().cloned().collect());
|
||||
CrateMetadata {
|
||||
blob,
|
||||
root,
|
||||
def_path_table,
|
||||
trait_impls,
|
||||
raw_proc_macros,
|
||||
source_map_import_info: Once::new(),
|
||||
alloc_decoding_state,
|
||||
dep_node_index: AtomicCell::new(DepNodeIndex::INVALID),
|
||||
cnum,
|
||||
cnum_map,
|
||||
dependencies,
|
||||
dep_kind: Lock::new(dep_kind),
|
||||
source,
|
||||
private_dep,
|
||||
host_hash,
|
||||
extern_crate: Lock::new(None),
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> CrateMetadataRef<'a> {
|
||||
fn is_proc_macro(&self, id: DefIndex) -> bool {
|
||||
self.root.proc_macro_data.and_then(|data| data.decode(self).find(|x| *x == id)).is_some()
|
||||
}
|
||||
@ -622,10 +580,6 @@ impl<'a, 'tcx> CrateMetadata {
|
||||
})
|
||||
}
|
||||
|
||||
fn local_def_id(&self, index: DefIndex) -> DefId {
|
||||
DefId { krate: self.cnum, index }
|
||||
}
|
||||
|
||||
fn raw_proc_macro(&self, id: DefIndex) -> &ProcMacro {
|
||||
// DefIndex's in root.proc_macro_data have a one-to-one correspondence
|
||||
// with items in 'raw_proc_macros'.
|
||||
@ -1191,18 +1145,6 @@ impl<'a, 'tcx> CrateMetadata {
|
||||
.collect()
|
||||
}
|
||||
|
||||
// Translate a DefId from the current compilation environment to a DefId
|
||||
// for an external crate.
|
||||
fn reverse_translate_def_id(&self, did: DefId) -> Option<DefId> {
|
||||
for (local, &global) in self.cnum_map.iter_enumerated() {
|
||||
if global == did.krate {
|
||||
return Some(DefId { krate: local, index: did.index });
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
fn get_inherent_implementations_for_type(
|
||||
&self,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
@ -1409,11 +1351,6 @@ impl<'a, 'tcx> CrateMetadata {
|
||||
DefPath::make(self.cnum, id, |parent| self.def_key(parent))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn def_path_hash(&self, index: DefIndex) -> DefPathHash {
|
||||
self.def_path_table.def_path_hash(index)
|
||||
}
|
||||
|
||||
/// Imports the source_map from an external crate into the source_map of the crate
|
||||
/// currently being compiled (the "local crate").
|
||||
///
|
||||
@ -1440,10 +1377,10 @@ impl<'a, 'tcx> CrateMetadata {
|
||||
/// Proc macro crates don't currently export spans, so this function does not have
|
||||
/// to work for them.
|
||||
fn imported_source_files(
|
||||
&'a self,
|
||||
&self,
|
||||
local_source_map: &source_map::SourceMap,
|
||||
) -> &[ImportedSourceFile] {
|
||||
self.source_map_import_info.init_locking(|| {
|
||||
) -> &'a [ImportedSourceFile] {
|
||||
self.cdata.source_map_import_info.init_locking(|| {
|
||||
let external_source_map = self.root.source_map.decode(self);
|
||||
|
||||
external_source_map
|
||||
@ -1516,29 +1453,50 @@ impl<'a, 'tcx> CrateMetadata {
|
||||
.collect()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the `DepNodeIndex` corresponding this crate. The result of this
|
||||
/// method is cached in the `dep_node_index` field.
|
||||
fn get_crate_dep_node_index(&self, tcx: TyCtxt<'tcx>) -> DepNodeIndex {
|
||||
let mut dep_node_index = self.dep_node_index.load();
|
||||
|
||||
if unlikely!(dep_node_index == DepNodeIndex::INVALID) {
|
||||
// We have not cached the DepNodeIndex for this upstream crate yet,
|
||||
// so use the dep-graph to find it out and cache it.
|
||||
// Note that multiple threads can enter this block concurrently.
|
||||
// That is fine because the DepNodeIndex remains constant
|
||||
// throughout the whole compilation session, and multiple stores
|
||||
// would always write the same value.
|
||||
|
||||
let def_path_hash = self.def_path_hash(CRATE_DEF_INDEX);
|
||||
let dep_node = def_path_hash.to_dep_node(dep_graph::DepKind::CrateMetadata);
|
||||
|
||||
dep_node_index = tcx.dep_graph.dep_node_index_of(&dep_node);
|
||||
assert!(dep_node_index != DepNodeIndex::INVALID);
|
||||
self.dep_node_index.store(dep_node_index);
|
||||
impl CrateMetadata {
|
||||
crate fn new(
|
||||
sess: &Session,
|
||||
blob: MetadataBlob,
|
||||
root: CrateRoot<'static>,
|
||||
raw_proc_macros: Option<&'static [ProcMacro]>,
|
||||
cnum: CrateNum,
|
||||
cnum_map: CrateNumMap,
|
||||
dep_kind: DepKind,
|
||||
source: CrateSource,
|
||||
private_dep: bool,
|
||||
host_hash: Option<Svh>,
|
||||
) -> CrateMetadata {
|
||||
let def_path_table = record_time(&sess.perf_stats.decode_def_path_tables_time, || {
|
||||
root.def_path_table.decode((&blob, sess))
|
||||
});
|
||||
let trait_impls = root
|
||||
.impls
|
||||
.decode((&blob, sess))
|
||||
.map(|trait_impls| (trait_impls.trait_id, trait_impls.impls))
|
||||
.collect();
|
||||
let alloc_decoding_state =
|
||||
AllocDecodingState::new(root.interpret_alloc_index.decode(&blob).collect());
|
||||
let dependencies = Lock::new(cnum_map.iter().cloned().collect());
|
||||
CrateMetadata {
|
||||
blob,
|
||||
root,
|
||||
def_path_table,
|
||||
trait_impls,
|
||||
raw_proc_macros,
|
||||
source_map_import_info: Once::new(),
|
||||
alloc_decoding_state,
|
||||
dep_node_index: AtomicCell::new(DepNodeIndex::INVALID),
|
||||
cnum,
|
||||
cnum_map,
|
||||
dependencies,
|
||||
dep_kind: Lock::new(dep_kind),
|
||||
source,
|
||||
private_dep,
|
||||
host_hash,
|
||||
extern_crate: Lock::new(None),
|
||||
}
|
||||
|
||||
dep_node_index
|
||||
}
|
||||
|
||||
crate fn dependencies(&self) -> LockGuard<'_, Vec<CrateNum>> {
|
||||
@ -1613,6 +1571,51 @@ impl<'a, 'tcx> CrateMetadata {
|
||||
crate fn hash(&self) -> Svh {
|
||||
self.root.hash
|
||||
}
|
||||
|
||||
fn local_def_id(&self, index: DefIndex) -> DefId {
|
||||
DefId { krate: self.cnum, index }
|
||||
}
|
||||
|
||||
// Translate a DefId from the current compilation environment to a DefId
|
||||
// for an external crate.
|
||||
fn reverse_translate_def_id(&self, did: DefId) -> Option<DefId> {
|
||||
for (local, &global) in self.cnum_map.iter_enumerated() {
|
||||
if global == did.krate {
|
||||
return Some(DefId { krate: local, index: did.index });
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn def_path_hash(&self, index: DefIndex) -> DefPathHash {
|
||||
self.def_path_table.def_path_hash(index)
|
||||
}
|
||||
|
||||
/// Get the `DepNodeIndex` corresponding this crate. The result of this
|
||||
/// method is cached in the `dep_node_index` field.
|
||||
fn get_crate_dep_node_index(&self, tcx: TyCtxt<'tcx>) -> DepNodeIndex {
|
||||
let mut dep_node_index = self.dep_node_index.load();
|
||||
|
||||
if unlikely!(dep_node_index == DepNodeIndex::INVALID) {
|
||||
// We have not cached the DepNodeIndex for this upstream crate yet,
|
||||
// so use the dep-graph to find it out and cache it.
|
||||
// Note that multiple threads can enter this block concurrently.
|
||||
// That is fine because the DepNodeIndex remains constant
|
||||
// throughout the whole compilation session, and multiple stores
|
||||
// would always write the same value.
|
||||
|
||||
let def_path_hash = self.def_path_hash(CRATE_DEF_INDEX);
|
||||
let dep_node = def_path_hash.to_dep_node(dep_graph::DepKind::CrateMetadata);
|
||||
|
||||
dep_node_index = tcx.dep_graph.dep_node_index_of(&dep_node);
|
||||
assert!(dep_node_index != DepNodeIndex::INVALID);
|
||||
self.dep_node_index.store(dep_node_index);
|
||||
}
|
||||
|
||||
dep_node_index
|
||||
}
|
||||
}
|
||||
|
||||
// Cannot be implemented on 'ProcMacro', as libproc_macro
|
||||
|
@ -517,7 +517,7 @@ impl CrateStore for CStore {
|
||||
}
|
||||
|
||||
fn def_path_table(&self, cnum: CrateNum) -> &DefPathTable {
|
||||
&self.get_crate_data(cnum).def_path_table
|
||||
&self.get_crate_data(cnum).cdata.def_path_table
|
||||
}
|
||||
|
||||
fn crates_untracked(&self) -> Vec<CrateNum> {
|
||||
|
@ -51,7 +51,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
&mut self,
|
||||
location: Location,
|
||||
desired_action: InitializationRequiringAction,
|
||||
(moved_place, used_place, span): (PlaceRef<'cx, 'tcx>, PlaceRef<'cx, 'tcx>, Span),
|
||||
(moved_place, used_place, span): (PlaceRef<'tcx>, PlaceRef<'tcx>, Span),
|
||||
mpi: MovePathIndex,
|
||||
) {
|
||||
debug!(
|
||||
@ -647,7 +647,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
// borrowed place and look for a access to a different field of the same union.
|
||||
let Place { local, projection } = second_borrowed_place;
|
||||
|
||||
let mut cursor = projection.as_ref();
|
||||
let mut cursor = &projection[..];
|
||||
while let [proj_base @ .., elem] = cursor {
|
||||
cursor = proj_base;
|
||||
|
||||
@ -1521,7 +1521,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
err.buffer(&mut self.errors_buffer);
|
||||
}
|
||||
|
||||
fn classify_drop_access_kind(&self, place: PlaceRef<'cx, 'tcx>) -> StorageDeadOrDrop<'tcx> {
|
||||
fn classify_drop_access_kind(&self, place: PlaceRef<'tcx>) -> StorageDeadOrDrop<'tcx> {
|
||||
let tcx = self.infcx.tcx;
|
||||
match place.projection {
|
||||
[] => StorageDeadOrDrop::LocalStorageDead,
|
||||
|
@ -51,7 +51,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
pub(super) fn add_moved_or_invoked_closure_note(
|
||||
&self,
|
||||
location: Location,
|
||||
place: PlaceRef<'cx, 'tcx>,
|
||||
place: PlaceRef<'tcx>,
|
||||
diag: &mut DiagnosticBuilder<'_>,
|
||||
) {
|
||||
debug!("add_moved_or_invoked_closure_note: location={:?} place={:?}", location, place);
|
||||
@ -139,7 +139,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
|
||||
/// End-user visible description of `place` if one can be found. If the
|
||||
/// place is a temporary for instance, None will be returned.
|
||||
pub(super) fn describe_place(&self, place_ref: PlaceRef<'cx, 'tcx>) -> Option<String> {
|
||||
pub(super) fn describe_place(&self, place_ref: PlaceRef<'tcx>) -> Option<String> {
|
||||
self.describe_place_with_options(place_ref, IncludingDowncast(false))
|
||||
}
|
||||
|
||||
@ -149,7 +149,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
/// `Downcast` and `IncludingDowncast` is true
|
||||
pub(super) fn describe_place_with_options(
|
||||
&self,
|
||||
place: PlaceRef<'cx, 'tcx>,
|
||||
place: PlaceRef<'tcx>,
|
||||
including_downcast: IncludingDowncast,
|
||||
) -> Option<String> {
|
||||
let mut buf = String::new();
|
||||
@ -162,7 +162,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
/// Appends end-user visible description of `place` to `buf`.
|
||||
fn append_place_to_string(
|
||||
&self,
|
||||
place: PlaceRef<'cx, 'tcx>,
|
||||
place: PlaceRef<'tcx>,
|
||||
buf: &mut String,
|
||||
mut autoderef: bool,
|
||||
including_downcast: &IncludingDowncast,
|
||||
@ -303,7 +303,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
}
|
||||
|
||||
/// End-user visible description of the `field`nth field of `base`
|
||||
fn describe_field(&self, place: PlaceRef<'cx, 'tcx>, field: Field) -> String {
|
||||
fn describe_field(&self, place: PlaceRef<'tcx>, field: Field) -> String {
|
||||
// FIXME Place2 Make this work iteratively
|
||||
match place {
|
||||
PlaceRef { local, projection: [] } => {
|
||||
@ -399,7 +399,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
|
||||
pub(super) fn borrowed_content_source(
|
||||
&self,
|
||||
deref_base: PlaceRef<'cx, 'tcx>,
|
||||
deref_base: PlaceRef<'tcx>,
|
||||
) -> BorrowedContentSource<'tcx> {
|
||||
let tcx = self.infcx.tcx;
|
||||
|
||||
@ -694,7 +694,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
/// Finds the spans associated to a move or copy of move_place at location.
|
||||
pub(super) fn move_spans(
|
||||
&self,
|
||||
moved_place: PlaceRef<'cx, 'tcx>, // Could also be an upvar.
|
||||
moved_place: PlaceRef<'tcx>, // Could also be an upvar.
|
||||
location: Location,
|
||||
) -> UseSpans {
|
||||
use self::UseSpans::*;
|
||||
@ -782,7 +782,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
fn closure_span(
|
||||
&self,
|
||||
def_id: DefId,
|
||||
target_place: PlaceRef<'cx, 'tcx>,
|
||||
target_place: PlaceRef<'tcx>,
|
||||
places: &Vec<Operand<'tcx>>,
|
||||
) -> Option<(Span, Option<GeneratorKind>, Span)> {
|
||||
debug!(
|
||||
|
@ -23,7 +23,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||
&mut self,
|
||||
access_place: &Place<'tcx>,
|
||||
span: Span,
|
||||
the_place_err: PlaceRef<'cx, 'tcx>,
|
||||
the_place_err: PlaceRef<'tcx>,
|
||||
error_access: AccessKind,
|
||||
location: Location,
|
||||
) {
|
||||
|
@ -86,6 +86,8 @@ crate struct Upvar {
|
||||
mutability: Mutability,
|
||||
}
|
||||
|
||||
const DEREF_PROJECTION: &[PlaceElem<'_>; 1] = &[ProjectionElem::Deref];
|
||||
|
||||
pub fn provide(providers: &mut Providers<'_>) {
|
||||
*providers = Providers { mir_borrowck, ..*providers };
|
||||
}
|
||||
@ -466,10 +468,10 @@ crate struct MirBorrowckCtxt<'cx, 'tcx> {
|
||||
/// `BTreeMap` is used to preserve the order of insertions when iterating. This is necessary
|
||||
/// when errors in the map are being re-added to the error buffer so that errors with the
|
||||
/// same primary span come out in a consistent order.
|
||||
move_error_reported: BTreeMap<Vec<MoveOutIndex>, (PlaceRef<'cx, 'tcx>, DiagnosticBuilder<'cx>)>,
|
||||
move_error_reported: BTreeMap<Vec<MoveOutIndex>, (PlaceRef<'tcx>, DiagnosticBuilder<'cx>)>,
|
||||
/// This field keeps track of errors reported in the checking of uninitialized variables,
|
||||
/// so that we don't report seemingly duplicate errors.
|
||||
uninitialized_error_reported: FxHashSet<PlaceRef<'cx, 'tcx>>,
|
||||
uninitialized_error_reported: FxHashSet<PlaceRef<'tcx>>,
|
||||
/// Errors to be reported buffer
|
||||
errors_buffer: Vec<Diagnostic>,
|
||||
/// This field keeps track of all the local variables that are declared mut and are mutated.
|
||||
@ -841,9 +843,9 @@ enum InitializationRequiringAction {
|
||||
PartialAssignment,
|
||||
}
|
||||
|
||||
struct RootPlace<'d, 'tcx> {
|
||||
struct RootPlace<'tcx> {
|
||||
place_local: Local,
|
||||
place_projection: &'d [PlaceElem<'tcx>],
|
||||
place_projection: &'tcx [PlaceElem<'tcx>],
|
||||
is_local_mutation_allowed: LocalMutationIsAllowed,
|
||||
}
|
||||
|
||||
@ -1413,7 +1415,6 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
) {
|
||||
debug!("check_for_invalidation_at_exit({:?})", borrow);
|
||||
let place = &borrow.borrowed_place;
|
||||
let deref = [ProjectionElem::Deref];
|
||||
let mut root_place = PlaceRef { local: place.local, projection: &[] };
|
||||
|
||||
// FIXME(nll-rfc#40): do more precise destructor tracking here. For now
|
||||
@ -1427,7 +1428,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
// Thread-locals might be dropped after the function exits
|
||||
// We have to dereference the outer reference because
|
||||
// borrows don't conflict behind shared references.
|
||||
root_place.projection = &deref;
|
||||
root_place.projection = DEREF_PROJECTION;
|
||||
(true, true)
|
||||
} else {
|
||||
(false, self.locals_are_invalidated_at_exit)
|
||||
@ -1526,7 +1527,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
&mut self,
|
||||
location: Location,
|
||||
desired_action: InitializationRequiringAction,
|
||||
place_span: (PlaceRef<'cx, 'tcx>, Span),
|
||||
place_span: (PlaceRef<'tcx>, Span),
|
||||
flow_state: &Flows<'cx, 'tcx>,
|
||||
) {
|
||||
let maybe_uninits = &flow_state.uninits;
|
||||
@ -1592,7 +1593,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
&mut self,
|
||||
location: Location,
|
||||
desired_action: InitializationRequiringAction,
|
||||
place_span: (PlaceRef<'cx, 'tcx>, Span),
|
||||
place_span: (PlaceRef<'tcx>, Span),
|
||||
maybe_uninits: &BitSet<MovePathIndex>,
|
||||
from: u32,
|
||||
to: u32,
|
||||
@ -1631,7 +1632,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
&mut self,
|
||||
location: Location,
|
||||
desired_action: InitializationRequiringAction,
|
||||
place_span: (PlaceRef<'cx, 'tcx>, Span),
|
||||
place_span: (PlaceRef<'tcx>, Span),
|
||||
flow_state: &Flows<'cx, 'tcx>,
|
||||
) {
|
||||
let maybe_uninits = &flow_state.uninits;
|
||||
@ -1709,10 +1710,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
/// An Err result includes a tag indicated why the search failed.
|
||||
/// Currently this can only occur if the place is built off of a
|
||||
/// static variable, as we do not track those in the MoveData.
|
||||
fn move_path_closest_to(
|
||||
&mut self,
|
||||
place: PlaceRef<'_, 'tcx>,
|
||||
) -> (PlaceRef<'cx, 'tcx>, MovePathIndex) {
|
||||
fn move_path_closest_to(&mut self, place: PlaceRef<'tcx>) -> (PlaceRef<'tcx>, MovePathIndex) {
|
||||
match self.move_data.rev_lookup.find(place) {
|
||||
LookupResult::Parent(Some(mpi)) | LookupResult::Exact(mpi) => {
|
||||
(self.move_data.move_paths[mpi].place.as_ref(), mpi)
|
||||
@ -1721,7 +1719,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
fn move_path_for_place(&mut self, place: PlaceRef<'_, 'tcx>) -> Option<MovePathIndex> {
|
||||
fn move_path_for_place(&mut self, place: PlaceRef<'tcx>) -> Option<MovePathIndex> {
|
||||
// If returns None, then there is no move path corresponding
|
||||
// to a direct owner of `place` (which means there is nothing
|
||||
// that borrowck tracks for its analysis).
|
||||
@ -1816,7 +1814,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
fn check_parent_of_field<'cx, 'tcx>(
|
||||
this: &mut MirBorrowckCtxt<'cx, 'tcx>,
|
||||
location: Location,
|
||||
base: PlaceRef<'cx, 'tcx>,
|
||||
base: PlaceRef<'tcx>,
|
||||
span: Span,
|
||||
flow_state: &Flows<'cx, 'tcx>,
|
||||
) {
|
||||
@ -2029,7 +2027,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
}
|
||||
|
||||
/// Adds the place into the used mutable variables set
|
||||
fn add_used_mut<'d>(&mut self, root_place: RootPlace<'d, 'tcx>, flow_state: &Flows<'cx, 'tcx>) {
|
||||
fn add_used_mut(&mut self, root_place: RootPlace<'tcx>, flow_state: &Flows<'cx, 'tcx>) {
|
||||
match root_place {
|
||||
RootPlace { place_local: local, place_projection: [], is_local_mutation_allowed } => {
|
||||
// If the local may have been initialized, and it is now currently being
|
||||
@ -2063,11 +2061,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
|
||||
/// Whether this value can be written or borrowed mutably.
|
||||
/// Returns the root place if the place passed in is a projection.
|
||||
fn is_mutable<'d>(
|
||||
fn is_mutable(
|
||||
&self,
|
||||
place: PlaceRef<'d, 'tcx>,
|
||||
place: PlaceRef<'tcx>,
|
||||
is_local_mutation_allowed: LocalMutationIsAllowed,
|
||||
) -> Result<RootPlace<'d, 'tcx>, PlaceRef<'d, 'tcx>> {
|
||||
) -> Result<RootPlace<'tcx>, PlaceRef<'tcx>> {
|
||||
match place {
|
||||
PlaceRef { local, projection: [] } => {
|
||||
let local = &self.body.local_decls[local];
|
||||
@ -2218,7 +2216,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
/// then returns the index of the field being projected. Note that this closure will always
|
||||
/// be `self` in the current MIR, because that is the only time we directly access the fields
|
||||
/// of a closure type.
|
||||
pub fn is_upvar_field_projection(&self, place_ref: PlaceRef<'cx, 'tcx>) -> Option<Field> {
|
||||
pub fn is_upvar_field_projection(&self, place_ref: PlaceRef<'tcx>) -> Option<Field> {
|
||||
let mut place_projection = place_ref.projection;
|
||||
let mut by_ref = false;
|
||||
|
||||
|
@ -48,7 +48,7 @@ pub(super) fn borrow_conflicts_with_place<'tcx>(
|
||||
body: &Body<'tcx>,
|
||||
borrow_place: &Place<'tcx>,
|
||||
borrow_kind: BorrowKind,
|
||||
access_place: PlaceRef<'_, 'tcx>,
|
||||
access_place: PlaceRef<'tcx>,
|
||||
access: AccessDepth,
|
||||
bias: PlaceConflictBias,
|
||||
) -> bool {
|
||||
@ -73,7 +73,7 @@ fn place_components_conflict<'tcx>(
|
||||
body: &Body<'tcx>,
|
||||
borrow_place: &Place<'tcx>,
|
||||
borrow_kind: BorrowKind,
|
||||
access_place: PlaceRef<'_, 'tcx>,
|
||||
access_place: PlaceRef<'tcx>,
|
||||
access: AccessDepth,
|
||||
bias: PlaceConflictBias,
|
||||
) -> bool {
|
||||
|
@ -13,12 +13,12 @@ use rustc::mir::{Place, PlaceRef, ProjectionElem, ReadOnlyBodyAndCache};
|
||||
use rustc::ty::{self, TyCtxt};
|
||||
use rustc_hir as hir;
|
||||
|
||||
pub trait IsPrefixOf<'cx, 'tcx> {
|
||||
fn is_prefix_of(&self, other: PlaceRef<'cx, 'tcx>) -> bool;
|
||||
pub trait IsPrefixOf<'tcx> {
|
||||
fn is_prefix_of(&self, other: PlaceRef<'tcx>) -> bool;
|
||||
}
|
||||
|
||||
impl<'cx, 'tcx> IsPrefixOf<'cx, 'tcx> for PlaceRef<'cx, 'tcx> {
|
||||
fn is_prefix_of(&self, other: PlaceRef<'cx, 'tcx>) -> bool {
|
||||
impl<'tcx> IsPrefixOf<'tcx> for PlaceRef<'tcx> {
|
||||
fn is_prefix_of(&self, other: PlaceRef<'tcx>) -> bool {
|
||||
self.local == other.local
|
||||
&& self.projection.len() <= other.projection.len()
|
||||
&& self.projection == &other.projection[..self.projection.len()]
|
||||
@ -29,7 +29,7 @@ pub(super) struct Prefixes<'cx, 'tcx> {
|
||||
body: ReadOnlyBodyAndCache<'cx, 'tcx>,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
kind: PrefixSet,
|
||||
next: Option<PlaceRef<'cx, 'tcx>>,
|
||||
next: Option<PlaceRef<'tcx>>,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||
@ -50,7 +50,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
/// terminating the iteration early based on `kind`.
|
||||
pub(super) fn prefixes(
|
||||
&self,
|
||||
place_ref: PlaceRef<'cx, 'tcx>,
|
||||
place_ref: PlaceRef<'tcx>,
|
||||
kind: PrefixSet,
|
||||
) -> Prefixes<'cx, 'tcx> {
|
||||
Prefixes { next: Some(place_ref), kind, body: self.body, tcx: self.infcx.tcx }
|
||||
@ -58,7 +58,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
}
|
||||
|
||||
impl<'cx, 'tcx> Iterator for Prefixes<'cx, 'tcx> {
|
||||
type Item = PlaceRef<'cx, 'tcx>;
|
||||
type Item = PlaceRef<'tcx>;
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
let mut cursor = self.next?;
|
||||
|
||||
|
@ -483,7 +483,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
|
||||
self.builder.data.loc_map[self.loc].push(move_out);
|
||||
}
|
||||
|
||||
fn gather_init(&mut self, place: PlaceRef<'cx, 'tcx>, kind: InitKind) {
|
||||
fn gather_init(&mut self, place: PlaceRef<'tcx>, kind: InitKind) {
|
||||
debug!("gather_init({:?}, {:?})", self.loc, place);
|
||||
|
||||
let mut place = place;
|
||||
|
@ -312,7 +312,7 @@ impl MovePathLookup {
|
||||
// alternative will *not* create a MovePath on the fly for an
|
||||
// unknown place, but will rather return the nearest available
|
||||
// parent.
|
||||
pub fn find(&self, place: PlaceRef<'_, '_>) -> LookupResult {
|
||||
pub fn find(&self, place: PlaceRef<'_>) -> LookupResult {
|
||||
let mut result = self.locals[place.local];
|
||||
|
||||
for elem in place.projection.iter() {
|
||||
|
@ -14,7 +14,7 @@ pub struct AddRetag;
|
||||
/// after the assignment, we can be sure to obtain the same place value.
|
||||
/// (Concurrent accesses by other threads are no problem as these are anyway non-atomic
|
||||
/// copies. Data races are UB.)
|
||||
fn is_stable(place: PlaceRef<'_, '_>) -> bool {
|
||||
fn is_stable(place: PlaceRef<'_>) -> bool {
|
||||
place.projection.iter().all(|elem| {
|
||||
match elem {
|
||||
// Which place this evaluates to can change with any memory write,
|
||||
|
@ -35,7 +35,7 @@ pub trait Qualif {
|
||||
fn in_projection_structurally(
|
||||
cx: &ConstCx<'_, 'tcx>,
|
||||
per_local: &mut impl FnMut(Local) -> bool,
|
||||
place: PlaceRef<'_, 'tcx>,
|
||||
place: PlaceRef<'tcx>,
|
||||
) -> bool {
|
||||
if let [proj_base @ .., elem] = place.projection {
|
||||
let base_qualif = Self::in_place(
|
||||
@ -67,7 +67,7 @@ pub trait Qualif {
|
||||
fn in_projection(
|
||||
cx: &ConstCx<'_, 'tcx>,
|
||||
per_local: &mut impl FnMut(Local) -> bool,
|
||||
place: PlaceRef<'_, 'tcx>,
|
||||
place: PlaceRef<'tcx>,
|
||||
) -> bool {
|
||||
Self::in_projection_structurally(cx, per_local, place)
|
||||
}
|
||||
@ -75,7 +75,7 @@ pub trait Qualif {
|
||||
fn in_place(
|
||||
cx: &ConstCx<'_, 'tcx>,
|
||||
per_local: &mut impl FnMut(Local) -> bool,
|
||||
place: PlaceRef<'_, 'tcx>,
|
||||
place: PlaceRef<'tcx>,
|
||||
) -> bool {
|
||||
match place {
|
||||
PlaceRef { local, projection: [] } => per_local(local),
|
||||
|
@ -474,7 +474,7 @@ impl<'tcx> Validator<'_, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
fn validate_place(&self, place: PlaceRef<'_, 'tcx>) -> Result<(), Unpromotable> {
|
||||
fn validate_place(&self, place: PlaceRef<'tcx>) -> Result<(), Unpromotable> {
|
||||
match place {
|
||||
PlaceRef { local, projection: [] } => self.validate_local(local),
|
||||
PlaceRef { local: _, projection: [proj_base @ .., elem] } => {
|
||||
|
@ -270,7 +270,6 @@ symbols! {
|
||||
doc_cfg,
|
||||
doc_keyword,
|
||||
doc_masked,
|
||||
doc_spotlight,
|
||||
doctest,
|
||||
document_private_items,
|
||||
dotdoteq_in_patterns,
|
||||
@ -689,7 +688,6 @@ symbols! {
|
||||
Some,
|
||||
specialization,
|
||||
speed,
|
||||
spotlight,
|
||||
sse4a_target_feature,
|
||||
stable,
|
||||
staged_api,
|
||||
|
@ -198,7 +198,6 @@ pub fn build_external_trait(cx: &DocContext<'_>, did: DefId) -> clean::Trait {
|
||||
let generics = (cx.tcx.generics_of(did), predicates).clean(cx);
|
||||
let generics = filter_non_trait_generics(did, generics);
|
||||
let (generics, supertrait_bounds) = separate_supertrait_bounds(generics);
|
||||
let is_spotlight = load_attrs(cx, did).clean(cx).has_doc_flag(sym::spotlight);
|
||||
let is_auto = cx.tcx.trait_is_auto(did);
|
||||
clean::Trait {
|
||||
auto: auto_trait,
|
||||
@ -206,7 +205,6 @@ pub fn build_external_trait(cx: &DocContext<'_>, did: DefId) -> clean::Trait {
|
||||
generics,
|
||||
items: trait_items,
|
||||
bounds: supertrait_bounds,
|
||||
is_spotlight,
|
||||
is_auto,
|
||||
}
|
||||
}
|
||||
|
@ -1013,7 +1013,6 @@ impl Clean<FnRetTy> for hir::FnRetTy<'_> {
|
||||
impl Clean<Item> for doctree::Trait<'_> {
|
||||
fn clean(&self, cx: &DocContext<'_>) -> Item {
|
||||
let attrs = self.attrs.clean(cx);
|
||||
let is_spotlight = attrs.has_doc_flag(sym::spotlight);
|
||||
Item {
|
||||
name: Some(self.name.clean(cx)),
|
||||
attrs,
|
||||
@ -1028,7 +1027,6 @@ impl Clean<Item> for doctree::Trait<'_> {
|
||||
items: self.items.iter().map(|ti| ti.clean(cx)).collect(),
|
||||
generics: self.generics.clean(cx),
|
||||
bounds: self.bounds.clean(cx),
|
||||
is_spotlight,
|
||||
is_auto: self.is_auto.clean(cx),
|
||||
}),
|
||||
}
|
||||
|
@ -951,7 +951,6 @@ pub struct Trait {
|
||||
pub items: Vec<Item>,
|
||||
pub generics: Generics,
|
||||
pub bounds: Vec<GenericBound>,
|
||||
pub is_spotlight: bool,
|
||||
pub is_auto: bool,
|
||||
}
|
||||
|
||||
|
@ -63,22 +63,10 @@ impl Buffer {
|
||||
Buffer { for_html: false, buffer: String::new() }
|
||||
}
|
||||
|
||||
crate fn is_empty(&self) -> bool {
|
||||
self.buffer.is_empty()
|
||||
}
|
||||
|
||||
crate fn into_inner(self) -> String {
|
||||
self.buffer
|
||||
}
|
||||
|
||||
crate fn insert_str(&mut self, idx: usize, s: &str) {
|
||||
self.buffer.insert_str(idx, s);
|
||||
}
|
||||
|
||||
crate fn push_str(&mut self, s: &str) {
|
||||
self.buffer.push_str(s);
|
||||
}
|
||||
|
||||
// Intended for consumption by write! and writeln! (std::fmt) but without
|
||||
// the fmt::Result return type imposed by fmt::Write (and avoiding the trait
|
||||
// import).
|
||||
|
@ -2325,7 +2325,7 @@ fn item_function(w: &mut Buffer, cx: &Context, it: &clean::Item, f: &clean::Func
|
||||
f.generics.print()
|
||||
)
|
||||
.len();
|
||||
write!(w, "{}<pre class='rust fn'>", render_spotlight_traits(it));
|
||||
write!(w, "<pre class='rust fn'>");
|
||||
render_attributes(w, it, false);
|
||||
write!(
|
||||
w,
|
||||
@ -2528,13 +2528,7 @@ fn item_trait(w: &mut Buffer, cx: &Context, it: &clean::Item, t: &clean::Trait)
|
||||
let item_type = m.type_();
|
||||
let id = cx.derive_id(format!("{}.{}", item_type, name));
|
||||
let ns_id = cx.derive_id(format!("{}.{}", name, item_type.name_space()));
|
||||
write!(
|
||||
w,
|
||||
"<h3 id='{id}' class='method'>{extra}<code id='{ns_id}'>",
|
||||
extra = render_spotlight_traits(m),
|
||||
id = id,
|
||||
ns_id = ns_id
|
||||
);
|
||||
write!(w, "<h3 id='{id}' class='method'><code id='{ns_id}'>", id = id, ns_id = ns_id);
|
||||
render_assoc_item(w, m, AssocItemLink::Anchor(Some(&id)), ItemType::Impl);
|
||||
write!(w, "</code>");
|
||||
render_stability_since(w, m, t);
|
||||
@ -3520,76 +3514,6 @@ fn should_render_item(item: &clean::Item, deref_mut_: bool) -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
fn render_spotlight_traits(item: &clean::Item) -> String {
|
||||
match item.inner {
|
||||
clean::FunctionItem(clean::Function { ref decl, .. })
|
||||
| clean::TyMethodItem(clean::TyMethod { ref decl, .. })
|
||||
| clean::MethodItem(clean::Method { ref decl, .. })
|
||||
| clean::ForeignFunctionItem(clean::Function { ref decl, .. }) => spotlight_decl(decl),
|
||||
_ => String::new(),
|
||||
}
|
||||
}
|
||||
|
||||
fn spotlight_decl(decl: &clean::FnDecl) -> String {
|
||||
let mut out = Buffer::html();
|
||||
let mut trait_ = String::new();
|
||||
|
||||
if let Some(did) = decl.output.def_id() {
|
||||
let c = cache();
|
||||
if let Some(impls) = c.impls.get(&did) {
|
||||
for i in impls {
|
||||
let impl_ = i.inner_impl();
|
||||
if impl_.trait_.def_id().map_or(false, |d| c.traits[&d].is_spotlight) {
|
||||
if out.is_empty() {
|
||||
out.push_str(&format!(
|
||||
"<h3 class=\"important\">Important traits for {}</h3>\
|
||||
<code class=\"content\">",
|
||||
impl_.for_.print()
|
||||
));
|
||||
trait_.push_str(&impl_.for_.print().to_string());
|
||||
}
|
||||
|
||||
//use the "where" class here to make it small
|
||||
out.push_str(&format!(
|
||||
"<span class=\"where fmt-newline\">{}</span>",
|
||||
impl_.print()
|
||||
));
|
||||
let t_did = impl_.trait_.def_id().unwrap();
|
||||
for it in &impl_.items {
|
||||
if let clean::TypedefItem(ref tydef, _) = it.inner {
|
||||
out.push_str("<span class=\"where fmt-newline\"> ");
|
||||
assoc_type(
|
||||
&mut out,
|
||||
it,
|
||||
&[],
|
||||
Some(&tydef.type_),
|
||||
AssocItemLink::GotoSource(t_did, &FxHashSet::default()),
|
||||
"",
|
||||
);
|
||||
out.push_str(";</span>");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !out.is_empty() {
|
||||
out.insert_str(
|
||||
0,
|
||||
&format!(
|
||||
"<div class=\"important-traits\"><div class='tooltip'>ⓘ\
|
||||
<span class='tooltiptext'>Important traits for {}</span></div>\
|
||||
<div class=\"content hidden\">",
|
||||
trait_
|
||||
),
|
||||
);
|
||||
out.push_str("</code></div></div>");
|
||||
}
|
||||
|
||||
out.into_inner()
|
||||
}
|
||||
|
||||
fn render_impl(
|
||||
w: &mut Buffer,
|
||||
cx: &Context,
|
||||
@ -3696,14 +3620,13 @@ fn render_impl(
|
||||
(true, " hidden")
|
||||
};
|
||||
match item.inner {
|
||||
clean::MethodItem(clean::Method { ref decl, .. })
|
||||
| clean::TyMethodItem(clean::TyMethod { ref decl, .. }) => {
|
||||
clean::MethodItem(clean::Method { .. })
|
||||
| clean::TyMethodItem(clean::TyMethod { .. }) => {
|
||||
// Only render when the method is not static or we allow static methods
|
||||
if render_method_item {
|
||||
let id = cx.derive_id(format!("{}.{}", item_type, name));
|
||||
let ns_id = cx.derive_id(format!("{}.{}", name, item_type.name_space()));
|
||||
write!(w, "<h4 id='{}' class=\"{}{}\">", id, item_type, extra_class);
|
||||
write!(w, "{}", spotlight_decl(decl));
|
||||
write!(w, "<code id='{}'>", ns_id);
|
||||
render_assoc_item(w, item, link.anchor(&id), ItemType::Impl);
|
||||
write!(w, "</code>");
|
||||
|
@ -341,7 +341,6 @@ function getSearchElement() {
|
||||
function handleEscape(ev) {
|
||||
var help = getHelpElement();
|
||||
var search = getSearchElement();
|
||||
hideModal();
|
||||
if (hasClass(help, "hidden") === false) {
|
||||
displayHelp(false, ev, help);
|
||||
} else if (hasClass(search, "hidden") === false) {
|
||||
@ -373,7 +372,6 @@ function getSearchElement() {
|
||||
case "s":
|
||||
case "S":
|
||||
displayHelp(false, ev);
|
||||
hideModal();
|
||||
ev.preventDefault();
|
||||
focusSearchBar();
|
||||
break;
|
||||
@ -386,7 +384,6 @@ function getSearchElement() {
|
||||
|
||||
case "?":
|
||||
if (ev.shiftKey) {
|
||||
hideModal();
|
||||
displayHelp(true, ev);
|
||||
}
|
||||
break;
|
||||
@ -2504,31 +2501,6 @@ function getSearchElement() {
|
||||
lineNumbersFunc(e);
|
||||
});
|
||||
|
||||
function showModal(content) {
|
||||
var modal = document.createElement("div");
|
||||
modal.id = "important";
|
||||
addClass(modal, "modal");
|
||||
modal.innerHTML = "<div class=\"modal-content\"><div class=\"close\" id=\"modal-close\">✕" +
|
||||
"</div><div class=\"whiter\"></div><span class=\"docblock\">" + content +
|
||||
"</span></div>";
|
||||
document.getElementsByTagName("body")[0].appendChild(modal);
|
||||
document.getElementById("modal-close").onclick = hideModal;
|
||||
modal.onclick = hideModal;
|
||||
}
|
||||
|
||||
function hideModal() {
|
||||
var modal = document.getElementById("important");
|
||||
if (modal) {
|
||||
modal.parentNode.removeChild(modal);
|
||||
}
|
||||
}
|
||||
|
||||
onEachLazy(document.getElementsByClassName("important-traits"), function(e) {
|
||||
e.onclick = function() {
|
||||
showModal(e.lastElementChild.innerHTML);
|
||||
};
|
||||
});
|
||||
|
||||
// In the search display, allows to switch between tabs.
|
||||
function printTab(nb) {
|
||||
if (nb === 0 || nb === 1 || nb === 2) {
|
||||
|
@ -143,12 +143,9 @@ code, pre, a.test-arrow {
|
||||
border-radius: 3px;
|
||||
padding: 0 0.1em;
|
||||
}
|
||||
.docblock pre code, .docblock-short pre code, .docblock code.spotlight {
|
||||
.docblock pre code, .docblock-short pre code {
|
||||
padding: 0;
|
||||
}
|
||||
.docblock code.spotlight :last-child {
|
||||
padding-bottom: 0.6em;
|
||||
}
|
||||
pre {
|
||||
padding: 14px;
|
||||
}
|
||||
@ -503,7 +500,7 @@ h4 > code, h3 > code, .invisible > code {
|
||||
font-size: 0.8em;
|
||||
}
|
||||
|
||||
.content .methods > div:not(.important-traits) {
|
||||
.content .methods > div {
|
||||
margin-left: 40px;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
@ -1072,7 +1069,7 @@ h3 > .collapse-toggle, h4 > .collapse-toggle {
|
||||
border-style: solid;
|
||||
}
|
||||
|
||||
.important-traits .tooltip .tooltiptext {
|
||||
.tooltip .tooltiptext {
|
||||
border: 1px solid;
|
||||
}
|
||||
|
||||
@ -1117,17 +1114,6 @@ pre.rust {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.important-traits {
|
||||
cursor: pointer;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
h4 > .important-traits {
|
||||
position: absolute;
|
||||
left: -44px;
|
||||
top: 2px;
|
||||
}
|
||||
|
||||
#all-types {
|
||||
text-align: center;
|
||||
border: 1px solid;
|
||||
@ -1354,12 +1340,6 @@ h4 > .important-traits {
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
h4 > .important-traits {
|
||||
position: absolute;
|
||||
left: -22px;
|
||||
top: 24px;
|
||||
}
|
||||
|
||||
#titles > div > div.count {
|
||||
float: left;
|
||||
width: 100%;
|
||||
@ -1462,82 +1442,12 @@ h4 > .important-traits {
|
||||
}
|
||||
}
|
||||
|
||||
.modal {
|
||||
position: fixed;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
z-index: 10000;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
display: block;
|
||||
max-width: 60%;
|
||||
min-width: 200px;
|
||||
padding: 8px;
|
||||
top: 40%;
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -40%);
|
||||
border: 1px solid;
|
||||
border-radius: 4px;
|
||||
border-top-right-radius: 0;
|
||||
}
|
||||
|
||||
.modal-content > .docblock {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
h3.important {
|
||||
margin: 0;
|
||||
margin-bottom: 13px;
|
||||
font-size: 19px;
|
||||
}
|
||||
|
||||
.modal-content > .docblock > code.content {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.modal-content > .close {
|
||||
position: absolute;
|
||||
font-weight: 900;
|
||||
right: -25px;
|
||||
top: -1px;
|
||||
font-size: 18px;
|
||||
width: 25px;
|
||||
padding-right: 2px;
|
||||
border-top-right-radius: 5px;
|
||||
border-bottom-right-radius: 5px;
|
||||
text-align: center;
|
||||
border: 1px solid;
|
||||
border-right: 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.modal-content > .whiter {
|
||||
height: 25px;
|
||||
position: absolute;
|
||||
width: 3px;
|
||||
right: -2px;
|
||||
top: 0px;
|
||||
}
|
||||
|
||||
#main > div.important-traits {
|
||||
position: absolute;
|
||||
left: -24px;
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
.content > .methods > .method > div.important-traits {
|
||||
position: absolute;
|
||||
font-weight: 400;
|
||||
left: -42px;
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
kbd {
|
||||
display: inline-block;
|
||||
padding: 3px 5px;
|
||||
|
@ -298,12 +298,6 @@ pre.ignore:hover, .information:hover + pre.ignore {
|
||||
border-color: transparent black transparent transparent;
|
||||
}
|
||||
|
||||
.important-traits .tooltip .tooltiptext {
|
||||
background-color: white;
|
||||
color: black;
|
||||
border-color: black;
|
||||
}
|
||||
|
||||
#titles > div:not(.selected) {
|
||||
background-color: #252525;
|
||||
border-top-color: #252525;
|
||||
@ -317,33 +311,6 @@ pre.ignore:hover, .information:hover + pre.ignore {
|
||||
color: #888;
|
||||
}
|
||||
|
||||
.modal {
|
||||
background-color: rgba(0,0,0,0.3);
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
background-color: #272727;
|
||||
border-color: #999;
|
||||
}
|
||||
|
||||
.modal-content > .close {
|
||||
background-color: #272727;
|
||||
border-color: #999;
|
||||
}
|
||||
|
||||
.modal-content > .close:hover {
|
||||
background-color: #ff1f1f;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.modal-content > .whiter {
|
||||
background-color: #272727;
|
||||
}
|
||||
|
||||
.modal-content > .close:hover + .whiter {
|
||||
background-color: #ff1f1f;
|
||||
}
|
||||
|
||||
@media (max-width: 700px) {
|
||||
.sidebar-menu {
|
||||
background-color: #505050;
|
||||
|
@ -292,12 +292,6 @@ pre.ignore:hover, .information:hover + pre.ignore {
|
||||
border-color: transparent black transparent transparent;
|
||||
}
|
||||
|
||||
.important-traits .tooltip .tooltiptext {
|
||||
background-color: white;
|
||||
color: black;
|
||||
border-color: black;
|
||||
}
|
||||
|
||||
#titles > div:not(.selected) {
|
||||
background-color: #e6e6e6;
|
||||
border-top-color: #e6e6e6;
|
||||
@ -311,33 +305,6 @@ pre.ignore:hover, .information:hover + pre.ignore {
|
||||
color: #888;
|
||||
}
|
||||
|
||||
.modal {
|
||||
background-color: rgba(0,0,0,0.3);
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
background-color: #eee;
|
||||
border-color: #999;
|
||||
}
|
||||
|
||||
.modal-content > .close {
|
||||
background-color: #eee;
|
||||
border-color: #999;
|
||||
}
|
||||
|
||||
.modal-content > .close:hover {
|
||||
background-color: #ff1f1f;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.modal-content > .whiter {
|
||||
background-color: #eee;
|
||||
}
|
||||
|
||||
.modal-content > .close:hover + .whiter {
|
||||
background-color: #ff1f1f;
|
||||
}
|
||||
|
||||
@media (max-width: 700px) {
|
||||
.sidebar-menu {
|
||||
background-color: #F1F1F1;
|
||||
|
@ -133,24 +133,41 @@ pub use alloc_crate::alloc::*;
|
||||
#[derive(Debug, Default, Copy, Clone)]
|
||||
pub struct System;
|
||||
|
||||
// The AllocRef impl just forwards to the GlobalAlloc impl, which is in `std::sys::*::alloc`.
|
||||
// The AllocRef impl checks the layout size to be non-zero and forwards to the GlobalAlloc impl,
|
||||
// which is in `std::sys::*::alloc`.
|
||||
#[unstable(feature = "allocator_api", issue = "32838")]
|
||||
unsafe impl AllocRef for System {
|
||||
#[inline]
|
||||
unsafe fn alloc(&mut self, layout: Layout) -> Result<(NonNull<u8>, usize), AllocErr> {
|
||||
NonNull::new(GlobalAlloc::alloc(self, layout)).ok_or(AllocErr).map(|p| (p, layout.size()))
|
||||
fn alloc(&mut self, layout: Layout) -> Result<(NonNull<u8>, usize), AllocErr> {
|
||||
if layout.size() == 0 {
|
||||
Ok((layout.dangling(), 0))
|
||||
} else {
|
||||
unsafe {
|
||||
NonNull::new(GlobalAlloc::alloc(self, layout))
|
||||
.ok_or(AllocErr)
|
||||
.map(|p| (p, layout.size()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn alloc_zeroed(&mut self, layout: Layout) -> Result<(NonNull<u8>, usize), AllocErr> {
|
||||
NonNull::new(GlobalAlloc::alloc_zeroed(self, layout))
|
||||
.ok_or(AllocErr)
|
||||
.map(|p| (p, layout.size()))
|
||||
fn alloc_zeroed(&mut self, layout: Layout) -> Result<(NonNull<u8>, usize), AllocErr> {
|
||||
if layout.size() == 0 {
|
||||
Ok((layout.dangling(), 0))
|
||||
} else {
|
||||
unsafe {
|
||||
NonNull::new(GlobalAlloc::alloc_zeroed(self, layout))
|
||||
.ok_or(AllocErr)
|
||||
.map(|p| (p, layout.size()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn dealloc(&mut self, ptr: NonNull<u8>, layout: Layout) {
|
||||
GlobalAlloc::dealloc(self, ptr.as_ptr(), layout)
|
||||
if layout.size() != 0 {
|
||||
GlobalAlloc::dealloc(self, ptr.as_ptr(), layout)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@ -160,9 +177,17 @@ unsafe impl AllocRef for System {
|
||||
layout: Layout,
|
||||
new_size: usize,
|
||||
) -> Result<(NonNull<u8>, usize), AllocErr> {
|
||||
NonNull::new(GlobalAlloc::realloc(self, ptr.as_ptr(), layout, new_size))
|
||||
.ok_or(AllocErr)
|
||||
.map(|p| (p, new_size))
|
||||
match (layout.size(), new_size) {
|
||||
(0, 0) => Ok((layout.dangling(), 0)),
|
||||
(0, _) => self.alloc(Layout::from_size_align_unchecked(new_size, layout.align())),
|
||||
(_, 0) => {
|
||||
self.dealloc(ptr, layout);
|
||||
Ok((layout.dangling(), 0))
|
||||
}
|
||||
(_, _) => NonNull::new(GlobalAlloc::realloc(self, ptr.as_ptr(), layout, new_size))
|
||||
.ok_or(AllocErr)
|
||||
.map(|p| (p, new_size)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -497,7 +497,6 @@ where
|
||||
/// [`&str`]: ../../std/primitive.str.html
|
||||
/// [slice]: ../../std/primitive.slice.html
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[doc(spotlight)]
|
||||
pub trait Read {
|
||||
/// Pull some bytes from this source into the specified buffer, returning
|
||||
/// how many bytes were read.
|
||||
@ -1228,7 +1227,6 @@ impl Initializer {
|
||||
///
|
||||
/// [`write_all`]: #method.write_all
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[doc(spotlight)]
|
||||
pub trait Write {
|
||||
/// Write a buffer into this writer, returning how many bytes were written.
|
||||
///
|
||||
|
@ -255,7 +255,6 @@
|
||||
#![feature(doc_cfg)]
|
||||
#![feature(doc_keyword)]
|
||||
#![feature(doc_masked)]
|
||||
#![feature(doc_spotlight)]
|
||||
#![feature(dropck_eyepatch)]
|
||||
#![feature(duration_constants)]
|
||||
#![feature(exact_size_is_empty)]
|
||||
|
@ -1,36 +0,0 @@
|
||||
#![feature(doc_spotlight)]
|
||||
|
||||
pub struct Wrapper<T> {
|
||||
inner: T,
|
||||
}
|
||||
|
||||
impl<T: SomeTrait> SomeTrait for Wrapper<T> {}
|
||||
|
||||
#[doc(spotlight)]
|
||||
pub trait SomeTrait {
|
||||
// @has doc_spotlight/trait.SomeTrait.html
|
||||
// @has - '//code[@class="content"]' 'impl<T: SomeTrait> SomeTrait for Wrapper<T>'
|
||||
fn wrap_me(self) -> Wrapper<Self> where Self: Sized {
|
||||
Wrapper {
|
||||
inner: self,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct SomeStruct;
|
||||
impl SomeTrait for SomeStruct {}
|
||||
|
||||
impl SomeStruct {
|
||||
// @has doc_spotlight/struct.SomeStruct.html
|
||||
// @has - '//code[@class="content"]' 'impl SomeTrait for SomeStruct'
|
||||
// @has - '//code[@class="content"]' 'impl<T: SomeTrait> SomeTrait for Wrapper<T>'
|
||||
pub fn new() -> SomeStruct {
|
||||
SomeStruct
|
||||
}
|
||||
}
|
||||
|
||||
// @has doc_spotlight/fn.bare_fn.html
|
||||
// @has - '//code[@class="content"]' 'impl SomeTrait for SomeStruct'
|
||||
pub fn bare_fn() -> SomeStruct {
|
||||
SomeStruct
|
||||
}
|
11
src/test/ui/asm/issue-62046.rs
Normal file
11
src/test/ui/asm/issue-62046.rs
Normal file
@ -0,0 +1,11 @@
|
||||
// build-fail
|
||||
// ignore-emscripten no asm! support
|
||||
|
||||
#![feature(asm)]
|
||||
|
||||
fn main() {
|
||||
unsafe {
|
||||
asm!("nop" : "+r"("r15"));
|
||||
//~^ malformed inline assembly
|
||||
}
|
||||
}
|
11
src/test/ui/asm/issue-62046.stderr
Normal file
11
src/test/ui/asm/issue-62046.stderr
Normal file
@ -0,0 +1,11 @@
|
||||
error[E0668]: malformed inline assembly
|
||||
--> $DIR/issue-62046.rs:8:9
|
||||
|
|
||||
LL | asm!("nop" : "+r"("r15"));
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0668`.
|
@ -0,0 +1,224 @@
|
||||
// Tests using a combination of pattern features has the expected borrow checking behavior
|
||||
#![feature(bindings_after_at)]
|
||||
#![feature(or_patterns)]
|
||||
#![feature(box_patterns)]
|
||||
|
||||
#![feature(move_ref_pattern)]
|
||||
|
||||
enum Test {
|
||||
Foo,
|
||||
Bar,
|
||||
_Baz,
|
||||
}
|
||||
|
||||
// bindings_after_at + slice_patterns
|
||||
|
||||
fn bindings_after_at_slice_patterns_move_binding(x: [String; 4]) {
|
||||
match x {
|
||||
a @ [.., _] => (),
|
||||
_ => (),
|
||||
};
|
||||
|
||||
&x;
|
||||
//~^ ERROR borrow of moved value
|
||||
}
|
||||
|
||||
fn bindings_after_at_slice_patterns_borrows_binding_mut(mut x: [String; 4]) {
|
||||
let r = match x {
|
||||
ref mut foo @ [.., _] => Some(foo),
|
||||
_ => None,
|
||||
};
|
||||
|
||||
&x;
|
||||
//~^ ERROR cannot borrow
|
||||
|
||||
drop(r);
|
||||
}
|
||||
|
||||
fn bindings_after_at_slice_patterns_borrows_slice_mut1(mut x: [String; 4]) {
|
||||
let r = match x {
|
||||
ref foo @ [.., ref mut bar] => (),
|
||||
//~^ ERROR cannot borrow
|
||||
_ => (),
|
||||
};
|
||||
|
||||
drop(r);
|
||||
}
|
||||
|
||||
fn bindings_after_at_slice_patterns_borrows_slice_mut2(mut x: [String; 4]) {
|
||||
let r = match x {
|
||||
[ref foo @ .., ref bar] => Some(foo),
|
||||
_ => None,
|
||||
};
|
||||
|
||||
&mut x;
|
||||
//~^ ERROR cannot borrow
|
||||
|
||||
drop(r);
|
||||
}
|
||||
|
||||
fn bindings_after_at_slice_patterns_borrows_both(mut x: [String; 4]) {
|
||||
let r = match x {
|
||||
ref foo @ [.., ref bar] => Some(foo),
|
||||
_ => None,
|
||||
};
|
||||
|
||||
&mut x;
|
||||
//~^ ERROR cannot borrow
|
||||
|
||||
drop(r);
|
||||
}
|
||||
|
||||
// bindings_after_at + or_patterns
|
||||
|
||||
fn bindings_after_at_or_patterns_move(x: Option<Test>) {
|
||||
match x {
|
||||
foo @ Some(Test::Foo | Test::Bar) => (),
|
||||
_ => (),
|
||||
}
|
||||
|
||||
&x;
|
||||
//~^ ERROR borrow of moved value
|
||||
}
|
||||
|
||||
fn bindings_after_at_or_patterns_borrows(mut x: Option<Test>) {
|
||||
let r = match x {
|
||||
ref foo @ Some(Test::Foo | Test::Bar) => Some(foo),
|
||||
_ => None,
|
||||
};
|
||||
|
||||
&mut x;
|
||||
//~^ ERROR cannot borrow
|
||||
|
||||
drop(r);
|
||||
}
|
||||
|
||||
fn bindings_after_at_or_patterns_borrows_mut(mut x: Option<Test>) {
|
||||
let r = match x {
|
||||
ref mut foo @ Some(Test::Foo | Test::Bar) => Some(foo),
|
||||
_ => None,
|
||||
};
|
||||
|
||||
&x;
|
||||
//~^ ERROR cannot borrow
|
||||
|
||||
drop(r);
|
||||
}
|
||||
|
||||
// bindings_after_at + box_patterns
|
||||
|
||||
fn bindings_after_at_box_patterns_borrows_both(mut x: Option<Box<String>>) {
|
||||
let r = match x {
|
||||
ref foo @ Some(box ref s) => Some(foo),
|
||||
_ => None,
|
||||
};
|
||||
|
||||
&mut x;
|
||||
//~^ ERROR cannot borrow
|
||||
|
||||
drop(r);
|
||||
}
|
||||
|
||||
fn bindings_after_at_box_patterns_borrows_mut(mut x: Option<Box<String>>) {
|
||||
match x {
|
||||
ref foo @ Some(box ref mut s) => (),
|
||||
//~^ ERROR cannot borrow
|
||||
_ => (),
|
||||
};
|
||||
}
|
||||
|
||||
// bindings_after_at + slice_patterns + or_patterns
|
||||
|
||||
fn bindings_after_at_slice_patterns_or_patterns_moves(x: [Option<Test>; 4]) {
|
||||
match x {
|
||||
a @ [.., Some(Test::Foo | Test::Bar)] => (),
|
||||
_ => (),
|
||||
};
|
||||
|
||||
&x;
|
||||
//~^ ERROR borrow of moved value
|
||||
}
|
||||
|
||||
fn bindings_after_at_slice_patterns_or_patterns_borrows_binding(mut x: [Option<Test>; 4]) {
|
||||
let r = match x {
|
||||
ref a @ [ref b @ .., Some(Test::Foo | Test::Bar)] => Some(a),
|
||||
_ => None,
|
||||
};
|
||||
|
||||
&mut x;
|
||||
//~^ ERROR cannot borrow
|
||||
|
||||
drop(r);
|
||||
}
|
||||
|
||||
fn bindings_after_at_slice_patterns_or_patterns_borrows_slice(mut x: [Option<Test>; 4]) {
|
||||
let r = match x {
|
||||
ref a @ [ref b @ .., Some(Test::Foo | Test::Bar)] => Some(b),
|
||||
_ => None,
|
||||
};
|
||||
|
||||
&mut x;
|
||||
//~^ ERROR cannot borrow
|
||||
|
||||
drop(r);
|
||||
}
|
||||
|
||||
// bindings_after_at + slice_patterns + box_patterns
|
||||
|
||||
fn bindings_after_at_slice_patterns_box_patterns_borrows(mut x: [Option<Box<String>>; 4]) {
|
||||
let r = match x {
|
||||
[_, ref a @ Some(box ref b), ..] => Some(a),
|
||||
_ => None,
|
||||
};
|
||||
|
||||
&mut x;
|
||||
//~^ ERROR cannot borrow
|
||||
|
||||
drop(r);
|
||||
}
|
||||
|
||||
// bindings_after_at + slice_patterns + or_patterns + box_patterns
|
||||
|
||||
fn bindings_after_at_slice_patterns_or_patterns_box_patterns_borrows(
|
||||
mut x: [Option<Box<Test>>; 4]
|
||||
) {
|
||||
let r = match x {
|
||||
[_, ref a @ Some(box Test::Foo | box Test::Bar), ..] => Some(a),
|
||||
_ => None,
|
||||
};
|
||||
|
||||
&mut x;
|
||||
//~^ ERROR cannot borrow
|
||||
|
||||
drop(r);
|
||||
}
|
||||
|
||||
fn bindings_after_at_slice_patterns_or_patterns_box_patterns_borrows_mut(
|
||||
mut x: [Option<Box<Test>>; 4]
|
||||
) {
|
||||
let r = match x {
|
||||
[_, ref mut a @ Some(box Test::Foo | box Test::Bar), ..] => Some(a),
|
||||
_ => None,
|
||||
};
|
||||
|
||||
&x;
|
||||
//~^ ERROR cannot borrow
|
||||
|
||||
drop(r);
|
||||
}
|
||||
|
||||
fn bindings_after_at_slice_patterns_or_patterns_box_patterns_borrows_binding(
|
||||
mut x: [Option<Box<Test>>; 4]
|
||||
) {
|
||||
let r = match x {
|
||||
ref a @ [_, ref b @ Some(box Test::Foo | box Test::Bar), ..] => Some(a),
|
||||
_ => None,
|
||||
};
|
||||
|
||||
&mut x;
|
||||
//~^ ERROR cannot borrow
|
||||
|
||||
drop(r);
|
||||
}
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,208 @@
|
||||
error: cannot borrow value as mutable because it is also borrowed as immutable
|
||||
--> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:40:9
|
||||
|
|
||||
LL | ref foo @ [.., ref mut bar] => (),
|
||||
| -------^^^^^^^^-----------^
|
||||
| | |
|
||||
| | mutable borrow, by `bar`, occurs here
|
||||
| immutable borrow, by `foo`, occurs here
|
||||
|
||||
error: cannot borrow value as mutable because it is also borrowed as immutable
|
||||
--> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:124:9
|
||||
|
|
||||
LL | ref foo @ Some(box ref mut s) => (),
|
||||
| -------^^^^^^^^^^^^---------^
|
||||
| | |
|
||||
| | mutable borrow, by `s`, occurs here
|
||||
| immutable borrow, by `foo`, occurs here
|
||||
|
||||
error[E0382]: borrow of moved value: `x`
|
||||
--> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:22:5
|
||||
|
|
||||
LL | fn bindings_after_at_slice_patterns_move_binding(x: [String; 4]) {
|
||||
| - move occurs because `x` has type `[std::string::String; 4]`, which does not implement the `Copy` trait
|
||||
LL | match x {
|
||||
LL | a @ [.., _] => (),
|
||||
| ----------- value moved here
|
||||
...
|
||||
LL | &x;
|
||||
| ^^ value borrowed here after move
|
||||
|
||||
error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable
|
||||
--> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:32:5
|
||||
|
|
||||
LL | ref mut foo @ [.., _] => Some(foo),
|
||||
| --------------------- mutable borrow occurs here
|
||||
...
|
||||
LL | &x;
|
||||
| ^^ immutable borrow occurs here
|
||||
...
|
||||
LL | drop(r);
|
||||
| - mutable borrow later used here
|
||||
|
||||
error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
|
||||
--> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:54:5
|
||||
|
|
||||
LL | [ref foo @ .., ref bar] => Some(foo),
|
||||
| ------------ immutable borrow occurs here
|
||||
...
|
||||
LL | &mut x;
|
||||
| ^^^^^^ mutable borrow occurs here
|
||||
...
|
||||
LL | drop(r);
|
||||
| - immutable borrow later used here
|
||||
|
||||
error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
|
||||
--> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:66:5
|
||||
|
|
||||
LL | ref foo @ [.., ref bar] => Some(foo),
|
||||
| ----------------------- immutable borrow occurs here
|
||||
...
|
||||
LL | &mut x;
|
||||
| ^^^^^^ mutable borrow occurs here
|
||||
...
|
||||
LL | drop(r);
|
||||
| - immutable borrow later used here
|
||||
|
||||
error[E0382]: borrow of moved value: `x`
|
||||
--> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:80:5
|
||||
|
|
||||
LL | fn bindings_after_at_or_patterns_move(x: Option<Test>) {
|
||||
| - move occurs because `x` has type `std::option::Option<Test>`, which does not implement the `Copy` trait
|
||||
LL | match x {
|
||||
LL | foo @ Some(Test::Foo | Test::Bar) => (),
|
||||
| ---------------------------------
|
||||
| |
|
||||
| value moved here
|
||||
| value moved here
|
||||
...
|
||||
LL | &x;
|
||||
| ^^ value borrowed here after move
|
||||
|
||||
error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
|
||||
--> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:90:5
|
||||
|
|
||||
LL | ref foo @ Some(Test::Foo | Test::Bar) => Some(foo),
|
||||
| ------------------------------------- immutable borrow occurs here
|
||||
...
|
||||
LL | &mut x;
|
||||
| ^^^^^^ mutable borrow occurs here
|
||||
...
|
||||
LL | drop(r);
|
||||
| - immutable borrow later used here
|
||||
|
||||
error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable
|
||||
--> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:102:5
|
||||
|
|
||||
LL | ref mut foo @ Some(Test::Foo | Test::Bar) => Some(foo),
|
||||
| ----------------------------------------- mutable borrow occurs here
|
||||
...
|
||||
LL | &x;
|
||||
| ^^ immutable borrow occurs here
|
||||
...
|
||||
LL | drop(r);
|
||||
| - mutable borrow later used here
|
||||
|
||||
error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
|
||||
--> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:116:5
|
||||
|
|
||||
LL | ref foo @ Some(box ref s) => Some(foo),
|
||||
| ------------------------- immutable borrow occurs here
|
||||
...
|
||||
LL | &mut x;
|
||||
| ^^^^^^ mutable borrow occurs here
|
||||
...
|
||||
LL | drop(r);
|
||||
| - immutable borrow later used here
|
||||
|
||||
error[E0382]: borrow of moved value: `x`
|
||||
--> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:138:5
|
||||
|
|
||||
LL | fn bindings_after_at_slice_patterns_or_patterns_moves(x: [Option<Test>; 4]) {
|
||||
| - move occurs because `x` has type `[std::option::Option<Test>; 4]`, which does not implement the `Copy` trait
|
||||
LL | match x {
|
||||
LL | a @ [.., Some(Test::Foo | Test::Bar)] => (),
|
||||
| -------------------------------------
|
||||
| |
|
||||
| value moved here
|
||||
| value moved here
|
||||
...
|
||||
LL | &x;
|
||||
| ^^ value borrowed here after move
|
||||
|
||||
error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
|
||||
--> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:148:5
|
||||
|
|
||||
LL | ref a @ [ref b @ .., Some(Test::Foo | Test::Bar)] => Some(a),
|
||||
| ------------------------------------------------- immutable borrow occurs here
|
||||
...
|
||||
LL | &mut x;
|
||||
| ^^^^^^ mutable borrow occurs here
|
||||
...
|
||||
LL | drop(r);
|
||||
| - immutable borrow later used here
|
||||
|
||||
error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
|
||||
--> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:160:5
|
||||
|
|
||||
LL | ref a @ [ref b @ .., Some(Test::Foo | Test::Bar)] => Some(b),
|
||||
| ---------- immutable borrow occurs here
|
||||
...
|
||||
LL | &mut x;
|
||||
| ^^^^^^ mutable borrow occurs here
|
||||
...
|
||||
LL | drop(r);
|
||||
| - immutable borrow later used here
|
||||
|
||||
error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
|
||||
--> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:174:5
|
||||
|
|
||||
LL | [_, ref a @ Some(box ref b), ..] => Some(a),
|
||||
| ----------------------- immutable borrow occurs here
|
||||
...
|
||||
LL | &mut x;
|
||||
| ^^^^^^ mutable borrow occurs here
|
||||
...
|
||||
LL | drop(r);
|
||||
| - immutable borrow later used here
|
||||
|
||||
error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
|
||||
--> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:190:5
|
||||
|
|
||||
LL | [_, ref a @ Some(box Test::Foo | box Test::Bar), ..] => Some(a),
|
||||
| ------------------------------------------- immutable borrow occurs here
|
||||
...
|
||||
LL | &mut x;
|
||||
| ^^^^^^ mutable borrow occurs here
|
||||
...
|
||||
LL | drop(r);
|
||||
| - immutable borrow later used here
|
||||
|
||||
error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable
|
||||
--> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:204:5
|
||||
|
|
||||
LL | [_, ref mut a @ Some(box Test::Foo | box Test::Bar), ..] => Some(a),
|
||||
| ----------------------------------------------- mutable borrow occurs here
|
||||
...
|
||||
LL | &x;
|
||||
| ^^ immutable borrow occurs here
|
||||
...
|
||||
LL | drop(r);
|
||||
| - mutable borrow later used here
|
||||
|
||||
error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
|
||||
--> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:218:5
|
||||
|
|
||||
LL | ref a @ [_, ref b @ Some(box Test::Foo | box Test::Bar), ..] => Some(a),
|
||||
| ------------------------------------------------------------ immutable borrow occurs here
|
||||
...
|
||||
LL | &mut x;
|
||||
| ^^^^^^ mutable borrow occurs here
|
||||
...
|
||||
LL | drop(r);
|
||||
| - immutable borrow later used here
|
||||
|
||||
error: aborting due to 17 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0382, E0502.
|
||||
For more information about an error, try `rustc --explain E0382`.
|
@ -1,4 +0,0 @@
|
||||
#[doc(spotlight)] //~ ERROR: `#[doc(spotlight)]` is experimental
|
||||
trait SomeTrait {}
|
||||
|
||||
fn main() {}
|
@ -1,12 +0,0 @@
|
||||
error[E0658]: `#[doc(spotlight)]` is experimental
|
||||
--> $DIR/feature-gate-doc_spotlight.rs:1:1
|
||||
|
|
||||
LL | #[doc(spotlight)]
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #45040 <https://github.com/rust-lang/rust/issues/45040> for more information
|
||||
= help: add `#![feature(doc_spotlight)]` to the crate attributes to enable
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
Loading…
Reference in New Issue
Block a user