Skip to content

Commit 9fcb8bc

Browse files
committed
reviews
1 parent 9216ccd commit 9fcb8bc

File tree

4 files changed

+90
-69
lines changed

4 files changed

+90
-69
lines changed

compiler/rustc_borrowck/src/type_check/mod.rs

Lines changed: 73 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -1533,76 +1533,81 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
15331533
*self.struct_tail(src.ty, location).kind()
15341534
&& let ty::Dynamic(dst_tty, dst_lt) =
15351535
*self.struct_tail(dst.ty, location).kind()
1536-
&& src_tty.principal().is_some()
1537-
&& dst_tty.principal().is_some()
15381536
{
1539-
// This checks (lifetime part of) vtable validity for pointer casts,
1540-
// which is irrelevant when there are aren't principal traits on
1541-
// both sides (aka only auto traits).
1542-
//
1543-
// Note that other checks (such as denying `dyn Send` -> `dyn
1544-
// Debug`) are in `rustc_hir_typeck`.
1545-
1546-
// Remove auto traits.
1547-
// Auto trait checks are handled in `rustc_hir_typeck`.
1548-
let src_obj = Ty::new_dynamic(
1549-
tcx,
1550-
tcx.mk_poly_existential_predicates(
1551-
&src_tty.without_auto_traits().collect::<Vec<_>>(),
1552-
),
1553-
src_lt,
1554-
);
1555-
let dst_obj = Ty::new_dynamic(
1556-
tcx,
1557-
tcx.mk_poly_existential_predicates(
1558-
&dst_tty.without_auto_traits().collect::<Vec<_>>(),
1537+
match (src_tty.principal(), dst_tty.principal()) {
1538+
(Some(_), Some(_)) => {
1539+
// This checks (lifetime part of) vtable validity for pointer casts,
1540+
// which is irrelevant when there are aren't principal traits on
1541+
// both sides (aka only auto traits).
1542+
//
1543+
// Note that other checks (such as denying `dyn Send` -> `dyn
1544+
// Debug`) are in `rustc_hir_typeck`.
1545+
1546+
// Remove auto traits.
1547+
// Auto trait checks are handled in `rustc_hir_typeck`.
1548+
let src_obj = Ty::new_dynamic(
1549+
tcx,
1550+
tcx.mk_poly_existential_predicates(
1551+
&src_tty.without_auto_traits().collect::<Vec<_>>(),
1552+
),
1553+
src_lt,
1554+
);
1555+
let dst_obj = Ty::new_dynamic(
1556+
tcx,
1557+
tcx.mk_poly_existential_predicates(
1558+
&dst_tty.without_auto_traits().collect::<Vec<_>>(),
1559+
),
1560+
dst_lt,
1561+
);
1562+
1563+
debug!(?src_tty, ?dst_tty, ?src_obj, ?dst_obj);
1564+
1565+
// Trait parameters are invariant, the only part that actually has
1566+
// subtyping here is the lifetime bound of the dyn-type.
1567+
//
1568+
// For example in `dyn Trait<'a> + 'b <: dyn Trait<'c> + 'd` we would
1569+
// require that `'a == 'c` but only that `'b: 'd`.
1570+
//
1571+
// We must not allow freely casting lifetime bounds of dyn-types as it
1572+
// may allow for inaccessible VTable methods being callable: #136702
1573+
self.sub_types(
1574+
src_obj,
1575+
dst_obj,
1576+
location.to_locations(),
1577+
ConstraintCategory::Cast {
1578+
is_raw_ptr_dyn_type_cast: true,
1579+
is_implicit_coercion: false,
1580+
unsize_to: None,
1581+
},
1582+
)
1583+
.unwrap();
1584+
}
1585+
(None, None) => {
1586+
// The principalless (no non-auto traits) case:
1587+
// You can only cast `dyn Send + 'long` to `dyn Send + 'short`.
1588+
self.constraints.outlives_constraints.push(
1589+
OutlivesConstraint {
1590+
sup: src_lt.as_var(),
1591+
sub: dst_lt.as_var(),
1592+
locations: location.to_locations(),
1593+
span: location.to_locations().span(self.body),
1594+
category: ConstraintCategory::Cast {
1595+
is_raw_ptr_dyn_type_cast: true,
1596+
is_implicit_coercion: false,
1597+
unsize_to: None,
1598+
},
1599+
variance_info: ty::VarianceDiagInfo::default(),
1600+
from_closure: false,
1601+
},
1602+
);
1603+
}
1604+
(None, Some(_)) => bug!(
1605+
"introducing a principal should have errored in HIR typeck"
15591606
),
1560-
dst_lt,
1561-
);
1562-
1563-
debug!(?src_tty, ?dst_tty, ?src_obj, ?dst_obj);
1564-
1565-
// Trait parameters are invariant, the only part that actually has
1566-
// subtyping here is the lifetime bound of the dyn-type.
1567-
//
1568-
// For example in `dyn Trait<'a> + 'b <: dyn Trait<'c> + 'd` we would
1569-
// require that `'a == 'c` but only that `'b: 'd`.
1570-
//
1571-
// We must not allow freely casting lifetime bounds of dyn-types as it
1572-
// may allow for inaccessible VTable methods being callable: #136702
1573-
self.sub_types(
1574-
src_obj,
1575-
dst_obj,
1576-
location.to_locations(),
1577-
ConstraintCategory::Cast {
1578-
is_raw_ptr_dyn_type_cast: true,
1579-
is_implicit_coercion: false,
1580-
unsize_to: None,
1581-
},
1582-
)
1583-
.unwrap();
1584-
} else if let ty::Dynamic(src_tty, src_lt) =
1585-
*self.struct_tail(src.ty, location).kind()
1586-
&& let ty::Dynamic(dst_tty, dst_lt) =
1587-
*self.struct_tail(dst.ty, location).kind()
1588-
&& src_tty.principal().is_none()
1589-
&& dst_tty.principal().is_none()
1590-
{
1591-
// The principalless (no non-auto traits) case:
1592-
// You can only cast `dyn Send + 'long` to `dyn Send + 'short`.
1593-
self.constraints.outlives_constraints.push(OutlivesConstraint {
1594-
sup: src_lt.as_var(),
1595-
sub: dst_lt.as_var(),
1596-
locations: location.to_locations(),
1597-
span: location.to_locations().span(self.body),
1598-
category: ConstraintCategory::Cast {
1599-
is_raw_ptr_dyn_type_cast: true,
1600-
is_implicit_coercion: false,
1601-
unsize_to: None,
1602-
},
1603-
variance_info: ty::VarianceDiagInfo::default(),
1604-
from_closure: false,
1605-
});
1607+
(Some(_), None) => {
1608+
bug!("dropping the principal should have been an unsizing cast")
1609+
}
1610+
}
16061611
}
16071612
}
16081613
CastKind::Transmute => {

tests/ui/cast/ptr-ptr-to-ptr-ptr-different-regions.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
//@ check-pass
22

3+
// We allow extending lifetimes of object types if they are behind two layers
4+
// of pointer indirection (as opposed to one). This is because this is the more
5+
// general case of casting between two sized types (`*mut T as *mut U`).
6+
37
trait Trait {
48
fn foo(&self) {}
59
}

tests/ui/cast/ptr-to-ptr-different-regions.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,15 @@ struct Foo<'a> {
77
}
88

99
fn extend_lifetime_very_very_safely<'a>(v: *const Foo<'a>) -> *const Foo<'static> {
10-
// This should pass because raw pointer casts can do anything they want.
10+
// This should pass because raw pointer casts can do anything they want when
11+
// VTables are not involved
1112
v as *const Foo<'static>
1213
}
1314

1415
trait Trait {}
1516

17+
// We want to forbid this as extending lifetimes on object types may allow for
18+
// uncallable VTable methods to become accessible.
1619
fn assert_static<'a>(ptr: *mut (dyn Trait + 'a)) -> *mut (dyn Trait + 'static) {
1720
ptr as _
1821
//~^ ERROR: lifetime may not live long enough

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,14 @@
11
//@ check-pass
22

3+
// Casting pointers to object types has some special rules in order to
4+
// ensure VTables stay valid. E.g.
5+
// - Cannot introduce new autotraits
6+
// - Cannot extend or shrink lifetimes in trait arguments
7+
// - Cannot extend the lifetime of the object type
8+
//
9+
// This test is a mostly miscellaneous set of examples of casts that do
10+
// uphold these rules
11+
312
trait Trait<'a> {}
413

514
fn remove_auto<'a>(x: *mut (dyn Trait<'a> + Send)) -> *mut dyn Trait<'a> {

0 commit comments

Comments
 (0)