resolve: Check resolution consistency for import paths and multi-segment macro paths

This commit is contained in:
Vadim Petrochenkov 2018-11-10 18:58:37 +03:00
parent 07af4ec7a2
commit 4c5d822a8b
20 changed files with 369 additions and 203 deletions

View File

@ -330,6 +330,7 @@ impl Def {
match *self {
Def::AssociatedTy(..) | Def::AssociatedConst(..) | Def::AssociatedExistential(..) |
Def::Enum(..) | Def::Existential(..) | Def::Err => "an",
Def::Macro(.., macro_kind) => macro_kind.article(),
_ => "a",
}
}

View File

@ -225,8 +225,8 @@ pub struct DefId {
impl fmt::Debug for DefId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "DefId({:?}/{}:{}",
self.krate.index(),
write!(f, "DefId({}/{}:{}",
self.krate,
self.index.address_space().index(),
self.index.as_array_index())?;

View File

@ -1025,6 +1025,18 @@ enum ModuleOrUniformRoot<'a> {
UniformRoot(UniformRootKind),
}
impl<'a> PartialEq for ModuleOrUniformRoot<'a> {
fn eq(&self, other: &Self) -> bool {
match (*self, *other) {
(ModuleOrUniformRoot::Module(lhs), ModuleOrUniformRoot::Module(rhs)) =>
ptr::eq(lhs, rhs),
(ModuleOrUniformRoot::UniformRoot(lhs), ModuleOrUniformRoot::UniformRoot(rhs)) =>
lhs == rhs,
_ => false,
}
}
}
#[derive(Clone, Debug)]
enum PathResult<'a> {
Module(ModuleOrUniformRoot<'a>),
@ -1066,9 +1078,10 @@ pub struct ModuleData<'a> {
normal_ancestor_id: DefId,
resolutions: RefCell<FxHashMap<(Ident, Namespace), &'a RefCell<NameResolution<'a>>>>,
legacy_macro_resolutions: RefCell<Vec<(Ident, MacroKind, ParentScope<'a>,
Option<&'a NameBinding<'a>>)>>,
macro_resolutions: RefCell<Vec<(Vec<Segment>, ParentScope<'a>, Span)>>,
single_segment_macro_resolutions: RefCell<Vec<(Ident, MacroKind, ParentScope<'a>,
Option<&'a NameBinding<'a>>)>>,
multi_segment_macro_resolutions: RefCell<Vec<(Vec<Segment>, Span, MacroKind, ParentScope<'a>,
Option<Def>)>>,
builtin_attrs: RefCell<Vec<(Ident, ParentScope<'a>)>>,
// Macro invocations that can expand into items in this module.
@ -1106,8 +1119,8 @@ impl<'a> ModuleData<'a> {
kind,
normal_ancestor_id,
resolutions: Default::default(),
legacy_macro_resolutions: RefCell::new(Vec::new()),
macro_resolutions: RefCell::new(Vec::new()),
single_segment_macro_resolutions: RefCell::new(Vec::new()),
multi_segment_macro_resolutions: RefCell::new(Vec::new()),
builtin_attrs: RefCell::new(Vec::new()),
unresolved_invocations: Default::default(),
no_implicit_prelude: false,
@ -1503,6 +1516,9 @@ pub struct Resolver<'a, 'b: 'a> {
/// The current self item if inside an ADT (used for better errors).
current_self_item: Option<NodeId>,
/// FIXME: Refactor things so that this is passed through arguments and not resolver.
last_import_segment: bool,
/// The idents for the primitive types.
primitive_type_table: PrimitiveTypeTable,
@ -1852,6 +1868,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
current_trait_ref: None,
current_self_type: None,
current_self_item: None,
last_import_segment: false,
primitive_type_table: PrimitiveTypeTable::new(),
@ -1953,27 +1970,23 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
self.arenas.alloc_module(module)
}
fn record_use(&mut self, ident: Ident, ns: Namespace, binding: &'a NameBinding<'a>)
-> bool /* true if an error was reported */ {
fn record_use(&mut self, ident: Ident, ns: Namespace, binding: &'a NameBinding<'a>) {
match binding.kind {
NameBindingKind::Import { directive, binding, ref used }
if !used.get() => {
NameBindingKind::Import { directive, binding, ref used } if !used.get() => {
used.set(true);
directive.used.set(true);
self.used_imports.insert((directive.id, ns));
self.add_to_glob_map(directive.id, ident);
self.record_use(ident, ns, binding)
self.record_use(ident, ns, binding);
}
NameBindingKind::Import { .. } => false,
NameBindingKind::Ambiguity { kind, b1, b2 } => {
self.ambiguity_errors.push(AmbiguityError {
kind, ident, b1, b2,
misc1: AmbiguityErrorMisc::None,
misc2: AmbiguityErrorMisc::None,
});
true
}
_ => false
_ => {}
}
}
@ -4801,7 +4814,6 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
fn report_errors(&mut self, krate: &Crate) {
self.report_with_use_injections(krate);
let mut reported_spans = FxHashSet::default();
for &(span_use, span_def) in &self.macro_expanded_macro_export_errors {
let msg = "macro-expanded `macro_export` macros from the current crate \
@ -4815,11 +4827,10 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
}
for ambiguity_error in &self.ambiguity_errors {
if reported_spans.insert(ambiguity_error.ident.span) {
self.report_ambiguity_error(ambiguity_error);
}
self.report_ambiguity_error(ambiguity_error);
}
let mut reported_spans = FxHashSet::default();
for &PrivacyError(dedup_span, ident, binding) in &self.privacy_errors {
if reported_spans.insert(dedup_span) {
span_err!(self.session, ident.span, E0603, "{} `{}` is private",

View File

@ -9,8 +9,9 @@
// except according to those terms.
use {AmbiguityError, AmbiguityKind, AmbiguityErrorMisc};
use {CrateLint, DeterminacyExt, Resolver, ResolutionError, is_known_tool, resolve_error};
use {CrateLint, DeterminacyExt, Resolver, ResolutionError};
use {Module, ModuleKind, NameBinding, NameBindingKind, PathResult, ToNameBinding};
use {is_known_tool, names_to_string, resolve_error};
use ModuleOrUniformRoot;
use Namespace::{self, *};
use build_reduced_graph::{BuildReducedGraphVisitor, IsMacroExport};
@ -480,29 +481,19 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
if path.len() > 1 {
let def = match self.resolve_path(&path, Some(MacroNS), parent_scope,
false, path_span, CrateLint::No) {
PathResult::NonModule(path_res) => match path_res.base_def() {
Def::Err => Err(Determinacy::Determined),
def @ _ => {
if path_res.unresolved_segments() > 0 {
self.found_unresolved_macro = true;
self.session.span_err(path_span,
"fail to resolve non-ident macro path");
Err(Determinacy::Determined)
} else {
Ok(def)
}
}
},
PathResult::Module(..) => unreachable!(),
PathResult::NonModule(path_res) if path_res.unresolved_segments() == 0 => {
Ok(path_res.base_def())
}
PathResult::Indeterminate if !force => return Err(Determinacy::Undetermined),
_ => {
PathResult::NonModule(..) | PathResult::Indeterminate | PathResult::Failed(..) => {
self.found_unresolved_macro = true;
Err(Determinacy::Determined)
},
}
PathResult::Module(..) => unreachable!(),
};
parent_scope.module.macro_resolutions.borrow_mut()
.push((path, parent_scope.clone(), path_span));
parent_scope.module.multi_segment_macro_resolutions.borrow_mut()
.push((path, path_span, kind, parent_scope.clone(), def.ok()));
def
} else {
@ -515,7 +506,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
Err(Determinacy::Undetermined) => return Err(Determinacy::Undetermined),
}
parent_scope.module.legacy_macro_resolutions.borrow_mut()
parent_scope.module.single_segment_macro_resolutions.borrow_mut()
.push((path[0].ident, kind, parent_scope.clone(), binding.ok()));
binding.map(|binding| binding.def_ignoring_ambiguity())
@ -922,50 +913,68 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
pub fn finalize_current_module_macro_resolutions(&mut self) {
let module = self.current_module;
let check_consistency = |this: &mut Self, path: &[Ident], span,
kind: MacroKind, initial_def, def| {
if let Some(initial_def) = initial_def {
if def != initial_def && def != Def::Err && this.ambiguity_errors.is_empty() {
// Make sure compilation does not succeed if preferred macro resolution
// has changed after the macro had been expanded. In theory all such
// situations should be reported as ambiguity errors, so this is a bug.
span_bug!(span, "inconsistent resolution for a macro");
}
} else {
// It's possible that the macro was unresolved (indeterminate) and silently
// expanded into a dummy fragment for recovery during expansion.
// Now, post-expansion, the resolution may succeed, but we can't change the
// past and need to report an error.
// However, non-speculative `resolve_path` can successfully return private items
// even if speculative `resolve_path` returned nothing previously, so we skip this
// less informative error if the privacy error is reported elsewhere.
if this.privacy_errors.is_empty() {
let msg = format!("cannot determine resolution for the {} `{}`",
kind.descr(), names_to_string(path));
let msg_note = "import resolution is stuck, try simplifying macro imports";
this.session.struct_span_err(span, &msg).note(msg_note).emit();
}
}
};
let macro_resolutions =
mem::replace(&mut *module.macro_resolutions.borrow_mut(), Vec::new());
for (mut path, parent_scope, path_span) in macro_resolutions {
mem::replace(&mut *module.multi_segment_macro_resolutions.borrow_mut(), Vec::new());
for (mut path, path_span, kind, parent_scope, initial_def) 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) {
PathResult::NonModule(_) => {},
PathResult::Failed(span, msg, _) => {
PathResult::NonModule(path_res) if path_res.unresolved_segments() == 0 => {
let def = path_res.base_def();
check_consistency(self, &path, path_span, kind, initial_def, def);
}
path_res @ PathResult::NonModule(..) | path_res @ PathResult::Failed(..) => {
let (span, msg) = if let PathResult::Failed(span, msg, ..) = path_res {
(span, msg)
} else {
(path_span, format!("partially resolved path in {} {}",
kind.article(), kind.descr()))
};
resolve_error(self, span, ResolutionError::FailedToResolve(&msg));
}
_ => unreachable!(),
PathResult::Module(..) | PathResult::Indeterminate => unreachable!(),
}
}
let legacy_macro_resolutions =
mem::replace(&mut *module.legacy_macro_resolutions.borrow_mut(), Vec::new());
for (ident, kind, parent_scope, initial_binding) in legacy_macro_resolutions {
let binding = self.early_resolve_ident_in_lexical_scope(
ident, MacroNS, Some(kind), false, &parent_scope, true, true, ident.span
);
match binding {
let macro_resolutions =
mem::replace(&mut *module.single_segment_macro_resolutions.borrow_mut(), Vec::new());
for (ident, kind, parent_scope, initial_binding) in macro_resolutions {
match self.early_resolve_ident_in_lexical_scope(ident, MacroNS, Some(kind), false,
&parent_scope, true, true, ident.span) {
Ok(binding) => {
let def = binding.def_ignoring_ambiguity();
if let Some(initial_binding) = initial_binding {
let initial_def = initial_binding.map(|initial_binding| {
self.record_use(ident, MacroNS, initial_binding);
let initial_def = initial_binding.def_ignoring_ambiguity();
if self.ambiguity_errors.is_empty() &&
def != initial_def && def != Def::Err {
// Make sure compilation does not succeed if preferred macro resolution
// has changed after the macro had been expanded. In theory all such
// situations should be reported as ambiguity errors, so this is a bug.
span_bug!(ident.span, "inconsistent resolution for a macro");
}
} else {
// It's possible that the macro was unresolved (indeterminate) and silently
// expanded into a dummy fragment for recovery during expansion.
// Now, post-expansion, the resolution may succeed, but we can't change the
// past and need to report an error.
let msg = format!("cannot determine resolution for the {} `{}`",
kind.descr(), ident);
let msg_note = "import resolution is stuck, try simplifying macro imports";
self.session.struct_span_err(ident.span, &msg).note(msg_note).emit();
}
initial_binding.def_ignoring_ambiguity()
});
let def = binding.def_ignoring_ambiguity();
check_consistency(self, &[ident], ident.span, kind, initial_def, def);
}
Err(..) => {
assert!(initial_binding.is_none());

View File

@ -222,40 +222,47 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> {
}
}
if record_used {
if let Some(binding) = resolution.binding {
if let Some(shadowed_glob) = resolution.shadowed_glob {
// Forbid expanded shadowing to avoid time travel.
if restricted_shadowing &&
binding.expansion != Mark::root() &&
binding.def() != shadowed_glob.def() {
self.ambiguity_errors.push(AmbiguityError {
kind: AmbiguityKind::GlobVsExpanded,
ident,
b1: binding,
b2: shadowed_glob,
misc1: AmbiguityErrorMisc::None,
misc2: AmbiguityErrorMisc::None,
});
}
}
if self.record_use(ident, ns, binding) {
return Ok(self.dummy_binding);
}
if !self.is_accessible(binding.vis) {
self.privacy_errors.push(PrivacyError(path_span, ident, binding));
}
}
return resolution.binding.ok_or(DeterminacyExt::Determined);
}
let check_usable = |this: &mut Self, binding: &'a NameBinding<'a>| {
// `extern crate` are always usable for backwards compatibility, see issue #37020.
// `extern crate` are always usable for backwards compatibility, see issue #37020,
// remove this together with `PUB_USE_OF_PRIVATE_EXTERN_CRATE`.
let usable = this.is_accessible(binding.vis) || binding.is_extern_crate();
if usable { Ok(binding) } else { Err(DeterminacyExt::Determined) }
};
if record_used {
return resolution.binding.ok_or(DeterminacyExt::Determined).and_then(|binding| {
if self.last_import_segment && check_usable(self, binding).is_err() {
Err(DeterminacyExt::Determined)
} else {
self.record_use(ident, ns, binding);
if let Some(shadowed_glob) = resolution.shadowed_glob {
// Forbid expanded shadowing to avoid time travel.
if restricted_shadowing &&
binding.expansion != Mark::root() &&
binding.def() != shadowed_glob.def() {
self.ambiguity_errors.push(AmbiguityError {
kind: AmbiguityKind::GlobVsExpanded,
ident,
b1: binding,
b2: shadowed_glob,
misc1: AmbiguityErrorMisc::None,
misc2: AmbiguityErrorMisc::None,
});
}
}
if !self.is_accessible(binding.vis) &&
// Remove this together with `PUB_USE_OF_PRIVATE_EXTERN_CRATE`
!(self.last_import_segment && binding.is_extern_crate()) {
self.privacy_errors.push(PrivacyError(path_span, ident, binding));
}
Ok(binding)
}
})
}
// Items and single imports are not shadowable, if we have one, then it's determined.
if let Some(binding) = resolution.binding {
if !binding.is_glob_import() {
@ -628,8 +635,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
let mut prev_root_id: NodeId = NodeId::from_u32(0);
for i in 0 .. self.determined_imports.len() {
let import = self.determined_imports[i];
let error = self.finalize_import(import);
if let Some((span, err, note)) = error {
if let Some((span, err, note)) = self.finalize_import(import) {
errors = true;
if let SingleImport { source, ref result, .. } = import.subclass {
@ -726,7 +732,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
/// If successful, the resolved bindings are written into the module.
fn resolve_import(&mut self, directive: &'b ImportDirective<'b>) -> bool {
debug!("(resolving import for module) resolving import `{}::...` in `{}`",
Segment::names_to_string(&directive.module_path[..]),
Segment::names_to_string(&directive.module_path),
module_to_string(self.current_module).unwrap_or_else(|| "???".to_string()));
self.current_module = directive.parent_scope.module;
@ -737,8 +743,8 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
// For better failure detection, pretend that the import will
// not define any names while resolving its module path.
let orig_vis = directive.vis.replace(ty::Visibility::Invisible);
let result = self.resolve_path(
&directive.module_path[..],
let path_res = self.resolve_path(
&directive.module_path,
None,
&directive.parent_scope,
false,
@ -747,10 +753,10 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
);
directive.vis.set(orig_vis);
match result {
match path_res {
PathResult::Module(module) => module,
PathResult::Indeterminate => return false,
_ => return true,
PathResult::NonModule(..) | PathResult::Failed(..) => return true,
}
};
@ -817,25 +823,37 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
directive: &'b ImportDirective<'b>
) -> Option<(Span, String, Option<String>)> {
self.current_module = directive.parent_scope.module;
let ImportDirective { ref module_path, span, .. } = *directive;
let module_result = self.resolve_path(
&module_path,
None,
&directive.parent_scope,
true,
span,
directive.crate_lint(),
);
let module = match module_result {
PathResult::Module(module) => module,
let orig_vis = directive.vis.replace(ty::Visibility::Invisible);
let path_res = self.resolve_path(&directive.module_path, None, &directive.parent_scope,
true, directive.span, directive.crate_lint());
directive.vis.set(orig_vis);
let module = match path_res {
PathResult::Module(module) => {
// Consistency checks, analogous to `finalize_current_module_macro_resolutions`.
if let Some(initial_module) = directive.imported_module.get() {
if module != initial_module && self.ambiguity_errors.is_empty() {
span_bug!(directive.span, "inconsistent resolution for an import");
}
} else {
if self.privacy_errors.is_empty() {
let msg = "cannot determine resolution for the import";
let msg_note = "import resolution is stuck, try simplifying other imports";
self.session.struct_span_err(directive.span, msg).note(msg_note).emit();
}
}
module
}
PathResult::Failed(span, msg, false) => {
assert!(directive.imported_module.get().is_none());
resolve_error(self, span, ResolutionError::FailedToResolve(&msg));
return None;
}
PathResult::Failed(span, msg, true) => {
assert!(directive.imported_module.get().is_none());
return if let Some((suggested_path, note)) = self.make_path_suggestion(
span, module_path.clone(), &directive.parent_scope
span, directive.module_path.clone(), &directive.parent_scope
) {
Some((
span,
@ -845,17 +863,22 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
} else {
Some((span, msg, None))
};
},
_ => return None,
}
PathResult::NonModule(path_res) if path_res.base_def() == Def::Err => {
// The error was already reported earlier.
assert!(directive.imported_module.get().is_none());
return None;
}
PathResult::Indeterminate | PathResult::NonModule(..) => unreachable!(),
};
let (ident, result, type_ns_only) = match directive.subclass {
SingleImport { source, ref result, type_ns_only, .. } => (source, result, type_ns_only),
GlobImport { is_prelude, ref max_vis } => {
if module_path.len() <= 1 {
if directive.module_path.len() <= 1 {
// HACK(eddyb) `lint_if_path_starts_with_module` needs at least
// 2 segments, so the `resolve_path` above won't trigger it.
let mut full_path = module_path.clone();
let mut full_path = directive.module_path.clone();
full_path.push(Segment::from_ident(keywords::Invalid.ident()));
self.lint_if_path_starts_with_module(
directive.crate_lint(),
@ -888,20 +911,39 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
let mut all_ns_err = true;
self.per_ns(|this, ns| if !type_ns_only || ns == TypeNS {
if let Ok(binding) = result[ns].get() {
all_ns_err = false;
if this.record_use(ident, ns, binding) {
if let ModuleOrUniformRoot::Module(module) = module {
this.resolution(module, ident, ns).borrow_mut().binding =
Some(this.dummy_binding);
let orig_vis = directive.vis.replace(ty::Visibility::Invisible);
let orig_last_import_segment = mem::replace(&mut this.last_import_segment, true);
let binding = this.resolve_ident_in_module(
module, ident, ns, Some(&directive.parent_scope), true, directive.span
);
this.last_import_segment = orig_last_import_segment;
directive.vis.set(orig_vis);
match binding {
Ok(binding) => {
// Consistency checks, analogous to `finalize_current_module_macro_resolutions`.
let initial_def = result[ns].get().map(|initial_binding| {
all_ns_err = false;
this.record_use(ident, MacroNS, initial_binding);
initial_binding.def_ignoring_ambiguity()
});
let def = binding.def_ignoring_ambiguity();
if let Ok(initial_def) = initial_def {
if def != initial_def && this.ambiguity_errors.is_empty() {
span_bug!(directive.span, "inconsistent resolution for an import");
}
} else {
if def != Def::Err &&
this.ambiguity_errors.is_empty() && this.privacy_errors.is_empty() {
let msg = "cannot determine resolution for the import";
let msg_note =
"import resolution is stuck, try simplifying other imports";
this.session.struct_span_err(directive.span, msg).note(msg_note).emit();
}
}
}
if ns == TypeNS {
if let ModuleOrUniformRoot::UniformRoot(..) = module {
// Make sure single-segment import is resolved non-speculatively
// at least once to report the feature error.
this.extern_prelude_get(ident, false, false);
}
Err(..) => {
assert!(result[ns].get().is_err());
}
}
});
@ -910,7 +952,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
let mut all_ns_failed = true;
self.per_ns(|this, ns| if !type_ns_only || ns == TypeNS {
let binding = this.resolve_ident_in_module(
module, ident, ns, Some(&directive.parent_scope), true, span
module, ident, ns, Some(&directive.parent_scope), true, directive.span
);
if binding.is_ok() {
all_ns_failed = false;
@ -969,7 +1011,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
}
}
};
Some((span, msg, None))
Some((directive.span, msg, None))
} else {
// `resolve_ident_in_module` reported a privacy error.
self.import_dummy_binding(directive);
@ -1018,10 +1060,10 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
}
}
if module_path.len() <= 1 {
if directive.module_path.len() <= 1 {
// HACK(eddyb) `lint_if_path_starts_with_module` needs at least
// 2 segments, so the `resolve_path` above won't trigger it.
let mut full_path = module_path.clone();
let mut full_path = directive.module_path.clone();
full_path.push(Segment::from_ident(ident));
self.per_ns(|this, ns| {
if let Ok(binding) = result[ns].get() {

View File

@ -595,6 +595,13 @@ impl MacroKind {
MacroKind::ProcMacroStub => "crate-local procedural macro",
}
}
pub fn article(self) -> &'static str {
match self {
MacroKind::Attr => "an",
_ => "a",
}
}
}
/// An enum representing the different kinds of syntax extensions.

View File

@ -12,5 +12,5 @@
fn main() {
enum Foo {}
let _ = Foo::bar!(); //~ ERROR fail to resolve non-ident macro path
let _ = Foo::bar!(); //~ ERROR failed to resolve. partially resolved path in a macro
}

View File

@ -1,8 +1,9 @@
error: fail to resolve non-ident macro path
error[E0433]: failed to resolve. partially resolved path in a macro
--> $DIR/extern-macro.rs:15:13
|
LL | let _ = Foo::bar!(); //~ ERROR fail to resolve non-ident macro path
| ^^^^^^^^
LL | let _ = Foo::bar!(); //~ ERROR failed to resolve. partially resolved path in a macro
| ^^^^^^^^ partially resolved path in a macro
error: aborting due to previous error
For more information about this error, try `rustc --explain E0433`.

View File

@ -10,7 +10,7 @@
mod m {
fn check() {
Result::Ok!(); //~ ERROR fail to resolve non-ident macro path
Result::Ok!(); //~ ERROR failed to resolve. partially resolved path in a macro
}
}

View File

@ -1,8 +1,9 @@
error: fail to resolve non-ident macro path
error[E0433]: failed to resolve. partially resolved path in a macro
--> $DIR/macro-path-prelude-fail-2.rs:13:9
|
LL | Result::Ok!(); //~ ERROR fail to resolve non-ident macro path
| ^^^^^^^^^^
LL | Result::Ok!(); //~ ERROR failed to resolve. partially resolved path in a macro
| ^^^^^^^^^^ partially resolved path in a macro
error: aborting due to previous error
For more information about this error, try `rustc --explain E0433`.

View File

@ -0,0 +1,9 @@
#![feature(decl_macro)]
mod m {
macro mac() {}
}
fn main() {
m::mac!(); //~ ERROR macro `mac` is private
}

View File

@ -0,0 +1,9 @@
error[E0603]: macro `mac` is private
--> $DIR/decl-macro.rs:8:8
|
LL | m::mac!(); //~ ERROR macro `mac` is private
| ^^^
error: aborting due to previous error
For more information about this error, try `rustc --explain E0603`.

View File

@ -2,7 +2,7 @@ error[E0432]: unresolved import `xcrate`
--> $DIR/non-existent-1.rs:13:5
|
LL | use xcrate::S; //~ ERROR unresolved import `xcrate`
| ^^^^^^ Could not find `xcrate` in `{{root}}`
| ^^^^^^ Use of undeclared type or module `xcrate`
error: aborting due to previous error

View File

@ -16,6 +16,6 @@ fn main() {
fn std() {}
enum std {}
use std as foo;
//~^ ERROR `std` import is ambiguous
//~| ERROR `std` import is ambiguous
//~^ ERROR `std` is ambiguous
//~| ERROR `std` is ambiguous
}

View File

@ -1,31 +1,39 @@
error: `std` import is ambiguous
error[E0659]: `std` is ambiguous (name vs any other name during import resolution)
--> $DIR/block-scoped-shadow.rs:18:9
|
LL | struct std;
| ----------- may refer to `self::std` in the future
...
LL | enum std {}
| ----------- shadowed by block-scoped `std`
LL | use std as foo;
| ^^^ can refer to external crate `::std`
| ^^^ ambiguous name
|
= help: write `::std` or `self::std` explicitly instead
= note: in the future, `#![feature(uniform_paths)]` may become the default
note: `std` could refer to the enum defined here
--> $DIR/block-scoped-shadow.rs:17:5
|
LL | enum std {}
| ^^^^^^^^^^^
note: `std` could also refer to the struct defined here
--> $DIR/block-scoped-shadow.rs:13:1
|
LL | struct std;
| ^^^^^^^^^^^
= help: use `self::std` to refer to the struct unambiguously
error: `std` import is ambiguous
error[E0659]: `std` is ambiguous (name vs any other name during import resolution)
--> $DIR/block-scoped-shadow.rs:18:9
|
LL | struct std;
| ----------- may refer to `self::std` in the future
...
LL | fn std() {}
| ----------- shadowed by block-scoped `std`
LL | enum std {}
LL | use std as foo;
| ^^^
| ^^^ ambiguous name
|
= help: write `self::std` explicitly instead
= note: in the future, `#![feature(uniform_paths)]` may become the default
note: `std` could refer to the function defined here
--> $DIR/block-scoped-shadow.rs:16:5
|
LL | fn std() {}
| ^^^^^^^^^^^
note: `std` could also refer to the unit struct defined here
--> $DIR/block-scoped-shadow.rs:13:1
|
LL | struct std;
| ^^^^^^^^^^^
= help: use `self::std` to refer to the unit struct unambiguously
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0659`.

View File

@ -0,0 +1,20 @@
// edition:2018
mod my {
pub mod sub {
pub fn bar() {}
}
}
mod sub {
pub fn bar() {}
}
fn foo() {
use my::sub;
{
use sub::bar; //~ ERROR `sub` is ambiguous
}
}
fn main() {}

View File

@ -0,0 +1,23 @@
error[E0659]: `sub` is ambiguous (name vs any other name during import resolution)
--> $DIR/block-scoped-shadow-nested.rs:16:13
|
LL | use sub::bar; //~ ERROR `sub` is ambiguous
| ^^^ ambiguous name
|
note: `sub` could refer to the module imported here
--> $DIR/block-scoped-shadow-nested.rs:14:9
|
LL | use my::sub;
| ^^^^^^^
note: `sub` could also refer to the module defined here
--> $DIR/block-scoped-shadow-nested.rs:9:1
|
LL | / mod sub {
LL | | pub fn bar() {}
LL | | }
| |_^
= help: use `self::sub` to refer to the module unambiguously
error: aborting due to previous error
For more information about this error, try `rustc --explain E0659`.

View File

@ -12,20 +12,20 @@
#![feature(uniform_paths)]
enum Foo { A, B }
enum Foo {}
struct std;
fn main() {
enum Foo {}
enum Foo { A, B }
use Foo::*;
//~^ ERROR `Foo` import is ambiguous
//~^ ERROR `Foo` is ambiguous
let _ = (A, B);
fn std() {}
enum std {}
use std as foo;
//~^ ERROR `std` import is ambiguous
//~| ERROR `std` import is ambiguous
//~^ ERROR `std` is ambiguous
//~| ERROR `std` is ambiguous
}

View File

@ -1,45 +1,57 @@
error: `Foo` import is ambiguous
error[E0659]: `Foo` is ambiguous (name vs any other name during import resolution)
--> $DIR/block-scoped-shadow.rs:21:9
|
LL | enum Foo { A, B }
| ----------------- can refer to `self::Foo`
...
LL | enum Foo {}
| ----------- shadowed by block-scoped `Foo`
LL | use Foo::*;
| ^^^
| ^^^ ambiguous name
|
= help: write `self::Foo` explicitly instead
= note: relative `use` paths enabled by `#![feature(uniform_paths)]`
note: `Foo` could refer to the enum defined here
--> $DIR/block-scoped-shadow.rs:20:5
|
LL | enum Foo { A, B }
| ^^^^^^^^^^^^^^^^^
note: `Foo` could also refer to the enum defined here
--> $DIR/block-scoped-shadow.rs:15:1
|
LL | enum Foo {}
| ^^^^^^^^^^^
= help: use `self::Foo` to refer to the enum unambiguously
error: `std` import is ambiguous
error[E0659]: `std` is ambiguous (name vs any other name during import resolution)
--> $DIR/block-scoped-shadow.rs:28:9
|
LL | struct std;
| ----------- can refer to `self::std`
...
LL | enum std {}
| ----------- shadowed by block-scoped `std`
LL | use std as foo;
| ^^^ can refer to external crate `::std`
| ^^^ ambiguous name
|
= help: write `::std` or `self::std` explicitly instead
= note: relative `use` paths enabled by `#![feature(uniform_paths)]`
error: `std` import is ambiguous
--> $DIR/block-scoped-shadow.rs:28:9
note: `std` could refer to the enum defined here
--> $DIR/block-scoped-shadow.rs:27:5
|
LL | enum std {}
| ^^^^^^^^^^^
note: `std` could also refer to the struct defined here
--> $DIR/block-scoped-shadow.rs:17:1
|
LL | struct std;
| ----------- can refer to `self::std`
...
| ^^^^^^^^^^^
= help: use `self::std` to refer to the struct unambiguously
error[E0659]: `std` is ambiguous (name vs any other name during import resolution)
--> $DIR/block-scoped-shadow.rs:28:9
|
LL | use std as foo;
| ^^^ ambiguous name
|
note: `std` could refer to the function defined here
--> $DIR/block-scoped-shadow.rs:26:5
|
LL | fn std() {}
| ----------- shadowed by block-scoped `std`
LL | enum std {}
LL | use std as foo;
| ^^^
| ^^^^^^^^^^^
note: `std` could also refer to the unit struct defined here
--> $DIR/block-scoped-shadow.rs:17:1
|
= help: write `self::std` explicitly instead
= note: relative `use` paths enabled by `#![feature(uniform_paths)]`
LL | struct std;
| ^^^^^^^^^^^
= help: use `self::std` to refer to the unit struct unambiguously
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0659`.

View File

@ -0,0 +1,13 @@
// compile-pass
// edition:2018
fn main() {
enum E { A, B, C }
use E::*;
match A {
A => {}
B => {}
C => {}
}
}