Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions compiler/rustc_ast/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3394,6 +3394,9 @@ pub enum AttrKind {
/// Doc attributes (e.g. `#[doc="..."]`) are represented with the `Normal`
/// variant (which is much less compact and thus more expensive).
DocComment(CommentKind, Symbol),

/// A regular (non-doc) comment.
Comment(CommentKind, Symbol),
}

#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
Expand Down
8 changes: 4 additions & 4 deletions compiler/rustc_ast/src/ast_traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -173,16 +173,16 @@ impl HasTokens for Attribute {
fn tokens(&self) -> Option<&LazyAttrTokenStream> {
match &self.kind {
AttrKind::Normal(normal) => normal.tokens.as_ref(),
kind @ AttrKind::DocComment(..) => {
panic!("Called tokens on doc comment attr {kind:?}")
kind @ (AttrKind::DocComment(..) | AttrKind::Comment(..)) => {
panic!("Called tokens on (doc) comment attr {kind:?}")
}
}
}
fn tokens_mut(&mut self) -> Option<&mut Option<LazyAttrTokenStream>> {
Some(match &mut self.kind {
AttrKind::Normal(normal) => &mut normal.tokens,
kind @ AttrKind::DocComment(..) => {
panic!("Called tokens_mut on doc comment attr {kind:?}")
kind @ (AttrKind::DocComment(..) | AttrKind::Comment(..)) => {
panic!("Called tokens_mut on (doc) comment attr {kind:?}")
}
})
}
Expand Down
49 changes: 36 additions & 13 deletions compiler/rustc_ast/src/attr/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ impl Attribute {
pub fn get_normal_item(&self) -> &AttrItem {
match &self.kind {
AttrKind::Normal(normal) => &normal.item,
AttrKind::DocComment(..) => panic!("unexpected doc comment"),
AttrKind::DocComment(..) | AttrKind::Comment(..) => panic!("unexpected (doc) comment"),
}
}

Expand All @@ -71,14 +71,14 @@ impl Attribute {
pub fn replace_args(&mut self, new_args: AttrItemKind) {
match &mut self.kind {
AttrKind::Normal(normal) => normal.item.args = new_args,
AttrKind::DocComment(..) => panic!("unexpected doc comment"),
AttrKind::DocComment(..) | AttrKind::Comment(..) => panic!("unexpected (doc) comment"),
}
}

pub fn unwrap_normal_item(self) -> AttrItem {
match self.kind {
AttrKind::Normal(normal) => normal.item,
AttrKind::DocComment(..) => panic!("unexpected doc comment"),
AttrKind::DocComment(..) | AttrKind::Comment(..) => panic!("unexpected (doc) comment"),
}
}
}
Expand All @@ -94,7 +94,7 @@ impl AttributeExt for Attribute {
AttrArgs::Eq { expr, .. } => Some(expr.span),
_ => None,
},
AttrKind::DocComment(..) => None,
AttrKind::DocComment(..) | AttrKind::Comment(..) => None,
}
}

Expand All @@ -103,7 +103,7 @@ impl AttributeExt for Attribute {
/// a doc comment) will return `false`.
fn is_doc_comment(&self) -> Option<Span> {
match self.kind {
AttrKind::Normal(..) => None,
AttrKind::Normal(..) | AttrKind::Comment(..) => None,
AttrKind::DocComment(..) => Some(self.span),
}
}
Expand All @@ -118,7 +118,7 @@ impl AttributeExt for Attribute {
None
}
}
AttrKind::DocComment(..) => None,
AttrKind::DocComment(..) | AttrKind::Comment(..) => None,
}
}

Expand All @@ -127,14 +127,14 @@ impl AttributeExt for Attribute {
AttrKind::Normal(p) => {
Some(p.item.path.segments.iter().map(|i| i.ident.name).collect())
}
AttrKind::DocComment(_, _) => None,
AttrKind::DocComment(_, _) | AttrKind::Comment(_, _) => None,
}
}

fn path_span(&self) -> Option<Span> {
match &self.kind {
AttrKind::Normal(attr) => Some(attr.item.path.span),
AttrKind::DocComment(_, _) => None,
AttrKind::DocComment(_, _) | AttrKind::Comment(_, _) => None,
}
}

Expand All @@ -150,7 +150,7 @@ impl AttributeExt for Attribute {
.zip(name)
.all(|(s, n)| s.args.is_none() && s.ident.name == *n)
}
AttrKind::DocComment(..) => false,
AttrKind::DocComment(..) | AttrKind::Comment(..) => false,
}
}

Expand All @@ -176,7 +176,7 @@ impl AttributeExt for Attribute {
fn meta_item_list(&self) -> Option<ThinVec<MetaItemInner>> {
match &self.kind {
AttrKind::Normal(normal) => normal.item.meta_item_list(),
AttrKind::DocComment(..) => None,
AttrKind::DocComment(..) | AttrKind::Comment(..) => None,
}
}

Expand All @@ -198,7 +198,7 @@ impl AttributeExt for Attribute {
fn value_str(&self) -> Option<Symbol> {
match &self.kind {
AttrKind::Normal(normal) => normal.item.value_str(),
AttrKind::DocComment(..) => None,
AttrKind::DocComment(..) | AttrKind::Comment(..) => None,
}
}

Expand Down Expand Up @@ -266,6 +266,7 @@ impl AttributeExt for Attribute {
fn doc_resolution_scope(&self) -> Option<AttrStyle> {
match &self.kind {
AttrKind::DocComment(..) => Some(self.style),
AttrKind::Comment(..) => None,
AttrKind::Normal(normal)
if normal.item.path == sym::doc && normal.item.value_str().is_some() =>
{
Expand Down Expand Up @@ -307,6 +308,11 @@ impl Attribute {
self.style
}

/// Returns `true` if this is a regular (non-doc) comment (`//` or `/* */`).
pub fn is_comment(&self) -> bool {
matches!(self.kind, AttrKind::Comment(..))
}

pub fn may_have_doc_links(&self) -> bool {
self.doc_str().is_some_and(|s| comments::may_have_doc_links(s.as_str()))
|| self.deprecation_note().is_some_and(|s| comments::may_have_doc_links(s.as_str()))
Expand All @@ -316,14 +322,14 @@ impl Attribute {
pub fn meta(&self) -> Option<MetaItem> {
match &self.kind {
AttrKind::Normal(normal) => normal.item.meta(self.span),
AttrKind::DocComment(..) => None,
AttrKind::DocComment(..) | AttrKind::Comment(..) => None,
}
}

pub fn meta_kind(&self) -> Option<MetaItemKind> {
match &self.kind {
AttrKind::Normal(normal) => normal.item.meta_kind(),
AttrKind::DocComment(..) => None,
AttrKind::DocComment(..) | AttrKind::Comment(..) => None,
}
}

Expand All @@ -339,6 +345,9 @@ impl Attribute {
token::DocComment(comment_kind, self.style, data),
self.span,
)],
// Regular comments are never part of any real token stream; returning
// an empty vec prevents them from being injected into macro inputs.
AttrKind::Comment(..) => vec![],
}
}
}
Expand Down Expand Up @@ -737,6 +746,20 @@ pub fn mk_doc_comment(
Attribute { kind: AttrKind::DocComment(comment_kind, data), id: g.mk_attr_id(), style, span }
}

pub fn mk_comment(
g: &AttrIdGenerator,
comment_kind: CommentKind,
data: Symbol,
span: Span,
) -> Attribute {
Attribute {
kind: AttrKind::Comment(comment_kind, data),
id: g.mk_attr_id(),
style: AttrStyle::Outer,
span,
}
}

fn mk_attr(
g: &AttrIdGenerator,
style: AttrStyle,
Expand Down
10 changes: 7 additions & 3 deletions compiler/rustc_ast/src/token.rs
Original file line number Diff line number Diff line change
Expand Up @@ -524,6 +524,10 @@ pub enum TokenKind {
/// similarly to symbols in string literal tokens.
DocComment(CommentKind, ast::AttrStyle, Symbol),

/// A regular (non-doc) comment token.
/// `Symbol` is the comment's data excluding its delimiters (`//`, `/*`, `*/`).
Comment(CommentKind, Symbol),

/// End Of File
Eof,
}
Expand Down Expand Up @@ -654,8 +658,8 @@ impl Token {
| FatArrow | Pound | Dollar | Question | SingleQuote => true,

OpenParen | CloseParen | OpenBrace | CloseBrace | OpenBracket | CloseBracket
| OpenInvisible(_) | CloseInvisible(_) | Literal(..) | DocComment(..) | Ident(..)
| NtIdent(..) | Lifetime(..) | NtLifetime(..) | Eof => false,
| OpenInvisible(_) | CloseInvisible(_) | Literal(..) | DocComment(..) | Comment(..)
| Ident(..) | NtIdent(..) | Lifetime(..) | NtLifetime(..) | Eof => false,
}
}

Expand Down Expand Up @@ -1072,7 +1076,7 @@ impl Token {
| Comma | Semi | PathSep | RArrow | LArrow | FatArrow | Pound | Dollar | Question
| OpenParen | CloseParen | OpenBrace | CloseBrace | OpenBracket | CloseBracket
| OpenInvisible(_) | CloseInvisible(_) | Literal(..) | Ident(..) | NtIdent(..)
| Lifetime(..) | NtLifetime(..) | DocComment(..) | Eof,
| Lifetime(..) | NtLifetime(..) | DocComment(..) | Comment(..) | Eof,
_,
) => {
return None;
Expand Down
20 changes: 20 additions & 0 deletions compiler/rustc_ast_pretty/src/pprust/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -696,6 +696,22 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
));
self.hardbreak()
}
ast::AttrKind::Comment(comment_kind, data) => {
// Printing here too would duplicate every comment.
// Only emit from the AST attribute when there is no source text available.
if self.comments().is_some() {
return false;
}
match comment_kind {
ast::token::CommentKind::Line => {
self.word(format!("//{}", data));
}
ast::token::CommentKind::Block => {
self.word(format!("/*{}*/", data));
}
}
self.hardbreak()
}
}
true
}
Expand Down Expand Up @@ -1095,6 +1111,10 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
doc_comment_to_string(DocFragmentKind::Sugared(comment_kind), attr_style, data)
.into()
}
token::Comment(comment_kind, data) => match comment_kind {
token::CommentKind::Line => format!("//{data}").into(),
token::CommentKind::Block => format!("/*{data}*/").into(),
},
token::Eof => "<eof>".into(),
}
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_ast_pretty/src/pprust/state/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -420,7 +420,7 @@ impl<'a> State<'a> {
// let _ = add_attr!(1 + 1);
//
// We must pretty-print `#[attr] (1 + 1)` not `#[attr] 1 + 1`.
!attrs.is_empty()
attrs.iter().any(|a| !a.is_comment())
&& matches!(
expr.kind,
ast::ExprKind::Binary(..)
Expand Down
3 changes: 3 additions & 0 deletions compiler/rustc_attr_parsing/src/interface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,9 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
comment: *symbol,
}));
}
// Regular comments have no semantic meaning
// for attribute parsing; skip them.
ast::AttrKind::Comment(..) => continue,
ast::AttrKind::Normal(n) => {
attr_paths.push(PathParser(&n.item.path));
let attr_path = AttrPath::from_ast(&n.item.path, lower_span);
Expand Down
5 changes: 4 additions & 1 deletion compiler/rustc_attr_parsing/src/validate_attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,10 @@ use rustc_span::{Span, Symbol, sym};
use crate::{AttributeParser, Late, session_diagnostics as errors};

pub fn check_attr(psess: &ParseSess, attr: &Attribute) {
if attr.is_doc_comment() || attr.has_name(sym::cfg_trace) || attr.has_name(sym::cfg_attr_trace)
if attr.is_doc_comment()
|| attr.is_comment()
|| attr.has_name(sym::cfg_trace)
|| attr.has_name(sym::cfg_attr_trace)
{
return;
}
Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_builtin_macros/src/asm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,10 @@ fn validate_asm_args<'a>(

for arg in args {
for attr in arg.attributes.0.iter() {
// FIXME: can we simply skip them?
if attr.is_comment() {
continue;
}
if !matches!(attr.name(), Some(sym::cfg | sym::cfg_attr)) {
ecx.dcx().emit_err(errors::AsmAttributeNotSupported { span: attr.span() });
}
Expand Down
6 changes: 5 additions & 1 deletion compiler/rustc_expand/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ pub(crate) fn attr_into_trace(mut attr: Attribute, trace_name: Symbol) -> Attrib
// This makes the trace attributes unobservable to token-based proc macros.
*tokens = Some(LazyAttrTokenStream::new_direct(AttrTokenStream::default()));
}
AttrKind::DocComment(..) => unreachable!(),
AttrKind::DocComment(..) | AttrKind::Comment(..) => unreachable!(),
}
attr
}
Expand Down Expand Up @@ -415,6 +415,10 @@ impl<'a> StripUnconfigured<'a> {
/// If attributes are not allowed on expressions, emit an error for `attr`
#[instrument(level = "trace", skip(self))]
pub(crate) fn maybe_emit_expr_attr_err(&self, attr: &Attribute) {
// Regular comments are never "real" attributes.
if attr.is_comment() {
return;
}
if self.features.is_some_and(|features| !features.stmt_expr_attributes())
&& !attr.span.allows_unstable(sym::stmt_expr_attributes)
{
Expand Down
5 changes: 4 additions & 1 deletion compiler/rustc_expand/src/expand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2114,7 +2114,10 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
let mut cfg_pos = None;
let mut attr_pos = None;
for (pos, attr) in item.attrs().iter().enumerate() {
if !attr.is_doc_comment() && !self.cx.expanded_inert_attrs.is_marked(attr) {
if !attr.is_doc_comment()
&& !attr.is_comment()
&& !self.cx.expanded_inert_attrs.is_marked(attr)
{
let name = attr.name();
if name == Some(sym::cfg) || name == Some(sym::cfg_attr) {
cfg_pos = Some(pos); // a cfg attr found, no need to search anymore
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_expand/src/mbe/macro_rules.rs
Original file line number Diff line number Diff line change
Expand Up @@ -925,10 +925,10 @@ fn is_empty_token_tree(sess: &Session, seq: &mbe::SequenceRepetition) -> bool {
while let Some(tt) = iter.next() {
match tt {
mbe::TokenTree::MetaVarDecl { kind: NonterminalKind::Vis, .. } => {}
mbe::TokenTree::Token(t @ Token { kind: DocComment(..), .. }) => {
mbe::TokenTree::Token(t @ Token { kind: DocComment(..) | Comment(..), .. }) => {
let mut now = t;
while let Some(&mbe::TokenTree::Token(
next @ Token { kind: DocComment(..), .. },
next @ Token { kind: DocComment(..) | Comment(..), .. },
)) = iter.peek()
{
now = next;
Expand Down
6 changes: 6 additions & 0 deletions compiler/rustc_expand/src/mbe/quoted.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,12 @@ fn parse(
// additional trees if need be.
let mut iter = input.iter();
while let Some(tree) = iter.next() {
// Skip regular comments.
// They have no semantic meaning in macro rules.
if let tokenstream::TokenTree::Token(Token { kind: token::Comment(..), .. }, _) = tree {
continue;
}

// Given the parsed tree, if there is a metavar and we are expecting matchers, actually
// parse out the matcher (i.e., in `$id:ident` this would parse the `:` and `ident`).
let tree = parse_tree(tree, &mut iter, part, sess, node_id, features, edition);
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_expand/src/proc_macro_server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,8 @@ impl FromInternal<TokenStream> for Vec<TokenTree<TokenStream, Span, Symbol>> {
span: DelimSpan::from_single(span),
}));
}
// FIXME: would it be safe to put an `unreachable!()` here?
Comment(..) => {}

OpenParen | CloseParen | OpenBrace | CloseBrace | OpenBracket | CloseBracket
| OpenInvisible(_) | CloseInvisible(_) | Eof => unreachable!(),
Expand Down
11 changes: 5 additions & 6 deletions compiler/rustc_lint/src/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -825,12 +825,11 @@ fn warn_if_doc(cx: &EarlyContext<'_>, node_span: Span, node_kind: &str, attrs: &

if is_doc_comment || is_doc_attribute {
let sub = match attr.kind {
AttrKind::DocComment(CommentKind::Line, _) | AttrKind::Normal(..) => {
BuiltinUnusedDocCommentSub::PlainHelp
}
AttrKind::DocComment(CommentKind::Block, _) => {
BuiltinUnusedDocCommentSub::BlockHelp
}
AttrKind::DocComment(CommentKind::Line, _)
| AttrKind::Normal(..)
| AttrKind::Comment(CommentKind::Line, _) => BuiltinUnusedDocCommentSub::PlainHelp,
AttrKind::DocComment(CommentKind::Block, _)
| AttrKind::Comment(CommentKind::Block, _) => BuiltinUnusedDocCommentSub::BlockHelp,
};
cx.emit_span_lint(
UNUSED_DOC_COMMENTS,
Expand Down
Loading
Loading