Auto merge of #59950 - Centril:rollup-hpmr62i, r=Centril

Rollup of 6 pull requests

Successful merges:

 - #59776 (Apply resource-suffix to search-index and source-files scripts as well)
 - #59784 (Suggest importing macros from the crate root)
 - #59812 (Exclude profiler-generated symbols from MSVC __imp_-symbol workaround.)
 - #59874 (Clean up handling of `-Z pgo-gen` commandline option.)
 - #59890 (Don't generate empty json variables)
 - #59911 (Revert "compile crates under test w/ -Zemit-stack-sizes")

Failed merges:

r? @ghost
This commit is contained in:
bors 2019-04-14 01:10:57 +00:00
commit ee621f4232
22 changed files with 880 additions and 198 deletions

View File

@ -187,33 +187,6 @@ fn main() {
cmd.arg("-C").arg(format!("debug-assertions={}", debug_assertions));
}
// Build all crates in the `std` facade with `-Z emit-stack-sizes` to add stack usage
// information.
//
// When you use this `-Z` flag with Cargo you get stack usage information on all crates
// compiled from source, and when you are using LTO you also get information on pre-compiled
// crates like `core` and `std`, even if they were not compiled with `-Z emit-stack-sizes`.
// However, there's an exception: `compiler_builtins`. This crate is special and doesn't
// participate in LTO because it's always linked as a separate object file. For this reason
// it's impossible to get stack usage information about `compiler-builtins` using
// `RUSTFLAGS` + Cargo, or `cargo rustc`.
//
// To make the stack usage information of all crates under the `std` facade available to
// Cargo based stack usage analysis tools, in both LTO and non-LTO mode, we compile them
// with the `-Z emit-stack-sizes` flag. The `RUSTC_EMIT_STACK_SIZES` var helps us apply this
// flag only to the crates in the `std` facade. The `-Z` flag is known to currently work
// with targets that produce ELF files so we limit its use flag to those targets.
//
// NOTE(japaric) if this ever causes problem with an LLVM upgrade or any PR feel free to
// remove it or comment it out
if env::var_os("RUSTC_EMIT_STACK_SIZES").is_some()
&& (target.contains("-linux-")
|| target.contains("-none-eabi")
|| target.ends_with("-none-elf"))
{
cmd.arg("-Zemit-stack-sizes");
}
if let Ok(s) = env::var("RUSTC_CODEGEN_UNITS") {
cmd.arg("-C").arg(format!("codegen-units={}", s));
}

View File

@ -97,8 +97,6 @@ impl Step for Std {
let _folder = builder.fold_output(|| format!("stage{}-std", compiler.stage));
builder.info(&format!("Building stage{} std artifacts ({} -> {})", compiler.stage,
&compiler.host, target));
// compile with `-Z emit-stack-sizes`; see bootstrap/src/rustc.rs for more details
cargo.env("RUSTC_EMIT_STACK_SIZES", "1");
run_cargo(builder,
&mut cargo,
&libstd_stamp(builder, compiler, target),
@ -397,8 +395,6 @@ impl Step for Test {
let _folder = builder.fold_output(|| format!("stage{}-test", compiler.stage));
builder.info(&format!("Building stage{} test artifacts ({} -> {})", compiler.stage,
&compiler.host, target));
// compile with `-Z emit-stack-sizes`; see bootstrap/src/rustc.rs for more details
cargo.env("RUSTC_EMIT_STACK_SIZES", "1");
run_cargo(builder,
&mut cargo,
&libtest_stamp(builder, compiler, target),

View File

@ -113,6 +113,21 @@ impl LinkerPluginLto {
}
}
#[derive(Clone, PartialEq, Hash)]
pub enum PgoGenerate {
Enabled(Option<PathBuf>),
Disabled,
}
impl PgoGenerate {
pub fn enabled(&self) -> bool {
match *self {
PgoGenerate::Enabled(_) => true,
PgoGenerate::Disabled => false,
}
}
}
#[derive(Clone, Copy, PartialEq, Hash)]
pub enum DebugInfo {
None,
@ -826,13 +841,15 @@ macro_rules! options {
pub const parse_linker_plugin_lto: Option<&str> =
Some("either a boolean (`yes`, `no`, `on`, `off`, etc), \
or the path to the linker plugin");
pub const parse_pgo_generate: Option<&str> =
Some("an optional path to the profiling data output directory");
pub const parse_merge_functions: Option<&str> =
Some("one of: `disabled`, `trampolines`, or `aliases`");
}
#[allow(dead_code)]
mod $mod_set {
use super::{$struct_name, Passes, Sanitizer, LtoCli, LinkerPluginLto};
use super::{$struct_name, Passes, Sanitizer, LtoCli, LinkerPluginLto, PgoGenerate};
use rustc_target::spec::{LinkerFlavor, MergeFunctions, PanicStrategy, RelroLevel};
use std::path::PathBuf;
use std::str::FromStr;
@ -1087,6 +1104,14 @@ macro_rules! options {
true
}
fn parse_pgo_generate(slot: &mut PgoGenerate, v: Option<&str>) -> bool {
*slot = match v {
None => PgoGenerate::Enabled(None),
Some(path) => PgoGenerate::Enabled(Some(PathBuf::from(path))),
};
true
}
fn parse_merge_functions(slot: &mut Option<MergeFunctions>, v: Option<&str>) -> bool {
match v.and_then(|s| MergeFunctions::from_str(s).ok()) {
Some(mergefunc) => *slot = Some(mergefunc),
@ -1363,7 +1388,7 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
"extra arguments to prepend to the linker invocation (space separated)"),
profile: bool = (false, parse_bool, [TRACKED],
"insert profiling code"),
pgo_gen: Option<String> = (None, parse_opt_string, [TRACKED],
pgo_gen: PgoGenerate = (PgoGenerate::Disabled, parse_pgo_generate, [TRACKED],
"Generate PGO profile data, to a given file, or to the default location if it's empty."),
pgo_use: String = (String::new(), parse_string, [TRACKED],
"Use PGO profile data from the given profile file."),
@ -1980,7 +2005,7 @@ pub fn build_session_options_and_crate_config(
);
}
if debugging_opts.pgo_gen.is_some() && !debugging_opts.pgo_use.is_empty() {
if debugging_opts.pgo_gen.enabled() && !debugging_opts.pgo_use.is_empty() {
early_error(
error_format,
"options `-Z pgo-gen` and `-Z pgo-use` are exclusive",
@ -2490,7 +2515,7 @@ mod dep_tracking {
use std::path::PathBuf;
use std::collections::hash_map::DefaultHasher;
use super::{CrateType, DebugInfo, ErrorOutputType, OptLevel, OutputTypes,
Passes, Sanitizer, LtoCli, LinkerPluginLto};
Passes, Sanitizer, LtoCli, LinkerPluginLto, PgoGenerate};
use syntax::feature_gate::UnstableFeatures;
use rustc_target::spec::{MergeFunctions, PanicStrategy, RelroLevel, TargetTriple};
use syntax::edition::Edition;
@ -2558,6 +2583,7 @@ mod dep_tracking {
impl_dep_tracking_hash_via_hash!(TargetTriple);
impl_dep_tracking_hash_via_hash!(Edition);
impl_dep_tracking_hash_via_hash!(LinkerPluginLto);
impl_dep_tracking_hash_via_hash!(PgoGenerate);
impl_dep_tracking_hash_for_sortable_vec_of!(String);
impl_dep_tracking_hash_for_sortable_vec_of!(PathBuf);
@ -2625,7 +2651,7 @@ mod tests {
build_session_options_and_crate_config,
to_crate_config
};
use crate::session::config::{LtoCli, LinkerPluginLto};
use crate::session::config::{LtoCli, LinkerPluginLto, PgoGenerate};
use crate::session::build_session;
use crate::session::search_paths::SearchPath;
use std::collections::{BTreeMap, BTreeSet};
@ -3124,7 +3150,7 @@ mod tests {
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
opts = reference.clone();
opts.debugging_opts.pgo_gen = Some(String::from("abc"));
opts.debugging_opts.pgo_gen = PgoGenerate::Enabled(None);
assert_ne!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts = reference.clone();

View File

@ -104,7 +104,7 @@ pub fn set_probestack(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) {
}
// probestack doesn't play nice either with pgo-gen.
if cx.sess().opts.debugging_opts.pgo_gen.is_some() {
if cx.sess().opts.debugging_opts.pgo_gen.enabled() {
return;
}

View File

@ -1014,7 +1014,7 @@ fn link_args(cmd: &mut dyn Linker,
cmd.build_static_executable();
}
if sess.opts.debugging_opts.pgo_gen.is_some() {
if sess.opts.debugging_opts.pgo_gen.enabled() {
cmd.pgo_gen();
}

View File

@ -13,7 +13,7 @@ use crate::LlvmCodegenBackend;
use rustc::hir::def_id::LOCAL_CRATE;
use rustc_codegen_ssa::back::write::{CodegenContext, ModuleConfig, run_assembler};
use rustc_codegen_ssa::traits::*;
use rustc::session::config::{self, OutputType, Passes, Lto};
use rustc::session::config::{self, OutputType, Passes, Lto, PgoGenerate};
use rustc::session::Session;
use rustc::ty::TyCtxt;
use rustc_codegen_ssa::{ModuleCodegen, CompiledModule};
@ -25,7 +25,7 @@ use errors::{Handler, FatalError};
use std::ffi::{CString, CStr};
use std::fs;
use std::io::{self, Write};
use std::path::Path;
use std::path::{Path, PathBuf};
use std::str;
use std::sync::Arc;
use std::slice;
@ -706,10 +706,20 @@ pub unsafe fn with_llvm_pmb(llmod: &llvm::Module,
.unwrap_or(llvm::CodeGenOptSizeNone);
let inline_threshold = config.inline_threshold;
let pgo_gen_path = config.pgo_gen.as_ref().map(|s| {
let s = if s.is_empty() { "default_%m.profraw" } else { s };
CString::new(s.as_bytes()).unwrap()
});
let pgo_gen_path = match config.pgo_gen {
PgoGenerate::Enabled(ref opt_dir_path) => {
let path = if let Some(dir_path) = opt_dir_path {
dir_path.join("default_%m.profraw")
} else {
PathBuf::from("default_%m.profraw")
};
Some(CString::new(format!("{}", path.display())).unwrap())
}
PgoGenerate::Disabled => {
None
}
};
let pgo_use_path = if config.pgo_use.is_empty() {
None
@ -793,6 +803,7 @@ fn create_msvc_imps(
} else {
"\x01__imp_"
};
unsafe {
let i8p_ty = Type::i8p_llcx(llcx);
let globals = base::iter_globals(llmod)
@ -800,14 +811,23 @@ fn create_msvc_imps(
llvm::LLVMRustGetLinkage(val) == llvm::Linkage::ExternalLinkage &&
llvm::LLVMIsDeclaration(val) == 0
})
.map(move |val| {
.filter_map(|val| {
// Exclude some symbols that we know are not Rust symbols.
let name = CStr::from_ptr(llvm::LLVMGetValueName(val));
if ignored(name.to_bytes()) {
None
} else {
Some((val, name))
}
})
.map(move |(val, name)| {
let mut imp_name = prefix.as_bytes().to_vec();
imp_name.extend(name.to_bytes());
let imp_name = CString::new(imp_name).unwrap();
(imp_name, val)
})
.collect::<Vec<_>>();
for (imp_name, val) in globals {
let imp = llvm::LLVMAddGlobal(llmod,
i8p_ty,
@ -816,4 +836,10 @@ fn create_msvc_imps(
llvm::LLVMRustSetLinkage(imp, llvm::Linkage::ExternalLinkage);
}
}
// Use this function to exclude certain symbols from `__imp` generation.
fn ignored(symbol_name: &[u8]) -> bool {
// These are symbols generated by LLVM's profiling instrumentation
symbol_name.starts_with(b"__llvm_profile_")
}
}

View File

@ -209,7 +209,7 @@ fn exported_symbols_provider_local<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
}
}
if tcx.sess.opts.debugging_opts.pgo_gen.is_some() {
if tcx.sess.opts.debugging_opts.pgo_gen.enabled() {
// These are weak symbols that point to the profile version and the
// profile name, which need to be treated as exported so LTO doesn't nix
// them.

View File

@ -12,7 +12,8 @@ use rustc_incremental::{copy_cgu_workproducts_to_incr_comp_cache_dir,
use rustc::dep_graph::{WorkProduct, WorkProductId, WorkProductFileKind};
use rustc::dep_graph::cgu_reuse_tracker::CguReuseTracker;
use rustc::middle::cstore::EncodedMetadata;
use rustc::session::config::{self, OutputFilenames, OutputType, Passes, Sanitizer, Lto};
use rustc::session::config::{self, OutputFilenames, OutputType, Passes, Lto,
Sanitizer, PgoGenerate};
use rustc::session::Session;
use rustc::util::nodemap::FxHashMap;
use rustc::hir::def_id::{CrateNum, LOCAL_CRATE};
@ -55,7 +56,7 @@ pub struct ModuleConfig {
/// Some(level) to optimize binary size, or None to not affect program size.
pub opt_size: Option<config::OptLevel>,
pub pgo_gen: Option<String>,
pub pgo_gen: PgoGenerate,
pub pgo_use: String,
// Flags indicating which outputs to produce.
@ -93,7 +94,7 @@ impl ModuleConfig {
opt_level: None,
opt_size: None,
pgo_gen: None,
pgo_gen: PgoGenerate::Disabled,
pgo_use: String::new(),
emit_no_opt_bc: false,

View File

@ -862,7 +862,7 @@ impl<'a> CrateLoader<'a> {
fn inject_profiler_runtime(&mut self) {
if self.sess.opts.debugging_opts.profile ||
self.sess.opts.debugging_opts.pgo_gen.is_some()
self.sess.opts.debugging_opts.pgo_gen.enabled()
{
info!("loading profiler");

View File

@ -4,16 +4,17 @@ use errors::{Applicability, DiagnosticBuilder, DiagnosticId};
use log::debug;
use rustc::hir::def::{Def, CtorKind, Namespace::*};
use rustc::hir::def_id::{CRATE_DEF_INDEX, DefId};
use rustc::session::config::nightly_options;
use syntax::ast::{Expr, ExprKind};
use syntax::symbol::keywords;
use syntax_pos::Span;
use rustc::session::{Session, config::nightly_options};
use syntax::ast::{Expr, ExprKind, Ident};
use syntax::ext::base::MacroKind;
use syntax::symbol::{Symbol, keywords};
use syntax_pos::{BytePos, Span};
use crate::macros::ParentScope;
use crate::resolve_imports::ImportResolver;
use crate::resolve_imports::{ImportDirective, ImportDirectiveSubclass, ImportResolver};
use crate::{import_candidate_to_enum_paths, is_self_type, is_self_value, path_names_to_string};
use crate::{AssocSuggestion, CrateLint, ImportSuggestion, ModuleOrUniformRoot, PathResult,
PathSource, Resolver, Segment};
PathSource, Resolver, Segment, Suggestion};
impl<'a> Resolver<'a> {
/// Handles error reporting for `smart_resolve_path_fragment` function.
@ -428,7 +429,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
span: Span,
mut path: Vec<Segment>,
parent_scope: &ParentScope<'b>,
) -> Option<(Vec<Segment>, Option<String>)> {
) -> Option<(Vec<Segment>, Vec<String>)> {
debug!("make_path_suggestion: span={:?} path={:?}", span, path);
match (path.get(0), path.get(1)) {
@ -463,13 +464,13 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
span: Span,
mut path: Vec<Segment>,
parent_scope: &ParentScope<'b>,
) -> Option<(Vec<Segment>, Option<String>)> {
) -> Option<(Vec<Segment>, Vec<String>)> {
// Replace first ident with `self` and check if that is valid.
path[0].ident.name = keywords::SelfLower.name();
let result = self.resolve_path(&path, None, parent_scope, false, span, CrateLint::No);
debug!("make_missing_self_suggestion: path={:?} result={:?}", path, result);
if let PathResult::Module(..) = result {
Some((path, None))
Some((path, Vec::new()))
} else {
None
}
@ -487,7 +488,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
span: Span,
mut path: Vec<Segment>,
parent_scope: &ParentScope<'b>,
) -> Option<(Vec<Segment>, Option<String>)> {
) -> Option<(Vec<Segment>, Vec<String>)> {
// Replace first ident with `crate` and check if that is valid.
path[0].ident.name = keywords::Crate.name();
let result = self.resolve_path(&path, None, parent_scope, false, span, CrateLint::No);
@ -495,11 +496,11 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
if let PathResult::Module(..) = result {
Some((
path,
Some(
vec![
"`use` statements changed in Rust 2018; read more at \
<https://doc.rust-lang.org/edition-guide/rust-2018/module-system/path-\
clarity.html>".to_string()
),
],
))
} else {
None
@ -518,13 +519,13 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
span: Span,
mut path: Vec<Segment>,
parent_scope: &ParentScope<'b>,
) -> Option<(Vec<Segment>, Option<String>)> {
) -> Option<(Vec<Segment>, Vec<String>)> {
// Replace first ident with `crate` and check if that is valid.
path[0].ident.name = keywords::Super.name();
let result = self.resolve_path(&path, None, parent_scope, false, span, CrateLint::No);
debug!("make_missing_super_suggestion: path={:?} result={:?}", path, result);
if let PathResult::Module(..) = result {
Some((path, None))
Some((path, Vec::new()))
} else {
None
}
@ -545,7 +546,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
span: Span,
mut path: Vec<Segment>,
parent_scope: &ParentScope<'b>,
) -> Option<(Vec<Segment>, Option<String>)> {
) -> Option<(Vec<Segment>, Vec<String>)> {
if path[1].ident.span.rust_2015() {
return None;
}
@ -564,10 +565,290 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
debug!("make_external_crate_suggestion: name={:?} path={:?} result={:?}",
name, path, result);
if let PathResult::Module(..) = result {
return Some((path, None));
return Some((path, Vec::new()));
}
}
None
}
/// Suggests importing a macro from the root of the crate rather than a module within
/// the crate.
///
/// ```
/// help: a macro with this name exists at the root of the crate
/// |
/// LL | use issue_59764::makro;
/// | ^^^^^^^^^^^^^^^^^^
/// |
/// = note: this could be because a macro annotated with `#[macro_export]` will be exported
/// at the root of the crate instead of the module where it is defined
/// ```
pub(crate) fn check_for_module_export_macro(
&self,
directive: &'b ImportDirective<'b>,
module: ModuleOrUniformRoot<'b>,
ident: Ident,
) -> Option<(Option<Suggestion>, Vec<String>)> {
let mut crate_module = if let ModuleOrUniformRoot::Module(module) = module {
module
} else {
return None;
};
while let Some(parent) = crate_module.parent {
crate_module = parent;
}
if ModuleOrUniformRoot::same_def(ModuleOrUniformRoot::Module(crate_module), module) {
// Don't make a suggestion if the import was already from the root of the
// crate.
return None;
}
let resolutions = crate_module.resolutions.borrow();
let resolution = resolutions.get(&(ident, MacroNS))?;
let binding = resolution.borrow().binding()?;
if let Def::Macro(_, MacroKind::Bang) = binding.def() {
let module_name = crate_module.kind.name().unwrap();
let import = match directive.subclass {
ImportDirectiveSubclass::SingleImport { source, target, .. } if source != target =>
format!("{} as {}", source, target),
_ => format!("{}", ident),
};
let mut corrections: Vec<(Span, String)> = Vec::new();
if !directive.is_nested() {
// Assume this is the easy case of `use issue_59764::foo::makro;` and just remove
// intermediate segments.
corrections.push((directive.span, format!("{}::{}", module_name, import)));
} else {
// Find the binding span (and any trailing commas and spaces).
// ie. `use a::b::{c, d, e};`
// ^^^
let (found_closing_brace, binding_span) = find_span_of_binding_until_next_binding(
self.resolver.session, directive.span, directive.use_span,
);
debug!("check_for_module_export_macro: found_closing_brace={:?} binding_span={:?}",
found_closing_brace, binding_span);
let mut removal_span = binding_span;
if found_closing_brace {
// If the binding span ended with a closing brace, as in the below example:
// ie. `use a::b::{c, d};`
// ^
// Then expand the span of characters to remove to include the previous
// binding's trailing comma.
// ie. `use a::b::{c, d};`
// ^^^
if let Some(previous_span) = extend_span_to_previous_binding(
self.resolver.session, binding_span,
) {
debug!("check_for_module_export_macro: previous_span={:?}", previous_span);
removal_span = removal_span.with_lo(previous_span.lo());
}
}
debug!("check_for_module_export_macro: removal_span={:?}", removal_span);
// Remove the `removal_span`.
corrections.push((removal_span, "".to_string()));
// Find the span after the crate name and if it has nested imports immediatately
// after the crate name already.
// ie. `use a::b::{c, d};`
// ^^^^^^^^^
// or `use a::{b, c, d}};`
// ^^^^^^^^^^^
let (has_nested, after_crate_name) = find_span_immediately_after_crate_name(
self.resolver.session, module_name, directive.use_span,
);
debug!("check_for_module_export_macro: has_nested={:?} after_crate_name={:?}",
has_nested, after_crate_name);
let source_map = self.resolver.session.source_map();
// Add the import to the start, with a `{` if required.
let start_point = source_map.start_point(after_crate_name);
if let Ok(start_snippet) = source_map.span_to_snippet(start_point) {
corrections.push((
start_point,
if has_nested {
// In this case, `start_snippet` must equal '{'.
format!("{}{}, ", start_snippet, import)
} else {
// In this case, add a `{`, then the moved import, then whatever
// was there before.
format!("{{{}, {}", import, start_snippet)
}
));
}
// Add a `};` to the end if nested, matching the `{` added at the start.
if !has_nested {
corrections.push((source_map.end_point(after_crate_name),
"};".to_string()));
}
}
let suggestion = Some((
corrections,
String::from("a macro with this name exists at the root of the crate"),
Applicability::MaybeIncorrect,
));
let note = vec![
"this could be because a macro annotated with `#[macro_export]` will be exported \
at the root of the crate instead of the module where it is defined".to_string(),
];
Some((suggestion, note))
} else {
None
}
}
}
/// Given a `binding_span` of a binding within a use statement:
///
/// ```
/// use foo::{a, b, c};
/// ^
/// ```
///
/// then return the span until the next binding or the end of the statement:
///
/// ```
/// use foo::{a, b, c};
/// ^^^
/// ```
pub(crate) fn find_span_of_binding_until_next_binding(
sess: &Session,
binding_span: Span,
use_span: Span,
) -> (bool, Span) {
let source_map = sess.source_map();
// Find the span of everything after the binding.
// ie. `a, e};` or `a};`
let binding_until_end = binding_span.with_hi(use_span.hi());
// Find everything after the binding but not including the binding.
// ie. `, e};` or `};`
let after_binding_until_end = binding_until_end.with_lo(binding_span.hi());
// Keep characters in the span until we encounter something that isn't a comma or
// whitespace.
// ie. `, ` or ``.
//
// Also note whether a closing brace character was encountered. If there
// was, then later go backwards to remove any trailing commas that are left.
let mut found_closing_brace = false;
let after_binding_until_next_binding = source_map.span_take_while(
after_binding_until_end,
|&ch| {
if ch == '}' { found_closing_brace = true; }
ch == ' ' || ch == ','
}
);
// Combine the two spans.
// ie. `a, ` or `a`.
//
// Removing these would leave `issue_52891::{d, e};` or `issue_52891::{d, e, };`
let span = binding_span.with_hi(after_binding_until_next_binding.hi());
(found_closing_brace, span)
}
/// Given a `binding_span`, return the span through to the comma or opening brace of the previous
/// binding.
///
/// ```
/// use foo::a::{a, b, c};
/// ^^--- binding span
/// |
/// returned span
///
/// use foo::{a, b, c};
/// --- binding span
/// ```
pub(crate) fn extend_span_to_previous_binding(
sess: &Session,
binding_span: Span,
) -> Option<Span> {
let source_map = sess.source_map();
// `prev_source` will contain all of the source that came before the span.
// Then split based on a command and take the first (ie. closest to our span)
// snippet. In the example, this is a space.
let prev_source = source_map.span_to_prev_source(binding_span).ok()?;
let prev_comma = prev_source.rsplit(',').collect::<Vec<_>>();
let prev_starting_brace = prev_source.rsplit('{').collect::<Vec<_>>();
if prev_comma.len() <= 1 || prev_starting_brace.len() <= 1 {
return None;
}
let prev_comma = prev_comma.first().unwrap();
let prev_starting_brace = prev_starting_brace.first().unwrap();
// If the amount of source code before the comma is greater than
// the amount of source code before the starting brace then we've only
// got one item in the nested item (eg. `issue_52891::{self}`).
if prev_comma.len() > prev_starting_brace.len() {
return None;
}
Some(binding_span.with_lo(BytePos(
// Take away the number of bytes for the characters we've found and an
// extra for the comma.
binding_span.lo().0 - (prev_comma.as_bytes().len() as u32) - 1
)))
}
/// Given a `use_span` of a binding within a use statement, returns the highlighted span and if
/// it is a nested use tree.
///
/// ```
/// use foo::a::{b, c};
/// ^^^^^^^^^^ // false
///
/// use foo::{a, b, c};
/// ^^^^^^^^^^ // true
///
/// use foo::{a, b::{c, d}};
/// ^^^^^^^^^^^^^^^ // true
/// ```
fn find_span_immediately_after_crate_name(
sess: &Session,
module_name: Symbol,
use_span: Span,
) -> (bool, Span) {
debug!("find_span_immediately_after_crate_name: module_name={:?} use_span={:?}",
module_name, use_span);
let source_map = sess.source_map();
// Using `use issue_59764::foo::{baz, makro};` as an example throughout..
let mut num_colons = 0;
// Find second colon.. `use issue_59764:`
let until_second_colon = source_map.span_take_while(use_span, |c| {
if *c == ':' { num_colons += 1; }
match c {
':' if num_colons == 2 => false,
_ => true,
}
});
// Find everything after the second colon.. `foo::{baz, makro};`
let from_second_colon = use_span.with_lo(until_second_colon.hi() + BytePos(1));
let mut found_a_non_whitespace_character = false;
// Find the first non-whitespace character in `from_second_colon`.. `f`
let after_second_colon = source_map.span_take_while(from_second_colon, |c| {
if found_a_non_whitespace_character { return false; }
if !c.is_whitespace() { found_a_non_whitespace_character = true; }
true
});
// Find the first `{` in from_second_colon.. `foo::{`
let next_left_bracket = source_map.span_through_char(from_second_colon, '{');
(next_left_bracket == after_second_colon, from_second_colon)
}

View File

@ -50,7 +50,7 @@ use syntax::ast::{QSelf, TraitItemKind, TraitRef, Ty, TyKind};
use syntax::ptr::P;
use syntax::{span_err, struct_span_err, unwrap_or, walk_list};
use syntax_pos::{BytePos, Span, DUMMY_SP, MultiSpan};
use syntax_pos::{Span, DUMMY_SP, MultiSpan};
use errors::{Applicability, DiagnosticBuilder, DiagnosticId};
use log::debug;
@ -62,6 +62,7 @@ use std::mem::replace;
use rustc_data_structures::ptr_key::PtrKey;
use rustc_data_structures::sync::Lrc;
use error_reporting::{find_span_of_binding_until_next_binding, extend_span_to_previous_binding};
use resolve_imports::{ImportDirective, ImportDirectiveSubclass, NameResolution, ImportResolver};
use macros::{InvocationData, LegacyBinding, ParentScope};
@ -138,8 +139,8 @@ impl Ord for BindingError {
}
}
/// A span, message, replacement text, and applicability.
type Suggestion = (Span, String, String, Applicability);
/// A vector of spans and replacements, a message and applicability.
type Suggestion = (Vec<(Span, String)>, String, Applicability);
enum ResolutionError<'a> {
/// Error E0401: can't use type or const parameters from outer function.
@ -389,8 +390,8 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver<'_>,
"failed to resolve: {}", &label);
err.span_label(span, label);
if let Some((span, msg, suggestion, applicability)) = suggestion {
err.span_suggestion(span, &msg, suggestion, applicability);
if let Some((suggestions, msg, applicability)) = suggestion {
err.multipart_suggestion(&msg, suggestions, applicability);
}
err
@ -1091,6 +1092,16 @@ enum ModuleKind {
Def(Def, Name),
}
impl ModuleKind {
/// Get name of the module.
pub fn name(&self) -> Option<Name> {
match self {
ModuleKind::Block(..) => None,
ModuleKind::Def(_, name) => Some(*name),
}
}
}
/// One node in the tree of modules.
pub struct ModuleData<'a> {
parent: Option<Module<'a>>,
@ -3770,9 +3781,8 @@ impl<'a> Resolver<'a> {
(
String::from("unresolved import"),
Some((
ident.span,
vec![(ident.span, candidate.path.to_string())],
String::from("a similar path exists"),
candidate.path.to_string(),
Applicability::MaybeIncorrect,
)),
)
@ -5141,7 +5151,6 @@ impl<'a> Resolver<'a> {
) {
assert!(directive.is_nested());
let message = "remove unnecessary import";
let source_map = self.session.source_map();
// Two examples will be used to illustrate the span manipulations we're doing:
//
@ -5150,73 +5159,24 @@ impl<'a> Resolver<'a> {
// - Given `use issue_52891::{d, e, a};` where `a` is a duplicate then `binding_span` is
// `a` and `directive.use_span` is `issue_52891::{d, e, a};`.
// Find the span of everything after the binding.
// ie. `a, e};` or `a};`
let binding_until_end = binding_span.with_hi(directive.use_span.hi());
// Find everything after the binding but not including the binding.
// ie. `, e};` or `};`
let after_binding_until_end = binding_until_end.with_lo(binding_span.hi());
// Keep characters in the span until we encounter something that isn't a comma or
// whitespace.
// ie. `, ` or ``.
//
// Also note whether a closing brace character was encountered. If there
// was, then later go backwards to remove any trailing commas that are left.
let mut found_closing_brace = false;
let after_binding_until_next_binding = source_map.span_take_while(
after_binding_until_end,
|&ch| {
if ch == '}' { found_closing_brace = true; }
ch == ' ' || ch == ','
}
let (found_closing_brace, span) = find_span_of_binding_until_next_binding(
self.session, binding_span, directive.use_span,
);
// Combine the two spans.
// ie. `a, ` or `a`.
//
// Removing these would leave `issue_52891::{d, e};` or `issue_52891::{d, e, };`
let span = binding_span.with_hi(after_binding_until_next_binding.hi());
// If there was a closing brace then identify the span to remove any trailing commas from
// previous imports.
if found_closing_brace {
if let Ok(prev_source) = source_map.span_to_prev_source(span) {
// `prev_source` will contain all of the source that came before the span.
// Then split based on a command and take the first (ie. closest to our span)
// snippet. In the example, this is a space.
let prev_comma = prev_source.rsplit(',').collect::<Vec<_>>();
let prev_starting_brace = prev_source.rsplit('{').collect::<Vec<_>>();
if prev_comma.len() > 1 && prev_starting_brace.len() > 1 {
let prev_comma = prev_comma.first().unwrap();
let prev_starting_brace = prev_starting_brace.first().unwrap();
// If the amount of source code before the comma is greater than
// the amount of source code before the starting brace then we've only
// got one item in the nested item (eg. `issue_52891::{self}`).
if prev_comma.len() > prev_starting_brace.len() {
// So just remove the entire line...
err.span_suggestion(
directive.use_span_with_attributes,
message,
String::new(),
Applicability::MaybeIncorrect,
);
return;
}
let span = span.with_lo(BytePos(
// Take away the number of bytes for the characters we've found and an
// extra for the comma.
span.lo().0 - (prev_comma.as_bytes().len() as u32) - 1
));
err.tool_only_span_suggestion(
span, message, String::new(), Applicability::MaybeIncorrect,
);
return;
}
if let Some(span) = extend_span_to_previous_binding(self.session, span) {
err.tool_only_span_suggestion(span, message, String::new(),
Applicability::MaybeIncorrect);
} else {
// Remove the entire line if we cannot extend the span back, this indicates a
// `issue_52891::{self}` case.
err.span_suggestion(directive.use_span_with_attributes, message, String::new(),
Applicability::MaybeIncorrect);
}
return;
}
err.span_suggestion(span, message, String::new(), Applicability::MachineApplicable);

View File

@ -145,7 +145,7 @@ pub struct NameResolution<'a> {
impl<'a> NameResolution<'a> {
// Returns the binding for the name if it is known or None if it not known.
fn binding(&self) -> Option<&'a NameBinding<'a>> {
pub(crate) fn binding(&self) -> Option<&'a NameBinding<'a>> {
self.binding.and_then(|binding| {
if !binding.is_glob_import() ||
self.single_imports.is_empty() { Some(binding) } else { None }
@ -636,7 +636,7 @@ impl<'a> Resolver<'a> {
struct UnresolvedImportError {
span: Span,
label: Option<String>,
note: Option<String>,
note: Vec<String>,
suggestion: Option<Suggestion>,
}
@ -756,8 +756,8 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
/// Upper limit on the number of `span_label` messages.
const MAX_LABEL_COUNT: usize = 10;
let (span, msg, note) = if errors.is_empty() {
(span.unwrap(), "unresolved import".to_string(), None)
let (span, msg) = if errors.is_empty() {
(span.unwrap(), "unresolved import".to_string())
} else {
let span = MultiSpan::from_spans(
errors
@ -766,11 +766,6 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
.collect(),
);
let note = errors
.iter()
.filter_map(|(_, err)| err.note.as_ref())
.last();
let paths = errors
.iter()
.map(|(path, _)| format!("`{}`", path))
@ -782,13 +777,15 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
paths.join(", "),
);
(span, msg, note)
(span, msg)
};
let mut diag = struct_span_err!(self.resolver.session, span, E0432, "{}", &msg);
if let Some(note) = &note {
diag.note(note);
if let Some((_, UnresolvedImportError { note, .. })) = errors.iter().last() {
for message in note {
diag.note(&message);
}
}
for (_, err) in errors.into_iter().take(MAX_LABEL_COUNT) {
@ -796,8 +793,8 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
diag.span_label(err.span, label);
}
if let Some((span, msg, suggestion, applicability)) = err.suggestion {
diag.span_suggestion(span, &msg, suggestion, applicability);
if let Some((suggestions, msg, applicability)) = err.suggestion {
diag.multipart_suggestion(&msg, suggestions, applicability);
}
}
@ -950,9 +947,8 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
label: None,
note,
suggestion: Some((
span,
vec![(span, Segment::names_to_string(&suggestion))],
String::from("a similar path exists"),
Segment::names_to_string(&suggestion),
Applicability::MaybeIncorrect,
)),
}
@ -961,7 +957,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
UnresolvedImportError {
span,
label: Some(label),
note: None,
note: Vec::new(),
suggestion,
}
}
@ -1006,7 +1002,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
return Some(UnresolvedImportError {
span: directive.span,
label: Some(String::from("cannot glob-import a module into itself")),
note: None,
note: Vec::new(),
suggestion: None,
});
}
@ -1114,15 +1110,19 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
}
});
let lev_suggestion =
find_best_match_for_name(names, &ident.as_str(), None).map(|suggestion| {
(
ident.span,
String::from("a similar name exists in the module"),
suggestion.to_string(),
Applicability::MaybeIncorrect,
)
});
let lev_suggestion = find_best_match_for_name(names, &ident.as_str(), None)
.map(|suggestion|
(vec![(ident.span, suggestion.to_string())],
String::from("a similar name exists in the module"),
Applicability::MaybeIncorrect)
);
let (suggestion, note) = match self.check_for_module_export_macro(
directive, module, ident,
) {
Some((suggestion, note)) => (suggestion.or(lev_suggestion), note),
_ => (lev_suggestion, Vec::new()),
};
let label = match module {
ModuleOrUniformRoot::Module(module) => {
@ -1143,11 +1143,12 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
}
}
};
Some(UnresolvedImportError {
span: directive.span,
label: Some(label),
note: None,
suggestion: lev_suggestion,
note,
suggestion,
})
} else {
// `resolve_ident_in_module` reported a privacy error.

View File

@ -157,11 +157,11 @@ pub fn render<T: fmt::Display, S: fmt::Display>(
window.rootPath = \"{root_path}\";\
window.currentCrate = \"{krate}\";\
</script>\
<script src=\"{root_path}aliases.js\"></script>\
<script src=\"{root_path}aliases{suffix}.js\"></script>\
<script src=\"{static_root_path}main{suffix}.js\"></script>\
{static_extra_scripts}\
{extra_scripts}\
<script defer src=\"{root_path}search-index.js\"></script>\
<script defer src=\"{root_path}search-index{suffix}.js\"></script>\
</body>\
</html>",
css_extension = if css_file_extension {

View File

@ -1013,7 +1013,7 @@ themePicker.onblur = handleThemeButtonsBlur;
})
}
let dst = cx.dst.join("aliases.js");
let dst = cx.dst.join(&format!("aliases{}.js", cx.shared.resource_suffix));
{
let (mut all_aliases, _, _) = try_err!(collect(&dst, &krate.name, "ALIASES", false), &dst);
let mut w = try_err!(File::create(&dst), &dst);
@ -1064,11 +1064,22 @@ themePicker.onblur = handleThemeButtonsBlur;
.expect("invalid osstring conversion")))
.collect::<Vec<_>>();
files.sort_unstable_by(|a, b| a.cmp(b));
// FIXME(imperio): we could avoid to generate "dirs" and "files" if they're empty.
format!("{{\"name\":\"{name}\",\"dirs\":[{subs}],\"files\":[{files}]}}",
let subs = subs.iter().map(|s| s.to_json_string()).collect::<Vec<_>>().join(",");
let dirs = if subs.is_empty() {
String::new()
} else {
format!(",\"dirs\":[{}]", subs)
};
let files = files.join(",");
let files = if files.is_empty() {
String::new()
} else {
format!(",\"files\":[{}]", files)
};
format!("{{\"name\":\"{name}\"{dirs}{files}}}",
name=self.elem.to_str().expect("invalid osstring conversion"),
subs=subs.iter().map(|s| s.to_json_string()).collect::<Vec<_>>().join(","),
files=files.join(","))
dirs=dirs,
files=files)
}
}
@ -1099,7 +1110,7 @@ themePicker.onblur = handleThemeButtonsBlur;
}
}
let dst = cx.dst.join("source-files.js");
let dst = cx.dst.join(&format!("source-files{}.js", cx.shared.resource_suffix));
let (mut all_sources, _krates, _) = try_err!(collect(&dst, &krate.name, "sourcesIndex",
false),
&dst);
@ -1115,7 +1126,7 @@ themePicker.onblur = handleThemeButtonsBlur;
}
// Update the search index
let dst = cx.dst.join("search-index.js");
let dst = cx.dst.join(&format!("search-index{}.js", cx.shared.resource_suffix));
let (mut all_indexes, mut krates, variables) = try_err!(collect(&dst,
&krate.name,
"searchIndex",
@ -1483,7 +1494,7 @@ impl<'a> SourceCollector<'a> {
description: &desc,
keywords: BASIC_KEYWORDS,
resource_suffix: &self.scx.resource_suffix,
extra_scripts: &["source-files"],
extra_scripts: &[&format!("source-files{}", self.scx.resource_suffix)],
static_extra_scripts: &[&format!("source-script{}", self.scx.resource_suffix)],
};
layout::render(&mut w, &self.scx.layout,

View File

@ -39,28 +39,32 @@ function createDirEntry(elem, parent, fullPath, currentFile, hasFoundFile) {
children.className = "children";
var folders = document.createElement("div");
folders.className = "folders";
for (var i = 0; i < elem.dirs.length; ++i) {
if (createDirEntry(elem.dirs[i], folders, fullPath, currentFile,
hasFoundFile) === true) {
addClass(name, "expand");
hasFoundFile = true;
if (elem.dirs) {
for (var i = 0; i < elem.dirs.length; ++i) {
if (createDirEntry(elem.dirs[i], folders, fullPath, currentFile,
hasFoundFile) === true) {
addClass(name, "expand");
hasFoundFile = true;
}
}
}
children.appendChild(folders);
var files = document.createElement("div");
files.className = "files";
for (i = 0; i < elem.files.length; ++i) {
var file = document.createElement("a");
file.innerText = elem.files[i];
file.href = window.rootPath + "src/" + fullPath + elem.files[i] + ".html";
if (hasFoundFile === false &&
currentFile === fullPath + elem.files[i]) {
file.className = "selected";
addClass(name, "expand");
hasFoundFile = true;
if (elem.files) {
for (i = 0; i < elem.files.length; ++i) {
var file = document.createElement("a");
file.innerText = elem.files[i];
file.href = window.rootPath + "src/" + fullPath + elem.files[i] + ".html";
if (hasFoundFile === false &&
currentFile === fullPath + elem.files[i]) {
file.className = "selected";
addClass(name, "expand");
hasFoundFile = true;
}
files.appendChild(file);
}
files.appendChild(file);
}
search.fullPath = fullPath;
children.appendChild(files);

View File

@ -1,10 +1,8 @@
-include ../tools.mk
# ignore-windows
all:
ifeq ($(PROFILER_SUPPORT),1)
$(RUSTC) -Copt-level=3 -Clto=fat -Z pgo-gen="$(TMPDIR)/test.profraw" test.rs
$(RUSTC) -Copt-level=3 -Clto=fat -Z pgo-gen="$(TMPDIR)" test.rs
$(call RUN,test) || exit 1
[ -e "$(TMPDIR)/test.profraw" ] || (echo "No .profraw file"; exit 1)
[ -e "$(TMPDIR)"/default_*.profraw ] || (echo "No .profraw file"; exit 1)
endif

View File

@ -0,0 +1,11 @@
-include ../tools.mk
all:
ifeq ($(PROFILER_SUPPORT),1)
$(RUSTC) -O -Ccodegen-units=1 -Z pgo-gen="$(TMPDIR)/test.profraw" --emit=llvm-ir test.rs
# We expect symbols starting with "__llvm_profile_".
$(CGREP) "__llvm_profile_" < $(TMPDIR)/test.ll
# We do NOT expect the "__imp_" version of these symbols.
$(CGREP) -v "__imp___llvm_profile_" < $(TMPDIR)/test.ll # 64 bit
$(CGREP) -v "__imp____llvm_profile_" < $(TMPDIR)/test.ll # 32 bit
endif

View File

@ -0,0 +1 @@
fn main() {}

View File

@ -1,10 +1,8 @@
-include ../tools.mk
# ignore-windows
all:
ifeq ($(PROFILER_SUPPORT),1)
$(RUSTC) -g -Z pgo-gen="$(TMPDIR)/test.profraw" test.rs
$(RUSTC) -g -Z pgo-gen="$(TMPDIR)" test.rs
$(call RUN,test) || exit 1
[ -e "$(TMPDIR)/test.profraw" ] || (echo "No .profraw file"; exit 1)
[ -e "$(TMPDIR)"/default_*.profraw ] || (echo "No .profraw file"; exit 1)
endif

View File

@ -0,0 +1,18 @@
pub mod foo {
#[macro_export]
macro_rules! makro {
($foo:ident) => {
fn $foo() { }
}
}
pub fn baz() {}
pub fn foobar() {}
pub mod barbaz {
pub fn barfoo() {}
}
}
pub fn foobaz() {}

136
src/test/ui/issue-59764.rs Normal file
View File

@ -0,0 +1,136 @@
// aux-build:issue-59764.rs
// compile-flags:--extern issue_59764
// edition:2018
#![allow(warnings)]
// This tests the suggestion to import macros from the root of a crate. This aims to capture
// the case where a user attempts to import a macro from the definition location instead of the
// root of the crate and the macro is annotated with `#![macro_export]`.
// Edge cases..
mod multiple_imports_same_line_at_end {
use issue_59764::foo::{baz, makro};
//~^ ERROR unresolved import `issue_59764::foo::makro` [E0432]
}
mod multiple_imports_multiline_at_end_trailing_comma {
use issue_59764::foo::{
baz,
makro, //~ ERROR unresolved import `issue_59764::foo::makro` [E0432]
};
}
mod multiple_imports_multiline_at_end {
use issue_59764::foo::{
baz,
makro //~ ERROR unresolved import `issue_59764::foo::makro` [E0432]
};
}
mod multiple_imports_same_line_in_middle {
use issue_59764::foo::{baz, makro, foobar};
//~^ ERROR unresolved import `issue_59764::foo::makro` [E0432]
}
mod multiple_imports_multiline_in_middle_trailing_comma {
use issue_59764::foo::{
baz,
makro, //~ ERROR unresolved import `issue_59764::foo::makro` [E0432]
foobar,
};
}
mod multiple_imports_multiline_in_middle {
use issue_59764::foo::{
baz,
makro, //~ ERROR unresolved import `issue_59764::foo::makro` [E0432]
foobar
};
}
mod nested_imports {
use issue_59764::{foobaz, foo::makro};
//~^ ERROR unresolved import `issue_59764::foo::makro` [E0432]
}
mod nested_multiple_imports {
use issue_59764::{foobaz, foo::{baz, makro}};
//~^ ERROR unresolved import `issue_59764::foo::makro` [E0432]
}
mod nested_multiline_multiple_imports_trailing_comma {
use issue_59764::{
foobaz,
foo::{
baz,
makro, //~ ERROR unresolved import `issue_59764::foo::makro` [E0432]
},
};
}
mod nested_multiline_multiple_imports {
use issue_59764::{
foobaz,
foo::{
baz,
makro //~ ERROR unresolved import `issue_59764::foo::makro` [E0432]
}
};
}
mod doubly_nested_multiple_imports {
use issue_59764::{foobaz, foo::{baz, makro, barbaz::{barfoo}}};
//~^ ERROR unresolved import `issue_59764::foo::makro` [E0432]
}
mod doubly_multiline_nested_multiple_imports {
use issue_59764::{
foobaz,
foo::{
baz,
makro, //~ ERROR unresolved import `issue_59764::foo::makro` [E0432]
barbaz::{
barfoo,
}
}
};
}
mod renamed_import {
use issue_59764::foo::makro as baz;
//~^ ERROR unresolved import `issue_59764::foo::makro` [E0432]
}
mod renamed_multiple_imports {
use issue_59764::foo::{baz, makro as foobar};
//~^ ERROR unresolved import `issue_59764::foo::makro` [E0432]
}
mod lots_of_whitespace {
use
issue_59764::{
foobaz,
foo::{baz,
makro as foobar} //~ ERROR unresolved import `issue_59764::foo::makro` [E0432]
};
}
// Simple case..
use issue_59764::foo::makro;
//~^ ERROR unresolved import `issue_59764::foo::makro` [E0432]
makro!(bar);
//~^ ERROR cannot determine resolution for the macro `makro`
fn main() {
bar();
//~^ ERROR cannot find function `bar` in this scope [E0425]
}

View File

@ -0,0 +1,241 @@
error[E0432]: unresolved import `issue_59764::foo::makro`
--> $DIR/issue-59764.rs:14:33
|
LL | use issue_59764::foo::{baz, makro};
| ^^^^^ no `makro` in `foo`
|
= note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined
help: a macro with this name exists at the root of the crate
|
LL | use issue_59764::{makro, foo::{baz}};
| ^^^^^^^^^ --^^
error[E0432]: unresolved import `issue_59764::foo::makro`
--> $DIR/issue-59764.rs:21:9
|
LL | makro,
| ^^^^^ no `makro` in `foo`
|
= note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined
help: a macro with this name exists at the root of the crate
|
LL | use issue_59764::{makro, foo::{
LL | baz,
LL |
LL | }};
|
error[E0432]: unresolved import `issue_59764::foo::makro`
--> $DIR/issue-59764.rs:28:9
|
LL | makro
| ^^^^^ no `makro` in `foo`
|
= note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined
help: a macro with this name exists at the root of the crate
|
LL | use issue_59764::{makro, foo::{
LL | baz,
LL |
LL | }};
|
error[E0432]: unresolved import `issue_59764::foo::makro`
--> $DIR/issue-59764.rs:33:33
|
LL | use issue_59764::foo::{baz, makro, foobar};
| ^^^^^ no `makro` in `foo`
|
= note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined
help: a macro with this name exists at the root of the crate
|
LL | use issue_59764::{makro, foo::{baz, foobar}};
| ^^^^^^^^^ -- ^^
error[E0432]: unresolved import `issue_59764::foo::makro`
--> $DIR/issue-59764.rs:40:9
|
LL | makro,
| ^^^^^ no `makro` in `foo`
|
= note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined
help: a macro with this name exists at the root of the crate
|
LL | use issue_59764::{makro, foo::{
LL | baz,
LL |
LL | foobar,
LL | }};
|
error[E0432]: unresolved import `issue_59764::foo::makro`
--> $DIR/issue-59764.rs:48:9
|
LL | makro,
| ^^^^^ no `makro` in `foo`
|
= note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined
help: a macro with this name exists at the root of the crate
|
LL | use issue_59764::{makro, foo::{
LL | baz,
LL |
LL | foobar
LL | }};
|
error[E0432]: unresolved import `issue_59764::foo::makro`
--> $DIR/issue-59764.rs:54:31
|
LL | use issue_59764::{foobaz, foo::makro};
| ^^^^^^^^^^ no `makro` in `foo`
|
= note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined
help: a macro with this name exists at the root of the crate
|
LL | use issue_59764::{makro, foobaz};
| ^^^^^^^ --
error[E0432]: unresolved import `issue_59764::foo::makro`
--> $DIR/issue-59764.rs:59:42
|
LL | use issue_59764::{foobaz, foo::{baz, makro}};
| ^^^^^ no `makro` in `foo`
|
= note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined
help: a macro with this name exists at the root of the crate
|
LL | use issue_59764::{makro, foobaz, foo::{baz}};
| ^^^^^^^ --
error[E0432]: unresolved import `issue_59764::foo::makro`
--> $DIR/issue-59764.rs:68:13
|
LL | makro,
| ^^^^^ no `makro` in `foo`
|
= note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined
help: a macro with this name exists at the root of the crate
|
LL | use issue_59764::{makro,
LL | foobaz,
LL | foo::{
LL | baz,
LL |
|
error[E0432]: unresolved import `issue_59764::foo::makro`
--> $DIR/issue-59764.rs:78:13
|
LL | makro
| ^^^^^ no `makro` in `foo`
|
= note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined
help: a macro with this name exists at the root of the crate
|
LL | use issue_59764::{makro,
LL | foobaz,
LL | foo::{
LL | baz,
LL |
|
error[E0432]: unresolved import `issue_59764::foo::makro`
--> $DIR/issue-59764.rs:84:42
|
LL | use issue_59764::{foobaz, foo::{baz, makro, barbaz::{barfoo}}};
| ^^^^^ no `makro` in `foo`
|
= note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined
help: a macro with this name exists at the root of the crate
|
LL | use issue_59764::{makro, foobaz, foo::{baz, barbaz::{barfoo}}};
| ^^^^^^^ --
error[E0432]: unresolved import `issue_59764::foo::makro`
--> $DIR/issue-59764.rs:93:13
|
LL | makro,
| ^^^^^ no `makro` in `foo`
|
= note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined
help: a macro with this name exists at the root of the crate
|
LL | use issue_59764::{makro,
LL | foobaz,
LL | foo::{
LL | baz,
LL |
|
error[E0432]: unresolved import `issue_59764::foo::makro`
--> $DIR/issue-59764.rs:102:9
|
LL | use issue_59764::foo::makro as baz;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no `makro` in `foo`
|
= note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined
help: a macro with this name exists at the root of the crate
|
LL | use issue_59764::makro as baz;
| ^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0432]: unresolved import `issue_59764::foo::makro`
--> $DIR/issue-59764.rs:107:33
|
LL | use issue_59764::foo::{baz, makro as foobar};
| ^^^^^^^^^^^^^^^ no `makro` in `foo`
|
= note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined
help: a macro with this name exists at the root of the crate
|
LL | use issue_59764::{makro as foobar, foo::{baz}};
| ^^^^^^^^^^^^^^^^^^^ --^^
error[E0432]: unresolved import `issue_59764::foo::makro`
--> $DIR/issue-59764.rs:120:17
|
LL | makro as foobar}
| ^^^^^^^^^^^^^^^ no `makro` in `foo`
|
= note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined
help: a macro with this name exists at the root of the crate
|
LL | issue_59764::{makro as foobar,
LL |
LL | foobaz,
LL |
LL |
LL | foo::{baz}
|
error[E0432]: unresolved import `issue_59764::foo::makro`
--> $DIR/issue-59764.rs:127:5
|
LL | use issue_59764::foo::makro;
| ^^^^^^^^^^^^^^^^^^^^^^^ no `makro` in `foo`
|
= note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined
help: a macro with this name exists at the root of the crate
|
LL | use issue_59764::makro;
| ^^^^^^^^^^^^^^^^^^
error: cannot determine resolution for the macro `makro`
--> $DIR/issue-59764.rs:130:1
|
LL | makro!(bar);
| ^^^^^
|
= note: import resolution is stuck, try simplifying macro imports
error[E0425]: cannot find function `bar` in this scope
--> $DIR/issue-59764.rs:134:5
|
LL | bar();
| ^^^ not found in this scope
error: aborting due to 18 previous errors
Some errors occurred: E0425, E0432.
For more information about an error, try `rustc --explain E0425`.