1
Fork 0

More informative error message for E0015

This commit is contained in:
Deadbeef 2021-11-03 17:34:30 +08:00
parent 9cdefd763b
commit 1b0dcdc341
No known key found for this signature in database
GPG key ID: 6D017A96D8E6C2F9
2 changed files with 49 additions and 47 deletions

View file

@ -797,7 +797,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
if let Some(trait_id) = tcx.trait_of_item(callee) { if let Some(trait_id) = tcx.trait_of_item(callee) {
trace!("attempting to call a trait method"); trace!("attempting to call a trait method");
if !self.tcx.features().const_trait_impl { if !self.tcx.features().const_trait_impl {
self.check_op(ops::FnCallNonConst(Some((callee, substs)))); self.check_op(ops::FnCallNonConst(callee, substs));
return; return;
} }
@ -856,7 +856,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
} }
if !nonconst_call_permission { if !nonconst_call_permission {
self.check_op(ops::FnCallNonConst(None)); self.check_op(ops::FnCallNonConst(callee, substs));
return; return;
} }
} }
@ -925,7 +925,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
} }
if !nonconst_call_permission { if !nonconst_call_permission {
self.check_op(ops::FnCallNonConst(None)); self.check_op(ops::FnCallNonConst(callee, substs));
return; return;
} }
} }

View file

@ -74,19 +74,24 @@ impl NonConstOp for FnCallIndirect {
/// A function call where the callee is not marked as `const`. /// A function call where the callee is not marked as `const`.
#[derive(Debug)] #[derive(Debug)]
pub struct FnCallNonConst<'tcx>(pub Option<(DefId, SubstsRef<'tcx>)>); pub struct FnCallNonConst<'tcx>(pub DefId, pub SubstsRef<'tcx>);
impl<'a> NonConstOp for FnCallNonConst<'a> { impl<'a> NonConstOp for FnCallNonConst<'a> {
fn build_error<'tcx>(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> { fn build_error<'tcx>(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
let FnCallNonConst(def_id, substs) = *self;
let mut err = struct_span_err!( let mut err = struct_span_err!(
ccx.tcx.sess, ccx.tcx.sess,
span, span,
E0015, E0015,
"cannot call non-const fn `{}` in {}s",
ccx.tcx.def_path_str_with_substs(def_id, substs),
ccx.const_kind()
);
err.note(&format!(
"calls in {}s are limited to constant functions, \ "calls in {}s are limited to constant functions, \
tuple structs and tuple variants", tuple structs and tuple variants",
ccx.const_kind(), ccx.const_kind(),
); ));
if let FnCallNonConst(Some((callee, substs))) = *self {
if let Some(trait_def_id) = ccx.tcx.lang_items().eq_trait() { if let Some(trait_def_id) = ccx.tcx.lang_items().eq_trait() {
if let Some(eq_item) = ccx.tcx.associated_items(trait_def_id).find_by_name_and_kind( if let Some(eq_item) = ccx.tcx.associated_items(trait_def_id).find_by_name_and_kind(
ccx.tcx, ccx.tcx,
@ -109,15 +114,13 @@ impl<'a> NonConstOp for FnCallNonConst<'a> {
} }
let deref = "*".repeat(num_refs); let deref = "*".repeat(num_refs);
if let Ok(call_str) = if let Ok(call_str) = ccx.tcx.sess.source_map().span_to_snippet(span) {
ccx.tcx.sess.source_map().span_to_snippet(span)
{
if let Some(eq_idx) = call_str.find("==") { if let Some(eq_idx) = call_str.find("==") {
if let Some(rhs_idx) = call_str[(eq_idx + 2)..] if let Some(rhs_idx) =
.find(|c: char| !c.is_whitespace()) call_str[(eq_idx + 2)..].find(|c: char| !c.is_whitespace())
{ {
let rhs_pos = span.lo() let rhs_pos =
+ BytePos::from_usize(eq_idx + 2 + rhs_idx); span.lo() + BytePos::from_usize(eq_idx + 2 + rhs_idx);
let rhs_span = span.with_lo(rhs_pos).with_hi(rhs_pos); let rhs_span = span.with_lo(rhs_pos).with_hi(rhs_pos);
err.multipart_suggestion( err.multipart_suggestion(
"consider dereferencing here", "consider dereferencing here",
@ -136,7 +139,6 @@ impl<'a> NonConstOp for FnCallNonConst<'a> {
} }
} }
} }
}
err err
} }