Skip to content

Commit 94ba57c

Browse files
committed
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
2 parents bb74d1f + 6e6cd68 commit 94ba57c

File tree

110 files changed

+1905
-284
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

110 files changed

+1905
-284
lines changed

Diff for: compiler/rustc_driver_impl/src/lib.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -1185,7 +1185,11 @@ fn print_flag_list<T>(
11851185
///
11861186
/// So with all that in mind, the comments below have some more detail about the
11871187
/// contortions done here to get things to work out correctly.
1188-
fn handle_options(handler: &EarlyErrorHandler, args: &[String]) -> Option<getopts::Matches> {
1188+
///
1189+
/// This does not need to be `pub` for rustc itself, but @chaosite needs it to
1190+
/// be public when using rustc as a library, see
1191+
/// <https://github.com/rust-lang/rust/commit/2b4c33817a5aaecabf4c6598d41e190080ec119e>
1192+
pub fn handle_options(handler: &EarlyErrorHandler, args: &[String]) -> Option<getopts::Matches> {
11891193
if args.is_empty() {
11901194
// user did not write `-v` nor `-Z unstable-options`, so do not
11911195
// include that extra information.

Diff for: compiler/rustc_hir_typeck/src/callee.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -650,7 +650,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
650650
.sess
651651
.source_map()
652652
.is_multiline(call_expr.span.with_lo(callee_expr.span.hi()))
653-
&& call_expr.span.ctxt() == callee_expr.span.ctxt();
653+
&& call_expr.span.eq_ctxt(callee_expr.span);
654654
if call_is_multiline {
655655
err.span_suggestion(
656656
callee_expr.span.shrink_to_hi(),

Diff for: compiler/rustc_interface/src/interface.rs

+132-7
Original file line numberDiff line numberDiff line change
@@ -125,8 +125,13 @@ pub fn parse_cfgspecs(
125125
/// Converts strings provided as `--check-cfg [specs]` into a `CheckCfg`.
126126
pub fn parse_check_cfg(handler: &EarlyErrorHandler, specs: Vec<String>) -> CheckCfg {
127127
rustc_span::create_default_session_if_not_set_then(move |_| {
128-
let mut check_cfg = CheckCfg::default();
128+
// If any --check-cfg is passed then exhaustive_values and exhaustive_names
129+
// are enabled by default.
130+
let exhaustive_names = !specs.is_empty();
131+
let exhaustive_values = !specs.is_empty();
132+
let mut check_cfg = CheckCfg { exhaustive_names, exhaustive_values, ..CheckCfg::default() };
129133

134+
let mut old_syntax = None;
130135
for s in specs {
131136
let sess = ParseSess::with_silent_emitter(Some(format!(
132137
"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
142147
};
143148
}
144149

145-
let expected_error = || {
146-
error!(
147-
"expected `names(name1, name2, ... nameN)` or \
148-
`values(name, \"value1\", \"value2\", ... \"valueN\")`"
149-
)
150-
};
150+
let expected_error =
151+
|| error!("expected `cfg(name, values(\"value1\", \"value2\", ... \"valueN\"))`");
151152

152153
match maybe_new_parser_from_source_str(&sess, filename, s.to_string()) {
153154
Ok(mut parser) => match parser.parse_meta_item() {
154155
Ok(meta_item) if parser.token == token::Eof => {
155156
if let Some(args) = meta_item.meta_item_list() {
156157
if meta_item.has_name(sym::names) {
158+
// defaults are flipped for the old syntax
159+
if old_syntax == None {
160+
check_cfg.exhaustive_names = false;
161+
check_cfg.exhaustive_values = false;
162+
}
163+
old_syntax = Some(true);
164+
157165
check_cfg.exhaustive_names = true;
158166
for arg in args {
159167
if arg.is_word() && arg.ident().is_some() {
@@ -167,6 +175,13 @@ pub fn parse_check_cfg(handler: &EarlyErrorHandler, specs: Vec<String>) -> Check
167175
}
168176
}
169177
} else if meta_item.has_name(sym::values) {
178+
// defaults are flipped for the old syntax
179+
if old_syntax == None {
180+
check_cfg.exhaustive_names = false;
181+
check_cfg.exhaustive_values = false;
182+
}
183+
old_syntax = Some(true);
184+
170185
if let Some((name, values)) = args.split_first() {
171186
if name.is_word() && name.ident().is_some() {
172187
let ident = name.ident().expect("multi-segment cfg key");
@@ -216,6 +231,116 @@ pub fn parse_check_cfg(handler: &EarlyErrorHandler, specs: Vec<String>) -> Check
216231
} else {
217232
expected_error();
218233
}
234+
} else if meta_item.has_name(sym::cfg) {
235+
old_syntax = Some(false);
236+
237+
let mut names = Vec::new();
238+
let mut values: FxHashSet<_> = Default::default();
239+
240+
let mut any_specified = false;
241+
let mut values_specified = false;
242+
let mut values_any_specified = false;
243+
244+
for arg in args {
245+
if arg.is_word() && let Some(ident) = arg.ident() {
246+
if values_specified {
247+
error!("`cfg()` names cannot be after values");
248+
}
249+
names.push(ident);
250+
} else if arg.has_name(sym::any)
251+
&& let Some(args) = arg.meta_item_list()
252+
{
253+
if any_specified {
254+
error!("`any()` cannot be specified multiple times");
255+
}
256+
any_specified = true;
257+
if !args.is_empty() {
258+
error!("`any()` must be empty");
259+
}
260+
} else if arg.has_name(sym::values)
261+
&& let Some(args) = arg.meta_item_list()
262+
{
263+
if names.is_empty() {
264+
error!(
265+
"`values()` cannot be specified before the names"
266+
);
267+
} else if values_specified {
268+
error!(
269+
"`values()` cannot be specified multiple times"
270+
);
271+
}
272+
values_specified = true;
273+
274+
for arg in args {
275+
if let Some(LitKind::Str(s, _)) =
276+
arg.lit().map(|lit| &lit.kind)
277+
{
278+
values.insert(Some(s.to_string()));
279+
} else if arg.has_name(sym::any)
280+
&& let Some(args) = arg.meta_item_list()
281+
{
282+
if values_any_specified {
283+
error!(
284+
"`any()` in `values()` cannot be specified multiple times"
285+
);
286+
}
287+
values_any_specified = true;
288+
if !args.is_empty() {
289+
error!("`any()` must be empty");
290+
}
291+
} else {
292+
error!(
293+
"`values()` arguments must be string literals or `any()`"
294+
);
295+
}
296+
}
297+
} else {
298+
error!(
299+
"`cfg()` arguments must be simple identifiers, `any()` or `values(...)`"
300+
);
301+
}
302+
}
303+
304+
if values.is_empty() && !values_any_specified && !any_specified {
305+
values.insert(None);
306+
} else if !values.is_empty() && values_any_specified {
307+
error!(
308+
"`values()` arguments cannot specify string literals and `any()` at the same time"
309+
);
310+
}
311+
312+
if any_specified {
313+
if !names.is_empty()
314+
|| !values.is_empty()
315+
|| values_any_specified
316+
{
317+
error!("`cfg(any())` can only be provided in isolation");
318+
}
319+
320+
check_cfg.exhaustive_names = false;
321+
} else {
322+
for name in names {
323+
check_cfg
324+
.expecteds
325+
.entry(name.to_string())
326+
.and_modify(|v| match v {
327+
ExpectedValues::Some(v)
328+
if !values_any_specified =>
329+
{
330+
v.extend(values.clone())
331+
}
332+
ExpectedValues::Some(_) => *v = ExpectedValues::Any,
333+
ExpectedValues::Any => {}
334+
})
335+
.or_insert_with(|| {
336+
if values_any_specified {
337+
ExpectedValues::Any
338+
} else {
339+
ExpectedValues::Some(values.clone())
340+
}
341+
});
342+
}
343+
}
219344
} else {
220345
expected_error();
221346
}

Diff for: compiler/rustc_interface/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#![feature(internal_output_capture)]
44
#![feature(thread_spawn_unchecked)]
55
#![feature(lazy_cell)]
6+
#![feature(let_chains)]
67
#![feature(try_blocks)]
78
#![recursion_limit = "256"]
89
#![allow(rustc::potential_query_instability)]

Diff for: compiler/rustc_lint/messages.ftl

+2
Original file line numberDiff line numberDiff line change
@@ -494,6 +494,8 @@ lint_renamed_lint = lint `{$name}` has been renamed to `{$replace}`
494494
495495
lint_requested_level = requested on the command line with `{$level} {$lint_name}`
496496
497+
lint_span_use_eq_ctxt = use `.eq_ctxt()` instead of `.ctxt() == .ctxt()`
498+
497499
lint_supertrait_as_deref_target = `{$t}` implements `Deref` with supertrait `{$target_principal}` as target
498500
.label = target type is set here
499501

Diff for: compiler/rustc_lint/src/internal.rs

+32-2
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,14 @@
33
44
use crate::lints::{
55
BadOptAccessDiag, DefaultHashTypesDiag, DiagOutOfImpl, LintPassByHand, NonExistentDocKeyword,
6-
QueryInstability, TyQualified, TykindDiag, TykindKind, UntranslatableDiag,
6+
QueryInstability, SpanUseEqCtxtDiag, TyQualified, TykindDiag, TykindKind, UntranslatableDiag,
77
UntranslatableDiagnosticTrivial,
88
};
99
use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext};
1010
use rustc_ast as ast;
1111
use rustc_hir::def::Res;
1212
use rustc_hir::{def_id::DefId, Expr, ExprKind, GenericArg, PatKind, Path, PathSegment, QPath};
13-
use rustc_hir::{HirId, Impl, Item, ItemKind, Node, Pat, Ty, TyKind};
13+
use rustc_hir::{BinOp, BinOpKind, HirId, Impl, Item, ItemKind, Node, Pat, Ty, TyKind};
1414
use rustc_middle::ty;
1515
use rustc_session::{declare_lint_pass, declare_tool_lint};
1616
use rustc_span::hygiene::{ExpnKind, MacroKind};
@@ -537,3 +537,33 @@ impl LateLintPass<'_> for BadOptAccess {
537537
}
538538
}
539539
}
540+
541+
declare_tool_lint! {
542+
pub rustc::SPAN_USE_EQ_CTXT,
543+
Allow,
544+
"forbid uses of `==` with `Span::ctxt`, suggest `Span::eq_ctxt` instead",
545+
report_in_external_macro: true
546+
}
547+
548+
declare_lint_pass!(SpanUseEqCtxt => [SPAN_USE_EQ_CTXT]);
549+
550+
impl<'tcx> LateLintPass<'tcx> for SpanUseEqCtxt {
551+
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'_>) {
552+
if let ExprKind::Binary(BinOp { node: BinOpKind::Eq, .. }, lhs, rhs) = expr.kind {
553+
if is_span_ctxt_call(cx, lhs) && is_span_ctxt_call(cx, rhs) {
554+
cx.emit_spanned_lint(SPAN_USE_EQ_CTXT, expr.span, SpanUseEqCtxtDiag);
555+
}
556+
}
557+
}
558+
}
559+
560+
fn is_span_ctxt_call(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
561+
match &expr.kind {
562+
ExprKind::MethodCall(..) => cx
563+
.typeck_results()
564+
.type_dependent_def_id(expr.hir_id)
565+
.is_some_and(|call_did| cx.tcx.is_diagnostic_item(sym::SpanCtxt, call_did)),
566+
567+
_ => false,
568+
}
569+
}

Diff for: compiler/rustc_lint/src/lib.rs

+3
Original file line numberDiff line numberDiff line change
@@ -531,6 +531,8 @@ fn register_internals(store: &mut LintStore) {
531531
store.register_late_mod_pass(|_| Box::new(BadOptAccess));
532532
store.register_lints(&PassByValue::get_lints());
533533
store.register_late_mod_pass(|_| Box::new(PassByValue));
534+
store.register_lints(&SpanUseEqCtxt::get_lints());
535+
store.register_late_mod_pass(|_| Box::new(SpanUseEqCtxt));
534536
// FIXME(davidtwco): deliberately do not include `UNTRANSLATABLE_DIAGNOSTIC` and
535537
// `DIAGNOSTIC_OUTSIDE_OF_IMPL` here because `-Wrustc::internal` is provided to every crate and
536538
// 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) {
548550
LintId::of(USAGE_OF_QUALIFIED_TY),
549551
LintId::of(EXISTING_DOC_KEYWORD),
550552
LintId::of(BAD_OPT_ACCESS),
553+
LintId::of(SPAN_USE_EQ_CTXT),
551554
],
552555
);
553556
}

Diff for: compiler/rustc_lint/src/lints.rs

+4
Original file line numberDiff line numberDiff line change
@@ -900,6 +900,10 @@ pub struct QueryInstability {
900900
pub query: Symbol,
901901
}
902902

903+
#[derive(LintDiagnostic)]
904+
#[diag(lint_span_use_eq_ctxt)]
905+
pub struct SpanUseEqCtxtDiag;
906+
903907
#[derive(LintDiagnostic)]
904908
#[diag(lint_tykind_kind)]
905909
pub struct TykindKind {

Diff for: compiler/rustc_mir_transform/src/coverage/spans.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -404,7 +404,7 @@ impl<'a> CoverageSpansGenerator<'a> {
404404

405405
let Some(visible_macro) = curr.visible_macro(self.body_span) else { return };
406406
if let Some(prev) = &self.some_prev
407-
&& prev.expn_span.ctxt() == curr.expn_span.ctxt()
407+
&& prev.expn_span.eq_ctxt(curr.expn_span)
408408
{
409409
return;
410410
}

Diff for: compiler/rustc_passes/src/loops.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,7 @@ impl<'a, 'hir> CheckLoopVisitor<'a, 'hir> {
231231
AsyncClosure(closure_span) => {
232232
self.sess.emit_err(BreakInsideAsyncBlock { span, closure_span, name });
233233
}
234-
UnlabeledBlock(block_span) if is_break && block_span.ctxt() == break_span.ctxt() => {
234+
UnlabeledBlock(block_span) if is_break && block_span.eq_ctxt(break_span) => {
235235
let suggestion = Some(OutsideLoopSuggestion { block_span, break_span });
236236
self.sess.emit_err(OutsideLoop { span, name, is_break, suggestion });
237237
}

Diff for: compiler/rustc_smir/src/rustc_internal/mod.rs

+24-4
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,11 @@
66
use crate::rustc_internal;
77
use crate::rustc_smir::Tables;
88
use rustc_data_structures::fx;
9+
use rustc_data_structures::fx::FxIndexMap;
910
use rustc_driver::{Callbacks, Compilation, RunCompiler};
1011
use rustc_interface::{interface, Queries};
1112
use rustc_middle::mir::interpret::AllocId;
13+
use rustc_middle::ty;
1214
use rustc_middle::ty::TyCtxt;
1315
use rustc_span::def_id::{CrateNum, DefId};
1416
use rustc_span::Span;
@@ -97,7 +99,7 @@ impl<'tcx> Tables<'tcx> {
9799
stable_mir::ty::Prov(self.create_alloc_id(aid))
98100
}
99101

100-
fn create_def_id(&mut self, did: DefId) -> stable_mir::DefId {
102+
pub(crate) fn create_def_id(&mut self, did: DefId) -> stable_mir::DefId {
101103
self.def_ids.create_or_fetch(did)
102104
}
103105

@@ -108,6 +110,17 @@ impl<'tcx> Tables<'tcx> {
108110
pub(crate) fn create_span(&mut self, span: Span) -> stable_mir::ty::Span {
109111
self.spans.create_or_fetch(span)
110112
}
113+
114+
pub(crate) fn instance_def(
115+
&mut self,
116+
instance: ty::Instance<'tcx>,
117+
) -> stable_mir::mir::mono::InstanceDef {
118+
self.instances.create_or_fetch(instance)
119+
}
120+
121+
pub(crate) fn static_def(&mut self, did: DefId) -> stable_mir::mir::mono::StaticDef {
122+
stable_mir::mir::mono::StaticDef(self.create_def_id(did))
123+
}
111124
}
112125

113126
pub fn crate_num(item: &stable_mir::Crate) -> CrateNum {
@@ -118,10 +131,11 @@ pub fn run(tcx: TyCtxt<'_>, f: impl FnOnce()) {
118131
stable_mir::run(
119132
Tables {
120133
tcx,
121-
def_ids: rustc_internal::IndexMap { index_map: fx::FxIndexMap::default() },
122-
alloc_ids: rustc_internal::IndexMap { index_map: fx::FxIndexMap::default() },
123-
spans: rustc_internal::IndexMap { index_map: fx::FxIndexMap::default() },
134+
def_ids: IndexMap::default(),
135+
alloc_ids: IndexMap::default(),
136+
spans: IndexMap::default(),
124137
types: vec![],
138+
instances: IndexMap::default(),
125139
},
126140
f,
127141
);
@@ -192,6 +206,12 @@ pub struct IndexMap<K, V> {
192206
index_map: fx::FxIndexMap<K, V>,
193207
}
194208

209+
impl<K, V> Default for IndexMap<K, V> {
210+
fn default() -> Self {
211+
Self { index_map: FxIndexMap::default() }
212+
}
213+
}
214+
195215
impl<K: PartialEq + Hash + Eq, V: Copy + Debug + PartialEq + IndexedVal> IndexMap<K, V> {
196216
pub fn create_or_fetch(&mut self, key: K) -> V {
197217
let len = self.index_map.len();

0 commit comments

Comments
 (0)