mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-16 17:03:35 +00:00
Auto merge of #110916 - matthiaskrgr:rollup-g3c33zc, r=matthiaskrgr
Rollup of 9 pull requests Successful merges: - #105745 (docs(std): clarify remove_dir_all errors) - #106456 (Correct `std::prelude` comment) - #106599 (Change memory ordering in System wrapper example) - #110838 (More `Typefoldable`/`TypeVisitable` cleanups) - #110851 (compiletest: emit assembly-output header in error) - #110853 (compiletest: add bpf-linker assembly support) - #110878 (Add `known-bug` tests for 4 unsound issues) - #110886 (`DepGraph` cleanups) - #110905 (Remove invalid value from scraped-examples.md) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
1a6ae3d692
@ -20,7 +20,7 @@ pub struct MismatchedProjectionTypes<'tcx> {
|
||||
pub err: ty::error::TypeError<'tcx>,
|
||||
}
|
||||
|
||||
#[derive(Clone, TypeFoldable, TypeVisitable)]
|
||||
#[derive(Clone)]
|
||||
pub struct Normalized<'tcx, T> {
|
||||
pub value: T,
|
||||
pub obligations: Vec<PredicateObligation<'tcx>>,
|
||||
|
@ -66,7 +66,6 @@ pub struct Place<'tcx> {
|
||||
///
|
||||
/// This is an HIR version of [`rustc_middle::mir::Place`].
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)]
|
||||
#[derive(TypeFoldable, TypeVisitable)]
|
||||
pub struct PlaceWithHirId<'tcx> {
|
||||
/// `HirId` of the expression or pattern producing this value.
|
||||
pub hir_id: HirId,
|
||||
|
@ -9,7 +9,7 @@ use crate::mir::visit::MirVisitable;
|
||||
use crate::ty::codec::{TyDecoder, TyEncoder};
|
||||
use crate::ty::fold::{FallibleTypeFolder, TypeFoldable};
|
||||
use crate::ty::print::{FmtPrinter, Printer};
|
||||
use crate::ty::visit::{TypeVisitable, TypeVisitableExt, TypeVisitor};
|
||||
use crate::ty::visit::TypeVisitableExt;
|
||||
use crate::ty::{self, List, Ty, TyCtxt};
|
||||
use crate::ty::{AdtDef, InstanceDef, ScalarInt, UserTypeAnnotationIndex};
|
||||
use crate::ty::{GenericArg, InternalSubsts, SubstsRef};
|
||||
@ -36,7 +36,7 @@ use either::Either;
|
||||
|
||||
use std::borrow::Cow;
|
||||
use std::fmt::{self, Debug, Display, Formatter, Write};
|
||||
use std::ops::{ControlFlow, Index, IndexMut};
|
||||
use std::ops::{Index, IndexMut};
|
||||
use std::{iter, mem};
|
||||
|
||||
pub use self::query::*;
|
||||
@ -2722,6 +2722,7 @@ impl<'tcx> UserTypeProjections {
|
||||
/// `field[0]` (aka `.0`), indicating that the type of `s` is
|
||||
/// determined by finding the type of the `.0` field from `T`.
|
||||
#[derive(Clone, Debug, TyEncodable, TyDecodable, Hash, HashStable, PartialEq)]
|
||||
#[derive(TypeFoldable, TypeVisitable)]
|
||||
pub struct UserTypeProjection {
|
||||
pub base: UserTypeAnnotationIndex,
|
||||
pub projs: Vec<ProjectionKind>,
|
||||
@ -2765,28 +2766,6 @@ impl UserTypeProjection {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for UserTypeProjection {
|
||||
fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
|
||||
self,
|
||||
folder: &mut F,
|
||||
) -> Result<Self, F::Error> {
|
||||
Ok(UserTypeProjection {
|
||||
base: self.base.try_fold_with(folder)?,
|
||||
projs: self.projs.try_fold_with(folder)?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for UserTypeProjection {
|
||||
fn visit_with<Vs: TypeVisitor<TyCtxt<'tcx>>>(
|
||||
&self,
|
||||
visitor: &mut Vs,
|
||||
) -> ControlFlow<Vs::BreakTy> {
|
||||
self.base.visit_with(visitor)
|
||||
// Note: there's nothing in `self.proj` to visit.
|
||||
}
|
||||
}
|
||||
|
||||
rustc_index::newtype_index! {
|
||||
#[derive(HashStable)]
|
||||
#[debug_format = "promoted[{}]"]
|
||||
|
@ -234,7 +234,6 @@ pub enum StmtKind<'tcx> {
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Copy, PartialEq, Eq, Hash, HashStable, TyEncodable, TyDecodable)]
|
||||
#[derive(TypeFoldable, TypeVisitable)]
|
||||
pub struct LocalVarId(pub hir::HirId);
|
||||
|
||||
/// A THIR expression.
|
||||
|
@ -569,7 +569,7 @@ pub struct DerivedObligationCause<'tcx> {
|
||||
pub parent_code: InternedObligationCauseCode<'tcx>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, TypeFoldable, TypeVisitable, Lift)]
|
||||
#[derive(Clone, Debug, TypeVisitable, Lift)]
|
||||
pub enum SelectionError<'tcx> {
|
||||
/// The trait is not implemented.
|
||||
Unimplemented,
|
||||
|
@ -103,7 +103,7 @@ pub type EvaluationCache<'tcx> = Cache<
|
||||
/// required for associated types to work in default impls, as the bounds
|
||||
/// are visible both as projection bounds and as where-clauses from the
|
||||
/// parameter environment.
|
||||
#[derive(PartialEq, Eq, Debug, Clone, TypeFoldable, TypeVisitable)]
|
||||
#[derive(PartialEq, Eq, Debug, Clone, TypeVisitable)]
|
||||
pub enum SelectionCandidate<'tcx> {
|
||||
/// A builtin implementation for some specific traits, used in cases
|
||||
/// where we cannot rely an ordinary library implementations.
|
||||
|
@ -120,7 +120,7 @@ impl<'tcx> std::ops::Deref for ExternalConstraints<'tcx> {
|
||||
}
|
||||
|
||||
/// Additional constraints returned on success.
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Hash, Default, TypeFoldable, TypeVisitable)]
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Hash, Default)]
|
||||
pub struct ExternalConstraintsData<'tcx> {
|
||||
// FIXME: implement this.
|
||||
pub region_constraints: QueryRegionConstraints<'tcx>,
|
||||
|
@ -28,7 +28,7 @@ impl<T> ExpectedFound<T> {
|
||||
}
|
||||
|
||||
// Data structures used in type unification
|
||||
#[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable, Lift, PartialEq, Eq)]
|
||||
#[derive(Copy, Clone, Debug, TypeVisitable, Lift, PartialEq, Eq)]
|
||||
#[rustc_pass_by_value]
|
||||
pub enum TypeError<'tcx> {
|
||||
Mismatch,
|
||||
|
@ -2690,7 +2690,7 @@ impl<'tcx> ty::PolyTraitPredicate<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, TypeFoldable, TypeVisitable, Lift)]
|
||||
#[derive(Debug, Copy, Clone, Lift)]
|
||||
pub struct PrintClosureAsImpl<'tcx> {
|
||||
pub closure: ty::ClosureSubsts<'tcx>,
|
||||
}
|
||||
|
@ -4,7 +4,6 @@
|
||||
//! to help with the tedium.
|
||||
|
||||
use crate::mir::interpret;
|
||||
use crate::mir::ProjectionKind;
|
||||
use crate::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeSuperFoldable};
|
||||
use crate::ty::print::{with_no_trimmed_paths, FmtPrinter, Printer};
|
||||
use crate::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor};
|
||||
@ -373,16 +372,6 @@ impl<'a, 'tcx> Lift<'tcx> for ty::ParamEnv<'a> {
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Traversal implementations.
|
||||
|
||||
/// AdtDefs are basically the same as a DefId.
|
||||
impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for ty::AdtDef<'tcx> {
|
||||
fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
|
||||
self,
|
||||
_folder: &mut F,
|
||||
) -> Result<Self, F::Error> {
|
||||
Ok(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for ty::AdtDef<'tcx> {
|
||||
fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(
|
||||
&self,
|
||||
@ -445,15 +434,6 @@ impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for &'tcx ty::List<ty::Const<'tcx>> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for &'tcx ty::List<ProjectionKind> {
|
||||
fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
|
||||
self,
|
||||
folder: &mut F,
|
||||
) -> Result<Self, F::Error> {
|
||||
ty::util::fold_list(self, folder, |tcx, v| tcx.mk_projs(v))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for Ty<'tcx> {
|
||||
fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
|
||||
self,
|
||||
|
@ -631,7 +631,7 @@ impl<'tcx> UpvarSubsts<'tcx> {
|
||||
/// type of the constant. The reason that `R` is represented as an extra type parameter
|
||||
/// is the same reason that [`ClosureSubsts`] have `CS` and `U` as type parameters:
|
||||
/// inline const can reference lifetimes that are internal to the creating function.
|
||||
#[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable)]
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct InlineConstSubsts<'tcx> {
|
||||
/// Generic parameters from the enclosing item,
|
||||
/// concatenated with the inferred type of the constant.
|
||||
|
@ -354,24 +354,20 @@ impl<K: DepKind> DepGraphData<K> {
|
||||
- dep-node: {key:?}"
|
||||
);
|
||||
|
||||
let task_deps = if cx.dep_context().is_eval_always(key.kind) {
|
||||
None
|
||||
let with_deps = |task_deps| K::with_deps(task_deps, || task(cx, arg));
|
||||
let (result, edges) = if cx.dep_context().is_eval_always(key.kind) {
|
||||
(with_deps(TaskDepsRef::EvalAlways), smallvec![])
|
||||
} else {
|
||||
Some(Lock::new(TaskDeps {
|
||||
let task_deps = Lock::new(TaskDeps {
|
||||
#[cfg(debug_assertions)]
|
||||
node: Some(key),
|
||||
reads: SmallVec::new(),
|
||||
read_set: Default::default(),
|
||||
phantom_data: PhantomData,
|
||||
}))
|
||||
});
|
||||
(with_deps(TaskDepsRef::Allow(&task_deps)), task_deps.into_inner().reads)
|
||||
};
|
||||
|
||||
let task_deps_ref =
|
||||
task_deps.as_ref().map(TaskDepsRef::Allow).unwrap_or(TaskDepsRef::EvalAlways);
|
||||
|
||||
let result = K::with_deps(task_deps_ref, || task(cx, arg));
|
||||
let edges = task_deps.map_or_else(|| smallvec![], |lock| lock.into_inner().reads);
|
||||
|
||||
let dcx = cx.dep_context();
|
||||
let hashing_timer = dcx.profiler().incr_result_hashing();
|
||||
let current_fingerprint =
|
||||
@ -1236,76 +1232,48 @@ impl<K: DepKind> CurrentDepGraph<K> {
|
||||
self.node_intern_event_id.map(|eid| profiler.generic_activity_with_event_id(eid));
|
||||
|
||||
if let Some(prev_index) = prev_graph.node_to_index_opt(&key) {
|
||||
// Determine the color and index of the new `DepNode`.
|
||||
if let Some(fingerprint) = fingerprint {
|
||||
if fingerprint == prev_graph.fingerprint_by_index(prev_index) {
|
||||
if print_status {
|
||||
eprintln!("[task::green] {key:?}");
|
||||
}
|
||||
|
||||
// This is a green node: it existed in the previous compilation,
|
||||
// its query was re-executed, and it has the same result as before.
|
||||
let mut prev_index_to_index = self.prev_index_to_index.lock();
|
||||
|
||||
let dep_node_index = match prev_index_to_index[prev_index] {
|
||||
Some(dep_node_index) => dep_node_index,
|
||||
None => {
|
||||
let dep_node_index =
|
||||
self.encoder.borrow().send(profiler, key, fingerprint, edges);
|
||||
prev_index_to_index[prev_index] = Some(dep_node_index);
|
||||
dep_node_index
|
||||
}
|
||||
};
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
self.record_edge(dep_node_index, key, fingerprint);
|
||||
(dep_node_index, Some((prev_index, DepNodeColor::Green(dep_node_index))))
|
||||
} else {
|
||||
if print_status {
|
||||
eprintln!("[task::red] {key:?}");
|
||||
}
|
||||
|
||||
// This is a red node: it existed in the previous compilation, its query
|
||||
// was re-executed, but it has a different result from before.
|
||||
let mut prev_index_to_index = self.prev_index_to_index.lock();
|
||||
|
||||
let dep_node_index = match prev_index_to_index[prev_index] {
|
||||
Some(dep_node_index) => dep_node_index,
|
||||
None => {
|
||||
let dep_node_index =
|
||||
self.encoder.borrow().send(profiler, key, fingerprint, edges);
|
||||
prev_index_to_index[prev_index] = Some(dep_node_index);
|
||||
dep_node_index
|
||||
}
|
||||
};
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
self.record_edge(dep_node_index, key, fingerprint);
|
||||
(dep_node_index, Some((prev_index, DepNodeColor::Red)))
|
||||
}
|
||||
} else {
|
||||
let get_dep_node_index = |color, fingerprint| {
|
||||
if print_status {
|
||||
eprintln!("[task::unknown] {key:?}");
|
||||
eprintln!("[task::{color:}] {key:?}");
|
||||
}
|
||||
|
||||
// This is a red node, effectively: it existed in the previous compilation
|
||||
// session, its query was re-executed, but it doesn't compute a result hash
|
||||
// (i.e. it represents a `no_hash` query), so we have no way of determining
|
||||
// whether or not the result was the same as before.
|
||||
let mut prev_index_to_index = self.prev_index_to_index.lock();
|
||||
|
||||
let dep_node_index = match prev_index_to_index[prev_index] {
|
||||
Some(dep_node_index) => dep_node_index,
|
||||
None => {
|
||||
let dep_node_index =
|
||||
self.encoder.borrow().send(profiler, key, Fingerprint::ZERO, edges);
|
||||
self.encoder.borrow().send(profiler, key, fingerprint, edges);
|
||||
prev_index_to_index[prev_index] = Some(dep_node_index);
|
||||
dep_node_index
|
||||
}
|
||||
};
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
self.record_edge(dep_node_index, key, Fingerprint::ZERO);
|
||||
self.record_edge(dep_node_index, key, fingerprint);
|
||||
|
||||
dep_node_index
|
||||
};
|
||||
|
||||
// Determine the color and index of the new `DepNode`.
|
||||
if let Some(fingerprint) = fingerprint {
|
||||
if fingerprint == prev_graph.fingerprint_by_index(prev_index) {
|
||||
// This is a green node: it existed in the previous compilation,
|
||||
// its query was re-executed, and it has the same result as before.
|
||||
let dep_node_index = get_dep_node_index("green", fingerprint);
|
||||
(dep_node_index, Some((prev_index, DepNodeColor::Green(dep_node_index))))
|
||||
} else {
|
||||
// This is a red node: it existed in the previous compilation, its query
|
||||
// was re-executed, but it has a different result from before.
|
||||
let dep_node_index = get_dep_node_index("red", fingerprint);
|
||||
(dep_node_index, Some((prev_index, DepNodeColor::Red)))
|
||||
}
|
||||
} else {
|
||||
// This is a red node, effectively: it existed in the previous compilation
|
||||
// session, its query was re-executed, but it doesn't compute a result hash
|
||||
// (i.e. it represents a `no_hash` query), so we have no way of determining
|
||||
// whether or not the result was the same as before.
|
||||
let dep_node_index = get_dep_node_index("unknown", Fingerprint::ZERO);
|
||||
(dep_node_index, Some((prev_index, DepNodeColor::Red)))
|
||||
}
|
||||
} else {
|
||||
|
@ -62,7 +62,7 @@ mod rustc {
|
||||
|
||||
use rustc_hir::lang_items::LangItem;
|
||||
use rustc_infer::infer::InferCtxt;
|
||||
use rustc_macros::{TypeFoldable, TypeVisitable};
|
||||
use rustc_macros::TypeVisitable;
|
||||
use rustc_middle::traits::ObligationCause;
|
||||
use rustc_middle::ty::Const;
|
||||
use rustc_middle::ty::ParamEnv;
|
||||
@ -70,7 +70,7 @@ mod rustc {
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
|
||||
/// The source and destination types of a transmutation.
|
||||
#[derive(TypeFoldable, TypeVisitable, Debug, Clone, Copy)]
|
||||
#[derive(TypeVisitable, Debug, Clone, Copy)]
|
||||
pub struct Types<'tcx> {
|
||||
/// The source type.
|
||||
pub src: Ty<'tcx>,
|
||||
|
@ -6,11 +6,10 @@ use crate::fold::{FallibleTypeFolder, TypeFoldable};
|
||||
use crate::visit::{TypeVisitable, TypeVisitor};
|
||||
use crate::Interner;
|
||||
use rustc_data_structures::functor::IdFunctor;
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_index::{Idx, IndexVec};
|
||||
|
||||
use std::ops::ControlFlow;
|
||||
use std::rc::Rc;
|
||||
use std::sync::Arc;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Atomic structs
|
||||
@ -106,25 +105,13 @@ impl<I: Interner, T: TypeVisitable<I>, E: TypeVisitable<I>> TypeVisitable<I> for
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Interner, T: TypeFoldable<I>> TypeFoldable<I> for Rc<T> {
|
||||
impl<I: Interner, T: TypeFoldable<I>> TypeFoldable<I> for Lrc<T> {
|
||||
fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
|
||||
self.try_map_id(|value| value.try_fold_with(folder))
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Interner, T: TypeVisitable<I>> TypeVisitable<I> for Rc<T> {
|
||||
fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
|
||||
(**self).visit_with(visitor)
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Interner, T: TypeFoldable<I>> TypeFoldable<I> for Arc<T> {
|
||||
fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
|
||||
self.try_map_id(|value| value.try_fold_with(folder))
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Interner, T: TypeVisitable<I>> TypeVisitable<I> for Arc<T> {
|
||||
impl<I: Interner, T: TypeVisitable<I>> TypeVisitable<I> for Lrc<T> {
|
||||
fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
|
||||
(**self).visit_with(visitor)
|
||||
}
|
||||
@ -154,24 +141,16 @@ impl<I: Interner, T: TypeVisitable<I>> TypeVisitable<I> for Vec<T> {
|
||||
}
|
||||
}
|
||||
|
||||
// `TypeFoldable` isn't impl'd for `&[T]`. It doesn't make sense in the general
|
||||
// case, because we can't return a new slice. But note that there are a couple
|
||||
// of trivial impls of `TypeFoldable` for specific slice types elsewhere.
|
||||
|
||||
impl<I: Interner, T: TypeVisitable<I>> TypeVisitable<I> for &[T] {
|
||||
fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
|
||||
self.iter().try_for_each(|t| t.visit_with(visitor))
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Interner, T: TypeFoldable<I>> TypeFoldable<I> for Box<[T]> {
|
||||
fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
|
||||
self.try_map_id(|t| t.try_fold_with(folder))
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Interner, T: TypeVisitable<I>> TypeVisitable<I> for Box<[T]> {
|
||||
fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
|
||||
self.iter().try_for_each(|t| t.visit_with(visitor))
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Interner, T: TypeFoldable<I>, Ix: Idx> TypeFoldable<I> for IndexVec<Ix, T> {
|
||||
fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
|
||||
self.try_map_id(|x| x.try_fold_with(folder))
|
||||
|
@ -93,7 +93,7 @@ pub use alloc_crate::alloc::*;
|
||||
///
|
||||
/// ```rust
|
||||
/// use std::alloc::{System, GlobalAlloc, Layout};
|
||||
/// use std::sync::atomic::{AtomicUsize, Ordering::SeqCst};
|
||||
/// use std::sync::atomic::{AtomicUsize, Ordering::Relaxed};
|
||||
///
|
||||
/// struct Counter;
|
||||
///
|
||||
@ -103,14 +103,14 @@ pub use alloc_crate::alloc::*;
|
||||
/// unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
|
||||
/// let ret = System.alloc(layout);
|
||||
/// if !ret.is_null() {
|
||||
/// ALLOCATED.fetch_add(layout.size(), SeqCst);
|
||||
/// ALLOCATED.fetch_add(layout.size(), Relaxed);
|
||||
/// }
|
||||
/// ret
|
||||
/// }
|
||||
///
|
||||
/// unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
|
||||
/// System.dealloc(ptr, layout);
|
||||
/// ALLOCATED.fetch_sub(layout.size(), SeqCst);
|
||||
/// ALLOCATED.fetch_sub(layout.size(), Relaxed);
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
@ -118,7 +118,7 @@ pub use alloc_crate::alloc::*;
|
||||
/// static A: Counter = Counter;
|
||||
///
|
||||
/// fn main() {
|
||||
/// println!("allocated bytes before main: {}", ALLOCATED.load(SeqCst));
|
||||
/// println!("allocated bytes before main: {}", ALLOCATED.load(Relaxed));
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
|
@ -2284,6 +2284,11 @@ pub fn remove_dir<P: AsRef<Path>>(path: P) -> io::Result<()> {
|
||||
///
|
||||
/// See [`fs::remove_file`] and [`fs::remove_dir`].
|
||||
///
|
||||
/// `remove_dir_all` will fail if `remove_dir` or `remove_file` fail on any constituent paths, including the root path.
|
||||
/// As a result, the directory you are deleting must exist, meaning that this function is not idempotent.
|
||||
///
|
||||
/// Consider ignoring the error if validating the removal is not required for your use case.
|
||||
///
|
||||
/// [`fs::remove_file`]: remove_file
|
||||
/// [`fs::remove_dir`]: remove_dir
|
||||
///
|
||||
|
@ -91,10 +91,10 @@ pub use core::prelude::v1::cfg_eval;
|
||||
)]
|
||||
pub use core::prelude::v1::type_ascribe;
|
||||
|
||||
// The file so far is equivalent to src/libcore/prelude/v1.rs,
|
||||
// and below to src/liballoc/prelude.rs.
|
||||
// Those files are duplicated rather than using glob imports
|
||||
// because we want docs to show these re-exports as pointing to within `std`.
|
||||
// The file so far is equivalent to core/src/prelude/v1.rs. It is duplicated
|
||||
// rather than glob imported because we want docs to show these re-exports as
|
||||
// pointing to within `std`.
|
||||
// Below are the items from the alloc crate.
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[doc(no_inline)]
|
||||
|
@ -24,14 +24,14 @@ Then this code snippet will be included in the documentation for `a_func`. This
|
||||
This feature is unstable, so you can enable it by calling Rustdoc with the unstable `rustdoc-scrape-examples` flag:
|
||||
|
||||
```bash
|
||||
cargo doc -Zunstable-options -Zrustdoc-scrape-examples=examples
|
||||
cargo doc -Zunstable-options -Zrustdoc-scrape-examples
|
||||
```
|
||||
|
||||
To enable this feature on [docs.rs](https://docs.rs), add this to your Cargo.toml:
|
||||
|
||||
```toml
|
||||
[package.metadata.docs.rs]
|
||||
cargo-args = ["-Zunstable-options", "-Zrustdoc-scrape-examples=examples"]
|
||||
cargo-args = ["-Zunstable-options", "-Zrustdoc-scrape-examples"]
|
||||
```
|
||||
|
||||
|
||||
|
@ -224,6 +224,7 @@ enum Emit {
|
||||
Metadata,
|
||||
LlvmIr,
|
||||
Asm,
|
||||
LinkArgsAsm,
|
||||
}
|
||||
|
||||
impl<'test> TestCx<'test> {
|
||||
@ -2035,6 +2036,9 @@ impl<'test> TestCx<'test> {
|
||||
Emit::Asm => {
|
||||
rustc.args(&["--emit", "asm"]);
|
||||
}
|
||||
Emit::LinkArgsAsm => {
|
||||
rustc.args(&["-Clink-args=--emit=asm"]);
|
||||
}
|
||||
}
|
||||
|
||||
if !is_rustdoc {
|
||||
@ -2328,11 +2332,15 @@ impl<'test> TestCx<'test> {
|
||||
emit = Emit::Asm;
|
||||
}
|
||||
|
||||
Some("bpf-linker") => {
|
||||
emit = Emit::LinkArgsAsm;
|
||||
}
|
||||
|
||||
Some("ptx-linker") => {
|
||||
// No extra flags needed.
|
||||
}
|
||||
|
||||
Some(_) => self.fatal("unknown 'assembly-output' header"),
|
||||
Some(header) => self.fatal(&format!("unknown 'assembly-output' header: {header}")),
|
||||
None => self.fatal("missing 'assembly-output' header"),
|
||||
}
|
||||
|
||||
|
41
tests/ui/coherence/coherence-overlap-negative-impls.rs
Normal file
41
tests/ui/coherence/coherence-overlap-negative-impls.rs
Normal file
@ -0,0 +1,41 @@
|
||||
// check-pass
|
||||
// known-bug: #74629
|
||||
|
||||
// Should fail. The `0` and `1` impls overlap, violating coherence. Eg, with
|
||||
// `T = Test, F = ()`, all bounds are true, making both impls applicable.
|
||||
// `Test: Fold<Nil>`, `Test: Fold<()>` are true because of `2`.
|
||||
// `Is<Test>: NotNil` is true because of `auto trait` and lack of negative impl.
|
||||
|
||||
#![feature(negative_impls)]
|
||||
#![feature(auto_traits)]
|
||||
|
||||
struct Nil;
|
||||
struct Cons<H>(H);
|
||||
struct Test;
|
||||
|
||||
trait Fold<F> {}
|
||||
|
||||
impl<T, F> Fold<F> for Cons<T> // 0
|
||||
where
|
||||
T: Fold<Nil>,
|
||||
{}
|
||||
|
||||
impl<T, F> Fold<F> for Cons<T> // 1
|
||||
where
|
||||
T: Fold<F>,
|
||||
private::Is<T>: private::NotNil,
|
||||
{}
|
||||
|
||||
impl<F> Fold<F> for Test {} // 2
|
||||
|
||||
mod private {
|
||||
use crate::Nil;
|
||||
|
||||
pub struct Is<T>(T);
|
||||
pub auto trait NotNil {}
|
||||
|
||||
#[allow(suspicious_auto_trait_impls)]
|
||||
impl !NotNil for Is<Nil> {}
|
||||
}
|
||||
|
||||
fn main() {}
|
35
tests/ui/specialization/issue-40582.rs
Normal file
35
tests/ui/specialization/issue-40582.rs
Normal file
@ -0,0 +1,35 @@
|
||||
// check-pass
|
||||
// known-bug: #40582
|
||||
|
||||
// Should fail. Should not be possible to implement `make_static`.
|
||||
|
||||
#![feature(specialization)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
trait FromRef<'a, T: ?Sized> {
|
||||
fn from_ref(r: &'a T) -> Self;
|
||||
}
|
||||
|
||||
impl<'a, T: ?Sized> FromRef<'a, T> for &'a T {
|
||||
fn from_ref(r: &'a T) -> Self {
|
||||
r
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: ?Sized, R> FromRef<'a, T> for R {
|
||||
default fn from_ref(_: &'a T) -> Self {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
fn make_static<T: ?Sized>(data: &T) -> &'static T {
|
||||
fn helper<T: ?Sized, R>(data: &T) -> R {
|
||||
R::from_ref(data)
|
||||
}
|
||||
helper(data)
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let s = "specialization".to_owned();
|
||||
println!("{:?}", make_static(s.as_str()));
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
// check-pass
|
||||
// known-bug: #105782
|
||||
|
||||
// Should fail. Default items completely drop candidates instead of ambiguity,
|
||||
// which is unsound during coherence, since coherence requires completeness.
|
||||
|
||||
#![feature(specialization)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
trait Default {
|
||||
type Id;
|
||||
}
|
||||
|
||||
impl<T> Default for T {
|
||||
default type Id = T;
|
||||
}
|
||||
|
||||
trait Overlap {
|
||||
type Assoc;
|
||||
}
|
||||
|
||||
impl Overlap for u32 {
|
||||
type Assoc = usize;
|
||||
}
|
||||
|
||||
impl Overlap for <u32 as Default>::Id {
|
||||
type Assoc = Box<usize>;
|
||||
}
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,46 @@
|
||||
// check-pass
|
||||
// known-bug: #49682
|
||||
// edition:2021
|
||||
|
||||
// Should fail. Keeping references to thread local statics can result in a
|
||||
// use-after-free.
|
||||
|
||||
#![feature(thread_local)]
|
||||
|
||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
use std::thread;
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[thread_local]
|
||||
static FOO: AtomicUsize = AtomicUsize::new(0);
|
||||
|
||||
#[allow(dead_code)]
|
||||
async fn bar() {}
|
||||
|
||||
#[allow(dead_code)]
|
||||
async fn foo() {
|
||||
let r = &FOO;
|
||||
bar().await;
|
||||
r.load(Ordering::SeqCst);
|
||||
}
|
||||
|
||||
fn main() {
|
||||
// &FOO = 0x7fd1e9cbf6d0
|
||||
_ = thread::spawn(|| {
|
||||
let g = foo();
|
||||
println!("&FOO = {:p}", &FOO);
|
||||
g
|
||||
})
|
||||
.join()
|
||||
.unwrap();
|
||||
|
||||
// &FOO = 0x7fd1e9cc0f50
|
||||
println!("&FOO = {:p}", &FOO);
|
||||
|
||||
// &FOO = 0x7fd1e9cbf6d0
|
||||
thread::spawn(move || {
|
||||
println!("&FOO = {:p}", &FOO);
|
||||
})
|
||||
.join()
|
||||
.unwrap();
|
||||
}
|
Loading…
Reference in New Issue
Block a user