Rollup merge of #94235 - Dirbaio:fix-chalk-opaque-debrujin, r=jackh726
chalk: Fix wrong debrujin index in opaque type handling. A folder in opaque type lowering was substituting all opaque type references with a variable with debrujin index 0 ignoring how many binders deep we are. This caused an ICE with `Not enough bound vars: ^0 not found in []` ([full logs](https://gist.github.com/Dirbaio/2b9374ff4fce37afb9d665dc9f0000df)) with the following code. ```rust fn main() -> () {} async fn foo(x: u32) -> u32 { x } ``` With the fix, it no longer ICEs. It still doesn't typecheck due to generator issues. I've added a "known-bug" test so that at least it doesn't regress back to ICEing. r? ``@jackh726``
This commit is contained in:
commit
d6ca388584
5 changed files with 94 additions and 18 deletions
|
@ -8,7 +8,7 @@
|
||||||
|
|
||||||
use rustc_middle::traits::ChalkRustInterner as RustInterner;
|
use rustc_middle::traits::ChalkRustInterner as RustInterner;
|
||||||
use rustc_middle::ty::subst::{InternalSubsts, Subst, SubstsRef};
|
use rustc_middle::ty::subst::{InternalSubsts, Subst, SubstsRef};
|
||||||
use rustc_middle::ty::{self, AssocItemContainer, AssocKind, TyCtxt, TypeFoldable};
|
use rustc_middle::ty::{self, AssocItemContainer, AssocKind, Ty, TyCtxt, TypeFoldable};
|
||||||
|
|
||||||
use rustc_ast::ast;
|
use rustc_ast::ast;
|
||||||
use rustc_attr as attr;
|
use rustc_attr as attr;
|
||||||
|
@ -482,21 +482,11 @@ impl<'tcx> chalk_solve::RustIrDatabase<RustInterner<'tcx>> for RustIrDatabase<'t
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(bound, _)| bound.subst(self.interner.tcx, &bound_vars))
|
.map(|(bound, _)| bound.subst(self.interner.tcx, &bound_vars))
|
||||||
.map(|bound| {
|
.map(|bound| {
|
||||||
bound.fold_with(&mut ty::fold::BottomUpFolder {
|
bound.fold_with(&mut ReplaceOpaqueTyFolder {
|
||||||
tcx: self.interner.tcx,
|
tcx: self.interner.tcx,
|
||||||
ty_op: |ty| {
|
opaque_ty_id,
|
||||||
if let ty::Opaque(def_id, substs) = *ty.kind() {
|
identity_substs,
|
||||||
if def_id == opaque_ty_id.0 && substs == identity_substs {
|
binder_index: ty::INNERMOST,
|
||||||
return self.interner.tcx.mk_ty(ty::Bound(
|
|
||||||
ty::INNERMOST,
|
|
||||||
ty::BoundTy::from(ty::BoundVar::from_u32(0)),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ty
|
|
||||||
},
|
|
||||||
lt_op: |lt| lt,
|
|
||||||
ct_op: |ct| ct,
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.filter_map(|bound| {
|
.filter_map(|bound| {
|
||||||
|
@ -739,3 +729,38 @@ fn binders_for<'tcx>(
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct ReplaceOpaqueTyFolder<'tcx> {
|
||||||
|
tcx: TyCtxt<'tcx>,
|
||||||
|
opaque_ty_id: chalk_ir::OpaqueTyId<RustInterner<'tcx>>,
|
||||||
|
identity_substs: SubstsRef<'tcx>,
|
||||||
|
binder_index: ty::DebruijnIndex,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> ty::TypeFolder<'tcx> for ReplaceOpaqueTyFolder<'tcx> {
|
||||||
|
fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
|
||||||
|
self.tcx
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fold_binder<T: TypeFoldable<'tcx>>(
|
||||||
|
&mut self,
|
||||||
|
t: ty::Binder<'tcx, T>,
|
||||||
|
) -> ty::Binder<'tcx, T> {
|
||||||
|
self.binder_index.shift_in(1);
|
||||||
|
let t = t.super_fold_with(self);
|
||||||
|
self.binder_index.shift_out(1);
|
||||||
|
t
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
|
||||||
|
if let ty::Opaque(def_id, substs) = *ty.kind() {
|
||||||
|
if def_id == self.opaque_ty_id.0 && substs == self.identity_substs {
|
||||||
|
return self.tcx.mk_ty(ty::Bound(
|
||||||
|
self.binder_index,
|
||||||
|
ty::BoundTy::from(ty::BoundVar::from_u32(0)),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ty
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -323,7 +323,10 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Ty<RustInterner<'tcx>>> for Ty<'tcx> {
|
||||||
ty::Closure(def_id, substs) => {
|
ty::Closure(def_id, substs) => {
|
||||||
chalk_ir::TyKind::Closure(chalk_ir::ClosureId(def_id), substs.lower_into(interner))
|
chalk_ir::TyKind::Closure(chalk_ir::ClosureId(def_id), substs.lower_into(interner))
|
||||||
}
|
}
|
||||||
ty::Generator(_def_id, _substs, _) => unimplemented!(),
|
ty::Generator(def_id, substs, _) => chalk_ir::TyKind::Generator(
|
||||||
|
chalk_ir::GeneratorId(def_id),
|
||||||
|
substs.lower_into(interner),
|
||||||
|
),
|
||||||
ty::GeneratorWitness(_) => unimplemented!(),
|
ty::GeneratorWitness(_) => unimplemented!(),
|
||||||
ty::Never => chalk_ir::TyKind::Never,
|
ty::Never => chalk_ir::TyKind::Never,
|
||||||
ty::Tuple(types) => {
|
ty::Tuple(types) => {
|
||||||
|
|
9
src/test/ui/chalkify/bugs/async.rs
Normal file
9
src/test/ui/chalkify/bugs/async.rs
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
// check-fail
|
||||||
|
// known-bug
|
||||||
|
// compile-flags: -Z chalk --edition=2021
|
||||||
|
|
||||||
|
fn main() -> () {}
|
||||||
|
|
||||||
|
async fn foo(x: u32) -> u32 {
|
||||||
|
x
|
||||||
|
}
|
39
src/test/ui/chalkify/bugs/async.stderr
Normal file
39
src/test/ui/chalkify/bugs/async.stderr
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
error[E0277]: the trait bound `[static generator@$DIR/async.rs:7:29: 9:2]: Generator<ResumeTy>` is not satisfied
|
||||||
|
--> $DIR/async.rs:7:29
|
||||||
|
|
|
||||||
|
LL | async fn foo(x: u32) -> u32 {
|
||||||
|
| _____________________________^
|
||||||
|
LL | | x
|
||||||
|
LL | | }
|
||||||
|
| |_^ the trait `Generator<ResumeTy>` is not implemented for `[static generator@$DIR/async.rs:7:29: 9:2]`
|
||||||
|
|
|
||||||
|
note: required by a bound in `from_generator`
|
||||||
|
--> $SRC_DIR/core/src/future/mod.rs:LL:COL
|
||||||
|
|
|
||||||
|
LL | T: Generator<ResumeTy, Yield = ()>,
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `from_generator`
|
||||||
|
|
||||||
|
error[E0280]: the requirement `<[static generator@$DIR/async.rs:7:29: 9:2] as Generator<ResumeTy>>::Yield == ()` is not satisfied
|
||||||
|
--> $DIR/async.rs:7:29
|
||||||
|
|
|
||||||
|
LL | async fn foo(x: u32) -> u32 {
|
||||||
|
| _____________________________^
|
||||||
|
LL | | x
|
||||||
|
LL | | }
|
||||||
|
| |_^
|
||||||
|
|
|
||||||
|
note: required by a bound in `from_generator`
|
||||||
|
--> $SRC_DIR/core/src/future/mod.rs:LL:COL
|
||||||
|
|
|
||||||
|
LL | T: Generator<ResumeTy, Yield = ()>,
|
||||||
|
| ^^^^^^^^^^ required by this bound in `from_generator`
|
||||||
|
|
||||||
|
error[E0280]: the requirement `<impl Future<Output = [async output]> as Future>::Output == u32` is not satisfied
|
||||||
|
--> $DIR/async.rs:7:25
|
||||||
|
|
|
||||||
|
LL | async fn foo(x: u32) -> u32 {
|
||||||
|
| ^^^
|
||||||
|
|
||||||
|
error: aborting due to 3 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0277`.
|
|
@ -10,8 +10,8 @@ use regex::Regex;
|
||||||
|
|
||||||
// A few of those error codes can't be tested but all the others can and *should* be tested!
|
// A few of those error codes can't be tested but all the others can and *should* be tested!
|
||||||
const EXEMPTED_FROM_TEST: &[&str] = &[
|
const EXEMPTED_FROM_TEST: &[&str] = &[
|
||||||
"E0279", "E0280", "E0313", "E0377", "E0461", "E0462", "E0465", "E0476", "E0514", "E0519",
|
"E0279", "E0313", "E0377", "E0461", "E0462", "E0465", "E0476", "E0514", "E0519", "E0523",
|
||||||
"E0523", "E0554", "E0640", "E0717", "E0729",
|
"E0554", "E0640", "E0717", "E0729",
|
||||||
];
|
];
|
||||||
|
|
||||||
// Some error codes don't have any tests apparently...
|
// Some error codes don't have any tests apparently...
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue