New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
#14902 Write a MIR lint for rooting analysis #20264
Changes from all commits
89177a7
ea0c1d4
011217b
4169308
41f4774
d5eafe0
2f4af72
53ed102
c6d04fa
88a1814
c1e333b
2f767d2
2416333
3c14830
fc4c611
File filter...
Jump to…
| @@ -13,12 +13,13 @@ use std::sync::mpsc::{Receiver, Sender}; | ||
| /// common event loop messages. While this SendableWorkerScriptChan is alive, the associated | ||
| /// Worker object will remain alive. | ||
| #[derive(Clone, JSTraceable)] | ||
| pub struct SendableWorkerScriptChan<T: DomObject> { | ||
| #[must_root] | ||
| pub struct SendableWorkerScriptChan<#[must_root] T: DomObject> { | ||
mrowqa
Author
|
||
| pub sender: Sender<(Trusted<T>, CommonScriptMsg)>, | ||
| pub worker: Trusted<T>, | ||
| } | ||
|
|
||
| impl<T: JSTraceable + DomObject + 'static> ScriptChan for SendableWorkerScriptChan<T> { | ||
| impl<#[must_root] T: JSTraceable + DomObject + 'static> ScriptChan for SendableWorkerScriptChan<T> { | ||
| fn send(&self, msg: CommonScriptMsg) -> Result<(), ()> { | ||
| self.sender.send((self.worker.clone(), msg)).map_err(|_| ()) | ||
| } | ||
| @@ -35,12 +36,13 @@ impl<T: JSTraceable + DomObject + 'static> ScriptChan for SendableWorkerScriptCh | ||
| /// worker event loop messages. While this SendableWorkerScriptChan is alive, the associated | ||
| /// Worker object will remain alive. | ||
| #[derive(Clone, JSTraceable)] | ||
| pub struct WorkerThreadWorkerChan<T: DomObject> { | ||
| #[must_root] | ||
| pub struct WorkerThreadWorkerChan<#[must_root] T: DomObject> { | ||
| pub sender: Sender<(Trusted<T>, WorkerScriptMsg)>, | ||
| pub worker: Trusted<T>, | ||
| } | ||
|
|
||
| impl<T: JSTraceable + DomObject + 'static> ScriptChan for WorkerThreadWorkerChan<T> { | ||
| impl<#[must_root] T: JSTraceable + DomObject + 'static> ScriptChan for WorkerThreadWorkerChan<T> { | ||
| fn send(&self, msg: CommonScriptMsg) -> Result<(), ()> { | ||
| self.sender | ||
| .send((self.worker.clone(), WorkerScriptMsg::Common(msg))) | ||
| @@ -55,7 +57,7 @@ impl<T: JSTraceable + DomObject + 'static> ScriptChan for WorkerThreadWorkerChan | ||
| } | ||
| } | ||
|
|
||
| impl<T: DomObject> ScriptPort for Receiver<(Trusted<T>, WorkerScriptMsg)> { | ||
| impl<#[must_root] T: DomObject> ScriptPort for Receiver<(Trusted<T>, WorkerScriptMsg)> { | ||
| fn recv(&self) -> Result<CommonScriptMsg, ()> { | ||
| match self.recv().map(|(_, msg)| msg) { | ||
| Ok(WorkerScriptMsg::Common(script_msg)) => Ok(script_msg), | ||
| @@ -12,14 +12,15 @@ use style::thread_state::{self, ThreadState}; | ||
| /// This extends the API of `std::cell::RefCell` to allow unsafe access in | ||
| /// certain situations, with dynamic checking in debug builds. | ||
| #[derive(Clone, Debug, Default, MallocSizeOf, PartialEq)] | ||
| pub struct DomRefCell<T> { | ||
| value: RefCell<T>, | ||
| //#[must_root] // TODO should it be #[must_root]? then -> there are usages with #[must_root] types and with normal ones; two different structs for them? or hacking plugin compiler further to mark structure as #[must_root] if it generic type is #[must_root]? | ||
jdm
Member
|
||
| pub struct DomRefCell<#[must_root] T> { | ||
| value: RefCell<T>, // TODO currently a little bit hacky since RefCell is currently on the exception list | ||
| } | ||
|
|
||
| // Functionality specific to Servo's `DomRefCell` type | ||
| // =================================================== | ||
|
|
||
| impl<T> DomRefCell<T> { | ||
| impl<#[must_root] T> DomRefCell<T> { | ||
| /// Return a reference to the contents. | ||
| /// | ||
| /// For use in the layout thread only. | ||
| @@ -47,8 +48,9 @@ impl<T> DomRefCell<T> { | ||
|
|
||
| // Functionality duplicated with `std::cell::RefCell` | ||
| // =================================================== | ||
| impl<T> DomRefCell<T> { | ||
| impl<#[must_root] T> DomRefCell<T> { | ||
| /// Create a new `DomRefCell` containing `value`. | ||
| #[allow(unrooted_must_root)] // TODO don't know if it is okay; T is unrooted argument | ||
| pub fn new(value: T) -> DomRefCell<T> { | ||
| DomRefCell { | ||
| value: RefCell::new(value), | ||
| @@ -62,6 +62,7 @@ use servo_config::opts; | ||
| use std::{char, ffi, ptr, slice}; | ||
|
|
||
| /// A trait to check whether a given `JSObject` implements an IDL interface. | ||
| #[must_root] | ||
mrowqa
Author
|
||
| pub trait IDLInterface { | ||
| /// Returns whether the given DOM class derives that interface. | ||
| fn derives(&'static DOMClass) -> bool; | ||
| @@ -105,7 +106,7 @@ impl<T: Float + FromJSValConvertible<Config=()>> FromJSValConvertible for Finite | ||
| } | ||
| } | ||
|
|
||
| impl <T: DomObject + IDLInterface> FromJSValConvertible for DomRoot<T> { | ||
| impl <#[must_root] T: DomObject + IDLInterface> FromJSValConvertible for DomRoot<T> { | ||
| type Config = (); | ||
|
|
||
| unsafe fn from_jsval(_cx: *mut JSContext, | ||
| @@ -420,7 +421,7 @@ pub unsafe fn private_from_proto_check<F>(mut obj: *mut JSObject, | ||
| } | ||
|
|
||
| /// Get a `*const T` for a DOM object accessible from a `JSObject`. | ||
| pub fn native_from_object<T>(obj: *mut JSObject) -> Result<*const T, ()> | ||
| pub fn native_from_object<#[must_root] T>(obj: *mut JSObject) -> Result<*const T, ()> | ||
| where T: DomObject + IDLInterface | ||
| { | ||
| unsafe { | ||
| @@ -434,15 +435,15 @@ pub fn native_from_object<T>(obj: *mut JSObject) -> Result<*const T, ()> | ||
| /// Returns Err(()) if `obj` is an opaque security wrapper or if the object is | ||
| /// not a reflector for a DOM object of the given type (as defined by the | ||
| /// proto_id and proto_depth). | ||
| pub fn root_from_object<T>(obj: *mut JSObject) -> Result<DomRoot<T>, ()> | ||
| pub fn root_from_object<#[must_root] T>(obj: *mut JSObject) -> Result<DomRoot<T>, ()> | ||
| where T: DomObject + IDLInterface | ||
| { | ||
| native_from_object(obj).map(|ptr| unsafe { DomRoot::from_ref(&*ptr) }) | ||
| } | ||
|
|
||
| /// Get a `*const T` for a DOM object accessible from a `HandleValue`. | ||
| /// Caller is responsible for throwing a JS exception if needed in case of error. | ||
| pub fn native_from_handlevalue<T>(v: HandleValue) -> Result<*const T, ()> | ||
| pub fn native_from_handlevalue<#[must_root] T>(v: HandleValue) -> Result<*const T, ()> | ||
| where T: DomObject + IDLInterface | ||
| { | ||
| if !v.get().is_object() { | ||
| @@ -453,7 +454,7 @@ pub fn native_from_handlevalue<T>(v: HandleValue) -> Result<*const T, ()> | ||
|
|
||
| /// Get a `DomRoot<T>` for a DOM object accessible from a `HandleValue`. | ||
| /// Caller is responsible for throwing a JS exception if needed in case of error. | ||
| pub fn root_from_handlevalue<T>(v: HandleValue) -> Result<DomRoot<T>, ()> | ||
| pub fn root_from_handlevalue<#[must_root] T>(v: HandleValue) -> Result<DomRoot<T>, ()> | ||
| where T: DomObject + IDLInterface | ||
| { | ||
| if !v.get().is_object() { | ||
| @@ -463,13 +464,13 @@ pub fn root_from_handlevalue<T>(v: HandleValue) -> Result<DomRoot<T>, ()> | ||
| } | ||
|
|
||
| /// Get a `DomRoot<T>` for a DOM object accessible from a `HandleObject`. | ||
| pub fn root_from_handleobject<T>(obj: HandleObject) -> Result<DomRoot<T>, ()> | ||
| pub fn root_from_handleobject<#[must_root] T>(obj: HandleObject) -> Result<DomRoot<T>, ()> | ||
| where T: DomObject + IDLInterface | ||
| { | ||
| root_from_object(obj.get()) | ||
| } | ||
|
|
||
| impl<T: DomObject> ToJSValConvertible for DomRoot<T> { | ||
| impl<#[must_root] T: DomObject> ToJSValConvertible for DomRoot<T> { | ||
| unsafe fn to_jsval(&self, cx: *mut JSContext, rval: MutableHandleValue) { | ||
| self.reflector().to_jsval(cx, rval); | ||
| } | ||
| @@ -13,7 +13,7 @@ use std::default::Default; | ||
|
|
||
| /// Create the reflector for a new DOM object and yield ownership to the | ||
| /// reflector. | ||
| pub fn reflect_dom_object<T, U>( | ||
| pub fn reflect_dom_object<#[must_root] T, #[must_root] U>( | ||
jdm
Member
|
||
| obj: Box<T>, | ||
| global: &U, | ||
| wrap_fn: unsafe fn(*mut JSContext, &GlobalScope, Box<T>) -> DomRoot<T>) | ||
| @@ -74,6 +74,7 @@ impl Reflector { | ||
| } | ||
|
|
||
| /// A trait to provide access to the `Reflector` for a DOM object. | ||
| #[must_root] | ||
|
||
| pub trait DomObject: 'static { | ||
| /// Returns the receiver's reflector. | ||
| fn reflector(&self) -> &Reflector; | ||
| @@ -91,6 +92,7 @@ impl DomObject for Reflector { | ||
| } | ||
|
|
||
| /// A trait to initialize the `Reflector` for a DOM object. | ||
| #[must_root] | ||
| pub trait MutDomObject: DomObject { | ||
| /// Initializes the Reflector | ||
| fn init_reflector(&mut self, obj: *mut JSObject); | ||
I'm confused by these changes -
Trusted<T>is a type that does not require rooting (due to the allow_unrooted_interior attribute), so it's not clear why T needs to be marked must_root here.