emit ConstEquate
in TypeRelating<D>
This commit is contained in:
parent
50d3ba5bcb
commit
d85d906f8c
6 changed files with 92 additions and 21 deletions
|
@ -817,12 +817,13 @@ impl<'tcx, D> ConstEquateRelation<'tcx> for TypeRelating<'_, 'tcx, D>
|
||||||
where
|
where
|
||||||
D: TypeRelatingDelegate<'tcx>,
|
D: TypeRelatingDelegate<'tcx>,
|
||||||
{
|
{
|
||||||
fn const_equate_obligation(&mut self, _a: ty::Const<'tcx>, _b: ty::Const<'tcx>) {
|
fn const_equate_obligation(&mut self, a: ty::Const<'tcx>, b: ty::Const<'tcx>) {
|
||||||
// We don't have to worry about the equality of consts during borrow checking
|
self.delegate.register_obligations(vec![Obligation::new(
|
||||||
// as consts always have a static lifetime.
|
self.tcx(),
|
||||||
// FIXME(oli-obk): is this really true? We can at least have HKL and with
|
ObligationCause::dummy(),
|
||||||
// inline consts we may have further lifetimes that may be unsound to treat as
|
self.param_env(),
|
||||||
// 'static.
|
ty::Binder::dummy(ty::PredicateKind::ConstEquate(a, b)),
|
||||||
|
)]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -629,6 +629,8 @@ pub fn super_relate_consts<'tcx, R: TypeRelation<'tcx>>(
|
||||||
b = tcx.expand_abstract_consts(b);
|
b = tcx.expand_abstract_consts(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
debug!("{}.super_relate_consts(normed_a = {:?}, normed_b = {:?})", relation.tag(), a, b);
|
||||||
|
|
||||||
// Currently, the values that can be unified are primitive types,
|
// Currently, the values that can be unified are primitive types,
|
||||||
// and those that derive both `PartialEq` and `Eq`, corresponding
|
// and those that derive both `PartialEq` and `Eq`, corresponding
|
||||||
// to structural-match types.
|
// to structural-match types.
|
||||||
|
@ -665,30 +667,28 @@ pub fn super_relate_consts<'tcx, R: TypeRelation<'tcx>>(
|
||||||
|
|
||||||
// FIXME(generic_const_exprs): is it possible to relate two consts which are not identical
|
// FIXME(generic_const_exprs): is it possible to relate two consts which are not identical
|
||||||
// exprs? Should we care about that?
|
// exprs? Should we care about that?
|
||||||
|
// FIXME(generic_const_exprs): relating the `ty()`s is a little weird since it is supposed to
|
||||||
|
// ICE If they mismatch. Unfortunately `ConstKind::Expr` is a little special and can be thought
|
||||||
|
// of as being generic over the argument types, however this is implicit so these types don't get
|
||||||
|
// related when we relate the substs of the item this const arg is for.
|
||||||
let expr = match (ae, be) {
|
let expr = match (ae, be) {
|
||||||
(Expr::Binop(a_op, al, ar), Expr::Binop(b_op, bl, br))
|
(Expr::Binop(a_op, al, ar), Expr::Binop(b_op, bl, br)) if a_op == b_op => {
|
||||||
if a_op == b_op && al.ty() == bl.ty() && ar.ty() == br.ty() =>
|
r.relate(al.ty(), bl.ty())?;
|
||||||
{
|
r.relate(ar.ty(), br.ty())?;
|
||||||
Expr::Binop(a_op, r.consts(al, bl)?, r.consts(ar, br)?)
|
Expr::Binop(a_op, r.consts(al, bl)?, r.consts(ar, br)?)
|
||||||
}
|
}
|
||||||
(Expr::UnOp(a_op, av), Expr::UnOp(b_op, bv))
|
(Expr::UnOp(a_op, av), Expr::UnOp(b_op, bv)) if a_op == b_op => {
|
||||||
if a_op == b_op && av.ty() == bv.ty() =>
|
r.relate(av.ty(), bv.ty())?;
|
||||||
{
|
|
||||||
Expr::UnOp(a_op, r.consts(av, bv)?)
|
Expr::UnOp(a_op, r.consts(av, bv)?)
|
||||||
}
|
}
|
||||||
(Expr::Cast(ak, av, at), Expr::Cast(bk, bv, bt))
|
(Expr::Cast(ak, av, at), Expr::Cast(bk, bv, bt)) if ak == bk => {
|
||||||
if ak == bk && av.ty() == bv.ty() =>
|
r.relate(av.ty(), bv.ty())?;
|
||||||
{
|
|
||||||
Expr::Cast(ak, r.consts(av, bv)?, r.tys(at, bt)?)
|
Expr::Cast(ak, r.consts(av, bv)?, r.tys(at, bt)?)
|
||||||
}
|
}
|
||||||
(Expr::FunctionCall(af, aa), Expr::FunctionCall(bf, ba))
|
(Expr::FunctionCall(af, aa), Expr::FunctionCall(bf, ba))
|
||||||
if aa.len() == ba.len()
|
if aa.len() == ba.len() =>
|
||||||
&& af.ty() == bf.ty()
|
|
||||||
&& aa
|
|
||||||
.iter()
|
|
||||||
.zip(ba.iter())
|
|
||||||
.all(|(a_arg, b_arg)| a_arg.ty() == b_arg.ty()) =>
|
|
||||||
{
|
{
|
||||||
|
r.relate(af.ty(), bf.ty())?;
|
||||||
let func = r.consts(af, bf)?;
|
let func = r.consts(af, bf)?;
|
||||||
let mut related_args = Vec::with_capacity(aa.len());
|
let mut related_args = Vec::with_capacity(aa.len());
|
||||||
for (a_arg, b_arg) in aa.iter().zip(ba.iter()) {
|
for (a_arg, b_arg) in aa.iter().zip(ba.iter()) {
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
// checks that when we relate a `Expr::Binop` we also relate the types of the
|
||||||
|
// const arguments.
|
||||||
|
#![feature(generic_const_exprs)]
|
||||||
|
#![allow(incomplete_features)]
|
||||||
|
|
||||||
|
struct Bar<const B: bool>;
|
||||||
|
|
||||||
|
const fn make_generic(_: usize, a: bool) -> bool {
|
||||||
|
a
|
||||||
|
}
|
||||||
|
|
||||||
|
fn foo<const N: usize>() -> Bar<{ make_generic(N, true == false) }> {
|
||||||
|
Bar::<{ make_generic(N, 1_u8 == 0_u8) }>
|
||||||
|
//~^ error: mismatched types
|
||||||
|
//~| error: unconstrained generic constant
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
|
@ -0,0 +1,20 @@
|
||||||
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/relate_binop_arg_tys.rs:13:5
|
||||||
|
|
|
||||||
|
LL | Bar::<{ make_generic(N, 1_u8 == 0_u8) }>
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `{ make_generic(N, true == false) }`, found `{ make_generic(N, 1_u8 == 0_u8) }`
|
||||||
|
|
|
||||||
|
= note: expected constant `{ make_generic(N, true == false) }`
|
||||||
|
found constant `{ make_generic(N, 1_u8 == 0_u8) }`
|
||||||
|
|
||||||
|
error: unconstrained generic constant
|
||||||
|
--> $DIR/relate_binop_arg_tys.rs:13:11
|
||||||
|
|
|
||||||
|
LL | Bar::<{ make_generic(N, 1_u8 == 0_u8) }>
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= help: try adding a `where` bound using this expression: `where [(); { make_generic(N, 1_u8 == 0_u8) }]:`
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0308`.
|
|
@ -0,0 +1,12 @@
|
||||||
|
// checks that when we relate a `Expr::Cast` we also relate the type of the
|
||||||
|
// const argument.
|
||||||
|
#![feature(generic_const_exprs)]
|
||||||
|
#![allow(incomplete_features)]
|
||||||
|
|
||||||
|
fn foo<const N: usize>() -> [(); (true as usize) + N] {
|
||||||
|
[(); (1_u8 as usize) + N]
|
||||||
|
//~^ error: mismatched types
|
||||||
|
//~| error: unconstrained generic constant
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
|
@ -0,0 +1,20 @@
|
||||||
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/relate_cast_arg_ty.rs:7:5
|
||||||
|
|
|
||||||
|
LL | [(); (1_u8 as usize) + N]
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `(true as usize) + N`, found `(1_u8 as usize) + N`
|
||||||
|
|
|
||||||
|
= note: expected constant `(true as usize) + N`
|
||||||
|
found constant `(1_u8 as usize) + N`
|
||||||
|
|
||||||
|
error: unconstrained generic constant
|
||||||
|
--> $DIR/relate_cast_arg_ty.rs:7:10
|
||||||
|
|
|
||||||
|
LL | [(); (1_u8 as usize) + N]
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= help: try adding a `where` bound using this expression: `where [(); (1_u8 as usize) + N]:`
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0308`.
|
Loading…
Add table
Add a link
Reference in a new issue