Skip to content

Commit 14cd467

Browse files
committed
Fix next solver handling of shallow trait impl check
1 parent 055d31c commit 14cd467

5 files changed

+57
-14
lines changed

compiler/rustc_trait_selection/src/infer.rs

+18-12
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use tracing::instrument;
1515

1616
use crate::infer::at::ToTrace;
1717
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};
1919

2020
#[extension(pub trait InferCtxtExt<'tcx>)]
2121
impl<'tcx> InferCtxt<'tcx> {
@@ -122,30 +122,36 @@ impl<'tcx> InferCtxt<'tcx> {
122122
/// - If this returns `Some([errors..])`, then the trait has an impl for
123123
/// the self type, but some nested obligations do not hold.
124124
/// - 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`.
128125
fn type_implements_trait_shallow(
129126
&self,
130127
trait_def_id: DefId,
131128
ty: Ty<'tcx>,
132129
param_env: ty::ParamEnv<'tcx>,
133130
) -> Option<Vec<traits::FulfillmentError<'tcx>>> {
134131
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(
137134
self.tcx,
138135
ObligationCause::dummy(),
139136
param_env,
140137
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;
146152
}
147-
Ok(None) | Err(_) => None,
148153
}
154+
Some(errors)
149155
})
150156
}
151157
}

tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.current.fixed

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//@[current] run-rustfix
1+
//@ run-rustfix
22
//@ revisions: current next
33
//@[next] compile-flags: -Znext-solver
44
#![allow(unused_variables, dead_code)]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
//@ run-rustfix
2+
//@ revisions: current next
3+
//@[next] compile-flags: -Znext-solver
4+
#![allow(unused_variables, dead_code)]
5+
use std::collections::{BTreeMap, HashSet};
6+
7+
#[derive(Debug, Eq, PartialEq, Hash)]
8+
#[derive(Clone)]
9+
enum Day {
10+
Mon,
11+
}
12+
13+
struct Class {
14+
days: BTreeMap<u32, HashSet<Day>>,
15+
}
16+
17+
impl Class {
18+
fn do_stuff(&self) {
19+
for (_, v) in &self.days {
20+
let mut x: HashSet<Day> = v.clone(); //~ ERROR
21+
let y: Vec<Day> = x.drain().collect();
22+
println!("{:?}", x);
23+
}
24+
}
25+
}
26+
27+
fn fail() {
28+
let c = Class { days: BTreeMap::new() };
29+
c.do_stuff();
30+
}
31+
fn main() {}

tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.next.stderr

+6
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,12 @@ note: `HashSet<Day>` does not implement `Clone`, so `&HashSet<Day>` was cloned i
1313
|
1414
LL | let mut x: HashSet<Day> = v.clone();
1515
| ^
16+
= help: `Clone` is not implemented because the trait bound `Day: Clone` is not satisfied
17+
help: consider annotating `Day` with `#[derive(Clone)]`
18+
|
19+
LL + #[derive(Clone)]
20+
LL | enum Day {
21+
|
1622

1723
error: aborting due to 1 previous error
1824

tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//@[current] run-rustfix
1+
//@ run-rustfix
22
//@ revisions: current next
33
//@[next] compile-flags: -Znext-solver
44
#![allow(unused_variables, dead_code)]

0 commit comments

Comments
 (0)