mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-27 20:42:04 +00:00
Merge commit 'ac998a74b3
' into sync-from-ra
This commit is contained in:
parent
d33d8675d0
commit
6b17dba68c
178 changed files with 7101 additions and 1965 deletions
|
@ -377,27 +377,39 @@ impl AttrsWithOwner {
|
|||
AttrDefId::GenericParamId(it) => match it {
|
||||
GenericParamId::ConstParamId(it) => {
|
||||
let src = it.parent().child_source(db);
|
||||
RawAttrs::from_attrs_owner(
|
||||
db.upcast(),
|
||||
src.with_value(&src.value[it.local_id()]),
|
||||
db.span_map(src.file_id).as_ref(),
|
||||
)
|
||||
// FIXME: We should be never getting `None` here.
|
||||
match src.value.get(it.local_id()) {
|
||||
Some(val) => RawAttrs::from_attrs_owner(
|
||||
db.upcast(),
|
||||
src.with_value(val),
|
||||
db.span_map(src.file_id).as_ref(),
|
||||
),
|
||||
None => RawAttrs::EMPTY,
|
||||
}
|
||||
}
|
||||
GenericParamId::TypeParamId(it) => {
|
||||
let src = it.parent().child_source(db);
|
||||
RawAttrs::from_attrs_owner(
|
||||
db.upcast(),
|
||||
src.with_value(&src.value[it.local_id()]),
|
||||
db.span_map(src.file_id).as_ref(),
|
||||
)
|
||||
// FIXME: We should be never getting `None` here.
|
||||
match src.value.get(it.local_id()) {
|
||||
Some(val) => RawAttrs::from_attrs_owner(
|
||||
db.upcast(),
|
||||
src.with_value(val),
|
||||
db.span_map(src.file_id).as_ref(),
|
||||
),
|
||||
None => RawAttrs::EMPTY,
|
||||
}
|
||||
}
|
||||
GenericParamId::LifetimeParamId(it) => {
|
||||
let src = it.parent.child_source(db);
|
||||
RawAttrs::from_attrs_owner(
|
||||
db.upcast(),
|
||||
src.with_value(&src.value[it.local_id]),
|
||||
db.span_map(src.file_id).as_ref(),
|
||||
)
|
||||
// FIXME: We should be never getting `None` here.
|
||||
match src.value.get(it.local_id) {
|
||||
Some(val) => RawAttrs::from_attrs_owner(
|
||||
db.upcast(),
|
||||
src.with_value(val),
|
||||
db.span_map(src.file_id).as_ref(),
|
||||
),
|
||||
None => RawAttrs::EMPTY,
|
||||
}
|
||||
}
|
||||
},
|
||||
AttrDefId::ExternBlockId(it) => attrs_from_item_tree_loc(db, it),
|
||||
|
|
|
@ -416,6 +416,11 @@ impl ExprCollector<'_> {
|
|||
let expr = e.expr().map(|e| self.collect_expr(e));
|
||||
self.alloc_expr(Expr::Return { expr }, syntax_ptr)
|
||||
}
|
||||
ast::Expr::BecomeExpr(e) => {
|
||||
let expr =
|
||||
e.expr().map(|e| self.collect_expr(e)).unwrap_or_else(|| self.missing_expr());
|
||||
self.alloc_expr(Expr::Become { expr }, syntax_ptr)
|
||||
}
|
||||
ast::Expr::YieldExpr(e) => {
|
||||
self.is_lowering_coroutine = true;
|
||||
let expr = e.expr().map(|e| self.collect_expr(e));
|
||||
|
@ -1000,10 +1005,6 @@ impl ExprCollector<'_> {
|
|||
krate: *krate,
|
||||
});
|
||||
}
|
||||
Some(ExpandError::RecursionOverflowPoisoned) => {
|
||||
// Recursion limit has been reached in the macro expansion tree, but not in
|
||||
// this very macro call. Don't add diagnostics to avoid duplication.
|
||||
}
|
||||
Some(err) => {
|
||||
self.source_map.diagnostics.push(BodyDiagnostic::MacroError {
|
||||
node: InFile::new(outer_file, syntax_ptr),
|
||||
|
@ -1112,7 +1113,7 @@ impl ExprCollector<'_> {
|
|||
statements.push(Statement::Expr { expr, has_semi });
|
||||
}
|
||||
}
|
||||
ast::Stmt::Item(_item) => (),
|
||||
ast::Stmt::Item(_item) => statements.push(Statement::Item),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -261,6 +261,11 @@ impl Printer<'_> {
|
|||
self.print_expr(*expr);
|
||||
}
|
||||
}
|
||||
Expr::Become { expr } => {
|
||||
w!(self, "become");
|
||||
self.whitespace();
|
||||
self.print_expr(*expr);
|
||||
}
|
||||
Expr::Yield { expr } => {
|
||||
w!(self, "yield");
|
||||
if let Some(expr) = expr {
|
||||
|
@ -623,6 +628,7 @@ impl Printer<'_> {
|
|||
}
|
||||
wln!(self);
|
||||
}
|
||||
Statement::Item => (),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -197,6 +197,7 @@ fn compute_block_scopes(
|
|||
Statement::Expr { expr, .. } => {
|
||||
compute_expr_scopes(*expr, body, scopes, scope);
|
||||
}
|
||||
Statement::Item => (),
|
||||
}
|
||||
}
|
||||
if let Some(expr) = tail {
|
||||
|
|
|
@ -634,7 +634,6 @@ impl<'a> AssocItemCollector<'a> {
|
|||
attr,
|
||||
) {
|
||||
Ok(ResolvedAttr::Macro(call_id)) => {
|
||||
self.attr_calls.push((ast_id, call_id));
|
||||
// If proc attribute macro expansion is disabled, skip expanding it here
|
||||
if !self.db.expand_proc_attr_macros() {
|
||||
continue 'attrs;
|
||||
|
@ -647,10 +646,21 @@ impl<'a> AssocItemCollector<'a> {
|
|||
// disabled. This is analogous to the handling in
|
||||
// `DefCollector::collect_macros`.
|
||||
if exp.is_dummy() {
|
||||
self.diagnostics.push(DefDiagnostic::unresolved_proc_macro(
|
||||
self.module_id.local_id,
|
||||
loc.kind,
|
||||
loc.def.krate,
|
||||
));
|
||||
|
||||
continue 'attrs;
|
||||
}
|
||||
if exp.is_disabled() {
|
||||
continue 'attrs;
|
||||
}
|
||||
}
|
||||
|
||||
self.attr_calls.push((ast_id, call_id));
|
||||
|
||||
let res =
|
||||
self.expander.enter_expand_id::<ast::MacroItems>(self.db, call_id);
|
||||
self.collect_macro_items(res, &|| loc.kind.clone());
|
||||
|
|
|
@ -140,13 +140,11 @@ impl Expander {
|
|||
// The overflow error should have been reported when it occurred (see the next branch),
|
||||
// so don't return overflow error here to avoid diagnostics duplication.
|
||||
cov_mark::hit!(overflow_but_not_me);
|
||||
return ExpandResult::only_err(ExpandError::RecursionOverflowPoisoned);
|
||||
return ExpandResult::ok(None);
|
||||
} else if self.recursion_limit.check(self.recursion_depth as usize + 1).is_err() {
|
||||
self.recursion_depth = u32::MAX;
|
||||
cov_mark::hit!(your_stack_belongs_to_me);
|
||||
return ExpandResult::only_err(ExpandError::other(
|
||||
"reached recursion limit during macro expansion",
|
||||
));
|
||||
return ExpandResult::only_err(ExpandError::RecursionOverflow);
|
||||
}
|
||||
|
||||
let ExpandResult { value, err } = op(self);
|
||||
|
|
|
@ -447,18 +447,25 @@ fn select_best_path(
|
|||
}
|
||||
const STD_CRATES: [Name; 3] = [known::std, known::core, known::alloc];
|
||||
|
||||
let choose = |new_path: (ModPath, _), old_path: (ModPath, _)| {
|
||||
let new_has_prelude = new_path.0.segments().iter().any(|seg| seg == &known::prelude);
|
||||
let old_has_prelude = old_path.0.segments().iter().any(|seg| seg == &known::prelude);
|
||||
let choose = |new: (ModPath, _), old: (ModPath, _)| {
|
||||
let (new_path, _) = &new;
|
||||
let (old_path, _) = &old;
|
||||
let new_has_prelude = new_path.segments().iter().any(|seg| seg == &known::prelude);
|
||||
let old_has_prelude = old_path.segments().iter().any(|seg| seg == &known::prelude);
|
||||
match (new_has_prelude, old_has_prelude, prefer_prelude) {
|
||||
(true, false, true) | (false, true, false) => new_path,
|
||||
(true, false, false) | (false, true, true) => old_path,
|
||||
// no prelude difference in the paths, so pick the smaller one
|
||||
(true, false, true) | (false, true, false) => new,
|
||||
(true, false, false) | (false, true, true) => old,
|
||||
// no prelude difference in the paths, so pick the shorter one
|
||||
(true, true, _) | (false, false, _) => {
|
||||
if new_path.0.len() < old_path.0.len() {
|
||||
new_path
|
||||
let new_path_is_shorter = new_path
|
||||
.len()
|
||||
.cmp(&old_path.len())
|
||||
.then_with(|| new_path.textual_len().cmp(&old_path.textual_len()))
|
||||
.is_lt();
|
||||
if new_path_is_shorter {
|
||||
new
|
||||
} else {
|
||||
old_path
|
||||
old
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -469,8 +476,8 @@ fn select_best_path(
|
|||
let rank = match prefer_no_std {
|
||||
false => |name: &Name| match name {
|
||||
name if name == &known::core => 0,
|
||||
name if name == &known::alloc => 0,
|
||||
name if name == &known::std => 1,
|
||||
name if name == &known::alloc => 1,
|
||||
name if name == &known::std => 2,
|
||||
_ => unreachable!(),
|
||||
},
|
||||
true => |name: &Name| match name {
|
||||
|
@ -1539,4 +1546,38 @@ pub mod foo {
|
|||
"krate::prelude::Foo",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn respect_segment_length() {
|
||||
check_found_path(
|
||||
r#"
|
||||
//- /main.rs crate:main deps:petgraph
|
||||
$0
|
||||
//- /petgraph.rs crate:petgraph
|
||||
pub mod graph {
|
||||
pub use crate::graph_impl::{
|
||||
NodeIndex
|
||||
};
|
||||
}
|
||||
|
||||
mod graph_impl {
|
||||
pub struct NodeIndex<Ix>(Ix);
|
||||
}
|
||||
|
||||
pub mod stable_graph {
|
||||
#[doc(no_inline)]
|
||||
pub use crate::graph::{NodeIndex};
|
||||
}
|
||||
|
||||
pub mod prelude {
|
||||
#[doc(no_inline)]
|
||||
pub use crate::graph::{NodeIndex};
|
||||
}
|
||||
"#,
|
||||
"petgraph::graph::NodeIndex",
|
||||
"petgraph::graph::NodeIndex",
|
||||
"petgraph::graph::NodeIndex",
|
||||
"petgraph::graph::NodeIndex",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -182,6 +182,7 @@ pub enum Expr {
|
|||
tail: Option<ExprId>,
|
||||
},
|
||||
Const(ConstBlockId),
|
||||
// FIXME: Fold this into Block with an unsafe flag?
|
||||
Unsafe {
|
||||
id: Option<BlockId>,
|
||||
statements: Box<[Statement]>,
|
||||
|
@ -216,6 +217,9 @@ pub enum Expr {
|
|||
Return {
|
||||
expr: Option<ExprId>,
|
||||
},
|
||||
Become {
|
||||
expr: ExprId,
|
||||
},
|
||||
Yield {
|
||||
expr: Option<ExprId>,
|
||||
},
|
||||
|
@ -349,6 +353,9 @@ pub enum Statement {
|
|||
expr: ExprId,
|
||||
has_semi: bool,
|
||||
},
|
||||
// At the moment, we only use this to figure out if a return expression
|
||||
// is really the last statement of a block. See #16566
|
||||
Item,
|
||||
}
|
||||
|
||||
impl Expr {
|
||||
|
@ -382,6 +389,7 @@ impl Expr {
|
|||
}
|
||||
}
|
||||
Statement::Expr { expr: expression, .. } => f(*expression),
|
||||
Statement::Item => (),
|
||||
}
|
||||
}
|
||||
if let &Some(expr) = tail {
|
||||
|
@ -410,6 +418,7 @@ impl Expr {
|
|||
f(expr);
|
||||
}
|
||||
}
|
||||
Expr::Become { expr } => f(*expr),
|
||||
Expr::RecordLit { fields, spread, .. } => {
|
||||
for field in fields.iter() {
|
||||
f(field.expr);
|
||||
|
|
|
@ -33,7 +33,7 @@ m!(&k");
|
|||
"#,
|
||||
expect![[r#"
|
||||
macro_rules! m { ($i:literal) => {}; }
|
||||
/* error: invalid token tree */"#]],
|
||||
/* error: mismatched delimiters */"#]],
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -68,26 +68,26 @@ m2!();
|
|||
"#,
|
||||
expect![[r#"
|
||||
macro_rules! i1 { invalid }
|
||||
/* error: invalid macro definition: expected subtree */
|
||||
/* error: macro definition has parse errors */
|
||||
|
||||
macro_rules! e1 { $i:ident => () }
|
||||
/* error: invalid macro definition: expected subtree */
|
||||
/* error: macro definition has parse errors */
|
||||
macro_rules! e2 { ($i:ident) () }
|
||||
/* error: invalid macro definition: expected `=` */
|
||||
/* error: macro definition has parse errors */
|
||||
macro_rules! e3 { ($(i:ident)_) => () }
|
||||
/* error: invalid macro definition: invalid repeat */
|
||||
/* error: macro definition has parse errors */
|
||||
|
||||
macro_rules! f1 { ($i) => ($i) }
|
||||
/* error: invalid macro definition: missing fragment specifier */
|
||||
/* error: macro definition has parse errors */
|
||||
macro_rules! f2 { ($i:) => ($i) }
|
||||
/* error: invalid macro definition: missing fragment specifier */
|
||||
/* error: macro definition has parse errors */
|
||||
macro_rules! f3 { ($i:_) => () }
|
||||
/* error: invalid macro definition: missing fragment specifier */
|
||||
/* error: macro definition has parse errors */
|
||||
|
||||
macro_rules! m1 { ($$i) => () }
|
||||
/* error: invalid macro definition: `$$` is not allowed on the pattern side */
|
||||
/* error: macro definition has parse errors */
|
||||
macro_rules! m2 { () => ( ${invalid()} ) }
|
||||
/* error: invalid macro definition: invalid metavariable expression */
|
||||
/* error: macro definition has parse errors */
|
||||
"#]],
|
||||
)
|
||||
}
|
||||
|
@ -137,18 +137,18 @@ macro_rules! m9 { ($($($($i:ident)?)*)+) => {}; }
|
|||
macro_rules! mA { ($($($($i:ident)+)?)*) => {}; }
|
||||
macro_rules! mB { ($($($($i:ident)+)*)?) => {}; }
|
||||
|
||||
/* error: invalid macro definition: empty token tree in repetition */
|
||||
/* error: invalid macro definition: empty token tree in repetition */
|
||||
/* error: invalid macro definition: empty token tree in repetition */
|
||||
/* error: invalid macro definition: empty token tree in repetition */
|
||||
/* error: invalid macro definition: empty token tree in repetition */
|
||||
/* error: invalid macro definition: empty token tree in repetition */
|
||||
/* error: invalid macro definition: empty token tree in repetition */
|
||||
/* error: invalid macro definition: empty token tree in repetition */
|
||||
/* error: invalid macro definition: empty token tree in repetition */
|
||||
/* error: invalid macro definition: empty token tree in repetition */
|
||||
/* error: invalid macro definition: empty token tree in repetition */
|
||||
/* error: invalid macro definition: empty token tree in repetition */
|
||||
/* error: macro definition has parse errors */
|
||||
/* error: macro definition has parse errors */
|
||||
/* error: macro definition has parse errors */
|
||||
/* error: macro definition has parse errors */
|
||||
/* error: macro definition has parse errors */
|
||||
/* error: macro definition has parse errors */
|
||||
/* error: macro definition has parse errors */
|
||||
/* error: macro definition has parse errors */
|
||||
/* error: macro definition has parse errors */
|
||||
/* error: macro definition has parse errors */
|
||||
/* error: macro definition has parse errors */
|
||||
/* error: macro definition has parse errors */
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
|
|
@ -275,9 +275,9 @@ macro_rules! depth_too_large {
|
|||
}
|
||||
|
||||
fn test() {
|
||||
/* error: invalid macro definition: invalid metavariable expression */;
|
||||
/* error: invalid macro definition: invalid metavariable expression */;
|
||||
/* error: invalid macro definition: invalid metavariable expression */;
|
||||
/* error: macro definition has parse errors */;
|
||||
/* error: macro definition has parse errors */;
|
||||
/* error: macro definition has parse errors */;
|
||||
}
|
||||
"#]],
|
||||
);
|
||||
|
|
|
@ -1090,3 +1090,57 @@ fn main() {
|
|||
"#]],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn regression_16529() {
|
||||
check(
|
||||
r#"
|
||||
mod any {
|
||||
#[macro_export]
|
||||
macro_rules! nameable {
|
||||
{
|
||||
struct $name:ident[$a:lifetime]
|
||||
} => {
|
||||
$crate::any::nameable! {
|
||||
struct $name[$a]
|
||||
a
|
||||
}
|
||||
};
|
||||
{
|
||||
struct $name:ident[$a:lifetime]
|
||||
a
|
||||
} => {};
|
||||
}
|
||||
pub use nameable;
|
||||
|
||||
nameable! {
|
||||
Name['a]
|
||||
}
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
mod any {
|
||||
#[macro_export]
|
||||
macro_rules! nameable {
|
||||
{
|
||||
struct $name:ident[$a:lifetime]
|
||||
} => {
|
||||
$crate::any::nameable! {
|
||||
struct $name[$a]
|
||||
a
|
||||
}
|
||||
};
|
||||
{
|
||||
struct $name:ident[$a:lifetime]
|
||||
a
|
||||
} => {};
|
||||
}
|
||||
pub use nameable;
|
||||
|
||||
/* error: unexpected token in input */$crate::any::nameable! {
|
||||
struct $name[$a]a
|
||||
}
|
||||
}
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
|
|
@ -97,8 +97,8 @@ m2!(x
|
|||
macro_rules! m1 { ($x:ident) => { ($x } }
|
||||
macro_rules! m2 { ($x:ident) => {} }
|
||||
|
||||
/* error: invalid macro definition: expected subtree */
|
||||
/* error: invalid token tree */
|
||||
/* error: macro definition has parse errors */
|
||||
/* error: mismatched delimiters */
|
||||
"#]],
|
||||
)
|
||||
}
|
||||
|
|
|
@ -58,6 +58,7 @@ pub fn identity_when_valid(_attr: TokenStream, item: TokenStream) -> TokenStream
|
|||
name: "identity_when_valid".into(),
|
||||
kind: ProcMacroKind::Attr,
|
||||
expander: sync::Arc::new(IdentityWhenValidProcMacroExpander),
|
||||
disabled: false,
|
||||
},
|
||||
)];
|
||||
let db = TestDB::with_files_extra_proc_macros(ra_fixture, extra_proc_macros);
|
||||
|
|
|
@ -11,7 +11,7 @@ use either::Either;
|
|||
use hir_expand::{
|
||||
ast_id_map::FileAstId,
|
||||
attrs::{Attr, AttrId},
|
||||
builtin_attr_macro::find_builtin_attr,
|
||||
builtin_attr_macro::{find_builtin_attr, BuiltinAttrExpander},
|
||||
builtin_derive_macro::find_builtin_derive,
|
||||
builtin_fn_macro::find_builtin_macro,
|
||||
name::{name, AsName, Name},
|
||||
|
@ -98,9 +98,13 @@ pub(super) fn collect_defs(db: &dyn DefDatabase, def_map: DefMap, tree_id: TreeI
|
|||
};
|
||||
(
|
||||
name.as_name(),
|
||||
CustomProcMacroExpander::new(hir_expand::proc_macro::ProcMacroId(
|
||||
idx as u32,
|
||||
)),
|
||||
if it.disabled {
|
||||
CustomProcMacroExpander::disabled()
|
||||
} else {
|
||||
CustomProcMacroExpander::new(
|
||||
hir_expand::proc_macro::ProcMacroId::new(idx as u32),
|
||||
)
|
||||
},
|
||||
)
|
||||
})
|
||||
.collect())
|
||||
|
@ -604,9 +608,6 @@ impl DefCollector<'_> {
|
|||
id: ItemTreeId<item_tree::Function>,
|
||||
fn_id: FunctionId,
|
||||
) {
|
||||
if self.def_map.block.is_some() {
|
||||
return;
|
||||
}
|
||||
let kind = def.kind.to_basedb_kind();
|
||||
let (expander, kind) =
|
||||
match self.proc_macros.as_ref().map(|it| it.iter().find(|(n, _)| n == &def.name)) {
|
||||
|
@ -1120,9 +1121,16 @@ impl DefCollector<'_> {
|
|||
let mut push_resolved = |directive: &MacroDirective, call_id| {
|
||||
resolved.push((directive.module_id, directive.depth, directive.container, call_id));
|
||||
};
|
||||
|
||||
#[derive(PartialEq, Eq)]
|
||||
enum Resolved {
|
||||
Yes,
|
||||
No,
|
||||
}
|
||||
|
||||
let mut res = ReachedFixedPoint::Yes;
|
||||
// Retain unresolved macros after this round of resolution.
|
||||
macros.retain(|directive| {
|
||||
let mut retain = |directive: &MacroDirective| {
|
||||
let subns = match &directive.kind {
|
||||
MacroDirectiveKind::FnLike { .. } => MacroSubNs::Bang,
|
||||
MacroDirectiveKind::Attr { .. } | MacroDirectiveKind::Derive { .. } => {
|
||||
|
@ -1156,10 +1164,11 @@ impl DefCollector<'_> {
|
|||
self.def_map.modules[directive.module_id]
|
||||
.scope
|
||||
.add_macro_invoc(ast_id.ast_id, call_id);
|
||||
|
||||
push_resolved(directive, call_id);
|
||||
|
||||
res = ReachedFixedPoint::No;
|
||||
return false;
|
||||
return Resolved::Yes;
|
||||
}
|
||||
}
|
||||
MacroDirectiveKind::Derive { ast_id, derive_attr, derive_pos, call_site } => {
|
||||
|
@ -1198,7 +1207,7 @@ impl DefCollector<'_> {
|
|||
|
||||
push_resolved(directive, call_id);
|
||||
res = ReachedFixedPoint::No;
|
||||
return false;
|
||||
return Resolved::Yes;
|
||||
}
|
||||
}
|
||||
MacroDirectiveKind::Attr { ast_id: file_ast_id, mod_item, attr, tree } => {
|
||||
|
@ -1221,7 +1230,7 @@ impl DefCollector<'_> {
|
|||
}
|
||||
.collect(&[*mod_item], directive.container);
|
||||
res = ReachedFixedPoint::No;
|
||||
false
|
||||
Resolved::Yes
|
||||
};
|
||||
|
||||
if let Some(ident) = path.as_ident() {
|
||||
|
@ -1237,13 +1246,18 @@ impl DefCollector<'_> {
|
|||
|
||||
let def = match resolver_def_id(path.clone()) {
|
||||
Some(def) if def.is_attribute() => def,
|
||||
_ => return true,
|
||||
_ => return Resolved::No,
|
||||
};
|
||||
if matches!(
|
||||
def,
|
||||
MacroDefId { kind: MacroDefKind::BuiltInAttr(expander, _),.. }
|
||||
if expander.is_derive()
|
||||
) {
|
||||
|
||||
if let MacroDefId {
|
||||
kind:
|
||||
MacroDefKind::BuiltInAttr(
|
||||
BuiltinAttrExpander::Derive | BuiltinAttrExpander::DeriveConst,
|
||||
_,
|
||||
),
|
||||
..
|
||||
} = def
|
||||
{
|
||||
// Resolved to `#[derive]`, we don't actually expand this attribute like
|
||||
// normal (as that would just be an identity expansion with extra output)
|
||||
// Instead we treat derive attributes special and apply them separately.
|
||||
|
@ -1316,16 +1330,6 @@ impl DefCollector<'_> {
|
|||
let call_id =
|
||||
attr_macro_as_call_id(self.db, file_ast_id, attr, self.def_map.krate, def);
|
||||
|
||||
// If proc attribute macro expansion is disabled, skip expanding it here
|
||||
if !self.db.expand_proc_attr_macros() {
|
||||
self.def_map.diagnostics.push(DefDiagnostic::unresolved_proc_macro(
|
||||
directive.module_id,
|
||||
self.db.lookup_intern_macro_call(call_id).kind,
|
||||
def.krate,
|
||||
));
|
||||
return recollect_without(self);
|
||||
}
|
||||
|
||||
// Skip #[test]/#[bench] expansion, which would merely result in more memory usage
|
||||
// due to duplicating functions into macro expansions
|
||||
if matches!(
|
||||
|
@ -1337,17 +1341,29 @@ impl DefCollector<'_> {
|
|||
}
|
||||
|
||||
if let MacroDefKind::ProcMacro(exp, ..) = def.kind {
|
||||
if exp.is_dummy() {
|
||||
// If there's no expander for the proc macro (e.g.
|
||||
// because proc macros are disabled, or building the
|
||||
// proc macro crate failed), report this and skip
|
||||
// expansion like we would if it was disabled
|
||||
// If proc attribute macro expansion is disabled, skip expanding it here
|
||||
if !self.db.expand_proc_attr_macros() {
|
||||
self.def_map.diagnostics.push(DefDiagnostic::unresolved_proc_macro(
|
||||
directive.module_id,
|
||||
self.db.lookup_intern_macro_call(call_id).kind,
|
||||
def.krate,
|
||||
));
|
||||
return recollect_without(self);
|
||||
}
|
||||
|
||||
// If there's no expander for the proc macro (e.g.
|
||||
// because proc macros are disabled, or building the
|
||||
// proc macro crate failed), report this and skip
|
||||
// expansion like we would if it was disabled
|
||||
if exp.is_dummy() {
|
||||
self.def_map.diagnostics.push(DefDiagnostic::unresolved_proc_macro(
|
||||
directive.module_id,
|
||||
self.db.lookup_intern_macro_call(call_id).kind,
|
||||
def.krate,
|
||||
));
|
||||
return recollect_without(self);
|
||||
}
|
||||
if exp.is_disabled() {
|
||||
return recollect_without(self);
|
||||
}
|
||||
}
|
||||
|
@ -1358,12 +1374,13 @@ impl DefCollector<'_> {
|
|||
|
||||
push_resolved(directive, call_id);
|
||||
res = ReachedFixedPoint::No;
|
||||
return false;
|
||||
return Resolved::Yes;
|
||||
}
|
||||
}
|
||||
|
||||
true
|
||||
});
|
||||
Resolved::No
|
||||
};
|
||||
macros.retain(|it| retain(it) == Resolved::No);
|
||||
// Attribute resolution can add unresolved macro invocations, so concatenate the lists.
|
||||
macros.extend(mem::take(&mut self.unresolved_macros));
|
||||
self.unresolved_macros = macros;
|
||||
|
@ -1673,7 +1690,11 @@ impl ModCollector<'_, '_> {
|
|||
FunctionLoc { container, id: ItemTreeId::new(self.tree_id, id) }.intern(db);
|
||||
|
||||
let vis = resolve_vis(def_map, &self.item_tree[it.visibility]);
|
||||
if self.def_collector.is_proc_macro && self.module_id == DefMap::ROOT {
|
||||
|
||||
if self.def_collector.def_map.block.is_none()
|
||||
&& self.def_collector.is_proc_macro
|
||||
&& self.module_id == DefMap::ROOT
|
||||
{
|
||||
if let Some(proc_macro) = attrs.parse_proc_macro_decl(&it.name) {
|
||||
self.def_collector.export_proc_macro(
|
||||
proc_macro,
|
||||
|
@ -2333,7 +2354,7 @@ impl ModCollector<'_, '_> {
|
|||
resolved_res.resolved_def.take_macros().map(|it| db.macro_def(it))
|
||||
},
|
||||
) {
|
||||
// FIXME: if there were errors, this mightve been in the eager expansion from an
|
||||
// FIXME: if there were errors, this might've been in the eager expansion from an
|
||||
// unresolved macro, so we need to push this into late macro resolution. see fixme above
|
||||
if res.err.is_none() {
|
||||
// Legacy macros need to be expanded immediately, so that any macros they produce
|
||||
|
|
|
@ -103,6 +103,9 @@ impl DefDiagnostic {
|
|||
}
|
||||
|
||||
// FIXME: Whats the difference between this and unresolved_macro_call
|
||||
// FIXME: This is used for a lot of things, unresolved proc macros, disabled proc macros, etc
|
||||
// yet the diagnostic handler in ide-diagnostics has to figure out what happened because this
|
||||
// struct loses all that information!
|
||||
pub(crate) fn unresolved_proc_macro(
|
||||
container: LocalModuleId,
|
||||
ast: MacroCallKind,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue