mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-26 08:44:35 +00:00
Add a "diagnostic item" scheme
This allows lints and other diagnostics to refer to items by a unique ID instead of relying on whacky path resolution schemes that may break when items are relocated.
This commit is contained in:
parent
fbdf1d2a71
commit
26e9990198
@ -291,6 +291,7 @@ use crate::raw_vec::RawVec;
|
||||
/// [`reserve`]: ../../std/vec/struct.Vec.html#method.reserve
|
||||
/// [owned slice]: ../../std/boxed/struct.Box.html
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[cfg_attr(all(not(bootstrap), not(test)), rustc_diagnostic_item = "vec_type")]
|
||||
pub struct Vec<T> {
|
||||
buf: RawVec<T>,
|
||||
len: usize,
|
||||
|
@ -518,7 +518,8 @@ impl Display for Arguments<'_> {
|
||||
label="`{Self}` cannot be formatted using `{{:?}}` because it doesn't implement `{Debug}`",
|
||||
)]
|
||||
#[doc(alias = "{:?}")]
|
||||
#[lang = "debug_trait"]
|
||||
#[cfg_attr(boostrap_stdarch_ignore_this, lang = "debug_trait")]
|
||||
#[cfg_attr(not(boostrap_stdarch_ignore_this), rustc_diagnostic_item = "debug_trait")]
|
||||
pub trait Debug {
|
||||
/// Formats the value using the given formatter.
|
||||
///
|
||||
|
@ -94,6 +94,10 @@ macro_rules! arena_types {
|
||||
rustc::hir::def_id::CrateNum
|
||||
>
|
||||
>,
|
||||
[few] diagnostic_items: rustc_data_structures::fx::FxHashMap<
|
||||
syntax::symbol::Symbol,
|
||||
rustc::hir::def_id::DefId,
|
||||
>,
|
||||
[few] resolve_lifetimes: rustc::middle::resolve_lifetime::ResolveLifetimes,
|
||||
[decode] generic_predicates: rustc::ty::GenericPredicates<'tcx>,
|
||||
[few] lint_levels: rustc::lint::LintLevelMap,
|
||||
|
@ -62,6 +62,7 @@
|
||||
#![feature(log_syntax)]
|
||||
#![feature(mem_take)]
|
||||
#![feature(associated_type_bounds)]
|
||||
#![feature(rustc_attrs)]
|
||||
|
||||
#![recursion_limit="512"]
|
||||
|
||||
@ -109,6 +110,7 @@ pub mod middle {
|
||||
pub mod cstore;
|
||||
pub mod dead;
|
||||
pub mod dependency_format;
|
||||
pub mod diagnostic_items;
|
||||
pub mod entry;
|
||||
pub mod exported_symbols;
|
||||
pub mod free_region;
|
||||
|
@ -159,29 +159,23 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TyTyKind {
|
||||
}
|
||||
|
||||
fn lint_ty_kind_usage(cx: &LateContext<'_, '_>, segment: &PathSegment) -> bool {
|
||||
if segment.ident.name == sym::TyKind {
|
||||
if let Some(res) = segment.res {
|
||||
if let Some(did) = res.opt_def_id() {
|
||||
return cx.match_def_path(did, TYKIND_PATH);
|
||||
}
|
||||
if let Some(res) = segment.res {
|
||||
if let Some(did) = res.opt_def_id() {
|
||||
return cx.tcx.is_diagnostic_item(sym::TyKind, did);
|
||||
}
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
const TYKIND_PATH: &[Symbol] = &[sym::rustc, sym::ty, sym::sty, sym::TyKind];
|
||||
const TY_PATH: &[Symbol] = &[sym::rustc, sym::ty, sym::Ty];
|
||||
const TYCTXT_PATH: &[Symbol] = &[sym::rustc, sym::ty, sym::context, sym::TyCtxt];
|
||||
|
||||
fn is_ty_or_ty_ctxt(cx: &LateContext<'_, '_>, ty: &Ty) -> Option<String> {
|
||||
match &ty.node {
|
||||
TyKind::Path(qpath) => {
|
||||
if let QPath::Resolved(_, path) = qpath {
|
||||
let did = path.res.opt_def_id()?;
|
||||
if cx.match_def_path(did, TY_PATH) {
|
||||
if cx.tcx.is_diagnostic_item(sym::Ty, did) {
|
||||
return Some(format!("Ty{}", gen_args(path.segments.last().unwrap())));
|
||||
} else if cx.match_def_path(did, TYCTXT_PATH) {
|
||||
} else if cx.tcx.is_diagnostic_item(sym::TyCtxt, did) {
|
||||
return Some(format!("TyCtxt{}", gen_args(path.segments.last().unwrap())));
|
||||
}
|
||||
}
|
||||
|
123
src/librustc/middle/diagnostic_items.rs
Normal file
123
src/librustc/middle/diagnostic_items.rs
Normal file
@ -0,0 +1,123 @@
|
||||
//! Detecting diagnostic items.
|
||||
//!
|
||||
//! Diagnostic items are items that are not language-inherent, but can reasonably be expected to
|
||||
//! exist for diagnostic purposes. This allows diagnostic authors to refer to specific items
|
||||
//! directly, without having to guess module paths and crates.
|
||||
//! Examples are:
|
||||
//!
|
||||
//! * Traits like `Debug`, that have no bearing on language semantics
|
||||
//!
|
||||
//! * Compiler internal types like `Ty` and `TyCtxt`
|
||||
|
||||
use crate::hir::def_id::{DefId, LOCAL_CRATE};
|
||||
use crate::ty::TyCtxt;
|
||||
use crate::util::nodemap::FxHashMap;
|
||||
|
||||
use syntax::ast;
|
||||
use syntax::symbol::{Symbol, sym};
|
||||
use crate::hir::itemlikevisit::ItemLikeVisitor;
|
||||
use crate::hir;
|
||||
|
||||
struct DiagnosticItemCollector<'tcx> {
|
||||
// items from this crate
|
||||
items: FxHashMap<Symbol, DefId>,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
}
|
||||
|
||||
impl<'v, 'tcx> ItemLikeVisitor<'v> for DiagnosticItemCollector<'tcx> {
|
||||
fn visit_item(&mut self, item: &hir::Item) {
|
||||
self.observe_item(&item.attrs, item.hir_id);
|
||||
}
|
||||
|
||||
fn visit_trait_item(&mut self, trait_item: &hir::TraitItem) {
|
||||
self.observe_item(&trait_item.attrs, trait_item.hir_id);
|
||||
}
|
||||
|
||||
fn visit_impl_item(&mut self, impl_item: &hir::ImplItem) {
|
||||
self.observe_item(&impl_item.attrs, impl_item.hir_id);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> DiagnosticItemCollector<'tcx> {
|
||||
fn new(tcx: TyCtxt<'tcx>) -> DiagnosticItemCollector<'tcx> {
|
||||
DiagnosticItemCollector {
|
||||
tcx,
|
||||
items: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
fn observe_item(&mut self, attrs: &[ast::Attribute], hir_id: hir::HirId) {
|
||||
if let Some(name) = extract(attrs) {
|
||||
let def_id = self.tcx.hir().local_def_id(hir_id);
|
||||
// insert into our table
|
||||
collect_item(self.tcx, &mut self.items, name, def_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn collect_item(
|
||||
tcx: TyCtxt<'_>,
|
||||
items: &mut FxHashMap<Symbol, DefId>,
|
||||
name: Symbol,
|
||||
item_def_id: DefId,
|
||||
) {
|
||||
// Check for duplicates.
|
||||
if let Some(original_def_id) = items.insert(name, item_def_id) {
|
||||
if original_def_id != item_def_id {
|
||||
let mut err = match tcx.hir().span_if_local(item_def_id) {
|
||||
Some(span) => tcx.sess.struct_span_err(
|
||||
span,
|
||||
&format!("duplicate diagnostic item found: `{}`.", name)),
|
||||
None => tcx.sess.struct_err(&format!(
|
||||
"duplicate diagnostic item in crate `{}`: `{}`.",
|
||||
tcx.crate_name(item_def_id.krate),
|
||||
name)),
|
||||
};
|
||||
if let Some(span) = tcx.hir().span_if_local(original_def_id) {
|
||||
span_note!(&mut err, span, "first defined here.");
|
||||
} else {
|
||||
err.note(&format!("first defined in crate `{}`.",
|
||||
tcx.crate_name(original_def_id.krate)));
|
||||
}
|
||||
err.emit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Extract the first `rustc_diagnostic_item = "$name"` out of a list of attributes.
|
||||
fn extract(attrs: &[ast::Attribute]) -> Option<Symbol> {
|
||||
attrs.iter().find_map(|attr| {
|
||||
if attr.check_name(sym::rustc_diagnostic_item) {
|
||||
attr.value_str()
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/// Traverse and collect the diagnostic items in the current
|
||||
pub fn collect<'tcx>(tcx: TyCtxt<'tcx>) -> &'tcx FxHashMap<Symbol, DefId> {
|
||||
// Initialize the collector.
|
||||
let mut collector = DiagnosticItemCollector::new(tcx);
|
||||
|
||||
// Collect diagnostic items in this crate.
|
||||
tcx.hir().krate().visit_all_item_likes(&mut collector);
|
||||
|
||||
tcx.arena.alloc(collector.items)
|
||||
}
|
||||
|
||||
|
||||
/// Traverse and collect all the diagnostic items in all crates.
|
||||
pub fn collect_all<'tcx>(tcx: TyCtxt<'tcx>) -> &'tcx FxHashMap<Symbol, DefId> {
|
||||
// Initialize the collector.
|
||||
let mut collector = FxHashMap::default();
|
||||
|
||||
// Collect diagnostic items in other crates.
|
||||
for &cnum in tcx.crates().iter().chain(std::iter::once(&LOCAL_CRATE)) {
|
||||
for (&name, &def_id) in tcx.diagnostic_items(cnum).iter() {
|
||||
collect_item(tcx, &mut collector, name, def_id);
|
||||
}
|
||||
}
|
||||
|
||||
tcx.arena.alloc(collector)
|
||||
}
|
@ -367,8 +367,6 @@ language_item_table! {
|
||||
|
||||
MaybeUninitLangItem, "maybe_uninit", maybe_uninit, Target::Union;
|
||||
|
||||
DebugTraitLangItem, "debug_trait", debug_trait, Target::Trait;
|
||||
|
||||
// Align offset for stride != 1, must not panic.
|
||||
AlignOffsetLangItem, "align_offset", align_offset_fn, Target::Fn;
|
||||
|
||||
|
@ -804,7 +804,7 @@ rustc_queries! {
|
||||
}
|
||||
|
||||
BorrowChecking {
|
||||
// Lifetime resolution. See `middle::resolve_lifetimes`.
|
||||
/// Lifetime resolution. See `middle::resolve_lifetimes`.
|
||||
query resolve_lifetimes(_: CrateNum) -> &'tcx ResolveLifetimes {
|
||||
desc { "resolving lifetimes" }
|
||||
}
|
||||
@ -846,13 +846,30 @@ rustc_queries! {
|
||||
-> &'tcx [(Symbol, Option<Symbol>)] {
|
||||
desc { "calculating the lib features defined in a crate" }
|
||||
}
|
||||
/// Returns the lang items defined in another crate by loading it from metadata.
|
||||
// FIXME: It is illegal to pass a `CrateNum` other than `LOCAL_CRATE` here, just get rid
|
||||
// of that argument?
|
||||
query get_lang_items(_: CrateNum) -> &'tcx LanguageItems {
|
||||
eval_always
|
||||
desc { "calculating the lang items map" }
|
||||
}
|
||||
|
||||
/// Returns all diagnostic items defined in all crates
|
||||
query all_diagnostic_items(_: CrateNum) -> &'tcx FxHashMap<Symbol, DefId> {
|
||||
eval_always
|
||||
desc { "calculating the diagnostic items map" }
|
||||
}
|
||||
|
||||
/// Returns the lang items defined in another crate by loading it from metadata.
|
||||
query defined_lang_items(_: CrateNum) -> &'tcx [(DefId, usize)] {
|
||||
desc { "calculating the lang items defined in a crate" }
|
||||
}
|
||||
|
||||
/// Returns the diagnostic items defined in a crate
|
||||
query diagnostic_items(_: CrateNum) -> &'tcx FxHashMap<Symbol, DefId> {
|
||||
desc { "calculating the diagnostic items map in a crate" }
|
||||
}
|
||||
|
||||
query missing_lang_items(_: CrateNum) -> &'tcx [LangItem] {
|
||||
desc { "calculating the missing lang items in a crate" }
|
||||
}
|
||||
|
@ -978,6 +978,7 @@ pub struct FreeRegionInfo {
|
||||
///
|
||||
/// [rustc guide]: https://rust-lang.github.io/rustc-guide/ty.html
|
||||
#[derive(Copy, Clone)]
|
||||
#[cfg_attr(not(bootstrap), rustc_diagnostic_item = "TyCtxt")]
|
||||
pub struct TyCtxt<'tcx> {
|
||||
gcx: &'tcx GlobalCtxt<'tcx>,
|
||||
}
|
||||
@ -1308,10 +1309,22 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
self.get_lib_features(LOCAL_CRATE)
|
||||
}
|
||||
|
||||
/// Obtain all lang items of this crate and all dependencies (recursively)
|
||||
pub fn lang_items(self) -> &'tcx middle::lang_items::LanguageItems {
|
||||
self.get_lang_items(LOCAL_CRATE)
|
||||
}
|
||||
|
||||
/// Obtain the given diagnostic item's `DefId`. Use `is_diagnostic_item` if you just want to
|
||||
/// compare against another `DefId`, since `is_diagnostic_item` is cheaper.
|
||||
pub fn get_diagnostic_item(self, name: Symbol) -> Option<DefId> {
|
||||
self.all_diagnostic_items(LOCAL_CRATE).get(&name).copied()
|
||||
}
|
||||
|
||||
/// Check whether the diagnostic item with the given `name` has the given `DefId`.
|
||||
pub fn is_diagnostic_item(self, name: Symbol, did: DefId) -> bool {
|
||||
self.diagnostic_items(did.krate).get(&name) == Some(&did)
|
||||
}
|
||||
|
||||
pub fn stability(self) -> &'tcx stability::Index<'tcx> {
|
||||
self.stability_index(LOCAL_CRATE)
|
||||
}
|
||||
@ -2896,6 +2909,14 @@ pub fn provide(providers: &mut ty::query::Providers<'_>) {
|
||||
assert_eq!(id, LOCAL_CRATE);
|
||||
tcx.arena.alloc(middle::lang_items::collect(tcx))
|
||||
};
|
||||
providers.diagnostic_items = |tcx, id| {
|
||||
assert_eq!(id, LOCAL_CRATE);
|
||||
middle::diagnostic_items::collect(tcx)
|
||||
};
|
||||
providers.all_diagnostic_items = |tcx, id| {
|
||||
assert_eq!(id, LOCAL_CRATE);
|
||||
middle::diagnostic_items::collect_all(tcx)
|
||||
};
|
||||
providers.maybe_unused_trait_import = |tcx, id| {
|
||||
tcx.maybe_unused_trait_imports.contains(&id)
|
||||
};
|
||||
|
@ -581,6 +581,7 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for ty::TyS<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(not(bootstrap), rustc_diagnostic_item = "Ty")]
|
||||
pub type Ty<'tcx> = &'tcx TyS<'tcx>;
|
||||
|
||||
impl<'tcx> rustc_serialize::UseSpecializedEncodable for Ty<'tcx> {}
|
||||
|
@ -86,6 +86,7 @@ impl BoundRegion {
|
||||
/// AST structure in `libsyntax/ast.rs` as well.
|
||||
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash,
|
||||
RustcEncodable, RustcDecodable, HashStable, Debug)]
|
||||
#[cfg_attr(not(bootstrap), rustc_diagnostic_item = "TyKind")]
|
||||
pub enum TyKind<'tcx> {
|
||||
/// The primitive boolean type. Written as `bool`.
|
||||
Bool,
|
||||
|
@ -570,7 +570,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDebugImplementations {
|
||||
_ => return,
|
||||
}
|
||||
|
||||
let debug = match cx.tcx.lang_items().debug_trait() {
|
||||
let debug = match cx.tcx.get_diagnostic_item(sym::debug_trait) {
|
||||
Some(debug) => debug,
|
||||
None => return,
|
||||
};
|
||||
|
@ -226,6 +226,7 @@ provide! { <'tcx> tcx, def_id, other, cdata,
|
||||
}
|
||||
defined_lib_features => { cdata.get_lib_features(tcx) }
|
||||
defined_lang_items => { cdata.get_lang_items(tcx) }
|
||||
diagnostic_items => { cdata.get_diagnostic_items(tcx) }
|
||||
missing_lang_items => { cdata.get_missing_lang_items(tcx) }
|
||||
|
||||
missing_extern_crate_item => {
|
||||
|
@ -12,6 +12,7 @@ use rustc::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel};
|
||||
use rustc::hir::def::{self, Res, DefKind, CtorOf, CtorKind};
|
||||
use rustc::hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE};
|
||||
use rustc_data_structures::fingerprint::Fingerprint;
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc::middle::lang_items;
|
||||
use rustc::mir::{self, interpret};
|
||||
use rustc::mir::interpret::AllocDecodingSession;
|
||||
@ -757,6 +758,23 @@ impl<'a, 'tcx> CrateMetadata {
|
||||
}
|
||||
}
|
||||
|
||||
/// Iterates over the diagnostic items in the given crate.
|
||||
pub fn get_diagnostic_items(
|
||||
&self,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
) -> &'tcx FxHashMap<Symbol, DefId> {
|
||||
tcx.arena.alloc(if self.is_proc_macro_crate() {
|
||||
// Proc macro crates do not export any diagnostic-items to the target.
|
||||
Default::default()
|
||||
} else {
|
||||
self.root
|
||||
.diagnostic_items
|
||||
.decode(self)
|
||||
.map(|(name, def_index)| (name, self.local_def_id(def_index)))
|
||||
.collect()
|
||||
})
|
||||
}
|
||||
|
||||
/// Iterates over each child of the given item.
|
||||
pub fn each_child_of_item<F>(&self, id: DefIndex, mut callback: F, sess: &Session)
|
||||
where F: FnMut(def::Export<hir::HirId>)
|
||||
|
@ -33,7 +33,7 @@ use syntax::ast;
|
||||
use syntax::attr;
|
||||
use syntax::ext::proc_macro::is_proc_macro_attr;
|
||||
use syntax::source_map::Spanned;
|
||||
use syntax::symbol::{kw, sym, Ident};
|
||||
use syntax::symbol::{kw, sym, Ident, Symbol};
|
||||
use syntax_pos::{self, FileName, SourceFile, Span};
|
||||
use log::{debug, trace};
|
||||
|
||||
@ -404,6 +404,11 @@ impl<'tcx> EncodeContext<'tcx> {
|
||||
let lang_items_missing = self.encode_lang_items_missing();
|
||||
let lang_item_bytes = self.position() - i;
|
||||
|
||||
// Encode the diagnostic items.
|
||||
i = self.position();
|
||||
let diagnostic_items = self.encode_diagnostic_items();
|
||||
let diagnostic_item_bytes = self.position() - i;
|
||||
|
||||
// Encode the native libraries used
|
||||
i = self.position();
|
||||
let native_libraries = self.encode_native_libraries();
|
||||
@ -520,6 +525,7 @@ impl<'tcx> EncodeContext<'tcx> {
|
||||
dylib_dependency_formats,
|
||||
lib_features,
|
||||
lang_items,
|
||||
diagnostic_items,
|
||||
lang_items_missing,
|
||||
native_libraries,
|
||||
foreign_modules,
|
||||
@ -545,6 +551,7 @@ impl<'tcx> EncodeContext<'tcx> {
|
||||
println!(" dep bytes: {}", dep_bytes);
|
||||
println!(" lib feature bytes: {}", lib_feature_bytes);
|
||||
println!(" lang item bytes: {}", lang_item_bytes);
|
||||
println!(" diagnostic item bytes: {}", diagnostic_item_bytes);
|
||||
println!(" native bytes: {}", native_lib_bytes);
|
||||
println!(" source_map bytes: {}", source_map_bytes);
|
||||
println!(" impl bytes: {}", impl_bytes);
|
||||
@ -1555,6 +1562,12 @@ impl EncodeContext<'tcx> {
|
||||
self.lazy(lib_features.to_vec())
|
||||
}
|
||||
|
||||
fn encode_diagnostic_items(&mut self) -> Lazy<[(Symbol, DefIndex)]> {
|
||||
let tcx = self.tcx;
|
||||
let diagnostic_items = tcx.diagnostic_items(LOCAL_CRATE);
|
||||
self.lazy(diagnostic_items.iter().map(|(&name, def_id)| (name, def_id.index)))
|
||||
}
|
||||
|
||||
fn encode_lang_items(&mut self) -> Lazy<[(DefIndex, usize)]> {
|
||||
let tcx = self.tcx;
|
||||
let lang_items = tcx.lang_items();
|
||||
|
@ -176,6 +176,7 @@ pub struct CrateRoot<'tcx> {
|
||||
pub lib_features: Lazy<[(Symbol, Option<Symbol>)]>,
|
||||
pub lang_items: Lazy<[(DefIndex, usize)]>,
|
||||
pub lang_items_missing: Lazy<[lang_items::LangItem]>,
|
||||
pub diagnostic_items: Lazy<[(Symbol, DefIndex)]>,
|
||||
pub native_libraries: Lazy<[NativeLibrary]>,
|
||||
pub foreign_modules: Lazy<[ForeignModule]>,
|
||||
pub source_map: Lazy<[syntax_pos::SourceFile]>,
|
||||
|
@ -461,6 +461,17 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
|
||||
lang, Normal, template!(NameValueStr: "name"), lang_items,
|
||||
"language items are subject to change",
|
||||
),
|
||||
(
|
||||
sym::rustc_diagnostic_item,
|
||||
Normal,
|
||||
template!(NameValueStr: "name"),
|
||||
Gated(
|
||||
Stability::Unstable,
|
||||
sym::rustc_attrs,
|
||||
"diagnostic items compiler internal support for linting",
|
||||
cfg_fn!(rustc_attrs),
|
||||
),
|
||||
),
|
||||
(
|
||||
sym::no_debug, Whitelisted, template!(Word),
|
||||
Gated(
|
||||
|
@ -225,9 +225,10 @@ symbols! {
|
||||
custom_inner_attributes,
|
||||
custom_test_frameworks,
|
||||
c_variadic,
|
||||
Debug,
|
||||
debug_trait,
|
||||
declare_lint_pass,
|
||||
decl_macro,
|
||||
Debug,
|
||||
Decodable,
|
||||
Default,
|
||||
default_lib_allocator,
|
||||
@ -238,6 +239,7 @@ symbols! {
|
||||
deref,
|
||||
deref_mut,
|
||||
derive,
|
||||
diagnostic,
|
||||
direct,
|
||||
doc,
|
||||
doc_alias,
|
||||
@ -569,6 +571,7 @@ symbols! {
|
||||
rustc_conversion_suggestion,
|
||||
rustc_def_path,
|
||||
rustc_deprecated,
|
||||
rustc_diagnostic_item,
|
||||
rustc_diagnostic_macros,
|
||||
rustc_dirty,
|
||||
rustc_dummy,
|
||||
|
2
src/test/ui/tool-attributes/diagnostic_item.rs
Normal file
2
src/test/ui/tool-attributes/diagnostic_item.rs
Normal file
@ -0,0 +1,2 @@
|
||||
#[rustc_diagnostic_item = "foomp"] //~ ERROR will never be stabilized
|
||||
struct Foomp;
|
17
src/test/ui/tool-attributes/diagnostic_item.stderr
Normal file
17
src/test/ui/tool-attributes/diagnostic_item.stderr
Normal file
@ -0,0 +1,17 @@
|
||||
error[E0658]: diagnostic items compiler are internal support for linting and will never be stabilized
|
||||
--> $DIR/diagnostic_item.rs:1:1
|
||||
|
|
||||
LL | #[rustc_diagnostic_item = "foomp"]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: for more information, see https://github.com/rust-lang/rust/issues/29642
|
||||
= help: add `#![feature(rustc_attrs)]` to the crate attributes to enable
|
||||
|
||||
error[E0601]: `main` function not found in crate `diagnostic_item`
|
||||
|
|
||||
= note: consider adding a `main` function to `$DIR/diagnostic_item.rs`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0601, E0658.
|
||||
For more information about an error, try `rustc --explain E0601`.
|
6
src/test/ui/tool-attributes/diagnostic_item2.rs
Normal file
6
src/test/ui/tool-attributes/diagnostic_item2.rs
Normal file
@ -0,0 +1,6 @@
|
||||
// check-pass
|
||||
|
||||
#[clippy::diagnostic_item = "mep"]
|
||||
struct Mep;
|
||||
|
||||
fn main() {}
|
7
src/test/ui/tool-attributes/diagnostic_item3.rs
Normal file
7
src/test/ui/tool-attributes/diagnostic_item3.rs
Normal file
@ -0,0 +1,7 @@
|
||||
// check-pass
|
||||
#![feature(rustc_attrs)]
|
||||
|
||||
#[rustc_diagnostic_item = "foomp"]
|
||||
struct Foomp;
|
||||
|
||||
fn main() {}
|
Loading…
Reference in New Issue
Block a user