Skip to content

Commit 5c18bc6

Browse files
committed
Auto merge of #106442 - matthiaskrgr:rollup-wivf7gh, r=matthiaskrgr
Rollup of 7 pull requests Successful merges: - #106200 (Suggest `impl Fn*` and `impl Future` in `-> _` return suggestions) - #106274 (Add JSON output to -Zdump-mono-stats) - #106292 (Add codegen test for `Box::new(uninit)` of big arrays) - #106327 (Add tidy check for dbg) - #106361 (Note maximum integer literal for `IntLiteralTooLarge`) - #106396 (Allow passing a specific date to `bump-stage0`) - #106436 (Enable doctests for rustc_query_impl) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
2 parents ddad1e1 + 4e590b3 commit 5c18bc6

File tree

37 files changed

+473
-127
lines changed

37 files changed

+473
-127
lines changed

Cargo.lock

+2
Original file line numberDiff line numberDiff line change
@@ -4243,6 +4243,8 @@ dependencies = [
42434243
"rustc_session",
42444244
"rustc_span",
42454245
"rustc_target",
4246+
"serde",
4247+
"serde_json",
42464248
"smallvec",
42474249
"tracing",
42484250
]

compiler/rustc_ast/src/util/literal.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ pub enum LitError {
3434
InvalidIntSuffix,
3535
InvalidFloatSuffix,
3636
NonDecimalFloat(u32),
37-
IntTooLarge,
37+
IntTooLarge(u32),
3838
}
3939

4040
impl LitKind {
@@ -333,6 +333,6 @@ fn integer_lit(symbol: Symbol, suffix: Option<Symbol>) -> Result<LitKind, LitErr
333333
// but these kinds of errors are already reported by the lexer.
334334
let from_lexer =
335335
base < 10 && s.chars().any(|c| c.to_digit(10).map_or(false, |d| d >= base));
336-
if from_lexer { LitError::LexerError } else { LitError::IntTooLarge }
336+
if from_lexer { LitError::LexerError } else { LitError::IntTooLarge(base) }
337337
})
338338
}

compiler/rustc_error_messages/locales/en-US/session.ftl

+1
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ session_invalid_float_literal_suffix = invalid suffix `{$suffix}` for float lite
8585
.help = valid suffixes are `f32` and `f64`
8686
8787
session_int_literal_too_large = integer literal is too large
88+
.note = value exceeds limit of `{$limit}`
8889
8990
session_invalid_int_literal_width = invalid width `{$width}` for integer literal
9091
.help = valid widths are 8, 16, 32, 64 and 128

compiler/rustc_hir_analysis/src/collect.rs

+97-50
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,16 @@
1717
use crate::astconv::AstConv;
1818
use crate::check::intrinsic::intrinsic_operation_unsafety;
1919
use crate::errors;
20+
use hir::def::DefKind;
2021
use rustc_data_structures::captures::Captures;
2122
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
2223
use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed, StashKey};
2324
use rustc_hir as hir;
2425
use rustc_hir::def_id::{DefId, LocalDefId};
2526
use rustc_hir::intravisit::{self, Visitor};
2627
use rustc_hir::{GenericParamKind, Node};
27-
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
2828
use rustc_infer::infer::TyCtxtInferExt;
29+
use rustc_infer::traits::ObligationCause;
2930
use rustc_middle::hir::nested_filter;
3031
use rustc_middle::ty::query::Providers;
3132
use rustc_middle::ty::util::{Discr, IntTypeExt};
@@ -1195,12 +1196,11 @@ fn infer_return_ty_for_fn_sig<'tcx>(
11951196
ty::ReErased => tcx.lifetimes.re_static,
11961197
_ => r,
11971198
});
1198-
let fn_sig = ty::Binder::dummy(fn_sig);
11991199

12001200
let mut visitor = HirPlaceholderCollector::default();
12011201
visitor.visit_ty(ty);
12021202
let mut diag = bad_placeholder(tcx, visitor.0, "return type");
1203-
let ret_ty = fn_sig.skip_binder().output();
1203+
let ret_ty = fn_sig.output();
12041204
if ret_ty.is_suggestable(tcx, false) {
12051205
diag.span_suggestion(
12061206
ty.span,
@@ -1223,26 +1223,26 @@ fn infer_return_ty_for_fn_sig<'tcx>(
12231223
Applicability::MachineApplicable,
12241224
);
12251225
}
1226+
} else if let Some(sugg) = suggest_impl_trait(tcx, ret_ty, ty.span, hir_id, def_id) {
1227+
diag.span_suggestion(
1228+
ty.span,
1229+
"replace with an appropriate return type",
1230+
sugg,
1231+
Applicability::MachineApplicable,
1232+
);
12261233
} else if ret_ty.is_closure() {
1227-
// We're dealing with a closure, so we should suggest using `impl Fn` or trait bounds
1228-
// to prevent the user from getting a papercut while trying to use the unique closure
1229-
// syntax (e.g. `[closure@src/lib.rs:2:5: 2:9]`).
12301234
diag.help("consider using an `Fn`, `FnMut`, or `FnOnce` trait bound");
1235+
}
1236+
// Also note how `Fn` traits work just in case!
1237+
if ret_ty.is_closure() {
12311238
diag.note(
12321239
"for more information on `Fn` traits and closure types, see \
12331240
https://doc.rust-lang.org/book/ch13-01-closures.html",
12341241
);
1235-
} else if let Some(i_ty) = suggest_impl_iterator(tcx, ret_ty, ty.span, hir_id, def_id) {
1236-
diag.span_suggestion(
1237-
ty.span,
1238-
"replace with an appropriate return type",
1239-
format!("impl Iterator<Item = {}>", i_ty),
1240-
Applicability::MachineApplicable,
1241-
);
12421242
}
12431243
diag.emit();
12441244

1245-
fn_sig
1245+
ty::Binder::dummy(fn_sig)
12461246
}
12471247
None => <dyn AstConv<'_>>::ty_of_fn(
12481248
icx,
@@ -1256,47 +1256,94 @@ fn infer_return_ty_for_fn_sig<'tcx>(
12561256
}
12571257
}
12581258

1259-
fn suggest_impl_iterator<'tcx>(
1259+
fn suggest_impl_trait<'tcx>(
12601260
tcx: TyCtxt<'tcx>,
12611261
ret_ty: Ty<'tcx>,
12621262
span: Span,
12631263
hir_id: hir::HirId,
12641264
def_id: LocalDefId,
1265-
) -> Option<Ty<'tcx>> {
1266-
let Some(iter_trait) = tcx.get_diagnostic_item(sym::Iterator) else { return None; };
1267-
let Some(iterator_item) = tcx.get_diagnostic_item(sym::IteratorItem) else { return None; };
1268-
if !tcx
1269-
.infer_ctxt()
1270-
.build()
1271-
.type_implements_trait(iter_trait, [ret_ty], tcx.param_env(def_id))
1272-
.must_apply_modulo_regions()
1273-
{
1274-
return None;
1275-
}
1276-
let infcx = tcx.infer_ctxt().build();
1277-
let ocx = ObligationCtxt::new_in_snapshot(&infcx);
1278-
// Find the type of `Iterator::Item`.
1279-
let origin = TypeVariableOrigin { kind: TypeVariableOriginKind::TypeInference, span };
1280-
let ty_var = infcx.next_ty_var(origin);
1281-
let projection = ty::Binder::dummy(ty::PredicateKind::Clause(ty::Clause::Projection(
1282-
ty::ProjectionPredicate {
1283-
projection_ty: tcx.mk_alias_ty(iterator_item, tcx.mk_substs([ret_ty.into()].iter())),
1284-
term: ty_var.into(),
1285-
},
1286-
)));
1287-
// Add `<ret_ty as Iterator>::Item = _` obligation.
1288-
ocx.register_obligation(crate::traits::Obligation::misc(
1289-
tcx,
1290-
span,
1291-
hir_id,
1292-
tcx.param_env(def_id),
1293-
projection,
1294-
));
1295-
if ocx.select_where_possible().is_empty()
1296-
&& let item_ty = infcx.resolve_vars_if_possible(ty_var)
1297-
&& item_ty.is_suggestable(tcx, false)
1298-
{
1299-
return Some(item_ty);
1265+
) -> Option<String> {
1266+
let format_as_assoc: fn(_, _, _, _, _) -> _ =
1267+
|tcx: TyCtxt<'tcx>,
1268+
_: ty::SubstsRef<'tcx>,
1269+
trait_def_id: DefId,
1270+
assoc_item_def_id: DefId,
1271+
item_ty: Ty<'tcx>| {
1272+
let trait_name = tcx.item_name(trait_def_id);
1273+
let assoc_name = tcx.item_name(assoc_item_def_id);
1274+
Some(format!("impl {trait_name}<{assoc_name} = {item_ty}>"))
1275+
};
1276+
let format_as_parenthesized: fn(_, _, _, _, _) -> _ =
1277+
|tcx: TyCtxt<'tcx>,
1278+
substs: ty::SubstsRef<'tcx>,
1279+
trait_def_id: DefId,
1280+
_: DefId,
1281+
item_ty: Ty<'tcx>| {
1282+
let trait_name = tcx.item_name(trait_def_id);
1283+
let args_tuple = substs.type_at(1);
1284+
let ty::Tuple(types) = *args_tuple.kind() else { return None; };
1285+
if !types.is_suggestable(tcx, false) {
1286+
return None;
1287+
}
1288+
let maybe_ret =
1289+
if item_ty.is_unit() { String::new() } else { format!(" -> {item_ty}") };
1290+
Some(format!(
1291+
"impl {trait_name}({}){maybe_ret}",
1292+
types.iter().map(|ty| ty.to_string()).collect::<Vec<_>>().join(", ")
1293+
))
1294+
};
1295+
1296+
for (trait_def_id, assoc_item_def_id, formatter) in [
1297+
(
1298+
tcx.get_diagnostic_item(sym::Iterator),
1299+
tcx.get_diagnostic_item(sym::IteratorItem),
1300+
format_as_assoc,
1301+
),
1302+
(
1303+
tcx.lang_items().future_trait(),
1304+
tcx.get_diagnostic_item(sym::FutureOutput),
1305+
format_as_assoc,
1306+
),
1307+
(tcx.lang_items().fn_trait(), tcx.lang_items().fn_once_output(), format_as_parenthesized),
1308+
(
1309+
tcx.lang_items().fn_mut_trait(),
1310+
tcx.lang_items().fn_once_output(),
1311+
format_as_parenthesized,
1312+
),
1313+
(
1314+
tcx.lang_items().fn_once_trait(),
1315+
tcx.lang_items().fn_once_output(),
1316+
format_as_parenthesized,
1317+
),
1318+
] {
1319+
let Some(trait_def_id) = trait_def_id else { continue; };
1320+
let Some(assoc_item_def_id) = assoc_item_def_id else { continue; };
1321+
if tcx.def_kind(assoc_item_def_id) != DefKind::AssocTy {
1322+
continue;
1323+
}
1324+
let param_env = tcx.param_env(def_id);
1325+
let infcx = tcx.infer_ctxt().build();
1326+
let substs = ty::InternalSubsts::for_item(tcx, trait_def_id, |param, _| {
1327+
if param.index == 0 { ret_ty.into() } else { infcx.var_for_def(span, param) }
1328+
});
1329+
if !infcx.type_implements_trait(trait_def_id, substs, param_env).must_apply_modulo_regions()
1330+
{
1331+
continue;
1332+
}
1333+
let ocx = ObligationCtxt::new_in_snapshot(&infcx);
1334+
let item_ty = ocx.normalize(
1335+
&ObligationCause::misc(span, hir_id),
1336+
param_env,
1337+
tcx.mk_projection(assoc_item_def_id, substs),
1338+
);
1339+
// FIXME(compiler-errors): We may benefit from resolving regions here.
1340+
if ocx.select_where_possible().is_empty()
1341+
&& let item_ty = infcx.resolve_vars_if_possible(item_ty)
1342+
&& item_ty.is_suggestable(tcx, false)
1343+
&& let Some(sugg) = formatter(tcx, infcx.resolve_vars_if_possible(substs), trait_def_id, assoc_item_def_id, item_ty)
1344+
{
1345+
return Some(sugg);
1346+
}
13001347
}
13011348
None
13021349
}

compiler/rustc_interface/src/tests.rs

+7-5
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,16 @@ use crate::interface::parse_cfgspecs;
33

44
use rustc_data_structures::fx::FxHashSet;
55
use rustc_errors::{emitter::HumanReadableErrorType, registry, ColorConfig};
6-
use rustc_session::config::InstrumentCoverage;
7-
use rustc_session::config::Strip;
6+
use rustc_session::config::rustc_optgroups;
87
use rustc_session::config::{build_configuration, build_session_options, to_crate_config};
9-
use rustc_session::config::{
10-
rustc_optgroups, ErrorOutputType, ExternLocation, LocationDetail, Options, Passes,
11-
};
128
use rustc_session::config::{
139
BranchProtection, Externs, OomStrategy, OutputType, OutputTypes, PAuthKey, PacRet,
1410
ProcMacroExecutionStrategy, SymbolManglingVersion, WasiExecModel,
1511
};
1612
use rustc_session::config::{CFGuard, ExternEntry, LinkerPluginLto, LtoCli, SwitchWithOptPath};
13+
use rustc_session::config::{DumpMonoStatsFormat, MirSpanview};
14+
use rustc_session::config::{ErrorOutputType, ExternLocation, LocationDetail, Options, Strip};
15+
use rustc_session::config::{InstrumentCoverage, Passes};
1716
use rustc_session::lint::Level;
1817
use rustc_session::search_paths::SearchPath;
1918
use rustc_session::utils::{CanonicalizedPath, NativeLib, NativeLibKind};
@@ -647,6 +646,9 @@ fn test_unstable_options_tracking_hash() {
647646
untracked!(dump_mir_dir, String::from("abc"));
648647
untracked!(dump_mir_exclude_pass_number, true);
649648
untracked!(dump_mir_graphviz, true);
649+
untracked!(dump_mir_spanview, Some(MirSpanview::Statement));
650+
untracked!(dump_mono_stats, SwitchWithOptPath::Enabled(Some("mono-items-dir/".into())));
651+
untracked!(dump_mono_stats_format, DumpMonoStatsFormat::Json);
650652
untracked!(dylib_lto, true);
651653
untracked!(emit_stack_sizes, true);
652654
untracked!(future_incompat_test, true);

compiler/rustc_monomorphize/Cargo.toml

+2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ edition = "2021"
66
[lib]
77

88
[dependencies]
9+
serde = "1"
10+
serde_json = "1"
911
smallvec = { version = "1.8.1", features = [ "union", "may_dangle" ] }
1012
tracing = "0.1"
1113
rustc_data_structures = { path = "../rustc_data_structures" }

compiler/rustc_monomorphize/src/partitioning/mod.rs

+35-19
Original file line numberDiff line numberDiff line change
@@ -102,14 +102,14 @@ use std::path::{Path, PathBuf};
102102

103103
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
104104
use rustc_data_structures::sync;
105-
use rustc_hir::def_id::DefIdSet;
105+
use rustc_hir::def_id::{DefIdSet, LOCAL_CRATE};
106106
use rustc_middle::mir;
107107
use rustc_middle::mir::mono::MonoItem;
108108
use rustc_middle::mir::mono::{CodegenUnit, Linkage};
109109
use rustc_middle::ty::print::with_no_trimmed_paths;
110110
use rustc_middle::ty::query::Providers;
111111
use rustc_middle::ty::TyCtxt;
112-
use rustc_session::config::SwitchWithOptPath;
112+
use rustc_session::config::{DumpMonoStatsFormat, SwitchWithOptPath};
113113
use rustc_span::symbol::Symbol;
114114

115115
use crate::collector::InliningMap;
@@ -417,7 +417,7 @@ fn collect_and_partition_mono_items(tcx: TyCtxt<'_>, (): ()) -> (&DefIdSet, &[Co
417417
// Output monomorphization stats per def_id
418418
if let SwitchWithOptPath::Enabled(ref path) = tcx.sess.opts.unstable_opts.dump_mono_stats {
419419
if let Err(err) =
420-
dump_mono_items_stats(tcx, &codegen_units, path, tcx.sess.opts.crate_name.as_deref())
420+
dump_mono_items_stats(tcx, &codegen_units, path, tcx.crate_name(LOCAL_CRATE))
421421
{
422422
tcx.sess.emit_fatal(CouldntDumpMonoStats { error: err.to_string() });
423423
}
@@ -483,7 +483,7 @@ fn dump_mono_items_stats<'tcx>(
483483
tcx: TyCtxt<'tcx>,
484484
codegen_units: &[CodegenUnit<'tcx>],
485485
output_directory: &Option<PathBuf>,
486-
crate_name: Option<&str>,
486+
crate_name: Symbol,
487487
) -> Result<(), Box<dyn std::error::Error>> {
488488
let output_directory = if let Some(ref directory) = output_directory {
489489
fs::create_dir_all(directory)?;
@@ -492,9 +492,11 @@ fn dump_mono_items_stats<'tcx>(
492492
Path::new(".")
493493
};
494494

495-
let filename = format!("{}.mono_items.md", crate_name.unwrap_or("unknown-crate"));
495+
let format = tcx.sess.opts.unstable_opts.dump_mono_stats_format;
496+
let ext = format.extension();
497+
let filename = format!("{crate_name}.mono_items.{ext}");
496498
let output_path = output_directory.join(&filename);
497-
let file = File::create(output_path)?;
499+
let file = File::create(&output_path)?;
498500
let mut file = BufWriter::new(file);
499501

500502
// Gather instantiated mono items grouped by def_id
@@ -508,30 +510,44 @@ fn dump_mono_items_stats<'tcx>(
508510
}
509511
}
510512

513+
#[derive(serde::Serialize)]
514+
struct MonoItem {
515+
name: String,
516+
instantiation_count: usize,
517+
size_estimate: usize,
518+
total_estimate: usize,
519+
}
520+
511521
// Output stats sorted by total instantiated size, from heaviest to lightest
512522
let mut stats: Vec<_> = items_per_def_id
513523
.into_iter()
514524
.map(|(def_id, items)| {
525+
let name = with_no_trimmed_paths!(tcx.def_path_str(def_id));
515526
let instantiation_count = items.len();
516527
let size_estimate = items[0].size_estimate(tcx);
517528
let total_estimate = instantiation_count * size_estimate;
518-
(def_id, instantiation_count, size_estimate, total_estimate)
529+
MonoItem { name, instantiation_count, size_estimate, total_estimate }
519530
})
520531
.collect();
521-
stats.sort_unstable_by_key(|(_, _, _, total_estimate)| cmp::Reverse(*total_estimate));
532+
stats.sort_unstable_by_key(|item| cmp::Reverse(item.total_estimate));
522533

523534
if !stats.is_empty() {
524-
writeln!(
525-
file,
526-
"| Item | Instantiation count | Estimated Cost Per Instantiation | Total Estimated Cost |"
527-
)?;
528-
writeln!(file, "| --- | ---: | ---: | ---: |")?;
529-
for (def_id, instantiation_count, size_estimate, total_estimate) in stats {
530-
let item = with_no_trimmed_paths!(tcx.def_path_str(def_id));
531-
writeln!(
532-
file,
533-
"| {item} | {instantiation_count} | {size_estimate} | {total_estimate} |"
534-
)?;
535+
match format {
536+
DumpMonoStatsFormat::Json => serde_json::to_writer(file, &stats)?,
537+
DumpMonoStatsFormat::Markdown => {
538+
writeln!(
539+
file,
540+
"| Item | Instantiation count | Estimated Cost Per Instantiation | Total Estimated Cost |"
541+
)?;
542+
writeln!(file, "| --- | ---: | ---: | ---: |")?;
543+
544+
for MonoItem { name, instantiation_count, size_estimate, total_estimate } in stats {
545+
writeln!(
546+
file,
547+
"| `{name}` | {instantiation_count} | {size_estimate} | {total_estimate} |"
548+
)?;
549+
}
550+
}
535551
}
536552
}
537553

compiler/rustc_query_impl/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ version = "0.0.0"
44
edition = "2021"
55

66
[lib]
7-
doctest = false
7+
88

99
[dependencies]
1010
measureme = "10.0.0"

0 commit comments

Comments
 (0)