diff --git a/src/librustc_codegen_ssa/mir/analyze.rs b/src/librustc_codegen_ssa/mir/analyze.rs index 71b9ff26140f9..5ce60b8b3d406 100644 --- a/src/librustc_codegen_ssa/mir/analyze.rs +++ b/src/librustc_codegen_ssa/mir/analyze.rs @@ -204,7 +204,7 @@ impl> LocalAnalyzer<'mir, 'a, 'tcx, Bx> { }; } - self.visit_place_base(&place_ref.local, context, location); + self.visit_local(&place_ref.local, context, location); self.visit_projection(place_ref.local, place_ref.projection, context, location); } } diff --git a/src/librustc_error_codes/error_codes.rs b/src/librustc_error_codes/error_codes.rs index 9f4b5fd85fd4d..bf4a6c52ab858 100644 --- a/src/librustc_error_codes/error_codes.rs +++ b/src/librustc_error_codes/error_codes.rs @@ -386,6 +386,7 @@ E0691: include_str!("./error_codes/E0691.md"), E0692: include_str!("./error_codes/E0692.md"), E0693: include_str!("./error_codes/E0693.md"), E0695: include_str!("./error_codes/E0695.md"), +E0696: include_str!("./error_codes/E0696.md"), E0697: include_str!("./error_codes/E0697.md"), E0698: include_str!("./error_codes/E0698.md"), E0699: include_str!("./error_codes/E0699.md"), @@ -604,7 +605,6 @@ E0753: include_str!("./error_codes/E0753.md"), E0687, // in-band lifetimes cannot be used in `fn`/`Fn` syntax E0688, // in-band lifetimes cannot be mixed with explicit lifetime binders // E0694, // an unknown tool name found in scoped attributes - E0696, // `continue` pointing to a labeled block // E0702, // replaced with a generic attribute input check // E0707, // multiple elided lifetimes used in arguments of `async fn` // E0709, // multiple different lifetimes used in arguments of `async fn` diff --git a/src/librustc_error_codes/error_codes/E0696.md b/src/librustc_error_codes/error_codes/E0696.md new file mode 100644 index 0000000000000..fc32d1cc5f798 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0696.md @@ -0,0 +1,49 @@ +A function is using `continue` keyword incorrectly. + +Erroneous code example: + +```compile_fail,E0696 +fn continue_simple() { + 'b: { + continue; // error! + } +} +fn continue_labeled() { + 'b: { + continue 'b; // error! + } +} +fn continue_crossing() { + loop { + 'b: { + continue; // error! + } + } +} +``` + +Here we have used the `continue` keyword incorrectly. As we +have seen above that `continue` pointing to a labeled block. + +To fix this we have to use the labeled block properly. +For example: + +``` +fn continue_simple() { + 'b: loop { + continue ; // ok! + } +} +fn continue_labeled() { + 'b: loop { + continue 'b; // ok! + } +} +fn continue_crossing() { + loop { + 'b: loop { + continue; // ok! + } + } +} +``` diff --git a/src/librustc_middle/mir/visit.rs b/src/librustc_middle/mir/visit.rs index efc12138d3487..6335246053608 100644 --- a/src/librustc_middle/mir/visit.rs +++ b/src/librustc_middle/mir/visit.rs @@ -163,13 +163,6 @@ macro_rules! make_mir_visitor { self.super_place(place, context, location); } - fn visit_place_base(&mut self, - local: & $($mutability)? Local, - context: PlaceContext, - location: Location) { - self.super_place_base(local, context, location); - } - visit_place_fns!($($mutability)?); fn visit_constant(&mut self, @@ -710,13 +703,6 @@ macro_rules! make_mir_visitor { ); } - fn super_place_base(&mut self, - local: & $($mutability)? Local, - context: PlaceContext, - location: Location) { - self.visit_local(local, context, location); - } - fn super_local_decl(&mut self, local: Local, local_decl: & $($mutability)? LocalDecl<'tcx>) { @@ -847,7 +833,7 @@ macro_rules! visit_place_fns { context: PlaceContext, location: Location, ) { - self.visit_place_base(&mut place.local, context, location); + self.visit_local(&mut place.local, context, location); if let Some(new_projection) = self.process_projection(&place.projection, location) { place.projection = self.tcx().intern_place_elems(&new_projection); @@ -936,7 +922,7 @@ macro_rules! visit_place_fns { }; } - self.visit_place_base(&place.local, context, location); + self.visit_local(&place.local, context, location); self.visit_projection(place.local, &place.projection, context, location); } diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs index af3a9da2f6ca6..348958ee6c59a 100644 --- a/src/librustc_mir/interpret/place.rs +++ b/src/librustc_mir/interpret/place.rs @@ -333,7 +333,7 @@ where let val = self.read_immediate(src)?; trace!("deref to {} on {:?}", val.layout.ty, *val); let place = self.ref_to_mplace(val)?; - self.mplace_access_checked(place) + self.mplace_access_checked(place, None) } /// Check if the given place is good for memory access with the given @@ -358,15 +358,20 @@ where /// Return the "access-checked" version of this `MPlace`, where for non-ZST /// this is definitely a `Pointer`. + /// + /// `force_align` must only be used when correct alignment does not matter, + /// like in Stacked Borrows. pub fn mplace_access_checked( &self, mut place: MPlaceTy<'tcx, M::PointerTag>, + force_align: Option, ) -> InterpResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> { let (size, align) = self .size_and_align_of_mplace(place)? .unwrap_or((place.layout.size, place.layout.align.abi)); assert!(place.mplace.align <= align, "dynamic alignment less strict than static one?"); - place.mplace.align = align; // maximally strict checking + // Check (stricter) dynamic alignment, unless forced otherwise. + place.mplace.align = force_align.unwrap_or(align); // When dereferencing a pointer, it must be non-NULL, aligned, and live. if let Some(ptr) = self.check_mplace_access(place, Some(size))? { place.mplace.ptr = ptr.into(); diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs index 7e63d8637be93..129dfe98e5ea7 100644 --- a/src/librustc_mir/monomorphize/collector.rs +++ b/src/librustc_mir/monomorphize/collector.rs @@ -648,7 +648,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> { self.super_terminator_kind(kind, location); } - fn visit_place_base( + fn visit_local( &mut self, _place_local: &Local, _context: mir::visit::PlaceContext, diff --git a/src/librustc_mir/transform/check_consts/ops.rs b/src/librustc_mir/transform/check_consts/ops.rs index b5e62aa20130b..c4b94b70938d3 100644 --- a/src/librustc_mir/transform/check_consts/ops.rs +++ b/src/librustc_mir/transform/check_consts/ops.rs @@ -147,6 +147,10 @@ impl NonConstOp for IfOrMatch { } } +#[derive(Debug)] +pub struct InlineAsm; +impl NonConstOp for InlineAsm {} + #[derive(Debug)] pub struct LiveDrop; impl NonConstOp for LiveDrop { diff --git a/src/librustc_mir/transform/check_consts/validation.rs b/src/librustc_mir/transform/check_consts/validation.rs index c51136cdaba2c..1a0f875191b3b 100644 --- a/src/librustc_mir/transform/check_consts/validation.rs +++ b/src/librustc_mir/transform/check_consts/validation.rs @@ -276,7 +276,7 @@ impl Visitor<'tcx> for Validator<'_, 'mir, 'tcx> { PlaceContext::MutatingUse(MutatingUseContext::Borrow) } }; - self.visit_place_base(&place.local, ctx, location); + self.visit_local(&place.local, ctx, location); self.visit_projection(place.local, reborrowed_proj, ctx, location); return; } @@ -289,7 +289,7 @@ impl Visitor<'tcx> for Validator<'_, 'mir, 'tcx> { } Mutability::Mut => PlaceContext::MutatingUse(MutatingUseContext::AddressOf), }; - self.visit_place_base(&place.local, ctx, location); + self.visit_local(&place.local, ctx, location); self.visit_projection(place.local, reborrowed_proj, ctx, location); return; } @@ -386,14 +386,13 @@ impl Visitor<'tcx> for Validator<'_, 'mir, 'tcx> { } } - fn visit_place_base(&mut self, place_local: &Local, context: PlaceContext, location: Location) { + fn visit_local(&mut self, place_local: &Local, context: PlaceContext, location: Location) { trace!( - "visit_place_base: place_local={:?} context={:?} location={:?}", + "visit_local: place_local={:?} context={:?} location={:?}", place_local, context, location, ); - self.super_place_base(place_local, context, location); } fn visit_operand(&mut self, op: &Operand<'tcx>, location: Location) { @@ -478,14 +477,24 @@ impl Visitor<'tcx> for Validator<'_, 'mir, 'tcx> { StatementKind::Assign(..) | StatementKind::SetDiscriminant { .. } => { self.super_statement(statement, location); } - StatementKind::FakeRead(FakeReadCause::ForMatchedPlace, _) => { + + StatementKind::FakeRead( + FakeReadCause::ForMatchedPlace + | FakeReadCause::ForMatchGuard + | FakeReadCause::ForGuardBinding, + _, + ) => { + self.super_statement(statement, location); self.check_op(ops::IfOrMatch); } - // FIXME(eddyb) should these really do nothing? - StatementKind::FakeRead(..) + StatementKind::LlvmInlineAsm { .. } => { + self.super_statement(statement, location); + self.check_op(ops::InlineAsm); + } + + StatementKind::FakeRead(FakeReadCause::ForLet | FakeReadCause::ForIndex, _) | StatementKind::StorageLive(_) | StatementKind::StorageDead(_) - | StatementKind::LlvmInlineAsm { .. } | StatementKind::Retag { .. } | StatementKind::AscribeUserType(..) | StatementKind::Nop => {} @@ -572,7 +581,19 @@ impl Visitor<'tcx> for Validator<'_, 'mir, 'tcx> { } } - _ => {} + // FIXME: Some of these are only caught by `min_const_fn`, but should error here + // instead. + TerminatorKind::Abort + | TerminatorKind::Assert { .. } + | TerminatorKind::FalseEdges { .. } + | TerminatorKind::FalseUnwind { .. } + | TerminatorKind::GeneratorDrop + | TerminatorKind::Goto { .. } + | TerminatorKind::Resume + | TerminatorKind::Return + | TerminatorKind::SwitchInt { .. } + | TerminatorKind::Unreachable + | TerminatorKind::Yield { .. } => {} } } } diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs index 4492895104526..257b6b4a5cfae 100644 --- a/src/librustc_mir/transform/generator.rs +++ b/src/librustc_mir/transform/generator.rs @@ -115,7 +115,7 @@ impl<'tcx> MutVisitor<'tcx> for DerefArgVisitor<'tcx> { self.tcx, ); } else { - self.visit_place_base(&mut place.local, context, location); + self.visit_local(&mut place.local, context, location); for elem in place.projection.iter() { if let PlaceElem::Index(local) = elem { @@ -154,7 +154,7 @@ impl<'tcx> MutVisitor<'tcx> for PinArgVisitor<'tcx> { self.tcx, ); } else { - self.visit_place_base(&mut place.local, context, location); + self.visit_local(&mut place.local, context, location); for elem in place.projection.iter() { if let PlaceElem::Index(local) = elem { diff --git a/src/test/ui/consts/inline_asm.rs b/src/test/ui/consts/inline_asm.rs new file mode 100644 index 0000000000000..c2ab97e54f0c8 --- /dev/null +++ b/src/test/ui/consts/inline_asm.rs @@ -0,0 +1,6 @@ +#![feature(llvm_asm)] + +const _: () = unsafe { llvm_asm!("nop") }; +//~^ ERROR contains unimplemented expression type + +fn main() {} diff --git a/src/test/ui/consts/inline_asm.stderr b/src/test/ui/consts/inline_asm.stderr new file mode 100644 index 0000000000000..0a064c8136651 --- /dev/null +++ b/src/test/ui/consts/inline_asm.stderr @@ -0,0 +1,11 @@ +error[E0019]: constant contains unimplemented expression type + --> $DIR/inline_asm.rs:3:24 + | +LL | const _: () = unsafe { llvm_asm!("nop") }; + | ^^^^^^^^^^^^^^^^ + | + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0019`. diff --git a/src/test/ui/consts/miri_unleashed/inline_asm.rs b/src/test/ui/consts/miri_unleashed/inline_asm.rs index f56131025627b..ddc4767b83aa1 100644 --- a/src/test/ui/consts/miri_unleashed/inline_asm.rs +++ b/src/test/ui/consts/miri_unleashed/inline_asm.rs @@ -11,4 +11,6 @@ static TEST_BAD: () = { //~^ ERROR could not evaluate static initializer //~| NOTE in this expansion of llvm_asm! //~| NOTE inline assembly is not supported + //~| WARN skipping const checks + //~| NOTE in this expansion of llvm_asm! }; diff --git a/src/test/ui/consts/miri_unleashed/inline_asm.stderr b/src/test/ui/consts/miri_unleashed/inline_asm.stderr index 3cbdd326c8233..444a0172621e2 100644 --- a/src/test/ui/consts/miri_unleashed/inline_asm.stderr +++ b/src/test/ui/consts/miri_unleashed/inline_asm.stderr @@ -1,3 +1,11 @@ +warning: skipping const checks + --> $DIR/inline_asm.rs:10:14 + | +LL | unsafe { llvm_asm!("xor %eax, %eax" ::: "eax"); } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this warning originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + error[E0080]: could not evaluate static initializer --> $DIR/inline_asm.rs:10:14 | @@ -6,6 +14,6 @@ LL | unsafe { llvm_asm!("xor %eax, %eax" ::: "eax"); } | = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to previous error +error: aborting due to previous error; 1 warning emitted For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/label/label_break_value_continue.stderr b/src/test/ui/label/label_break_value_continue.stderr index c5f79ed6333ee..9b8693dc584c4 100644 --- a/src/test/ui/label/label_break_value_continue.stderr +++ b/src/test/ui/label/label_break_value_continue.stderr @@ -21,4 +21,5 @@ LL | continue; error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0695`. +Some errors have detailed explanations: E0695, E0696. +For more information about an error, try `rustc --explain E0695`.