diff --git a/compiler/rustc_infer/src/infer/nll_relate/mod.rs b/compiler/rustc_infer/src/infer/nll_relate/mod.rs index f83219b8ee2a0..a2cfe8d88816c 100644 --- a/compiler/rustc_infer/src/infer/nll_relate/mod.rs +++ b/compiler/rustc_infer/src/infer/nll_relate/mod.rs @@ -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)), + )]); } } diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs index fa87301df7e77..890dabde1f73d 100644 --- a/compiler/rustc_middle/src/ty/relate.rs +++ b/compiler/rustc_middle/src/ty/relate.rs @@ -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. @@ -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()) { diff --git a/tests/ui/const-generics/generic_const_exprs/const_kind_expr/relate_binop_arg_tys.rs b/tests/ui/const-generics/generic_const_exprs/const_kind_expr/relate_binop_arg_tys.rs new file mode 100644 index 0000000000000..fd52fc3554129 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/const_kind_expr/relate_binop_arg_tys.rs @@ -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 fn make_generic(_: usize, a: bool) -> bool { + a +} + +fn foo() -> Bar<{ make_generic(N, true == false) }> { + Bar::<{ make_generic(N, 1_u8 == 0_u8) }> + //~^ error: mismatched types + //~| error: unconstrained generic constant +} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/const_kind_expr/relate_binop_arg_tys.stderr b/tests/ui/const-generics/generic_const_exprs/const_kind_expr/relate_binop_arg_tys.stderr new file mode 100644 index 0000000000000..ba824e84a5aca --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/const_kind_expr/relate_binop_arg_tys.stderr @@ -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`. diff --git a/tests/ui/const-generics/generic_const_exprs/const_kind_expr/relate_cast_arg_ty.rs b/tests/ui/const-generics/generic_const_exprs/const_kind_expr/relate_cast_arg_ty.rs new file mode 100644 index 0000000000000..bef9d4b9e996f --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/const_kind_expr/relate_cast_arg_ty.rs @@ -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() -> [(); (true as usize) + N] { + [(); (1_u8 as usize) + N] + //~^ error: mismatched types + //~| error: unconstrained generic constant +} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/const_kind_expr/relate_cast_arg_ty.stderr b/tests/ui/const-generics/generic_const_exprs/const_kind_expr/relate_cast_arg_ty.stderr new file mode 100644 index 0000000000000..d3ba870a2d7cf --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/const_kind_expr/relate_cast_arg_ty.stderr @@ -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`.