diff options
Diffstat (limited to 'components/script_plugins')
-rw-r--r-- | components/script_plugins/lib.rs | 60 | ||||
-rw-r--r-- | components/script_plugins/unrooted_must_root.rs | 92 | ||||
-rw-r--r-- | components/script_plugins/utils.rs | 6 | ||||
-rw-r--r-- | components/script_plugins/webidl_must_inherit.rs | 14 |
4 files changed, 130 insertions, 42 deletions
diff --git a/components/script_plugins/lib.rs b/components/script_plugins/lib.rs index 7d0460bf5a1..39e211bed7e 100644 --- a/components/script_plugins/lib.rs +++ b/components/script_plugins/lib.rs @@ -29,6 +29,7 @@ extern crate webidl; use rustc_plugin::Registry; use syntax::feature_gate::AttributeType::Whitelisted; +use syntax::symbol::Symbol; #[cfg(feature = "unrooted_must_root_lint")] mod unrooted_must_root; @@ -42,14 +43,61 @@ mod utils; #[plugin_registrar] pub fn plugin_registrar(reg: &mut Registry) { + let symbols = crate::Symbols::new(); + #[cfg(feature = "unrooted_must_root_lint")] - reg.register_late_lint_pass(Box::new(unrooted_must_root::UnrootedPass::new())); + reg.register_late_lint_pass(Box::new(unrooted_must_root::UnrootedPass::new( + symbols.clone(), + ))); #[cfg(feature = "webidl_lint")] - reg.register_late_lint_pass(Box::new(webidl_must_inherit::WebIdlPass::new())); + reg.register_late_lint_pass(Box::new(webidl_must_inherit::WebIdlPass::new( + symbols.clone(), + ))); + + reg.register_attribute(symbols.allow_unrooted_interior, Whitelisted); + reg.register_attribute(symbols.allow_unrooted_in_rc, Whitelisted); + reg.register_attribute(symbols.must_root, Whitelisted); + reg.register_attribute(symbols.webidl, Whitelisted); +} + +macro_rules! symbols { + ($($s: ident)+) => { + #[derive(Clone)] + #[allow(non_snake_case)] + struct Symbols { + $( $s: Symbol, )+ + } + + impl Symbols { + fn new() -> Self { + Symbols { + $( $s: Symbol::intern(stringify!($s)), )+ + } + } + } + } +} - reg.register_attribute("allow_unrooted_interior".to_string(), Whitelisted); - reg.register_attribute("allow_unrooted_in_rc".to_string(), Whitelisted); - reg.register_attribute("must_root".to_string(), Whitelisted); - reg.register_attribute("webidl".to_string(), Whitelisted); +symbols! { + allow_unrooted_interior + allow_unrooted_in_rc + must_root + webidl + alloc + rc + Rc + cell + Ref + RefMut + slice + Iter + IterMut + collections + hash + map + set + Entry + OccupiedEntry + VacantEntry } diff --git a/components/script_plugins/unrooted_must_root.rs b/components/script_plugins/unrooted_must_root.rs index 4babfe49f3a..0e6f9e16e65 100644 --- a/components/script_plugins/unrooted_must_root.rs +++ b/components/script_plugins/unrooted_must_root.rs @@ -7,6 +7,7 @@ use rustc::hir::intravisit as visit; use rustc::hir::{self, ExprKind, HirId}; use rustc::lint::{LateContext, LateLintPass, LintArray, LintContext, LintPass}; use rustc::ty; +use syntax::symbol::sym; use syntax::{ast, source_map}; declare_lint!( @@ -32,30 +33,37 @@ declare_lint!( /// Structs which have their own mechanism of rooting their unrooted contents (e.g. `ScriptThread`) /// can be marked as `#[allow(unrooted_must_root)]`. Smart pointers which root their interior type /// can be marked as `#[allow_unrooted_interior]` -pub struct UnrootedPass; +pub(crate) struct UnrootedPass { + symbols: crate::Symbols, +} impl UnrootedPass { - pub fn new() -> UnrootedPass { - UnrootedPass + pub fn new(symbols: crate::Symbols) -> UnrootedPass { + UnrootedPass { symbols } } } /// Checks if a type is unrooted or contains any owned unrooted types -fn is_unrooted_ty(cx: &LateContext, ty: &ty::TyS, in_new_function: bool) -> bool { +fn is_unrooted_ty( + sym: &crate::Symbols, + cx: &LateContext, + ty: &ty::TyS, + in_new_function: bool, +) -> bool { let mut ret = false; ty.maybe_walk(|t| { match t.sty { ty::Adt(did, substs) => { - if cx.tcx.has_attr(did.did, "must_root") { + if cx.tcx.has_attr(did.did, sym.must_root) { ret = true; false - } else if cx.tcx.has_attr(did.did, "allow_unrooted_interior") { + } else if cx.tcx.has_attr(did.did, sym.allow_unrooted_interior) { false - } else if match_def_path(cx, did.did, &["alloc", "rc", "Rc"]) { + } else if match_def_path(cx, did.did, &[sym.alloc, sym.rc, sym.Rc]) { // Rc<Promise> is okay let inner = substs.type_at(0); if let ty::Adt(did, _) = inner.sty { - if cx.tcx.has_attr(did.did, "allow_unrooted_in_rc") { + if cx.tcx.has_attr(did.did, sym.allow_unrooted_in_rc) { false } else { true @@ -63,23 +71,47 @@ fn is_unrooted_ty(cx: &LateContext, ty: &ty::TyS, in_new_function: bool) -> bool } else { true } - } else if match_def_path(cx, did.did, &["core", "cell", "Ref"]) || - match_def_path(cx, did.did, &["core", "cell", "RefMut"]) || - match_def_path(cx, did.did, &["core", "slice", "Iter"]) || - match_def_path(cx, did.did, &["core", "slice", "IterMut"]) || - match_def_path(cx, did.did, &["std", "collections", "hash", "map", "Entry"]) || + } else if match_def_path(cx, did.did, &[sym::core, sym.cell, sym.Ref]) || + match_def_path(cx, did.did, &[sym::core, sym.cell, sym.RefMut]) || + match_def_path(cx, did.did, &[sym::core, sym.slice, sym.Iter]) || + match_def_path(cx, did.did, &[sym::core, sym.slice, sym.IterMut]) || + match_def_path( + cx, + did.did, + &[sym::std, sym.collections, sym.hash, sym.map, sym.Entry], + ) || + match_def_path( + cx, + did.did, + &[ + sym::std, + sym.collections, + sym.hash, + sym.map, + sym.OccupiedEntry, + ], + ) || match_def_path( cx, did.did, - &["std", "collections", "hash", "map", "OccupiedEntry"], + &[ + sym::std, + sym.collections, + sym.hash, + sym.map, + sym.VacantEntry, + ], ) || match_def_path( cx, did.did, - &["std", "collections", "hash", "map", "VacantEntry"], + &[sym::std, sym.collections, sym.hash, sym.map, sym.Iter], ) || - match_def_path(cx, did.did, &["std", "collections", "hash", "map", "Iter"]) || - match_def_path(cx, did.did, &["std", "collections", "hash", "set", "Iter"]) + match_def_path( + cx, + did.did, + &[sym::std, sym.collections, sym.hash, sym.set, sym.Iter], + ) { // Structures which are semantically similar to an &ptr. false @@ -126,10 +158,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnrootedPass { .hir() .expect_item_by_hir_id(cx.tcx.hir().get_parent_item(id)), }; - if item.attrs.iter().all(|a| !a.check_name("must_root")) { + if item + .attrs + .iter() + .all(|a| !a.check_name(self.symbols.must_root)) + { for ref field in def.fields() { let def_id = cx.tcx.hir().local_def_id_from_hir_id(field.hir_id); - if is_unrooted_ty(cx, cx.tcx.type_of(def_id), false) { + if is_unrooted_ty(&self.symbols, cx, cx.tcx.type_of(def_id), false) { cx.span_lint(UNROOTED_MUST_ROOT, field.span, "Type must be rooted, use #[must_root] on the struct definition to propagate") } @@ -144,13 +180,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnrootedPass { .expect_item_by_hir_id(map.get_parent_item(var.node.id)) .attrs .iter() - .all(|a| !a.check_name("must_root")) + .all(|a| !a.check_name(self.symbols.must_root)) { match var.node.data { hir::VariantData::Tuple(ref fields, ..) => { for ref field in fields { let def_id = cx.tcx.hir().local_def_id_from_hir_id(field.hir_id); - if is_unrooted_ty(cx, cx.tcx.type_of(def_id), false) { + if is_unrooted_ty(&self.symbols, cx, cx.tcx.type_of(def_id), false) { cx.span_lint( UNROOTED_MUST_ROOT, field.ty.span, @@ -186,13 +222,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnrootedPass { let sig = cx.tcx.type_of(def_id).fn_sig(cx.tcx); for (arg, ty) in decl.inputs.iter().zip(sig.inputs().skip_binder().iter()) { - if is_unrooted_ty(cx, ty, false) { + if is_unrooted_ty(&self.symbols, cx, ty, false) { cx.span_lint(UNROOTED_MUST_ROOT, arg.span, "Type must be rooted") } } if !in_new_function { - if is_unrooted_ty(cx, sig.output().skip_binder(), false) { + if is_unrooted_ty(&self.symbols, cx, sig.output().skip_binder(), false) { cx.span_lint( UNROOTED_MUST_ROOT, decl.output.span(), @@ -203,6 +239,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnrootedPass { } let mut visitor = FnDefVisitor { + symbols: &self.symbols, cx: cx, in_new_function: in_new_function, }; @@ -211,6 +248,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnrootedPass { } struct FnDefVisitor<'a, 'b: 'a, 'tcx: 'a + 'b> { + symbols: &'a crate::Symbols, cx: &'a LateContext<'b, 'tcx>, in_new_function: bool, } @@ -219,16 +257,16 @@ impl<'a, 'b, 'tcx> visit::Visitor<'tcx> for FnDefVisitor<'a, 'b, 'tcx> { fn visit_expr(&mut self, expr: &'tcx hir::Expr) { let cx = self.cx; - fn require_rooted(cx: &LateContext, in_new_function: bool, subexpr: &hir::Expr) { + let require_rooted = |cx: &LateContext, in_new_function: bool, subexpr: &hir::Expr| { let ty = cx.tables.expr_ty(&subexpr); - if is_unrooted_ty(cx, ty, in_new_function) { + if is_unrooted_ty(&self.symbols, cx, ty, in_new_function) { cx.span_lint( UNROOTED_MUST_ROOT, subexpr.span, &format!("Expression of type {:?} must be rooted", ty), ) } - } + }; match expr.node { // Trait casts from #[must_root] types are not allowed @@ -263,7 +301,7 @@ impl<'a, 'b, 'tcx> visit::Visitor<'tcx> for FnDefVisitor<'a, 'b, 'tcx> { hir::PatKind::Binding(hir::BindingAnnotation::Unannotated, ..) | hir::PatKind::Binding(hir::BindingAnnotation::Mutable, ..) => { let ty = cx.tables.pat_ty(pat); - if is_unrooted_ty(cx, ty, self.in_new_function) { + if is_unrooted_ty(&self.symbols, cx, ty, self.in_new_function) { cx.span_lint( UNROOTED_MUST_ROOT, pat.span, diff --git a/components/script_plugins/utils.rs b/components/script_plugins/utils.rs index c580879ebd8..e6398de35e1 100644 --- a/components/script_plugins/utils.rs +++ b/components/script_plugins/utils.rs @@ -5,11 +5,12 @@ use rustc::hir::def_id::DefId; use rustc::lint::LateContext; use syntax::source_map::{ExpnFormat, Span}; +use syntax::symbol::Symbol; /// check if a DefId's path matches the given absolute type path /// usage e.g. with /// `match_def_path(cx, id, &["core", "option", "Option"])` -pub fn match_def_path(cx: &LateContext, def_id: DefId, path: &[&str]) -> bool { +pub fn match_def_path(cx: &LateContext, def_id: DefId, path: &[Symbol]) -> bool { let krate = &cx.tcx.crate_name(def_id.krate); if krate != &path[0] { return false; @@ -24,9 +25,8 @@ pub fn match_def_path(cx: &LateContext, def_id: DefId, path: &[&str]) -> bool { other .into_iter() - .map(|e| e.data) .zip(path) - .all(|(nm, p)| &*nm.as_interned_str().as_str() == *p) + .all(|(e, p)| e.data.as_interned_str().as_symbol() == *p) } pub fn in_derive_expn(span: Span) -> bool { diff --git a/components/script_plugins/webidl_must_inherit.rs b/components/script_plugins/webidl_must_inherit.rs index 89233bb943e..cdf7f573ba9 100644 --- a/components/script_plugins/webidl_must_inherit.rs +++ b/components/script_plugins/webidl_must_inherit.rs @@ -23,7 +23,9 @@ declare_lint!( "Warn and report usage of incorrect webidl inheritance" ); -pub struct WebIdlPass; +pub(crate) struct WebIdlPass { + symbols: crate::Symbols, +} #[derive(Clone, Debug)] pub struct ParentMismatchError { @@ -53,8 +55,8 @@ impl Error for ParentMismatchError { } impl WebIdlPass { - pub fn new() -> WebIdlPass { - WebIdlPass + pub fn new(symbols: crate::Symbols) -> WebIdlPass { + WebIdlPass { symbols } } } @@ -74,12 +76,12 @@ fn get_webidl_path(struct_name: &str) -> io::Result<path::PathBuf> { Ok(dir) } -fn is_webidl_ty(cx: &LateContext, ty: &ty::TyS) -> bool { +fn is_webidl_ty(symbols: &crate::Symbols, cx: &LateContext, ty: &ty::TyS) -> bool { let mut ret = false; ty.maybe_walk(|t| { match t.sty { ty::Adt(did, _substs) => { - if cx.tcx.has_attr(did.did, "webidl") { + if cx.tcx.has_attr(did.did, symbols.webidl) { ret = true; } false @@ -156,7 +158,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for WebIdlPass { id: HirId, ) { let def_id = cx.tcx.hir().local_def_id_from_hir_id(id); - if !is_webidl_ty(cx, cx.tcx.type_of(def_id)) { + if !is_webidl_ty(&self.symbols, cx, cx.tcx.type_of(def_id)) { return; } |