Skip to content

Commit e1e3180

Browse files
committed
rustdoc: use the next solver for blanket impl synthesis
1 parent c416a6f commit e1e3180

File tree

1 file changed

+26
-32
lines changed

1 file changed

+26
-32
lines changed

src/librustdoc/clean/blanket_impl.rs

+26-32
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
use rustc_hir as hir;
2-
use rustc_infer::infer::{DefineOpaqueTypes, InferOk, TyCtxtInferExt};
3-
use rustc_infer::traits;
2+
use rustc_infer::infer::TyCtxtInferExt;
3+
use rustc_infer::traits::ObligationCause;
44
use rustc_middle::ty::{self, Upcast};
55
use rustc_span::def_id::DefId;
66
use rustc_span::DUMMY_SP;
7-
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
7+
use rustc_trait_selection::traits;
88
use thin_vec::ThinVec;
99

1010
use crate::clean;
@@ -30,53 +30,47 @@ pub(crate) fn synthesize_blanket_impls(
3030
}
3131
// NOTE: doesn't use `for_each_relevant_impl` to avoid looking at anything besides blanket impls
3232
let trait_impls = tcx.trait_impls_of(trait_def_id);
33-
'blanket_impls: for &impl_def_id in trait_impls.blanket_impls() {
33+
for &impl_def_id in trait_impls.blanket_impls() {
3434
trace!("considering impl `{impl_def_id:?}` for trait `{trait_def_id:?}`");
3535

3636
let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap();
3737
if !matches!(trait_ref.skip_binder().self_ty().kind(), ty::Param(_)) {
3838
continue;
3939
}
40-
let infcx = tcx.infer_ctxt().build();
40+
let infcx = tcx.infer_ctxt().with_next_trait_solver(true).build();
41+
let ocx = traits::ObligationCtxt::new(&infcx);
42+
4143
let args = infcx.fresh_args_for_item(DUMMY_SP, item_def_id);
4244
let impl_ty = ty.instantiate(tcx, args);
4345
let param_env = ty::ParamEnv::empty();
46+
let cause = ObligationCause::dummy();
4447

4548
let impl_args = infcx.fresh_args_for_item(DUMMY_SP, impl_def_id);
4649
let impl_trait_ref = trait_ref.instantiate(tcx, impl_args);
4750

4851
// Require the type the impl is implemented on to match
4952
// our type, and ignore the impl if there was a mismatch.
50-
let Ok(eq_result) = infcx.at(&traits::ObligationCause::dummy(), param_env).eq(
51-
DefineOpaqueTypes::Yes,
52-
impl_trait_ref.self_ty(),
53-
impl_ty,
54-
) else {
53+
if ocx.eq(&cause, param_env, impl_trait_ref.self_ty(), impl_ty).is_err() {
5554
continue;
56-
};
57-
let InferOk { value: (), obligations } = eq_result;
58-
// FIXME(eddyb) ignoring `obligations` might cause false positives.
59-
drop(obligations);
55+
}
6056

61-
let predicates = tcx
62-
.predicates_of(impl_def_id)
63-
.instantiate(tcx, impl_args)
64-
.predicates
65-
.into_iter()
66-
.chain(Some(impl_trait_ref.upcast(tcx)));
67-
for predicate in predicates {
68-
let obligation = traits::Obligation::new(
69-
tcx,
70-
traits::ObligationCause::dummy(),
71-
param_env,
72-
predicate,
73-
);
74-
match infcx.evaluate_obligation(&obligation) {
75-
Ok(eval_result) if eval_result.may_apply() => {}
76-
Err(traits::OverflowError::Canonical) => {}
77-
_ => continue 'blanket_impls,
78-
}
57+
ocx.register_obligations(traits::predicates_for_generics(
58+
|_, _| cause.clone(),
59+
param_env,
60+
tcx.predicates_of(impl_def_id).instantiate(tcx, impl_args),
61+
));
62+
63+
ocx.register_obligation(traits::Obligation {
64+
cause,
65+
recursion_depth: 0,
66+
param_env,
67+
predicate: impl_trait_ref.upcast(tcx),
68+
});
69+
70+
if !ocx.select_where_possible().is_empty() {
71+
continue;
7972
}
73+
8074
debug!("found applicable impl for trait ref {trait_ref:?}");
8175

8276
cx.generated_synthetics.insert((ty.skip_binder(), trait_def_id));

0 commit comments

Comments
 (0)