Skip to content

Commit

Permalink
look at assoc ct, check the type of nodes
Browse files Browse the repository at this point in the history
  • Loading branch information
lcnr committed Nov 7, 2020
1 parent 0256d06 commit 439171e
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 0 deletions.
17 changes: 17 additions & 0 deletions compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -512,6 +512,13 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
block = &self.body.basic_blocks()[next];
} else {
assert_eq!(self.locals[mir::RETURN_PLACE], self.nodes.last().unwrap());
// `AbstractConst`s should not contain any promoteds as they require references which
// are not allowed.
assert!(!self.nodes.iter().any(|n| matches!(
n.node,
Node::Leaf(ty::Const { val: ty::ConstKind::Unevaluated(_, _, Some(_)), ty: _ })
)));

self.nodes[self.locals[mir::RETURN_PLACE]].used = true;
if let Some(&unused) = self.nodes.iter().find(|n| !n.used) {
self.error(Some(unused.span), "dead code")?;
Expand Down Expand Up @@ -609,6 +616,10 @@ pub(super) fn try_unify<'tcx>(
(Node::Leaf(a_ct), Node::Leaf(b_ct)) => {
let a_ct = a_ct.subst(tcx, a.substs);
let b_ct = b_ct.subst(tcx, b.substs);
if a_ct.ty != b_ct.ty {
return false;
}

match (a_ct.val, b_ct.val) {
// We can just unify errors with everything to reduce the amount of
// emitted errors here.
Expand All @@ -621,6 +632,12 @@ pub(super) fn try_unify<'tcx>(
// we do not want to use `assert_eq!(a(), b())` to infer that `N` and `M` have to be `1`. This
// means that we only allow inference variables if they are equal.
(ty::ConstKind::Infer(a_val), ty::ConstKind::Infer(b_val)) => a_val == b_val,
// We may want to instead recurse into unevaluated constants here. That may require some
// care to prevent infinite recursion, so let's just ignore this for now.
(
ty::ConstKind::Unevaluated(a_def, a_substs, None),
ty::ConstKind::Unevaluated(b_def, b_substs, None),
) => a_def == b_def && a_substs == b_substs,
// FIXME(const_evaluatable_checked): We may want to either actually try
// to evaluate `a_ct` and `b_ct` if they are are fully concrete or something like
// this, for now we just return false here.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// run-pass
#![feature(const_generics, const_evaluatable_checked)]
#![allow(incomplete_features)]

pub trait BlockCipher {
const BLOCK_SIZE: usize;
}

struct FooCipher;
impl BlockCipher for FooCipher {
const BLOCK_SIZE: usize = 64;
}

struct BarCipher;
impl BlockCipher for BarCipher {
const BLOCK_SIZE: usize = 32;
}

pub struct Block<C>(C);

pub fn test<C: BlockCipher, const M: usize>()
where
[u8; M - C::BLOCK_SIZE]: Sized,
{
let _ = [0; M - C::BLOCK_SIZE];
}

fn main() {
test::<FooCipher, 128>();
test::<BarCipher, 64>();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#![feature(const_generics, const_evaluatable_checked)]
#![allow(incomplete_features)]

use std::mem::size_of;
use std::marker::PhantomData;

struct Foo<T>(PhantomData<T>);

fn test<T>() -> [u8; size_of::<T>()] {
[0; size_of::<Foo<T>>()]
//~^ ERROR unconstrained generic constant
}

fn main() {
test::<u32>();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
error: unconstrained generic constant
--> $DIR/different-fn.rs:10:9
|
LL | [0; size_of::<Foo<T>>()]
| ^^^^^^^^^^^^^^^^^^^
|
help: consider adding a `where` bound for this expression
--> $DIR/different-fn.rs:10:9
|
LL | [0; size_of::<Foo<T>>()]
| ^^^^^^^^^^^^^^^^^^^

error: aborting due to previous error

0 comments on commit 439171e

Please sign in to comment.