Skip to content

Commit c86c933

Browse files
authored
Rollup merge of #109755 - compiler-errors:new-solver-generator-witness-mir, r=cjgillot
Implement support for `GeneratorWitnessMIR` in new solver r? ```@cjgillot``` I mostly want this to cut down the number of failing UI tests when running the UI test suite with `--compare-mode=next-solver`, but there doesn't seem like much reason to block implementing this since it adds minimal complexity to the existing structural traits impl in the new solver. If others are against adding this for some reason, then maybe we should just make `GeneratorWitnessMIR` return `NoSolution` for these traits. Anything but an ICE please 😸 🧊
2 parents 3e21d68 + 4a4fc3b commit c86c933

File tree

3 files changed

+90
-3
lines changed

3 files changed

+90
-3
lines changed

compiler/rustc_trait_selection/src/solve/trait_goals/structural_traits.rs

+46-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
use rustc_data_structures::fx::FxHashMap;
22
use rustc_hir::{def_id::DefId, Movability, Mutability};
33
use rustc_infer::traits::query::NoSolution;
4-
use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable};
4+
use rustc_middle::ty::{
5+
self, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt,
6+
};
57

68
use crate::solve::EvalCtxt;
79

@@ -60,7 +62,16 @@ pub(super) fn instantiate_constituent_tys_for_auto_trait<'tcx>(
6062

6163
ty::GeneratorWitness(types) => Ok(ecx.instantiate_binder_with_placeholders(types).to_vec()),
6264

63-
ty::GeneratorWitnessMIR(..) => todo!(),
65+
ty::GeneratorWitnessMIR(def_id, substs) => Ok(ecx
66+
.tcx()
67+
.generator_hidden_types(def_id)
68+
.map(|bty| {
69+
ecx.instantiate_binder_with_placeholders(replace_erased_lifetimes_with_bound_vars(
70+
tcx,
71+
bty.subst(tcx, substs),
72+
))
73+
})
74+
.collect()),
6475

6576
// For `PhantomData<T>`, we pass `T`.
6677
ty::Adt(def, substs) if def.is_phantom_data() => Ok(vec![substs.type_at(0)]),
@@ -76,6 +87,29 @@ pub(super) fn instantiate_constituent_tys_for_auto_trait<'tcx>(
7687
}
7788
}
7889

90+
fn replace_erased_lifetimes_with_bound_vars<'tcx>(
91+
tcx: TyCtxt<'tcx>,
92+
ty: Ty<'tcx>,
93+
) -> ty::Binder<'tcx, Ty<'tcx>> {
94+
debug_assert!(!ty.has_late_bound_regions());
95+
let mut counter = 0;
96+
let ty = tcx.fold_regions(ty, |mut r, current_depth| {
97+
if let ty::ReErased = r.kind() {
98+
let br = ty::BoundRegion {
99+
var: ty::BoundVar::from_u32(counter),
100+
kind: ty::BrAnon(counter, None),
101+
};
102+
counter += 1;
103+
r = tcx.mk_re_late_bound(current_depth, br);
104+
}
105+
r
106+
});
107+
let bound_vars = tcx.mk_bound_variable_kinds_from_iter(
108+
(0..counter).map(|i| ty::BoundVariableKind::Region(ty::BrAnon(i, None))),
109+
);
110+
ty::Binder::bind_with_vars(ty, bound_vars)
111+
}
112+
79113
pub(super) fn instantiate_constituent_tys_for_sized_trait<'tcx>(
80114
ecx: &EvalCtxt<'_, 'tcx>,
81115
ty: Ty<'tcx>,
@@ -178,7 +212,16 @@ pub(super) fn instantiate_constituent_tys_for_copy_clone_trait<'tcx>(
178212

179213
ty::GeneratorWitness(types) => Ok(ecx.instantiate_binder_with_placeholders(types).to_vec()),
180214

181-
ty::GeneratorWitnessMIR(..) => todo!(),
215+
ty::GeneratorWitnessMIR(def_id, substs) => Ok(ecx
216+
.tcx()
217+
.generator_hidden_types(def_id)
218+
.map(|bty| {
219+
ecx.instantiate_binder_with_placeholders(replace_erased_lifetimes_with_bound_vars(
220+
ecx.tcx(),
221+
bty.subst(ecx.tcx(), substs),
222+
))
223+
})
224+
.collect()),
182225
}
183226
}
184227

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
error[E0277]: `impl Future<Output = ()>` cannot be sent between threads safely
2+
--> $DIR/auto-with-drop_tracking_mir.rs:24:13
3+
|
4+
LL | is_send(foo());
5+
| ------- ^^^^^ `impl Future<Output = ()>` cannot be sent between threads safely
6+
| |
7+
| required by a bound introduced by this call
8+
|
9+
= help: the trait `Send` is not implemented for `impl Future<Output = ()>`
10+
note: required by a bound in `is_send`
11+
--> $DIR/auto-with-drop_tracking_mir.rs:23:24
12+
|
13+
LL | fn is_send(_: impl Send) {}
14+
| ^^^^ required by this bound in `is_send`
15+
16+
error: aborting due to previous error
17+
18+
For more information about this error, try `rustc --explain E0277`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// compile-flags: -Ztrait-solver=next -Zdrop-tracking-mir
2+
// edition: 2021
3+
// revisions: pass fail
4+
//[pass] check-pass
5+
6+
#![feature(negative_impls)]
7+
8+
struct NotSync;
9+
impl !Sync for NotSync {}
10+
11+
async fn foo() {
12+
#[cfg(pass)]
13+
let x = &();
14+
#[cfg(fail)]
15+
let x = &NotSync;
16+
bar().await;
17+
drop(x);
18+
}
19+
20+
async fn bar() {}
21+
22+
fn main() {
23+
fn is_send(_: impl Send) {}
24+
is_send(foo());
25+
//[fail]~^ ERROR `impl Future<Output = ()>` cannot be sent between threads safely
26+
}

0 commit comments

Comments
 (0)