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

`}

`