Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

emit ConstEquate in TypeRelating<D> #107434

Merged
merged 1 commit into from
Feb 5, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 7 additions & 6 deletions compiler/rustc_infer/src/infer/nll_relate/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -817,12 +817,13 @@ impl<'tcx, D> ConstEquateRelation<'tcx> for TypeRelating<'_, 'tcx, D>
where
D: TypeRelatingDelegate<'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
// as consts always have a static lifetime.
// FIXME(oli-obk): is this really true? We can at least have HKL and with
// inline consts we may have further lifetimes that may be unsound to treat as
// 'static.
fn const_equate_obligation(&mut self, a: ty::Const<'tcx>, b: ty::Const<'tcx>) {
self.delegate.register_obligations(vec![Obligation::new(
self.tcx(),
ObligationCause::dummy(),
self.param_env(),
ty::Binder::dummy(ty::PredicateKind::ConstEquate(a, b)),
)]);
}
}

Expand Down
30 changes: 15 additions & 15 deletions compiler/rustc_middle/src/ty/relate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -629,6 +629,8 @@ pub fn super_relate_consts<'tcx, R: TypeRelation<'tcx>>(
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,
// and those that derive both `PartialEq` and `Eq`, corresponding
// to structural-match types.
Expand Down Expand Up @@ -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
// 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) {
(Expr::Binop(a_op, al, ar), Expr::Binop(b_op, bl, br))
if a_op == b_op && al.ty() == bl.ty() && ar.ty() == br.ty() =>
{
(Expr::Binop(a_op, al, ar), Expr::Binop(b_op, bl, br)) if a_op == b_op => {
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::UnOp(a_op, av), Expr::UnOp(b_op, bv))
if a_op == b_op && av.ty() == bv.ty() =>
{
(Expr::UnOp(a_op, av), Expr::UnOp(b_op, bv)) if a_op == b_op => {
r.relate(av.ty(), bv.ty())?;
Expr::UnOp(a_op, r.consts(av, bv)?)
}
(Expr::Cast(ak, av, at), Expr::Cast(bk, bv, bt))
if ak == bk && av.ty() == bv.ty() =>
{
(Expr::Cast(ak, av, at), Expr::Cast(bk, bv, bt)) if ak == bk => {
r.relate(av.ty(), bv.ty())?;
Expr::Cast(ak, r.consts(av, bv)?, r.tys(at, bt)?)
}
(Expr::FunctionCall(af, aa), Expr::FunctionCall(bf, ba))
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()) =>
if aa.len() == ba.len() =>
{
r.relate(af.ty(), bf.ty())?;
let func = r.consts(af, bf)?;
let mut related_args = Vec::with_capacity(aa.len());
for (a_arg, b_arg) in aa.iter().zip(ba.iter()) {
Expand Down
Original file line number Diff line number Diff line change
@@ -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() {}
Original file line number Diff line number Diff line change
@@ -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`.
Original file line number Diff line number Diff line change
@@ -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() {}
Original file line number Diff line number Diff line change
@@ -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`.