use crate::{CrateLint, ParentScope, ResolutionError, Resolver, Scope, ScopeSet, Weak};
use crate::{ModuleKind, ModuleOrUniformRoot, NameBinding, PathResult, Segment, ToNameBinding};
use rustc::middle::stability;
-use rustc::session::parse::feature_err;
-use rustc::session::Session;
-use rustc::{lint, span_bug, ty};
+use rustc::{span_bug, ty};
use rustc_ast::ast::{self, Ident, NodeId};
use rustc_ast_pretty::pprust;
use rustc_attr::{self as attr, StabilityLevel};
use rustc_feature::is_builtin_attr_name;
use rustc_hir::def::{self, DefKind, NonMacroAttrKind};
use rustc_hir::def_id;
+use rustc_session::lint::builtin::UNUSED_MACROS;
+use rustc_session::parse::feature_err;
+use rustc_session::Session;
use rustc_span::edition::Edition;
use rustc_span::hygiene::{self, ExpnData, ExpnId, ExpnKind};
use rustc_span::symbol::{kw, sym, Symbol};
force,
) {
Ok((Some(ext), _)) => {
- let span = path.segments.last().unwrap().ident.span.modern();
+ let span = path
+ .segments
+ .last()
+ .unwrap()
+ .ident
+ .span
+ .normalize_to_macros_2_0();
helper_attrs.extend(
ext.helper_attrs.iter().map(|name| Ident::new(*name, span)),
);
fn check_unused_macros(&mut self) {
for (&node_id, &span) in self.unused_macros.iter() {
- self.lint_buffer.buffer_lint(
- lint::builtin::UNUSED_MACROS,
- node_id,
- span,
- "unused macro definition",
- );
+ self.lint_buffer.buffer_lint(UNUSED_MACROS, node_id, span, "unused macro definition");
}
}
fn add_derive_copy(&mut self, expn_id: ExpnId) {
self.containers_deriving_copy.insert(expn_id);
}
+
+ // The function that implements the resolution logic of `#[cfg_accessible(path)]`.
+ // Returns true if the path can certainly be resolved in one of three namespaces,
+ // returns false if the path certainly cannot be resolved in any of the three namespaces.
+ // Returns `Indeterminate` if we cannot give a certain answer yet.
+ fn cfg_accessible(&mut self, expn_id: ExpnId, path: &ast::Path) -> Result<bool, Indeterminate> {
+ let span = path.span;
+ let path = &Segment::from_path(path);
+ let parent_scope = self.invocation_parent_scopes[&expn_id];
+
+ let mut indeterminate = false;
+ for ns in [TypeNS, ValueNS, MacroNS].iter().copied() {
+ match self.resolve_path(path, Some(ns), &parent_scope, false, span, CrateLint::No) {
+ PathResult::Module(ModuleOrUniformRoot::Module(_)) => return Ok(true),
+ PathResult::NonModule(partial_res) if partial_res.unresolved_segments() == 0 => {
+ return Ok(true);
+ }
+ PathResult::Indeterminate => indeterminate = true,
+ // FIXME: `resolve_path` is not ready to report partially resolved paths
+ // correctly, so we just report an error if the path was reported as unresolved.
+ // This needs to be fixed for `cfg_accessible` to be useful.
+ PathResult::NonModule(..) | PathResult::Failed { .. } => {}
+ PathResult::Module(_) => panic!("unexpected path resolution"),
+ }
+ }
+
+ if indeterminate {
+ return Err(Indeterminate);
+ }
+
+ self.session
+ .struct_span_err(span, "not sure whether the path is accessible or not")
+ .span_note(span, "`cfg_accessible` is not fully implemented")
+ .emit();
+ Ok(false)
+ }
}
impl<'a> Resolver<'a> {