diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 39a9194cf5e..f613025fe37 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -894,6 +894,7 @@ enum NameBindingKind<'a> { binding: &'a NameBinding<'a>, directive: &'a ImportDirective<'a>, used: Cell, + legacy_self_import: bool, }, Ambiguity { b1: &'a NameBinding<'a>, @@ -1346,8 +1347,13 @@ impl<'a> Resolver<'a> { } match binding.kind { - NameBindingKind::Import { directive, binding, ref used } if !used.get() => { + NameBindingKind::Import { directive, binding, ref used, legacy_self_import } + if !used.get() => { used.set(true); + if legacy_self_import { + self.warn_legacy_self_import(directive); + return false; + } self.used_imports.insert((directive.id, ns)); self.add_to_glob_map(directive.id, ident); self.record_use(ident, ns, binding, span) @@ -3110,6 +3116,12 @@ impl<'a> Resolver<'a> { err.emit(); self.name_already_seen.insert(name, span); } + + fn warn_legacy_self_import(&self, directive: &'a ImportDirective<'a>) { + let (id, span) = (directive.id, directive.span); + let msg = "`self` no longer imports values".to_string(); + self.session.add_lint(lint::builtin::LEGACY_IMPORTS, id, span, msg); + } } fn is_struct_like(def: Def) -> bool { diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index 1702a1441bf..65e599ac6c7 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -297,6 +297,7 @@ impl<'a> Resolver<'a> { binding: binding, directive: directive, used: Cell::new(false), + legacy_self_import: false, }, span: directive.span, vis: vis, @@ -594,6 +595,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { }; let mut all_ns_err = true; + let mut legacy_self_import = None; self.per_ns(|this, ns| if !type_ns_only || ns == TypeNS { if let Ok(binding) = result[ns].get() { all_ns_err = false; @@ -602,9 +604,25 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { Some(this.dummy_binding); } } + } else if let Ok(binding) = this.resolve_ident_in_module(module, ident, ns, false, None) { + legacy_self_import = Some(directive); + let binding = this.arenas.alloc_name_binding(NameBinding { + kind: NameBindingKind::Import { + binding: binding, + directive: directive, + used: Cell::new(false), + legacy_self_import: true, + }, + ..*binding + }); + let _ = this.try_define(directive.parent, ident, ns, binding); }); if all_ns_err { + if let Some(directive) = legacy_self_import { + self.warn_legacy_self_import(directive); + return None; + } let mut all_ns_failed = true; self.per_ns(|this, ns| if !type_ns_only || ns == TypeNS { match this.resolve_ident_in_module(module, ident, ns, false, Some(span)) { diff --git a/src/test/compile-fail/issue-38293.rs b/src/test/compile-fail/issue-38293.rs index f97fad7bd74..bf24621a869 100644 --- a/src/test/compile-fail/issue-38293.rs +++ b/src/test/compile-fail/issue-38293.rs @@ -10,22 +10,24 @@ // Test that `fn foo::bar::{self}` only imports `bar` in the type namespace. +#![allow(unused)] +#![deny(legacy_imports)] + mod foo { pub fn f() { } } use foo::f::{self}; -//~^ ERROR unresolved import -//~| NOTE no `f` in `foo` +//~^ ERROR `self` no longer imports values +//~| WARN hard error mod bar { pub fn baz() {} pub mod baz {} } use bar::baz::{self}; +//~^ ERROR `self` no longer imports values +//~| WARN hard error fn main() { baz(); - //~^ ERROR unresolved name `baz` - //~| NOTE unresolved name - //~| HELP module `baz` cannot be used as an expression }