about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_typeck/src/collect.rs23
-rw-r--r--src/test/ui/const-generics/const_evaluatable_checked/cross_crate_predicate.rs1
-rw-r--r--src/test/ui/const-generics/const_evaluatable_checked/cross_crate_predicate.stderr20
-rw-r--r--src/test/ui/const-generics/const_evaluatable_checked/from-sig-fail.rs11
-rw-r--r--src/test/ui/const-generics/const_evaluatable_checked/from-sig-fail.stderr9
-rw-r--r--src/test/ui/const-generics/const_evaluatable_checked/from-sig.rs14
6 files changed, 72 insertions, 6 deletions
diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs
index 458622dd65a..d04b5cf588f 100644
--- a/compiler/rustc_typeck/src/collect.rs
+++ b/compiler/rustc_typeck/src/collect.rs
@@ -1678,8 +1678,10 @@ fn predicates_defined_on(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicate
 
     if tcx.features().const_evaluatable_checked {
         let const_evaluatable = const_evaluatable_predicates_of(tcx, def_id, &result);
-        result.predicates =
-            tcx.arena.alloc_from_iter(result.predicates.iter().copied().chain(const_evaluatable));
+        if !const_evaluatable.is_empty() {
+            result.predicates =
+                tcx.arena.alloc_from_iter(result.predicates.iter().copied().chain(const_evaluatable));
+        }
     }
 
     debug!("predicates_defined_on({:?}) = {:?}", def_id, result);
@@ -1690,7 +1692,7 @@ pub fn const_evaluatable_predicates_of<'tcx>(
     tcx: TyCtxt<'tcx>,
     def_id: DefId,
     predicates: &ty::GenericPredicates<'tcx>,
-) -> impl Iterator<Item = (ty::Predicate<'tcx>, Span)> {
+) -> Vec<(ty::Predicate<'tcx>, Span)> {
     #[derive(Default)]
     struct ConstCollector<'tcx> {
         ct: SmallVec<[(ty::WithOptConstParam<DefId>, SubstsRef<'tcx>, Span); 4]>,
@@ -1711,10 +1713,21 @@ pub fn const_evaluatable_predicates_of<'tcx>(
         collector.curr_span = span;
         pred.visit_with(&mut collector);
     }
-    warn!("const_evaluatable_predicates_of({:?}) = {:?}", def_id, collector.ct);
+
+    match tcx.def_kind(def_id) {
+        DefKind::Fn | DefKind::AssocFn => {
+            tcx.fn_sig(def_id).visit_with(&mut collector);
+        }
+        _ => (),
+    }
+    debug!("const_evaluatable_predicates_of({:?}) = {:?}", def_id, collector.ct);
+
+    // We only want unique const evaluatable predicates.
+    collector.ct.sort();
+    collector.ct.dedup();
     collector.ct.into_iter().map(move |(def_id, subst, span)| {
         (ty::PredicateAtom::ConstEvaluatable(def_id, subst).to_predicate(tcx), span)
-    })
+    }).collect()
 }
 
 /// Returns a list of all type predicates (explicit and implicit) for the definition with
diff --git a/src/test/ui/const-generics/const_evaluatable_checked/cross_crate_predicate.rs b/src/test/ui/const-generics/const_evaluatable_checked/cross_crate_predicate.rs
index 22369923329..52b89cfa045 100644
--- a/src/test/ui/const-generics/const_evaluatable_checked/cross_crate_predicate.rs
+++ b/src/test/ui/const-generics/const_evaluatable_checked/cross_crate_predicate.rs
@@ -8,6 +8,7 @@ fn user<T>() {
     //~^ ERROR constant expression depends
     //~| ERROR constant expression depends
     //~| ERROR constant expression depends
+    //~| ERROR constant expression depends
 }
 
 fn main() {}
diff --git a/src/test/ui/const-generics/const_evaluatable_checked/cross_crate_predicate.stderr b/src/test/ui/const-generics/const_evaluatable_checked/cross_crate_predicate.stderr
index 63abb782b93..e8afb495e60 100644
--- a/src/test/ui/const-generics/const_evaluatable_checked/cross_crate_predicate.stderr
+++ b/src/test/ui/const-generics/const_evaluatable_checked/cross_crate_predicate.stderr
@@ -15,6 +15,19 @@ error: constant expression depends on a generic parameter
   --> $DIR/cross_crate_predicate.rs:7:13
    |
 LL |     let _ = const_evaluatable_lib::test1::<T>();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | 
+  ::: $DIR/auxiliary/const_evaluatable_lib.rs:6:41
+   |
+LL |     [u8; std::mem::size_of::<T>() - 1]: Sized,
+   |                                         ----- required by this bound in `test1`
+   |
+   = note: this may fail depending on what value the parameter takes
+
+error: constant expression depends on a generic parameter
+  --> $DIR/cross_crate_predicate.rs:7:13
+   |
+LL |     let _ = const_evaluatable_lib::test1::<T>();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    | 
   ::: $DIR/auxiliary/const_evaluatable_lib.rs:6:41
@@ -29,8 +42,13 @@ error: constant expression depends on a generic parameter
    |
 LL |     let _ = const_evaluatable_lib::test1::<T>();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | 
+  ::: $DIR/auxiliary/const_evaluatable_lib.rs:6:41
+   |
+LL |     [u8; std::mem::size_of::<T>() - 1]: Sized,
+   |                                         ----- required by this bound in `test1::{{constant}}#1`
    |
    = note: this may fail depending on what value the parameter takes
 
-error: aborting due to 3 previous errors
+error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/const-generics/const_evaluatable_checked/from-sig-fail.rs b/src/test/ui/const-generics/const_evaluatable_checked/from-sig-fail.rs
new file mode 100644
index 00000000000..3da4688702c
--- /dev/null
+++ b/src/test/ui/const-generics/const_evaluatable_checked/from-sig-fail.rs
@@ -0,0 +1,11 @@
+#![feature(const_generics, const_evaluatable_checked)]
+#![allow(incomplete_features)]
+
+fn test<const N: usize>() -> [u8; N - 1] {
+    //~^ ERROR evaluation of constant
+    todo!()
+}
+
+fn main() {
+    test::<0>();
+}
diff --git a/src/test/ui/const-generics/const_evaluatable_checked/from-sig-fail.stderr b/src/test/ui/const-generics/const_evaluatable_checked/from-sig-fail.stderr
new file mode 100644
index 00000000000..a5acfec34aa
--- /dev/null
+++ b/src/test/ui/const-generics/const_evaluatable_checked/from-sig-fail.stderr
@@ -0,0 +1,9 @@
+error[E0080]: evaluation of constant value failed
+  --> $DIR/from-sig-fail.rs:4:35
+   |
+LL | fn test<const N: usize>() -> [u8; N - 1] {
+   |                                   ^^^^^ attempt to compute `0_usize - 1_usize` which would overflow
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/const-generics/const_evaluatable_checked/from-sig.rs b/src/test/ui/const-generics/const_evaluatable_checked/from-sig.rs
new file mode 100644
index 00000000000..5c05a5acfe9
--- /dev/null
+++ b/src/test/ui/const-generics/const_evaluatable_checked/from-sig.rs
@@ -0,0 +1,14 @@
+// run-pass
+#![feature(const_generics, const_evaluatable_checked)]
+#![allow(incomplete_features)]
+
+struct Foo<const B: bool>;
+
+fn test<const N: usize>() -> Foo<{ N > 10 }> {
+    Foo
+}
+
+fn main() {
+    let _: Foo<true> = test::<12>();
+    let _: Foo<false> = test::<9>();
+}