Resolve absolute paths as extern under a feature flag

This commit is contained in:
Vadim Petrochenkov 2017-12-10 03:30:47 +03:00
parent 9552b9cfd2
commit b07e26e36e
15 changed files with 238 additions and 3 deletions

View File

@ -357,6 +357,7 @@ impl CrateStore for DummyCrateStore {
pub trait CrateLoader {
fn process_item(&mut self, item: &ast::Item, defs: &Definitions);
fn postprocess(&mut self, krate: &ast::Crate);
fn resolve_crate_from_path(&mut self, name: Symbol, span: Span) -> CrateNum;
}
// This method is used when generating the command line to pass through to

View File

@ -1087,4 +1087,8 @@ impl<'a> middle::cstore::CrateLoader for CrateLoader<'a> {
_ => {}
}
}
fn resolve_crate_from_path(&mut self, name: Symbol, span: Span) -> CrateNum {
self.resolve_crate(&None, name, name, None, span, PathKind::Crate, DepKind::Explicit).0
}
}

View File

@ -58,6 +58,7 @@ use syntax::ast::{Item, ItemKind, ImplItem, ImplItemKind};
use syntax::ast::{Local, Mutability, Pat, PatKind, Path};
use syntax::ast::{QSelf, TraitItemKind, TraitRef, Ty, TyKind};
use syntax::feature_gate::{feature_err, emit_feature_err, GateIssue};
use syntax::parse::token;
use syntax_pos::{Span, DUMMY_SP, MultiSpan};
use errors::{DiagnosticBuilder, DiagnosticId};
@ -2959,6 +2960,16 @@ impl<'a> Resolver<'a> {
// `$crate::a::b`
module = Some(self.resolve_crate_root(ident.node.ctxt));
continue
} else if i == 1 && self.session.features.borrow().extern_absolute_paths &&
path[0].node.name == keywords::CrateRoot.name() &&
!token::Ident(ident.node).is_path_segment_keyword() {
// `::extern_crate::a::b`
let crate_id = self.crate_loader.resolve_crate_from_path(name, ident.span);
let crate_root =
self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX });
self.populate_module_if_necessary(crate_root);
module = Some(crate_root);
continue
}
}

View File

@ -12,14 +12,14 @@ use self::ImportDirectiveSubclass::*;
use {AmbiguityError, Module, PerNS};
use Namespace::{self, TypeNS, MacroNS};
use {NameBinding, NameBindingKind, PathResult, PrivacyError};
use {NameBinding, NameBindingKind, ToNameBinding, PathResult, PrivacyError};
use Resolver;
use {names_to_string, module_to_string};
use {resolve_error, ResolutionError};
use rustc::ty;
use rustc::lint::builtin::PUB_USE_OF_PRIVATE_EXTERN_CRATE;
use rustc::hir::def_id::DefId;
use rustc::hir::def_id::{CRATE_DEF_INDEX, DefId};
use rustc::hir::def::*;
use rustc::session::DiagnosticMessageId;
use rustc::util::nodemap::{FxHashMap, FxHashSet};
@ -602,8 +602,60 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
// If appropriate, returns an error to report.
fn finalize_import(&mut self, directive: &'b ImportDirective<'b>) -> Option<(Span, String)> {
self.current_module = directive.parent;
let ImportDirective { ref module_path, span, .. } = *directive;
// Extern crate mode for absolute paths needs some
// special support for single-segment imports.
let extern_absolute_paths = self.session.features.borrow().extern_absolute_paths;
if module_path.len() == 1 && module_path[0].node.name == keywords::CrateRoot.name() {
match directive.subclass {
GlobImport { .. } if extern_absolute_paths => {
return Some((directive.span,
"cannot glob-import all possible crates".to_string()));
}
SingleImport { source, target, .. } => {
let crate_root = if source.name == keywords::Crate.name() {
if target.name == keywords::Crate.name() {
return Some((directive.span,
"crate root imports need to be explicitly named: \
`use crate as name;`".to_string()));
} else {
Some(self.resolve_crate_root(source.ctxt.modern()))
}
} else if extern_absolute_paths &&
!token::Ident(source).is_path_segment_keyword() {
let crate_id =
self.crate_loader.resolve_crate_from_path(source.name, directive.span);
let crate_root =
self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX });
self.populate_module_if_necessary(crate_root);
Some(crate_root)
} else {
None
};
if let Some(crate_root) = crate_root {
let binding = (crate_root, ty::Visibility::Public, directive.span,
directive.expansion).to_name_binding(self.arenas);
let binding = self.arenas.alloc_name_binding(NameBinding {
kind: NameBindingKind::Import {
binding,
directive,
used: Cell::new(false),
legacy_self_import: false,
},
vis: directive.vis.get(),
span: directive.span,
expansion: directive.expansion,
});
let _ = self.try_define(directive.parent, target, TypeNS, binding);
return None;
}
}
_ => {}
}
}
let module_result = self.resolve_path(&module_path, None, true, span);
let module = match module_result {
PathResult::Module(module) => module,

View File

@ -430,6 +430,9 @@ declare_features! (
// generic associated types (RFC 1598)
(active, generic_associated_types, "1.23.0", Some(44265)),
// Resolve absolute paths as paths from other crates
(active, extern_absolute_paths, "1.24.0", Some(44660)),
);
declare_features! (

View File

@ -0,0 +1,15 @@
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[derive(Debug)]
pub struct S;
#[derive(Debug)]
pub struct Z;

View File

@ -0,0 +1,15 @@
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![feature(extern_absolute_paths)]
use xcrate::S; //~ ERROR can't find crate for `xcrate`
fn main() {}

View File

@ -0,0 +1,15 @@
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![feature(extern_absolute_paths)]
fn main() {
let s = ::xcrate::S; //~ ERROR can't find crate for `xcrate`
}

View File

@ -0,0 +1,15 @@
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![feature(extern_absolute_paths)]
use ycrate; //~ ERROR can't find crate for `ycrate`
fn main() {}

View File

@ -0,0 +1,24 @@
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// aux-build:xcrate.rs
#![feature(crate_in_paths)]
#![feature(extern_absolute_paths)]
use crate; //~ ERROR unresolved import `crate`
//~^ NOTE crate root imports need to be explicitly named: `use crate as name;`
use *; //~ ERROR unresolved import `*`
//~^ NOTE cannot glob-import all possible crates
fn main() {
let s = ::xcrate; //~ ERROR expected value, found module `xcrate`
//~^ NOTE not a value
}

View File

@ -11,10 +11,12 @@
#![feature(crate_in_paths)]
use crate::m::f;
use crate as root;
mod m {
pub fn f() -> u8 { 1 }
pub fn g() -> u8 { 2 }
pub fn h() -> u8 { 3 }
// OK, visibilities are implicitly absolute like imports
pub(in crate::m) struct S;
@ -23,14 +25,17 @@ mod m {
mod n
{
use crate::m::f;
use crate as root;
pub fn check() {
assert_eq!(f(), 1);
assert_eq!(::crate::m::g(), 2);
assert_eq!(root::m::h(), 3);
}
}
fn main() {
assert_eq!(f(), 1);
assert_eq!(::crate::m::g(), 2);
assert_eq!(root::m::h(), 3);
n::check();
}

View File

@ -0,0 +1,15 @@
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[derive(Debug)]
pub struct S;
#[derive(Debug)]
pub struct Z;

View File

@ -0,0 +1,31 @@
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// aux-build:xcrate.rs
#![feature(extern_absolute_paths)]
use xcrate::Z;
fn f() {
use xcrate;
use xcrate as ycrate;
let s = xcrate::S;
assert_eq!(format!("{:?}", s), "S");
let z = ycrate::Z;
assert_eq!(format!("{:?}", z), "Z");
}
fn main() {
let s = ::xcrate::S;
assert_eq!(format!("{:?}", s), "S");
let z = Z;
assert_eq!(format!("{:?}", z), "Z");
}

View File

@ -0,0 +1,15 @@
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use core::default; //~ ERROR unresolved import `core`
fn main() {
let _: u8 = ::core::default::Default(); //~ ERROR failed to resolve
}

View File

@ -0,0 +1,14 @@
error[E0432]: unresolved import `core`
--> $DIR/feature-gate-extern_absolute_paths.rs:11:5
|
11 | use core::default; //~ ERROR unresolved import `core`
| ^^^^ Maybe a missing `extern crate core;`?
error[E0433]: failed to resolve. Maybe a missing `extern crate core;`?
--> $DIR/feature-gate-extern_absolute_paths.rs:14:19
|
14 | let _: u8 = ::core::default::Default(); //~ ERROR failed to resolve
| ^^^^ Maybe a missing `extern crate core;`?
error: aborting due to 2 previous errors