Skip to content

Commit

Permalink
Auto merge of rust-lang#116855 - matthiaskrgr:rollup-i2izdwb, r=matth…
Browse files Browse the repository at this point in the history
…iaskrgr

Rollup of 5 pull requests

Successful merges:

 - rust-lang#111072 (Add new simpler and more explicit syntax for check-cfg)
 - rust-lang#116717 (Special case iterator chain checks for suggestion)
 - rust-lang#116719 (Add MonoItems and Instance to stable_mir)
 - rust-lang#116787 (Implement an internal lint encouraging use of `Span::eq_ctxt`)
 - rust-lang#116827 (Make `handle_options` public again.)

r? `@ghost`
`@rustbot` modify labels: rollup
  • Loading branch information
bors committed Oct 17, 2023
2 parents bb74d1f + 6e6cd68 commit 94ba57c
Show file tree
Hide file tree
Showing 110 changed files with 1,905 additions and 284 deletions.
6 changes: 5 additions & 1 deletion compiler/rustc_driver_impl/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_typeck/src/callee.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
Expand Down
139 changes: 132 additions & 7 deletions compiler/rustc_interface/src/interface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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}`"
Expand All @@ -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() {
Expand All @@ -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");
Expand Down Expand Up @@ -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();
}
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_interface/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_lint/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
34 changes: 32 additions & 2 deletions compiler/rustc_lint/src/internal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -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,
}
}
3 changes: 3 additions & 0 deletions compiler/rustc_lint/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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),
],
);
}
Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_lint/src/lints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_mir_transform/src/coverage/spans.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_passes/src/loops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 });
}
Expand Down
28 changes: 24 additions & 4 deletions compiler/rustc_smir/src/rustc_internal/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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)
}

Expand All @@ -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 {
Expand All @@ -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,
);
Expand Down Expand Up @@ -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();
Expand Down

0 comments on commit 94ba57c

Please sign in to comment.