Skip to content

Commit 2c462a2

Browse files
committed
Auto merge of #69325 - Centril:rollup-vce2ko2, r=Centril
Rollup of 5 pull requests Successful merges: - #68877 (On mismatched argument count point at arguments) - #69185 (Unify and improve const-prop lints) - #69305 (Tweak binding lifetime suggestion text) - #69311 (Clean up E0321 and E0322) - #69317 (Fix broken link to the rustc guide) Failed merges: r? @ghost
2 parents bfb9604 + c1165ce commit 2c462a2

File tree

132 files changed

+1903
-1277
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

132 files changed

+1903
-1277
lines changed

src/librustc_error_codes/error_codes/E0321.md

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
A cross-crate opt-out trait was implemented on something which wasn't a struct
2-
or enum type. Erroneous code example:
2+
or enum type.
3+
4+
Erroneous code example:
35

46
```compile_fail,E0321
57
#![feature(optin_builtin_traits)]

src/librustc_error_codes/error_codes/E0322.md

+10
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,13 @@
1+
The `Sized` trait was implemented explicitly.
2+
3+
Erroneous code example:
4+
5+
```compile_fail,E0322
6+
struct Foo;
7+
8+
impl Sized for Foo {} // error!
9+
```
10+
111
The `Sized` trait is a special trait built-in to the compiler for types with a
212
constant size known at compile-time. This trait is automatically implemented
313
for types as needed by the compiler, and it is currently disallowed to

src/librustc_infer/infer/error_reporting/mod.rs

+12-10
Original file line numberDiff line numberDiff line change
@@ -1781,28 +1781,30 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
17811781
bound_kind: GenericKind<'tcx>,
17821782
sub: S,
17831783
) {
1784-
let consider = format!(
1785-
"consider adding an explicit lifetime bound {}",
1786-
if type_param_span.map(|(_, _, is_impl_trait)| is_impl_trait).unwrap_or(false) {
1787-
format!(" `{}` to `{}`...", sub, bound_kind)
1788-
} else {
1789-
format!("`{}: {}`...", bound_kind, sub)
1790-
},
1791-
);
1784+
let msg = "consider adding an explicit lifetime bound";
17921785
if let Some((sp, has_lifetimes, is_impl_trait)) = type_param_span {
17931786
let suggestion = if is_impl_trait {
17941787
format!("{} + {}", bound_kind, sub)
17951788
} else {
17961789
let tail = if has_lifetimes { " + " } else { "" };
17971790
format!("{}: {}{}", bound_kind, sub, tail)
17981791
};
1799-
err.span_suggestion_short(
1792+
err.span_suggestion(
18001793
sp,
1801-
&consider,
1794+
&format!("{}...", msg),
18021795
suggestion,
18031796
Applicability::MaybeIncorrect, // Issue #41966
18041797
);
18051798
} else {
1799+
let consider = format!(
1800+
"{} {}...",
1801+
msg,
1802+
if type_param_span.map(|(_, _, is_impl_trait)| is_impl_trait).unwrap_or(false) {
1803+
format!(" `{}` to `{}`", sub, bound_kind)
1804+
} else {
1805+
format!("`{}: {}`", bound_kind, sub)
1806+
},
1807+
);
18061808
err.help(&consider);
18071809
}
18081810
}

src/librustc_lint/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,7 @@ fn register_builtins(store: &mut LintStore, no_interleave_lints: bool) {
305305
store.register_renamed("unstable_name_collision", "unstable_name_collisions");
306306
store.register_renamed("unused_doc_comment", "unused_doc_comments");
307307
store.register_renamed("async_idents", "keyword_idents");
308+
store.register_renamed("exceeding_bitshifts", "arithmetic_overflow");
308309
store.register_removed("unknown_features", "replaced by an error");
309310
store.register_removed("unsigned_negation", "replaced by negate_unsigned feature gate");
310311
store.register_removed("negate_unsigned", "cast a signed value instead");

src/librustc_mir/transform/const_prop.rs

+86-91
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
use std::borrow::Cow;
55
use std::cell::Cell;
66

7-
use rustc::mir::interpret::{InterpError, InterpResult, Scalar};
7+
use rustc::lint;
8+
use rustc::mir::interpret::{InterpResult, Scalar};
89
use rustc::mir::visit::{
910
MutVisitor, MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor,
1011
};
@@ -292,7 +293,6 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine {
292293
struct ConstPropagator<'mir, 'tcx> {
293294
ecx: InterpCx<'mir, 'tcx, ConstPropMachine>,
294295
tcx: TyCtxt<'tcx>,
295-
source: MirSource<'tcx>,
296296
can_const_prop: IndexVec<Local, ConstPropMode>,
297297
param_env: ParamEnv<'tcx>,
298298
// FIXME(eddyb) avoid cloning these two fields more than once,
@@ -372,7 +372,6 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
372372
ConstPropagator {
373373
ecx,
374374
tcx,
375-
source,
376375
param_env,
377376
can_const_prop,
378377
// FIXME(eddyb) avoid cloning these two fields more than once,
@@ -501,19 +500,20 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
501500
}
502501
}
503502

504-
fn report_panic_as_lint(&self, source_info: SourceInfo, panic: AssertKind<u64>) -> Option<()> {
505-
// Somewhat convoluted way to re-use the CTFE error reporting code.
503+
fn report_assert_as_lint(
504+
&self,
505+
lint: &'static lint::Lint,
506+
source_info: SourceInfo,
507+
message: &'static str,
508+
panic: AssertKind<u64>,
509+
) -> Option<()> {
506510
let lint_root = self.lint_root(source_info)?;
507-
let error = InterpError::MachineStop(Box::new(format!("{:?}", panic)));
508-
let mut diagnostic = error_to_const_error(&self.ecx, error.into());
509-
diagnostic.span = source_info.span; // fix the span
510-
diagnostic.report_as_lint(
511-
self.tcx.at(source_info.span),
512-
"this expression will panic at runtime",
513-
lint_root,
514-
None,
515-
);
516-
None
511+
self.tcx.struct_span_lint_hir(lint, lint_root, source_info.span, |lint| {
512+
let mut err = lint.build(message);
513+
err.span_label(source_info.span, format!("{:?}", panic));
514+
err.emit()
515+
});
516+
return None;
517517
}
518518

519519
fn check_unary_op(
@@ -530,7 +530,12 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
530530
// `AssertKind` only has an `OverflowNeg` variant, so make sure that is
531531
// appropriate to use.
532532
assert_eq!(op, UnOp::Neg, "Neg is the only UnOp that can overflow");
533-
self.report_panic_as_lint(source_info, AssertKind::OverflowNeg)?;
533+
self.report_assert_as_lint(
534+
lint::builtin::ARITHMETIC_OVERFLOW,
535+
source_info,
536+
"this arithmetic operation will overflow",
537+
AssertKind::OverflowNeg,
538+
)?;
534539
}
535540

536541
Some(())
@@ -542,27 +547,24 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
542547
left: &Operand<'tcx>,
543548
right: &Operand<'tcx>,
544549
source_info: SourceInfo,
545-
place_layout: TyLayout<'tcx>,
546550
) -> Option<()> {
547551
let r =
548552
self.use_ecx(|this| this.ecx.read_immediate(this.ecx.eval_operand(right, None)?))?;
549553
// Check for exceeding shifts *even if* we cannot evaluate the LHS.
550554
if op == BinOp::Shr || op == BinOp::Shl {
551-
let left_bits = place_layout.size.bits();
555+
// We need the type of the LHS. We cannot use `place_layout` as that is the type
556+
// of the result, which for checked binops is not the same!
557+
let left_ty = left.ty(&self.local_decls, self.tcx);
558+
let left_size_bits = self.ecx.layout_of(left_ty).ok()?.size.bits();
552559
let right_size = r.layout.size;
553560
let r_bits = r.to_scalar().and_then(|r| r.to_bits(right_size));
554-
if r_bits.map_or(false, |b| b >= left_bits as u128) {
555-
let lint_root = self.lint_root(source_info)?;
556-
self.tcx.struct_span_lint_hir(
557-
::rustc::lint::builtin::EXCEEDING_BITSHIFTS,
558-
lint_root,
559-
source_info.span,
560-
|lint| {
561-
let dir = if op == BinOp::Shr { "right" } else { "left" };
562-
lint.build(&format!("attempt to shift {} with overflow", dir)).emit()
563-
},
564-
);
565-
return None;
561+
if r_bits.map_or(false, |b| b >= left_size_bits as u128) {
562+
self.report_assert_as_lint(
563+
lint::builtin::ARITHMETIC_OVERFLOW,
564+
source_info,
565+
"this arithmetic operation will overflow",
566+
AssertKind::Overflow(op),
567+
)?;
566568
}
567569
}
568570

@@ -572,7 +574,12 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
572574
let (_res, overflow, _ty) = this.ecx.overflowing_binary_op(op, l, r)?;
573575
Ok(overflow)
574576
})? {
575-
self.report_panic_as_lint(source_info, AssertKind::Overflow(op))?;
577+
self.report_assert_as_lint(
578+
lint::builtin::ARITHMETIC_OVERFLOW,
579+
source_info,
580+
"this arithmetic operation will overflow",
581+
AssertKind::Overflow(op),
582+
)?;
576583
}
577584

578585
Some(())
@@ -595,8 +602,6 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
595602
return None;
596603
}
597604

598-
let overflow_check = self.tcx.sess.overflow_checks();
599-
600605
// Perform any special handling for specific Rvalue types.
601606
// Generally, checks here fall into one of two categories:
602607
// 1. Additional checking to provide useful lints to the user
@@ -606,20 +611,25 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
606611
// - In this case, we'll return `None` from this function to stop evaluation.
607612
match rvalue {
608613
// Additional checking: give lints to the user if an overflow would occur.
609-
// If `overflow_check` is set, running const-prop on the `Assert` terminators
610-
// will already generate the appropriate messages.
611-
Rvalue::UnaryOp(op, arg) if !overflow_check => {
614+
// We do this here and not in the `Assert` terminator as that terminator is
615+
// only sometimes emitted (overflow checks can be disabled), but we want to always
616+
// lint.
617+
Rvalue::UnaryOp(op, arg) => {
612618
trace!("checking UnaryOp(op = {:?}, arg = {:?})", op, arg);
613619
self.check_unary_op(*op, arg, source_info)?;
614620
}
615-
616-
// Additional checking: check for overflows on integer binary operations and report
617-
// them to the user as lints.
618-
// If `overflow_check` is set, running const-prop on the `Assert` terminators
619-
// will already generate the appropriate messages.
620-
Rvalue::BinaryOp(op, left, right) if !overflow_check => {
621+
Rvalue::BinaryOp(op, left, right) => {
621622
trace!("checking BinaryOp(op = {:?}, left = {:?}, right = {:?})", op, left, right);
622-
self.check_binary_op(*op, left, right, source_info, place_layout)?;
623+
self.check_binary_op(*op, left, right, source_info)?;
624+
}
625+
Rvalue::CheckedBinaryOp(op, left, right) => {
626+
trace!(
627+
"checking CheckedBinaryOp(op = {:?}, left = {:?}, right = {:?})",
628+
op,
629+
left,
630+
right
631+
);
632+
self.check_binary_op(*op, left, right, source_info)?;
623633
}
624634

625635
// Do not try creating references (#67862)
@@ -898,54 +908,39 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> {
898908
}
899909
Operand::Constant(_) => {}
900910
}
901-
let span = terminator.source_info.span;
902-
let hir_id = self
903-
.tcx
904-
.hir()
905-
.as_local_hir_id(self.source.def_id())
906-
.expect("some part of a failing const eval must be local");
907-
self.tcx.struct_span_lint_hir(
908-
::rustc::lint::builtin::CONST_ERR,
909-
hir_id,
910-
span,
911-
|lint| {
912-
let msg = match msg {
913-
AssertKind::Overflow(_)
914-
| AssertKind::OverflowNeg
915-
| AssertKind::DivisionByZero
916-
| AssertKind::RemainderByZero => msg.description().to_owned(),
917-
AssertKind::BoundsCheck { ref len, ref index } => {
918-
let len = self
919-
.eval_operand(len, source_info)
920-
.expect("len must be const");
921-
let len = match self.ecx.read_scalar(len) {
922-
Ok(ScalarMaybeUndef::Scalar(Scalar::Raw {
923-
data,
924-
..
925-
})) => data,
926-
other => bug!("const len not primitive: {:?}", other),
927-
};
928-
let index = self
929-
.eval_operand(index, source_info)
930-
.expect("index must be const");
931-
let index = match self.ecx.read_scalar(index) {
932-
Ok(ScalarMaybeUndef::Scalar(Scalar::Raw {
933-
data,
934-
..
935-
})) => data,
936-
other => bug!("const index not primitive: {:?}", other),
937-
};
938-
format!(
939-
"index out of bounds: \
940-
the len is {} but the index is {}",
941-
len, index,
942-
)
943-
}
944-
// Need proper const propagator for these
945-
_ => return,
946-
};
947-
lint.build(&msg).emit()
948-
},
911+
let msg = match msg {
912+
AssertKind::DivisionByZero => AssertKind::DivisionByZero,
913+
AssertKind::RemainderByZero => AssertKind::RemainderByZero,
914+
AssertKind::BoundsCheck { ref len, ref index } => {
915+
let len =
916+
self.eval_operand(len, source_info).expect("len must be const");
917+
let len = self
918+
.ecx
919+
.read_scalar(len)
920+
.unwrap()
921+
.to_machine_usize(&self.tcx)
922+
.unwrap();
923+
let index = self
924+
.eval_operand(index, source_info)
925+
.expect("index must be const");
926+
let index = self
927+
.ecx
928+
.read_scalar(index)
929+
.unwrap()
930+
.to_machine_usize(&self.tcx)
931+
.unwrap();
932+
AssertKind::BoundsCheck { len, index }
933+
}
934+
// Overflow is are already covered by checks on the binary operators.
935+
AssertKind::Overflow(_) | AssertKind::OverflowNeg => return,
936+
// Need proper const propagator for these.
937+
_ => return,
938+
};
939+
self.report_assert_as_lint(
940+
lint::builtin::UNCONDITIONAL_PANIC,
941+
source_info,
942+
"this operation will panic at runtime",
943+
msg,
949944
);
950945
} else {
951946
if self.should_const_prop(value) {

src/librustc_passes/region.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
//! For more information about how MIR-based region-checking works,
55
//! see the [rustc guide].
66
//!
7-
//! [rustc guide]: https://rust-lang.github.io/rustc-guide/mir/borrowck.html
7+
//! [rustc guide]: https://rust-lang.github.io/rustc-guide/borrow_check.html
88
99
use rustc::hir::map::Map;
1010
use rustc::middle::region::*;

src/librustc_session/lint/builtin.rs

+10-3
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,15 @@ declare_lint! {
4141
}
4242

4343
declare_lint! {
44-
pub EXCEEDING_BITSHIFTS,
44+
pub ARITHMETIC_OVERFLOW,
4545
Deny,
46-
"shift exceeds the type's number of bits"
46+
"arithmetic operation overflows"
47+
}
48+
49+
declare_lint! {
50+
pub UNCONDITIONAL_PANIC,
51+
Deny,
52+
"operation will cause a panic at runtime"
4753
}
4854

4955
declare_lint! {
@@ -495,7 +501,8 @@ declare_lint_pass! {
495501
/// that are used by other parts of the compiler.
496502
HardwiredLints => [
497503
ILLEGAL_FLOATING_POINT_LITERAL_PATTERN,
498-
EXCEEDING_BITSHIFTS,
504+
ARITHMETIC_OVERFLOW,
505+
UNCONDITIONAL_PANIC,
499506
UNUSED_IMPORTS,
500507
UNUSED_EXTERN_CRATES,
501508
UNUSED_QUALIFICATIONS,

0 commit comments

Comments
 (0)