From 145868427989655f286a3dda0cd46435bcdf42ac Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 25 Mar 2018 18:51:32 +0300 Subject: [PATCH] Fix feature gating for crate/extern in paths --- src/libsyntax/feature_gate.rs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 24bfb5d9088f..e1f1d95b8ab5 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -1766,11 +1766,19 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { fn visit_path(&mut self, path: &'a ast::Path, _id: NodeId) { for segment in &path.segments { + // Identifiers we are going to check could come from a legacy macro (e.g. `#[test]`). + // For such macros identifiers must have empty context, because this context is + // used during name resolution and produced names must be unhygienic for compatibility. + // On the other hand, we need the actual non-empty context for feature gate checking + // because it's hygienic even for legacy macros. As previously stated, such context + // cannot be kept in identifiers, so it's kept in paths instead and we take it from + // there while keeping location info from the ident span. + let span = segment.ident.span.with_ctxt(path.span.ctxt()); if segment.ident.name == keywords::Crate.name() { - gate_feature_post!(&self, crate_in_paths, segment.ident.span, + gate_feature_post!(&self, crate_in_paths, span, "`crate` in paths is experimental"); } else if segment.ident.name == keywords::Extern.name() { - gate_feature_post!(&self, extern_in_paths, segment.ident.span, + gate_feature_post!(&self, extern_in_paths, span, "`extern` in paths is experimental"); } }