Skip to content

Commit 6525671

Browse files
committed
Add better diagnostic for missing where clause
Previously, it's not clear what exactly should be added in the suggested where clause, so this adds an example to demonstrate.
1 parent 04caa63 commit 6525671

File tree

7 files changed

+93
-18
lines changed

7 files changed

+93
-18
lines changed

compiler/rustc_trait_selection/src/traits/const_evaluatable.rs

+17-13
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,7 @@ use rustc_infer::infer::InferCtxt;
1616
use rustc_middle::mir::abstract_const::{Node, NodeId};
1717
use rustc_middle::mir::interpret::ErrorHandled;
1818
use rustc_middle::mir::{self, Rvalue, StatementKind, TerminatorKind};
19-
use rustc_middle::ty::subst::Subst;
20-
use rustc_middle::ty::subst::SubstsRef;
19+
use rustc_middle::ty::subst::{Subst, SubstsRef};
2120
use rustc_middle::ty::{self, TyCtxt, TypeFoldable};
2221
use rustc_session::lint;
2322
use rustc_span::def_id::{DefId, LocalDefId};
@@ -43,10 +42,6 @@ pub fn is_const_evaluatable<'cx, 'tcx>(
4342
for pred in param_env.caller_bounds() {
4443
match pred.kind().skip_binder() {
4544
ty::PredicateKind::ConstEvaluatable(b_def, b_substs) => {
46-
debug!(
47-
"is_const_evaluatable: caller_bound={:?}, {:?}",
48-
b_def, b_substs
49-
);
5045
if b_def == def && b_substs == substs {
5146
debug!("is_const_evaluatable: caller_bound ~~> ok");
5247
return Ok(());
@@ -100,15 +95,24 @@ pub fn is_const_evaluatable<'cx, 'tcx>(
10095
}
10196
FailureKind::MentionsParam => {
10297
// FIXME(const_evaluatable_checked): Better error message.
103-
infcx
104-
.tcx
105-
.sess
106-
.struct_span_err(span, "unconstrained generic constant")
107-
.span_help(
98+
let mut err =
99+
infcx.tcx.sess.struct_span_err(span, "unconstrained generic constant");
100+
let const_span = tcx.def_span(def.did);
101+
// FIXME(const_evaluatable_checked): Update this suggestion once
102+
// explicit const evaluatable bounds are implemented.
103+
if let Ok(snippet) = infcx.tcx.sess.source_map().span_to_snippet(const_span)
104+
{
105+
err.span_help(
108106
tcx.def_span(def.did),
107+
&format!("try adding a `where` bound using this expression: where [u8; {}]: Sized", snippet),
108+
);
109+
} else {
110+
err.span_help(
111+
const_span,
109112
"consider adding a `where` bound for this expression",
110-
)
111-
.emit();
113+
);
114+
}
115+
err.emit();
112116
return Err(ErrorHandled::Reported(ErrorReported));
113117
}
114118
FailureKind::Concrete => {

src/test/ui/const-generics/const_evaluatable_checked/cross_crate_predicate.stderr

+4-4
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ error: unconstrained generic constant
44
LL | let _ = const_evaluatable_lib::test1::<T>();
55
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
66
|
7-
help: consider adding a `where` bound for this expression
7+
help: try adding a `where` bound using this expression: where [u8; std::mem::size_of::<T>() - 1]: Sized
88
--> $DIR/auxiliary/const_evaluatable_lib.rs:6:10
99
|
1010
LL | [u8; std::mem::size_of::<T>() - 1]: Sized,
@@ -16,7 +16,7 @@ error: unconstrained generic constant
1616
LL | let _ = const_evaluatable_lib::test1::<T>();
1717
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1818
|
19-
help: consider adding a `where` bound for this expression
19+
help: try adding a `where` bound using this expression: where [u8; std::mem::size_of::<T>() - 1]: Sized
2020
--> $DIR/auxiliary/const_evaluatable_lib.rs:4:27
2121
|
2222
LL | pub fn test1<T>() -> [u8; std::mem::size_of::<T>() - 1]
@@ -28,7 +28,7 @@ error: unconstrained generic constant
2828
LL | let _ = const_evaluatable_lib::test1::<T>();
2929
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
3030
|
31-
help: consider adding a `where` bound for this expression
31+
help: try adding a `where` bound using this expression: where [u8; std::mem::size_of::<T>() - 1]: Sized
3232
--> $DIR/auxiliary/const_evaluatable_lib.rs:6:10
3333
|
3434
LL | [u8; std::mem::size_of::<T>() - 1]: Sized,
@@ -40,7 +40,7 @@ error: unconstrained generic constant
4040
LL | let _ = const_evaluatable_lib::test1::<T>();
4141
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
4242
|
43-
help: consider adding a `where` bound for this expression
43+
help: try adding a `where` bound using this expression: where [u8; std::mem::size_of::<T>() - 1]: Sized
4444
--> $DIR/auxiliary/const_evaluatable_lib.rs:4:27
4545
|
4646
LL | pub fn test1<T>() -> [u8; std::mem::size_of::<T>() - 1]

src/test/ui/const-generics/const_evaluatable_checked/different-fn.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ error: unconstrained generic constant
44
LL | [0; size_of::<Foo<T>>()]
55
| ^^^^^^^^^^^^^^^^^^^
66
|
7-
help: consider adding a `where` bound for this expression
7+
help: try adding a `where` bound using this expression: where [u8; size_of::<Foo<T>>()]: Sized
88
--> $DIR/different-fn.rs:10:9
99
|
1010
LL | [0; size_of::<Foo<T>>()]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#![crate_type = "lib"]
2+
#![feature(const_generics, const_evaluatable_checked)]
3+
#![allow(incomplete_features)]
4+
5+
const fn complex_maths<T>(n : usize) -> usize {
6+
2 * n + 1
7+
}
8+
9+
struct Example<T, const N: usize> {
10+
a: [f32; N],
11+
b: [f32; complex_maths::<T>(N)],
12+
//~^ ERROR unconstrained
13+
c: T,
14+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
error: unconstrained generic constant
2+
--> $DIR/needs_where_clause.rs:11:6
3+
|
4+
LL | b: [f32; complex_maths::<T>(N)],
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6+
|
7+
help: try adding a `where` bound using this expression: where [u8; complex_maths::<T>(N)]: Sized
8+
--> $DIR/needs_where_clause.rs:11:12
9+
|
10+
LL | b: [f32; complex_maths::<T>(N)],
11+
| ^^^^^^^^^^^^^^^^^^^^^
12+
13+
error: aborting due to previous error
14+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
#![feature(const_generics, const_evaluatable_checked)]
2+
#![allow(incomplete_features, unused)]
3+
4+
const fn complex_maths(n : usize) -> usize {
5+
2 * n + 1
6+
}
7+
8+
pub struct Example<const N: usize> {
9+
a: [f32; N],
10+
b: [f32; complex_maths(N)],
11+
//~^ ERROR unconstrained generic
12+
}
13+
14+
impl<const N: usize> Example<N> {
15+
pub fn new() -> Self {
16+
Self {
17+
a: [0.; N],
18+
b: [0.; complex_maths(N)],
19+
}
20+
}
21+
}
22+
23+
impl Example<2> {
24+
pub fn sum(&self) -> f32 {
25+
self.a.iter().sum::<f32>() + self.b.iter().sum::<f32>()
26+
}
27+
}
28+
29+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
error: unconstrained generic constant
2+
--> $DIR/no_where_clause.rs:10:6
3+
|
4+
LL | b: [f32; complex_maths(N)],
5+
| ^^^^^^^^^^^^^^^^^^^^^^^
6+
|
7+
help: try adding a `where` bound using this expression: where [u8; complex_maths(N)]: Sized
8+
--> $DIR/no_where_clause.rs:10:12
9+
|
10+
LL | b: [f32; complex_maths(N)],
11+
| ^^^^^^^^^^^^^^^^
12+
13+
error: aborting due to previous error
14+

0 commit comments

Comments
 (0)