Skip to content
Merged
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
60 changes: 60 additions & 0 deletions compiler/rustc_attr_parsing/src/attributes/debugger.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
use rustc_hir::attrs::{DebugVisualizer, DebuggerVisualizerType};

use super::prelude::*;

pub(crate) struct DebuggerViualizerParser;

impl<S: Stage> CombineAttributeParser<S> for DebuggerViualizerParser {
const PATH: &[Symbol] = &[sym::debugger_visualizer];
const ALLOWED_TARGETS: AllowedTargets =
AllowedTargets::AllowList(&[Allow(Target::Mod), Allow(Target::Crate)]);
const TEMPLATE: AttributeTemplate = template!(
List: &[r#"natvis_file = "...", gdb_script_file = "...""#],
"https://doc.rust-lang.org/reference/attributes/debugger.html#the-debugger_visualizer-attribute"
);

type Item = DebugVisualizer;
const CONVERT: ConvertFn<Self::Item> = |v, _| AttributeKind::DebuggerVisualizer(v);

fn extend<'c>(
cx: &'c mut AcceptContext<'_, '_, S>,
args: &'c ArgParser<'_>,
) -> impl IntoIterator<Item = Self::Item> + 'c {
let Some(l) = args.list() else {
cx.expected_list(args.span().unwrap_or(cx.attr_span));
return None;
};
let Some(single) = l.single() else {
cx.expected_single_argument(l.span);
return None;
};
let Some(mi) = single.meta_item() else {
cx.expected_name_value(single.span(), None);
return None;
};
let path = mi.path().word_sym();
let visualizer_type = match path {
Some(sym::natvis_file) => DebuggerVisualizerType::Natvis,
Some(sym::gdb_script_file) => DebuggerVisualizerType::GdbPrettyPrinter,
_ => {
cx.expected_specific_argument(
mi.path().span(),
&[sym::natvis_file, sym::gdb_script_file],
);
return None;
}
};

let Some(path) = mi.args().name_value() else {
cx.expected_name_value(single.span(), path);
return None;
};

let Some(path) = path.value_as_str() else {
cx.expected_string_literal(path.value_span, Some(path.value_as_lit()));
return None;
};

Some(DebugVisualizer { span: mi.span(), visualizer_type, path })
}
}
1 change: 1 addition & 0 deletions compiler/rustc_attr_parsing/src/attributes/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ pub(crate) mod cfg_old;
pub(crate) mod codegen_attrs;
pub(crate) mod confusables;
pub(crate) mod crate_level;
pub(crate) mod debugger;
pub(crate) mod deprecation;
pub(crate) mod dummy;
pub(crate) mod inline;
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_attr_parsing/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ use crate::attributes::crate_level::{
CrateNameParser, MoveSizeLimitParser, NoCoreParser, NoStdParser, PatternComplexityLimitParser,
RecursionLimitParser, RustcCoherenceIsCoreParser, TypeLengthLimitParser,
};
use crate::attributes::debugger::DebuggerViualizerParser;
use crate::attributes::deprecation::DeprecationParser;
use crate::attributes::dummy::DummyParser;
use crate::attributes::inline::{InlineParser, RustcForceInlineParser};
Expand Down Expand Up @@ -163,6 +164,7 @@ attribute_parsers!(
// tidy-alphabetical-start
Combine<AllowConstFnUnstableParser>,
Combine<AllowInternalUnstableParser>,
Combine<DebuggerViualizerParser>,
Combine<ForceTargetFeatureParser>,
Combine<LinkParser>,
Combine<ReprParser>,
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

use rustc_codegen_ssa::base::collect_debugger_visualizers_transitive;
use rustc_codegen_ssa::traits::*;
use rustc_hir::attrs::DebuggerVisualizerType;
use rustc_hir::def_id::LOCAL_CRATE;
use rustc_middle::bug;
use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerType;
use rustc_session::config::{CrateType, DebugInfo};

use crate::builder::Builder;
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_codegen_ssa/src/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@ use rustc_data_structures::fx::{FxHashMap, FxIndexSet};
use rustc_data_structures::profiling::{get_resident_set_size, print_time_passes_entry};
use rustc_data_structures::sync::{IntoDynSyncSend, par_map};
use rustc_data_structures::unord::UnordMap;
use rustc_hir::attrs::OptimizeAttr;
use rustc_hir::attrs::{DebuggerVisualizerType, OptimizeAttr};
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
use rustc_hir::lang_items::LangItem;
use rustc_hir::{ItemId, Target};
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
use rustc_middle::middle::debugger_visualizer::{DebuggerVisualizerFile, DebuggerVisualizerType};
use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile;
use rustc_middle::middle::dependency_format::Dependencies;
use rustc_middle::middle::exported_symbols::{self, SymbolExportKind};
use rustc_middle::middle::lang_items;
Expand Down
19 changes: 18 additions & 1 deletion compiler/rustc_hir/src/attrs/data_structures.rs
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,20 @@ pub struct LinkEntry {
pub import_name_type: Option<(PeImportNameType, Span)>,
}

#[derive(HashStable_Generic, PrintAttribute)]
#[derive(Copy, PartialEq, PartialOrd, Clone, Ord, Eq, Hash, Debug, Encodable, Decodable)]
pub enum DebuggerVisualizerType {
Natvis,
GdbPrettyPrinter,
}

#[derive(Debug, Encodable, Decodable, Clone, HashStable_Generic, PrintAttribute)]
pub struct DebugVisualizer {
pub span: Span,
pub visualizer_type: DebuggerVisualizerType,
pub path: Symbol,
}

/// Represents parsed *built-in* inert attributes.
///
/// ## Overview
Expand Down Expand Up @@ -485,7 +499,10 @@ pub enum AttributeKind {
/// Represents `#[custom_mir]`.
CustomMir(Option<(MirDialect, Span)>, Option<(MirPhase, Span)>, Span),

///Represents `#[rustc_deny_explicit_impl]`.
/// Represents `#[debugger_visualizer]`.
DebuggerVisualizer(ThinVec<DebugVisualizer>),

/// Represents `#[rustc_deny_explicit_impl]`.
DenyExplicitImpl(Span),

/// Represents [`#[deprecated]`](https://doc.rust-lang.org/stable/reference/attributes/diagnostics.html#the-deprecated-attribute).
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_hir/src/attrs/encode_cross_crate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ impl AttributeKind {
Coverage(..) => No,
CrateName { .. } => No,
CustomMir(_, _, _) => Yes,
DebuggerVisualizer(..) => No,
DenyExplicitImpl(..) => No,
Deprecation { .. } => Yes,
DoNotImplementViaObject(..) => No,
Expand Down
8 changes: 1 addition & 7 deletions compiler/rustc_middle/src/middle/debugger_visualizer.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,9 @@
use std::path::PathBuf;
use std::sync::Arc;

use rustc_hir::attrs::DebuggerVisualizerType;
use rustc_macros::{Decodable, Encodable, HashStable};

#[derive(HashStable)]
#[derive(Copy, PartialEq, PartialOrd, Clone, Ord, Eq, Hash, Debug, Encodable, Decodable)]
pub enum DebuggerVisualizerType {
Natvis,
GdbPrettyPrinter,
}

/// A single debugger visualizer file.
#[derive(HashStable)]
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Encodable, Decodable)]
Expand Down
9 changes: 0 additions & 9 deletions compiler/rustc_passes/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -93,15 +93,6 @@ passes_dead_codes =
}
} never {$participle}
passes_debug_visualizer_invalid =
invalid argument
.note_1 = expected: `natvis_file = "..."`
.note_2 = OR
.note_3 = expected: `gdb_script_file = "..."`
passes_debug_visualizer_placement =
attribute should be applied to a module
passes_debug_visualizer_unreadable =
couldn't read {$file}: {$error}
Expand Down
16 changes: 1 addition & 15 deletions compiler/rustc_passes/src/check_attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
| AttributeKind::ObjcClass { .. }
| AttributeKind::ObjcSelector { .. }
| AttributeKind::RustcCoherenceIsCore(..)
| AttributeKind::DebuggerVisualizer(..)
) => { /* do nothing */ }
Attribute::Unparsed(attr_item) => {
style = Some(attr_item.style);
Expand All @@ -301,7 +302,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
&mut doc_aliases,
),
[sym::no_link, ..] => self.check_no_link(hir_id, attr, span, target),
[sym::debugger_visualizer, ..] => self.check_debugger_visualizer(attr, target),
[sym::rustc_no_implicit_autorefs, ..] => {
self.check_applied_to_fn_or_method(hir_id, attr.span(), span, target)
}
Expand Down Expand Up @@ -1782,20 +1782,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
}
}

/// Checks if the items on the `#[debugger_visualizer]` attribute are valid.
fn check_debugger_visualizer(&self, attr: &Attribute, target: Target) {
// Here we only check that the #[debugger_visualizer] attribute is attached
// to nothing other than a module. All other checks are done in the
// `debugger_visualizer` query where they need to be done for decoding
// anyway.
match target {
Target::Mod => {}
_ => {
self.dcx().emit_err(errors::DebugVisualizerPlacement { span: attr.span() });
}
}
}

/// Outputs an error for `#[allow_internal_unstable]` which can only be applied to macros.
/// (Allows proc_macro functions)
fn check_rustc_allow_const_fn_unstable(
Expand Down
113 changes: 56 additions & 57 deletions compiler/rustc_passes/src/debugger_visualizer.rs
Original file line number Diff line number Diff line change
@@ -1,67 +1,60 @@
//! Detecting usage of the `#[debugger_visualizer]` attribute.

use rustc_ast::Attribute;
use rustc_ast::ast::NodeId;
use rustc_ast::{HasNodeId, ItemKind, ast};
use rustc_attr_parsing::AttributeParser;
use rustc_expand::base::resolve_path;
use rustc_middle::middle::debugger_visualizer::{DebuggerVisualizerFile, DebuggerVisualizerType};
use rustc_hir::Attribute;
use rustc_hir::attrs::{AttributeKind, DebugVisualizer};
use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile;
use rustc_middle::query::{LocalCrate, Providers};
use rustc_middle::ty::TyCtxt;
use rustc_session::Session;
use rustc_span::sym;
use rustc_span::{DUMMY_SP, Span, sym};

use crate::errors::{DebugVisualizerInvalid, DebugVisualizerUnreadable};
use crate::errors::DebugVisualizerUnreadable;

impl DebuggerVisualizerCollector<'_> {
fn check_for_debugger_visualizer(&mut self, attr: &Attribute) {
if attr.has_name(sym::debugger_visualizer) {
let Some(hints) = attr.meta_item_list() else {
self.sess.dcx().emit_err(DebugVisualizerInvalid { span: attr.span });
return;
};
fn check_for_debugger_visualizer(
&mut self,
attrs: &[ast::Attribute],
span: Span,
node_id: NodeId,
) {
if let Some(Attribute::Parsed(AttributeKind::DebuggerVisualizer(visualizers))) =
AttributeParser::parse_limited(
&self.sess,
attrs,
sym::debugger_visualizer,
span,
node_id,
None,
)
{
for DebugVisualizer { span, visualizer_type, path } in visualizers {
let file = match resolve_path(&self.sess, path.as_str(), span) {
Ok(file) => file,
Err(err) => {
err.emit();
return;
}
};

let [hint] = hints.as_slice() else {
self.sess.dcx().emit_err(DebugVisualizerInvalid { span: attr.span });
return;
};

let Some(meta_item) = hint.meta_item() else {
self.sess.dcx().emit_err(DebugVisualizerInvalid { span: attr.span });
return;
};

let (visualizer_type, visualizer_path) = match (meta_item.name(), meta_item.value_str())
{
(Some(sym::natvis_file), Some(value)) => (DebuggerVisualizerType::Natvis, value),
(Some(sym::gdb_script_file), Some(value)) => {
(DebuggerVisualizerType::GdbPrettyPrinter, value)
}
(_, _) => {
self.sess.dcx().emit_err(DebugVisualizerInvalid { span: meta_item.span });
return;
}
};

let file = match resolve_path(&self.sess, visualizer_path.as_str(), attr.span) {
Ok(file) => file,
Err(err) => {
err.emit();
return;
}
};

match self.sess.source_map().load_binary_file(&file) {
Ok((source, _)) => {
self.visualizers.push(DebuggerVisualizerFile::new(
source,
visualizer_type,
file,
));
}
Err(error) => {
self.sess.dcx().emit_err(DebugVisualizerUnreadable {
span: meta_item.span,
file: &file,
error,
});
match self.sess.source_map().load_binary_file(&file) {
Ok((source, _)) => {
self.visualizers.push(DebuggerVisualizerFile::new(
source,
visualizer_type,
file,
));
}
Err(error) => {
self.sess.dcx().emit_err(DebugVisualizerUnreadable {
span,
file: &file,
error,
});
}
}
}
}
Expand All @@ -74,9 +67,15 @@ struct DebuggerVisualizerCollector<'a> {
}

impl<'ast> rustc_ast::visit::Visitor<'ast> for DebuggerVisualizerCollector<'_> {
fn visit_attribute(&mut self, attr: &'ast Attribute) {
self.check_for_debugger_visualizer(attr);
rustc_ast::visit::walk_attribute(self, attr);
fn visit_item(&mut self, item: &'ast rustc_ast::Item) -> Self::Result {
if let ItemKind::Mod(..) = item.kind {
self.check_for_debugger_visualizer(&item.attrs, item.span, item.node_id());
}
rustc_ast::visit::walk_item(self, item);
}
fn visit_crate(&mut self, krate: &'ast ast::Crate) -> Self::Result {
self.check_for_debugger_visualizer(&krate.attrs, DUMMY_SP, krate.id);
rustc_ast::visit::walk_crate(self, krate);
}
}

Expand Down
17 changes: 0 additions & 17 deletions compiler/rustc_passes/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -475,23 +475,6 @@ pub(crate) struct MacroOnlyAttribute {
pub span: Span,
}

#[derive(Diagnostic)]
#[diag(passes_debug_visualizer_placement)]
pub(crate) struct DebugVisualizerPlacement {
#[primary_span]
pub span: Span,
}

#[derive(Diagnostic)]
#[diag(passes_debug_visualizer_invalid)]
#[note(passes_note_1)]
#[note(passes_note_2)]
#[note(passes_note_3)]
pub(crate) struct DebugVisualizerInvalid {
#[primary_span]
pub span: Span,
}

#[derive(Diagnostic)]
#[diag(passes_debug_visualizer_unreadable)]
pub(crate) struct DebugVisualizerUnreadable<'a> {
Expand Down
3 changes: 1 addition & 2 deletions tests/ui/attributes/malformed-attrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -185,8 +185,7 @@ extern "C" {
#[forbid]
//~^ ERROR malformed
#[debugger_visualizer]
//~^ ERROR invalid argument
//~| ERROR malformed `debugger_visualizer` attribute input
//~^ ERROR malformed `debugger_visualizer` attribute input
#[automatically_derived = 18]
//~^ ERROR malformed
mod yooo {
Expand Down
Loading
Loading