Skip to content

Commit 0bfbaa6

Browse files
committed
Auto merge of #61253 - nnethercote:avoid-hygiene_data-lookups, r=petrochenkov
Avoid `hygiene_data` lookups These commits mostly introduce compound operations that allow two close adjacent `hygiene_data` lookups to be combined. r? @petrochenkov
2 parents aee7012 + 95ea7fd commit 0bfbaa6

File tree

21 files changed

+100
-62
lines changed

21 files changed

+100
-62
lines changed

src/librustc/lint/internal.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TyTyKind {
113113
.help("try using `Ty` instead")
114114
.emit();
115115
} else {
116-
if ty.span.ctxt().outer().expn_info().is_some() {
116+
if ty.span.ctxt().outer_expn_info().is_some() {
117117
return;
118118
}
119119
if let Some(t) = is_ty_or_ty_ctxt(cx, ty) {

src/librustc/lint/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -880,7 +880,7 @@ pub fn provide(providers: &mut Providers<'_>) {
880880
/// This is used to test whether a lint should not even begin to figure out whether it should
881881
/// be reported on the current node.
882882
pub fn in_external_macro(sess: &Session, span: Span) -> bool {
883-
let info = match span.ctxt().outer().expn_info() {
883+
let info = match span.ctxt().outer_expn_info() {
884884
Some(info) => info,
885885
// no ExpnInfo means this span doesn't come from a macro
886886
None => return false,
@@ -908,7 +908,7 @@ pub fn in_external_macro(sess: &Session, span: Span) -> bool {
908908

909909
/// Returns whether `span` originates in a derive macro's expansion
910910
pub fn in_derive_expansion(span: Span) -> bool {
911-
let info = match span.ctxt().outer().expn_info() {
911+
let info = match span.ctxt().outer_expn_info() {
912912
Some(info) => info,
913913
// no ExpnInfo means this span doesn't come from a macro
914914
None => return false,

src/librustc/traits/error_reporting.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
6565
format: ExpnFormat::CompilerDesugaring(_),
6666
def_site: Some(def_span),
6767
..
68-
}) = span.ctxt().outer().expn_info() {
68+
}) = span.ctxt().outer_expn_info() {
6969
span = def_span;
7070
}
7171

src/librustc/ty/mod.rs

+21-8
Original file line numberDiff line numberDiff line change
@@ -2886,7 +2886,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
28862886

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

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

3091-
pub fn adjust_ident(self, mut ident: Ident, scope: DefId, block: hir::HirId) -> (Ident, DefId) {
3092-
ident = ident.modern();
3093-
let target_expansion = match scope.krate {
3095+
fn expansion_that_defined(self, scope: DefId) -> Mark {
3096+
match scope.krate {
30943097
LOCAL_CRATE => self.hir().definitions().expansion_that_defined(scope.index),
30953098
_ => Mark::root(),
3096-
};
3097-
let scope = match ident.span.adjust(target_expansion) {
3099+
}
3100+
}
3101+
3102+
pub fn adjust_ident(self, mut ident: Ident, scope: DefId) -> Ident {
3103+
ident = ident.modern();
3104+
ident.span.adjust(self.expansion_that_defined(scope));
3105+
ident
3106+
}
3107+
3108+
pub fn adjust_ident_and_get_scope(self, mut ident: Ident, scope: DefId, block: hir::HirId)
3109+
-> (Ident, DefId) {
3110+
ident = ident.modern();
3111+
let scope = match ident.span.adjust(self.expansion_that_defined(scope)) {
30983112
Some(actual_expansion) =>
30993113
self.hir().definitions().parent_module_of_macro_def(actual_expansion),
3100-
None if block == hir::DUMMY_HIR_ID => DefId::local(CRATE_DEF_INDEX), // Dummy DefId
31013114
None => self.hir().get_module_parent_by_hir_id(block),
31023115
};
31033116
(ident, scope)

src/librustc_codegen_ssa/mir/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
131131
// at the level above that.
132132
let mut span = source_info.span;
133133
while span.ctxt() != NO_EXPANSION && span.ctxt() != self.mir.span.ctxt() {
134-
if let Some(info) = span.ctxt().outer().expn_info() {
134+
if let Some(info) = span.ctxt().outer_expn_info() {
135135
span = info.call_site;
136136
} else {
137137
break;

src/librustc_lint/builtin.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonShorthandFieldPatterns {
158158
if fieldpat.node.is_shorthand {
159159
continue;
160160
}
161-
if fieldpat.span.ctxt().outer().expn_info().is_some() {
161+
if fieldpat.span.ctxt().outer_expn_info().is_some() {
162162
// Don't lint if this is a macro expansion: macro authors
163163
// shouldn't have to worry about this kind of style issue
164164
// (Issue #49588)
@@ -1003,7 +1003,7 @@ impl UnreachablePub {
10031003
let mut applicability = Applicability::MachineApplicable;
10041004
match vis.node {
10051005
hir::VisibilityKind::Public if !cx.access_levels.is_reachable(id) => {
1006-
if span.ctxt().outer().expn_info().is_some() {
1006+
if span.ctxt().outer_expn_info().is_some() {
10071007
applicability = Applicability::MaybeIncorrect;
10081008
}
10091009
let def_span = cx.tcx.sess.source_map().def_span(span);

src/librustc_lint/unused.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -391,9 +391,8 @@ impl EarlyLintPass for UnusedParens {
391391
// trigger in situations that macro authors shouldn't have to care about, e.g.,
392392
// when a parenthesized token tree matched in one macro expansion is matched as
393393
// an expression in another and used as a fn/method argument (Issue #47775)
394-
if e.span.ctxt().outer().expn_info()
395-
.map_or(false, |info| info.call_site.ctxt().outer()
396-
.expn_info().is_some()) {
394+
if e.span.ctxt().outer_expn_info()
395+
.map_or(false, |info| info.call_site.ctxt().outer_expn_info().is_some()) {
397396
return;
398397
}
399398
let msg = format!("{} argument", call_kind);

src/librustc_privacy/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -845,7 +845,7 @@ impl<'a, 'tcx> NamePrivacyVisitor<'a, 'tcx> {
845845
field: &'tcx ty::FieldDef) { // definition of the field
846846
let ident = Ident::new(kw::Invalid, use_ctxt);
847847
let current_hir = self.current_item;
848-
let def_id = self.tcx.adjust_ident(ident, def.did, current_hir).1;
848+
let def_id = self.tcx.adjust_ident_and_get_scope(ident, def.did, current_hir).1;
849849
if !def.is_enum() && !field.vis.is_accessible_from(def_id, self.tcx) {
850850
struct_span_err!(self.tcx.sess, span, E0451, "field `{}` of {} `{}` is private",
851851
field.ident, def.variant_descr(), self.tcx.def_path_str(def.did))

src/librustc_resolve/lib.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -762,7 +762,7 @@ impl<'tcx> Visitor<'tcx> for UsePlacementFinder {
762762
ItemKind::Use(..) => {
763763
// don't suggest placing a use before the prelude
764764
// import or other generated ones
765-
if item.span.ctxt().outer().expn_info().is_none() {
765+
if item.span.ctxt().outer_expn_info().is_none() {
766766
self.span = Some(item.span.shrink_to_lo());
767767
self.found_use = true;
768768
return;
@@ -772,7 +772,7 @@ impl<'tcx> Visitor<'tcx> for UsePlacementFinder {
772772
ItemKind::ExternCrate(_) => {}
773773
// but place them before the first other item
774774
_ => if self.span.map_or(true, |span| item.span < span ) {
775-
if item.span.ctxt().outer().expn_info().is_none() {
775+
if item.span.ctxt().outer_expn_info().is_none() {
776776
// don't insert between attributes and an item
777777
if item.attrs.is_empty() {
778778
self.span = Some(item.span.shrink_to_lo());
@@ -2308,7 +2308,7 @@ impl<'a> Resolver<'a> {
23082308

23092309
fn hygienic_lexical_parent(&mut self, module: Module<'a>, span: &mut Span)
23102310
-> Option<Module<'a>> {
2311-
if !module.expansion.is_descendant_of(span.ctxt().outer()) {
2311+
if !module.expansion.outer_is_descendant_of(span.ctxt()) {
23122312
return Some(self.macro_def_scope(span.remove_mark()));
23132313
}
23142314

@@ -2344,7 +2344,7 @@ impl<'a> Resolver<'a> {
23442344
module.expansion.is_descendant_of(parent.expansion) {
23452345
// The macro is a proc macro derive
23462346
if module.expansion.looks_like_proc_macro_derive() {
2347-
if parent.expansion.is_descendant_of(span.ctxt().outer()) {
2347+
if parent.expansion.outer_is_descendant_of(span.ctxt()) {
23482348
*poisoned = Some(node_id);
23492349
return module.parent;
23502350
}

src/librustc_resolve/macros.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -413,7 +413,7 @@ impl<'a> Resolver<'a> {
413413

414414
// Possibly apply the macro helper hack
415415
if kind == MacroKind::Bang && path.len() == 1 &&
416-
path[0].ident.span.ctxt().outer().expn_info()
416+
path[0].ident.span.ctxt().outer_expn_info()
417417
.map_or(false, |info| info.local_inner_macros) {
418418
let root = Ident::new(kw::DollarCrate, path[0].ident.span);
419419
path.insert(0, Segment::from_ident(root));

src/librustc_typeck/astconv.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -903,7 +903,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
903903
}?;
904904

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

14351435
let trait_did = bound.def_id();
1436-
let (assoc_ident, def_scope) = tcx.adjust_ident(assoc_ident, trait_did, hir_ref_id);
1436+
let (assoc_ident, def_scope) =
1437+
tcx.adjust_ident_and_get_scope(assoc_ident, trait_did, hir_ref_id);
14371438
let item = tcx.associated_items(trait_did).find(|i| {
14381439
Namespace::from(i.kind) == Namespace::Type &&
14391440
i.ident.modern() == assoc_ident

src/librustc_typeck/check/_match.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1184,7 +1184,7 @@ https://doc.rust-lang.org/reference/types.html#trait-objects");
11841184
let mut inexistent_fields = vec![];
11851185
// Typecheck each field.
11861186
for &Spanned { node: ref field, span } in fields {
1187-
let ident = tcx.adjust_ident(field.ident, variant.def_id, self.body_id).0;
1187+
let ident = tcx.adjust_ident(field.ident, variant.def_id);
11881188
let field_ty = match used_fields.entry(ident) {
11891189
Occupied(occupied) => {
11901190
struct_span_err!(tcx.sess, span, E0025,

src/librustc_typeck/check/demand.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -331,7 +331,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
331331

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

336336
match (&expr.node, &expected.sty, &checked_ty.sty) {
337337
(_, &ty::Ref(_, exp, _), &ty::Ref(_, check, _)) => match (&exp.sty, &check.sty) {

src/librustc_typeck/check/method/probe.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -510,7 +510,8 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
510510
{
511511
let is_accessible = if let Some(name) = self.method_name {
512512
let item = candidate.item;
513-
let def_scope = self.tcx.adjust_ident(name, item.container.id(), self.body_id).1;
513+
let def_scope =
514+
self.tcx.adjust_ident_and_get_scope(name, item.container.id(), self.body_id).1;
514515
item.vis.is_accessible_from(def_scope, self.tcx)
515516
} else {
516517
true

src/librustc_typeck/check/method/suggest.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -892,7 +892,7 @@ impl<'a, 'tcx, 'gcx> hir::intravisit::Visitor<'tcx> for UsePlacementFinder<'a, '
892892
hir::ItemKind::Use(..) => {
893893
// Don't suggest placing a `use` before the prelude
894894
// import or other generated ones.
895-
if item.span.ctxt().outer().expn_info().is_none() {
895+
if item.span.ctxt().outer_expn_info().is_none() {
896896
self.span = Some(item.span.shrink_to_lo());
897897
self.found_use = true;
898898
return;
@@ -902,7 +902,7 @@ impl<'a, 'tcx, 'gcx> hir::intravisit::Visitor<'tcx> for UsePlacementFinder<'a, '
902902
hir::ItemKind::ExternCrate(_) => {}
903903
// ...but do place them before the first other item.
904904
_ => if self.span.map_or(true, |span| item.span < span ) {
905-
if item.span.ctxt().outer().expn_info().is_none() {
905+
if item.span.ctxt().outer_expn_info().is_none() {
906906
// Don't insert between attributes and an item.
907907
if item.attrs.is_empty() {
908908
self.span = Some(item.span.shrink_to_lo());

src/librustc_typeck/check/mod.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -3339,7 +3339,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
33393339
ty::Adt(base_def, substs) if !base_def.is_enum() => {
33403340
debug!("struct named {:?}", base_t);
33413341
let (ident, def_scope) =
3342-
self.tcx.adjust_ident(field, base_def.did, self.body_id);
3342+
self.tcx.adjust_ident_and_get_scope(field, base_def.did, self.body_id);
33433343
let fields = &base_def.non_enum_variant().fields;
33443344
if let Some(index) = fields.iter().position(|f| f.ident.modern() == ident) {
33453345
let field = &fields[index];
@@ -3510,7 +3510,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
35103510

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

36293630
// Type-check each field.
36303631
for field in ast_fields {
3631-
let ident = tcx.adjust_ident(field.ident, variant.def_id, self.body_id).0;
3632+
let ident = tcx.adjust_ident(field.ident, variant.def_id);
36323633
let field_type = if let Some((i, v_field)) = remaining_fields.remove(&ident) {
36333634
seen_fields.insert(ident, field.span);
36343635
self.write_field_index(field.hir_id, i);

src/libsyntax/ext/base.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -872,7 +872,7 @@ impl<'a> ExtCtxt<'a> {
872872
let mut ctxt = self.backtrace();
873873
let mut last_macro = None;
874874
loop {
875-
if ctxt.outer().expn_info().map_or(None, |info| {
875+
if ctxt.outer_expn_info().map_or(None, |info| {
876876
if info.format.name() == sym::include {
877877
// Stop going up the backtrace once include! is encountered
878878
return None;

src/libsyntax/source_map.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@ use errors::SourceMapper;
3030
/// otherwise return the call site span up to the `enclosing_sp` by
3131
/// following the `expn_info` chain.
3232
pub fn original_sp(sp: Span, enclosing_sp: Span) -> Span {
33-
let call_site1 = sp.ctxt().outer().expn_info().map(|ei| ei.call_site);
34-
let call_site2 = enclosing_sp.ctxt().outer().expn_info().map(|ei| ei.call_site);
33+
let call_site1 = sp.ctxt().outer_expn_info().map(|ei| ei.call_site);
34+
let call_site2 = enclosing_sp.ctxt().outer_expn_info().map(|ei| ei.call_site);
3535
match (call_site1, call_site2) {
3636
(None, _) => sp,
3737
(Some(call_site1), Some(call_site2)) if call_site1 == call_site2 => sp,

src/libsyntax_ext/proc_macro_server.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -680,7 +680,7 @@ impl server::Span for Rustc<'_> {
680680
self.sess.source_map().lookup_char_pos(span.lo()).file
681681
}
682682
fn parent(&mut self, span: Self::Span) -> Option<Self::Span> {
683-
span.ctxt().outer().expn_info().map(|i| i.call_site)
683+
span.ctxt().outer_expn_info().map(|i| i.call_site)
684684
}
685685
fn source(&mut self, span: Self::Span) -> Self::Span {
686686
span.source_callsite()

src/libsyntax_pos/hygiene.rs

+37-14
Original file line numberDiff line numberDiff line change
@@ -112,16 +112,14 @@ impl Mark {
112112
HygieneData::with(|data| data.marks[self.0 as usize].default_transparency = transparency)
113113
}
114114

115-
pub fn is_descendant_of(mut self, ancestor: Mark) -> bool {
116-
HygieneData::with(|data| {
117-
while self != ancestor {
118-
if self == Mark::root() {
119-
return false;
120-
}
121-
self = data.marks[self.0 as usize].parent;
122-
}
123-
true
124-
})
115+
pub fn is_descendant_of(self, ancestor: Mark) -> bool {
116+
HygieneData::with(|data| data.is_descendant_of(self, ancestor))
117+
}
118+
119+
/// `mark.outer_is_descendant_of(ctxt)` is equivalent to but faster than
120+
/// `mark.is_descendant_of(ctxt.outer())`.
121+
pub fn outer_is_descendant_of(self, ctxt: SyntaxContext) -> bool {
122+
HygieneData::with(|data| data.is_descendant_of(self, data.outer(ctxt)))
125123
}
126124

127125
/// Computes a mark such that both input marks are descendants of (or equal to) the returned
@@ -201,6 +199,24 @@ impl HygieneData {
201199
fn with<T, F: FnOnce(&mut HygieneData) -> T>(f: F) -> T {
202200
GLOBALS.with(|globals| f(&mut *globals.hygiene_data.borrow_mut()))
203201
}
202+
203+
fn outer(&self, ctxt: SyntaxContext) -> Mark {
204+
self.syntax_contexts[ctxt.0 as usize].outer_mark
205+
}
206+
207+
fn expn_info(&self, mark: Mark) -> Option<ExpnInfo> {
208+
self.marks[mark.0 as usize].expn_info.clone()
209+
}
210+
211+
fn is_descendant_of(&self, mut mark: Mark, ancestor: Mark) -> bool {
212+
while mark != ancestor {
213+
if mark == Mark::root() {
214+
return false;
215+
}
216+
mark = self.marks[mark.0 as usize].parent;
217+
}
218+
true
219+
}
204220
}
205221

206222
pub fn clear_markings() {
@@ -416,7 +432,7 @@ impl SyntaxContext {
416432
/// or `None` if we privacy check as usual (i.e., not w.r.t. a macro definition scope).
417433
pub fn adjust(&mut self, expansion: Mark) -> Option<Mark> {
418434
let mut scope = None;
419-
while !expansion.is_descendant_of(self.outer()) {
435+
while !expansion.outer_is_descendant_of(*self) {
420436
scope = Some(self.remove_mark());
421437
}
422438
scope
@@ -450,7 +466,7 @@ impl SyntaxContext {
450466
pub fn glob_adjust(&mut self, expansion: Mark, mut glob_ctxt: SyntaxContext)
451467
-> Option<Option<Mark>> {
452468
let mut scope = None;
453-
while !expansion.is_descendant_of(glob_ctxt.outer()) {
469+
while !expansion.outer_is_descendant_of(glob_ctxt) {
454470
scope = Some(glob_ctxt.remove_mark());
455471
if self.remove_mark() != scope.unwrap() {
456472
return None;
@@ -476,7 +492,7 @@ impl SyntaxContext {
476492
}
477493

478494
let mut marks = Vec::new();
479-
while !expansion.is_descendant_of(glob_ctxt.outer()) {
495+
while !expansion.outer_is_descendant_of(glob_ctxt) {
480496
marks.push(glob_ctxt.remove_mark());
481497
}
482498

@@ -499,7 +515,14 @@ impl SyntaxContext {
499515

500516
#[inline]
501517
pub fn outer(self) -> Mark {
502-
HygieneData::with(|data| data.syntax_contexts[self.0 as usize].outer_mark)
518+
HygieneData::with(|data| data.outer(self))
519+
}
520+
521+
/// `ctxt.outer_expn_info()` is equivalent to but faster than
522+
/// `ctxt.outer().expn_info()`.
523+
#[inline]
524+
pub fn outer_expn_info(self) -> Option<ExpnInfo> {
525+
HygieneData::with(|data| data.expn_info(data.outer(self)))
503526
}
504527

505528
pub fn dollar_crate_name(self) -> Symbol {

0 commit comments

Comments
 (0)