Skip to content

Commit 05ad698

Browse files
committed
More informative error message for E0015
1 parent 7ae5508 commit 05ad698

File tree

2 files changed

+51
-49
lines changed

2 files changed

+51
-49
lines changed

compiler/rustc_const_eval/src/transform/check_consts/check.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -801,7 +801,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
801801
if let Some(trait_id) = tcx.trait_of_item(callee) {
802802
trace!("attempting to call a trait method");
803803
if !self.tcx.features().const_trait_impl {
804-
self.check_op(ops::FnCallNonConst(Some((callee, substs))));
804+
self.check_op(ops::FnCallNonConst(callee, substs));
805805
return;
806806
}
807807

@@ -856,7 +856,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
856856
}
857857

858858
if !nonconst_call_permission {
859-
self.check_op(ops::FnCallNonConst(None));
859+
self.check_op(ops::FnCallNonConst(callee, substs));
860860
return;
861861
}
862862
}
@@ -925,7 +925,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
925925
}
926926

927927
if !nonconst_call_permission {
928-
self.check_op(ops::FnCallNonConst(None));
928+
self.check_op(ops::FnCallNonConst(callee, substs));
929929
return;
930930
}
931931
}

compiler/rustc_const_eval/src/transform/check_consts/ops.rs

+48-46
Original file line numberDiff line numberDiff line change
@@ -74,65 +74,67 @@ impl NonConstOp for FnCallIndirect {
7474

7575
/// A function call where the callee is not marked as `const`.
7676
#[derive(Debug)]
77-
pub struct FnCallNonConst<'tcx>(pub Option<(DefId, SubstsRef<'tcx>)>);
77+
pub struct FnCallNonConst<'tcx>(pub DefId, pub SubstsRef<'tcx>);
7878
impl<'a> NonConstOp for FnCallNonConst<'a> {
7979
fn build_error<'tcx>(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
80+
let FnCallNonConst(def_id, substs) = *self;
8081
let mut err = struct_span_err!(
8182
ccx.tcx.sess,
8283
span,
8384
E0015,
85+
"cannot call non-const fn `{}` in {}s",
86+
ccx.tcx.def_path_str_with_substs(def_id, substs),
87+
ccx.const_kind()
88+
);
89+
err.note(&format!(
8490
"calls in {}s are limited to constant functions, \
8591
tuple structs and tuple variants",
8692
ccx.const_kind(),
87-
);
88-
89-
if let FnCallNonConst(Some((callee, substs))) = *self {
90-
if let Some(trait_def_id) = ccx.tcx.lang_items().eq_trait() {
91-
if let Some(eq_item) = ccx.tcx.associated_items(trait_def_id).find_by_name_and_kind(
92-
ccx.tcx,
93-
Ident::with_dummy_span(sym::eq),
94-
AssocKind::Fn,
95-
trait_def_id,
96-
) {
97-
if callee == eq_item.def_id && substs.len() == 2 {
98-
match (substs[0].unpack(), substs[1].unpack()) {
99-
(GenericArgKind::Type(self_ty), GenericArgKind::Type(rhs_ty))
100-
if self_ty == rhs_ty
101-
&& self_ty.is_ref()
102-
&& self_ty.peel_refs().is_primitive() =>
103-
{
104-
let mut num_refs = 0;
105-
let mut tmp_ty = self_ty;
106-
while let rustc_middle::ty::Ref(_, inner_ty, _) = tmp_ty.kind() {
107-
num_refs += 1;
108-
tmp_ty = inner_ty;
109-
}
110-
let deref = "*".repeat(num_refs);
111-
112-
if let Ok(call_str) =
113-
ccx.tcx.sess.source_map().span_to_snippet(span)
114-
{
115-
if let Some(eq_idx) = call_str.find("==") {
116-
if let Some(rhs_idx) = call_str[(eq_idx + 2)..]
117-
.find(|c: char| !c.is_whitespace())
118-
{
119-
let rhs_pos = span.lo()
120-
+ BytePos::from_usize(eq_idx + 2 + rhs_idx);
121-
let rhs_span = span.with_lo(rhs_pos).with_hi(rhs_pos);
122-
err.multipart_suggestion(
123-
"consider dereferencing here",
124-
vec![
125-
(span.shrink_to_lo(), deref.clone()),
126-
(rhs_span, deref),
127-
],
128-
Applicability::MachineApplicable,
129-
);
130-
}
93+
));
94+
95+
if let Some(trait_def_id) = ccx.tcx.lang_items().eq_trait() {
96+
if let Some(eq_item) = ccx.tcx.associated_items(trait_def_id).find_by_name_and_kind(
97+
ccx.tcx,
98+
Ident::with_dummy_span(sym::eq),
99+
AssocKind::Fn,
100+
trait_def_id,
101+
) {
102+
if callee == eq_item.def_id && substs.len() == 2 {
103+
match (substs[0].unpack(), substs[1].unpack()) {
104+
(GenericArgKind::Type(self_ty), GenericArgKind::Type(rhs_ty))
105+
if self_ty == rhs_ty
106+
&& self_ty.is_ref()
107+
&& self_ty.peel_refs().is_primitive() =>
108+
{
109+
let mut num_refs = 0;
110+
let mut tmp_ty = self_ty;
111+
while let rustc_middle::ty::Ref(_, inner_ty, _) = tmp_ty.kind() {
112+
num_refs += 1;
113+
tmp_ty = inner_ty;
114+
}
115+
let deref = "*".repeat(num_refs);
116+
117+
if let Ok(call_str) = ccx.tcx.sess.source_map().span_to_snippet(span) {
118+
if let Some(eq_idx) = call_str.find("==") {
119+
if let Some(rhs_idx) =
120+
call_str[(eq_idx + 2)..].find(|c: char| !c.is_whitespace())
121+
{
122+
let rhs_pos =
123+
span.lo() + BytePos::from_usize(eq_idx + 2 + rhs_idx);
124+
let rhs_span = span.with_lo(rhs_pos).with_hi(rhs_pos);
125+
err.multipart_suggestion(
126+
"consider dereferencing here",
127+
vec![
128+
(span.shrink_to_lo(), deref.clone()),
129+
(rhs_span, deref),
130+
],
131+
Applicability::MachineApplicable,
132+
);
131133
}
132134
}
133135
}
134-
_ => {}
135136
}
137+
_ => {}
136138
}
137139
}
138140
}

0 commit comments

Comments
 (0)