Auto merge of #108709 - matthiaskrgr:rollup-j2tjbyx, r=matthiaskrgr
Rollup of 8 pull requests Successful merges: - #104549 (add -Zexport-executable-symbols to unstable book) - #108292 (Label opaque type for 'captures lifetime' error message) - #108540 (Add `Atomic*::from_ptr`) - #108634 (Add link to component dashboard) - #108647 (Remove dead pgo.sh file) - #108678 (Use `Option::as_slice` where applicable) - #108681 (Improve comments in `needs_process_obligation`.) - #108688 (Match unmatched backticks in library/) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
70adb4e5b4
50 changed files with 341 additions and 324 deletions
|
@ -426,6 +426,7 @@ impl<O: ForestObligation> ObligationForest<O> {
|
|||
// nodes. Therefore we use a `while` loop.
|
||||
let mut index = 0;
|
||||
while let Some(node) = self.nodes.get_mut(index) {
|
||||
// This test is extremely hot.
|
||||
if node.state.get() != NodeState::Pending
|
||||
|| !processor.needs_process_obligation(&node.obligation)
|
||||
{
|
||||
|
@ -439,6 +440,7 @@ impl<O: ForestObligation> ObligationForest<O> {
|
|||
// out of sync with `nodes`. It's not very common, but it does
|
||||
// happen, and code in `compress` has to allow for it.
|
||||
|
||||
// This code is much less hot.
|
||||
match processor.process_obligation(&mut node.obligation) {
|
||||
ProcessResult::Unchanged => {
|
||||
// No change in state.
|
||||
|
|
|
@ -36,7 +36,6 @@ use rustc_trait_selection::traits::{self, ObligationCauseCode, SelectionContext}
|
|||
|
||||
use std::iter;
|
||||
use std::mem;
|
||||
use std::slice;
|
||||
|
||||
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
pub(in super::super) fn check_casts(&mut self) {
|
||||
|
@ -1507,11 +1506,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
let coerce = if blk.targeted_by_break {
|
||||
CoerceMany::new(coerce_to_ty)
|
||||
} else {
|
||||
let tail_expr: &[&hir::Expr<'_>] = match tail_expr {
|
||||
Some(e) => slice::from_ref(e),
|
||||
None => &[],
|
||||
};
|
||||
CoerceMany::with_coercion_sites(coerce_to_ty, tail_expr)
|
||||
CoerceMany::with_coercion_sites(coerce_to_ty, blk.expr.as_slice())
|
||||
};
|
||||
|
||||
let prev_diverges = self.diverges.get();
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#![feature(min_specialization)]
|
||||
#![feature(control_flow_enum)]
|
||||
#![feature(drain_filter)]
|
||||
#![feature(option_as_slice)]
|
||||
#![allow(rustc::potential_query_instability)]
|
||||
#![recursion_limit = "256"]
|
||||
|
||||
|
|
|
@ -749,14 +749,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
}
|
||||
|
||||
let opname = Ident::with_dummy_span(opname);
|
||||
let input_types =
|
||||
opt_rhs.as_ref().map(|(_, ty)| std::slice::from_ref(ty)).unwrap_or_default();
|
||||
let (opt_rhs_expr, opt_rhs_ty) = opt_rhs.unzip();
|
||||
let input_types = opt_rhs_ty.as_slice();
|
||||
let cause = self.cause(
|
||||
span,
|
||||
traits::BinOp {
|
||||
rhs_span: opt_rhs.map(|(expr, _)| expr.span),
|
||||
is_lit: opt_rhs
|
||||
.map_or(false, |(expr, _)| matches!(expr.kind, hir::ExprKind::Lit(_))),
|
||||
rhs_span: opt_rhs_expr.map(|expr| expr.span),
|
||||
is_lit: opt_rhs_expr
|
||||
.map_or(false, |expr| matches!(expr.kind, hir::ExprKind::Lit(_))),
|
||||
output_ty: expected.only_has_type(self),
|
||||
},
|
||||
);
|
||||
|
|
|
@ -11,7 +11,6 @@ use rustc_middle::ty::adjustment::{AllowTwoPhase, AutoBorrow, AutoBorrowMutabili
|
|||
use rustc_middle::ty::{self, Ty};
|
||||
use rustc_span::symbol::{sym, Ident};
|
||||
use rustc_span::Span;
|
||||
use std::slice;
|
||||
|
||||
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
/// Type-check `*oprnd_expr` with `oprnd_expr` type-checked already.
|
||||
|
@ -393,11 +392,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
Some(self.typeck_results.borrow().node_substs(expr.hir_id).type_at(1))
|
||||
}
|
||||
};
|
||||
let arg_tys = match arg_ty {
|
||||
None => &[],
|
||||
Some(ref ty) => slice::from_ref(ty),
|
||||
};
|
||||
|
||||
let arg_tys = arg_ty.as_slice();
|
||||
let method = self.try_mutable_overloaded_place_op(expr.span, base_ty, arg_tys, op);
|
||||
let method = match method {
|
||||
Some(ok) => self.register_infer_ok_obligations(ok),
|
||||
|
|
|
@ -345,3 +345,6 @@ infer_prlf_defined_without_sub = the lifetime defined here...
|
|||
infer_prlf_must_oultive_with_sup = ...must outlive the lifetime `{$sup_symbol}` defined here
|
||||
infer_prlf_must_oultive_without_sup = ...must outlive the lifetime defined here
|
||||
infer_prlf_known_limitation = this is a known limitation that will be removed in the future (see issue #100013 <https://github.com/rust-lang/rust/issues/100013> for more information)
|
||||
|
||||
infer_opaque_captures_lifetime = hidden type for `{$opaque_ty}` captures lifetime that does not appear in bounds
|
||||
.label = opaque type defined here
|
||||
|
|
|
@ -1147,3 +1147,13 @@ pub enum PlaceholderRelationLfNotSatisfied {
|
|||
note: (),
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(infer_opaque_captures_lifetime, code = "E0700")]
|
||||
pub struct OpaqueCapturesLifetime<'tcx> {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
#[label]
|
||||
pub opaque_ty_span: Span,
|
||||
pub opaque_ty: Ty<'tcx>,
|
||||
}
|
||||
|
|
|
@ -49,6 +49,7 @@ use super::lexical_region_resolve::RegionResolutionError;
|
|||
use super::region_constraints::GenericKind;
|
||||
use super::{InferCtxt, RegionVariableOrigin, SubregionOrigin, TypeTrace, ValuePairs};
|
||||
|
||||
use crate::errors;
|
||||
use crate::infer;
|
||||
use crate::infer::error_reporting::nice_region_error::find_anon_type::find_anon_type;
|
||||
use crate::infer::ExpectedFound;
|
||||
|
@ -281,15 +282,13 @@ pub fn unexpected_hidden_region_diagnostic<'tcx>(
|
|||
span: Span,
|
||||
hidden_ty: Ty<'tcx>,
|
||||
hidden_region: ty::Region<'tcx>,
|
||||
opaque_ty: ty::OpaqueTypeKey<'tcx>,
|
||||
opaque_ty_key: ty::OpaqueTypeKey<'tcx>,
|
||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
||||
let opaque_ty = tcx.mk_opaque(opaque_ty.def_id.to_def_id(), opaque_ty.substs);
|
||||
let mut err = struct_span_err!(
|
||||
tcx.sess,
|
||||
let mut err = tcx.sess.create_err(errors::OpaqueCapturesLifetime {
|
||||
span,
|
||||
E0700,
|
||||
"hidden type for `{opaque_ty}` captures lifetime that does not appear in bounds",
|
||||
);
|
||||
opaque_ty: tcx.mk_opaque(opaque_ty_key.def_id.to_def_id(), opaque_ty_key.substs),
|
||||
opaque_ty_span: tcx.def_span(opaque_ty_key.def_id),
|
||||
});
|
||||
|
||||
// Explain the region we are capturing.
|
||||
match *hidden_region {
|
||||
|
|
|
@ -212,36 +212,44 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
|
|||
|
||||
/// Identifies whether a predicate obligation needs processing.
|
||||
///
|
||||
/// This is always inlined, despite its size, because it has a single
|
||||
/// callsite and it is called *very* frequently.
|
||||
/// This is always inlined because it has a single callsite and it is
|
||||
/// called *very* frequently. Be careful modifying this code! Several
|
||||
/// compile-time benchmarks are very sensitive to even small changes.
|
||||
#[inline(always)]
|
||||
fn needs_process_obligation(&self, pending_obligation: &Self::Obligation) -> bool {
|
||||
// If we were stalled on some unresolved variables, first check whether
|
||||
// any of them have been resolved; if not, don't bother doing more work
|
||||
// yet.
|
||||
match pending_obligation.stalled_on.len() {
|
||||
// Match arms are in order of frequency, which matters because this
|
||||
// code is so hot. 1 and 0 dominate; 2+ is fairly rare.
|
||||
1 => {
|
||||
let infer_var = pending_obligation.stalled_on[0];
|
||||
self.selcx.infcx.ty_or_const_infer_var_changed(infer_var)
|
||||
}
|
||||
0 => {
|
||||
// In this case we haven't changed, but wish to make a change.
|
||||
true
|
||||
}
|
||||
_ => {
|
||||
// This `for` loop was once a call to `all()`, but this lower-level
|
||||
// form was a perf win. See #64545 for details.
|
||||
(|| {
|
||||
for &infer_var in &pending_obligation.stalled_on {
|
||||
if self.selcx.infcx.ty_or_const_infer_var_changed(infer_var) {
|
||||
return true;
|
||||
}
|
||||
let stalled_on = &pending_obligation.stalled_on;
|
||||
match stalled_on.len() {
|
||||
// This case is the hottest most of the time, being hit up to 99%
|
||||
// of the time. `keccak` and `cranelift-codegen-0.82.1` are
|
||||
// benchmarks that particularly stress this path.
|
||||
1 => self.selcx.infcx.ty_or_const_infer_var_changed(stalled_on[0]),
|
||||
|
||||
// In this case we haven't changed, but wish to make a change. Note
|
||||
// that this is a special case, and is not equivalent to the `_`
|
||||
// case below, which would return `false` for an empty `stalled_on`
|
||||
// vector.
|
||||
//
|
||||
// This case is usually hit only 1% of the time or less, though it
|
||||
// reaches 20% in `wasmparser-0.101.0`.
|
||||
0 => true,
|
||||
|
||||
// This case is usually hit only 1% of the time or less, though it
|
||||
// reaches 95% in `mime-0.3.16`, 64% in `wast-54.0.0`, and 12% in
|
||||
// `inflate-0.4.5`.
|
||||
//
|
||||
// The obvious way of writing this, with a call to `any()` and no
|
||||
// closure, is currently slower than this version.
|
||||
_ => (|| {
|
||||
for &infer_var in stalled_on {
|
||||
if self.selcx.infcx.ty_or_const_infer_var_changed(infer_var) {
|
||||
return true;
|
||||
}
|
||||
false
|
||||
})()
|
||||
}
|
||||
}
|
||||
false
|
||||
})(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue