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/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_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_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/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 6665f160dec8a..58e9e41e6a53c 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)?; 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/normalize.css b/src/librustdoc/html/static/normalize.css index da9a75e3e85e9..0e0426279183f 100644 --- a/src/librustdoc/html/static/normalize.css +++ b/src/librustdoc/html/static/normalize.css @@ -1,2 +1,2 @@ /* ignore-tidy-linelength */ -/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */html{line-height:1.15;-webkit-text-size-adjust:100%}body{margin:0}main{display:block}h1{font-size:2em;margin:.67em 0}hr{box-sizing:content-box;height:0;overflow:visible}pre{font-family:monospace,monospace;font-size:1em}a{background-color:transparent}abbr[title]{border-bottom:none;text-decoration:underline;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}img{border-style:none}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring,button:-moz-focusring{outline:1px dotted ButtonText}fieldset{padding:.35em .75em .625em}legend{box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{vertical-align:baseline}textarea{overflow:auto}[type=checkbox],[type=radio]{box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}details{display:block}summary{display:list-item}template{display:none}[hidden]{display:none} +/*! normalize.css v3.0.0 | MIT License | git.io/normalize */html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:bold}dfn{font-style:italic}h1{font-size:2em;margin:.67em 0}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0}input[type="number"]::-webkit-inner-spin-button,input[type="number"]::-webkit-outer-spin-button{height:auto}input[type="search"]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:bold}table{border-collapse:collapse;border-spacing:0}td,th{padding:0} 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/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/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/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;