diff --git a/components/script/dom/bindings/root.rs b/components/script/dom/bindings/root.rs index 18cb006202..6ac0c41710 100644 --- a/components/script/dom/bindings/root.rs +++ b/components/script/dom/bindings/root.rs @@ -126,7 +126,7 @@ where } /// A rooted reference to a DOM object. -pub type DomRoot = Root>; +pub type DomRoot<#[must_root] T> = Root>; impl DomRoot { /// Cast a DOM object root upwards to one of the interfaces it derives from. diff --git a/components/script_plugins/unrooted_must_root.rs b/components/script_plugins/unrooted_must_root.rs index 2da3884201..7b3113c1b6 100644 --- a/components/script_plugins/unrooted_must_root.rs +++ b/components/script_plugins/unrooted_must_root.rs @@ -193,7 +193,7 @@ impl<'a, 'b, 'tcx> UnrootedCx<'a, 'b, 'tcx> { ret } - fn has_unrooted_generic_substs(&self, did: hir::def_id::DefId, substs: &ty::subst::Substs) -> bool { + fn has_unrooted_generic_substs(&self, did: hir::def_id::DefId, substs: &ty::subst::Substs, st: &mut String) -> bool { let cx = self.late_cx; if cx.tcx.has_attr(did, "allow_unrooted_interior") { @@ -211,22 +211,48 @@ impl<'a, 'b, 'tcx> UnrootedCx<'a, 'b, 'tcx> { return false; } - let generics = cx.tcx.generics_of(did); - for ty_param_def in &generics.types { - // If type has `#[must_root]`, then it is ok to - // give it a must-root type, so just skip. - if cx.tcx.has_attr(ty_param_def.def_id, "must_root") { - continue; - } + let def_path = get_def_path(cx, did); + st.push_str(&def_path.join("::")); + st.push_str(&"\n"); + + // maybe check if some def_path.last() is/not "{{impl}}" + //if cx.tcx.type_of(did).is_trait() { + // return false; + //} + //cx.tcx.type_of(did); +// if let Some(trref) = cx.tcx.impl_trait_ref(did) { +// let mut it = trref.substs.types(); +// it.next().expect("trait is implemented for specific type"); +// for arg_ty in it { +// if self.is_unrooted_ty(arg_ty, false) { +// st.push_str(&" >! "); +// st.push_str(&arg_ty.to_string()); +// return true; +// } +// } +// } +// else { + let generics = cx.tcx.generics_of(did); + for ty_param_def in &generics.types { + // If type has `#[must_root]`, then it is ok to + // give it a must-root type, so just skip. + if cx.tcx.has_attr(ty_param_def.def_id, "must_root") { + continue; + } - let arg_ty = substs.type_at(ty_param_def.index as usize); - if self.is_unrooted_ty(arg_ty, false) { - return true; + let arg_ty = substs.type_at(ty_param_def.index as usize); + if self.is_unrooted_ty(arg_ty, false) { + st.push_str(&" > "); + st.push_str(&arg_ty.to_string()); + return true; + } } - } +// } +// let generics = cx.tcx.generics_of(did); // hackhack + st.push_str(&" par$$ "); match generics.parent { - Some(p_did) => self.has_unrooted_generic_substs(p_did, substs), + Some(p_did) => self.has_unrooted_generic_substs(p_did, substs, st), None => false, } } @@ -251,10 +277,11 @@ impl<'a, 'b, 'tcx> MirVisitor<'tcx> for MirFnVisitor<'a, 'b, 'tcx> { let cx = ur_cx.late_cx; match decl.ty.sty { ty::TyAdt(adt_def, substs) => { + let mut type_info = String::new(); if adt_def.is_box() && self.in_new_function { // Boxes of unrooted types are allowed in new functions. } - else if ur_cx.has_unrooted_generic_substs(adt_def.did, substs) { + else if ur_cx.has_unrooted_generic_substs(adt_def.did, substs, &mut type_info) { cx.span_lint(UNROOTED_MUST_ROOT, decl.source_info.span, "ADT generic type must be rooted.") } }, @@ -270,16 +297,19 @@ impl<'a, 'b, 'tcx> MirVisitor<'tcx> for MirFnVisitor<'a, 'b, 'tcx> { match constant.ty.sty { ty::TyFnDef(callee_def_id, callee_substs) => { let def_path = get_def_path(cx, callee_def_id); + let mut type_info = String::new(); // TODO remove following commented code // cx.span_lint(UNROOTED_MUST_ROOT, constant.span, &def_path.join("::")); // tmp auxiliary call if self.in_new_function && (// match_def_path(cx, callee_def_id, &["alloc", "boxed", "{{impl}}", "new"]) || def_path.last().unwrap().starts_with("new_") || def_path.last().unwrap() == "new") { // "new"-like (constructors) functions are allowed } - else if ur_cx.has_unrooted_generic_substs(callee_def_id, callee_substs) { + else if ur_cx.has_unrooted_generic_substs(callee_def_id, callee_substs, &mut type_info) { // TODO tmp code - delete later - let mut msg = "Callee generic type must be rooted.".to_string(); - msg.push_str(&def_path.join("::")); + let mut msg = "Callee generic type must be rooted.\n".to_string(); + //msg.push_str(&def_path.join("::")); + //msg.push_str(&"\n"); + msg.push_str(&type_info); cx.span_lint(UNROOTED_MUST_ROOT, constant.span, &msg); //cx.span_lint(UNROOTED_MUST_ROOT, constant.span, "Callee generic type must be rooted.") } diff --git a/tests/unit/script_plugins/lib.rs b/tests/unit/script_plugins/lib.rs index 83b5dd4fc4..651b173838 100644 --- a/tests/unit/script_plugins/lib.rs +++ b/tests/unit/script_plugins/lib.rs @@ -7,7 +7,6 @@ pub mod unrooted_must_root { ``` #![feature(plugin)] #![plugin(script_plugins)] - #![feature(generic_param_attrs)] #[derive(Clone, Debug)] // derive should not be checked #[must_root] struct Foo(i32); @@ -71,7 +70,6 @@ pub mod unrooted_must_root { ```compile_fail #![feature(plugin)] #![plugin(script_plugins)] - #![feature(generic_param_attrs)] #[must_root] struct Foo(i32); struct Bar<#[must_root] T>(T); @@ -89,7 +87,6 @@ pub mod unrooted_must_root { ```compile_fail #![feature(plugin)] #![plugin(script_plugins)] - #![feature(generic_param_attrs)] fn foo() { } fn bar<#[must_root] U>() { foo::(); } @@ -103,7 +100,6 @@ pub mod unrooted_must_root { ```compile_fail #![feature(plugin)] #![plugin(script_plugins)] - #![feature(generic_param_attrs)] fn foo<#[must_root] T>() { } fn bar<#[must_root] U>() { @@ -235,7 +231,6 @@ pub mod unrooted_must_root { ```compile_fail #![feature(plugin)] #![plugin(script_plugins)] - #![feature(generic_param_attrs)] #[must_root] struct Foo(i32); struct SomeContainer(T); @@ -259,7 +254,6 @@ pub mod unrooted_must_root { ``` #![feature(plugin)] #![plugin(script_plugins)] - #![feature(generic_param_attrs)] #[must_root] struct Foo(i32); #[allow_unrooted_interior] struct SomeContainer(T); @@ -280,11 +274,35 @@ pub mod unrooted_must_root { */ pub fn allowing_unrooted_interior() {} + /** + ``` + #![feature(plugin)] + #![plugin(script_plugins)] + + #[must_root] struct Foo(i32); + + // #[must_root] -- this is needed! + trait Bar { + fn extract(&self) -> i32; + } + + impl Bar for Foo { + fn extract(&self) -> i32 { self.0 } + } + + fn test() { + Foo(3).extract(); + } + + fn main() {} + ``` + */ + pub fn allow_impl_for_must_root() {} + /* * ``` #![feature(plugin)] #![plugin(script_plugins)] - #![feature(generic_param_attrs)] #[derive(Default)] #[must_root] struct Foo(i32);