4173: Use core instead of std for builtin derive macros r=edwin0cheng a=edwin0cheng

Fixed #4087.

We can't use `$crate` here right now because : 

1. We have to able to detect `macro` 2.0 in collecting phase for finding `rustc_builtin_macro` attrs.
2. And we have to make hygiene works for builtin derive macro.

r= @flodiebold 

Co-authored-by: Edwin Cheng <edwin0cheng@gmail.com>
This commit is contained in:
bors[bot] 2020-04-27 20:12:27 +00:00 committed by GitHub
commit da1f316b02
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 109 additions and 37 deletions

View File

@ -9,7 +9,7 @@ use ra_syntax::{
};
use crate::db::AstDatabase;
use crate::{name, quote, LazyMacroId, MacroDefId, MacroDefKind};
use crate::{name, quote, LazyMacroId, MacroCallId, MacroDefId, MacroDefKind};
macro_rules! register_builtin {
( $($trait:ident => $expand:ident),* ) => {
@ -153,76 +153,113 @@ fn expand_simple_derive(
Ok(expanded)
}
fn find_builtin_crate(db: &dyn AstDatabase, id: LazyMacroId) -> tt::TokenTree {
// FIXME: make hygiene works for builtin derive macro
// such that $crate can be used here.
let m: MacroCallId = id.into();
let file_id = m.as_file().original_file(db);
let cg = db.crate_graph();
let krates = db.relevant_crates(file_id);
let krate = match krates.get(0) {
Some(krate) => krate,
None => {
let tt = quote! { core };
return tt.token_trees[0].clone();
}
};
// XXX
// All crates except core itself should have a dependency on core,
// We detect `core` by seeing whether it doesn't have such a dependency.
let tt = if cg[*krate].dependencies.iter().any(|dep| dep.name == "core") {
quote! { core }
} else {
quote! { crate }
};
tt.token_trees[0].clone()
}
fn copy_expand(
_db: &dyn AstDatabase,
_id: LazyMacroId,
db: &dyn AstDatabase,
id: LazyMacroId,
tt: &tt::Subtree,
) -> Result<tt::Subtree, mbe::ExpandError> {
expand_simple_derive(tt, quote! { std::marker::Copy })
let krate = find_builtin_crate(db, id);
expand_simple_derive(tt, quote! { #krate::marker::Copy })
}
fn clone_expand(
_db: &dyn AstDatabase,
_id: LazyMacroId,
db: &dyn AstDatabase,
id: LazyMacroId,
tt: &tt::Subtree,
) -> Result<tt::Subtree, mbe::ExpandError> {
expand_simple_derive(tt, quote! { std::clone::Clone })
let krate = find_builtin_crate(db, id);
expand_simple_derive(tt, quote! { #krate::clone::Clone })
}
fn default_expand(
_db: &dyn AstDatabase,
_id: LazyMacroId,
db: &dyn AstDatabase,
id: LazyMacroId,
tt: &tt::Subtree,
) -> Result<tt::Subtree, mbe::ExpandError> {
expand_simple_derive(tt, quote! { std::default::Default })
let krate = find_builtin_crate(db, id);
expand_simple_derive(tt, quote! { #krate::default::Default })
}
fn debug_expand(
_db: &dyn AstDatabase,
_id: LazyMacroId,
db: &dyn AstDatabase,
id: LazyMacroId,
tt: &tt::Subtree,
) -> Result<tt::Subtree, mbe::ExpandError> {
expand_simple_derive(tt, quote! { std::fmt::Debug })
let krate = find_builtin_crate(db, id);
expand_simple_derive(tt, quote! { #krate::fmt::Debug })
}
fn hash_expand(
_db: &dyn AstDatabase,
_id: LazyMacroId,
db: &dyn AstDatabase,
id: LazyMacroId,
tt: &tt::Subtree,
) -> Result<tt::Subtree, mbe::ExpandError> {
expand_simple_derive(tt, quote! { std::hash::Hash })
let krate = find_builtin_crate(db, id);
expand_simple_derive(tt, quote! { #krate::hash::Hash })
}
fn eq_expand(
_db: &dyn AstDatabase,
_id: LazyMacroId,
db: &dyn AstDatabase,
id: LazyMacroId,
tt: &tt::Subtree,
) -> Result<tt::Subtree, mbe::ExpandError> {
expand_simple_derive(tt, quote! { std::cmp::Eq })
let krate = find_builtin_crate(db, id);
expand_simple_derive(tt, quote! { #krate::cmp::Eq })
}
fn partial_eq_expand(
_db: &dyn AstDatabase,
_id: LazyMacroId,
db: &dyn AstDatabase,
id: LazyMacroId,
tt: &tt::Subtree,
) -> Result<tt::Subtree, mbe::ExpandError> {
expand_simple_derive(tt, quote! { std::cmp::PartialEq })
let krate = find_builtin_crate(db, id);
expand_simple_derive(tt, quote! { #krate::cmp::PartialEq })
}
fn ord_expand(
_db: &dyn AstDatabase,
_id: LazyMacroId,
db: &dyn AstDatabase,
id: LazyMacroId,
tt: &tt::Subtree,
) -> Result<tt::Subtree, mbe::ExpandError> {
expand_simple_derive(tt, quote! { std::cmp::Ord })
let krate = find_builtin_crate(db, id);
expand_simple_derive(tt, quote! { #krate::cmp::Ord })
}
fn partial_ord_expand(
_db: &dyn AstDatabase,
_id: LazyMacroId,
db: &dyn AstDatabase,
id: LazyMacroId,
tt: &tt::Subtree,
) -> Result<tt::Subtree, mbe::ExpandError> {
expand_simple_derive(tt, quote! { std::cmp::PartialOrd })
let krate = find_builtin_crate(db, id);
expand_simple_derive(tt, quote! { #krate::cmp::PartialOrd })
}
#[cfg(test)]
@ -234,8 +271,18 @@ mod tests {
fn expand_builtin_derive(s: &str, name: Name) -> String {
let def = find_builtin_derive(&name).unwrap();
let fixture = format!(
r#"//- /main.rs crate:main deps:core
<|>
{}
//- /lib.rs crate:core
// empty
"#,
s
);
let (db, file_id) = TestDB::with_single_file(&s);
let (db, file_pos) = TestDB::with_position(&fixture);
let file_id = file_pos.file_id;
let parsed = db.parse(file_id);
let items: Vec<_> =
parsed.syntax_node().descendants().filter_map(ast::ModuleItem::cast).collect();
@ -264,7 +311,7 @@ mod tests {
known::Copy,
);
assert_eq!(expanded, "impl< >std::marker::CopyforFoo< >{}");
assert_eq!(expanded, "impl< >core::marker::CopyforFoo< >{}");
}
#[test]
@ -279,7 +326,7 @@ mod tests {
assert_eq!(
expanded,
"impl<T0:std::marker::Copy,T1:std::marker::Copy>std::marker::CopyforFoo<T0,T1>{}"
"impl<T0:core::marker::Copy,T1:core::marker::Copy>core::marker::CopyforFoo<T0,T1>{}"
);
}
@ -297,7 +344,7 @@ mod tests {
assert_eq!(
expanded,
"impl<T0:std::marker::Copy,T1:std::marker::Copy>std::marker::CopyforFoo<T0,T1>{}"
"impl<T0:core::marker::Copy,T1:core::marker::Copy>core::marker::CopyforFoo<T0,T1>{}"
);
}
@ -313,7 +360,7 @@ mod tests {
assert_eq!(
expanded,
"impl<T0:std::clone::Clone,T1:std::clone::Clone>std::clone::CloneforFoo<T0,T1>{}"
"impl<T0:core::clone::Clone,T1:core::clone::Clone>core::clone::CloneforFoo<T0,T1>{}"
);
}
}

View File

@ -622,14 +622,14 @@ fn main() {
fn infer_derive_clone_simple() {
let (db, pos) = TestDB::with_position(
r#"
//- /main.rs crate:main deps:std
//- /main.rs crate:main deps:core
#[derive(Clone)]
struct S;
fn test() {
S.clone()<|>;
}
//- /lib.rs crate:std
//- /lib.rs crate:core
#[prelude_import]
use clone::*;
mod clone {
@ -642,11 +642,36 @@ mod clone {
assert_eq!("S", type_at_pos(&db, pos));
}
#[test]
fn infer_derive_clone_in_core() {
let (db, pos) = TestDB::with_position(
r#"
//- /lib.rs crate:core
#[prelude_import]
use clone::*;
mod clone {
trait Clone {
fn clone(&self) -> Self;
}
}
#[derive(Clone)]
pub struct S;
//- /main.rs crate:main deps:core
use core::S;
fn test() {
S.clone()<|>;
}
"#,
);
assert_eq!("S", type_at_pos(&db, pos));
}
#[test]
fn infer_derive_clone_with_params() {
let (db, pos) = TestDB::with_position(
r#"
//- /main.rs crate:main deps:std
//- /main.rs crate:main deps:core
#[derive(Clone)]
struct S;
#[derive(Clone)]
@ -656,7 +681,7 @@ fn test() {
(Wrapper(S).clone(), Wrapper(NonClone).clone())<|>;
}
//- /lib.rs crate:std
//- /lib.rs crate:core
#[prelude_import]
use clone::*;
mod clone {