Fix ICEs from imports of items not defined in modules

This commit is contained in:
Vadim Petrochenkov 2018-11-11 20:28:56 +03:00
parent cfd762954b
commit a38f903114
13 changed files with 197 additions and 32 deletions

View File

@ -261,6 +261,12 @@ impl NonMacroAttrKind {
impl Def {
pub fn def_id(&self) -> DefId {
self.opt_def_id().unwrap_or_else(|| {
bug!("attempted .def_id() on invalid def: {:?}", self)
})
}
pub fn opt_def_id(&self) -> Option<DefId> {
match *self {
Def::Fn(id) | Def::Mod(id) | Def::Static(id, _) |
Def::Variant(id) | Def::VariantCtor(id, ..) | Def::Enum(id) |
@ -268,9 +274,8 @@ impl Def {
Def::AssociatedTy(id) | Def::TyParam(id) | Def::Struct(id) | Def::StructCtor(id, ..) |
Def::Union(id) | Def::Trait(id) | Def::Method(id) | Def::Const(id) |
Def::AssociatedConst(id) | Def::Macro(id, ..) |
Def::Existential(id) | Def::AssociatedExistential(id) | Def::ForeignTy(id) |
Def::SelfCtor(id) => {
id
Def::Existential(id) | Def::AssociatedExistential(id) | Def::ForeignTy(id) => {
Some(id)
}
Def::Local(..) |
@ -278,10 +283,11 @@ impl Def {
Def::Label(..) |
Def::PrimTy(..) |
Def::SelfTy(..) |
Def::SelfCtor(..) |
Def::ToolMod |
Def::NonMacroAttr(..) |
Def::Err => {
bug!("attempted .def_id() on invalid def: {:?}", self)
None
}
}
}

View File

@ -80,7 +80,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
self.check_def_id(def.def_id());
}
_ if self.in_pat => (),
Def::PrimTy(..) | Def::SelfTy(..) |
Def::PrimTy(..) | Def::SelfTy(..) | Def::SelfCtor(..) |
Def::Local(..) | Def::Upvar(..) => {}
Def::Variant(variant_id) | Def::VariantCtor(variant_id, ..) => {
if let Some(enum_id) = self.tcx.parent_def_id(variant_id) {

View File

@ -781,10 +781,8 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> {
fn visit_path(&mut self, path: &'tcx hir::Path, id: hir::HirId) {
let id = self.tcx.hir.hir_to_node_id(id);
match path.def {
Def::Local(..) | Def::Upvar(..) | Def::SelfCtor(..) |
Def::PrimTy(..) | Def::SelfTy(..) | Def::Err => {}
_ => self.tcx.check_stability(path.def.def_id(), Some(id), path.span)
if let Some(def_id) = path.def.opt_def_id() {
self.tcx.check_stability(def_id, Some(id), path.span)
}
intravisit::walk_path(self, path)
}

View File

@ -361,9 +361,11 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> {
let def_id = self.tcx.hir.local_def_id(id);
if let Some(exports) = self.tcx.module_exports(def_id) {
for export in exports.iter() {
if let Some(node_id) = self.tcx.hir.as_local_node_id(export.def.def_id()) {
if export.vis == ty::Visibility::Public {
self.update(node_id, Some(AccessLevel::Exported));
if export.vis == ty::Visibility::Public {
if let Some(def_id) = export.def.opt_def_id() {
if let Some(node_id) = self.tcx.hir.as_local_node_id(def_id) {
self.update(node_id, Some(AccessLevel::Exported));
}
}
}
}

View File

@ -227,7 +227,7 @@ impl<'a, 'crateloader: 'a> base::Resolver for Resolver<'a, 'crateloader> {
let binding = self.arenas.alloc_name_binding(NameBinding {
kind: NameBindingKind::Def(Def::Macro(def_id, kind), false),
span: DUMMY_SP,
vis: ty::Visibility::Invisible,
vis: ty::Visibility::Public,
expansion: Mark::root(),
});
if self.builtin_macros.insert(ident.name, binding).is_some() {

View File

@ -1081,8 +1081,18 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
// this may resolve to either a value or a type, but for documentation
// purposes it's good enough to just favor one over the other.
self.per_ns(|this, ns| if let Some(binding) = result[ns].get().ok() {
let mut def = binding.def();
if let Def::Macro(def_id, _) = def {
// `DefId`s from the "built-in macro crate" should not leak from resolve because
// later stages are not ready to deal with them and produce lots of ICEs. Replace
// them with `Def::Err` until some saner scheme is implemented for built-in macros.
if def_id.krate == CrateNum::BuiltinMacros {
this.session.span_err(directive.span, "cannot import a built-in macro");
def = Def::Err;
}
}
let import = this.import_map.entry(directive.id).or_default();
import[ns] = Some(PathResolution::new(binding.def()));
import[ns] = Some(PathResolution::new(def));
});
debug!("(resolving single import) successfully resolved import");
@ -1154,9 +1164,10 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
if binding.is_import() || binding.is_macro_def() {
let def = binding.def();
if def != Def::Err {
let def_id = def.def_id();
if !def_id.is_local() && def_id.krate != CrateNum::BuiltinMacros {
self.cstore.export_macros_untracked(def_id.krate);
if let Some(def_id) = def.opt_def_id() {
if !def_id.is_local() && def_id.krate != CrateNum::BuiltinMacros {
self.cstore.export_macros_untracked(def_id.krate);
}
}
reexports.push(Export {
ident: ident.modern(),

View File

@ -13,7 +13,7 @@
// Tests that arbitrary crates (other than `core`, `std` and `meta`)
// aren't allowed without `--extern`, even if they're in the sysroot.
use alloc; //~ ERROR unresolved import `alloc`
use test; //~ ERROR unresolved import `test`
use proc_macro; //~ ERROR unresolved import `proc_macro`
use test; //~ ERROR cannot import a built-in macro
use proc_macro; // OK, imports the built-in `proc_macro` attribute, but not the `proc_macro` crate.
fn main() {}

View File

@ -1,21 +1,15 @@
error: cannot import a built-in macro
--> $DIR/not-whitelisted.rs:16:5
|
LL | use test; //~ ERROR cannot import a built-in macro
| ^^^^
error[E0432]: unresolved import `alloc`
--> $DIR/not-whitelisted.rs:15:5
|
LL | use alloc; //~ ERROR unresolved import `alloc`
| ^^^^^ no `alloc` external crate
error[E0432]: unresolved import `test`
--> $DIR/not-whitelisted.rs:16:5
|
LL | use test; //~ ERROR unresolved import `test`
| ^^^^ no `test` external crate
error[E0432]: unresolved import `proc_macro`
--> $DIR/not-whitelisted.rs:17:5
|
LL | use proc_macro; //~ ERROR unresolved import `proc_macro`
| ^^^^^^^^^^ no `proc_macro` external crate
error: aborting due to 3 previous errors
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0432`.

View File

@ -0,0 +1,44 @@
// edition:2018
// For the time being `macro_rules` items are treated as *very* private...
#![feature(underscore_imports, decl_macro)]
mod m1 {
macro_rules! legacy_macro { () => () }
// ... so they can't be imported by themselves, ...
use legacy_macro as _; //~ ERROR `legacy_macro` is private, and cannot be re-exported
}
mod m2 {
macro_rules! legacy_macro { () => () }
type legacy_macro = u8;
// ... but don't prevent names from other namespaces from being imported, ...
use legacy_macro as _; // OK
}
mod m3 {
macro legacy_macro() {}
fn f() {
macro_rules! legacy_macro { () => () }
// ... but still create ambiguities with other names in the same namespace.
use legacy_macro as _; //~ ERROR `legacy_macro` is ambiguous
//~| ERROR `legacy_macro` is private, and cannot be re-exported
}
}
mod exported {
// Exported macros are treated as private as well,
// some better rules need to be figured out later.
#[macro_export]
macro_rules! legacy_macro { () => () }
use legacy_macro as _; //~ ERROR `legacy_macro` is private, and cannot be re-exported
}
fn main() {}

View File

@ -0,0 +1,58 @@
error[E0364]: `legacy_macro` is private, and cannot be re-exported
--> $DIR/macro-rules.rs:11:9
|
LL | use legacy_macro as _; //~ ERROR `legacy_macro` is private, and cannot be re-exported
| ^^^^^^^^^^^^^^^^^
|
note: consider marking `legacy_macro` as `pub` in the imported module
--> $DIR/macro-rules.rs:11:9
|
LL | use legacy_macro as _; //~ ERROR `legacy_macro` is private, and cannot be re-exported
| ^^^^^^^^^^^^^^^^^
error[E0364]: `legacy_macro` is private, and cannot be re-exported
--> $DIR/macro-rules.rs:30:13
|
LL | use legacy_macro as _; //~ ERROR `legacy_macro` is ambiguous
| ^^^^^^^^^^^^^^^^^
|
note: consider marking `legacy_macro` as `pub` in the imported module
--> $DIR/macro-rules.rs:30:13
|
LL | use legacy_macro as _; //~ ERROR `legacy_macro` is ambiguous
| ^^^^^^^^^^^^^^^^^
error[E0364]: `legacy_macro` is private, and cannot be re-exported
--> $DIR/macro-rules.rs:41:9
|
LL | use legacy_macro as _; //~ ERROR `legacy_macro` is private, and cannot be re-exported
| ^^^^^^^^^^^^^^^^^
|
note: consider marking `legacy_macro` as `pub` in the imported module
--> $DIR/macro-rules.rs:41:9
|
LL | use legacy_macro as _; //~ ERROR `legacy_macro` is private, and cannot be re-exported
| ^^^^^^^^^^^^^^^^^
error[E0659]: `legacy_macro` is ambiguous (name vs any other name during import resolution)
--> $DIR/macro-rules.rs:30:13
|
LL | use legacy_macro as _; //~ ERROR `legacy_macro` is ambiguous
| ^^^^^^^^^^^^ ambiguous name
|
note: `legacy_macro` could refer to the macro defined here
--> $DIR/macro-rules.rs:27:9
|
LL | macro_rules! legacy_macro { () => () }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: `legacy_macro` could also refer to the macro defined here
--> $DIR/macro-rules.rs:24:5
|
LL | macro legacy_macro() {}
| ^^^^^^^^^^^^^^^^^^^^^^^
= help: use `self::legacy_macro` to refer to this macro unambiguously
error: aborting due to 4 previous errors
Some errors occurred: E0364, E0659.
For more information about an error, try `rustc --explain E0364`.

View File

@ -0,0 +1,11 @@
// edition:2018
// Built-in macro
use env as env_imported; //~ ERROR cannot import a built-in macro
// Tool attribute
use rustfmt::skip as imported_rustfmt_skip; //~ ERROR unresolved import `rustfmt`
fn main() {
env_imported!("PATH");
}

View File

@ -0,0 +1,15 @@
error: cannot import a built-in macro
--> $DIR/prelude-fail.rs:4:5
|
LL | use env as env_imported; //~ ERROR cannot import a built-in macro
| ^^^^^^^^^^^^^^^^^^^
error[E0432]: unresolved import `rustfmt`
--> $DIR/prelude-fail.rs:7:5
|
LL | use rustfmt::skip as imported_rustfmt_skip; //~ ERROR unresolved import `rustfmt`
| ^^^^^^^ Not a module `rustfmt`
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0432`.

View File

@ -0,0 +1,26 @@
// compile-pass
// edition:2018
// Macro imported with `#[macro_use] extern crate`
use vec as imported_vec;
// Built-in attribute
use inline as imported_inline;
// Tool module
use rustfmt as imported_rustfmt;
// Standard library prelude
use Vec as ImportedVec;
// Built-in type
use u8 as imported_u8;
type A = imported_u8;
#[imported_inline]
#[imported_rustfmt::skip]
fn main() {
imported_vec![0];
ImportedVec::<u8>::new();
}