Auto merge of #67079 - nnethercote:optimize-shallow_resolve_changed, r=nikomatsakis
Optimize `shallow_resolve_changed` r? @nikomatsakis
This commit is contained in:
commit
3eebe058e5
2 changed files with 36 additions and 28 deletions
|
@ -1618,37 +1618,37 @@ impl<'a, 'tcx> ShallowResolver<'a, 'tcx> {
|
||||||
// inlined, despite being large, because it has only two call sites that
|
// inlined, despite being large, because it has only two call sites that
|
||||||
// are extremely hot.
|
// are extremely hot.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn shallow_resolve_changed(&mut self, typ: Ty<'tcx>) -> bool {
|
pub fn shallow_resolve_changed(&self, infer: ty::InferTy) -> bool {
|
||||||
match typ.kind {
|
match infer {
|
||||||
ty::Infer(ty::TyVar(v)) => {
|
ty::TyVar(v) => {
|
||||||
use self::type_variable::TypeVariableValue;
|
use self::type_variable::TypeVariableValue;
|
||||||
|
|
||||||
// See the comment in `shallow_resolve()`.
|
// If `inlined_probe` returns a `Known` value its `kind` never
|
||||||
|
// matches `infer`.
|
||||||
match self.infcx.type_variables.borrow_mut().inlined_probe(v) {
|
match self.infcx.type_variables.borrow_mut().inlined_probe(v) {
|
||||||
TypeVariableValue::Known { value: t } => self.fold_ty(t) != typ,
|
|
||||||
TypeVariableValue::Unknown { .. } => false,
|
TypeVariableValue::Unknown { .. } => false,
|
||||||
|
TypeVariableValue::Known { .. } => true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ty::Infer(ty::IntVar(v)) => {
|
ty::IntVar(v) => {
|
||||||
match self.infcx.int_unification_table.borrow_mut().inlined_probe_value(v) {
|
// If inlined_probe_value returns a value it's always a
|
||||||
Some(v) => v.to_type(self.infcx.tcx) != typ,
|
// `ty::Int(_)` or `ty::UInt(_)`, which nevers matches a
|
||||||
None => false,
|
// `ty::Infer(_)`.
|
||||||
}
|
self.infcx.int_unification_table.borrow_mut().inlined_probe_value(v).is_some()
|
||||||
}
|
}
|
||||||
|
|
||||||
ty::Infer(ty::FloatVar(v)) => {
|
ty::FloatVar(v) => {
|
||||||
|
// If inlined_probe_value returns a value it's always a
|
||||||
|
// `ty::Float(_)`, which nevers matches a `ty::Infer(_)`.
|
||||||
|
//
|
||||||
// Not `inlined_probe_value(v)` because this call site is colder.
|
// Not `inlined_probe_value(v)` because this call site is colder.
|
||||||
match self.infcx.float_unification_table.borrow_mut().probe_value(v) {
|
self.infcx.float_unification_table.borrow_mut().probe_value(v).is_some()
|
||||||
Some(v) => v.to_type(self.infcx.tcx) != typ,
|
|
||||||
None => false,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_ => false,
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx> TypeFolder<'tcx> for ShallowResolver<'a, 'tcx> {
|
impl<'a, 'tcx> TypeFolder<'tcx> for ShallowResolver<'a, 'tcx> {
|
||||||
|
|
|
@ -65,7 +65,7 @@ pub struct FulfillmentContext<'tcx> {
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct PendingPredicateObligation<'tcx> {
|
pub struct PendingPredicateObligation<'tcx> {
|
||||||
pub obligation: PredicateObligation<'tcx>,
|
pub obligation: PredicateObligation<'tcx>,
|
||||||
pub stalled_on: Vec<Ty<'tcx>>,
|
pub stalled_on: Vec<ty::InferTy>,
|
||||||
}
|
}
|
||||||
|
|
||||||
// `PendingPredicateObligation` is used a lot. Make sure it doesn't unintentionally get bigger.
|
// `PendingPredicateObligation` is used a lot. Make sure it doesn't unintentionally get bigger.
|
||||||
|
@ -263,8 +263,8 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> {
|
||||||
// Match arms are in order of frequency, which matters because this
|
// Match arms are in order of frequency, which matters because this
|
||||||
// code is so hot. 1 and 0 dominate; 2+ is fairly rare.
|
// code is so hot. 1 and 0 dominate; 2+ is fairly rare.
|
||||||
1 => {
|
1 => {
|
||||||
let ty = pending_obligation.stalled_on[0];
|
let infer = pending_obligation.stalled_on[0];
|
||||||
ShallowResolver::new(self.selcx.infcx()).shallow_resolve_changed(ty)
|
ShallowResolver::new(self.selcx.infcx()).shallow_resolve_changed(infer)
|
||||||
}
|
}
|
||||||
0 => {
|
0 => {
|
||||||
// In this case we haven't changed, but wish to make a change.
|
// In this case we haven't changed, but wish to make a change.
|
||||||
|
@ -274,8 +274,8 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> {
|
||||||
// This `for` loop was once a call to `all()`, but this lower-level
|
// This `for` loop was once a call to `all()`, but this lower-level
|
||||||
// form was a perf win. See #64545 for details.
|
// form was a perf win. See #64545 for details.
|
||||||
(|| {
|
(|| {
|
||||||
for &ty in &pending_obligation.stalled_on {
|
for &infer in &pending_obligation.stalled_on {
|
||||||
if ShallowResolver::new(self.selcx.infcx()).shallow_resolve_changed(ty) {
|
if ShallowResolver::new(self.selcx.infcx()).shallow_resolve_changed(infer) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -305,6 +305,13 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> {
|
||||||
|
|
||||||
debug!("process_obligation: obligation = {:?} cause = {:?}", obligation, obligation.cause);
|
debug!("process_obligation: obligation = {:?} cause = {:?}", obligation, obligation.cause);
|
||||||
|
|
||||||
|
fn infer_ty(ty: Ty<'tcx>) -> ty::InferTy {
|
||||||
|
match ty.kind {
|
||||||
|
ty::Infer(infer) => infer,
|
||||||
|
_ => panic!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
match obligation.predicate {
|
match obligation.predicate {
|
||||||
ty::Predicate::Trait(ref data) => {
|
ty::Predicate::Trait(ref data) => {
|
||||||
let trait_obligation = obligation.with(data.clone());
|
let trait_obligation = obligation.with(data.clone());
|
||||||
|
@ -459,7 +466,7 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> {
|
||||||
obligation.cause.span,
|
obligation.cause.span,
|
||||||
) {
|
) {
|
||||||
None => {
|
None => {
|
||||||
pending_obligation.stalled_on = vec![ty];
|
pending_obligation.stalled_on = vec![infer_ty(ty)];
|
||||||
ProcessResult::Unchanged
|
ProcessResult::Unchanged
|
||||||
}
|
}
|
||||||
Some(os) => ProcessResult::Changed(mk_pending(os))
|
Some(os) => ProcessResult::Changed(mk_pending(os))
|
||||||
|
@ -472,8 +479,8 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> {
|
||||||
subtype) {
|
subtype) {
|
||||||
None => {
|
None => {
|
||||||
// None means that both are unresolved.
|
// None means that both are unresolved.
|
||||||
pending_obligation.stalled_on = vec![subtype.skip_binder().a,
|
pending_obligation.stalled_on = vec![infer_ty(subtype.skip_binder().a),
|
||||||
subtype.skip_binder().b];
|
infer_ty(subtype.skip_binder().b)];
|
||||||
ProcessResult::Unchanged
|
ProcessResult::Unchanged
|
||||||
}
|
}
|
||||||
Some(Ok(ok)) => {
|
Some(Ok(ok)) => {
|
||||||
|
@ -517,7 +524,8 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> {
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
pending_obligation.stalled_on = substs.types().collect();
|
pending_obligation.stalled_on =
|
||||||
|
substs.types().map(|ty| infer_ty(ty)).collect();
|
||||||
ProcessResult::Unchanged
|
ProcessResult::Unchanged
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -542,13 +550,13 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> {
|
||||||
fn trait_ref_type_vars<'a, 'tcx>(
|
fn trait_ref_type_vars<'a, 'tcx>(
|
||||||
selcx: &mut SelectionContext<'a, 'tcx>,
|
selcx: &mut SelectionContext<'a, 'tcx>,
|
||||||
t: ty::PolyTraitRef<'tcx>,
|
t: ty::PolyTraitRef<'tcx>,
|
||||||
) -> Vec<Ty<'tcx>> {
|
) -> Vec<ty::InferTy> {
|
||||||
t.skip_binder() // ok b/c this check doesn't care about regions
|
t.skip_binder() // ok b/c this check doesn't care about regions
|
||||||
.input_types()
|
.input_types()
|
||||||
.map(|t| selcx.infcx().resolve_vars_if_possible(&t))
|
.map(|t| selcx.infcx().resolve_vars_if_possible(&t))
|
||||||
.filter(|t| t.has_infer_types())
|
.filter(|t| t.has_infer_types())
|
||||||
.flat_map(|t| t.walk())
|
.flat_map(|t| t.walk())
|
||||||
.filter(|t| match t.kind { ty::Infer(_) => true, _ => false })
|
.filter_map(|t| match t.kind { ty::Infer(infer) => Some(infer), _ => None })
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue