#![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 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;
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 {
"access to extern crates through prelude is experimental").emit();
}
- let crate_id = self.crate_loader.process_path_extern(ident.name, ident.span);
- let crate_root = self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX });
- self.populate_module_if_necessary(crate_root);
+ let crate_root = self.load_extern_prelude_crate_if_needed(ident);
let binding = (crate_root, ty::Visibility::Public,
ident.span, Mark::root()).to_name_binding(self.arenas);
None
}
+ fn load_extern_prelude_crate_if_needed(&mut self, ident: Ident) -> Module<'a> {
+ let crate_id = self.crate_loader.process_path_extern(ident.name, ident.span);
+ let crate_root = self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX });
+ self.populate_module_if_necessary(&crate_root);
+ crate_root
+ }
+
fn hygienic_lexical_parent(&mut self, module: Module<'a>, span: &mut Span)
-> Option<Module<'a>> {
if !module.expansion.is_descendant_of(span.ctxt().outer()) {
// 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();
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);
}
}
- /// When name resolution fails, this method can be used to look up candidate
- /// entities with the expected name. It allows filtering them using the
- /// supplied predicate (which should be used to only accept the types of
- /// definitions expected e.g. traits). The lookup spans across all crates.
- ///
- /// NOTE: The method does not look into imports, but this is not a problem,
- /// since we report the definitions (thus, the de-aliased imports).
- fn lookup_import_candidates<FilterFn>(&mut self,
+ fn lookup_import_candidates_from_module<FilterFn>(&mut self,
lookup_name: Name,
namespace: Namespace,
+ start_module: &'a ModuleData<'a>,
+ crate_name: Ident,
filter_fn: FilterFn)
-> Vec<ImportSuggestion>
where FilterFn: Fn(Def) -> bool
let mut candidates = Vec::new();
let mut worklist = Vec::new();
let mut seen_modules = FxHashSet();
- worklist.push((self.graph_root, Vec::new(), false));
+ let not_local_module = crate_name != keywords::Crate.ident();
+ worklist.push((start_module, Vec::<ast::PathSegment>::new(), not_local_module));
while let Some((in_module,
path_segments,
if ident.name == lookup_name && ns == namespace {
if filter_fn(name_binding.def()) {
// create the path
- let mut segms = if self.session.rust_2018() && !in_module_is_extern {
+ let mut segms = path_segments.clone();
+ if self.session.rust_2018() {
// crate-local absolute paths start with `crate::` in edition 2018
// FIXME: may also be stabilized for Rust 2015 (Issues #45477, #44660)
- let mut full_segms = vec![
- ast::PathSegment::from_ident(keywords::Crate.ident())
- ];
- full_segms.extend(path_segments.clone());
- full_segms
- } else {
- path_segments.clone()
- };
+ segms.insert(
+ 0, ast::PathSegment::from_ident(crate_name)
+ );
+ }
segms.push(ast::PathSegment::from_ident(ident));
let path = Path {
let mut path_segments = path_segments.clone();
path_segments.push(ast::PathSegment::from_ident(ident));
- if !in_module_is_extern || name_binding.vis == ty::Visibility::Public {
+ let is_extern_crate_that_also_appears_in_prelude =
+ name_binding.is_extern_crate() &&
+ self.session.rust_2018();
+
+ let is_visible_to_user =
+ !in_module_is_extern || name_binding.vis == ty::Visibility::Public;
+
+ if !is_extern_crate_that_also_appears_in_prelude && is_visible_to_user {
// add the module to the lookup
let is_extern = in_module_is_extern || name_binding.is_extern_crate();
if seen_modules.insert(module.def_id().unwrap()) {
candidates
}
+ /// When name resolution fails, this method can be used to look up candidate
+ /// entities with the expected name. It allows filtering them using the
+ /// supplied predicate (which should be used to only accept the types of
+ /// definitions expected e.g. traits). The lookup spans across all crates.
+ ///
+ /// NOTE: The method does not look into imports, but this is not a problem,
+ /// since we report the definitions (thus, the de-aliased imports).
+ fn lookup_import_candidates<FilterFn>(&mut self,
+ lookup_name: Name,
+ namespace: Namespace,
+ filter_fn: FilterFn)
+ -> Vec<ImportSuggestion>
+ where FilterFn: Fn(Def) -> bool
+ {
+ let mut suggestions = vec![];
+
+ suggestions.extend(
+ self.lookup_import_candidates_from_module(
+ lookup_name, namespace, self.graph_root, keywords::Crate.ident(), &filter_fn
+ )
+ );
+
+ if self.session.features_untracked().extern_prelude {
+ let extern_prelude_names = self.extern_prelude.clone();
+ for &krate_name in extern_prelude_names.iter() {
+ let krate_ident = Ident::with_empty_ctxt(krate_name);
+ let external_prelude_module = self.load_extern_prelude_crate_if_needed(krate_ident);
+
+ suggestions.extend(
+ self.lookup_import_candidates_from_module(
+ lookup_name, namespace, external_prelude_module, krate_ident, &filter_fn
+ )
+ );
+ }
+ }
+
+ suggestions
+ }
+
fn find_module(&mut self,
module_def: Def)
-> Option<(Module<'a>, ImportSuggestion)>
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);
}