Use FileAstId<ast::Adt> in nameres where appropriate instead

This commit is contained in:
Lukas Wirth 2022-01-07 14:19:11 +01:00
parent 08adce61a1
commit ca4baa6e55
23 changed files with 98 additions and 65 deletions

View File

@ -649,8 +649,12 @@ impl Module {
let node = ast_id.to_node(db.upcast());
ast_id.with_value(SyntaxNodePtr::from(AstPtr::new(&node)))
}
MacroCallKind::Derive { ast_id, .. }
| MacroCallKind::Attr { ast_id, .. } => {
MacroCallKind::Derive { ast_id, .. } => {
// FIXME: point to the attribute instead, this creates very large diagnostics
let node = ast_id.to_node(db.upcast());
ast_id.with_value(SyntaxNodePtr::from(AstPtr::new(&node)))
}
MacroCallKind::Attr { ast_id, .. } => {
// FIXME: point to the attribute instead, this creates very large diagnostics
let node = ast_id.to_node(db.upcast());
ast_id.with_value(SyntaxNodePtr::from(AstPtr::new(&node)))

View File

@ -18,7 +18,7 @@ use rustc_hash::{FxHashMap, FxHashSet};
use smallvec::{smallvec, SmallVec};
use syntax::{
algo::skip_trivia_token,
ast::{self, HasAttrs, HasGenericParams, HasLoopBody},
ast::{self, HasAttrs as _, HasGenericParams, HasLoopBody},
match_ast, AstNode, AstToken, Direction, SyntaxElement, SyntaxNode, SyntaxNodePtr, SyntaxToken,
TextSize, T,
};
@ -27,9 +27,9 @@ use crate::{
db::HirDatabase,
semantics::source_to_def::{ChildContainer, SourceToDefCache, SourceToDefCtx},
source_analyzer::{resolve_hir_path, SourceAnalyzer},
Access, AssocItem, BuiltinAttr, Callable, ConstParam, Crate, Field, Function, HasSource,
HirFileId, Impl, InFile, Label, LifetimeParam, Local, MacroDef, Module, ModuleDef, Name, Path,
ScopeDef, ToolModule, Trait, Type, TypeAlias, TypeParam, VariantDef,
Access, AssocItem, BuiltinAttr, Callable, ConstParam, Crate, Field, Function, HasAttrs as _,
HasSource, HirFileId, Impl, InFile, Label, LifetimeParam, Local, MacroDef, Module, ModuleDef,
Name, Path, ScopeDef, ToolModule, Trait, Type, TypeAlias, TypeParam, VariantDef,
};
#[derive(Debug, Clone, PartialEq, Eq)]
@ -486,7 +486,7 @@ impl<'db> SemanticsImpl<'db> {
let adt = InFile::new(file_id, &adt);
let src = InFile::new(file_id, attr.clone());
self.with_ctx(|ctx| {
let res = ctx.attr_to_derive_macro_call(adt, src)?;
let (_, res) = ctx.attr_to_derive_macro_call(adt, src)?;
Some(res.to_vec())
})
}
@ -917,15 +917,14 @@ impl<'db> SemanticsImpl<'db> {
let tt = derive.token_tree()?;
let file = self.find_file(derive.syntax());
let adt = derive.syntax().parent().and_then(ast::Adt::cast)?;
let adt_def = ToDef::to_def(self, file.with_value(adt.clone()))?;
let res = self.with_ctx(|ctx| {
let attr_def = ctx.attr_to_def(file.with_value(derive.clone()))?;
let derives = ctx.attr_to_derive_macro_call(
let (attr_id, derives) = ctx.attr_to_derive_macro_call(
file.with_value(&adt),
file.with_value(derive.clone()),
)?;
let mut derive_paths = attr_def.parse_path_comma_token_tree()?;
let attrs = adt_def.attrs(self.db);
let mut derive_paths = attrs[attr_id].parse_path_comma_token_tree()?;
let derive_idx = tt
.syntax()
@ -1225,7 +1224,6 @@ to_def_impls![
(crate::Local, ast::SelfParam, self_param_to_def),
(crate::Label, ast::Label, label_to_def),
(crate::Adt, ast::Adt, adt_to_def),
(crate::Attr, ast::Attr, attr_to_def),
];
fn find_root(node: &SyntaxNode) -> SyntaxNode {

View File

@ -87,6 +87,7 @@
use base_db::FileId;
use hir_def::{
attr::AttrId,
child_by_source::ChildBySource,
dyn_map::DynMap,
expr::{LabelId, PatId},
@ -210,19 +211,6 @@ impl SourceToDefCtx<'_, '_> {
ast::Adt::Union(it) => self.union_to_def(InFile::new(file_id, it)).map(AdtId::UnionId),
}
}
pub(super) fn attr_to_def(
&mut self,
InFile { file_id, value }: InFile<ast::Attr>,
) -> Option<crate::Attr> {
// FIXME: Use dynmap?
let adt = value.syntax().parent().and_then(ast::Adt::cast)?;
let attr_pos = ast::HasAttrs::attrs(&adt).position(|it| it == value)?;
let attrs = {
let def = self.adt_to_def(InFile::new(file_id, adt))?;
self.db.attrs(def.into())
};
attrs.get(attr_pos).cloned()
}
pub(super) fn bind_pat_to_def(
&mut self,
src: InFile<ast::IdentPat>,
@ -254,16 +242,16 @@ impl SourceToDefCtx<'_, '_> {
pub(super) fn item_to_macro_call(&mut self, src: InFile<ast::Item>) -> Option<MacroCallId> {
let map = self.dyn_map(src.as_ref())?;
map[keys::ATTR_MACRO].get(&src).copied()
map[keys::ATTR_MACRO_CALL].get(&src).copied()
}
pub(super) fn attr_to_derive_macro_call(
&mut self,
item: InFile<&ast::Adt>,
src: InFile<ast::Attr>,
) -> Option<&[Option<MacroCallId>]> {
) -> Option<(AttrId, &[Option<MacroCallId>])> {
let map = self.dyn_map(item)?;
map[keys::DERIVE_MACRO].get(&src).map(AsRef::as_ref)
map[keys::DERIVE_MACRO_CALL].get(&src).map(|(id, ids)| (*id, &**ids))
}
fn to_def<Ast: AstNode + 'static, ID: Copy + 'static>(
@ -328,7 +316,8 @@ impl SourceToDefCtx<'_, '_> {
}
pub(super) fn macro_to_def(&mut self, src: InFile<ast::Macro>) -> Option<MacroDefId> {
let makro = self.dyn_map(src.as_ref()).and_then(|it| it[keys::MACRO].get(&src).copied());
let makro =
self.dyn_map(src.as_ref()).and_then(|it| it[keys::MACRO_CALL].get(&src).copied());
if let res @ Some(_) = makro {
return res;
}

View File

@ -6,7 +6,7 @@
use either::Either;
use hir_expand::HirFileId;
use syntax::ast::HasAttrs;
use syntax::ast::HasDocComments;
use crate::{
db::DefDatabase,
@ -110,7 +110,7 @@ impl ChildBySource for ItemScope {
// FIXME: Do we need to add proc-macros into a PROCMACRO dynmap here?
Either::Right(_fn) => return,
};
res[keys::MACRO].insert(src, makro);
res[keys::MACRO_CALL].insert(src, makro);
}
});
self.unnamed_consts().for_each(|konst| {
@ -120,13 +120,16 @@ impl ChildBySource for ItemScope {
self.impls().for_each(|imp| add_impl(db, file_id, res, imp));
self.attr_macro_invocs().for_each(|(ast_id, call_id)| {
let item = ast_id.with_value(ast_id.to_node(db.upcast()));
res[keys::ATTR_MACRO].insert(item, call_id);
res[keys::ATTR_MACRO_CALL].insert(item, call_id);
});
self.derive_macro_invocs().for_each(|(ast_id, calls)| {
let item = ast_id.to_node(db.upcast());
let adt = ast_id.to_node(db.upcast());
for (attr_id, calls) in calls {
if let Some(attr) = item.attrs().nth(attr_id.ast_index as usize) {
res[keys::DERIVE_MACRO].insert(ast_id.with_value(attr), calls.into());
if let Some(Either::Right(attr)) =
adt.doc_comments_and_attrs().nth(attr_id.ast_index as usize)
{
res[keys::DERIVE_MACRO_CALL]
.insert(ast_id.with_value(attr), (attr_id, calls.into()));
}
}
});

View File

@ -67,7 +67,7 @@ pub struct ItemScope {
/// The derive macro invocations in this scope, keyed by the owner item over the actual derive attributes
/// paired with the derive macro invocations for the specific attribute.
derive_macros:
FxHashMap<AstId<ast::Item>, SmallVec<[(AttrId, SmallVec<[Option<MacroCallId>; 1]>); 1]>>,
FxHashMap<AstId<ast::Adt>, SmallVec<[(AttrId, SmallVec<[Option<MacroCallId>; 1]>); 1]>>,
}
pub(crate) static BUILTIN_SCOPE: Lazy<FxHashMap<Name, PerNs>> = Lazy::new(|| {
@ -204,12 +204,12 @@ impl ItemScope {
pub(crate) fn set_derive_macro_invoc(
&mut self,
item: AstId<ast::Item>,
adt: AstId<ast::Adt>,
call: MacroCallId,
attr_id: AttrId,
idx: usize,
) {
if let Some(derives) = self.derive_macros.get_mut(&item) {
if let Some(derives) = self.derive_macros.get_mut(&adt) {
if let Some((_, invocs)) = derives.iter_mut().find(|&&mut (id, _)| id == attr_id) {
invocs[idx] = Some(call);
}
@ -221,17 +221,17 @@ impl ItemScope {
/// independent of their indices.
pub(crate) fn init_derive_attribute(
&mut self,
item: AstId<ast::Item>,
adt: AstId<ast::Adt>,
attr_id: AttrId,
len: usize,
) {
self.derive_macros.entry(item).or_default().push((attr_id, smallvec![None; len]));
self.derive_macros.entry(adt).or_default().push((attr_id, smallvec![None; len]));
}
pub(crate) fn derive_macro_invocs(
&self,
) -> impl Iterator<
Item = (AstId<ast::Item>, impl Iterator<Item = (AttrId, &[Option<MacroCallId>])>),
Item = (AstId<ast::Adt>, impl Iterator<Item = (AttrId, &[Option<MacroCallId>])>),
> + '_ {
self.derive_macros
.iter()

View File

@ -7,6 +7,7 @@ use rustc_hash::FxHashMap;
use syntax::{ast, AstNode, AstPtr};
use crate::{
attr::AttrId,
dyn_map::{DynMap, Policy},
ConstId, ConstParamId, EnumId, EnumVariantId, FieldId, FunctionId, ImplId, LifetimeParamId,
StaticId, StructId, TraitId, TypeAliasId, TypeParamId, UnionId,
@ -31,9 +32,9 @@ pub const TYPE_PARAM: Key<ast::TypeParam, TypeParamId> = Key::new();
pub const LIFETIME_PARAM: Key<ast::LifetimeParam, LifetimeParamId> = Key::new();
pub const CONST_PARAM: Key<ast::ConstParam, ConstParamId> = Key::new();
pub const MACRO: Key<ast::Macro, MacroDefId> = Key::new();
pub const ATTR_MACRO: Key<ast::Item, MacroCallId> = Key::new();
pub const DERIVE_MACRO: Key<ast::Attr, Box<[Option<MacroCallId>]>> = Key::new();
pub const MACRO_CALL: Key<ast::Macro, MacroDefId> = Key::new();
pub const ATTR_MACRO_CALL: Key<ast::Item, MacroCallId> = Key::new();
pub const DERIVE_MACRO_CALL: Key<ast::Attr, (AttrId, Box<[Option<MacroCallId>]>)> = Key::new();
/// XXX: AST Nodes and SyntaxNodes have identity equality semantics: nodes are
/// equal if they point to exactly the same object.

View File

@ -751,7 +751,7 @@ fn macro_call_as_call_id(
}
fn derive_macro_as_call_id(
item_attr: &AstIdWithPath<ast::Item>,
item_attr: &AstIdWithPath<ast::Adt>,
derive_attr: AttrId,
db: &dyn db::DefDatabase,
krate: CrateId,

View File

@ -8,6 +8,7 @@ use std::iter;
use base_db::{CrateId, Edition, FileId, ProcMacroId};
use cfg::{CfgExpr, CfgOptions};
use hir_expand::{
ast_id_map::FileAstId,
builtin_attr_macro::find_builtin_attr,
builtin_derive_macro::find_builtin_derive,
builtin_fn_macro::find_builtin_macro,
@ -30,8 +31,8 @@ use crate::{
intern::Interned,
item_scope::{ImportType, PerNsGlobImports},
item_tree::{
self, Fields, FileItemTreeId, ImportKind, ItemTree, ItemTreeId, MacroCall, MacroDef,
MacroRules, Mod, ModItem, ModKind, TreeId,
self, Fields, FileItemTreeId, ImportKind, ItemTree, ItemTreeId, ItemTreeNode, MacroCall,
MacroDef, MacroRules, Mod, ModItem, ModKind, TreeId,
},
macro_call_as_call_id,
nameres::{
@ -217,7 +218,7 @@ struct MacroDirective {
#[derive(Clone, Debug, Eq, PartialEq)]
enum MacroDirectiveKind {
FnLike { ast_id: AstIdWithPath<ast::MacroCall>, expand_to: ExpandTo },
Derive { ast_id: AstIdWithPath<ast::Item>, derive_attr: AttrId, derive_pos: usize },
Derive { ast_id: AstIdWithPath<ast::Adt>, derive_attr: AttrId, derive_pos: usize },
Attr { ast_id: AstIdWithPath<ast::Item>, attr: Attr, mod_item: ModItem, tree: TreeId },
}
@ -1129,8 +1130,11 @@ impl DefCollector<'_> {
) {
// Resolved to `#[derive]`
match mod_item {
ModItem::Struct(_) | ModItem::Union(_) | ModItem::Enum(_) => (),
let item_tree = tree.item_tree(self.db);
let ast_adt_id: FileAstId<ast::Adt> = match *mod_item {
ModItem::Struct(strukt) => item_tree[strukt].ast_id().upcast(),
ModItem::Union(union) => item_tree[union].ast_id().upcast(),
ModItem::Enum(enum_) => item_tree[enum_].ast_id().upcast(),
_ => {
let diag = DefDiagnostic::invalid_derive_target(
directive.module_id,
@ -1140,7 +1144,8 @@ impl DefCollector<'_> {
self.def_map.diagnostics.push(diag);
return recollect_without(self);
}
}
};
let ast_id = ast_id.with_value(ast_adt_id);
match attr.parse_path_comma_token_tree() {
Some(derive_macros) => {
@ -1274,7 +1279,7 @@ impl DefCollector<'_> {
if let Some(def) = def_map.exported_proc_macros.get(&loc.def) {
if let ProcMacroKind::CustomDerive { helpers } = &def.kind {
self.derive_helpers_in_scope
.entry(*ast_id)
.entry(ast_id.map(|it| it.upcast()))
.or_default()
.extend(helpers.iter().cloned());
}

View File

@ -33,7 +33,7 @@ pub enum DefDiagnosticKind {
InvalidDeriveTarget { ast: AstId<ast::Item>, id: u32 },
MalformedDerive { ast: AstId<ast::Item>, id: u32 },
MalformedDerive { ast: AstId<ast::Adt>, id: u32 },
}
#[derive(Debug, PartialEq, Eq)]
@ -121,7 +121,7 @@ impl DefDiagnostic {
pub(super) fn malformed_derive(
container: LocalModuleId,
ast: AstId<ast::Item>,
ast: AstId<ast::Adt>,
id: AttrId,
) -> Self {
Self {

View File

@ -121,7 +121,7 @@ pub enum MacroCallKind {
expand_to: ExpandTo,
},
Derive {
ast_id: AstId<ast::Item>,
ast_id: AstId<ast::Adt>,
derive_name: Box<str>,
/// Syntactical index of the invoking `#[derive]` attribute.
///
@ -328,11 +328,10 @@ impl MacroDefId {
impl MacroCallKind {
/// Returns the file containing the macro invocation.
fn file_id(&self) -> HirFileId {
match self {
MacroCallKind::FnLike { ast_id, .. } => ast_id.file_id,
MacroCallKind::Derive { ast_id, .. } | MacroCallKind::Attr { ast_id, .. } => {
ast_id.file_id
}
match *self {
MacroCallKind::FnLike { ast_id: InFile { file_id, .. }, .. }
| MacroCallKind::Derive { ast_id: InFile { file_id, .. }, .. }
| MacroCallKind::Attr { ast_id: InFile { file_id, .. }, .. } => file_id,
}
}
@ -341,7 +340,10 @@ impl MacroCallKind {
MacroCallKind::FnLike { ast_id, .. } => {
ast_id.with_value(ast_id.to_node(db).syntax().clone())
}
MacroCallKind::Derive { ast_id, .. } | MacroCallKind::Attr { ast_id, .. } => {
MacroCallKind::Derive { ast_id, .. } => {
ast_id.with_value(ast_id.to_node(db).syntax().clone())
}
MacroCallKind::Attr { ast_id, .. } => {
ast_id.with_value(ast_id.to_node(db).syntax().clone())
}
}
@ -352,9 +354,8 @@ impl MacroCallKind {
MacroCallKind::FnLike { ast_id, .. } => {
Some(ast_id.to_node(db).token_tree()?.syntax().clone())
}
MacroCallKind::Derive { ast_id, .. } | MacroCallKind::Attr { ast_id, .. } => {
Some(ast_id.to_node(db).syntax().clone())
}
MacroCallKind::Derive { ast_id, .. } => Some(ast_id.to_node(db).syntax().clone()),
MacroCallKind::Attr { ast_id, .. } => Some(ast_id.to_node(db).syntax().clone()),
}
}

View File

@ -80,6 +80,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
.numeric_literal { color: #BFEBBF; }
.bool_literal { color: #BFE6EB; }
.macro { color: #94BFF3; }
.derive { color: #94BFF3; font-style: italic; }
.module { color: #AFD8AF; }
.value_param { color: #DCDCCC; }
.variable { color: #DCDCCC; }

View File

@ -28,6 +28,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
.numeric_literal { color: #BFEBBF; }
.bool_literal { color: #BFE6EB; }
.macro { color: #94BFF3; }
.derive { color: #94BFF3; font-style: italic; }
.module { color: #AFD8AF; }
.value_param { color: #DCDCCC; }
.variable { color: #DCDCCC; }

View File

@ -28,6 +28,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
.numeric_literal { color: #BFEBBF; }
.bool_literal { color: #BFE6EB; }
.macro { color: #94BFF3; }
.derive { color: #94BFF3; font-style: italic; }
.module { color: #AFD8AF; }
.value_param { color: #DCDCCC; }
.variable { color: #DCDCCC; }

View File

@ -28,6 +28,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
.numeric_literal { color: #BFEBBF; }
.bool_literal { color: #BFE6EB; }
.macro { color: #94BFF3; }
.derive { color: #94BFF3; font-style: italic; }
.module { color: #AFD8AF; }
.value_param { color: #DCDCCC; }
.variable { color: #DCDCCC; }

View File

@ -28,6 +28,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
.numeric_literal { color: #BFEBBF; }
.bool_literal { color: #BFE6EB; }
.macro { color: #94BFF3; }
.derive { color: #94BFF3; font-style: italic; }
.module { color: #AFD8AF; }
.value_param { color: #DCDCCC; }
.variable { color: #DCDCCC; }

View File

@ -28,6 +28,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
.numeric_literal { color: #BFEBBF; }
.bool_literal { color: #BFE6EB; }
.macro { color: #94BFF3; }
.derive { color: #94BFF3; font-style: italic; }
.module { color: #AFD8AF; }
.value_param { color: #DCDCCC; }
.variable { color: #DCDCCC; }

View File

@ -28,6 +28,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
.numeric_literal { color: #BFEBBF; }
.bool_literal { color: #BFE6EB; }
.macro { color: #94BFF3; }
.derive { color: #94BFF3; font-style: italic; }
.module { color: #AFD8AF; }
.value_param { color: #DCDCCC; }
.variable { color: #DCDCCC; }

View File

@ -28,6 +28,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
.numeric_literal { color: #BFEBBF; }
.bool_literal { color: #BFE6EB; }
.macro { color: #94BFF3; }
.derive { color: #94BFF3; font-style: italic; }
.module { color: #AFD8AF; }
.value_param { color: #DCDCCC; }
.variable { color: #DCDCCC; }

View File

@ -28,6 +28,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
.numeric_literal { color: #BFEBBF; }
.bool_literal { color: #BFE6EB; }
.macro { color: #94BFF3; }
.derive { color: #94BFF3; font-style: italic; }
.module { color: #AFD8AF; }
.value_param { color: #DCDCCC; }
.variable { color: #DCDCCC; }

View File

@ -28,6 +28,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
.numeric_literal { color: #BFEBBF; }
.bool_literal { color: #BFE6EB; }
.macro { color: #94BFF3; }
.derive { color: #94BFF3; font-style: italic; }
.module { color: #AFD8AF; }
.value_param { color: #DCDCCC; }
.variable { color: #DCDCCC; }
@ -89,7 +90,17 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
<span class="brace">}</span>
<span class="keyword">use</span> <span class="self_keyword crate_root">self</span><span class="operator">::</span><span class="struct">FooCopy</span><span class="operator">::</span><span class="brace">{</span><span class="self_keyword">self</span> <span class="keyword">as</span> <span class="struct declaration">BarCopy</span><span class="brace">}</span><span class="semicolon">;</span>
<span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="attribute attribute default_library library">derive</span><span class="parenthesis attribute">(</span><span class="derive attribute default_library library">Copy</span><span class="parenthesis attribute">)</span><span class="attribute_bracket attribute">]</span>
<span class="comment documentation">/// This is a doc comment</span>
<span class="comment">// This is a normal comment</span>
<span class="comment documentation">/// This is a doc comment</span>
<span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="attribute attribute default_library library">derive</span><span class="parenthesis attribute">(</span><span class="derive attribute default_library library">Copy</span><span class="parenthesis attribute">)</span><span class="attribute_bracket attribute">]</span>
<span class="comment">// This is another normal comment</span>
<span class="comment documentation">/// This is another doc comment</span>
<span class="comment">// This is another normal comment</span>
<span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="attribute attribute default_library library">derive</span><span class="parenthesis attribute">(</span><span class="derive attribute default_library library">Copy</span><span class="parenthesis attribute">)</span><span class="attribute_bracket attribute">]</span>
<span class="comment">// The reason for these being here is to test AttrIds</span>
<span class="keyword">struct</span> <span class="struct declaration">FooCopy</span> <span class="brace">{</span>
<span class="field declaration">x</span><span class="colon">:</span> <span class="builtin_type">u32</span><span class="comma">,</span>
<span class="brace">}</span>

View File

@ -28,6 +28,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
.numeric_literal { color: #BFEBBF; }
.bool_literal { color: #BFE6EB; }
.macro { color: #94BFF3; }
.derive { color: #94BFF3; font-style: italic; }
.module { color: #AFD8AF; }
.value_param { color: #DCDCCC; }
.variable { color: #DCDCCC; }

View File

@ -28,6 +28,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
.numeric_literal { color: #BFEBBF; }
.bool_literal { color: #BFE6EB; }
.macro { color: #94BFF3; }
.derive { color: #94BFF3; font-style: italic; }
.module { color: #AFD8AF; }
.value_param { color: #DCDCCC; }
.variable { color: #DCDCCC; }

View File

@ -62,7 +62,17 @@ impl Foo {
}
use self::FooCopy::{self as BarCopy};
#[derive(Copy)]
/// This is a doc comment
// This is a normal comment
/// This is a doc comment
#[derive(Copy)]
// This is another normal comment
/// This is another doc comment
// This is another normal comment
#[derive(Copy)]
// The reason for these being here is to test AttrIds
struct FooCopy {
x: u32,
}