From 6a5014329aecf73da81943216729ab64fa255368 Mon Sep 17 00:00:00 2001 From: Edwin Cheng Date: Tue, 28 Apr 2020 01:48:55 +0800 Subject: Use core instead of std for builtin derive macros --- crates/ra_hir_expand/src/builtin_derive.rs | 93 ++++++++++++++++++++---------- crates/ra_hir_ty/src/tests/macros.rs | 8 +-- 2 files changed, 65 insertions(+), 36 deletions(-) (limited to 'crates') diff --git a/crates/ra_hir_expand/src/builtin_derive.rs b/crates/ra_hir_expand/src/builtin_derive.rs index bb45b0f1d..dae623dd0 100644 --- a/crates/ra_hir_expand/src/builtin_derive.rs +++ b/crates/ra_hir_expand/src/builtin_derive.rs @@ -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,105 @@ 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 crates = db.relevant_crates(file_id); + let mut crate_names = + crates.iter().filter_map(|krate| cg[*krate].display_name.clone()).map(|it| it.to_string()); + + let tt = if crate_names.any(|name| name == "std" || name == "core") { + quote! { krate } + } else { + quote! { core } + }; + + tt.token_trees[0].clone() +} + fn copy_expand( - _db: &dyn AstDatabase, - _id: LazyMacroId, + db: &dyn AstDatabase, + id: LazyMacroId, tt: &tt::Subtree, ) -> Result { - 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 { - 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 { - 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 { - 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 { - 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 { - 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 { - 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 { - 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 { - 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)] @@ -264,7 +293,7 @@ mod tests { known::Copy, ); - assert_eq!(expanded, "impl< >std::marker::CopyforFoo< >{}"); + assert_eq!(expanded, "impl< >core::marker::CopyforFoo< >{}"); } #[test] @@ -279,7 +308,7 @@ mod tests { assert_eq!( expanded, - "implstd::marker::CopyforFoo{}" + "implcore::marker::CopyforFoo{}" ); } @@ -297,7 +326,7 @@ mod tests { assert_eq!( expanded, - "implstd::marker::CopyforFoo{}" + "implcore::marker::CopyforFoo{}" ); } @@ -313,7 +342,7 @@ mod tests { assert_eq!( expanded, - "implstd::clone::CloneforFoo{}" + "implcore::clone::CloneforFoo{}" ); } } diff --git a/crates/ra_hir_ty/src/tests/macros.rs b/crates/ra_hir_ty/src/tests/macros.rs index 6b5267232..4f82ff702 100644 --- a/crates/ra_hir_ty/src/tests/macros.rs +++ b/crates/ra_hir_ty/src/tests/macros.rs @@ -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 { @@ -646,7 +646,7 @@ mod clone { 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 +656,7 @@ fn test() { (Wrapper(S).clone(), Wrapper(NonClone).clone())<|>; } -//- /lib.rs crate:std +//- /lib.rs crate:core #[prelude_import] use clone::*; mod clone { -- cgit v1.2.3 From 213d208e2d61576e104a9d5e003efc4ad1abc469 Mon Sep 17 00:00:00 2001 From: Edwin Cheng Date: Tue, 28 Apr 2020 02:10:17 +0800 Subject: Add test --- crates/ra_hir_expand/src/builtin_derive.rs | 2 +- crates/ra_hir_ty/src/tests/macros.rs | 26 ++++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) (limited to 'crates') diff --git a/crates/ra_hir_expand/src/builtin_derive.rs b/crates/ra_hir_expand/src/builtin_derive.rs index dae623dd0..cc8c45347 100644 --- a/crates/ra_hir_expand/src/builtin_derive.rs +++ b/crates/ra_hir_expand/src/builtin_derive.rs @@ -165,7 +165,7 @@ fn find_builtin_crate(db: &dyn AstDatabase, id: LazyMacroId) -> tt::TokenTree { crates.iter().filter_map(|krate| cg[*krate].display_name.clone()).map(|it| it.to_string()); let tt = if crate_names.any(|name| name == "std" || name == "core") { - quote! { krate } + quote! { crate } } else { quote! { core } }; diff --git a/crates/ra_hir_ty/src/tests/macros.rs b/crates/ra_hir_ty/src/tests/macros.rs index 4f82ff702..ac5485bc9 100644 --- a/crates/ra_hir_ty/src/tests/macros.rs +++ b/crates/ra_hir_ty/src/tests/macros.rs @@ -642,6 +642,32 @@ mod clone { assert_eq!("S", type_at_pos(&db, pos)); } +#[test] +fn infer_derive_clone_in_core() { + let (db, pos) = TestDB::with_position( + r#" +//- /main.rs crate:main deps:core +use core::S; +fn test() { + S.clone()<|>; +} + +//- /lib.rs crate:core +#[prelude_import] +use clone::*; +mod clone { + trait Clone { + fn clone(&self) -> Self; + } +} +#[derive(Clone)] +pub struct S; + +"#, + ); + assert_eq!("S", type_at_pos(&db, pos)); +} + #[test] fn infer_derive_clone_with_params() { let (db, pos) = TestDB::with_position( -- cgit v1.2.3 From 6d3b0af900e6cefb507939b311672b7795703461 Mon Sep 17 00:00:00 2001 From: Edwin Cheng Date: Tue, 28 Apr 2020 03:32:47 +0800 Subject: Use empty-deps tricks to detect it is core --- crates/ra_hir_expand/src/builtin_derive.rs | 26 +++++++++++++++++++++----- crates/ra_hir_ty/src/tests/macros.rs | 11 +++++------ 2 files changed, 26 insertions(+), 11 deletions(-) (limited to 'crates') diff --git a/crates/ra_hir_expand/src/builtin_derive.rs b/crates/ra_hir_expand/src/builtin_derive.rs index cc8c45347..3bd3f7041 100644 --- a/crates/ra_hir_expand/src/builtin_derive.rs +++ b/crates/ra_hir_expand/src/builtin_derive.rs @@ -160,11 +160,17 @@ fn find_builtin_crate(db: &dyn AstDatabase, id: LazyMacroId) -> tt::TokenTree { let m: MacroCallId = id.into(); let file_id = m.as_file().original_file(db); let cg = db.crate_graph(); - let crates = db.relevant_crates(file_id); - let mut crate_names = - crates.iter().filter_map(|krate| cg[*krate].display_name.clone()).map(|it| it.to_string()); + 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(); + } + }; - let tt = if crate_names.any(|name| name == "std" || name == "core") { + // Check whether it has any deps, if not, it should be core: + let tt = if cg[*krate].dependencies.is_empty() { quote! { crate } } else { quote! { core } @@ -263,8 +269,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(); diff --git a/crates/ra_hir_ty/src/tests/macros.rs b/crates/ra_hir_ty/src/tests/macros.rs index ac5485bc9..5ddecbdc6 100644 --- a/crates/ra_hir_ty/src/tests/macros.rs +++ b/crates/ra_hir_ty/src/tests/macros.rs @@ -646,12 +646,6 @@ mod clone { fn infer_derive_clone_in_core() { let (db, pos) = TestDB::with_position( r#" -//- /main.rs crate:main deps:core -use core::S; -fn test() { - S.clone()<|>; -} - //- /lib.rs crate:core #[prelude_import] use clone::*; @@ -663,6 +657,11 @@ mod clone { #[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)); -- cgit v1.2.3 From c69f9c1b0a849b2cf5349e707508358e42bc8bb5 Mon Sep 17 00:00:00 2001 From: Edwin Cheng Date: Tue, 28 Apr 2020 04:11:24 +0800 Subject: Check dep name to detect it is core --- crates/ra_hir_expand/src/builtin_derive.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'crates') diff --git a/crates/ra_hir_expand/src/builtin_derive.rs b/crates/ra_hir_expand/src/builtin_derive.rs index 3bd3f7041..e60f879a3 100644 --- a/crates/ra_hir_expand/src/builtin_derive.rs +++ b/crates/ra_hir_expand/src/builtin_derive.rs @@ -169,11 +169,13 @@ fn find_builtin_crate(db: &dyn AstDatabase, id: LazyMacroId) -> tt::TokenTree { } }; - // Check whether it has any deps, if not, it should be core: - let tt = if cg[*krate].dependencies.is_empty() { - quote! { crate } - } else { + // 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() -- cgit v1.2.3