Skip to content

Commit 4a4fc3b

Browse files
Implement support for GeneratorWitnessMIR in new solver
1 parent 2fb0e8d commit 4a4fc3b

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)