]>
Commit | Line | Data |
---|---|---|
e1599b0c XL |
1 | //! A bunch of methods and structures more or less related to resolving macros and |
2 | //! interface provided by `Resolver` to macro expander. | |
3 | ||
dfeec247 | 4 | use crate::imports::ImportResolver; |
9fa01778 | 5 | use crate::Namespace::*; |
dfeec247 XL |
6 | use crate::{AmbiguityError, AmbiguityErrorMisc, AmbiguityKind, Determinacy}; |
7 | use crate::{CrateLint, ParentScope, ResolutionError, Resolver, Scope, ScopeSet, Weak}; | |
8 | use crate::{ModuleKind, ModuleOrUniformRoot, NameBinding, PathResult, Segment, ToNameBinding}; | |
f9f354fc | 9 | use rustc_ast::ast::{self, NodeId}; |
f035d41b | 10 | use rustc_ast_lowering::ResolverAstLowering; |
74b04a01 XL |
11 | use rustc_ast_pretty::pprust; |
12 | use rustc_attr::{self as attr, StabilityLevel}; | |
dfeec247 | 13 | use rustc_data_structures::fx::FxHashSet; |
f035d41b | 14 | use rustc_expand::base::{Indeterminate, InvocationRes, ResolverExpand, SyntaxExtension}; |
dfeec247 XL |
15 | use rustc_expand::compile_declarative_macro; |
16 | use rustc_expand::expand::{AstFragment, AstFragmentKind, Invocation, InvocationKind}; | |
60c5eb7d | 17 | use rustc_feature::is_builtin_attr_name; |
dfeec247 XL |
18 | use rustc_hir::def::{self, DefKind, NonMacroAttrKind}; |
19 | use rustc_hir::def_id; | |
ba9703b0 XL |
20 | use rustc_middle::middle::stability; |
21 | use rustc_middle::{span_bug, ty}; | |
22 | use rustc_session::lint::builtin::UNUSED_MACROS; | |
23 | use rustc_session::Session; | |
dfeec247 XL |
24 | use rustc_span::edition::Edition; |
25 | use rustc_span::hygiene::{self, ExpnData, ExpnId, ExpnKind}; | |
f9f354fc | 26 | use rustc_span::symbol::{kw, sym, Ident, Symbol}; |
dfeec247 | 27 | use rustc_span::{Span, DUMMY_SP}; |
9e0c209e | 28 | |
0531ce1d | 29 | use rustc_data_structures::sync::Lrc; |
dfeec247 XL |
30 | use rustc_span::hygiene::{AstPass, MacroKind}; |
31 | use std::{mem, ptr}; | |
b7449926 | 32 | |
e1599b0c | 33 | type Res = def::Res<NodeId>; |
c30ab7b3 | 34 | |
b7449926 | 35 | /// Binding produced by a `macro_rules` item. |
ba9703b0 | 36 | /// Not modularized, can shadow previous `macro_rules` bindings, etc. |
0bf4aa26 | 37 | #[derive(Debug)] |
ba9703b0 | 38 | pub struct MacroRulesBinding<'a> { |
416331ca | 39 | crate binding: &'a NameBinding<'a>, |
ba9703b0 XL |
40 | /// `macro_rules` scope into which the `macro_rules` item was planted. |
41 | crate parent_macro_rules_scope: MacroRulesScope<'a>, | |
416331ca | 42 | crate ident: Ident, |
b7449926 XL |
43 | } |
44 | ||
9fa01778 XL |
45 | /// The scope introduced by a `macro_rules!` macro. |
46 | /// This starts at the macro's definition and ends at the end of the macro's parent | |
47 | /// module (named or unnamed), or even further if it escapes with `#[macro_use]`. | |
ba9703b0 | 48 | /// Some macro invocations need to introduce `macro_rules` scopes too because they |
9fa01778 | 49 | /// can potentially expand into macro definitions. |
0bf4aa26 | 50 | #[derive(Copy, Clone, Debug)] |
ba9703b0 | 51 | pub enum MacroRulesScope<'a> { |
b7449926 | 52 | /// Empty "root" scope at the crate start containing no names. |
c30ab7b3 | 53 | Empty, |
9fa01778 | 54 | /// The scope introduced by a `macro_rules!` macro definition. |
ba9703b0 | 55 | Binding(&'a MacroRulesBinding<'a>), |
9fa01778 | 56 | /// The scope introduced by a macro invocation that can potentially |
b7449926 | 57 | /// create a `macro_rules!` macro definition. |
e1599b0c | 58 | Invocation(ExpnId), |
c30ab7b3 SL |
59 | } |
60 | ||
b7449926 XL |
61 | // Macro namespace is separated into two sub-namespaces, one for bang macros and |
62 | // one for attribute-like macros (attributes, derives). | |
63 | // We ignore resolutions from one sub-namespace when searching names in scope for another. | |
13cf67c4 | 64 | fn sub_namespace_match(candidate: Option<MacroKind>, requirement: Option<MacroKind>) -> bool { |
b7449926 | 65 | #[derive(PartialEq)] |
dfeec247 XL |
66 | enum SubNS { |
67 | Bang, | |
68 | AttrLike, | |
69 | } | |
b7449926 | 70 | let sub_ns = |kind| match kind { |
416331ca XL |
71 | MacroKind::Bang => SubNS::Bang, |
72 | MacroKind::Attr | MacroKind::Derive => SubNS::AttrLike, | |
b7449926 | 73 | }; |
416331ca XL |
74 | let candidate = candidate.map(sub_ns); |
75 | let requirement = requirement.map(sub_ns); | |
b7449926 | 76 | // "No specific sub-namespace" means "matches anything" for both requirements and candidates. |
13cf67c4 | 77 | candidate.is_none() || requirement.is_none() || candidate == requirement |
cc61c64b XL |
78 | } |
79 | ||
dc9dc135 XL |
80 | // We don't want to format a path using pretty-printing, |
81 | // `format!("{}", path)`, because that tries to insert | |
82 | // line-breaks and is slow. | |
416331ca XL |
83 | fn fast_print_path(path: &ast::Path) -> Symbol { |
84 | if path.segments.len() == 1 { | |
ba9703b0 | 85 | path.segments[0].ident.name |
416331ca XL |
86 | } else { |
87 | let mut path_str = String::with_capacity(64); | |
88 | for (i, segment) in path.segments.iter().enumerate() { | |
89 | if i != 0 { | |
90 | path_str.push_str("::"); | |
91 | } | |
92 | if segment.ident.name != kw::PathRoot { | |
93 | path_str.push_str(&segment.ident.as_str()) | |
94 | } | |
dc9dc135 | 95 | } |
416331ca | 96 | Symbol::intern(&path_str) |
dc9dc135 | 97 | } |
dc9dc135 XL |
98 | } |
99 | ||
60c5eb7d XL |
100 | /// The code common between processing `#![register_tool]` and `#![register_attr]`. |
101 | fn registered_idents( | |
102 | sess: &Session, | |
103 | attrs: &[ast::Attribute], | |
104 | attr_name: Symbol, | |
105 | descr: &str, | |
106 | ) -> FxHashSet<Ident> { | |
107 | let mut registered = FxHashSet::default(); | |
108 | for attr in attr::filter_by_name(attrs, attr_name) { | |
109 | for nested_meta in attr.meta_item_list().unwrap_or_default() { | |
110 | match nested_meta.ident() { | |
dfeec247 XL |
111 | Some(ident) => { |
112 | if let Some(old_ident) = registered.replace(ident) { | |
113 | let msg = format!("{} `{}` was already registered", descr, ident); | |
114 | sess.struct_span_err(ident.span, &msg) | |
115 | .span_label(old_ident.span, "already registered here") | |
116 | .emit(); | |
117 | } | |
60c5eb7d XL |
118 | } |
119 | None => { | |
120 | let msg = format!("`{}` only accepts identifiers", attr_name); | |
121 | let span = nested_meta.span(); | |
122 | sess.struct_span_err(span, &msg).span_label(span, "not an identifier").emit(); | |
123 | } | |
124 | } | |
125 | } | |
126 | } | |
127 | registered | |
128 | } | |
129 | ||
130 | crate fn registered_attrs_and_tools( | |
131 | sess: &Session, | |
132 | attrs: &[ast::Attribute], | |
133 | ) -> (FxHashSet<Ident>, FxHashSet<Ident>) { | |
134 | let registered_attrs = registered_idents(sess, attrs, sym::register_attr, "attribute"); | |
135 | let mut registered_tools = registered_idents(sess, attrs, sym::register_tool, "tool"); | |
136 | // We implicitly add `rustfmt` and `clippy` to known tools, | |
137 | // but it's not an error to register them explicitly. | |
138 | let predefined_tools = [sym::clippy, sym::rustfmt]; | |
139 | registered_tools.extend(predefined_tools.iter().cloned().map(Ident::with_dummy_span)); | |
140 | (registered_attrs, registered_tools) | |
141 | } | |
142 | ||
f035d41b | 143 | impl<'a> ResolverExpand for Resolver<'a> { |
e1599b0c | 144 | fn next_node_id(&mut self) -> NodeId { |
60c5eb7d | 145 | self.next_node_id() |
9e0c209e SL |
146 | } |
147 | ||
416331ca XL |
148 | fn resolve_dollar_crates(&mut self) { |
149 | hygiene::update_dollar_crate_names(|ctxt| { | |
150 | let ident = Ident::new(kw::DollarCrate, DUMMY_SP.with_ctxt(ctxt)); | |
151 | match self.resolve_crate_root(ident).kind { | |
152 | ModuleKind::Def(.., name) if name != kw::Invalid => name, | |
153 | _ => kw::Crate, | |
476ff2be | 154 | } |
416331ca | 155 | }); |
32a655c1 SL |
156 | } |
157 | ||
e74abb32 | 158 | fn visit_ast_fragment_with_placeholders(&mut self, expansion: ExpnId, fragment: &AstFragment) { |
e1599b0c XL |
159 | // Integrate the new AST fragment into all the definition and module structures. |
160 | // We are inside the `expansion` now, but other parent scope components are still the same. | |
161 | let parent_scope = ParentScope { expansion, ..self.invocation_parent_scopes[&expansion] }; | |
ba9703b0 XL |
162 | let output_macro_rules_scope = self.build_reduced_graph(fragment, parent_scope); |
163 | self.output_macro_rules_scopes.insert(expansion, output_macro_rules_scope); | |
e1599b0c XL |
164 | |
165 | parent_scope.module.unexpanded_invocations.borrow_mut().remove(&expansion); | |
9e0c209e SL |
166 | } |
167 | ||
f9f354fc | 168 | fn register_builtin_macro(&mut self, ident: Ident, ext: SyntaxExtension) { |
416331ca | 169 | if self.builtin_macros.insert(ident.name, ext).is_some() { |
dfeec247 XL |
170 | self.session |
171 | .span_err(ident.span, &format!("built-in macro `{}` was already defined", ident)); | |
b7449926 | 172 | } |
9e0c209e SL |
173 | } |
174 | ||
e1599b0c XL |
175 | // Create a new Expansion with a definition site of the provided module, or |
176 | // a fake empty `#[no_implicit_prelude]` module if no module is provided. | |
177 | fn expansion_for_ast_pass( | |
178 | &mut self, | |
179 | call_site: Span, | |
180 | pass: AstPass, | |
181 | features: &[Symbol], | |
182 | parent_module_id: Option<NodeId>, | |
183 | ) -> ExpnId { | |
184 | let expn_id = ExpnId::fresh(Some(ExpnData::allow_unstable( | |
185 | ExpnKind::AstPass(pass), | |
186 | call_site, | |
187 | self.session.edition(), | |
188 | features.into(), | |
f9f354fc | 189 | None, |
e1599b0c XL |
190 | ))); |
191 | ||
192 | let parent_scope = if let Some(module_id) = parent_module_id { | |
f035d41b | 193 | let parent_def_id = self.local_def_id(module_id); |
ba9703b0 | 194 | self.definitions.add_parent_module_of_macro_def(expn_id, parent_def_id.to_def_id()); |
e1599b0c XL |
195 | self.module_map[&parent_def_id] |
196 | } else { | |
197 | self.definitions.add_parent_module_of_macro_def( | |
198 | expn_id, | |
199 | def_id::DefId::local(def_id::CRATE_DEF_INDEX), | |
200 | ); | |
201 | self.empty_module | |
202 | }; | |
203 | self.ast_transform_scopes.insert(expn_id, parent_scope); | |
204 | expn_id | |
205 | } | |
206 | ||
476ff2be | 207 | fn resolve_imports(&mut self) { |
416331ca | 208 | ImportResolver { r: self }.resolve_imports() |
476ff2be SL |
209 | } |
210 | ||
e1599b0c | 211 | fn resolve_macro_invocation( |
dfeec247 XL |
212 | &mut self, |
213 | invoc: &Invocation, | |
214 | eager_expansion_root: ExpnId, | |
215 | force: bool, | |
e1599b0c | 216 | ) -> Result<InvocationRes, Indeterminate> { |
416331ca | 217 | let invoc_id = invoc.expansion_data.id; |
e1599b0c XL |
218 | let parent_scope = match self.invocation_parent_scopes.get(&invoc_id) { |
219 | Some(parent_scope) => *parent_scope, | |
220 | None => { | |
221 | // If there's no entry in the table, then we are resolving an eagerly expanded | |
222 | // macro, which should inherit its parent scope from its eager expansion root - | |
223 | // the macro that requested this eager expansion. | |
dfeec247 XL |
224 | let parent_scope = *self |
225 | .invocation_parent_scopes | |
226 | .get(&eager_expansion_root) | |
e1599b0c XL |
227 | .expect("non-eager expansion without a parent scope"); |
228 | self.invocation_parent_scopes.insert(invoc_id, parent_scope); | |
229 | parent_scope | |
230 | } | |
231 | }; | |
232 | ||
233 | let (path, kind, derives, after_derive) = match invoc.kind { | |
dfeec247 XL |
234 | InvocationKind::Attr { ref attr, ref derives, after_derive, .. } => ( |
235 | &attr.get_normal_item().path, | |
236 | MacroKind::Attr, | |
237 | self.arenas.alloc_ast_paths(derives), | |
238 | after_derive, | |
239 | ), | |
240 | InvocationKind::Bang { ref mac, .. } => (&mac.path, MacroKind::Bang, &[][..], false), | |
241 | InvocationKind::Derive { ref path, .. } => (path, MacroKind::Derive, &[][..], false), | |
416331ca | 242 | InvocationKind::DeriveContainer { ref derives, .. } => { |
e1599b0c XL |
243 | // Block expansion of the container until we resolve all derives in it. |
244 | // This is required for two reasons: | |
245 | // - Derive helper attributes are in scope for the item to which the `#[derive]` | |
246 | // is applied, so they have to be produced by the container's expansion rather | |
247 | // than by individual derives. | |
248 | // - Derives in the container need to know whether one of them is a built-in `Copy`. | |
249 | // FIXME: Try to avoid repeated resolutions for derives here and in expansion. | |
250 | let mut exts = Vec::new(); | |
60c5eb7d | 251 | let mut helper_attrs = Vec::new(); |
e1599b0c | 252 | for path in derives { |
dfeec247 XL |
253 | exts.push( |
254 | match self.resolve_macro_path( | |
255 | path, | |
256 | Some(MacroKind::Derive), | |
257 | &parent_scope, | |
258 | true, | |
259 | force, | |
260 | ) { | |
261 | Ok((Some(ext), _)) => { | |
ba9703b0 XL |
262 | let span = path |
263 | .segments | |
264 | .last() | |
265 | .unwrap() | |
266 | .ident | |
267 | .span | |
268 | .normalize_to_macros_2_0(); | |
dfeec247 XL |
269 | helper_attrs.extend( |
270 | ext.helper_attrs.iter().map(|name| Ident::new(*name, span)), | |
271 | ); | |
272 | if ext.is_derive_copy { | |
273 | self.add_derive_copy(invoc_id); | |
274 | } | |
275 | ext | |
60c5eb7d | 276 | } |
dfeec247 XL |
277 | Ok(_) | Err(Determinacy::Determined) => { |
278 | self.dummy_ext(MacroKind::Derive) | |
279 | } | |
280 | Err(Determinacy::Undetermined) => return Err(Indeterminate), | |
281 | }, | |
282 | ) | |
416331ca | 283 | } |
60c5eb7d | 284 | self.helper_attrs.insert(invoc_id, helper_attrs); |
e1599b0c | 285 | return Ok(InvocationRes::DeriveContainer(exts)); |
416331ca | 286 | } |
8bb4bdeb | 287 | }; |
b7449926 | 288 | |
e1599b0c XL |
289 | // Derives are not included when `invocations` are collected, so we have to add them here. |
290 | let parent_scope = &ParentScope { derives, ..parent_scope }; | |
f035d41b XL |
291 | let node_id = self.lint_node_id(eager_expansion_root); |
292 | let (ext, res) = self.smart_resolve_macro_path(path, kind, parent_scope, node_id, force)?; | |
b7449926 | 293 | |
416331ca | 294 | let span = invoc.span(); |
f9f354fc XL |
295 | invoc_id.set_expn_data(ext.expn_data( |
296 | parent_scope.expansion, | |
297 | span, | |
298 | fast_print_path(path), | |
299 | res.opt_def_id(), | |
300 | )); | |
301 | ||
302 | if let Res::Def(_, _) = res { | |
0bf4aa26 | 303 | if after_derive { |
416331ca | 304 | self.session.span_err(span, "macro attributes must be placed before `#[derive]`"); |
b7449926 | 305 | } |
416331ca XL |
306 | let normal_module_def_id = self.macro_def_scope(invoc_id).normal_ancestor_id; |
307 | self.definitions.add_parent_module_of_macro_def(invoc_id, normal_module_def_id); | |
8faf50e0 | 308 | } |
b7449926 | 309 | |
e1599b0c XL |
310 | match invoc.fragment_kind { |
311 | AstFragmentKind::Arms | |
dfeec247 XL |
312 | | AstFragmentKind::Fields |
313 | | AstFragmentKind::FieldPats | |
314 | | AstFragmentKind::GenericParams | |
315 | | AstFragmentKind::Params | |
316 | | AstFragmentKind::StructFields | |
317 | | AstFragmentKind::Variants => { | |
e1599b0c XL |
318 | if let Res::Def(..) = res { |
319 | self.session.span_err( | |
320 | span, | |
dfeec247 XL |
321 | &format!( |
322 | "expected an inert attribute, found {} {}", | |
323 | res.article(), | |
324 | res.descr() | |
325 | ), | |
e1599b0c XL |
326 | ); |
327 | return Ok(InvocationRes::Single(self.dummy_ext(kind))); | |
328 | } | |
dfeec247 | 329 | } |
e1599b0c XL |
330 | _ => {} |
331 | } | |
332 | ||
333 | Ok(InvocationRes::Single(ext)) | |
8bb4bdeb XL |
334 | } |
335 | ||
e74abb32 | 336 | fn check_unused_macros(&mut self) { |
f9f354fc | 337 | for (_, &(node_id, span)) in self.unused_macros.iter() { |
ba9703b0 | 338 | self.lint_buffer.buffer_lint(UNUSED_MACROS, node_id, span, "unused macro definition"); |
7cac9316 | 339 | } |
8bb4bdeb | 340 | } |
416331ca | 341 | |
f035d41b XL |
342 | fn lint_node_id(&mut self, expn_id: ExpnId) -> NodeId { |
343 | self.invocation_parents | |
344 | .get(&expn_id) | |
345 | .map_or(ast::CRATE_NODE_ID, |id| self.def_id_to_node_id[*id]) | |
346 | } | |
347 | ||
60c5eb7d XL |
348 | fn has_derive_copy(&self, expn_id: ExpnId) -> bool { |
349 | self.containers_deriving_copy.contains(&expn_id) | |
416331ca XL |
350 | } |
351 | ||
60c5eb7d XL |
352 | fn add_derive_copy(&mut self, expn_id: ExpnId) { |
353 | self.containers_deriving_copy.insert(expn_id); | |
416331ca | 354 | } |
ba9703b0 XL |
355 | |
356 | // The function that implements the resolution logic of `#[cfg_accessible(path)]`. | |
357 | // Returns true if the path can certainly be resolved in one of three namespaces, | |
358 | // returns false if the path certainly cannot be resolved in any of the three namespaces. | |
359 | // Returns `Indeterminate` if we cannot give a certain answer yet. | |
360 | fn cfg_accessible(&mut self, expn_id: ExpnId, path: &ast::Path) -> Result<bool, Indeterminate> { | |
361 | let span = path.span; | |
362 | let path = &Segment::from_path(path); | |
363 | let parent_scope = self.invocation_parent_scopes[&expn_id]; | |
364 | ||
365 | let mut indeterminate = false; | |
366 | for ns in [TypeNS, ValueNS, MacroNS].iter().copied() { | |
367 | match self.resolve_path(path, Some(ns), &parent_scope, false, span, CrateLint::No) { | |
368 | PathResult::Module(ModuleOrUniformRoot::Module(_)) => return Ok(true), | |
369 | PathResult::NonModule(partial_res) if partial_res.unresolved_segments() == 0 => { | |
370 | return Ok(true); | |
371 | } | |
372 | PathResult::Indeterminate => indeterminate = true, | |
373 | // FIXME: `resolve_path` is not ready to report partially resolved paths | |
374 | // correctly, so we just report an error if the path was reported as unresolved. | |
375 | // This needs to be fixed for `cfg_accessible` to be useful. | |
376 | PathResult::NonModule(..) | PathResult::Failed { .. } => {} | |
377 | PathResult::Module(_) => panic!("unexpected path resolution"), | |
378 | } | |
379 | } | |
380 | ||
381 | if indeterminate { | |
382 | return Err(Indeterminate); | |
383 | } | |
384 | ||
385 | self.session | |
386 | .struct_span_err(span, "not sure whether the path is accessible or not") | |
387 | .span_note(span, "`cfg_accessible` is not fully implemented") | |
388 | .emit(); | |
389 | Ok(false) | |
390 | } | |
8bb4bdeb XL |
391 | } |
392 | ||
0731742a | 393 | impl<'a> Resolver<'a> { |
416331ca XL |
394 | /// Resolve macro path with error reporting and recovery. |
395 | fn smart_resolve_macro_path( | |
b7449926 XL |
396 | &mut self, |
397 | path: &ast::Path, | |
398 | kind: MacroKind, | |
399 | parent_scope: &ParentScope<'a>, | |
f035d41b | 400 | node_id: NodeId, |
b7449926 | 401 | force: bool, |
416331ca | 402 | ) -> Result<(Lrc<SyntaxExtension>, Res), Indeterminate> { |
dfeec247 XL |
403 | let (ext, res) = match self.resolve_macro_path(path, Some(kind), parent_scope, true, force) |
404 | { | |
416331ca XL |
405 | Ok((Some(ext), res)) => (ext, res), |
406 | // Use dummy syntax extensions for unresolved macros for better recovery. | |
407 | Ok((None, res)) => (self.dummy_ext(kind), res), | |
408 | Err(Determinacy::Determined) => (self.dummy_ext(kind), Res::Err), | |
409 | Err(Determinacy::Undetermined) => return Err(Indeterminate), | |
410 | }; | |
b7449926 | 411 | |
ba9703b0 | 412 | // Report errors for the resolved macro. |
416331ca XL |
413 | for segment in &path.segments { |
414 | if let Some(args) = &segment.args { | |
415 | self.session.span_err(args.span(), "generic arguments in macro path"); | |
416 | } | |
ba9703b0 XL |
417 | if kind == MacroKind::Attr && segment.ident.as_str().starts_with("rustc") { |
418 | self.session.span_err( | |
419 | segment.ident.span, | |
420 | "attributes starting with `rustc` are reserved for use by the `rustc` compiler", | |
421 | ); | |
8bb4bdeb XL |
422 | } |
423 | } | |
424 | ||
48663c56 | 425 | match res { |
416331ca | 426 | Res::Def(DefKind::Macro(_), def_id) => { |
f9f354fc XL |
427 | if let Some(def_id) = def_id.as_local() { |
428 | self.unused_macros.remove(&def_id); | |
429 | if self.proc_macro_stubs.contains(&def_id) { | |
416331ca XL |
430 | self.session.span_err( |
431 | path.span, | |
432 | "can't use a procedural macro from the same crate that defines it", | |
433 | ); | |
b7449926 | 434 | } |
b7449926 | 435 | } |
83c7162d | 436 | } |
416331ca | 437 | Res::NonMacroAttr(..) | Res::Err => {} |
48663c56 | 438 | _ => panic!("expected `DefKind::Macro` or `Res::NonMacroAttr`"), |
416331ca | 439 | }; |
9fa01778 | 440 | |
f035d41b | 441 | self.check_stability_and_deprecation(&ext, path, node_id); |
9fa01778 | 442 | |
416331ca | 443 | Ok(if ext.macro_kind() != kind { |
e1599b0c | 444 | let expected = kind.descr_expected(); |
e74abb32 XL |
445 | let path_str = pprust::path_to_string(path); |
446 | let msg = format!("expected {}, found {} `{}`", expected, res.descr(), path_str); | |
dfeec247 XL |
447 | self.session |
448 | .struct_span_err(path.span, &msg) | |
449 | .span_label(path.span, format!("not {} {}", kind.article(), expected)) | |
450 | .emit(); | |
416331ca XL |
451 | // Use dummy syntax extensions for unexpected macro kinds for better recovery. |
452 | (self.dummy_ext(kind), Res::Err) | |
453 | } else { | |
454 | (ext, res) | |
455 | }) | |
9fa01778 XL |
456 | } |
457 | ||
416331ca | 458 | pub fn resolve_macro_path( |
b7449926 XL |
459 | &mut self, |
460 | path: &ast::Path, | |
416331ca | 461 | kind: Option<MacroKind>, |
b7449926 | 462 | parent_scope: &ParentScope<'a>, |
13cf67c4 | 463 | trace: bool, |
b7449926 | 464 | force: bool, |
416331ca | 465 | ) -> Result<(Option<Lrc<SyntaxExtension>>, Res), Determinacy> { |
0bf4aa26 | 466 | let path_span = path.span; |
13cf67c4 | 467 | let mut path = Segment::from_path(path); |
476ff2be | 468 | |
8faf50e0 | 469 | // Possibly apply the macro helper hack |
dfeec247 XL |
470 | if kind == Some(MacroKind::Bang) |
471 | && path.len() == 1 | |
472 | && path[0].ident.span.ctxt().outer_expn_data().local_inner_macros | |
473 | { | |
dc9dc135 | 474 | let root = Ident::new(kw::DollarCrate, path[0].ident.span); |
13cf67c4 | 475 | path.insert(0, Segment::from_ident(root)); |
8faf50e0 XL |
476 | } |
477 | ||
416331ca | 478 | let res = if path.len() > 1 { |
dfeec247 XL |
479 | let res = match self.resolve_path( |
480 | &path, | |
481 | Some(MacroNS), | |
482 | parent_scope, | |
483 | false, | |
484 | path_span, | |
485 | CrateLint::No, | |
486 | ) { | |
13cf67c4 | 487 | PathResult::NonModule(path_res) if path_res.unresolved_segments() == 0 => { |
48663c56 | 488 | Ok(path_res.base_res()) |
13cf67c4 | 489 | } |
476ff2be | 490 | PathResult::Indeterminate if !force => return Err(Determinacy::Undetermined), |
532ac7d7 XL |
491 | PathResult::NonModule(..) |
492 | | PathResult::Indeterminate | |
493 | | PathResult::Failed { .. } => Err(Determinacy::Determined), | |
13cf67c4 | 494 | PathResult::Module(..) => unreachable!(), |
476ff2be | 495 | }; |
0bf4aa26 | 496 | |
13cf67c4 | 497 | if trace { |
416331ca | 498 | let kind = kind.expect("macro kind must be specified if tracing is enabled"); |
dfeec247 XL |
499 | self.multi_segment_macro_resolutions.push(( |
500 | path, | |
501 | path_span, | |
502 | kind, | |
503 | *parent_scope, | |
504 | res.ok(), | |
505 | )); | |
13cf67c4 | 506 | } |
476ff2be | 507 | |
48663c56 XL |
508 | self.prohibit_imported_non_macro_attrs(None, res.ok(), path_span); |
509 | res | |
cc61c64b | 510 | } else { |
416331ca | 511 | let scope_set = kind.map_or(ScopeSet::All(MacroNS, false), ScopeSet::Macro); |
0bf4aa26 | 512 | let binding = self.early_resolve_ident_in_lexical_scope( |
dfeec247 XL |
513 | path[0].ident, |
514 | scope_set, | |
515 | parent_scope, | |
516 | false, | |
517 | force, | |
518 | path_span, | |
0bf4aa26 | 519 | ); |
0731742a XL |
520 | if let Err(Determinacy::Undetermined) = binding { |
521 | return Err(Determinacy::Undetermined); | |
cc61c64b | 522 | } |
476ff2be | 523 | |
13cf67c4 | 524 | if trace { |
416331ca | 525 | let kind = kind.expect("macro kind must be specified if tracing is enabled"); |
dfeec247 XL |
526 | self.single_segment_macro_resolutions.push(( |
527 | path[0].ident, | |
528 | kind, | |
529 | *parent_scope, | |
530 | binding.ok(), | |
531 | )); | |
13cf67c4 | 532 | } |
8bb4bdeb | 533 | |
48663c56 XL |
534 | let res = binding.map(|binding| binding.res()); |
535 | self.prohibit_imported_non_macro_attrs(binding.ok(), res.ok(), path_span); | |
536 | res | |
416331ca XL |
537 | }; |
538 | ||
539 | res.map(|res| (self.get_macro(res), res)) | |
c30ab7b3 | 540 | } |
9e0c209e | 541 | |
0bf4aa26 | 542 | // Resolve an identifier in lexical scope. |
b7449926 XL |
543 | // This is a variation of `fn resolve_ident_in_lexical_scope` that can be run during |
544 | // expansion and import resolution (perhaps they can be merged in the future). | |
0731742a | 545 | // The function is used for resolving initial segments of macro paths (e.g., `foo` in |
13cf67c4 | 546 | // `foo::bar!(); or `foo!();`) and also for import paths on 2018 edition. |
0bf4aa26 | 547 | crate fn early_resolve_ident_in_lexical_scope( |
b7449926 | 548 | &mut self, |
13cf67c4 XL |
549 | orig_ident: Ident, |
550 | scope_set: ScopeSet, | |
b7449926 XL |
551 | parent_scope: &ParentScope<'a>, |
552 | record_used: bool, | |
553 | force: bool, | |
554 | path_span: Span, | |
0bf4aa26 | 555 | ) -> Result<&'a NameBinding<'a>, Determinacy> { |
9fa01778 | 556 | bitflags::bitflags! { |
0bf4aa26 | 557 | struct Flags: u8 { |
60c5eb7d XL |
558 | const MACRO_RULES = 1 << 0; |
559 | const MODULE = 1 << 1; | |
560 | const DERIVE_HELPER_COMPAT = 1 << 2; | |
561 | const MISC_SUGGEST_CRATE = 1 << 3; | |
562 | const MISC_SUGGEST_SELF = 1 << 4; | |
563 | const MISC_FROM_PRELUDE = 1 << 5; | |
0bf4aa26 XL |
564 | } |
565 | } | |
b7449926 | 566 | |
b7449926 | 567 | assert!(force || !record_used); // `record_used` implies `force` |
13cf67c4 XL |
568 | |
569 | // Make sure `self`, `super` etc produce an error when passed to here. | |
416331ca | 570 | if orig_ident.is_path_segment_keyword() { |
13cf67c4 XL |
571 | return Err(Determinacy::Determined); |
572 | } | |
b7449926 | 573 | |
416331ca XL |
574 | let (ns, macro_kind, is_import) = match scope_set { |
575 | ScopeSet::All(ns, is_import) => (ns, None, is_import), | |
576 | ScopeSet::AbsolutePath(ns) => (ns, None, false), | |
577 | ScopeSet::Macro(macro_kind) => (MacroNS, Some(macro_kind), false), | |
578 | }; | |
579 | ||
b7449926 XL |
580 | // This is *the* result, resolution from the scope closest to the resolved identifier. |
581 | // However, sometimes this result is "weak" because it comes from a glob import or | |
582 | // a macro expansion, and in this case it cannot shadow names from outer scopes, e.g. | |
583 | // mod m { ... } // solution in outer scope | |
584 | // { | |
585 | // use prefix::*; // imports another `m` - innermost solution | |
586 | // // weak, cannot shadow the outer `m`, need to report ambiguity error | |
587 | // m::mac!(); | |
588 | // } | |
589 | // So we have to save the innermost solution and continue searching in outer scopes | |
590 | // to detect potential ambiguities. | |
9fa01778 | 591 | let mut innermost_result: Option<(&NameBinding<'_>, Flags)> = None; |
416331ca | 592 | let mut determinacy = Determinacy::Determined; |
b7449926 XL |
593 | |
594 | // Go through all the scopes and try to resolve the name. | |
dfeec247 XL |
595 | let break_result = self.visit_scopes( |
596 | scope_set, | |
597 | parent_scope, | |
598 | orig_ident, | |
599 | |this, scope, use_prelude, ident| { | |
600 | let ok = |res, span, arenas| { | |
601 | Ok(( | |
602 | (res, ty::Visibility::Public, span, ExpnId::root()).to_name_binding(arenas), | |
603 | Flags::empty(), | |
604 | )) | |
605 | }; | |
606 | let result = match scope { | |
607 | Scope::DeriveHelpers(expn_id) => { | |
608 | if let Some(attr) = this | |
609 | .helper_attrs | |
610 | .get(&expn_id) | |
611 | .and_then(|attrs| attrs.iter().rfind(|i| ident == **i)) | |
612 | { | |
613 | let binding = ( | |
614 | Res::NonMacroAttr(NonMacroAttrKind::DeriveHelper), | |
615 | ty::Visibility::Public, | |
616 | attr.span, | |
617 | expn_id, | |
618 | ) | |
619 | .to_name_binding(this.arenas); | |
620 | Ok((binding, Flags::empty())) | |
621 | } else { | |
622 | Err(Determinacy::Determined) | |
623 | } | |
60c5eb7d | 624 | } |
dfeec247 XL |
625 | Scope::DeriveHelpersCompat => { |
626 | let mut result = Err(Determinacy::Determined); | |
627 | for derive in parent_scope.derives { | |
628 | let parent_scope = &ParentScope { derives: &[], ..*parent_scope }; | |
629 | match this.resolve_macro_path( | |
630 | derive, | |
631 | Some(MacroKind::Derive), | |
632 | parent_scope, | |
633 | true, | |
634 | force, | |
635 | ) { | |
636 | Ok((Some(ext), _)) => { | |
637 | if ext.helper_attrs.contains(&ident.name) { | |
638 | let binding = ( | |
639 | Res::NonMacroAttr(NonMacroAttrKind::DeriveHelper), | |
640 | ty::Visibility::Public, | |
641 | derive.span, | |
642 | ExpnId::root(), | |
643 | ) | |
644 | .to_name_binding(this.arenas); | |
645 | result = Ok((binding, Flags::DERIVE_HELPER_COMPAT)); | |
646 | break; | |
647 | } | |
648 | } | |
649 | Ok(_) | Err(Determinacy::Determined) => {} | |
650 | Err(Determinacy::Undetermined) => { | |
651 | result = Err(Determinacy::Undetermined) | |
652 | } | |
0bf4aa26 XL |
653 | } |
654 | } | |
dfeec247 | 655 | result |
0bf4aa26 | 656 | } |
ba9703b0 XL |
657 | Scope::MacroRules(macro_rules_scope) => match macro_rules_scope { |
658 | MacroRulesScope::Binding(macro_rules_binding) | |
659 | if ident == macro_rules_binding.ident => | |
660 | { | |
661 | Ok((macro_rules_binding.binding, Flags::MACRO_RULES)) | |
13cf67c4 | 662 | } |
ba9703b0 XL |
663 | MacroRulesScope::Invocation(invoc_id) |
664 | if !this.output_macro_rules_scopes.contains_key(&invoc_id) => | |
dfeec247 XL |
665 | { |
666 | Err(Determinacy::Undetermined) | |
667 | } | |
668 | _ => Err(Determinacy::Determined), | |
669 | }, | |
670 | Scope::CrateRoot => { | |
671 | let root_ident = Ident::new(kw::PathRoot, ident.span); | |
672 | let root_module = this.resolve_crate_root(root_ident); | |
673 | let binding = this.resolve_ident_in_module_ext( | |
674 | ModuleOrUniformRoot::Module(root_module), | |
416331ca XL |
675 | ident, |
676 | ns, | |
677 | parent_scope, | |
dfeec247 | 678 | record_used, |
416331ca | 679 | path_span, |
dfeec247 XL |
680 | ); |
681 | match binding { | |
682 | Ok(binding) => Ok((binding, Flags::MODULE | Flags::MISC_SUGGEST_CRATE)), | |
683 | Err((Determinacy::Undetermined, Weak::No)) => { | |
684 | return Some(Err(Determinacy::determined(force))); | |
685 | } | |
686 | Err((Determinacy::Undetermined, Weak::Yes)) => { | |
687 | Err(Determinacy::Undetermined) | |
b7449926 | 688 | } |
dfeec247 | 689 | Err((Determinacy::Determined, _)) => Err(Determinacy::Determined), |
b7449926 XL |
690 | } |
691 | } | |
dfeec247 XL |
692 | Scope::Module(module) => { |
693 | let adjusted_parent_scope = &ParentScope { module, ..*parent_scope }; | |
694 | let binding = this.resolve_ident_in_module_unadjusted_ext( | |
695 | ModuleOrUniformRoot::Module(module), | |
696 | ident, | |
697 | ns, | |
698 | adjusted_parent_scope, | |
699 | true, | |
700 | record_used, | |
701 | path_span, | |
702 | ); | |
703 | match binding { | |
704 | Ok(binding) => { | |
705 | let misc_flags = if ptr::eq(module, this.graph_root) { | |
706 | Flags::MISC_SUGGEST_CRATE | |
707 | } else if module.is_normal() { | |
708 | Flags::MISC_SUGGEST_SELF | |
709 | } else { | |
710 | Flags::empty() | |
711 | }; | |
712 | Ok((binding, Flags::MODULE | misc_flags)) | |
713 | } | |
714 | Err((Determinacy::Undetermined, Weak::No)) => { | |
715 | return Some(Err(Determinacy::determined(force))); | |
716 | } | |
717 | Err((Determinacy::Undetermined, Weak::Yes)) => { | |
718 | Err(Determinacy::Undetermined) | |
719 | } | |
720 | Err((Determinacy::Determined, _)) => Err(Determinacy::Determined), | |
721 | } | |
722 | } | |
723 | Scope::RegisteredAttrs => match this.registered_attrs.get(&ident).cloned() { | |
724 | Some(ident) => ok( | |
725 | Res::NonMacroAttr(NonMacroAttrKind::Registered), | |
726 | ident.span, | |
727 | this.arenas, | |
728 | ), | |
729 | None => Err(Determinacy::Determined), | |
730 | }, | |
731 | Scope::MacroUsePrelude => { | |
732 | match this.macro_use_prelude.get(&ident.name).cloned() { | |
733 | Some(binding) => Ok((binding, Flags::MISC_FROM_PRELUDE)), | |
734 | None => Err(Determinacy::determined( | |
735 | this.graph_root.unexpanded_invocations.borrow().is_empty(), | |
736 | )), | |
737 | } | |
738 | } | |
739 | Scope::BuiltinAttrs => { | |
740 | if is_builtin_attr_name(ident.name) { | |
741 | ok(Res::NonMacroAttr(NonMacroAttrKind::Builtin), DUMMY_SP, this.arenas) | |
742 | } else { | |
743 | Err(Determinacy::Determined) | |
744 | } | |
7cac9316 | 745 | } |
dfeec247 XL |
746 | Scope::ExternPrelude => match this.extern_prelude_get(ident, !record_used) { |
747 | Some(binding) => Ok((binding, Flags::empty())), | |
748 | None => Err(Determinacy::determined( | |
749 | this.graph_root.unexpanded_invocations.borrow().is_empty(), | |
750 | )), | |
751 | }, | |
752 | Scope::ToolPrelude => match this.registered_tools.get(&ident).cloned() { | |
753 | Some(ident) => ok(Res::ToolMod, ident.span, this.arenas), | |
754 | None => Err(Determinacy::Determined), | |
755 | }, | |
756 | Scope::StdLibPrelude => { | |
757 | let mut result = Err(Determinacy::Determined); | |
758 | if let Some(prelude) = this.prelude { | |
759 | if let Ok(binding) = this.resolve_ident_in_module_unadjusted( | |
760 | ModuleOrUniformRoot::Module(prelude), | |
761 | ident, | |
762 | ns, | |
763 | parent_scope, | |
764 | false, | |
765 | path_span, | |
766 | ) { | |
767 | if use_prelude || this.is_builtin_macro(binding.res()) { | |
768 | result = Ok((binding, Flags::MISC_FROM_PRELUDE)); | |
769 | } | |
770 | } | |
771 | } | |
772 | result | |
773 | } | |
774 | Scope::BuiltinTypes => { | |
775 | match this.primitive_type_table.primitive_types.get(&ident.name).cloned() { | |
776 | Some(prim_ty) => ok(Res::PrimTy(prim_ty), DUMMY_SP, this.arenas), | |
777 | None => Err(Determinacy::Determined), | |
778 | } | |
779 | } | |
780 | }; | |
781 | ||
782 | match result { | |
783 | Ok((binding, flags)) | |
784 | if sub_namespace_match(binding.macro_kind(), macro_kind) => | |
785 | { | |
786 | if !record_used { | |
787 | return Some(Ok(binding)); | |
788 | } | |
789 | ||
790 | if let Some((innermost_binding, innermost_flags)) = innermost_result { | |
791 | // Found another solution, if the first one was "weak", report an error. | |
792 | let (res, innermost_res) = (binding.res(), innermost_binding.res()); | |
793 | if res != innermost_res { | |
794 | let builtin = Res::NonMacroAttr(NonMacroAttrKind::Builtin); | |
795 | let is_derive_helper_compat = |res, flags: Flags| { | |
796 | res == Res::NonMacroAttr(NonMacroAttrKind::DeriveHelper) | |
797 | && flags.contains(Flags::DERIVE_HELPER_COMPAT) | |
798 | }; | |
b7449926 | 799 | |
dfeec247 XL |
800 | let ambiguity_error_kind = if is_import { |
801 | Some(AmbiguityKind::Import) | |
802 | } else if innermost_res == builtin || res == builtin { | |
803 | Some(AmbiguityKind::BuiltinAttr) | |
804 | } else if is_derive_helper_compat(innermost_res, innermost_flags) | |
805 | || is_derive_helper_compat(res, flags) | |
806 | { | |
807 | Some(AmbiguityKind::DeriveHelper) | |
808 | } else if innermost_flags.contains(Flags::MACRO_RULES) | |
809 | && flags.contains(Flags::MODULE) | |
ba9703b0 XL |
810 | && !this.disambiguate_macro_rules_vs_modularized( |
811 | innermost_binding, | |
812 | binding, | |
813 | ) | |
dfeec247 XL |
814 | || flags.contains(Flags::MACRO_RULES) |
815 | && innermost_flags.contains(Flags::MODULE) | |
ba9703b0 | 816 | && !this.disambiguate_macro_rules_vs_modularized( |
dfeec247 XL |
817 | binding, |
818 | innermost_binding, | |
819 | ) | |
820 | { | |
ba9703b0 | 821 | Some(AmbiguityKind::MacroRulesVsModularized) |
dfeec247 XL |
822 | } else if innermost_binding.is_glob_import() { |
823 | Some(AmbiguityKind::GlobVsOuter) | |
824 | } else if innermost_binding | |
825 | .may_appear_after(parent_scope.expansion, binding) | |
826 | { | |
827 | Some(AmbiguityKind::MoreExpandedVsOuter) | |
13cf67c4 | 828 | } else { |
dfeec247 | 829 | None |
13cf67c4 | 830 | }; |
dfeec247 XL |
831 | if let Some(kind) = ambiguity_error_kind { |
832 | let misc = |f: Flags| { | |
833 | if f.contains(Flags::MISC_SUGGEST_CRATE) { | |
834 | AmbiguityErrorMisc::SuggestCrate | |
835 | } else if f.contains(Flags::MISC_SUGGEST_SELF) { | |
836 | AmbiguityErrorMisc::SuggestSelf | |
837 | } else if f.contains(Flags::MISC_FROM_PRELUDE) { | |
838 | AmbiguityErrorMisc::FromPrelude | |
839 | } else { | |
840 | AmbiguityErrorMisc::None | |
841 | } | |
842 | }; | |
843 | this.ambiguity_errors.push(AmbiguityError { | |
844 | kind, | |
845 | ident: orig_ident, | |
846 | b1: innermost_binding, | |
847 | b2: binding, | |
848 | misc1: misc(innermost_flags), | |
849 | misc2: misc(flags), | |
850 | }); | |
851 | return Some(Ok(innermost_binding)); | |
852 | } | |
13cf67c4 | 853 | } |
dfeec247 XL |
854 | } else { |
855 | // Found the first solution. | |
856 | innermost_result = Some((binding, flags)); | |
476ff2be | 857 | } |
476ff2be | 858 | } |
dfeec247 XL |
859 | Ok(..) | Err(Determinacy::Determined) => {} |
860 | Err(Determinacy::Undetermined) => determinacy = Determinacy::Undetermined, | |
b7449926 | 861 | } |
13cf67c4 | 862 | |
dfeec247 XL |
863 | None |
864 | }, | |
865 | ); | |
13cf67c4 | 866 | |
416331ca XL |
867 | if let Some(break_result) = break_result { |
868 | return break_result; | |
b7449926 | 869 | } |
476ff2be | 870 | |
b7449926 | 871 | // The first found solution was the only one, return it. |
532ac7d7 | 872 | if let Some((binding, _)) = innermost_result { |
0bf4aa26 | 873 | return Ok(binding); |
b7449926 XL |
874 | } |
875 | ||
60c5eb7d | 876 | Err(Determinacy::determined(determinacy == Determinacy::Determined || force)) |
476ff2be SL |
877 | } |
878 | ||
e1599b0c | 879 | crate fn finalize_macro_resolutions(&mut self) { |
dfeec247 XL |
880 | let check_consistency = |this: &mut Self, |
881 | path: &[Segment], | |
882 | span, | |
883 | kind: MacroKind, | |
884 | initial_res: Option<Res>, | |
885 | res: Res| { | |
48663c56 XL |
886 | if let Some(initial_res) = initial_res { |
887 | if res != initial_res && res != Res::Err && this.ambiguity_errors.is_empty() { | |
13cf67c4 XL |
888 | // Make sure compilation does not succeed if preferred macro resolution |
889 | // has changed after the macro had been expanded. In theory all such | |
890 | // situations should be reported as ambiguity errors, so this is a bug. | |
60c5eb7d | 891 | span_bug!(span, "inconsistent resolution for a macro"); |
13cf67c4 XL |
892 | } |
893 | } else { | |
894 | // It's possible that the macro was unresolved (indeterminate) and silently | |
895 | // expanded into a dummy fragment for recovery during expansion. | |
896 | // Now, post-expansion, the resolution may succeed, but we can't change the | |
897 | // past and need to report an error. | |
898 | // However, non-speculative `resolve_path` can successfully return private items | |
899 | // even if speculative `resolve_path` returned nothing previously, so we skip this | |
900 | // less informative error if the privacy error is reported elsewhere. | |
901 | if this.privacy_errors.is_empty() { | |
dfeec247 XL |
902 | let msg = format!( |
903 | "cannot determine resolution for the {} `{}`", | |
904 | kind.descr(), | |
905 | Segment::names_to_string(path) | |
906 | ); | |
13cf67c4 XL |
907 | let msg_note = "import resolution is stuck, try simplifying macro imports"; |
908 | this.session.struct_span_err(span, &msg).note(msg_note).emit(); | |
909 | } | |
910 | } | |
911 | }; | |
912 | ||
e1599b0c | 913 | let macro_resolutions = mem::take(&mut self.multi_segment_macro_resolutions); |
48663c56 | 914 | for (mut path, path_span, kind, parent_scope, initial_res) in macro_resolutions { |
13cf67c4 | 915 | // FIXME: Path resolution will ICE if segment IDs present. |
dfeec247 XL |
916 | for seg in &mut path { |
917 | seg.id = None; | |
918 | } | |
416331ca | 919 | match self.resolve_path( |
dfeec247 XL |
920 | &path, |
921 | Some(MacroNS), | |
922 | &parent_scope, | |
923 | true, | |
924 | path_span, | |
925 | CrateLint::No, | |
416331ca | 926 | ) { |
13cf67c4 | 927 | PathResult::NonModule(path_res) if path_res.unresolved_segments() == 0 => { |
48663c56 XL |
928 | let res = path_res.base_res(); |
929 | check_consistency(self, &path, path_span, kind, initial_res, res); | |
13cf67c4 | 930 | } |
532ac7d7 XL |
931 | path_res @ PathResult::NonModule(..) | path_res @ PathResult::Failed { .. } => { |
932 | let (span, label) = if let PathResult::Failed { span, label, .. } = path_res { | |
933 | (span, label) | |
13cf67c4 | 934 | } else { |
dfeec247 XL |
935 | ( |
936 | path_span, | |
937 | format!( | |
938 | "partially resolved path in {} {}", | |
939 | kind.article(), | |
940 | kind.descr() | |
941 | ), | |
942 | ) | |
13cf67c4 | 943 | }; |
dfeec247 XL |
944 | self.report_error( |
945 | span, | |
946 | ResolutionError::FailedToResolve { label, suggestion: None }, | |
947 | ); | |
476ff2be | 948 | } |
13cf67c4 | 949 | PathResult::Module(..) | PathResult::Indeterminate => unreachable!(), |
476ff2be SL |
950 | } |
951 | } | |
952 | ||
e1599b0c | 953 | let macro_resolutions = mem::take(&mut self.single_segment_macro_resolutions); |
13cf67c4 | 954 | for (ident, kind, parent_scope, initial_binding) in macro_resolutions { |
dfeec247 XL |
955 | match self.early_resolve_ident_in_lexical_scope( |
956 | ident, | |
957 | ScopeSet::Macro(kind), | |
958 | &parent_scope, | |
959 | true, | |
960 | true, | |
961 | ident.span, | |
962 | ) { | |
0bf4aa26 | 963 | Ok(binding) => { |
48663c56 | 964 | let initial_res = initial_binding.map(|initial_binding| { |
13cf67c4 | 965 | self.record_use(ident, MacroNS, initial_binding, false); |
48663c56 | 966 | initial_binding.res() |
13cf67c4 | 967 | }); |
48663c56 | 968 | let res = binding.res(); |
13cf67c4 | 969 | let seg = Segment::from_ident(ident); |
48663c56 | 970 | check_consistency(self, &[seg], ident.span, kind, initial_res, res); |
94b46f34 | 971 | } |
0bf4aa26 | 972 | Err(..) => { |
e1599b0c XL |
973 | let expected = kind.descr_expected(); |
974 | let msg = format!("cannot find {} `{}` in this scope", expected, ident); | |
0bf4aa26 | 975 | let mut err = self.session.struct_span_err(ident.span, &msg); |
416331ca | 976 | self.unresolved_macro_suggestions(&mut err, kind, &parent_scope, ident); |
8bb4bdeb | 977 | err.emit(); |
b7449926 | 978 | } |
0bf4aa26 | 979 | } |
c30ab7b3 | 980 | } |
b7449926 | 981 | |
e1599b0c | 982 | let builtin_attrs = mem::take(&mut self.builtin_attrs); |
b7449926 | 983 | for (ident, parent_scope) in builtin_attrs { |
13cf67c4 | 984 | let _ = self.early_resolve_ident_in_lexical_scope( |
dfeec247 XL |
985 | ident, |
986 | ScopeSet::Macro(MacroKind::Attr), | |
987 | &parent_scope, | |
988 | true, | |
989 | true, | |
990 | ident.span, | |
0bf4aa26 | 991 | ); |
b7449926 | 992 | } |
9e0c209e | 993 | } |
9e0c209e | 994 | |
f035d41b XL |
995 | fn check_stability_and_deprecation( |
996 | &mut self, | |
997 | ext: &SyntaxExtension, | |
998 | path: &ast::Path, | |
999 | node_id: NodeId, | |
1000 | ) { | |
416331ca XL |
1001 | let span = path.span; |
1002 | if let Some(stability) = &ext.stability { | |
1003 | if let StabilityLevel::Unstable { reason, issue, is_soft } = stability.level { | |
1004 | let feature = stability.feature; | |
1005 | if !self.active_features.contains(&feature) && !span.allows_unstable(feature) { | |
e74abb32 | 1006 | let lint_buffer = &mut self.lint_buffer; |
dfeec247 XL |
1007 | let soft_handler = |
1008 | |lint, span, msg: &_| lint_buffer.buffer_lint(lint, node_id, span, msg); | |
e74abb32 | 1009 | stability::report_unstable( |
dfeec247 XL |
1010 | self.session, |
1011 | feature, | |
1012 | reason, | |
1013 | issue, | |
1014 | is_soft, | |
1015 | span, | |
1016 | soft_handler, | |
e74abb32 | 1017 | ); |
416331ca XL |
1018 | } |
1019 | } | |
1020 | if let Some(depr) = &stability.rustc_depr { | |
e74abb32 XL |
1021 | let path = pprust::path_to_string(path); |
1022 | let (message, lint) = stability::rustc_deprecation_message(depr, &path); | |
416331ca | 1023 | stability::early_report_deprecation( |
dfeec247 XL |
1024 | &mut self.lint_buffer, |
1025 | &message, | |
1026 | depr.suggestion, | |
1027 | lint, | |
1028 | span, | |
416331ca XL |
1029 | ); |
1030 | } | |
1031 | } | |
1032 | if let Some(depr) = &ext.deprecation { | |
e74abb32 XL |
1033 | let path = pprust::path_to_string(&path); |
1034 | let (message, lint) = stability::deprecation_message(depr, &path); | |
1035 | stability::early_report_deprecation(&mut self.lint_buffer, &message, None, lint, span); | |
416331ca XL |
1036 | } |
1037 | } | |
1038 | ||
dfeec247 XL |
1039 | fn prohibit_imported_non_macro_attrs( |
1040 | &self, | |
1041 | binding: Option<&'a NameBinding<'a>>, | |
1042 | res: Option<Res>, | |
1043 | span: Span, | |
1044 | ) { | |
48663c56 | 1045 | if let Some(Res::NonMacroAttr(kind)) = res { |
69743fb6 | 1046 | if kind != NonMacroAttrKind::Tool && binding.map_or(true, |b| b.is_import()) { |
60c5eb7d XL |
1047 | let msg = |
1048 | format!("cannot use {} {} through an import", kind.article(), kind.descr()); | |
69743fb6 XL |
1049 | let mut err = self.session.struct_span_err(span, &msg); |
1050 | if let Some(binding) = binding { | |
1051 | err.span_note(binding.span, &format!("the {} imported here", kind.descr())); | |
1052 | } | |
1053 | err.emit(); | |
1054 | } | |
1055 | } | |
1056 | } | |
1057 | ||
416331ca XL |
1058 | crate fn check_reserved_macro_name(&mut self, ident: Ident, res: Res) { |
1059 | // Reserve some names that are not quite covered by the general check | |
1060 | // performed on `Resolver::builtin_attrs`. | |
1061 | if ident.name == sym::cfg || ident.name == sym::cfg_attr || ident.name == sym::derive { | |
1062 | let macro_kind = self.get_macro(res).map(|ext| ext.macro_kind()); | |
1063 | if macro_kind.is_some() && sub_namespace_match(macro_kind, Some(MacroKind::Attr)) { | |
1064 | self.session.span_err( | |
dfeec247 XL |
1065 | ident.span, |
1066 | &format!("name `{}` is reserved in attribute namespace", ident), | |
416331ca XL |
1067 | ); |
1068 | } | |
dc9dc135 | 1069 | } |
416331ca | 1070 | } |
dc9dc135 | 1071 | |
60c5eb7d XL |
1072 | /// Compile the macro into a `SyntaxExtension` and possibly replace |
1073 | /// its expander to a pre-defined one for built-in macros. | |
e1599b0c | 1074 | crate fn compile_macro(&mut self, item: &ast::Item, edition: Edition) -> SyntaxExtension { |
e74abb32 | 1075 | let mut result = compile_declarative_macro( |
dfeec247 XL |
1076 | &self.session.parse_sess, |
1077 | self.session.features_untracked(), | |
1078 | item, | |
1079 | edition, | |
416331ca | 1080 | ); |
8bb4bdeb | 1081 | |
416331ca XL |
1082 | if result.is_builtin { |
1083 | // The macro was marked with `#[rustc_builtin_macro]`. | |
1084 | if let Some(ext) = self.builtin_macros.remove(&item.ident.name) { | |
60c5eb7d XL |
1085 | // The macro is a built-in, replace its expander function |
1086 | // while still taking everything else from the source code. | |
1087 | result.kind = ext.kind; | |
9e0c209e | 1088 | } else { |
416331ca XL |
1089 | let msg = format!("cannot find a built-in macro with name `{}`", item.ident); |
1090 | self.session.span_err(item.span, &msg); | |
9e0c209e SL |
1091 | } |
1092 | } | |
32a655c1 | 1093 | |
e1599b0c | 1094 | result |
32a655c1 | 1095 | } |
9e0c209e | 1096 | } |