mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-28 11:20:54 +00:00
Check for derive attributes by item path, not derive
identifier
This commit is contained in:
parent
32f425d801
commit
91bbc55eed
@ -8,7 +8,7 @@ use either::Either;
|
|||||||
use hir_expand::{hygiene::Hygiene, name::AsName, AstId, InFile};
|
use hir_expand::{hygiene::Hygiene, name::AsName, AstId, InFile};
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use la_arena::ArenaMap;
|
use la_arena::ArenaMap;
|
||||||
use mbe::{syntax_node_to_token_tree, DelimiterKind};
|
use mbe::{syntax_node_to_token_tree, DelimiterKind, Punct};
|
||||||
use smallvec::{smallvec, SmallVec};
|
use smallvec::{smallvec, SmallVec};
|
||||||
use syntax::{
|
use syntax::{
|
||||||
ast::{self, AstNode, HasAttrs, IsString},
|
ast::{self, AstNode, HasAttrs, IsString},
|
||||||
@ -722,41 +722,35 @@ impl Attr {
|
|||||||
/// Parses this attribute as a `#[derive]`, returns an iterator that yields all contained paths
|
/// Parses this attribute as a `#[derive]`, returns an iterator that yields all contained paths
|
||||||
/// to derive macros.
|
/// to derive macros.
|
||||||
///
|
///
|
||||||
/// Returns `None` when the attribute is not a well-formed `#[derive]` attribute.
|
/// Returns `None` when the attribute does not have a well-formed `#[derive]` attribute input.
|
||||||
pub(crate) fn parse_derive(&self) -> Option<impl Iterator<Item = ModPath>> {
|
pub(crate) fn parse_derive(&self) -> Option<impl Iterator<Item = ModPath>> {
|
||||||
if self.path.as_ident() != Some(&hir_expand::name![derive]) {
|
if let Some(AttrInput::TokenTree(args, _)) = self.input.as_deref() {
|
||||||
return None;
|
if args.delimiter_kind() != Some(DelimiterKind::Parenthesis) {
|
||||||
}
|
return None;
|
||||||
|
|
||||||
match self.input.as_deref() {
|
|
||||||
Some(AttrInput::TokenTree(args, _)) => {
|
|
||||||
let mut counter = 0;
|
|
||||||
let paths = args
|
|
||||||
.token_trees
|
|
||||||
.iter()
|
|
||||||
.group_by(move |tt| {
|
|
||||||
match tt {
|
|
||||||
tt::TokenTree::Leaf(tt::Leaf::Punct(p)) if p.char == ',' => {
|
|
||||||
counter += 1;
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
counter
|
|
||||||
})
|
|
||||||
.into_iter()
|
|
||||||
.map(|(_, tts)| {
|
|
||||||
let segments = tts.filter_map(|tt| match tt {
|
|
||||||
tt::TokenTree::Leaf(tt::Leaf::Ident(id)) => Some(id.as_name()),
|
|
||||||
_ => None,
|
|
||||||
});
|
|
||||||
ModPath::from_segments(PathKind::Plain, segments)
|
|
||||||
})
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
|
|
||||||
Some(paths.into_iter())
|
|
||||||
}
|
}
|
||||||
_ => None,
|
let mut counter = 0;
|
||||||
|
let paths = args
|
||||||
|
.token_trees
|
||||||
|
.iter()
|
||||||
|
.group_by(move |tt| {
|
||||||
|
if let tt::TokenTree::Leaf(tt::Leaf::Punct(Punct { char: ',', .. })) = tt {
|
||||||
|
counter += 1;
|
||||||
|
}
|
||||||
|
counter
|
||||||
|
})
|
||||||
|
.into_iter()
|
||||||
|
.map(|(_, tts)| {
|
||||||
|
let segments = tts.filter_map(|tt| match tt {
|
||||||
|
tt::TokenTree::Leaf(tt::Leaf::Ident(id)) => Some(id.as_name()),
|
||||||
|
_ => None,
|
||||||
|
});
|
||||||
|
ModPath::from_segments(PathKind::Plain, segments)
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
return Some(paths.into_iter());
|
||||||
}
|
}
|
||||||
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn string_value(&self) -> Option<&SmolStr> {
|
pub fn string_value(&self) -> Option<&SmolStr> {
|
||||||
|
@ -26,12 +26,16 @@ fn test_copy_expand_in_core() {
|
|||||||
check(
|
check(
|
||||||
r#"
|
r#"
|
||||||
#[rustc_builtin_macro]
|
#[rustc_builtin_macro]
|
||||||
|
macro derive {}
|
||||||
|
#[rustc_builtin_macro]
|
||||||
macro Copy {}
|
macro Copy {}
|
||||||
#[derive(Copy)]
|
#[derive(Copy)]
|
||||||
struct Foo;
|
struct Foo;
|
||||||
"#,
|
"#,
|
||||||
expect![[r##"
|
expect![[r##"
|
||||||
#[rustc_builtin_macro]
|
#[rustc_builtin_macro]
|
||||||
|
macro derive {}
|
||||||
|
#[rustc_builtin_macro]
|
||||||
macro Copy {}
|
macro Copy {}
|
||||||
#[derive(Copy)]
|
#[derive(Copy)]
|
||||||
struct Foo;
|
struct Foo;
|
||||||
|
@ -31,6 +31,7 @@ fn derive_censoring() {
|
|||||||
check(
|
check(
|
||||||
r#"
|
r#"
|
||||||
//- proc_macros: derive_identity
|
//- proc_macros: derive_identity
|
||||||
|
//- minicore:derive
|
||||||
#[attr1]
|
#[attr1]
|
||||||
#[derive(Foo)]
|
#[derive(Foo)]
|
||||||
#[derive(proc_macros::DeriveIdentity)]
|
#[derive(proc_macros::DeriveIdentity)]
|
||||||
|
@ -9,7 +9,7 @@ use base_db::{CrateId, Edition, FileId, ProcMacroId};
|
|||||||
use cfg::{CfgExpr, CfgOptions};
|
use cfg::{CfgExpr, CfgOptions};
|
||||||
use hir_expand::{
|
use hir_expand::{
|
||||||
ast_id_map::FileAstId,
|
ast_id_map::FileAstId,
|
||||||
builtin_attr_macro::{find_builtin_attr, is_builtin_test_or_bench_attr},
|
builtin_attr_macro::find_builtin_attr,
|
||||||
builtin_derive_macro::find_builtin_derive,
|
builtin_derive_macro::find_builtin_derive,
|
||||||
builtin_fn_macro::find_builtin_macro,
|
builtin_fn_macro::find_builtin_macro,
|
||||||
name::{name, AsName, Name},
|
name::{name, AsName, Name},
|
||||||
@ -781,7 +781,7 @@ impl DefCollector<'_> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn resolve_extern_crate(&self, name: &Name) -> PerNs {
|
fn resolve_extern_crate(&self, name: &Name) -> PerNs {
|
||||||
if name == &name!(self) {
|
if *name == name!(self) {
|
||||||
cov_mark::hit!(extern_crate_self_as);
|
cov_mark::hit!(extern_crate_self_as);
|
||||||
let root = match self.def_map.block {
|
let root = match self.def_map.block {
|
||||||
Some(_) => {
|
Some(_) => {
|
||||||
@ -1105,7 +1105,7 @@ impl DefCollector<'_> {
|
|||||||
let mod_dir = self.mod_dirs[&directive.module_id].clone();
|
let mod_dir = self.mod_dirs[&directive.module_id].clone();
|
||||||
self.skip_attrs.insert(InFile::new(file_id, *mod_item), attr.id);
|
self.skip_attrs.insert(InFile::new(file_id, *mod_item), attr.id);
|
||||||
ModCollector {
|
ModCollector {
|
||||||
def_collector: &mut *self,
|
def_collector: self,
|
||||||
macro_depth: directive.depth,
|
macro_depth: directive.depth,
|
||||||
module_id: directive.module_id,
|
module_id: directive.module_id,
|
||||||
tree_id: TreeId::new(file_id, None),
|
tree_id: TreeId::new(file_id, None),
|
||||||
@ -1121,6 +1121,65 @@ impl DefCollector<'_> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let def = resolver(ast_id.path.clone()).filter(MacroDefId::is_attribute);
|
||||||
|
if matches!(
|
||||||
|
def,
|
||||||
|
Some(MacroDefId { kind:MacroDefKind::BuiltInAttr(expander, _),.. })
|
||||||
|
if expander.is_derive()
|
||||||
|
) {
|
||||||
|
// Resolved to derive
|
||||||
|
let file_id = ast_id.ast_id.file_id;
|
||||||
|
let item_tree = self.db.file_item_tree(file_id);
|
||||||
|
|
||||||
|
let ast_id: FileAstId<ast::Item> = match *mod_item {
|
||||||
|
ModItem::Struct(it) => item_tree[it].ast_id.upcast(),
|
||||||
|
ModItem::Union(it) => item_tree[it].ast_id.upcast(),
|
||||||
|
ModItem::Enum(it) => item_tree[it].ast_id.upcast(),
|
||||||
|
_ => {
|
||||||
|
// Cannot use derive on this item.
|
||||||
|
// FIXME: diagnose
|
||||||
|
res = ReachedFixedPoint::No;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
match attr.parse_derive() {
|
||||||
|
Some(derive_macros) => {
|
||||||
|
for path in derive_macros {
|
||||||
|
let ast_id = AstIdWithPath::new(file_id, ast_id, path);
|
||||||
|
self.unresolved_macros.push(MacroDirective {
|
||||||
|
module_id: directive.module_id,
|
||||||
|
depth: directive.depth + 1,
|
||||||
|
kind: MacroDirectiveKind::Derive {
|
||||||
|
ast_id,
|
||||||
|
derive_attr: attr.id,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
// FIXME: diagnose
|
||||||
|
tracing::debug!("malformed derive: {:?}", attr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mod_dir = self.mod_dirs[&directive.module_id].clone();
|
||||||
|
self.skip_attrs.insert(InFile::new(file_id, *mod_item), attr.id);
|
||||||
|
ModCollector {
|
||||||
|
def_collector: &mut *self,
|
||||||
|
macro_depth: directive.depth,
|
||||||
|
module_id: directive.module_id,
|
||||||
|
tree_id: TreeId::new(file_id, None),
|
||||||
|
item_tree: &item_tree,
|
||||||
|
mod_dir,
|
||||||
|
}
|
||||||
|
.collect(&[*mod_item]);
|
||||||
|
|
||||||
|
// Remove the original directive since we resolved it.
|
||||||
|
res = ReachedFixedPoint::No;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if !self.db.enable_proc_attr_macros() {
|
if !self.db.enable_proc_attr_macros() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -1138,7 +1197,11 @@ impl DefCollector<'_> {
|
|||||||
|
|
||||||
// Skip #[test]/#[bench] expansion, which would merely result in more memory usage
|
// Skip #[test]/#[bench] expansion, which would merely result in more memory usage
|
||||||
// due to duplicating functions into macro expansions
|
// due to duplicating functions into macro expansions
|
||||||
if is_builtin_test_or_bench_attr(loc.def) {
|
if matches!(
|
||||||
|
loc.def.kind,
|
||||||
|
MacroDefKind::BuiltInAttr(expander, _)
|
||||||
|
if expander.is_test() || expander.is_bench()
|
||||||
|
) {
|
||||||
let file_id = ast_id.ast_id.file_id;
|
let file_id = ast_id.ast_id.file_id;
|
||||||
let item_tree = self.db.file_item_tree(file_id);
|
let item_tree = self.db.file_item_tree(file_id);
|
||||||
let mod_dir = self.mod_dirs[&directive.module_id].clone();
|
let mod_dir = self.mod_dirs[&directive.module_id].clone();
|
||||||
@ -1281,7 +1344,7 @@ impl DefCollector<'_> {
|
|||||||
for directive in &self.unresolved_macros {
|
for directive in &self.unresolved_macros {
|
||||||
match &directive.kind {
|
match &directive.kind {
|
||||||
MacroDirectiveKind::FnLike { ast_id, expand_to } => {
|
MacroDirectiveKind::FnLike { ast_id, expand_to } => {
|
||||||
match macro_call_as_call_id(
|
let macro_call_as_call_id = macro_call_as_call_id(
|
||||||
ast_id,
|
ast_id,
|
||||||
*expand_to,
|
*expand_to,
|
||||||
self.db,
|
self.db,
|
||||||
@ -1297,15 +1360,13 @@ impl DefCollector<'_> {
|
|||||||
resolved_res.resolved_def.take_macros()
|
resolved_res.resolved_def.take_macros()
|
||||||
},
|
},
|
||||||
&mut |_| (),
|
&mut |_| (),
|
||||||
) {
|
);
|
||||||
Ok(_) => (),
|
if let Err(UnresolvedMacro { path }) = macro_call_as_call_id {
|
||||||
Err(UnresolvedMacro { path }) => {
|
self.def_map.diagnostics.push(DefDiagnostic::unresolved_macro_call(
|
||||||
self.def_map.diagnostics.push(DefDiagnostic::unresolved_macro_call(
|
directive.module_id,
|
||||||
directive.module_id,
|
ast_id.ast_id,
|
||||||
ast_id.ast_id,
|
path,
|
||||||
path,
|
));
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
MacroDirectiveKind::Derive { .. } | MacroDirectiveKind::Attr { .. } => {
|
MacroDirectiveKind::Derive { .. } | MacroDirectiveKind::Attr { .. } => {
|
||||||
@ -1747,26 +1808,23 @@ impl ModCollector<'_, '_> {
|
|||||||
});
|
});
|
||||||
|
|
||||||
for attr in iter {
|
for attr in iter {
|
||||||
if attr.path.as_ident() == Some(&hir_expand::name![derive]) {
|
if self.is_builtin_or_registered_attr(&attr.path) {
|
||||||
self.collect_derive(attr, mod_item);
|
|
||||||
} else if self.is_builtin_or_registered_attr(&attr.path) {
|
|
||||||
continue;
|
continue;
|
||||||
} else {
|
|
||||||
tracing::debug!("non-builtin attribute {}", attr.path);
|
|
||||||
|
|
||||||
let ast_id = AstIdWithPath::new(
|
|
||||||
self.file_id(),
|
|
||||||
mod_item.ast_id(self.item_tree),
|
|
||||||
attr.path.as_ref().clone(),
|
|
||||||
);
|
|
||||||
self.def_collector.unresolved_macros.push(MacroDirective {
|
|
||||||
module_id: self.module_id,
|
|
||||||
depth: self.macro_depth + 1,
|
|
||||||
kind: MacroDirectiveKind::Attr { ast_id, attr: attr.clone(), mod_item },
|
|
||||||
});
|
|
||||||
|
|
||||||
return Err(());
|
|
||||||
}
|
}
|
||||||
|
tracing::debug!("non-builtin attribute {}", attr.path);
|
||||||
|
|
||||||
|
let ast_id = AstIdWithPath::new(
|
||||||
|
self.file_id(),
|
||||||
|
mod_item.ast_id(self.item_tree),
|
||||||
|
attr.path.as_ref().clone(),
|
||||||
|
);
|
||||||
|
self.def_collector.unresolved_macros.push(MacroDirective {
|
||||||
|
module_id: self.module_id,
|
||||||
|
depth: self.macro_depth + 1,
|
||||||
|
kind: MacroDirectiveKind::Attr { ast_id, attr: attr.clone(), mod_item },
|
||||||
|
});
|
||||||
|
|
||||||
|
return Err(());
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -1800,36 +1858,6 @@ impl ModCollector<'_, '_> {
|
|||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
fn collect_derive(&mut self, attr: &Attr, mod_item: ModItem) {
|
|
||||||
let ast_id: FileAstId<ast::Item> = match mod_item {
|
|
||||||
ModItem::Struct(it) => self.item_tree[it].ast_id.upcast(),
|
|
||||||
ModItem::Union(it) => self.item_tree[it].ast_id.upcast(),
|
|
||||||
ModItem::Enum(it) => self.item_tree[it].ast_id.upcast(),
|
|
||||||
_ => {
|
|
||||||
// Cannot use derive on this item.
|
|
||||||
// FIXME: diagnose
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
match attr.parse_derive() {
|
|
||||||
Some(derive_macros) => {
|
|
||||||
for path in derive_macros {
|
|
||||||
let ast_id = AstIdWithPath::new(self.file_id(), ast_id, path);
|
|
||||||
self.def_collector.unresolved_macros.push(MacroDirective {
|
|
||||||
module_id: self.module_id,
|
|
||||||
depth: self.macro_depth + 1,
|
|
||||||
kind: MacroDirectiveKind::Derive { ast_id, derive_attr: attr.id },
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
// FIXME: diagnose
|
|
||||||
tracing::debug!("malformed derive: {:?}", attr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// If `attrs` registers a procedural macro, collects its definition.
|
/// If `attrs` registers a procedural macro, collects its definition.
|
||||||
fn collect_proc_macro_def(&mut self, func_name: &Name, ast_id: AstId<ast::Fn>, attrs: &Attrs) {
|
fn collect_proc_macro_def(&mut self, func_name: &Name, ast_id: AstId<ast::Fn>, attrs: &Attrs) {
|
||||||
// FIXME: this should only be done in the root module of `proc-macro` crates, not everywhere
|
// FIXME: this should only be done in the root module of `proc-macro` crates, not everywhere
|
||||||
|
@ -669,19 +669,20 @@ pub struct bar;
|
|||||||
fn expand_derive() {
|
fn expand_derive() {
|
||||||
let map = compute_crate_def_map(
|
let map = compute_crate_def_map(
|
||||||
r#"
|
r#"
|
||||||
//- /main.rs crate:main deps:core
|
//- /main.rs crate:main deps:core
|
||||||
use core::Copy;
|
use core::Copy;
|
||||||
|
|
||||||
#[derive(Copy, core::Clone)]
|
#[core::derive(Copy, core::Clone)]
|
||||||
struct Foo;
|
struct Foo;
|
||||||
|
|
||||||
//- /core.rs crate:core
|
//- /core.rs crate:core
|
||||||
#[rustc_builtin_macro]
|
#[rustc_builtin_macro]
|
||||||
pub macro Copy {}
|
pub macro derive($item:item) {}
|
||||||
|
#[rustc_builtin_macro]
|
||||||
#[rustc_builtin_macro]
|
pub macro Copy {}
|
||||||
pub macro Clone {}
|
#[rustc_builtin_macro]
|
||||||
"#,
|
pub macro Clone {}
|
||||||
|
"#,
|
||||||
);
|
);
|
||||||
assert_eq!(map.modules[map.root].scope.impls().len(), 2);
|
assert_eq!(map.modules[map.root].scope.impls().len(), 2);
|
||||||
}
|
}
|
||||||
@ -712,17 +713,19 @@ fn builtin_derive_with_unresolved_attributes_fall_back() {
|
|||||||
cov_mark::check!(unresolved_attribute_fallback);
|
cov_mark::check!(unresolved_attribute_fallback);
|
||||||
let map = compute_crate_def_map(
|
let map = compute_crate_def_map(
|
||||||
r#"
|
r#"
|
||||||
//- /main.rs crate:main deps:core
|
//- /main.rs crate:main deps:core
|
||||||
use core::Clone;
|
use core::{Clone, derive};
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
#[unresolved]
|
#[unresolved]
|
||||||
struct Foo;
|
struct Foo;
|
||||||
|
|
||||||
//- /core.rs crate:core
|
//- /core.rs crate:core
|
||||||
#[rustc_builtin_macro]
|
#[rustc_builtin_macro]
|
||||||
pub macro Clone {}
|
pub macro derive($item:item) {}
|
||||||
"#,
|
#[rustc_builtin_macro]
|
||||||
|
pub macro Clone {}
|
||||||
|
"#,
|
||||||
);
|
);
|
||||||
assert_eq!(map.modules[map.root].scope.impls().len(), 1);
|
assert_eq!(map.modules[map.root].scope.impls().len(), 1);
|
||||||
}
|
}
|
||||||
@ -799,6 +802,9 @@ fn resolves_derive_helper() {
|
|||||||
check(
|
check(
|
||||||
r#"
|
r#"
|
||||||
//- /main.rs crate:main deps:proc
|
//- /main.rs crate:main deps:proc
|
||||||
|
#[rustc_builtin_macro]
|
||||||
|
pub macro derive($item:item) {}
|
||||||
|
|
||||||
#[derive(proc::Derive)]
|
#[derive(proc::Derive)]
|
||||||
#[helper]
|
#[helper]
|
||||||
#[unresolved]
|
#[unresolved]
|
||||||
@ -811,6 +817,7 @@ fn derive() {}
|
|||||||
expect![[r#"
|
expect![[r#"
|
||||||
crate
|
crate
|
||||||
S: t v
|
S: t v
|
||||||
|
derive: m
|
||||||
"#]],
|
"#]],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -36,6 +36,18 @@ macro_rules! register_builtin {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl BuiltinAttrExpander {
|
||||||
|
pub fn is_derive(self) -> bool {
|
||||||
|
matches!(self, BuiltinAttrExpander::Derive)
|
||||||
|
}
|
||||||
|
pub fn is_test(self) -> bool {
|
||||||
|
matches!(self, BuiltinAttrExpander::Test)
|
||||||
|
}
|
||||||
|
pub fn is_bench(self) -> bool {
|
||||||
|
matches!(self, BuiltinAttrExpander::Bench)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
register_builtin! {
|
register_builtin! {
|
||||||
(bench, Bench) => dummy_attr_expand,
|
(bench, Bench) => dummy_attr_expand,
|
||||||
(cfg_accessible, CfgAccessible) => dummy_attr_expand,
|
(cfg_accessible, CfgAccessible) => dummy_attr_expand,
|
||||||
@ -46,16 +58,6 @@ register_builtin! {
|
|||||||
(test_case, TestCase) => dummy_attr_expand
|
(test_case, TestCase) => dummy_attr_expand
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_builtin_test_or_bench_attr(makro: MacroDefId) -> bool {
|
|
||||||
match makro.kind {
|
|
||||||
MacroDefKind::BuiltInAttr(expander, ..) => {
|
|
||||||
BuiltinAttrExpander::find_by_name(&name!(test)) == Some(expander)
|
|
||||||
|| BuiltinAttrExpander::find_by_name(&name!(bench)) == Some(expander)
|
|
||||||
}
|
|
||||||
_ => false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn find_builtin_attr(
|
pub fn find_builtin_attr(
|
||||||
ident: &name::Name,
|
ident: &name::Name,
|
||||||
krate: CrateId,
|
krate: CrateId,
|
||||||
|
@ -974,61 +974,12 @@ fn infer_builtin_macros_env() {
|
|||||||
fn infer_derive_clone_simple() {
|
fn infer_derive_clone_simple() {
|
||||||
check_types(
|
check_types(
|
||||||
r#"
|
r#"
|
||||||
//- /main.rs crate:main deps:core
|
//- minicore: derive, clone
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
struct S;
|
struct S;
|
||||||
fn test() {
|
fn test() {
|
||||||
S.clone();
|
S.clone();
|
||||||
} //^^^^^^^^^ S
|
} //^^^^^^^^^ S
|
||||||
|
|
||||||
//- /lib.rs crate:core
|
|
||||||
pub mod prelude {
|
|
||||||
pub mod rust_2018 {
|
|
||||||
#[rustc_builtin_macro]
|
|
||||||
pub macro Clone {}
|
|
||||||
pub use crate::clone::Clone;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub mod clone {
|
|
||||||
pub trait Clone {
|
|
||||||
fn clone(&self) -> Self;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"#,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn infer_derive_clone_in_core() {
|
|
||||||
check_types(
|
|
||||||
r#"
|
|
||||||
//- /lib.rs crate:core
|
|
||||||
#[prelude_import]
|
|
||||||
use prelude::rust_2018::*;
|
|
||||||
|
|
||||||
pub mod prelude {
|
|
||||||
pub mod rust_2018 {
|
|
||||||
#[rustc_builtin_macro]
|
|
||||||
pub macro Clone {}
|
|
||||||
pub use crate::clone::Clone;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub mod clone {
|
|
||||||
pub trait Clone {
|
|
||||||
fn clone(&self) -> Self;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct S;
|
|
||||||
|
|
||||||
//- /main.rs crate:main deps:core
|
|
||||||
use core::S;
|
|
||||||
fn test() {
|
|
||||||
S.clone();
|
|
||||||
} //^^^^^^^^^ S
|
|
||||||
"#,
|
"#,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -1037,7 +988,7 @@ fn test() {
|
|||||||
fn infer_derive_clone_with_params() {
|
fn infer_derive_clone_with_params() {
|
||||||
check_types(
|
check_types(
|
||||||
r#"
|
r#"
|
||||||
//- /main.rs crate:main deps:core
|
//- minicore: clone, derive
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
struct S;
|
struct S;
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
@ -1048,21 +999,6 @@ fn test() {
|
|||||||
x;
|
x;
|
||||||
//^ (Wrapper<S>, {unknown})
|
//^ (Wrapper<S>, {unknown})
|
||||||
}
|
}
|
||||||
|
|
||||||
//- /lib.rs crate:core
|
|
||||||
pub mod prelude {
|
|
||||||
pub mod rust_2018 {
|
|
||||||
#[rustc_builtin_macro]
|
|
||||||
pub macro Clone {}
|
|
||||||
pub use crate::clone::Clone;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub mod clone {
|
|
||||||
pub trait Clone {
|
|
||||||
fn clone(&self) -> Self;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"#,
|
"#,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -1072,7 +1008,7 @@ fn infer_custom_derive_simple() {
|
|||||||
// FIXME: this test current now do nothing
|
// FIXME: this test current now do nothing
|
||||||
check_types(
|
check_types(
|
||||||
r#"
|
r#"
|
||||||
//- /main.rs crate:main
|
//- minicore: derive
|
||||||
use foo::Foo;
|
use foo::Foo;
|
||||||
|
|
||||||
#[derive(Foo)]
|
#[derive(Foo)]
|
||||||
|
@ -367,9 +367,7 @@ fn main() {
|
|||||||
check(
|
check(
|
||||||
r#"
|
r#"
|
||||||
//- proc_macros: identity
|
//- proc_macros: identity
|
||||||
|
//- minicore: clone, derive
|
||||||
#[rustc_builtin_macro]
|
|
||||||
pub macro Clone {}
|
|
||||||
|
|
||||||
#[proc_macros::identity]
|
#[proc_macros::identity]
|
||||||
#[derive(C$0lone)]
|
#[derive(C$0lone)]
|
||||||
@ -377,7 +375,7 @@ struct Foo {}
|
|||||||
"#,
|
"#,
|
||||||
expect![[r#"
|
expect![[r#"
|
||||||
Clone
|
Clone
|
||||||
impl< >crate::clone::Clone for Foo< >{}
|
impl< >core::clone::Clone for Foo< >{}
|
||||||
|
|
||||||
"#]],
|
"#]],
|
||||||
);
|
);
|
||||||
@ -387,10 +385,7 @@ struct Foo {}
|
|||||||
fn macro_expand_derive2() {
|
fn macro_expand_derive2() {
|
||||||
check(
|
check(
|
||||||
r#"
|
r#"
|
||||||
#[rustc_builtin_macro]
|
//- minicore: copy, clone, derive
|
||||||
pub macro Clone {}
|
|
||||||
#[rustc_builtin_macro]
|
|
||||||
pub macro Copy {}
|
|
||||||
|
|
||||||
#[derive(Cop$0y)]
|
#[derive(Cop$0y)]
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
@ -398,7 +393,7 @@ struct Foo {}
|
|||||||
"#,
|
"#,
|
||||||
expect![[r#"
|
expect![[r#"
|
||||||
Copy
|
Copy
|
||||||
impl< >crate::marker::Copy for Foo< >{}
|
impl< >core::marker::Copy for Foo< >{}
|
||||||
|
|
||||||
"#]],
|
"#]],
|
||||||
);
|
);
|
||||||
@ -408,19 +403,16 @@ struct Foo {}
|
|||||||
fn macro_expand_derive_multi() {
|
fn macro_expand_derive_multi() {
|
||||||
check(
|
check(
|
||||||
r#"
|
r#"
|
||||||
#[rustc_builtin_macro]
|
//- minicore: copy, clone, derive
|
||||||
pub macro Clone {}
|
|
||||||
#[rustc_builtin_macro]
|
|
||||||
pub macro Copy {}
|
|
||||||
|
|
||||||
#[derive(Cop$0y, Clone)]
|
#[derive(Cop$0y, Clone)]
|
||||||
struct Foo {}
|
struct Foo {}
|
||||||
"#,
|
"#,
|
||||||
expect![[r#"
|
expect![[r#"
|
||||||
Copy, Clone
|
Copy, Clone
|
||||||
impl< >crate::marker::Copy for Foo< >{}
|
impl< >core::marker::Copy for Foo< >{}
|
||||||
|
|
||||||
impl< >crate::clone::Clone for Foo< >{}
|
impl< >core::clone::Clone for Foo< >{}
|
||||||
|
|
||||||
"#]],
|
"#]],
|
||||||
);
|
);
|
||||||
|
@ -805,6 +805,9 @@ bar = {path = "../bar"}
|
|||||||
|
|
||||||
//- /foo/src/main.rs
|
//- /foo/src/main.rs
|
||||||
use bar::Bar;
|
use bar::Bar;
|
||||||
|
|
||||||
|
#[rustc_builtin_macro]
|
||||||
|
macro derive($item:item) {}
|
||||||
trait Bar {
|
trait Bar {
|
||||||
fn bar();
|
fn bar();
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user