4137: Prefer core/alloc paths on #![no_std] r=matklad a=jonas-schievink



Co-authored-by: Jonas Schievink <jonasschievink@gmail.com>
This commit is contained in:
bors[bot] 2020-04-25 16:19:21 +00:00 committed by GitHub
commit 67afeebaf5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 87 additions and 14 deletions

View File

@ -13,7 +13,8 @@ use ra_syntax::{
use tt::Subtree; use tt::Subtree;
use crate::{ use crate::{
db::DefDatabase, path::ModPath, src::HasChildSource, src::HasSource, AdtId, AttrDefId, Lookup, db::DefDatabase, nameres::ModuleSource, path::ModPath, src::HasChildSource, src::HasSource,
AdtId, AttrDefId, Lookup,
}; };
#[derive(Default, Debug, Clone, PartialEq, Eq)] #[derive(Default, Debug, Clone, PartialEq, Eq)]
@ -37,11 +38,19 @@ impl Attrs {
match def { match def {
AttrDefId::ModuleId(module) => { AttrDefId::ModuleId(module) => {
let def_map = db.crate_def_map(module.krate); let def_map = db.crate_def_map(module.krate);
let src = match def_map[module.local_id].declaration_source(db) { let mod_data = &def_map[module.local_id];
Some(it) => it, match mod_data.declaration_source(db) {
None => return Attrs::default(), Some(it) => {
}; Attrs::from_attrs_owner(db, it.as_ref().map(|it| it as &dyn AttrsOwner))
Attrs::from_attrs_owner(db, src.as_ref().map(|it| it as &dyn AttrsOwner)) }
None => Attrs::from_attrs_owner(
db,
mod_data.definition_source(db).as_ref().map(|src| match src {
ModuleSource::SourceFile(file) => file as &dyn AttrsOwner,
ModuleSource::Module(module) => module as &dyn AttrsOwner,
}),
),
}
} }
AttrDefId::FieldId(it) => { AttrDefId::FieldId(it) => {
let src = it.parent.child_source(db); let src = it.parent.child_source(db);
@ -106,7 +115,9 @@ pub struct Attr {
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq)]
pub enum AttrInput { pub enum AttrInput {
/// `#[attr = "string"]`
Literal(SmolStr), Literal(SmolStr),
/// `#[attr(subtree)]`
TokenTree(Subtree), TokenTree(Subtree),
} }

View File

@ -19,7 +19,7 @@ impl ModPath {
// When std library is present, paths starting with `std::` // When std library is present, paths starting with `std::`
// should be preferred over paths starting with `core::` and `alloc::` // should be preferred over paths starting with `core::` and `alloc::`
fn should_start_with_std(&self) -> bool { fn can_start_with_std(&self) -> bool {
self.segments self.segments
.first() .first()
.filter(|&first_segment| { .filter(|&first_segment| {
@ -132,6 +132,9 @@ fn find_path_inner(
} }
// - otherwise, look for modules containing (reexporting) it and import it from one of those // - otherwise, look for modules containing (reexporting) it and import it from one of those
let crate_root = ModuleId { local_id: def_map.root, krate: from.krate };
let crate_attrs = db.attrs(crate_root.into());
let prefer_no_std = crate_attrs.by_key("no_std").exists();
let importable_locations = find_importable_locations(db, item, from); let importable_locations = find_importable_locations(db, item, from);
let mut best_path = None; let mut best_path = None;
let mut best_path_len = max_len; let mut best_path_len = max_len;
@ -147,21 +150,32 @@ fn find_path_inner(
}; };
path.segments.push(name); path.segments.push(name);
let new_path = let new_path = if let Some(best_path) = best_path {
if let Some(best_path) = best_path { select_best_path(best_path, path) } else { path }; select_best_path(best_path, path, prefer_no_std)
} else {
path
};
best_path_len = new_path.len(); best_path_len = new_path.len();
best_path = Some(new_path); best_path = Some(new_path);
} }
best_path best_path
} }
fn select_best_path(old_path: ModPath, new_path: ModPath) -> ModPath { fn select_best_path(old_path: ModPath, new_path: ModPath, prefer_no_std: bool) -> ModPath {
if old_path.starts_with_std() && new_path.should_start_with_std() { if old_path.starts_with_std() && new_path.can_start_with_std() {
tested_by!(prefer_std_paths); tested_by!(prefer_std_paths);
old_path if prefer_no_std {
} else if new_path.starts_with_std() && old_path.should_start_with_std() { new_path
} else {
old_path
}
} else if new_path.starts_with_std() && old_path.can_start_with_std() {
tested_by!(prefer_std_paths); tested_by!(prefer_std_paths);
new_path if prefer_no_std {
old_path
} else {
new_path
}
} else if new_path.len() < old_path.len() { } else if new_path.len() < old_path.len() {
new_path new_path
} else { } else {
@ -512,6 +526,54 @@ mod tests {
check_found_path(code, "std::sync::Arc"); check_found_path(code, "std::sync::Arc");
} }
#[test]
fn prefer_alloc_paths_over_std() {
covers!(prefer_std_paths);
let code = r#"
//- /main.rs crate:main deps:alloc,std
#![no_std]
<|>
//- /std.rs crate:std deps:alloc
pub mod sync {
pub use alloc::sync::Arc;
}
//- /zzz.rs crate:alloc
pub mod sync {
pub struct Arc;
}
"#;
check_found_path(code, "alloc::sync::Arc");
}
#[test]
fn prefer_core_paths_over_std() {
covers!(prefer_std_paths);
let code = r#"
//- /main.rs crate:main deps:core,std
#![no_std]
<|>
//- /std.rs crate:std deps:core
pub mod fmt {
pub use core::fmt::Error;
}
//- /zzz.rs crate:core
pub mod fmt {
pub struct Error;
}
"#;
check_found_path(code, "core::fmt::Error");
}
#[test] #[test]
fn prefer_shorter_paths_if_not_alloc() { fn prefer_shorter_paths_if_not_alloc() {
let code = r#" let code = r#"