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:
bors 2020-03-10 05:48:27 +00:00
commit dd155df0a6
60 changed files with 924 additions and 885 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -90,7 +90,6 @@
#![feature(custom_inner_attributes)]
#![feature(decl_macro)]
#![feature(doc_cfg)]
#![feature(doc_spotlight)]
#![feature(extern_types)]
#![feature(fundamental)]
#![feature(intrinsics)]

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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] } => {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,11 @@
// build-fail
// ignore-emscripten no asm! support
#![feature(asm)]
fn main() {
unsafe {
asm!("nop" : "+r"("r15"));
//~^ malformed inline assembly
}
}

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

View File

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

View File

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

View File

@ -1,4 +0,0 @@
#[doc(spotlight)] //~ ERROR: `#[doc(spotlight)]` is experimental
trait SomeTrait {}
fn main() {}

View File

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