Skip to content

Commit 9ab2a0e

Browse files
authoredMar 19, 2025
Rollup merge of rust-lang#138594 - oli-obk:no-select, r=lcnr
Fix next solver handling of shallow trait impl check I'm trying to remove unnecessary direct calls to `select`, and this one seemed like a good place to start 😆 r? `@compiler-errors` or `@lcnr`
2 parents c3f74bc + 14cd467 commit 9ab2a0e

6 files changed

+86
-22
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.fixed ‎tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.current.fixed

+5-4
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,17 @@
11
//@ run-rustfix
2+
//@ revisions: current next
3+
//@[next] compile-flags: -Znext-solver
24
#![allow(unused_variables, dead_code)]
3-
use std::collections::BTreeMap;
4-
use std::collections::HashSet;
5+
use std::collections::{BTreeMap, HashSet};
56

6-
#[derive(Debug,Eq,PartialEq,Hash)]
7+
#[derive(Debug, Eq, PartialEq, Hash)]
78
#[derive(Clone)]
89
enum Day {
910
Mon,
1011
}
1112

1213
struct Class {
13-
days: BTreeMap<u32, HashSet<Day>>
14+
days: BTreeMap<u32, HashSet<Day>>,
1415
}
1516

1617
impl Class {

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

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0308]: mismatched types
2-
--> $DIR/assignment-of-clone-call-on-ref-due-to-missing-bound.rs:18:39
2+
--> $DIR/assignment-of-clone-call-on-ref-due-to-missing-bound.rs:19:39
33
|
44
LL | let mut x: HashSet<Day> = v.clone();
55
| ------------ ^^^^^^^^^ expected `HashSet<Day>`, found `&HashSet<Day>`
@@ -9,7 +9,7 @@ LL | let mut x: HashSet<Day> = v.clone();
99
= note: expected struct `HashSet<_>`
1010
found reference `&HashSet<_>`
1111
note: `HashSet<Day>` does not implement `Clone`, so `&HashSet<Day>` was cloned instead
12-
--> $DIR/assignment-of-clone-call-on-ref-due-to-missing-bound.rs:18:39
12+
--> $DIR/assignment-of-clone-call-on-ref-due-to-missing-bound.rs:19:39
1313
|
1414
LL | let mut x: HashSet<Day> = v.clone();
1515
| ^
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() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
error[E0308]: mismatched types
2+
--> $DIR/assignment-of-clone-call-on-ref-due-to-missing-bound.rs:19:39
3+
|
4+
LL | let mut x: HashSet<Day> = v.clone();
5+
| ------------ ^^^^^^^^^ expected `HashSet<Day>`, found `&HashSet<Day>`
6+
| |
7+
| expected due to this
8+
|
9+
= note: expected struct `HashSet<_>`
10+
found reference `&HashSet<_>`
11+
note: `HashSet<Day>` does not implement `Clone`, so `&HashSet<Day>` was cloned instead
12+
--> $DIR/assignment-of-clone-call-on-ref-due-to-missing-bound.rs:19:39
13+
|
14+
LL | let mut x: HashSet<Day> = v.clone();
15+
| ^
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+
|
22+
23+
error: aborting due to 1 previous error
24+
25+
For more information about this error, try `rustc --explain E0308`.

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

+5-4
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
11
//@ run-rustfix
2+
//@ revisions: current next
3+
//@[next] compile-flags: -Znext-solver
24
#![allow(unused_variables, dead_code)]
3-
use std::collections::BTreeMap;
4-
use std::collections::HashSet;
5+
use std::collections::{BTreeMap, HashSet};
56

6-
#[derive(Debug,Eq,PartialEq,Hash)]
7+
#[derive(Debug, Eq, PartialEq, Hash)]
78
enum Day {
89
Mon,
910
}
1011

1112
struct Class {
12-
days: BTreeMap<u32, HashSet<Day>>
13+
days: BTreeMap<u32, HashSet<Day>>,
1314
}
1415

1516
impl Class {

0 commit comments

Comments
 (0)