From 2c879e3f6812f0536d2f1330c2373ddfb049014e Mon Sep 17 00:00:00 2001 From: Ryan1729 Date: Sun, 2 Aug 2020 18:19:33 -0600 Subject: [PATCH 01/54] make parts of rustc_typeck public --- src/librustc_typeck/check/cast.rs | 4 ++-- src/librustc_typeck/check/mod.rs | 2 +- src/librustc_typeck/lib.rs | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs index a877df68326d6..418ea29b84f2f 100644 --- a/src/librustc_typeck/check/cast.rs +++ b/src/librustc_typeck/check/cast.rs @@ -147,7 +147,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } #[derive(Copy, Clone)] -enum CastError { +pub enum CastError { ErrorReported, CastToBool, @@ -593,7 +593,7 @@ impl<'a, 'tcx> CastCheck<'tcx> { /// Checks a cast, and report an error if one exists. In some cases, this /// can return Ok and create type errors in the fcx rather than returning /// directly. coercion-cast is handled in check instead of here. - fn do_check(&self, fcx: &FnCtxt<'a, 'tcx>) -> Result { + pub fn do_check(&self, fcx: &FnCtxt<'a, 'tcx>) -> Result { use rustc_middle::ty::cast::CastTy::*; use rustc_middle::ty::cast::IntTy::*; diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 63e9e9a821502..83581a7083a0e 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -67,7 +67,7 @@ type parameter). pub mod _match; mod autoderef; mod callee; -mod cast; +pub mod cast; mod closure; pub mod coercion; mod compare_method; diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index 056090baa22d0..2a49341efbb5c 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -74,11 +74,11 @@ extern crate log; #[macro_use] extern crate rustc_middle; -// This is used by Clippy. +// These are used by Clippy. pub mod expr_use_visitor; +pub mod check; mod astconv; -mod check; mod check_unused; mod coherence; mod collect; From f029a9a90afe3acbea605b3bd82e68708796ebd1 Mon Sep 17 00:00:00 2001 From: Ryan1729 Date: Sun, 2 Aug 2020 18:41:50 -0600 Subject: [PATCH 02/54] run cargo dev new_lint then move transmutes_expressible_as_ptr_casts into transmute module --- src/tools/clippy/CHANGELOG.md | 1 + src/tools/clippy/clippy_lints/src/lib.rs | 3 +++ .../clippy/clippy_lints/src/transmute.rs | 23 +++++++++++++++++++ src/tools/clippy/src/lintlist/mod.rs | 7 ++++++ .../ui/transmutes_expressible_as_ptr_casts.rs | 5 ++++ 5 files changed, 39 insertions(+) create mode 100644 src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.rs diff --git a/src/tools/clippy/CHANGELOG.md b/src/tools/clippy/CHANGELOG.md index 776b04295f949..a6e6949101775 100644 --- a/src/tools/clippy/CHANGELOG.md +++ b/src/tools/clippy/CHANGELOG.md @@ -1730,6 +1730,7 @@ Released 2018-09-13 [`transmute_int_to_float`]: https://rust-lang.github.io/rust-clippy/master/index.html#transmute_int_to_float [`transmute_ptr_to_ptr`]: https://rust-lang.github.io/rust-clippy/master/index.html#transmute_ptr_to_ptr [`transmute_ptr_to_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#transmute_ptr_to_ref +[`transmutes_expressible_as_ptr_casts`]: https://rust-lang.github.io/rust-clippy/master/index.html#transmutes_expressible_as_ptr_casts [`transmuting_null`]: https://rust-lang.github.io/rust-clippy/master/index.html#transmuting_null [`trivial_regex`]: https://rust-lang.github.io/rust-clippy/master/index.html#trivial_regex [`trivially_copy_pass_by_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#trivially_copy_pass_by_ref diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs index f371942dbeec5..87b5309ff1c71 100644 --- a/src/tools/clippy/clippy_lints/src/lib.rs +++ b/src/tools/clippy/clippy_lints/src/lib.rs @@ -798,6 +798,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &transmute::UNSOUND_COLLECTION_TRANSMUTE, &transmute::USELESS_TRANSMUTE, &transmute::WRONG_TRANSMUTE, + &transmute::TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS, &transmuting_null::TRANSMUTING_NULL, &trivially_copy_pass_by_ref::TRIVIALLY_COPY_PASS_BY_REF, &try_err::TRY_ERR, @@ -1426,6 +1427,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&transmute::TRANSMUTE_PTR_TO_REF), LintId::of(&transmute::UNSOUND_COLLECTION_TRANSMUTE), LintId::of(&transmute::WRONG_TRANSMUTE), + LintId::of(&transmute::TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS), LintId::of(&transmuting_null::TRANSMUTING_NULL), LintId::of(&try_err::TRY_ERR), LintId::of(&types::ABSURD_EXTREME_COMPARISONS), @@ -1624,6 +1626,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&transmute::TRANSMUTE_INT_TO_FLOAT), LintId::of(&transmute::TRANSMUTE_PTR_TO_PTR), LintId::of(&transmute::TRANSMUTE_PTR_TO_REF), + LintId::of(&transmute::TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS), LintId::of(&types::BORROWED_BOX), LintId::of(&types::CHAR_LIT_AS_U8), LintId::of(&types::TYPE_COMPLEXITY), diff --git a/src/tools/clippy/clippy_lints/src/transmute.rs b/src/tools/clippy/clippy_lints/src/transmute.rs index d55eb1a0c9387..ce2ac24f5325f 100644 --- a/src/tools/clippy/clippy_lints/src/transmute.rs +++ b/src/tools/clippy/clippy_lints/src/transmute.rs @@ -269,6 +269,28 @@ declare_clippy_lint! { correctness, "transmute between collections of layout-incompatible types" } + +declare_clippy_lint! { + /// **What it does:** + /// + /// **Why is this bad?** + /// + /// **Known problems:** None. + /// + /// **Example:** + /// + /// ```rust + /// // example code where clippy issues a warning + /// ``` + /// Use instead: + /// ```rust + /// // example code which does not raise clippy warning + /// ``` + pub TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS, + complexity, + "default lint description" +} + declare_lint_pass!(Transmute => [ CROSSPOINTER_TRANSMUTE, TRANSMUTE_PTR_TO_REF, @@ -281,6 +303,7 @@ declare_lint_pass!(Transmute => [ TRANSMUTE_INT_TO_FLOAT, TRANSMUTE_FLOAT_TO_INT, UNSOUND_COLLECTION_TRANSMUTE, + TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS, ]); // used to check for UNSOUND_COLLECTION_TRANSMUTE diff --git a/src/tools/clippy/src/lintlist/mod.rs b/src/tools/clippy/src/lintlist/mod.rs index 1879aae77fb65..9363039041da4 100644 --- a/src/tools/clippy/src/lintlist/mod.rs +++ b/src/tools/clippy/src/lintlist/mod.rs @@ -2215,6 +2215,13 @@ pub static ref ALL_LINTS: Vec = vec![ deprecation: None, module: "transmute", }, + Lint { + name: "transmutes_expressible_as_ptr_casts", + group: "complexity", + desc: "default lint description", + deprecation: None, + module: "transmute", + }, Lint { name: "transmuting_null", group: "correctness", diff --git a/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.rs b/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.rs new file mode 100644 index 0000000000000..2b32ae213fbbb --- /dev/null +++ b/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.rs @@ -0,0 +1,5 @@ +#![warn(clippy::transmutes_expressible_as_ptr_casts)] + +fn main() { + // test code goes here +} From 1ee2a78034cdefefae4ee1d9294c1745729390d7 Mon Sep 17 00:00:00 2001 From: Ryan1729 Date: Sun, 2 Aug 2020 21:30:25 -0600 Subject: [PATCH 03/54] make InheritedBuilder::enter public --- src/librustc_typeck/check/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 83581a7083a0e..a40b6860f7765 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -648,7 +648,7 @@ impl Inherited<'_, 'tcx> { } impl<'tcx> InheritedBuilder<'tcx> { - fn enter(&mut self, f: F) -> R + pub fn enter(&mut self, f: F) -> R where F: for<'a> FnOnce(Inherited<'a, 'tcx>) -> R, { From 2ee5d382822a28ac89b0c4b87ff45a49fd37140a Mon Sep 17 00:00:00 2001 From: Ryan1729 Date: Sun, 2 Aug 2020 22:00:51 -0600 Subject: [PATCH 04/54] initial compiling version of TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS --- .../clippy/clippy_lints/src/transmute.rs | 74 ++++++++++++++++++- 1 file changed, 72 insertions(+), 2 deletions(-) diff --git a/src/tools/clippy/clippy_lints/src/transmute.rs b/src/tools/clippy/clippy_lints/src/transmute.rs index ce2ac24f5325f..d5b694ce3118d 100644 --- a/src/tools/clippy/clippy_lints/src/transmute.rs +++ b/src/tools/clippy/clippy_lints/src/transmute.rs @@ -7,8 +7,10 @@ use rustc_ast::ast; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind, GenericArg, Mutability, QPath, TyKind, UnOp}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_middle::ty::{self, Ty}; +use rustc_middle::ty::{self, cast::CastKind, Ty}; +use rustc_span::DUMMY_SP; use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_typeck::check::{cast::CastCheck, FnCtxt, Inherited}; use std::borrow::Cow; declare_clippy_lint! { @@ -624,7 +626,21 @@ impl<'tcx> LateLintPass<'tcx> for Transmute { ); } }, - _ => return, + (_, _) if can_be_expressed_as_pointer_cast(cx, e, from_ty, to_ty) => { + span_lint( + cx, + TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS, + e.span, + &format!( + "transmute from `{}` to `{}` which could be expressed as a pointer cast instead", + from_ty, + to_ty + ) + ); + }, + _ => { + return + }, } } } @@ -671,3 +687,57 @@ fn is_layout_incompatible<'tcx>(cx: &LateContext<'tcx>, from: Ty<'tcx>, to: Ty<' false } } + +/// Check if the the type conversion can be expressed as a pointer cast, instead of a transmute. +fn can_be_expressed_as_pointer_cast<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>, from_ty: Ty<'tcx>, to_ty: Ty<'tcx>) -> bool { + use CastKind::*; + matches!( + check_cast(cx, e, from_ty, to_ty), + Some( + PtrPtrCast + | PtrAddrCast + | AddrPtrCast + | ArrayPtrCast + | FnPtrPtrCast + | FnPtrAddrCast + ) + ) +} + +/// If a cast from from_ty to to_ty is valid, returns an Ok containing the kind of the cast. +fn check_cast<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>, from_ty: Ty<'tcx>, to_ty: Ty<'tcx>) -> Option { + let hir_id = e.hir_id; + let local_def_id = hir_id.owner; + + Inherited::build(cx.tcx, local_def_id).enter(|inherited| { + let fn_ctxt = FnCtxt::new( + &inherited, + // TODO should we try to get the correct ParamEnv? + ty::ParamEnv::empty(), + hir_id + ); + + // If we already have errors, we can't be sure we can pointer cast. + if fn_ctxt.errors_reported_since_creation() { + return None; + } + + if let Ok(check) = CastCheck::new( + &fn_ctxt, + e, + from_ty, + to_ty, + // We won't show any error to the user, so we don't care what the span is here. + DUMMY_SP, + DUMMY_SP, + ) { + check.do_check(&fn_ctxt) + .ok() + // do_check's documentation says that it might return Ok and create + // errors in the fcx instead of returing Err in some cases. + .filter(|_| !fn_ctxt.errors_reported_since_creation()) + } else { + None + } + }) +} \ No newline at end of file From 499ca743d72a20bbee16b9ebadce29d55c1cc8a7 Mon Sep 17 00:00:00 2001 From: Ryan1729 Date: Sun, 2 Aug 2020 23:17:11 -0600 Subject: [PATCH 05/54] write currently failing test for transmutes_expressible_as_ptr_casts There are 5 errors, when there should be 7. --- .../ui/transmutes_expressible_as_ptr_casts.rs | 54 ++++++++++++++++++- ...transmutes_expressible_as_ptr_casts.stderr | 1 + 2 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.stderr diff --git a/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.rs b/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.rs index 2b32ae213fbbb..e6b9dddd34216 100644 --- a/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.rs +++ b/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.rs @@ -1,5 +1,57 @@ #![warn(clippy::transmutes_expressible_as_ptr_casts)] +// rustc_typeck::check::cast contains documentation about when a cast `e as U` is +// valid, which we quote from below. +use std::mem::transmute; + fn main() { - // test code goes here + // e is an integer and U is *U_0, while U_0: Sized; addr-ptr-cast + let ptr_i32_transmute = unsafe { + transmute::(-1) + }; + let ptr_i32 = -1isize as *const i32; + + // e has type *T, U is *U_0, and either U_0: Sized ... + let ptr_i8_transmute = unsafe { + transmute::<*const i32, *const i8>(ptr_i32) + }; + let ptr_i8 = ptr_i32 as *const i8; + + let slice_ptr = &[0,1,2,3] as *const [i32]; + + // ... or pointer_kind(T) = pointer_kind(U_0); ptr-ptr-cast + let ptr_to_unsized_transmute = unsafe { + transmute::<*const [i32], *const [u16]>(slice_ptr) + }; + let ptr_to_unsized = slice_ptr as *const [u16]; + // TODO: We could try testing vtable casts here too, but maybe + // we should wait until std::raw::TraitObject is stabilized? + + // e has type *T and U is a numeric type, while T: Sized; ptr-addr-cast + let usize_from_int_ptr_transmute = unsafe { + transmute::<*const i32, usize>(ptr_i32) + }; + let usize_from_int_ptr = ptr_i32 as usize; + + let array_ref: &[i32; 4] = &[1,2,3,4]; + + // e has type &[T; n] and U is *const T; array-ptr-cast + let array_ptr_transmute = unsafe { + transmute::<&[i32; 4], *const [i32; 4]>(array_ref) + }; + let array_ptr = array_ref as *const [i32; 4]; + + fn foo(_: usize) -> u8 { 42 } + + // e is a function pointer type and U has type *T, while T: Sized; fptr-ptr-cast + let usize_ptr_transmute = unsafe { + transmute:: u8, *const usize>(foo) + }; + let usize_ptr_transmute = foo as *const usize; + + // e is a function pointer type and U is an integer; fptr-addr-cast + let usize_from_fn_ptr_transmute = unsafe { + transmute:: u8, usize>(foo) + }; + let usize_from_fn_ptr = foo as *const usize; } diff --git a/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.stderr b/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.stderr new file mode 100644 index 0000000000000..6bae1fa1b4fc6 --- /dev/null +++ b/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.stderr @@ -0,0 +1 @@ +Should have 7 errors, one for each transmute From 338780cdb68a33e1ec5dea788398d722ce1368dc Mon Sep 17 00:00:00 2001 From: Ryan1729 Date: Mon, 3 Aug 2020 00:16:11 -0600 Subject: [PATCH 06/54] accidentally cause an ICE by putting the TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS handling after the match The reason I did this in the first place was to try and figure out why I don't see my expected 7 error messages --- .../clippy/clippy_lints/src/transmute.rs | 34 +++++++++++-------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/src/tools/clippy/clippy_lints/src/transmute.rs b/src/tools/clippy/clippy_lints/src/transmute.rs index d5b694ce3118d..d6b1a5df71fa0 100644 --- a/src/tools/clippy/clippy_lints/src/transmute.rs +++ b/src/tools/clippy/clippy_lints/src/transmute.rs @@ -626,21 +626,25 @@ impl<'tcx> LateLintPass<'tcx> for Transmute { ); } }, - (_, _) if can_be_expressed_as_pointer_cast(cx, e, from_ty, to_ty) => { - span_lint( - cx, - TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS, - e.span, - &format!( - "transmute from `{}` to `{}` which could be expressed as a pointer cast instead", - from_ty, - to_ty - ) - ); - }, - _ => { - return - }, + _ => {}, + } + if can_be_expressed_as_pointer_cast(cx, e, from_ty, to_ty) { + span_lint_and_then( + cx, + TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS, + e.span, + &format!( + "transmute from `{}` to `{}` which could be expressed as a pointer cast instead", + from_ty, + to_ty + ), + |diag| { + if let Some(arg) = sugg::Sugg::hir_opt(cx, &args[0]) { + let sugg = format!("{} as {}", arg, to_ty); + diag.span_suggestion(e.span, "try", sugg, Applicability::Unspecified); + } + } + ) } } } From 3f73082d024162a13dc527bb77ca256a4fdf5838 Mon Sep 17 00:00:00 2001 From: Ryan1729 Date: Mon, 3 Aug 2020 00:54:03 -0600 Subject: [PATCH 07/54] try putting the can_be_expressed_as_pointer_cast at the top and find that we still get an ICE --- .../clippy/clippy_lints/src/transmute.rs | 42 ++++++++++--------- src/tools/clippy/tests/ui/transmute.rs | 2 +- .../clippy/tests/ui/transmute_ptr_to_ptr.rs | 2 +- 3 files changed, 25 insertions(+), 21 deletions(-) diff --git a/src/tools/clippy/clippy_lints/src/transmute.rs b/src/tools/clippy/clippy_lints/src/transmute.rs index d6b1a5df71fa0..7ab3f0d96763c 100644 --- a/src/tools/clippy/clippy_lints/src/transmute.rs +++ b/src/tools/clippy/clippy_lints/src/transmute.rs @@ -330,6 +330,26 @@ impl<'tcx> LateLintPass<'tcx> for Transmute { let from_ty = cx.typeck_results().expr_ty(&args[0]); let to_ty = cx.typeck_results().expr_ty(e); + if can_be_expressed_as_pointer_cast(cx, e, from_ty, to_ty) { + span_lint_and_then( + cx, + TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS, + e.span, + &format!( + "transmute from `{}` to `{}` which could be expressed as a pointer cast instead", + from_ty, + to_ty + ), + |diag| { + if let Some(arg) = sugg::Sugg::hir_opt(cx, &args[0]) { + let sugg = format!("{} as {}", arg, to_ty); + diag.span_suggestion(e.span, "try", sugg, Applicability::Unspecified); + } + } + ); + return + } + match (&from_ty.kind, &to_ty.kind) { _ if from_ty == to_ty => span_lint( cx, @@ -626,25 +646,9 @@ impl<'tcx> LateLintPass<'tcx> for Transmute { ); } }, - _ => {}, - } - if can_be_expressed_as_pointer_cast(cx, e, from_ty, to_ty) { - span_lint_and_then( - cx, - TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS, - e.span, - &format!( - "transmute from `{}` to `{}` which could be expressed as a pointer cast instead", - from_ty, - to_ty - ), - |diag| { - if let Some(arg) = sugg::Sugg::hir_opt(cx, &args[0]) { - let sugg = format!("{} as {}", arg, to_ty); - diag.span_suggestion(e.span, "try", sugg, Applicability::Unspecified); - } - } - ) + _ => { + return; + }, } } } diff --git a/src/tools/clippy/tests/ui/transmute.rs b/src/tools/clippy/tests/ui/transmute.rs index bb853d237047f..b3171d2e7dcfd 100644 --- a/src/tools/clippy/tests/ui/transmute.rs +++ b/src/tools/clippy/tests/ui/transmute.rs @@ -1,7 +1,7 @@ #![allow(dead_code)] +#![allow(clippy::transmutes_expressible_as_ptr_casts)] extern crate core; - use std::mem::transmute as my_transmute; use std::vec::Vec as MyVec; diff --git a/src/tools/clippy/tests/ui/transmute_ptr_to_ptr.rs b/src/tools/clippy/tests/ui/transmute_ptr_to_ptr.rs index 0d8a322f2b2b0..009b5fa534cf0 100644 --- a/src/tools/clippy/tests/ui/transmute_ptr_to_ptr.rs +++ b/src/tools/clippy/tests/ui/transmute_ptr_to_ptr.rs @@ -1,5 +1,5 @@ #![warn(clippy::transmute_ptr_to_ptr)] - +#![allow(clippy::transmutes_expressible_as_ptr_casts)] // Make sure we can modify lifetimes, which is one of the recommended uses // of transmute From 90e1ae1ef9a6c8a64ec2553bae4dbec123fed0bd Mon Sep 17 00:00:00 2001 From: Ryan1729 Date: Mon, 3 Aug 2020 02:47:25 -0600 Subject: [PATCH 08/54] get the expected number of errors by acknowledging that other lints are covering the same ground --- .../clippy/clippy_lints/src/transmute.rs | 80 +++++++++---------- src/tools/clippy/tests/ui/transmute.rs | 2 +- .../clippy/tests/ui/transmute_ptr_to_ptr.rs | 2 +- .../ui/transmutes_expressible_as_ptr_casts.rs | 10 ++- ...transmutes_expressible_as_ptr_casts.stderr | 51 +++++++++++- 5 files changed, 100 insertions(+), 45 deletions(-) diff --git a/src/tools/clippy/clippy_lints/src/transmute.rs b/src/tools/clippy/clippy_lints/src/transmute.rs index 7ab3f0d96763c..269d2f00353aa 100644 --- a/src/tools/clippy/clippy_lints/src/transmute.rs +++ b/src/tools/clippy/clippy_lints/src/transmute.rs @@ -50,6 +50,29 @@ declare_clippy_lint! { "transmutes that have the same to and from types or could be a cast/coercion" } +// FIXME: Merge this lint with USELESS_TRANSMUTE once that is out of the nursery. +declare_clippy_lint! { + /// **What it does:**Checks for transmutes that could be a pointer cast. + /// + /// **Why is this bad?** Readability. The code tricks people into thinking that + /// something complex is going on. + /// + /// **Known problems:** None. + /// + /// **Example:** + /// + /// ```rust,ignore + /// core::intrinsics::transmute::<*const [i32], *const [u16]>(p) + /// ``` + /// Use instead: + /// ```rust + /// p as *const [u16] + /// ``` + pub TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS, + complexity, + "transmutes that could be a pointer cast" +} + declare_clippy_lint! { /// **What it does:** Checks for transmutes between a type `T` and `*T`. /// @@ -272,27 +295,6 @@ declare_clippy_lint! { "transmute between collections of layout-incompatible types" } -declare_clippy_lint! { - /// **What it does:** - /// - /// **Why is this bad?** - /// - /// **Known problems:** None. - /// - /// **Example:** - /// - /// ```rust - /// // example code where clippy issues a warning - /// ``` - /// Use instead: - /// ```rust - /// // example code which does not raise clippy warning - /// ``` - pub TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS, - complexity, - "default lint description" -} - declare_lint_pass!(Transmute => [ CROSSPOINTER_TRANSMUTE, TRANSMUTE_PTR_TO_REF, @@ -330,26 +332,6 @@ impl<'tcx> LateLintPass<'tcx> for Transmute { let from_ty = cx.typeck_results().expr_ty(&args[0]); let to_ty = cx.typeck_results().expr_ty(e); - if can_be_expressed_as_pointer_cast(cx, e, from_ty, to_ty) { - span_lint_and_then( - cx, - TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS, - e.span, - &format!( - "transmute from `{}` to `{}` which could be expressed as a pointer cast instead", - from_ty, - to_ty - ), - |diag| { - if let Some(arg) = sugg::Sugg::hir_opt(cx, &args[0]) { - let sugg = format!("{} as {}", arg, to_ty); - diag.span_suggestion(e.span, "try", sugg, Applicability::Unspecified); - } - } - ); - return - } - match (&from_ty.kind, &to_ty.kind) { _ if from_ty == to_ty => span_lint( cx, @@ -646,6 +628,22 @@ impl<'tcx> LateLintPass<'tcx> for Transmute { ); } }, + (_, _) if can_be_expressed_as_pointer_cast(cx, e, from_ty, to_ty) => span_lint_and_then( + cx, + TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS, + e.span, + &format!( + "transmute from `{}` to `{}` which could be expressed as a pointer cast instead", + from_ty, + to_ty + ), + |diag| { + if let Some(arg) = sugg::Sugg::hir_opt(cx, &args[0]) { + let sugg = arg.as_ty(&to_ty.to_string()).to_string(); + diag.span_suggestion(e.span, "try", sugg, Applicability::Unspecified); + } + } + ), _ => { return; }, diff --git a/src/tools/clippy/tests/ui/transmute.rs b/src/tools/clippy/tests/ui/transmute.rs index b3171d2e7dcfd..bb853d237047f 100644 --- a/src/tools/clippy/tests/ui/transmute.rs +++ b/src/tools/clippy/tests/ui/transmute.rs @@ -1,7 +1,7 @@ #![allow(dead_code)] -#![allow(clippy::transmutes_expressible_as_ptr_casts)] extern crate core; + use std::mem::transmute as my_transmute; use std::vec::Vec as MyVec; diff --git a/src/tools/clippy/tests/ui/transmute_ptr_to_ptr.rs b/src/tools/clippy/tests/ui/transmute_ptr_to_ptr.rs index 009b5fa534cf0..0d8a322f2b2b0 100644 --- a/src/tools/clippy/tests/ui/transmute_ptr_to_ptr.rs +++ b/src/tools/clippy/tests/ui/transmute_ptr_to_ptr.rs @@ -1,5 +1,5 @@ #![warn(clippy::transmute_ptr_to_ptr)] -#![allow(clippy::transmutes_expressible_as_ptr_casts)] + // Make sure we can modify lifetimes, which is one of the recommended uses // of transmute diff --git a/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.rs b/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.rs index e6b9dddd34216..db544b438a28f 100644 --- a/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.rs +++ b/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.rs @@ -1,10 +1,18 @@ #![warn(clippy::transmutes_expressible_as_ptr_casts)] +// These two warnings currrently cover the cases transmutes_expressible_as_ptr_casts +// would otherwise be responsible for +#![warn(clippy::useless_transmute)] +#![warn(clippy::transmute_ptr_to_ptr)] + +use std::mem::transmute; // rustc_typeck::check::cast contains documentation about when a cast `e as U` is // valid, which we quote from below. -use std::mem::transmute; fn main() { + // We should see an error message for each transmute, and no error messages for + // the casts, since the casts are the recommended fixes. + // e is an integer and U is *U_0, while U_0: Sized; addr-ptr-cast let ptr_i32_transmute = unsafe { transmute::(-1) diff --git a/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.stderr b/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.stderr index 6bae1fa1b4fc6..7cd316bf38aac 100644 --- a/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.stderr +++ b/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.stderr @@ -1 +1,50 @@ -Should have 7 errors, one for each transmute +error: transmute from an integer to a pointer + --> $DIR/transmutes_expressible_as_ptr_casts.rs:18:9 + | +LL | transmute::(-1) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `-1 as *const i32` + | + = note: `-D clippy::useless-transmute` implied by `-D warnings` + +error: transmute from a pointer to a pointer + --> $DIR/transmutes_expressible_as_ptr_casts.rs:24:9 + | +LL | transmute::<*const i32, *const i8>(ptr_i32) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `ptr_i32 as *const i8` + | + = note: `-D clippy::transmute-ptr-to-ptr` implied by `-D warnings` + +error: transmute from a pointer to a pointer + --> $DIR/transmutes_expressible_as_ptr_casts.rs:32:9 + | +LL | transmute::<*const [i32], *const [u16]>(slice_ptr) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `slice_ptr as *const [u16]` + +error: transmute from `*const i32` to `usize` which could be expressed as a pointer cast instead + --> $DIR/transmutes_expressible_as_ptr_casts.rs:40:9 + | +LL | transmute::<*const i32, usize>(ptr_i32) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `ptr_i32 as usize` + | + = note: `-D clippy::transmutes-expressible-as-ptr-casts` implied by `-D warnings` + +error: transmute from a reference to a pointer + --> $DIR/transmutes_expressible_as_ptr_casts.rs:48:9 + | +LL | transmute::<&[i32; 4], *const [i32; 4]>(array_ref) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `array_ref as *const [i32; 4]` + +error: transmute from `fn(usize) -> u8 {main::foo}` to `*const usize` which could be expressed as a pointer cast instead + --> $DIR/transmutes_expressible_as_ptr_casts.rs:56:9 + | +LL | transmute:: u8, *const usize>(foo) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `foo as *const usize` + +error: transmute from `fn(usize) -> u8 {main::foo}` to `usize` which could be expressed as a pointer cast instead + --> $DIR/transmutes_expressible_as_ptr_casts.rs:62:9 + | +LL | transmute:: u8, usize>(foo) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `foo as usize` + +error: aborting due to 7 previous errors + From fb837873626d9fb799d2ab822c5a9f5b73a9483e Mon Sep 17 00:00:00 2001 From: Ryan1729 Date: Mon, 3 Aug 2020 19:00:38 -0600 Subject: [PATCH 09/54] address some review comments --- src/tools/clippy/clippy_lints/src/transmute.rs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/tools/clippy/clippy_lints/src/transmute.rs b/src/tools/clippy/clippy_lints/src/transmute.rs index 269d2f00353aa..b6747c73f7057 100644 --- a/src/tools/clippy/clippy_lints/src/transmute.rs +++ b/src/tools/clippy/clippy_lints/src/transmute.rs @@ -718,15 +718,12 @@ fn check_cast<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>, from_ty: Ty<'tcx> Inherited::build(cx.tcx, local_def_id).enter(|inherited| { let fn_ctxt = FnCtxt::new( &inherited, - // TODO should we try to get the correct ParamEnv? - ty::ParamEnv::empty(), + cx.param_env, hir_id ); // If we already have errors, we can't be sure we can pointer cast. - if fn_ctxt.errors_reported_since_creation() { - return None; - } + assert!(!fn_ctxt.errors_reported_since_creation()); if let Ok(check) = CastCheck::new( &fn_ctxt, @@ -746,4 +743,4 @@ fn check_cast<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>, from_ty: Ty<'tcx> None } }) -} \ No newline at end of file +} From 336f06ebc66638e85715336394f3bd9a8c6949a3 Mon Sep 17 00:00:00 2001 From: Ryan1729 Date: Tue, 4 Aug 2020 16:45:47 -0600 Subject: [PATCH 10/54] add description to assert --- src/tools/clippy/clippy_lints/src/transmute.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/tools/clippy/clippy_lints/src/transmute.rs b/src/tools/clippy/clippy_lints/src/transmute.rs index b6747c73f7057..ea14f2829ea52 100644 --- a/src/tools/clippy/clippy_lints/src/transmute.rs +++ b/src/tools/clippy/clippy_lints/src/transmute.rs @@ -723,7 +723,10 @@ fn check_cast<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>, from_ty: Ty<'tcx> ); // If we already have errors, we can't be sure we can pointer cast. - assert!(!fn_ctxt.errors_reported_since_creation()); + assert!( + !fn_ctxt.errors_reported_since_creation(), + "Newly created FnCtxt contained errors" + ); if let Ok(check) = CastCheck::new( &fn_ctxt, From 7edfd435e98866dfdef31112b90b3b91f22bedc1 Mon Sep 17 00:00:00 2001 From: Ryan1729 Date: Wed, 5 Aug 2020 20:23:29 -0600 Subject: [PATCH 11/54] add documentation to functions that call `do_check` and add a test against lint ordering changing --- src/tools/clippy/clippy_lints/src/transmute.rs | 10 ++++++++-- .../tests/ui/transmutes_expressible_as_ptr_casts.rs | 11 +++++++++++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/src/tools/clippy/clippy_lints/src/transmute.rs b/src/tools/clippy/clippy_lints/src/transmute.rs index ea14f2829ea52..231f13b236c18 100644 --- a/src/tools/clippy/clippy_lints/src/transmute.rs +++ b/src/tools/clippy/clippy_lints/src/transmute.rs @@ -694,7 +694,10 @@ fn is_layout_incompatible<'tcx>(cx: &LateContext<'tcx>, from: Ty<'tcx>, to: Ty<' } } -/// Check if the the type conversion can be expressed as a pointer cast, instead of a transmute. +/// Check if the the type conversion can be expressed as a pointer cast, instead of +/// a transmute. In certain cases, including some invalid casts from array +/// references to pointers, this may cause additional errors to be emitted and/or +/// ICE error messages. fn can_be_expressed_as_pointer_cast<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>, from_ty: Ty<'tcx>, to_ty: Ty<'tcx>) -> bool { use CastKind::*; matches!( @@ -710,7 +713,10 @@ fn can_be_expressed_as_pointer_cast<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr< ) } -/// If a cast from from_ty to to_ty is valid, returns an Ok containing the kind of the cast. +/// If a cast from from_ty to to_ty is valid, returns an Ok containing the kind of +/// the cast. In certain cases, including some invalid casts from array references +/// to pointers, this may cause additional errors to be emitted and/or ICE error +/// messages. fn check_cast<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>, from_ty: Ty<'tcx>, to_ty: Ty<'tcx>) -> Option { let hir_id = e.hir_id; let local_def_id = hir_id.owner; diff --git a/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.rs b/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.rs index db544b438a28f..007526da40df8 100644 --- a/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.rs +++ b/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.rs @@ -63,3 +63,14 @@ fn main() { }; let usize_from_fn_ptr = foo as *const usize; } + +// If a ref-to-ptr cast of this form where the pointer type points to a type other +// than the referenced type, calling `CastCheck::do_check` has been observed to +// cause an ICE error message. `do_check` is currently called inside the +// `transmutes_expressible_as_ptr_casts` check, but other, more specific lints +// currently prevent it from being called in these cases. This test is meant to +// fail if the ordering of the checks ever changes enough to cause these cases to +// fall through into `do_check`. +fn trigger_do_check_to_emit_error(in_param: &[i32; 1]) -> *const u8 { + unsafe { transmute::<&[i32; 1], *const u8>(in_param) } +} \ No newline at end of file From 6af3fbe7ffeea291c1f3be355e097cb965723c05 Mon Sep 17 00:00:00 2001 From: Ryan1729 Date: Wed, 5 Aug 2020 21:28:22 -0600 Subject: [PATCH 12/54] add extra error message to the expected stderr for transmutes_expressible_as_ptr_casts test --- .../tests/ui/transmutes_expressible_as_ptr_casts.stderr | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.stderr b/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.stderr index 7cd316bf38aac..e6edacbd0de8e 100644 --- a/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.stderr +++ b/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.stderr @@ -46,5 +46,11 @@ error: transmute from `fn(usize) -> u8 {main::foo}` to `usize` which could be ex LL | transmute:: u8, usize>(foo) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `foo as usize` -error: aborting due to 7 previous errors +error: transmute from a reference to a pointer + --> $DIR/transmutes_expressible_as_ptr_casts.rs:75:14 + | +LL | unsafe { transmute::<&[i32; 1], *const u8>(in_param) } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `in_param as *const [i32; 1] as *const u8` + +error: aborting due to 8 previous errors From 16316004116cf20e3ae4e1b23d3315ecd5cf3c6f Mon Sep 17 00:00:00 2001 From: Ryan1729 Date: Thu, 6 Aug 2020 04:18:14 -0600 Subject: [PATCH 13/54] change filter to assert, and update comments --- .../clippy/clippy_lints/src/transmute.rs | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/src/tools/clippy/clippy_lints/src/transmute.rs b/src/tools/clippy/clippy_lints/src/transmute.rs index 231f13b236c18..9f356811f2204 100644 --- a/src/tools/clippy/clippy_lints/src/transmute.rs +++ b/src/tools/clippy/clippy_lints/src/transmute.rs @@ -697,7 +697,7 @@ fn is_layout_incompatible<'tcx>(cx: &LateContext<'tcx>, from: Ty<'tcx>, to: Ty<' /// Check if the the type conversion can be expressed as a pointer cast, instead of /// a transmute. In certain cases, including some invalid casts from array /// references to pointers, this may cause additional errors to be emitted and/or -/// ICE error messages. +/// ICE error messages. This function will panic if that occurs. fn can_be_expressed_as_pointer_cast<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>, from_ty: Ty<'tcx>, to_ty: Ty<'tcx>) -> bool { use CastKind::*; matches!( @@ -716,7 +716,7 @@ fn can_be_expressed_as_pointer_cast<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr< /// If a cast from from_ty to to_ty is valid, returns an Ok containing the kind of /// the cast. In certain cases, including some invalid casts from array references /// to pointers, this may cause additional errors to be emitted and/or ICE error -/// messages. +/// messages. This function will panic if that occurs. fn check_cast<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>, from_ty: Ty<'tcx>, to_ty: Ty<'tcx>) -> Option { let hir_id = e.hir_id; let local_def_id = hir_id.owner; @@ -743,11 +743,17 @@ fn check_cast<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>, from_ty: Ty<'tcx> DUMMY_SP, DUMMY_SP, ) { - check.do_check(&fn_ctxt) - .ok() - // do_check's documentation says that it might return Ok and create - // errors in the fcx instead of returing Err in some cases. - .filter(|_| !fn_ctxt.errors_reported_since_creation()) + let res = check.do_check(&fn_ctxt); + + // do_check's documentation says that it might return Ok and create + // errors in the fcx instead of returing Err in some cases. Those cases + // should be filtered out before getting here. + assert!( + !fn_ctxt.errors_reported_since_creation(), + "`fn_ctxt` contained errors after cast check!" + ); + + res.ok() } else { None } From c93aff874f44868cb0b78af578831e45a12908ac Mon Sep 17 00:00:00 2001 From: Ryan1729 Date: Thu, 6 Aug 2020 04:49:06 -0600 Subject: [PATCH 14/54] add newline to transmutes_expressible_as_ptr_casts.rs --- .../clippy/tests/ui/transmutes_expressible_as_ptr_casts.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.rs b/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.rs index 007526da40df8..7e99c92835985 100644 --- a/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.rs +++ b/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.rs @@ -73,4 +73,4 @@ fn main() { // fall through into `do_check`. fn trigger_do_check_to_emit_error(in_param: &[i32; 1]) -> *const u8 { unsafe { transmute::<&[i32; 1], *const u8>(in_param) } -} \ No newline at end of file +} From 8d5b5a3348f3d0bbae717944b827fc363b50cd87 Mon Sep 17 00:00:00 2001 From: Ryan1729 Date: Thu, 6 Aug 2020 06:08:32 -0600 Subject: [PATCH 15/54] run ./x.py fmt --- src/librustc_typeck/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index 2a49341efbb5c..49843fa43dd8c 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -75,8 +75,8 @@ extern crate log; extern crate rustc_middle; // These are used by Clippy. -pub mod expr_use_visitor; pub mod check; +pub mod expr_use_visitor; mod astconv; mod check_unused; From ddaf67a3890a2b91252e4a0a469765c482ef74fb Mon Sep 17 00:00:00 2001 From: Ryan1729 Date: Thu, 6 Aug 2020 06:11:23 -0600 Subject: [PATCH 16/54] run clippy_dev update_lints --- src/tools/clippy/clippy_lints/src/lib.rs | 6 +++--- src/tools/clippy/src/lintlist/mod.rs | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs index 87b5309ff1c71..828ee91059601 100644 --- a/src/tools/clippy/clippy_lints/src/lib.rs +++ b/src/tools/clippy/clippy_lints/src/lib.rs @@ -788,6 +788,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &to_digit_is_some::TO_DIGIT_IS_SOME, &trait_bounds::TYPE_REPETITION_IN_BOUNDS, &transmute::CROSSPOINTER_TRANSMUTE, + &transmute::TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS, &transmute::TRANSMUTE_BYTES_TO_STR, &transmute::TRANSMUTE_FLOAT_TO_INT, &transmute::TRANSMUTE_INT_TO_BOOL, @@ -798,7 +799,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &transmute::UNSOUND_COLLECTION_TRANSMUTE, &transmute::USELESS_TRANSMUTE, &transmute::WRONG_TRANSMUTE, - &transmute::TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS, &transmuting_null::TRANSMUTING_NULL, &trivially_copy_pass_by_ref::TRIVIALLY_COPY_PASS_BY_REF, &try_err::TRY_ERR, @@ -1418,6 +1418,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&temporary_assignment::TEMPORARY_ASSIGNMENT), LintId::of(&to_digit_is_some::TO_DIGIT_IS_SOME), LintId::of(&transmute::CROSSPOINTER_TRANSMUTE), + LintId::of(&transmute::TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS), LintId::of(&transmute::TRANSMUTE_BYTES_TO_STR), LintId::of(&transmute::TRANSMUTE_FLOAT_TO_INT), LintId::of(&transmute::TRANSMUTE_INT_TO_BOOL), @@ -1427,7 +1428,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&transmute::TRANSMUTE_PTR_TO_REF), LintId::of(&transmute::UNSOUND_COLLECTION_TRANSMUTE), LintId::of(&transmute::WRONG_TRANSMUTE), - LintId::of(&transmute::TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS), LintId::of(&transmuting_null::TRANSMUTING_NULL), LintId::of(&try_err::TRY_ERR), LintId::of(&types::ABSURD_EXTREME_COMPARISONS), @@ -1619,6 +1619,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&swap::MANUAL_SWAP), LintId::of(&temporary_assignment::TEMPORARY_ASSIGNMENT), LintId::of(&transmute::CROSSPOINTER_TRANSMUTE), + LintId::of(&transmute::TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS), LintId::of(&transmute::TRANSMUTE_BYTES_TO_STR), LintId::of(&transmute::TRANSMUTE_FLOAT_TO_INT), LintId::of(&transmute::TRANSMUTE_INT_TO_BOOL), @@ -1626,7 +1627,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&transmute::TRANSMUTE_INT_TO_FLOAT), LintId::of(&transmute::TRANSMUTE_PTR_TO_PTR), LintId::of(&transmute::TRANSMUTE_PTR_TO_REF), - LintId::of(&transmute::TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS), LintId::of(&types::BORROWED_BOX), LintId::of(&types::CHAR_LIT_AS_U8), LintId::of(&types::TYPE_COMPLEXITY), diff --git a/src/tools/clippy/src/lintlist/mod.rs b/src/tools/clippy/src/lintlist/mod.rs index 9363039041da4..1f3f70631fb29 100644 --- a/src/tools/clippy/src/lintlist/mod.rs +++ b/src/tools/clippy/src/lintlist/mod.rs @@ -2218,7 +2218,7 @@ pub static ref ALL_LINTS: Vec = vec![ Lint { name: "transmutes_expressible_as_ptr_casts", group: "complexity", - desc: "default lint description", + desc: "transmutes that could be a pointer cast", deprecation: None, module: "transmute", }, From 794d1771eec4f1dd649da58fd6e02e7409d37c12 Mon Sep 17 00:00:00 2001 From: Ryan1729 Date: Thu, 6 Aug 2020 06:15:57 -0600 Subject: [PATCH 17/54] run clippy_dev fmt This seemed to overdo it a bit, affecting multiple submodules, and changing a file I didn't touch, so I didn't commit those changes --- .../clippy/clippy_lints/src/transmute.rs | 34 +++++++------------ 1 file changed, 12 insertions(+), 22 deletions(-) diff --git a/src/tools/clippy/clippy_lints/src/transmute.rs b/src/tools/clippy/clippy_lints/src/transmute.rs index 9f356811f2204..7d707b8a0c857 100644 --- a/src/tools/clippy/clippy_lints/src/transmute.rs +++ b/src/tools/clippy/clippy_lints/src/transmute.rs @@ -8,8 +8,8 @@ use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind, GenericArg, Mutability, QPath, TyKind, UnOp}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::{self, cast::CastKind, Ty}; -use rustc_span::DUMMY_SP; use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_span::DUMMY_SP; use rustc_typeck::check::{cast::CastCheck, FnCtxt, Inherited}; use std::borrow::Cow; @@ -698,18 +698,16 @@ fn is_layout_incompatible<'tcx>(cx: &LateContext<'tcx>, from: Ty<'tcx>, to: Ty<' /// a transmute. In certain cases, including some invalid casts from array /// references to pointers, this may cause additional errors to be emitted and/or /// ICE error messages. This function will panic if that occurs. -fn can_be_expressed_as_pointer_cast<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>, from_ty: Ty<'tcx>, to_ty: Ty<'tcx>) -> bool { +fn can_be_expressed_as_pointer_cast<'tcx>( + cx: &LateContext<'tcx>, + e: &'tcx Expr<'_>, + from_ty: Ty<'tcx>, + to_ty: Ty<'tcx>, +) -> bool { use CastKind::*; matches!( check_cast(cx, e, from_ty, to_ty), - Some( - PtrPtrCast - | PtrAddrCast - | AddrPtrCast - | ArrayPtrCast - | FnPtrPtrCast - | FnPtrAddrCast - ) + Some(PtrPtrCast | PtrAddrCast | AddrPtrCast | ArrayPtrCast | FnPtrPtrCast | FnPtrAddrCast) ) } @@ -722,26 +720,18 @@ fn check_cast<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>, from_ty: Ty<'tcx> let local_def_id = hir_id.owner; Inherited::build(cx.tcx, local_def_id).enter(|inherited| { - let fn_ctxt = FnCtxt::new( - &inherited, - cx.param_env, - hir_id - ); + let fn_ctxt = FnCtxt::new(&inherited, cx.param_env, hir_id); // If we already have errors, we can't be sure we can pointer cast. assert!( - !fn_ctxt.errors_reported_since_creation(), + !fn_ctxt.errors_reported_since_creation(), "Newly created FnCtxt contained errors" ); if let Ok(check) = CastCheck::new( - &fn_ctxt, - e, - from_ty, - to_ty, + &fn_ctxt, e, from_ty, to_ty, // We won't show any error to the user, so we don't care what the span is here. - DUMMY_SP, - DUMMY_SP, + DUMMY_SP, DUMMY_SP, ) { let res = check.do_check(&fn_ctxt); From 8beff7fe7a125ac471f12a21b0a77a5dbaf6c6f1 Mon Sep 17 00:00:00 2001 From: Ryan Wiedemann Date: Thu, 6 Aug 2020 07:57:31 -0600 Subject: [PATCH 18/54] Apply suggestions from code review Co-authored-by: Philipp Krones --- src/tools/clippy/clippy_lints/src/transmute.rs | 4 ++-- .../clippy/tests/ui/transmutes_expressible_as_ptr_casts.rs | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/tools/clippy/clippy_lints/src/transmute.rs b/src/tools/clippy/clippy_lints/src/transmute.rs index 7d707b8a0c857..f077c14618316 100644 --- a/src/tools/clippy/clippy_lints/src/transmute.rs +++ b/src/tools/clippy/clippy_lints/src/transmute.rs @@ -640,7 +640,7 @@ impl<'tcx> LateLintPass<'tcx> for Transmute { |diag| { if let Some(arg) = sugg::Sugg::hir_opt(cx, &args[0]) { let sugg = arg.as_ty(&to_ty.to_string()).to_string(); - diag.span_suggestion(e.span, "try", sugg, Applicability::Unspecified); + diag.span_suggestion(e.span, "try", sugg, Applicability::MachineApplicable); } } ), @@ -694,7 +694,7 @@ fn is_layout_incompatible<'tcx>(cx: &LateContext<'tcx>, from: Ty<'tcx>, to: Ty<' } } -/// Check if the the type conversion can be expressed as a pointer cast, instead of +/// Check if the type conversion can be expressed as a pointer cast, instead of /// a transmute. In certain cases, including some invalid casts from array /// references to pointers, this may cause additional errors to be emitted and/or /// ICE error messages. This function will panic if that occurs. diff --git a/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.rs b/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.rs index 7e99c92835985..2693094ba6ce5 100644 --- a/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.rs +++ b/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.rs @@ -1,3 +1,4 @@ +// run-rustfix #![warn(clippy::transmutes_expressible_as_ptr_casts)] // These two warnings currrently cover the cases transmutes_expressible_as_ptr_casts // would otherwise be responsible for From ac513a11149f7cbcea4afc423760a27f2d914ec0 Mon Sep 17 00:00:00 2001 From: Ryan1729 Date: Thu, 6 Aug 2020 20:28:29 -0600 Subject: [PATCH 19/54] copy over *.fixed file --- .../transmutes_expressible_as_ptr_casts.fixed | 77 +++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.fixed diff --git a/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.fixed b/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.fixed new file mode 100644 index 0000000000000..ab181687e1eb3 --- /dev/null +++ b/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.fixed @@ -0,0 +1,77 @@ +// run-rustfix +#![warn(clippy::transmutes_expressible_as_ptr_casts)] +// These two warnings currrently cover the cases transmutes_expressible_as_ptr_casts +// would otherwise be responsible for +#![warn(clippy::useless_transmute)] +#![warn(clippy::transmute_ptr_to_ptr)] + +use std::mem::transmute; + +// rustc_typeck::check::cast contains documentation about when a cast `e as U` is +// valid, which we quote from below. + +fn main() { + // We should see an error message for each transmute, and no error messages for + // the casts, since the casts are the recommended fixes. + + // e is an integer and U is *U_0, while U_0: Sized; addr-ptr-cast + let ptr_i32_transmute = unsafe { + -1 as *const i32 + }; + let ptr_i32 = -1isize as *const i32; + + // e has type *T, U is *U_0, and either U_0: Sized ... + let ptr_i8_transmute = unsafe { + ptr_i32 as *const i8 + }; + let ptr_i8 = ptr_i32 as *const i8; + + let slice_ptr = &[0,1,2,3] as *const [i32]; + + // ... or pointer_kind(T) = pointer_kind(U_0); ptr-ptr-cast + let ptr_to_unsized_transmute = unsafe { + slice_ptr as *const [u16] + }; + let ptr_to_unsized = slice_ptr as *const [u16]; + // TODO: We could try testing vtable casts here too, but maybe + // we should wait until std::raw::TraitObject is stabilized? + + // e has type *T and U is a numeric type, while T: Sized; ptr-addr-cast + let usize_from_int_ptr_transmute = unsafe { + ptr_i32 as usize + }; + let usize_from_int_ptr = ptr_i32 as usize; + + let array_ref: &[i32; 4] = &[1,2,3,4]; + + // e has type &[T; n] and U is *const T; array-ptr-cast + let array_ptr_transmute = unsafe { + array_ref as *const [i32; 4] + }; + let array_ptr = array_ref as *const [i32; 4]; + + fn foo(_: usize) -> u8 { 42 } + + // e is a function pointer type and U has type *T, while T: Sized; fptr-ptr-cast + let usize_ptr_transmute = unsafe { + foo as *const usize + }; + let usize_ptr_transmute = foo as *const usize; + + // e is a function pointer type and U is an integer; fptr-addr-cast + let usize_from_fn_ptr_transmute = unsafe { + foo as usize + }; + let usize_from_fn_ptr = foo as *const usize; +} + +// If a ref-to-ptr cast of this form where the pointer type points to a type other +// than the referenced type, calling `CastCheck::do_check` has been observed to +// cause an ICE error message. `do_check` is currently called inside the +// `transmutes_expressible_as_ptr_casts` check, but other, more specific lints +// currently prevent it from being called in these cases. This test is meant to +// fail if the ordering of the checks ever changes enough to cause these cases to +// fall through into `do_check`. +fn trigger_do_check_to_emit_error(in_param: &[i32; 1]) -> *const u8 { + unsafe { in_param as *const [i32; 1] as *const u8 } +} From 358e22cd322c69cde872a1ea726361ad5aae0c6e Mon Sep 17 00:00:00 2001 From: Ryan1729 Date: Sat, 8 Aug 2020 21:03:41 -0600 Subject: [PATCH 20/54] update stderr for transmutes_expressible_as_ptr_casts --- .../transmutes_expressible_as_ptr_casts.stderr | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.stderr b/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.stderr index e6edacbd0de8e..721888802157b 100644 --- a/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.stderr +++ b/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.stderr @@ -1,5 +1,5 @@ error: transmute from an integer to a pointer - --> $DIR/transmutes_expressible_as_ptr_casts.rs:18:9 + --> $DIR/transmutes_expressible_as_ptr_casts.rs:19:9 | LL | transmute::(-1) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `-1 as *const i32` @@ -7,7 +7,7 @@ LL | transmute::(-1) = note: `-D clippy::useless-transmute` implied by `-D warnings` error: transmute from a pointer to a pointer - --> $DIR/transmutes_expressible_as_ptr_casts.rs:24:9 + --> $DIR/transmutes_expressible_as_ptr_casts.rs:25:9 | LL | transmute::<*const i32, *const i8>(ptr_i32) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `ptr_i32 as *const i8` @@ -15,13 +15,13 @@ LL | transmute::<*const i32, *const i8>(ptr_i32) = note: `-D clippy::transmute-ptr-to-ptr` implied by `-D warnings` error: transmute from a pointer to a pointer - --> $DIR/transmutes_expressible_as_ptr_casts.rs:32:9 + --> $DIR/transmutes_expressible_as_ptr_casts.rs:33:9 | LL | transmute::<*const [i32], *const [u16]>(slice_ptr) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `slice_ptr as *const [u16]` error: transmute from `*const i32` to `usize` which could be expressed as a pointer cast instead - --> $DIR/transmutes_expressible_as_ptr_casts.rs:40:9 + --> $DIR/transmutes_expressible_as_ptr_casts.rs:41:9 | LL | transmute::<*const i32, usize>(ptr_i32) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `ptr_i32 as usize` @@ -29,25 +29,25 @@ LL | transmute::<*const i32, usize>(ptr_i32) = note: `-D clippy::transmutes-expressible-as-ptr-casts` implied by `-D warnings` error: transmute from a reference to a pointer - --> $DIR/transmutes_expressible_as_ptr_casts.rs:48:9 + --> $DIR/transmutes_expressible_as_ptr_casts.rs:49:9 | LL | transmute::<&[i32; 4], *const [i32; 4]>(array_ref) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `array_ref as *const [i32; 4]` error: transmute from `fn(usize) -> u8 {main::foo}` to `*const usize` which could be expressed as a pointer cast instead - --> $DIR/transmutes_expressible_as_ptr_casts.rs:56:9 + --> $DIR/transmutes_expressible_as_ptr_casts.rs:57:9 | LL | transmute:: u8, *const usize>(foo) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `foo as *const usize` error: transmute from `fn(usize) -> u8 {main::foo}` to `usize` which could be expressed as a pointer cast instead - --> $DIR/transmutes_expressible_as_ptr_casts.rs:62:9 + --> $DIR/transmutes_expressible_as_ptr_casts.rs:63:9 | LL | transmute:: u8, usize>(foo) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `foo as usize` error: transmute from a reference to a pointer - --> $DIR/transmutes_expressible_as_ptr_casts.rs:75:14 + --> $DIR/transmutes_expressible_as_ptr_casts.rs:76:14 | LL | unsafe { transmute::<&[i32; 1], *const u8>(in_param) } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `in_param as *const [i32; 1] as *const u8` From 0136f902a9ce42d7055838cb0d975847ff1154de Mon Sep 17 00:00:00 2001 From: Ryan1729 Date: Sun, 9 Aug 2020 00:15:56 -0600 Subject: [PATCH 21/54] add a test example of where transmutes_expressible_as_ptr_casts should not suggest anything --- .../ui/transmutes_expressible_as_ptr_casts.fixed | 14 +++++++++++++- .../ui/transmutes_expressible_as_ptr_casts.rs | 14 +++++++++++++- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.fixed b/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.fixed index ab181687e1eb3..d80c9f62ed066 100644 --- a/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.fixed +++ b/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.fixed @@ -5,7 +5,7 @@ #![warn(clippy::useless_transmute)] #![warn(clippy::transmute_ptr_to_ptr)] -use std::mem::transmute; +use std::mem::{size_of, transmute}; // rustc_typeck::check::cast contains documentation about when a cast `e as U` is // valid, which we quote from below. @@ -75,3 +75,15 @@ fn main() { fn trigger_do_check_to_emit_error(in_param: &[i32; 1]) -> *const u8 { unsafe { in_param as *const [i32; 1] as *const u8 } } + +#[repr(C)] +struct Single(u64); + +#[repr(C)] +struct Pair(u32, u32); + +fn cannot_be_expressed_as_pointer_cast(in_param: Single) -> Pair { + assert_eq!(size_of::(), size_of::()); + + unsafe { transmute::(in_param) } +} diff --git a/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.rs b/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.rs index 2693094ba6ce5..4f27a3a88ba7c 100644 --- a/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.rs +++ b/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.rs @@ -5,7 +5,7 @@ #![warn(clippy::useless_transmute)] #![warn(clippy::transmute_ptr_to_ptr)] -use std::mem::transmute; +use std::mem::{size_of, transmute}; // rustc_typeck::check::cast contains documentation about when a cast `e as U` is // valid, which we quote from below. @@ -75,3 +75,15 @@ fn main() { fn trigger_do_check_to_emit_error(in_param: &[i32; 1]) -> *const u8 { unsafe { transmute::<&[i32; 1], *const u8>(in_param) } } + +#[repr(C)] +struct Single(u64); + +#[repr(C)] +struct Pair(u32, u32); + +fn cannot_be_expressed_as_pointer_cast(in_param: Single) -> Pair { + assert_eq!(size_of::(), size_of::()); + + unsafe { transmute::(in_param) } +} From 0abc67a235bf8f1b3fb22b76a6d294b14864126b Mon Sep 17 00:00:00 2001 From: Ryan1729 Date: Sun, 9 Aug 2020 00:28:56 -0600 Subject: [PATCH 22/54] fix unary minus on usize and unused variable errors in .fixed file --- .../transmutes_expressible_as_ptr_casts.fixed | 30 +++++++++---------- .../ui/transmutes_expressible_as_ptr_casts.rs | 30 +++++++++---------- ...transmutes_expressible_as_ptr_casts.stderr | 4 +-- 3 files changed, 32 insertions(+), 32 deletions(-) diff --git a/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.fixed b/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.fixed index d80c9f62ed066..4d3eba93bb3e5 100644 --- a/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.fixed +++ b/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.fixed @@ -15,54 +15,54 @@ fn main() { // the casts, since the casts are the recommended fixes. // e is an integer and U is *U_0, while U_0: Sized; addr-ptr-cast - let ptr_i32_transmute = unsafe { - -1 as *const i32 + let _ptr_i32_transmute = unsafe { + usize::MAX as *const i32 }; - let ptr_i32 = -1isize as *const i32; + let ptr_i32 = usize::MAX as *const i32; // e has type *T, U is *U_0, and either U_0: Sized ... - let ptr_i8_transmute = unsafe { + let _ptr_i8_transmute = unsafe { ptr_i32 as *const i8 }; - let ptr_i8 = ptr_i32 as *const i8; + let _ptr_i8 = ptr_i32 as *const i8; let slice_ptr = &[0,1,2,3] as *const [i32]; // ... or pointer_kind(T) = pointer_kind(U_0); ptr-ptr-cast - let ptr_to_unsized_transmute = unsafe { + let _ptr_to_unsized_transmute = unsafe { slice_ptr as *const [u16] }; - let ptr_to_unsized = slice_ptr as *const [u16]; + let _ptr_to_unsized = slice_ptr as *const [u16]; // TODO: We could try testing vtable casts here too, but maybe // we should wait until std::raw::TraitObject is stabilized? // e has type *T and U is a numeric type, while T: Sized; ptr-addr-cast - let usize_from_int_ptr_transmute = unsafe { + let _usize_from_int_ptr_transmute = unsafe { ptr_i32 as usize }; - let usize_from_int_ptr = ptr_i32 as usize; + let _usize_from_int_ptr = ptr_i32 as usize; let array_ref: &[i32; 4] = &[1,2,3,4]; // e has type &[T; n] and U is *const T; array-ptr-cast - let array_ptr_transmute = unsafe { + let _array_ptr_transmute = unsafe { array_ref as *const [i32; 4] }; - let array_ptr = array_ref as *const [i32; 4]; + let _array_ptr = array_ref as *const [i32; 4]; fn foo(_: usize) -> u8 { 42 } // e is a function pointer type and U has type *T, while T: Sized; fptr-ptr-cast - let usize_ptr_transmute = unsafe { + let _usize_ptr_transmute = unsafe { foo as *const usize }; - let usize_ptr_transmute = foo as *const usize; + let _usize_ptr_transmute = foo as *const usize; // e is a function pointer type and U is an integer; fptr-addr-cast - let usize_from_fn_ptr_transmute = unsafe { + let _usize_from_fn_ptr_transmute = unsafe { foo as usize }; - let usize_from_fn_ptr = foo as *const usize; + let _usize_from_fn_ptr = foo as *const usize; } // If a ref-to-ptr cast of this form where the pointer type points to a type other diff --git a/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.rs b/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.rs index 4f27a3a88ba7c..8748121064332 100644 --- a/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.rs +++ b/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.rs @@ -15,54 +15,54 @@ fn main() { // the casts, since the casts are the recommended fixes. // e is an integer and U is *U_0, while U_0: Sized; addr-ptr-cast - let ptr_i32_transmute = unsafe { - transmute::(-1) + let _ptr_i32_transmute = unsafe { + transmute::(usize::MAX) }; - let ptr_i32 = -1isize as *const i32; + let ptr_i32 = usize::MAX as *const i32; // e has type *T, U is *U_0, and either U_0: Sized ... - let ptr_i8_transmute = unsafe { + let _ptr_i8_transmute = unsafe { transmute::<*const i32, *const i8>(ptr_i32) }; - let ptr_i8 = ptr_i32 as *const i8; + let _ptr_i8 = ptr_i32 as *const i8; let slice_ptr = &[0,1,2,3] as *const [i32]; // ... or pointer_kind(T) = pointer_kind(U_0); ptr-ptr-cast - let ptr_to_unsized_transmute = unsafe { + let _ptr_to_unsized_transmute = unsafe { transmute::<*const [i32], *const [u16]>(slice_ptr) }; - let ptr_to_unsized = slice_ptr as *const [u16]; + let _ptr_to_unsized = slice_ptr as *const [u16]; // TODO: We could try testing vtable casts here too, but maybe // we should wait until std::raw::TraitObject is stabilized? // e has type *T and U is a numeric type, while T: Sized; ptr-addr-cast - let usize_from_int_ptr_transmute = unsafe { + let _usize_from_int_ptr_transmute = unsafe { transmute::<*const i32, usize>(ptr_i32) }; - let usize_from_int_ptr = ptr_i32 as usize; + let _usize_from_int_ptr = ptr_i32 as usize; let array_ref: &[i32; 4] = &[1,2,3,4]; // e has type &[T; n] and U is *const T; array-ptr-cast - let array_ptr_transmute = unsafe { + let _array_ptr_transmute = unsafe { transmute::<&[i32; 4], *const [i32; 4]>(array_ref) }; - let array_ptr = array_ref as *const [i32; 4]; + let _array_ptr = array_ref as *const [i32; 4]; fn foo(_: usize) -> u8 { 42 } // e is a function pointer type and U has type *T, while T: Sized; fptr-ptr-cast - let usize_ptr_transmute = unsafe { + let _usize_ptr_transmute = unsafe { transmute:: u8, *const usize>(foo) }; - let usize_ptr_transmute = foo as *const usize; + let _usize_ptr_transmute = foo as *const usize; // e is a function pointer type and U is an integer; fptr-addr-cast - let usize_from_fn_ptr_transmute = unsafe { + let _usize_from_fn_ptr_transmute = unsafe { transmute:: u8, usize>(foo) }; - let usize_from_fn_ptr = foo as *const usize; + let _usize_from_fn_ptr = foo as *const usize; } // If a ref-to-ptr cast of this form where the pointer type points to a type other diff --git a/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.stderr b/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.stderr index 721888802157b..72fb8689d657a 100644 --- a/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.stderr +++ b/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.stderr @@ -1,8 +1,8 @@ error: transmute from an integer to a pointer --> $DIR/transmutes_expressible_as_ptr_casts.rs:19:9 | -LL | transmute::(-1) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `-1 as *const i32` +LL | transmute::(usize::MAX) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `usize::MAX as *const i32` | = note: `-D clippy::useless-transmute` implied by `-D warnings` From 4cae6b8115f722cea553cc178df255bb9c90710e Mon Sep 17 00:00:00 2001 From: Ryan1729 Date: Sun, 9 Aug 2020 00:39:14 -0600 Subject: [PATCH 23/54] add allow unused_unsafe and allow dead_code --- .../ui/transmutes_expressible_as_ptr_casts.fixed | 3 ++- .../ui/transmutes_expressible_as_ptr_casts.rs | 3 ++- .../transmutes_expressible_as_ptr_casts.stderr | 16 ++++++++-------- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.fixed b/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.fixed index 4d3eba93bb3e5..98288dde6d845 100644 --- a/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.fixed +++ b/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.fixed @@ -4,12 +4,13 @@ // would otherwise be responsible for #![warn(clippy::useless_transmute)] #![warn(clippy::transmute_ptr_to_ptr)] +#![allow(unused_unsafe)] +#![allow(dead_code)] use std::mem::{size_of, transmute}; // rustc_typeck::check::cast contains documentation about when a cast `e as U` is // valid, which we quote from below. - fn main() { // We should see an error message for each transmute, and no error messages for // the casts, since the casts are the recommended fixes. diff --git a/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.rs b/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.rs index 8748121064332..fd5055c08f633 100644 --- a/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.rs +++ b/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.rs @@ -4,12 +4,13 @@ // would otherwise be responsible for #![warn(clippy::useless_transmute)] #![warn(clippy::transmute_ptr_to_ptr)] +#![allow(unused_unsafe)] +#![allow(dead_code)] use std::mem::{size_of, transmute}; // rustc_typeck::check::cast contains documentation about when a cast `e as U` is // valid, which we quote from below. - fn main() { // We should see an error message for each transmute, and no error messages for // the casts, since the casts are the recommended fixes. diff --git a/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.stderr b/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.stderr index 72fb8689d657a..46597acc6c0d2 100644 --- a/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.stderr +++ b/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.stderr @@ -1,5 +1,5 @@ error: transmute from an integer to a pointer - --> $DIR/transmutes_expressible_as_ptr_casts.rs:19:9 + --> $DIR/transmutes_expressible_as_ptr_casts.rs:20:9 | LL | transmute::(usize::MAX) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `usize::MAX as *const i32` @@ -7,7 +7,7 @@ LL | transmute::(usize::MAX) = note: `-D clippy::useless-transmute` implied by `-D warnings` error: transmute from a pointer to a pointer - --> $DIR/transmutes_expressible_as_ptr_casts.rs:25:9 + --> $DIR/transmutes_expressible_as_ptr_casts.rs:26:9 | LL | transmute::<*const i32, *const i8>(ptr_i32) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `ptr_i32 as *const i8` @@ -15,13 +15,13 @@ LL | transmute::<*const i32, *const i8>(ptr_i32) = note: `-D clippy::transmute-ptr-to-ptr` implied by `-D warnings` error: transmute from a pointer to a pointer - --> $DIR/transmutes_expressible_as_ptr_casts.rs:33:9 + --> $DIR/transmutes_expressible_as_ptr_casts.rs:34:9 | LL | transmute::<*const [i32], *const [u16]>(slice_ptr) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `slice_ptr as *const [u16]` error: transmute from `*const i32` to `usize` which could be expressed as a pointer cast instead - --> $DIR/transmutes_expressible_as_ptr_casts.rs:41:9 + --> $DIR/transmutes_expressible_as_ptr_casts.rs:42:9 | LL | transmute::<*const i32, usize>(ptr_i32) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `ptr_i32 as usize` @@ -29,25 +29,25 @@ LL | transmute::<*const i32, usize>(ptr_i32) = note: `-D clippy::transmutes-expressible-as-ptr-casts` implied by `-D warnings` error: transmute from a reference to a pointer - --> $DIR/transmutes_expressible_as_ptr_casts.rs:49:9 + --> $DIR/transmutes_expressible_as_ptr_casts.rs:50:9 | LL | transmute::<&[i32; 4], *const [i32; 4]>(array_ref) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `array_ref as *const [i32; 4]` error: transmute from `fn(usize) -> u8 {main::foo}` to `*const usize` which could be expressed as a pointer cast instead - --> $DIR/transmutes_expressible_as_ptr_casts.rs:57:9 + --> $DIR/transmutes_expressible_as_ptr_casts.rs:58:9 | LL | transmute:: u8, *const usize>(foo) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `foo as *const usize` error: transmute from `fn(usize) -> u8 {main::foo}` to `usize` which could be expressed as a pointer cast instead - --> $DIR/transmutes_expressible_as_ptr_casts.rs:63:9 + --> $DIR/transmutes_expressible_as_ptr_casts.rs:64:9 | LL | transmute:: u8, usize>(foo) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `foo as usize` error: transmute from a reference to a pointer - --> $DIR/transmutes_expressible_as_ptr_casts.rs:76:14 + --> $DIR/transmutes_expressible_as_ptr_casts.rs:77:14 | LL | unsafe { transmute::<&[i32; 1], *const u8>(in_param) } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `in_param as *const [i32; 1] as *const u8` From f5d9195e5acf91287f3f710270ff5e15abbf36c4 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 7 Aug 2020 11:19:07 +0200 Subject: [PATCH 24/54] Only add a border for the rust logo --- src/librustdoc/html/layout.rs | 2 +- src/librustdoc/html/static/themes/ayu.css | 7 +++++-- src/librustdoc/html/static/themes/dark.css | 7 +++++-- src/librustdoc/html/static/themes/light.css | 4 ++-- 4 files changed, 13 insertions(+), 7 deletions(-) diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs index cc6b38ebcdb7f..03011ce4ab304 100644 --- a/src/librustdoc/html/layout.rs +++ b/src/librustdoc/html/layout.rs @@ -138,7 +138,7 @@ pub fn render( if layout.logo.is_empty() { format!( "\ -
\ + ", path = p, static_root_path = static_root_path, diff --git a/src/librustdoc/html/static/themes/ayu.css b/src/librustdoc/html/static/themes/ayu.css index 60f0d25b219e7..8d176bb352616 100644 --- a/src/librustdoc/html/static/themes/ayu.css +++ b/src/librustdoc/html/static/themes/ayu.css @@ -62,8 +62,11 @@ pre { background-color: #14191f; } -.logo-container > img { - filter: drop-shadow(0 0 5px #fff); +.logo-container.rust-logo > img { + filter: drop-shadow(1px 0 0px #fff) + drop-shadow(0 1px 0 #fff) + drop-shadow(-1px 0 0 #fff) + drop-shadow(0 -1px 0 #fff); } /* Improve the scrollbar display on firefox */ diff --git a/src/librustdoc/html/static/themes/dark.css b/src/librustdoc/html/static/themes/dark.css index 34c6cbbf4fa21..1c14ab364b38c 100644 --- a/src/librustdoc/html/static/themes/dark.css +++ b/src/librustdoc/html/static/themes/dark.css @@ -34,8 +34,11 @@ pre { background-color: #505050; } -.logo-container > img { - filter: drop-shadow(0 0 5px #fff); +.logo-container.rust-logo > img { + filter: drop-shadow(1px 0 0px #fff) + drop-shadow(0 1px 0 #fff) + drop-shadow(-1px 0 0 #fff) + drop-shadow(0 -1px 0 #fff) } /* Improve the scrollbar display on firefox */ diff --git a/src/librustdoc/html/static/themes/light.css b/src/librustdoc/html/static/themes/light.css index 137aad4ed4398..4aafb6c9f94b1 100644 --- a/src/librustdoc/html/static/themes/light.css +++ b/src/librustdoc/html/static/themes/light.css @@ -45,8 +45,8 @@ pre { scrollbar-color: rgba(36, 37, 39, 0.6) #d9d9d9; } -.logo-container > img { - filter: drop-shadow(0 0 5px #aaa); +.logo-container.rust-logo > img { + /* No need for a border in here! */ } /* Improve the scrollbar display on webkit-based browsers */ From e62d748717ac6621582adb82df626496f029e893 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Sat, 8 Aug 2020 21:05:50 -0400 Subject: [PATCH 25/54] Avoid deleting temporary files on error Previously if the compiler error'd, fatally, then temporary directories which should be preserved by -Csave-temps would be deleted due to fatal compiler errors being implemented as panics. --- Cargo.lock | 1 + src/librustc_codegen_ssa/back/link.rs | 39 +++++++++--------------- src/librustc_data_structures/Cargo.toml | 1 + src/librustc_data_structures/lib.rs | 1 + src/librustc_data_structures/temp_dir.rs | 34 +++++++++++++++++++++ src/librustc_interface/passes.rs | 2 ++ 6 files changed, 54 insertions(+), 24 deletions(-) create mode 100644 src/librustc_data_structures/temp_dir.rs diff --git a/Cargo.lock b/Cargo.lock index 2685de2244e94..3f8bf0ac8e890 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3367,6 +3367,7 @@ dependencies = [ "smallvec 1.4.0", "stable_deref_trait", "stacker", + "tempfile", "tracing", "winapi 0.3.8", ] diff --git a/src/librustc_codegen_ssa/back/link.rs b/src/librustc_codegen_ssa/back/link.rs index 6912667c391d0..d725a60118e3c 100644 --- a/src/librustc_codegen_ssa/back/link.rs +++ b/src/librustc_codegen_ssa/back/link.rs @@ -1,4 +1,5 @@ use rustc_data_structures::fx::FxHashSet; +use rustc_data_structures::temp_dir::MaybeTempDir; use rustc_fs_util::fix_windows_verbatim_for_gcc; use rustc_hir::def_id::CrateNum; use rustc_middle::middle::cstore::{EncodedMetadata, LibSource, NativeLib}; @@ -23,7 +24,7 @@ use super::rpath::{self, RPathConfig}; use crate::{looks_like_rust_object_file, CodegenResults, CrateInfo, METADATA_FILENAME}; use cc::windows_registry; -use tempfile::{Builder as TempFileBuilder, TempDir}; +use tempfile::Builder as TempFileBuilder; use std::ffi::OsString; use std::path::{Path, PathBuf}; @@ -70,27 +71,21 @@ pub fn link_binary<'a, B: ArchiveBuilder<'a>>( } }); - let tmpdir = TempFileBuilder::new() - .prefix("rustc") - .tempdir() - .unwrap_or_else(|err| sess.fatal(&format!("couldn't create a temp dir: {}", err))); - if outputs.outputs.should_codegen() { + let tmpdir = TempFileBuilder::new() + .prefix("rustc") + .tempdir() + .unwrap_or_else(|err| sess.fatal(&format!("couldn't create a temp dir: {}", err))); + let path = MaybeTempDir::new(tmpdir, sess.opts.cg.save_temps); let out_filename = out_filename(sess, crate_type, outputs, crate_name); match crate_type { CrateType::Rlib => { let _timer = sess.timer("link_rlib"); - link_rlib::( - sess, - codegen_results, - RlibFlavor::Normal, - &out_filename, - &tmpdir, - ) - .build(); + link_rlib::(sess, codegen_results, RlibFlavor::Normal, &out_filename, &path) + .build(); } CrateType::Staticlib => { - link_staticlib::(sess, codegen_results, &out_filename, &tmpdir); + link_staticlib::(sess, codegen_results, &out_filename, &path); } _ => { link_natively::( @@ -98,7 +93,7 @@ pub fn link_binary<'a, B: ArchiveBuilder<'a>>( crate_type, &out_filename, codegen_results, - tmpdir.path(), + path.as_ref(), target_cpu, ); } @@ -107,10 +102,6 @@ pub fn link_binary<'a, B: ArchiveBuilder<'a>>( sess.parse_sess.span_diagnostic.emit_artifact_notification(&out_filename, "link"); } } - - if sess.opts.cg.save_temps { - let _ = tmpdir.into_path(); - } } // Remove the temporary object file and metadata if we aren't saving temps @@ -279,8 +270,8 @@ pub fn each_linked_rlib( /// building an `.rlib` (stomping over one another), or writing an `.rmeta` into a /// directory being searched for `extern crate` (observing an incomplete file). /// The returned path is the temporary file containing the complete metadata. -pub fn emit_metadata(sess: &Session, metadata: &EncodedMetadata, tmpdir: &TempDir) -> PathBuf { - let out_filename = tmpdir.path().join(METADATA_FILENAME); +pub fn emit_metadata(sess: &Session, metadata: &EncodedMetadata, tmpdir: &MaybeTempDir) -> PathBuf { + let out_filename = tmpdir.as_ref().join(METADATA_FILENAME); let result = fs::write(&out_filename, &metadata.raw_data); if let Err(e) = result { @@ -301,7 +292,7 @@ fn link_rlib<'a, B: ArchiveBuilder<'a>>( codegen_results: &CodegenResults, flavor: RlibFlavor, out_filename: &Path, - tmpdir: &TempDir, + tmpdir: &MaybeTempDir, ) -> B { info!("preparing rlib to {:?}", out_filename); let mut ab = ::new(sess, out_filename, None); @@ -406,7 +397,7 @@ fn link_staticlib<'a, B: ArchiveBuilder<'a>>( sess: &'a Session, codegen_results: &CodegenResults, out_filename: &Path, - tempdir: &TempDir, + tempdir: &MaybeTempDir, ) { let mut ab = link_rlib::(sess, codegen_results, RlibFlavor::StaticlibBase, out_filename, tempdir); diff --git a/src/librustc_data_structures/Cargo.toml b/src/librustc_data_structures/Cargo.toml index d0dbad5d2afe5..36c32e6003112 100644 --- a/src/librustc_data_structures/Cargo.toml +++ b/src/librustc_data_structures/Cargo.toml @@ -30,6 +30,7 @@ bitflags = "1.2.1" measureme = "0.7.1" libc = "0.2" stacker = "0.1.9" +tempfile = "3.0.5" [dependencies.parking_lot] version = "0.10" diff --git a/src/librustc_data_structures/lib.rs b/src/librustc_data_structures/lib.rs index 0b2e7cda1b4cc..3884fc051056e 100644 --- a/src/librustc_data_structures/lib.rs +++ b/src/librustc_data_structures/lib.rs @@ -95,6 +95,7 @@ pub mod vec_linked_list; pub mod work_queue; pub use atomic_ref::AtomicRef; pub mod frozen; +pub mod temp_dir; pub struct OnDrop(pub F); diff --git a/src/librustc_data_structures/temp_dir.rs b/src/librustc_data_structures/temp_dir.rs new file mode 100644 index 0000000000000..0d9b3e3ca25c0 --- /dev/null +++ b/src/librustc_data_structures/temp_dir.rs @@ -0,0 +1,34 @@ +use std::mem::ManuallyDrop; +use std::path::Path; +use tempfile::TempDir; + +/// This is used to avoid TempDir being dropped on error paths unintentionally. +#[derive(Debug)] +pub struct MaybeTempDir { + dir: ManuallyDrop, + // Whether the TempDir should be deleted on drop. + keep: bool, +} + +impl Drop for MaybeTempDir { + fn drop(&mut self) { + // Safety: We are in the destructor, and no further access will + // occur. + let dir = unsafe { ManuallyDrop::take(&mut self.dir) }; + if self.keep { + dir.into_path(); + } + } +} + +impl AsRef for MaybeTempDir { + fn as_ref(&self) -> &Path { + self.dir.path() + } +} + +impl MaybeTempDir { + pub fn new(dir: TempDir, keep_on_drop: bool) -> MaybeTempDir { + MaybeTempDir { dir: ManuallyDrop::new(dir), keep: keep_on_drop } + } +} diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index 6c0343330c8c9..701fca8e4b534 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -9,6 +9,7 @@ use rustc_ast::{self, ast, visit}; use rustc_codegen_ssa::back::link::emit_metadata; use rustc_codegen_ssa::traits::CodegenBackend; use rustc_data_structures::sync::{par_iter, Lrc, OnceCell, ParallelIterator, WorkerLocal}; +use rustc_data_structures::temp_dir::MaybeTempDir; use rustc_data_structures::{box_region_allow_access, declare_box_region_type, parallel}; use rustc_errors::{ErrorReported, PResult}; use rustc_expand::base::ExtCtxt; @@ -974,6 +975,7 @@ fn encode_and_write_metadata( .prefix("rmeta") .tempdir_in(out_filename.parent().unwrap()) .unwrap_or_else(|err| tcx.sess.fatal(&format!("couldn't create a temp dir: {}", err))); + let metadata_tmpdir = MaybeTempDir::new(metadata_tmpdir, tcx.sess.opts.cg.save_temps); let metadata_filename = emit_metadata(tcx.sess, &metadata, &metadata_tmpdir); if let Err(e) = fs::rename(&metadata_filename, &out_filename) { tcx.sess.fatal(&format!("failed to write {}: {}", out_filename.display(), e)); From 07b5a4e0d41c9d82a9877922f179fd76f6677b23 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Sat, 8 Aug 2020 18:09:40 -0700 Subject: [PATCH 26/54] Don't try to use wasm intrinsics on vectors This commit fixes an issue with #74695 where the fptosi and fptoui specializations on wasm were accidentally used on vector types by the `simd_cast` intrinsic. This issue showed up as broken CI for the stdsimd crate. Here this commit simply skips the specialization on vector kinds flowing into `fpto{s,u}i`. --- src/librustc_codegen_llvm/builder.rs | 55 ++++++++++++++++------------ 1 file changed, 31 insertions(+), 24 deletions(-) diff --git a/src/librustc_codegen_llvm/builder.rs b/src/librustc_codegen_llvm/builder.rs index 1124e91bf7185..a0f4311b33a26 100644 --- a/src/librustc_codegen_llvm/builder.rs +++ b/src/librustc_codegen_llvm/builder.rs @@ -728,20 +728,25 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { // codegen. Note that this has a semantic difference in that the // intrinsic can trap whereas `fptoui` never traps. That difference, // however, is handled by `fptosui_may_trap` above. + // + // Note that we skip the wasm intrinsics for vector types where `fptoui` + // must be used instead. if self.wasm_and_missing_nontrapping_fptoint() { let src_ty = self.cx.val_ty(val); - let float_width = self.cx.float_width(src_ty); - let int_width = self.cx.int_width(dest_ty); - let name = match (int_width, float_width) { - (32, 32) => Some("llvm.wasm.trunc.unsigned.i32.f32"), - (32, 64) => Some("llvm.wasm.trunc.unsigned.i32.f64"), - (64, 32) => Some("llvm.wasm.trunc.unsigned.i64.f32"), - (64, 64) => Some("llvm.wasm.trunc.unsigned.i64.f64"), - _ => None, - }; - if let Some(name) = name { - let intrinsic = self.get_intrinsic(name); - return self.call(intrinsic, &[val], None); + if self.cx.type_kind(src_ty) != TypeKind::Vector { + let float_width = self.cx.float_width(src_ty); + let int_width = self.cx.int_width(dest_ty); + let name = match (int_width, float_width) { + (32, 32) => Some("llvm.wasm.trunc.unsigned.i32.f32"), + (32, 64) => Some("llvm.wasm.trunc.unsigned.i32.f64"), + (64, 32) => Some("llvm.wasm.trunc.unsigned.i64.f32"), + (64, 64) => Some("llvm.wasm.trunc.unsigned.i64.f64"), + _ => None, + }; + if let Some(name) = name { + let intrinsic = self.get_intrinsic(name); + return self.call(intrinsic, &[val], None); + } } } unsafe { llvm::LLVMBuildFPToUI(self.llbuilder, val, dest_ty, UNNAMED) } @@ -750,18 +755,20 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { fn fptosi(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { if self.wasm_and_missing_nontrapping_fptoint() { let src_ty = self.cx.val_ty(val); - let float_width = self.cx.float_width(src_ty); - let int_width = self.cx.int_width(dest_ty); - let name = match (int_width, float_width) { - (32, 32) => Some("llvm.wasm.trunc.signed.i32.f32"), - (32, 64) => Some("llvm.wasm.trunc.signed.i32.f64"), - (64, 32) => Some("llvm.wasm.trunc.signed.i64.f32"), - (64, 64) => Some("llvm.wasm.trunc.signed.i64.f64"), - _ => None, - }; - if let Some(name) = name { - let intrinsic = self.get_intrinsic(name); - return self.call(intrinsic, &[val], None); + if self.cx.type_kind(src_ty) != TypeKind::Vector { + let float_width = self.cx.float_width(src_ty); + let int_width = self.cx.int_width(dest_ty); + let name = match (int_width, float_width) { + (32, 32) => Some("llvm.wasm.trunc.signed.i32.f32"), + (32, 64) => Some("llvm.wasm.trunc.signed.i32.f64"), + (64, 32) => Some("llvm.wasm.trunc.signed.i64.f32"), + (64, 64) => Some("llvm.wasm.trunc.signed.i64.f64"), + _ => None, + }; + if let Some(name) = name { + let intrinsic = self.get_intrinsic(name); + return self.call(intrinsic, &[val], None); + } } } unsafe { llvm::LLVMBuildFPToSI(self.llbuilder, val, dest_ty, UNNAMED) } From 5705f79e90fabd019e2d93a05d62bbba204b22c2 Mon Sep 17 00:00:00 2001 From: David Wood Date: Sun, 9 Aug 2020 14:53:33 +0100 Subject: [PATCH 27/54] instance: only polymorphize upvar substs This commit restricts the substitution polymorphization added in #75255 to only apply to the tupled upvar substitution, rather than all substitutions, fixing a bunch of regressions when polymorphization is enabled. Signed-off-by: David Wood --- src/librustc_middle/ty/flags.rs | 6 --- src/librustc_middle/ty/fold.rs | 6 --- src/librustc_middle/ty/instance.rs | 53 ++++++++++++------- src/librustc_middle/ty/mod.rs | 4 -- .../polymorphization/pr-75255.rs | 52 ------------------ 5 files changed, 33 insertions(+), 88 deletions(-) delete mode 100644 src/test/codegen-units/polymorphization/pr-75255.rs diff --git a/src/librustc_middle/ty/flags.rs b/src/librustc_middle/ty/flags.rs index 81f7474962c8d..27f50c240db67 100644 --- a/src/librustc_middle/ty/flags.rs +++ b/src/librustc_middle/ty/flags.rs @@ -85,8 +85,6 @@ impl FlagComputation { } &ty::Generator(_, ref substs, _) => { - self.add_flags(TypeFlags::MAY_POLYMORPHIZE); - let substs = substs.as_generator(); let should_remove_further_specializable = !self.flags.contains(TypeFlags::STILL_FURTHER_SPECIALIZABLE); @@ -109,8 +107,6 @@ impl FlagComputation { } &ty::Closure(_, substs) => { - self.add_flags(TypeFlags::MAY_POLYMORPHIZE); - let substs = substs.as_closure(); let should_remove_further_specializable = !self.flags.contains(TypeFlags::STILL_FURTHER_SPECIALIZABLE); @@ -196,8 +192,6 @@ impl FlagComputation { } &ty::FnDef(_, substs) => { - self.add_flags(TypeFlags::MAY_POLYMORPHIZE); - self.add_substs(substs); } diff --git a/src/librustc_middle/ty/fold.rs b/src/librustc_middle/ty/fold.rs index 87434f3f26777..492f8ce9ef1a9 100644 --- a/src/librustc_middle/ty/fold.rs +++ b/src/librustc_middle/ty/fold.rs @@ -150,12 +150,6 @@ pub trait TypeFoldable<'tcx>: fmt::Debug + Clone { self.has_type_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE) } - /// Does this value contain closures, generators or functions such that it may require - /// polymorphization? - fn may_polymorphize(&self) -> bool { - self.has_type_flags(TypeFlags::MAY_POLYMORPHIZE) - } - /// A visitor that does not recurse into types, works like `fn walk_shallow` in `Ty`. fn visit_tys_shallow(&self, visit: impl FnMut(Ty<'tcx>) -> bool) -> bool { pub struct Visitor(F); diff --git a/src/librustc_middle/ty/instance.rs b/src/librustc_middle/ty/instance.rs index cf876db26bc76..2def000da6480 100644 --- a/src/librustc_middle/ty/instance.rs +++ b/src/librustc_middle/ty/instance.rs @@ -492,6 +492,20 @@ fn polymorphize<'tcx>( let unused = tcx.unused_generic_params(def_id); debug!("polymorphize: unused={:?}", unused); + // If this is a closure or generator then we need to handle the case where another closure + // from the function is captured as an upvar and hasn't been polymorphized. In this case, + // the unpolymorphized upvar closure would result in a polymorphized closure producing + // multiple mono items (and eventually symbol clashes). + let upvars_ty = if tcx.is_closure(def_id) { + Some(substs.as_closure().tupled_upvars_ty()) + } else if tcx.type_of(def_id).is_generator() { + Some(substs.as_generator().tupled_upvars_ty()) + } else { + None + }; + let has_upvars = upvars_ty.map(|ty| ty.tuple_fields().count() > 0).unwrap_or(false); + debug!("polymorphize: upvars_ty={:?} has_upvars={:?}", upvars_ty, has_upvars); + struct PolymorphizationFolder<'tcx> { tcx: TyCtxt<'tcx>, }; @@ -512,14 +526,6 @@ fn polymorphize<'tcx>( self.tcx.mk_closure(def_id, polymorphized_substs) } } - ty::FnDef(def_id, substs) => { - let polymorphized_substs = polymorphize(self.tcx, def_id, substs); - if substs == polymorphized_substs { - ty - } else { - self.tcx.mk_fn_def(def_id, polymorphized_substs) - } - } ty::Generator(def_id, substs, movability) => { let polymorphized_substs = polymorphize(self.tcx, def_id, substs); if substs == polymorphized_substs { @@ -537,24 +543,31 @@ fn polymorphize<'tcx>( let is_unused = unused.contains(param.index).unwrap_or(false); debug!("polymorphize: param={:?} is_unused={:?}", param, is_unused); match param.kind { - // If parameter is a const or type parameter.. + // Upvar case: If parameter is a type parameter.. + ty::GenericParamDefKind::Type { .. } if + // ..and has upvars.. + has_upvars && + // ..and this param has the same type as the tupled upvars.. + upvars_ty == Some(substs[param.index as usize].expect_ty()) => { + // ..then double-check that polymorphization marked it used.. + debug_assert!(!is_unused); + // ..and polymorphize any closures/generators captured as upvars. + let upvars_ty = upvars_ty.unwrap(); + let polymorphized_upvars_ty = upvars_ty.fold_with( + &mut PolymorphizationFolder { tcx }); + debug!("polymorphize: polymorphized_upvars_ty={:?}", polymorphized_upvars_ty); + ty::GenericArg::from(polymorphized_upvars_ty) + }, + + // Simple case: If parameter is a const or type parameter.. ty::GenericParamDefKind::Const | ty::GenericParamDefKind::Type { .. } if // ..and is within range and unused.. unused.contains(param.index).unwrap_or(false) => // ..then use the identity for this parameter. tcx.mk_param_from_def(param), - // If the parameter does not contain any closures or generators, then use the - // substitution directly. - _ if !substs.may_polymorphize() => substs[param.index as usize], - - // Otherwise, use the substitution after polymorphizing. - _ => { - let arg = substs[param.index as usize]; - let polymorphized_arg = arg.fold_with(&mut PolymorphizationFolder { tcx }); - debug!("polymorphize: arg={:?} polymorphized_arg={:?}", arg, polymorphized_arg); - ty::GenericArg::from(polymorphized_arg) - } + // Otherwise, use the parameter as before. + _ => substs[param.index as usize], } }) } diff --git a/src/librustc_middle/ty/mod.rs b/src/librustc_middle/ty/mod.rs index 0102225b9b567..6798addb8aaa3 100644 --- a/src/librustc_middle/ty/mod.rs +++ b/src/librustc_middle/ty/mod.rs @@ -575,10 +575,6 @@ bitflags! { /// Does this value have parameters/placeholders/inference variables which could be /// replaced later, in a way that would change the results of `impl` specialization? const STILL_FURTHER_SPECIALIZABLE = 1 << 17; - - /// Does this value contain closures, generators or functions such that it may require - /// polymorphization? - const MAY_POLYMORPHIZE = 1 << 18; } } diff --git a/src/test/codegen-units/polymorphization/pr-75255.rs b/src/test/codegen-units/polymorphization/pr-75255.rs deleted file mode 100644 index af47b440640af..0000000000000 --- a/src/test/codegen-units/polymorphization/pr-75255.rs +++ /dev/null @@ -1,52 +0,0 @@ -// compile-flags:-Zpolymorphize=on -Zprint-mono-items=lazy -Copt-level=1 -// ignore-tidy-linelength - -#![crate_type = "rlib"] - -// Test that only one copy of `Iter::map` and `iter::repeat` are generated. - -fn unused() -> u64 { - 42 -} - -fn foo() { - let x = [1, 2, 3, std::mem::size_of::()]; - x.iter().map(|_| ()); -} - -//~ MONO_ITEM fn core::iter[0]::adapters[0]::{{impl}}[29]::new[0], pr_75255::foo[0]::{{closure}}[0]> @@ pr_75255-cgu.0[External] -//~ MONO_ITEM fn core::iter[0]::traits[0]::iterator[0]::Iterator[0]::map[0], (), pr_75255::foo[0]::{{closure}}[0]> @@ pr_75255-cgu.1[Internal] - -fn bar() { - std::iter::repeat(unused::); -} - -//~ MONO_ITEM fn core::iter[0]::sources[0]::repeat[0] u64> @@ pr_75255-cgu.1[Internal] - -pub fn dispatch() { - foo::(); - foo::>(); - - bar::(); - bar::>(); -} - -// These are all the items that aren't relevant to the test. -//~ MONO_ITEM fn core::mem[0]::size_of[0] @@ pr_75255-cgu.1[Internal] -//~ MONO_ITEM fn core::mem[0]::size_of[0]> @@ pr_75255-cgu.1[Internal] -//~ MONO_ITEM fn core::mem[0]::size_of[0] @@ pr_75255-cgu.1[Internal] -//~ MONO_ITEM fn core::ptr[0]::const_ptr[0]::{{impl}}[0]::add[0] @@ pr_75255-cgu.1[Internal] -//~ MONO_ITEM fn core::ptr[0]::const_ptr[0]::{{impl}}[0]::is_null[0] @@ pr_75255-cgu.1[Internal] -//~ MONO_ITEM fn core::ptr[0]::const_ptr[0]::{{impl}}[0]::offset[0] @@ pr_75255-cgu.1[Internal] -//~ MONO_ITEM fn core::ptr[0]::const_ptr[0]::{{impl}}[0]::wrapping_add[0] @@ pr_75255-cgu.1[Internal] -//~ MONO_ITEM fn core::ptr[0]::const_ptr[0]::{{impl}}[0]::wrapping_offset[0] @@ pr_75255-cgu.1[Internal] -//~ MONO_ITEM fn core::ptr[0]::non_null[0]::{{impl}}[3]::new_unchecked[0] @@ pr_75255-cgu.1[Internal] -//~ MONO_ITEM fn core::ptr[0]::null[0] @@ pr_75255-cgu.1[Internal] -//~ MONO_ITEM fn core::slice[0]::{{impl}}[0]::as_ptr[0] @@ pr_75255-cgu.1[Internal] -//~ MONO_ITEM fn core::slice[0]::{{impl}}[0]::iter[0] @@ pr_75255-cgu.1[Internal] -//~ MONO_ITEM fn core::slice[0]::{{impl}}[0]::len[0] @@ pr_75255-cgu.1[Internal] -//~ MONO_ITEM fn pr_75255::dispatch[0] @@ pr_75255-cgu.1[External] -//~ MONO_ITEM fn pr_75255::foo[0] @@ pr_75255-cgu.1[Internal] -//~ MONO_ITEM fn pr_75255::foo[0]> @@ pr_75255-cgu.1[Internal] -//~ MONO_ITEM fn pr_75255::bar[0] @@ pr_75255-cgu.1[Internal] -//~ MONO_ITEM fn pr_75255::bar[0]> @@ pr_75255-cgu.1[Internal] From 17988533a6762290d24f3835d76878fef9d549d8 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 9 Aug 2020 15:37:32 +0200 Subject: [PATCH 28/54] move const_eval error reporting logic into rustc_mir::const_eval::error --- src/librustc_middle/mir/interpret/error.rs | 169 +------------------ src/librustc_middle/mir/interpret/mod.rs | 6 +- src/librustc_mir/const_eval/error.rs | 170 ++++++++++++++++++-- src/librustc_mir/const_eval/eval_queries.rs | 9 +- src/librustc_mir/interpret/eval_context.rs | 35 +++- src/librustc_mir/interpret/mod.rs | 2 +- src/librustc_mir/transform/const_prop.rs | 4 +- 7 files changed, 201 insertions(+), 194 deletions(-) diff --git a/src/librustc_middle/mir/interpret/error.rs b/src/librustc_middle/mir/interpret/error.rs index c904cd83a78bc..5be09c0e9bc2b 100644 --- a/src/librustc_middle/mir/interpret/error.rs +++ b/src/librustc_middle/mir/interpret/error.rs @@ -1,17 +1,13 @@ use super::{AllocId, Pointer, RawConst, Scalar}; use crate::mir::interpret::ConstValue; -use crate::ty::layout::LayoutError; -use crate::ty::query::TyCtxtAt; -use crate::ty::{self, layout, tls, FnSig, Ty}; +use crate::ty::{layout, query::TyCtxtAt, tls, FnSig, Ty}; use rustc_data_structures::sync::Lock; use rustc_errors::{pluralize, struct_span_err, DiagnosticBuilder, ErrorReported}; -use rustc_hir as hir; -use rustc_hir::definitions::DefPathData; use rustc_macros::HashStable; use rustc_session::CtfeBacktrace; -use rustc_span::{def_id::DefId, Pos, Span}; +use rustc_span::def_id::DefId; use rustc_target::abi::{Align, Size}; use std::{any::Any, backtrace::Backtrace, fmt, mem}; @@ -34,167 +30,6 @@ CloneTypeFoldableAndLiftImpls! { pub type ConstEvalRawResult<'tcx> = Result, ErrorHandled>; pub type ConstEvalResult<'tcx> = Result, ErrorHandled>; -#[derive(Debug)] -pub struct ConstEvalErr<'tcx> { - pub span: Span, - pub error: crate::mir::interpret::InterpError<'tcx>, - pub stacktrace: Vec>, -} - -#[derive(Debug)] -pub struct FrameInfo<'tcx> { - pub instance: ty::Instance<'tcx>, - pub span: Span, - pub lint_root: Option, -} - -impl<'tcx> fmt::Display for FrameInfo<'tcx> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - ty::tls::with(|tcx| { - if tcx.def_key(self.instance.def_id()).disambiguated_data.data - == DefPathData::ClosureExpr - { - write!(f, "inside closure")?; - } else { - write!(f, "inside `{}`", self.instance)?; - } - if !self.span.is_dummy() { - let lo = tcx.sess.source_map().lookup_char_pos(self.span.lo()); - write!(f, " at {}:{}:{}", lo.file.name, lo.line, lo.col.to_usize() + 1)?; - } - Ok(()) - }) - } -} - -impl<'tcx> ConstEvalErr<'tcx> { - pub fn struct_error( - &self, - tcx: TyCtxtAt<'tcx>, - message: &str, - emit: impl FnOnce(DiagnosticBuilder<'_>), - ) -> ErrorHandled { - self.struct_generic(tcx, message, emit, None) - } - - pub fn report_as_error(&self, tcx: TyCtxtAt<'tcx>, message: &str) -> ErrorHandled { - self.struct_error(tcx, message, |mut e| e.emit()) - } - - pub fn report_as_lint( - &self, - tcx: TyCtxtAt<'tcx>, - message: &str, - lint_root: hir::HirId, - span: Option, - ) -> ErrorHandled { - self.struct_generic( - tcx, - message, - |mut lint: DiagnosticBuilder<'_>| { - // Apply the span. - if let Some(span) = span { - let primary_spans = lint.span.primary_spans().to_vec(); - // point at the actual error as the primary span - lint.replace_span_with(span); - // point to the `const` statement as a secondary span - // they don't have any label - for sp in primary_spans { - if sp != span { - lint.span_label(sp, ""); - } - } - } - lint.emit(); - }, - Some(lint_root), - ) - } - - /// Create a diagnostic for this const eval error. - /// - /// Sets the message passed in via `message` and adds span labels with detailed error - /// information before handing control back to `emit` to do any final processing. - /// It's the caller's responsibility to call emit(), stash(), etc. within the `emit` - /// function to dispose of the diagnostic properly. - /// - /// If `lint_root.is_some()` report it as a lint, else report it as a hard error. - /// (Except that for some errors, we ignore all that -- see `must_error` below.) - fn struct_generic( - &self, - tcx: TyCtxtAt<'tcx>, - message: &str, - emit: impl FnOnce(DiagnosticBuilder<'_>), - lint_root: Option, - ) -> ErrorHandled { - let must_error = match self.error { - err_inval!(Layout(LayoutError::Unknown(_))) | err_inval!(TooGeneric) => { - return ErrorHandled::TooGeneric; - } - err_inval!(TypeckError(error_reported)) => { - return ErrorHandled::Reported(error_reported); - } - // We must *always* hard error on these, even if the caller wants just a lint. - err_inval!(Layout(LayoutError::SizeOverflow(_))) => true, - _ => false, - }; - trace!("reporting const eval failure at {:?}", self.span); - - let err_msg = match &self.error { - InterpError::MachineStop(msg) => { - // A custom error (`ConstEvalErrKind` in `librustc_mir/interp/const_eval/error.rs`). - // Should be turned into a string by now. - msg.downcast_ref::().expect("invalid MachineStop payload").clone() - } - err => err.to_string(), - }; - - let finish = |mut err: DiagnosticBuilder<'_>, span_msg: Option| { - if let Some(span_msg) = span_msg { - err.span_label(self.span, span_msg); - } - // Add spans for the stacktrace. Don't print a single-line backtrace though. - if self.stacktrace.len() > 1 { - for frame_info in &self.stacktrace { - err.span_label(frame_info.span, frame_info.to_string()); - } - } - // Let the caller finish the job. - emit(err) - }; - - if must_error { - // The `message` makes little sense here, this is a more serious error than the - // caller thinks anyway. - // See . - finish(struct_error(tcx, &err_msg), None); - ErrorHandled::Reported(ErrorReported) - } else { - // Regular case. - if let Some(lint_root) = lint_root { - // Report as lint. - let hir_id = self - .stacktrace - .iter() - .rev() - .find_map(|frame| frame.lint_root) - .unwrap_or(lint_root); - tcx.struct_span_lint_hir( - rustc_session::lint::builtin::CONST_ERR, - hir_id, - tcx.span, - |lint| finish(lint.build(message), Some(err_msg)), - ); - ErrorHandled::Linted - } else { - // Report as hard error. - finish(struct_error(tcx, message), Some(err_msg)); - ErrorHandled::Reported(ErrorReported) - } - } - } -} - pub fn struct_error<'tcx>(tcx: TyCtxtAt<'tcx>, msg: &str) -> DiagnosticBuilder<'tcx> { struct_span_err!(tcx.sess, tcx.span, E0080, "{}", msg) } diff --git a/src/librustc_middle/mir/interpret/mod.rs b/src/librustc_middle/mir/interpret/mod.rs index 5e57b60894a58..2507f2184fff1 100644 --- a/src/librustc_middle/mir/interpret/mod.rs +++ b/src/librustc_middle/mir/interpret/mod.rs @@ -117,9 +117,9 @@ use crate::ty::subst::GenericArgKind; use crate::ty::{self, Instance, Ty, TyCtxt}; pub use self::error::{ - struct_error, CheckInAllocMsg, ConstEvalErr, ConstEvalRawResult, ConstEvalResult, ErrorHandled, - FrameInfo, InterpError, InterpErrorInfo, InterpResult, InvalidProgramInfo, MachineStopType, - ResourceExhaustionInfo, UndefinedBehaviorInfo, UninitBytesAccess, UnsupportedOpInfo, + struct_error, CheckInAllocMsg, ConstEvalRawResult, ConstEvalResult, ErrorHandled, InterpError, + InterpErrorInfo, InterpResult, InvalidProgramInfo, MachineStopType, ResourceExhaustionInfo, + UndefinedBehaviorInfo, UninitBytesAccess, UnsupportedOpInfo, }; pub use self::value::{get_slice_bytes, ConstValue, RawConst, Scalar, ScalarMaybeUninit}; diff --git a/src/librustc_mir/const_eval/error.rs b/src/librustc_mir/const_eval/error.rs index 8a72be33b8429..044d27a6a9dc3 100644 --- a/src/librustc_mir/const_eval/error.rs +++ b/src/librustc_mir/const_eval/error.rs @@ -1,12 +1,16 @@ use std::error::Error; use std::fmt; +use rustc_errors::{DiagnosticBuilder, ErrorReported}; +use rustc_hir as hir; use rustc_middle::mir::AssertKind; -use rustc_middle::ty::ConstInt; +use rustc_middle::ty::{layout::LayoutError, query::TyCtxtAt, ConstInt}; use rustc_span::{Span, Symbol}; use super::InterpCx; -use crate::interpret::{ConstEvalErr, InterpErrorInfo, Machine}; +use crate::interpret::{ + struct_error, ErrorHandled, FrameInfo, InterpError, InterpErrorInfo, Machine, +}; /// The CTFE machine has some custom error kinds. #[derive(Clone, Debug)] @@ -48,15 +52,155 @@ impl fmt::Display for ConstEvalErrKind { impl Error for ConstEvalErrKind {} -/// Turn an interpreter error into something to report to the user. -/// As a side-effect, if RUSTC_CTFE_BACKTRACE is set, this prints the backtrace. -/// Should be called only if the error is actually going to to be reported! -pub fn error_to_const_error<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>>( - ecx: &InterpCx<'mir, 'tcx, M>, - error: InterpErrorInfo<'tcx>, - span: Option, -) -> ConstEvalErr<'tcx> { - error.print_backtrace(); - let stacktrace = ecx.generate_stacktrace(); - ConstEvalErr { error: error.kind, stacktrace, span: span.unwrap_or_else(|| ecx.cur_span()) } +/// When const-evaluation errors, this type is constructed with the resulting information, +/// and then used to emit the error as a lint or hard error. +#[derive(Debug)] +pub struct ConstEvalErr<'tcx> { + pub span: Span, + pub error: InterpError<'tcx>, + pub stacktrace: Vec>, +} + +impl<'tcx> ConstEvalErr<'tcx> { + /// Turn an interpreter error into something to report to the user. + /// As a side-effect, if RUSTC_CTFE_BACKTRACE is set, this prints the backtrace. + /// Should be called only if the error is actually going to to be reported! + pub fn new<'mir, M: Machine<'mir, 'tcx>>( + ecx: &InterpCx<'mir, 'tcx, M>, + error: InterpErrorInfo<'tcx>, + span: Option, + ) -> ConstEvalErr<'tcx> + where + 'tcx: 'mir, + { + error.print_backtrace(); + let stacktrace = ecx.generate_stacktrace(); + ConstEvalErr { error: error.kind, stacktrace, span: span.unwrap_or_else(|| ecx.cur_span()) } + } + + pub fn struct_error( + &self, + tcx: TyCtxtAt<'tcx>, + message: &str, + emit: impl FnOnce(DiagnosticBuilder<'_>), + ) -> ErrorHandled { + self.struct_generic(tcx, message, emit, None) + } + + pub fn report_as_error(&self, tcx: TyCtxtAt<'tcx>, message: &str) -> ErrorHandled { + self.struct_error(tcx, message, |mut e| e.emit()) + } + + pub fn report_as_lint( + &self, + tcx: TyCtxtAt<'tcx>, + message: &str, + lint_root: hir::HirId, + span: Option, + ) -> ErrorHandled { + self.struct_generic( + tcx, + message, + |mut lint: DiagnosticBuilder<'_>| { + // Apply the span. + if let Some(span) = span { + let primary_spans = lint.span.primary_spans().to_vec(); + // point at the actual error as the primary span + lint.replace_span_with(span); + // point to the `const` statement as a secondary span + // they don't have any label + for sp in primary_spans { + if sp != span { + lint.span_label(sp, ""); + } + } + } + lint.emit(); + }, + Some(lint_root), + ) + } + + /// Create a diagnostic for this const eval error. + /// + /// Sets the message passed in via `message` and adds span labels with detailed error + /// information before handing control back to `emit` to do any final processing. + /// It's the caller's responsibility to call emit(), stash(), etc. within the `emit` + /// function to dispose of the diagnostic properly. + /// + /// If `lint_root.is_some()` report it as a lint, else report it as a hard error. + /// (Except that for some errors, we ignore all that -- see `must_error` below.) + fn struct_generic( + &self, + tcx: TyCtxtAt<'tcx>, + message: &str, + emit: impl FnOnce(DiagnosticBuilder<'_>), + lint_root: Option, + ) -> ErrorHandled { + let must_error = match self.error { + err_inval!(Layout(LayoutError::Unknown(_))) | err_inval!(TooGeneric) => { + return ErrorHandled::TooGeneric; + } + err_inval!(TypeckError(error_reported)) => { + return ErrorHandled::Reported(error_reported); + } + // We must *always* hard error on these, even if the caller wants just a lint. + err_inval!(Layout(LayoutError::SizeOverflow(_))) => true, + _ => false, + }; + trace!("reporting const eval failure at {:?}", self.span); + + let err_msg = match &self.error { + InterpError::MachineStop(msg) => { + // A custom error (`ConstEvalErrKind` in `librustc_mir/interp/const_eval/error.rs`). + // Should be turned into a string by now. + msg.downcast_ref::().expect("invalid MachineStop payload").clone() + } + err => err.to_string(), + }; + + let finish = |mut err: DiagnosticBuilder<'_>, span_msg: Option| { + if let Some(span_msg) = span_msg { + err.span_label(self.span, span_msg); + } + // Add spans for the stacktrace. Don't print a single-line backtrace though. + if self.stacktrace.len() > 1 { + for frame_info in &self.stacktrace { + err.span_label(frame_info.span, frame_info.to_string()); + } + } + // Let the caller finish the job. + emit(err) + }; + + if must_error { + // The `message` makes little sense here, this is a more serious error than the + // caller thinks anyway. + // See . + finish(struct_error(tcx, &err_msg), None); + ErrorHandled::Reported(ErrorReported) + } else { + // Regular case. + if let Some(lint_root) = lint_root { + // Report as lint. + let hir_id = self + .stacktrace + .iter() + .rev() + .find_map(|frame| frame.lint_root) + .unwrap_or(lint_root); + tcx.struct_span_lint_hir( + rustc_session::lint::builtin::CONST_ERR, + hir_id, + tcx.span, + |lint| finish(lint.build(message), Some(err_msg)), + ); + ErrorHandled::Linted + } else { + // Report as hard error. + finish(struct_error(tcx, message), Some(err_msg)); + ErrorHandled::Reported(ErrorReported) + } + } + } } diff --git a/src/librustc_mir/const_eval/eval_queries.rs b/src/librustc_mir/const_eval/eval_queries.rs index 42fba8982d23c..7fbe5c409d3ce 100644 --- a/src/librustc_mir/const_eval/eval_queries.rs +++ b/src/librustc_mir/const_eval/eval_queries.rs @@ -1,13 +1,14 @@ -use super::{error_to_const_error, CompileTimeEvalContext, CompileTimeInterpreter, MemoryExtra}; +use super::{CompileTimeEvalContext, CompileTimeInterpreter, ConstEvalErr, MemoryExtra}; use crate::interpret::eval_nullary_intrinsic; use crate::interpret::{ intern_const_alloc_recursive, Allocation, ConstValue, GlobalId, Immediate, InternKind, InterpCx, InterpResult, MPlaceTy, MemoryKind, OpTy, RawConst, RefTracking, Scalar, ScalarMaybeUninit, StackPopCleanup, }; + use rustc_hir::def::DefKind; use rustc_middle::mir; -use rustc_middle::mir::interpret::{ConstEvalErr, ErrorHandled}; +use rustc_middle::mir::interpret::ErrorHandled; use rustc_middle::traits::Reveal; use rustc_middle::ty::{self, subst::Subst, TyCtxt}; use rustc_span::source_map::Span; @@ -213,7 +214,7 @@ fn validate_and_turn_into_const<'tcx>( })(); val.map_err(|error| { - let err = error_to_const_error(&ecx, error, None); + let err = ConstEvalErr::new(&ecx, error, None); err.struct_error(ecx.tcx, "it is undefined behavior to use this value", |mut diag| { diag.note(note_on_undefined_behavior_error()); diag.emit(); @@ -312,7 +313,7 @@ pub fn const_eval_raw_provider<'tcx>( res.and_then(|body| eval_body_using_ecx(&mut ecx, cid, &body)) .map(|place| RawConst { alloc_id: place.ptr.assert_ptr().alloc_id, ty: place.layout.ty }) .map_err(|error| { - let err = error_to_const_error(&ecx, error, None); + let err = ConstEvalErr::new(&ecx, error, None); // errors in statics are always emitted as fatal errors if is_static { // Ensure that if the above error was either `TooGeneric` or `Reported` diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index 1e9be09781508..fc192cd9b3cb2 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -1,22 +1,22 @@ use std::cell::Cell; +use std::fmt; use std::mem; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; -use rustc_hir::def::DefKind; -use rustc_hir::def_id::DefId; +use rustc_hir::{self as hir, def::DefKind, def_id::DefId, definitions::DefPathData}; use rustc_index::vec::IndexVec; use rustc_macros::HashStable; use rustc_middle::ich::StableHashingContext; use rustc_middle::mir; use rustc_middle::mir::interpret::{ - sign_extend, truncate, FrameInfo, GlobalId, InterpResult, Pointer, Scalar, + sign_extend, truncate, GlobalId, InterpResult, Pointer, Scalar, }; use rustc_middle::ty::layout::{self, TyAndLayout}; use rustc_middle::ty::{ self, query::TyCtxtAt, subst::SubstsRef, ParamEnv, Ty, TyCtxt, TypeFoldable, }; -use rustc_span::{source_map::DUMMY_SP, Span}; +use rustc_span::{source_map::DUMMY_SP, Pos, Span}; use rustc_target::abi::{Align, HasDataLayout, LayoutOf, Size, TargetDataLayout}; use super::{ @@ -88,6 +88,14 @@ pub struct Frame<'mir, 'tcx, Tag = (), Extra = ()> { pub loc: Option, } +/// What we store about a frame in an interpreter backtrace. +#[derive(Debug)] +pub struct FrameInfo<'tcx> { + pub instance: ty::Instance<'tcx>, + pub span: Span, + pub lint_root: Option, +} + #[derive(Clone, Eq, PartialEq, Debug, HashStable)] // Miri debug-prints these pub enum StackPopCleanup { /// Jump to the next block in the caller, or cause UB if None (that's a function @@ -185,6 +193,25 @@ impl<'mir, 'tcx, Tag, Extra> Frame<'mir, 'tcx, Tag, Extra> { } } +impl<'tcx> fmt::Display for FrameInfo<'tcx> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + ty::tls::with(|tcx| { + if tcx.def_key(self.instance.def_id()).disambiguated_data.data + == DefPathData::ClosureExpr + { + write!(f, "inside closure")?; + } else { + write!(f, "inside `{}`", self.instance)?; + } + if !self.span.is_dummy() { + let lo = tcx.sess.source_map().lookup_char_pos(self.span.lo()); + write!(f, " at {}:{}:{}", lo.file.name, lo.line, lo.col.to_usize() + 1)?; + } + Ok(()) + }) + } +} + impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> HasDataLayout for InterpCx<'mir, 'tcx, M> { #[inline] fn data_layout(&self) -> &TargetDataLayout { diff --git a/src/librustc_mir/interpret/mod.rs b/src/librustc_mir/interpret/mod.rs index ebb061f48518b..5218b03d65ecc 100644 --- a/src/librustc_mir/interpret/mod.rs +++ b/src/librustc_mir/interpret/mod.rs @@ -18,7 +18,7 @@ mod visitor; pub use rustc_middle::mir::interpret::*; // have all the `interpret` symbols in one place: here -pub use self::eval_context::{Frame, InterpCx, LocalState, LocalValue, StackPopCleanup}; +pub use self::eval_context::{Frame, FrameInfo, InterpCx, LocalState, LocalValue, StackPopCleanup}; pub use self::intern::{intern_const_alloc_recursive, InternKind}; pub use self::machine::{compile_time_machine, AllocMap, Machine, MayLeak, StackPopJump}; pub use self::memory::{get_static, AllocCheck, FnVal, Memory, MemoryKind}; diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index db0b0415728ae..bff83b3c6db74 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -26,7 +26,7 @@ use rustc_span::{def_id::DefId, Span}; use rustc_target::abi::{HasDataLayout, LayoutOf, Size, TargetDataLayout}; use rustc_trait_selection::traits; -use crate::const_eval::error_to_const_error; +use crate::const_eval::ConstEvalErr; use crate::interpret::{ self, compile_time_machine, truncate, AllocId, Allocation, Frame, ImmTy, Immediate, InterpCx, LocalState, LocalValue, MemPlace, Memory, MemoryKind, OpTy, Operand as InterpOperand, PlaceTy, @@ -451,7 +451,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { Ok(op) => Some(op), Err(error) => { let tcx = self.ecx.tcx.at(c.span); - let err = error_to_const_error(&self.ecx, error, Some(c.span)); + let err = ConstEvalErr::new(&self.ecx, error, Some(c.span)); if let Some(lint_root) = self.lint_root(source_info) { let lint_only = match c.literal.val { // Promoteds must lint and not error as the user didn't ask for them From 88119c7199401afe87b46cf4c889a61833ed1157 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 9 Aug 2020 17:47:29 +0200 Subject: [PATCH 29/54] evaluate required_consts when pushing stack frame in Miri engine --- src/librustc_mir/interpret/eval_context.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index fc192cd9b3cb2..7c2f749c1567c 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -652,6 +652,13 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let frame = M::init_frame_extra(self, pre_frame)?; self.stack_mut().push(frame); + // Make sure all the constants required by this frame evaluate successfully (post-monomorphization check). + for const_ in &body.required_consts { + let const_ = + self.subst_from_current_frame_and_normalize_erasing_regions(const_.literal); + self.const_to_op(const_, None)?; + } + // Locals are initially uninitialized. let dummy = LocalState { value: LocalValue::Uninitialized, layout: Cell::new(None) }; let mut locals = IndexVec::from_elem(dummy, &body.local_decls); From 4ab5e7d5c091c71eaa2bb1d5a7f887075fec219c Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 9 Aug 2020 18:54:56 +0200 Subject: [PATCH 30/54] bless MIR --- ...allocation2.main.ConstProp.after.mir.32bit | 30 ++++++++--------- ...allocation2.main.ConstProp.after.mir.64bit | 32 +++++++++---------- 2 files changed, 31 insertions(+), 31 deletions(-) diff --git a/src/test/mir-opt/const_allocation2.main.ConstProp.after.mir.32bit b/src/test/mir-opt/const_allocation2.main.ConstProp.after.mir.32bit index d386d24782926..71d55dbb96e11 100644 --- a/src/test/mir-opt/const_allocation2.main.ConstProp.after.mir.32bit +++ b/src/test/mir-opt/const_allocation2.main.ConstProp.after.mir.32bit @@ -30,41 +30,41 @@ fn main() -> () { } alloc0 (static: FOO, size: 8, align: 4) { - ╾─alloc21─╼ 03 00 00 00 │ ╾──╼.... + ╾─alloc23─╼ 03 00 00 00 │ ╾──╼.... } -alloc21 (size: 48, align: 4) { - 0x00 │ 00 00 00 00 __ __ __ __ ╾─alloc4──╼ 00 00 00 00 │ ....░░░░╾──╼.... - 0x10 │ 00 00 00 00 __ __ __ __ ╾─alloc9──╼ 02 00 00 00 │ ....░░░░╾──╼.... - 0x20 │ 01 00 00 00 2a 00 00 00 ╾─alloc19─╼ 03 00 00 00 │ ....*...╾──╼.... +alloc23 (size: 48, align: 4) { + 0x00 │ 00 00 00 00 __ __ __ __ ╾─alloc8──╼ 00 00 00 00 │ ....░░░░╾──╼.... + 0x10 │ 00 00 00 00 __ __ __ __ ╾─alloc13─╼ 02 00 00 00 │ ....░░░░╾──╼.... + 0x20 │ 01 00 00 00 2a 00 00 00 ╾─alloc21─╼ 03 00 00 00 │ ....*...╾──╼.... } -alloc4 (size: 0, align: 4) {} +alloc8 (size: 0, align: 4) {} -alloc9 (size: 8, align: 4) { - ╾─alloc7──╼ ╾─alloc8──╼ │ ╾──╼╾──╼ +alloc13 (size: 8, align: 4) { + ╾─alloc11─╼ ╾─alloc12─╼ │ ╾──╼╾──╼ } -alloc7 (size: 1, align: 1) { +alloc11 (size: 1, align: 1) { 05 │ . } -alloc8 (size: 1, align: 1) { +alloc12 (size: 1, align: 1) { 06 │ . } -alloc19 (size: 12, align: 4) { - ╾─a15+0x3─╼ ╾─alloc16─╼ ╾─a18+0x2─╼ │ ╾──╼╾──╼╾──╼ +alloc21 (size: 12, align: 4) { + ╾─a17+0x3─╼ ╾─alloc18─╼ ╾─a20+0x2─╼ │ ╾──╼╾──╼╾──╼ } -alloc15 (size: 4, align: 1) { +alloc17 (size: 4, align: 1) { 2a 45 15 6f │ *E.o } -alloc16 (size: 1, align: 1) { +alloc18 (size: 1, align: 1) { 2a │ * } -alloc18 (size: 4, align: 1) { +alloc20 (size: 4, align: 1) { 2a 45 15 6f │ *E.o } diff --git a/src/test/mir-opt/const_allocation2.main.ConstProp.after.mir.64bit b/src/test/mir-opt/const_allocation2.main.ConstProp.after.mir.64bit index d7acd0f0f4335..79bad7ea9262b 100644 --- a/src/test/mir-opt/const_allocation2.main.ConstProp.after.mir.64bit +++ b/src/test/mir-opt/const_allocation2.main.ConstProp.after.mir.64bit @@ -30,44 +30,44 @@ fn main() -> () { } alloc0 (static: FOO, size: 16, align: 8) { - ╾───────alloc21───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ + ╾───────alloc23───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ } -alloc21 (size: 72, align: 8) { - 0x00 │ 00 00 00 00 __ __ __ __ ╾───────alloc4────────╼ │ ....░░░░╾──────╼ +alloc23 (size: 72, align: 8) { + 0x00 │ 00 00 00 00 __ __ __ __ ╾───────alloc8────────╼ │ ....░░░░╾──────╼ 0x10 │ 00 00 00 00 00 00 00 00 00 00 00 00 __ __ __ __ │ ............░░░░ - 0x20 │ ╾───────alloc9────────╼ 02 00 00 00 00 00 00 00 │ ╾──────╼........ - 0x30 │ 01 00 00 00 2a 00 00 00 ╾───────alloc19───────╼ │ ....*...╾──────╼ + 0x20 │ ╾───────alloc13───────╼ 02 00 00 00 00 00 00 00 │ ╾──────╼........ + 0x30 │ 01 00 00 00 2a 00 00 00 ╾───────alloc21───────╼ │ ....*...╾──────╼ 0x40 │ 03 00 00 00 00 00 00 00 │ ........ } -alloc4 (size: 0, align: 8) {} +alloc8 (size: 0, align: 8) {} -alloc9 (size: 16, align: 8) { - ╾───────alloc7────────╼ ╾───────alloc8────────╼ │ ╾──────╼╾──────╼ +alloc13 (size: 16, align: 8) { + ╾───────alloc11───────╼ ╾───────alloc12───────╼ │ ╾──────╼╾──────╼ } -alloc7 (size: 1, align: 1) { +alloc11 (size: 1, align: 1) { 05 │ . } -alloc8 (size: 1, align: 1) { +alloc12 (size: 1, align: 1) { 06 │ . } -alloc19 (size: 24, align: 8) { - 0x00 │ ╾─────alloc15+0x3─────╼ ╾───────alloc16───────╼ │ ╾──────╼╾──────╼ - 0x10 │ ╾─────alloc18+0x2─────╼ │ ╾──────╼ +alloc21 (size: 24, align: 8) { + 0x00 │ ╾─────alloc17+0x3─────╼ ╾───────alloc18───────╼ │ ╾──────╼╾──────╼ + 0x10 │ ╾─────alloc20+0x2─────╼ │ ╾──────╼ } -alloc15 (size: 4, align: 1) { +alloc17 (size: 4, align: 1) { 2a 45 15 6f │ *E.o } -alloc16 (size: 1, align: 1) { +alloc18 (size: 1, align: 1) { 2a │ * } -alloc18 (size: 4, align: 1) { +alloc20 (size: 4, align: 1) { 2a 45 15 6f │ *E.o } From 9914b8f830070bbabc20c443b1cd9a81f863e97a Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 10 Aug 2020 10:58:53 +0200 Subject: [PATCH 31/54] add test for unused erroneous const in CTFE --- .../ui/consts/const-eval/erroneous-const.rs | 20 +++++++++ .../consts/const-eval/erroneous-const.stderr | 43 +++++++++++++++++++ 2 files changed, 63 insertions(+) create mode 100644 src/test/ui/consts/const-eval/erroneous-const.rs create mode 100644 src/test/ui/consts/const-eval/erroneous-const.stderr diff --git a/src/test/ui/consts/const-eval/erroneous-const.rs b/src/test/ui/consts/const-eval/erroneous-const.rs new file mode 100644 index 0000000000000..93c4e9372e8fb --- /dev/null +++ b/src/test/ui/consts/const-eval/erroneous-const.rs @@ -0,0 +1,20 @@ +//! Make sure we error on erroneous consts even if they are unused. +#![warn(const_err, unconditional_panic)] + +struct PrintName(T); +impl PrintName { + const VOID: () = [()][2]; //~WARN any use of this value will cause an error + //~^ WARN this operation will panic at runtime +} + +const fn no_codegen() { + if false { //~ERROR evaluation of constant value failed + let _ = PrintName::::VOID; + } +} + +pub static FOO: () = no_codegen::(); //~ERROR could not evaluate static initializer + +fn main() { + FOO +} diff --git a/src/test/ui/consts/const-eval/erroneous-const.stderr b/src/test/ui/consts/const-eval/erroneous-const.stderr new file mode 100644 index 0000000000000..da7e7247d50f9 --- /dev/null +++ b/src/test/ui/consts/const-eval/erroneous-const.stderr @@ -0,0 +1,43 @@ +warning: this operation will panic at runtime + --> $DIR/erroneous-const.rs:6:22 + | +LL | const VOID: () = [()][2]; + | ^^^^^^^ index out of bounds: the len is 1 but the index is 2 + | +note: the lint level is defined here + --> $DIR/erroneous-const.rs:2:20 + | +LL | #![warn(const_err, unconditional_panic)] + | ^^^^^^^^^^^^^^^^^^^ + +warning: any use of this value will cause an error + --> $DIR/erroneous-const.rs:6:22 + | +LL | const VOID: () = [()][2]; + | -----------------^^^^^^^- + | | + | index out of bounds: the len is 1 but the index is 2 + | +note: the lint level is defined here + --> $DIR/erroneous-const.rs:2:9 + | +LL | #![warn(const_err, unconditional_panic)] + | ^^^^^^^^^ + +error[E0080]: evaluation of constant value failed + --> $DIR/erroneous-const.rs:11:5 + | +LL | / if false { +LL | | let _ = PrintName::::VOID; +LL | | } + | |_____^ referenced constant has errors + +error[E0080]: could not evaluate static initializer + --> $DIR/erroneous-const.rs:16:22 + | +LL | pub static FOO: () = no_codegen::(); + | ^^^^^^^^^^^^^^^^^^^ referenced constant has errors + +error: aborting due to 2 previous errors; 2 warnings emitted + +For more information about this error, try `rustc --explain E0080`. From a5c11fb5ebefa1833ff072d5adc51a61e1a68044 Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Mon, 10 Aug 2020 08:05:43 -0400 Subject: [PATCH 32/54] Use existing `infcx` when emitting trait impl diagnostic Fixes #75361 Fixes #74918 Previously, we were creating a new `InferCtxt`, which caused an ICE when used with type variables from the existing `InferCtxt` --- .../trait_impl_difference.rs | 8 ++--- .../issue-74918-missing-lifetime.rs | 28 +++++++++++++++++ .../issue-74918-missing-lifetime.stderr | 30 +++++++++++++++++++ .../issue-75361-mismatched-impl.rs | 24 +++++++++++++++ .../issue-75361-mismatched-impl.stderr | 19 ++++++++++++ 5 files changed, 104 insertions(+), 5 deletions(-) create mode 100644 src/test/ui/mismatched_types/issue-74918-missing-lifetime.rs create mode 100644 src/test/ui/mismatched_types/issue-74918-missing-lifetime.stderr create mode 100644 src/test/ui/mismatched_types/issue-75361-mismatched-impl.rs create mode 100644 src/test/ui/mismatched_types/issue-75361-mismatched-impl.stderr diff --git a/src/librustc_infer/infer/error_reporting/nice_region_error/trait_impl_difference.rs b/src/librustc_infer/infer/error_reporting/nice_region_error/trait_impl_difference.rs index 45aee2b39654d..1ddf88c030660 100644 --- a/src/librustc_infer/infer/error_reporting/nice_region_error/trait_impl_difference.rs +++ b/src/librustc_infer/infer/error_reporting/nice_region_error/trait_impl_difference.rs @@ -2,7 +2,7 @@ use crate::infer::error_reporting::nice_region_error::NiceRegionError; use crate::infer::lexical_region_resolve::RegionResolutionError; -use crate::infer::{Subtype, TyCtxtInferExt, ValuePairs}; +use crate::infer::{Subtype, ValuePairs}; use crate::traits::ObligationCauseCode::CompareImplMethodObligation; use rustc_errors::ErrorReported; use rustc_hir as hir; @@ -53,7 +53,6 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { } fn emit_err(&self, sp: Span, expected: Ty<'tcx>, found: Ty<'tcx>, trait_def_id: DefId) { - let tcx = self.tcx(); let trait_sp = self.tcx().def_span(trait_def_id); let mut err = self .tcx() @@ -85,9 +84,8 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { ); } - if let Some((expected, found)) = tcx - .infer_ctxt() - .enter(|infcx| infcx.expected_found_str_ty(&ExpectedFound { expected, found })) + if let Some((expected, found)) = + self.infcx.expected_found_str_ty(&ExpectedFound { expected, found }) { // Highlighted the differences when showing the "expected/found" note. err.note_expected_found(&"", expected, &"", found); diff --git a/src/test/ui/mismatched_types/issue-74918-missing-lifetime.rs b/src/test/ui/mismatched_types/issue-74918-missing-lifetime.rs new file mode 100644 index 0000000000000..0e3ea4bc8c9de --- /dev/null +++ b/src/test/ui/mismatched_types/issue-74918-missing-lifetime.rs @@ -0,0 +1,28 @@ +// Regression test for issue #74918 +// Tests that we don't ICE after emitting an error + +struct ChunkingIterator> { + source: S, +} + +impl> Iterator for ChunkingIterator { + type Item = IteratorChunk; //~ ERROR missing lifetime + + fn next(&mut self) -> Option> { //~ ERROR `impl` + todo!() + } +} + +struct IteratorChunk<'a, T, S: Iterator> { + source: &'a mut S, +} + +impl> Iterator for IteratorChunk<'_, T, S> { + type Item = T; + + fn next(&mut self) -> Option { + todo!() + } +} + +fn main() {} diff --git a/src/test/ui/mismatched_types/issue-74918-missing-lifetime.stderr b/src/test/ui/mismatched_types/issue-74918-missing-lifetime.stderr new file mode 100644 index 0000000000000..da3056eac9009 --- /dev/null +++ b/src/test/ui/mismatched_types/issue-74918-missing-lifetime.stderr @@ -0,0 +1,30 @@ +error[E0106]: missing lifetime specifier + --> $DIR/issue-74918-missing-lifetime.rs:9:31 + | +LL | type Item = IteratorChunk; + | ^ expected named lifetime parameter + | +help: consider introducing a named lifetime parameter + | +LL | type Item<'a> = IteratorChunk<<'a>T, S>; + | ^^^^ ^^^^ + +error: `impl` item signature doesn't match `trait` item signature + --> $DIR/issue-74918-missing-lifetime.rs:11:5 + | +LL | fn next(&mut self) -> Option> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found `fn(&mut ChunkingIterator) -> std::option::Option>` + | + ::: $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL + | +LL | fn next(&mut self) -> Option; + | ----------------------------------------- expected `fn(&mut ChunkingIterator) -> std::option::Option>` + | + = note: expected `fn(&mut ChunkingIterator) -> std::option::Option>` + found `fn(&mut ChunkingIterator) -> std::option::Option>` + = help: the lifetime requirements from the `impl` do not correspond to the requirements in the `trait` + = help: verify the lifetime relationships in the `trait` and `impl` between the `self` argument, the other inputs and its output + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0106`. diff --git a/src/test/ui/mismatched_types/issue-75361-mismatched-impl.rs b/src/test/ui/mismatched_types/issue-75361-mismatched-impl.rs new file mode 100644 index 0000000000000..4410514476dc1 --- /dev/null +++ b/src/test/ui/mismatched_types/issue-75361-mismatched-impl.rs @@ -0,0 +1,24 @@ +// Regresison test for issue #75361 +// Tests that we don't ICE on mismatched types with inference variables + + +trait MyTrait { + type Item; +} + +pub trait Graph { + type EdgeType; + + fn adjacent_edges(&self) -> Box>; +} + +impl Graph for T { + type EdgeType = T; + + fn adjacent_edges(&self) -> Box + '_> { //~ ERROR `impl` + panic!() + } + +} + +fn main() {} diff --git a/src/test/ui/mismatched_types/issue-75361-mismatched-impl.stderr b/src/test/ui/mismatched_types/issue-75361-mismatched-impl.stderr new file mode 100644 index 0000000000000..5be7f5271dee8 --- /dev/null +++ b/src/test/ui/mismatched_types/issue-75361-mismatched-impl.stderr @@ -0,0 +1,19 @@ +error: `impl` item signature doesn't match `trait` item signature + --> $DIR/issue-75361-mismatched-impl.rs:18:3 + | +LL | fn adjacent_edges(&self) -> Box>; + | --------------------------------------------------------------------- expected `fn(&T) -> std::boxed::Box<(dyn MyTrait + 'static)>` +... +LL | fn adjacent_edges(&self) -> Box + '_> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found `fn(&T) -> std::boxed::Box>` + | + = note: expected `fn(&T) -> std::boxed::Box<(dyn MyTrait + 'static)>` + found `fn(&T) -> std::boxed::Box>` +help: the lifetime requirements from the `impl` do not correspond to the requirements in the `trait` + --> $DIR/issue-75361-mismatched-impl.rs:12:55 + | +LL | fn adjacent_edges(&self) -> Box>; + | ^^^^^^^^^^^^^^ consider borrowing this type parameter in the trait + +error: aborting due to previous error + From 732023e01415c4181498b8c717fa344c72b9e566 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 10 Aug 2020 16:42:11 +0200 Subject: [PATCH 33/54] Add help button --- src/librustdoc/html/layout.rs | 1 + src/librustdoc/html/static/main.js | 4 +++- src/librustdoc/html/static/rustdoc.css | 18 ++++++++++++++---- src/librustdoc/html/static/themes/ayu.css | 5 +++-- src/librustdoc/html/static/themes/dark.css | 5 +++-- src/librustdoc/html/static/themes/light.css | 5 +++-- 6 files changed, 27 insertions(+), 11 deletions(-) diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs index 03011ce4ab304..fd67a66395d7c 100644 --- a/src/librustdoc/html/layout.rs +++ b/src/librustdoc/html/layout.rs @@ -95,6 +95,7 @@ pub fn render( placeholder=\"Click or press ‘S’ to search, ‘?’ for more options…\" \ type=\"search\">\
\ + ? \ div { display: inline-flex; - width: calc(100% - 34px); + width: calc(100% - 63px); } #crate-search { margin-top: 5px; @@ -1250,14 +1250,24 @@ h4 > .notable-traits { outline: none; } -#settings-menu { +#settings-menu, .help-button { position: absolute; - right: 0; top: 10px; +} + +#settings-menu { + right: 0; outline: none; } -#theme-picker, #settings-menu { +.help-button { + right: 30px; + font-family: "Fira Sans",sans-serif; + text-align: center; + font-size: 17px; +} + +#theme-picker, #settings-menu, .help-button { padding: 4px; width: 27px; height: 29px; diff --git a/src/librustdoc/html/static/themes/ayu.css b/src/librustdoc/html/static/themes/ayu.css index 8d176bb352616..6e8db1e9eb792 100644 --- a/src/librustdoc/html/static/themes/ayu.css +++ b/src/librustdoc/html/static/themes/ayu.css @@ -492,7 +492,7 @@ kbd { box-shadow-color: #c6cbd1; } -#theme-picker, #settings-menu { +#theme-picker, #settings-menu, .help-button { border-color: #5c6773; background-color: #0f1419; } @@ -502,7 +502,8 @@ kbd { } #theme-picker:hover, #theme-picker:focus, -#settings-menu:hover, #settings-menu:focus { +#settings-menu:hover, #settings-menu:focus, +.help-button:hover, .help-button:focus { border-color: #e0e0e0; } diff --git a/src/librustdoc/html/static/themes/dark.css b/src/librustdoc/html/static/themes/dark.css index 1c14ab364b38c..eeb1f0a3d4a0b 100644 --- a/src/librustdoc/html/static/themes/dark.css +++ b/src/librustdoc/html/static/themes/dark.css @@ -386,13 +386,14 @@ kbd { box-shadow-color: #c6cbd1; } -#theme-picker, #settings-menu { +#theme-picker, #settings-menu, .help-button { border-color: #e0e0e0; background: #f0f0f0; } #theme-picker:hover, #theme-picker:focus, -#settings-menu:hover, #settings-menu:focus { +#settings-menu:hover, #settings-menu:focus, +.help-button:hover, .help-button:focus { border-color: #ffb900; } diff --git a/src/librustdoc/html/static/themes/light.css b/src/librustdoc/html/static/themes/light.css index 4aafb6c9f94b1..9dea875b87747 100644 --- a/src/librustdoc/html/static/themes/light.css +++ b/src/librustdoc/html/static/themes/light.css @@ -377,13 +377,14 @@ kbd { box-shadow-color: #c6cbd1; } -#theme-picker, #settings-menu { +#theme-picker, #settings-menu, .help-button { border-color: #e0e0e0; background-color: #fff; } #theme-picker:hover, #theme-picker:focus, -#settings-menu:hover, #settings-menu:focus { +#settings-menu:hover, #settings-menu:focus, +.help-button:hover, .help-button:focus { border-color: #717171; } From ecb69e04493094de812fbf242dd8c98969268985 Mon Sep 17 00:00:00 2001 From: Denis Vasilik Date: Sun, 9 Aug 2020 23:06:44 +0200 Subject: [PATCH 34/54] Use intra-doc links --- library/core/src/borrow.rs | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/library/core/src/borrow.rs b/library/core/src/borrow.rs index 3e533255becb5..8d52fb2ad8f4c 100644 --- a/library/core/src/borrow.rs +++ b/library/core/src/borrow.rs @@ -40,14 +40,13 @@ /// provide a reference to related type `T`, it is often better to use /// [`AsRef`] as more types can safely implement it. /// -/// [`AsRef`]: ../../std/convert/trait.AsRef.html -/// [`BorrowMut`]: trait.BorrowMut.html +/// [`AsRef`]: crate::convert::AsRef +/// [`BorrowMut`]: BorrowMut /// [`Box`]: ../../std/boxed/struct.Box.html /// [`Mutex`]: ../../std/sync/struct.Mutex.html /// [`Rc`]: ../../std/rc/struct.Rc.html -/// [`str`]: ../../std/primitive.str.html /// [`String`]: ../../std/string/struct.String.html -/// [`borrow`]: #tymethod.borrow +/// [`borrow`]: Borrow::borrow /// /// # Examples /// @@ -152,10 +151,9 @@ /// If it wants to allow others access to the underlying `str`, it can do /// that via `AsRef` which doesn’t carry any extra requirements. /// -/// [`Hash`]: ../../std/hash/trait.Hash.html +/// [`Hash`]: crate::hash::Hash /// [`HashMap`]: ../../std/collections/struct.HashMap.html /// [`String`]: ../../std/string/struct.String.html -/// [`str`]: ../../std/primitive.str.html #[stable(feature = "rust1", since = "1.0.0")] pub trait Borrow { /// Immutably borrows from an owned value. @@ -187,7 +185,7 @@ pub trait Borrow { /// an underlying type by providing a mutable reference. See [`Borrow`] /// for more information on borrowing as another type. /// -/// [`Borrow`]: trait.Borrow.html +/// [`Borrow`]: Borrow #[stable(feature = "rust1", since = "1.0.0")] pub trait BorrowMut: Borrow { /// Mutably borrows from an owned value. From bedff08b690d6d2a4ba8e132caff9e68d3bfd6aa Mon Sep 17 00:00:00 2001 From: Denis Vasilik Date: Mon, 10 Aug 2020 20:29:20 +0200 Subject: [PATCH 35/54] Remove AsRef link as it is in the prelude --- library/core/src/borrow.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/library/core/src/borrow.rs b/library/core/src/borrow.rs index 8d52fb2ad8f4c..6f5a6aa7c79ca 100644 --- a/library/core/src/borrow.rs +++ b/library/core/src/borrow.rs @@ -40,7 +40,6 @@ /// provide a reference to related type `T`, it is often better to use /// [`AsRef`] as more types can safely implement it. /// -/// [`AsRef`]: crate::convert::AsRef /// [`BorrowMut`]: BorrowMut /// [`Box`]: ../../std/boxed/struct.Box.html /// [`Mutex`]: ../../std/sync/struct.Mutex.html From b51d0a60398e2a89c86f30cd28a1a1ba23b394cf Mon Sep 17 00:00:00 2001 From: Denis Vasilik Date: Mon, 10 Aug 2020 23:14:43 +0200 Subject: [PATCH 36/54] Remove links that are in scope --- library/core/src/cmp.rs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/library/core/src/cmp.rs b/library/core/src/cmp.rs index 79085740119bd..a61ad087ffbff 100644 --- a/library/core/src/cmp.rs +++ b/library/core/src/cmp.rs @@ -17,12 +17,6 @@ //! //! For more details, see the respective documentation of each item in the list. //! -//! [`Eq`]: trait.Eq.html -//! [`PartialEq`]: trait.PartialEq.html -//! [`Ord`]: trait.Ord.html -//! [`PartialOrd`]: trait.PartialOrd.html -//! [`Ordering`]: enum.Ordering.html -//! [`Reverse`]: struct.Reverse.html //! [`max`]: fn.max.html //! [`min`]: fn.min.html From 16f28f08ea437aacc98389a04baf49ad0cfe320e Mon Sep 17 00:00:00 2001 From: Denis Vasilik Date: Mon, 10 Aug 2020 23:16:01 +0200 Subject: [PATCH 37/54] Use intra-doc links --- library/core/src/cmp.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/core/src/cmp.rs b/library/core/src/cmp.rs index a61ad087ffbff..e775ded60f593 100644 --- a/library/core/src/cmp.rs +++ b/library/core/src/cmp.rs @@ -17,8 +17,8 @@ //! //! For more details, see the respective documentation of each item in the list. //! -//! [`max`]: fn.max.html -//! [`min`]: fn.min.html +//! [`max`]: Ord::max +//! [`min`]: Ord::min #![stable(feature = "rust1", since = "1.0.0")] From 82fb3dc7f4a2cf3dedf28905559e60e24625526f Mon Sep 17 00:00:00 2001 From: Lukas Kalbertodt Date: Wed, 22 Jul 2020 11:41:15 +0200 Subject: [PATCH 38/54] Improve `f32` and `f64` primitive documentation --- library/std/src/primitive_docs.rs | 44 ++++++++++++++++++++++++++++--- 1 file changed, 41 insertions(+), 3 deletions(-) diff --git a/library/std/src/primitive_docs.rs b/library/std/src/primitive_docs.rs index 86de509e80a10..f9c96b7c3d4b3 100644 --- a/library/std/src/primitive_docs.rs +++ b/library/std/src/primitive_docs.rs @@ -764,19 +764,57 @@ mod prim_str {} mod prim_tuple {} #[doc(primitive = "f32")] -/// The 32-bit floating point type. +/// A 32-bit floating point type (specifically, the "binary32" type defined in IEEE 754-2008). +/// +/// This type can represent a wide range of decimal numbers, like `3.5`, `27`, +/// `-113.75`, `0.0078125`, `34359738368`, `0`, `-1`. So unlike integer types +/// (like `i32`), floating point types can represent non-integer numbers, too. +/// +/// However, being able to represent this wide range of numbers comes at the +/// cost of precision: floats can only represent some of the real numbers and +/// calculation with floats round to a nearby representable number. For example, +/// `5.0` and `1.0` can be exactly represented as `f32`, but `1.0 / 5.0` results +/// in `0.20000000298023223876953125` since `0.2` cannot be exactly represented +/// as `f32`. Note however, that printing floats with `println` and friends will +/// often discard insignificant digits: `println!("{}", 1.0f32 / 5.0f32)` will +/// print `0.2`. +/// +/// The precision is better for numbers near 0 and worse for large numbers. For +/// example, above 224, not even all integers are representable. +/// +/// Additionally, `f32` can represent a couple of special values: +/// +/// - `-0`: this is just due to how floats are encoded. It is semantically +/// equivalent to `0` and `-0.0 == 0.0` results in `true`. +/// - [∞](#associatedconstant.INFINITY) and +/// [-∞](#associatedconstant.NEG_INFINITY): these result from calculations +/// like `1.0 / 0.0`. +/// - [NaN (not a number)](#associatedconstant.NAN): this value results from +/// calculations like `(-1.0).sqrt()`. NaN has some potentially unexpected +/// behavior: it is unequal to any float, including itself! It is also neither +/// smaller nor greater than any float, making it impossible to sort. Lastly, +/// it is considered infectious as almost all calculations where one of the +/// operands is NaN will also result in NaN. +/// +/// For more information on floating point numbers, see [Wikipedia][wikipedia]. /// /// *[See also the `std::f32::consts` module](f32/consts/index.html).* /// +/// [wikipedia]: https://en.wikipedia.org/wiki/Single-precision_floating-point_format #[stable(feature = "rust1", since = "1.0.0")] mod prim_f32 {} #[doc(primitive = "f64")] -// -/// The 64-bit floating point type. +/// A 64-bit floating point type (specifically, the "binary64" type defined in IEEE 754-2008). +/// +/// This type is very similar to [`f32`](primitive.f32.html), but has increased +/// precision by using twice as many bits. Please see [the documentation for +/// `f32`](primitive.f32.html) or [Wikipedia on double precision +/// values][wikipedia] for more information. /// /// *[See also the `std::f64::consts` module](f64/consts/index.html).* /// +/// [wikipedia]: https://en.wikipedia.org/wiki/Double-precision_floating-point_format #[stable(feature = "rust1", since = "1.0.0")] mod prim_f64 {} From d2842eace92b8206cc6638b89b851b9104906998 Mon Sep 17 00:00:00 2001 From: Stein Somers Date: Tue, 14 Jul 2020 11:32:50 +0200 Subject: [PATCH 39/54] BTreeMap: better distinguish the root holder from the root node --- library/alloc/src/collections/btree/map.rs | 73 +++++++++++---------- library/alloc/src/collections/btree/node.rs | 20 +++--- 2 files changed, 51 insertions(+), 42 deletions(-) diff --git a/library/alloc/src/collections/btree/map.rs b/library/alloc/src/collections/btree/map.rs index 7e27aeb85392c..e7d243bfcb0f7 100644 --- a/library/alloc/src/collections/btree/map.rs +++ b/library/alloc/src/collections/btree/map.rs @@ -2,14 +2,14 @@ use core::borrow::Borrow; use core::cmp::Ordering; -use core::fmt::Debug; +use core::fmt::{self, Debug}; use core::hash::{Hash, Hasher}; use core::iter::{FromIterator, FusedIterator, Peekable}; use core::marker::PhantomData; use core::mem::{self, ManuallyDrop}; use core::ops::Bound::{Excluded, Included, Unbounded}; use core::ops::{Index, RangeBounds}; -use core::{fmt, ptr}; +use core::ptr; use super::node::{self, marker, ForceResult::*, Handle, InsertResult::*, NodeRef}; use super::search::{self, SearchResult::*}; @@ -154,7 +154,7 @@ impl Clone for BTreeMap { { let root = out_tree.root.as_mut().unwrap(); // unwrap succeeds because we just wrapped - let mut out_node = match root.as_mut().force() { + let mut out_node = match root.node_as_mut().force() { Leaf(leaf) => leaf, Internal(_) => unreachable!(), }; @@ -210,7 +210,7 @@ impl Clone for BTreeMap { // Ord` constraint, which this method lacks. BTreeMap { root: None, length: 0 } } else { - clone_subtree(self.root.as_ref().unwrap().as_ref()) // unwrap succeeds because not empty + clone_subtree(self.root.as_ref().unwrap().node_as_ref()) // unwrap succeeds because not empty } } } @@ -223,14 +223,16 @@ where type Key = K; fn get(&self, key: &Q) -> Option<&K> { - match search::search_tree(self.root.as_ref()?.as_ref(), key) { + let root_node = self.root.as_ref()?.node_as_ref(); + match search::search_tree(root_node, key) { Found(handle) => Some(handle.into_kv().0), GoDown(_) => None, } } fn take(&mut self, key: &Q) -> Option { - match search::search_tree(self.root.as_mut()?.as_mut(), key) { + let root_node = self.root.as_mut()?.node_as_mut(); + match search::search_tree(root_node, key) { Found(handle) => Some( OccupiedEntry { handle, length: &mut self.length, _marker: PhantomData } .remove_kv() @@ -242,7 +244,7 @@ where fn replace(&mut self, key: K) -> Option { let root = Self::ensure_is_owned(&mut self.root); - match search::search_tree::, K, (), K>(root.as_mut(), &key) { + match search::search_tree::, K, (), K>(root.node_as_mut(), &key) { Found(handle) => Some(mem::replace(handle.into_kv_mut().0, key)), GoDown(handle) => { VacantEntry { key, handle, length: &mut self.length, _marker: PhantomData } @@ -565,7 +567,8 @@ impl BTreeMap { K: Borrow, Q: Ord, { - match search::search_tree(self.root.as_ref()?.as_ref(), key) { + let root_node = self.root.as_ref()?.node_as_ref(); + match search::search_tree(root_node, key) { Found(handle) => Some(handle.into_kv().1), GoDown(_) => None, } @@ -592,7 +595,8 @@ impl BTreeMap { K: Borrow, Q: Ord, { - match search::search_tree(self.root.as_ref()?.as_ref(), k) { + let root_node = self.root.as_ref()?.node_as_ref(); + match search::search_tree(root_node, k) { Found(handle) => Some(handle.into_kv()), GoDown(_) => None, } @@ -617,8 +621,8 @@ impl BTreeMap { /// ``` #[unstable(feature = "map_first_last", issue = "62924")] pub fn first_key_value(&self) -> Option<(&K, &V)> { - let front = self.root.as_ref()?.as_ref().first_leaf_edge(); - front.right_kv().ok().map(Handle::into_kv) + let root_node = self.root.as_ref()?.node_as_ref(); + root_node.first_leaf_edge().right_kv().ok().map(Handle::into_kv) } /// Returns the first entry in the map for in-place manipulation. @@ -643,8 +647,8 @@ impl BTreeMap { /// ``` #[unstable(feature = "map_first_last", issue = "62924")] pub fn first_entry(&mut self) -> Option> { - let front = self.root.as_mut()?.as_mut().first_leaf_edge(); - let kv = front.right_kv().ok()?; + let root_node = self.root.as_mut()?.node_as_mut(); + let kv = root_node.first_leaf_edge().right_kv().ok()?; Some(OccupiedEntry { handle: kv.forget_node_type(), length: &mut self.length, @@ -694,8 +698,8 @@ impl BTreeMap { /// ``` #[unstable(feature = "map_first_last", issue = "62924")] pub fn last_key_value(&self) -> Option<(&K, &V)> { - let back = self.root.as_ref()?.as_ref().last_leaf_edge(); - back.left_kv().ok().map(Handle::into_kv) + let root_node = self.root.as_ref()?.node_as_ref(); + root_node.last_leaf_edge().left_kv().ok().map(Handle::into_kv) } /// Returns the last entry in the map for in-place manipulation. @@ -720,8 +724,8 @@ impl BTreeMap { /// ``` #[unstable(feature = "map_first_last", issue = "62924")] pub fn last_entry(&mut self) -> Option> { - let back = self.root.as_mut()?.as_mut().last_leaf_edge(); - let kv = back.left_kv().ok()?; + let root_node = self.root.as_mut()?.node_as_mut(); + let kv = root_node.last_leaf_edge().left_kv().ok()?; Some(OccupiedEntry { handle: kv.forget_node_type(), length: &mut self.length, @@ -805,7 +809,8 @@ impl BTreeMap { K: Borrow, Q: Ord, { - match search::search_tree(self.root.as_mut()?.as_mut(), key) { + let root_node = self.root.as_mut()?.node_as_mut(); + match search::search_tree(root_node, key) { Found(handle) => Some(handle.into_kv_mut().1), GoDown(_) => None, } @@ -899,7 +904,8 @@ impl BTreeMap { K: Borrow, Q: Ord, { - match search::search_tree(self.root.as_mut()?.as_mut(), key) { + let root_node = self.root.as_mut()?.node_as_mut(); + match search::search_tree(root_node, key) { Found(handle) => Some( OccupiedEntry { handle, length: &mut self.length, _marker: PhantomData } .remove_entry(), @@ -995,7 +1001,7 @@ impl BTreeMap { R: RangeBounds, { if let Some(root) = &self.root { - let (f, b) = range_search(root.as_ref(), range); + let (f, b) = range_search(root.node_as_ref(), range); Range { front: Some(f), back: Some(b) } } else { @@ -1041,7 +1047,7 @@ impl BTreeMap { R: RangeBounds, { if let Some(root) = &mut self.root { - let (f, b) = range_search(root.as_mut(), range); + let (f, b) = range_search(root.node_as_mut(), range); RangeMut { front: Some(f), back: Some(b), _marker: PhantomData } } else { @@ -1071,7 +1077,7 @@ impl BTreeMap { pub fn entry(&mut self, key: K) -> Entry<'_, K, V> { // FIXME(@porglezomp) Avoid allocating if we don't insert let root = Self::ensure_is_owned(&mut self.root); - match search::search_tree(root.as_mut(), &key) { + match search::search_tree(root.node_as_mut(), &key) { Found(handle) => { Occupied(OccupiedEntry { handle, length: &mut self.length, _marker: PhantomData }) } @@ -1083,7 +1089,7 @@ impl BTreeMap { fn from_sorted_iter>(&mut self, iter: I) { let root = Self::ensure_is_owned(&mut self.root); - let mut cur_node = root.as_mut().last_leaf_edge().into_node(); + let mut cur_node = root.node_as_mut().last_leaf_edge().into_node(); // Iterate through all key-value pairs, pushing them into nodes at the right level. for (key, value) in iter { // Try to push key-value pair into the current leaf node. @@ -1133,7 +1139,7 @@ impl BTreeMap { fn fix_right_edge(root: &mut node::Root) { // Handle underfull nodes, start from the top. - let mut cur_node = root.as_mut(); + let mut cur_node = root.node_as_mut(); while let Internal(internal) = cur_node.force() { // Check if right-most child is underfull. let mut last_edge = internal.last_edge(); @@ -1201,8 +1207,8 @@ impl BTreeMap { } { - let mut left_node = left_root.as_mut(); - let mut right_node = right_root.as_mut(); + let mut left_node = left_root.node_as_mut(); + let mut right_node = right_root.node_as_mut(); loop { let mut split_edge = match search::search_node(left_node, key) { @@ -1280,7 +1286,8 @@ impl BTreeMap { DrainFilter { pred, inner: self.drain_filter_inner() } } pub(super) fn drain_filter_inner(&mut self) -> DrainFilterInner<'_, K, V> { - let front = self.root.as_mut().map(|r| r.as_mut().first_leaf_edge()); + let root_node = self.root.as_mut().map(|r| r.node_as_mut()); + let front = root_node.map(|rn| rn.first_leaf_edge()); DrainFilterInner { length: &mut self.length, cur_leaf_edge: front, @@ -1315,7 +1322,7 @@ impl BTreeMap { res } - self.length = dfs(self.root.as_ref().unwrap().as_ref()); + self.length = dfs(self.root.as_ref().unwrap().node_as_ref()); } /// Creates a consuming iterator visiting all the keys, in sorted order. @@ -2251,7 +2258,7 @@ impl BTreeMap { #[stable(feature = "rust1", since = "1.0.0")] pub fn iter(&self) -> Iter<'_, K, V> { if let Some(root) = &self.root { - let (f, b) = full_range_search(root.as_ref()); + let (f, b) = full_range_search(root.node_as_ref()); Iter { range: Range { front: Some(f), back: Some(b) }, length: self.length } } else { @@ -2283,7 +2290,7 @@ impl BTreeMap { #[stable(feature = "rust1", since = "1.0.0")] pub fn iter_mut(&mut self) -> IterMut<'_, K, V> { if let Some(root) = &mut self.root { - let (f, b) = full_range_search(root.as_mut()); + let (f, b) = full_range_search(root.node_as_mut()); IterMut { range: RangeMut { front: Some(f), back: Some(b), _marker: PhantomData }, @@ -2895,7 +2902,7 @@ impl<'a, K: 'a, V: 'a> Handle, K, V, marker::LeafOrInter impl node::Root { /// Removes empty levels on the top, but keep an empty leaf if the entire tree is empty. fn fix_top(&mut self) { - while self.height() > 0 && self.as_ref().len() == 0 { + while self.height() > 0 && self.node_as_ref().len() == 0 { self.pop_internal_level(); } } @@ -2904,7 +2911,7 @@ impl node::Root { self.fix_top(); { - let mut cur_node = self.as_mut(); + let mut cur_node = self.node_as_mut(); while let Internal(node) = cur_node.force() { let mut last_kv = node.last_kv(); @@ -2930,7 +2937,7 @@ impl node::Root { self.fix_top(); { - let mut cur_node = self.as_mut(); + let mut cur_node = self.node_as_mut(); while let Internal(node) = cur_node.force() { let mut first_kv = node.first_kv(); diff --git a/library/alloc/src/collections/btree/node.rs b/library/alloc/src/collections/btree/node.rs index 4e52c16d20d20..f70869148d59f 100644 --- a/library/alloc/src/collections/btree/node.rs +++ b/library/alloc/src/collections/btree/node.rs @@ -163,7 +163,8 @@ impl Root { Root { node: BoxedNode::from_leaf(Box::new(unsafe { LeafNode::new() })), height: 0 } } - pub fn as_ref(&self) -> NodeRef, K, V, marker::LeafOrInternal> { + /// Borrows and returns an immutable reference to the node owned by the root. + pub fn node_as_ref(&self) -> NodeRef, K, V, marker::LeafOrInternal> { NodeRef { height: self.height, node: self.node.as_ptr(), @@ -172,7 +173,8 @@ impl Root { } } - pub fn as_mut(&mut self) -> NodeRef, K, V, marker::LeafOrInternal> { + /// Borrows and returns a mutable reference to the node owned by the root. + pub fn node_as_mut(&mut self) -> NodeRef, K, V, marker::LeafOrInternal> { NodeRef { height: self.height, node: self.node.as_ptr(), @@ -226,12 +228,12 @@ impl Root { self.node = unsafe { BoxedNode::from_ptr( - self.as_mut().cast_unchecked::().first_edge().descend().node, + self.node_as_mut().cast_unchecked::().first_edge().descend().node, ) }; self.height -= 1; unsafe { - (*self.as_mut().as_leaf_mut()).parent = ptr::null(); + (*self.node_as_mut().as_leaf_mut()).parent = ptr::null(); } unsafe { @@ -616,7 +618,7 @@ impl<'a, K, V> NodeRef, K, V, marker::LeafOrInternal> { let edge = ptr::read(internal.as_internal().edges.get_unchecked(idx + 1).as_ptr()); let mut new_root = Root { node: edge, height: internal.height - 1 }; - (*new_root.as_mut().as_leaf_mut()).parent = ptr::null(); + (*new_root.node_as_mut().as_leaf_mut()).parent = ptr::null(); Some(new_root) } }; @@ -648,7 +650,7 @@ impl<'a, K, V> NodeRef, K, V, marker::LeafOrInternal> { ); let mut new_root = Root { node: edge, height: internal.height - 1 }; - (*new_root.as_mut().as_leaf_mut()).parent = ptr::null(); + (*new_root.node_as_mut().as_leaf_mut()).parent = ptr::null(); for i in 0..old_len { Handle::new_edge(internal.reborrow_mut(), i).correct_parent_link(); @@ -868,7 +870,7 @@ impl<'a, K, V> Handle, K, V, marker::Leaf>, marker::Edge } else { unsafe { Handle::new_edge( - right.as_mut().cast_unchecked::(), + right.node_as_mut().cast_unchecked::(), self.idx - (B + 1), ) .insert_fit(key, val) @@ -943,7 +945,7 @@ impl<'a, K, V> Handle, K, V, marker::Internal>, marker:: } else { unsafe { Handle::new_edge( - right.as_mut().cast_unchecked::(), + right.node_as_mut().cast_unchecked::(), self.idx - (B + 1), ) .insert_fit(key, val, edge); @@ -1117,7 +1119,7 @@ impl<'a, K, V> Handle, K, V, marker::Internal>, marker:: let mut new_root = Root { node: BoxedNode::from_internal(new_node), height }; for i in 0..(new_len + 1) { - Handle::new_edge(new_root.as_mut().cast_unchecked(), i).correct_parent_link(); + Handle::new_edge(new_root.node_as_mut().cast_unchecked(), i).correct_parent_link(); } (self.node, k, v, new_root) From 1c33dee9531f6e1dc67ac830161b6e301ecd2117 Mon Sep 17 00:00:00 2001 From: Erin Power Date: Sat, 25 Jul 2020 16:36:17 +0200 Subject: [PATCH 40/54] Update RELEASES.md for 1.46.0 Co-authored-by: Yuki Okushi Co-authored-by: Lonami --- RELEASES.md | 103 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 103 insertions(+) diff --git a/RELEASES.md b/RELEASES.md index 4859532f7a1f7..b3d8c2f65f633 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1,3 +1,104 @@ +Version 1.46.0 (2020-08-27) +========================== + +Language +-------- +- [`if`, `match`, and `loop` expressions can now be used in const functions.][72437] +- [Additionally you are now also able to coerce and cast to slices (`&[T]`) in + const functions.][73862] +- [The `#[track_caller]` attribute can now be added to functions to use the + function's caller's location information for panic messages.][72445] +- [Recursively indexing into tuples no longer needs parentheses.][71322] E.g. + `x.0.0` over `(x.0).0`. +- [`mem::transmute` can now be used in static and constants.][72920] **Note** + You currently can't use `mem::transmute` in constant functions. + +Compiler +-------- +- [You can now use the `cdylib` target on Apple iOS and tvOS platforms.][73516] +- [Enabled static "Position Independent Executables" by default + for `x86_64-unknown-linux-musl`.][70740] + +Libraries +--------- +- [`mem::forget` is now a `const fn`.][73887] +- [`String` now implements `From`.][73466] +- [The `leading_ones`, and `trailing_ones` methods have been stabilised for all + integer types.][73032] +- [`vec::IntoIter` now implements `AsRef<[T]>`.][72583] +- [All non-zero integer types (`NonZeroU8`) now implement `TryFrom` for their + zero-able equivalent (e.g. `TryFrom`).][72717] +- [`&[T]` and `&mut [T]` now implement `PartialEq>`.][71660] +- [`(String, u16)` now implements `ToSocketAddrs`.][73007] +- [`vec::Drain<'_, T>` now implements `AsRef<[T]>`.][72584] + +Stabilized APIs +--------------- +- [`Option::zip`] +- [`vec::Drain::as_slice`] + +Cargo +----- +Added a number of new environment variables that are now available when +compiling your crate. + +- [`CARGO_BIN_NAME` and `CARGO_CRATE_NAME`][cargo/8270] Providing the name of + the specific binary being compiled and the name of the crate. +- [`CARGO_PKG_LICENSE`][cargo/8325] The license from the manifest of the package. +- [`CARGO_PKG_LICENSE_FILE`][cargo/8387] The path to the license file. + +Compatibility Notes +------------------- +- [The target configuration option `abi_blacklist` has been renamed + to `unsupported_abis`.][74150] The old name will still continue to work. +- [Rustc will now warn if you have a C-like enum that implements `Drop`.][72331] + This was previously accepted but will become a hard error in a future release. +- [Rustc will fail to compile if you have a struct with + `#[repr(i128)]` or `#[repr(u128)]`.][74109] This representation is currently only + allowed on `enum`s. +- [Tokens passed to `macro_rules!` are now always captured.][73293] This helps + ensure that spans have the correct information, and may cause breakage if you + were relying on receiving spans with dummy information. +- [The InnoSetup installer for Windows is no longer available.][72569] This was + a legacy installer that was replaced by a MSI installer a few years ago but + was still being built. +- [`{f32, f64}::asinh` now returns the correct values for negative numbers.][72486] +- [Rustc will no longer accept overlapping trait implementations that only + differ in how the lifetime was bound.][72493] +- [Rustc now correctly relates the lifetime of an existential associated + type.][71896] This fixes some edge cases where `rustc` would erroneously allow + you to pass a shorter lifetime than expected. + +[74109]: https://github.com/rust-lang/rust/pull/74109/ +[74150]: https://github.com/rust-lang/rust/pull/74150/ +[73862]: https://github.com/rust-lang/rust/pull/73862/ +[73887]: https://github.com/rust-lang/rust/pull/73887/ +[73466]: https://github.com/rust-lang/rust/pull/73466/ +[73516]: https://github.com/rust-lang/rust/pull/73516/ +[73293]: https://github.com/rust-lang/rust/pull/73293/ +[73007]: https://github.com/rust-lang/rust/pull/73007/ +[73032]: https://github.com/rust-lang/rust/pull/73032/ +[72920]: https://github.com/rust-lang/rust/pull/72920/ +[72569]: https://github.com/rust-lang/rust/pull/72569/ +[72583]: https://github.com/rust-lang/rust/pull/72583/ +[72584]: https://github.com/rust-lang/rust/pull/72584/ +[72717]: https://github.com/rust-lang/rust/pull/72717/ +[72437]: https://github.com/rust-lang/rust/pull/72437/ +[72445]: https://github.com/rust-lang/rust/pull/72445/ +[72486]: https://github.com/rust-lang/rust/pull/72486/ +[72493]: https://github.com/rust-lang/rust/pull/72493/ +[72331]: https://github.com/rust-lang/rust/pull/72331/ +[71896]: https://github.com/rust-lang/rust/pull/71896/ +[71660]: https://github.com/rust-lang/rust/pull/71660/ +[71322]: https://github.com/rust-lang/rust/pull/71322/ +[70740]: https://github.com/rust-lang/rust/pull/70740/ +[cargo/8270]: https://github.com/rust-lang/cargo/pull/8270/ +[cargo/8325]: https://github.com/rust-lang/cargo/pull/8325/ +[cargo/8387]: https://github.com/rust-lang/cargo/pull/8387/ +[`Option::zip`]: https://doc.rust-lang.org/stable/std/option/enum.Option.html#method.zip +[`vec::Drain::as_slice`]: https://doc.rust-lang.org/stable/std/vec/struct.Drain.html#method.as_slice + + Version 1.45.2 (2020-08-03) ========================== @@ -7,6 +108,7 @@ Version 1.45.2 (2020-08-03) [74954]: https://github.com/rust-lang/rust/issues/74954 [74784]: https://github.com/rust-lang/rust/issues/74784 + Version 1.45.1 (2020-07-30) ========================== @@ -20,6 +122,7 @@ Version 1.45.1 (2020-07-30) [74509]: https://github.com/rust-lang/rust/pull/74509 [74457]: https://github.com/rust-lang/rust/pull/74457 + Version 1.45.0 (2020-07-16) ========================== From 6428eb1f179b853075350b35cbd6b9ff282dc213 Mon Sep 17 00:00:00 2001 From: Lzu Tao Date: Wed, 5 Aug 2020 10:29:38 +0000 Subject: [PATCH 41/54] Transmute between big endian `s6_addr` and `[u16; 8]`. The old code already made the assumption to reinterpret `Ipv6Addr` as `[u16; 8]`. Glibc, Linux, FreeBSD, Win32 all makes this assumption. The main motivation of using union it to better optimize code. ref: * https://docs.microsoft.com/en-us/windows/win32/api/in6addr/ns-in6addr-in6_addr * https://github.com/freebsd/freebsd/blob/1d6e4247415d264485ee94b59fdbc12e0c566fd0/contrib/ntp/lib/isc/include/isc/ipv6.h#L63 * https://github.com/zephyrproject-rtos/zephyr/blob/8b531aa996bba254c03129658490af59597acd78/include/net/net_ip.h#L137 * https://sourceware.org/git/?p=glibc.git;a=blob;f=inet/netinet/in.h;h=f6355c7efe5192b88337b136ef687fe9a5ed648c;hb=HEAD#l216 Co-authored-by: Josh Stone Co-authored-by: Peter Atashian --- library/std/src/lib.rs | 1 + library/std/src/net/ip.rs | 54 +++++++++++++++++++-------------------- 2 files changed, 28 insertions(+), 27 deletions(-) diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 0569e46241a80..f0487e0dff148 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -249,6 +249,7 @@ #![feature(clamp)] #![feature(concat_idents)] #![feature(const_cstr_unchecked)] +#![feature(const_fn_transmute)] #![feature(const_raw_ptr_deref)] #![feature(container_error_extra)] #![feature(core_intrinsics)] diff --git a/library/std/src/net/ip.rs b/library/std/src/net/ip.rs index 159ab981b237d..5d103e6403750 100644 --- a/library/std/src/net/ip.rs +++ b/library/std/src/net/ip.rs @@ -10,6 +10,7 @@ use crate::cmp::Ordering; use crate::fmt::{self, Write as FmtWrite}; use crate::hash; use crate::io::Write as IoWrite; +use crate::mem::transmute; use crate::sys::net::netc as c; use crate::sys_common::{AsInner, FromInner}; @@ -1045,27 +1046,23 @@ impl Ipv6Addr { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_ipv6", since = "1.32.0")] + #[allow_internal_unstable(const_fn_transmute)] pub const fn new(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16, h: u16) -> Ipv6Addr { + let addr16 = [ + a.to_be(), + b.to_be(), + c.to_be(), + d.to_be(), + e.to_be(), + f.to_be(), + g.to_be(), + h.to_be(), + ]; Ipv6Addr { inner: c::in6_addr { - s6_addr: [ - (a >> 8) as u8, - a as u8, - (b >> 8) as u8, - b as u8, - (c >> 8) as u8, - c as u8, - (d >> 8) as u8, - d as u8, - (e >> 8) as u8, - e as u8, - (f >> 8) as u8, - f as u8, - (g >> 8) as u8, - g as u8, - (h >> 8) as u8, - h as u8, - ], + // All elements in `addr16` are big endian. + // SAFETY: `[u16; 8]` is always safe to transmute to `[u8; 16]`. + s6_addr: unsafe { transmute::<_, [u8; 16]>(addr16) }, }, } } @@ -1108,16 +1105,19 @@ impl Ipv6Addr { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn segments(&self) -> [u16; 8] { - let arr = &self.inner.s6_addr; + // All elements in `s6_addr` must be big endian. + // SAFETY: `[u8; 16]` is always safe to transmute to `[u16; 8]`. + let [a, b, c, d, e, f, g, h] = unsafe { transmute::<_, [u16; 8]>(self.inner.s6_addr) }; + // We want native endian u16 [ - u16::from_be_bytes([arr[0], arr[1]]), - u16::from_be_bytes([arr[2], arr[3]]), - u16::from_be_bytes([arr[4], arr[5]]), - u16::from_be_bytes([arr[6], arr[7]]), - u16::from_be_bytes([arr[8], arr[9]]), - u16::from_be_bytes([arr[10], arr[11]]), - u16::from_be_bytes([arr[12], arr[13]]), - u16::from_be_bytes([arr[14], arr[15]]), + u16::from_be(a), + u16::from_be(b), + u16::from_be(c), + u16::from_be(d), + u16::from_be(e), + u16::from_be(f), + u16::from_be(g), + u16::from_be(h), ] } From b1f4d6c445a252b3120a65d31aba82cf4ada3b10 Mon Sep 17 00:00:00 2001 From: Philippe Nadon Date: Sat, 8 Aug 2020 07:53:47 -0600 Subject: [PATCH 42/54] Miri: Renamed "undef" to "uninit" Renamed remaining references to "undef" to "uninit" when referring to Miri. Impacted directories are: - src/librustc_codegen_llvm/consts.rs - src/librustc_middle/mir/interpret/ - src/librustc_middle/ty/print/pretty.rs - src/librustc_mir/ - src/tools/clippy/clippy_lints/src/consts.rs Upon building Miri based on the new changes it was verified that no changes needed to be made with the Miri project. Related issue #71193 --- src/librustc_codegen_llvm/consts.rs | 10 ++++---- .../mir/interpret/allocation.rs | 24 +++++++++---------- src/librustc_middle/mir/interpret/value.rs | 2 +- src/librustc_middle/ty/print/pretty.rs | 4 ++-- src/librustc_mir/interpret/memory.rs | 6 ++--- src/librustc_mir/interpret/operand.rs | 2 +- src/librustc_mir/interpret/place.rs | 4 ++-- src/librustc_mir/interpret/validity.rs | 8 +++---- src/librustc_mir/transform/const_prop.rs | 2 +- src/librustc_mir/util/pretty.rs | 6 ++--- src/tools/clippy/clippy_lints/src/consts.rs | 6 ++--- 11 files changed, 37 insertions(+), 37 deletions(-) diff --git a/src/librustc_codegen_llvm/consts.rs b/src/librustc_codegen_llvm/consts.rs index acfb294f7c12b..024834bfe2aa5 100644 --- a/src/librustc_codegen_llvm/consts.rs +++ b/src/librustc_codegen_llvm/consts.rs @@ -41,7 +41,7 @@ pub fn const_alloc_to_llvm(cx: &CodegenCx<'ll, '_>, alloc: &Allocation) -> &'ll // some arbitrary byte value. // // FIXME: relay undef bytes to codegen as undef const bytes - let bytes = alloc.inspect_with_undef_and_ptr_outside_interpreter(next_offset..offset); + let bytes = alloc.inspect_with_uninit_and_ptr_outside_interpreter(next_offset..offset); llvals.push(cx.const_bytes(bytes)); } let ptr_offset = read_target_uint( @@ -49,7 +49,7 @@ pub fn const_alloc_to_llvm(cx: &CodegenCx<'ll, '_>, alloc: &Allocation) -> &'ll // This `inspect` is okay since it is within the bounds of the allocation, it doesn't // affect interpreter execution (we inspect the result after interpreter execution), // and we properly interpret the relocation as a relocation pointer offset. - alloc.inspect_with_undef_and_ptr_outside_interpreter(offset..(offset + pointer_size)), + alloc.inspect_with_uninit_and_ptr_outside_interpreter(offset..(offset + pointer_size)), ) .expect("const_alloc_to_llvm: could not read relocation pointer") as u64; @@ -74,7 +74,7 @@ pub fn const_alloc_to_llvm(cx: &CodegenCx<'ll, '_>, alloc: &Allocation) -> &'ll // arbitrary byte value. // // FIXME: relay undef bytes to codegen as undef const bytes - let bytes = alloc.inspect_with_undef_and_ptr_outside_interpreter(range); + let bytes = alloc.inspect_with_uninit_and_ptr_outside_interpreter(range); llvals.push(cx.const_bytes(bytes)); } @@ -452,7 +452,7 @@ impl StaticMethods for CodegenCx<'ll, 'tcx> { // BSS. let all_bytes_are_zero = alloc.relocations().is_empty() && alloc - .inspect_with_undef_and_ptr_outside_interpreter(0..alloc.len()) + .inspect_with_uninit_and_ptr_outside_interpreter(0..alloc.len()) .iter() .all(|&byte| byte == 0); @@ -480,7 +480,7 @@ impl StaticMethods for CodegenCx<'ll, 'tcx> { // because we are doing this access to inspect the final interpreter state (not // as part of the interpreter execution). let bytes = - alloc.inspect_with_undef_and_ptr_outside_interpreter(0..alloc.len()); + alloc.inspect_with_uninit_and_ptr_outside_interpreter(0..alloc.len()); let alloc = llvm::LLVMMDStringInContext( self.llcx, bytes.as_ptr().cast(), diff --git a/src/librustc_middle/mir/interpret/allocation.rs b/src/librustc_middle/mir/interpret/allocation.rs index dd4fc7adff117..b23deb2e3bc9b 100644 --- a/src/librustc_middle/mir/interpret/allocation.rs +++ b/src/librustc_middle/mir/interpret/allocation.rs @@ -154,10 +154,10 @@ impl Allocation { } /// Looks at a slice which may describe uninitialized bytes or describe a relocation. This differs - /// from `get_bytes_with_undef_and_ptr` in that it does no relocation checks (even on the + /// from `get_bytes_with_uninit_and_ptr` in that it does no relocation checks (even on the /// edges) at all. It further ignores `AllocationExtra` callbacks. /// This must not be used for reads affecting the interpreter execution. - pub fn inspect_with_undef_and_ptr_outside_interpreter(&self, range: Range) -> &[u8] { + pub fn inspect_with_uninit_and_ptr_outside_interpreter(&self, range: Range) -> &[u8] { &self.bytes[range] } @@ -194,7 +194,7 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { /// The last argument controls whether we error out when there are uninitialized /// or pointer bytes. You should never call this, call `get_bytes` or - /// `get_bytes_with_undef_and_ptr` instead, + /// `get_bytes_with_uninit_and_ptr` instead, /// /// This function also guarantees that the resulting pointer will remain stable /// even when new allocations are pushed to the `HashMap`. `copy_repeatedly` relies @@ -244,7 +244,7 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { /// /// It is the caller's responsibility to check bounds and alignment beforehand. #[inline] - pub fn get_bytes_with_undef_and_ptr( + pub fn get_bytes_with_uninit_and_ptr( &self, cx: &impl HasDataLayout, ptr: Pointer, @@ -302,19 +302,19 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { } /// Validates that `ptr.offset` and `ptr.offset + size` do not point to the middle of a - /// relocation. If `allow_ptr_and_undef` is `false`, also enforces that the memory in the + /// relocation. If `allow_uninit_and_ptr` is `false`, also enforces that the memory in the /// given range contains neither relocations nor uninitialized bytes. pub fn check_bytes( &self, cx: &impl HasDataLayout, ptr: Pointer, size: Size, - allow_ptr_and_undef: bool, + allow_uninit_and_ptr: bool, ) -> InterpResult<'tcx> { // Check bounds and relocations on the edges. - self.get_bytes_with_undef_and_ptr(cx, ptr, size)?; + self.get_bytes_with_uninit_and_ptr(cx, ptr, size)?; // Check uninit and ptr. - if !allow_ptr_and_undef { + if !allow_uninit_and_ptr { self.check_init(ptr, size)?; self.check_relocations(cx, ptr, size)?; } @@ -361,7 +361,7 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { size: Size, ) -> InterpResult<'tcx, ScalarMaybeUninit> { // `get_bytes_unchecked` tests relocation edges. - let bytes = self.get_bytes_with_undef_and_ptr(cx, ptr, size)?; + let bytes = self.get_bytes_with_uninit_and_ptr(cx, ptr, size)?; // Uninit check happens *after* we established that the alignment is correct. // We must not return `Ok()` for unaligned pointers! if self.is_init(ptr, size).is_err() { @@ -594,7 +594,7 @@ impl InitMaskCompressed { /// Transferring the initialization mask to other allocations. impl Allocation { /// Creates a run-length encoding of the initialization mask. - pub fn compress_undef_range(&self, src: Pointer, size: Size) -> InitMaskCompressed { + pub fn compress_uninit_range(&self, src: Pointer, size: Size) -> InitMaskCompressed { // Since we are copying `size` bytes from `src` to `dest + i * size` (`for i in 0..repeat`), // a naive initialization mask copying algorithm would repeatedly have to read the initialization mask from // the source and write it to the destination. Even if we optimized the memory accesses, @@ -636,8 +636,8 @@ impl Allocation { size: Size, repeat: u64, ) { - // An optimization where we can just overwrite an entire range of definedness bits if - // they are going to be uniformly `1` or `0`. + // An optimization where we can just overwrite an entire range of initialization + // bits if they are going to be uniformly `1` or `0`. if defined.ranges.len() <= 1 { self.init_mask.set_range_inbounds( dest.offset, diff --git a/src/librustc_middle/mir/interpret/value.rs b/src/librustc_middle/mir/interpret/value.rs index b4e7a5b98e33b..50c76e29663f6 100644 --- a/src/librustc_middle/mir/interpret/value.rs +++ b/src/librustc_middle/mir/interpret/value.rs @@ -58,7 +58,7 @@ impl<'tcx> ConstValue<'tcx> { pub fn try_to_str_slice(&self) -> Option<&'tcx str> { if let ConstValue::Slice { data, start, end } = *self { - ::std::str::from_utf8(data.inspect_with_undef_and_ptr_outside_interpreter(start..end)) + ::std::str::from_utf8(data.inspect_with_uninit_and_ptr_outside_interpreter(start..end)) .ok() } else { None diff --git a/src/librustc_middle/ty/print/pretty.rs b/src/librustc_middle/ty/print/pretty.rs index 3bb9c20370e8c..87944db60de66 100644 --- a/src/librustc_middle/ty/print/pretty.rs +++ b/src/librustc_middle/ty/print/pretty.rs @@ -1107,7 +1107,7 @@ pub trait PrettyPrinter<'tcx>: // The `inspect` here is okay since we checked the bounds, and there are // no relocations (we have an active slice reference here). We don't use // this result to affect interpreter execution. - let byte_str = data.inspect_with_undef_and_ptr_outside_interpreter(start..end); + let byte_str = data.inspect_with_uninit_and_ptr_outside_interpreter(start..end); self.pretty_print_byte_str(byte_str) } ( @@ -1117,7 +1117,7 @@ pub trait PrettyPrinter<'tcx>: // The `inspect` here is okay since we checked the bounds, and there are no // relocations (we have an active `str` reference here). We don't use this // result to affect interpreter execution. - let slice = data.inspect_with_undef_and_ptr_outside_interpreter(start..end); + let slice = data.inspect_with_uninit_and_ptr_outside_interpreter(start..end); let s = ::std::str::from_utf8(slice).expect("non utf8 str from miri"); p!(write("{:?}", s)); Ok(self) diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index 7dfa913fd08bd..705a547262f02 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -926,7 +926,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { // first copy the relocations to a temporary buffer, because // `get_bytes_mut` will clear the relocations, which is correct, // since we don't want to keep any relocations at the target. - // (`get_bytes_with_undef_and_ptr` below checks that there are no + // (`get_bytes_with_uninit_and_ptr` below checks that there are no // relocations overlapping the edges; those would not be handled correctly). let relocations = self.get_raw(src.alloc_id)?.prepare_relocation_copy(self, src, size, dest, length); @@ -935,7 +935,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { // This checks relocation edges on the src. let src_bytes = - self.get_raw(src.alloc_id)?.get_bytes_with_undef_and_ptr(&tcx, src, size)?.as_ptr(); + self.get_raw(src.alloc_id)?.get_bytes_with_uninit_and_ptr(&tcx, src, size)?.as_ptr(); let dest_bytes = self.get_raw_mut(dest.alloc_id)?.get_bytes_mut(&tcx, dest, size * length)?; // `Size` multiplication @@ -948,7 +948,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { let dest_bytes = dest_bytes.as_mut_ptr(); // Prepare a copy of the initialization mask. - let compressed = self.get_raw(src.alloc_id)?.compress_undef_range(src, size); + let compressed = self.get_raw(src.alloc_id)?.compress_uninit_range(src, size); if compressed.no_bytes_init() { // Fast path: If all bytes are `uninit` then there is nothing to copy. The target range diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs index 49fde4009132d..0b58caef54d2b 100644 --- a/src/librustc_mir/interpret/operand.rs +++ b/src/librustc_mir/interpret/operand.rs @@ -106,7 +106,7 @@ impl std::fmt::Display for ImmTy<'tcx, Tag> { } ScalarMaybeUninit::Uninit => cx.typed_value( |mut this| { - this.write_str("{undef ")?; + this.write_str("{uninit ")?; Ok(this) }, |this| this.print_type(ty), diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs index 15e341d9c4c01..20fd8e43361d6 100644 --- a/src/librustc_mir/interpret/place.rs +++ b/src/librustc_mir/interpret/place.rs @@ -61,7 +61,7 @@ impl MemPlaceMeta { pub struct MemPlace { /// A place may have an integral pointer for ZSTs, and since it might /// be turned back into a reference before ever being dereferenced. - /// However, it may never be undef. + /// However, it may never be uninit. pub ptr: Scalar, pub align: Align, /// Metadata for unsized places. Interpretation is up to the type. @@ -729,7 +729,7 @@ where "Size mismatch when writing bits" ) } - Immediate::Scalar(ScalarMaybeUninit::Uninit) => {} // undef can have any size + Immediate::Scalar(ScalarMaybeUninit::Uninit) => {} // uninit can have any size Immediate::ScalarPair(_, _) => { // FIXME: Can we check anything here? } diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs index f1c5a67ed33f1..9cd20340138cf 100644 --- a/src/librustc_mir/interpret/validity.rs +++ b/src/librustc_mir/interpret/validity.rs @@ -508,12 +508,12 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' } } else { // At run-time, for now, we accept *anything* for these types, including - // undef. We should fix that, but let's start low. + // uninit. We should fix that, but let's start low. } Ok(true) } ty::RawPtr(..) => { - // We are conservative with undef for integers, but try to + // We are conservative with uninit for integers, but try to // actually enforce the strict rules for raw pointers (mostly because // that lets us re-use `ref_to_mplace`). let place = try_validation!( @@ -807,12 +807,12 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M> // reject it. However, that's good: We don't inherently want // to reject those pointers, we just do not have the machinery to // talk about parts of a pointer. - // We also accept undef, for consistency with the slow path. + // We also accept uninit, for consistency with the slow path. match self.ecx.memory.get_raw(ptr.alloc_id)?.check_bytes( self.ecx, ptr, size, - /*allow_ptr_and_undef*/ self.ref_tracking_for_consts.is_none(), + /*allow_uninit_and_ptr*/ self.ref_tracking_for_consts.is_none(), ) { // In the happy case, we needn't check anything else. Ok(()) => {} diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index bff83b3c6db74..07b13af6ba776 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -1076,7 +1076,7 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> { // ```rust // let mut x = 42; // x = SOME_MUTABLE_STATIC; - // // x must now be undefined + // // x must now be uninit // ``` // FIXME: we overzealously erase the entire local, because that's easier to // implement. diff --git a/src/librustc_mir/util/pretty.rs b/src/librustc_mir/util/pretty.rs index 25657ba98b893..c3dbac08ed800 100644 --- a/src/librustc_mir/util/pretty.rs +++ b/src/librustc_mir/util/pretty.rs @@ -743,8 +743,8 @@ fn write_allocation_bytes( if let Some(&(tag, target_id)) = alloc.relocations().get(&i) { // Memory with a relocation must be defined let j = i.bytes_usize(); - let offset = - alloc.inspect_with_undef_and_ptr_outside_interpreter(j..j + ptr_size.bytes_usize()); + let offset = alloc + .inspect_with_uninit_and_ptr_outside_interpreter(j..j + ptr_size.bytes_usize()); let offset = read_target_uint(tcx.data_layout.endian, offset).unwrap(); let offset = Size::from_bytes(offset); let relocation_width = |bytes| bytes * 3; @@ -803,7 +803,7 @@ fn write_allocation_bytes( // Checked definedness (and thus range) and relocations. This access also doesn't // influence interpreter execution but is only for debugging. - let c = alloc.inspect_with_undef_and_ptr_outside_interpreter(j..j + 1)[0]; + let c = alloc.inspect_with_uninit_and_ptr_outside_interpreter(j..j + 1)[0]; write!(w, "{:02x}", c)?; if c.is_ascii_control() || c >= 0x80 { ascii.push('.'); diff --git a/src/tools/clippy/clippy_lints/src/consts.rs b/src/tools/clippy/clippy_lints/src/consts.rs index 49ff86a205d96..c77b80bc23733 100644 --- a/src/tools/clippy/clippy_lints/src/consts.rs +++ b/src/tools/clippy/clippy_lints/src/consts.rs @@ -517,7 +517,7 @@ pub fn miri_to_const(result: &ty::Const<'_>) -> Option { ty::ConstKind::Value(ConstValue::Slice { data, start, end }) => match result.ty.kind { ty::Ref(_, tam, _) => match tam.kind { ty::Str => String::from_utf8( - data.inspect_with_undef_and_ptr_outside_interpreter(start..end) + data.inspect_with_uninit_and_ptr_outside_interpreter(start..end) .to_owned(), ) .ok() @@ -530,7 +530,7 @@ pub fn miri_to_const(result: &ty::Const<'_>) -> Option { ty::Array(sub_type, len) => match sub_type.kind { ty::Float(FloatTy::F32) => match miri_to_const(len) { Some(Constant::Int(len)) => alloc - .inspect_with_undef_and_ptr_outside_interpreter(0..(4 * len as usize)) + .inspect_with_uninit_and_ptr_outside_interpreter(0..(4 * len as usize)) .to_owned() .chunks(4) .map(|chunk| { @@ -544,7 +544,7 @@ pub fn miri_to_const(result: &ty::Const<'_>) -> Option { }, ty::Float(FloatTy::F64) => match miri_to_const(len) { Some(Constant::Int(len)) => alloc - .inspect_with_undef_and_ptr_outside_interpreter(0..(8 * len as usize)) + .inspect_with_uninit_and_ptr_outside_interpreter(0..(8 * len as usize)) .to_owned() .chunks(8) .map(|chunk| { From f71b9b098fab9251d5baeb4acc234d9d2873aada Mon Sep 17 00:00:00 2001 From: David Wood Date: Sun, 9 Aug 2020 11:22:50 +0100 Subject: [PATCH 43/54] polymorphize: constrain unevaluated const handling This commit constrains the support added for handling unevaluated consts in polymorphization (introduced in #75260) by: - Skipping associated constants as this causes cycle errors. - Skipping promoted constants when they contain `Self` as this ensures `T` is used in constants of the form `>`. Signed-off-by: David Wood --- src/librustc_mir/monomorphize/polymorphize.rs | 14 ++++++++++---- .../ui/polymorphization/promoted-function-3.rs | 14 ++++++++++++++ 2 files changed, 24 insertions(+), 4 deletions(-) create mode 100644 src/test/ui/polymorphization/promoted-function-3.rs diff --git a/src/librustc_mir/monomorphize/polymorphize.rs b/src/librustc_mir/monomorphize/polymorphize.rs index a996b6fb9d924..fc9f7f1af622f 100644 --- a/src/librustc_mir/monomorphize/polymorphize.rs +++ b/src/librustc_mir/monomorphize/polymorphize.rs @@ -269,15 +269,21 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for UsedGenericParametersVisitor<'a, 'tcx> { self.unused_parameters.clear(param.index); false } - ty::ConstKind::Unevaluated(_, _, Some(p)) => { + ty::ConstKind::Unevaluated(def, _, Some(p)) + // Avoid considering `T` unused when constants are of the form: + // `>::foo::promoted[p]` + if self.def_id == def.did && !self.tcx.generics_of(def.did).has_self => + { // If there is a promoted, don't look at the substs - since it will always contain // the generic parameters, instead, traverse the promoted MIR. - let promoted = self.tcx.promoted_mir(self.def_id); + let promoted = self.tcx.promoted_mir(def.did); self.visit_body(&promoted[p]); false } - ty::ConstKind::Unevaluated(def_id, unevaluated_substs, None) => { - self.visit_child_body(def_id.did, unevaluated_substs); + ty::ConstKind::Unevaluated(def, unevaluated_substs, None) + if self.tcx.def_kind(def.did) == DefKind::AnonConst => + { + self.visit_child_body(def.did, unevaluated_substs); false } _ => c.super_visit_with(self), diff --git a/src/test/ui/polymorphization/promoted-function-3.rs b/src/test/ui/polymorphization/promoted-function-3.rs new file mode 100644 index 0000000000000..1c84df13e10b0 --- /dev/null +++ b/src/test/ui/polymorphization/promoted-function-3.rs @@ -0,0 +1,14 @@ +// run-pass +// compile-flags: -Zpolymorphize=on -Zmir-opt-level=3 + +fn caller() -> &'static usize { + callee::() +} + +fn callee() -> &'static usize { + &std::mem::size_of::() +} + +fn main() { + assert_eq!(caller::<(), ()>(), &0); +} From d3bd75e37d1460af22146dfd206da83378faa15b Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 9 Aug 2020 18:01:37 +0200 Subject: [PATCH 44/54] move stack size check to const_eval machine --- src/librustc_mir/const_eval/machine.rs | 9 +++++++++ src/librustc_mir/interpret/eval_context.rs | 6 +----- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/librustc_mir/const_eval/machine.rs b/src/librustc_mir/const_eval/machine.rs index 0dac8b6491011..3a753a0edb665 100644 --- a/src/librustc_mir/const_eval/machine.rs +++ b/src/librustc_mir/const_eval/machine.rs @@ -301,6 +301,15 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, Ok(()) } + fn after_stack_push(ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx> { + // Enforce stack size limit. + if !ecx.tcx.sess.recursion_limit().value_within_limit(ecx.stack().len()) { + throw_exhaust!(StackFrameLimitReached) + } else { + Ok(()) + } + } + #[inline(always)] fn stack( ecx: &'a InterpCx<'mir, 'tcx, Self>, diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index 7c2f749c1567c..bcf2899b439b5 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -687,11 +687,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { M::after_stack_push(self)?; info!("ENTERING({}) {}", self.frame_idx(), self.frame().instance); - if !self.tcx.sess.recursion_limit().value_within_limit(self.stack().len()) { - throw_exhaust!(StackFrameLimitReached) - } else { - Ok(()) - } + Ok(()) } /// Jump to the given block. From cbedc47daa40e797795ccb9a80994c1800f1dee6 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Sun, 9 Aug 2020 21:23:19 +0200 Subject: [PATCH 45/54] Rustdoc: Fix natural ordering to look at all numbers. The old implementation only looks at numbers at the end, but not in other places in a name: "u8" and "u16" got sorted properly, but "u8_bla" and "u16_bla" did not. --- src/librustdoc/html/render/mod.rs | 54 +++++++++++++++++++---------- src/librustdoc/html/render/tests.rs | 38 ++++++++++++++------ 2 files changed, 63 insertions(+), 29 deletions(-) diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 4cbc56333b155..3635753969286 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -1903,23 +1903,41 @@ fn document_non_exhaustive(w: &mut Buffer, item: &clean::Item) { } } -fn name_key(name: &str) -> (&str, u64, usize) { - let end = name.bytes().rposition(|b| b.is_ascii_digit()).map_or(name.len(), |i| i + 1); - - // find number at end - let split = name[0..end].bytes().rposition(|b| !b.is_ascii_digit()).map_or(0, |i| i + 1); - - // count leading zeroes - let after_zeroes = - name[split..end].bytes().position(|b| b != b'0').map_or(name.len(), |extra| split + extra); - - // sort leading zeroes last - let num_zeroes = after_zeroes - split; - - match name[split..end].parse() { - Ok(n) => (&name[..split], n, num_zeroes), - Err(_) => (name, 0, num_zeroes), +/// Compare two strings treating multi-digit numbers as single units (i.e. natural sort order). +pub fn compare_names(mut lhs: &str, mut rhs: &str) -> Ordering { + /// Takes a non-numeric and a numeric part from the given &str. + fn take_parts<'a>(s: &mut &'a str) -> (&'a str, &'a str) { + let i = s.find(|c: char| c.is_ascii_digit()); + let (a, b) = s.split_at(i.unwrap_or(s.len())); + let i = b.find(|c: char| !c.is_ascii_digit()); + let (b, c) = b.split_at(i.unwrap_or(b.len())); + *s = c; + (a, b) + } + + while !lhs.is_empty() || !rhs.is_empty() { + let (la, lb) = take_parts(&mut lhs); + let (ra, rb) = take_parts(&mut rhs); + // First process the non-numeric part. + match la.cmp(ra) { + Ordering::Equal => (), + x => return x, + } + // Then process the numeric part, if both sides have one (and they fit in a u64). + if let (Ok(ln), Ok(rn)) = (lb.parse::(), rb.parse::()) { + match ln.cmp(&rn) { + Ordering::Equal => (), + x => return x, + } + } + // Then process the numeric part again, but this time as strings. + match lb.cmp(rb) { + Ordering::Equal => (), + x => return x, + } } + + Ordering::Equal } fn item_module(w: &mut Buffer, cx: &Context, item: &clean::Item, items: &[clean::Item]) { @@ -1962,7 +1980,7 @@ fn item_module(w: &mut Buffer, cx: &Context, item: &clean::Item, items: &[clean: } let lhs = i1.name.as_ref().map_or("", |s| &**s); let rhs = i2.name.as_ref().map_or("", |s| &**s); - name_key(lhs).cmp(&name_key(rhs)) + compare_names(lhs, rhs) } if cx.shared.sort_modules_alphabetically { @@ -2395,7 +2413,7 @@ fn compare_impl<'a, 'b>(lhs: &'a &&Impl, rhs: &'b &&Impl) -> Ordering { let rhs = format!("{}", rhs.inner_impl().print()); // lhs and rhs are formatted as HTML, which may be unnecessary - name_key(&lhs).cmp(&name_key(&rhs)) + compare_names(&lhs, &rhs) } fn item_trait(w: &mut Buffer, cx: &Context, it: &clean::Item, t: &clean::Trait, cache: &Cache) { diff --git a/src/librustdoc/html/render/tests.rs b/src/librustdoc/html/render/tests.rs index 99ad26549f5d3..abf5f05fe58ab 100644 --- a/src/librustdoc/html/render/tests.rs +++ b/src/librustdoc/html/render/tests.rs @@ -1,24 +1,40 @@ use super::*; #[test] -fn test_name_key() { - assert_eq!(name_key("0"), ("", 0, 1)); - assert_eq!(name_key("123"), ("", 123, 0)); - assert_eq!(name_key("Fruit"), ("Fruit", 0, 0)); - assert_eq!(name_key("Fruit0"), ("Fruit", 0, 1)); - assert_eq!(name_key("Fruit0000"), ("Fruit", 0, 4)); - assert_eq!(name_key("Fruit01"), ("Fruit", 1, 1)); - assert_eq!(name_key("Fruit10"), ("Fruit", 10, 0)); - assert_eq!(name_key("Fruit123"), ("Fruit", 123, 0)); +fn test_compare_names() { + for &(a, b) in &[ + ("hello", "world"), + ("", "world"), + ("123", "hello"), + ("123", ""), + ("123test", "123"), + ("hello", ""), + ("hello", "hello"), + ("hello123", "hello123"), + ("hello123", "hello12"), + ("hello12", "hello123"), + ("hello01abc", "hello01xyz"), + ("hello0abc", "hello0"), + ("hello0", "hello0abc"), + ("01", "1"), + ] { + assert_eq!(compare_names(a, b), a.cmp(b), "{:?} - {:?}", a, b); + } + assert_eq!(compare_names("u8", "u16"), Ordering::Less); + assert_eq!(compare_names("u32", "u16"), Ordering::Greater); + assert_eq!(compare_names("u8_to_f64", "u16_to_f64"), Ordering::Less); + assert_eq!(compare_names("u32_to_f64", "u16_to_f64"), Ordering::Greater); + assert_eq!(compare_names("u16_to_f64", "u16_to_f64"), Ordering::Equal); + assert_eq!(compare_names("u16_to_f32", "u16_to_f64"), Ordering::Less); } #[test] fn test_name_sorting() { let names = [ - "Apple", "Banana", "Fruit", "Fruit0", "Fruit00", "Fruit1", "Fruit01", "Fruit2", "Fruit02", + "Apple", "Banana", "Fruit", "Fruit0", "Fruit00", "Fruit01", "Fruit1", "Fruit02", "Fruit2", "Fruit20", "Fruit30x", "Fruit100", "Pear", ]; let mut sorted = names.to_owned(); - sorted.sort_by_key(|&s| name_key(s)); + sorted.sort_by(|&l, r| compare_names(l, r)); assert_eq!(names, sorted); } From 5b74e4a5e1e0c2e5cf9ba1dcfce9ff052ec84b83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 9 Aug 2020 16:56:47 -0700 Subject: [PATCH 46/54] Tweak conditions for E0026 and E0769 When we have a tuple struct used with struct we don't want to suggest using the (valid) struct syntax with numeric field names. Instead we want to suggest the expected syntax. Given ```rust fn main() { match MyOption::MySome(42) { MyOption::MySome { x: 42 } => (), _ => (), } } ``` We now emit E0769 "tuple variant `MyOption::MySome` written as struct variant" instead of E0026 "variant `MyOption::MySome` does not have a field named `x`". --- src/librustc_typeck/check/pat.rs | 11 +++++++++-- src/test/ui/issues/issue-17800.rs | 2 +- src/test/ui/issues/issue-17800.stderr | 11 ++++------- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/src/librustc_typeck/check/pat.rs b/src/librustc_typeck/check/pat.rs index f598ada900fee..1c78bef98527a 100644 --- a/src/librustc_typeck/check/pat.rs +++ b/src/librustc_typeck/check/pat.rs @@ -1229,8 +1229,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Applicability::MaybeIncorrect, ); - // we don't want to throw `E0027` in case we have thrown `E0026` for them - unmentioned_fields.retain(|&x| x.name != suggested_name); + // When we have a tuple struct used with struct we don't want to suggest using + // the (valid) struct syntax with numeric field names. Instead we want to + // suggest the expected syntax. We infer that this is the case by parsing the + // `Ident` into an unsized integer. The suggestion will be emitted elsewhere in + // `smart_resolve_context_dependent_help`. + if suggested_name.to_ident_string().parse::().is_err() { + // We don't want to throw `E0027` in case we have thrown `E0026` for them. + unmentioned_fields.retain(|&x| x.name != suggested_name); + } } } } diff --git a/src/test/ui/issues/issue-17800.rs b/src/test/ui/issues/issue-17800.rs index 45879d68b3541..5254f45d7c2de 100644 --- a/src/test/ui/issues/issue-17800.rs +++ b/src/test/ui/issues/issue-17800.rs @@ -6,7 +6,7 @@ enum MyOption { fn main() { match MyOption::MySome(42) { MyOption::MySome { x: 42 } => (), - //~^ ERROR variant `MyOption::MySome` does not have a field named `x` + //~^ ERROR tuple variant `MyOption::MySome` written as struct variant _ => (), } } diff --git a/src/test/ui/issues/issue-17800.stderr b/src/test/ui/issues/issue-17800.stderr index 6efc7f0c06e11..fc034a0cbf3b8 100644 --- a/src/test/ui/issues/issue-17800.stderr +++ b/src/test/ui/issues/issue-17800.stderr @@ -1,12 +1,9 @@ -error[E0026]: variant `MyOption::MySome` does not have a field named `x` - --> $DIR/issue-17800.rs:8:28 +error[E0769]: tuple variant `MyOption::MySome` written as struct variant + --> $DIR/issue-17800.rs:8:9 | LL | MyOption::MySome { x: 42 } => (), - | ^ - | | - | variant `MyOption::MySome` does not have this field - | help: a field with a similar name exists: `0` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the tuple variant pattern syntax instead: `MyOption::MySome(42)` error: aborting due to previous error -For more information about this error, try `rustc --explain E0026`. +For more information about this error, try `rustc --explain E0769`. From 0c13114c484cf6842c7acfbf516b17f5307cb1a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 9 Aug 2020 17:48:32 -0700 Subject: [PATCH 47/54] Small cleanup Remove unnecessary `unwrap`. --- src/librustc_resolve/late/diagnostics.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/librustc_resolve/late/diagnostics.rs b/src/librustc_resolve/late/diagnostics.rs index dcab0858a75ae..c57c0e5194185 100644 --- a/src/librustc_resolve/late/diagnostics.rs +++ b/src/librustc_resolve/late/diagnostics.rs @@ -392,15 +392,15 @@ impl<'a> LateResolutionVisitor<'a, '_, '_> { /// return the span of whole call and the span for all arguments expect the first one (`self`). fn call_has_self_arg(&self, source: PathSource<'_>) -> Option<(Span, Option)> { let mut has_self_arg = None; - if let PathSource::Expr(parent) = source { - match &parent?.kind { + if let PathSource::Expr(Some(parent)) = source { + match &parent.kind { ExprKind::Call(_, args) if !args.is_empty() => { let mut expr_kind = &args[0].kind; loop { match expr_kind { ExprKind::Path(_, arg_name) if arg_name.segments.len() == 1 => { if arg_name.segments[0].ident.name == kw::SelfLower { - let call_span = parent.unwrap().span; + let call_span = parent.span; let tail_args_span = if args.len() > 1 { Some(Span::new( args[1].span.lo(), From 72e5043bad003d881f460f99e498461f209a2e30 Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Mon, 10 Aug 2020 12:04:51 +0200 Subject: [PATCH 48/54] unused_delims: trim expr --- src/librustc_lint/unused.rs | 36 ++++++++++--------- .../ui/const-generics/unused_braces.fixed | 2 +- src/test/ui/lint/unused_braces.fixed | 8 ++--- src/test/ui/lint/unused_braces_borrow.fixed | 2 +- .../try-block/try-block-unused-delims.fixed | 2 +- 5 files changed, 26 insertions(+), 24 deletions(-) diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs index 5de9a16e09881..ecc8a192f18ea 100644 --- a/src/librustc_lint/unused.rs +++ b/src/librustc_lint/unused.rs @@ -481,25 +481,27 @@ trait UnusedDelimLint { let mut err = lint.build(&span_msg); let mut ate_left_paren = false; let mut ate_right_paren = false; - let parens_removed = pattern.trim_matches(|c| match c { - '(' | '{' => { - if ate_left_paren { - false - } else { - ate_left_paren = true; - true + let parens_removed = pattern + .trim_matches(|c| match c { + '(' | '{' => { + if ate_left_paren { + false + } else { + ate_left_paren = true; + true + } } - } - ')' | '}' => { - if ate_right_paren { - false - } else { - ate_right_paren = true; - true + ')' | '}' => { + if ate_right_paren { + false + } else { + ate_right_paren = true; + true + } } - } - _ => false, - }); + _ => false, + }) + .trim(); let replace = { let mut replace = if keep_space.0 { diff --git a/src/test/ui/const-generics/unused_braces.fixed b/src/test/ui/const-generics/unused_braces.fixed index 5c2b9267af583..836f26efc9601 100644 --- a/src/test/ui/const-generics/unused_braces.fixed +++ b/src/test/ui/const-generics/unused_braces.fixed @@ -10,6 +10,6 @@ struct A; fn main() { let _: A<7>; // ok - let _: A< 7 >; //~ WARN unnecessary braces + let _: A<7>; //~ WARN unnecessary braces let _: A<{ 3 + 5 }>; // ok } diff --git a/src/test/ui/lint/unused_braces.fixed b/src/test/ui/lint/unused_braces.fixed index c0225911c6ed0..1a88d985dd86a 100644 --- a/src/test/ui/lint/unused_braces.fixed +++ b/src/test/ui/lint/unused_braces.fixed @@ -23,18 +23,18 @@ fn main() { } } - if true { + if true { //~^ WARN unnecessary braces } - while false { + while false { //~^ WARN unnecessary braces } - let _: [u8; 3 ]; + let _: [u8; 3]; //~^ WARN unnecessary braces - consume( 7 ); + consume(7); //~^ WARN unnecessary braces // Do not emit lint for multiline blocks. diff --git a/src/test/ui/lint/unused_braces_borrow.fixed b/src/test/ui/lint/unused_braces_borrow.fixed index 25950334549f9..583506f891d01 100644 --- a/src/test/ui/lint/unused_braces_borrow.fixed +++ b/src/test/ui/lint/unused_braces_borrow.fixed @@ -21,6 +21,6 @@ fn main() { }; consume(&{ a.b }); - consume( a.b ); + consume(a.b); //~^ WARN unnecessary braces } diff --git a/src/test/ui/try-block/try-block-unused-delims.fixed b/src/test/ui/try-block/try-block-unused-delims.fixed index c8b03c2006840..756081738c3d7 100644 --- a/src/test/ui/try-block/try-block-unused-delims.fixed +++ b/src/test/ui/try-block/try-block-unused-delims.fixed @@ -11,7 +11,7 @@ fn main() { consume(try {}); //~^ WARN unnecessary parentheses - consume( try {} ); + consume(try {}); //~^ WARN unnecessary braces match try {} { From 2407bf9814fdd894d8f4be3a49ac4391bf773dd6 Mon Sep 17 00:00:00 2001 From: Ivan Tham Date: Mon, 10 Aug 2020 18:51:14 +0800 Subject: [PATCH 49/54] Add sample fix for E0749 Even though the description is clear but the solution may not be as straightforward. Adding a suggested fix. --- src/librustc_error_codes/error_codes/E0749.md | 1 + 1 file changed, 1 insertion(+) diff --git a/src/librustc_error_codes/error_codes/E0749.md b/src/librustc_error_codes/error_codes/E0749.md index 7a1a745b53c12..74cd2903f6d01 100644 --- a/src/librustc_error_codes/error_codes/E0749.md +++ b/src/librustc_error_codes/error_codes/E0749.md @@ -11,6 +11,7 @@ trait MyTrait { impl !MyTrait for u32 { type Foo = i32; // error! } +// impl !MyTrait for u32 {} // fix # fn main() {} ``` From f0cee8ff2ba5fa886dd790e4b16f58a6eb3ca859 Mon Sep 17 00:00:00 2001 From: Ivan Tham Date: Mon, 10 Aug 2020 22:33:17 +0800 Subject: [PATCH 50/54] Split fix into another section for E0749 --- src/librustc_error_codes/error_codes/E0749.md | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/librustc_error_codes/error_codes/E0749.md b/src/librustc_error_codes/error_codes/E0749.md index 74cd2903f6d01..962da0eda08f6 100644 --- a/src/librustc_error_codes/error_codes/E0749.md +++ b/src/librustc_error_codes/error_codes/E0749.md @@ -11,10 +11,20 @@ trait MyTrait { impl !MyTrait for u32 { type Foo = i32; // error! } -// impl !MyTrait for u32 {} // fix # fn main() {} ``` Negative impls are not allowed to have any items. Negative impls declare that a trait is **not** implemented (and never will be) and hence there is no need to specify the values for trait methods or other items. + +One way to fix this is to remove the items in negative impls. + +``` +# #![feature(negative_impls)] +trait MyTrait { + type Foo; +} + +impl !MyTrait for u32 {} +``` From 4f284db823f262df8721a23c689c84926613b852 Mon Sep 17 00:00:00 2001 From: Ivan Tham Date: Mon, 10 Aug 2020 22:46:15 +0800 Subject: [PATCH 51/54] Use : rather than . in example description Co-authored-by: Guillaume Gomez --- src/librustc_error_codes/error_codes/E0749.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_error_codes/error_codes/E0749.md b/src/librustc_error_codes/error_codes/E0749.md index 962da0eda08f6..5b6bfe75cfc90 100644 --- a/src/librustc_error_codes/error_codes/E0749.md +++ b/src/librustc_error_codes/error_codes/E0749.md @@ -18,7 +18,7 @@ Negative impls are not allowed to have any items. Negative impls declare that a trait is **not** implemented (and never will be) and hence there is no need to specify the values for trait methods or other items. -One way to fix this is to remove the items in negative impls. +One way to fix this is to remove the items in negative impls: ``` # #![feature(negative_impls)] From 8bbef5c37c4b90edb7356eee57eea9fcca7df6a7 Mon Sep 17 00:00:00 2001 From: Ivan Tham Date: Tue, 11 Aug 2020 01:06:30 +0800 Subject: [PATCH 52/54] Remove empty fn main from E0749 --- src/librustc_error_codes/error_codes/E0749.md | 1 - 1 file changed, 1 deletion(-) diff --git a/src/librustc_error_codes/error_codes/E0749.md b/src/librustc_error_codes/error_codes/E0749.md index 5b6bfe75cfc90..dfe90ae89e4cb 100644 --- a/src/librustc_error_codes/error_codes/E0749.md +++ b/src/librustc_error_codes/error_codes/E0749.md @@ -11,7 +11,6 @@ trait MyTrait { impl !MyTrait for u32 { type Foo = i32; // error! } -# fn main() {} ``` Negative impls are not allowed to have any items. Negative impls declare that a From d19541e216c88548650f694624fd40f75c067c83 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 17 May 2020 15:39:35 +0200 Subject: [PATCH 53/54] move Deaggregate pass to post_borrowck_cleanup --- src/librustc_mir/interpret/step.rs | 4 +- src/librustc_mir/transform/const_prop.rs | 26 ++- src/librustc_mir/transform/mod.rs | 11 +- src/test/codegen/consts.rs | 4 +- .../const_prop/aggregate.main.ConstProp.diff | 4 +- .../discriminant.main.ConstProp.diff.32bit | 22 +-- .../discriminant.main.ConstProp.diff.64bit | 22 +-- .../issue_66971.main.ConstProp.diff | 9 +- .../issue_67019.main.ConstProp.diff | 24 ++- ...ble_variable_aggregate.main.ConstProp.diff | 9 +- ...able_aggregate_mut_ref.main.ConstProp.diff | 3 +- ...variable_unprop_assign.main.ConstProp.diff | 9 +- ...es_into_variable.main.ConstProp.diff.32bit | 3 +- ...es_into_variable.main.ConstProp.diff.64bit | 3 +- ...le_literal_propagation.main.ConstProp.diff | 9 +- .../const_prop_miscompile.bar.ConstProp.diff | 12 +- .../const_prop_miscompile.foo.ConstProp.diff | 12 +- ...float_to_exponential_common.ConstProp.diff | 162 ++++++++++++++++++ src/test/mir-opt/funky_arms.rs | 56 ++++++ ...main-{{closure}}.StateTransform.before.mir | 5 +- ...ny.main-{{closure}}.generator_resume.0.mir | 17 +- .../inline_closure.foo.Inline.after.mir | 12 +- ...e_closure_borrows_arg.foo.Inline.after.mir | 12 +- ...line_closure_captures.foo.Inline.after.mir | 13 +- .../issue_73223.main.PreCodegen.diff.32bit | 161 +++++++++-------- .../issue_73223.main.PreCodegen.diff.64bit | 161 +++++++++-------- ..._73223.main.SimplifyArmIdentity.diff.32bit | 16 +- ..._73223.main.SimplifyArmIdentity.diff.64bit | 16 +- ...entity.main.SimplifyArmIdentity.diff.32bit | 9 +- ...entity.main.SimplifyArmIdentity.diff.64bit | 9 +- ...ves_unused_consts.main.SimplifyLocals.diff | 42 ++--- ...minant_reads.map.SimplifyLocals.diff.32bit | 8 +- ...minant_reads.map.SimplifyLocals.diff.64bit | 8 +- ...after-uninhabited-enum-branching.after.mir | 4 +- ...anching.main.UninhabitedEnumBranching.diff | 4 +- ...oops.change_loop_body.ConstProp.diff.32bit | 84 +++++++++ ...oops.change_loop_body.ConstProp.diff.64bit | 84 +++++++++ ...hange_loop_body.PreCodegen.after.mir.32bit | 33 ++++ ...hange_loop_body.PreCodegen.after.mir.64bit | 33 ++++ src/test/mir-opt/while_let_loops.rs | 15 ++ 40 files changed, 793 insertions(+), 357 deletions(-) create mode 100644 src/test/mir-opt/funky_arms.float_to_exponential_common.ConstProp.diff create mode 100644 src/test/mir-opt/funky_arms.rs create mode 100644 src/test/mir-opt/while_let_loops.change_loop_body.ConstProp.diff.32bit create mode 100644 src/test/mir-opt/while_let_loops.change_loop_body.ConstProp.diff.64bit create mode 100644 src/test/mir-opt/while_let_loops.change_loop_body.PreCodegen.after.mir.32bit create mode 100644 src/test/mir-opt/while_let_loops.change_loop_body.PreCodegen.after.mir.64bit create mode 100644 src/test/mir-opt/while_let_loops.rs diff --git a/src/librustc_mir/interpret/step.rs b/src/librustc_mir/interpret/step.rs index fcd26c86c473d..93624c32d300c 100644 --- a/src/librustc_mir/interpret/step.rs +++ b/src/librustc_mir/interpret/step.rs @@ -74,7 +74,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Ok(true) } - fn statement(&mut self, stmt: &mir::Statement<'tcx>) -> InterpResult<'tcx> { + /// Runs the interpretation logic for the given `mir::Statement` at the current frame and + /// statement counter. This also moves the statement counter forward. + crate fn statement(&mut self, stmt: &mir::Statement<'tcx>) -> InterpResult<'tcx> { info!("{:?}", stmt); use rustc_middle::mir::StatementKind::*; diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index 07b13af6ba776..6cf296f2a3fda 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -252,6 +252,11 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine<'mir, 'tcx> throw_machine_stop_str!("tried to write to a local that is marked as not propagatable") } if frame == 0 && ecx.machine.only_propagate_inside_block_locals.contains(local) { + trace!( + "mutating local {:?} which is restricted to its block. \ + Will remove it from const-prop after block is finished.", + local + ); ecx.machine.written_only_inside_own_block_locals.insert(local); } ecx.machine.stack[frame].locals[local].access_mut() @@ -427,6 +432,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { match f(self) { Ok(val) => Some(val), Err(error) => { + trace!("InterpCx operation failed: {:?}", error); // Some errors shouldn't come up because creating them causes // an allocation, which we should avoid. When that happens, // dedicated error variants should be introduced instead. @@ -969,10 +975,10 @@ impl<'tcx> Visitor<'tcx> for CanConstProp { ConstPropMode::OnlyPropagateInto => {} other @ ConstPropMode::FullConstProp => { trace!( - "local {:?} can't be propagated because of multiple assignments", - local, + "local {:?} can't be propagated because of multiple assignments. Previous state: {:?}", + local, other, ); - *other = ConstPropMode::OnlyPropagateInto; + *other = ConstPropMode::OnlyInsideOwnBlock; } } } @@ -1089,6 +1095,20 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> { } } else { match statement.kind { + StatementKind::SetDiscriminant { ref place, .. } => { + match self.ecx.machine.can_const_prop[place.local] { + ConstPropMode::FullConstProp | ConstPropMode::OnlyInsideOwnBlock => { + if self.use_ecx(|this| this.ecx.statement(statement)).is_some() { + trace!("propped discriminant into {:?}", place); + } else { + Self::remove_const(&mut self.ecx, place.local); + } + } + ConstPropMode::OnlyPropagateInto | ConstPropMode::NoPropagation => { + Self::remove_const(&mut self.ecx, place.local); + } + } + } StatementKind::StorageLive(local) | StatementKind::StorageDead(local) => { let frame = self.ecx.frame_mut(); frame.locals[local].value = diff --git a/src/librustc_mir/transform/mod.rs b/src/librustc_mir/transform/mod.rs index 26b4a6968971d..3803ee78fd4d9 100644 --- a/src/librustc_mir/transform/mod.rs +++ b/src/librustc_mir/transform/mod.rs @@ -408,6 +408,9 @@ fn run_post_borrowck_cleanup_passes<'tcx>( // but before optimizations begin. &add_retag::AddRetag, &simplify::SimplifyCfg::new("elaborate-drops"), + // `Deaggregator` is conceptually part of MIR building, some backends rely on it happening + // and it can help optimizations. + &deaggregator::Deaggregator, ]; run_passes( @@ -439,11 +442,6 @@ fn run_optimization_passes<'tcx>( &instcombine::InstCombine, &const_prop::ConstProp, &simplify_branches::SimplifyBranches::new("after-const-prop"), - // Run deaggregation here because: - // 1. Some codegen backends require it - // 2. It creates additional possibilities for some MIR optimizations to trigger - // FIXME(#70073): Why is this done here and not in `post_borrowck_cleanup`? - &deaggregator::Deaggregator, &simplify_try::SimplifyArmIdentity, &simplify_try::SimplifyBranchSame, ©_prop::CopyPropagation, @@ -460,9 +458,6 @@ fn run_optimization_passes<'tcx>( &generator::StateTransform, // FIXME(#70073): This pass is responsible for both optimization as well as some lints. &const_prop::ConstProp, - // Even if we don't do optimizations, still run deaggregation because some backends assume - // that deaggregation always occurs. - &deaggregator::Deaggregator, ]; let pre_codegen_cleanup: &[&dyn MirPass<'tcx>] = &[ diff --git a/src/test/codegen/consts.rs b/src/test/codegen/consts.rs index ed93af2f993d3..318f9b0eec3a9 100644 --- a/src/test/codegen/consts.rs +++ b/src/test/codegen/consts.rs @@ -10,11 +10,11 @@ // CHECK: @STATIC = {{.*}}, align 4 // This checks the constants from inline_enum_const -// CHECK: @alloc7 = {{.*}}, align 2 +// CHECK: @alloc8 = {{.*}}, align 2 // This checks the constants from {low,high}_align_const, they share the same // constant, but the alignment differs, so the higher one should be used -// CHECK: [[LOW_HIGH:@[0-9]+]] = {{.*}} getelementptr inbounds (<{ [8 x i8] }>, <{ [8 x i8] }>* @alloc19, i32 0, i32 0, i32 0), {{.*}} +// CHECK: [[LOW_HIGH:@[0-9]+]] = {{.*}} getelementptr inbounds (<{ [8 x i8] }>, <{ [8 x i8] }>* @alloc20, i32 0, i32 0, i32 0), {{.*}} #[derive(Copy, Clone)] // repr(i16) is required for the {low,high}_align_const test diff --git a/src/test/mir-opt/const_prop/aggregate.main.ConstProp.diff b/src/test/mir-opt/const_prop/aggregate.main.ConstProp.diff index e84e88b93fcd8..6992abae6c2be 100644 --- a/src/test/mir-opt/const_prop/aggregate.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/aggregate.main.ConstProp.diff @@ -14,19 +14,21 @@ StorageLive(_1); // scope 0 at $DIR/aggregate.rs:5:9: 5:10 StorageLive(_2); // scope 0 at $DIR/aggregate.rs:5:13: 5:24 StorageLive(_3); // scope 0 at $DIR/aggregate.rs:5:13: 5:22 - _3 = (const 0_i32, const 1_i32, const 2_i32); // scope 0 at $DIR/aggregate.rs:5:13: 5:22 + (_3.0: i32) = const 0_i32; // scope 0 at $DIR/aggregate.rs:5:13: 5:22 // ty::Const // + ty: i32 // + val: Value(Scalar(0x00000000)) // mir::Constant // + span: $DIR/aggregate.rs:5:14: 5:15 // + literal: Const { ty: i32, val: Value(Scalar(0x00000000)) } + (_3.1: i32) = const 1_i32; // scope 0 at $DIR/aggregate.rs:5:13: 5:22 // ty::Const // + ty: i32 // + val: Value(Scalar(0x00000001)) // mir::Constant // + span: $DIR/aggregate.rs:5:17: 5:18 // + literal: Const { ty: i32, val: Value(Scalar(0x00000001)) } + (_3.2: i32) = const 2_i32; // scope 0 at $DIR/aggregate.rs:5:13: 5:22 // ty::Const // + ty: i32 // + val: Value(Scalar(0x00000002)) diff --git a/src/test/mir-opt/const_prop/discriminant.main.ConstProp.diff.32bit b/src/test/mir-opt/const_prop/discriminant.main.ConstProp.diff.32bit index 539a16f52dca2..be9b24bfde8aa 100644 --- a/src/test/mir-opt/const_prop/discriminant.main.ConstProp.diff.32bit +++ b/src/test/mir-opt/const_prop/discriminant.main.ConstProp.diff.32bit @@ -15,19 +15,16 @@ StorageLive(_1); // scope 0 at $DIR/discriminant.rs:11:9: 11:10 StorageLive(_2); // scope 0 at $DIR/discriminant.rs:11:13: 11:64 StorageLive(_3); // scope 0 at $DIR/discriminant.rs:11:34: 11:44 -- _3 = std::option::Option::::Some(const true); // scope 0 at $DIR/discriminant.rs:11:34: 11:44 -+ _3 = const std::option::Option::::Some(true); // scope 0 at $DIR/discriminant.rs:11:34: 11:44 + ((_3 as Some).0: bool) = const true; // scope 0 at $DIR/discriminant.rs:11:34: 11:44 // ty::Const -- // + ty: bool -+ // + ty: std::option::Option + // + ty: bool // + val: Value(Scalar(0x01)) // mir::Constant -- // + span: $DIR/discriminant.rs:11:39: 11:43 -- // + literal: Const { ty: bool, val: Value(Scalar(0x01)) } + // + span: $DIR/discriminant.rs:11:39: 11:43 + // + literal: Const { ty: bool, val: Value(Scalar(0x01)) } + discriminant(_3) = 1; // scope 0 at $DIR/discriminant.rs:11:34: 11:44 - _4 = discriminant(_3); // scope 0 at $DIR/discriminant.rs:11:21: 11:31 - switchInt(move _4) -> [1_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/discriminant.rs:11:21: 11:31 -+ // + span: $DIR/discriminant.rs:11:34: 11:44 -+ // + literal: Const { ty: std::option::Option, val: Value(Scalar(0x01)) } + _4 = const 1_isize; // scope 0 at $DIR/discriminant.rs:11:21: 11:31 + // ty::Const + // + ty: isize @@ -56,14 +53,7 @@ } bb2: { -- switchInt(((_3 as Some).0: bool)) -> [false: bb1, otherwise: bb3]; // scope 0 at $DIR/discriminant.rs:11:26: 11:30 -+ switchInt(const true) -> [false: bb1, otherwise: bb3]; // scope 0 at $DIR/discriminant.rs:11:26: 11:30 -+ // ty::Const -+ // + ty: bool -+ // + val: Value(Scalar(0x01)) -+ // mir::Constant -+ // + span: $DIR/discriminant.rs:11:26: 11:30 -+ // + literal: Const { ty: bool, val: Value(Scalar(0x01)) } + switchInt(((_3 as Some).0: bool)) -> [false: bb1, otherwise: bb3]; // scope 0 at $DIR/discriminant.rs:11:26: 11:30 } bb3: { diff --git a/src/test/mir-opt/const_prop/discriminant.main.ConstProp.diff.64bit b/src/test/mir-opt/const_prop/discriminant.main.ConstProp.diff.64bit index 20875448eddc9..05b57a6c28075 100644 --- a/src/test/mir-opt/const_prop/discriminant.main.ConstProp.diff.64bit +++ b/src/test/mir-opt/const_prop/discriminant.main.ConstProp.diff.64bit @@ -15,19 +15,16 @@ StorageLive(_1); // scope 0 at $DIR/discriminant.rs:11:9: 11:10 StorageLive(_2); // scope 0 at $DIR/discriminant.rs:11:13: 11:64 StorageLive(_3); // scope 0 at $DIR/discriminant.rs:11:34: 11:44 -- _3 = std::option::Option::::Some(const true); // scope 0 at $DIR/discriminant.rs:11:34: 11:44 -+ _3 = const std::option::Option::::Some(true); // scope 0 at $DIR/discriminant.rs:11:34: 11:44 + ((_3 as Some).0: bool) = const true; // scope 0 at $DIR/discriminant.rs:11:34: 11:44 // ty::Const -- // + ty: bool -+ // + ty: std::option::Option + // + ty: bool // + val: Value(Scalar(0x01)) // mir::Constant -- // + span: $DIR/discriminant.rs:11:39: 11:43 -- // + literal: Const { ty: bool, val: Value(Scalar(0x01)) } + // + span: $DIR/discriminant.rs:11:39: 11:43 + // + literal: Const { ty: bool, val: Value(Scalar(0x01)) } + discriminant(_3) = 1; // scope 0 at $DIR/discriminant.rs:11:34: 11:44 - _4 = discriminant(_3); // scope 0 at $DIR/discriminant.rs:11:21: 11:31 - switchInt(move _4) -> [1_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/discriminant.rs:11:21: 11:31 -+ // + span: $DIR/discriminant.rs:11:34: 11:44 -+ // + literal: Const { ty: std::option::Option, val: Value(Scalar(0x01)) } + _4 = const 1_isize; // scope 0 at $DIR/discriminant.rs:11:21: 11:31 + // ty::Const + // + ty: isize @@ -56,14 +53,7 @@ } bb2: { -- switchInt(((_3 as Some).0: bool)) -> [false: bb1, otherwise: bb3]; // scope 0 at $DIR/discriminant.rs:11:26: 11:30 -+ switchInt(const true) -> [false: bb1, otherwise: bb3]; // scope 0 at $DIR/discriminant.rs:11:26: 11:30 -+ // ty::Const -+ // + ty: bool -+ // + val: Value(Scalar(0x01)) -+ // mir::Constant -+ // + span: $DIR/discriminant.rs:11:26: 11:30 -+ // + literal: Const { ty: bool, val: Value(Scalar(0x01)) } + switchInt(((_3 as Some).0: bool)) -> [false: bb1, otherwise: bb3]; // scope 0 at $DIR/discriminant.rs:11:26: 11:30 } bb3: { diff --git a/src/test/mir-opt/const_prop/issue_66971.main.ConstProp.diff b/src/test/mir-opt/const_prop/issue_66971.main.ConstProp.diff index 242907b5599d8..59e5b207f120c 100644 --- a/src/test/mir-opt/const_prop/issue_66971.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/issue_66971.main.ConstProp.diff @@ -11,21 +11,22 @@ StorageLive(_1); // scope 0 at $DIR/issue-66971.rs:16:5: 16:23 StorageLive(_2); // scope 0 at $DIR/issue-66971.rs:16:12: 16:22 StorageLive(_3); // scope 0 at $DIR/issue-66971.rs:16:13: 16:15 -- _3 = (); // scope 0 at $DIR/issue-66971.rs:16:13: 16:15 -+ _3 = const (); // scope 0 at $DIR/issue-66971.rs:16:13: 16:15 +- (_2.0: ()) = move _3; // scope 0 at $DIR/issue-66971.rs:16:12: 16:22 ++ (_2.0: ()) = const (); // scope 0 at $DIR/issue-66971.rs:16:12: 16:22 + // ty::Const + // + ty: () + // + val: Value(Scalar()) + // mir::Constant -+ // + span: $DIR/issue-66971.rs:16:13: 16:15 ++ // + span: $DIR/issue-66971.rs:16:12: 16:22 + // + literal: Const { ty: (), val: Value(Scalar()) } - _2 = (move _3, const 0_u8, const 0_u8); // scope 0 at $DIR/issue-66971.rs:16:12: 16:22 + (_2.1: u8) = const 0_u8; // scope 0 at $DIR/issue-66971.rs:16:12: 16:22 // ty::Const // + ty: u8 // + val: Value(Scalar(0x00)) // mir::Constant // + span: $DIR/issue-66971.rs:16:17: 16:18 // + literal: Const { ty: u8, val: Value(Scalar(0x00)) } + (_2.2: u8) = const 0_u8; // scope 0 at $DIR/issue-66971.rs:16:12: 16:22 // ty::Const // + ty: u8 // + val: Value(Scalar(0x00)) diff --git a/src/test/mir-opt/const_prop/issue_67019.main.ConstProp.diff b/src/test/mir-opt/const_prop/issue_67019.main.ConstProp.diff index d5c1105d7caff..d3e5e9fe5b422 100644 --- a/src/test/mir-opt/const_prop/issue_67019.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/issue_67019.main.ConstProp.diff @@ -11,22 +11,34 @@ StorageLive(_1); // scope 0 at $DIR/issue-67019.rs:11:5: 11:20 StorageLive(_2); // scope 0 at $DIR/issue-67019.rs:11:10: 11:19 StorageLive(_3); // scope 0 at $DIR/issue-67019.rs:11:11: 11:17 - _3 = (const 1_u8, const 2_u8); // scope 0 at $DIR/issue-67019.rs:11:11: 11:17 + (_3.0: u8) = const 1_u8; // scope 0 at $DIR/issue-67019.rs:11:11: 11:17 // ty::Const // + ty: u8 // + val: Value(Scalar(0x01)) // mir::Constant -- // + span: $DIR/issue-67019.rs:11:12: 11:13 -+ // + span: $DIR/issue-67019.rs:11:11: 11:17 + // + span: $DIR/issue-67019.rs:11:12: 11:13 // + literal: Const { ty: u8, val: Value(Scalar(0x01)) } + (_3.1: u8) = const 2_u8; // scope 0 at $DIR/issue-67019.rs:11:11: 11:17 // ty::Const // + ty: u8 // + val: Value(Scalar(0x02)) // mir::Constant -- // + span: $DIR/issue-67019.rs:11:15: 11:16 -+ // + span: $DIR/issue-67019.rs:11:11: 11:17 + // + span: $DIR/issue-67019.rs:11:15: 11:16 // + literal: Const { ty: u8, val: Value(Scalar(0x02)) } - _2 = (move _3,); // scope 0 at $DIR/issue-67019.rs:11:10: 11:19 +- (_2.0: (u8, u8)) = move _3; // scope 0 at $DIR/issue-67019.rs:11:10: 11:19 ++ (_2.0: (u8, u8)) = (const 1_u8, const 2_u8); // scope 0 at $DIR/issue-67019.rs:11:10: 11:19 ++ // ty::Const ++ // + ty: u8 ++ // + val: Value(Scalar(0x01)) ++ // mir::Constant ++ // + span: $DIR/issue-67019.rs:11:10: 11:19 ++ // + literal: Const { ty: u8, val: Value(Scalar(0x01)) } ++ // ty::Const ++ // + ty: u8 ++ // + val: Value(Scalar(0x02)) ++ // mir::Constant ++ // + span: $DIR/issue-67019.rs:11:10: 11:19 ++ // + literal: Const { ty: u8, val: Value(Scalar(0x02)) } StorageDead(_3); // scope 0 at $DIR/issue-67019.rs:11:18: 11:19 _1 = const test(move _2) -> bb1; // scope 0 at $DIR/issue-67019.rs:11:5: 11:20 // ty::Const diff --git a/src/test/mir-opt/const_prop/mutable_variable_aggregate.main.ConstProp.diff b/src/test/mir-opt/const_prop/mutable_variable_aggregate.main.ConstProp.diff index f581b222c83cb..617702a520912 100644 --- a/src/test/mir-opt/const_prop/mutable_variable_aggregate.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/mutable_variable_aggregate.main.ConstProp.diff @@ -14,20 +14,19 @@ bb0: { StorageLive(_1); // scope 0 at $DIR/mutable_variable_aggregate.rs:5:9: 5:14 - _1 = (const 42_i32, const 43_i32); // scope 0 at $DIR/mutable_variable_aggregate.rs:5:17: 5:25 + (_1.0: i32) = const 42_i32; // scope 0 at $DIR/mutable_variable_aggregate.rs:5:17: 5:25 // ty::Const // + ty: i32 // + val: Value(Scalar(0x0000002a)) // mir::Constant -- // + span: $DIR/mutable_variable_aggregate.rs:5:18: 5:20 -+ // + span: $DIR/mutable_variable_aggregate.rs:5:17: 5:25 + // + span: $DIR/mutable_variable_aggregate.rs:5:18: 5:20 // + literal: Const { ty: i32, val: Value(Scalar(0x0000002a)) } + (_1.1: i32) = const 43_i32; // scope 0 at $DIR/mutable_variable_aggregate.rs:5:17: 5:25 // ty::Const // + ty: i32 // + val: Value(Scalar(0x0000002b)) // mir::Constant -- // + span: $DIR/mutable_variable_aggregate.rs:5:22: 5:24 -+ // + span: $DIR/mutable_variable_aggregate.rs:5:17: 5:25 + // + span: $DIR/mutable_variable_aggregate.rs:5:22: 5:24 // + literal: Const { ty: i32, val: Value(Scalar(0x0000002b)) } (_1.1: i32) = const 99_i32; // scope 1 at $DIR/mutable_variable_aggregate.rs:6:5: 6:13 // ty::Const diff --git a/src/test/mir-opt/const_prop/mutable_variable_aggregate_mut_ref.main.ConstProp.diff b/src/test/mir-opt/const_prop/mutable_variable_aggregate_mut_ref.main.ConstProp.diff index 6e2ee0957ab33..dbf77cf6b378b 100644 --- a/src/test/mir-opt/const_prop/mutable_variable_aggregate_mut_ref.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/mutable_variable_aggregate_mut_ref.main.ConstProp.diff @@ -18,13 +18,14 @@ bb0: { StorageLive(_1); // scope 0 at $DIR/mutable_variable_aggregate_mut_ref.rs:5:9: 5:14 - _1 = (const 42_i32, const 43_i32); // scope 0 at $DIR/mutable_variable_aggregate_mut_ref.rs:5:17: 5:25 + (_1.0: i32) = const 42_i32; // scope 0 at $DIR/mutable_variable_aggregate_mut_ref.rs:5:17: 5:25 // ty::Const // + ty: i32 // + val: Value(Scalar(0x0000002a)) // mir::Constant // + span: $DIR/mutable_variable_aggregate_mut_ref.rs:5:18: 5:20 // + literal: Const { ty: i32, val: Value(Scalar(0x0000002a)) } + (_1.1: i32) = const 43_i32; // scope 0 at $DIR/mutable_variable_aggregate_mut_ref.rs:5:17: 5:25 // ty::Const // + ty: i32 // + val: Value(Scalar(0x0000002b)) diff --git a/src/test/mir-opt/const_prop/mutable_variable_unprop_assign.main.ConstProp.diff b/src/test/mir-opt/const_prop/mutable_variable_unprop_assign.main.ConstProp.diff index b59b180b07d7f..84e858debddc0 100644 --- a/src/test/mir-opt/const_prop/mutable_variable_unprop_assign.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/mutable_variable_unprop_assign.main.ConstProp.diff @@ -34,20 +34,19 @@ bb1: { StorageLive(_2); // scope 1 at $DIR/mutable_variable_unprop_assign.rs:6:9: 6:14 - _2 = (const 1_i32, const 2_i32); // scope 1 at $DIR/mutable_variable_unprop_assign.rs:6:29: 6:35 + (_2.0: i32) = const 1_i32; // scope 1 at $DIR/mutable_variable_unprop_assign.rs:6:29: 6:35 // ty::Const // + ty: i32 // + val: Value(Scalar(0x00000001)) // mir::Constant -- // + span: $DIR/mutable_variable_unprop_assign.rs:6:30: 6:31 -+ // + span: $DIR/mutable_variable_unprop_assign.rs:6:29: 6:35 + // + span: $DIR/mutable_variable_unprop_assign.rs:6:30: 6:31 // + literal: Const { ty: i32, val: Value(Scalar(0x00000001)) } + (_2.1: i32) = const 2_i32; // scope 1 at $DIR/mutable_variable_unprop_assign.rs:6:29: 6:35 // ty::Const // + ty: i32 // + val: Value(Scalar(0x00000002)) // mir::Constant -- // + span: $DIR/mutable_variable_unprop_assign.rs:6:33: 6:34 -+ // + span: $DIR/mutable_variable_unprop_assign.rs:6:29: 6:35 + // + span: $DIR/mutable_variable_unprop_assign.rs:6:33: 6:34 // + literal: Const { ty: i32, val: Value(Scalar(0x00000002)) } StorageLive(_3); // scope 2 at $DIR/mutable_variable_unprop_assign.rs:7:11: 7:12 _3 = _1; // scope 2 at $DIR/mutable_variable_unprop_assign.rs:7:11: 7:12 diff --git a/src/test/mir-opt/const_prop/optimizes_into_variable.main.ConstProp.diff.32bit b/src/test/mir-opt/const_prop/optimizes_into_variable.main.ConstProp.diff.32bit index 5312784bc8aae..c2381f3da90dd 100644 --- a/src/test/mir-opt/const_prop/optimizes_into_variable.main.ConstProp.diff.32bit +++ b/src/test/mir-opt/const_prop/optimizes_into_variable.main.ConstProp.diff.32bit @@ -173,13 +173,14 @@ StorageDead(_4); // scope 1 at $DIR/optimizes_into_variable.rs:13:34: 13:35 StorageLive(_8); // scope 2 at $DIR/optimizes_into_variable.rs:14:9: 14:10 StorageLive(_9); // scope 2 at $DIR/optimizes_into_variable.rs:14:13: 14:36 - _9 = Point { x: const 12_u32, y: const 42_u32 }; // scope 2 at $DIR/optimizes_into_variable.rs:14:13: 14:36 + (_9.0: u32) = const 12_u32; // scope 2 at $DIR/optimizes_into_variable.rs:14:13: 14:36 // ty::Const // + ty: u32 // + val: Value(Scalar(0x0000000c)) // mir::Constant // + span: $DIR/optimizes_into_variable.rs:14:25: 14:27 // + literal: Const { ty: u32, val: Value(Scalar(0x0000000c)) } + (_9.1: u32) = const 42_u32; // scope 2 at $DIR/optimizes_into_variable.rs:14:13: 14:36 // ty::Const // + ty: u32 // + val: Value(Scalar(0x0000002a)) diff --git a/src/test/mir-opt/const_prop/optimizes_into_variable.main.ConstProp.diff.64bit b/src/test/mir-opt/const_prop/optimizes_into_variable.main.ConstProp.diff.64bit index 7af9984136667..bc965b4ade730 100644 --- a/src/test/mir-opt/const_prop/optimizes_into_variable.main.ConstProp.diff.64bit +++ b/src/test/mir-opt/const_prop/optimizes_into_variable.main.ConstProp.diff.64bit @@ -173,13 +173,14 @@ StorageDead(_4); // scope 1 at $DIR/optimizes_into_variable.rs:13:34: 13:35 StorageLive(_8); // scope 2 at $DIR/optimizes_into_variable.rs:14:9: 14:10 StorageLive(_9); // scope 2 at $DIR/optimizes_into_variable.rs:14:13: 14:36 - _9 = Point { x: const 12_u32, y: const 42_u32 }; // scope 2 at $DIR/optimizes_into_variable.rs:14:13: 14:36 + (_9.0: u32) = const 12_u32; // scope 2 at $DIR/optimizes_into_variable.rs:14:13: 14:36 // ty::Const // + ty: u32 // + val: Value(Scalar(0x0000000c)) // mir::Constant // + span: $DIR/optimizes_into_variable.rs:14:25: 14:27 // + literal: Const { ty: u32, val: Value(Scalar(0x0000000c)) } + (_9.1: u32) = const 42_u32; // scope 2 at $DIR/optimizes_into_variable.rs:14:13: 14:36 // ty::Const // + ty: u32 // + val: Value(Scalar(0x0000002a)) diff --git a/src/test/mir-opt/const_prop/tuple_literal_propagation.main.ConstProp.diff b/src/test/mir-opt/const_prop/tuple_literal_propagation.main.ConstProp.diff index 941ec64a3cc12..e4a0ef27b24ed 100644 --- a/src/test/mir-opt/const_prop/tuple_literal_propagation.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/tuple_literal_propagation.main.ConstProp.diff @@ -12,20 +12,19 @@ bb0: { StorageLive(_1); // scope 0 at $DIR/tuple_literal_propagation.rs:3:9: 3:10 - _1 = (const 1_u32, const 2_u32); // scope 0 at $DIR/tuple_literal_propagation.rs:3:13: 3:19 + (_1.0: u32) = const 1_u32; // scope 0 at $DIR/tuple_literal_propagation.rs:3:13: 3:19 // ty::Const // + ty: u32 // + val: Value(Scalar(0x00000001)) // mir::Constant -- // + span: $DIR/tuple_literal_propagation.rs:3:14: 3:15 -+ // + span: $DIR/tuple_literal_propagation.rs:3:13: 3:19 + // + span: $DIR/tuple_literal_propagation.rs:3:14: 3:15 // + literal: Const { ty: u32, val: Value(Scalar(0x00000001)) } + (_1.1: u32) = const 2_u32; // scope 0 at $DIR/tuple_literal_propagation.rs:3:13: 3:19 // ty::Const // + ty: u32 // + val: Value(Scalar(0x00000002)) // mir::Constant -- // + span: $DIR/tuple_literal_propagation.rs:3:17: 3:18 -+ // + span: $DIR/tuple_literal_propagation.rs:3:13: 3:19 + // + span: $DIR/tuple_literal_propagation.rs:3:17: 3:18 // + literal: Const { ty: u32, val: Value(Scalar(0x00000002)) } StorageLive(_2); // scope 1 at $DIR/tuple_literal_propagation.rs:5:5: 5:15 StorageLive(_3); // scope 1 at $DIR/tuple_literal_propagation.rs:5:13: 5:14 diff --git a/src/test/mir-opt/const_prop_miscompile.bar.ConstProp.diff b/src/test/mir-opt/const_prop_miscompile.bar.ConstProp.diff index 5fe35b479c126..b4733b5ed39f9 100644 --- a/src/test/mir-opt/const_prop_miscompile.bar.ConstProp.diff +++ b/src/test/mir-opt/const_prop_miscompile.bar.ConstProp.diff @@ -19,17 +19,13 @@ bb0: { StorageLive(_1); // scope 0 at $DIR/const_prop_miscompile.rs:12:9: 12:14 -- _1 = (const 1_i32,); // scope 0 at $DIR/const_prop_miscompile.rs:12:17: 12:21 -+ _1 = const (1_i32,); // scope 0 at $DIR/const_prop_miscompile.rs:12:17: 12:21 + (_1.0: i32) = const 1_i32; // scope 0 at $DIR/const_prop_miscompile.rs:12:17: 12:21 // ty::Const -- // + ty: i32 -+ // + ty: (i32,) + // + ty: i32 // + val: Value(Scalar(0x00000001)) // mir::Constant -- // + span: $DIR/const_prop_miscompile.rs:12:18: 12:19 -- // + literal: Const { ty: i32, val: Value(Scalar(0x00000001)) } -+ // + span: $DIR/const_prop_miscompile.rs:12:17: 12:21 -+ // + literal: Const { ty: (i32,), val: Value(Scalar(0x00000001)) } + // + span: $DIR/const_prop_miscompile.rs:12:18: 12:19 + // + literal: Const { ty: i32, val: Value(Scalar(0x00000001)) } StorageLive(_2); // scope 1 at $DIR/const_prop_miscompile.rs:13:5: 15:6 StorageLive(_3); // scope 2 at $DIR/const_prop_miscompile.rs:14:10: 14:22 _3 = &raw mut (_1.0: i32); // scope 2 at $DIR/const_prop_miscompile.rs:14:10: 14:22 diff --git a/src/test/mir-opt/const_prop_miscompile.foo.ConstProp.diff b/src/test/mir-opt/const_prop_miscompile.foo.ConstProp.diff index 98e9825c1c435..b54fc41d0b496 100644 --- a/src/test/mir-opt/const_prop_miscompile.foo.ConstProp.diff +++ b/src/test/mir-opt/const_prop_miscompile.foo.ConstProp.diff @@ -16,17 +16,13 @@ bb0: { StorageLive(_1); // scope 0 at $DIR/const_prop_miscompile.rs:5:9: 5:14 -- _1 = (const 1_i32,); // scope 0 at $DIR/const_prop_miscompile.rs:5:17: 5:21 -+ _1 = const (1_i32,); // scope 0 at $DIR/const_prop_miscompile.rs:5:17: 5:21 + (_1.0: i32) = const 1_i32; // scope 0 at $DIR/const_prop_miscompile.rs:5:17: 5:21 // ty::Const -- // + ty: i32 -+ // + ty: (i32,) + // + ty: i32 // + val: Value(Scalar(0x00000001)) // mir::Constant -- // + span: $DIR/const_prop_miscompile.rs:5:18: 5:19 -- // + literal: Const { ty: i32, val: Value(Scalar(0x00000001)) } -+ // + span: $DIR/const_prop_miscompile.rs:5:17: 5:21 -+ // + literal: Const { ty: (i32,), val: Value(Scalar(0x00000001)) } + // + span: $DIR/const_prop_miscompile.rs:5:18: 5:19 + // + literal: Const { ty: i32, val: Value(Scalar(0x00000001)) } StorageLive(_2); // scope 1 at $DIR/const_prop_miscompile.rs:6:6: 6:14 _2 = &mut (_1.0: i32); // scope 1 at $DIR/const_prop_miscompile.rs:6:6: 6:14 (*_2) = const 5_i32; // scope 1 at $DIR/const_prop_miscompile.rs:6:5: 6:18 diff --git a/src/test/mir-opt/funky_arms.float_to_exponential_common.ConstProp.diff b/src/test/mir-opt/funky_arms.float_to_exponential_common.ConstProp.diff new file mode 100644 index 0000000000000..5f928ea2a1629 --- /dev/null +++ b/src/test/mir-opt/funky_arms.float_to_exponential_common.ConstProp.diff @@ -0,0 +1,162 @@ +- // MIR for `float_to_exponential_common` before ConstProp ++ // MIR for `float_to_exponential_common` after ConstProp + + fn float_to_exponential_common(_1: &mut std::fmt::Formatter, _2: &T, _3: bool) -> std::result::Result<(), std::fmt::Error> { + debug fmt => _1; // in scope 0 at $DIR/funky_arms.rs:11:35: 11:38 + debug num => _2; // in scope 0 at $DIR/funky_arms.rs:11:60: 11:63 + debug upper => _3; // in scope 0 at $DIR/funky_arms.rs:11:69: 11:74 + let mut _0: std::result::Result<(), std::fmt::Error>; // return place in scope 0 at $DIR/funky_arms.rs:11:85: 11:91 + let _4: bool; // in scope 0 at $DIR/funky_arms.rs:15:9: 15:19 + let mut _5: &std::fmt::Formatter; // in scope 0 at $DIR/funky_arms.rs:15:22: 15:25 + let mut _7: std::option::Option; // in scope 0 at $DIR/funky_arms.rs:24:30: 24:45 + let mut _8: &std::fmt::Formatter; // in scope 0 at $DIR/funky_arms.rs:24:30: 24:33 + let mut _9: isize; // in scope 0 at $DIR/funky_arms.rs:24:12: 24:27 + let mut _11: &mut std::fmt::Formatter; // in scope 0 at $DIR/funky_arms.rs:26:43: 26:46 + let mut _12: &T; // in scope 0 at $DIR/funky_arms.rs:26:48: 26:51 + let mut _13: core::num::flt2dec::Sign; // in scope 0 at $DIR/funky_arms.rs:26:53: 26:57 + let mut _14: u32; // in scope 0 at $DIR/funky_arms.rs:26:59: 26:79 + let mut _15: u32; // in scope 0 at $DIR/funky_arms.rs:26:59: 26:75 + let mut _16: usize; // in scope 0 at $DIR/funky_arms.rs:26:59: 26:68 + let mut _17: bool; // in scope 0 at $DIR/funky_arms.rs:26:81: 26:86 + let mut _18: &mut std::fmt::Formatter; // in scope 0 at $DIR/funky_arms.rs:28:46: 28:49 + let mut _19: &T; // in scope 0 at $DIR/funky_arms.rs:28:51: 28:54 + let mut _20: core::num::flt2dec::Sign; // in scope 0 at $DIR/funky_arms.rs:28:56: 28:60 + let mut _21: bool; // in scope 0 at $DIR/funky_arms.rs:28:62: 28:67 + scope 1 { + debug force_sign => _4; // in scope 1 at $DIR/funky_arms.rs:15:9: 15:19 + let _6: core::num::flt2dec::Sign; // in scope 1 at $DIR/funky_arms.rs:19:9: 19:13 + scope 2 { + debug sign => _6; // in scope 2 at $DIR/funky_arms.rs:19:9: 19:13 + let _10: usize; // in scope 2 at $DIR/funky_arms.rs:24:17: 24:26 + scope 3 { + debug precision => _10; // in scope 3 at $DIR/funky_arms.rs:24:17: 24:26 + } + } + } + + bb0: { + StorageLive(_4); // scope 0 at $DIR/funky_arms.rs:15:9: 15:19 + StorageLive(_5); // scope 0 at $DIR/funky_arms.rs:15:22: 15:25 + _5 = &(*_1); // scope 0 at $DIR/funky_arms.rs:15:22: 15:25 + _4 = const std::fmt::Formatter::sign_plus(move _5) -> bb1; // scope 0 at $DIR/funky_arms.rs:15:22: 15:37 + // ty::Const + // + ty: for<'r> fn(&'r std::fmt::Formatter) -> bool {std::fmt::Formatter::sign_plus} + // + val: Value(Scalar()) + // mir::Constant + // + span: $DIR/funky_arms.rs:15:26: 15:35 + // + literal: Const { ty: for<'r> fn(&'r std::fmt::Formatter) -> bool {std::fmt::Formatter::sign_plus}, val: Value(Scalar()) } + } + + bb1: { + StorageDead(_5); // scope 0 at $DIR/funky_arms.rs:15:36: 15:37 + StorageLive(_6); // scope 1 at $DIR/funky_arms.rs:19:9: 19:13 + switchInt(_4) -> [false: bb3, otherwise: bb2]; // scope 1 at $DIR/funky_arms.rs:20:9: 20:14 + } + + bb2: { + discriminant(_6) = 2; // scope 1 at $DIR/funky_arms.rs:21:17: 21:41 + goto -> bb4; // scope 1 at $DIR/funky_arms.rs:19:16: 22:6 + } + + bb3: { + discriminant(_6) = 0; // scope 1 at $DIR/funky_arms.rs:20:18: 20:38 + goto -> bb4; // scope 1 at $DIR/funky_arms.rs:19:16: 22:6 + } + + bb4: { + StorageLive(_7); // scope 2 at $DIR/funky_arms.rs:24:30: 24:45 + StorageLive(_8); // scope 2 at $DIR/funky_arms.rs:24:30: 24:33 + _8 = &(*_1); // scope 2 at $DIR/funky_arms.rs:24:30: 24:33 + _7 = const std::fmt::Formatter::precision(move _8) -> bb5; // scope 2 at $DIR/funky_arms.rs:24:30: 24:45 + // ty::Const + // + ty: for<'r> fn(&'r std::fmt::Formatter) -> std::option::Option {std::fmt::Formatter::precision} + // + val: Value(Scalar()) + // mir::Constant + // + span: $DIR/funky_arms.rs:24:34: 24:43 + // + literal: Const { ty: for<'r> fn(&'r std::fmt::Formatter) -> std::option::Option {std::fmt::Formatter::precision}, val: Value(Scalar()) } + } + + bb5: { + StorageDead(_8); // scope 2 at $DIR/funky_arms.rs:24:44: 24:45 + _9 = discriminant(_7); // scope 2 at $DIR/funky_arms.rs:24:12: 24:27 + switchInt(move _9) -> [1_isize: bb7, otherwise: bb6]; // scope 2 at $DIR/funky_arms.rs:24:12: 24:27 + } + + bb6: { + StorageLive(_18); // scope 2 at $DIR/funky_arms.rs:28:46: 28:49 + _18 = &mut (*_1); // scope 2 at $DIR/funky_arms.rs:28:46: 28:49 + StorageLive(_19); // scope 2 at $DIR/funky_arms.rs:28:51: 28:54 + _19 = _2; // scope 2 at $DIR/funky_arms.rs:28:51: 28:54 + StorageLive(_20); // scope 2 at $DIR/funky_arms.rs:28:56: 28:60 + _20 = _6; // scope 2 at $DIR/funky_arms.rs:28:56: 28:60 + StorageLive(_21); // scope 2 at $DIR/funky_arms.rs:28:62: 28:67 + _21 = _3; // scope 2 at $DIR/funky_arms.rs:28:62: 28:67 + _0 = const float_to_exponential_common_shortest::(move _18, move _19, move _20, move _21) -> bb9; // scope 2 at $DIR/funky_arms.rs:28:9: 28:68 + // ty::Const + // + ty: for<'r, 's, 't0> fn(&'r mut std::fmt::Formatter<'s>, &'t0 T, core::num::flt2dec::Sign, bool) -> std::result::Result<(), std::fmt::Error> {float_to_exponential_common_shortest::} + // + val: Value(Scalar()) + // mir::Constant + // + span: $DIR/funky_arms.rs:28:9: 28:45 + // + literal: Const { ty: for<'r, 's, 't0> fn(&'r mut std::fmt::Formatter<'s>, &'t0 T, core::num::flt2dec::Sign, bool) -> std::result::Result<(), std::fmt::Error> {float_to_exponential_common_shortest::}, val: Value(Scalar()) } + } + + bb7: { + StorageLive(_10); // scope 2 at $DIR/funky_arms.rs:24:17: 24:26 + _10 = ((_7 as Some).0: usize); // scope 2 at $DIR/funky_arms.rs:24:17: 24:26 + StorageLive(_11); // scope 3 at $DIR/funky_arms.rs:26:43: 26:46 + _11 = &mut (*_1); // scope 3 at $DIR/funky_arms.rs:26:43: 26:46 + StorageLive(_12); // scope 3 at $DIR/funky_arms.rs:26:48: 26:51 + _12 = _2; // scope 3 at $DIR/funky_arms.rs:26:48: 26:51 + StorageLive(_13); // scope 3 at $DIR/funky_arms.rs:26:53: 26:57 + _13 = _6; // scope 3 at $DIR/funky_arms.rs:26:53: 26:57 + StorageLive(_14); // scope 3 at $DIR/funky_arms.rs:26:59: 26:79 + StorageLive(_15); // scope 3 at $DIR/funky_arms.rs:26:59: 26:75 + StorageLive(_16); // scope 3 at $DIR/funky_arms.rs:26:59: 26:68 + _16 = _10; // scope 3 at $DIR/funky_arms.rs:26:59: 26:68 + _15 = move _16 as u32 (Misc); // scope 3 at $DIR/funky_arms.rs:26:59: 26:75 + StorageDead(_16); // scope 3 at $DIR/funky_arms.rs:26:74: 26:75 + _14 = Add(move _15, const 1_u32); // scope 3 at $DIR/funky_arms.rs:26:59: 26:79 + // ty::Const + // + ty: u32 + // + val: Value(Scalar(0x00000001)) + // mir::Constant + // + span: $DIR/funky_arms.rs:26:78: 26:79 + // + literal: Const { ty: u32, val: Value(Scalar(0x00000001)) } + StorageDead(_15); // scope 3 at $DIR/funky_arms.rs:26:78: 26:79 + StorageLive(_17); // scope 3 at $DIR/funky_arms.rs:26:81: 26:86 + _17 = _3; // scope 3 at $DIR/funky_arms.rs:26:81: 26:86 + _0 = const float_to_exponential_common_exact::(move _11, move _12, move _13, move _14, move _17) -> bb8; // scope 3 at $DIR/funky_arms.rs:26:9: 26:87 + // ty::Const + // + ty: for<'r, 's, 't0> fn(&'r mut std::fmt::Formatter<'s>, &'t0 T, core::num::flt2dec::Sign, u32, bool) -> std::result::Result<(), std::fmt::Error> {float_to_exponential_common_exact::} + // + val: Value(Scalar()) + // mir::Constant + // + span: $DIR/funky_arms.rs:26:9: 26:42 + // + literal: Const { ty: for<'r, 's, 't0> fn(&'r mut std::fmt::Formatter<'s>, &'t0 T, core::num::flt2dec::Sign, u32, bool) -> std::result::Result<(), std::fmt::Error> {float_to_exponential_common_exact::}, val: Value(Scalar()) } + } + + bb8: { + StorageDead(_17); // scope 3 at $DIR/funky_arms.rs:26:86: 26:87 + StorageDead(_14); // scope 3 at $DIR/funky_arms.rs:26:86: 26:87 + StorageDead(_13); // scope 3 at $DIR/funky_arms.rs:26:86: 26:87 + StorageDead(_12); // scope 3 at $DIR/funky_arms.rs:26:86: 26:87 + StorageDead(_11); // scope 3 at $DIR/funky_arms.rs:26:86: 26:87 + StorageDead(_10); // scope 2 at $DIR/funky_arms.rs:27:5: 27:6 + goto -> bb10; // scope 2 at $DIR/funky_arms.rs:24:5: 29:6 + } + + bb9: { + StorageDead(_21); // scope 2 at $DIR/funky_arms.rs:28:67: 28:68 + StorageDead(_20); // scope 2 at $DIR/funky_arms.rs:28:67: 28:68 + StorageDead(_19); // scope 2 at $DIR/funky_arms.rs:28:67: 28:68 + StorageDead(_18); // scope 2 at $DIR/funky_arms.rs:28:67: 28:68 + goto -> bb10; // scope 2 at $DIR/funky_arms.rs:24:5: 29:6 + } + + bb10: { + StorageDead(_6); // scope 1 at $DIR/funky_arms.rs:30:1: 30:2 + StorageDead(_4); // scope 0 at $DIR/funky_arms.rs:30:1: 30:2 + StorageDead(_7); // scope 0 at $DIR/funky_arms.rs:30:1: 30:2 + return; // scope 0 at $DIR/funky_arms.rs:30:2: 30:2 + } + } + diff --git a/src/test/mir-opt/funky_arms.rs b/src/test/mir-opt/funky_arms.rs new file mode 100644 index 0000000000000..3e70d85e0d47f --- /dev/null +++ b/src/test/mir-opt/funky_arms.rs @@ -0,0 +1,56 @@ +// compile-flags: --crate-type lib -Cdebug-assertions=no + +#![feature(flt2dec)] + +extern crate core; + +use core::num::flt2dec; +use std::fmt::{Formatter, Result}; + +// EMIT_MIR funky_arms.float_to_exponential_common.ConstProp.diff +fn float_to_exponential_common(fmt: &mut Formatter<'_>, num: &T, upper: bool) -> Result +where + T: flt2dec::DecodableFloat, +{ + let force_sign = fmt.sign_plus(); + // A bug in const propagation (never reached master, but during dev of a PR) caused the + // `sign = Minus` assignment to get propagated into all future reads of `sign`. This is + // wrong because `sign` could also have `MinusPlus` value. + let sign = match force_sign { + false => flt2dec::Sign::Minus, + true => flt2dec::Sign::MinusPlus, + }; + + if let Some(precision) = fmt.precision() { + // 1 integral digit + `precision` fractional digits = `precision + 1` total digits + float_to_exponential_common_exact(fmt, num, sign, precision as u32 + 1, upper) + } else { + float_to_exponential_common_shortest(fmt, num, sign, upper) + } +} +#[inline(never)] +fn float_to_exponential_common_exact( + fmt: &mut Formatter<'_>, + num: &T, + sign: flt2dec::Sign, + precision: u32, + upper: bool, +) -> Result +where + T: flt2dec::DecodableFloat, +{ + unimplemented!() +} + +#[inline(never)] +fn float_to_exponential_common_shortest( + fmt: &mut Formatter<'_>, + num: &T, + sign: flt2dec::Sign, + upper: bool, +) -> Result +where + T: flt2dec::DecodableFloat, +{ + unimplemented!() +} diff --git a/src/test/mir-opt/generator_storage_dead_unwind.main-{{closure}}.StateTransform.before.mir b/src/test/mir-opt/generator_storage_dead_unwind.main-{{closure}}.StateTransform.before.mir index 7dcfda32ca4a2..356470f8fec87 100644 --- a/src/test/mir-opt/generator_storage_dead_unwind.main-{{closure}}.StateTransform.before.mir +++ b/src/test/mir-opt/generator_storage_dead_unwind.main-{{closure}}.StateTransform.before.mir @@ -21,7 +21,7 @@ yields () bb0: { StorageLive(_3); // scope 0 at $DIR/generator-storage-dead-unwind.rs:23:13: 23:14 - _3 = Foo(const 5_i32); // scope 0 at $DIR/generator-storage-dead-unwind.rs:23:17: 23:23 + (_3.0: i32) = const 5_i32; // scope 0 at $DIR/generator-storage-dead-unwind.rs:23:17: 23:23 // ty::Const // + ty: i32 // + val: Value(Scalar(0x00000005)) @@ -29,7 +29,7 @@ yields () // + span: $DIR/generator-storage-dead-unwind.rs:23:21: 23:22 // + literal: Const { ty: i32, val: Value(Scalar(0x00000005)) } StorageLive(_4); // scope 1 at $DIR/generator-storage-dead-unwind.rs:24:13: 24:14 - _4 = Bar(const 6_i32); // scope 1 at $DIR/generator-storage-dead-unwind.rs:24:17: 24:23 + (_4.0: i32) = const 6_i32; // scope 1 at $DIR/generator-storage-dead-unwind.rs:24:17: 24:23 // ty::Const // + ty: i32 // + val: Value(Scalar(0x00000006)) @@ -38,7 +38,6 @@ yields () // + literal: Const { ty: i32, val: Value(Scalar(0x00000006)) } StorageLive(_5); // scope 2 at $DIR/generator-storage-dead-unwind.rs:25:9: 25:14 StorageLive(_6); // scope 2 at $DIR/generator-storage-dead-unwind.rs:25:9: 25:14 - _6 = (); // scope 2 at $DIR/generator-storage-dead-unwind.rs:25:9: 25:14 _5 = yield(move _6) -> [resume: bb2, drop: bb4]; // scope 2 at $DIR/generator-storage-dead-unwind.rs:25:9: 25:14 } diff --git a/src/test/mir-opt/generator_tiny.main-{{closure}}.generator_resume.0.mir b/src/test/mir-opt/generator_tiny.main-{{closure}}.generator_resume.0.mir index 8776e5919bd8d..41fc04774dbca 100644 --- a/src/test/mir-opt/generator_tiny.main-{{closure}}.generator_resume.0.mir +++ b/src/test/mir-opt/generator_tiny.main-{{closure}}.generator_resume.0.mir @@ -1,17 +1,13 @@ // MIR for `main::{{closure}}#0` 0 generator_resume /* generator_layout = GeneratorLayout { - field_tys: { - _0: HasDrop, - }, + field_tys: {}, variant_fields: { Unresumed(0): [], Returned (1): [], Panicked (2): [], - Suspend0 (3): [_0], - }, - storage_conflicts: BitMatrix(1x1) { - (_0, _0), + Suspend0 (3): [], }, + storage_conflicts: BitMatrix(0x0) {}, } */ fn main::{{closure}}#0(_1: std::pin::Pin<&mut [generator@$DIR/generator-tiny.rs:19:16: 25:6 {u8, HasDrop, ()}]>, _2: u8) -> std::ops::GeneratorState<(), ()> { @@ -27,7 +23,7 @@ fn main::{{closure}}#0(_1: std::pin::Pin<&mut [generator@$DIR/generator-tiny.rs: let _10: u8; // in scope 0 at $DIR/generator-tiny.rs:19:17: 19:19 let mut _11: u32; // in scope 0 at $DIR/generator-tiny.rs:19:16: 25:6 scope 1 { - debug _d => (((*(_1.0: &mut [generator@$DIR/generator-tiny.rs:19:16: 25:6 {u8, HasDrop, ()}])) as variant#3).0: HasDrop); // in scope 1 at $DIR/generator-tiny.rs:20:13: 20:15 + debug _d => _3; // in scope 1 at $DIR/generator-tiny.rs:20:13: 20:15 } bb0: { @@ -37,8 +33,7 @@ fn main::{{closure}}#0(_1: std::pin::Pin<&mut [generator@$DIR/generator-tiny.rs: bb1: { _10 = move _2; // scope 0 at $DIR/generator-tiny.rs:19:16: 25:6 - nop; // scope 0 at $DIR/generator-tiny.rs:20:13: 20:15 - (((*(_1.0: &mut [generator@$DIR/generator-tiny.rs:19:16: 25:6 {u8, HasDrop, ()}])) as variant#3).0: HasDrop) = HasDrop; // scope 0 at $DIR/generator-tiny.rs:20:18: 20:25 + StorageLive(_3); // scope 0 at $DIR/generator-tiny.rs:20:13: 20:15 StorageLive(_4); // scope 1 at $DIR/generator-tiny.rs:21:9: 24:10 goto -> bb2; // scope 1 at $DIR/generator-tiny.rs:21:9: 24:10 } @@ -46,7 +41,6 @@ fn main::{{closure}}#0(_1: std::pin::Pin<&mut [generator@$DIR/generator-tiny.rs: bb2: { StorageLive(_6); // scope 1 at $DIR/generator-tiny.rs:22:13: 22:18 StorageLive(_7); // scope 1 at $DIR/generator-tiny.rs:22:13: 22:18 - _7 = (); // scope 1 at $DIR/generator-tiny.rs:22:13: 22:18 _0 = std::ops::GeneratorState::<(), ()>::Yielded(move _7); // scope 1 at $DIR/generator-tiny.rs:22:13: 22:18 discriminant((*(_1.0: &mut [generator@$DIR/generator-tiny.rs:19:16: 25:6 {u8, HasDrop, ()}]))) = 3; // scope 1 at $DIR/generator-tiny.rs:22:13: 22:18 return; // scope 1 at $DIR/generator-tiny.rs:22:13: 22:18 @@ -78,6 +72,7 @@ fn main::{{closure}}#0(_1: std::pin::Pin<&mut [generator@$DIR/generator-tiny.rs: } bb5: { + StorageLive(_3); // scope 0 at $DIR/generator-tiny.rs:19:16: 25:6 StorageLive(_4); // scope 0 at $DIR/generator-tiny.rs:19:16: 25:6 StorageLive(_6); // scope 0 at $DIR/generator-tiny.rs:19:16: 25:6 StorageLive(_7); // scope 0 at $DIR/generator-tiny.rs:19:16: 25:6 diff --git a/src/test/mir-opt/inline/inline_closure.foo.Inline.after.mir b/src/test/mir-opt/inline/inline_closure.foo.Inline.after.mir index bd0ec8c7ddbd5..b40a8047c4185 100644 --- a/src/test/mir-opt/inline/inline_closure.foo.Inline.after.mir +++ b/src/test/mir-opt/inline/inline_closure.foo.Inline.after.mir @@ -21,15 +21,6 @@ fn foo(_1: T, _2: i32) -> i32 { bb0: { StorageLive(_3); // scope 0 at $DIR/inline-closure.rs:11:9: 11:10 - _3 = [closure@foo::::{{closure}}#0]; // scope 0 at $DIR/inline-closure.rs:11:13: 11:24 - // closure - // + def_id: DefId(0:6 ~ inline_closure[317d]::foo[0]::{{closure}}[0]) - // + substs: [ - // T, - // i8, - // extern "rust-call" fn((i32, i32)) -> i32, - // (), - // ] StorageLive(_4); // scope 1 at $DIR/inline-closure.rs:12:5: 12:6 _4 = &_3; // scope 1 at $DIR/inline-closure.rs:12:5: 12:6 StorageLive(_5); // scope 1 at $DIR/inline-closure.rs:12:5: 12:12 @@ -37,7 +28,8 @@ fn foo(_1: T, _2: i32) -> i32 { _6 = _2; // scope 1 at $DIR/inline-closure.rs:12:7: 12:8 StorageLive(_7); // scope 1 at $DIR/inline-closure.rs:12:10: 12:11 _7 = _2; // scope 1 at $DIR/inline-closure.rs:12:10: 12:11 - _5 = (move _6, move _7); // scope 1 at $DIR/inline-closure.rs:12:5: 12:12 + (_5.0: i32) = move _6; // scope 1 at $DIR/inline-closure.rs:12:5: 12:12 + (_5.1: i32) = move _7; // scope 1 at $DIR/inline-closure.rs:12:5: 12:12 _8 = move (_5.0: i32); // scope 1 at $DIR/inline-closure.rs:12:5: 12:12 _9 = move (_5.1: i32); // scope 1 at $DIR/inline-closure.rs:12:5: 12:12 _0 = _8; // scope 2 at $DIR/inline-closure.rs:11:22: 11:24 diff --git a/src/test/mir-opt/inline/inline_closure_borrows_arg.foo.Inline.after.mir b/src/test/mir-opt/inline/inline_closure_borrows_arg.foo.Inline.after.mir index cea3c59a3e479..f6dd741364039 100644 --- a/src/test/mir-opt/inline/inline_closure_borrows_arg.foo.Inline.after.mir +++ b/src/test/mir-opt/inline/inline_closure_borrows_arg.foo.Inline.after.mir @@ -24,15 +24,6 @@ fn foo(_1: T, _2: &i32) -> i32 { bb0: { StorageLive(_3); // scope 0 at $DIR/inline-closure-borrows-arg.rs:12:9: 12:10 - _3 = [closure@foo::::{{closure}}#0]; // scope 0 at $DIR/inline-closure-borrows-arg.rs:12:13: 15:6 - // closure - // + def_id: DefId(0:6 ~ inline_closure_borrows_arg[317d]::foo[0]::{{closure}}[0]) - // + substs: [ - // T, - // i8, - // for<'r, 's> extern "rust-call" fn((&'r i32, &'s i32)) -> i32, - // (), - // ] StorageLive(_4); // scope 1 at $DIR/inline-closure-borrows-arg.rs:16:5: 16:6 _4 = &_3; // scope 1 at $DIR/inline-closure-borrows-arg.rs:16:5: 16:6 StorageLive(_5); // scope 1 at $DIR/inline-closure-borrows-arg.rs:16:5: 16:12 @@ -40,7 +31,8 @@ fn foo(_1: T, _2: &i32) -> i32 { _6 = &(*_2); // scope 1 at $DIR/inline-closure-borrows-arg.rs:16:7: 16:8 StorageLive(_7); // scope 1 at $DIR/inline-closure-borrows-arg.rs:16:10: 16:11 _7 = &(*_2); // scope 1 at $DIR/inline-closure-borrows-arg.rs:16:10: 16:11 - _5 = (move _6, move _7); // scope 1 at $DIR/inline-closure-borrows-arg.rs:16:5: 16:12 + (_5.0: &i32) = move _6; // scope 1 at $DIR/inline-closure-borrows-arg.rs:16:5: 16:12 + (_5.1: &i32) = move _7; // scope 1 at $DIR/inline-closure-borrows-arg.rs:16:5: 16:12 _8 = move (_5.0: &i32); // scope 1 at $DIR/inline-closure-borrows-arg.rs:16:5: 16:12 _9 = move (_5.1: &i32); // scope 1 at $DIR/inline-closure-borrows-arg.rs:16:5: 16:12 _0 = (*_8); // scope 3 at $DIR/inline-closure-borrows-arg.rs:14:9: 14:18 diff --git a/src/test/mir-opt/inline/inline_closure_captures.foo.Inline.after.mir b/src/test/mir-opt/inline/inline_closure_captures.foo.Inline.after.mir index eeff914ccffb9..e2b5d6567c299 100644 --- a/src/test/mir-opt/inline/inline_closure_captures.foo.Inline.after.mir +++ b/src/test/mir-opt/inline/inline_closure_captures.foo.Inline.after.mir @@ -28,15 +28,8 @@ fn foo(_1: T, _2: i32) -> (i32, T) { _4 = &_2; // scope 0 at $DIR/inline-closure-captures.rs:11:13: 11:24 StorageLive(_5); // scope 0 at $DIR/inline-closure-captures.rs:11:13: 11:24 _5 = &_1; // scope 0 at $DIR/inline-closure-captures.rs:11:13: 11:24 - _3 = [closure@foo::::{{closure}}#0] { q: move _4, t: move _5 }; // scope 0 at $DIR/inline-closure-captures.rs:11:13: 11:24 - // closure - // + def_id: DefId(0:6 ~ inline_closure_captures[317d]::foo[0]::{{closure}}[0]) - // + substs: [ - // T, - // i8, - // extern "rust-call" fn((i32,)) -> (i32, T), - // (&i32, &T), - // ] + (_3.0: &i32) = move _4; // scope 0 at $DIR/inline-closure-captures.rs:11:13: 11:24 + (_3.1: &T) = move _5; // scope 0 at $DIR/inline-closure-captures.rs:11:13: 11:24 StorageDead(_5); // scope 0 at $DIR/inline-closure-captures.rs:11:23: 11:24 StorageDead(_4); // scope 0 at $DIR/inline-closure-captures.rs:11:23: 11:24 StorageLive(_6); // scope 1 at $DIR/inline-closure-captures.rs:12:5: 12:6 @@ -44,7 +37,7 @@ fn foo(_1: T, _2: i32) -> (i32, T) { StorageLive(_7); // scope 1 at $DIR/inline-closure-captures.rs:12:5: 12:9 StorageLive(_8); // scope 1 at $DIR/inline-closure-captures.rs:12:7: 12:8 _8 = _2; // scope 1 at $DIR/inline-closure-captures.rs:12:7: 12:8 - _7 = (move _8,); // scope 1 at $DIR/inline-closure-captures.rs:12:5: 12:9 + (_7.0: i32) = move _8; // scope 1 at $DIR/inline-closure-captures.rs:12:5: 12:9 _11 = move (_7.0: i32); // scope 1 at $DIR/inline-closure-captures.rs:12:5: 12:9 StorageLive(_9); // scope 2 at $DIR/inline-closure-captures.rs:11:19: 11:20 _9 = (*((*_6).0: &i32)); // scope 2 at $DIR/inline-closure-captures.rs:11:19: 11:20 diff --git a/src/test/mir-opt/issue_73223.main.PreCodegen.diff.32bit b/src/test/mir-opt/issue_73223.main.PreCodegen.diff.32bit index 4c9da471f0b94..919c37a5fc341 100644 --- a/src/test/mir-opt/issue_73223.main.PreCodegen.diff.32bit +++ b/src/test/mir-opt/issue_73223.main.PreCodegen.diff.32bit @@ -11,22 +11,20 @@ let mut _9: bool; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL let mut _10: bool; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL let mut _11: i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let mut _12: i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let _13: &std::fmt::Arguments; // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL - let _14: std::fmt::Arguments; // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL - let mut _15: &[&str]; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let mut _16: &[std::fmt::ArgumentV1]; // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL - let _17: &[std::fmt::ArgumentV1; 2]; // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL - let _18: [std::fmt::ArgumentV1; 2]; // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL - let mut _19: (&&i32, &&i32); // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL - let mut _20: &&i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let _21: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let mut _22: &&i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let _23: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let _12: &std::fmt::Arguments; // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL + let _13: std::fmt::Arguments; // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL + let mut _14: &[&str]; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let mut _15: &[std::fmt::ArgumentV1]; // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL + let _16: &[std::fmt::ArgumentV1; 2]; // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL + let _17: [std::fmt::ArgumentV1; 2]; // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL + let mut _18: (&&i32, &&i32); // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL + let mut _19: &&i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let _20: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let mut _21: &&i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let mut _24: std::fmt::ArgumentV1; // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL + let mut _25: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL let mut _26: std::fmt::ArgumentV1; // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL let mut _27: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let mut _28: std::fmt::ArgumentV1; // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL - let mut _29: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL scope 1 { debug split => _2; // in scope 1 at $DIR/issue-73223.rs:2:9: 2:14 let _3: std::option::Option; // in scope 1 at $DIR/issue-73223.rs:7:9: 7:14 @@ -37,28 +35,28 @@ scope 4 { debug left_val => _7; // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL debug right_val => _8; // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let _24: &&i32; // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let _25: &&i32; // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let _22: &&i32; // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let _23: &&i32; // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL scope 5 { - debug arg0 => _24; // in scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - debug arg1 => _25; // in scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + debug arg0 => _22; // in scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + debug arg1 => _23; // in scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL scope 6 { - debug x => _24; // in scope 6 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL - debug f => _27; // in scope 6 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL - let mut _30: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 6 at $SRC_DIR/std/src/macros.rs:LL:COL - let mut _31: &core::fmt::Opaque; // in scope 6 at $SRC_DIR/std/src/macros.rs:LL:COL + debug x => _22; // in scope 6 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL + debug f => _25; // in scope 6 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL + let mut _28: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 6 at $SRC_DIR/std/src/macros.rs:LL:COL + let mut _29: &core::fmt::Opaque; // in scope 6 at $SRC_DIR/std/src/macros.rs:LL:COL } scope 8 { - debug x => _25; // in scope 8 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL - debug f => _29; // in scope 8 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL - let mut _32: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 8 at $SRC_DIR/std/src/macros.rs:LL:COL - let mut _33: &core::fmt::Opaque; // in scope 8 at $SRC_DIR/std/src/macros.rs:LL:COL + debug x => _23; // in scope 8 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL + debug f => _27; // in scope 8 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL + let mut _30: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 8 at $SRC_DIR/std/src/macros.rs:LL:COL + let mut _31: &core::fmt::Opaque; // in scope 8 at $SRC_DIR/std/src/macros.rs:LL:COL } } scope 10 { - debug pieces => _15; // in scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL - debug args => _16; // in scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL - let mut _34: std::option::Option<&[std::fmt::rt::v1::Argument]>; // in scope 10 at $SRC_DIR/std/src/macros.rs:LL:COL + debug pieces => _14; // in scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL + debug args => _15; // in scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL + let mut _32: std::option::Option<&[std::fmt::rt::v1::Argument]>; // in scope 10 at $SRC_DIR/std/src/macros.rs:LL:COL } } } @@ -103,16 +101,18 @@ StorageDead(_6); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageLive(_7); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL _7 = (_5.0: &i32); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_8); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL _8 = (_5.1: &i32); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageLive(_9); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageLive(_10); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageLive(_11); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL _11 = (*_7); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_12); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _12 = (*_8); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _10 = Eq(move _11, move _12); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageDead(_12); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _10 = Eq(move _11, const 1_i32); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + // ty::Const + // + ty: i32 + // + val: Value(Scalar(0x00000001)) + // mir::Constant + // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL + // + literal: Const { ty: i32, val: Value(Scalar(0x00000001)) } StorageDead(_11); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL _9 = Not(move _10); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageDead(_10); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL @@ -121,7 +121,6 @@ bb1: { StorageDead(_9); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageDead(_8); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageDead(_7); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageDead(_5); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL _0 = const (); // scope 0 at $DIR/issue-73223.rs:1:11: 9:2 @@ -136,40 +135,38 @@ } bb2: { - StorageLive(_14); // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL - _15 = const main::promoted[0] as &[&str] (Pointer(Unsize)); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageLive(_13); // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL + _14 = const main::promoted[0] as &[&str] (Pointer(Unsize)); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL // ty::Const // + ty: &[&str; 3] // + val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main[0]), const_param_did: None }, [], Some(promoted[0])) // mir::Constant // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL // + literal: Const { ty: &[&str; 3], val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main[0]), const_param_did: None }, [], Some(promoted[0])) } + StorageLive(_17); // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL StorageLive(_18); // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL - StorageLive(_19); // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL + StorageLive(_19); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageLive(_20); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _20 = _7; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _19 = &_20; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageLive(_21); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _21 = _7; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _20 = &_21; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_22); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_23); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _23 = _8; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _22 = &_23; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - (_19.0: &&i32) = move _20; // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL - (_19.1: &&i32) = move _22; // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL - StorageDead(_22); // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL - StorageDead(_20); // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL - _24 = (_19.0: &&i32); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _25 = (_19.1: &&i32); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_26); // scope 5 at $SRC_DIR/std/src/macros.rs:LL:COL - _27 = const <&i32 as std::fmt::Debug>::fmt as for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer)); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _21 = &_8; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + (_18.0: &&i32) = move _19; // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL + (_18.1: &&i32) = move _21; // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL + StorageDead(_21); // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL + StorageDead(_19); // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL + _22 = (_18.0: &&i32); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _23 = (_18.1: &&i32); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageLive(_24); // scope 5 at $SRC_DIR/std/src/macros.rs:LL:COL + _25 = const <&i32 as std::fmt::Debug>::fmt as for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer)); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL // ty::Const // + ty: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> {<&i32 as std::fmt::Debug>::fmt} // + val: Value(Scalar()) // mir::Constant // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL // + literal: Const { ty: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> {<&i32 as std::fmt::Debug>::fmt}, val: Value(Scalar()) } - StorageLive(_30); // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL - _30 = const std::intrinsics::transmute:: fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>, for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>>(move _27) -> bb3; // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL + StorageLive(_28); // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL + _28 = const std::intrinsics::transmute:: fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>, for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>>(move _25) -> bb3; // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL // ty::Const // + ty: unsafe extern "rust-intrinsic" fn(for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>) -> for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> {std::intrinsics::transmute:: fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>, for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>>} // + val: Value(Scalar()) @@ -179,8 +176,8 @@ } bb3: { - StorageLive(_31); // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL - _31 = const std::intrinsics::transmute::<&&i32, &core::fmt::Opaque>(move _24) -> bb4; // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL + StorageLive(_29); // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL + _29 = const std::intrinsics::transmute::<&&i32, &core::fmt::Opaque>(move _22) -> bb4; // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL // ty::Const // + ty: unsafe extern "rust-intrinsic" fn(&&i32) -> &core::fmt::Opaque {std::intrinsics::transmute::<&&i32, &core::fmt::Opaque>} // + val: Value(Scalar()) @@ -190,20 +187,20 @@ } bb4: { - (_26.0: &core::fmt::Opaque) = move _31; // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL - (_26.1: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>) = move _30; // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL - StorageDead(_31); // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL - StorageDead(_30); // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL - StorageLive(_28); // scope 5 at $SRC_DIR/std/src/macros.rs:LL:COL - _29 = const <&i32 as std::fmt::Debug>::fmt as for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer)); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + (_24.0: &core::fmt::Opaque) = move _29; // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL + (_24.1: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>) = move _28; // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL + StorageDead(_29); // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL + StorageDead(_28); // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL + StorageLive(_26); // scope 5 at $SRC_DIR/std/src/macros.rs:LL:COL + _27 = const <&i32 as std::fmt::Debug>::fmt as for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer)); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL // ty::Const // + ty: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> {<&i32 as std::fmt::Debug>::fmt} // + val: Value(Scalar()) // mir::Constant // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL // + literal: Const { ty: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> {<&i32 as std::fmt::Debug>::fmt}, val: Value(Scalar()) } - StorageLive(_32); // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL - _32 = const std::intrinsics::transmute:: fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>, for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>>(move _29) -> bb5; // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL + StorageLive(_30); // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL + _30 = const std::intrinsics::transmute:: fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>, for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>>(move _27) -> bb5; // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL // ty::Const // + ty: unsafe extern "rust-intrinsic" fn(for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>) -> for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> {std::intrinsics::transmute:: fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>, for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>>} // + val: Value(Scalar()) @@ -213,8 +210,8 @@ } bb5: { - StorageLive(_33); // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL - _33 = const std::intrinsics::transmute::<&&i32, &core::fmt::Opaque>(move _25) -> bb6; // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL + StorageLive(_31); // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL + _31 = const std::intrinsics::transmute::<&&i32, &core::fmt::Opaque>(move _23) -> bb6; // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL // ty::Const // + ty: unsafe extern "rust-intrinsic" fn(&&i32) -> &core::fmt::Opaque {std::intrinsics::transmute::<&&i32, &core::fmt::Opaque>} // + val: Value(Scalar()) @@ -224,23 +221,23 @@ } bb6: { - (_28.0: &core::fmt::Opaque) = move _33; // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL - (_28.1: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>) = move _32; // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL - StorageDead(_33); // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL - StorageDead(_32); // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL - _18 = [move _26, move _28]; // scope 5 at $SRC_DIR/std/src/macros.rs:LL:COL - StorageDead(_28); // scope 5 at $SRC_DIR/std/src/macros.rs:LL:COL + (_26.0: &core::fmt::Opaque) = move _31; // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL + (_26.1: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>) = move _30; // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL + StorageDead(_31); // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL + StorageDead(_30); // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL + _17 = [move _24, move _26]; // scope 5 at $SRC_DIR/std/src/macros.rs:LL:COL StorageDead(_26); // scope 5 at $SRC_DIR/std/src/macros.rs:LL:COL - _17 = &_18; // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL - _16 = move _17 as &[std::fmt::ArgumentV1] (Pointer(Unsize)); // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL - StorageLive(_34); // scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL - discriminant(_34) = 0; // scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL - (_14.0: &[&str]) = move _15; // scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL - (_14.1: std::option::Option<&[std::fmt::rt::v1::Argument]>) = move _34; // scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL - (_14.2: &[std::fmt::ArgumentV1]) = move _16; // scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL - StorageDead(_34); // scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL - _13 = &_14; // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL - const std::rt::begin_panic_fmt(move _13); // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL + StorageDead(_24); // scope 5 at $SRC_DIR/std/src/macros.rs:LL:COL + _16 = &_17; // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL + _15 = move _16 as &[std::fmt::ArgumentV1] (Pointer(Unsize)); // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL + StorageLive(_32); // scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL + discriminant(_32) = 0; // scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL + (_13.0: &[&str]) = move _14; // scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL + (_13.1: std::option::Option<&[std::fmt::rt::v1::Argument]>) = move _32; // scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL + (_13.2: &[std::fmt::ArgumentV1]) = move _15; // scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL + StorageDead(_32); // scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL + _12 = &_13; // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL + const std::rt::begin_panic_fmt(move _12); // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL // ty::Const // + ty: for<'r, 's> fn(&'r std::fmt::Arguments<'s>) -> ! {std::rt::begin_panic_fmt} // + val: Value(Scalar()) diff --git a/src/test/mir-opt/issue_73223.main.PreCodegen.diff.64bit b/src/test/mir-opt/issue_73223.main.PreCodegen.diff.64bit index 4c9da471f0b94..919c37a5fc341 100644 --- a/src/test/mir-opt/issue_73223.main.PreCodegen.diff.64bit +++ b/src/test/mir-opt/issue_73223.main.PreCodegen.diff.64bit @@ -11,22 +11,20 @@ let mut _9: bool; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL let mut _10: bool; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL let mut _11: i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let mut _12: i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let _13: &std::fmt::Arguments; // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL - let _14: std::fmt::Arguments; // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL - let mut _15: &[&str]; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let mut _16: &[std::fmt::ArgumentV1]; // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL - let _17: &[std::fmt::ArgumentV1; 2]; // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL - let _18: [std::fmt::ArgumentV1; 2]; // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL - let mut _19: (&&i32, &&i32); // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL - let mut _20: &&i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let _21: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let mut _22: &&i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let _23: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let _12: &std::fmt::Arguments; // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL + let _13: std::fmt::Arguments; // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL + let mut _14: &[&str]; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let mut _15: &[std::fmt::ArgumentV1]; // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL + let _16: &[std::fmt::ArgumentV1; 2]; // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL + let _17: [std::fmt::ArgumentV1; 2]; // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL + let mut _18: (&&i32, &&i32); // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL + let mut _19: &&i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let _20: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let mut _21: &&i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let mut _24: std::fmt::ArgumentV1; // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL + let mut _25: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL let mut _26: std::fmt::ArgumentV1; // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL let mut _27: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let mut _28: std::fmt::ArgumentV1; // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL - let mut _29: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL scope 1 { debug split => _2; // in scope 1 at $DIR/issue-73223.rs:2:9: 2:14 let _3: std::option::Option; // in scope 1 at $DIR/issue-73223.rs:7:9: 7:14 @@ -37,28 +35,28 @@ scope 4 { debug left_val => _7; // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL debug right_val => _8; // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let _24: &&i32; // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let _25: &&i32; // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let _22: &&i32; // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let _23: &&i32; // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL scope 5 { - debug arg0 => _24; // in scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - debug arg1 => _25; // in scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + debug arg0 => _22; // in scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + debug arg1 => _23; // in scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL scope 6 { - debug x => _24; // in scope 6 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL - debug f => _27; // in scope 6 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL - let mut _30: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 6 at $SRC_DIR/std/src/macros.rs:LL:COL - let mut _31: &core::fmt::Opaque; // in scope 6 at $SRC_DIR/std/src/macros.rs:LL:COL + debug x => _22; // in scope 6 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL + debug f => _25; // in scope 6 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL + let mut _28: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 6 at $SRC_DIR/std/src/macros.rs:LL:COL + let mut _29: &core::fmt::Opaque; // in scope 6 at $SRC_DIR/std/src/macros.rs:LL:COL } scope 8 { - debug x => _25; // in scope 8 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL - debug f => _29; // in scope 8 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL - let mut _32: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 8 at $SRC_DIR/std/src/macros.rs:LL:COL - let mut _33: &core::fmt::Opaque; // in scope 8 at $SRC_DIR/std/src/macros.rs:LL:COL + debug x => _23; // in scope 8 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL + debug f => _27; // in scope 8 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL + let mut _30: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 8 at $SRC_DIR/std/src/macros.rs:LL:COL + let mut _31: &core::fmt::Opaque; // in scope 8 at $SRC_DIR/std/src/macros.rs:LL:COL } } scope 10 { - debug pieces => _15; // in scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL - debug args => _16; // in scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL - let mut _34: std::option::Option<&[std::fmt::rt::v1::Argument]>; // in scope 10 at $SRC_DIR/std/src/macros.rs:LL:COL + debug pieces => _14; // in scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL + debug args => _15; // in scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL + let mut _32: std::option::Option<&[std::fmt::rt::v1::Argument]>; // in scope 10 at $SRC_DIR/std/src/macros.rs:LL:COL } } } @@ -103,16 +101,18 @@ StorageDead(_6); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageLive(_7); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL _7 = (_5.0: &i32); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_8); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL _8 = (_5.1: &i32); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageLive(_9); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageLive(_10); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageLive(_11); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL _11 = (*_7); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_12); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _12 = (*_8); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _10 = Eq(move _11, move _12); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageDead(_12); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _10 = Eq(move _11, const 1_i32); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + // ty::Const + // + ty: i32 + // + val: Value(Scalar(0x00000001)) + // mir::Constant + // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL + // + literal: Const { ty: i32, val: Value(Scalar(0x00000001)) } StorageDead(_11); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL _9 = Not(move _10); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageDead(_10); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL @@ -121,7 +121,6 @@ bb1: { StorageDead(_9); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageDead(_8); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageDead(_7); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageDead(_5); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL _0 = const (); // scope 0 at $DIR/issue-73223.rs:1:11: 9:2 @@ -136,40 +135,38 @@ } bb2: { - StorageLive(_14); // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL - _15 = const main::promoted[0] as &[&str] (Pointer(Unsize)); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageLive(_13); // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL + _14 = const main::promoted[0] as &[&str] (Pointer(Unsize)); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL // ty::Const // + ty: &[&str; 3] // + val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main[0]), const_param_did: None }, [], Some(promoted[0])) // mir::Constant // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL // + literal: Const { ty: &[&str; 3], val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main[0]), const_param_did: None }, [], Some(promoted[0])) } + StorageLive(_17); // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL StorageLive(_18); // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL - StorageLive(_19); // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL + StorageLive(_19); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageLive(_20); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _20 = _7; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _19 = &_20; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageLive(_21); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _21 = _7; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _20 = &_21; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_22); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_23); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _23 = _8; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _22 = &_23; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - (_19.0: &&i32) = move _20; // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL - (_19.1: &&i32) = move _22; // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL - StorageDead(_22); // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL - StorageDead(_20); // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL - _24 = (_19.0: &&i32); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _25 = (_19.1: &&i32); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_26); // scope 5 at $SRC_DIR/std/src/macros.rs:LL:COL - _27 = const <&i32 as std::fmt::Debug>::fmt as for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer)); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _21 = &_8; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + (_18.0: &&i32) = move _19; // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL + (_18.1: &&i32) = move _21; // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL + StorageDead(_21); // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL + StorageDead(_19); // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL + _22 = (_18.0: &&i32); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _23 = (_18.1: &&i32); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageLive(_24); // scope 5 at $SRC_DIR/std/src/macros.rs:LL:COL + _25 = const <&i32 as std::fmt::Debug>::fmt as for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer)); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL // ty::Const // + ty: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> {<&i32 as std::fmt::Debug>::fmt} // + val: Value(Scalar()) // mir::Constant // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL // + literal: Const { ty: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> {<&i32 as std::fmt::Debug>::fmt}, val: Value(Scalar()) } - StorageLive(_30); // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL - _30 = const std::intrinsics::transmute:: fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>, for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>>(move _27) -> bb3; // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL + StorageLive(_28); // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL + _28 = const std::intrinsics::transmute:: fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>, for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>>(move _25) -> bb3; // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL // ty::Const // + ty: unsafe extern "rust-intrinsic" fn(for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>) -> for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> {std::intrinsics::transmute:: fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>, for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>>} // + val: Value(Scalar()) @@ -179,8 +176,8 @@ } bb3: { - StorageLive(_31); // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL - _31 = const std::intrinsics::transmute::<&&i32, &core::fmt::Opaque>(move _24) -> bb4; // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL + StorageLive(_29); // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL + _29 = const std::intrinsics::transmute::<&&i32, &core::fmt::Opaque>(move _22) -> bb4; // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL // ty::Const // + ty: unsafe extern "rust-intrinsic" fn(&&i32) -> &core::fmt::Opaque {std::intrinsics::transmute::<&&i32, &core::fmt::Opaque>} // + val: Value(Scalar()) @@ -190,20 +187,20 @@ } bb4: { - (_26.0: &core::fmt::Opaque) = move _31; // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL - (_26.1: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>) = move _30; // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL - StorageDead(_31); // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL - StorageDead(_30); // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL - StorageLive(_28); // scope 5 at $SRC_DIR/std/src/macros.rs:LL:COL - _29 = const <&i32 as std::fmt::Debug>::fmt as for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer)); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + (_24.0: &core::fmt::Opaque) = move _29; // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL + (_24.1: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>) = move _28; // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL + StorageDead(_29); // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL + StorageDead(_28); // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL + StorageLive(_26); // scope 5 at $SRC_DIR/std/src/macros.rs:LL:COL + _27 = const <&i32 as std::fmt::Debug>::fmt as for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer)); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL // ty::Const // + ty: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> {<&i32 as std::fmt::Debug>::fmt} // + val: Value(Scalar()) // mir::Constant // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL // + literal: Const { ty: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> {<&i32 as std::fmt::Debug>::fmt}, val: Value(Scalar()) } - StorageLive(_32); // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL - _32 = const std::intrinsics::transmute:: fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>, for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>>(move _29) -> bb5; // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL + StorageLive(_30); // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL + _30 = const std::intrinsics::transmute:: fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>, for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>>(move _27) -> bb5; // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL // ty::Const // + ty: unsafe extern "rust-intrinsic" fn(for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>) -> for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> {std::intrinsics::transmute:: fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>, for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>>} // + val: Value(Scalar()) @@ -213,8 +210,8 @@ } bb5: { - StorageLive(_33); // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL - _33 = const std::intrinsics::transmute::<&&i32, &core::fmt::Opaque>(move _25) -> bb6; // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL + StorageLive(_31); // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL + _31 = const std::intrinsics::transmute::<&&i32, &core::fmt::Opaque>(move _23) -> bb6; // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL // ty::Const // + ty: unsafe extern "rust-intrinsic" fn(&&i32) -> &core::fmt::Opaque {std::intrinsics::transmute::<&&i32, &core::fmt::Opaque>} // + val: Value(Scalar()) @@ -224,23 +221,23 @@ } bb6: { - (_28.0: &core::fmt::Opaque) = move _33; // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL - (_28.1: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>) = move _32; // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL - StorageDead(_33); // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL - StorageDead(_32); // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL - _18 = [move _26, move _28]; // scope 5 at $SRC_DIR/std/src/macros.rs:LL:COL - StorageDead(_28); // scope 5 at $SRC_DIR/std/src/macros.rs:LL:COL + (_26.0: &core::fmt::Opaque) = move _31; // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL + (_26.1: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>) = move _30; // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL + StorageDead(_31); // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL + StorageDead(_30); // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL + _17 = [move _24, move _26]; // scope 5 at $SRC_DIR/std/src/macros.rs:LL:COL StorageDead(_26); // scope 5 at $SRC_DIR/std/src/macros.rs:LL:COL - _17 = &_18; // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL - _16 = move _17 as &[std::fmt::ArgumentV1] (Pointer(Unsize)); // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL - StorageLive(_34); // scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL - discriminant(_34) = 0; // scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL - (_14.0: &[&str]) = move _15; // scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL - (_14.1: std::option::Option<&[std::fmt::rt::v1::Argument]>) = move _34; // scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL - (_14.2: &[std::fmt::ArgumentV1]) = move _16; // scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL - StorageDead(_34); // scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL - _13 = &_14; // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL - const std::rt::begin_panic_fmt(move _13); // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL + StorageDead(_24); // scope 5 at $SRC_DIR/std/src/macros.rs:LL:COL + _16 = &_17; // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL + _15 = move _16 as &[std::fmt::ArgumentV1] (Pointer(Unsize)); // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL + StorageLive(_32); // scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL + discriminant(_32) = 0; // scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL + (_13.0: &[&str]) = move _14; // scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL + (_13.1: std::option::Option<&[std::fmt::rt::v1::Argument]>) = move _32; // scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL + (_13.2: &[std::fmt::ArgumentV1]) = move _15; // scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL + StorageDead(_32); // scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL + _12 = &_13; // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL + const std::rt::begin_panic_fmt(move _12); // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL // ty::Const // + ty: for<'r, 's> fn(&'r std::fmt::Arguments<'s>) -> ! {std::rt::begin_panic_fmt} // + val: Value(Scalar()) diff --git a/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.diff.32bit b/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.diff.32bit index dd0e8f4b2ad4f..28d949be271e8 100644 --- a/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.diff.32bit +++ b/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.diff.32bit @@ -165,8 +165,20 @@ StorageLive(_17); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL _17 = (*_13); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageLive(_18); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _18 = (*_14); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _16 = Eq(move _17, move _18); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _18 = const 1_i32; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + // ty::Const + // + ty: i32 + // + val: Value(Scalar(0x00000001)) + // mir::Constant + // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL + // + literal: Const { ty: i32, val: Value(Scalar(0x00000001)) } + _16 = Eq(move _17, const 1_i32); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + // ty::Const + // + ty: i32 + // + val: Value(Scalar(0x00000001)) + // mir::Constant + // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL + // + literal: Const { ty: i32, val: Value(Scalar(0x00000001)) } StorageDead(_18); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageDead(_17); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL _15 = Not(move _16); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL diff --git a/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.diff.64bit b/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.diff.64bit index d465f60f34d7c..2b854850deaf1 100644 --- a/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.diff.64bit +++ b/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.diff.64bit @@ -165,8 +165,20 @@ StorageLive(_17); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL _17 = (*_13); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageLive(_18); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _18 = (*_14); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _16 = Eq(move _17, move _18); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _18 = const 1_i32; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + // ty::Const + // + ty: i32 + // + val: Value(Scalar(0x00000001)) + // mir::Constant + // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL + // + literal: Const { ty: i32, val: Value(Scalar(0x00000001)) } + _16 = Eq(move _17, const 1_i32); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + // ty::Const + // + ty: i32 + // + val: Value(Scalar(0x00000001)) + // mir::Constant + // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL + // + literal: Const { ty: i32, val: Value(Scalar(0x00000001)) } StorageDead(_18); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageDead(_17); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL _15 = Not(move _16); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL diff --git a/src/test/mir-opt/simplify_arm_identity.main.SimplifyArmIdentity.diff.32bit b/src/test/mir-opt/simplify_arm_identity.main.SimplifyArmIdentity.diff.32bit index 0de80f72a1e70..b7b239ea414d6 100644 --- a/src/test/mir-opt/simplify_arm_identity.main.SimplifyArmIdentity.diff.32bit +++ b/src/test/mir-opt/simplify_arm_identity.main.SimplifyArmIdentity.diff.32bit @@ -39,13 +39,14 @@ } bb1: { - _2 = const Dst::Foo(0_u8); // scope 1 at $DIR/simplify-arm-identity.rs:21:21: 21:32 + ((_2 as Foo).0: u8) = const 0_u8; // scope 1 at $DIR/simplify-arm-identity.rs:21:21: 21:32 // ty::Const - // + ty: Dst + // + ty: u8 // + val: Value(Scalar(0x00)) // mir::Constant - // + span: $DIR/simplify-arm-identity.rs:21:21: 21:32 - // + literal: Const { ty: Dst, val: Value(Scalar(0x00)) } + // + span: $DIR/simplify-arm-identity.rs:21:30: 21:31 + // + literal: Const { ty: u8, val: Value(Scalar(0x00)) } + discriminant(_2) = 0; // scope 1 at $DIR/simplify-arm-identity.rs:21:21: 21:32 goto -> bb4; // scope 1 at $DIR/simplify-arm-identity.rs:19:18: 22:6 } diff --git a/src/test/mir-opt/simplify_arm_identity.main.SimplifyArmIdentity.diff.64bit b/src/test/mir-opt/simplify_arm_identity.main.SimplifyArmIdentity.diff.64bit index 4fa0aff8fa0ef..34282526da0fa 100644 --- a/src/test/mir-opt/simplify_arm_identity.main.SimplifyArmIdentity.diff.64bit +++ b/src/test/mir-opt/simplify_arm_identity.main.SimplifyArmIdentity.diff.64bit @@ -39,13 +39,14 @@ } bb1: { - _2 = const Dst::Foo(0_u8); // scope 1 at $DIR/simplify-arm-identity.rs:21:21: 21:32 + ((_2 as Foo).0: u8) = const 0_u8; // scope 1 at $DIR/simplify-arm-identity.rs:21:21: 21:32 // ty::Const - // + ty: Dst + // + ty: u8 // + val: Value(Scalar(0x00)) // mir::Constant - // + span: $DIR/simplify-arm-identity.rs:21:21: 21:32 - // + literal: Const { ty: Dst, val: Value(Scalar(0x00)) } + // + span: $DIR/simplify-arm-identity.rs:21:30: 21:31 + // + literal: Const { ty: u8, val: Value(Scalar(0x00)) } + discriminant(_2) = 0; // scope 1 at $DIR/simplify-arm-identity.rs:21:21: 21:32 goto -> bb4; // scope 1 at $DIR/simplify-arm-identity.rs:19:18: 22:6 } diff --git a/src/test/mir-opt/simplify_locals_removes_unused_consts.main.SimplifyLocals.diff b/src/test/mir-opt/simplify_locals_removes_unused_consts.main.SimplifyLocals.diff index db06b0392df6c..8b5936116b3a7 100644 --- a/src/test/mir-opt/simplify_locals_removes_unused_consts.main.SimplifyLocals.diff +++ b/src/test/mir-opt/simplify_locals_removes_unused_consts.main.SimplifyLocals.diff @@ -22,58 +22,44 @@ bb0: { - StorageLive(_1); // scope 0 at $DIR/simplify-locals-removes-unused-consts.rs:13:20: 13:28 - StorageLive(_2); // scope 0 at $DIR/simplify-locals-removes-unused-consts.rs:13:21: 13:23 -- _2 = const (); // scope 0 at $DIR/simplify-locals-removes-unused-consts.rs:13:21: 13:23 +- StorageLive(_3); // scope 0 at $DIR/simplify-locals-removes-unused-consts.rs:13:25: 13:27 +- (_1.0: ()) = const (); // scope 0 at $DIR/simplify-locals-removes-unused-consts.rs:13:20: 13:28 + StorageLive(_1); // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:14:5: 14:22 + _1 = const use_zst(const ((), ())) -> bb1; // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:14:5: 14:22 // ty::Const - // + ty: () - // + val: Value(Scalar()) - // mir::Constant -- // + span: $DIR/simplify-locals-removes-unused-consts.rs:13:21: 13:23 +- // + span: $DIR/simplify-locals-removes-unused-consts.rs:13:20: 13:28 - // + literal: Const { ty: (), val: Value(Scalar()) } -- StorageLive(_3); // scope 0 at $DIR/simplify-locals-removes-unused-consts.rs:13:25: 13:27 -- _3 = const (); // scope 0 at $DIR/simplify-locals-removes-unused-consts.rs:13:25: 13:27 +- (_1.1: ()) = const (); // scope 0 at $DIR/simplify-locals-removes-unused-consts.rs:13:20: 13:28 - // ty::Const - // + ty: () - // + val: Value(Scalar()) - // mir::Constant -- // + span: $DIR/simplify-locals-removes-unused-consts.rs:13:25: 13:27 -- // + literal: Const { ty: (), val: Value(Scalar()) } -- _1 = const ((), ()); // scope 0 at $DIR/simplify-locals-removes-unused-consts.rs:13:20: 13:28 -- // ty::Const -- // + ty: ((), ()) -- // + val: Value(Scalar()) -- // mir::Constant - // + span: $DIR/simplify-locals-removes-unused-consts.rs:13:20: 13:28 -- // + literal: Const { ty: ((), ()), val: Value(Scalar()) } +- // + literal: Const { ty: (), val: Value(Scalar()) } - StorageDead(_3); // scope 0 at $DIR/simplify-locals-removes-unused-consts.rs:13:27: 13:28 - StorageDead(_2); // scope 0 at $DIR/simplify-locals-removes-unused-consts.rs:13:27: 13:28 - StorageDead(_1); // scope 0 at $DIR/simplify-locals-removes-unused-consts.rs:13:28: 13:29 - StorageLive(_4); // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:14:5: 14:22 - StorageLive(_5); // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:14:13: 14:21 - StorageLive(_6); // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:14:14: 14:16 -- _6 = const (); // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:14:14: 14:16 -- // ty::Const -- // + ty: () -- // + val: Value(Scalar()) -- // mir::Constant -- // + span: $DIR/simplify-locals-removes-unused-consts.rs:14:14: 14:16 -- // + literal: Const { ty: (), val: Value(Scalar()) } - StorageLive(_7); // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:14:18: 14:20 -- _7 = const (); // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:14:18: 14:20 +- (_5.0: ()) = const (); // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:14:13: 14:21 - // ty::Const - // + ty: () - // + val: Value(Scalar()) - // mir::Constant -- // + span: $DIR/simplify-locals-removes-unused-consts.rs:14:18: 14:20 +- // + span: $DIR/simplify-locals-removes-unused-consts.rs:14:13: 14:21 - // + literal: Const { ty: (), val: Value(Scalar()) } -- _5 = const ((), ()); // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:14:13: 14:21 +- (_5.1: ()) = const (); // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:14:13: 14:21 - // ty::Const -- // + ty: ((), ()) +- // + ty: () - // + val: Value(Scalar()) - // mir::Constant - // + span: $DIR/simplify-locals-removes-unused-consts.rs:14:13: 14:21 -- // + literal: Const { ty: ((), ()), val: Value(Scalar()) } +- // + literal: Const { ty: (), val: Value(Scalar()) } - StorageDead(_7); // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:14:20: 14:21 - StorageDead(_6); // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:14:20: 14:21 - _4 = const use_zst(const ((), ())) -> bb1; // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:14:5: 14:22 @@ -98,16 +84,16 @@ - StorageLive(_9); // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:16:12: 16:34 - StorageLive(_10); // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:16:12: 16:30 - StorageLive(_11); // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:16:12: 16:28 -- _11 = const Temp { x: 40_u8 }; // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:16:12: 16:28 +- (_11.0: u8) = const 40_u8; // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:16:12: 16:28 + StorageDead(_1); // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:14:22: 14:23 + StorageLive(_2); // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:16:5: 16:35 + _2 = const use_u8(const 42_u8) -> bb2; // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:16:5: 16:35 // ty::Const -- // + ty: Temp +- // + ty: u8 - // + val: Value(Scalar(0x28)) - // mir::Constant -- // + span: $DIR/simplify-locals-removes-unused-consts.rs:16:12: 16:28 -- // + literal: Const { ty: Temp, val: Value(Scalar(0x28)) } +- // + span: $DIR/simplify-locals-removes-unused-consts.rs:16:23: 16:25 +- // + literal: Const { ty: u8, val: Value(Scalar(0x28)) } - _10 = const 40_u8; // scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:16:12: 16:30 - // ty::Const - // + ty: u8 diff --git a/src/test/mir-opt/simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals.diff.32bit b/src/test/mir-opt/simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals.diff.32bit index 440c5f8772ed1..0bd13e009ddc8 100644 --- a/src/test/mir-opt/simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals.diff.32bit +++ b/src/test/mir-opt/simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals.diff.32bit @@ -39,13 +39,7 @@ } bb2: { - _0 = const std::option::Option::>::None; // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:3:17: 3:21 - // ty::Const - // + ty: std::option::Option> - // + val: Value(Scalar(0x00000000)) - // mir::Constant - // + span: $DIR/simplify-locals-removes-unused-discriminant-reads.rs:3:17: 3:21 - // + literal: Const { ty: std::option::Option>, val: Value(Scalar(0x00000000)) } + discriminant(_0) = 0; // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:3:17: 3:21 goto -> bb3; // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:2:5: 5:6 } diff --git a/src/test/mir-opt/simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals.diff.64bit b/src/test/mir-opt/simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals.diff.64bit index c12d1715b486d..0bd13e009ddc8 100644 --- a/src/test/mir-opt/simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals.diff.64bit +++ b/src/test/mir-opt/simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals.diff.64bit @@ -39,13 +39,7 @@ } bb2: { - _0 = const std::option::Option::>::None; // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:3:17: 3:21 - // ty::Const - // + ty: std::option::Option> - // + val: Value(Scalar(0x0000000000000000)) - // mir::Constant - // + span: $DIR/simplify-locals-removes-unused-discriminant-reads.rs:3:17: 3:21 - // + literal: Const { ty: std::option::Option>, val: Value(Scalar(0x0000000000000000)) } + discriminant(_0) = 0; // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:3:17: 3:21 goto -> bb3; // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:2:5: 5:6 } diff --git a/src/test/mir-opt/uninhabited_enum_branching.main.SimplifyCfg-after-uninhabited-enum-branching.after.mir b/src/test/mir-opt/uninhabited_enum_branching.main.SimplifyCfg-after-uninhabited-enum-branching.after.mir index 4f4fb7defc379..24fd26591bd82 100644 --- a/src/test/mir-opt/uninhabited_enum_branching.main.SimplifyCfg-after-uninhabited-enum-branching.after.mir +++ b/src/test/mir-opt/uninhabited_enum_branching.main.SimplifyCfg-after-uninhabited-enum-branching.after.mir @@ -15,7 +15,7 @@ fn main() -> () { bb0: { StorageLive(_1); // scope 0 at $DIR/uninhabited_enum_branching.rs:20:5: 24:6 StorageLive(_2); // scope 0 at $DIR/uninhabited_enum_branching.rs:20:11: 20:19 - _2 = Test1::C; // scope 0 at $DIR/uninhabited_enum_branching.rs:20:11: 20:19 + discriminant(_2) = 2; // scope 0 at $DIR/uninhabited_enum_branching.rs:20:11: 20:19 _3 = discriminant(_2); // scope 0 at $DIR/uninhabited_enum_branching.rs:21:9: 21:20 StorageLive(_5); // scope 0 at $DIR/uninhabited_enum_branching.rs:23:21: 23:24 _5 = const "C"; // scope 0 at $DIR/uninhabited_enum_branching.rs:23:21: 23:24 @@ -31,7 +31,7 @@ fn main() -> () { StorageDead(_1); // scope 0 at $DIR/uninhabited_enum_branching.rs:24:6: 24:7 StorageLive(_6); // scope 0 at $DIR/uninhabited_enum_branching.rs:26:5: 29:6 StorageLive(_7); // scope 0 at $DIR/uninhabited_enum_branching.rs:26:11: 26:19 - _7 = Test2::D; // scope 0 at $DIR/uninhabited_enum_branching.rs:26:11: 26:19 + discriminant(_7) = 0; // scope 0 at $DIR/uninhabited_enum_branching.rs:26:11: 26:19 _8 = discriminant(_7); // scope 0 at $DIR/uninhabited_enum_branching.rs:27:9: 27:17 switchInt(move _8) -> [4_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/uninhabited_enum_branching.rs:27:9: 27:17 } diff --git a/src/test/mir-opt/uninhabited_enum_branching.main.UninhabitedEnumBranching.diff b/src/test/mir-opt/uninhabited_enum_branching.main.UninhabitedEnumBranching.diff index d262c9432ca83..7e0a95edf3e7d 100644 --- a/src/test/mir-opt/uninhabited_enum_branching.main.UninhabitedEnumBranching.diff +++ b/src/test/mir-opt/uninhabited_enum_branching.main.UninhabitedEnumBranching.diff @@ -16,7 +16,7 @@ bb0: { StorageLive(_1); // scope 0 at $DIR/uninhabited_enum_branching.rs:20:5: 24:6 StorageLive(_2); // scope 0 at $DIR/uninhabited_enum_branching.rs:20:11: 20:19 - _2 = Test1::C; // scope 0 at $DIR/uninhabited_enum_branching.rs:20:11: 20:19 + discriminant(_2) = 2; // scope 0 at $DIR/uninhabited_enum_branching.rs:20:11: 20:19 _3 = discriminant(_2); // scope 0 at $DIR/uninhabited_enum_branching.rs:21:9: 21:20 - switchInt(move _3) -> [0_isize: bb2, 1_isize: bb3, otherwise: bb1]; // scope 0 at $DIR/uninhabited_enum_branching.rs:21:9: 21:20 + switchInt(move _3) -> bb1; // scope 0 at $DIR/uninhabited_enum_branching.rs:21:9: 21:20 @@ -66,7 +66,7 @@ StorageDead(_1); // scope 0 at $DIR/uninhabited_enum_branching.rs:24:6: 24:7 StorageLive(_6); // scope 0 at $DIR/uninhabited_enum_branching.rs:26:5: 29:6 StorageLive(_7); // scope 0 at $DIR/uninhabited_enum_branching.rs:26:11: 26:19 - _7 = Test2::D; // scope 0 at $DIR/uninhabited_enum_branching.rs:26:11: 26:19 + discriminant(_7) = 0; // scope 0 at $DIR/uninhabited_enum_branching.rs:26:11: 26:19 _8 = discriminant(_7); // scope 0 at $DIR/uninhabited_enum_branching.rs:27:9: 27:17 switchInt(move _8) -> [4_isize: bb6, otherwise: bb5]; // scope 0 at $DIR/uninhabited_enum_branching.rs:27:9: 27:17 } diff --git a/src/test/mir-opt/while_let_loops.change_loop_body.ConstProp.diff.32bit b/src/test/mir-opt/while_let_loops.change_loop_body.ConstProp.diff.32bit new file mode 100644 index 0000000000000..ff98b0e32268a --- /dev/null +++ b/src/test/mir-opt/while_let_loops.change_loop_body.ConstProp.diff.32bit @@ -0,0 +1,84 @@ +- // MIR for `change_loop_body` before ConstProp ++ // MIR for `change_loop_body` after ConstProp + + fn change_loop_body() -> () { + let mut _0: (); // return place in scope 0 at $DIR/while_let_loops.rs:5:27: 5:27 + let mut _1: i32; // in scope 0 at $DIR/while_let_loops.rs:6:9: 6:15 + let mut _2: (); // in scope 0 at $DIR/while_let_loops.rs:5:1: 11:2 + let mut _3: std::option::Option; // in scope 0 at $DIR/while_let_loops.rs:7:28: 7:32 + let mut _4: isize; // in scope 0 at $DIR/while_let_loops.rs:7:15: 7:25 + let mut _5: !; // in scope 0 at $DIR/while_let_loops.rs:7:33: 10:6 + let mut _6: !; // in scope 0 at $DIR/while_let_loops.rs:7:5: 10:6 + scope 1 { + debug _x => _1; // in scope 1 at $DIR/while_let_loops.rs:6:9: 6:15 + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/while_let_loops.rs:6:9: 6:15 + _1 = const 0_i32; // scope 0 at $DIR/while_let_loops.rs:6:18: 6:19 + // ty::Const + // + ty: i32 + // + val: Value(Scalar(0x00000000)) + // mir::Constant + // + span: $DIR/while_let_loops.rs:6:18: 6:19 + // + literal: Const { ty: i32, val: Value(Scalar(0x00000000)) } + StorageLive(_3); // scope 1 at $DIR/while_let_loops.rs:7:28: 7:32 + discriminant(_3) = 0; // scope 1 at $DIR/while_let_loops.rs:7:28: 7:32 +- _4 = discriminant(_3); // scope 1 at $DIR/while_let_loops.rs:7:15: 7:25 +- switchInt(move _4) -> [1_isize: bb2, otherwise: bb1]; // scope 1 at $DIR/while_let_loops.rs:7:15: 7:25 ++ _4 = const 0_isize; // scope 1 at $DIR/while_let_loops.rs:7:15: 7:25 ++ // ty::Const ++ // + ty: isize ++ // + val: Value(Scalar(0x00000000)) ++ // mir::Constant ++ // + span: $DIR/while_let_loops.rs:7:15: 7:25 ++ // + literal: Const { ty: isize, val: Value(Scalar(0x00000000)) } ++ switchInt(const 0_isize) -> [1_isize: bb2, otherwise: bb1]; // scope 1 at $DIR/while_let_loops.rs:7:15: 7:25 ++ // ty::Const ++ // + ty: isize ++ // + val: Value(Scalar(0x00000000)) ++ // mir::Constant ++ // + span: $DIR/while_let_loops.rs:7:15: 7:25 ++ // + literal: Const { ty: isize, val: Value(Scalar(0x00000000)) } + } + + bb1: { + _0 = const (); // scope 1 at $DIR/while_let_loops.rs:7:5: 10:6 + // ty::Const + // + ty: () + // + val: Value(Scalar()) + // mir::Constant + // + span: $DIR/while_let_loops.rs:7:5: 10:6 + // + literal: Const { ty: (), val: Value(Scalar()) } + goto -> bb4; // scope 1 at $DIR/while_let_loops.rs:7:5: 10:6 + } + + bb2: { + switchInt(((_3 as Some).0: u32)) -> [0_u32: bb3, otherwise: bb1]; // scope 1 at $DIR/while_let_loops.rs:7:20: 7:24 + } + + bb3: { + _1 = const 1_i32; // scope 1 at $DIR/while_let_loops.rs:8:9: 8:15 + // ty::Const + // + ty: i32 + // + val: Value(Scalar(0x00000001)) + // mir::Constant + // + span: $DIR/while_let_loops.rs:8:14: 8:15 + // + literal: Const { ty: i32, val: Value(Scalar(0x00000001)) } + _0 = const (); // scope 1 at $DIR/while_let_loops.rs:9:9: 9:14 + // ty::Const + // + ty: () + // + val: Value(Scalar()) + // mir::Constant + // + span: $DIR/while_let_loops.rs:9:9: 9:14 + // + literal: Const { ty: (), val: Value(Scalar()) } + goto -> bb4; // scope 1 at $DIR/while_let_loops.rs:9:9: 9:14 + } + + bb4: { + StorageDead(_3); // scope 1 at $DIR/while_let_loops.rs:10:5: 10:6 + StorageDead(_1); // scope 0 at $DIR/while_let_loops.rs:11:1: 11:2 + return; // scope 0 at $DIR/while_let_loops.rs:11:2: 11:2 + } + } + diff --git a/src/test/mir-opt/while_let_loops.change_loop_body.ConstProp.diff.64bit b/src/test/mir-opt/while_let_loops.change_loop_body.ConstProp.diff.64bit new file mode 100644 index 0000000000000..612d44f413fe7 --- /dev/null +++ b/src/test/mir-opt/while_let_loops.change_loop_body.ConstProp.diff.64bit @@ -0,0 +1,84 @@ +- // MIR for `change_loop_body` before ConstProp ++ // MIR for `change_loop_body` after ConstProp + + fn change_loop_body() -> () { + let mut _0: (); // return place in scope 0 at $DIR/while_let_loops.rs:5:27: 5:27 + let mut _1: i32; // in scope 0 at $DIR/while_let_loops.rs:6:9: 6:15 + let mut _2: (); // in scope 0 at $DIR/while_let_loops.rs:5:1: 11:2 + let mut _3: std::option::Option; // in scope 0 at $DIR/while_let_loops.rs:7:28: 7:32 + let mut _4: isize; // in scope 0 at $DIR/while_let_loops.rs:7:15: 7:25 + let mut _5: !; // in scope 0 at $DIR/while_let_loops.rs:7:33: 10:6 + let mut _6: !; // in scope 0 at $DIR/while_let_loops.rs:7:5: 10:6 + scope 1 { + debug _x => _1; // in scope 1 at $DIR/while_let_loops.rs:6:9: 6:15 + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/while_let_loops.rs:6:9: 6:15 + _1 = const 0_i32; // scope 0 at $DIR/while_let_loops.rs:6:18: 6:19 + // ty::Const + // + ty: i32 + // + val: Value(Scalar(0x00000000)) + // mir::Constant + // + span: $DIR/while_let_loops.rs:6:18: 6:19 + // + literal: Const { ty: i32, val: Value(Scalar(0x00000000)) } + StorageLive(_3); // scope 1 at $DIR/while_let_loops.rs:7:28: 7:32 + discriminant(_3) = 0; // scope 1 at $DIR/while_let_loops.rs:7:28: 7:32 +- _4 = discriminant(_3); // scope 1 at $DIR/while_let_loops.rs:7:15: 7:25 +- switchInt(move _4) -> [1_isize: bb2, otherwise: bb1]; // scope 1 at $DIR/while_let_loops.rs:7:15: 7:25 ++ _4 = const 0_isize; // scope 1 at $DIR/while_let_loops.rs:7:15: 7:25 ++ // ty::Const ++ // + ty: isize ++ // + val: Value(Scalar(0x0000000000000000)) ++ // mir::Constant ++ // + span: $DIR/while_let_loops.rs:7:15: 7:25 ++ // + literal: Const { ty: isize, val: Value(Scalar(0x0000000000000000)) } ++ switchInt(const 0_isize) -> [1_isize: bb2, otherwise: bb1]; // scope 1 at $DIR/while_let_loops.rs:7:15: 7:25 ++ // ty::Const ++ // + ty: isize ++ // + val: Value(Scalar(0x0000000000000000)) ++ // mir::Constant ++ // + span: $DIR/while_let_loops.rs:7:15: 7:25 ++ // + literal: Const { ty: isize, val: Value(Scalar(0x0000000000000000)) } + } + + bb1: { + _0 = const (); // scope 1 at $DIR/while_let_loops.rs:7:5: 10:6 + // ty::Const + // + ty: () + // + val: Value(Scalar()) + // mir::Constant + // + span: $DIR/while_let_loops.rs:7:5: 10:6 + // + literal: Const { ty: (), val: Value(Scalar()) } + goto -> bb4; // scope 1 at $DIR/while_let_loops.rs:7:5: 10:6 + } + + bb2: { + switchInt(((_3 as Some).0: u32)) -> [0_u32: bb3, otherwise: bb1]; // scope 1 at $DIR/while_let_loops.rs:7:20: 7:24 + } + + bb3: { + _1 = const 1_i32; // scope 1 at $DIR/while_let_loops.rs:8:9: 8:15 + // ty::Const + // + ty: i32 + // + val: Value(Scalar(0x00000001)) + // mir::Constant + // + span: $DIR/while_let_loops.rs:8:14: 8:15 + // + literal: Const { ty: i32, val: Value(Scalar(0x00000001)) } + _0 = const (); // scope 1 at $DIR/while_let_loops.rs:9:9: 9:14 + // ty::Const + // + ty: () + // + val: Value(Scalar()) + // mir::Constant + // + span: $DIR/while_let_loops.rs:9:9: 9:14 + // + literal: Const { ty: (), val: Value(Scalar()) } + goto -> bb4; // scope 1 at $DIR/while_let_loops.rs:9:9: 9:14 + } + + bb4: { + StorageDead(_3); // scope 1 at $DIR/while_let_loops.rs:10:5: 10:6 + StorageDead(_1); // scope 0 at $DIR/while_let_loops.rs:11:1: 11:2 + return; // scope 0 at $DIR/while_let_loops.rs:11:2: 11:2 + } + } + diff --git a/src/test/mir-opt/while_let_loops.change_loop_body.PreCodegen.after.mir.32bit b/src/test/mir-opt/while_let_loops.change_loop_body.PreCodegen.after.mir.32bit new file mode 100644 index 0000000000000..f6fe12489199d --- /dev/null +++ b/src/test/mir-opt/while_let_loops.change_loop_body.PreCodegen.after.mir.32bit @@ -0,0 +1,33 @@ +// MIR for `change_loop_body` after PreCodegen + +fn change_loop_body() -> () { + let mut _0: (); // return place in scope 0 at $DIR/while_let_loops.rs:5:27: 5:27 + let mut _1: i32; // in scope 0 at $DIR/while_let_loops.rs:6:9: 6:15 + let mut _2: std::option::Option; // in scope 0 at $DIR/while_let_loops.rs:7:28: 7:32 + scope 1 { + debug _x => _1; // in scope 1 at $DIR/while_let_loops.rs:6:9: 6:15 + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/while_let_loops.rs:6:9: 6:15 + _1 = const 0_i32; // scope 0 at $DIR/while_let_loops.rs:6:18: 6:19 + // ty::Const + // + ty: i32 + // + val: Value(Scalar(0x00000000)) + // mir::Constant + // + span: $DIR/while_let_loops.rs:6:18: 6:19 + // + literal: Const { ty: i32, val: Value(Scalar(0x00000000)) } + StorageLive(_2); // scope 1 at $DIR/while_let_loops.rs:7:28: 7:32 + discriminant(_2) = 0; // scope 1 at $DIR/while_let_loops.rs:7:28: 7:32 + _0 = const (); // scope 1 at $DIR/while_let_loops.rs:7:5: 10:6 + // ty::Const + // + ty: () + // + val: Value(Scalar()) + // mir::Constant + // + span: $DIR/while_let_loops.rs:7:5: 10:6 + // + literal: Const { ty: (), val: Value(Scalar()) } + StorageDead(_2); // scope 1 at $DIR/while_let_loops.rs:10:5: 10:6 + StorageDead(_1); // scope 0 at $DIR/while_let_loops.rs:11:1: 11:2 + return; // scope 0 at $DIR/while_let_loops.rs:11:2: 11:2 + } +} diff --git a/src/test/mir-opt/while_let_loops.change_loop_body.PreCodegen.after.mir.64bit b/src/test/mir-opt/while_let_loops.change_loop_body.PreCodegen.after.mir.64bit new file mode 100644 index 0000000000000..f6fe12489199d --- /dev/null +++ b/src/test/mir-opt/while_let_loops.change_loop_body.PreCodegen.after.mir.64bit @@ -0,0 +1,33 @@ +// MIR for `change_loop_body` after PreCodegen + +fn change_loop_body() -> () { + let mut _0: (); // return place in scope 0 at $DIR/while_let_loops.rs:5:27: 5:27 + let mut _1: i32; // in scope 0 at $DIR/while_let_loops.rs:6:9: 6:15 + let mut _2: std::option::Option; // in scope 0 at $DIR/while_let_loops.rs:7:28: 7:32 + scope 1 { + debug _x => _1; // in scope 1 at $DIR/while_let_loops.rs:6:9: 6:15 + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/while_let_loops.rs:6:9: 6:15 + _1 = const 0_i32; // scope 0 at $DIR/while_let_loops.rs:6:18: 6:19 + // ty::Const + // + ty: i32 + // + val: Value(Scalar(0x00000000)) + // mir::Constant + // + span: $DIR/while_let_loops.rs:6:18: 6:19 + // + literal: Const { ty: i32, val: Value(Scalar(0x00000000)) } + StorageLive(_2); // scope 1 at $DIR/while_let_loops.rs:7:28: 7:32 + discriminant(_2) = 0; // scope 1 at $DIR/while_let_loops.rs:7:28: 7:32 + _0 = const (); // scope 1 at $DIR/while_let_loops.rs:7:5: 10:6 + // ty::Const + // + ty: () + // + val: Value(Scalar()) + // mir::Constant + // + span: $DIR/while_let_loops.rs:7:5: 10:6 + // + literal: Const { ty: (), val: Value(Scalar()) } + StorageDead(_2); // scope 1 at $DIR/while_let_loops.rs:10:5: 10:6 + StorageDead(_1); // scope 0 at $DIR/while_let_loops.rs:11:1: 11:2 + return; // scope 0 at $DIR/while_let_loops.rs:11:2: 11:2 + } +} diff --git a/src/test/mir-opt/while_let_loops.rs b/src/test/mir-opt/while_let_loops.rs new file mode 100644 index 0000000000000..f320a218c852c --- /dev/null +++ b/src/test/mir-opt/while_let_loops.rs @@ -0,0 +1,15 @@ +// EMIT_MIR while_let_loops.change_loop_body.ConstProp.diff +// EMIT_MIR while_let_loops.change_loop_body.PreCodegen.after.mir +// EMIT_MIR_FOR_EACH_BIT_WIDTH + +pub fn change_loop_body() { + let mut _x = 0; + while let Some(0u32) = None { + _x = 1; + break; + } +} + +fn main() { + change_loop_body(); +} From 34e6f06cc81c49b05eea21e2e9f35df68acf37f2 Mon Sep 17 00:00:00 2001 From: Matthew Y <32047956+5M1Sec@users.noreply.github.com> Date: Tue, 11 Aug 2020 16:59:45 -0400 Subject: [PATCH 54/54] parent d19541e216c88548650f694624fd40f75c067c83 author Matthew Y <32047956+5M1Sec@users.noreply.github.com> 1597179585 -0400 committer 5M1Sec <32047956+5M1Sec@users.noreply.github.com> 1597541078 -0400 Allowing raw ptr dereference in const fn Change ``UnsafetyViolationKind::General` to `UnsafetyViolationKind::GeneralAndConstFn` in check_unsafety.rs Bless min_const_fn Add test case from issue 75340 into a new file --- src/librustc_mir/transform/check_unsafety.rs | 2 +- .../consts/min_const_fn/const_fn_raw_ptr_deref.rs | 10 ++++++++++ .../consts/min_const_fn/min_const_fn_unsafe_bad.rs | 2 +- .../min_const_fn/min_const_fn_unsafe_bad.stderr | 14 +++----------- .../consts/min_const_fn/min_const_fn_unsafe_ok.rs | 1 - 5 files changed, 15 insertions(+), 14 deletions(-) create mode 100644 src/test/ui/consts/min_const_fn/const_fn_raw_ptr_deref.rs diff --git a/src/librustc_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs index 9c06e173bcd57..e492b707f1756 100644 --- a/src/librustc_mir/transform/check_unsafety.rs +++ b/src/librustc_mir/transform/check_unsafety.rs @@ -228,7 +228,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { let base_ty = Place::ty_from(place.local, proj_base, self.body, self.tcx).ty; match base_ty.kind { ty::RawPtr(..) => self.require_unsafe( - UnsafetyViolationKind::General, + UnsafetyViolationKind::GeneralAndConstFn, UnsafetyViolationDetails::DerefOfRawPointer, ), ty::Adt(adt, _) => { diff --git a/src/test/ui/consts/min_const_fn/const_fn_raw_ptr_deref.rs b/src/test/ui/consts/min_const_fn/const_fn_raw_ptr_deref.rs new file mode 100644 index 0000000000000..9aec348965fad --- /dev/null +++ b/src/test/ui/consts/min_const_fn/const_fn_raw_ptr_deref.rs @@ -0,0 +1,10 @@ +// check-pass +#![feature(const_raw_ptr_deref)] +#![feature(raw_ref_macros)] +use std::ptr; + +const fn test_fn(x: *const i32) { + let x2 = unsafe { ptr::raw_const!(*x) }; +} + +fn main() {} diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_unsafe_bad.rs b/src/test/ui/consts/min_const_fn/min_const_fn_unsafe_bad.rs index 0b1ab1c34ff2f..6462d736ad194 100644 --- a/src/test/ui/consts/min_const_fn/min_const_fn_unsafe_bad.rs +++ b/src/test/ui/consts/min_const_fn/min_const_fn_unsafe_bad.rs @@ -1,4 +1,4 @@ -const fn bad_const_fn_deref_raw(x: *mut usize) -> &'static usize { unsafe { &*x } } //~ is unsafe +const fn bad_const_fn_deref_raw(x: *mut usize) -> &'static usize { unsafe { &*x } } //~^ dereferencing raw pointers in constant functions const unsafe fn bad_const_unsafe_deref_raw(x: *mut usize) -> usize { *x } diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_unsafe_bad.stderr b/src/test/ui/consts/min_const_fn/min_const_fn_unsafe_bad.stderr index 97b0a778d2c72..427ecff5c6d1a 100644 --- a/src/test/ui/consts/min_const_fn/min_const_fn_unsafe_bad.stderr +++ b/src/test/ui/consts/min_const_fn/min_const_fn_unsafe_bad.stderr @@ -34,15 +34,7 @@ LL | Foo { x: () }.y = note: see issue #57563 for more information = help: add `#![feature(const_fn)]` to the crate attributes to enable -error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block - --> $DIR/min_const_fn_unsafe_bad.rs:1:77 - | -LL | const fn bad_const_fn_deref_raw(x: *mut usize) -> &'static usize { unsafe { &*x } } - | ^^^ dereference of raw pointer - | - = note: raw pointers may be NULL, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior - -error: aborting due to 5 previous errors +error: aborting due to 4 previous errors -Some errors have detailed explanations: E0133, E0658, E0723. -For more information about an error, try `rustc --explain E0133`. +Some errors have detailed explanations: E0658, E0723. +For more information about an error, try `rustc --explain E0658`. diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_unsafe_ok.rs b/src/test/ui/consts/min_const_fn/min_const_fn_unsafe_ok.rs index 02c7970deca64..6fa95e20e789c 100644 --- a/src/test/ui/consts/min_const_fn/min_const_fn_unsafe_ok.rs +++ b/src/test/ui/consts/min_const_fn/min_const_fn_unsafe_ok.rs @@ -1,5 +1,4 @@ // check-pass - const unsafe fn ret_i32_no_unsafe() -> i32 { 42 } const unsafe fn ret_null_ptr_no_unsafe() -> *const T { std::ptr::null() } const unsafe fn ret_null_mut_ptr_no_unsafe() -> *mut T { std::ptr::null_mut() }