Skip to content

Commit 1091a7a

Browse files
authored
Rollup merge of rust-lang#110878 - whtahy:105107/known-bug-tests-for-unsound-issues, r=jackh726
Add `known-bug` tests for 4 unsound issues This PR adds `known-bug` tests for 4 unsound issues as part of rust-lang#105107 - rust-lang#40582 - rust-lang#49682 - rust-lang#74629 - rust-lang#105782
2 parents d3c43d0 + fcf8468 commit 1091a7a

File tree

4 files changed

+152
-0
lines changed

4 files changed

+152
-0
lines changed
+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// check-pass
2+
// known-bug: #74629
3+
4+
// Should fail. The `0` and `1` impls overlap, violating coherence. Eg, with
5+
// `T = Test, F = ()`, all bounds are true, making both impls applicable.
6+
// `Test: Fold<Nil>`, `Test: Fold<()>` are true because of `2`.
7+
// `Is<Test>: NotNil` is true because of `auto trait` and lack of negative impl.
8+
9+
#![feature(negative_impls)]
10+
#![feature(auto_traits)]
11+
12+
struct Nil;
13+
struct Cons<H>(H);
14+
struct Test;
15+
16+
trait Fold<F> {}
17+
18+
impl<T, F> Fold<F> for Cons<T> // 0
19+
where
20+
T: Fold<Nil>,
21+
{}
22+
23+
impl<T, F> Fold<F> for Cons<T> // 1
24+
where
25+
T: Fold<F>,
26+
private::Is<T>: private::NotNil,
27+
{}
28+
29+
impl<F> Fold<F> for Test {} // 2
30+
31+
mod private {
32+
use crate::Nil;
33+
34+
pub struct Is<T>(T);
35+
pub auto trait NotNil {}
36+
37+
#[allow(suspicious_auto_trait_impls)]
38+
impl !NotNil for Is<Nil> {}
39+
}
40+
41+
fn main() {}

Diff for: tests/ui/specialization/issue-40582.rs

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// check-pass
2+
// known-bug: #40582
3+
4+
// Should fail. Should not be possible to implement `make_static`.
5+
6+
#![feature(specialization)]
7+
#![allow(incomplete_features)]
8+
9+
trait FromRef<'a, T: ?Sized> {
10+
fn from_ref(r: &'a T) -> Self;
11+
}
12+
13+
impl<'a, T: ?Sized> FromRef<'a, T> for &'a T {
14+
fn from_ref(r: &'a T) -> Self {
15+
r
16+
}
17+
}
18+
19+
impl<'a, T: ?Sized, R> FromRef<'a, T> for R {
20+
default fn from_ref(_: &'a T) -> Self {
21+
unimplemented!()
22+
}
23+
}
24+
25+
fn make_static<T: ?Sized>(data: &T) -> &'static T {
26+
fn helper<T: ?Sized, R>(data: &T) -> R {
27+
R::from_ref(data)
28+
}
29+
helper(data)
30+
}
31+
32+
fn main() {
33+
let s = "specialization".to_owned();
34+
println!("{:?}", make_static(s.as_str()));
35+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// check-pass
2+
// known-bug: #105782
3+
4+
// Should fail. Default items completely drop candidates instead of ambiguity,
5+
// which is unsound during coherence, since coherence requires completeness.
6+
7+
#![feature(specialization)]
8+
#![allow(incomplete_features)]
9+
10+
trait Default {
11+
type Id;
12+
}
13+
14+
impl<T> Default for T {
15+
default type Id = T;
16+
}
17+
18+
trait Overlap {
19+
type Assoc;
20+
}
21+
22+
impl Overlap for u32 {
23+
type Assoc = usize;
24+
}
25+
26+
impl Overlap for <u32 as Default>::Id {
27+
type Assoc = Box<usize>;
28+
}
29+
30+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// check-pass
2+
// known-bug: #49682
3+
// edition:2021
4+
5+
// Should fail. Keeping references to thread local statics can result in a
6+
// use-after-free.
7+
8+
#![feature(thread_local)]
9+
10+
use std::sync::atomic::{AtomicUsize, Ordering};
11+
use std::thread;
12+
13+
#[allow(dead_code)]
14+
#[thread_local]
15+
static FOO: AtomicUsize = AtomicUsize::new(0);
16+
17+
#[allow(dead_code)]
18+
async fn bar() {}
19+
20+
#[allow(dead_code)]
21+
async fn foo() {
22+
let r = &FOO;
23+
bar().await;
24+
r.load(Ordering::SeqCst);
25+
}
26+
27+
fn main() {
28+
// &FOO = 0x7fd1e9cbf6d0
29+
_ = thread::spawn(|| {
30+
let g = foo();
31+
println!("&FOO = {:p}", &FOO);
32+
g
33+
})
34+
.join()
35+
.unwrap();
36+
37+
// &FOO = 0x7fd1e9cc0f50
38+
println!("&FOO = {:p}", &FOO);
39+
40+
// &FOO = 0x7fd1e9cbf6d0
41+
thread::spawn(move || {
42+
println!("&FOO = {:p}", &FOO);
43+
})
44+
.join()
45+
.unwrap();
46+
}

0 commit comments

Comments
 (0)