From 521d8bc32e25ee31a0ccc9de77720207b69ac358 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Tue, 21 Jul 2015 23:41:19 +0530 Subject: [PATCH] Make enum/fn part of unrooted_must_root handle type parameters --- .../plugins/lints/unrooted_must_root.rs | 43 ++++++++----------- components/script/dom/bindings/js.rs | 1 + components/script/page.rs | 2 +- 3 files changed, 19 insertions(+), 27 deletions(-) diff --git a/components/plugins/lints/unrooted_must_root.rs b/components/plugins/lints/unrooted_must_root.rs index 073212eabe6..55607b39b30 100644 --- a/components/plugins/lints/unrooted_must_root.rs +++ b/components/plugins/lints/unrooted_must_root.rs @@ -6,7 +6,8 @@ use syntax::{ast, codemap, visit}; use syntax::attr::AttrMetaMethods; use rustc::ast_map; use rustc::lint::{Context, LintPass, LintArray}; -use rustc::middle::{ty, def}; +use rustc::middle::ty; +use rustc::middle::astconv_util::ast_ty_to_prim_ty; use utils::{match_def_path, unsafe_context}; declare_lint!(UNROOTED_MUST_ROOT, Deny, @@ -36,27 +37,8 @@ impl UnrootedPass { } } } -// Checks if a type has the #[must_root] annotation. -// Unwraps pointers as well -// TODO (#3874, sort of): unwrap other types like Vec/Option/HashMap/etc -fn lint_unrooted_ty(cx: &Context, ty: &ast::Ty, warning: &str) { - match ty.node { - ast::TyVec(ref t) | ast::TyFixedLengthVec(ref t, _) => - lint_unrooted_ty(cx, &**t, warning), - ast::TyPath(..) => { - match cx.tcx.def_map.borrow()[&ty.id] { - def::PathResolution{ base_def: def::DefTy(def_id, _), .. } => { - if cx.tcx.has_attr(def_id, "must_root") { - cx.span_lint(UNROOTED_MUST_ROOT, ty.span, warning); - } - } - _ => (), - } - } - _ => (), - }; -} +/// Checks if a type is unrooted or contains any owned unrooted types fn is_unrooted_ty(cx: &Context, ty: &ty::TyS, in_new_function: bool) -> bool { let mut ret = false; ty.maybe_walk(|t| { @@ -104,7 +86,8 @@ impl LintPass for UnrootedPass { if item.attrs.iter().all(|a| !a.check_name("must_root")) { for ref field in def.fields.iter() { if is_unrooted_ty(cx, cx.tcx.node_id_to_type(field.node.id), false) { - cx.span_lint(UNROOTED_MUST_ROOT, field.span, "Type must be rooted, use #[must_root] on the struct definition to propagate") + cx.span_lint(UNROOTED_MUST_ROOT, field.span, + "Type must be rooted, use #[must_root] on the struct definition to propagate") } } } @@ -116,8 +99,13 @@ impl LintPass for UnrootedPass { match var.node.kind { ast::TupleVariantKind(ref vec) => { for ty in vec.iter() { - lint_unrooted_ty(cx, &*ty.ty, - "Type must be rooted, use #[must_root] on the enum definition to propagate") + ast_ty_to_prim_ty(cx.tcx, &*ty.ty).map(|t| { + if is_unrooted_ty(cx, t, false) { + cx.span_lint(UNROOTED_MUST_ROOT, ty.ty.span, + "Type must be rooted, use #[must_root] on \ + the enum definition to propagate") + } + }); } } _ => () // Struct variants already caught by check_struct_def @@ -150,8 +138,11 @@ impl LintPass for UnrootedPass { match block.rules { ast::DefaultBlock => { for arg in decl.inputs.iter() { - lint_unrooted_ty(cx, &*arg.ty, - "Type must be rooted") + ast_ty_to_prim_ty(cx.tcx, &*arg.ty).map(|t| { + if is_unrooted_ty(cx, t, false) { + cx.span_lint(UNROOTED_MUST_ROOT, arg.ty.span, "Type must be rooted") + } + }); } } _ => () // fn is `unsafe` diff --git a/components/script/dom/bindings/js.rs b/components/script/dom/bindings/js.rs index e5e9561a092..fc929db1cac 100644 --- a/components/script/dom/bindings/js.rs +++ b/components/script/dom/bindings/js.rs @@ -81,6 +81,7 @@ impl JS { /// An unrooted reference to a DOM object for use in layout. `Layout*Helpers` /// traits must be implemented on this. +#[allow_unrooted_interior] pub struct LayoutJS { ptr: NonZero<*const T> } diff --git a/components/script/page.rs b/components/script/page.rs index 3d9dc1d8da7..1286a1427f1 100644 --- a/components/script/page.rs +++ b/components/script/page.rs @@ -14,7 +14,7 @@ use std::rc::Rc; /// Encapsulates a handle to a frame in a frame tree. #[derive(JSTraceable)] -#[allow(unrooted_must_root)] // FIXME(#6686) this is wrong +#[allow(unrooted_must_root)] // FIXME(#6687) this is wrong pub struct Page { /// Pipeline id associated with this page. id: PipelineId,