Skip to content

Commit d525233

Browse files
committed
Add check for non-principal trait casts
1 parent 634f912 commit d525233

File tree

4 files changed

+274
-14
lines changed

4 files changed

+274
-14
lines changed

compiler/rustc_borrowck/src/type_check/mod.rs

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1563,15 +1563,6 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
15631563
//
15641564
// We must not allow freely casting lifetime bounds of dyn-types as it
15651565
// may allow for inaccessible VTable methods being callable: #136702
1566-
//
1567-
// We don't enforce this for casts of principal-less dyn types as their
1568-
// VTables do not contain any functions with `Self: 'a` bounds that
1569-
// could start holding after a pointer cast.
1570-
//
1571-
// We also don't enforce this for casts of pointers to pointers to dyn
1572-
// types. E.g. `*mut *mut dyn Trait + 'a -> *mut *mut dyn Trait +
1573-
// 'static` is allowed. This is fine because there is no actual VTable
1574-
// in play.
15751566
self.sub_types(
15761567
src_obj,
15771568
dst_obj,
@@ -1583,6 +1574,28 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
15831574
},
15841575
)
15851576
.unwrap();
1577+
} else if let ty::Dynamic(src_tty, src_lt) =
1578+
*self.struct_tail(src.ty, location).kind()
1579+
&& let ty::Dynamic(dst_tty, dst_lt) =
1580+
*self.struct_tail(dst.ty, location).kind()
1581+
&& src_tty.principal().is_none()
1582+
&& dst_tty.principal().is_none()
1583+
{
1584+
// The principalless (no non-auto traits) case:
1585+
// You can only cast `dyn Send + 'long` to `dyn Send + 'short`.
1586+
self.constraints.outlives_constraints.push(OutlivesConstraint {
1587+
sup: src_lt.as_var(),
1588+
sub: dst_lt.as_var(),
1589+
locations: location.to_locations(),
1590+
span: location.to_locations().span(self.body),
1591+
category: ConstraintCategory::Cast {
1592+
is_raw_ptr_dyn_type_cast: true,
1593+
is_implicit_coercion: false,
1594+
unsize_to: None,
1595+
},
1596+
variance_info: ty::VarianceDiagInfo::default(),
1597+
from_closure: false,
1598+
});
15861599
}
15871600
}
15881601
CastKind::Transmute => {
Lines changed: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,49 @@
1-
//@ check-pass
21
// Test cases involving principal-less traits (dyn Send without a primary trait).
32

4-
fn lifetime_cast_send<'a, 'b>(a: *mut (dyn Send + 'a)) -> *mut (dyn Send + 'b) {
5-
a as _
3+
struct Wrapper<T: ?Sized>(T);
4+
5+
// Cast to same auto trait
6+
7+
fn unprincipled<'a, 'b>(x: *mut (dyn Send + 'a)) -> *mut (dyn Send + 'b) {
8+
x as _
9+
//~^ ERROR: lifetime may not live long enough
10+
}
11+
12+
fn unprincipled_static<'a>(x: *mut (dyn Send + 'a)) -> *mut (dyn Send + 'static) {
13+
x as _
14+
//~^ ERROR: lifetime may not live long enough
15+
}
16+
17+
fn unprincipled_wrap<'a, 'b>(x: *mut (dyn Send + 'a)) -> *mut Wrapper<dyn Send + 'b> {
18+
x as _
19+
//~^ ERROR: lifetime may not live long enough
20+
}
21+
22+
fn unprincipled_wrap_static<'a>(x: *mut (dyn Send + 'a)) -> *mut Wrapper<dyn Send + 'static> {
23+
x as _
24+
//~^ ERROR: lifetime may not live long enough
25+
}
26+
27+
// Cast to different auto trait
28+
29+
fn unprincipled2<'a, 'b>(x: *mut (dyn Send + 'a)) -> *mut (dyn Sync + 'b) {
30+
x as _
31+
//~^ ERROR: lifetime may not live long enough
32+
}
33+
34+
fn unprincipled2_static<'a>(x: *mut (dyn Send + 'a)) -> *mut (dyn Sync + 'static) {
35+
x as _
36+
//~^ ERROR: lifetime may not live long enough
37+
}
38+
39+
fn unprincipled_wrap2<'a, 'b>(x: *mut (dyn Send + 'a)) -> *mut Wrapper<dyn Sync + 'b> {
40+
x as _
41+
//~^ ERROR: lifetime may not live long enough
42+
}
43+
44+
fn unprincipled_wrap2_static<'a>(x: *mut (dyn Send + 'a)) -> *mut Wrapper<dyn Sync + 'static> {
45+
x as _
46+
//~^ ERROR: lifetime may not live long enough
647
}
748

849
fn main() {}
Lines changed: 206 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,206 @@
1+
error: lifetime may not live long enough
2+
--> $DIR/ptr-to-ptr-principalless.rs:8:5
3+
|
4+
LL | fn unprincipled<'a, 'b>(x: *mut (dyn Send + 'a)) -> *mut (dyn Send + 'b) {
5+
| -- -- lifetime `'b` defined here
6+
| |
7+
| lifetime `'a` defined here
8+
LL | x as _
9+
| ^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
10+
|
11+
= help: consider adding the following bound: `'a: 'b`
12+
= note: requirement occurs because of a mutable pointer to `dyn Send`
13+
= note: mutable pointers are invariant over their type parameter
14+
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
15+
note: raw pointer casts of trait objects do not cast away lifetimes
16+
--> $DIR/ptr-to-ptr-principalless.rs:8:5
17+
|
18+
LL | x as _
19+
| ^^^^^^
20+
= note: this was previously accepted by the compiler but was changed recently
21+
= help: see <https://github.com/rust-lang/rust/issues/141402> for more information
22+
23+
error: lifetime may not live long enough
24+
--> $DIR/ptr-to-ptr-principalless.rs:13:5
25+
|
26+
LL | fn unprincipled_static<'a>(x: *mut (dyn Send + 'a)) -> *mut (dyn Send + 'static) {
27+
| -- lifetime `'a` defined here
28+
LL | x as _
29+
| ^^^^^^ returning this value requires that `'a` must outlive `'static`
30+
|
31+
= note: requirement occurs because of a mutable pointer to `dyn Send`
32+
= note: mutable pointers are invariant over their type parameter
33+
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
34+
note: raw pointer casts of trait objects do not cast away lifetimes
35+
--> $DIR/ptr-to-ptr-principalless.rs:13:5
36+
|
37+
LL | x as _
38+
| ^^^^^^
39+
= note: this was previously accepted by the compiler but was changed recently
40+
= help: see <https://github.com/rust-lang/rust/issues/141402> for more information
41+
help: consider changing the trait object's explicit `'static` bound to the lifetime of argument `x`
42+
|
43+
LL - fn unprincipled_static<'a>(x: *mut (dyn Send + 'a)) -> *mut (dyn Send + 'static) {
44+
LL + fn unprincipled_static<'a>(x: *mut (dyn Send + 'a)) -> *mut (dyn Send + 'a) {
45+
|
46+
help: alternatively, add an explicit `'static` bound to this reference
47+
|
48+
LL - fn unprincipled_static<'a>(x: *mut (dyn Send + 'a)) -> *mut (dyn Send + 'static) {
49+
LL + fn unprincipled_static<'a>(x: *mut (dyn Send + 'static)) -> *mut (dyn Send + 'static) {
50+
|
51+
52+
error: lifetime may not live long enough
53+
--> $DIR/ptr-to-ptr-principalless.rs:18:5
54+
|
55+
LL | fn unprincipled_wrap<'a, 'b>(x: *mut (dyn Send + 'a)) -> *mut Wrapper<dyn Send + 'b> {
56+
| -- -- lifetime `'b` defined here
57+
| |
58+
| lifetime `'a` defined here
59+
LL | x as _
60+
| ^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
61+
|
62+
= help: consider adding the following bound: `'a: 'b`
63+
= note: requirement occurs because of a mutable pointer to `Wrapper<dyn Send>`
64+
= note: mutable pointers are invariant over their type parameter
65+
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
66+
note: raw pointer casts of trait objects do not cast away lifetimes
67+
--> $DIR/ptr-to-ptr-principalless.rs:18:5
68+
|
69+
LL | x as _
70+
| ^^^^^^
71+
= note: this was previously accepted by the compiler but was changed recently
72+
= help: see <https://github.com/rust-lang/rust/issues/141402> for more information
73+
74+
error: lifetime may not live long enough
75+
--> $DIR/ptr-to-ptr-principalless.rs:23:5
76+
|
77+
LL | fn unprincipled_wrap_static<'a>(x: *mut (dyn Send + 'a)) -> *mut Wrapper<dyn Send + 'static> {
78+
| -- lifetime `'a` defined here
79+
LL | x as _
80+
| ^^^^^^ returning this value requires that `'a` must outlive `'static`
81+
|
82+
= note: requirement occurs because of a mutable pointer to `Wrapper<dyn Send>`
83+
= note: mutable pointers are invariant over their type parameter
84+
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
85+
note: raw pointer casts of trait objects do not cast away lifetimes
86+
--> $DIR/ptr-to-ptr-principalless.rs:23:5
87+
|
88+
LL | x as _
89+
| ^^^^^^
90+
= note: this was previously accepted by the compiler but was changed recently
91+
= help: see <https://github.com/rust-lang/rust/issues/141402> for more information
92+
help: consider changing the trait object's explicit `'static` bound to the lifetime of argument `x`
93+
|
94+
LL - fn unprincipled_wrap_static<'a>(x: *mut (dyn Send + 'a)) -> *mut Wrapper<dyn Send + 'static> {
95+
LL + fn unprincipled_wrap_static<'a>(x: *mut (dyn Send + 'a)) -> *mut Wrapper<dyn Send + 'a> {
96+
|
97+
help: alternatively, add an explicit `'static` bound to this reference
98+
|
99+
LL - fn unprincipled_wrap_static<'a>(x: *mut (dyn Send + 'a)) -> *mut Wrapper<dyn Send + 'static> {
100+
LL + fn unprincipled_wrap_static<'a>(x: *mut (dyn Send + 'static)) -> *mut Wrapper<dyn Send + 'static> {
101+
|
102+
103+
error: lifetime may not live long enough
104+
--> $DIR/ptr-to-ptr-principalless.rs:30:5
105+
|
106+
LL | fn unprincipled2<'a, 'b>(x: *mut (dyn Send + 'a)) -> *mut (dyn Sync + 'b) {
107+
| -- -- lifetime `'b` defined here
108+
| |
109+
| lifetime `'a` defined here
110+
LL | x as _
111+
| ^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
112+
|
113+
= help: consider adding the following bound: `'a: 'b`
114+
= note: requirement occurs because of a mutable pointer to `dyn Sync`
115+
= note: mutable pointers are invariant over their type parameter
116+
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
117+
note: raw pointer casts of trait objects do not cast away lifetimes
118+
--> $DIR/ptr-to-ptr-principalless.rs:30:5
119+
|
120+
LL | x as _
121+
| ^^^^^^
122+
= note: this was previously accepted by the compiler but was changed recently
123+
= help: see <https://github.com/rust-lang/rust/issues/141402> for more information
124+
125+
error: lifetime may not live long enough
126+
--> $DIR/ptr-to-ptr-principalless.rs:35:5
127+
|
128+
LL | fn unprincipled2_static<'a>(x: *mut (dyn Send + 'a)) -> *mut (dyn Sync + 'static) {
129+
| -- lifetime `'a` defined here
130+
LL | x as _
131+
| ^^^^^^ returning this value requires that `'a` must outlive `'static`
132+
|
133+
= note: requirement occurs because of a mutable pointer to `dyn Sync`
134+
= note: mutable pointers are invariant over their type parameter
135+
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
136+
note: raw pointer casts of trait objects do not cast away lifetimes
137+
--> $DIR/ptr-to-ptr-principalless.rs:35:5
138+
|
139+
LL | x as _
140+
| ^^^^^^
141+
= note: this was previously accepted by the compiler but was changed recently
142+
= help: see <https://github.com/rust-lang/rust/issues/141402> for more information
143+
help: consider changing the trait object's explicit `'static` bound to the lifetime of argument `x`
144+
|
145+
LL - fn unprincipled2_static<'a>(x: *mut (dyn Send + 'a)) -> *mut (dyn Sync + 'static) {
146+
LL + fn unprincipled2_static<'a>(x: *mut (dyn Send + 'a)) -> *mut (dyn Sync + 'a) {
147+
|
148+
help: alternatively, add an explicit `'static` bound to this reference
149+
|
150+
LL - fn unprincipled2_static<'a>(x: *mut (dyn Send + 'a)) -> *mut (dyn Sync + 'static) {
151+
LL + fn unprincipled2_static<'a>(x: *mut (dyn Send + 'static)) -> *mut (dyn Sync + 'static) {
152+
|
153+
154+
error: lifetime may not live long enough
155+
--> $DIR/ptr-to-ptr-principalless.rs:40:5
156+
|
157+
LL | fn unprincipled_wrap2<'a, 'b>(x: *mut (dyn Send + 'a)) -> *mut Wrapper<dyn Sync + 'b> {
158+
| -- -- lifetime `'b` defined here
159+
| |
160+
| lifetime `'a` defined here
161+
LL | x as _
162+
| ^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
163+
|
164+
= help: consider adding the following bound: `'a: 'b`
165+
= note: requirement occurs because of a mutable pointer to `Wrapper<dyn Sync>`
166+
= note: mutable pointers are invariant over their type parameter
167+
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
168+
note: raw pointer casts of trait objects do not cast away lifetimes
169+
--> $DIR/ptr-to-ptr-principalless.rs:40:5
170+
|
171+
LL | x as _
172+
| ^^^^^^
173+
= note: this was previously accepted by the compiler but was changed recently
174+
= help: see <https://github.com/rust-lang/rust/issues/141402> for more information
175+
176+
error: lifetime may not live long enough
177+
--> $DIR/ptr-to-ptr-principalless.rs:45:5
178+
|
179+
LL | fn unprincipled_wrap2_static<'a>(x: *mut (dyn Send + 'a)) -> *mut Wrapper<dyn Sync + 'static> {
180+
| -- lifetime `'a` defined here
181+
LL | x as _
182+
| ^^^^^^ returning this value requires that `'a` must outlive `'static`
183+
|
184+
= note: requirement occurs because of a mutable pointer to `Wrapper<dyn Sync>`
185+
= note: mutable pointers are invariant over their type parameter
186+
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
187+
note: raw pointer casts of trait objects do not cast away lifetimes
188+
--> $DIR/ptr-to-ptr-principalless.rs:45:5
189+
|
190+
LL | x as _
191+
| ^^^^^^
192+
= note: this was previously accepted by the compiler but was changed recently
193+
= help: see <https://github.com/rust-lang/rust/issues/141402> for more information
194+
help: consider changing the trait object's explicit `'static` bound to the lifetime of argument `x`
195+
|
196+
LL - fn unprincipled_wrap2_static<'a>(x: *mut (dyn Send + 'a)) -> *mut Wrapper<dyn Sync + 'static> {
197+
LL + fn unprincipled_wrap2_static<'a>(x: *mut (dyn Send + 'a)) -> *mut Wrapper<dyn Sync + 'a> {
198+
|
199+
help: alternatively, add an explicit `'static` bound to this reference
200+
|
201+
LL - fn unprincipled_wrap2_static<'a>(x: *mut (dyn Send + 'a)) -> *mut Wrapper<dyn Sync + 'static> {
202+
LL + fn unprincipled_wrap2_static<'a>(x: *mut (dyn Send + 'static)) -> *mut Wrapper<dyn Sync + 'static> {
203+
|
204+
205+
error: aborting due to 8 previous errors
206+

tests/ui/cast/ptr-to-trait-obj-ok.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ fn cast_away_higher_ranked<'a>(x: *mut dyn for<'b> Trait<'b>) -> *mut dyn Trait<
1616
x as _
1717
}
1818

19-
fn unprincipled<'a, 'b>(x: *mut (dyn Send + 'a)) -> *mut (dyn Sync + 'b) {
19+
fn unprincipled<'a: 'b, 'b>(x: *mut (dyn Send + 'a)) -> *mut (dyn Sync + 'b) {
2020
x as _
2121
}
2222

@@ -41,7 +41,7 @@ fn cast_away_higher_ranked_wrap<'a>(x: *mut dyn for<'b> Trait<'b>) -> *mut Wrapp
4141
x as _
4242
}
4343

44-
fn unprincipled_wrap<'a, 'b>(x: *mut (dyn Send + 'a)) -> *mut Wrapper<dyn Sync + 'b> {
44+
fn unprincipled_wrap<'a: 'b, 'b>(x: *mut (dyn Send + 'a)) -> *mut Wrapper<dyn Sync + 'b> {
4545
x as _
4646
}
4747

0 commit comments

Comments
 (0)