Skip to content

Commit e63c410

Browse files
committed
traits/fulfill: track full Tys instead of InferTys in stalled_on.
1 parent f4c675c commit e63c410

File tree

1 file changed

+40
-32
lines changed

1 file changed

+40
-32
lines changed

src/librustc_trait_selection/traits/fulfill.rs

+40-32
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,10 @@ pub struct FulfillmentContext<'tcx> {
7373
#[derive(Clone, Debug)]
7474
pub struct PendingPredicateObligation<'tcx> {
7575
pub obligation: PredicateObligation<'tcx>,
76-
pub stalled_on: Vec<ty::InferTy>,
76+
// FIXME(eddyb) look into whether this could be a `SmallVec`.
77+
// Judging by the comment in `process_obligation`, the 1-element
78+
// case is common so this could be a `SmallVec<[_; 1]>`.
79+
pub stalled_on: Vec<Ty<'tcx>>,
7780
}
7881

7982
// `PendingPredicateObligation` is used a lot. Make sure it doesn't unintentionally get bigger.
@@ -266,8 +269,13 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> {
266269
// Match arms are in order of frequency, which matters because this
267270
// code is so hot. 1 and 0 dominate; 2+ is fairly rare.
268271
1 => {
269-
let infer = pending_obligation.stalled_on[0];
270-
ShallowResolver::new(self.selcx.infcx()).shallow_resolve_changed(infer)
272+
let unresolved = pending_obligation.stalled_on[0];
273+
match unresolved.kind {
274+
ty::Infer(infer) => {
275+
ShallowResolver::new(self.selcx.infcx()).shallow_resolve_changed(infer)
276+
}
277+
_ => unreachable!(),
278+
}
271279
}
272280
0 => {
273281
// In this case we haven't changed, but wish to make a change.
@@ -277,9 +285,16 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> {
277285
// This `for` loop was once a call to `all()`, but this lower-level
278286
// form was a perf win. See #64545 for details.
279287
(|| {
280-
for &infer in &pending_obligation.stalled_on {
281-
if ShallowResolver::new(self.selcx.infcx()).shallow_resolve_changed(infer) {
282-
return true;
288+
for &unresolved in &pending_obligation.stalled_on {
289+
match unresolved.kind {
290+
ty::Infer(infer) => {
291+
if ShallowResolver::new(self.selcx.infcx())
292+
.shallow_resolve_changed(infer)
293+
{
294+
return true;
295+
}
296+
}
297+
_ => unreachable!(),
283298
}
284299
}
285300
false
@@ -309,13 +324,6 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> {
309324

310325
debug!("process_obligation: obligation = {:?} cause = {:?}", obligation, obligation.cause);
311326

312-
fn infer_ty(ty: Ty<'tcx>) -> ty::InferTy {
313-
match ty.kind {
314-
ty::Infer(infer) => infer,
315-
_ => panic!(),
316-
}
317-
}
318-
319327
match obligation.predicate {
320328
ty::Predicate::Trait(ref data, _) => {
321329
let trait_obligation = obligation.with(data.clone());
@@ -351,7 +359,7 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> {
351359
// trait selection is because we don't have enough
352360
// information about the types in the trait.
353361
pending_obligation.stalled_on =
354-
trait_ref_type_vars(self.selcx, data.to_poly_trait_ref());
362+
trait_ref_infer_vars(self.selcx, data.to_poly_trait_ref());
355363

356364
debug!(
357365
"process_predicate: pending obligation {:?} now stalled on {:?}",
@@ -429,7 +437,7 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> {
429437
Ok(None) => {
430438
let tcx = self.selcx.tcx();
431439
pending_obligation.stalled_on =
432-
trait_ref_type_vars(self.selcx, data.to_poly_trait_ref(tcx));
440+
trait_ref_infer_vars(self.selcx, data.to_poly_trait_ref(tcx));
433441
ProcessResult::Unchanged
434442
}
435443
Ok(Some(os)) => ProcessResult::Changed(mk_pending(os)),
@@ -467,7 +475,8 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> {
467475
obligation.cause.span,
468476
) {
469477
None => {
470-
pending_obligation.stalled_on = vec![infer_ty(ty)];
478+
assert!(matches!(ty.kind, ty::Infer(_)));
479+
pending_obligation.stalled_on = vec![ty];
471480
ProcessResult::Unchanged
472481
}
473482
Some(os) => ProcessResult::Changed(mk_pending(os)),
@@ -482,10 +491,10 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> {
482491
) {
483492
None => {
484493
// None means that both are unresolved.
485-
pending_obligation.stalled_on = vec![
486-
infer_ty(subtype.skip_binder().a),
487-
infer_ty(subtype.skip_binder().b),
488-
];
494+
assert!(matches!(subtype.skip_binder().a.kind, ty::Infer(_)));
495+
assert!(matches!(subtype.skip_binder().b.kind, ty::Infer(_)));
496+
pending_obligation.stalled_on =
497+
vec![subtype.skip_binder().a, subtype.skip_binder().b];
489498
ProcessResult::Unchanged
490499
}
491500
Some(Ok(ok)) => ProcessResult::Changed(mk_pending(ok.obligations)),
@@ -534,20 +543,19 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> {
534543
}
535544
}
536545

537-
/// Returns the set of type variables contained in a trait ref
538-
fn trait_ref_type_vars<'a, 'tcx>(
546+
/// Returns the set of inference variables contained in a trait ref.
547+
fn trait_ref_infer_vars<'a, 'tcx>(
539548
selcx: &mut SelectionContext<'a, 'tcx>,
540-
t: ty::PolyTraitRef<'tcx>,
541-
) -> Vec<ty::InferTy> {
542-
t.skip_binder() // ok b/c this check doesn't care about regions
549+
ty: ty::PolyTraitRef<'tcx>,
550+
) -> Vec<Ty<'tcx>> {
551+
ty.skip_binder() // ok b/c this check doesn't care about regions
543552
.input_types()
544-
.map(|t| selcx.infcx().resolve_vars_if_possible(&t))
545-
.filter(|t| t.has_infer_types())
546-
.flat_map(|t| t.walk())
547-
.filter_map(|t| match t.kind {
548-
ty::Infer(infer) => Some(infer),
549-
_ => None,
550-
})
553+
.map(|ty| selcx.infcx().resolve_vars_if_possible(&ty))
554+
// FIXME(eddyb) try using `maybe_walk` to skip *all* subtrees that
555+
// don't contain inference variables, not just the outermost level.
556+
.filter(|ty| ty.has_infer_types())
557+
.flat_map(|ty| ty.walk())
558+
.filter(|ty| matches!(ty.kind, ty::Infer(_)))
551559
.collect()
552560
}
553561

0 commit comments

Comments
 (0)