mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-28 02:57:37 +00:00
Auto merge of #82552 - GuillaumeGomez:rollup-8dn1ztn, r=GuillaumeGomez
Rollup of 8 pull requests Successful merges: - #81940 (Stabilize str_split_once) - #82165 (Reword labels on E0308 involving async fn return type) - #82456 (Replaced some unwrap_or and map_or with lazy variants) - #82491 (Consider inexpensive inlining criteria first) - #82506 (Properly account for non-shorthand pattern field in unused variable lint) - #82535 (Set codegen thread names) - #82545 (rustdoc: add optional woff2 versions of FiraSans.) - #82549 (Revert "Update normalize.css to 8.0.1") Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
9c09c1f7cf
@ -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)]
|
||||
|
@ -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<Symbol> {
|
||||
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
|
||||
}
|
||||
|
@ -481,9 +481,9 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {
|
||||
}
|
||||
|
||||
fn get_parameter_names(cx: &CodegenCx<'_, '_>, generics: &ty::Generics) -> Vec<Symbol> {
|
||||
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
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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("")),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -712,6 +712,33 @@ impl<B: WriteBackendMethods> WorkItem<B> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 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<B: WriteBackendMethods> {
|
||||
@ -1609,56 +1636,59 @@ fn start_executing_work<B: ExtraBackendMethods>(
|
||||
pub struct WorkerFatalError;
|
||||
|
||||
fn spawn_work<B: ExtraBackendMethods>(cgcx: CodegenContext<B>, work: WorkItem<B>) {
|
||||
thread::spawn(move || {
|
||||
// Set up a destructor which will fire off a message that we're done as
|
||||
// we exit.
|
||||
struct Bomb<B: ExtraBackendMethods> {
|
||||
coordinator_send: Sender<Box<dyn Any + Send>>,
|
||||
result: Option<Result<WorkItemResult<B>, FatalError>>,
|
||||
worker_id: usize,
|
||||
}
|
||||
impl<B: ExtraBackendMethods> Drop for Bomb<B> {
|
||||
fn drop(&mut self) {
|
||||
let worker_id = self.worker_id;
|
||||
let msg = match self.result.take() {
|
||||
Some(Ok(WorkItemResult::Compiled(m))) => {
|
||||
Message::Done::<B> { result: Ok(m), worker_id }
|
||||
}
|
||||
Some(Ok(WorkItemResult::NeedsLink(m))) => {
|
||||
Message::NeedsLink::<B> { module: m, worker_id }
|
||||
}
|
||||
Some(Ok(WorkItemResult::NeedsFatLTO(m))) => {
|
||||
Message::NeedsFatLTO::<B> { result: m, worker_id }
|
||||
}
|
||||
Some(Ok(WorkItemResult::NeedsThinLTO(name, thin_buffer))) => {
|
||||
Message::NeedsThinLTO::<B> { name, thin_buffer, worker_id }
|
||||
}
|
||||
Some(Err(FatalError)) => {
|
||||
Message::Done::<B> { result: Err(Some(WorkerFatalError)), worker_id }
|
||||
}
|
||||
None => Message::Done::<B> { 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<B: ExtraBackendMethods> {
|
||||
coordinator_send: Sender<Box<dyn Any + Send>>,
|
||||
result: Option<Result<WorkItemResult<B>, FatalError>>,
|
||||
worker_id: usize,
|
||||
}
|
||||
impl<B: ExtraBackendMethods> Drop for Bomb<B> {
|
||||
fn drop(&mut self) {
|
||||
let worker_id = self.worker_id;
|
||||
let msg = match self.result.take() {
|
||||
Some(Ok(WorkItemResult::Compiled(m))) => {
|
||||
Message::Done::<B> { result: Ok(m), worker_id }
|
||||
}
|
||||
Some(Ok(WorkItemResult::NeedsLink(m))) => {
|
||||
Message::NeedsLink::<B> { module: m, worker_id }
|
||||
}
|
||||
Some(Ok(WorkItemResult::NeedsFatLTO(m))) => {
|
||||
Message::NeedsFatLTO::<B> { result: m, worker_id }
|
||||
}
|
||||
Some(Ok(WorkItemResult::NeedsThinLTO(name, thin_buffer))) => {
|
||||
Message::NeedsThinLTO::<B> { name, thin_buffer, worker_id }
|
||||
}
|
||||
Some(Err(FatalError)) => {
|
||||
Message::Done::<B> { result: Err(Some(WorkerFatalError)), worker_id }
|
||||
}
|
||||
None => Message::Done::<B> { result: Err(None), worker_id },
|
||||
};
|
||||
drop(self.coordinator_send.send(Box::new(msg)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut bomb = Bomb::<B> {
|
||||
coordinator_send: cgcx.coordinator_send.clone(),
|
||||
result: None,
|
||||
worker_id: cgcx.worker,
|
||||
};
|
||||
let mut bomb = Bomb::<B> {
|
||||
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 {
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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)]
|
||||
|
@ -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!(
|
||||
|
@ -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(
|
||||
|
@ -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]
|
||||
|
@ -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<BasicBlock>) {
|
||||
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;
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
if !self.is_mir_available(callsite.callee, caller_body) {
|
||||
debug!("MIR unavailable {}", callsite.callee);
|
||||
continue;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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 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;
|
||||
|
||||
self.history.push(callsite.callee);
|
||||
self.process_blocks(caller_body, new_blocks);
|
||||
self.history.pop();
|
||||
}
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self, caller_body))]
|
||||
fn is_mir_available(&self, callee: Instance<'tcx>, caller_body: &Body<'tcx>) -> bool {
|
||||
/// 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<std::ops::Range<BasicBlock>, &'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");
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
Ok(new_blocks)
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
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<CallSite<'tcx>> {
|
||||
// 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;
|
||||
|
||||
if callsite.fn_sig.c_variadic() {
|
||||
debug!("callee is variadic - not inlining");
|
||||
return false;
|
||||
/// 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");
|
||||
}
|
||||
|
||||
let codegen_fn_attrs = tcx.codegen_fn_attrs(callsite.callee.def_id());
|
||||
|
||||
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 self.codegen_fn_attrs.no_sanitize != codegen_fn_attrs.no_sanitize {
|
||||
debug!("`callee has incompatible no_sanitize attribute - not inlining");
|
||||
return false;
|
||||
}
|
||||
|
||||
if self.codegen_fn_attrs.instruction_set != codegen_fn_attrs.instruction_set {
|
||||
debug!("`callee has incompatible instruction set - not inlining");
|
||||
return false;
|
||||
}
|
||||
|
||||
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;
|
||||
let is_generic = callsite.callee.substs.non_erasable_generics().next().is_some();
|
||||
if !is_generic && !callee_attrs.requests_inline() {
|
||||
return Err("not exported");
|
||||
}
|
||||
}
|
||||
|
||||
let mut threshold = if hinted {
|
||||
if callsite.fn_sig.c_variadic() {
|
||||
return Err("C variadic");
|
||||
}
|
||||
|
||||
if callee_attrs.flags.contains(CodegenFnAttrFlags::NAKED) {
|
||||
return Err("naked");
|
||||
}
|
||||
|
||||
if callee_attrs.flags.contains(CodegenFnAttrFlags::COLD) {
|
||||
return Err("cold");
|
||||
}
|
||||
|
||||
if callee_attrs.no_sanitize != self.codegen_fn_attrs.no_sanitize {
|
||||
return Err("incompatible sanitizer set");
|
||||
}
|
||||
|
||||
if callee_attrs.instruction_set != self.codegen_fn_attrs.instruction_set {
|
||||
return Err("incompatible instruction set");
|
||||
}
|
||||
|
||||
for feature in &callee_attrs.target_features {
|
||||
if !self.codegen_fn_attrs.target_features.contains(feature) {
|
||||
return Err("incompatible target feature");
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
|
@ -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 ");
|
||||
|
@ -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);
|
||||
});
|
||||
|
@ -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 {
|
||||
|
@ -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.
|
||||
|
@ -1,7 +1,6 @@
|
||||
#![feature(crate_visibility_modifier)]
|
||||
#![feature(once_cell)]
|
||||
#![feature(or_patterns)]
|
||||
#![feature(str_split_once)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate bitflags;
|
||||
|
@ -22,7 +22,6 @@
|
||||
#![feature(nll)]
|
||||
#![feature(min_specialization)]
|
||||
#![feature(option_expect_none)]
|
||||
#![feature(str_split_once)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate rustc_macros;
|
||||
|
@ -15,7 +15,6 @@
|
||||
#![feature(never_type)]
|
||||
#![feature(associated_type_bounds)]
|
||||
#![feature(exhaustive_patterns)]
|
||||
#![feature(str_split_once)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate rustc_macros;
|
||||
|
@ -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))
|
||||
),
|
||||
);
|
||||
}
|
||||
|
@ -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()
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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(),
|
||||
|
@ -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)
|
||||
})
|
||||
|
@ -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,
|
||||
|
@ -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)]
|
||||
|
@ -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
|
||||
|
@ -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)]
|
||||
|
@ -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};
|
||||
|
@ -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)?;
|
||||
|
BIN
src/librustdoc/html/static/FiraSans-Medium.woff2
Normal file
BIN
src/librustdoc/html/static/FiraSans-Medium.woff2
Normal file
Binary file not shown.
BIN
src/librustdoc/html/static/FiraSans-Regular.woff2
Normal file
BIN
src/librustdoc/html/static/FiraSans-Regular.woff2
Normal file
Binary file not shown.
2
src/librustdoc/html/static/normalize.css
vendored
2
src/librustdoc/html/static/normalize.css
vendored
@ -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}
|
||||
|
@ -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. */
|
||||
|
@ -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");
|
||||
}
|
||||
|
@ -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)]
|
||||
|
@ -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`
|
||||
|
@ -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
|
||||
|
@ -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`
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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`
|
||||
|
@ -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`
|
||||
|
@ -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`
|
||||
|
16
src/test/ui/lint/unused_variables-issue-82488.fixed
Normal file
16
src/test/ui/lint/unused_variables-issue-82488.fixed
Normal file
@ -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 });
|
||||
}
|
16
src/test/ui/lint/unused_variables-issue-82488.rs
Normal file
16
src/test/ui/lint/unused_variables-issue-82488.rs
Normal file
@ -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 });
|
||||
}
|
14
src/test/ui/lint/unused_variables-issue-82488.stderr
Normal file
14
src/test/ui/lint/unused_variables-issue-82488.stderr
Normal file
@ -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
|
||||
|
@ -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`
|
||||
|
||||
|
@ -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`
|
||||
|
||||
|
@ -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`
|
||||
|
||||
|
@ -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`
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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};
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user