Skip to content

Commit fd3942e

Browse files
bors[bot]Veykril
andauthored
Merge #11382
11382: fix: Fix `cfg_attr` invalidating derive identifier IDE functionalities r=Veykril a=Veykril Proper fix for #11298 bors r+ Co-authored-by: Lukas Wirth <[email protected]>
2 parents c08df0f + ddf7b70 commit fd3942e

File tree

11 files changed

+75
-85
lines changed

11 files changed

+75
-85
lines changed

crates/hir/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -664,7 +664,7 @@ fn emit_def_diagnostic(db: &dyn HirDatabase, acc: &mut Vec<AnyDiagnostic>, diag:
664664
let attr = node
665665
.doc_comments_and_attrs()
666666
.nth((*invoc_attr_index) as usize)
667-
.and_then(Either::right)
667+
.and_then(Either::left)
668668
.unwrap_or_else(|| panic!("cannot find attribute #{}", invoc_attr_index));
669669
(
670670
ast_id.with_value(SyntaxNodePtr::from(AstPtr::new(&attr))),

crates/hir/src/semantics.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -364,9 +364,6 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
364364
self.imp.resolve_derive_ident(derive, ident)
365365
}
366366

367-
// FIXME: use this instead?
368-
// pub fn resolve_name_ref(&self, name_ref: &ast::NameRef) -> Option<???>;
369-
370367
pub fn record_literal_missing_fields(&self, literal: &ast::RecordExpr) -> Vec<(Field, Type)> {
371368
self.imp.record_literal_missing_fields(literal)
372369
}
@@ -931,7 +928,6 @@ impl<'db> SemanticsImpl<'db> {
931928
file.with_value(derive.clone()),
932929
)?;
933930
let attrs = adt_def.attrs(self.db);
934-
// FIXME: https://github.com/rust-analyzer/rust-analyzer/issues/11298
935931
let mut derive_paths = attrs.get(attr_id)?.parse_path_comma_token_tree()?;
936932

937933
let derive_idx = tt

crates/hir_def/src/attr.rs

Lines changed: 37 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,8 @@ impl ops::Deref for RawAttrs {
7373
}
7474
}
7575
impl Attrs {
76-
pub fn get(&self, AttrId { ast_index, .. }: AttrId) -> Option<&Attr> {
77-
(**self).get(ast_index as usize)
76+
pub fn get(&self, id: AttrId) -> Option<&Attr> {
77+
(**self).iter().find(|attr| attr.id == id)
7878
}
7979
}
8080

@@ -89,14 +89,6 @@ impl ops::Deref for Attrs {
8989
}
9090
}
9191

92-
impl ops::Index<AttrId> for Attrs {
93-
type Output = Attr;
94-
95-
fn index(&self, AttrId { ast_index, .. }: AttrId) -> &Self::Output {
96-
&(**self)[ast_index as usize]
97-
}
98-
}
99-
10092
impl ops::Deref for AttrsWithOwner {
10193
type Target = Attrs;
10294

@@ -110,7 +102,7 @@ impl RawAttrs {
110102

111103
pub(crate) fn new(db: &dyn DefDatabase, owner: &dyn ast::HasAttrs, hygiene: &Hygiene) -> Self {
112104
let entries = collect_attrs(owner)
113-
.flat_map(|(id, attr)| match attr {
105+
.filter_map(|(id, attr)| match attr {
114106
Either::Left(attr) => {
115107
attr.meta().and_then(|meta| Attr::from_src(db, meta, hygiene, id))
116108
}
@@ -525,38 +517,36 @@ impl AttrsWithOwner {
525517

526518
fn inner_attributes(
527519
syntax: &SyntaxNode,
528-
) -> Option<(impl Iterator<Item = ast::Attr>, impl Iterator<Item = ast::Comment>)> {
529-
let (attrs, docs) = match_ast! {
520+
) -> Option<impl Iterator<Item = Either<ast::Attr, ast::Comment>>> {
521+
let node = match_ast! {
530522
match syntax {
531-
ast::SourceFile(it) => (it.attrs(), ast::DocCommentIter::from_syntax_node(it.syntax())),
532-
ast::ExternBlock(it) => {
533-
let extern_item_list = it.extern_item_list()?;
534-
(extern_item_list.attrs(), ast::DocCommentIter::from_syntax_node(extern_item_list.syntax()))
535-
},
536-
ast::Fn(it) => {
537-
let body = it.body()?;
538-
let stmt_list = body.stmt_list()?;
539-
(stmt_list.attrs(), ast::DocCommentIter::from_syntax_node(body.syntax()))
540-
},
541-
ast::Impl(it) => {
542-
let assoc_item_list = it.assoc_item_list()?;
543-
(assoc_item_list.attrs(), ast::DocCommentIter::from_syntax_node(assoc_item_list.syntax()))
544-
},
545-
ast::Module(it) => {
546-
let item_list = it.item_list()?;
547-
(item_list.attrs(), ast::DocCommentIter::from_syntax_node(item_list.syntax()))
523+
ast::SourceFile(_) => syntax.clone(),
524+
ast::ExternBlock(it) => it.extern_item_list()?.syntax().clone(),
525+
ast::Fn(it) => it.body()?.stmt_list()?.syntax().clone(),
526+
ast::Impl(it) => it.assoc_item_list()?.syntax().clone(),
527+
ast::Module(it) => it.item_list()?.syntax().clone(),
528+
ast::BlockExpr(it) => {
529+
use syntax::SyntaxKind::{BLOCK_EXPR , EXPR_STMT};
530+
// Block expressions accept outer and inner attributes, but only when they are the outer
531+
// expression of an expression statement or the final expression of another block expression.
532+
let may_carry_attributes = matches!(
533+
it.syntax().parent().map(|it| it.kind()),
534+
Some(BLOCK_EXPR | EXPR_STMT)
535+
);
536+
if !may_carry_attributes {
537+
return None
538+
}
539+
syntax.clone()
548540
},
549-
// FIXME: BlockExpr's only accept inner attributes in specific cases
550-
// Excerpt from the reference:
551-
// Block expressions accept outer and inner attributes, but only when they are the outer
552-
// expression of an expression statement or the final expression of another block expression.
553-
ast::BlockExpr(_it) => return None,
554541
_ => return None,
555542
}
556543
};
557-
let attrs = attrs.filter(|attr| attr.kind().is_inner());
558-
let docs = docs.filter(|doc| doc.is_inner());
559-
Some((attrs, docs))
544+
545+
let attrs = ast::AttrDocCommentIter::from_syntax_node(&node).filter(|el| match el {
546+
Either::Left(attr) => attr.kind().is_inner(),
547+
Either::Right(comment) => comment.is_inner(),
548+
});
549+
Some(attrs)
560550
}
561551

562552
#[derive(Debug)]
@@ -833,24 +823,16 @@ fn attrs_from_item_tree<N: ItemTreeNode>(id: ItemTreeId<N>, db: &dyn DefDatabase
833823
fn collect_attrs(
834824
owner: &dyn ast::HasAttrs,
835825
) -> impl Iterator<Item = (AttrId, Either<ast::Attr, ast::Comment>)> {
836-
let (inner_attrs, inner_docs) = inner_attributes(owner.syntax())
837-
.map_or((None, None), |(attrs, docs)| (Some(attrs), Some(docs)));
838-
839-
let outer_attrs = owner.attrs().filter(|attr| attr.kind().is_outer());
840-
let attrs = outer_attrs
841-
.chain(inner_attrs.into_iter().flatten())
842-
.map(|attr| (attr.syntax().text_range().start(), Either::Left(attr)));
843-
844-
let outer_docs =
845-
ast::DocCommentIter::from_syntax_node(owner.syntax()).filter(ast::Comment::is_outer);
846-
let docs = outer_docs
847-
.chain(inner_docs.into_iter().flatten())
848-
.map(|docs_text| (docs_text.syntax().text_range().start(), Either::Right(docs_text)));
849-
// sort here by syntax node offset because the source can have doc attributes and doc strings be interleaved
850-
docs.chain(attrs)
851-
.sorted_by_key(|&(offset, _)| offset)
826+
let inner_attrs = inner_attributes(owner.syntax()).into_iter().flatten();
827+
let outer_attrs =
828+
ast::AttrDocCommentIter::from_syntax_node(owner.syntax()).filter(|el| match el {
829+
Either::Left(attr) => attr.kind().is_outer(),
830+
Either::Right(comment) => comment.is_outer(),
831+
});
832+
outer_attrs
833+
.chain(inner_attrs)
852834
.enumerate()
853-
.map(|(id, (_, attr))| (AttrId { ast_index: id as u32 }, attr))
835+
.map(|(id, attr)| (AttrId { ast_index: id as u32 }, attr))
854836
}
855837

856838
pub(crate) fn variants_attrs_source_map(

crates/hir_def/src/child_by_source.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ impl ChildBySource for ItemScope {
117117
|(ast_id, calls)| {
118118
let adt = ast_id.to_node(db.upcast());
119119
calls.for_each(|(attr_id, calls)| {
120-
if let Some(Either::Right(attr)) =
120+
if let Some(Either::Left(attr)) =
121121
adt.doc_comments_and_attrs().nth(attr_id.ast_index as usize)
122122
{
123123
res[keys::DERIVE_MACRO_CALL].insert(attr, (attr_id, calls.into()));

crates/hir_expand/src/db.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ pub fn expand_speculative(
157157
let attr = item
158158
.doc_comments_and_attrs()
159159
.nth(invoc_attr_index as usize)
160-
.and_then(Either::right)?;
160+
.and_then(Either::left)?;
161161
match attr.token_tree() {
162162
Some(token_tree) => {
163163
let (mut tree, map) = syntax_node_to_token_tree(attr.token_tree()?.syntax());
@@ -323,7 +323,7 @@ fn censor_for_macro_input(loc: &MacroCallLoc, node: &SyntaxNode) -> FxHashSet<Sy
323323
ast::Item::cast(node.clone())?
324324
.doc_comments_and_attrs()
325325
.nth(invoc_attr_index as usize)
326-
.and_then(Either::right)
326+
.and_then(Either::left)
327327
.map(|attr| attr.syntax().clone())
328328
.into_iter()
329329
.collect()

crates/hir_expand/src/hygiene.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ fn make_hygiene_info(
191191
.to_node(db)
192192
.doc_comments_and_attrs()
193193
.nth(invoc_attr_index as usize)
194-
.and_then(Either::right)?
194+
.and_then(Either::left)?
195195
.token_tree()?;
196196
Some(InFile::new(ast_id.file_id, tt))
197197
}

crates/hir_expand/src/lib.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,7 @@ impl HirFileId {
205205
.to_node(db)
206206
.doc_comments_and_attrs()
207207
.nth(invoc_attr_index as usize)
208-
.and_then(Either::right)?
208+
.and_then(Either::left)?
209209
.token_tree()?;
210210
Some(InFile::new(ast_id.file_id, tt))
211211
}
@@ -382,7 +382,7 @@ impl MacroCallKind {
382382
.doc_comments_and_attrs()
383383
.nth(derive_attr_index as usize)
384384
.expect("missing derive")
385-
.expect_right("derive is a doc comment?")
385+
.expect_left("derive is a doc comment?")
386386
.syntax()
387387
.text_range()
388388
}
@@ -391,7 +391,7 @@ impl MacroCallKind {
391391
.doc_comments_and_attrs()
392392
.nth(invoc_attr_index as usize)
393393
.expect("missing attribute")
394-
.expect_right("attribute macro is a doc comment?")
394+
.expect_left("attribute macro is a doc comment?")
395395
.syntax()
396396
.text_range(),
397397
};
@@ -483,7 +483,7 @@ impl ExpansionInfo {
483483
let attr = item
484484
.doc_comments_and_attrs()
485485
.nth(*invoc_attr_index as usize)
486-
.and_then(Either::right)?;
486+
.and_then(Either::left)?;
487487
match attr.token_tree() {
488488
Some(token_tree)
489489
if token_tree.syntax().text_range().contains_range(token_range) =>

crates/ide/src/goto_definition.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1364,10 +1364,21 @@ impl Twait for Stwuct {
13641364
fn goto_def_derive_input() {
13651365
check(
13661366
r#"
1367+
//- minicore:derive
1368+
#[rustc_builtin_macro]
1369+
pub macro Copy {}
1370+
// ^^^^
1371+
#[derive(Copy$0)]
1372+
struct Foo;
1373+
"#,
1374+
);
1375+
check(
1376+
r#"
13671377
//- minicore:derive
13681378
#[rustc_builtin_macro]
13691379
pub macro Copy {}
13701380
// ^^^^
1381+
#[cfg_attr(feature = "false", derive)]
13711382
#[derive(Copy$0)]
13721383
struct Foo;
13731384
"#,

crates/syntax/src/ast.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@ pub use self::{
2727
operators::{ArithOp, BinaryOp, CmpOp, LogicOp, Ordering, RangeOp, UnaryOp},
2828
token_ext::{CommentKind, CommentPlacement, CommentShape, IsString, QuoteOffsets, Radix},
2929
traits::{
30-
DocCommentIter, HasArgList, HasAttrs, HasDocComments, HasGenericParams, HasLoopBody,
31-
HasModuleItem, HasName, HasTypeBounds, HasVisibility,
30+
AttrDocCommentIter, DocCommentIter, HasArgList, HasAttrs, HasDocComments, HasGenericParams,
31+
HasLoopBody, HasModuleItem, HasName, HasTypeBounds, HasVisibility,
3232
},
3333
};
3434

crates/syntax/src/ast/node_ext.rs

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -160,14 +160,9 @@ impl ast::Attr {
160160
}
161161

162162
pub fn kind(&self) -> AttrKind {
163-
let first_token = self.syntax().first_token();
164-
let first_token_kind = first_token.as_ref().map(SyntaxToken::kind);
165-
let second_token_kind =
166-
first_token.and_then(|token| token.next_token()).as_ref().map(SyntaxToken::kind);
167-
168-
match (first_token_kind, second_token_kind) {
169-
(Some(T![#]), Some(T![!])) => AttrKind::Inner,
170-
_ => AttrKind::Outer,
163+
match self.excl_token() {
164+
Some(_) => AttrKind::Inner,
165+
None => AttrKind::Outer,
171166
}
172167
}
173168

crates/syntax/src/ast/traits.rs

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,8 @@ pub trait HasDocComments: HasAttrs {
7676
fn doc_comments(&self) -> DocCommentIter {
7777
DocCommentIter { iter: self.syntax().children_with_tokens() }
7878
}
79-
fn doc_comments_and_attrs(&self) -> AttrCommentIter {
80-
AttrCommentIter { iter: self.syntax().children_with_tokens() }
79+
fn doc_comments_and_attrs(&self) -> AttrDocCommentIter {
80+
AttrDocCommentIter { iter: self.syntax().children_with_tokens() }
8181
}
8282
}
8383

@@ -113,17 +113,23 @@ impl Iterator for DocCommentIter {
113113
}
114114
}
115115

116-
pub struct AttrCommentIter {
116+
pub struct AttrDocCommentIter {
117117
iter: SyntaxElementChildren,
118118
}
119119

120-
impl Iterator for AttrCommentIter {
121-
type Item = Either<ast::Comment, ast::Attr>;
120+
impl AttrDocCommentIter {
121+
pub fn from_syntax_node(syntax_node: &ast::SyntaxNode) -> AttrDocCommentIter {
122+
AttrDocCommentIter { iter: syntax_node.children_with_tokens() }
123+
}
124+
}
125+
126+
impl Iterator for AttrDocCommentIter {
127+
type Item = Either<ast::Attr, ast::Comment>;
122128
fn next(&mut self) -> Option<Self::Item> {
123129
self.iter.by_ref().find_map(|el| match el {
124-
SyntaxElement::Node(node) => ast::Attr::cast(node).map(Either::Right),
130+
SyntaxElement::Node(node) => ast::Attr::cast(node).map(Either::Left),
125131
SyntaxElement::Token(tok) => {
126-
ast::Comment::cast(tok).filter(ast::Comment::is_doc).map(Either::Left)
132+
ast::Comment::cast(tok).filter(ast::Comment::is_doc).map(Either::Right)
127133
}
128134
})
129135
}

0 commit comments

Comments
 (0)