From e7c53d4ca22cbc51bdd2657a26575f306df97cb9 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Fri, 13 Oct 2017 21:55:11 +0200 Subject: [PATCH] Use pointer casts instead of tramsutes to raw::TraitObject MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- components/layout/flow.rs | 24 ++++++++++-------------- components/layout/lib.rs | 9 --------- tests/unit/layout/lib.rs | 29 ----------------------------- 3 files changed, 10 insertions(+), 52 deletions(-) diff --git a/components/layout/flow.rs b/components/layout/flow.rs index fbcf78669316..8dad21045231 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; @@ -452,10 +452,9 @@ pub trait Flow: fmt::Debug + Sync + Send + 'static { #[inline(always)] #[allow(unsafe_code)] pub fn base(this: &T) -> &BaseFlow { - unsafe { - let obj = mem::transmute::<&&T, &::TraitObject>(&this); - mem::transmute::<*mut (), &BaseFlow>(obj.data) - } + let ptr: *const T = this; + let ptr = ptr as *const BaseFlow; + unsafe { &*ptr } } /// Iterates over the children of this immutable flow. @@ -466,10 +465,9 @@ pub fn child_iter<'a>(flow: &'a Flow) -> FlowListIterator { #[inline(always)] #[allow(unsafe_code)] pub fn mut_base(this: &mut T) -> &mut BaseFlow { - unsafe { - let obj = mem::transmute::<&&mut T, &::TraitObject>(&this); - mem::transmute::<*mut (), &mut BaseFlow>(obj.data) - } + let ptr: *mut T = this; + let ptr = ptr as *mut BaseFlow; + unsafe { &mut *ptr } } /// Iterates over the children of this flow. @@ -1419,11 +1417,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) } } diff --git a/components/layout/lib.rs b/components/layout/lib.rs index 1e48a2b5a6d4..f9c3cbeda2bb 100644 --- a/components/layout/lib.rs +++ b/components/layout/lib.rs @@ -90,12 +90,3 @@ pub use self::data::LayoutData; // We can't use servo_arc for everything in layout, because the Flow stuff uses // weak references. use servo_arc::Arc as ServoArc; - -/// Stable copy of std::raw::TraitObject -/// test/unit/layout/lib.rs asserts that the memory layout matches. -#[repr(C)] -#[derive(Clone, Copy)] -pub struct TraitObject { - pub data: *mut (), - pub vtable: *mut (), -} diff --git a/tests/unit/layout/lib.rs b/tests/unit/layout/lib.rs index bc1d9dfd464d..a763135260a5 100644 --- a/tests/unit/layout/lib.rs +++ b/tests/unit/layout/lib.rs @@ -2,36 +2,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#![feature(raw)] - extern crate layout; #[macro_use] extern crate size_of_test; #[cfg(all(test, target_pointer_width = "64"))] mod size_of; - -use std::mem; -use std::ptr; -use std::raw; - -#[test] -fn test_trait_object_layout() { - assert_eq!(mem::size_of::(), mem::size_of::()); - let null: *mut () = ptr::null_mut(); - let a = raw::TraitObject { - data: null, - vtable: null, - }; - let b = layout::TraitObject { - data: null, - vtable: null, - }; - - fn offset(struct_: &T, field: &U) -> usize { - let addr_struct = struct_ as *const T as usize; - let addr_field = field as *const U as usize; - addr_field - addr_struct - } - - assert_eq!(offset(&a, &a.data), offset(&b, &b.data)); - assert_eq!(offset(&a, &a.vtable), offset(&b, &b.vtable)); -}