html_root_url = "https://doc.rust-lang.org/nightly/")]
#![feature(crate_visibility_modifier)]
-#![cfg_attr(not(stage0), feature(nll))]
+#![feature(nll)]
#![feature(rustc_diagnostic_macros)]
#![feature(slice_sort_by_cached_key)]
use rustc::hir::def::*;
use rustc::hir::def::Namespace::*;
use rustc::hir::def_id::{CRATE_DEF_INDEX, LOCAL_CRATE, DefId};
-use rustc::ty;
use rustc::hir::{Freevar, FreevarMap, TraitCandidate, TraitMap, GlobMap};
+use rustc::session::config::nightly_options;
+use rustc::ty;
use rustc::util::nodemap::{NodeMap, NodeSet, FxHashMap, FxHashSet, DefIdMap};
use rustc_metadata::creader::CrateLoader;
use syntax::ast::{Item, ItemKind, ImplItem, ImplItemKind};
use syntax::ast::{Label, Local, Mutability, Pat, PatKind, Path};
use syntax::ast::{QSelf, TraitItemKind, TraitRef, Ty, TyKind};
-use syntax::feature_gate::{feature_err, GateIssue};
use syntax::ptr::P;
use syntax_pos::{Span, DUMMY_SP, MultiSpan};
graph_root: Module<'a>,
prelude: Option<Module<'a>>,
- extern_prelude: FxHashSet<Name>,
/// n.b. This is used only for better diagnostics, not name resolution itself.
has_self: FxHashSet<DefId>,
/// The current self type if inside an impl (used for better errors).
current_self_type: Option<Ty>,
+ /// The current self item if inside an ADT (used for better errors).
+ current_self_item: Option<NodeId>,
+
/// The idents for the primitive types.
primitive_type_table: PrimitiveTypeTable,
current_type_ascription: Vec<Span>,
injected_crate: Option<Module<'a>>,
-
- /// Only supposed to be used by rustdoc, otherwise should be false.
- pub ignore_extern_prelude_feature: bool,
}
/// Nothing really interesting here, it just provides memory for the rest of the crate.
DefCollector::new(&mut definitions, Mark::root())
.collect_root(crate_name, session.local_crate_disambiguator());
- let mut extern_prelude: FxHashSet<Name> =
- session.opts.externs.iter().map(|kv| Symbol::intern(kv.0)).collect();
-
- // HACK(eddyb) this ignore the `no_{core,std}` attributes.
- // FIXME(eddyb) warn (elsewhere) if core/std is used with `no_{core,std}`.
- // if !attr::contains_name(&krate.attrs, "no_core") {
- // if !attr::contains_name(&krate.attrs, "no_std") {
- extern_prelude.insert(Symbol::intern("core"));
- extern_prelude.insert(Symbol::intern("std"));
- extern_prelude.insert(Symbol::intern("meta"));
-
let mut invocations = FxHashMap();
invocations.insert(Mark::root(),
arenas.alloc_invocation_data(InvocationData::root(graph_root)));
// AST.
graph_root,
prelude: None,
- extern_prelude,
has_self: FxHashSet(),
field_names: FxHashMap(),
current_trait_ref: None,
current_self_type: None,
+ current_self_item: None,
primitive_type_table: PrimitiveTypeTable::new(),
unused_macros: FxHashSet(),
current_type_ascription: Vec::new(),
injected_crate: None,
- ignore_extern_prelude_feature: false,
}
}
if !module.no_implicit_prelude {
// `record_used` means that we don't try to load crates during speculative resolution
- if record_used && ns == TypeNS && self.extern_prelude.contains(&ident.name) {
- if !self.session.features_untracked().extern_prelude &&
- !self.ignore_extern_prelude_feature {
- feature_err(&self.session.parse_sess, "extern_prelude",
- ident.span, GateIssue::Language,
- "access to extern crates through prelude is experimental").emit();
- }
-
+ if record_used && ns == TypeNS && self.session.extern_prelude.contains(&ident.name) {
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);
}
fn resolve_adt(&mut self, item: &Item, generics: &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| {
+ self.with_current_self_item(item, |this| {
+ this.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);
- });
- } else {
- visit::walk_item(this, item);
- }
+ }
+ });
});
}
result
}
+ fn with_current_self_item<T, F>(&mut self, self_item: &Item, f: F) -> T
+ where F: FnOnce(&mut Resolver) -> T
+ {
+ let previous_value = replace(&mut self.current_self_item, Some(self_item.id));
+ let result = f(self);
+ self.current_self_item = previous_value;
+ result
+ }
+
/// This is called to resolve a trait reference from an `impl` (i.e. `impl Trait for Foo`)
fn with_optional_trait_ref<T, F>(&mut self, opt_trait_ref: Option<&TraitRef>, f: F) -> T
where F: FnOnce(&mut Resolver, Option<DefId>) -> T
"traits and impls"
};
err.span_label(span, format!("`Self` is only available in {}", available_in));
+ if this.current_self_item.is_some() && nightly_options::is_nightly_build() {
+ err.help("add #![feature(self_in_typedefs)] to the crate attributes \
+ to enable");
+ }
return (err, Vec::new());
}
if is_self_value(path, ns) {
__diagnostic_used!(E0424);
err.code(DiagnosticId::Error("E0424".into()));
- err.span_label(span, format!("`self` value is only available in \
+ err.span_label(span, format!("`self` value is a keyword \
+ only available in \
methods with `self` parameter"));
return (err, Vec::new());
}
Applicability::MachineApplicable,
);
if !self_is_available {
- err.span_label(span, format!("`self` value is only available in \
+ err.span_label(span, format!("`self` value is a keyword \
+ only available in \
methods with `self` parameter"));
}
}
// 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.source_map();
+ let sm = this.session.source_map();
let mut sp = span;
loop {
- sp = cm.next_point(sp);
- match cm.span_to_snippet(sp) {
+ sp = sm.next_point(sp);
+ match sm.span_to_snippet(sp) {
Ok(ref snippet) => {
if snippet.chars().any(|c| { !c.is_whitespace() }) {
break;
_ => break,
}
}
- let followed_by_brace = match cm.span_to_snippet(sp) {
+ let followed_by_brace = match sm.span_to_snippet(sp) {
Ok(ref snippet) if snippet == "{" => true,
_ => false,
};
- if let (PathSource::Expr(None), true) = (source, followed_by_brace) {
- err.span_label(
- span,
- format!("did you mean `({} {{ /* fields */ }})`?", path_str),
- );
- } else {
- err.span_label(
- span,
- format!("did you mean `{} {{ /* fields */ }}`?", path_str),
- );
+ match source {
+ PathSource::Expr(Some(parent)) => {
+ match parent.node {
+ ExprKind::MethodCall(ref path_assignment, _) => {
+ err.span_suggestion_with_applicability(
+ sm.start_point(parent.span)
+ .to(path_assignment.ident.span),
+ "use `::` to access an associated function",
+ format!("{}::{}",
+ path_str,
+ path_assignment.ident),
+ Applicability::MaybeIncorrect
+ );
+ return (err, candidates);
+ },
+ _ => {
+ err.span_label(
+ span,
+ format!("did you mean `{} {{ /* fields */ }}`?",
+ path_str),
+ );
+ return (err, candidates);
+ },
+ }
+ },
+ PathSource::Expr(None) if followed_by_brace == true => {
+ err.span_label(
+ span,
+ format!("did you mean `({} {{ /* fields */ }})`?",
+ path_str),
+ );
+ return (err, candidates);
+ },
+ _ => {
+ err.span_label(
+ span,
+ format!("did you mean `{} {{ /* fields */ }}`?",
+ path_str),
+ );
+ return (err, candidates);
+ },
}
}
return (err, candidates);
}
if name == keywords::Extern.name() ||
name == keywords::CrateRoot.name() &&
- self.session.features_untracked().extern_absolute_paths &&
self.session.rust_2018() {
module = Some(ModuleOrUniformRoot::UniformRoot(name));
continue;
return
}
- // In the 2015 edition there's no use in emitting lints unless the
- // crate's already enabled the feature that we're going to suggest
- if !self.session.features_untracked().crate_in_paths {
- return
- }
-
let (diag_id, diag_span) = match crate_lint {
CrateLint::No => return,
CrateLint::SimplePath(id) => (id, path_span),
} else {
// Items from the prelude
if !module.no_implicit_prelude {
- names.extend(self.extern_prelude.iter().cloned());
+ names.extend(self.session.extern_prelude.iter().cloned());
if let Some(prelude) = self.prelude {
add_module_candidates(prelude, &mut names);
}
)
);
- if self.session.features_untracked().extern_prelude {
- let extern_prelude_names = self.extern_prelude.clone();
- for &name in extern_prelude_names.iter() {
+ if self.session.rust_2018() {
+ for &name in &self.session.extern_prelude {
let ident = Ident::with_empty_ctxt(name);
match self.crate_loader.maybe_process_path_extern(name, ident.span) {
Some(crate_id) => {