diff options
| author | bors <bors@rust-lang.org> | 2023-01-04 09:41:43 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2023-01-04 09:41:43 +0000 |
| commit | 5c18bc6137256693e604a701b7d1bf10e93aaa2d (patch) | |
| tree | 8d778b9253efbb7c9bc9fdf823a2097b781c55f7 /compiler | |
| parent | ddad1e1f15f77074738bb3d7fb7688a9177b6450 (diff) | |
| parent | 4e590b3ee9622c90814c656e784e2facd5bc21ca (diff) | |
| download | rust-5c18bc6137256693e604a701b7d1bf10e93aaa2d.tar.gz rust-5c18bc6137256693e604a701b7d1bf10e93aaa2d.zip | |
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
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/rustc_ast/src/util/literal.rs | 4 | ||||
| -rw-r--r-- | compiler/rustc_error_messages/locales/en-US/session.ftl | 1 | ||||
| -rw-r--r-- | compiler/rustc_hir_analysis/src/collect.rs | 147 | ||||
| -rw-r--r-- | compiler/rustc_interface/src/tests.rs | 12 | ||||
| -rw-r--r-- | compiler/rustc_monomorphize/Cargo.toml | 2 | ||||
| -rw-r--r-- | compiler/rustc_monomorphize/src/partitioning/mod.rs | 54 | ||||
| -rw-r--r-- | compiler/rustc_query_impl/Cargo.toml | 2 | ||||
| -rw-r--r-- | compiler/rustc_session/src/config.rs | 18 | ||||
| -rw-r--r-- | compiler/rustc_session/src/errors.rs | 13 | ||||
| -rw-r--r-- | compiler/rustc_session/src/options.rs | 20 | ||||
| -rw-r--r-- | compiler/rustc_span/src/symbol.rs | 1 |
11 files changed, 194 insertions, 80 deletions
diff --git a/compiler/rustc_ast/src/util/literal.rs b/compiler/rustc_ast/src/util/literal.rs index 0daeecb53a8..69a9a583048 100644 --- a/compiler/rustc_ast/src/util/literal.rs +++ b/compiler/rustc_ast/src/util/literal.rs @@ -34,7 +34,7 @@ pub enum LitError { InvalidIntSuffix, InvalidFloatSuffix, NonDecimalFloat(u32), - IntTooLarge, + IntTooLarge(u32), } impl LitKind { @@ -333,6 +333,6 @@ fn integer_lit(symbol: Symbol, suffix: Option<Symbol>) -> Result<LitKind, LitErr // but these kinds of errors are already reported by the lexer. let from_lexer = base < 10 && s.chars().any(|c| c.to_digit(10).map_or(false, |d| d >= base)); - if from_lexer { LitError::LexerError } else { LitError::IntTooLarge } + if from_lexer { LitError::LexerError } else { LitError::IntTooLarge(base) } }) } diff --git a/compiler/rustc_error_messages/locales/en-US/session.ftl b/compiler/rustc_error_messages/locales/en-US/session.ftl index ab9e8b6baae..bc37d91a7c6 100644 --- a/compiler/rustc_error_messages/locales/en-US/session.ftl +++ b/compiler/rustc_error_messages/locales/en-US/session.ftl @@ -85,6 +85,7 @@ session_invalid_float_literal_suffix = invalid suffix `{$suffix}` for float lite .help = valid suffixes are `f32` and `f64` session_int_literal_too_large = integer literal is too large + .note = value exceeds limit of `{$limit}` session_invalid_int_literal_width = invalid width `{$width}` for integer literal .help = valid widths are 8, 16, 32, 64 and 128 diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 1ff7429e415..cf847047c90 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -17,6 +17,7 @@ use crate::astconv::AstConv; use crate::check::intrinsic::intrinsic_operation_unsafety; use crate::errors; +use hir::def::DefKind; use rustc_data_structures::captures::Captures; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed, StashKey}; @@ -24,8 +25,8 @@ use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::{GenericParamKind, Node}; -use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::infer::TyCtxtInferExt; +use rustc_infer::traits::ObligationCause; use rustc_middle::hir::nested_filter; use rustc_middle::ty::query::Providers; use rustc_middle::ty::util::{Discr, IntTypeExt}; @@ -1195,12 +1196,11 @@ fn infer_return_ty_for_fn_sig<'tcx>( ty::ReErased => tcx.lifetimes.re_static, _ => r, }); - let fn_sig = ty::Binder::dummy(fn_sig); let mut visitor = HirPlaceholderCollector::default(); visitor.visit_ty(ty); let mut diag = bad_placeholder(tcx, visitor.0, "return type"); - let ret_ty = fn_sig.skip_binder().output(); + let ret_ty = fn_sig.output(); if ret_ty.is_suggestable(tcx, false) { diag.span_suggestion( ty.span, @@ -1223,26 +1223,26 @@ fn infer_return_ty_for_fn_sig<'tcx>( Applicability::MachineApplicable, ); } + } else if let Some(sugg) = suggest_impl_trait(tcx, ret_ty, ty.span, hir_id, def_id) { + diag.span_suggestion( + ty.span, + "replace with an appropriate return type", + sugg, + Applicability::MachineApplicable, + ); } else if ret_ty.is_closure() { - // We're dealing with a closure, so we should suggest using `impl Fn` or trait bounds - // to prevent the user from getting a papercut while trying to use the unique closure - // syntax (e.g. `[closure@src/lib.rs:2:5: 2:9]`). diag.help("consider using an `Fn`, `FnMut`, or `FnOnce` trait bound"); + } + // Also note how `Fn` traits work just in case! + if ret_ty.is_closure() { diag.note( "for more information on `Fn` traits and closure types, see \ https://doc.rust-lang.org/book/ch13-01-closures.html", ); - } else if let Some(i_ty) = suggest_impl_iterator(tcx, ret_ty, ty.span, hir_id, def_id) { - diag.span_suggestion( - ty.span, - "replace with an appropriate return type", - format!("impl Iterator<Item = {}>", i_ty), - Applicability::MachineApplicable, - ); } diag.emit(); - fn_sig + ty::Binder::dummy(fn_sig) } None => <dyn AstConv<'_>>::ty_of_fn( icx, @@ -1256,47 +1256,94 @@ fn infer_return_ty_for_fn_sig<'tcx>( } } -fn suggest_impl_iterator<'tcx>( +fn suggest_impl_trait<'tcx>( tcx: TyCtxt<'tcx>, ret_ty: Ty<'tcx>, span: Span, hir_id: hir::HirId, def_id: LocalDefId, -) -> Option<Ty<'tcx>> { - let Some(iter_trait) = tcx.get_diagnostic_item(sym::Iterator) else { return None; }; - let Some(iterator_item) = tcx.get_diagnostic_item(sym::IteratorItem) else { return None; }; - if !tcx - .infer_ctxt() - .build() - .type_implements_trait(iter_trait, [ret_ty], tcx.param_env(def_id)) - .must_apply_modulo_regions() - { - return None; - } - let infcx = tcx.infer_ctxt().build(); - let ocx = ObligationCtxt::new_in_snapshot(&infcx); - // Find the type of `Iterator::Item`. - let origin = TypeVariableOrigin { kind: TypeVariableOriginKind::TypeInference, span }; - let ty_var = infcx.next_ty_var(origin); - let projection = ty::Binder::dummy(ty::PredicateKind::Clause(ty::Clause::Projection( - ty::ProjectionPredicate { - projection_ty: tcx.mk_alias_ty(iterator_item, tcx.mk_substs([ret_ty.into()].iter())), - term: ty_var.into(), - }, - ))); - // Add `<ret_ty as Iterator>::Item = _` obligation. - ocx.register_obligation(crate::traits::Obligation::misc( - tcx, - span, - hir_id, - tcx.param_env(def_id), - projection, - )); - if ocx.select_where_possible().is_empty() - && let item_ty = infcx.resolve_vars_if_possible(ty_var) - && item_ty.is_suggestable(tcx, false) - { - return Some(item_ty); +) -> Option<String> { + let format_as_assoc: fn(_, _, _, _, _) -> _ = + |tcx: TyCtxt<'tcx>, + _: ty::SubstsRef<'tcx>, + trait_def_id: DefId, + assoc_item_def_id: DefId, + item_ty: Ty<'tcx>| { + let trait_name = tcx.item_name(trait_def_id); + let assoc_name = tcx.item_name(assoc_item_def_id); + Some(format!("impl {trait_name}<{assoc_name} = {item_ty}>")) + }; + let format_as_parenthesized: fn(_, _, _, _, _) -> _ = + |tcx: TyCtxt<'tcx>, + substs: ty::SubstsRef<'tcx>, + trait_def_id: DefId, + _: DefId, + item_ty: Ty<'tcx>| { + let trait_name = tcx.item_name(trait_def_id); + let args_tuple = substs.type_at(1); + let ty::Tuple(types) = *args_tuple.kind() else { return None; }; + if !types.is_suggestable(tcx, false) { + return None; + } + let maybe_ret = + if item_ty.is_unit() { String::new() } else { format!(" -> {item_ty}") }; + Some(format!( + "impl {trait_name}({}){maybe_ret}", + types.iter().map(|ty| ty.to_string()).collect::<Vec<_>>().join(", ") + )) + }; + + for (trait_def_id, assoc_item_def_id, formatter) in [ + ( + tcx.get_diagnostic_item(sym::Iterator), + tcx.get_diagnostic_item(sym::IteratorItem), + format_as_assoc, + ), + ( + tcx.lang_items().future_trait(), + tcx.get_diagnostic_item(sym::FutureOutput), + format_as_assoc, + ), + (tcx.lang_items().fn_trait(), tcx.lang_items().fn_once_output(), format_as_parenthesized), + ( + tcx.lang_items().fn_mut_trait(), + tcx.lang_items().fn_once_output(), + format_as_parenthesized, + ), + ( + tcx.lang_items().fn_once_trait(), + tcx.lang_items().fn_once_output(), + format_as_parenthesized, + ), + ] { + let Some(trait_def_id) = trait_def_id else { continue; }; + let Some(assoc_item_def_id) = assoc_item_def_id else { continue; }; + if tcx.def_kind(assoc_item_def_id) != DefKind::AssocTy { + continue; + } + let param_env = tcx.param_env(def_id); + let infcx = tcx.infer_ctxt().build(); + let substs = ty::InternalSubsts::for_item(tcx, trait_def_id, |param, _| { + if param.index == 0 { ret_ty.into() } else { infcx.var_for_def(span, param) } + }); + if !infcx.type_implements_trait(trait_def_id, substs, param_env).must_apply_modulo_regions() + { + continue; + } + let ocx = ObligationCtxt::new_in_snapshot(&infcx); + let item_ty = ocx.normalize( + &ObligationCause::misc(span, hir_id), + param_env, + tcx.mk_projection(assoc_item_def_id, substs), + ); + // FIXME(compiler-errors): We may benefit from resolving regions here. + if ocx.select_where_possible().is_empty() + && let item_ty = infcx.resolve_vars_if_possible(item_ty) + && item_ty.is_suggestable(tcx, false) + && let Some(sugg) = formatter(tcx, infcx.resolve_vars_if_possible(substs), trait_def_id, assoc_item_def_id, item_ty) + { + return Some(sugg); + } } None } diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index eb3baba999b..9ec71c6b87e 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -3,17 +3,16 @@ use crate::interface::parse_cfgspecs; use rustc_data_structures::fx::FxHashSet; use rustc_errors::{emitter::HumanReadableErrorType, registry, ColorConfig}; -use rustc_session::config::InstrumentCoverage; -use rustc_session::config::Strip; +use rustc_session::config::rustc_optgroups; use rustc_session::config::{build_configuration, build_session_options, to_crate_config}; use rustc_session::config::{ - rustc_optgroups, ErrorOutputType, ExternLocation, LocationDetail, Options, Passes, -}; -use rustc_session::config::{ BranchProtection, Externs, OomStrategy, OutputType, OutputTypes, PAuthKey, PacRet, ProcMacroExecutionStrategy, SymbolManglingVersion, WasiExecModel, }; use rustc_session::config::{CFGuard, ExternEntry, LinkerPluginLto, LtoCli, SwitchWithOptPath}; +use rustc_session::config::{DumpMonoStatsFormat, MirSpanview}; +use rustc_session::config::{ErrorOutputType, ExternLocation, LocationDetail, Options, Strip}; +use rustc_session::config::{InstrumentCoverage, Passes}; use rustc_session::lint::Level; use rustc_session::search_paths::SearchPath; use rustc_session::utils::{CanonicalizedPath, NativeLib, NativeLibKind}; @@ -647,6 +646,9 @@ fn test_unstable_options_tracking_hash() { untracked!(dump_mir_dir, String::from("abc")); untracked!(dump_mir_exclude_pass_number, true); untracked!(dump_mir_graphviz, true); + untracked!(dump_mir_spanview, Some(MirSpanview::Statement)); + untracked!(dump_mono_stats, SwitchWithOptPath::Enabled(Some("mono-items-dir/".into()))); + untracked!(dump_mono_stats_format, DumpMonoStatsFormat::Json); untracked!(dylib_lto, true); untracked!(emit_stack_sizes, true); untracked!(future_incompat_test, true); diff --git a/compiler/rustc_monomorphize/Cargo.toml b/compiler/rustc_monomorphize/Cargo.toml index 6ee5330b63f..c8af10576b4 100644 --- a/compiler/rustc_monomorphize/Cargo.toml +++ b/compiler/rustc_monomorphize/Cargo.toml @@ -6,6 +6,8 @@ edition = "2021" [lib] [dependencies] +serde = "1" +serde_json = "1" smallvec = { version = "1.8.1", features = [ "union", "may_dangle" ] } tracing = "0.1" rustc_data_structures = { path = "../rustc_data_structures" } diff --git a/compiler/rustc_monomorphize/src/partitioning/mod.rs b/compiler/rustc_monomorphize/src/partitioning/mod.rs index 4f25fc71314..97fbb458e79 100644 --- a/compiler/rustc_monomorphize/src/partitioning/mod.rs +++ b/compiler/rustc_monomorphize/src/partitioning/mod.rs @@ -102,14 +102,14 @@ use std::path::{Path, PathBuf}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::sync; -use rustc_hir::def_id::DefIdSet; +use rustc_hir::def_id::{DefIdSet, LOCAL_CRATE}; use rustc_middle::mir; use rustc_middle::mir::mono::MonoItem; use rustc_middle::mir::mono::{CodegenUnit, Linkage}; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::query::Providers; use rustc_middle::ty::TyCtxt; -use rustc_session::config::SwitchWithOptPath; +use rustc_session::config::{DumpMonoStatsFormat, SwitchWithOptPath}; use rustc_span::symbol::Symbol; use crate::collector::InliningMap; @@ -417,7 +417,7 @@ fn collect_and_partition_mono_items(tcx: TyCtxt<'_>, (): ()) -> (&DefIdSet, &[Co // Output monomorphization stats per def_id if let SwitchWithOptPath::Enabled(ref path) = tcx.sess.opts.unstable_opts.dump_mono_stats { if let Err(err) = - dump_mono_items_stats(tcx, &codegen_units, path, tcx.sess.opts.crate_name.as_deref()) + dump_mono_items_stats(tcx, &codegen_units, path, tcx.crate_name(LOCAL_CRATE)) { tcx.sess.emit_fatal(CouldntDumpMonoStats { error: err.to_string() }); } @@ -483,7 +483,7 @@ fn dump_mono_items_stats<'tcx>( tcx: TyCtxt<'tcx>, codegen_units: &[CodegenUnit<'tcx>], output_directory: &Option<PathBuf>, - crate_name: Option<&str>, + crate_name: Symbol, ) -> Result<(), Box<dyn std::error::Error>> { let output_directory = if let Some(ref directory) = output_directory { fs::create_dir_all(directory)?; @@ -492,9 +492,11 @@ fn dump_mono_items_stats<'tcx>( Path::new(".") }; - let filename = format!("{}.mono_items.md", crate_name.unwrap_or("unknown-crate")); + let format = tcx.sess.opts.unstable_opts.dump_mono_stats_format; + let ext = format.extension(); + let filename = format!("{crate_name}.mono_items.{ext}"); let output_path = output_directory.join(&filename); - let file = File::create(output_path)?; + let file = File::create(&output_path)?; let mut file = BufWriter::new(file); // Gather instantiated mono items grouped by def_id @@ -508,30 +510,44 @@ fn dump_mono_items_stats<'tcx>( } } + #[derive(serde::Serialize)] + struct MonoItem { + name: String, + instantiation_count: usize, + size_estimate: usize, + total_estimate: usize, + } + // Output stats sorted by total instantiated size, from heaviest to lightest let mut stats: Vec<_> = items_per_def_id .into_iter() .map(|(def_id, items)| { + let name = with_no_trimmed_paths!(tcx.def_path_str(def_id)); let instantiation_count = items.len(); let size_estimate = items[0].size_estimate(tcx); let total_estimate = instantiation_count * size_estimate; - (def_id, instantiation_count, size_estimate, total_estimate) + MonoItem { name, instantiation_count, size_estimate, total_estimate } }) .collect(); - stats.sort_unstable_by_key(|(_, _, _, total_estimate)| cmp::Reverse(*total_estimate)); + stats.sort_unstable_by_key(|item| cmp::Reverse(item.total_estimate)); if !stats.is_empty() { - writeln!( - file, - "| Item | Instantiation count | Estimated Cost Per Instantiation | Total Estimated Cost |" - )?; - writeln!(file, "| --- | ---: | ---: | ---: |")?; - for (def_id, instantiation_count, size_estimate, total_estimate) in stats { - let item = with_no_trimmed_paths!(tcx.def_path_str(def_id)); - writeln!( - file, - "| {item} | {instantiation_count} | {size_estimate} | {total_estimate} |" - )?; + match format { + DumpMonoStatsFormat::Json => serde_json::to_writer(file, &stats)?, + DumpMonoStatsFormat::Markdown => { + writeln!( + file, + "| Item | Instantiation count | Estimated Cost Per Instantiation | Total Estimated Cost |" + )?; + writeln!(file, "| --- | ---: | ---: | ---: |")?; + + for MonoItem { name, instantiation_count, size_estimate, total_estimate } in stats { + writeln!( + file, + "| `{name}` | {instantiation_count} | {size_estimate} | {total_estimate} |" + )?; + } + } } } diff --git a/compiler/rustc_query_impl/Cargo.toml b/compiler/rustc_query_impl/Cargo.toml index b2111a1262a..46e77626479 100644 --- a/compiler/rustc_query_impl/Cargo.toml +++ b/compiler/rustc_query_impl/Cargo.toml @@ -4,7 +4,7 @@ version = "0.0.0" edition = "2021" [lib] -doctest = false + [dependencies] measureme = "10.0.0" diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 02e3992a6a9..5f78f6d079d 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -2981,3 +2981,21 @@ pub enum ProcMacroExecutionStrategy { /// Run the proc-macro code on a different thread. CrossThread, } + +/// Which format to use for `-Z dump-mono-stats` +#[derive(Clone, Copy, PartialEq, Hash, Debug)] +pub enum DumpMonoStatsFormat { + /// Pretty-print a markdown table + Markdown, + /// Emit structured JSON + Json, +} + +impl DumpMonoStatsFormat { + pub fn extension(self) -> &'static str { + match self { + Self::Markdown => "md", + Self::Json => "json", + } + } +} diff --git a/compiler/rustc_session/src/errors.rs b/compiler/rustc_session/src/errors.rs index e72b76cfee9..f5a72573d58 100644 --- a/compiler/rustc_session/src/errors.rs +++ b/compiler/rustc_session/src/errors.rs @@ -260,9 +260,11 @@ pub(crate) struct InvalidFloatLiteralSuffix { #[derive(Diagnostic)] #[diag(session_int_literal_too_large)] +#[note] pub(crate) struct IntLiteralTooLarge { #[primary_span] pub span: Span, + pub limit: String, } #[derive(Diagnostic)] @@ -361,8 +363,15 @@ pub fn report_lit_error(sess: &ParseSess, err: LitError, lit: token::Lit, span: _ => unreachable!(), }; } - LitError::IntTooLarge => { - sess.emit_err(IntLiteralTooLarge { span }); + LitError::IntTooLarge(base) => { + let max = u128::MAX; + let limit = match base { + 2 => format!("{max:#b}"), + 8 => format!("{max:#o}"), + 16 => format!("{max:#x}"), + _ => format!("{max}"), + }; + sess.emit_err(IntLiteralTooLarge { span, limit }); } } } diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 9bf581ff73d..b379aef80fb 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -377,6 +377,7 @@ mod desc { pub const parse_linker_flavor: &str = ::rustc_target::spec::LinkerFlavorCli::one_of(); pub const parse_optimization_fuel: &str = "crate=integer"; pub const parse_mir_spanview: &str = "`statement` (default), `terminator`, or `block`"; + pub const parse_dump_mono_stats: &str = "`markdown` (default) or `json`"; pub const parse_instrument_coverage: &str = "`all` (default), `except-unused-generics`, `except-unused-functions`, or `off`"; pub const parse_unpretty: &str = "`string` or `string=string`"; @@ -820,6 +821,21 @@ mod parse { true } + pub(crate) fn parse_dump_mono_stats(slot: &mut DumpMonoStatsFormat, v: Option<&str>) -> bool { + match v { + None => true, + Some("json") => { + *slot = DumpMonoStatsFormat::Json; + true + } + Some("markdown") => { + *slot = DumpMonoStatsFormat::Markdown; + true + } + Some(_) => false, + } + } + pub(crate) fn parse_instrument_coverage( slot: &mut Option<InstrumentCoverage>, v: Option<&str>, @@ -1295,7 +1311,9 @@ options! { an additional `.html` file showing the computed coverage spans."), dump_mono_stats: SwitchWithOptPath = (SwitchWithOptPath::Disabled, parse_switch_with_opt_path, [UNTRACKED], - "output statistics about monomorphization collection (format: markdown)"), + "output statistics about monomorphization collection"), + dump_mono_stats_format: DumpMonoStatsFormat = (DumpMonoStatsFormat::Markdown, parse_dump_mono_stats, [UNTRACKED], + "the format to use for -Z dump-mono-stats (`markdown` (default) or `json`)"), dwarf_version: Option<u32> = (None, parse_opt_number, [TRACKED], "version of DWARF debug information to emit (default: 2 or 4, depending on platform)"), dylib_lto: bool = (false, parse_bool, [UNTRACKED], diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 85510fa2c66..5d5f8d6d654 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -193,6 +193,7 @@ symbols! { FromIterator, FromResidual, Future, + FutureOutput, FxHashMap, FxHashSet, GlobalAlloc, |
