Skip to content

Commit

Permalink
Rollup merge of rust-lang#112232 - fee1-dead-contrib:match-eq-const-m…
Browse files Browse the repository at this point in the history
…sg, r=b-naber

Better error for non const `PartialEq` call generated by `match`

Resolves rust-lang#90237
  • Loading branch information
matthiaskrgr authored Jun 18, 2023
2 parents 677710e + 89c24af commit 7b91275
Show file tree
Hide file tree
Showing 35 changed files with 213 additions and 102 deletions.
7 changes: 5 additions & 2 deletions compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use rustc_infer::traits::ObligationCause;
use rustc_middle::hir::nested_filter::OnlyBodies;
use rustc_middle::mir::tcx::PlaceTy;
use rustc_middle::mir::{
self, AggregateKind, BindingForm, BorrowKind, ClearCrossCrate, ConstraintCategory,
self, AggregateKind, BindingForm, BorrowKind, CallSource, ClearCrossCrate, ConstraintCategory,
FakeReadCause, LocalDecl, LocalInfo, LocalKind, Location, Operand, Place, PlaceRef,
ProjectionElem, Rvalue, Statement, StatementKind, Terminator, TerminatorKind, VarBindingForm,
};
Expand Down Expand Up @@ -2579,7 +2579,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
fn explain_deref_coercion(&mut self, loan: &BorrowData<'tcx>, err: &mut Diagnostic) {
let tcx = self.infcx.tcx;
if let (
Some(Terminator { kind: TerminatorKind::Call { from_hir_call: false, .. }, .. }),
Some(Terminator {
kind: TerminatorKind::Call { call_source: CallSource::OverloadedOperator, .. },
..
}),
Some((method_did, method_substs)),
) = (
&self.body[loan.reserve_location.block].terminator,
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ use rustc_hir::intravisit::Visitor;
use rustc_index::IndexSlice;
use rustc_infer::infer::NllRegionVariableOrigin;
use rustc_middle::mir::{
Body, CastKind, ConstraintCategory, FakeReadCause, Local, LocalInfo, Location, Operand, Place,
Rvalue, Statement, StatementKind, TerminatorKind,
Body, CallSource, CastKind, ConstraintCategory, FakeReadCause, Local, LocalInfo, Location,
Operand, Place, Rvalue, Statement, StatementKind, TerminatorKind,
};
use rustc_middle::ty::adjustment::PointerCast;
use rustc_middle::ty::{self, RegionVid, TyCtxt};
Expand Down Expand Up @@ -494,7 +494,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
} else if self.was_captured_by_trait_object(borrow) {
LaterUseKind::TraitCapture
} else if location.statement_index == block.statements.len() {
if let TerminatorKind::Call { func, from_hir_call: true, .. } =
if let TerminatorKind::Call { func, call_source: CallSource::Normal, .. } =
&block.terminator().kind
{
// Just point to the function, to reduce the chance of overlapping spans.
Expand Down
16 changes: 11 additions & 5 deletions compiler/rustc_borrowck/src/diagnostics/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@ use rustc_index::IndexSlice;
use rustc_infer::infer::LateBoundRegionConversionTime;
use rustc_middle::mir::tcx::PlaceTy;
use rustc_middle::mir::{
AggregateKind, Constant, FakeReadCause, Local, LocalInfo, LocalKind, Location, Operand, Place,
PlaceRef, ProjectionElem, Rvalue, Statement, StatementKind, Terminator, TerminatorKind,
AggregateKind, CallSource, Constant, FakeReadCause, Local, LocalInfo, LocalKind, Location,
Operand, Place, PlaceRef, ProjectionElem, Rvalue, Statement, StatementKind, Terminator,
TerminatorKind,
};
use rustc_middle::ty::print::Print;
use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
Expand Down Expand Up @@ -414,7 +415,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
if !is_terminator {
continue;
} else if let Some(Terminator {
kind: TerminatorKind::Call { func, from_hir_call: false, .. },
kind:
TerminatorKind::Call {
func,
call_source: CallSource::OverloadedOperator,
..
},
..
}) = &bbd.terminator
{
Expand Down Expand Up @@ -839,7 +845,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
debug!("move_spans: target_temp = {:?}", target_temp);

if let Some(Terminator {
kind: TerminatorKind::Call { fn_span, from_hir_call, .. }, ..
kind: TerminatorKind::Call { fn_span, call_source, .. }, ..
}) = &self.body[location.block].terminator
{
let Some((method_did, method_substs)) =
Expand All @@ -859,7 +865,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
method_did,
method_substs,
*fn_span,
*from_hir_call,
call_source.from_hir_call(),
Some(self.infcx.tcx.fn_arg_names(method_did)[0]),
);

Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_borrowck/src/invalidation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> {
destination,
target: _,
unwind: _,
from_hir_call: _,
call_source: _,
fn_span: _,
} => {
self.consume_operand(location, func);
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_borrowck/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -710,7 +710,7 @@ impl<'cx, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx, R> for MirBorro
destination,
target: _,
unwind: _,
from_hir_call: _,
call_source: _,
fn_span: _,
} => {
self.consume_operand(loc, (func, span), flow_state);
Expand Down
8 changes: 4 additions & 4 deletions compiler/rustc_borrowck/src/type_check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1370,7 +1370,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
}
// FIXME: check the values
}
TerminatorKind::Call { func, args, destination, from_hir_call, target, .. } => {
TerminatorKind::Call { func, args, destination, call_source, target, .. } => {
self.check_operand(func, term_location);
for arg in args {
self.check_operand(arg, term_location);
Expand Down Expand Up @@ -1446,7 +1446,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
.add_element(region_vid, term_location);
}

self.check_call_inputs(body, term, &sig, args, term_location, *from_hir_call);
self.check_call_inputs(body, term, &sig, args, term_location, *call_source);
}
TerminatorKind::Assert { cond, msg, .. } => {
self.check_operand(cond, term_location);
Expand Down Expand Up @@ -1573,7 +1573,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
sig: &ty::FnSig<'tcx>,
args: &[Operand<'tcx>],
term_location: Location,
from_hir_call: bool,
call_source: CallSource,
) {
debug!("check_call_inputs({:?}, {:?})", sig, args);
if args.len() < sig.inputs().len() || (args.len() > sig.inputs().len() && !sig.c_variadic) {
Expand All @@ -1591,7 +1591,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
let op_arg_ty = op_arg.ty(body, self.tcx());

let op_arg_ty = self.normalize(op_arg_ty, term_location);
let category = if from_hir_call {
let category = if call_source.from_hir_call() {
ConstraintCategory::CallArgument(self.infcx.tcx.erase_regions(func_ty))
} else {
ConstraintCategory::Boring
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_codegen_cranelift/src/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -421,7 +421,7 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) {
target,
fn_span,
unwind: _,
from_hir_call: _,
call_source: _,
} => {
fx.tcx.prof.generic_activity("codegen call").run(|| {
crate::abi::codegen_terminator_call(
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_codegen_ssa/src/mir/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1280,7 +1280,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
destination,
target,
unwind,
from_hir_call: _,
call_source: _,
fn_span,
} => self.codegen_call_terminator(
helper,
Expand Down
3 changes: 3 additions & 0 deletions compiler/rustc_const_eval/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,9 @@ const_eval_long_running =
.label = the const evaluator is currently interpreting this expression
.help = the constant being evaluated
const_eval_match_eq_non_const = cannot match on `{$ty}` in {const_eval_const_context}s
.note = `{$ty}` cannot be compared in compile-time, and therefore cannot be used in `match`es
const_eval_max_num_nodes_in_const = maximum number of nodes exceeded in constant {$global_const_id}
const_eval_memory_access_test = memory access failed
Expand Down
12 changes: 12 additions & 0 deletions compiler/rustc_const_eval/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,18 @@ pub struct RawBytesNote {
pub bytes: String,
}

// FIXME(fee1-dead) do not use stringly typed `ConstContext`

#[derive(Diagnostic)]
#[diag(const_eval_match_eq_non_const, code = "E0015")]
#[note]
pub struct NonConstMatchEq<'tcx> {
#[primary_span]
pub span: Span,
pub ty: Ty<'tcx>,
pub kind: ConstContext,
}

#[derive(Diagnostic)]
#[diag(const_eval_for_loop_into_iter_non_const, code = "E0015")]
pub struct NonConstForLoopIntoIter<'tcx> {
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_const_eval/src/interpret/terminator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
destination,
target,
unwind,
from_hir_call: _,
call_source: _,
fn_span: _,
} => {
let old_stack = self.frame_idx();
Expand Down
12 changes: 6 additions & 6 deletions compiler/rustc_const_eval/src/transform/check_consts/check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -702,7 +702,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
self.super_terminator(terminator, location);

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

Expand Down Expand Up @@ -755,7 +755,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
callee,
substs,
span: *fn_span,
from_hir_call: *from_hir_call,
call_source: *call_source,
feature: Some(sym::const_trait_impl),
});
return;
Expand Down Expand Up @@ -797,7 +797,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
callee,
substs,
span: *fn_span,
from_hir_call: *from_hir_call,
call_source: *call_source,
feature: None,
});

Expand All @@ -823,7 +823,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
callee,
substs,
span: *fn_span,
from_hir_call: *from_hir_call,
call_source: *call_source,
feature: None,
});
return;
Expand Down Expand Up @@ -866,7 +866,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
callee,
substs,
span: *fn_span,
from_hir_call: *from_hir_call,
call_source: *call_source,
feature: None,
});
return;
Expand Down Expand Up @@ -926,7 +926,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
callee,
substs,
span: *fn_span,
from_hir_call: *from_hir_call,
call_source: *call_source,
feature: None,
});
return;
Expand Down
94 changes: 53 additions & 41 deletions compiler/rustc_const_eval/src/transform/check_consts/ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_infer::infer::TyCtxtInferExt;
use rustc_infer::traits::{ImplSource, Obligation, ObligationCause};
use rustc_middle::mir;
use rustc_middle::mir::{self, CallSource};
use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_middle::ty::subst::{GenericArgKind, SubstsRef};
use rustc_middle::ty::{suggest_constraining_type_param, Adt, Closure, FnDef, FnPtr, Param, Ty};
Expand Down Expand Up @@ -100,7 +100,7 @@ pub struct FnCallNonConst<'tcx> {
pub callee: DefId,
pub substs: SubstsRef<'tcx>,
pub span: Span,
pub from_hir_call: bool,
pub call_source: CallSource,
pub feature: Option<Symbol>,
}

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

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

let call_kind = call_kind(tcx, ccx.param_env, callee, substs, span, from_hir_call, None);
let call_kind =
call_kind(tcx, ccx.param_env, callee, substs, span, call_source.from_hir_call(), None);

debug!(?call_kind);

Expand Down Expand Up @@ -219,48 +220,59 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> {
err
}
CallKind::Operator { trait_id, self_ty, .. } => {
let mut sugg = None;

if Some(trait_id) == ccx.tcx.lang_items().eq_trait() {
match (substs[0].unpack(), substs[1].unpack()) {
(GenericArgKind::Type(self_ty), GenericArgKind::Type(rhs_ty))
if self_ty == rhs_ty
&& self_ty.is_ref()
&& self_ty.peel_refs().is_primitive() =>
{
let mut num_refs = 0;
let mut tmp_ty = self_ty;
while let rustc_middle::ty::Ref(_, inner_ty, _) = tmp_ty.kind() {
num_refs += 1;
tmp_ty = *inner_ty;
}
let deref = "*".repeat(num_refs);

if let Ok(call_str) = ccx.tcx.sess.source_map().span_to_snippet(span) {
if let Some(eq_idx) = call_str.find("==") {
if let Some(rhs_idx) =
call_str[(eq_idx + 2)..].find(|c: char| !c.is_whitespace())
{
let rhs_pos =
span.lo() + BytePos::from_usize(eq_idx + 2 + rhs_idx);
let rhs_span = span.with_lo(rhs_pos).with_hi(rhs_pos);
sugg = Some(errors::ConsiderDereferencing {
deref,
span: span.shrink_to_lo(),
rhs_span,
});
let mut err = if let CallSource::MatchCmp = call_source {
tcx.sess.create_err(errors::NonConstMatchEq {
span,
kind: ccx.const_kind(),
ty: self_ty,
})
} else {
let mut sugg = None;

if Some(trait_id) == ccx.tcx.lang_items().eq_trait() {
match (substs[0].unpack(), substs[1].unpack()) {
(GenericArgKind::Type(self_ty), GenericArgKind::Type(rhs_ty))
if self_ty == rhs_ty
&& self_ty.is_ref()
&& self_ty.peel_refs().is_primitive() =>
{
let mut num_refs = 0;
let mut tmp_ty = self_ty;
while let rustc_middle::ty::Ref(_, inner_ty, _) = tmp_ty.kind() {
num_refs += 1;
tmp_ty = *inner_ty;
}
let deref = "*".repeat(num_refs);

if let Ok(call_str) =
ccx.tcx.sess.source_map().span_to_snippet(span)
{
if let Some(eq_idx) = call_str.find("==") {
if let Some(rhs_idx) = call_str[(eq_idx + 2)..]
.find(|c: char| !c.is_whitespace())
{
let rhs_pos = span.lo()
+ BytePos::from_usize(eq_idx + 2 + rhs_idx);
let rhs_span = span.with_lo(rhs_pos).with_hi(rhs_pos);
sugg = Some(errors::ConsiderDereferencing {
deref,
span: span.shrink_to_lo(),
rhs_span,
});
}
}
}
}
_ => {}
}
_ => {}
}
}
let mut err = tcx.sess.create_err(errors::NonConstOperator {
span,
kind: ccx.const_kind(),
sugg,
});
tcx.sess.create_err(errors::NonConstOperator {
span,
kind: ccx.const_kind(),
sugg,
})
};

diag_trait(&mut err, self_ty, trait_id);
err
}
Expand Down
Loading

0 comments on commit 7b91275

Please sign in to comment.