Fix next solver handling of shallow trait impl check · rust-lang/rust@14cd467 (original) (raw)
`@@ -15,7 +15,7 @@ use tracing::instrument;
`
15
15
``
16
16
`use crate::infer::at::ToTrace;
`
17
17
`use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
`
18
``
`-
use crate::traits::{self, Obligation, ObligationCause, ObligationCtxt, SelectionContext};
`
``
18
`+
use crate::traits::{self, Obligation, ObligationCause, ObligationCtxt};
`
19
19
``
20
20
`#[extension(pub trait InferCtxtExt<'tcx>)]
`
21
21
`impl<'tcx> InferCtxt<'tcx> {
`
`@@ -122,30 +122,36 @@ impl<'tcx> InferCtxt<'tcx> {
`
122
122
`` /// - If this returns Some([errors..])
, then the trait has an impl for
``
123
123
`/// the self type, but some nested obligations do not hold.
`
124
124
`` /// - If this returns None
, no implementation that applies could be found.
``
125
``
`-
///
`
126
``
`-
/// FIXME(-Znext-solver): Due to the recursive nature of the new solver,
`
127
``
`` -
/// this will probably only ever return Some([])
or None
.
``
128
125
`fn type_implements_trait_shallow(
`
129
126
`&self,
`
130
127
`trait_def_id: DefId,
`
131
128
`ty: Ty<'tcx>,
`
132
129
`param_env: ty::ParamEnv<'tcx>,
`
133
130
`) -> Option<Vec<traits::FulfillmentError<'tcx>>> {
`
134
131
`self.probe(|_snapshot| {
`
135
``
`-
let mut selcx = SelectionContext::new(self);
`
136
``
`-
match selcx.select(&Obligation::new(
`
``
132
`+
let ocx = ObligationCtxt::new_with_diagnostics(self);
`
``
133
`+
ocx.register_obligation(Obligation::new(
`
137
134
`self.tcx,
`
138
135
`ObligationCause::dummy(),
`
139
136
` param_env,
`
140
137
` ty::TraitRef::new(self.tcx, trait_def_id, [ty]),
`
141
``
`-
)) {
`
142
``
`-
Ok(Some(selection)) => {
`
143
``
`-
let ocx = ObligationCtxt::new_with_diagnostics(self);
`
144
``
`-
ocx.register_obligations(selection.nested_obligations());
`
145
``
`-
Some(ocx.select_all_or_error())
`
``
138
`+
));
`
``
139
`+
let errors = ocx.select_where_possible();
`
``
140
`+
// Find the original predicate in the list of predicates that could definitely not be fulfilled.
`
``
141
`+
// If it is in that list, then we know this doesn't even shallowly implement the trait.
`
``
142
`+
// If it is not in that list, it was fulfilled, but there may be nested obligations, which we don't care about here.
`
``
143
`+
for error in &errors {
`
``
144
`+
let Some(trait_clause) = error.obligation.predicate.as_trait_clause() else {
`
``
145
`+
continue;
`
``
146
`+
};
`
``
147
`+
let Some(bound_ty) = trait_clause.self_ty().no_bound_vars() else { continue };
`
``
148
`+
if trait_clause.def_id() == trait_def_id
`
``
149
`+
&& ocx.eq(&ObligationCause::dummy(), param_env, bound_ty, ty).is_ok()
`
``
150
`+
{
`
``
151
`+
return None;
`
146
152
`}
`
147
``
`-
Ok(None) | Err(_) => None,
`
148
153
`}
`
``
154
`+
Some(errors)
`
149
155
`})
`
150
156
`}
`
151
157
`}
`