diff options
author | bors-servo <lbergstrom+bors@mozilla.com> | 2017-10-13 21:43:09 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-10-13 21:43:09 -0500 |
commit | 86a5135ffaa60d4743b6f6950fc395c2615e85ba (patch) | |
tree | ed0e65587ac5c4c5a27dbfeee1c9135bafbbd8ec /components/layout/flow.rs | |
parent | f0b8dad063b459db12ac27d44afff32cd6923d30 (diff) | |
parent | b505c9e94817847e19f22854b2ee4258f66f18d2 (diff) | |
download | servo-86a5135ffaa60d4743b6f6950fc395c2615e85ba.tar.gz servo-86a5135ffaa60d4743b6f6950fc395c2615e85ba.zip |
Auto merge of #18870 - servo:cast, r=KiChjang
Use pointer casts instead of tramsutes to raw::TraitObject
Casting `*const T` to `*const U` with `U: Sized` is allowed even if `T: ?Sized`. This safely extracts the data pointer out of a trait object, without relying on the memory representation of trait objects.
<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/18870)
<!-- Reviewable:end -->
Diffstat (limited to 'components/layout/flow.rs')
-rw-r--r-- | components/layout/flow.rs | 38 |
1 files changed, 21 insertions, 17 deletions
diff --git a/components/layout/flow.rs b/components/layout/flow.rs index fbcf7866931..990e29e0238 100644 --- a/components/layout/flow.rs +++ b/components/layout/flow.rs @@ -44,7 +44,7 @@ use multicol::MulticolFlow; use parallel::FlowParallelInfo; use serde::ser::{Serialize, SerializeStruct, Serializer}; use servo_geometry::{au_rect_to_f32_rect, f32_rect_to_au_rect, max_rect}; -use std::{fmt, mem}; +use std::fmt; use std::iter::Zip; use std::slice::IterMut; use std::sync::Arc; @@ -65,11 +65,19 @@ use table_rowgroup::TableRowGroupFlow; use table_wrapper::TableWrapperFlow; use webrender_api::ClipAndScrollInfo; +/// This marker trait indicates that a type is a struct with `#[repr(C)]` whose first field +/// is of type `BaseFlow` or some type that also implements this trait. +/// +/// In other words, the memory representation of `BaseFlow` must be a prefix +/// of the memory representation of types implementing `HasBaseFlow`. +#[allow(unsafe_code)] +pub unsafe trait HasBaseFlow {} + /// Virtual methods that make up a float context. /// /// Note that virtual methods have a cost; we should not overuse them in Servo. Consider adding /// methods to `ImmutableFlowUtils` or `MutableFlowUtils` before adding more methods here. -pub trait Flow: fmt::Debug + Sync + Send + 'static { +pub trait Flow: HasBaseFlow + fmt::Debug + Sync + Send + 'static { // RTTI // // TODO(pcwalton): Use Rust's RTTI, once that works. @@ -451,11 +459,10 @@ pub trait Flow: fmt::Debug + Sync + Send + 'static { #[inline(always)] #[allow(unsafe_code)] -pub fn base<T: ?Sized + Flow>(this: &T) -> &BaseFlow { - unsafe { - let obj = mem::transmute::<&&T, &::TraitObject>(&this); - mem::transmute::<*mut (), &BaseFlow>(obj.data) - } +pub fn base<T: ?Sized + HasBaseFlow>(this: &T) -> &BaseFlow { + let ptr: *const T = this; + let ptr = ptr as *const BaseFlow; + unsafe { &*ptr } } /// Iterates over the children of this immutable flow. @@ -465,11 +472,10 @@ pub fn child_iter<'a>(flow: &'a Flow) -> FlowListIterator { #[inline(always)] #[allow(unsafe_code)] -pub fn mut_base<T: ?Sized + Flow>(this: &mut T) -> &mut BaseFlow { - unsafe { - let obj = mem::transmute::<&&mut T, &::TraitObject>(&this); - mem::transmute::<*mut (), &mut BaseFlow>(obj.data) - } +pub fn mut_base<T: ?Sized + HasBaseFlow>(this: &mut T) -> &mut BaseFlow { + let ptr: *mut T = this; + let ptr = ptr as *mut BaseFlow; + unsafe { &mut *ptr } } /// Iterates over the children of this flow. @@ -1419,11 +1425,9 @@ impl ContainingBlockLink { pub struct OpaqueFlow(pub usize); impl OpaqueFlow { - #[allow(unsafe_code)] pub fn from_flow(flow: &Flow) -> OpaqueFlow { - unsafe { - let object = mem::transmute::<&Flow, ::TraitObject>(flow); - OpaqueFlow(object.data as usize) - } + let object_ptr: *const Flow = flow; + let data_ptr = object_ptr as *const (); + OpaqueFlow(data_ptr as usize) } } |