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:
bors 2023-10-17 18:51:46 +00:00
commit 94ba57cef4
110 changed files with 1948 additions and 327 deletions

View File

@ -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.

View File

@ -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(),

View File

@ -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();
}

View File

@ -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)]

View File

@ -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

View File

@ -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,
}
}

View File

@ -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),
],
);
}

View File

@ -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 {

View File

@ -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;
}

View File

@ -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 });
}

View File

@ -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();

View File

@ -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)),
}
}
}

View File

@ -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 {

View File

@ -303,6 +303,7 @@ symbols! {
SliceIndex,
SliceIter,
Some,
SpanCtxt,
String,
StructuralEq,
StructuralPartialEq,

View File

@ -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)),

View 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 {}

View File

@ -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

View File

@ -1,3 +1,4 @@
mod body;
pub mod mono;
pub use body::*;

View 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
}
}

View File

@ -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

View File

@ -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() {}
```

View File

@ -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, _, _)

View File

@ -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,

View File

@ -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());

View File

@ -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`

View File

@ -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 {

View File

@ -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));

View File

@ -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 {

View File

@ -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(

View File

@ -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;

View File

@ -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 {

View File

@ -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())

View File

@ -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;

View File

@ -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(..))

View File

@ -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 {

View File

@ -1,2 +1,2 @@
// check-fail
// compile-flags: --check-cfg=names()
// compile-flags: --check-cfg=cfg()

View File

@ -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)]

View File

@ -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"

View 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()`
}

View 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

View 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(())
}

View File

@ -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)]

View File

@ -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() {

View File

@ -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)]

View File

@ -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)]

View File

@ -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 {

View File

@ -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)]

View File

@ -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)]

View 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() {}

View 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

View File

@ -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

View File

@ -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() {}

View File

@ -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() {}

View 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

View 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_names_values` as condition name
|
= help: was set with `--cfg` but isn't in the `--check-cfg` expected names
warning: 3 warnings emitted

View 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

View 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

View 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() {}

View File

@ -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

View 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

View 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() {}

View 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

View File

@ -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")]
| ^^^^----------

View 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() {}

View 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

View File

@ -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"))`)

View File

@ -0,0 +1,2 @@
error: invalid `--check-cfg` argument: `cfg(...)` (expected `cfg(name, values("value1", "value2", ... "valueN"))`)

View File

@ -0,0 +1,2 @@
error: invalid `--check-cfg` argument: `cfg(foo,values(bar))` (`values()` arguments must be string literals or `any()`)

View File

@ -0,0 +1,2 @@
error: invalid `--check-cfg` argument: `cfg(foo,values("bar",bar,"bar"))` (`values()` arguments must be string literals or `any()`)

View File

@ -0,0 +1,2 @@
error: invalid `--check-cfg` argument: `cfg(any(),values(any()))` (`values()` cannot be specified before the names)

View File

@ -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)

View File

@ -0,0 +1,2 @@
error: invalid `--check-cfg` argument: `cfg(any(),any())` (`any()` cannot be specified multiple times)

View File

@ -0,0 +1,2 @@
error: invalid `--check-cfg` argument: `cfg(foo,values(),values())` (`values()` cannot be specified multiple times)

View File

@ -0,0 +1,2 @@
error: invalid `--check-cfg` argument: `cfg(foo,values(any(),any()))` (`any()` in `values()` cannot be specified multiple times)

View File

@ -0,0 +1,2 @@
error: invalid `--check-cfg` argument: `cfg(any(foo))` (`any()` must be empty)

View File

@ -0,0 +1,2 @@
error: invalid `--check-cfg` argument: `cfg(foo,values(any(bar)))` (`any()` must be empty)

View File

@ -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() {}

View File

@ -0,0 +1,2 @@
error: invalid `--check-cfg` argument: `cfg("NOT_IDENT")` (`cfg()` arguments must be simple identifiers, `any()` or `values(...)`)

View File

@ -0,0 +1,2 @@
error: invalid `--check-cfg` argument: `cfg(foo,"NOT_IDENT",bar)` (`cfg()` arguments must be simple identifiers, `any()` or `values(...)`)

View File

@ -0,0 +1,2 @@
error: invalid `--check-cfg` argument: `abc()` (expected `cfg(name, values("value1", "value2", ... "valueN"))`)

View File

@ -0,0 +1,2 @@
error: invalid `--check-cfg` argument: `cfg(foo,test())` (`cfg()` arguments must be simple identifiers, `any()` or `values(...)`)

View File

@ -0,0 +1,2 @@
error: invalid `--check-cfg` argument: `cfg(foo,values(test()))` (`values()` arguments must be string literals or `any()`)

View File

@ -0,0 +1,2 @@
error: invalid `--check-cfg` argument: `cfg(values(any()),foo)` (`values()` cannot be specified before the names)

View File

@ -0,0 +1,2 @@
error: invalid `--check-cfg` argument: `cfg(foo,any())` (`cfg(any())` can only be provided in isolation)

View File

@ -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() {}

View File

@ -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() {}

View File

@ -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"));
| ^^^^^^^^^^^^^^^^^

View 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

View File

@ -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() {}

View File

@ -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")]
| ^^^^--------

View 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

View 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() {}

View 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

View 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

View File

@ -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() {}

View File

@ -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)]

View File

@ -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`

View 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

View 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() {}

View File

@ -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