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:
bors 2023-04-27 20:42:46 +00:00
commit 1a6ae3d692
23 changed files with 228 additions and 159 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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

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

View File

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

View File

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