From 828f6fdbe57a7b0e6b7bf7194ee9a2079b2779cd Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 27 May 2019 13:38:23 +1000 Subject: [PATCH] Introduce and use `Mark::outer_is_descendant_of()`. It reduces two `hygiene_data` accesses to one on some hot paths. --- src/librustc_resolve/lib.rs | 4 ++-- src/libsyntax_pos/hygiene.rs | 21 ++++++++++++++++++--- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index c05b69ab44f..f9cf95a873f 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -2308,7 +2308,7 @@ impl<'a> Resolver<'a> { fn hygienic_lexical_parent(&mut self, module: Module<'a>, span: &mut Span) -> Option> { - if !module.expansion.is_descendant_of(span.ctxt().outer()) { + if !module.expansion.outer_is_descendant_of(span.ctxt()) { return Some(self.macro_def_scope(span.remove_mark())); } @@ -2344,7 +2344,7 @@ impl<'a> Resolver<'a> { module.expansion.is_descendant_of(parent.expansion) { // The macro is a proc macro derive if module.expansion.looks_like_proc_macro_derive() { - if parent.expansion.is_descendant_of(span.ctxt().outer()) { + if parent.expansion.outer_is_descendant_of(span.ctxt()) { *poisoned = Some(node_id); return module.parent; } diff --git a/src/libsyntax_pos/hygiene.rs b/src/libsyntax_pos/hygiene.rs index e8dcd8171c9..3ffeaf43b85 100644 --- a/src/libsyntax_pos/hygiene.rs +++ b/src/libsyntax_pos/hygiene.rs @@ -124,6 +124,21 @@ impl Mark { }) } + /// `mark.outer_is_descendant_of(ctxt)` is equivalent to but faster than + /// `mark.is_descendant_of(ctxt.outer())`. + pub fn outer_is_descendant_of(mut self, ctxt: SyntaxContext) -> bool { + HygieneData::with(|data| { + let outer = data.syntax_contexts[ctxt.0 as usize].outer_mark; + while self != outer { + if self == Mark::root() { + return false; + } + self = data.marks[self.0 as usize].parent; + } + true + }) + } + /// Computes a mark such that both input marks are descendants of (or equal to) the returned /// mark. That is, the following holds: /// @@ -416,7 +431,7 @@ impl SyntaxContext { /// or `None` if we privacy check as usual (i.e., not w.r.t. a macro definition scope). pub fn adjust(&mut self, expansion: Mark) -> Option { let mut scope = None; - while !expansion.is_descendant_of(self.outer()) { + while !expansion.outer_is_descendant_of(*self) { scope = Some(self.remove_mark()); } scope @@ -450,7 +465,7 @@ impl SyntaxContext { pub fn glob_adjust(&mut self, expansion: Mark, mut glob_ctxt: SyntaxContext) -> Option> { let mut scope = None; - while !expansion.is_descendant_of(glob_ctxt.outer()) { + while !expansion.outer_is_descendant_of(glob_ctxt) { scope = Some(glob_ctxt.remove_mark()); if self.remove_mark() != scope.unwrap() { return None; @@ -476,7 +491,7 @@ impl SyntaxContext { } let mut marks = Vec::new(); - while !expansion.is_descendant_of(glob_ctxt.outer()) { + while !expansion.outer_is_descendant_of(glob_ctxt) { marks.push(glob_ctxt.remove_mark()); }