Skip to content

Avoid hygiene_data lookups #61253

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

Merged
merged 5 commits into from
May 30, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/librustc/lint/internal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TyTyKind {
.help("try using `Ty` instead")
.emit();
} else {
if ty.span.ctxt().outer().expn_info().is_some() {
if ty.span.ctxt().outer_expn_info().is_some() {
return;
}
if let Some(t) = is_ty_or_ty_ctxt(cx, ty) {
Expand Down
4 changes: 2 additions & 2 deletions src/librustc/lint/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -880,7 +880,7 @@ pub fn provide(providers: &mut Providers<'_>) {
/// This is used to test whether a lint should not even begin to figure out whether it should
/// be reported on the current node.
pub fn in_external_macro(sess: &Session, span: Span) -> bool {
let info = match span.ctxt().outer().expn_info() {
let info = match span.ctxt().outer_expn_info() {
Some(info) => info,
// no ExpnInfo means this span doesn't come from a macro
None => return false,
Expand Down Expand Up @@ -908,7 +908,7 @@ pub fn in_external_macro(sess: &Session, span: Span) -> bool {

/// Returns whether `span` originates in a derive macro's expansion
pub fn in_derive_expansion(span: Span) -> bool {
let info = match span.ctxt().outer().expn_info() {
let info = match span.ctxt().outer_expn_info() {
Some(info) => info,
// no ExpnInfo means this span doesn't come from a macro
None => return false,
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/traits/error_reporting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
format: ExpnFormat::CompilerDesugaring(_),
def_site: Some(def_span),
..
}) = span.ctxt().outer().expn_info() {
}) = span.ctxt().outer_expn_info() {
span = def_span;
}

Expand Down
29 changes: 21 additions & 8 deletions src/librustc/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2886,7 +2886,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {

pub fn find_field_index(self, ident: Ident, variant: &VariantDef) -> Option<usize> {
variant.fields.iter().position(|field| {
self.adjust_ident(ident, variant.def_id, hir::DUMMY_HIR_ID).0 == field.ident.modern()
self.hygienic_eq(ident, field.ident, variant.def_id)
})
}

Expand Down Expand Up @@ -3085,19 +3085,32 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
/// its supposed definition name (`def_name`). The method also needs `DefId` of the supposed
/// definition's parent/scope to perform comparison.
pub fn hygienic_eq(self, use_name: Ident, def_name: Ident, def_parent_def_id: DefId) -> bool {
self.adjust_ident(use_name, def_parent_def_id, hir::DUMMY_HIR_ID).0 == def_name.modern()
// We could use `Ident::eq` here, but we deliberately don't. The name
// comparison fails frequently, and we want to avoid the expensive
// `modern()` calls required for the span comparison whenever possible.
use_name.name == def_name.name &&
self.adjust_ident(use_name, def_parent_def_id).span.ctxt() == def_name.modern().span.ctxt()
}

pub fn adjust_ident(self, mut ident: Ident, scope: DefId, block: hir::HirId) -> (Ident, DefId) {
ident = ident.modern();
let target_expansion = match scope.krate {
fn expansion_that_defined(self, scope: DefId) -> Mark {
match scope.krate {
LOCAL_CRATE => self.hir().definitions().expansion_that_defined(scope.index),
_ => Mark::root(),
};
let scope = match ident.span.adjust(target_expansion) {
}
}

pub fn adjust_ident(self, mut ident: Ident, scope: DefId) -> Ident {
ident = ident.modern();
ident.span.adjust(self.expansion_that_defined(scope));
ident
}

pub fn adjust_ident_and_get_scope(self, mut ident: Ident, scope: DefId, block: hir::HirId)
-> (Ident, DefId) {
ident = ident.modern();
let scope = match ident.span.adjust(self.expansion_that_defined(scope)) {
Some(actual_expansion) =>
self.hir().definitions().parent_module_of_macro_def(actual_expansion),
None if block == hir::DUMMY_HIR_ID => DefId::local(CRATE_DEF_INDEX), // Dummy DefId
None => self.hir().get_module_parent_by_hir_id(block),
};
(ident, scope)
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_codegen_ssa/mir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
// at the level above that.
let mut span = source_info.span;
while span.ctxt() != NO_EXPANSION && span.ctxt() != self.mir.span.ctxt() {
if let Some(info) = span.ctxt().outer().expn_info() {
if let Some(info) = span.ctxt().outer_expn_info() {
span = info.call_site;
} else {
break;
Expand Down
4 changes: 2 additions & 2 deletions src/librustc_lint/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonShorthandFieldPatterns {
if fieldpat.node.is_shorthand {
continue;
}
if fieldpat.span.ctxt().outer().expn_info().is_some() {
if fieldpat.span.ctxt().outer_expn_info().is_some() {
// Don't lint if this is a macro expansion: macro authors
// shouldn't have to worry about this kind of style issue
// (Issue #49588)
Expand Down Expand Up @@ -1003,7 +1003,7 @@ impl UnreachablePub {
let mut applicability = Applicability::MachineApplicable;
match vis.node {
hir::VisibilityKind::Public if !cx.access_levels.is_reachable(id) => {
if span.ctxt().outer().expn_info().is_some() {
if span.ctxt().outer_expn_info().is_some() {
applicability = Applicability::MaybeIncorrect;
}
let def_span = cx.tcx.sess.source_map().def_span(span);
Expand Down
5 changes: 2 additions & 3 deletions src/librustc_lint/unused.rs
Original file line number Diff line number Diff line change
Expand Up @@ -391,9 +391,8 @@ impl EarlyLintPass for UnusedParens {
// trigger in situations that macro authors shouldn't have to care about, e.g.,
// when a parenthesized token tree matched in one macro expansion is matched as
// an expression in another and used as a fn/method argument (Issue #47775)
if e.span.ctxt().outer().expn_info()
.map_or(false, |info| info.call_site.ctxt().outer()
.expn_info().is_some()) {
if e.span.ctxt().outer_expn_info()
.map_or(false, |info| info.call_site.ctxt().outer_expn_info().is_some()) {
return;
}
let msg = format!("{} argument", call_kind);
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_privacy/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -845,7 +845,7 @@ impl<'a, 'tcx> NamePrivacyVisitor<'a, 'tcx> {
field: &'tcx ty::FieldDef) { // definition of the field
let ident = Ident::new(kw::Invalid, use_ctxt);
let current_hir = self.current_item;
let def_id = self.tcx.adjust_ident(ident, def.did, current_hir).1;
let def_id = self.tcx.adjust_ident_and_get_scope(ident, def.did, current_hir).1;
if !def.is_enum() && !field.vis.is_accessible_from(def_id, self.tcx) {
struct_span_err!(self.tcx.sess, span, E0451, "field `{}` of {} `{}` is private",
field.ident, def.variant_descr(), self.tcx.def_path_str(def.did))
Expand Down
8 changes: 4 additions & 4 deletions src/librustc_resolve/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -762,7 +762,7 @@ impl<'tcx> Visitor<'tcx> for UsePlacementFinder {
ItemKind::Use(..) => {
// don't suggest placing a use before the prelude
// import or other generated ones
if item.span.ctxt().outer().expn_info().is_none() {
if item.span.ctxt().outer_expn_info().is_none() {
self.span = Some(item.span.shrink_to_lo());
self.found_use = true;
return;
Expand All @@ -772,7 +772,7 @@ impl<'tcx> Visitor<'tcx> for UsePlacementFinder {
ItemKind::ExternCrate(_) => {}
// but place them before the first other item
_ => if self.span.map_or(true, |span| item.span < span ) {
if item.span.ctxt().outer().expn_info().is_none() {
if item.span.ctxt().outer_expn_info().is_none() {
// don't insert between attributes and an item
if item.attrs.is_empty() {
self.span = Some(item.span.shrink_to_lo());
Expand Down Expand Up @@ -2308,7 +2308,7 @@ impl<'a> Resolver<'a> {

fn hygienic_lexical_parent(&mut self, module: Module<'a>, span: &mut Span)
-> Option<Module<'a>> {
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()));
}

Expand Down Expand Up @@ -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;
}
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_resolve/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -413,7 +413,7 @@ impl<'a> Resolver<'a> {

// Possibly apply the macro helper hack
if kind == MacroKind::Bang && path.len() == 1 &&
path[0].ident.span.ctxt().outer().expn_info()
path[0].ident.span.ctxt().outer_expn_info()
.map_or(false, |info| info.local_inner_macros) {
let root = Ident::new(kw::DollarCrate, path[0].ident.span);
path.insert(0, Segment::from_ident(root));
Expand Down
5 changes: 3 additions & 2 deletions src/librustc_typeck/astconv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -903,7 +903,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
}?;

let (assoc_ident, def_scope) =
tcx.adjust_ident(binding.item_name, candidate.def_id(), hir_ref_id);
tcx.adjust_ident_and_get_scope(binding.item_name, candidate.def_id(), hir_ref_id);
let assoc_ty = tcx.associated_items(candidate.def_id()).find(|i| {
i.kind == ty::AssocKind::Type && i.ident.modern() == assoc_ident
}).expect("missing associated type");
Expand Down Expand Up @@ -1433,7 +1433,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
};

let trait_did = bound.def_id();
let (assoc_ident, def_scope) = tcx.adjust_ident(assoc_ident, trait_did, hir_ref_id);
let (assoc_ident, def_scope) =
tcx.adjust_ident_and_get_scope(assoc_ident, trait_did, hir_ref_id);
let item = tcx.associated_items(trait_did).find(|i| {
Namespace::from(i.kind) == Namespace::Type &&
i.ident.modern() == assoc_ident
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_typeck/check/_match.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1184,7 +1184,7 @@ https://doc.rust-lang.org/reference/types.html#trait-objects");
let mut inexistent_fields = vec![];
// Typecheck each field.
for &Spanned { node: ref field, span } in fields {
let ident = tcx.adjust_ident(field.ident, variant.def_id, self.body_id).0;
let ident = tcx.adjust_ident(field.ident, variant.def_id);
let field_ty = match used_fields.entry(ident) {
Occupied(occupied) => {
struct_span_err!(tcx.sess, span, E0025,
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_typeck/check/demand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {

// Check the `expn_info()` to see if this is a macro; if so, it's hard to
// extract the text and make a good suggestion, so don't bother.
let is_macro = sp.ctxt().outer().expn_info().is_some();
let is_macro = sp.ctxt().outer_expn_info().is_some();

match (&expr.node, &expected.sty, &checked_ty.sty) {
(_, &ty::Ref(_, exp, _), &ty::Ref(_, check, _)) => match (&exp.sty, &check.sty) {
Expand Down
3 changes: 2 additions & 1 deletion src/librustc_typeck/check/method/probe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -510,7 +510,8 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
{
let is_accessible = if let Some(name) = self.method_name {
let item = candidate.item;
let def_scope = self.tcx.adjust_ident(name, item.container.id(), self.body_id).1;
let def_scope =
self.tcx.adjust_ident_and_get_scope(name, item.container.id(), self.body_id).1;
item.vis.is_accessible_from(def_scope, self.tcx)
} else {
true
Expand Down
4 changes: 2 additions & 2 deletions src/librustc_typeck/check/method/suggest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -892,7 +892,7 @@ impl<'a, 'tcx, 'gcx> hir::intravisit::Visitor<'tcx> for UsePlacementFinder<'a, '
hir::ItemKind::Use(..) => {
// Don't suggest placing a `use` before the prelude
// import or other generated ones.
if item.span.ctxt().outer().expn_info().is_none() {
if item.span.ctxt().outer_expn_info().is_none() {
self.span = Some(item.span.shrink_to_lo());
self.found_use = true;
return;
Expand All @@ -902,7 +902,7 @@ impl<'a, 'tcx, 'gcx> hir::intravisit::Visitor<'tcx> for UsePlacementFinder<'a, '
hir::ItemKind::ExternCrate(_) => {}
// ...but do place them before the first other item.
_ => if self.span.map_or(true, |span| item.span < span ) {
if item.span.ctxt().outer().expn_info().is_none() {
if item.span.ctxt().outer_expn_info().is_none() {
// Don't insert between attributes and an item.
if item.attrs.is_empty() {
self.span = Some(item.span.shrink_to_lo());
Expand Down
7 changes: 4 additions & 3 deletions src/librustc_typeck/check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3339,7 +3339,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
ty::Adt(base_def, substs) if !base_def.is_enum() => {
debug!("struct named {:?}", base_t);
let (ident, def_scope) =
self.tcx.adjust_ident(field, base_def.did, self.body_id);
self.tcx.adjust_ident_and_get_scope(field, base_def.did, self.body_id);
let fields = &base_def.non_enum_variant().fields;
if let Some(index) = fields.iter().position(|f| f.ident.modern() == ident) {
let field = &fields[index];
Expand Down Expand Up @@ -3510,7 +3510,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {

fn available_field_names(&self, variant: &'tcx ty::VariantDef) -> Vec<ast::Name> {
variant.fields.iter().filter(|field| {
let def_scope = self.tcx.adjust_ident(field.ident, variant.def_id, self.body_id).1;
let def_scope =
self.tcx.adjust_ident_and_get_scope(field.ident, variant.def_id, self.body_id).1;
field.vis.is_accessible_from(def_scope, self.tcx)
})
.map(|field| field.ident.name)
Expand Down Expand Up @@ -3628,7 +3629,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {

// Type-check each field.
for field in ast_fields {
let ident = tcx.adjust_ident(field.ident, variant.def_id, self.body_id).0;
let ident = tcx.adjust_ident(field.ident, variant.def_id);
let field_type = if let Some((i, v_field)) = remaining_fields.remove(&ident) {
seen_fields.insert(ident, field.span);
self.write_field_index(field.hir_id, i);
Expand Down
2 changes: 1 addition & 1 deletion src/libsyntax/ext/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -872,7 +872,7 @@ impl<'a> ExtCtxt<'a> {
let mut ctxt = self.backtrace();
let mut last_macro = None;
loop {
if ctxt.outer().expn_info().map_or(None, |info| {
if ctxt.outer_expn_info().map_or(None, |info| {
if info.format.name() == sym::include {
// Stop going up the backtrace once include! is encountered
return None;
Expand Down
4 changes: 2 additions & 2 deletions src/libsyntax/source_map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ use errors::SourceMapper;
/// otherwise return the call site span up to the `enclosing_sp` by
/// following the `expn_info` chain.
pub fn original_sp(sp: Span, enclosing_sp: Span) -> Span {
let call_site1 = sp.ctxt().outer().expn_info().map(|ei| ei.call_site);
let call_site2 = enclosing_sp.ctxt().outer().expn_info().map(|ei| ei.call_site);
let call_site1 = sp.ctxt().outer_expn_info().map(|ei| ei.call_site);
let call_site2 = enclosing_sp.ctxt().outer_expn_info().map(|ei| ei.call_site);
match (call_site1, call_site2) {
(None, _) => sp,
(Some(call_site1), Some(call_site2)) if call_site1 == call_site2 => sp,
Expand Down
2 changes: 1 addition & 1 deletion src/libsyntax_ext/proc_macro_server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -680,7 +680,7 @@ impl server::Span for Rustc<'_> {
self.sess.source_map().lookup_char_pos(span.lo()).file
}
fn parent(&mut self, span: Self::Span) -> Option<Self::Span> {
span.ctxt().outer().expn_info().map(|i| i.call_site)
span.ctxt().outer_expn_info().map(|i| i.call_site)
}
fn source(&mut self, span: Self::Span) -> Self::Span {
span.source_callsite()
Expand Down
51 changes: 37 additions & 14 deletions src/libsyntax_pos/hygiene.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,16 +112,14 @@ impl Mark {
HygieneData::with(|data| data.marks[self.0 as usize].default_transparency = transparency)
}

pub fn is_descendant_of(mut self, ancestor: Mark) -> bool {
HygieneData::with(|data| {
while self != ancestor {
if self == Mark::root() {
return false;
}
self = data.marks[self.0 as usize].parent;
}
true
})
pub fn is_descendant_of(self, ancestor: Mark) -> bool {
HygieneData::with(|data| data.is_descendant_of(self, ancestor))
}

/// `mark.outer_is_descendant_of(ctxt)` is equivalent to but faster than
/// `mark.is_descendant_of(ctxt.outer())`.
pub fn outer_is_descendant_of(self, ctxt: SyntaxContext) -> bool {
HygieneData::with(|data| data.is_descendant_of(self, data.outer(ctxt)))
}

/// Computes a mark such that both input marks are descendants of (or equal to) the returned
Expand Down Expand Up @@ -201,6 +199,24 @@ impl HygieneData {
fn with<T, F: FnOnce(&mut HygieneData) -> T>(f: F) -> T {
GLOBALS.with(|globals| f(&mut *globals.hygiene_data.borrow_mut()))
}

fn outer(&self, ctxt: SyntaxContext) -> Mark {
self.syntax_contexts[ctxt.0 as usize].outer_mark
}

fn expn_info(&self, mark: Mark) -> Option<ExpnInfo> {
self.marks[mark.0 as usize].expn_info.clone()
}

fn is_descendant_of(&self, mut mark: Mark, ancestor: Mark) -> bool {
while mark != ancestor {
if mark == Mark::root() {
return false;
}
mark = self.marks[mark.0 as usize].parent;
}
true
}
}

pub fn clear_markings() {
Expand Down Expand Up @@ -416,7 +432,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<Mark> {
let mut scope = None;
while !expansion.is_descendant_of(self.outer()) {
while !expansion.outer_is_descendant_of(*self) {
scope = Some(self.remove_mark());
}
scope
Expand Down Expand Up @@ -450,7 +466,7 @@ impl SyntaxContext {
pub fn glob_adjust(&mut self, expansion: Mark, mut glob_ctxt: SyntaxContext)
-> Option<Option<Mark>> {
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;
Expand All @@ -476,7 +492,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());
}

Expand All @@ -499,7 +515,14 @@ impl SyntaxContext {

#[inline]
pub fn outer(self) -> Mark {
HygieneData::with(|data| data.syntax_contexts[self.0 as usize].outer_mark)
HygieneData::with(|data| data.outer(self))
}

/// `ctxt.outer_expn_info()` is equivalent to but faster than
/// `ctxt.outer().expn_info()`.
#[inline]
pub fn outer_expn_info(self) -> Option<ExpnInfo> {
HygieneData::with(|data| data.expn_info(data.outer(self)))
}

pub fn dollar_crate_name(self) -> Symbol {
Expand Down
Loading