Skip to content

Rollup of 4 pull requests #63437

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 17 commits into from
Aug 10, 2019
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -27,6 +27,7 @@ __pycache__/
/inst/
/llvm/
/mingw-build/
# Created by default with `src/ci/docker/run.sh`:
/obj/
/rustllvm/
/src/libcore/unicode/DerivedCoreProperties.txt
@@ -38,6 +39,8 @@ __pycache__/
/src/libcore/unicode/UnicodeData.txt
/src/libcore/unicode/downloaded
/target/
# Generated by compiletest for incremental:
/tmp/
tags
tags.*
TAGS
92 changes: 38 additions & 54 deletions src/librustc/hir/lowering.rs
Original file line number Diff line number Diff line change
@@ -37,7 +37,7 @@ use crate::hir::{self, ParamName};
use crate::hir::HirVec;
use crate::hir::map::{DefKey, DefPathData, Definitions};
use crate::hir::def_id::{DefId, DefIndex, CRATE_DEF_INDEX};
use crate::hir::def::{Res, DefKind, PartialRes, PerNS};
use crate::hir::def::{Namespace, Res, DefKind, PartialRes, PerNS};
use crate::hir::{GenericArg, ConstArg};
use crate::hir::ptr::P;
use crate::lint::builtin::{self, PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES,
@@ -148,13 +148,6 @@ pub struct LoweringContext<'a> {
}

pub trait Resolver {
/// Resolve a path generated by the lowerer when expanding `for`, `if let`, etc.
fn resolve_ast_path(
&mut self,
path: &ast::Path,
is_value: bool,
) -> Res<NodeId>;

/// Obtain resolution for a `NodeId` with a single resolution.
fn get_partial_res(&mut self, id: NodeId) -> Option<PartialRes>;

@@ -175,7 +168,7 @@ pub trait Resolver {
span: Span,
crate_root: Option<Symbol>,
components: &[Symbol],
is_value: bool,
ns: Namespace,
) -> (ast::Path, Res<NodeId>);

fn has_derives(&self, node_id: NodeId, derives: SpecialDerives) -> bool;
@@ -4447,23 +4440,23 @@ impl<'a> LoweringContext<'a> {
})
}

fn lower_exprs(&mut self, exprs: &[AstP<Expr>]) -> HirVec<hir::Expr> {
exprs.iter().map(|x| self.lower_expr(x)).collect()
}

fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
let kind = match e.node {
ExprKind::Box(ref inner) => hir::ExprKind::Box(P(self.lower_expr(inner))),
ExprKind::Array(ref exprs) => {
hir::ExprKind::Array(exprs.iter().map(|x| self.lower_expr(x)).collect())
}
ExprKind::Array(ref exprs) => hir::ExprKind::Array(self.lower_exprs(exprs)),
ExprKind::Repeat(ref expr, ref count) => {
let expr = P(self.lower_expr(expr));
let count = self.lower_anon_const(count);
hir::ExprKind::Repeat(expr, count)
}
ExprKind::Tup(ref elts) => {
hir::ExprKind::Tup(elts.iter().map(|x| self.lower_expr(x)).collect())
}
ExprKind::Tup(ref elts) => hir::ExprKind::Tup(self.lower_exprs(elts)),
ExprKind::Call(ref f, ref args) => {
let f = P(self.lower_expr(f));
hir::ExprKind::Call(f, args.iter().map(|x| self.lower_expr(x)).collect())
hir::ExprKind::Call(f, self.lower_exprs(args))
}
ExprKind::MethodCall(ref seg, ref args) => {
let hir_seg = P(self.lower_path_segment(
@@ -4475,7 +4468,7 @@ impl<'a> LoweringContext<'a> {
ImplTraitContext::disallowed(),
None,
));
let args = args.iter().map(|x| self.lower_expr(x)).collect();
let args = self.lower_exprs(args);
hir::ExprKind::MethodCall(hir_seg, seg.ident.span, args)
}
ExprKind::Binary(binop, ref lhs, ref rhs) => {
@@ -5049,17 +5042,9 @@ impl<'a> LoweringContext<'a> {
));
let arms = hir_vec![pat_arm, break_arm];

P(self.expr(
head_sp,
hir::ExprKind::Match(
next_expr,
arms,
hir::MatchSource::ForLoopDesugar
),
ThinVec::new(),
))
self.expr_match(head_sp, next_expr, arms, hir::MatchSource::ForLoopDesugar)
};
let match_stmt = self.stmt(head_sp, hir::StmtKind::Expr(match_expr));
let match_stmt = self.stmt_expr(head_sp, match_expr);

let next_expr = P(self.expr_ident(head_sp, next_ident, next_pat_hid));

@@ -5083,8 +5068,8 @@ impl<'a> LoweringContext<'a> {
);

let body_block = self.with_loop_scope(e.id, |this| this.lower_block(body, false));
let body_expr = P(self.expr_block(body_block, ThinVec::new()));
let body_stmt = self.stmt(body.span, hir::StmtKind::Expr(body_expr));
let body_expr = self.expr_block(body_block, ThinVec::new());
let body_stmt = self.stmt_expr(body.span, body_expr);

let loop_block = P(self.block_all(
e.span,
@@ -5127,8 +5112,10 @@ impl<'a> LoweringContext<'a> {
));

// This is effectively `{ let _result = ...; _result }`.
// The construct was introduced in #21984.
// FIXME(60253): Is this still necessary?
// The construct was introduced in #21984 and is necessary to make sure that
// temporaries in the `head` expression are dropped and do not leak to the
// surrounding scope of the `match` since the `match` is not a terminating scope.
//
// Also, add the attributes to the outer returned expr node.
return self.expr_drop_temps(head_sp, match_expr, e.attrs.clone())
}
@@ -5254,7 +5241,7 @@ impl<'a> LoweringContext<'a> {
}

fn lower_stmt(&mut self, s: &Stmt) -> SmallVec<[hir::Stmt; 1]> {
smallvec![match s.node {
let node = match s.node {
StmtKind::Local(ref l) => {
let (l, item_ids) = self.lower_local(l);
let mut ids: SmallVec<[hir::Stmt; 1]> = item_ids
@@ -5291,21 +5278,14 @@ impl<'a> LoweringContext<'a> {
})
.collect();
}
StmtKind::Expr(ref e) => {
hir::Stmt {
hir_id: self.lower_node_id(s.id),
node: hir::StmtKind::Expr(P(self.lower_expr(e))),
span: s.span,
}
},
StmtKind::Semi(ref e) => {
hir::Stmt {
hir_id: self.lower_node_id(s.id),
node: hir::StmtKind::Semi(P(self.lower_expr(e))),
span: s.span,
}
},
StmtKind::Expr(ref e) => hir::StmtKind::Expr(P(self.lower_expr(e))),
StmtKind::Semi(ref e) => hir::StmtKind::Semi(P(self.lower_expr(e))),
StmtKind::Mac(..) => panic!("Shouldn't exist here"),
};
smallvec![hir::Stmt {
hir_id: self.lower_node_id(s.id),
node,
span: s.span,
}]
}

@@ -5567,6 +5547,10 @@ impl<'a> LoweringContext<'a> {
hir::Stmt { span, node, hir_id: self.next_id() }
}

fn stmt_expr(&mut self, span: Span, expr: hir::Expr) -> hir::Stmt {
self.stmt(span, hir::StmtKind::Expr(P(expr)))
}

fn stmt_let_pat(
&mut self,
attrs: ThinVec<Attribute>,
@@ -5717,8 +5701,8 @@ impl<'a> LoweringContext<'a> {
params: Option<P<hir::GenericArgs>>,
is_value: bool,
) -> hir::Path {
let (path, res) = self.resolver
.resolve_str_path(span, self.crate_root, components, is_value);
let ns = if is_value { Namespace::ValueNS } else { Namespace::TypeNS };
let (path, res) = self.resolver.resolve_str_path(span, self.crate_root, components, ns);

let mut segments: Vec<_> = path.segments.iter().map(|segment| {
let res = self.expect_full_res(segment.id);
@@ -6060,23 +6044,23 @@ impl<'a> LoweringContext<'a> {
};

let match_stmt = {
let match_expr = P(self.expr_match(
let match_expr = self.expr_match(
span,
poll_expr,
hir_vec![ready_arm, pending_arm],
hir::MatchSource::AwaitDesugar,
));
self.stmt(span, hir::StmtKind::Expr(match_expr))
);
self.stmt_expr(span, match_expr)
};

let yield_stmt = {
let unit = self.expr_unit(span);
let yield_expr = P(self.expr(
let yield_expr = self.expr(
span,
hir::ExprKind::Yield(P(unit), hir::YieldSource::Await),
ThinVec::new(),
));
self.stmt(span, hir::StmtKind::Expr(yield_expr))
);
self.stmt_expr(span, yield_expr)
};

let loop_block = P(self.block_all(
21 changes: 6 additions & 15 deletions src/librustc_driver/lib.rs
Original file line number Diff line number Diff line change
@@ -957,14 +957,11 @@ fn print_flag_list<T>(cmdline_opt: &str,
/// otherwise returns `None`.
///
/// The compiler's handling of options is a little complicated as it ties into
/// our stability story, and it's even *more* complicated by historical
/// accidents. The current intention of each compiler option is to have one of
/// three modes:
/// our stability story. The current intention of each compiler option is to
/// have one of two modes:
///
/// 1. An option is stable and can be used everywhere.
/// 2. An option is unstable, but was historically allowed on the stable
/// channel.
/// 3. An option is unstable, and can only be used on nightly.
/// 2. An option is unstable, and can only be used on nightly.
///
/// Like unstable library and language features, however, unstable options have
/// always required a form of "opt in" to indicate that you're using them. This
@@ -1007,19 +1004,13 @@ pub fn handle_options(args: &[String]) -> Option<getopts::Matches> {
// this option that was passed.
// * If we're a nightly compiler, then unstable options are now unlocked, so
// we're good to go.
// * Otherwise, if we're a truly unstable option then we generate an error
// * Otherwise, if we're an unstable option then we generate an error
// (unstable option being used on stable)
// * If we're a historically stable-but-should-be-unstable option then we
// emit a warning that we're going to turn this into an error soon.
nightly_options::check_nightly_options(&matches, &config::rustc_optgroups());

if matches.opt_present("h") || matches.opt_present("help") {
// Only show unstable options in --help if we *really* accept unstable
// options, which catches the case where we got `-Z unstable-options` on
// the stable channel of Rust which was accidentally allowed
// historically.
usage(matches.opt_present("verbose"),
nightly_options::is_unstable_enabled(&matches));
// Only show unstable options in --help if we accept unstable options.
usage(matches.opt_present("verbose"), nightly_options::is_unstable_enabled(&matches));
return None;
}

750 changes: 480 additions & 270 deletions src/librustc_resolve/build_reduced_graph.rs

Large diffs are not rendered by default.

201 changes: 91 additions & 110 deletions src/librustc_resolve/check_unused.rs
Original file line number Diff line number Diff line change
@@ -23,8 +23,6 @@
// - `check_crate` finally emits the diagnostics based on the data generated
// in the last step

use std::ops::{Deref, DerefMut};

use crate::Resolver;
use crate::resolve_imports::ImportDirectiveSubclass;

@@ -49,45 +47,30 @@ impl<'a> UnusedImport<'a> {
}

struct UnusedImportCheckVisitor<'a, 'b> {
resolver: &'a mut Resolver<'b>,
r: &'a mut Resolver<'b>,
/// All the (so far) unused imports, grouped path list
unused_imports: NodeMap<UnusedImport<'a>>,
base_use_tree: Option<&'a ast::UseTree>,
base_id: ast::NodeId,
item_span: Span,
}

// Deref and DerefMut impls allow treating UnusedImportCheckVisitor as Resolver.
impl<'a, 'b> Deref for UnusedImportCheckVisitor<'a, 'b> {
type Target = Resolver<'b>;

fn deref<'c>(&'c self) -> &'c Resolver<'b> {
&*self.resolver
}
}

impl<'a, 'b> DerefMut for UnusedImportCheckVisitor<'a, 'b> {
fn deref_mut<'c>(&'c mut self) -> &'c mut Resolver<'b> {
&mut *self.resolver
}
}

impl<'a, 'b> UnusedImportCheckVisitor<'a, 'b> {
// We have information about whether `use` (import) directives are actually
// used now. If an import is not used at all, we signal a lint error.
fn check_import(&mut self, id: ast::NodeId) {
let mut used = false;
self.per_ns(|this, ns| used |= this.used_imports.contains(&(id, ns)));
self.r.per_ns(|this, ns| used |= this.used_imports.contains(&(id, ns)));
if !used {
if self.maybe_unused_trait_imports.contains(&id) {
if self.r.maybe_unused_trait_imports.contains(&id) {
// Check later.
return;
}
self.unused_import(self.base_id).add(id);
} else {
// This trait import is definitely used, in a way other than
// method resolution.
self.maybe_unused_trait_imports.remove(&id);
self.r.maybe_unused_trait_imports.remove(&id);
if let Some(i) = self.unused_imports.get_mut(&self.base_id) {
i.unused.remove(&id);
}
@@ -238,104 +221,102 @@ fn calc_unused_spans(
}
}

pub fn check_crate(resolver: &mut Resolver<'_>, krate: &ast::Crate) {
for directive in resolver.potentially_unused_imports.iter() {
match directive.subclass {
_ if directive.used.get() ||
directive.vis.get() == ty::Visibility::Public ||
directive.span.is_dummy() => {
if let ImportDirectiveSubclass::MacroUse = directive.subclass {
if !directive.span.is_dummy() {
resolver.session.buffer_lint(
lint::builtin::MACRO_USE_EXTERN_CRATE,
directive.id,
directive.span,
"deprecated `#[macro_use]` directive used to \
import macros should be replaced at use sites \
with a `use` statement to import the macro \
instead",
);
impl Resolver<'_> {
crate fn check_unused(&mut self, krate: &ast::Crate) {
for directive in self.potentially_unused_imports.iter() {
match directive.subclass {
_ if directive.used.get() ||
directive.vis.get() == ty::Visibility::Public ||
directive.span.is_dummy() => {
if let ImportDirectiveSubclass::MacroUse = directive.subclass {
if !directive.span.is_dummy() {
self.session.buffer_lint(
lint::builtin::MACRO_USE_EXTERN_CRATE,
directive.id,
directive.span,
"deprecated `#[macro_use]` directive used to \
import macros should be replaced at use sites \
with a `use` statement to import the macro \
instead",
);
}
}
}
ImportDirectiveSubclass::ExternCrate { .. } => {
self.maybe_unused_extern_crates.push((directive.id, directive.span));
}
ImportDirectiveSubclass::MacroUse => {
let lint = lint::builtin::UNUSED_IMPORTS;
let msg = "unused `#[macro_use]` import";
self.session.buffer_lint(lint, directive.id, directive.span, msg);
}
_ => {}
}
ImportDirectiveSubclass::ExternCrate { .. } => {
resolver.maybe_unused_extern_crates.push((directive.id, directive.span));
}
ImportDirectiveSubclass::MacroUse => {
let lint = lint::builtin::UNUSED_IMPORTS;
let msg = "unused `#[macro_use]` import";
resolver.session.buffer_lint(lint, directive.id, directive.span, msg);
}
_ => {}
}
}

for (id, span) in resolver.unused_labels.iter() {
resolver.session.buffer_lint(lint::builtin::UNUSED_LABELS, *id, *span, "unused label");
}

let mut visitor = UnusedImportCheckVisitor {
resolver,
unused_imports: Default::default(),
base_use_tree: None,
base_id: ast::DUMMY_NODE_ID,
item_span: DUMMY_SP,
};
visit::walk_crate(&mut visitor, krate);

for unused in visitor.unused_imports.values() {
let mut fixes = Vec::new();
let mut spans = match calc_unused_spans(unused, unused.use_tree, unused.use_tree_id) {
UnusedSpanResult::Used => continue,
UnusedSpanResult::FlatUnused(span, remove) => {
fixes.push((remove, String::new()));
vec![span]
}
UnusedSpanResult::NestedFullUnused(spans, remove) => {
fixes.push((remove, String::new()));
spans
}
UnusedSpanResult::NestedPartialUnused(spans, remove) => {
for fix in &remove {
fixes.push((*fix, String::new()));
}
spans
}
let mut visitor = UnusedImportCheckVisitor {
r: self,
unused_imports: Default::default(),
base_use_tree: None,
base_id: ast::DUMMY_NODE_ID,
item_span: DUMMY_SP,
};
visit::walk_crate(&mut visitor, krate);

let len = spans.len();
spans.sort();
let ms = MultiSpan::from_spans(spans.clone());
let mut span_snippets = spans.iter()
.filter_map(|s| {
match visitor.session.source_map().span_to_snippet(*s) {
Ok(s) => Some(format!("`{}`", s)),
_ => None,
for unused in visitor.unused_imports.values() {
let mut fixes = Vec::new();
let mut spans = match calc_unused_spans(unused, unused.use_tree, unused.use_tree_id) {
UnusedSpanResult::Used => continue,
UnusedSpanResult::FlatUnused(span, remove) => {
fixes.push((remove, String::new()));
vec![span]
}
}).collect::<Vec<String>>();
span_snippets.sort();
let msg = format!("unused import{}{}",
if len > 1 { "s" } else { "" },
if !span_snippets.is_empty() {
format!(": {}", span_snippets.join(", "))
} else {
String::new()
});
UnusedSpanResult::NestedFullUnused(spans, remove) => {
fixes.push((remove, String::new()));
spans
}
UnusedSpanResult::NestedPartialUnused(spans, remove) => {
for fix in &remove {
fixes.push((*fix, String::new()));
}
spans
}
};

let fix_msg = if fixes.len() == 1 && fixes[0].0 == unused.item_span {
"remove the whole `use` item"
} else if spans.len() > 1 {
"remove the unused imports"
} else {
"remove the unused import"
};
let len = spans.len();
spans.sort();
let ms = MultiSpan::from_spans(spans.clone());
let mut span_snippets = spans.iter()
.filter_map(|s| {
match visitor.r.session.source_map().span_to_snippet(*s) {
Ok(s) => Some(format!("`{}`", s)),
_ => None,
}
}).collect::<Vec<String>>();
span_snippets.sort();
let msg = format!("unused import{}{}",
if len > 1 { "s" } else { "" },
if !span_snippets.is_empty() {
format!(": {}", span_snippets.join(", "))
} else {
String::new()
});

visitor.session.buffer_lint_with_diagnostic(
lint::builtin::UNUSED_IMPORTS,
unused.use_tree_id,
ms,
&msg,
lint::builtin::BuiltinLintDiagnostics::UnusedImports(fix_msg.into(), fixes),
);
let fix_msg = if fixes.len() == 1 && fixes[0].0 == unused.item_span {
"remove the whole `use` item"
} else if spans.len() > 1 {
"remove the unused imports"
} else {
"remove the unused import"
};

visitor.r.session.buffer_lint_with_diagnostic(
lint::builtin::UNUSED_IMPORTS,
unused.use_tree_id,
ms,
&msg,
lint::builtin::BuiltinLintDiagnostics::UnusedImports(fix_msg.into(), fixes),
);
}
}
}
907 changes: 269 additions & 638 deletions src/librustc_resolve/diagnostics.rs

Large diffs are not rendered by default.

2,004 changes: 2,004 additions & 0 deletions src/librustc_resolve/late.rs

Large diffs are not rendered by default.

770 changes: 770 additions & 0 deletions src/librustc_resolve/late/diagnostics.rs

Large diffs are not rendered by default.

2,725 changes: 153 additions & 2,572 deletions src/librustc_resolve/lib.rs

Large diffs are not rendered by default.

139 changes: 32 additions & 107 deletions src/librustc_resolve/macros.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
use crate::{AmbiguityError, AmbiguityKind, AmbiguityErrorMisc, Determinacy};
use crate::{CrateLint, Resolver, ResolutionError, Scope, ScopeSet, ParentScope, Weak};
use crate::{Module, ModuleKind, NameBinding, PathResult, Segment, ToNameBinding};
use crate::{resolve_error, KNOWN_TOOLS};
use crate::ModuleOrUniformRoot;
use crate::{ModuleOrUniformRoot, KNOWN_TOOLS};
use crate::Namespace::*;
use crate::build_reduced_graph::{BuildReducedGraphVisitor, IsMacroExport};
use crate::build_reduced_graph::BuildReducedGraphVisitor;
use crate::resolve_imports::ImportResolver;
use rustc::hir::def_id::{DefId, CRATE_DEF_INDEX};
use rustc::hir::def::{self, DefKind, NonMacroAttrKind};
use rustc::hir::map::DefCollector;
use rustc::middle::stability;
use rustc::{ty, lint, span_bug};
use syntax::ast::{self, Ident, ItemKind};
use syntax::attr::{self, StabilityLevel};
use syntax::ast::{self, Ident};
use syntax::attr::StabilityLevel;
use syntax::edition::Edition;
use syntax::ext::base::{self, Indeterminate, SpecialDerives};
use syntax::ext::base::{MacroKind, SyntaxExtension};
@@ -116,21 +114,6 @@ fn fast_print_path(path: &ast::Path) -> Symbol {
}
}

fn proc_macro_stub(item: &ast::Item) -> Option<(MacroKind, Ident, Span)> {
if attr::contains_name(&item.attrs, sym::proc_macro) {
return Some((MacroKind::Bang, item.ident, item.span));
} else if attr::contains_name(&item.attrs, sym::proc_macro_attribute) {
return Some((MacroKind::Attr, item.ident, item.span));
} else if let Some(attr) = attr::find_by_name(&item.attrs, sym::proc_macro_derive) {
if let Some(nested_meta) = attr.meta_item_list().and_then(|list| list.get(0).cloned()) {
if let Some(ident) = nested_meta.ident() {
return Some((MacroKind::Derive, ident, ident.span));
}
}
}
None
}

impl<'a> base::Resolver for Resolver<'a> {
fn next_node_id(&mut self) -> ast::NodeId {
self.session.next_node_id()
@@ -166,21 +149,24 @@ impl<'a> base::Resolver for Resolver<'a> {
fragment.visit_with(&mut DefCollector::new(&mut self.definitions, expn_id));

let invocation = self.invocations[&expn_id];
self.current_module = invocation.module;
self.current_module.unresolved_invocations.borrow_mut().remove(&expn_id);
self.current_module.unresolved_invocations.borrow_mut().extend(derives);
invocation.module.unresolved_invocations.borrow_mut().remove(&expn_id);
invocation.module.unresolved_invocations.borrow_mut().extend(derives);
let parent_def = self.definitions.invocation_parent(expn_id);
for &derive_invoc_id in derives {
self.definitions.set_invocation_parent(derive_invoc_id, parent_def);
}
self.invocations.extend(derives.iter().map(|&derive| (derive, invocation)));
let mut visitor = BuildReducedGraphVisitor {
resolver: self,
current_legacy_scope: invocation.parent_legacy_scope,
expansion: expn_id,
r: self,
parent_scope: ParentScope {
module: invocation.module,
expansion: expn_id,
legacy: invocation.parent_legacy_scope,
derives: Vec::new(),
},
};
fragment.visit_with(&mut visitor);
invocation.output_legacy_scope.set(Some(visitor.current_legacy_scope));
invocation.output_legacy_scope.set(Some(visitor.parent_scope.legacy));
}

fn register_builtin_macro(&mut self, ident: ast::Ident, ext: SyntaxExtension) {
@@ -191,7 +177,7 @@ impl<'a> base::Resolver for Resolver<'a> {
}

fn resolve_imports(&mut self) {
ImportResolver { resolver: self }.resolve_imports()
ImportResolver { r: self }.resolve_imports()
}

fn resolve_macro_invocation(&mut self, invoc: &Invocation, invoc_id: ExpnId, force: bool)
@@ -210,10 +196,10 @@ impl<'a> base::Resolver for Resolver<'a> {
// will automatically knows about itself.
let mut result = Ok(None);
if derives.len() > 1 {
let parent_scope = self.invoc_parent_scope(invoc_id, Vec::new());
let parent_scope = &self.invoc_parent_scope(invoc_id, Vec::new());
for path in derives {
match self.resolve_macro_path(path, Some(MacroKind::Derive),
&parent_scope, true, force) {
parent_scope, true, force) {
Ok((Some(ref ext), _)) if ext.is_derive_copy => {
self.add_derives(invoc.expansion_data.id, SpecialDerives::COPY);
return Ok(None);
@@ -227,8 +213,8 @@ impl<'a> base::Resolver for Resolver<'a> {
}
};

let parent_scope = self.invoc_parent_scope(invoc_id, derives_in_scope);
let (ext, res) = self.smart_resolve_macro_path(path, kind, &parent_scope, force)?;
let parent_scope = &self.invoc_parent_scope(invoc_id, derives_in_scope);
let (ext, res) = self.smart_resolve_macro_path(path, kind, parent_scope, force)?;

let span = invoc.span();
invoc.expansion_data.id.set_expn_info(ext.expn_info(span, fast_print_path(path)));
@@ -388,8 +374,7 @@ impl<'a> Resolver<'a> {
self.prohibit_imported_non_macro_attrs(None, res.ok(), path_span);
res
} else {
// Macro without a specific kind restriction is equvalent to a macro import.
let scope_set = kind.map_or(ScopeSet::Import(MacroNS), ScopeSet::Macro);
let scope_set = kind.map_or(ScopeSet::All(MacroNS, false), ScopeSet::Macro);
let binding = self.early_resolve_ident_in_lexical_scope(
path[0].ident, scope_set, parent_scope, false, force, path_span
);
@@ -444,10 +429,9 @@ impl<'a> Resolver<'a> {
}

let (ns, macro_kind, is_import) = match scope_set {
ScopeSet::Import(ns) => (ns, None, true),
ScopeSet::All(ns, is_import) => (ns, None, is_import),
ScopeSet::AbsolutePath(ns) => (ns, None, false),
ScopeSet::Macro(macro_kind) => (MacroNS, Some(macro_kind), false),
ScopeSet::Module => (TypeNS, None, false),
};

// This is *the* result, resolution from the scope closest to the resolved identifier.
@@ -471,9 +455,9 @@ impl<'a> Resolver<'a> {
Scope::DeriveHelpers => {
let mut result = Err(Determinacy::Determined);
for derive in &parent_scope.derives {
let parent_scope = ParentScope { derives: Vec::new(), ..*parent_scope };
let parent_scope = &ParentScope { derives: Vec::new(), ..*parent_scope };
match this.resolve_macro_path(derive, Some(MacroKind::Derive),
&parent_scope, true, force) {
parent_scope, true, force) {
Ok((Some(ext), _)) => if ext.helper_attrs.contains(&ident.name) {
let binding = (Res::NonMacroAttr(NonMacroAttrKind::DeriveHelper),
ty::Visibility::Public, derive.span, ExpnId::root())
@@ -502,7 +486,7 @@ impl<'a> Resolver<'a> {
ModuleOrUniformRoot::Module(root_module),
ident,
ns,
None,
parent_scope,
record_used,
path_span,
);
@@ -516,17 +500,16 @@ impl<'a> Resolver<'a> {
}
}
Scope::Module(module) => {
let orig_current_module = mem::replace(&mut this.current_module, module);
let adjusted_parent_scope = &ParentScope { module, ..parent_scope.clone() };
let binding = this.resolve_ident_in_module_unadjusted_ext(
ModuleOrUniformRoot::Module(module),
ident,
ns,
None,
adjusted_parent_scope,
true,
record_used,
path_span,
);
this.current_module = orig_current_module;
match binding {
Ok(binding) => {
let misc_flags = if ptr::eq(module, this.graph_root) {
@@ -588,6 +571,7 @@ impl<'a> Resolver<'a> {
ModuleOrUniformRoot::Module(prelude),
ident,
ns,
parent_scope,
false,
path_span,
) {
@@ -710,9 +694,7 @@ impl<'a> Resolver<'a> {
}
}

pub fn finalize_current_module_macro_resolutions(&mut self) {
let module = self.current_module;

pub fn finalize_current_module_macro_resolutions(&mut self, module: Module<'a>) {
let check_consistency = |this: &mut Self, path: &[Segment], span, kind: MacroKind,
initial_res: Option<Res>, res: Res| {
if let Some(initial_res) = initial_res {
@@ -753,8 +735,9 @@ impl<'a> Resolver<'a> {
for (mut path, path_span, kind, parent_scope, initial_res) in macro_resolutions {
// FIXME: Path resolution will ICE if segment IDs present.
for seg in &mut path { seg.id = None; }
match self.resolve_path(&path, Some(MacroNS), &parent_scope,
true, path_span, CrateLint::No) {
match self.resolve_path(
&path, Some(MacroNS), &parent_scope, true, path_span, CrateLint::No
) {
PathResult::NonModule(path_res) if path_res.unresolved_segments() == 0 => {
let res = path_res.base_res();
check_consistency(self, &path, path_span, kind, initial_res, res);
@@ -766,7 +749,7 @@ impl<'a> Resolver<'a> {
(path_span, format!("partially resolved path in {} {}",
kind.article(), kind.descr()))
};
resolve_error(self, span, ResolutionError::FailedToResolve {
self.report_error(span, ResolutionError::FailedToResolve {
label,
suggestion: None
});
@@ -886,62 +869,4 @@ impl<'a> Resolver<'a> {

Lrc::new(result)
}

pub fn define_macro(&mut self,
item: &ast::Item,
expansion: ExpnId,
current_legacy_scope: &mut LegacyScope<'a>) {
let (ext, ident, span, is_legacy) = match &item.node {
ItemKind::MacroDef(def) => {
let ext = self.compile_macro(item, self.session.edition());
(ext, item.ident, item.span, def.legacy)
}
ItemKind::Fn(..) => match proc_macro_stub(item) {
Some((macro_kind, ident, span)) => {
self.proc_macro_stubs.insert(item.id);
(self.dummy_ext(macro_kind), ident, span, false)
}
None => return,
}
_ => unreachable!(),
};

let def_id = self.definitions.local_def_id(item.id);
let res = Res::Def(DefKind::Macro(ext.macro_kind()), def_id);
self.macro_map.insert(def_id, ext);
self.local_macro_def_scopes.insert(item.id, self.current_module);

if is_legacy {
let ident = ident.modern();
self.macro_names.insert(ident);
let is_macro_export = attr::contains_name(&item.attrs, sym::macro_export);
let vis = if is_macro_export {
ty::Visibility::Public
} else {
ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX))
};
let binding = (res, vis, span, expansion).to_name_binding(self.arenas);
self.set_binding_parent_module(binding, self.current_module);
let legacy_binding = self.arenas.alloc_legacy_binding(LegacyBinding {
parent_legacy_scope: *current_legacy_scope, binding, ident
});
*current_legacy_scope = LegacyScope::Binding(legacy_binding);
self.all_macros.insert(ident.name, res);
if is_macro_export {
let module = self.graph_root;
self.define(module, ident, MacroNS,
(res, vis, span, expansion, IsMacroExport));
} else {
self.check_reserved_macro_name(ident, res);
self.unused_macros.insert(item.id, span);
}
} else {
let module = self.current_module;
let vis = self.resolve_visibility(&item.vis);
if vis != ty::Visibility::Public {
self.unused_macros.insert(item.id, span);
}
self.define(module, ident, MacroNS, (res, vis, span, expansion));
}
}
}
231 changes: 89 additions & 142 deletions src/librustc_resolve/resolve_imports.rs

Large diffs are not rendered by default.

21 changes: 8 additions & 13 deletions src/librustdoc/passes/collect_intra_doc_links.rs
Original file line number Diff line number Diff line change
@@ -61,15 +61,11 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
{
let cx = self.cx;

// In case we're in a module, try to resolve the relative
// path.
if let Some(id) = parent_id.or(self.mod_ids.last().cloned()) {
// FIXME: `with_scope` requires the `NodeId` of a module.
let node_id = cx.tcx.hir().hir_to_node_id(id);
// In case we're in a module, try to resolve the relative path.
if let Some(module_id) = parent_id.or(self.mod_ids.last().cloned()) {
let module_id = cx.tcx.hir().hir_to_node_id(module_id);
let result = cx.enter_resolver(|resolver| {
resolver.with_scope(node_id, |resolver| {
resolver.resolve_str_path_error(DUMMY_SP, &path_str, ns == ValueNS)
})
resolver.resolve_str_path_error(DUMMY_SP, &path_str, ns, module_id)
});
let result = match result {
Ok((_, Res::Err)) => Err(()),
@@ -85,6 +81,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
Res::Def(DefKind::AssocTy, _) => false,
Res::Def(DefKind::Variant, _) => return handle_variant(cx, res),
// Not a trait item; just return what we found.
Res::PrimTy(..) => return Ok((res, Some(path_str.to_owned()))),
_ => return Ok((res, None))
};

@@ -133,11 +130,9 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
.ok_or(());
}

// FIXME: `with_scope` requires the `NodeId` of a module.
let node_id = cx.tcx.hir().hir_to_node_id(id);
let (_, ty_res) = cx.enter_resolver(|resolver| resolver.with_scope(node_id, |resolver| {
resolver.resolve_str_path_error(DUMMY_SP, &path, false)
}))?;
let (_, ty_res) = cx.enter_resolver(|resolver| {
resolver.resolve_str_path_error(DUMMY_SP, &path, TypeNS, module_id)
})?;
if let Res::Err = ty_res {
return Err(());
}
17 changes: 17 additions & 0 deletions src/test/ui/hygiene/privacy-early.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// edition:2018

#![feature(decl_macro)]

mod foo {
fn f() {}
macro f() {}

pub macro m() {
use f as g; //~ ERROR `f` is private, and cannot be re-exported
f!();
}
}

fn main() {
foo::m!();
}
21 changes: 21 additions & 0 deletions src/test/ui/hygiene/privacy-early.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
error[E0364]: `f` is private, and cannot be re-exported
--> $DIR/privacy-early.rs:10:13
|
LL | use f as g;
| ^^^^^^
...
LL | foo::m!();
| ---------- in this macro invocation
|
note: consider marking `f` as `pub` in the imported module
--> $DIR/privacy-early.rs:10:13
|
LL | use f as g;
| ^^^^^^
...
LL | foo::m!();
| ---------- in this macro invocation

error: aborting due to previous error

For more information about this error, try `rustc --explain E0364`.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// edition:2018
// build-pass (FIXME(62277): could be check-pass?)
// check-pass
// revisions: migrate mir
//[mir]compile-flags: -Z borrowck=mir

4 changes: 2 additions & 2 deletions src/test/ui/resolve/resolve-bad-visibility.rs
Original file line number Diff line number Diff line change
@@ -4,8 +4,8 @@ trait Tr {}
pub(in E) struct S; //~ ERROR expected module, found enum `E`
pub(in Tr) struct Z; //~ ERROR expected module, found trait `Tr`
pub(in std::vec) struct F; //~ ERROR visibilities can only be restricted to ancestor modules
pub(in nonexistent) struct G; //~ ERROR cannot find module `nonexistent` in the crate root
pub(in too_soon) struct H; //~ ERROR cannot find module `too_soon` in the crate root
pub(in nonexistent) struct G; //~ ERROR failed to resolve
pub(in too_soon) struct H; //~ ERROR failed to resolve

// Visibilities are resolved eagerly without waiting for modules becoming fully populated.
// Visibilities can only use ancestor modules legally which are always available in time,
21 changes: 11 additions & 10 deletions src/test/ui/resolve/resolve-bad-visibility.stderr
Original file line number Diff line number Diff line change
@@ -1,9 +1,3 @@
error: visibilities can only be restricted to ancestor modules
--> $DIR/resolve-bad-visibility.rs:6:8
|
LL | pub(in std::vec) struct F;
| ^^^^^^^^

error[E0577]: expected module, found enum `E`
--> $DIR/resolve-bad-visibility.rs:4:8
|
@@ -16,17 +10,24 @@ error[E0577]: expected module, found trait `Tr`
LL | pub(in Tr) struct Z;
| ^^ not a module

error[E0578]: cannot find module `nonexistent` in the crate root
error: visibilities can only be restricted to ancestor modules
--> $DIR/resolve-bad-visibility.rs:6:8
|
LL | pub(in std::vec) struct F;
| ^^^^^^^^

error[E0433]: failed to resolve: maybe a missing crate `nonexistent`?
--> $DIR/resolve-bad-visibility.rs:7:8
|
LL | pub(in nonexistent) struct G;
| ^^^^^^^^^^^ not found in the crate root
| ^^^^^^^^^^^ maybe a missing crate `nonexistent`?

error[E0578]: cannot find module `too_soon` in the crate root
error[E0433]: failed to resolve: maybe a missing crate `too_soon`?
--> $DIR/resolve-bad-visibility.rs:8:8
|
LL | pub(in too_soon) struct H;
| ^^^^^^^^ not found in the crate root
| ^^^^^^^^ maybe a missing crate `too_soon`?

error: aborting due to 5 previous errors

For more information about this error, try `rustc --explain E0433`.
5 changes: 5 additions & 0 deletions src/test/ui/resolve/visibility-indeterminate.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// edition:2018

foo!(); //~ ERROR cannot find macro `foo!` in this scope

pub(in ::bar) struct Baz {} //~ ERROR cannot determine resolution for the visibility
19 changes: 19 additions & 0 deletions src/test/ui/resolve/visibility-indeterminate.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
error[E0578]: cannot determine resolution for the visibility
--> $DIR/visibility-indeterminate.rs:5:8
|
LL | pub(in ::bar) struct Baz {}
| ^^^^^

error: cannot find macro `foo!` in this scope
--> $DIR/visibility-indeterminate.rs:3:1
|
LL | foo!();
| ^^^

error[E0601]: `main` function not found in crate `visibility_indeterminate`
|
= note: consider adding a `main` function to `$DIR/visibility-indeterminate.rs`

error: aborting due to 3 previous errors

For more information about this error, try `rustc --explain E0601`.
14 changes: 6 additions & 8 deletions src/test/ui/span/visibility-ty-params.stderr
Original file line number Diff line number Diff line change
@@ -4,19 +4,17 @@ error: unexpected generic arguments in path
LL | m!{ S<u8> }
| ^^^^^

error[E0577]: expected module, found struct `S`
--> $DIR/visibility-ty-params.rs:6:5
|
LL | m!{ S<u8> }
| ^^^^^ not a module

error: unexpected generic arguments in path
--> $DIR/visibility-ty-params.rs:10:9
|
LL | m!{ m<> }
| ^^^

error[E0577]: expected module, found struct `S`
--> $DIR/visibility-ty-params.rs:6:5
|
LL | m!{ S<u8> }
| -^^^^
| |
| help: a module with a similar name exists: `m`

error: aborting due to 3 previous errors