Skip to content

Commit

Permalink
Merge #816
Browse files Browse the repository at this point in the history
816: Prelude & Edition 2015 import resolution r=matklad a=flodiebold

I implemented the prelude import, but it turned out to be useless without being able to resolve any of the imports in the prelude 😅 So I had to add some edition handling and handle 2015-style imports (at least the simplified scheme proposed in rust-lang/rust#57745). So now finally `Option` resolves 😄 

One remaining problem is that we don't actually know the edition for sysroot crates. They're currently hardcoded to 2015, but there's already a bunch of PRs upgrading the editions of various rustc crates, so we'll have to detect the edition somehow, or just change the hardcoding to 2018 later, I guess...

~Also currently missing is completion for prelude names, though that shouldn't be hard to add. And `Vec` still doesn't resolve, so I need to look into that.~

Co-authored-by: Florian Diebold <flodiebold@gmail.com>
  • Loading branch information
bors[bot] and flodiebold committed Feb 13, 2019
2 parents 65266c6 + e99034d commit f94e112
Show file tree
Hide file tree
Showing 18 changed files with 403 additions and 60 deletions.
44 changes: 32 additions & 12 deletions crates/ra_db/src/input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,15 +56,31 @@ pub struct CyclicDependencies;
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct CrateId(pub u32);

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Edition {
Edition2018,
Edition2015,
}

impl Edition {
pub fn from_string(s: &str) -> Edition {
match s {
"2015" => Edition::Edition2015,
"2018" | _ => Edition::Edition2018,
}
}
}

#[derive(Debug, Clone, PartialEq, Eq)]
struct CrateData {
file_id: FileId,
edition: Edition,
dependencies: Vec<Dependency>,
}

impl CrateData {
fn new(file_id: FileId) -> CrateData {
CrateData { file_id, dependencies: Vec::new() }
fn new(file_id: FileId, edition: Edition) -> CrateData {
CrateData { file_id, edition, dependencies: Vec::new() }
}

fn add_dep(&mut self, name: SmolStr, crate_id: CrateId) {
Expand All @@ -85,9 +101,9 @@ impl Dependency {
}

impl CrateGraph {
pub fn add_crate_root(&mut self, file_id: FileId) -> CrateId {
pub fn add_crate_root(&mut self, file_id: FileId, edition: Edition) -> CrateId {
let crate_id = CrateId(self.arena.len() as u32);
let prev = self.arena.insert(crate_id, CrateData::new(file_id));
let prev = self.arena.insert(crate_id, CrateData::new(file_id, edition));
assert!(prev.is_none());
crate_id
}
Expand All @@ -112,6 +128,10 @@ impl CrateGraph {
self.arena[&crate_id].file_id
}

pub fn edition(&self, crate_id: CrateId) -> Edition {
self.arena[&crate_id].edition
}

// TODO: this only finds one crate with the given root; we could have multiple
pub fn crate_id_for_crate_root(&self, file_id: FileId) -> Option<CrateId> {
let (&crate_id, _) = self.arena.iter().find(|(_crate_id, data)| data.file_id == file_id)?;
Expand Down Expand Up @@ -159,14 +179,14 @@ impl CrateGraph {

#[cfg(test)]
mod tests {
use super::{CrateGraph, FileId, SmolStr};
use super::{CrateGraph, FileId, SmolStr, Edition::Edition2018};

#[test]
fn it_should_painc_because_of_cycle_dependencies() {
fn it_should_panic_because_of_cycle_dependencies() {
let mut graph = CrateGraph::default();
let crate1 = graph.add_crate_root(FileId(1u32));
let crate2 = graph.add_crate_root(FileId(2u32));
let crate3 = graph.add_crate_root(FileId(3u32));
let crate1 = graph.add_crate_root(FileId(1u32), Edition2018);
let crate2 = graph.add_crate_root(FileId(2u32), Edition2018);
let crate3 = graph.add_crate_root(FileId(3u32), Edition2018);
assert!(graph.add_dep(crate1, SmolStr::new("crate2"), crate2).is_ok());
assert!(graph.add_dep(crate2, SmolStr::new("crate3"), crate3).is_ok());
assert!(graph.add_dep(crate3, SmolStr::new("crate1"), crate1).is_err());
Expand All @@ -175,9 +195,9 @@ mod tests {
#[test]
fn it_works() {
let mut graph = CrateGraph::default();
let crate1 = graph.add_crate_root(FileId(1u32));
let crate2 = graph.add_crate_root(FileId(2u32));
let crate3 = graph.add_crate_root(FileId(3u32));
let crate1 = graph.add_crate_root(FileId(1u32), Edition2018);
let crate2 = graph.add_crate_root(FileId(2u32), Edition2018);
let crate3 = graph.add_crate_root(FileId(3u32), Edition2018);
assert!(graph.add_dep(crate1, SmolStr::new("crate2"), crate2).is_ok());
assert!(graph.add_dep(crate2, SmolStr::new("crate3"), crate3).is_ok());
}
Expand Down
2 changes: 1 addition & 1 deletion crates/ra_db/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ pub use ::salsa as salsa;
pub use crate::{
cancellation::Canceled,
input::{
FileId, CrateId, SourceRoot, SourceRootId, CrateGraph, Dependency,
FileId, CrateId, SourceRoot, SourceRootId, CrateGraph, Dependency, Edition,
},
loc2id::LocationIntener,
};
Expand Down
9 changes: 8 additions & 1 deletion crates/ra_hir/src/code_model_api.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::sync::Arc;

use relative_path::RelativePathBuf;
use ra_db::{CrateId, FileId, SourceRootId};
use ra_db::{CrateId, FileId, SourceRootId, Edition};
use ra_syntax::{ast::self, TreeArc, SyntaxNode};

use crate::{
Expand Down Expand Up @@ -38,13 +38,20 @@ impl Crate {
pub fn crate_id(&self) -> CrateId {
self.crate_id
}

pub fn dependencies(&self, db: &impl PersistentHirDatabase) -> Vec<CrateDependency> {
self.dependencies_impl(db)
}

pub fn root_module(&self, db: &impl PersistentHirDatabase) -> Option<Module> {
self.root_module_impl(db)
}

pub fn edition(&self, db: &impl PersistentHirDatabase) -> Edition {
let crate_graph = db.crate_graph();
crate_graph.edition(self.crate_id)
}

// TODO: should this be in source_binder?
pub fn source_root_crates(
db: &impl PersistentHirDatabase,
Expand Down
1 change: 1 addition & 0 deletions crates/ra_hir/src/marks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ test_utils::marks!(
type_var_resolves_to_int_var
glob_enum
glob_across_crates
std_prelude
);
18 changes: 11 additions & 7 deletions crates/ra_hir/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use std::{sync::Arc, panic};
use parking_lot::Mutex;
use ra_db::{
FilePosition, FileId, CrateGraph, SourceRoot, SourceRootId, SourceDatabase, salsa,
Edition,
};
use relative_path::RelativePathBuf;
use test_utils::{parse_fixture, CURSOR_MARKER, extract_offset};
Expand Down Expand Up @@ -58,12 +59,12 @@ impl MockDatabase {
pub fn set_crate_graph_from_fixture(&mut self, graph: CrateGraphFixture) {
let mut ids = FxHashMap::default();
let mut crate_graph = CrateGraph::default();
for (crate_name, (crate_root, _)) in graph.0.iter() {
for (crate_name, (crate_root, edition, _)) in graph.0.iter() {
let crate_root = self.file_id_of(&crate_root);
let crate_id = crate_graph.add_crate_root(crate_root);
let crate_id = crate_graph.add_crate_root(crate_root, *edition);
ids.insert(crate_name, crate_id);
}
for (crate_name, (_, deps)) in graph.0.iter() {
for (crate_name, (_, _, deps)) in graph.0.iter() {
let from = ids[crate_name];
for dep in deps {
let to = ids[dep];
Expand Down Expand Up @@ -144,7 +145,7 @@ impl MockDatabase {

if is_crate_root {
let mut crate_graph = CrateGraph::default();
crate_graph.add_crate_root(file_id);
crate_graph.add_crate_root(file_id, Edition::Edition2018);
self.set_crate_graph(Arc::new(crate_graph));
}
file_id
Expand Down Expand Up @@ -232,16 +233,19 @@ impl MockDatabase {
}

#[derive(Default)]
pub struct CrateGraphFixture(pub FxHashMap<String, (String, Vec<String>)>);
pub struct CrateGraphFixture(pub FxHashMap<String, (String, Edition, Vec<String>)>);

#[macro_export]
macro_rules! crate_graph {
($($crate_name:literal: ($crate_path:literal, [$($dep:literal),*]),)*) => {{
($($crate_name:literal: ($crate_path:literal, $($edition:literal,)? [$($dep:literal),*]),)*) => {{
let mut res = $crate::mock::CrateGraphFixture::default();
$(
#[allow(unused_mut, unused_assignments)]
let mut edition = ra_db::Edition::Edition2018;
$(edition = ra_db::Edition::from_string($edition);)?
res.0.insert(
$crate_name.to_string(),
($crate_path.to_string(), vec![$($dep.to_string()),*])
($crate_path.to_string(), edition, vec![$($dep.to_string()),*])
);
)*
res
Expand Down
Loading

0 comments on commit f94e112

Please sign in to comment.