mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 06:44:35 +00:00
Auto merge of #116855 - matthiaskrgr:rollup-i2izdwb, r=matthiaskrgr
Rollup of 5 pull requests Successful merges: - #111072 (Add new simpler and more explicit syntax for check-cfg) - #116717 (Special case iterator chain checks for suggestion) - #116719 (Add MonoItems and Instance to stable_mir) - #116787 (Implement an internal lint encouraging use of `Span::eq_ctxt`) - #116827 (Make `handle_options` public again.) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
94ba57cef4
@ -1185,7 +1185,11 @@ fn print_flag_list<T>(
|
||||
///
|
||||
/// So with all that in mind, the comments below have some more detail about the
|
||||
/// contortions done here to get things to work out correctly.
|
||||
fn handle_options(handler: &EarlyErrorHandler, args: &[String]) -> Option<getopts::Matches> {
|
||||
///
|
||||
/// This does not need to be `pub` for rustc itself, but @chaosite needs it to
|
||||
/// be public when using rustc as a library, see
|
||||
/// <https://github.com/rust-lang/rust/commit/2b4c33817a5aaecabf4c6598d41e190080ec119e>
|
||||
pub fn handle_options(handler: &EarlyErrorHandler, args: &[String]) -> Option<getopts::Matches> {
|
||||
if args.is_empty() {
|
||||
// user did not write `-v` nor `-Z unstable-options`, so do not
|
||||
// include that extra information.
|
||||
|
@ -650,7 +650,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
.sess
|
||||
.source_map()
|
||||
.is_multiline(call_expr.span.with_lo(callee_expr.span.hi()))
|
||||
&& call_expr.span.ctxt() == callee_expr.span.ctxt();
|
||||
&& call_expr.span.eq_ctxt(callee_expr.span);
|
||||
if call_is_multiline {
|
||||
err.span_suggestion(
|
||||
callee_expr.span.shrink_to_hi(),
|
||||
|
@ -125,8 +125,13 @@ pub fn parse_cfgspecs(
|
||||
/// Converts strings provided as `--check-cfg [specs]` into a `CheckCfg`.
|
||||
pub fn parse_check_cfg(handler: &EarlyErrorHandler, specs: Vec<String>) -> CheckCfg {
|
||||
rustc_span::create_default_session_if_not_set_then(move |_| {
|
||||
let mut check_cfg = CheckCfg::default();
|
||||
// If any --check-cfg is passed then exhaustive_values and exhaustive_names
|
||||
// are enabled by default.
|
||||
let exhaustive_names = !specs.is_empty();
|
||||
let exhaustive_values = !specs.is_empty();
|
||||
let mut check_cfg = CheckCfg { exhaustive_names, exhaustive_values, ..CheckCfg::default() };
|
||||
|
||||
let mut old_syntax = None;
|
||||
for s in specs {
|
||||
let sess = ParseSess::with_silent_emitter(Some(format!(
|
||||
"this error occurred on the command line: `--check-cfg={s}`"
|
||||
@ -142,18 +147,21 @@ pub fn parse_check_cfg(handler: &EarlyErrorHandler, specs: Vec<String>) -> Check
|
||||
};
|
||||
}
|
||||
|
||||
let expected_error = || {
|
||||
error!(
|
||||
"expected `names(name1, name2, ... nameN)` or \
|
||||
`values(name, \"value1\", \"value2\", ... \"valueN\")`"
|
||||
)
|
||||
};
|
||||
let expected_error =
|
||||
|| error!("expected `cfg(name, values(\"value1\", \"value2\", ... \"valueN\"))`");
|
||||
|
||||
match maybe_new_parser_from_source_str(&sess, filename, s.to_string()) {
|
||||
Ok(mut parser) => match parser.parse_meta_item() {
|
||||
Ok(meta_item) if parser.token == token::Eof => {
|
||||
if let Some(args) = meta_item.meta_item_list() {
|
||||
if meta_item.has_name(sym::names) {
|
||||
// defaults are flipped for the old syntax
|
||||
if old_syntax == None {
|
||||
check_cfg.exhaustive_names = false;
|
||||
check_cfg.exhaustive_values = false;
|
||||
}
|
||||
old_syntax = Some(true);
|
||||
|
||||
check_cfg.exhaustive_names = true;
|
||||
for arg in args {
|
||||
if arg.is_word() && arg.ident().is_some() {
|
||||
@ -167,6 +175,13 @@ pub fn parse_check_cfg(handler: &EarlyErrorHandler, specs: Vec<String>) -> Check
|
||||
}
|
||||
}
|
||||
} else if meta_item.has_name(sym::values) {
|
||||
// defaults are flipped for the old syntax
|
||||
if old_syntax == None {
|
||||
check_cfg.exhaustive_names = false;
|
||||
check_cfg.exhaustive_values = false;
|
||||
}
|
||||
old_syntax = Some(true);
|
||||
|
||||
if let Some((name, values)) = args.split_first() {
|
||||
if name.is_word() && name.ident().is_some() {
|
||||
let ident = name.ident().expect("multi-segment cfg key");
|
||||
@ -216,6 +231,116 @@ pub fn parse_check_cfg(handler: &EarlyErrorHandler, specs: Vec<String>) -> Check
|
||||
} else {
|
||||
expected_error();
|
||||
}
|
||||
} else if meta_item.has_name(sym::cfg) {
|
||||
old_syntax = Some(false);
|
||||
|
||||
let mut names = Vec::new();
|
||||
let mut values: FxHashSet<_> = Default::default();
|
||||
|
||||
let mut any_specified = false;
|
||||
let mut values_specified = false;
|
||||
let mut values_any_specified = false;
|
||||
|
||||
for arg in args {
|
||||
if arg.is_word() && let Some(ident) = arg.ident() {
|
||||
if values_specified {
|
||||
error!("`cfg()` names cannot be after values");
|
||||
}
|
||||
names.push(ident);
|
||||
} else if arg.has_name(sym::any)
|
||||
&& let Some(args) = arg.meta_item_list()
|
||||
{
|
||||
if any_specified {
|
||||
error!("`any()` cannot be specified multiple times");
|
||||
}
|
||||
any_specified = true;
|
||||
if !args.is_empty() {
|
||||
error!("`any()` must be empty");
|
||||
}
|
||||
} else if arg.has_name(sym::values)
|
||||
&& let Some(args) = arg.meta_item_list()
|
||||
{
|
||||
if names.is_empty() {
|
||||
error!(
|
||||
"`values()` cannot be specified before the names"
|
||||
);
|
||||
} else if values_specified {
|
||||
error!(
|
||||
"`values()` cannot be specified multiple times"
|
||||
);
|
||||
}
|
||||
values_specified = true;
|
||||
|
||||
for arg in args {
|
||||
if let Some(LitKind::Str(s, _)) =
|
||||
arg.lit().map(|lit| &lit.kind)
|
||||
{
|
||||
values.insert(Some(s.to_string()));
|
||||
} else if arg.has_name(sym::any)
|
||||
&& let Some(args) = arg.meta_item_list()
|
||||
{
|
||||
if values_any_specified {
|
||||
error!(
|
||||
"`any()` in `values()` cannot be specified multiple times"
|
||||
);
|
||||
}
|
||||
values_any_specified = true;
|
||||
if !args.is_empty() {
|
||||
error!("`any()` must be empty");
|
||||
}
|
||||
} else {
|
||||
error!(
|
||||
"`values()` arguments must be string literals or `any()`"
|
||||
);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
error!(
|
||||
"`cfg()` arguments must be simple identifiers, `any()` or `values(...)`"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if values.is_empty() && !values_any_specified && !any_specified {
|
||||
values.insert(None);
|
||||
} else if !values.is_empty() && values_any_specified {
|
||||
error!(
|
||||
"`values()` arguments cannot specify string literals and `any()` at the same time"
|
||||
);
|
||||
}
|
||||
|
||||
if any_specified {
|
||||
if !names.is_empty()
|
||||
|| !values.is_empty()
|
||||
|| values_any_specified
|
||||
{
|
||||
error!("`cfg(any())` can only be provided in isolation");
|
||||
}
|
||||
|
||||
check_cfg.exhaustive_names = false;
|
||||
} else {
|
||||
for name in names {
|
||||
check_cfg
|
||||
.expecteds
|
||||
.entry(name.to_string())
|
||||
.and_modify(|v| match v {
|
||||
ExpectedValues::Some(v)
|
||||
if !values_any_specified =>
|
||||
{
|
||||
v.extend(values.clone())
|
||||
}
|
||||
ExpectedValues::Some(_) => *v = ExpectedValues::Any,
|
||||
ExpectedValues::Any => {}
|
||||
})
|
||||
.or_insert_with(|| {
|
||||
if values_any_specified {
|
||||
ExpectedValues::Any
|
||||
} else {
|
||||
ExpectedValues::Some(values.clone())
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
} else {
|
||||
expected_error();
|
||||
}
|
||||
|
@ -3,6 +3,7 @@
|
||||
#![feature(internal_output_capture)]
|
||||
#![feature(thread_spawn_unchecked)]
|
||||
#![feature(lazy_cell)]
|
||||
#![feature(let_chains)]
|
||||
#![feature(try_blocks)]
|
||||
#![recursion_limit = "256"]
|
||||
#![allow(rustc::potential_query_instability)]
|
||||
|
@ -494,6 +494,8 @@ lint_renamed_lint = lint `{$name}` has been renamed to `{$replace}`
|
||||
|
||||
lint_requested_level = requested on the command line with `{$level} {$lint_name}`
|
||||
|
||||
lint_span_use_eq_ctxt = use `.eq_ctxt()` instead of `.ctxt() == .ctxt()`
|
||||
|
||||
lint_supertrait_as_deref_target = `{$t}` implements `Deref` with supertrait `{$target_principal}` as target
|
||||
.label = target type is set here
|
||||
|
||||
|
@ -3,14 +3,14 @@
|
||||
|
||||
use crate::lints::{
|
||||
BadOptAccessDiag, DefaultHashTypesDiag, DiagOutOfImpl, LintPassByHand, NonExistentDocKeyword,
|
||||
QueryInstability, TyQualified, TykindDiag, TykindKind, UntranslatableDiag,
|
||||
QueryInstability, SpanUseEqCtxtDiag, TyQualified, TykindDiag, TykindKind, UntranslatableDiag,
|
||||
UntranslatableDiagnosticTrivial,
|
||||
};
|
||||
use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext};
|
||||
use rustc_ast as ast;
|
||||
use rustc_hir::def::Res;
|
||||
use rustc_hir::{def_id::DefId, Expr, ExprKind, GenericArg, PatKind, Path, PathSegment, QPath};
|
||||
use rustc_hir::{HirId, Impl, Item, ItemKind, Node, Pat, Ty, TyKind};
|
||||
use rustc_hir::{BinOp, BinOpKind, HirId, Impl, Item, ItemKind, Node, Pat, Ty, TyKind};
|
||||
use rustc_middle::ty;
|
||||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||
use rustc_span::hygiene::{ExpnKind, MacroKind};
|
||||
@ -537,3 +537,33 @@ impl LateLintPass<'_> for BadOptAccess {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
declare_tool_lint! {
|
||||
pub rustc::SPAN_USE_EQ_CTXT,
|
||||
Allow,
|
||||
"forbid uses of `==` with `Span::ctxt`, suggest `Span::eq_ctxt` instead",
|
||||
report_in_external_macro: true
|
||||
}
|
||||
|
||||
declare_lint_pass!(SpanUseEqCtxt => [SPAN_USE_EQ_CTXT]);
|
||||
|
||||
impl<'tcx> LateLintPass<'tcx> for SpanUseEqCtxt {
|
||||
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'_>) {
|
||||
if let ExprKind::Binary(BinOp { node: BinOpKind::Eq, .. }, lhs, rhs) = expr.kind {
|
||||
if is_span_ctxt_call(cx, lhs) && is_span_ctxt_call(cx, rhs) {
|
||||
cx.emit_spanned_lint(SPAN_USE_EQ_CTXT, expr.span, SpanUseEqCtxtDiag);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn is_span_ctxt_call(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
|
||||
match &expr.kind {
|
||||
ExprKind::MethodCall(..) => cx
|
||||
.typeck_results()
|
||||
.type_dependent_def_id(expr.hir_id)
|
||||
.is_some_and(|call_did| cx.tcx.is_diagnostic_item(sym::SpanCtxt, call_did)),
|
||||
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
@ -531,6 +531,8 @@ fn register_internals(store: &mut LintStore) {
|
||||
store.register_late_mod_pass(|_| Box::new(BadOptAccess));
|
||||
store.register_lints(&PassByValue::get_lints());
|
||||
store.register_late_mod_pass(|_| Box::new(PassByValue));
|
||||
store.register_lints(&SpanUseEqCtxt::get_lints());
|
||||
store.register_late_mod_pass(|_| Box::new(SpanUseEqCtxt));
|
||||
// FIXME(davidtwco): deliberately do not include `UNTRANSLATABLE_DIAGNOSTIC` and
|
||||
// `DIAGNOSTIC_OUTSIDE_OF_IMPL` here because `-Wrustc::internal` is provided to every crate and
|
||||
// these lints will trigger all of the time - change this once migration to diagnostic structs
|
||||
@ -548,6 +550,7 @@ fn register_internals(store: &mut LintStore) {
|
||||
LintId::of(USAGE_OF_QUALIFIED_TY),
|
||||
LintId::of(EXISTING_DOC_KEYWORD),
|
||||
LintId::of(BAD_OPT_ACCESS),
|
||||
LintId::of(SPAN_USE_EQ_CTXT),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
@ -900,6 +900,10 @@ pub struct QueryInstability {
|
||||
pub query: Symbol,
|
||||
}
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
#[diag(lint_span_use_eq_ctxt)]
|
||||
pub struct SpanUseEqCtxtDiag;
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
#[diag(lint_tykind_kind)]
|
||||
pub struct TykindKind {
|
||||
|
@ -404,7 +404,7 @@ impl<'a> CoverageSpansGenerator<'a> {
|
||||
|
||||
let Some(visible_macro) = curr.visible_macro(self.body_span) else { return };
|
||||
if let Some(prev) = &self.some_prev
|
||||
&& prev.expn_span.ctxt() == curr.expn_span.ctxt()
|
||||
&& prev.expn_span.eq_ctxt(curr.expn_span)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
@ -231,7 +231,7 @@ impl<'a, 'hir> CheckLoopVisitor<'a, 'hir> {
|
||||
AsyncClosure(closure_span) => {
|
||||
self.sess.emit_err(BreakInsideAsyncBlock { span, closure_span, name });
|
||||
}
|
||||
UnlabeledBlock(block_span) if is_break && block_span.ctxt() == break_span.ctxt() => {
|
||||
UnlabeledBlock(block_span) if is_break && block_span.eq_ctxt(break_span) => {
|
||||
let suggestion = Some(OutsideLoopSuggestion { block_span, break_span });
|
||||
self.sess.emit_err(OutsideLoop { span, name, is_break, suggestion });
|
||||
}
|
||||
|
@ -6,9 +6,11 @@
|
||||
use crate::rustc_internal;
|
||||
use crate::rustc_smir::Tables;
|
||||
use rustc_data_structures::fx;
|
||||
use rustc_data_structures::fx::FxIndexMap;
|
||||
use rustc_driver::{Callbacks, Compilation, RunCompiler};
|
||||
use rustc_interface::{interface, Queries};
|
||||
use rustc_middle::mir::interpret::AllocId;
|
||||
use rustc_middle::ty;
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_span::def_id::{CrateNum, DefId};
|
||||
use rustc_span::Span;
|
||||
@ -97,7 +99,7 @@ impl<'tcx> Tables<'tcx> {
|
||||
stable_mir::ty::Prov(self.create_alloc_id(aid))
|
||||
}
|
||||
|
||||
fn create_def_id(&mut self, did: DefId) -> stable_mir::DefId {
|
||||
pub(crate) fn create_def_id(&mut self, did: DefId) -> stable_mir::DefId {
|
||||
self.def_ids.create_or_fetch(did)
|
||||
}
|
||||
|
||||
@ -108,6 +110,17 @@ impl<'tcx> Tables<'tcx> {
|
||||
pub(crate) fn create_span(&mut self, span: Span) -> stable_mir::ty::Span {
|
||||
self.spans.create_or_fetch(span)
|
||||
}
|
||||
|
||||
pub(crate) fn instance_def(
|
||||
&mut self,
|
||||
instance: ty::Instance<'tcx>,
|
||||
) -> stable_mir::mir::mono::InstanceDef {
|
||||
self.instances.create_or_fetch(instance)
|
||||
}
|
||||
|
||||
pub(crate) fn static_def(&mut self, did: DefId) -> stable_mir::mir::mono::StaticDef {
|
||||
stable_mir::mir::mono::StaticDef(self.create_def_id(did))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn crate_num(item: &stable_mir::Crate) -> CrateNum {
|
||||
@ -118,10 +131,11 @@ pub fn run(tcx: TyCtxt<'_>, f: impl FnOnce()) {
|
||||
stable_mir::run(
|
||||
Tables {
|
||||
tcx,
|
||||
def_ids: rustc_internal::IndexMap { index_map: fx::FxIndexMap::default() },
|
||||
alloc_ids: rustc_internal::IndexMap { index_map: fx::FxIndexMap::default() },
|
||||
spans: rustc_internal::IndexMap { index_map: fx::FxIndexMap::default() },
|
||||
def_ids: IndexMap::default(),
|
||||
alloc_ids: IndexMap::default(),
|
||||
spans: IndexMap::default(),
|
||||
types: vec![],
|
||||
instances: IndexMap::default(),
|
||||
},
|
||||
f,
|
||||
);
|
||||
@ -192,6 +206,12 @@ pub struct IndexMap<K, V> {
|
||||
index_map: fx::FxIndexMap<K, V>,
|
||||
}
|
||||
|
||||
impl<K, V> Default for IndexMap<K, V> {
|
||||
fn default() -> Self {
|
||||
Self { index_map: FxIndexMap::default() }
|
||||
}
|
||||
}
|
||||
|
||||
impl<K: PartialEq + Hash + Eq, V: Copy + Debug + PartialEq + IndexedVal> IndexMap<K, V> {
|
||||
pub fn create_or_fetch(&mut self, key: K) -> V {
|
||||
let len = self.index_map.len();
|
||||
|
@ -13,10 +13,12 @@ use crate::rustc_smir::stable_mir::ty::{BoundRegion, EarlyBoundRegion, Region};
|
||||
use rustc_hir as hir;
|
||||
use rustc_middle::mir;
|
||||
use rustc_middle::mir::interpret::{alloc_range, AllocId};
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt, Variance};
|
||||
use rustc_middle::mir::mono::MonoItem;
|
||||
use rustc_middle::ty::{self, Instance, ParamEnv, Ty, TyCtxt, Variance};
|
||||
use rustc_span::def_id::{CrateNum, DefId, LOCAL_CRATE};
|
||||
use rustc_target::abi::FieldIdx;
|
||||
use stable_mir::mir::{CopyNonOverlapping, Statement, UserTypeProjection, VariantIdx};
|
||||
use stable_mir::mir::mono::InstanceDef;
|
||||
use stable_mir::mir::{Body, CopyNonOverlapping, Statement, UserTypeProjection, VariantIdx};
|
||||
use stable_mir::ty::{
|
||||
FloatTy, GenericParamDef, IntTy, LineInfo, Movability, RigidTy, Span, TyKind, UintTy,
|
||||
};
|
||||
@ -119,29 +121,7 @@ impl<'tcx> Context for Tables<'tcx> {
|
||||
|
||||
fn mir_body(&mut self, item: stable_mir::DefId) -> stable_mir::mir::Body {
|
||||
let def_id = self[item];
|
||||
let mir = self.tcx.instance_mir(ty::InstanceDef::Item(def_id));
|
||||
stable_mir::mir::Body {
|
||||
blocks: mir
|
||||
.basic_blocks
|
||||
.iter()
|
||||
.map(|block| stable_mir::mir::BasicBlock {
|
||||
terminator: block.terminator().stable(self),
|
||||
statements: block
|
||||
.statements
|
||||
.iter()
|
||||
.map(|statement| statement.stable(self))
|
||||
.collect(),
|
||||
})
|
||||
.collect(),
|
||||
locals: mir
|
||||
.local_decls
|
||||
.iter()
|
||||
.map(|decl| stable_mir::mir::LocalDecl {
|
||||
ty: self.intern_ty(decl.ty),
|
||||
span: decl.source_info.span.stable(self),
|
||||
})
|
||||
.collect(),
|
||||
}
|
||||
self.tcx.instance_mir(ty::InstanceDef::Item(def_id)).stable(self)
|
||||
}
|
||||
|
||||
fn ty_kind(&mut self, ty: stable_mir::ty::Ty) -> TyKind {
|
||||
@ -190,6 +170,34 @@ impl<'tcx> Context for Tables<'tcx> {
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
|
||||
fn instance_body(&mut self, _def: InstanceDef) -> Body {
|
||||
todo!("Monomorphize the body")
|
||||
}
|
||||
|
||||
fn instance_ty(&mut self, def: InstanceDef) -> stable_mir::ty::Ty {
|
||||
let instance = self.instances[def];
|
||||
let ty = instance.ty(self.tcx, ParamEnv::empty());
|
||||
self.intern_ty(ty)
|
||||
}
|
||||
|
||||
fn instance_def_id(&mut self, def: InstanceDef) -> stable_mir::DefId {
|
||||
let def_id = self.instances[def].def_id();
|
||||
self.create_def_id(def_id)
|
||||
}
|
||||
|
||||
fn mono_instance(&mut self, item: stable_mir::CrateItem) -> stable_mir::mir::mono::Instance {
|
||||
let def_id = self[item.0];
|
||||
Instance::mono(self.tcx, def_id).stable(self)
|
||||
}
|
||||
|
||||
fn requires_monomorphization(&self, def_id: stable_mir::DefId) -> bool {
|
||||
let def_id = self[def_id];
|
||||
let generics = self.tcx.generics_of(def_id);
|
||||
let result = generics.requires_monomorphization(self.tcx);
|
||||
println!("req {result}: {def_id:?}");
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
@ -224,7 +232,8 @@ pub struct Tables<'tcx> {
|
||||
pub def_ids: IndexMap<DefId, stable_mir::DefId>,
|
||||
pub alloc_ids: IndexMap<AllocId, stable_mir::AllocId>,
|
||||
pub spans: IndexMap<rustc_span::Span, Span>,
|
||||
pub types: Vec<MaybeStable<stable_mir::ty::TyKind, Ty<'tcx>>>,
|
||||
pub types: Vec<MaybeStable<TyKind, Ty<'tcx>>>,
|
||||
pub instances: IndexMap<ty::Instance<'tcx>, InstanceDef>,
|
||||
}
|
||||
|
||||
impl<'tcx> Tables<'tcx> {
|
||||
@ -254,6 +263,35 @@ pub(crate) trait Stable<'tcx> {
|
||||
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T;
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for mir::Body<'tcx> {
|
||||
type T = stable_mir::mir::Body;
|
||||
|
||||
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||
stable_mir::mir::Body {
|
||||
blocks: self
|
||||
.basic_blocks
|
||||
.iter()
|
||||
.map(|block| stable_mir::mir::BasicBlock {
|
||||
terminator: block.terminator().stable(tables),
|
||||
statements: block
|
||||
.statements
|
||||
.iter()
|
||||
.map(|statement| statement.stable(tables))
|
||||
.collect(),
|
||||
})
|
||||
.collect(),
|
||||
locals: self
|
||||
.local_decls
|
||||
.iter()
|
||||
.map(|decl| stable_mir::mir::LocalDecl {
|
||||
ty: tables.intern_ty(decl.ty),
|
||||
span: decl.source_info.span.stable(tables),
|
||||
})
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for mir::Statement<'tcx> {
|
||||
type T = stable_mir::mir::Statement;
|
||||
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||
@ -1637,3 +1675,38 @@ impl<'tcx> Stable<'tcx> for DefKind {
|
||||
opaque(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for ty::Instance<'tcx> {
|
||||
type T = stable_mir::mir::mono::Instance;
|
||||
|
||||
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||
let def = tables.instance_def(*self);
|
||||
let kind = match self.def {
|
||||
ty::InstanceDef::Item(..) => stable_mir::mir::mono::InstanceKind::Item,
|
||||
ty::InstanceDef::Intrinsic(..) => stable_mir::mir::mono::InstanceKind::Intrinsic,
|
||||
ty::InstanceDef::Virtual(..) => stable_mir::mir::mono::InstanceKind::Virtual,
|
||||
ty::InstanceDef::VTableShim(..)
|
||||
| ty::InstanceDef::ReifyShim(..)
|
||||
| ty::InstanceDef::FnPtrAddrShim(..)
|
||||
| ty::InstanceDef::ClosureOnceShim { .. }
|
||||
| ty::InstanceDef::ThreadLocalShim(..)
|
||||
| ty::InstanceDef::DropGlue(..)
|
||||
| ty::InstanceDef::CloneShim(..)
|
||||
| ty::InstanceDef::FnPtrShim(..) => stable_mir::mir::mono::InstanceKind::Shim,
|
||||
};
|
||||
stable_mir::mir::mono::Instance { def, kind }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for MonoItem<'tcx> {
|
||||
type T = stable_mir::mir::mono::MonoItem;
|
||||
|
||||
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||
use stable_mir::mir::mono::MonoItem as StableMonoItem;
|
||||
match self {
|
||||
MonoItem::Fn(instance) => StableMonoItem::Fn(instance.stable(tables)),
|
||||
MonoItem::Static(def_id) => StableMonoItem::Static(tables.static_def(*def_id)),
|
||||
MonoItem::GlobalAsm(item_id) => StableMonoItem::GlobalAsm(opaque(item_id)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -212,6 +212,7 @@ impl Span {
|
||||
|
||||
/// This function is used as a fast path when decoding the full `SpanData` is not necessary.
|
||||
/// It's a cut-down version of `data_untracked`.
|
||||
#[cfg_attr(not(test), rustc_diagnostic_item = "SpanCtxt")]
|
||||
#[inline]
|
||||
pub fn ctxt(self) -> SyntaxContext {
|
||||
if self.len_with_tag_or_marker != BASE_LEN_INTERNED_MARKER {
|
||||
|
@ -303,6 +303,7 @@ symbols! {
|
||||
SliceIndex,
|
||||
SliceIter,
|
||||
Some,
|
||||
SpanCtxt,
|
||||
String,
|
||||
StructuralEq,
|
||||
StructuralPartialEq,
|
||||
|
@ -313,6 +313,18 @@ pub trait TypeErrCtxtExt<'tcx> {
|
||||
predicate: ty::Predicate<'tcx>,
|
||||
call_hir_id: HirId,
|
||||
);
|
||||
|
||||
fn look_for_iterator_item_mistakes(
|
||||
&self,
|
||||
assocs_in_this_method: &[Option<(Span, (DefId, Ty<'tcx>))>],
|
||||
typeck_results: &TypeckResults<'tcx>,
|
||||
type_diffs: &[TypeError<'tcx>],
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
path_segment: &hir::PathSegment<'_>,
|
||||
args: &[hir::Expr<'_>],
|
||||
err: &mut Diagnostic,
|
||||
);
|
||||
|
||||
fn point_at_chain(
|
||||
&self,
|
||||
expr: &hir::Expr<'_>,
|
||||
@ -321,6 +333,7 @@ pub trait TypeErrCtxtExt<'tcx> {
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
err: &mut Diagnostic,
|
||||
);
|
||||
|
||||
fn probe_assoc_types_at_expr(
|
||||
&self,
|
||||
type_diffs: &[TypeError<'tcx>],
|
||||
@ -3612,6 +3625,109 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
fn look_for_iterator_item_mistakes(
|
||||
&self,
|
||||
assocs_in_this_method: &[Option<(Span, (DefId, Ty<'tcx>))>],
|
||||
typeck_results: &TypeckResults<'tcx>,
|
||||
type_diffs: &[TypeError<'tcx>],
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
path_segment: &hir::PathSegment<'_>,
|
||||
args: &[hir::Expr<'_>],
|
||||
err: &mut Diagnostic,
|
||||
) {
|
||||
let tcx = self.tcx;
|
||||
// Special case for iterator chains, we look at potential failures of `Iterator::Item`
|
||||
// not being `: Clone` and `Iterator::map` calls with spurious trailing `;`.
|
||||
for entry in assocs_in_this_method {
|
||||
let Some((_span, (def_id, ty))) = entry else {
|
||||
continue;
|
||||
};
|
||||
for diff in type_diffs {
|
||||
let Sorts(expected_found) = diff else {
|
||||
continue;
|
||||
};
|
||||
if tcx.is_diagnostic_item(sym::IteratorItem, *def_id)
|
||||
&& path_segment.ident.name == sym::map
|
||||
&& self.can_eq(param_env, expected_found.found, *ty)
|
||||
&& let [arg] = args
|
||||
&& let hir::ExprKind::Closure(closure) = arg.kind
|
||||
{
|
||||
let body = tcx.hir().body(closure.body);
|
||||
if let hir::ExprKind::Block(block, None) = body.value.kind
|
||||
&& let None = block.expr
|
||||
&& let [.., stmt] = block.stmts
|
||||
&& let hir::StmtKind::Semi(expr) = stmt.kind
|
||||
// FIXME: actually check the expected vs found types, but right now
|
||||
// the expected is a projection that we need to resolve.
|
||||
// && let Some(tail_ty) = typeck_results.expr_ty_opt(expr)
|
||||
&& expected_found.found.is_unit()
|
||||
{
|
||||
err.span_suggestion_verbose(
|
||||
expr.span.shrink_to_hi().with_hi(stmt.span.hi()),
|
||||
"consider removing this semicolon",
|
||||
String::new(),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
let expr = if let hir::ExprKind::Block(block, None) = body.value.kind
|
||||
&& let Some(expr) = block.expr
|
||||
{
|
||||
expr
|
||||
} else {
|
||||
body.value
|
||||
};
|
||||
if let hir::ExprKind::MethodCall(path_segment, rcvr, [], span) = expr.kind
|
||||
&& path_segment.ident.name == sym::clone
|
||||
&& let Some(expr_ty) = typeck_results.expr_ty_opt(expr)
|
||||
&& let Some(rcvr_ty) = typeck_results.expr_ty_opt(rcvr)
|
||||
&& self.can_eq(param_env, expr_ty, rcvr_ty)
|
||||
&& let ty::Ref(_, ty, _) = expr_ty.kind()
|
||||
{
|
||||
err.span_label(
|
||||
span,
|
||||
format!(
|
||||
"this method call is cloning the reference `{expr_ty}`, not \
|
||||
`{ty}` which doesn't implement `Clone`",
|
||||
),
|
||||
);
|
||||
let ty::Param(..) = ty.kind() else {
|
||||
continue;
|
||||
};
|
||||
let hir = tcx.hir();
|
||||
let node = hir.get_by_def_id(hir.get_parent_item(expr.hir_id).def_id);
|
||||
|
||||
let pred = ty::Binder::dummy(ty::TraitPredicate {
|
||||
trait_ref: ty::TraitRef::from_lang_item(
|
||||
tcx,
|
||||
LangItem::Clone,
|
||||
span,
|
||||
[*ty],
|
||||
),
|
||||
polarity: ty::ImplPolarity::Positive,
|
||||
});
|
||||
let Some(generics) = node.generics() else {
|
||||
continue;
|
||||
};
|
||||
let Some(body_id) = node.body_id() else {
|
||||
continue;
|
||||
};
|
||||
suggest_restriction(
|
||||
tcx,
|
||||
hir.body_owner_def_id(body_id),
|
||||
&generics,
|
||||
&format!("type parameter `{ty}`"),
|
||||
err,
|
||||
node.fn_sig(),
|
||||
None,
|
||||
pred,
|
||||
None,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn point_at_chain(
|
||||
&self,
|
||||
expr: &hir::Expr<'_>,
|
||||
@ -3631,13 +3747,22 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
||||
let mut prev_ty = self.resolve_vars_if_possible(
|
||||
typeck_results.expr_ty_adjusted_opt(expr).unwrap_or(Ty::new_misc_error(tcx)),
|
||||
);
|
||||
while let hir::ExprKind::MethodCall(_path_segment, rcvr_expr, _args, span) = expr.kind {
|
||||
while let hir::ExprKind::MethodCall(path_segment, rcvr_expr, args, span) = expr.kind {
|
||||
// Point at every method call in the chain with the resulting type.
|
||||
// vec![1, 2, 3].iter().map(mapper).sum<i32>()
|
||||
// ^^^^^^ ^^^^^^^^^^^
|
||||
expr = rcvr_expr;
|
||||
let assocs_in_this_method =
|
||||
self.probe_assoc_types_at_expr(&type_diffs, span, prev_ty, expr.hir_id, param_env);
|
||||
self.look_for_iterator_item_mistakes(
|
||||
&assocs_in_this_method,
|
||||
typeck_results,
|
||||
&type_diffs,
|
||||
param_env,
|
||||
path_segment,
|
||||
args,
|
||||
err,
|
||||
);
|
||||
assocs.push(assocs_in_this_method);
|
||||
prev_ty = self.resolve_vars_if_possible(
|
||||
typeck_results.expr_ty_adjusted_opt(expr).unwrap_or(Ty::new_misc_error(tcx)),
|
||||
|
69
compiler/stable_mir/src/error.rs
Normal file
69
compiler/stable_mir/src/error.rs
Normal file
@ -0,0 +1,69 @@
|
||||
//! When things go wrong, we need some error handling.
|
||||
//! There are a few different types of errors in StableMIR:
|
||||
//!
|
||||
//! - [CompilerError]: This represents errors that can be raised when invoking the compiler.
|
||||
//! - [Error]: Generic error that represents the reason why a request that could not be fulfilled.
|
||||
|
||||
use std::fmt::{Debug, Display, Formatter};
|
||||
use std::{error, fmt};
|
||||
|
||||
/// An error type used to represent an error that has already been reported by the compiler.
|
||||
#[derive(Clone, Copy, PartialEq, Eq)]
|
||||
pub enum CompilerError<T> {
|
||||
/// Internal compiler error (I.e.: Compiler crashed).
|
||||
ICE,
|
||||
/// Compilation failed.
|
||||
CompilationFailed,
|
||||
/// Compilation was interrupted.
|
||||
Interrupted(T),
|
||||
/// Compilation skipped. This happens when users invoke rustc to retrieve information such as
|
||||
/// --version.
|
||||
Skipped,
|
||||
}
|
||||
|
||||
/// A generic error to represent an API request that cannot be fulfilled.
|
||||
#[derive(Debug)]
|
||||
pub struct Error(String);
|
||||
|
||||
impl Error {
|
||||
pub(crate) fn new(msg: String) -> Self {
|
||||
Self(msg)
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Error {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
Display::fmt(&self.0, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Display for CompilerError<T>
|
||||
where
|
||||
T: Display,
|
||||
{
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
CompilerError::ICE => write!(f, "Internal Compiler Error"),
|
||||
CompilerError::CompilationFailed => write!(f, "Compilation Failed"),
|
||||
CompilerError::Interrupted(reason) => write!(f, "Compilation Interrupted: {reason}"),
|
||||
CompilerError::Skipped => write!(f, "Compilation Skipped"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Debug for CompilerError<T>
|
||||
where
|
||||
T: Debug,
|
||||
{
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
CompilerError::ICE => write!(f, "Internal Compiler Error"),
|
||||
CompilerError::CompilationFailed => write!(f, "Compilation Failed"),
|
||||
CompilerError::Interrupted(reason) => write!(f, "Compilation Interrupted: {reason:?}"),
|
||||
CompilerError::Skipped => write!(f, "Compilation Skipped"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl error::Error for Error {}
|
||||
impl<T> error::Error for CompilerError<T> where T: Display + Debug {}
|
@ -17,6 +17,8 @@
|
||||
//! The goal is to eventually be published on
|
||||
//! [crates.io](https://crates.io).
|
||||
|
||||
use crate::mir::mono::InstanceDef;
|
||||
use crate::mir::Body;
|
||||
use std::cell::Cell;
|
||||
use std::fmt;
|
||||
use std::fmt::Debug;
|
||||
@ -29,11 +31,15 @@ use self::ty::{
|
||||
#[macro_use]
|
||||
extern crate scoped_tls;
|
||||
|
||||
pub mod error;
|
||||
pub mod fold;
|
||||
pub mod mir;
|
||||
pub mod ty;
|
||||
pub mod visitor;
|
||||
|
||||
pub use error::*;
|
||||
use mir::mono::Instance;
|
||||
|
||||
/// Use String for now but we should replace it.
|
||||
pub type Symbol = String;
|
||||
|
||||
@ -85,20 +91,6 @@ pub type TraitDecls = Vec<TraitDef>;
|
||||
/// A list of impl trait decls.
|
||||
pub type ImplTraitDecls = Vec<ImplDef>;
|
||||
|
||||
/// An error type used to represent an error that has already been reported by the compiler.
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
pub enum CompilerError<T> {
|
||||
/// Internal compiler error (I.e.: Compiler crashed).
|
||||
ICE,
|
||||
/// Compilation failed.
|
||||
CompilationFailed,
|
||||
/// Compilation was interrupted.
|
||||
Interrupted(T),
|
||||
/// Compilation skipped. This happens when users invoke rustc to retrieve information such as
|
||||
/// --version.
|
||||
Skipped,
|
||||
}
|
||||
|
||||
/// Holds information about a crate.
|
||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||
pub struct Crate {
|
||||
@ -113,7 +105,7 @@ pub type Filename = Opaque;
|
||||
/// Holds information about an item in the crate.
|
||||
/// For now, it only stores the item DefId. Use functions inside `rustc_internal` module to
|
||||
/// use this item.
|
||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||
pub struct CrateItem(pub DefId);
|
||||
|
||||
impl CrateItem {
|
||||
@ -132,6 +124,10 @@ impl CrateItem {
|
||||
pub fn kind(&self) -> DefKind {
|
||||
with(|cx| cx.def_kind(self.0))
|
||||
}
|
||||
|
||||
pub fn requires_monomorphization(&self) -> bool {
|
||||
with(|cx| cx.requires_monomorphization(self.0))
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the function where execution starts if the current
|
||||
@ -220,6 +216,23 @@ pub trait Context {
|
||||
|
||||
/// Create a new `Ty` from scratch without information from rustc.
|
||||
fn mk_ty(&mut self, kind: TyKind) -> Ty;
|
||||
|
||||
/// Get the body of an Instance.
|
||||
/// FIXME: Monomorphize the body.
|
||||
fn instance_body(&mut self, instance: InstanceDef) -> Body;
|
||||
|
||||
/// Get the instance type with generic substitutions applied and lifetimes erased.
|
||||
fn instance_ty(&mut self, instance: InstanceDef) -> Ty;
|
||||
|
||||
/// Get the instance.
|
||||
fn instance_def_id(&mut self, instance: InstanceDef) -> DefId;
|
||||
|
||||
/// Convert a non-generic crate item into an instance.
|
||||
/// This function will panic if the item is generic.
|
||||
fn mono_instance(&mut self, item: CrateItem) -> Instance;
|
||||
|
||||
/// Item requires monomorphization.
|
||||
fn requires_monomorphization(&self, def_id: DefId) -> bool;
|
||||
}
|
||||
|
||||
// A thread local variable that stores a pointer to the tables mapping between TyCtxt
|
||||
|
@ -1,3 +1,4 @@
|
||||
mod body;
|
||||
pub mod mono;
|
||||
|
||||
pub use body::*;
|
||||
|
89
compiler/stable_mir/src/mir/mono.rs
Normal file
89
compiler/stable_mir/src/mir/mono.rs
Normal file
@ -0,0 +1,89 @@
|
||||
use crate::mir::Body;
|
||||
use crate::ty::{IndexedVal, Ty};
|
||||
use crate::{with, CrateItem, DefId, Error, Opaque};
|
||||
use std::fmt::Debug;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum MonoItem {
|
||||
Fn(Instance),
|
||||
Static(StaticDef),
|
||||
GlobalAsm(Opaque),
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct Instance {
|
||||
/// The type of instance.
|
||||
pub kind: InstanceKind,
|
||||
/// An ID used to get the instance definition from the compiler.
|
||||
/// Do not use this field directly.
|
||||
pub def: InstanceDef,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
pub enum InstanceKind {
|
||||
/// A user defined item.
|
||||
Item,
|
||||
/// A compiler intrinsic function.
|
||||
Intrinsic,
|
||||
/// A virtual function definition stored in a VTable.
|
||||
Virtual,
|
||||
/// A compiler generated shim.
|
||||
Shim,
|
||||
}
|
||||
|
||||
impl Instance {
|
||||
/// Get the body of an Instance. The body will be eagerly monomorphized.
|
||||
pub fn body(&self) -> Body {
|
||||
with(|context| context.instance_body(self.def))
|
||||
}
|
||||
|
||||
/// Get the instance type with generic substitutions applied and lifetimes erased.
|
||||
pub fn ty(&self) -> Ty {
|
||||
with(|context| context.instance_ty(self.def))
|
||||
}
|
||||
}
|
||||
|
||||
/// Try to convert a crate item into an instance.
|
||||
/// The item cannot be generic in order to be converted into an instance.
|
||||
impl TryFrom<CrateItem> for Instance {
|
||||
type Error = crate::Error;
|
||||
|
||||
fn try_from(item: CrateItem) -> Result<Self, Self::Error> {
|
||||
with(|context| {
|
||||
if !context.requires_monomorphization(item.0) {
|
||||
Ok(context.mono_instance(item))
|
||||
} else {
|
||||
Err(Error::new("Item requires monomorphization".to_string()))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Try to convert an instance into a crate item.
|
||||
/// Only user defined instances can be converted.
|
||||
impl TryFrom<Instance> for CrateItem {
|
||||
type Error = crate::Error;
|
||||
|
||||
fn try_from(value: Instance) -> Result<Self, Self::Error> {
|
||||
if value.kind == InstanceKind::Item {
|
||||
Ok(CrateItem(with(|context| context.instance_def_id(value.def))))
|
||||
} else {
|
||||
Err(Error::new(format!("Item kind `{:?}` cannot be converted", value.kind)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
pub struct InstanceDef(usize);
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
||||
pub struct StaticDef(pub DefId);
|
||||
|
||||
impl IndexedVal for InstanceDef {
|
||||
fn to_val(index: usize) -> Self {
|
||||
InstanceDef(index)
|
||||
}
|
||||
fn to_index(&self) -> usize {
|
||||
self.0
|
||||
}
|
||||
}
|
@ -628,10 +628,10 @@ Using this flag looks like this:
|
||||
|
||||
```bash
|
||||
$ rustdoc src/lib.rs -Z unstable-options \
|
||||
--check-cfg='names()' --check-cfg='values(feature, "foo", "bar")'
|
||||
--check-cfg='cfg(feature, values("foo", "bar"))'
|
||||
```
|
||||
|
||||
The example above check every well known names (`target_os`, `doc`, `test`, ... via `names()`)
|
||||
The example above check every well known names and values (`target_os`, `doc`, `test`, ...)
|
||||
and check the values of `feature`: `foo` and `bar`.
|
||||
|
||||
### `--generate-link-to-definition`: Generate links on types in source code
|
||||
|
@ -10,18 +10,185 @@ This feature allows you to enable complete or partial checking of configuration.
|
||||
check them. The `--check-cfg` option takes a value, called the _check cfg specification_. The
|
||||
check cfg specification is parsed using the Rust metadata syntax, just as the `--cfg` option is.
|
||||
|
||||
`--check-cfg` option can take one of two forms:
|
||||
`--check-cfg` option take one form:
|
||||
|
||||
1. `--check-cfg names(...)` enables checking condition names.
|
||||
2. `--check-cfg values(...)` enables checking the values within list-valued conditions.
|
||||
|
||||
These two options are independent. `names` checks only the namespace of condition names
|
||||
while `values` checks only the namespace of the values of list-valued conditions.
|
||||
1. `--check-cfg cfg(...)` enables checking the values within list-valued conditions.
|
||||
|
||||
NOTE: No implicit expectation is added when using `--cfg` for both forms. Users are expected to
|
||||
pass all expected names and values using `names(...)` and `values(...)`.
|
||||
pass all expected names and values using `cfg(...)`.
|
||||
|
||||
## The `names(...)` form
|
||||
## The `cfg(...)` form
|
||||
|
||||
The `cfg(...)` form enables checking the values within list-valued conditions. It has this
|
||||
basic form:
|
||||
|
||||
```bash
|
||||
rustc --check-cfg 'cfg(name1, ..., nameN, values("value1", "value2", ... "valueN"))'
|
||||
```
|
||||
|
||||
where `name` is a bare identifier (has no quotes) and each `"value"` term is a quoted literal
|
||||
string. `name` specifies the name of the condition, such as `feature` or `my_cfg`.
|
||||
|
||||
When the `cfg(...)` option is specified, `rustc` will check every `#[cfg(name = "value")]`
|
||||
attribute, `#[cfg_attr(name = "value")]` attribute, `#[link(name = "a", cfg(name = "value"))]`
|
||||
and `cfg!(name = "value")` call. It will check that the `"value"` specified is present in the
|
||||
list of expected values. If `"value"` is not in it, then `rustc` will report an `unexpected_cfgs`
|
||||
lint diagnostic. The default diagnostic level for this lint is `Warn`.
|
||||
|
||||
To enable checking of values, but to provide an empty set of expected values, use these forms:
|
||||
|
||||
```bash
|
||||
rustc --check-cfg 'cfg(name1, ..., nameN)'
|
||||
rustc --check-cfg 'cfg(name1, ..., nameN, values())'
|
||||
```
|
||||
|
||||
To enable checking of name but not values (i.e. unknown expected values), use this form:
|
||||
|
||||
```bash
|
||||
rustc --check-cfg 'cfg(name1, ..., nameN, values(any()))'
|
||||
```
|
||||
|
||||
The `--check-cfg cfg(...)` option can be repeated, both for the same condition name and for
|
||||
different names. If it is repeated for the same condition name, then the sets of values for that
|
||||
condition are merged together (presedence is given to `any()`).
|
||||
|
||||
## Well known names and values
|
||||
|
||||
`rustc` has a internal list of well known names and their corresponding values.
|
||||
Those well known names and values follows the same stability as what they refer to.
|
||||
|
||||
Well known values checking is always enabled as long as a `--check-cfg` argument is present.
|
||||
|
||||
Well known names checking is always enable as long as a `--check-cfg` argument is present
|
||||
**unless** any `cfg(any())` argument is passed.
|
||||
|
||||
To disable checking of well known names, use this form:
|
||||
|
||||
```bash
|
||||
rustc --check-cfg 'cfg(any())'
|
||||
```
|
||||
|
||||
NOTE: If one want to enable values and names checking without having any cfg to declare, one
|
||||
can use an empty `cfg()` argument.
|
||||
|
||||
## Examples
|
||||
|
||||
Consider this command line:
|
||||
|
||||
```bash
|
||||
rustc --check-cfg 'cfg(feature, values("lion", "zebra"))' \
|
||||
--cfg 'feature="lion"' -Z unstable-options \
|
||||
example.rs
|
||||
```
|
||||
|
||||
This command line indicates that this crate has two features: `lion` and `zebra`. The `lion`
|
||||
feature is enabled, while the `zebra` feature is disabled. Exhaustive checking of names and
|
||||
values are enabled by default. Consider compiling this code:
|
||||
|
||||
```rust
|
||||
// This is expected, and tame_lion() will be compiled
|
||||
#[cfg(feature = "lion")]
|
||||
fn tame_lion(lion: Lion) {}
|
||||
|
||||
// This is expected, and ride_zebra() will NOT be compiled.
|
||||
#[cfg(feature = "zebra")]
|
||||
fn ride_zebra(zebra: Zebra) {}
|
||||
|
||||
// This is UNEXPECTED, and will cause a compiler warning (by default).
|
||||
#[cfg(feature = "platypus")]
|
||||
fn poke_platypus() {}
|
||||
|
||||
// This is UNEXPECTED, because 'feechure' is not a known condition name,
|
||||
// and will cause a compiler warning (by default).
|
||||
#[cfg(feechure = "lion")]
|
||||
fn tame_lion() {}
|
||||
|
||||
// This is UNEXPECTED, because 'windows' is a well known condition name,
|
||||
// and because 'windows' doens't take any values,
|
||||
// and will cause a compiler warning (by default).
|
||||
#[cfg(windows = "unix")]
|
||||
fn tame_windows() {}
|
||||
```
|
||||
|
||||
### Example: Checking condition names, but not values
|
||||
|
||||
```bash
|
||||
# This turns on checking for condition names, but not values, such as 'feature' values.
|
||||
rustc --check-cfg 'cfg(is_embedded, has_feathers, values(any()))' \
|
||||
--cfg has_feathers -Z unstable-options
|
||||
```
|
||||
|
||||
```rust
|
||||
#[cfg(is_embedded)] // This is expected as "is_embedded" was provided in cfg()
|
||||
fn do_embedded() {} // and because names exhaustiveness was not disabled
|
||||
|
||||
#[cfg(has_feathers)] // This is expected as "has_feathers" was provided in cfg()
|
||||
fn do_features() {} // and because names exhaustiveness was not disbaled
|
||||
|
||||
#[cfg(has_feathers = "zapping")] // This is expected as "has_feathers" was provided in cfg()
|
||||
// and because no value checking was enable for "has_feathers"
|
||||
// no warning is emitted for the value "zapping"
|
||||
fn do_zapping() {}
|
||||
|
||||
#[cfg(has_mumble_frotz)] // This is UNEXPECTED because names checking is enable and
|
||||
// "has_mumble_frotz" was not provided in cfg()
|
||||
fn do_mumble_frotz() {}
|
||||
```
|
||||
|
||||
### Example: Checking feature values, but not condition names
|
||||
|
||||
```bash
|
||||
# This turns on checking for feature values, but not for condition names.
|
||||
rustc --check-cfg 'configure(feature, values("zapping", "lasers"))' \
|
||||
--check-cfg 'cfg(any())' \
|
||||
--cfg 'feature="zapping"' -Z unstable-options
|
||||
```
|
||||
|
||||
```rust
|
||||
#[cfg(is_embedded)] // This is doesn't raise a warning, because names checking was
|
||||
// disabled by 'cfg(any())'
|
||||
fn do_embedded() {}
|
||||
|
||||
#[cfg(has_feathers)] // Same as above, 'cfg(any())' was provided so no name
|
||||
// checking is performed
|
||||
fn do_features() {}
|
||||
|
||||
#[cfg(feature = "lasers")] // This is expected, "lasers" is in the cfg(feature) list
|
||||
fn shoot_lasers() {}
|
||||
|
||||
#[cfg(feature = "monkeys")] // This is UNEXPECTED, because "monkeys" is not in the
|
||||
// cfg(feature) list
|
||||
fn write_shakespeare() {}
|
||||
```
|
||||
|
||||
### Example: Checking both condition names and feature values
|
||||
|
||||
```bash
|
||||
# This turns on checking for feature values and for condition names.
|
||||
rustc --check-cfg 'cfg(is_embedded, has_feathers)' \
|
||||
--check-cfg 'cfg(feature, values("zapping", "lasers"))' \
|
||||
--cfg has_feathers --cfg 'feature="zapping"' -Z unstable-options
|
||||
```
|
||||
|
||||
```rust
|
||||
#[cfg(is_embedded)] // This is expected because "is_embedded" was provided in cfg()
|
||||
fn do_embedded() {} // and doesn't take any value
|
||||
|
||||
#[cfg(has_feathers)] // This is expected because "has_feathers" was provided in cfg()
|
||||
fn do_features() {} // and deosn't take any value
|
||||
|
||||
#[cfg(has_mumble_frotz)] // This is UNEXPECTED, because "has_mumble_frotz" was never provided
|
||||
fn do_mumble_frotz() {}
|
||||
|
||||
#[cfg(feature = "lasers")] // This is expected, "lasers" is in the cfg(feature) list
|
||||
fn shoot_lasers() {}
|
||||
|
||||
#[cfg(feature = "monkeys")] // This is UNEXPECTED, because "monkeys" is not in
|
||||
// the cfg(feature) list
|
||||
fn write_shakespeare() {}
|
||||
```
|
||||
|
||||
## The deprecated `names(...)` form
|
||||
|
||||
The `names(...)` form enables checking the names. This form uses a named list:
|
||||
|
||||
@ -56,7 +223,7 @@ The first form enables checking condition names, while specifying that there are
|
||||
condition names (outside of the set of well-known names defined by `rustc`). Omitting the
|
||||
`--check-cfg 'names(...)'` option does not enable checking condition names.
|
||||
|
||||
## The `values(...)` form
|
||||
## The deprecated `values(...)` form
|
||||
|
||||
The `values(...)` form enables checking the values within list-valued conditions. It has this
|
||||
form:
|
||||
@ -87,120 +254,3 @@ condition are merged together.
|
||||
If `values()` is specified, then `rustc` will enable the checking of well-known values defined
|
||||
by itself. Note that it's necessary to specify the `values()` form to enable the checking of
|
||||
well known values, specifying the other forms doesn't implicitly enable it.
|
||||
|
||||
## Examples
|
||||
|
||||
Consider this command line:
|
||||
|
||||
```bash
|
||||
rustc --check-cfg 'names(feature)' \
|
||||
--check-cfg 'values(feature, "lion", "zebra")' \
|
||||
--cfg 'feature="lion"' -Z unstable-options \
|
||||
example.rs
|
||||
```
|
||||
|
||||
This command line indicates that this crate has two features: `lion` and `zebra`. The `lion`
|
||||
feature is enabled, while the `zebra` feature is disabled. Consider compiling this code:
|
||||
|
||||
```rust
|
||||
// This is expected, and tame_lion() will be compiled
|
||||
#[cfg(feature = "lion")]
|
||||
fn tame_lion(lion: Lion) {}
|
||||
|
||||
// This is expected, and ride_zebra() will NOT be compiled.
|
||||
#[cfg(feature = "zebra")]
|
||||
fn ride_zebra(zebra: Zebra) {}
|
||||
|
||||
// This is UNEXPECTED, and will cause a compiler warning (by default).
|
||||
#[cfg(feature = "platypus")]
|
||||
fn poke_platypus() {}
|
||||
|
||||
// This is UNEXPECTED, because 'feechure' is not a known condition name,
|
||||
// and will cause a compiler warning (by default).
|
||||
#[cfg(feechure = "lion")]
|
||||
fn tame_lion() {}
|
||||
```
|
||||
|
||||
> Note: The `--check-cfg names(feature)` option is necessary only to enable checking the condition
|
||||
> name, as in the last example. `feature` is a well-known (always-expected) condition name, and so
|
||||
> it is not necessary to specify it in a `--check-cfg 'names(...)'` option. That option can be
|
||||
> shortened to > `--check-cfg names()` in order to enable checking well-known condition names.
|
||||
|
||||
### Example: Checking condition names, but not values
|
||||
|
||||
```bash
|
||||
# This turns on checking for condition names, but not values, such as 'feature' values.
|
||||
rustc --check-cfg 'names(is_embedded, has_feathers)' \
|
||||
--cfg has_feathers -Z unstable-options
|
||||
```
|
||||
|
||||
```rust
|
||||
#[cfg(is_embedded)] // This is expected as "is_embedded" was provided in names()
|
||||
fn do_embedded() {}
|
||||
|
||||
#[cfg(has_feathers)] // This is expected as "has_feathers" was provided in names()
|
||||
fn do_features() {}
|
||||
|
||||
#[cfg(has_feathers = "zapping")] // This is expected as "has_feathers" was provided in names()
|
||||
// and because no value checking was enable for "has_feathers"
|
||||
// no warning is emitted for the value "zapping"
|
||||
fn do_zapping() {}
|
||||
|
||||
#[cfg(has_mumble_frotz)] // This is UNEXPECTED because names checking is enable and
|
||||
// "has_mumble_frotz" was not provided in names()
|
||||
fn do_mumble_frotz() {}
|
||||
```
|
||||
|
||||
### Example: Checking feature values, but not condition names
|
||||
|
||||
```bash
|
||||
# This turns on checking for feature values, but not for condition names.
|
||||
rustc --check-cfg 'values(feature, "zapping", "lasers")' \
|
||||
--cfg 'feature="zapping"' -Z unstable-options
|
||||
```
|
||||
|
||||
```rust
|
||||
#[cfg(is_embedded)] // This is doesn't raise a warning, because names checking was not
|
||||
// enable (ie not names())
|
||||
fn do_embedded() {}
|
||||
|
||||
#[cfg(has_feathers)] // Same as above, --check-cfg names(...) was never used so no name
|
||||
// checking is performed
|
||||
fn do_features() {}
|
||||
|
||||
|
||||
#[cfg(feature = "lasers")] // This is expected, "lasers" is in the values(feature) list
|
||||
fn shoot_lasers() {}
|
||||
|
||||
#[cfg(feature = "monkeys")] // This is UNEXPECTED, because "monkeys" is not in the
|
||||
// --check-cfg values(feature) list
|
||||
fn write_shakespeare() {}
|
||||
```
|
||||
|
||||
### Example: Checking both condition names and feature values
|
||||
|
||||
```bash
|
||||
# This turns on checking for feature values and for condition names.
|
||||
rustc --check-cfg 'names(is_embedded, has_feathers)' \
|
||||
--check-cfg 'values(feature, "zapping", "lasers")' \
|
||||
--cfg has_feathers --cfg 'feature="zapping"' -Z unstable-options
|
||||
```
|
||||
|
||||
```rust
|
||||
#[cfg(is_embedded)] // This is expected because "is_embedded" was provided in names()
|
||||
fn do_embedded() {}
|
||||
|
||||
#[cfg(has_feathers)] // This is expected because "has_feathers" was provided in names()
|
||||
fn do_features() {}
|
||||
|
||||
#[cfg(has_mumble_frotz)] // This is UNEXPECTED, because has_mumble_frotz is not in the
|
||||
// --check-cfg names(...) list
|
||||
fn do_mumble_frotz() {}
|
||||
|
||||
#[cfg(feature = "lasers")] // This is expected, "lasers" is in the values(feature) list
|
||||
fn shoot_lasers() {}
|
||||
|
||||
#[cfg(feature = "monkeys")] // This is UNEXPECTED, because "monkeys" is not in
|
||||
// the values(feature) list
|
||||
fn write_shakespeare() {}
|
||||
```
|
||||
|
@ -701,7 +701,7 @@ fn deref_method_same_type<'tcx>(result_ty: Ty<'tcx>, arg_ty: Ty<'tcx>) -> bool {
|
||||
|
||||
fn in_postfix_position<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'tcx>) -> bool {
|
||||
if let Some(parent) = get_parent_expr(cx, e)
|
||||
&& parent.span.ctxt() == e.span.ctxt()
|
||||
&& parent.span.eq_ctxt(e.span)
|
||||
{
|
||||
match parent.kind {
|
||||
ExprKind::Call(child, _) | ExprKind::MethodCall(_, child, _, _) | ExprKind::Index(child, _, _)
|
||||
|
@ -241,7 +241,7 @@ fn try_parse_contains<'tcx>(cx: &LateContext<'_>, expr: &'tcx Expr<'_>) -> Optio
|
||||
},
|
||||
],
|
||||
_,
|
||||
) if key_span.ctxt() == expr.span.ctxt() => {
|
||||
) if key_span.eq_ctxt(expr.span) => {
|
||||
let id = cx.typeck_results().type_dependent_def_id(expr.hir_id)?;
|
||||
let expr = ContainsExpr {
|
||||
negated,
|
||||
|
@ -274,7 +274,7 @@ fn check_array(cx: &EarlyContext<'_>, expr: &Expr) {
|
||||
for element in array {
|
||||
if_chain! {
|
||||
if let ExprKind::Binary(ref op, ref lhs, _) = element.kind;
|
||||
if has_unary_equivalent(op.node) && lhs.span.ctxt() == op.span.ctxt();
|
||||
if has_unary_equivalent(op.node) && lhs.span.eq_ctxt(op.span);
|
||||
let space_span = lhs.span.between(op.span);
|
||||
if let Some(space_snippet) = snippet_opt(cx, space_span);
|
||||
let lint_span = lhs.span.with_lo(lhs.span.hi());
|
||||
|
@ -31,7 +31,7 @@ impl LateLintPass<'_> for UnderscoreTyped {
|
||||
if !in_external_macro(cx.tcx.sess, local.span);
|
||||
if let Some(ty) = local.ty; // Ensure that it has a type defined
|
||||
if let TyKind::Infer = &ty.kind; // that type is '_'
|
||||
if local.span.ctxt() == ty.span.ctxt();
|
||||
if local.span.eq_ctxt(ty.span);
|
||||
then {
|
||||
// NOTE: Using `is_from_proc_macro` on `init` will require that it's initialized,
|
||||
// this doesn't. Alternatively, `WithSearchPat` can be implemented for `Ty`
|
||||
|
@ -59,7 +59,7 @@ impl<'tcx> QuestionMark {
|
||||
let Some(init) = local.init &&
|
||||
local.els.is_none() &&
|
||||
local.ty.is_none() &&
|
||||
init.span.ctxt() == stmt.span.ctxt() &&
|
||||
init.span.eq_ctxt(stmt.span) &&
|
||||
let Some(if_let_or_match) = IfLetOrMatch::parse(cx, init)
|
||||
{
|
||||
match if_let_or_match {
|
||||
|
@ -57,7 +57,7 @@ fn check_arm<'tcx>(
|
||||
}
|
||||
},
|
||||
};
|
||||
if outer_pat.span.ctxt() == inner_scrutinee.span.ctxt();
|
||||
if outer_pat.span.eq_ctxt(inner_scrutinee.span);
|
||||
// match expression must be a local binding
|
||||
// match <local> { .. }
|
||||
if let Some(binding_id) = path_to_local(peel_ref_operators(cx, inner_scrutinee));
|
||||
|
@ -119,7 +119,7 @@ where
|
||||
// it's being passed by value.
|
||||
let scrutinee = peel_hir_expr_refs(scrutinee).0;
|
||||
let (scrutinee_str, _) = snippet_with_context(cx, scrutinee.span, expr_ctxt, "..", &mut app);
|
||||
let scrutinee_str = if scrutinee.span.ctxt() == expr.span.ctxt() && scrutinee.precedence().order() < PREC_POSTFIX {
|
||||
let scrutinee_str = if scrutinee.span.eq_ctxt(expr.span) && scrutinee.precedence().order() < PREC_POSTFIX {
|
||||
format!("({scrutinee_str})")
|
||||
} else {
|
||||
scrutinee_str.into()
|
||||
@ -130,7 +130,7 @@ where
|
||||
if_chain! {
|
||||
if !some_expr.needs_unsafe_block;
|
||||
if let Some(func) = can_pass_as_func(cx, id, some_expr.expr);
|
||||
if func.span.ctxt() == some_expr.expr.span.ctxt();
|
||||
if func.span.eq_ctxt(some_expr.expr.span);
|
||||
then {
|
||||
snippet_with_applicability(cx, func.span, "..", &mut app).into_owned()
|
||||
} else {
|
||||
|
@ -56,7 +56,7 @@ pub(super) fn check<'tcx>(
|
||||
// lint, with note if neither arg is > 1 line and both map() and
|
||||
// unwrap_or_else() have the same span
|
||||
let multiline = map_snippet.lines().count() > 1 || unwrap_snippet.lines().count() > 1;
|
||||
let same_span = map_arg.span.ctxt() == unwrap_arg.span.ctxt();
|
||||
let same_span = map_arg.span.eq_ctxt(unwrap_arg.span);
|
||||
if same_span && !multiline {
|
||||
let var_snippet = snippet(cx, recv.span, "..");
|
||||
span_lint_and_sugg(
|
||||
|
@ -125,7 +125,7 @@ fn check(cx: &LateContext<'_>, expr: &Expr<'_>) {
|
||||
if let ExprKind::Match(inner_expr_with_q, _, MatchSource::TryDesugar(_)) = &arg.kind;
|
||||
if let ExprKind::Call(called, [inner_expr]) = &inner_expr_with_q.kind;
|
||||
if let ExprKind::Path(QPath::LangItem(LangItem::TryTraitBranch, ..)) = &called.kind;
|
||||
if expr.span.ctxt() == inner_expr.span.ctxt();
|
||||
if expr.span.eq_ctxt(inner_expr.span);
|
||||
let expr_ty = cx.typeck_results().expr_ty(expr);
|
||||
let inner_ty = cx.typeck_results().expr_ty(inner_expr);
|
||||
if expr_ty == inner_ty;
|
||||
|
@ -51,7 +51,7 @@ impl<'tcx> LateLintPass<'tcx> for NonOctalUnixPermissions {
|
||||
|| (path.ident.name == sym!(set_mode)
|
||||
&& cx.tcx.is_diagnostic_item(sym::FsPermissions, adt.did()));
|
||||
if let ExprKind::Lit(_) = param.kind;
|
||||
if param.span.ctxt() == expr.span.ctxt();
|
||||
if param.span.eq_ctxt(expr.span);
|
||||
|
||||
then {
|
||||
let Some(snip) = snippet_opt(cx, param.span) else {
|
||||
@ -70,7 +70,7 @@ impl<'tcx> LateLintPass<'tcx> for NonOctalUnixPermissions {
|
||||
if let Some(def_id) = cx.qpath_res(path, func.hir_id).opt_def_id();
|
||||
if match_def_path(cx, def_id, &paths::PERMISSIONS_FROM_MODE);
|
||||
if let ExprKind::Lit(_) = param.kind;
|
||||
if param.span.ctxt() == expr.span.ctxt();
|
||||
if param.span.eq_ctxt(expr.span);
|
||||
if let Some(snip) = snippet_opt(cx, param.span);
|
||||
if !snip.starts_with("0o");
|
||||
then {
|
||||
|
@ -48,7 +48,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantAsyncBlock {
|
||||
let Some(body_expr) = desugar_async_block(cx, expr) &&
|
||||
let Some(expr) = desugar_await(peel_blocks(body_expr)) &&
|
||||
// The await prefix must not come from a macro as its content could change in the future.
|
||||
expr.span.ctxt() == body_expr.span.ctxt() &&
|
||||
expr.span.eq_ctxt(body_expr.span) &&
|
||||
// An async block does not have immediate side-effects from a `.await` point-of-view.
|
||||
(!expr.can_have_side_effects() || desugar_async_block(cx, expr).is_some()) &&
|
||||
let Some(shortened_span) = walk_span_to_context(expr.span, span.ctxt())
|
||||
|
@ -50,7 +50,7 @@ impl EarlyLintPass for DerefAddrOf {
|
||||
if_chain! {
|
||||
if let ExprKind::Unary(UnOp::Deref, ref deref_target) = e.kind;
|
||||
if let ExprKind::AddrOf(_, ref mutability, ref addrof_target) = without_parens(deref_target).kind;
|
||||
if deref_target.span.ctxt() == e.span.ctxt();
|
||||
if deref_target.span.eq_ctxt(e.span);
|
||||
if !addrof_target.span.from_expansion();
|
||||
then {
|
||||
let mut applicability = Applicability::MachineApplicable;
|
||||
|
@ -33,7 +33,7 @@ impl LateLintPass<'_> for ConfusingXorAndPow {
|
||||
if !in_external_macro(cx.sess(), expr.span)
|
||||
&& let ExprKind::Binary(op, left, right) = &expr.kind
|
||||
&& op.node == BinOpKind::BitXor
|
||||
&& left.span.ctxt() == right.span.ctxt()
|
||||
&& left.span.eq_ctxt(right.span)
|
||||
&& let ExprKind::Lit(lit_left) = &left.kind
|
||||
&& let ExprKind::Lit(lit_right) = &right.kind
|
||||
&& matches!(lit_right.node, LitKind::Int(..) | LitKind::Float(..))
|
||||
|
@ -245,7 +245,7 @@ impl<'a> PanicExpn<'a> {
|
||||
return None;
|
||||
};
|
||||
let result = match name {
|
||||
"panic" if arg.span.ctxt() == expr.span.ctxt() => Self::Empty,
|
||||
"panic" if arg.span.eq_ctxt(expr.span) => Self::Empty,
|
||||
"panic" | "panic_str" => Self::Str(arg),
|
||||
"panic_display" | "panic_cold_display" => {
|
||||
let ExprKind::AddrOf(_, _, e) = &arg.kind else {
|
||||
|
@ -1,2 +1,2 @@
|
||||
// check-fail
|
||||
// compile-flags: --check-cfg=names()
|
||||
// compile-flags: --check-cfg=cfg()
|
||||
|
@ -1,5 +1,5 @@
|
||||
// check-pass
|
||||
// compile-flags: --check-cfg=names() -Z unstable-options
|
||||
// compile-flags: --check-cfg=cfg() -Z unstable-options
|
||||
|
||||
/// uniz is nor a builtin nor pass as arguments so is unexpected
|
||||
#[cfg(uniz)]
|
||||
|
@ -1,5 +1,5 @@
|
||||
// check-pass
|
||||
// compile-flags: --test --nocapture --check-cfg=values(feature,"test") -Z unstable-options
|
||||
// compile-flags: --test --nocapture --check-cfg=cfg(feature,values("test")) -Z unstable-options
|
||||
// normalize-stderr-test: "tests/rustdoc-ui/doctest" -> "$$DIR"
|
||||
// normalize-stdout-test: "tests/rustdoc-ui/doctest" -> "$$DIR"
|
||||
// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME"
|
||||
|
13
tests/ui-fulldeps/internal-lints/span_use_eq_ctxt.rs
Normal file
13
tests/ui-fulldeps/internal-lints/span_use_eq_ctxt.rs
Normal file
@ -0,0 +1,13 @@
|
||||
// Test the `rustc::span_use_eq_ctxt` internal lint
|
||||
// compile-flags: -Z unstable-options
|
||||
|
||||
#![feature(rustc_private)]
|
||||
#![deny(rustc::span_use_eq_ctxt)]
|
||||
#![crate_type = "lib"]
|
||||
|
||||
extern crate rustc_span;
|
||||
use rustc_span::Span;
|
||||
|
||||
pub fn f(s: Span, t: Span) -> bool {
|
||||
s.ctxt() == t.ctxt() //~ ERROR use `.eq_ctxt()` instead of `.ctxt() == .ctxt()`
|
||||
}
|
14
tests/ui-fulldeps/internal-lints/span_use_eq_ctxt.stderr
Normal file
14
tests/ui-fulldeps/internal-lints/span_use_eq_ctxt.stderr
Normal file
@ -0,0 +1,14 @@
|
||||
error: use `.eq_ctxt()` instead of `.ctxt() == .ctxt()`
|
||||
--> $DIR/span_use_eq_ctxt.rs:12:5
|
||||
|
|
||||
LL | s.ctxt() == t.ctxt()
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/span_use_eq_ctxt.rs:5:9
|
||||
|
|
||||
LL | #![deny(rustc::span_use_eq_ctxt)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
91
tests/ui-fulldeps/stable-mir/instance.rs
Normal file
91
tests/ui-fulldeps/stable-mir/instance.rs
Normal file
@ -0,0 +1,91 @@
|
||||
// run-pass
|
||||
// Test that users are able to use stable mir APIs to retrieve monomorphized instances
|
||||
|
||||
// ignore-stage1
|
||||
// ignore-cross-compile
|
||||
// ignore-remote
|
||||
// edition: 2021
|
||||
|
||||
#![feature(rustc_private)]
|
||||
#![feature(assert_matches)]
|
||||
#![feature(control_flow_enum)]
|
||||
|
||||
extern crate rustc_middle;
|
||||
extern crate rustc_smir;
|
||||
extern crate stable_mir;
|
||||
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
|
||||
use stable_mir::*;
|
||||
use rustc_smir::rustc_internal;
|
||||
use std::io::Write;
|
||||
use std::ops::ControlFlow;
|
||||
|
||||
const CRATE_NAME: &str = "input";
|
||||
|
||||
/// This function uses the Stable MIR APIs to get information about the test crate.
|
||||
fn test_stable_mir(_tcx: TyCtxt<'_>) -> ControlFlow<()> {
|
||||
let items = stable_mir::all_local_items();
|
||||
|
||||
// Get all items and split generic vs monomorphic items.
|
||||
let (generic, mono) : (Vec<_>, Vec<_>) = items.into_iter().partition(|item| {
|
||||
item.requires_monomorphization()
|
||||
});
|
||||
assert_eq!(mono.len(), 3, "Expected 2 mono functions and one constant");
|
||||
assert_eq!(generic.len(), 2, "Expected 2 generic functions");
|
||||
|
||||
// For all monomorphic items, get the correspondent instances.
|
||||
let instances = mono.iter().filter_map(|item| {
|
||||
mir::mono::Instance::try_from(*item).ok()
|
||||
}).collect::<Vec<mir::mono::Instance>>();
|
||||
assert_eq!(instances.len(), mono.len());
|
||||
|
||||
// For all generic items, try_from should fail.
|
||||
assert!(generic.iter().all(|item| mir::mono::Instance::try_from(*item).is_err()));
|
||||
|
||||
ControlFlow::Continue(())
|
||||
}
|
||||
|
||||
|
||||
/// This test will generate and analyze a dummy crate using the stable mir.
|
||||
/// For that, it will first write the dummy crate into a file.
|
||||
/// Then it will create a `StableMir` using custom arguments and then
|
||||
/// it will run the compiler.
|
||||
fn main() {
|
||||
let path = "instance_input.rs";
|
||||
generate_input(&path).unwrap();
|
||||
let args = vec![
|
||||
"rustc".to_string(),
|
||||
"--crate-type=lib".to_string(),
|
||||
"--crate-name".to_string(),
|
||||
CRATE_NAME.to_string(),
|
||||
path.to_string(),
|
||||
];
|
||||
rustc_internal::StableMir::new(args, test_stable_mir).run().unwrap();
|
||||
}
|
||||
|
||||
fn generate_input(path: &str) -> std::io::Result<()> {
|
||||
let mut file = std::fs::File::create(path)?;
|
||||
write!(
|
||||
file,
|
||||
r#"
|
||||
pub fn ty_param<T>(t: &T) -> T where T: Clone {{
|
||||
t.clone()
|
||||
}}
|
||||
|
||||
pub fn const_param<const LEN: usize>(a: [bool; LEN]) -> bool {{
|
||||
LEN > 0 && a[0]
|
||||
}}
|
||||
|
||||
pub fn monomorphic() {{
|
||||
}}
|
||||
|
||||
pub mod foo {{
|
||||
pub fn bar_mono(i: i32) -> i64 {{
|
||||
i as i64
|
||||
}}
|
||||
}}
|
||||
"#
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
// This test check that #![allow(unexpected_cfgs)] works with --cfg
|
||||
//
|
||||
// check-pass
|
||||
// compile-flags: --cfg=unexpected --check-cfg=names() -Z unstable-options
|
||||
// compile-flags: --cfg=unexpected --check-cfg=cfg() -Z unstable-options
|
||||
|
||||
#![allow(unexpected_cfgs)]
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
// This test check that local #[allow(unexpected_cfgs)] works
|
||||
//
|
||||
// check-pass
|
||||
// compile-flags:--check-cfg=names() -Z unstable-options
|
||||
// compile-flags: --check-cfg=cfg() -Z unstable-options
|
||||
|
||||
#[allow(unexpected_cfgs)]
|
||||
fn foo() {
|
||||
|
@ -1,7 +1,7 @@
|
||||
// This test check that #[allow(unexpected_cfgs)] doesn't work if put on the same level
|
||||
//
|
||||
// check-pass
|
||||
// compile-flags:--check-cfg=names() -Z unstable-options
|
||||
// compile-flags: --check-cfg=cfg() -Z unstable-options
|
||||
|
||||
#[allow(unexpected_cfgs)]
|
||||
#[cfg(FALSE)]
|
||||
|
@ -1,7 +1,7 @@
|
||||
// This test check that a top-level #![allow(unexpected_cfgs)] works
|
||||
//
|
||||
// check-pass
|
||||
// compile-flags:--check-cfg=names() -Z unstable-options
|
||||
// compile-flags: --check-cfg=cfg() -Z unstable-options
|
||||
|
||||
#![allow(unexpected_cfgs)]
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
// This test check that #[allow(unexpected_cfgs)] work if put on an upper level
|
||||
//
|
||||
// check-pass
|
||||
// compile-flags:--check-cfg=names() -Z unstable-options
|
||||
// compile-flags: --check-cfg=cfg() -Z unstable-options
|
||||
|
||||
#[allow(unexpected_cfgs)]
|
||||
mod aa {
|
||||
|
@ -1,7 +1,7 @@
|
||||
// This test check that we correctly emit an warning for compact cfg
|
||||
//
|
||||
// check-pass
|
||||
// compile-flags:--check-cfg=names() -Z unstable-options
|
||||
// compile-flags: --check-cfg=cfg() -Z unstable-options
|
||||
|
||||
#![feature(cfg_target_compact)]
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
// This test check that we correctly emit an warning for compact cfg
|
||||
//
|
||||
// check-pass
|
||||
// compile-flags:--check-cfg=values() -Z unstable-options
|
||||
// compile-flags: --check-cfg=cfg() -Z unstable-options
|
||||
|
||||
#![feature(cfg_target_compact)]
|
||||
|
||||
|
13
tests/ui/check-cfg/concat-values.rs
Normal file
13
tests/ui/check-cfg/concat-values.rs
Normal file
@ -0,0 +1,13 @@
|
||||
// check-pass
|
||||
// compile-flags: -Z unstable-options
|
||||
// compile-flags: --check-cfg=cfg(my_cfg,values("foo")) --check-cfg=cfg(my_cfg,values("bar"))
|
||||
|
||||
#[cfg(my_cfg)]
|
||||
//~^ WARNING unexpected `cfg` condition value
|
||||
fn my_cfg() {}
|
||||
|
||||
#[cfg(my_cfg = "unk")]
|
||||
//~^ WARNING unexpected `cfg` condition value
|
||||
fn my_cfg() {}
|
||||
|
||||
fn main() {}
|
19
tests/ui/check-cfg/concat-values.stderr
Normal file
19
tests/ui/check-cfg/concat-values.stderr
Normal file
@ -0,0 +1,19 @@
|
||||
warning: unexpected `cfg` condition value: (none)
|
||||
--> $DIR/concat-values.rs:5:7
|
||||
|
|
||||
LL | #[cfg(my_cfg)]
|
||||
| ^^^^^^
|
||||
|
|
||||
= note: expected values for `my_cfg` are: `bar`, `foo`
|
||||
= note: `#[warn(unexpected_cfgs)]` on by default
|
||||
|
||||
warning: unexpected `cfg` condition value: `unk`
|
||||
--> $DIR/concat-values.rs:9:7
|
||||
|
|
||||
LL | #[cfg(my_cfg = "unk")]
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: expected values for `my_cfg` are: `bar`, `foo`
|
||||
|
||||
warning: 2 warnings emitted
|
||||
|
@ -1,5 +1,5 @@
|
||||
// check-pass
|
||||
// compile-flags: --check-cfg=names() --check-cfg=values(feature,"foo") --check-cfg=values(no_values) -Z unstable-options
|
||||
// compile-flags: --check-cfg=cfg(feature,values("foo")) --check-cfg=cfg(no_values) -Z unstable-options
|
||||
|
||||
#[cfg(featur)]
|
||||
//~^ WARNING unexpected `cfg` condition name
|
||||
|
@ -1,10 +0,0 @@
|
||||
// Check warning for unexpected cfg
|
||||
//
|
||||
// check-pass
|
||||
// compile-flags: --check-cfg=names() -Z unstable-options
|
||||
|
||||
#[cfg(unknown_key = "value")]
|
||||
//~^ WARNING unexpected `cfg` condition name
|
||||
pub fn f() {}
|
||||
|
||||
fn main() {}
|
@ -1,10 +0,0 @@
|
||||
// Check warning for unexpected cfg value
|
||||
//
|
||||
// check-pass
|
||||
// compile-flags: --check-cfg=values() -Z unstable-options
|
||||
|
||||
#[cfg(test = "value")]
|
||||
//~^ WARNING unexpected `cfg` condition value
|
||||
pub fn f() {}
|
||||
|
||||
fn main() {}
|
25
tests/ui/check-cfg/exhaustive-names-values.empty_cfg.stderr
Normal file
25
tests/ui/check-cfg/exhaustive-names-values.empty_cfg.stderr
Normal file
@ -0,0 +1,25 @@
|
||||
warning: unexpected `cfg` condition name: `unknown_key`
|
||||
--> $DIR/exhaustive-names-values.rs:12:7
|
||||
|
|
||||
LL | #[cfg(unknown_key = "value")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: expected names are: `debug_assertions`, `doc`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows`
|
||||
= note: `#[warn(unexpected_cfgs)]` on by default
|
||||
|
||||
warning: unexpected `cfg` condition value: `value`
|
||||
--> $DIR/exhaustive-names-values.rs:16:7
|
||||
|
|
||||
LL | #[cfg(test = "value")]
|
||||
| ^^^^----------
|
||||
| |
|
||||
| help: remove the value
|
||||
|
|
||||
= note: no expected value for `test`
|
||||
|
||||
warning: unexpected `empty_cfg` as condition name
|
||||
|
|
||||
= help: was set with `--cfg` but isn't in the `--check-cfg` expected names
|
||||
|
||||
warning: 3 warnings emitted
|
||||
|
@ -0,0 +1,25 @@
|
||||
warning: unexpected `cfg` condition name: `unknown_key`
|
||||
--> $DIR/exhaustive-names-values.rs:12:7
|
||||
|
|
||||
LL | #[cfg(unknown_key = "value")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: expected names are: `debug_assertions`, `doc`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows`
|
||||
= note: `#[warn(unexpected_cfgs)]` on by default
|
||||
|
||||
warning: unexpected `cfg` condition value: `value`
|
||||
--> $DIR/exhaustive-names-values.rs:16:7
|
||||
|
|
||||
LL | #[cfg(test = "value")]
|
||||
| ^^^^----------
|
||||
| |
|
||||
| help: remove the value
|
||||
|
|
||||
= note: no expected value for `test`
|
||||
|
||||
warning: unexpected `empty_names_values` as condition name
|
||||
|
|
||||
= help: was set with `--cfg` but isn't in the `--check-cfg` expected names
|
||||
|
||||
warning: 3 warnings emitted
|
||||
|
33
tests/ui/check-cfg/exhaustive-names-values.feature.stderr
Normal file
33
tests/ui/check-cfg/exhaustive-names-values.feature.stderr
Normal file
@ -0,0 +1,33 @@
|
||||
warning: unexpected `cfg` condition name: `unknown_key`
|
||||
--> $DIR/exhaustive-names-values.rs:12:7
|
||||
|
|
||||
LL | #[cfg(unknown_key = "value")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: expected names are: `debug_assertions`, `doc`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows`
|
||||
= note: `#[warn(unexpected_cfgs)]` on by default
|
||||
|
||||
warning: unexpected `cfg` condition value: `value`
|
||||
--> $DIR/exhaustive-names-values.rs:16:7
|
||||
|
|
||||
LL | #[cfg(test = "value")]
|
||||
| ^^^^----------
|
||||
| |
|
||||
| help: remove the value
|
||||
|
|
||||
= note: no expected value for `test`
|
||||
|
||||
warning: unexpected `cfg` condition value: `unk`
|
||||
--> $DIR/exhaustive-names-values.rs:20:7
|
||||
|
|
||||
LL | #[cfg(feature = "unk")]
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: expected values for `feature` are: `std`
|
||||
|
||||
warning: unexpected condition value `` for condition name `feature`
|
||||
|
|
||||
= help: was set with `--cfg` but isn't in the `--check-cfg` expected values
|
||||
|
||||
warning: 4 warnings emitted
|
||||
|
33
tests/ui/check-cfg/exhaustive-names-values.full.stderr
Normal file
33
tests/ui/check-cfg/exhaustive-names-values.full.stderr
Normal file
@ -0,0 +1,33 @@
|
||||
warning: unexpected `cfg` condition name: `unknown_key`
|
||||
--> $DIR/exhaustive-names-values.rs:12:7
|
||||
|
|
||||
LL | #[cfg(unknown_key = "value")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: expected names are: `debug_assertions`, `doc`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows`
|
||||
= note: `#[warn(unexpected_cfgs)]` on by default
|
||||
|
||||
warning: unexpected `cfg` condition value: `value`
|
||||
--> $DIR/exhaustive-names-values.rs:16:7
|
||||
|
|
||||
LL | #[cfg(test = "value")]
|
||||
| ^^^^----------
|
||||
| |
|
||||
| help: remove the value
|
||||
|
|
||||
= note: no expected value for `test`
|
||||
|
||||
warning: unexpected `cfg` condition value: `unk`
|
||||
--> $DIR/exhaustive-names-values.rs:20:7
|
||||
|
|
||||
LL | #[cfg(feature = "unk")]
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: expected values for `feature` are: `std`
|
||||
|
||||
warning: unexpected `full` as condition name
|
||||
|
|
||||
= help: was set with `--cfg` but isn't in the `--check-cfg` expected names
|
||||
|
||||
warning: 4 warnings emitted
|
||||
|
34
tests/ui/check-cfg/exhaustive-names-values.rs
Normal file
34
tests/ui/check-cfg/exhaustive-names-values.rs
Normal file
@ -0,0 +1,34 @@
|
||||
// Check warning for unexpected cfg in the code and in the CLI
|
||||
// arguments (here the revision cfg).
|
||||
//
|
||||
// check-pass
|
||||
// revisions: empty_names_values empty_cfg feature full
|
||||
// compile-flags: -Z unstable-options
|
||||
// [empty_names_values]compile-flags: --check-cfg=names() --check-cfg=values()
|
||||
// [empty_cfg]compile-flags: --check-cfg=cfg()
|
||||
// [feature]compile-flags: --check-cfg=cfg(feature,values("std"))
|
||||
// [full]compile-flags: --check-cfg=cfg(feature,values("std")) --check-cfg=cfg()
|
||||
|
||||
#[cfg(unknown_key = "value")]
|
||||
//~^ WARNING unexpected `cfg` condition name
|
||||
pub fn f() {}
|
||||
|
||||
#[cfg(test = "value")]
|
||||
//~^ WARNING unexpected `cfg` condition value
|
||||
pub fn f() {}
|
||||
|
||||
#[cfg(feature = "unk")]
|
||||
//[feature]~^ WARNING unexpected `cfg` condition value
|
||||
//[full]~^^ WARNING unexpected `cfg` condition value
|
||||
pub fn feat() {}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
pub fn feat() {}
|
||||
|
||||
#[cfg(windows)]
|
||||
pub fn win() {}
|
||||
|
||||
#[cfg(unix)]
|
||||
pub fn unix() {}
|
||||
|
||||
fn main() {}
|
@ -1,5 +1,5 @@
|
||||
warning: unexpected `cfg` condition name: `unknown_key`
|
||||
--> $DIR/empty-names.rs:6:7
|
||||
--> $DIR/exhaustive-names.rs:8:7
|
||||
|
|
||||
LL | #[cfg(unknown_key = "value")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -7,5 +7,9 @@ LL | #[cfg(unknown_key = "value")]
|
||||
= help: expected names are: `debug_assertions`, `doc`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows`
|
||||
= note: `#[warn(unexpected_cfgs)]` on by default
|
||||
|
||||
warning: 1 warning emitted
|
||||
warning: unexpected `empty_names` as condition name
|
||||
|
|
||||
= help: was set with `--cfg` but isn't in the `--check-cfg` expected names
|
||||
|
||||
warning: 2 warnings emitted
|
||||
|
15
tests/ui/check-cfg/exhaustive-names.exhaustive_names.stderr
Normal file
15
tests/ui/check-cfg/exhaustive-names.exhaustive_names.stderr
Normal file
@ -0,0 +1,15 @@
|
||||
warning: unexpected `cfg` condition name: `unknown_key`
|
||||
--> $DIR/exhaustive-names.rs:8:7
|
||||
|
|
||||
LL | #[cfg(unknown_key = "value")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: expected names are: `debug_assertions`, `doc`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows`
|
||||
= note: `#[warn(unexpected_cfgs)]` on by default
|
||||
|
||||
warning: unexpected `exhaustive_names` as condition name
|
||||
|
|
||||
= help: was set with `--cfg` but isn't in the `--check-cfg` expected names
|
||||
|
||||
warning: 2 warnings emitted
|
||||
|
12
tests/ui/check-cfg/exhaustive-names.rs
Normal file
12
tests/ui/check-cfg/exhaustive-names.rs
Normal file
@ -0,0 +1,12 @@
|
||||
// Check warning for unexpected cfg
|
||||
//
|
||||
// check-pass
|
||||
// revisions: empty_names exhaustive_names
|
||||
// [empty_names]compile-flags: --check-cfg=names() -Z unstable-options
|
||||
// [exhaustive_names]compile-flags: --check-cfg=cfg() -Z unstable-options
|
||||
|
||||
#[cfg(unknown_key = "value")]
|
||||
//~^ WARNING unexpected `cfg` condition name
|
||||
pub fn f() {}
|
||||
|
||||
fn main() {}
|
17
tests/ui/check-cfg/exhaustive-values.empty_cfg.stderr
Normal file
17
tests/ui/check-cfg/exhaustive-values.empty_cfg.stderr
Normal file
@ -0,0 +1,17 @@
|
||||
warning: unexpected `cfg` condition value: `value`
|
||||
--> $DIR/exhaustive-values.rs:9:7
|
||||
|
|
||||
LL | #[cfg(test = "value")]
|
||||
| ^^^^----------
|
||||
| |
|
||||
| help: remove the value
|
||||
|
|
||||
= note: no expected value for `test`
|
||||
= note: `#[warn(unexpected_cfgs)]` on by default
|
||||
|
||||
warning: unexpected `empty_cfg` as condition name
|
||||
|
|
||||
= help: was set with `--cfg` but isn't in the `--check-cfg` expected names
|
||||
|
||||
warning: 2 warnings emitted
|
||||
|
@ -1,5 +1,5 @@
|
||||
warning: unexpected `cfg` condition value: `value`
|
||||
--> $DIR/empty-values.rs:6:7
|
||||
--> $DIR/exhaustive-values.rs:9:7
|
||||
|
|
||||
LL | #[cfg(test = "value")]
|
||||
| ^^^^----------
|
13
tests/ui/check-cfg/exhaustive-values.rs
Normal file
13
tests/ui/check-cfg/exhaustive-values.rs
Normal file
@ -0,0 +1,13 @@
|
||||
// Check warning for unexpected cfg value
|
||||
//
|
||||
// check-pass
|
||||
// revisions: empty_values empty_cfg without_names
|
||||
// [empty_values]compile-flags: --check-cfg=values() -Z unstable-options
|
||||
// [empty_cfg]compile-flags: --check-cfg=cfg() -Z unstable-options
|
||||
// [without_names]compile-flags: --check-cfg=cfg(any()) -Z unstable-options
|
||||
|
||||
#[cfg(test = "value")]
|
||||
//~^ WARNING unexpected `cfg` condition value
|
||||
pub fn f() {}
|
||||
|
||||
fn main() {}
|
13
tests/ui/check-cfg/exhaustive-values.without_names.stderr
Normal file
13
tests/ui/check-cfg/exhaustive-values.without_names.stderr
Normal file
@ -0,0 +1,13 @@
|
||||
warning: unexpected `cfg` condition value: `value`
|
||||
--> $DIR/exhaustive-values.rs:9:7
|
||||
|
|
||||
LL | #[cfg(test = "value")]
|
||||
| ^^^^----------
|
||||
| |
|
||||
| help: remove the value
|
||||
|
|
||||
= note: no expected value for `test`
|
||||
= note: `#[warn(unexpected_cfgs)]` on by default
|
||||
|
||||
warning: 1 warning emitted
|
||||
|
@ -1,2 +1,2 @@
|
||||
error: invalid `--check-cfg` argument: `anything_else(...)` (expected `names(name1, name2, ... nameN)` or `values(name, "value1", "value2", ... "valueN")`)
|
||||
error: invalid `--check-cfg` argument: `anything_else(...)` (expected `cfg(name, values("value1", "value2", ... "valueN"))`)
|
||||
|
||||
|
2
tests/ui/check-cfg/invalid-arguments.giberich.stderr
Normal file
2
tests/ui/check-cfg/invalid-arguments.giberich.stderr
Normal file
@ -0,0 +1,2 @@
|
||||
error: invalid `--check-cfg` argument: `cfg(...)` (expected `cfg(name, values("value1", "value2", ... "valueN"))`)
|
||||
|
@ -0,0 +1,2 @@
|
||||
error: invalid `--check-cfg` argument: `cfg(foo,values(bar))` (`values()` arguments must be string literals or `any()`)
|
||||
|
@ -0,0 +1,2 @@
|
||||
error: invalid `--check-cfg` argument: `cfg(foo,values("bar",bar,"bar"))` (`values()` arguments must be string literals or `any()`)
|
||||
|
2
tests/ui/check-cfg/invalid-arguments.mixed_any.stderr
Normal file
2
tests/ui/check-cfg/invalid-arguments.mixed_any.stderr
Normal file
@ -0,0 +1,2 @@
|
||||
error: invalid `--check-cfg` argument: `cfg(any(),values(any()))` (`values()` cannot be specified before the names)
|
||||
|
@ -0,0 +1,2 @@
|
||||
error: invalid `--check-cfg` argument: `cfg(foo,values("bar",any()))` (`values()` arguments cannot specify string literals and `any()` at the same time)
|
||||
|
2
tests/ui/check-cfg/invalid-arguments.multiple_any.stderr
Normal file
2
tests/ui/check-cfg/invalid-arguments.multiple_any.stderr
Normal file
@ -0,0 +1,2 @@
|
||||
error: invalid `--check-cfg` argument: `cfg(any(),any())` (`any()` cannot be specified multiple times)
|
||||
|
@ -0,0 +1,2 @@
|
||||
error: invalid `--check-cfg` argument: `cfg(foo,values(),values())` (`values()` cannot be specified multiple times)
|
||||
|
@ -0,0 +1,2 @@
|
||||
error: invalid `--check-cfg` argument: `cfg(foo,values(any(),any()))` (`any()` in `values()` cannot be specified multiple times)
|
||||
|
@ -0,0 +1,2 @@
|
||||
error: invalid `--check-cfg` argument: `cfg(any(foo))` (`any()` must be empty)
|
||||
|
@ -0,0 +1,2 @@
|
||||
error: invalid `--check-cfg` argument: `cfg(foo,values(any(bar)))` (`any()` must be empty)
|
||||
|
@ -2,9 +2,33 @@
|
||||
//
|
||||
// check-fail
|
||||
// revisions: anything_else names_simple_ident values_simple_ident values_string_literals
|
||||
// [anything_else]compile-flags: -Z unstable-options --check-cfg=anything_else(...)
|
||||
// [names_simple_ident]compile-flags: -Z unstable-options --check-cfg=names("NOT_IDENT")
|
||||
// [values_simple_ident]compile-flags: -Z unstable-options --check-cfg=values("NOT_IDENT")
|
||||
// [values_string_literals]compile-flags: -Z unstable-options --check-cfg=values(test,12)
|
||||
// revisions: string_for_name_1 string_for_name_2 multiple_any multiple_values
|
||||
// revisions: multiple_values_any not_empty_any not_empty_values_any
|
||||
// revisions: values_any_missing_values values_any_before_ident ident_in_values_1
|
||||
// revisions: ident_in_values_2 unknown_meta_item_1 unknown_meta_item_2 unknown_meta_item_3
|
||||
// revisions: mixed_values_any mixed_any giberich
|
||||
//
|
||||
// compile-flags: -Z unstable-options
|
||||
// [anything_else]compile-flags: --check-cfg=anything_else(...)
|
||||
// [names_simple_ident]compile-flags: --check-cfg=names("NOT_IDENT")
|
||||
// [values_simple_ident]compile-flags: --check-cfg=values("NOT_IDENT")
|
||||
// [values_string_literals]compile-flags: --check-cfg=values(test,12)
|
||||
// [string_for_name_1]compile-flags: --check-cfg=cfg("NOT_IDENT")
|
||||
// [string_for_name_2]compile-flags: --check-cfg=cfg(foo,"NOT_IDENT",bar)
|
||||
// [multiple_any]compile-flags: --check-cfg=cfg(any(),any())
|
||||
// [multiple_values]compile-flags: --check-cfg=cfg(foo,values(),values())
|
||||
// [multiple_values_any]compile-flags: --check-cfg=cfg(foo,values(any(),any()))
|
||||
// [not_empty_any]compile-flags: --check-cfg=cfg(any(foo))
|
||||
// [not_empty_values_any]compile-flags: --check-cfg=cfg(foo,values(any(bar)))
|
||||
// [values_any_missing_values]compile-flags: --check-cfg=cfg(foo,any())
|
||||
// [values_any_before_ident]compile-flags: --check-cfg=cfg(values(any()),foo)
|
||||
// [ident_in_values_1]compile-flags: --check-cfg=cfg(foo,values(bar))
|
||||
// [ident_in_values_2]compile-flags: --check-cfg=cfg(foo,values("bar",bar,"bar"))
|
||||
// [unknown_meta_item_1]compile-flags: --check-cfg=abc()
|
||||
// [unknown_meta_item_2]compile-flags: --check-cfg=cfg(foo,test())
|
||||
// [unknown_meta_item_3]compile-flags: --check-cfg=cfg(foo,values(test()))
|
||||
// [mixed_values_any]compile-flags: --check-cfg=cfg(foo,values("bar",any()))
|
||||
// [mixed_any]compile-flags: --check-cfg=cfg(any(),values(any()))
|
||||
// [giberich]compile-flags: --check-cfg=cfg(...)
|
||||
|
||||
fn main() {}
|
||||
|
@ -0,0 +1,2 @@
|
||||
error: invalid `--check-cfg` argument: `cfg("NOT_IDENT")` (`cfg()` arguments must be simple identifiers, `any()` or `values(...)`)
|
||||
|
@ -0,0 +1,2 @@
|
||||
error: invalid `--check-cfg` argument: `cfg(foo,"NOT_IDENT",bar)` (`cfg()` arguments must be simple identifiers, `any()` or `values(...)`)
|
||||
|
@ -0,0 +1,2 @@
|
||||
error: invalid `--check-cfg` argument: `abc()` (expected `cfg(name, values("value1", "value2", ... "valueN"))`)
|
||||
|
@ -0,0 +1,2 @@
|
||||
error: invalid `--check-cfg` argument: `cfg(foo,test())` (`cfg()` arguments must be simple identifiers, `any()` or `values(...)`)
|
||||
|
@ -0,0 +1,2 @@
|
||||
error: invalid `--check-cfg` argument: `cfg(foo,values(test()))` (`values()` arguments must be string literals or `any()`)
|
||||
|
@ -0,0 +1,2 @@
|
||||
error: invalid `--check-cfg` argument: `cfg(values(any()),foo)` (`values()` cannot be specified before the names)
|
||||
|
@ -0,0 +1,2 @@
|
||||
error: invalid `--check-cfg` argument: `cfg(foo,any())` (`cfg(any())` can only be provided in isolation)
|
||||
|
@ -1,14 +0,0 @@
|
||||
// Check warning for invalid configuration name
|
||||
//
|
||||
// edition:2018
|
||||
// check-pass
|
||||
// compile-flags: --check-cfg=names() -Z unstable-options
|
||||
|
||||
#[cfg(widnows)]
|
||||
//~^ WARNING unexpected `cfg` condition name
|
||||
pub fn f() {}
|
||||
|
||||
#[cfg(windows)]
|
||||
pub fn g() {}
|
||||
|
||||
pub fn main() {}
|
@ -1,18 +0,0 @@
|
||||
// Check warning for invalid configuration value
|
||||
//
|
||||
// edition:2018
|
||||
// check-pass
|
||||
// compile-flags: --check-cfg=values(feature,"serde","full") --cfg=feature="rand" -Z unstable-options
|
||||
|
||||
#[cfg(feature = "sedre")]
|
||||
//~^ WARNING unexpected `cfg` condition value
|
||||
pub fn f() {}
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
pub fn g() {}
|
||||
|
||||
#[cfg(feature = "rand")]
|
||||
//~^ WARNING unexpected `cfg` condition value
|
||||
pub fn h() {}
|
||||
|
||||
pub fn main() {}
|
@ -1,5 +1,5 @@
|
||||
warning: unexpected `cfg` condition name: `widnows`
|
||||
--> $DIR/mix.rs:11:7
|
||||
--> $DIR/mix.rs:15:7
|
||||
|
|
||||
LL | #[cfg(widnows)]
|
||||
| ^^^^^^^ help: there is a config with a similar name: `windows`
|
||||
@ -7,7 +7,7 @@ LL | #[cfg(widnows)]
|
||||
= note: `#[warn(unexpected_cfgs)]` on by default
|
||||
|
||||
warning: unexpected `cfg` condition value: (none)
|
||||
--> $DIR/mix.rs:15:7
|
||||
--> $DIR/mix.rs:19:7
|
||||
|
|
||||
LL | #[cfg(feature)]
|
||||
| ^^^^^^^- help: specify a config value: `= "foo"`
|
||||
@ -15,7 +15,7 @@ LL | #[cfg(feature)]
|
||||
= note: expected values for `feature` are: `foo`
|
||||
|
||||
warning: unexpected `cfg` condition value: `bar`
|
||||
--> $DIR/mix.rs:22:7
|
||||
--> $DIR/mix.rs:26:7
|
||||
|
|
||||
LL | #[cfg(feature = "bar")]
|
||||
| ^^^^^^^^^^^^^^^
|
||||
@ -23,7 +23,7 @@ LL | #[cfg(feature = "bar")]
|
||||
= note: expected values for `feature` are: `foo`
|
||||
|
||||
warning: unexpected `cfg` condition value: `zebra`
|
||||
--> $DIR/mix.rs:26:7
|
||||
--> $DIR/mix.rs:30:7
|
||||
|
|
||||
LL | #[cfg(feature = "zebra")]
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
@ -31,12 +31,12 @@ LL | #[cfg(feature = "zebra")]
|
||||
= note: expected values for `feature` are: `foo`
|
||||
|
||||
warning: unexpected `cfg` condition name: `uu`
|
||||
--> $DIR/mix.rs:30:12
|
||||
--> $DIR/mix.rs:34:12
|
||||
|
|
||||
LL | #[cfg_attr(uu, test)]
|
||||
| ^^
|
||||
|
|
||||
= help: expected names are: `debug_assertions`, `doc`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows`
|
||||
= help: expected names are: `cfg`, `debug_assertions`, `doc`, `doctest`, `feature`, `miri`, `names_values`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows`
|
||||
|
||||
warning: unexpected condition value `bar` for condition name `feature`
|
||||
|
|
||||
@ -47,13 +47,13 @@ warning: unexpected `unknown_name` as condition name
|
||||
= help: was set with `--cfg` but isn't in the `--check-cfg` expected names
|
||||
|
||||
warning: unexpected `cfg` condition name: `widnows`
|
||||
--> $DIR/mix.rs:39:10
|
||||
--> $DIR/mix.rs:43:10
|
||||
|
|
||||
LL | cfg!(widnows);
|
||||
| ^^^^^^^ help: there is a config with a similar name: `windows`
|
||||
|
||||
warning: unexpected `cfg` condition value: `bar`
|
||||
--> $DIR/mix.rs:42:10
|
||||
--> $DIR/mix.rs:46:10
|
||||
|
|
||||
LL | cfg!(feature = "bar");
|
||||
| ^^^^^^^^^^^^^^^
|
||||
@ -61,7 +61,7 @@ LL | cfg!(feature = "bar");
|
||||
= note: expected values for `feature` are: `foo`
|
||||
|
||||
warning: unexpected `cfg` condition value: `zebra`
|
||||
--> $DIR/mix.rs:44:10
|
||||
--> $DIR/mix.rs:48:10
|
||||
|
|
||||
LL | cfg!(feature = "zebra");
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
@ -69,25 +69,25 @@ LL | cfg!(feature = "zebra");
|
||||
= note: expected values for `feature` are: `foo`
|
||||
|
||||
warning: unexpected `cfg` condition name: `xxx`
|
||||
--> $DIR/mix.rs:46:10
|
||||
--> $DIR/mix.rs:50:10
|
||||
|
|
||||
LL | cfg!(xxx = "foo");
|
||||
| ^^^^^^^^^^^
|
||||
|
||||
warning: unexpected `cfg` condition name: `xxx`
|
||||
--> $DIR/mix.rs:48:10
|
||||
--> $DIR/mix.rs:52:10
|
||||
|
|
||||
LL | cfg!(xxx);
|
||||
| ^^^
|
||||
|
||||
warning: unexpected `cfg` condition name: `xxx`
|
||||
--> $DIR/mix.rs:50:14
|
||||
--> $DIR/mix.rs:54:14
|
||||
|
|
||||
LL | cfg!(any(xxx, windows));
|
||||
| ^^^
|
||||
|
||||
warning: unexpected `cfg` condition value: `bad`
|
||||
--> $DIR/mix.rs:52:14
|
||||
--> $DIR/mix.rs:56:14
|
||||
|
|
||||
LL | cfg!(any(feature = "bad", windows));
|
||||
| ^^^^^^^^^^^^^^^
|
||||
@ -95,43 +95,43 @@ LL | cfg!(any(feature = "bad", windows));
|
||||
= note: expected values for `feature` are: `foo`
|
||||
|
||||
warning: unexpected `cfg` condition name: `xxx`
|
||||
--> $DIR/mix.rs:54:23
|
||||
--> $DIR/mix.rs:58:23
|
||||
|
|
||||
LL | cfg!(any(windows, xxx));
|
||||
| ^^^
|
||||
|
||||
warning: unexpected `cfg` condition name: `xxx`
|
||||
--> $DIR/mix.rs:56:20
|
||||
--> $DIR/mix.rs:60:20
|
||||
|
|
||||
LL | cfg!(all(unix, xxx));
|
||||
| ^^^
|
||||
|
||||
warning: unexpected `cfg` condition name: `aa`
|
||||
--> $DIR/mix.rs:58:14
|
||||
--> $DIR/mix.rs:62:14
|
||||
|
|
||||
LL | cfg!(all(aa, bb));
|
||||
| ^^
|
||||
|
||||
warning: unexpected `cfg` condition name: `bb`
|
||||
--> $DIR/mix.rs:58:18
|
||||
--> $DIR/mix.rs:62:18
|
||||
|
|
||||
LL | cfg!(all(aa, bb));
|
||||
| ^^
|
||||
|
||||
warning: unexpected `cfg` condition name: `aa`
|
||||
--> $DIR/mix.rs:61:14
|
||||
--> $DIR/mix.rs:65:14
|
||||
|
|
||||
LL | cfg!(any(aa, bb));
|
||||
| ^^
|
||||
|
||||
warning: unexpected `cfg` condition name: `bb`
|
||||
--> $DIR/mix.rs:61:18
|
||||
--> $DIR/mix.rs:65:18
|
||||
|
|
||||
LL | cfg!(any(aa, bb));
|
||||
| ^^
|
||||
|
||||
warning: unexpected `cfg` condition value: `zebra`
|
||||
--> $DIR/mix.rs:64:20
|
||||
--> $DIR/mix.rs:68:20
|
||||
|
|
||||
LL | cfg!(any(unix, feature = "zebra"));
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
@ -139,13 +139,13 @@ LL | cfg!(any(unix, feature = "zebra"));
|
||||
= note: expected values for `feature` are: `foo`
|
||||
|
||||
warning: unexpected `cfg` condition name: `xxx`
|
||||
--> $DIR/mix.rs:66:14
|
||||
--> $DIR/mix.rs:70:14
|
||||
|
|
||||
LL | cfg!(any(xxx, feature = "zebra"));
|
||||
| ^^^
|
||||
|
||||
warning: unexpected `cfg` condition value: `zebra`
|
||||
--> $DIR/mix.rs:66:19
|
||||
--> $DIR/mix.rs:70:19
|
||||
|
|
||||
LL | cfg!(any(xxx, feature = "zebra"));
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
@ -153,19 +153,19 @@ LL | cfg!(any(xxx, feature = "zebra"));
|
||||
= note: expected values for `feature` are: `foo`
|
||||
|
||||
warning: unexpected `cfg` condition name: `xxx`
|
||||
--> $DIR/mix.rs:69:14
|
||||
--> $DIR/mix.rs:73:14
|
||||
|
|
||||
LL | cfg!(any(xxx, unix, xxx));
|
||||
| ^^^
|
||||
|
||||
warning: unexpected `cfg` condition name: `xxx`
|
||||
--> $DIR/mix.rs:69:25
|
||||
--> $DIR/mix.rs:73:25
|
||||
|
|
||||
LL | cfg!(any(xxx, unix, xxx));
|
||||
| ^^^
|
||||
|
||||
warning: unexpected `cfg` condition value: `zebra`
|
||||
--> $DIR/mix.rs:72:14
|
||||
--> $DIR/mix.rs:76:14
|
||||
|
|
||||
LL | cfg!(all(feature = "zebra", feature = "zebra", feature = "zebra"));
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
@ -173,7 +173,7 @@ LL | cfg!(all(feature = "zebra", feature = "zebra", feature = "zebra"));
|
||||
= note: expected values for `feature` are: `foo`
|
||||
|
||||
warning: unexpected `cfg` condition value: `zebra`
|
||||
--> $DIR/mix.rs:72:33
|
||||
--> $DIR/mix.rs:76:33
|
||||
|
|
||||
LL | cfg!(all(feature = "zebra", feature = "zebra", feature = "zebra"));
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
@ -181,7 +181,7 @@ LL | cfg!(all(feature = "zebra", feature = "zebra", feature = "zebra"));
|
||||
= note: expected values for `feature` are: `foo`
|
||||
|
||||
warning: unexpected `cfg` condition value: `zebra`
|
||||
--> $DIR/mix.rs:72:52
|
||||
--> $DIR/mix.rs:76:52
|
||||
|
|
||||
LL | cfg!(all(feature = "zebra", feature = "zebra", feature = "zebra"));
|
||||
| ^^^^^^^^^^^^^^^^^
|
192
tests/ui/check-cfg/mix.names_values.stderr
Normal file
192
tests/ui/check-cfg/mix.names_values.stderr
Normal file
@ -0,0 +1,192 @@
|
||||
warning: unexpected `cfg` condition name: `widnows`
|
||||
--> $DIR/mix.rs:15:7
|
||||
|
|
||||
LL | #[cfg(widnows)]
|
||||
| ^^^^^^^ help: there is a config with a similar name: `windows`
|
||||
|
|
||||
= note: `#[warn(unexpected_cfgs)]` on by default
|
||||
|
||||
warning: unexpected `cfg` condition value: (none)
|
||||
--> $DIR/mix.rs:19:7
|
||||
|
|
||||
LL | #[cfg(feature)]
|
||||
| ^^^^^^^- help: specify a config value: `= "foo"`
|
||||
|
|
||||
= note: expected values for `feature` are: `foo`
|
||||
|
||||
warning: unexpected `cfg` condition value: `bar`
|
||||
--> $DIR/mix.rs:26:7
|
||||
|
|
||||
LL | #[cfg(feature = "bar")]
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: expected values for `feature` are: `foo`
|
||||
|
||||
warning: unexpected `cfg` condition value: `zebra`
|
||||
--> $DIR/mix.rs:30:7
|
||||
|
|
||||
LL | #[cfg(feature = "zebra")]
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: expected values for `feature` are: `foo`
|
||||
|
||||
warning: unexpected `cfg` condition name: `uu`
|
||||
--> $DIR/mix.rs:34:12
|
||||
|
|
||||
LL | #[cfg_attr(uu, test)]
|
||||
| ^^
|
||||
|
|
||||
= help: expected names are: `cfg`, `debug_assertions`, `doc`, `doctest`, `feature`, `miri`, `names_values`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows`
|
||||
|
||||
warning: unexpected condition value `bar` for condition name `feature`
|
||||
|
|
||||
= help: was set with `--cfg` but isn't in the `--check-cfg` expected values
|
||||
|
||||
warning: unexpected `unknown_name` as condition name
|
||||
|
|
||||
= help: was set with `--cfg` but isn't in the `--check-cfg` expected names
|
||||
|
||||
warning: unexpected `cfg` condition name: `widnows`
|
||||
--> $DIR/mix.rs:43:10
|
||||
|
|
||||
LL | cfg!(widnows);
|
||||
| ^^^^^^^ help: there is a config with a similar name: `windows`
|
||||
|
||||
warning: unexpected `cfg` condition value: `bar`
|
||||
--> $DIR/mix.rs:46:10
|
||||
|
|
||||
LL | cfg!(feature = "bar");
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: expected values for `feature` are: `foo`
|
||||
|
||||
warning: unexpected `cfg` condition value: `zebra`
|
||||
--> $DIR/mix.rs:48:10
|
||||
|
|
||||
LL | cfg!(feature = "zebra");
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: expected values for `feature` are: `foo`
|
||||
|
||||
warning: unexpected `cfg` condition name: `xxx`
|
||||
--> $DIR/mix.rs:50:10
|
||||
|
|
||||
LL | cfg!(xxx = "foo");
|
||||
| ^^^^^^^^^^^
|
||||
|
||||
warning: unexpected `cfg` condition name: `xxx`
|
||||
--> $DIR/mix.rs:52:10
|
||||
|
|
||||
LL | cfg!(xxx);
|
||||
| ^^^
|
||||
|
||||
warning: unexpected `cfg` condition name: `xxx`
|
||||
--> $DIR/mix.rs:54:14
|
||||
|
|
||||
LL | cfg!(any(xxx, windows));
|
||||
| ^^^
|
||||
|
||||
warning: unexpected `cfg` condition value: `bad`
|
||||
--> $DIR/mix.rs:56:14
|
||||
|
|
||||
LL | cfg!(any(feature = "bad", windows));
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: expected values for `feature` are: `foo`
|
||||
|
||||
warning: unexpected `cfg` condition name: `xxx`
|
||||
--> $DIR/mix.rs:58:23
|
||||
|
|
||||
LL | cfg!(any(windows, xxx));
|
||||
| ^^^
|
||||
|
||||
warning: unexpected `cfg` condition name: `xxx`
|
||||
--> $DIR/mix.rs:60:20
|
||||
|
|
||||
LL | cfg!(all(unix, xxx));
|
||||
| ^^^
|
||||
|
||||
warning: unexpected `cfg` condition name: `aa`
|
||||
--> $DIR/mix.rs:62:14
|
||||
|
|
||||
LL | cfg!(all(aa, bb));
|
||||
| ^^
|
||||
|
||||
warning: unexpected `cfg` condition name: `bb`
|
||||
--> $DIR/mix.rs:62:18
|
||||
|
|
||||
LL | cfg!(all(aa, bb));
|
||||
| ^^
|
||||
|
||||
warning: unexpected `cfg` condition name: `aa`
|
||||
--> $DIR/mix.rs:65:14
|
||||
|
|
||||
LL | cfg!(any(aa, bb));
|
||||
| ^^
|
||||
|
||||
warning: unexpected `cfg` condition name: `bb`
|
||||
--> $DIR/mix.rs:65:18
|
||||
|
|
||||
LL | cfg!(any(aa, bb));
|
||||
| ^^
|
||||
|
||||
warning: unexpected `cfg` condition value: `zebra`
|
||||
--> $DIR/mix.rs:68:20
|
||||
|
|
||||
LL | cfg!(any(unix, feature = "zebra"));
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: expected values for `feature` are: `foo`
|
||||
|
||||
warning: unexpected `cfg` condition name: `xxx`
|
||||
--> $DIR/mix.rs:70:14
|
||||
|
|
||||
LL | cfg!(any(xxx, feature = "zebra"));
|
||||
| ^^^
|
||||
|
||||
warning: unexpected `cfg` condition value: `zebra`
|
||||
--> $DIR/mix.rs:70:19
|
||||
|
|
||||
LL | cfg!(any(xxx, feature = "zebra"));
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: expected values for `feature` are: `foo`
|
||||
|
||||
warning: unexpected `cfg` condition name: `xxx`
|
||||
--> $DIR/mix.rs:73:14
|
||||
|
|
||||
LL | cfg!(any(xxx, unix, xxx));
|
||||
| ^^^
|
||||
|
||||
warning: unexpected `cfg` condition name: `xxx`
|
||||
--> $DIR/mix.rs:73:25
|
||||
|
|
||||
LL | cfg!(any(xxx, unix, xxx));
|
||||
| ^^^
|
||||
|
||||
warning: unexpected `cfg` condition value: `zebra`
|
||||
--> $DIR/mix.rs:76:14
|
||||
|
|
||||
LL | cfg!(all(feature = "zebra", feature = "zebra", feature = "zebra"));
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: expected values for `feature` are: `foo`
|
||||
|
||||
warning: unexpected `cfg` condition value: `zebra`
|
||||
--> $DIR/mix.rs:76:33
|
||||
|
|
||||
LL | cfg!(all(feature = "zebra", feature = "zebra", feature = "zebra"));
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: expected values for `feature` are: `foo`
|
||||
|
||||
warning: unexpected `cfg` condition value: `zebra`
|
||||
--> $DIR/mix.rs:76:52
|
||||
|
|
||||
LL | cfg!(all(feature = "zebra", feature = "zebra", feature = "zebra"));
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: expected values for `feature` are: `foo`
|
||||
|
||||
warning: 28 warnings emitted
|
||||
|
@ -3,7 +3,11 @@
|
||||
// we correctly lint on the `cfg!` macro and `cfg_attr` attribute.
|
||||
//
|
||||
// check-pass
|
||||
// compile-flags: --check-cfg=names() --check-cfg=values(feature,"foo") --cfg feature="bar" --cfg unknown_name -Z unstable-options
|
||||
// revisions: names_values cfg
|
||||
// compile-flags: --cfg feature="bar" --cfg unknown_name -Z unstable-options
|
||||
// compile-flags: --check-cfg=cfg(names_values,cfg)
|
||||
// [names_values]compile-flags: --check-cfg=names() --check-cfg=values(feature,"foo")
|
||||
// [cfg]compile-flags: --check-cfg=cfg(feature,values("foo"))
|
||||
|
||||
#[cfg(windows)]
|
||||
fn do_windows_stuff() {}
|
||||
|
@ -1,5 +1,5 @@
|
||||
warning: unexpected `cfg` condition value: `foo`
|
||||
--> $DIR/no-values.rs:6:7
|
||||
--> $DIR/no-expected-values.rs:12:7
|
||||
|
|
||||
LL | #[cfg(feature = "foo")]
|
||||
| ^^^^^^^--------
|
||||
@ -10,7 +10,7 @@ LL | #[cfg(feature = "foo")]
|
||||
= note: `#[warn(unexpected_cfgs)]` on by default
|
||||
|
||||
warning: unexpected `cfg` condition value: `foo`
|
||||
--> $DIR/no-values.rs:10:7
|
||||
--> $DIR/no-expected-values.rs:16:7
|
||||
|
|
||||
LL | #[cfg(test = "foo")]
|
||||
| ^^^^--------
|
23
tests/ui/check-cfg/no-expected-values.mixed.stderr
Normal file
23
tests/ui/check-cfg/no-expected-values.mixed.stderr
Normal file
@ -0,0 +1,23 @@
|
||||
warning: unexpected `cfg` condition value: `foo`
|
||||
--> $DIR/no-expected-values.rs:12:7
|
||||
|
|
||||
LL | #[cfg(feature = "foo")]
|
||||
| ^^^^^^^--------
|
||||
| |
|
||||
| help: remove the value
|
||||
|
|
||||
= note: no expected value for `feature`
|
||||
= note: `#[warn(unexpected_cfgs)]` on by default
|
||||
|
||||
warning: unexpected `cfg` condition value: `foo`
|
||||
--> $DIR/no-expected-values.rs:16:7
|
||||
|
|
||||
LL | #[cfg(test = "foo")]
|
||||
| ^^^^--------
|
||||
| |
|
||||
| help: remove the value
|
||||
|
|
||||
= note: no expected value for `test`
|
||||
|
||||
warning: 2 warnings emitted
|
||||
|
20
tests/ui/check-cfg/no-expected-values.rs
Normal file
20
tests/ui/check-cfg/no-expected-values.rs
Normal file
@ -0,0 +1,20 @@
|
||||
// Check that we detect unexpected value when none are allowed
|
||||
//
|
||||
// check-pass
|
||||
// revisions: values simple mixed empty
|
||||
// compile-flags: -Z unstable-options
|
||||
// compile-flags: --check-cfg=cfg(values,simple,mixed,empty)
|
||||
// [values]compile-flags: --check-cfg=values(test) --check-cfg=values(feature)
|
||||
// [simple]compile-flags: --check-cfg=cfg(test) --check-cfg=cfg(feature)
|
||||
// [mixed]compile-flags: --check-cfg=cfg(test,feature)
|
||||
// [empty]compile-flags: --check-cfg=cfg(test,feature,values())
|
||||
|
||||
#[cfg(feature = "foo")]
|
||||
//~^ WARNING unexpected `cfg` condition value
|
||||
fn do_foo() {}
|
||||
|
||||
#[cfg(test = "foo")]
|
||||
//~^ WARNING unexpected `cfg` condition value
|
||||
fn do_foo() {}
|
||||
|
||||
fn main() {}
|
23
tests/ui/check-cfg/no-expected-values.simple.stderr
Normal file
23
tests/ui/check-cfg/no-expected-values.simple.stderr
Normal file
@ -0,0 +1,23 @@
|
||||
warning: unexpected `cfg` condition value: `foo`
|
||||
--> $DIR/no-expected-values.rs:12:7
|
||||
|
|
||||
LL | #[cfg(feature = "foo")]
|
||||
| ^^^^^^^--------
|
||||
| |
|
||||
| help: remove the value
|
||||
|
|
||||
= note: no expected value for `feature`
|
||||
= note: `#[warn(unexpected_cfgs)]` on by default
|
||||
|
||||
warning: unexpected `cfg` condition value: `foo`
|
||||
--> $DIR/no-expected-values.rs:16:7
|
||||
|
|
||||
LL | #[cfg(test = "foo")]
|
||||
| ^^^^--------
|
||||
| |
|
||||
| help: remove the value
|
||||
|
|
||||
= note: no expected value for `test`
|
||||
|
||||
warning: 2 warnings emitted
|
||||
|
23
tests/ui/check-cfg/no-expected-values.values.stderr
Normal file
23
tests/ui/check-cfg/no-expected-values.values.stderr
Normal file
@ -0,0 +1,23 @@
|
||||
warning: unexpected `cfg` condition value: `foo`
|
||||
--> $DIR/no-expected-values.rs:12:7
|
||||
|
|
||||
LL | #[cfg(feature = "foo")]
|
||||
| ^^^^^^^--------
|
||||
| |
|
||||
| help: remove the value
|
||||
|
|
||||
= note: no expected value for `feature`
|
||||
= note: `#[warn(unexpected_cfgs)]` on by default
|
||||
|
||||
warning: unexpected `cfg` condition value: `foo`
|
||||
--> $DIR/no-expected-values.rs:16:7
|
||||
|
|
||||
LL | #[cfg(test = "foo")]
|
||||
| ^^^^--------
|
||||
| |
|
||||
| help: remove the value
|
||||
|
|
||||
= note: no expected value for `test`
|
||||
|
||||
warning: 2 warnings emitted
|
||||
|
@ -1,14 +0,0 @@
|
||||
// Check that we detect unexpected value when none are allowed
|
||||
//
|
||||
// check-pass
|
||||
// compile-flags: --check-cfg=values(test) --check-cfg=values(feature) -Z unstable-options
|
||||
|
||||
#[cfg(feature = "foo")]
|
||||
//~^ WARNING unexpected `cfg` condition value
|
||||
fn do_foo() {}
|
||||
|
||||
#[cfg(test = "foo")]
|
||||
//~^ WARNING unexpected `cfg` condition value
|
||||
fn do_foo() {}
|
||||
|
||||
fn main() {}
|
@ -1,7 +1,7 @@
|
||||
// This test checks that there is no ICE with this code
|
||||
//
|
||||
// check-pass
|
||||
// compile-flags:--check-cfg=names() -Z unstable-options
|
||||
// compile-flags:--check-cfg=cfg() -Z unstable-options
|
||||
|
||||
fn main() {
|
||||
#[cfg(crossbeam_loom)]
|
||||
|
@ -1,5 +1,5 @@
|
||||
warning: unexpected `cfg` condition name: `widnows`
|
||||
--> $DIR/invalid-cfg-name.rs:7:7
|
||||
--> $DIR/unexpected-cfg-name.rs:9:7
|
||||
|
|
||||
LL | #[cfg(widnows)]
|
||||
| ^^^^^^^ help: there is a config with a similar name: `windows`
|
10
tests/ui/check-cfg/unexpected-cfg-name.names.stderr
Normal file
10
tests/ui/check-cfg/unexpected-cfg-name.names.stderr
Normal file
@ -0,0 +1,10 @@
|
||||
warning: unexpected `cfg` condition name: `widnows`
|
||||
--> $DIR/unexpected-cfg-name.rs:9:7
|
||||
|
|
||||
LL | #[cfg(widnows)]
|
||||
| ^^^^^^^ help: there is a config with a similar name: `windows`
|
||||
|
|
||||
= note: `#[warn(unexpected_cfgs)]` on by default
|
||||
|
||||
warning: 1 warning emitted
|
||||
|
16
tests/ui/check-cfg/unexpected-cfg-name.rs
Normal file
16
tests/ui/check-cfg/unexpected-cfg-name.rs
Normal file
@ -0,0 +1,16 @@
|
||||
// Check warning for unexpected configuration name
|
||||
//
|
||||
// check-pass
|
||||
// revisions: names exhaustive
|
||||
// compile-flags: --check-cfg=cfg(names,exhaustive)
|
||||
// [names]compile-flags: --check-cfg=names() -Z unstable-options
|
||||
// [exhaustive]compile-flags: --check-cfg=cfg() -Z unstable-options
|
||||
|
||||
#[cfg(widnows)]
|
||||
//~^ WARNING unexpected `cfg` condition name
|
||||
pub fn f() {}
|
||||
|
||||
#[cfg(windows)]
|
||||
pub fn g() {}
|
||||
|
||||
pub fn main() {}
|
@ -1,5 +1,5 @@
|
||||
warning: unexpected `cfg` condition value: `sedre`
|
||||
--> $DIR/invalid-cfg-value.rs:7:7
|
||||
--> $DIR/unexpected-cfg-value.rs:11:7
|
||||
|
|
||||
LL | #[cfg(feature = "sedre")]
|
||||
| ^^^^^^^^^^-------
|
||||
@ -10,7 +10,7 @@ LL | #[cfg(feature = "sedre")]
|
||||
= note: `#[warn(unexpected_cfgs)]` on by default
|
||||
|
||||
warning: unexpected `cfg` condition value: `rand`
|
||||
--> $DIR/invalid-cfg-value.rs:14:7
|
||||
--> $DIR/unexpected-cfg-value.rs:18:7
|
||||
|
|
||||
LL | #[cfg(feature = "rand")]
|
||||
| ^^^^^^^^^^^^^^^^
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user