// except according to those terms.
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
- html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
- html_root_url = "https://doc.rust-lang.org/nightly/")]
+ html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
+ html_root_url = "https://doc.rust-lang.org/nightly/")]
#![feature(crate_visibility_modifier)]
#![cfg_attr(not(stage0), feature(nll))]
+#![cfg_attr(not(stage0), feature(infer_outlives_requirements))]
#![feature(rustc_diagnostic_macros)]
#![feature(slice_sort_by_cached_key)]
use self::RibKind::*;
use rustc::hir::map::{Definitions, DefCollector};
-use rustc::hir::{self, PrimTy, TyBool, TyChar, TyFloat, TyInt, TyUint, TyStr};
+use rustc::hir::{self, PrimTy, Bool, Char, Float, Int, Uint, Str};
use rustc::middle::cstore::CrateStore;
use rustc::session::Session;
use rustc::lint;
use rustc_metadata::creader::CrateLoader;
use rustc_metadata::cstore::CStore;
-use syntax::codemap::CodeMap;
+use syntax::source_map::SourceMap;
use syntax::ext::hygiene::{Mark, Transparency, SyntaxContext};
use syntax::ast::{self, Name, NodeId, Ident, FloatTy, IntTy, UintTy};
use syntax::ext::base::SyntaxExtension;
use syntax::ptr::P;
use syntax_pos::{Span, DUMMY_SP, MultiSpan};
-use errors::{DiagnosticBuilder, DiagnosticId};
+use errors::{Applicability, DiagnosticBuilder, DiagnosticId};
use std::cell::{Cell, RefCell};
use std::cmp;
use rustc_data_structures::sync::Lrc;
use resolve_imports::{ImportDirective, ImportDirectiveSubclass, NameResolution, ImportResolver};
-use macros::{InvocationData, LegacyBinding, LegacyScope, MacroBinding};
+use macros::{InvocationData, LegacyBinding};
// NB: This module needs to be declared first so diagnostics are
// registered before they are used.
"can't use type parameters from outer function");
err.span_label(span, "use of type variable from outer function");
- let cm = resolver.session.codemap();
+ let cm = resolver.session.source_map();
match outer_def {
Def::SelfTy(_, maybe_impl_defid) => {
if let Some(impl_span) = maybe_impl_defid.map_or(None,
|def_id| resolver.definitions.opt_span(def_id)) {
err.span_label(reduce_impl_span_to_impl_keyword(cm, impl_span),
- "`Self` type implicitely declared here, on the `impl`");
+ "`Self` type implicitly declared here, on the `impl`");
}
},
Def::TyParam(typaram_defid) => {
let sugg_msg = "try using a local type parameter instead";
if let Some((sugg_span, new_snippet)) = cm.generate_local_type_param_snippet(span) {
// Suggest the modification to the user
- err.span_suggestion(sugg_span,
- sugg_msg,
- new_snippet);
+ err.span_suggestion_with_applicability(
+ sugg_span,
+ sugg_msg,
+ new_snippet,
+ Applicability::MachineApplicable,
+ );
} else if let Some(sp) = cm.generate_fn_name_span(span) {
err.span_label(sp, "try adding a local type parameter in this method instead");
} else {
///
/// Attention: The method used is very fragile since it essentially duplicates the work of the
/// parser. If you need to use this function or something similar, please consider updating the
-/// codemap functions and this function to something more robust.
-fn reduce_impl_span_to_impl_keyword(cm: &CodeMap, impl_span: Span) -> Span {
+/// source_map functions and this function to something more robust.
+fn reduce_impl_span_to_impl_keyword(cm: &SourceMap, impl_span: Span) -> Span {
let impl_span = cm.span_until_char(impl_span, '<');
let impl_span = cm.span_until_whitespace(impl_span);
impl_span
Def::Trait(..) | Def::TyAlias(..) | Def::AssociatedTy(..) |
Def::PrimTy(..) | Def::TyParam(..) | Def::SelfTy(..) |
Def::Existential(..) |
- Def::TyForeign(..) => true,
+ Def::ForeignTy(..) => true,
_ => false,
},
PathSource::Trait(AliasPossibility::No) => match def {
.filter_map(|param| match param.kind {
GenericParamKind::Lifetime { .. } => None,
GenericParamKind::Type { ref default, .. } => {
- if found_default || default.is_some() {
- found_default = true;
- return Some((Ident::with_empty_ctxt(param.ident.name), Def::Err));
+ found_default |= default.is_some();
+ if found_default {
+ Some((Ident::with_empty_ctxt(param.ident.name), Def::Err))
+ } else {
+ None
}
- None
}
}));
fn new() -> PrimitiveTypeTable {
let mut table = PrimitiveTypeTable { primitive_types: FxHashMap() };
- table.intern("bool", TyBool);
- table.intern("char", TyChar);
- table.intern("f32", TyFloat(FloatTy::F32));
- table.intern("f64", TyFloat(FloatTy::F64));
- table.intern("isize", TyInt(IntTy::Isize));
- table.intern("i8", TyInt(IntTy::I8));
- table.intern("i16", TyInt(IntTy::I16));
- table.intern("i32", TyInt(IntTy::I32));
- table.intern("i64", TyInt(IntTy::I64));
- table.intern("i128", TyInt(IntTy::I128));
- table.intern("str", TyStr);
- table.intern("usize", TyUint(UintTy::Usize));
- table.intern("u8", TyUint(UintTy::U8));
- table.intern("u16", TyUint(UintTy::U16));
- table.intern("u32", TyUint(UintTy::U32));
- table.intern("u64", TyUint(UintTy::U64));
- table.intern("u128", TyUint(UintTy::U128));
+ table.intern("bool", Bool);
+ table.intern("char", Char);
+ table.intern("f32", Float(FloatTy::F32));
+ table.intern("f64", Float(FloatTy::F64));
+ table.intern("isize", Int(IntTy::Isize));
+ table.intern("i8", Int(IntTy::I8));
+ table.intern("i16", Int(IntTy::I16));
+ table.intern("i32", Int(IntTy::I32));
+ table.intern("i64", Int(IntTy::I64));
+ table.intern("i128", Int(IntTy::I128));
+ table.intern("str", Str);
+ table.intern("usize", Uint(UintTy::Usize));
+ table.intern("u8", Uint(UintTy::U8));
+ table.intern("u16", Uint(UintTy::U16));
+ table.intern("u32", Uint(UintTy::U32));
+ table.intern("u64", Uint(UintTy::U64));
+ table.intern("u128", Uint(UintTy::U128));
table
}
proc_mac_errors: Vec<macros::ProcMacError>,
/// crate-local macro expanded `macro_export` referred to by a module-relative path
macro_expanded_macro_export_errors: BTreeSet<(Span, Span)>,
-
- gated_errors: FxHashSet<Span>,
+ /// macro-expanded `macro_rules` shadowing existing macros
disallowed_shadowing: Vec<&'a LegacyBinding<'a>>,
arenas: &'a ResolverArenas<'a>,
dummy_binding: &'a NameBinding<'a>,
- /// true if `#![feature(use_extern_macros)]`
- use_extern_macros: bool,
crate_loader: &'a mut CrateLoader<'b>,
macro_names: FxHashSet<Ident>,
macro_prelude: FxHashMap<Name, &'a NameBinding<'a>>,
pub all_macros: FxHashMap<Name, Def>,
- lexical_macro_resolutions: Vec<(Ident, &'a Cell<LegacyScope<'a>>)>,
macro_map: FxHashMap<DefId, Lrc<SyntaxExtension>>,
macro_defs: FxHashMap<Mark, DefId>,
local_macro_def_scopes: FxHashMap<NodeId, Module<'a>>,
- macro_exports: Vec<Export>, // FIXME: Remove when `use_extern_macros` is stabilized
pub whitelisted_legacy_custom_derives: Vec<Name>,
pub found_unresolved_macro: bool,
invocations.insert(Mark::root(),
arenas.alloc_invocation_data(InvocationData::root(graph_root)));
- let features = session.features_untracked();
-
let mut macro_defs = FxHashMap();
macro_defs.insert(Mark::root(), root_def_id);
ambiguity_errors: Vec::new(),
use_injections: Vec::new(),
proc_mac_errors: Vec::new(),
- gated_errors: FxHashSet(),
disallowed_shadowing: Vec::new(),
macro_expanded_macro_export_errors: BTreeSet::new(),
vis: ty::Visibility::Public,
}),
- use_extern_macros: features.use_extern_macros(),
-
crate_loader,
macro_names: FxHashSet(),
macro_prelude: FxHashMap(),
all_macros: FxHashMap(),
- lexical_macro_resolutions: Vec::new(),
macro_map: FxHashMap(),
- macro_exports: Vec::new(),
invocations,
macro_defs,
local_macro_def_scopes: FxHashMap(),
fn per_ns<F: FnMut(&mut Self, Namespace)>(&mut self, mut f: F) {
f(self, TypeNS);
f(self, ValueNS);
- if self.use_extern_macros {
- f(self, MacroNS);
- }
+ f(self, MacroNS);
}
fn macro_def(&self, mut ctxt: SyntaxContext) -> DefId {
fn add_to_glob_map(&mut self, id: NodeId, ident: Ident) {
if self.make_glob_map {
- self.glob_map.entry(id).or_insert_with(FxHashSet).insert(ident.name);
+ self.glob_map.entry(id).or_default().insert(ident.name);
}
}
}
ident.span = ident.span.modern();
+ let mut poisoned = None;
loop {
- let (opt_module, poisoned) = if let Some(node_id) = record_used_id {
+ let opt_module = if let Some(node_id) = record_used_id {
self.hygienic_lexical_parent_with_compatibility_fallback(module, &mut ident.span,
- node_id)
+ node_id, &mut poisoned)
} else {
- (self.hygienic_lexical_parent(module, &mut ident.span), None)
+ self.hygienic_lexical_parent(module, &mut ident.span)
};
module = unwrap_or!(opt_module, break);
let orig_current_module = self.current_module;
}
return Some(LexicalScopeBinding::Item(binding))
}
- _ if poisoned.is_some() => break,
Err(Determined) => continue,
Err(Undetermined) =>
span_bug!(ident.span, "undetermined resolution during main resolution pass"),
None
}
- fn hygienic_lexical_parent_with_compatibility_fallback(
- &mut self, module: Module<'a>, span: &mut Span, node_id: NodeId
- ) -> (Option<Module<'a>>, /* poisoned */ Option<NodeId>)
- {
+ fn hygienic_lexical_parent_with_compatibility_fallback(&mut self, module: Module<'a>,
+ span: &mut Span, node_id: NodeId,
+ poisoned: &mut Option<NodeId>)
+ -> Option<Module<'a>> {
if let module @ Some(..) = self.hygienic_lexical_parent(module, span) {
- return (module, None);
+ return module;
}
// We need to support the next case under a deprecation warning
// The macro is a proc macro derive
if module.expansion.looks_like_proc_macro_derive() {
if parent.expansion.is_descendant_of(span.ctxt().outer()) {
- return (module.parent, Some(node_id));
+ *poisoned = Some(node_id);
+ return module.parent;
}
}
}
}
- (None, None)
+ None
}
fn resolve_ident_in_module(&mut self,
fn resolve_item(&mut self, item: &Item) {
let name = item.ident.name;
-
debug!("(resolving item) resolving {}", name);
- self.check_proc_macro_attrs(&item.attrs);
-
match item.node {
- ItemKind::Enum(_, ref generics) |
ItemKind::Ty(_, ref generics) |
- ItemKind::Existential(_, ref generics) |
- ItemKind::Struct(_, ref generics) |
- ItemKind::Union(_, ref generics) |
- ItemKind::Fn(_, _, ref generics, _) => {
+ ItemKind::Fn(_, _, ref generics, _) |
+ ItemKind::Existential(_, ref generics) => {
self.with_type_parameter_rib(HasTypeParameters(generics, ItemRibKind),
- |this| visit::walk_item(this, item));
+ |this| visit::walk_item(this, item));
+ }
+
+ ItemKind::Enum(_, ref generics) |
+ ItemKind::Struct(_, ref generics) |
+ ItemKind::Union(_, ref generics) => {
+ self.with_type_parameter_rib(HasTypeParameters(generics, ItemRibKind), |this| {
+ let item_def_id = this.definitions.local_def_id(item.id);
+ if this.session.features_untracked().self_in_typedefs {
+ this.with_self_rib(Def::SelfTy(None, Some(item_def_id)), |this| {
+ visit::walk_item(this, item);
+ });
+ } else {
+ visit::walk_item(this, item);
+ }
+ });
}
ItemKind::Impl(.., ref generics, ref opt_trait_ref, ref self_type, ref impl_items) =>
walk_list!(this, visit_param_bound, bounds);
for trait_item in trait_items {
- this.check_proc_macro_attrs(&trait_item.attrs);
-
let type_parameters = HasTypeParameters(&trait_item.generics,
TraitOrImplItemRibKind);
this.with_type_parameter_rib(type_parameters, |this| {
HasTypeParameters(generics, rib_kind) => {
let mut function_type_rib = Rib::new(rib_kind);
let mut seen_bindings = FxHashMap();
- generics.params.iter().for_each(|param| match param.kind {
- GenericParamKind::Lifetime { .. } => {}
- GenericParamKind::Type { .. } => {
- let ident = param.ident.modern();
- debug!("with_type_parameter_rib: {}", param.id);
-
- if seen_bindings.contains_key(&ident) {
- let span = seen_bindings.get(&ident).unwrap();
- let err = ResolutionError::NameAlreadyUsedInTypeParameterList(
- ident.name,
- span,
- );
- resolve_error(self, param.ident.span, err);
- }
- seen_bindings.entry(ident).or_insert(param.ident.span);
+ for param in &generics.params {
+ match param.kind {
+ GenericParamKind::Lifetime { .. } => {}
+ GenericParamKind::Type { .. } => {
+ let ident = param.ident.modern();
+ debug!("with_type_parameter_rib: {}", param.id);
+
+ if seen_bindings.contains_key(&ident) {
+ let span = seen_bindings.get(&ident).unwrap();
+ let err = ResolutionError::NameAlreadyUsedInTypeParameterList(
+ ident.name,
+ span,
+ );
+ resolve_error(self, param.ident.span, err);
+ }
+ seen_bindings.entry(ident).or_insert(param.ident.span);
- // Plain insert (no renaming).
- let def = Def::TyParam(self.definitions.local_def_id(param.id));
- function_type_rib.bindings.insert(ident, def);
- self.record_def(param.id, PathResolution::new(def));
+ // Plain insert (no renaming).
+ let def = Def::TyParam(self.definitions.local_def_id(param.id));
+ function_type_rib.bindings.insert(ident, def);
+ self.record_def(param.id, PathResolution::new(def));
+ }
}
- });
+ }
self.ribs[TypeNS].push(function_type_rib);
}
let item_def_id = this.definitions.local_def_id(item_id);
this.with_self_rib(Def::SelfTy(trait_id, Some(item_def_id)), |this| {
if let Some(trait_ref) = opt_trait_reference.as_ref() {
- // Resolve type arguments in trait path
+ // Resolve type arguments in the trait path.
visit::walk_trait_ref(this, trait_ref);
}
// Resolve the self type.
this.visit_ty(self_type);
// Resolve the type parameters.
this.visit_generics(generics);
+ // Resolve the items within the impl.
this.with_current_self_type(self_type, |this| {
for impl_item in impl_items {
- this.check_proc_macro_attrs(&impl_item.attrs);
this.resolve_visibility(&impl_item.vis);
// We also need a new scope for the impl item type parameters.
// If this is a trait impl, ensure the const
// exists in trait
this.check_trait_item(impl_item.ident,
- ValueNS,
- impl_item.span,
+ ValueNS,
+ impl_item.span,
|n, s| ConstNotMemberOfTrait(n, s));
this.with_constant_rib(|this|
visit::walk_impl_item(this, impl_item)
// If this is a trait impl, ensure the method
// exists in trait
this.check_trait_item(impl_item.ident,
- ValueNS,
- impl_item.span,
+ ValueNS,
+ impl_item.span,
|n, s| MethodNotMemberOfTrait(n, s));
visit::walk_impl_item(this, impl_item);
// If this is a trait impl, ensure the type
// exists in trait
this.check_trait_item(impl_item.ident,
- TypeNS,
- impl_item.span,
+ TypeNS,
+ impl_item.span,
|n, s| TypeNotMemberOfTrait(n, s));
this.visit_ty(ty);
// If this is a trait impl, ensure the type
// exists in trait
this.check_trait_item(impl_item.ident,
- TypeNS,
- impl_item.span,
+ TypeNS,
+ impl_item.span,
|n, s| TypeNotMemberOfTrait(n, s));
for bound in bounds {
// This has to happen *after* we determine which pat_idents are variants
self.check_consistent_bindings(&arm.pats);
- walk_list!(self, visit_expr, &arm.guard);
+ match arm.guard {
+ Some(ast::Guard::If(ref expr)) => self.visit_expr(expr),
+ _ => {}
+ }
self.visit_expr(&arm.body);
self.ribs[ValueNS].pop();
if is_self_type(path, ns) {
__diagnostic_used!(E0411);
err.code(DiagnosticId::Error("E0411".into()));
- err.span_label(span, "`Self` is only available in traits and impls");
+ let available_in = if this.session.features_untracked().self_in_typedefs {
+ "impls, traits, and type definitions"
+ } else {
+ "traits and impls"
+ };
+ err.span_label(span, format!("`Self` is only available in {}", available_in));
return (err, Vec::new());
}
if is_self_value(path, ns) {
enum_path);
err.help(&msg);
} else {
- err.span_suggestion(span, "you can try using the variant's enum",
- enum_path);
+ err.span_suggestion_with_applicability(
+ span,
+ "you can try using the variant's enum",
+ enum_path,
+ Applicability::MachineApplicable,
+ );
}
}
}
let self_is_available = this.self_value_is_available(path[0].span, span);
match candidate {
AssocSuggestion::Field => {
- err.span_suggestion(span, "try",
- format!("self.{}", path_str));
+ err.span_suggestion_with_applicability(
+ span,
+ "try",
+ format!("self.{}", path_str),
+ Applicability::MachineApplicable,
+ );
if !self_is_available {
err.span_label(span, format!("`self` value is only available in \
methods with `self` parameter"));
}
}
AssocSuggestion::MethodWithSelf if self_is_available => {
- err.span_suggestion(span, "try",
- format!("self.{}", path_str));
+ err.span_suggestion_with_applicability(
+ span,
+ "try",
+ format!("self.{}", path_str),
+ Applicability::MachineApplicable,
+ );
}
AssocSuggestion::MethodWithSelf | AssocSuggestion::AssocItem => {
- err.span_suggestion(span, "try",
- format!("Self::{}", path_str));
+ err.span_suggestion_with_applicability(
+ span,
+ "try",
+ format!("Self::{}", path_str),
+ Applicability::MachineApplicable,
+ );
}
}
return (err, candidates);
// parser issue where a struct literal is being used on an expression
// where a brace being opened means a block is being started. Look
// ahead for the next text to see if `span` is followed by a `{`.
- let cm = this.session.codemap();
+ let cm = this.session.source_map();
let mut sp = span;
loop {
sp = cm.next_point(sp);
err: &mut DiagnosticBuilder,
base_span: Span) {
debug!("type_ascription_suggetion {:?}", base_span);
- let cm = self.session.codemap();
+ let cm = self.session.source_map();
debug!("self.current_type_ascription {:?}", self.current_type_ascription);
if let Some(sp) = self.current_type_ascription.last() {
let mut sp = *sp;
let ns = if is_last { opt_ns.unwrap_or(TypeNS) } else { TypeNS };
let name = ident.name;
- if i == 0 && ns == TypeNS && name == keywords::SelfValue.name() {
- let mut ctxt = ident.span.ctxt().modern();
- module = Some(ModuleOrUniformRoot::Module(
- self.resolve_self(&mut ctxt, self.current_module)));
- continue
- } else if allow_super && ns == TypeNS && name == keywords::Super.name() {
- let mut ctxt = ident.span.ctxt().modern();
- let self_module_parent = match i {
- 0 => self.resolve_self(&mut ctxt, self.current_module).parent,
- _ => match module {
- Some(ModuleOrUniformRoot::Module(module)) => module.parent,
- _ => None,
- },
- };
- if let Some(parent) = self_module_parent {
- module = Some(ModuleOrUniformRoot::Module(
- self.resolve_self(&mut ctxt, parent)));
- continue
- } else {
+ allow_super &= ns == TypeNS &&
+ (name == keywords::SelfValue.name() ||
+ name == keywords::Super.name());
+
+ if ns == TypeNS {
+ if allow_super && name == keywords::Super.name() {
+ let mut ctxt = ident.span.ctxt().modern();
+ let self_module = match i {
+ 0 => Some(self.resolve_self(&mut ctxt, self.current_module)),
+ _ => match module {
+ Some(ModuleOrUniformRoot::Module(module)) => Some(module),
+ _ => None,
+ },
+ };
+ if let Some(self_module) = self_module {
+ if let Some(parent) = self_module.parent {
+ module = Some(ModuleOrUniformRoot::Module(
+ self.resolve_self(&mut ctxt, parent)));
+ continue;
+ }
+ }
let msg = "There are too many initial `super`s.".to_string();
return PathResult::Failed(ident.span, msg, false);
}
- }
- allow_super = false;
-
- if ns == TypeNS {
if i == 0 {
+ if name == keywords::SelfValue.name() {
+ let mut ctxt = ident.span.ctxt().modern();
+ module = Some(ModuleOrUniformRoot::Module(
+ self.resolve_self(&mut ctxt, self.current_module)));
+ continue;
+ }
if name == keywords::Extern.name() ||
name == keywords::CrateRoot.name() &&
self.session.features_untracked().extern_absolute_paths &&
module = Some(ModuleOrUniformRoot::UniformRoot(name));
continue;
}
- }
- if (i == 0 && name == keywords::CrateRoot.name()) ||
- (i == 0 && name == keywords::Crate.name()) ||
- (i == 0 && name == keywords::DollarCrate.name()) ||
- (i == 1 && name == keywords::Crate.name() &&
- path[0].name == keywords::CrateRoot.name()) {
- // `::a::b`, `crate::a::b`, `::crate::a::b` or `$crate::a::b`
- module = Some(ModuleOrUniformRoot::Module(
- self.resolve_crate_root(ident)));
- continue
+ if name == keywords::CrateRoot.name() ||
+ name == keywords::Crate.name() ||
+ name == keywords::DollarCrate.name() {
+ // `::a::b`, `crate::a::b` or `$crate::a::b`
+ module = Some(ModuleOrUniformRoot::Module(
+ self.resolve_crate_root(ident)));
+ continue;
+ }
}
}
// Report special messages for path segment keywords in wrong positions.
- if name == keywords::CrateRoot.name() && i != 0 ||
- name == keywords::DollarCrate.name() && i != 0 ||
- name == keywords::SelfValue.name() && i != 0 ||
- name == keywords::SelfType.name() && i != 0 ||
- name == keywords::Super.name() && i != 0 ||
- name == keywords::Extern.name() && i != 0 ||
- // we allow crate::foo and ::crate::foo but nothing else
- name == keywords::Crate.name() && i > 1 &&
- path[0].name != keywords::CrateRoot.name() ||
- name == keywords::Crate.name() && path.len() == 1 {
+ if ident.is_path_segment_keyword() && i != 0 {
let name_str = if name == keywords::CrateRoot.name() {
"crate root".to_string()
} else {
} else if opt_ns == Some(MacroNS) {
assert!(ns == TypeNS);
self.resolve_lexical_macro_path_segment(ident, ns, record_used, record_used,
- false, path_span).map(MacroBinding::binding)
+ false, path_span).map(|(b, _)| b)
} else {
let record_used_id =
if record_used { crate_lint.node_id().or(Some(CRATE_NODE_ID)) } else { None };
let seen = self.freevars_seen
.entry(function_id)
- .or_insert_with(|| NodeMap());
+ .or_default();
if let Some(&index) = seen.get(&node_id) {
def = Def::Upvar(node_id, index, function_id);
continue;
}
let vec = self.freevars
.entry(function_id)
- .or_insert_with(|| vec![]);
+ .or_default();
let depth = vec.len();
def = Def::Upvar(node_id, depth, function_id);
}
}
// Add primitive types to the mix
- if filter_fn(Def::PrimTy(TyBool)) {
+ if filter_fn(Def::PrimTy(Bool)) {
names.extend(
self.primitive_type_table.primitive_types.iter().map(|(name, _)| name)
)
vis.is_accessible_from(module.normal_ancestor_id, self)
}
+ fn report_ambiguity_error(
+ &self, name: Name, span: Span, _lexical: bool,
+ def1: Def, is_import1: bool, is_glob1: bool, from_expansion1: bool, span1: Span,
+ def2: Def, is_import2: bool, _is_glob2: bool, _from_expansion2: bool, span2: Span,
+ ) {
+ let participle = |is_import: bool| if is_import { "imported" } else { "defined" };
+ let msg1 = format!("`{}` could refer to the name {} here", name, participle(is_import1));
+ let msg2 =
+ format!("`{}` could also refer to the name {} here", name, participle(is_import2));
+ let note = if from_expansion1 {
+ Some(if let Def::Macro(..) = def1 {
+ format!("macro-expanded {} do not shadow",
+ if is_import1 { "macro imports" } else { "macros" })
+ } else {
+ format!("macro-expanded {} do not shadow when used in a macro invocation path",
+ if is_import1 { "imports" } else { "items" })
+ })
+ } else if is_glob1 {
+ Some(format!("consider adding an explicit import of `{}` to disambiguate", name))
+ } else {
+ None
+ };
+
+ let mut err = struct_span_err!(self.session, span, E0659, "`{}` is ambiguous", name);
+ err.span_note(span1, &msg1);
+ match def2 {
+ Def::Macro(..) if span2.is_dummy() =>
+ err.note(&format!("`{}` is also a builtin macro", name)),
+ _ => err.span_note(span2, &msg2),
+ };
+ if let Some(note) = note {
+ err.note(¬e);
+ }
+ err.emit();
+ }
+
fn report_errors(&mut self, krate: &Crate) {
self.report_shadowing_errors();
self.report_with_use_injections(krate);
for &(span_use, span_def) in &self.macro_expanded_macro_export_errors {
let msg = "macro-expanded `macro_export` macros from the current crate \
cannot be referred to by absolute paths";
- self.session.struct_span_err(span_use, msg)
- .span_note(span_def, "the macro is defined here")
- .emit();
+ self.session.buffer_lint_with_diagnostic(
+ lint::builtin::MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS,
+ CRATE_NODE_ID, span_use, msg,
+ lint::builtin::BuiltinLintDiagnostics::
+ MacroExpandedMacroExportsAccessedByAbsolutePaths(span_def),
+ );
}
for &AmbiguityError { span, name, b1, b2, lexical } in &self.ambiguity_errors {
- if !reported_spans.insert(span) { continue }
- let participle = |binding: &NameBinding| {
- if binding.is_import() { "imported" } else { "defined" }
- };
- let msg1 = format!("`{}` could refer to the name {} here", name, participle(b1));
- let msg2 = format!("`{}` could also refer to the name {} here", name, participle(b2));
- let note = if b1.expansion == Mark::root() || !lexical && b1.is_glob_import() {
- format!("consider adding an explicit import of `{}` to disambiguate", name)
- } else if let Def::Macro(..) = b1.def() {
- format!("macro-expanded {} do not shadow",
- if b1.is_import() { "macro imports" } else { "macros" })
- } else {
- format!("macro-expanded {} do not shadow when used in a macro invocation path",
- if b1.is_import() { "imports" } else { "items" })
- };
-
- let mut err = struct_span_err!(self.session, span, E0659, "`{}` is ambiguous", name);
- err.span_note(b1.span, &msg1);
- match b2.def() {
- Def::Macro(..) if b2.span.is_dummy() =>
- err.note(&format!("`{}` is also a builtin macro", name)),
- _ => err.span_note(b2.span, &msg2),
- };
- err.note(¬e).emit();
+ if reported_spans.insert(span) {
+ self.report_ambiguity_error(
+ name, span, lexical,
+ b1.def(), b1.is_import(), b1.is_glob_import(),
+ b1.expansion != Mark::root(), b1.span,
+ b2.def(), b2.is_import(), b2.is_glob_import(),
+ b2.expansion != Mark::root(), b2.span,
+ );
+ }
}
for &PrivacyError(span, name, binding) in &self.privacy_errors {
}
fn report_shadowing_errors(&mut self) {
- for (ident, scope) in replace(&mut self.lexical_macro_resolutions, Vec::new()) {
- self.resolve_legacy_scope(scope, ident, true);
- }
-
let mut reported_errors = FxHashSet();
for binding in replace(&mut self.disallowed_shadowing, Vec::new()) {
if self.resolve_legacy_scope(&binding.parent, binding.ident, false).is_some() &&
false => "defined",
};
- let (name, span) = (ident.name, self.session.codemap().def_span(new_binding.span));
+ let (name, span) = (ident.name, self.session.source_map().def_span(new_binding.span));
if let Some(s) = self.name_already_seen.get(&name) {
if s == &span {
err.span_label(span, format!("`{}` re{} here", name, new_participle));
if !old_binding.span.is_dummy() {
- err.span_label(self.session.codemap().def_span(old_binding.span),
+ err.span_label(self.session.source_map().def_span(old_binding.span),
format!("previous {} of the {} `{}` here", old_noun, old_kind, name));
}
old_binding
};
- let cm = self.session.codemap();
+ let cm = self.session.source_map();
let rename_msg = "You can use `as` to change the binding name of the import";
if let (Ok(snippet), false) = (cm.span_to_snippet(binding.span),
format!("other_{}", name)
};
- err.span_suggestion(binding.span,
- rename_msg,
- if snippet.ends_with(';') {
- format!("{} as {};",
- &snippet[..snippet.len()-1],
- suggested_name)
- } else {
- format!("{} as {}", snippet, suggested_name)
- });
+ err.span_suggestion_with_applicability(
+ binding.span,
+ rename_msg,
+ if snippet.ends_with(';') {
+ format!("{} as {};", &snippet[..snippet.len() - 1], suggested_name)
+ } else {
+ format!("{} as {}", snippet, suggested_name)
+ },
+ Applicability::MachineApplicable,
+ );
} else {
err.span_label(binding.span, rename_msg);
}
err.emit();
self.name_already_seen.insert(name, span);
}
-
- fn check_proc_macro_attrs(&mut self, attrs: &[ast::Attribute]) {
- if self.use_extern_macros { return; }
-
- for attr in attrs {
- if attr.path.segments.len() > 1 {
- continue
- }
- let ident = attr.path.segments[0].ident;
- let result = self.resolve_lexical_macro_path_segment(ident,
- MacroNS,
- false,
- false,
- true,
- attr.path.span);
- if let Ok(binding) = result {
- if let SyntaxExtension::AttrProcMacro(..) = *binding.binding().get_macro(self) {
- attr::mark_known(attr);
-
- let msg = "attribute procedural macros are experimental";
- let feature = "use_extern_macros";
-
- feature_err(&self.session.parse_sess, feature,
- attr.span, GateIssue::Language, msg)
- .span_label(binding.span(), "procedural macro imported here")
- .emit();
- }
- }
- }
- }
}
fn is_self_type(path: &[Ident], namespace: Namespace) -> bool {