diff --git a/Cargo.lock b/Cargo.lock index 7491c1712669c..235355e3bfc9d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2139,11 +2139,14 @@ dependencies = [ [[package]] name = "measureme" -version = "9.0.0" +version = "9.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22bf8d885d073610aee20e7fa205c4341ed32a761dbde96da5fd96301a8d3e82" +checksum = "4a98e07fe802486895addb2b5467f33f205e82c426bfaf350f5d8109b137767c" dependencies = [ + "log", + "memmap", "parking_lot", + "perf-event-open-sys", "rustc-hash", "smallvec 1.6.1", ] @@ -2540,6 +2543,15 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" +[[package]] +name = "perf-event-open-sys" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce9bedf5da2c234fdf2391ede2b90fabf585355f33100689bc364a3ea558561a" +dependencies = [ + "libc", +] + [[package]] name = "pest" version = "2.1.3" diff --git a/compiler/rustc_codegen_cranelift/src/lib.rs b/compiler/rustc_codegen_cranelift/src/lib.rs index 170750461cace..1480ab2513378 100644 --- a/compiler/rustc_codegen_cranelift/src/lib.rs +++ b/compiler/rustc_codegen_cranelift/src/lib.rs @@ -5,8 +5,7 @@ associated_type_bounds, never_type, try_blocks, - hash_drain_filter, - str_split_once + hash_drain_filter )] #![warn(rust_2018_idioms)] #![warn(unused_lifetimes)] diff --git a/compiler/rustc_codegen_llvm/Cargo.toml b/compiler/rustc_codegen_llvm/Cargo.toml index ebbb852f21cc8..6dad087a31ba2 100644 --- a/compiler/rustc_codegen_llvm/Cargo.toml +++ b/compiler/rustc_codegen_llvm/Cargo.toml @@ -11,7 +11,7 @@ doctest = false [dependencies] bitflags = "1.0" libc = "0.2" -measureme = "9.0.0" +measureme = "9.1.0" snap = "1" tracing = "0.1" rustc_middle = { path = "../rustc_middle" } diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index d935fc83b7212..1464784ae288c 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -2372,7 +2372,7 @@ fn compute_type_parameters(cx: &CodegenCx<'ll, 'tcx>, ty: Ty<'tcx>) -> &'ll DIAr fn get_parameter_names(cx: &CodegenCx<'_, '_>, generics: &ty::Generics) -> Vec { let mut names = generics .parent - .map_or(vec![], |def_id| get_parameter_names(cx, cx.tcx.generics_of(def_id))); + .map_or_else(Vec::new, |def_id| get_parameter_names(cx, cx.tcx.generics_of(def_id))); names.extend(generics.params.iter().map(|param| param.name)); names } diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs index 955e739b2c126..c28b0d64651e3 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs @@ -481,9 +481,9 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { } fn get_parameter_names(cx: &CodegenCx<'_, '_>, generics: &ty::Generics) -> Vec { - let mut names = generics - .parent - .map_or(vec![], |def_id| get_parameter_names(cx, cx.tcx.generics_of(def_id))); + let mut names = generics.parent.map_or_else(Vec::new, |def_id| { + get_parameter_names(cx, cx.tcx.generics_of(def_id)) + }); names.extend(generics.params.iter().map(|param| param.name)); names } diff --git a/compiler/rustc_codegen_llvm/src/metadata.rs b/compiler/rustc_codegen_llvm/src/metadata.rs index 3912d6a3a48b6..b007df5730621 100644 --- a/compiler/rustc_codegen_llvm/src/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/metadata.rs @@ -65,8 +65,8 @@ fn search_meta_section<'a>( while llvm::LLVMIsSectionIteratorAtEnd(of.llof, si.llsi) == False { let mut name_buf = None; let name_len = llvm::LLVMRustGetSectionName(si.llsi, &mut name_buf); - let name = name_buf.map_or( - String::new(), // We got a NULL ptr, ignore `name_len`. + let name = name_buf.map_or_else( + String::new, // We got a NULL ptr, ignore `name_len`. |buf| { String::from_utf8( slice::from_raw_parts(buf.as_ptr() as *const u8, name_len as usize) diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 08932e26bf1c7..caa6a6a8e3a26 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -2082,7 +2082,7 @@ fn add_upstream_rust_crates<'a, B: ArchiveBuilder<'a>>( let filestem = cratepath.file_stem().unwrap().to_str().unwrap(); cmd.link_rust_dylib( Symbol::intern(&unlib(&sess.target, filestem)), - parent.unwrap_or(Path::new("")), + parent.unwrap_or_else(|| Path::new("")), ); } } diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index d931c57fba247..7b8ce157fc2b4 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -712,6 +712,33 @@ impl WorkItem { } } } + + /// Generate a short description of this work item suitable for use as a thread name. + fn short_description(&self) -> String { + // `pthread_setname()` on *nix is limited to 15 characters and longer names are ignored. + // Use very short descriptions in this case to maximize the space available for the module name. + // Windows does not have that limitation so use slightly more descriptive names there. + match self { + WorkItem::Optimize(m) => { + #[cfg(windows)] + return format!("optimize module {}", m.name); + #[cfg(not(windows))] + return format!("opt {}", m.name); + } + WorkItem::CopyPostLtoArtifacts(m) => { + #[cfg(windows)] + return format!("copy LTO artifacts for {}", m.name); + #[cfg(not(windows))] + return format!("copy {}", m.name); + } + WorkItem::LTO(m) => { + #[cfg(windows)] + return format!("LTO module {}", m.name()); + #[cfg(not(windows))] + return format!("LTO {}", m.name()); + } + } + } } enum WorkItemResult { @@ -1609,56 +1636,59 @@ fn start_executing_work( pub struct WorkerFatalError; fn spawn_work(cgcx: CodegenContext, work: WorkItem) { - thread::spawn(move || { - // Set up a destructor which will fire off a message that we're done as - // we exit. - struct Bomb { - coordinator_send: Sender>, - result: Option, FatalError>>, - worker_id: usize, - } - impl Drop for Bomb { - fn drop(&mut self) { - let worker_id = self.worker_id; - let msg = match self.result.take() { - Some(Ok(WorkItemResult::Compiled(m))) => { - Message::Done:: { result: Ok(m), worker_id } - } - Some(Ok(WorkItemResult::NeedsLink(m))) => { - Message::NeedsLink:: { module: m, worker_id } - } - Some(Ok(WorkItemResult::NeedsFatLTO(m))) => { - Message::NeedsFatLTO:: { result: m, worker_id } - } - Some(Ok(WorkItemResult::NeedsThinLTO(name, thin_buffer))) => { - Message::NeedsThinLTO:: { name, thin_buffer, worker_id } - } - Some(Err(FatalError)) => { - Message::Done:: { result: Err(Some(WorkerFatalError)), worker_id } - } - None => Message::Done:: { result: Err(None), worker_id }, - }; - drop(self.coordinator_send.send(Box::new(msg))); + let builder = thread::Builder::new().name(work.short_description()); + builder + .spawn(move || { + // Set up a destructor which will fire off a message that we're done as + // we exit. + struct Bomb { + coordinator_send: Sender>, + result: Option, FatalError>>, + worker_id: usize, + } + impl Drop for Bomb { + fn drop(&mut self) { + let worker_id = self.worker_id; + let msg = match self.result.take() { + Some(Ok(WorkItemResult::Compiled(m))) => { + Message::Done:: { result: Ok(m), worker_id } + } + Some(Ok(WorkItemResult::NeedsLink(m))) => { + Message::NeedsLink:: { module: m, worker_id } + } + Some(Ok(WorkItemResult::NeedsFatLTO(m))) => { + Message::NeedsFatLTO:: { result: m, worker_id } + } + Some(Ok(WorkItemResult::NeedsThinLTO(name, thin_buffer))) => { + Message::NeedsThinLTO:: { name, thin_buffer, worker_id } + } + Some(Err(FatalError)) => { + Message::Done:: { result: Err(Some(WorkerFatalError)), worker_id } + } + None => Message::Done:: { result: Err(None), worker_id }, + }; + drop(self.coordinator_send.send(Box::new(msg))); + } } - } - let mut bomb = Bomb:: { - coordinator_send: cgcx.coordinator_send.clone(), - result: None, - worker_id: cgcx.worker, - }; + let mut bomb = Bomb:: { + coordinator_send: cgcx.coordinator_send.clone(), + result: None, + worker_id: cgcx.worker, + }; - // Execute the work itself, and if it finishes successfully then flag - // ourselves as a success as well. - // - // Note that we ignore any `FatalError` coming out of `execute_work_item`, - // as a diagnostic was already sent off to the main thread - just - // surface that there was an error in this worker. - bomb.result = { - let _prof_timer = work.start_profiling(&cgcx); - Some(execute_work_item(&cgcx, work)) - }; - }); + // Execute the work itself, and if it finishes successfully then flag + // ourselves as a success as well. + // + // Note that we ignore any `FatalError` coming out of `execute_work_item`, + // as a diagnostic was already sent off to the main thread - just + // surface that there was an error in this worker. + bomb.result = { + let _prof_timer = work.start_profiling(&cgcx); + Some(execute_work_item(&cgcx, work)) + }; + }) + .expect("failed to spawn thread"); } enum SharedEmitterMessage { diff --git a/compiler/rustc_data_structures/Cargo.toml b/compiler/rustc_data_structures/Cargo.toml index e3476517de583..818c43642566c 100644 --- a/compiler/rustc_data_structures/Cargo.toml +++ b/compiler/rustc_data_structures/Cargo.toml @@ -25,7 +25,7 @@ rustc-hash = "1.1.0" smallvec = { version = "1.6.1", features = ["union", "may_dangle"] } rustc_index = { path = "../rustc_index", package = "rustc_index" } bitflags = "1.2.1" -measureme = "9.0.0" +measureme = "9.1.0" libc = "0.2" stacker = "0.1.12" tempfile = "3.0.5" diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 9e55f7e558999..2d5f43e5890d0 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -1484,13 +1484,16 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { for (key, values) in types.iter() { let count = values.len(); let kind = key.descr(); + let mut returned_async_output_error = false; for sp in values { err.span_label( *sp, format!( "{}{}{} {}{}", - if sp.is_desugaring(DesugaringKind::Async) { - "the `Output` of this `async fn`'s " + if sp.is_desugaring(DesugaringKind::Async) + && !returned_async_output_error + { + "checked the `Output` of this `async fn`, " } else if count == 1 { "the " } else { @@ -1502,6 +1505,12 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { pluralize!(count), ), ); + if sp.is_desugaring(DesugaringKind::Async) + && returned_async_output_error == false + { + err.note("while checking the return type of the `async fn`"); + returned_async_output_error = true; + } } } } diff --git a/compiler/rustc_lint/src/non_fmt_panic.rs b/compiler/rustc_lint/src/non_fmt_panic.rs index bfe37ce6959e7..5a27135581747 100644 --- a/compiler/rustc_lint/src/non_fmt_panic.rs +++ b/compiler/rustc_lint/src/non_fmt_panic.rs @@ -201,7 +201,7 @@ fn check_panic_str<'tcx>( Some(v) if v.len() == 1 => "panic message contains a brace", _ => "panic message contains braces", }; - cx.struct_span_lint(NON_FMT_PANIC, brace_spans.unwrap_or(vec![span]), |lint| { + cx.struct_span_lint(NON_FMT_PANIC, brace_spans.unwrap_or_else(|| vec![span]), |lint| { let mut l = lint.build(msg); l.note("this message is not used as a format string, but will be in Rust 2021"); if span.contains(arg.span) { diff --git a/compiler/rustc_macros/src/query.rs b/compiler/rustc_macros/src/query.rs index 3e67525567f97..291e7ef045e4f 100644 --- a/compiler/rustc_macros/src/query.rs +++ b/compiler/rustc_macros/src/query.rs @@ -378,14 +378,14 @@ fn add_query_description_impl( let t = &(t.0).0; quote! { #t } }) - .unwrap_or(quote! { _ }); + .unwrap_or_else(|| quote! { _ }); let value = args .as_ref() .map(|t| { let t = &(t.1).0; quote! { #t } }) - .unwrap_or(quote! { _ }); + .unwrap_or_else(|| quote! { _ }); // expr is a `Block`, meaning that `{ #expr }` gets expanded // to `{ { stmts... } }`, which triggers the `unused_braces` lint. quote! { @@ -409,7 +409,7 @@ fn add_query_description_impl( }; let (tcx, desc) = modifiers.desc; - let tcx = tcx.as_ref().map_or(quote! { _ }, |t| quote! { #t }); + let tcx = tcx.as_ref().map_or_else(|| quote! { _ }, |t| quote! { #t }); let desc = quote! { #[allow(unused_variables)] diff --git a/compiler/rustc_macros/src/session_diagnostic.rs b/compiler/rustc_macros/src/session_diagnostic.rs index 5c061a9d3c794..8a0fce209b7fb 100644 --- a/compiler/rustc_macros/src/session_diagnostic.rs +++ b/compiler/rustc_macros/src/session_diagnostic.rs @@ -473,9 +473,9 @@ impl<'a> SessionDiagnosticDeriveBuilder<'a> { .map( |applicability_idx| quote!(#binding.#applicability_idx), ) - .unwrap_or(quote!( - rustc_errors::Applicability::Unspecified - )); + .unwrap_or_else(|| { + quote!(rustc_errors::Applicability::Unspecified) + }); return Ok((span, applicability)); } throw_span_err!( diff --git a/compiler/rustc_middle/Cargo.toml b/compiler/rustc_middle/Cargo.toml index 7de398a1898e5..0674233165501 100644 --- a/compiler/rustc_middle/Cargo.toml +++ b/compiler/rustc_middle/Cargo.toml @@ -28,6 +28,6 @@ rustc_ast = { path = "../rustc_ast" } rustc_span = { path = "../rustc_span" } chalk-ir = "0.55.0" smallvec = { version = "1.6.1", features = ["union", "may_dangle"] } -measureme = "9.0.0" +measureme = "9.1.0" rustc_session = { path = "../rustc_session" } rustc_type_ir = { path = "../rustc_type_ir" } diff --git a/compiler/rustc_mir/src/const_eval/eval_queries.rs b/compiler/rustc_mir/src/const_eval/eval_queries.rs index de898460368b8..fa234ff5feb64 100644 --- a/compiler/rustc_mir/src/const_eval/eval_queries.rs +++ b/compiler/rustc_mir/src/const_eval/eval_queries.rs @@ -50,7 +50,7 @@ fn eval_body_using_ecx<'mir, 'tcx>( let name = with_no_trimmed_paths(|| ty::tls::with(|tcx| tcx.def_path_str(cid.instance.def_id()))); - let prom = cid.promoted.map_or(String::new(), |p| format!("::promoted[{:?}]", p)); + let prom = cid.promoted.map_or_else(String::new, |p| format!("::promoted[{:?}]", p)); trace!("eval_body_using_ecx: pushing stack frame for global: {}{}", name, prom); ecx.push_stack_frame( diff --git a/compiler/rustc_mir/src/lib.rs b/compiler/rustc_mir/src/lib.rs index 8b3881ef9de10..508510a81e1fb 100644 --- a/compiler/rustc_mir/src/lib.rs +++ b/compiler/rustc_mir/src/lib.rs @@ -28,7 +28,6 @@ Rust MIR: a lowered representation of Rust. #![feature(or_patterns)] #![feature(once_cell)] #![feature(control_flow_enum)] -#![feature(str_split_once)] #![recursion_limit = "256"] #[macro_use] diff --git a/compiler/rustc_mir/src/transform/inline.rs b/compiler/rustc_mir/src/transform/inline.rs index f4f69fc8ac62b..16279040a1c3f 100644 --- a/compiler/rustc_mir/src/transform/inline.rs +++ b/compiler/rustc_mir/src/transform/inline.rs @@ -1,6 +1,6 @@ //! Inlining pass for MIR functions -use rustc_attr as attr; +use rustc_attr::InlineAttr; use rustc_hir as hir; use rustc_index::bit_set::BitSet; use rustc_index::vec::Idx; @@ -106,72 +106,90 @@ struct Inliner<'tcx> { impl Inliner<'tcx> { fn process_blocks(&mut self, caller_body: &mut Body<'tcx>, blocks: Range) { for bb in blocks { - let callsite = match self.get_valid_function_call(bb, &caller_body[bb], caller_body) { + let bb_data = &caller_body[bb]; + if bb_data.is_cleanup { + continue; + } + + let callsite = match self.resolve_callsite(caller_body, bb, bb_data) { None => continue, Some(it) => it, }; + let span = trace_span!("process_blocks", %callsite.callee, ?bb); let _guard = span.enter(); - trace!( - "checking for self recursion ({:?} vs body_source: {:?})", - callsite.callee.def_id(), - caller_body.source.def_id() - ); - if callsite.callee.def_id() == caller_body.source.def_id() { - debug!("Not inlining a function into itself"); - continue; - } - - if !self.is_mir_available(callsite.callee, caller_body) { - debug!("MIR unavailable {}", callsite.callee); - continue; + match self.try_inlining(caller_body, &callsite) { + Err(reason) => { + debug!("not-inlined {} [{}]", callsite.callee, reason); + continue; + } + Ok(new_blocks) => { + debug!("inlined {}", callsite.callee); + self.changed = true; + self.history.push(callsite.callee); + self.process_blocks(caller_body, new_blocks); + self.history.pop(); + } } + } + } - let span = trace_span!("instance_mir", %callsite.callee); - let instance_mir_guard = span.enter(); - let callee_body = self.tcx.instance_mir(callsite.callee.def); - drop(instance_mir_guard); - if !self.should_inline(callsite, callee_body) { - continue; - } + /// Attempts to inline a callsite into the caller body. When successful returns basic blocks + /// containing the inlined body. Otherwise returns an error describing why inlining didn't take + /// place. + fn try_inlining( + &self, + caller_body: &mut Body<'tcx>, + callsite: &CallSite<'tcx>, + ) -> Result, &'static str> { + let callee_attrs = self.tcx.codegen_fn_attrs(callsite.callee.def_id()); + self.check_codegen_attributes(callsite, callee_attrs)?; + self.check_mir_is_available(caller_body, &callsite.callee)?; + let callee_body = self.tcx.instance_mir(callsite.callee.def); + self.check_mir_body(callsite, callee_body, callee_attrs)?; + + if !self.tcx.consider_optimizing(|| { + format!("Inline {:?} into {}", callee_body.span, callsite.callee) + }) { + return Err("optimization fuel exhausted"); + } - if !self.tcx.consider_optimizing(|| { - format!("Inline {:?} into {}", callee_body.span, callsite.callee) - }) { - return; - } + let callee_body = callsite.callee.subst_mir_and_normalize_erasing_regions( + self.tcx, + self.param_env, + callee_body.clone(), + ); - let callee_body = callsite.callee.subst_mir_and_normalize_erasing_regions( - self.tcx, - self.param_env, - callee_body.clone(), - ); + let old_blocks = caller_body.basic_blocks().next_index(); + self.inline_call(caller_body, &callsite, callee_body); + let new_blocks = old_blocks..caller_body.basic_blocks().next_index(); - let old_blocks = caller_body.basic_blocks().next_index(); - self.inline_call(callsite, caller_body, callee_body); - let new_blocks = old_blocks..caller_body.basic_blocks().next_index(); - self.changed = true; + Ok(new_blocks) + } - self.history.push(callsite.callee); - self.process_blocks(caller_body, new_blocks); - self.history.pop(); + fn check_mir_is_available( + &self, + caller_body: &Body<'tcx>, + callee: &Instance<'tcx>, + ) -> Result<(), &'static str> { + if callee.def_id() == caller_body.source.def_id() { + return Err("self-recursion"); } - } - #[instrument(level = "debug", skip(self, caller_body))] - fn is_mir_available(&self, callee: Instance<'tcx>, caller_body: &Body<'tcx>) -> bool { match callee.def { InstanceDef::Item(_) => { // If there is no MIR available (either because it was not in metadata or // because it has no MIR because it's an extern function), then the inliner // won't cause cycles on this. if !self.tcx.is_mir_available(callee.def_id()) { - return false; + return Err("item MIR unavailable"); } } // These have no own callable MIR. - InstanceDef::Intrinsic(_) | InstanceDef::Virtual(..) => return false, + InstanceDef::Intrinsic(_) | InstanceDef::Virtual(..) => { + return Err("instance without MIR (intrinsic / virtual)"); + } // This cannot result in an immediate cycle since the callee MIR is a shim, which does // not get any optimizations run on it. Any subsequent inlining may cause cycles, but we // do not need to catch this here, we can wait until the inliner decides to continue @@ -181,13 +199,13 @@ impl Inliner<'tcx> { | InstanceDef::FnPtrShim(..) | InstanceDef::ClosureOnceShim { .. } | InstanceDef::DropGlue(..) - | InstanceDef::CloneShim(..) => return true, + | InstanceDef::CloneShim(..) => return Ok(()), } if self.tcx.is_constructor(callee.def_id()) { trace!("constructors always have MIR"); // Constructor functions cannot cause a query cycle. - return true; + return Ok(()); } if let Some(callee_def_id) = callee.def_id().as_local() { @@ -196,39 +214,44 @@ impl Inliner<'tcx> { // since their `optimized_mir` is used for layout computation, which can // create a cycle, even when no attempt is made to inline the function // in the other direction. - caller_body.generator_kind.is_none() - && ( - // Avoid a cycle here by only using `instance_mir` only if we have - // a lower `HirId` than the callee. This ensures that the callee will - // not inline us. This trick only works without incremental compilation. - // So don't do it if that is enabled. - !self.tcx.dep_graph.is_fully_enabled() - && self.hir_id < callee_hir_id - // If we know for sure that the function we're calling will itself try to - // call us, then we avoid inlining that function. - || !self.tcx.mir_callgraph_reachable((callee, caller_body.source.def_id().expect_local())) - ) + if caller_body.generator_kind.is_some() { + return Err("local generator (query cycle avoidance)"); + } + + // Avoid a cycle here by only using `instance_mir` only if we have + // a lower `HirId` than the callee. This ensures that the callee will + // not inline us. This trick only works without incremental compilation. + // So don't do it if that is enabled. + if !self.tcx.dep_graph.is_fully_enabled() && self.hir_id < callee_hir_id { + return Ok(()); + } + + // If we know for sure that the function we're calling will itself try to + // call us, then we avoid inlining that function. + if self + .tcx + .mir_callgraph_reachable((*callee, caller_body.source.def_id().expect_local())) + { + return Err("caller might be reachable from callee (query cycle avoidance)"); + } + + Ok(()) } else { // This cannot result in an immediate cycle since the callee MIR is from another crate // and is already optimized. Any subsequent inlining may cause cycles, but we do // not need to catch this here, we can wait until the inliner decides to continue // inlining a second time. trace!("functions from other crates always have MIR"); - true + Ok(()) } } - fn get_valid_function_call( + fn resolve_callsite( &self, + caller_body: &Body<'tcx>, bb: BasicBlock, bb_data: &BasicBlockData<'tcx>, - caller_body: &Body<'tcx>, ) -> Option> { - // Don't inline calls that are in cleanup blocks. - if bb_data.is_cleanup { - return None; - } - // Only consider direct calls to functions let terminator = bb_data.terminator(); if let TerminatorKind::Call { ref func, ref destination, .. } = terminator.kind { @@ -258,73 +281,73 @@ impl Inliner<'tcx> { None } - #[instrument(level = "debug", skip(self, callee_body))] - fn should_inline(&self, callsite: CallSite<'tcx>, callee_body: &Body<'tcx>) -> bool { - let tcx = self.tcx; + /// Returns an error if inlining is not possible based on codegen attributes alone. A success + /// indicates that inlining decision should be based on other criteria. + fn check_codegen_attributes( + &self, + callsite: &CallSite<'tcx>, + callee_attrs: &CodegenFnAttrs, + ) -> Result<(), &'satic str> { + if let InlineAttr::Never = callee_attrs.inline { + return Err("never inline hint"); + } + + // Only inline local functions if they would be eligible for cross-crate + // inlining. This is to ensure that the final crate doesn't have MIR that + // reference unexported symbols + if callsite.callee.def_id().is_local() { + let is_generic = callsite.callee.substs.non_erasable_generics().next().is_some(); + if !is_generic && !callee_attrs.requests_inline() { + return Err("not exported"); + } + } if callsite.fn_sig.c_variadic() { - debug!("callee is variadic - not inlining"); - return false; + return Err("C variadic"); } - let codegen_fn_attrs = tcx.codegen_fn_attrs(callsite.callee.def_id()); + if callee_attrs.flags.contains(CodegenFnAttrFlags::NAKED) { + return Err("naked"); + } - let self_features = &self.codegen_fn_attrs.target_features; - let callee_features = &codegen_fn_attrs.target_features; - if callee_features.iter().any(|feature| !self_features.contains(feature)) { - debug!("`callee has extra target features - not inlining"); - return false; + if callee_attrs.flags.contains(CodegenFnAttrFlags::COLD) { + return Err("cold"); } - if self.codegen_fn_attrs.no_sanitize != codegen_fn_attrs.no_sanitize { - debug!("`callee has incompatible no_sanitize attribute - not inlining"); - return false; + if callee_attrs.no_sanitize != self.codegen_fn_attrs.no_sanitize { + return Err("incompatible sanitizer set"); } - if self.codegen_fn_attrs.instruction_set != codegen_fn_attrs.instruction_set { - debug!("`callee has incompatible instruction set - not inlining"); - return false; + if callee_attrs.instruction_set != self.codegen_fn_attrs.instruction_set { + return Err("incompatible instruction set"); } - let hinted = match codegen_fn_attrs.inline { - // Just treat inline(always) as a hint for now, - // there are cases that prevent inlining that we - // need to check for first. - attr::InlineAttr::Always => true, - attr::InlineAttr::Never => { - debug!("`#[inline(never)]` present - not inlining"); - return false; - } - attr::InlineAttr::Hint => true, - attr::InlineAttr::None => false, - }; - - // Only inline local functions if they would be eligible for cross-crate - // inlining. This is to ensure that the final crate doesn't have MIR that - // reference unexported symbols - if callsite.callee.def_id().is_local() { - if callsite.callee.substs.non_erasable_generics().count() == 0 && !hinted { - debug!(" callee is an exported function - not inlining"); - return false; + for feature in &callee_attrs.target_features { + if !self.codegen_fn_attrs.target_features.contains(feature) { + return Err("incompatible target feature"); } } - let mut threshold = if hinted { + Ok(()) + } + + /// Returns inlining decision that is based on the examination of callee MIR body. + /// Assumes that codegen attributes have been checked for compatibility already. + #[instrument(level = "debug", skip(self, callee_body))] + fn check_mir_body( + &self, + callsite: &CallSite<'tcx>, + callee_body: &Body<'tcx>, + callee_attrs: &CodegenFnAttrs, + ) -> Result<(), &'static str> { + let tcx = self.tcx; + + let mut threshold = if callee_attrs.requests_inline() { self.tcx.sess.opts.debugging_opts.inline_mir_hint_threshold } else { self.tcx.sess.opts.debugging_opts.inline_mir_threshold }; - if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::NAKED) { - debug!("#[naked] present - not inlining"); - return false; - } - - if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::COLD) { - debug!("#[cold] present - not inlining"); - return false; - } - // Give a bonus functions with a small number of blocks, // We normally have two or three blocks for even // very small functions. @@ -393,11 +416,10 @@ impl Inliner<'tcx> { if let Ok(Some(instance)) = Instance::resolve(self.tcx, self.param_env, def_id, substs) { - if callsite.callee.def_id() == instance.def_id() - || self.history.contains(&instance) - { - debug!("`callee is recursive - not inlining"); - return false; + if callsite.callee.def_id() == instance.def_id() { + return Err("self-recursion"); + } else if self.history.contains(&instance) { + return Err("already inlined"); } } // Don't give intrinsics the extra penalty for calls @@ -450,24 +472,24 @@ impl Inliner<'tcx> { } } - if let attr::InlineAttr::Always = codegen_fn_attrs.inline { + if let InlineAttr::Always = callee_attrs.inline { debug!("INLINING {:?} because inline(always) [cost={}]", callsite, cost); - true + Ok(()) } else { if cost <= threshold { debug!("INLINING {:?} [cost={} <= threshold={}]", callsite, cost, threshold); - true + Ok(()) } else { debug!("NOT inlining {:?} [cost={} > threshold={}]", callsite, cost, threshold); - false + Err("cost above threshold") } } } fn inline_call( &self, - callsite: CallSite<'tcx>, caller_body: &mut Body<'tcx>, + callsite: &CallSite<'tcx>, mut callee_body: Body<'tcx>, ) { let terminator = caller_body[callsite.block].terminator.take().unwrap(); diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 0f49386dec07b..5b4939b740726 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -223,7 +223,7 @@ impl<'a> Parser<'a> { fn tokens_to_string(tokens: &[TokenType]) -> String { let mut i = tokens.iter(); // This might be a sign we need a connect method on `Iterator`. - let b = i.next().map_or(String::new(), |t| t.to_string()); + let b = i.next().map_or_else(String::new, |t| t.to_string()); i.enumerate().fold(b, |mut b, (i, a)| { if tokens.len() > 2 && i == tokens.len() - 2 { b.push_str(", or "); diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs index c11dc231d482c..82f19770a123b 100644 --- a/compiler/rustc_passes/src/liveness.rs +++ b/compiler/rustc_passes/src/liveness.rs @@ -367,12 +367,17 @@ impl<'tcx> Visitor<'tcx> for IrMaps<'tcx> { } fn visit_param(&mut self, param: &'tcx hir::Param<'tcx>) { - let is_shorthand = matches!(param.pat.kind, rustc_hir::PatKind::Struct(..)); param.pat.each_binding(|_bm, hir_id, _x, ident| { - let var = if is_shorthand { - Local(LocalInfo { id: hir_id, name: ident.name, is_shorthand: true }) - } else { - Param(hir_id, ident.name) + let var = match param.pat.kind { + rustc_hir::PatKind::Struct(_, fields, _) => Local(LocalInfo { + id: hir_id, + name: ident.name, + is_shorthand: fields + .iter() + .find(|f| f.ident == ident) + .map_or(false, |f| f.is_shorthand), + }), + _ => Param(hir_id, ident.name), }; self.add_variable(var); }); diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs index c0e4a1bdf07a4..493f25f4992d1 100644 --- a/compiler/rustc_resolve/src/late/lifetimes.rs +++ b/compiler/rustc_resolve/src/late/lifetimes.rs @@ -1971,7 +1971,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { // Therefore, we would compute `object_lifetime_defaults` to a // vector like `['x, 'static]`. Note that the vector only // includes type parameters. - let object_lifetime_defaults = type_def_id.map_or(vec![], |def_id| { + let object_lifetime_defaults = type_def_id.map_or_else(Vec::new, |def_id| { let in_body = { let mut scope = self.scope; loop { diff --git a/compiler/rustc_session/src/filesearch.rs b/compiler/rustc_session/src/filesearch.rs index 47f14fa6b7a74..2df326628e787 100644 --- a/compiler/rustc_session/src/filesearch.rs +++ b/compiler/rustc_session/src/filesearch.rs @@ -169,7 +169,7 @@ pub fn get_or_default_sysroot() -> PathBuf { // Check if sysroot is found using env::args().next(), and if is not found, // use env::current_exe() to imply sysroot. - from_env_args_next().unwrap_or(from_current_exe()) + from_env_args_next().unwrap_or_else(from_current_exe) } // The name of the directory rustc expects libraries to be located. diff --git a/compiler/rustc_session/src/lib.rs b/compiler/rustc_session/src/lib.rs index 36bf8634c6eec..d002f59739166 100644 --- a/compiler/rustc_session/src/lib.rs +++ b/compiler/rustc_session/src/lib.rs @@ -1,7 +1,6 @@ #![feature(crate_visibility_modifier)] #![feature(once_cell)] #![feature(or_patterns)] -#![feature(str_split_once)] #[macro_use] extern crate bitflags; diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index 4b03d38ccba5b..4dce029e86b50 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -22,7 +22,6 @@ #![feature(nll)] #![feature(min_specialization)] #![feature(option_expect_none)] -#![feature(str_split_once)] #[macro_use] extern crate rustc_macros; diff --git a/compiler/rustc_target/src/lib.rs b/compiler/rustc_target/src/lib.rs index 1ad57582ebafb..fb747dfcbd337 100644 --- a/compiler/rustc_target/src/lib.rs +++ b/compiler/rustc_target/src/lib.rs @@ -15,7 +15,6 @@ #![feature(never_type)] #![feature(associated_type_bounds)] #![feature(exhaustive_patterns)] -#![feature(str_split_once)] #[macro_use] extern crate rustc_macros; diff --git a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs index 0133a961c11a7..264cc4f248cec 100644 --- a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs @@ -349,7 +349,7 @@ fn report_negative_positive_conflict( E0751, "found both positive and negative implementation of trait `{}`{}:", overlap.trait_desc, - overlap.self_desc.clone().map_or(String::new(), |ty| format!(" for type `{}`", ty)) + overlap.self_desc.clone().map_or_else(String::new, |ty| format!(" for type `{}`", ty)) ); match tcx.span_of_impl(negative_impl_def_id) { @@ -397,7 +397,10 @@ fn report_conflicting_impls( let msg = format!( "conflicting implementations of trait `{}`{}:{}", overlap.trait_desc, - overlap.self_desc.clone().map_or(String::new(), |ty| { format!(" for type `{}`", ty) }), + overlap + .self_desc + .clone() + .map_or_else(String::new, |ty| { format!(" for type `{}`", ty) }), match used_to_be_allowed { Some(FutureCompatOverlapErrorKind::Issue33140) => " (E0119)", _ => "", @@ -415,7 +418,7 @@ fn report_conflicting_impls( impl_span, format!( "conflicting implementation{}", - overlap.self_desc.map_or(String::new(), |ty| format!(" for `{}`", ty)) + overlap.self_desc.map_or_else(String::new, |ty| format!(" for `{}`", ty)) ), ); } diff --git a/compiler/rustc_typeck/src/check/method/probe.rs b/compiler/rustc_typeck/src/check/method/probe.rs index c25aec5b2b7e9..38ff88553e8d1 100644 --- a/compiler/rustc_typeck/src/check/method/probe.rs +++ b/compiler/rustc_typeck/src/check/method/probe.rs @@ -1716,7 +1716,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { } else { self.fcx .associated_item(def_id, name, Namespace::ValueNS) - .map_or(Vec::new(), |x| vec![x]) + .map_or_else(Vec::new, |x| vec![x]) } } else { self.tcx.associated_items(def_id).in_definition_order().copied().collect() diff --git a/compiler/rustc_typeck/src/check/mod.rs b/compiler/rustc_typeck/src/check/mod.rs index fce7ae8119e17..bb85336d7fb2d 100644 --- a/compiler/rustc_typeck/src/check/mod.rs +++ b/compiler/rustc_typeck/src/check/mod.rs @@ -1062,7 +1062,10 @@ fn report_unexpected_variant_res(tcx: TyCtxt<'_>, res: Res, span: Span) { E0533, "expected unit struct, unit variant or constant, found {}{}", res.descr(), - tcx.sess.source_map().span_to_snippet(span).map_or(String::new(), |s| format!(" `{}`", s)), + tcx.sess + .source_map() + .span_to_snippet(span) + .map_or_else(|_| String::new(), |s| format!(" `{}`", s)), ) .emit(); } diff --git a/compiler/rustc_typeck/src/check/pat.rs b/compiler/rustc_typeck/src/check/pat.rs index 897b1f01569f4..f8ca916caf127 100644 --- a/compiler/rustc_typeck/src/check/pat.rs +++ b/compiler/rustc_typeck/src/check/pat.rs @@ -879,7 +879,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let sm = tcx.sess.source_map(); let path_str = sm .span_to_snippet(sm.span_until_char(pat.span, '(')) - .map_or(String::new(), |s| format!(" `{}`", s.trim_end())); + .map_or_else(|_| String::new(), |s| format!(" `{}`", s.trim_end())); let msg = format!( "expected tuple struct or tuple variant, found {}{}", res.descr(), diff --git a/compiler/rustc_typeck/src/check/writeback.rs b/compiler/rustc_typeck/src/check/writeback.rs index 4f78598215077..af82a3bb4f59a 100644 --- a/compiler/rustc_typeck/src/check/writeback.rs +++ b/compiler/rustc_typeck/src/check/writeback.rs @@ -348,9 +348,9 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { let min_list_wb = min_list .iter() .map(|captured_place| { - let locatable = captured_place.info.path_expr_id.unwrap_or( - self.tcx().hir().local_def_id_to_hir_id(closure_def_id.expect_local()), - ); + let locatable = captured_place.info.path_expr_id.unwrap_or_else(|| { + self.tcx().hir().local_def_id_to_hir_id(closure_def_id.expect_local()) + }); self.resolve(captured_place.clone(), &locatable) }) diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index fc8e50b4b65ba..9fbc56f051beb 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -2387,7 +2387,7 @@ fn compute_sig_of_foreign_fn_decl<'tcx>( .sess .source_map() .span_to_snippet(ast_ty.span) - .map_or(String::new(), |s| format!(" `{}`", s)); + .map_or_else(|_| String::new(), |s| format!(" `{}`", s)); tcx.sess .struct_span_err( ast_ty.span, diff --git a/library/alloc/tests/lib.rs b/library/alloc/tests/lib.rs index dd98f806451d8..9c92d96dc7059 100644 --- a/library/alloc/tests/lib.rs +++ b/library/alloc/tests/lib.rs @@ -6,7 +6,6 @@ #![feature(exact_size_is_empty)] #![feature(new_uninit)] #![feature(pattern)] -#![feature(str_split_once)] #![feature(trusted_len)] #![feature(try_reserve)] #![feature(unboxed_closures)] diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs index 6a35378ca7b50..50ccc2a2eaba1 100644 --- a/library/core/src/str/mod.rs +++ b/library/core/src/str/mod.rs @@ -1506,13 +1506,11 @@ impl str { /// # Examples /// /// ``` - /// #![feature(str_split_once)] - /// /// assert_eq!("cfg".split_once('='), None); /// assert_eq!("cfg=foo".split_once('='), Some(("cfg", "foo"))); /// assert_eq!("cfg=foo=bar".split_once('='), Some(("cfg", "foo=bar"))); /// ``` - #[unstable(feature = "str_split_once", reason = "newly added", issue = "74773")] + #[stable(feature = "str_split_once", since = "1.52.0")] #[inline] pub fn split_once<'a, P: Pattern<'a>>(&'a self, delimiter: P) -> Option<(&'a str, &'a str)> { let (start, end) = delimiter.into_searcher(self).next_match()?; @@ -1525,13 +1523,11 @@ impl str { /// # Examples /// /// ``` - /// #![feature(str_split_once)] - /// /// assert_eq!("cfg".rsplit_once('='), None); /// assert_eq!("cfg=foo".rsplit_once('='), Some(("cfg", "foo"))); /// assert_eq!("cfg=foo=bar".rsplit_once('='), Some(("cfg=foo", "bar"))); /// ``` - #[unstable(feature = "str_split_once", reason = "newly added", issue = "74773")] + #[stable(feature = "str_split_once", since = "1.52.0")] #[inline] pub fn rsplit_once<'a, P>(&'a self, delimiter: P) -> Option<(&'a str, &'a str)> where diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 32aca8c83924d..63b65d8b41383 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -314,7 +314,6 @@ #![feature(stdsimd)] #![feature(stmt_expr_attributes)] #![feature(str_internals)] -#![feature(str_split_once)] #![feature(test)] #![feature(thread_local)] #![feature(thread_local_internals)] diff --git a/library/test/src/lib.rs b/library/test/src/lib.rs index f9e65be9b0d40..3415eaa9fb345 100644 --- a/library/test/src/lib.rs +++ b/library/test/src/lib.rs @@ -31,7 +31,6 @@ #![feature(termination_trait_lib)] #![feature(test)] #![feature(total_cmp)] -#![feature(str_split_once)] // Public reexports pub use self::bench::{black_box, Bencher}; diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 7aa34333e175d..a67f91c8a808d 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2129,12 +2129,12 @@ fn clean_extern_crate( } // FIXME: using `from_def_id_and_kind` breaks `rustdoc/masked` for some reason vec![Item { - name: None, + name: Some(name), attrs: box krate.attrs.clean(cx), source: krate.span.clean(cx), def_id: crate_def_id, visibility: krate.vis.clean(cx), - kind: box ExternCrateItem(name, orig_name), + kind: box ExternCrateItem { src: orig_name }, }] } diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 7fc48cd5f0b38..1efde8d81889c 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -324,7 +324,10 @@ impl Item { #[derive(Clone, Debug)] crate enum ItemKind { - ExternCrateItem(Symbol, Option), + ExternCrateItem { + /// The crate's name, *not* the name it's imported as. + src: Option, + }, ImportItem(Import), StructItem(Struct), UnionItem(Union), @@ -377,7 +380,7 @@ impl ItemKind { TraitItem(t) => t.items.iter(), ImplItem(i) => i.items.iter(), ModuleItem(m) => m.items.iter(), - ExternCrateItem(_, _) + ExternCrateItem { .. } | ImportItem(_) | FunctionItem(_) | TypedefItem(_, _) diff --git a/src/librustdoc/formats/item_type.rs b/src/librustdoc/formats/item_type.rs index 7922a1ffa062e..460d4b907c09a 100644 --- a/src/librustdoc/formats/item_type.rs +++ b/src/librustdoc/formats/item_type.rs @@ -67,7 +67,7 @@ impl<'a> From<&'a clean::Item> for ItemType { match *kind { clean::ModuleItem(..) => ItemType::Module, - clean::ExternCrateItem(..) => ItemType::ExternCrate, + clean::ExternCrateItem { .. } => ItemType::ExternCrate, clean::ImportItem(..) => ItemType::Import, clean::StructItem(..) => ItemType::Struct, clean::UnionItem(..) => ItemType::Union, diff --git a/src/librustdoc/formats/renderer.rs b/src/librustdoc/formats/renderer.rs index 6437ba45511a1..c6d2befc9b7cf 100644 --- a/src/librustdoc/formats/renderer.rs +++ b/src/librustdoc/formats/renderer.rs @@ -102,7 +102,9 @@ crate fn run_format<'tcx, T: FormatRenderer<'tcx>>( } cx.mod_item_out(&name)?; - } else if item.name.is_some() { + // FIXME: checking `item.name.is_some()` is very implicit and leads to lots of special + // cases. Use an explicit match instead. + } else if item.name.is_some() && !item.is_extern_crate() { prof.generic_activity_with_arg("render_item", &*item.name.unwrap_or(unknown).as_str()) .run(|| cx.item(item))?; } diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 6665f160dec8a..673ffc02d7e24 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -883,6 +883,8 @@ themePicker.onblur = handleThemeButtonsBlur; static_files::NORMALIZE_CSS, options.enable_minification, )?; + write(cx.dst.join("FiraSans-Regular.woff2"), static_files::fira_sans::REGULAR2)?; + write(cx.dst.join("FiraSans-Medium.woff2"), static_files::fira_sans::MEDIUM2)?; write(cx.dst.join("FiraSans-Regular.woff"), static_files::fira_sans::REGULAR)?; write(cx.dst.join("FiraSans-Medium.woff"), static_files::fira_sans::MEDIUM)?; write(cx.dst.join("FiraSans-LICENSE.txt"), static_files::fira_sans::LICENSE)?; @@ -2150,7 +2152,7 @@ fn item_module(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item, items: &[cl } match *myitem.kind { - clean::ExternCrateItem(ref name, ref src) => { + clean::ExternCrateItem { ref src } => { use crate::html::format::anchor; match *src { @@ -2159,13 +2161,13 @@ fn item_module(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item, items: &[cl "{}extern crate {} as {};", myitem.visibility.print_with_space(cx.tcx(), myitem.def_id, cx.cache()), anchor(myitem.def_id, &*src.as_str(), cx.cache()), - name + myitem.name.as_ref().unwrap(), ), None => write!( w, "{}extern crate {};", myitem.visibility.print_with_space(cx.tcx(), myitem.def_id, cx.cache()), - anchor(myitem.def_id, &*name.as_str(), cx.cache()) + anchor(myitem.def_id, &*myitem.name.as_ref().unwrap().as_str(), cx.cache()), ), } w.write_str(""); diff --git a/src/librustdoc/html/static/FiraSans-Medium.woff2 b/src/librustdoc/html/static/FiraSans-Medium.woff2 new file mode 100644 index 0000000000000..7a1e5fc548ef2 Binary files /dev/null and b/src/librustdoc/html/static/FiraSans-Medium.woff2 differ diff --git a/src/librustdoc/html/static/FiraSans-Regular.woff2 b/src/librustdoc/html/static/FiraSans-Regular.woff2 new file mode 100644 index 0000000000000..e766e06ccb0d4 Binary files /dev/null and b/src/librustdoc/html/static/FiraSans-Regular.woff2 differ diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css index 56f17b7a616cd..e3d63fa2308e2 100644 --- a/src/librustdoc/html/static/rustdoc.css +++ b/src/librustdoc/html/static/rustdoc.css @@ -3,13 +3,17 @@ font-family: 'Fira Sans'; font-style: normal; font-weight: 400; - src: local('Fira Sans'), url("FiraSans-Regular.woff") format('woff'); + src: local('Fira Sans'), + url("FiraSans-Regular.woff2") format("woff2"), + url("FiraSans-Regular.woff") format('woff'); } @font-face { font-family: 'Fira Sans'; font-style: normal; font-weight: 500; - src: local('Fira Sans Medium'), url("FiraSans-Medium.woff") format('woff'); + src: local('Fira Sans Medium'), + url("FiraSans-Medium.woff2") format("woff2"), + url("FiraSans-Medium.woff") format('woff'); } /* See SourceSerifPro-LICENSE.txt for the Source Serif Pro license. */ diff --git a/src/librustdoc/html/static_files.rs b/src/librustdoc/html/static_files.rs index 132ac42c42283..701e106df67f3 100644 --- a/src/librustdoc/html/static_files.rs +++ b/src/librustdoc/html/static_files.rs @@ -76,9 +76,15 @@ crate mod fira_sans { /// The file `FiraSans-Regular.woff`, the Regular variant of the Fira Sans font. crate static REGULAR: &[u8] = include_bytes!("static/FiraSans-Regular.woff"); + /// The file `FiraSans-Regular.woff2`, the Regular variant of the Fira Sans font in woff2. + crate static REGULAR2: &[u8] = include_bytes!("static/FiraSans-Regular.woff2"); + /// The file `FiraSans-Medium.woff`, the Medium variant of the Fira Sans font. crate static MEDIUM: &[u8] = include_bytes!("static/FiraSans-Medium.woff"); + /// The file `FiraSans-Medium.woff2`, the Medium variant of the Fira Sans font in woff2. + crate static MEDIUM2: &[u8] = include_bytes!("static/FiraSans-Medium.woff2"); + /// The file `FiraSans-LICENSE.txt`, the license text for the Fira Sans font. crate static LICENSE: &[u8] = include_bytes!("static/FiraSans-LICENSE.txt"); } diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index da09d49a0066a..864d133408f81 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -25,32 +25,37 @@ impl JsonRenderer<'_> { let item_type = ItemType::from(&item); let deprecation = item.deprecation(self.tcx); let clean::Item { source, name, attrs, kind, visibility, def_id } = item; - match *kind { - clean::StrippedItem(_) => None, - kind => Some(Item { - id: from_def_id(def_id), - crate_id: def_id.krate.as_u32(), - name: name.map(|sym| sym.to_string()), - source: self.convert_span(source), - visibility: self.convert_visibility(visibility), - docs: attrs.collapsed_doc_value(), - links: attrs - .links - .into_iter() - .filter_map(|clean::ItemLink { link, did, .. }| { - did.map(|did| (link, from_def_id(did))) - }) - .collect(), - attrs: attrs - .other_attrs - .iter() - .map(rustc_ast_pretty::pprust::attribute_to_string) - .collect(), - deprecation: deprecation.map(from_deprecation), - kind: item_type.into(), - inner: from_clean_item_kind(kind, self.tcx), - }), - } + let inner = match *kind { + clean::ItemKind::ExternCrateItem { ref src } => ItemEnum::ExternCrateItem { + name: name.as_ref().unwrap().to_string(), + rename: src.map(|x| x.to_string()), + }, + clean::StrippedItem(_) => return None, + x => from_clean_item_kind(x, self.tcx), + }; + Some(Item { + id: from_def_id(def_id), + crate_id: def_id.krate.as_u32(), + name: name.map(|sym| sym.to_string()), + source: self.convert_span(source), + visibility: self.convert_visibility(visibility), + docs: attrs.collapsed_doc_value(), + links: attrs + .links + .into_iter() + .filter_map(|clean::ItemLink { link, did, .. }| { + did.map(|did| (link, from_def_id(did))) + }) + .collect(), + attrs: attrs + .other_attrs + .iter() + .map(rustc_ast_pretty::pprust::attribute_to_string) + .collect(), + deprecation: deprecation.map(from_deprecation), + kind: item_type.into(), + inner, + }) } fn convert_span(&self, span: clean::Span) -> Option { @@ -153,9 +158,6 @@ fn from_clean_item_kind(item: clean::ItemKind, tcx: TyCtxt<'_>) -> ItemEnum { use clean::ItemKind::*; match item { ModuleItem(m) => ItemEnum::ModuleItem(m.into()), - ExternCrateItem(c, a) => { - ItemEnum::ExternCrateItem { name: c.to_string(), rename: a.map(|x| x.to_string()) } - } ImportItem(i) => ItemEnum::ImportItem(i.into()), StructItem(s) => ItemEnum::StructItem(s.into()), UnionItem(u) => ItemEnum::UnionItem(u.into()), @@ -186,6 +188,7 @@ fn from_clean_item_kind(item: clean::ItemKind, tcx: TyCtxt<'_>) -> ItemEnum { PrimitiveItem(_) | KeywordItem(_) => { panic!("{:?} is not supported for JSON output", item) } + ExternCrateItem { .. } => unreachable!(), } } diff --git a/src/librustdoc/json/mod.rs b/src/librustdoc/json/mod.rs index a3b214677941b..a6b96ab4c021a 100644 --- a/src/librustdoc/json/mod.rs +++ b/src/librustdoc/json/mod.rs @@ -184,7 +184,7 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> { match &*item.kind { // These don't have names so they don't get added to the output by default ImportItem(_) => self.item(item.clone()).unwrap(), - ExternCrateItem(_, _) => self.item(item.clone()).unwrap(), + ExternCrateItem { .. } => self.item(item.clone()).unwrap(), ImplItem(i) => i.items.iter().for_each(|i| self.item(i.clone()).unwrap()), _ => {} } diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index d7978c4a0228d..2342ed3ab670d 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -14,7 +14,6 @@ #![feature(never_type)] #![feature(once_cell)] #![feature(type_ascription)] -#![feature(str_split_once)] #![feature(iter_intersperse)] #![recursion_limit = "256"] #![deny(rustc::internal)] diff --git a/src/librustdoc/passes/calculate_doc_coverage.rs b/src/librustdoc/passes/calculate_doc_coverage.rs index c3365b844ecb8..3739805ef0a5f 100644 --- a/src/librustdoc/passes/calculate_doc_coverage.rs +++ b/src/librustdoc/passes/calculate_doc_coverage.rs @@ -193,7 +193,7 @@ impl<'a, 'b> fold::DocFolder for CoverageCalculator<'a, 'b> { // don't count items in stripped modules return Some(i); } - clean::ImportItem(..) | clean::ExternCrateItem(..) => { + clean::ImportItem(..) | clean::ExternCrateItem { .. } => { // docs on `use` and `extern crate` statements are not displayed, so they're not // worth counting return Some(i); diff --git a/src/librustdoc/passes/doc_test_lints.rs b/src/librustdoc/passes/doc_test_lints.rs index e8e1bead84fb6..a8e5ad28e279e 100644 --- a/src/librustdoc/passes/doc_test_lints.rs +++ b/src/librustdoc/passes/doc_test_lints.rs @@ -60,7 +60,7 @@ crate fn should_have_doc_example(cx: &DocContext<'_>, item: &clean::Item) -> boo | clean::TypedefItem(_, _) | clean::StaticItem(_) | clean::ConstantItem(_) - | clean::ExternCrateItem(_, _) + | clean::ExternCrateItem { .. } | clean::ImportItem(_) | clean::PrimitiveItem(_) | clean::KeywordItem(_) diff --git a/src/librustdoc/passes/stripper.rs b/src/librustdoc/passes/stripper.rs index 162b70973b418..44d54563f27a2 100644 --- a/src/librustdoc/passes/stripper.rs +++ b/src/librustdoc/passes/stripper.rs @@ -66,7 +66,7 @@ impl<'a> DocFolder for Stripper<'a> { } // handled in the `strip-priv-imports` pass - clean::ExternCrateItem(..) | clean::ImportItem(..) => {} + clean::ExternCrateItem { .. } | clean::ImportItem(..) => {} clean::ImplItem(..) => {} @@ -161,7 +161,9 @@ crate struct ImportStripper; impl DocFolder for ImportStripper { fn fold_item(&mut self, i: Item) -> Option { match *i.kind { - clean::ExternCrateItem(..) | clean::ImportItem(..) if !i.visibility.is_public() => None, + clean::ExternCrateItem { .. } | clean::ImportItem(..) if !i.visibility.is_public() => { + None + } _ => Some(self.fold_item_recur(i)), } } diff --git a/src/test/ui/async-await/dont-suggest-missing-await.stderr b/src/test/ui/async-await/dont-suggest-missing-await.stderr index 14e72c2b1e7e2..654a3bcc92dd8 100644 --- a/src/test/ui/async-await/dont-suggest-missing-await.stderr +++ b/src/test/ui/async-await/dont-suggest-missing-await.stderr @@ -2,11 +2,12 @@ error[E0308]: mismatched types --> $DIR/dont-suggest-missing-await.rs:14:18 | LL | async fn make_u32() -> u32 { - | --- the `Output` of this `async fn`'s found opaque type + | --- checked the `Output` of this `async fn`, found opaque type ... LL | take_u32(x) | ^ expected `u32`, found opaque type | + = note: while checking the return type of the `async fn` = note: expected type `u32` found opaque type `impl Future` help: consider `await`ing on the `Future` diff --git a/src/test/ui/async-await/generator-desc.stderr b/src/test/ui/async-await/generator-desc.stderr index b85926c7a03c0..04f191cc5e8cb 100644 --- a/src/test/ui/async-await/generator-desc.stderr +++ b/src/test/ui/async-await/generator-desc.stderr @@ -13,13 +13,15 @@ error[E0308]: mismatched types --> $DIR/generator-desc.rs:12:16 | LL | async fn one() {} - | - the `Output` of this `async fn`'s expected opaque type + | - checked the `Output` of this `async fn`, expected opaque type LL | async fn two() {} - | - the `Output` of this `async fn`'s found opaque type + | - checked the `Output` of this `async fn`, found opaque type ... LL | fun(one(), two()); | ^^^^^ expected opaque type, found a different opaque type | + = note: while checking the return type of the `async fn` + = note: while checking the return type of the `async fn` = note: expected opaque type `impl Future` (opaque type at <$DIR/generator-desc.rs:5:16>) found opaque type `impl Future` (opaque type at <$DIR/generator-desc.rs:6:16>) = help: consider `await`ing on both `Future`s diff --git a/src/test/ui/async-await/issue-61076.rs b/src/test/ui/async-await/issue-61076.rs index 8a7b166cb15bd..4a8e841b33d49 100644 --- a/src/test/ui/async-await/issue-61076.rs +++ b/src/test/ui/async-await/issue-61076.rs @@ -56,7 +56,7 @@ async fn struct_() -> Struct { } async fn tuple() -> Tuple { - //~^ NOTE the `Output` of this `async fn`'s expected opaque type + //~^ NOTE checked the `Output` of this `async fn`, expected opaque type Tuple(1i32) } @@ -92,6 +92,7 @@ async fn match_() { Tuple(_) => {} //~ ERROR mismatched types //~^ NOTE expected opaque type, found struct `Tuple` //~| NOTE expected opaque type `impl Future` + //~| NOTE while checking the return type of the `async fn` } } diff --git a/src/test/ui/async-await/issue-61076.stderr b/src/test/ui/async-await/issue-61076.stderr index db6dc3ea00a8d..fd00522fac703 100644 --- a/src/test/ui/async-await/issue-61076.stderr +++ b/src/test/ui/async-await/issue-61076.stderr @@ -61,11 +61,12 @@ error[E0308]: mismatched types --> $DIR/issue-61076.rs:92:9 | LL | async fn tuple() -> Tuple { - | ----- the `Output` of this `async fn`'s expected opaque type + | ----- checked the `Output` of this `async fn`, expected opaque type ... LL | Tuple(_) => {} | ^^^^^^^^ expected opaque type, found struct `Tuple` | + = note: while checking the return type of the `async fn` = note: expected opaque type `impl Future` found struct `Tuple` help: consider `await`ing on the `Future` diff --git a/src/test/ui/async-await/suggest-missing-await-closure.stderr b/src/test/ui/async-await/suggest-missing-await-closure.stderr index 2151057aa7fc0..483e52536a1b4 100644 --- a/src/test/ui/async-await/suggest-missing-await-closure.stderr +++ b/src/test/ui/async-await/suggest-missing-await-closure.stderr @@ -2,11 +2,12 @@ error[E0308]: mismatched types --> $DIR/suggest-missing-await-closure.rs:16:18 | LL | async fn make_u32() -> u32 { - | --- the `Output` of this `async fn`'s found opaque type + | --- checked the `Output` of this `async fn`, found opaque type ... LL | take_u32(x) | ^ expected `u32`, found opaque type | + = note: while checking the return type of the `async fn` = note: expected type `u32` found opaque type `impl Future` help: consider `await`ing on the `Future` diff --git a/src/test/ui/async-await/suggest-missing-await.stderr b/src/test/ui/async-await/suggest-missing-await.stderr index 26e81a52c2141..14b5ee95ee8ba 100644 --- a/src/test/ui/async-await/suggest-missing-await.stderr +++ b/src/test/ui/async-await/suggest-missing-await.stderr @@ -2,11 +2,12 @@ error[E0308]: mismatched types --> $DIR/suggest-missing-await.rs:12:14 | LL | async fn make_u32() -> u32 { - | --- the `Output` of this `async fn`'s found opaque type + | --- checked the `Output` of this `async fn`, found opaque type ... LL | take_u32(x) | ^ expected `u32`, found opaque type | + = note: while checking the return type of the `async fn` = note: expected type `u32` found opaque type `impl Future` help: consider `await`ing on the `Future` @@ -18,11 +19,12 @@ error[E0308]: mismatched types --> $DIR/suggest-missing-await.rs:22:5 | LL | async fn dummy() {} - | - the `Output` of this `async fn`'s found opaque type + | - checked the `Output` of this `async fn`, found opaque type ... LL | dummy() | ^^^^^^^ expected `()`, found opaque type | + = note: while checking the return type of the `async fn` = note: expected unit type `()` found opaque type `impl Future` help: consider `await`ing on the `Future` diff --git a/src/test/ui/lint/unused_variables-issue-82488.fixed b/src/test/ui/lint/unused_variables-issue-82488.fixed new file mode 100644 index 0000000000000..3cb2c90d0d348 --- /dev/null +++ b/src/test/ui/lint/unused_variables-issue-82488.fixed @@ -0,0 +1,16 @@ +// run-rustfix +#![deny(unused_variables)] + +struct Point { + x: u32, + y: u32 +} + +fn process_point(Point { x, y: _renamed }: Point) { +//~^ ERROR unused variable: `renamed` + let _ = x; +} + +fn main() { + process_point(Point { x: 0, y: 0 }); +} diff --git a/src/test/ui/lint/unused_variables-issue-82488.rs b/src/test/ui/lint/unused_variables-issue-82488.rs new file mode 100644 index 0000000000000..007b0799bbb0d --- /dev/null +++ b/src/test/ui/lint/unused_variables-issue-82488.rs @@ -0,0 +1,16 @@ +// run-rustfix +#![deny(unused_variables)] + +struct Point { + x: u32, + y: u32 +} + +fn process_point(Point { x, y: renamed }: Point) { +//~^ ERROR unused variable: `renamed` + let _ = x; +} + +fn main() { + process_point(Point { x: 0, y: 0 }); +} diff --git a/src/test/ui/lint/unused_variables-issue-82488.stderr b/src/test/ui/lint/unused_variables-issue-82488.stderr new file mode 100644 index 0000000000000..dce03a0f738b3 --- /dev/null +++ b/src/test/ui/lint/unused_variables-issue-82488.stderr @@ -0,0 +1,14 @@ +error: unused variable: `renamed` + --> $DIR/unused_variables-issue-82488.rs:9:32 + | +LL | fn process_point(Point { x, y: renamed }: Point) { + | ^^^^^^^ help: if this is intentional, prefix it with an underscore: `_renamed` + | +note: the lint level is defined here + --> $DIR/unused_variables-issue-82488.rs:2:9 + | +LL | #![deny(unused_variables)] + | ^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/parser/fn-header-semantic-fail.stderr b/src/test/ui/parser/fn-header-semantic-fail.stderr index 4fde243b2f8ec..2e513415e6c64 100644 --- a/src/test/ui/parser/fn-header-semantic-fail.stderr +++ b/src/test/ui/parser/fn-header-semantic-fail.stderr @@ -189,9 +189,10 @@ LL | async fn ft1(); LL | async fn ft1() {} | ^ | | - | the `Output` of this `async fn`'s found opaque type + | checked the `Output` of this `async fn`, found opaque type | expected `()`, found opaque type | + = note: while checking the return type of the `async fn` = note: expected fn pointer `fn()` found fn pointer `fn() -> impl Future` @@ -204,9 +205,10 @@ LL | const async unsafe extern "C" fn ft5(); LL | const async unsafe extern "C" fn ft5() {} | ^ | | - | the `Output` of this `async fn`'s found opaque type + | checked the `Output` of this `async fn`, found opaque type | expected `()`, found opaque type | + = note: while checking the return type of the `async fn` = note: expected fn pointer `unsafe extern "C" fn()` found fn pointer `unsafe extern "C" fn() -> impl Future` diff --git a/src/test/ui/resolve/issue-70736-async-fn-no-body-def-collector.stderr b/src/test/ui/resolve/issue-70736-async-fn-no-body-def-collector.stderr index 9b59e41501102..4025b5030dc0f 100644 --- a/src/test/ui/resolve/issue-70736-async-fn-no-body-def-collector.stderr +++ b/src/test/ui/resolve/issue-70736-async-fn-no-body-def-collector.stderr @@ -53,9 +53,10 @@ LL | async fn associated(); LL | async fn associated(); | ^ | | - | the `Output` of this `async fn`'s found opaque type + | checked the `Output` of this `async fn`, found opaque type | expected `()`, found opaque type | + = note: while checking the return type of the `async fn` = note: expected fn pointer `fn()` found fn pointer `fn() -> impl Future` diff --git a/src/test/ui/suggestions/issue-81839.stderr b/src/test/ui/suggestions/issue-81839.stderr index 1a289d39e4467..f907658708730 100644 --- a/src/test/ui/suggestions/issue-81839.stderr +++ b/src/test/ui/suggestions/issue-81839.stderr @@ -17,8 +17,9 @@ LL | | } ::: $DIR/auxiliary/issue-81839.rs:6:49 | LL | pub async fn answer_str(&self, _s: &str) -> Test { - | ---- the `Output` of this `async fn`'s found opaque type + | ---- checked the `Output` of this `async fn`, found opaque type | + = note: while checking the return type of the `async fn` = note: expected type `()` found opaque type `impl Future` diff --git a/src/test/ui/suggestions/match-prev-arm-needing-semi.rs b/src/test/ui/suggestions/match-prev-arm-needing-semi.rs index b8ac030b0bbbe..3b2cff3140d63 100644 --- a/src/test/ui/suggestions/match-prev-arm-needing-semi.rs +++ b/src/test/ui/suggestions/match-prev-arm-needing-semi.rs @@ -13,9 +13,9 @@ fn extra_semicolon() { }; } -async fn async_dummy() {} //~ NOTE the `Output` of this `async fn`'s found opaque type -async fn async_dummy2() {} //~ NOTE the `Output` of this `async fn`'s found opaque type -//~^ NOTE the `Output` of this `async fn`'s found opaque type +async fn async_dummy() {} //~ NOTE checked the `Output` of this `async fn`, found opaque type +async fn async_dummy2() {} //~ NOTE checked the `Output` of this `async fn`, found opaque type +//~| NOTE checked the `Output` of this `async fn`, found opaque type async fn async_extra_semicolon_same() { let _ = match true { //~ NOTE `match` arms have incompatible types @@ -26,6 +26,7 @@ async fn async_extra_semicolon_same() { false => async_dummy(), //~ ERROR `match` arms have incompatible types //~^ NOTE expected `()`, found opaque type //~| NOTE expected type `()` + //~| NOTE while checking the return type of the `async fn` //~| HELP consider `await`ing on the `Future` }; } @@ -39,6 +40,7 @@ async fn async_extra_semicolon_different() { false => async_dummy2(), //~ ERROR `match` arms have incompatible types //~^ NOTE expected `()`, found opaque type //~| NOTE expected type `()` + //~| NOTE while checking the return type of the `async fn` //~| HELP consider `await`ing on the `Future` }; } @@ -51,6 +53,7 @@ async fn async_different_futures() { //~^ NOTE expected opaque type, found a different opaque type //~| NOTE expected type `impl Future` //~| NOTE distinct uses of `impl Trait` result in different opaque types + //~| NOTE while checking the return type of the `async fn` }; } diff --git a/src/test/ui/suggestions/match-prev-arm-needing-semi.stderr b/src/test/ui/suggestions/match-prev-arm-needing-semi.stderr index fae0c498b440a..e31ea9679b51d 100644 --- a/src/test/ui/suggestions/match-prev-arm-needing-semi.stderr +++ b/src/test/ui/suggestions/match-prev-arm-needing-semi.stderr @@ -2,7 +2,7 @@ error[E0308]: `match` arms have incompatible types --> $DIR/match-prev-arm-needing-semi.rs:26:18 | LL | async fn async_dummy() {} - | - the `Output` of this `async fn`'s found opaque type + | - checked the `Output` of this `async fn`, found opaque type ... LL | let _ = match true { | _____________- @@ -18,6 +18,7 @@ LL | | LL | | }; | |_____- `match` arms have incompatible types | + = note: while checking the return type of the `async fn` = note: expected type `()` found opaque type `impl Future` help: consider `await`ing on the `Future` @@ -30,10 +31,10 @@ LL | async_dummy() | -- error[E0308]: `match` arms have incompatible types - --> $DIR/match-prev-arm-needing-semi.rs:39:18 + --> $DIR/match-prev-arm-needing-semi.rs:40:18 | LL | async fn async_dummy2() {} - | - the `Output` of this `async fn`'s found opaque type + | - checked the `Output` of this `async fn`, found opaque type ... LL | let _ = match true { | _____________- @@ -49,6 +50,7 @@ LL | | LL | | }; | |_____- `match` arms have incompatible types | + = note: while checking the return type of the `async fn` = note: expected type `()` found opaque type `impl Future` help: consider `await`ing on the `Future` @@ -64,10 +66,10 @@ LL | false => Box::new(async_dummy2()), | error[E0308]: `match` arms have incompatible types - --> $DIR/match-prev-arm-needing-semi.rs:50:18 + --> $DIR/match-prev-arm-needing-semi.rs:52:18 | LL | async fn async_dummy2() {} - | - the `Output` of this `async fn`'s found opaque type + | - checked the `Output` of this `async fn`, found opaque type ... LL | let _ = match true { | _____________- @@ -81,6 +83,7 @@ LL | | LL | | }; | |_____- `match` arms have incompatible types | + = note: while checking the return type of the `async fn` = note: expected type `impl Future` (opaque type at <$DIR/match-prev-arm-needing-semi.rs:16:24>) found opaque type `impl Future` (opaque type at <$DIR/match-prev-arm-needing-semi.rs:17:25>) = note: distinct uses of `impl Trait` result in different opaque types diff --git a/src/tools/linkchecker/main.rs b/src/tools/linkchecker/main.rs index 1ab3aead966db..01e067ea0b803 100644 --- a/src/tools/linkchecker/main.rs +++ b/src/tools/linkchecker/main.rs @@ -14,7 +14,7 @@ //! A few exceptions are allowed as there's known bugs in rustdoc, but this //! should catch the majority of "broken link" cases. -#![feature(str_split_once)] +#![cfg_attr(bootstrap, feature(str_split_once))] use std::collections::hash_map::Entry; use std::collections::{HashMap, HashSet}; diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index f127086724fc6..c1395f37aa8eb 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -131,6 +131,7 @@ const PERMITTED_DEPENDENCIES: &[&str] = &[ "parking_lot", "parking_lot_core", "pathdiff", + "perf-event-open-sys", "pkg-config", "polonius-engine", "ppv-lite86", diff --git a/src/tools/tidy/src/lib.rs b/src/tools/tidy/src/lib.rs index 27972c4992442..11d36751f67bb 100644 --- a/src/tools/tidy/src/lib.rs +++ b/src/tools/tidy/src/lib.rs @@ -3,7 +3,7 @@ //! This library contains the tidy lints and exposes it //! to be used by tools. -#![feature(str_split_once)] +#![cfg_attr(bootstrap, feature(str_split_once))] use std::fs::File; use std::io::Read;