Skip to content

Commit 89c24af

Browse files
committed
Better error for non const PartialEq call generated by match
1 parent ed7281e commit 89c24af

File tree

35 files changed

+213
-102
lines changed

35 files changed

+213
-102
lines changed

compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use rustc_infer::traits::ObligationCause;
1414
use rustc_middle::hir::nested_filter::OnlyBodies;
1515
use rustc_middle::mir::tcx::PlaceTy;
1616
use rustc_middle::mir::{
17-
self, AggregateKind, BindingForm, BorrowKind, ClearCrossCrate, ConstraintCategory,
17+
self, AggregateKind, BindingForm, BorrowKind, CallSource, ClearCrossCrate, ConstraintCategory,
1818
FakeReadCause, LocalDecl, LocalInfo, LocalKind, Location, Operand, Place, PlaceRef,
1919
ProjectionElem, Rvalue, Statement, StatementKind, Terminator, TerminatorKind, VarBindingForm,
2020
};
@@ -2579,7 +2579,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
25792579
fn explain_deref_coercion(&mut self, loan: &BorrowData<'tcx>, err: &mut Diagnostic) {
25802580
let tcx = self.infcx.tcx;
25812581
if let (
2582-
Some(Terminator { kind: TerminatorKind::Call { from_hir_call: false, .. }, .. }),
2582+
Some(Terminator {
2583+
kind: TerminatorKind::Call { call_source: CallSource::OverloadedOperator, .. },
2584+
..
2585+
}),
25832586
Some((method_did, method_substs)),
25842587
) = (
25852588
&self.body[loan.reserve_location.block].terminator,

compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ use rustc_hir::intravisit::Visitor;
66
use rustc_index::IndexSlice;
77
use rustc_infer::infer::NllRegionVariableOrigin;
88
use rustc_middle::mir::{
9-
Body, CastKind, ConstraintCategory, FakeReadCause, Local, LocalInfo, Location, Operand, Place,
10-
Rvalue, Statement, StatementKind, TerminatorKind,
9+
Body, CallSource, CastKind, ConstraintCategory, FakeReadCause, Local, LocalInfo, Location,
10+
Operand, Place, Rvalue, Statement, StatementKind, TerminatorKind,
1111
};
1212
use rustc_middle::ty::adjustment::PointerCast;
1313
use rustc_middle::ty::{self, RegionVid, TyCtxt};
@@ -494,7 +494,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
494494
} else if self.was_captured_by_trait_object(borrow) {
495495
LaterUseKind::TraitCapture
496496
} else if location.statement_index == block.statements.len() {
497-
if let TerminatorKind::Call { func, from_hir_call: true, .. } =
497+
if let TerminatorKind::Call { func, call_source: CallSource::Normal, .. } =
498498
&block.terminator().kind
499499
{
500500
// Just point to the function, to reduce the chance of overlapping spans.

compiler/rustc_borrowck/src/diagnostics/mod.rs

+11-5
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,9 @@ use rustc_index::IndexSlice;
1313
use rustc_infer::infer::LateBoundRegionConversionTime;
1414
use rustc_middle::mir::tcx::PlaceTy;
1515
use rustc_middle::mir::{
16-
AggregateKind, Constant, FakeReadCause, Local, LocalInfo, LocalKind, Location, Operand, Place,
17-
PlaceRef, ProjectionElem, Rvalue, Statement, StatementKind, Terminator, TerminatorKind,
16+
AggregateKind, CallSource, Constant, FakeReadCause, Local, LocalInfo, LocalKind, Location,
17+
Operand, Place, PlaceRef, ProjectionElem, Rvalue, Statement, StatementKind, Terminator,
18+
TerminatorKind,
1819
};
1920
use rustc_middle::ty::print::Print;
2021
use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
@@ -414,7 +415,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
414415
if !is_terminator {
415416
continue;
416417
} else if let Some(Terminator {
417-
kind: TerminatorKind::Call { func, from_hir_call: false, .. },
418+
kind:
419+
TerminatorKind::Call {
420+
func,
421+
call_source: CallSource::OverloadedOperator,
422+
..
423+
},
418424
..
419425
}) = &bbd.terminator
420426
{
@@ -839,7 +845,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
839845
debug!("move_spans: target_temp = {:?}", target_temp);
840846

841847
if let Some(Terminator {
842-
kind: TerminatorKind::Call { fn_span, from_hir_call, .. }, ..
848+
kind: TerminatorKind::Call { fn_span, call_source, .. }, ..
843849
}) = &self.body[location.block].terminator
844850
{
845851
let Some((method_did, method_substs)) =
@@ -859,7 +865,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
859865
method_did,
860866
method_substs,
861867
*fn_span,
862-
*from_hir_call,
868+
call_source.from_hir_call(),
863869
Some(self.infcx.tcx.fn_arg_names(method_did)[0]),
864870
);
865871

compiler/rustc_borrowck/src/invalidation.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> {
128128
destination,
129129
target: _,
130130
unwind: _,
131-
from_hir_call: _,
131+
call_source: _,
132132
fn_span: _,
133133
} => {
134134
self.consume_operand(location, func);

compiler/rustc_borrowck/src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -710,7 +710,7 @@ impl<'cx, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx, R> for MirBorro
710710
destination,
711711
target: _,
712712
unwind: _,
713-
from_hir_call: _,
713+
call_source: _,
714714
fn_span: _,
715715
} => {
716716
self.consume_operand(loc, (func, span), flow_state);

compiler/rustc_borrowck/src/type_check/mod.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -1370,7 +1370,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
13701370
}
13711371
// FIXME: check the values
13721372
}
1373-
TerminatorKind::Call { func, args, destination, from_hir_call, target, .. } => {
1373+
TerminatorKind::Call { func, args, destination, call_source, target, .. } => {
13741374
self.check_operand(func, term_location);
13751375
for arg in args {
13761376
self.check_operand(arg, term_location);
@@ -1444,7 +1444,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
14441444
.add_element(region_vid, term_location);
14451445
}
14461446

1447-
self.check_call_inputs(body, term, &sig, args, term_location, *from_hir_call);
1447+
self.check_call_inputs(body, term, &sig, args, term_location, *call_source);
14481448
}
14491449
TerminatorKind::Assert { cond, msg, .. } => {
14501450
self.check_operand(cond, term_location);
@@ -1571,7 +1571,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
15711571
sig: &ty::FnSig<'tcx>,
15721572
args: &[Operand<'tcx>],
15731573
term_location: Location,
1574-
from_hir_call: bool,
1574+
call_source: CallSource,
15751575
) {
15761576
debug!("check_call_inputs({:?}, {:?})", sig, args);
15771577
if args.len() < sig.inputs().len() || (args.len() > sig.inputs().len() && !sig.c_variadic) {
@@ -1589,7 +1589,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
15891589
let op_arg_ty = op_arg.ty(body, self.tcx());
15901590

15911591
let op_arg_ty = self.normalize(op_arg_ty, term_location);
1592-
let category = if from_hir_call {
1592+
let category = if call_source.from_hir_call() {
15931593
ConstraintCategory::CallArgument(self.infcx.tcx.erase_regions(func_ty))
15941594
} else {
15951595
ConstraintCategory::Boring

compiler/rustc_codegen_cranelift/src/base.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -421,7 +421,7 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) {
421421
target,
422422
fn_span,
423423
unwind: _,
424-
from_hir_call: _,
424+
call_source: _,
425425
} => {
426426
fx.tcx.prof.generic_activity("codegen call").run(|| {
427427
crate::abi::codegen_terminator_call(

compiler/rustc_codegen_ssa/src/mir/block.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1280,7 +1280,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
12801280
destination,
12811281
target,
12821282
unwind,
1283-
from_hir_call: _,
1283+
call_source: _,
12841284
fn_span,
12851285
} => self.codegen_call_terminator(
12861286
helper,

compiler/rustc_const_eval/messages.ftl

+3
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,9 @@ const_eval_long_running =
210210
.label = the const evaluator is currently interpreting this expression
211211
.help = the constant being evaluated
212212
213+
const_eval_match_eq_non_const = cannot match on `{$ty}` in {const_eval_const_context}s
214+
.note = `{$ty}` cannot be compared in compile-time, and therefore cannot be used in `match`es
215+
213216
const_eval_max_num_nodes_in_const = maximum number of nodes exceeded in constant {$global_const_id}
214217
215218
const_eval_memory_access_test = memory access failed

compiler/rustc_const_eval/src/errors.rs

+12
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,18 @@ pub struct RawBytesNote {
271271
pub bytes: String,
272272
}
273273

274+
// FIXME(fee1-dead) do not use stringly typed `ConstContext`
275+
276+
#[derive(Diagnostic)]
277+
#[diag(const_eval_match_eq_non_const, code = "E0015")]
278+
#[note]
279+
pub struct NonConstMatchEq<'tcx> {
280+
#[primary_span]
281+
pub span: Span,
282+
pub ty: Ty<'tcx>,
283+
pub kind: ConstContext,
284+
}
285+
274286
#[derive(Diagnostic)]
275287
#[diag(const_eval_for_loop_into_iter_non_const, code = "E0015")]
276288
pub struct NonConstForLoopIntoIter<'tcx> {

compiler/rustc_const_eval/src/interpret/terminator.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
6262
destination,
6363
target,
6464
unwind,
65-
from_hir_call: _,
65+
call_source: _,
6666
fn_span: _,
6767
} => {
6868
let old_stack = self.frame_idx();

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

+6-6
Original file line numberDiff line numberDiff line change
@@ -702,7 +702,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
702702
self.super_terminator(terminator, location);
703703

704704
match &terminator.kind {
705-
TerminatorKind::Call { func, args, fn_span, from_hir_call, .. } => {
705+
TerminatorKind::Call { func, args, fn_span, call_source, .. } => {
706706
let ConstCx { tcx, body, param_env, .. } = *self.ccx;
707707
let caller = self.def_id();
708708

@@ -755,7 +755,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
755755
callee,
756756
substs,
757757
span: *fn_span,
758-
from_hir_call: *from_hir_call,
758+
call_source: *call_source,
759759
feature: Some(sym::const_trait_impl),
760760
});
761761
return;
@@ -797,7 +797,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
797797
callee,
798798
substs,
799799
span: *fn_span,
800-
from_hir_call: *from_hir_call,
800+
call_source: *call_source,
801801
feature: None,
802802
});
803803

@@ -823,7 +823,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
823823
callee,
824824
substs,
825825
span: *fn_span,
826-
from_hir_call: *from_hir_call,
826+
call_source: *call_source,
827827
feature: None,
828828
});
829829
return;
@@ -866,7 +866,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
866866
callee,
867867
substs,
868868
span: *fn_span,
869-
from_hir_call: *from_hir_call,
869+
call_source: *call_source,
870870
feature: None,
871871
});
872872
return;
@@ -926,7 +926,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
926926
callee,
927927
substs,
928928
span: *fn_span,
929-
from_hir_call: *from_hir_call,
929+
call_source: *call_source,
930930
feature: None,
931931
});
932932
return;

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

+53-41
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use rustc_hir as hir;
77
use rustc_hir::def_id::DefId;
88
use rustc_infer::infer::TyCtxtInferExt;
99
use rustc_infer::traits::{ImplSource, Obligation, ObligationCause};
10-
use rustc_middle::mir;
10+
use rustc_middle::mir::{self, CallSource};
1111
use rustc_middle::ty::print::with_no_trimmed_paths;
1212
use rustc_middle::ty::subst::{GenericArgKind, SubstsRef};
1313
use rustc_middle::ty::{suggest_constraining_type_param, Adt, Closure, FnDef, FnPtr, Param, Ty};
@@ -100,7 +100,7 @@ pub struct FnCallNonConst<'tcx> {
100100
pub callee: DefId,
101101
pub substs: SubstsRef<'tcx>,
102102
pub span: Span,
103-
pub from_hir_call: bool,
103+
pub call_source: CallSource,
104104
pub feature: Option<Symbol>,
105105
}
106106

@@ -110,7 +110,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> {
110110
ccx: &ConstCx<'_, 'tcx>,
111111
_: Span,
112112
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
113-
let FnCallNonConst { caller, callee, substs, span, from_hir_call, feature } = *self;
113+
let FnCallNonConst { caller, callee, substs, span, call_source, feature } = *self;
114114
let ConstCx { tcx, param_env, .. } = *ccx;
115115

116116
let diag_trait = |err, self_ty: Ty<'_>, trait_id| {
@@ -157,7 +157,8 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> {
157157
}
158158
};
159159

160-
let call_kind = call_kind(tcx, ccx.param_env, callee, substs, span, from_hir_call, None);
160+
let call_kind =
161+
call_kind(tcx, ccx.param_env, callee, substs, span, call_source.from_hir_call(), None);
161162

162163
debug!(?call_kind);
163164

@@ -219,48 +220,59 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> {
219220
err
220221
}
221222
CallKind::Operator { trait_id, self_ty, .. } => {
222-
let mut sugg = None;
223-
224-
if Some(trait_id) == ccx.tcx.lang_items().eq_trait() {
225-
match (substs[0].unpack(), substs[1].unpack()) {
226-
(GenericArgKind::Type(self_ty), GenericArgKind::Type(rhs_ty))
227-
if self_ty == rhs_ty
228-
&& self_ty.is_ref()
229-
&& self_ty.peel_refs().is_primitive() =>
230-
{
231-
let mut num_refs = 0;
232-
let mut tmp_ty = self_ty;
233-
while let rustc_middle::ty::Ref(_, inner_ty, _) = tmp_ty.kind() {
234-
num_refs += 1;
235-
tmp_ty = *inner_ty;
236-
}
237-
let deref = "*".repeat(num_refs);
238-
239-
if let Ok(call_str) = ccx.tcx.sess.source_map().span_to_snippet(span) {
240-
if let Some(eq_idx) = call_str.find("==") {
241-
if let Some(rhs_idx) =
242-
call_str[(eq_idx + 2)..].find(|c: char| !c.is_whitespace())
243-
{
244-
let rhs_pos =
245-
span.lo() + BytePos::from_usize(eq_idx + 2 + rhs_idx);
246-
let rhs_span = span.with_lo(rhs_pos).with_hi(rhs_pos);
247-
sugg = Some(errors::ConsiderDereferencing {
248-
deref,
249-
span: span.shrink_to_lo(),
250-
rhs_span,
251-
});
223+
let mut err = if let CallSource::MatchCmp = call_source {
224+
tcx.sess.create_err(errors::NonConstMatchEq {
225+
span,
226+
kind: ccx.const_kind(),
227+
ty: self_ty,
228+
})
229+
} else {
230+
let mut sugg = None;
231+
232+
if Some(trait_id) == ccx.tcx.lang_items().eq_trait() {
233+
match (substs[0].unpack(), substs[1].unpack()) {
234+
(GenericArgKind::Type(self_ty), GenericArgKind::Type(rhs_ty))
235+
if self_ty == rhs_ty
236+
&& self_ty.is_ref()
237+
&& self_ty.peel_refs().is_primitive() =>
238+
{
239+
let mut num_refs = 0;
240+
let mut tmp_ty = self_ty;
241+
while let rustc_middle::ty::Ref(_, inner_ty, _) = tmp_ty.kind() {
242+
num_refs += 1;
243+
tmp_ty = *inner_ty;
244+
}
245+
let deref = "*".repeat(num_refs);
246+
247+
if let Ok(call_str) =
248+
ccx.tcx.sess.source_map().span_to_snippet(span)
249+
{
250+
if let Some(eq_idx) = call_str.find("==") {
251+
if let Some(rhs_idx) = call_str[(eq_idx + 2)..]
252+
.find(|c: char| !c.is_whitespace())
253+
{
254+
let rhs_pos = span.lo()
255+
+ BytePos::from_usize(eq_idx + 2 + rhs_idx);
256+
let rhs_span = span.with_lo(rhs_pos).with_hi(rhs_pos);
257+
sugg = Some(errors::ConsiderDereferencing {
258+
deref,
259+
span: span.shrink_to_lo(),
260+
rhs_span,
261+
});
262+
}
252263
}
253264
}
254265
}
266+
_ => {}
255267
}
256-
_ => {}
257268
}
258-
}
259-
let mut err = tcx.sess.create_err(errors::NonConstOperator {
260-
span,
261-
kind: ccx.const_kind(),
262-
sugg,
263-
});
269+
tcx.sess.create_err(errors::NonConstOperator {
270+
span,
271+
kind: ccx.const_kind(),
272+
sugg,
273+
})
274+
};
275+
264276
diag_trait(&mut err, self_ty, trait_id);
265277
err
266278
}

0 commit comments

Comments
 (0)