diff --git a/Cargo.lock b/Cargo.lock index fd65ed8d4a2d6..152689953b8a9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -154,7 +154,7 @@ version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" dependencies = [ - "hermit-abi", + "hermit-abi 0.1.19", "libc", "winapi", ] @@ -1610,6 +1610,15 @@ name = "hermit-abi" version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + +[[package]] +name = "hermit-abi" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ab7905ea95c6d9af62940f9d7dd9596d54c334ae2c15300c482051292d5637f" dependencies = [ "compiler_builtins", "libc", @@ -2396,7 +2405,7 @@ version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" dependencies = [ - "hermit-abi", + "hermit-abi 0.1.19", "libc", ] @@ -4782,7 +4791,7 @@ dependencies = [ "dlmalloc", "fortanix-sgx-abi", "hashbrown 0.12.0", - "hermit-abi", + "hermit-abi 0.2.0", "libc", "miniz_oxide", "object 0.26.2", diff --git a/RELEASES.md b/RELEASES.md index a9422fa103ed8..96da1660c0feb 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1,3 +1,168 @@ +Version 1.59.0 (2022-02-24) +========================== + +Language +-------- + +- [Stabilize default arguments for const generics][90207] +- [Stabilize destructuring assignment][90521] +- [Relax private in public lint on generic bounds and where clauses of trait impls][90586] +- [Stabilize asm! and global_asm! for x86, x86_64, ARM, Aarch64, and RISC-V][91728] + +Compiler +-------- + +- [Stabilize new symbol mangling format, leaving it opt-in (-Csymbol-mangling-version=v0)][90128] +- [Emit LLVM optimization remarks when enabled with `-Cremark`][90833] +- [Fix sparc64 ABI for aggregates with floating point members][91003] +- [Warn when a `#[test]`-like built-in attribute macro is present multiple times.][91172] +- [Add support for riscv64gc-unknown-freebsd][91284] +- [Stabilize `-Z emit-future-incompat` as `--json future-incompat`][91535] + +Libraries +--------- + +- [Remove unnecessary bounds for some Hash{Map,Set} methods][91593] + +Stabilized APIs +--------------- + +- [`std::thread::available_parallelism`][available_parallelism] +- [`Result::copied`][result-copied] +- [`Result::cloned`][result-cloned] +- [`arch::asm!`][asm] +- [`arch::global_asm!`][global_asm] +- [`ops::ControlFlow::is_break`][is_break] +- [`ops::ControlFlow::is_continue`][is_continue] +- [`TryFrom for u8`][try_from_char_u8] +- [`char::TryFromCharError`][try_from_char_err] + implementing `Clone`, `Debug`, `Display`, `PartialEq`, `Copy`, `Eq`, `Error` +- [`iter::zip`][zip] +- [`NonZeroU8::is_power_of_two`][is_power_of_two8] +- [`NonZeroU16::is_power_of_two`][is_power_of_two16] +- [`NonZeroU32::is_power_of_two`][is_power_of_two32] +- [`NonZeroU64::is_power_of_two`][is_power_of_two64] +- [`NonZeroU128::is_power_of_two`][is_power_of_two128] +- [`DoubleEndedIterator for ToLowercase`][lowercase] +- [`DoubleEndedIterator for ToUppercase`][uppercase] +- [`TryFrom<&mut [T]> for [T; N]`][tryfrom_ref_arr] +- [`UnwindSafe for Once`][unwindsafe_once] +- [`RefUnwindSafe for Once`][refunwindsafe_once] +- [armv8 neon intrinsics for aarch64][stdarch/1266] + +Const-stable: + +- [`mem::MaybeUninit::as_ptr`][muninit_ptr] +- [`mem::MaybeUninit::assume_init`][muninit_init] +- [`mem::MaybeUninit::assume_init_ref`][muninit_init_ref] +- [`ffi::CStr::from_bytes_with_nul_unchecked`][cstr_from_bytes] + +Cargo +----- + +- [Stabilize the `strip` profile option][cargo/10088] +- [Stabilize future-incompat-report][cargo/10165] +- [Support abbreviating `--release` as `-r`][cargo/10133] +- [Support `term.quiet` configuration][cargo/10152] +- [Remove `--host` from cargo {publish,search,login}][cargo/10145] + +Compatibility Notes +------------------- + +- [Refactor weak symbols in std::sys::unix][90846] + This may add new, versioned, symbols when building with a newer glibc, as the + standard library uses weak linkage rather than dynamically attempting to load + certain symbols at runtime. +- [Deprecate crate_type and crate_name nested inside `#![cfg_attr]`][83744] + This adds a future compatibility lint to supporting the use of cfg_attr + wrapping either crate_type or crate_name specification within Rust files; + it is recommended that users migrate to setting the equivalent command line + flags. +- [Remove effect of `#[no_link]` attribute on name resolution][92034] + This may expose new names, leading to conflicts with preexisting names in a + given namespace and a compilation failure. +- [Cargo will document libraries before binaries.][cargo/10172] +- [Respect doc=false in dependencies, not just the root crate][cargo/10201] +- [Weaken guarantee around advancing underlying iterators in zip][83791] +- [Make split_inclusive() on an empty slice yield an empty output][89825] +- [Update std::env::temp_dir to use GetTempPath2 on Windows when available.][89999] + +Internal Changes +---------------- + +These changes provide no direct user facing benefits, but represent significant +improvements to the internals and overall performance of rustc +and related tools. + +- [Fix many cases of normalization-related ICEs][91255] +- [Replace dominators algorithm with simple Lengauer-Tarjan][85013] +- [Store liveness in interval sets for region inference][90637] + +- [Remove `in_band_lifetimes` from the compiler and standard library, in preparation for removing this + unstable feature.][91867] + +[91867]: https://github.com/rust-lang/rust/issues/91867 +[83744]: https://github.com/rust-lang/rust/pull/83744/ +[83791]: https://github.com/rust-lang/rust/pull/83791/ +[85013]: https://github.com/rust-lang/rust/pull/85013/ +[89825]: https://github.com/rust-lang/rust/pull/89825/ +[89999]: https://github.com/rust-lang/rust/pull/89999/ +[90128]: https://github.com/rust-lang/rust/pull/90128/ +[90207]: https://github.com/rust-lang/rust/pull/90207/ +[90521]: https://github.com/rust-lang/rust/pull/90521/ +[90586]: https://github.com/rust-lang/rust/pull/90586/ +[90637]: https://github.com/rust-lang/rust/pull/90637/ +[90833]: https://github.com/rust-lang/rust/pull/90833/ +[90846]: https://github.com/rust-lang/rust/pull/90846/ +[91003]: https://github.com/rust-lang/rust/pull/91003/ +[91172]: https://github.com/rust-lang/rust/pull/91172/ +[91255]: https://github.com/rust-lang/rust/pull/91255/ +[91284]: https://github.com/rust-lang/rust/pull/91284/ +[91535]: https://github.com/rust-lang/rust/pull/91535/ +[91593]: https://github.com/rust-lang/rust/pull/91593/ +[91728]: https://github.com/rust-lang/rust/pull/91728/ +[91878]: https://github.com/rust-lang/rust/pull/91878/ +[91896]: https://github.com/rust-lang/rust/pull/91896/ +[91926]: https://github.com/rust-lang/rust/pull/91926/ +[91984]: https://github.com/rust-lang/rust/pull/91984/ +[92020]: https://github.com/rust-lang/rust/pull/92020/ +[92034]: https://github.com/rust-lang/rust/pull/92034/ +[92483]: https://github.com/rust-lang/rust/pull/92483/ +[cargo/10088]: https://github.com/rust-lang/cargo/pull/10088/ +[cargo/10133]: https://github.com/rust-lang/cargo/pull/10133/ +[cargo/10145]: https://github.com/rust-lang/cargo/pull/10145/ +[cargo/10152]: https://github.com/rust-lang/cargo/pull/10152/ +[cargo/10165]: https://github.com/rust-lang/cargo/pull/10165/ +[cargo/10172]: https://github.com/rust-lang/cargo/pull/10172/ +[cargo/10201]: https://github.com/rust-lang/cargo/pull/10201/ +[cargo/10269]: https://github.com/rust-lang/cargo/pull/10269/ + +[cstr_from_bytes]: https://doc.rust-lang.org/stable/std/ffi/struct.CStr.html#method.from_bytes_with_nul_unchecked +[muninit_ptr]: https://doc.rust-lang.org/stable/std/mem/union.MaybeUninit.html#method.as_ptr +[muninit_init]: https://doc.rust-lang.org/stable/std/mem/union.MaybeUninit.html#method.assume_init +[muninit_init_ref]: https://doc.rust-lang.org/stable/std/mem/union.MaybeUninit.html#method.assume_init_ref +[unwindsafe_once]: https://doc.rust-lang.org/stable/std/sync/struct.Once.html#impl-UnwindSafe +[refunwindsafe_once]: https://doc.rust-lang.org/stable/std/sync/struct.Once.html#impl-RefUnwindSafe +[tryfrom_ref_arr]: https://doc.rust-lang.org/stable/std/convert/trait.TryFrom.html#impl-TryFrom%3C%26%27_%20mut%20%5BT%5D%3E +[lowercase]: https://doc.rust-lang.org/stable/std/char/struct.ToLowercase.html#impl-DoubleEndedIterator +[uppercase]: https://doc.rust-lang.org/stable/std/char/struct.ToUppercase.html#impl-DoubleEndedIterator +[try_from_char_err]: https://doc.rust-lang.org/stable/std/char/struct.TryFromCharError.html +[available_parallelism]: https://doc.rust-lang.org/stable/std/thread/fn.available_parallelism.html +[result-copied]: https://doc.rust-lang.org/stable/std/result/enum.Result.html#method.copied +[result-cloned]: https://doc.rust-lang.org/stable/std/result/enum.Result.html#method.cloned +[asm]: https://doc.rust-lang.org/stable/core/arch/macro.asm.html +[global_asm]: https://doc.rust-lang.org/stable/core/arch/macro.global_asm.html +[is_break]: https://doc.rust-lang.org/stable/std/ops/enum.ControlFlow.html#method.is_break +[is_continue]: https://doc.rust-lang.org/stable/std/ops/enum.ControlFlow.html#method.is_continue +[try_from_char_u8]: https://doc.rust-lang.org/stable/std/primitive.char.html#impl-TryFrom%3Cchar%3E +[zip]: https://doc.rust-lang.org/stable/std/iter/fn.zip.html +[is_power_of_two8]: https://doc.rust-lang.org/stable/core/num/struct.NonZeroU8.html#method.is_power_of_two +[is_power_of_two16]: https://doc.rust-lang.org/stable/core/num/struct.NonZeroU16.html#method.is_power_of_two +[is_power_of_two32]: https://doc.rust-lang.org/stable/core/num/struct.NonZeroU32.html#method.is_power_of_two +[is_power_of_two64]: https://doc.rust-lang.org/stable/core/num/struct.NonZeroU64.html#method.is_power_of_two +[is_power_of_two128]: https://doc.rust-lang.org/stable/core/num/struct.NonZeroU128.html#method.is_power_of_two +[stdarch/1266]: https://github.com/rust-lang/stdarch/pull/1266 + Version 1.58.1 (2022-01-19) =========================== diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs index 18fcc99ffbaa0..0211d7b336736 100644 --- a/compiler/rustc_ast_lowering/src/asm.rs +++ b/compiler/rustc_ast_lowering/src/asm.rs @@ -339,9 +339,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let idx2 = *o.get(); let &(ref op2, op_sp2) = &operands[idx2]; - let reg2 = match op2.reg() { - Some(asm::InlineAsmRegOrRegClass::Reg(r)) => r, - _ => unreachable!(), + let Some(asm::InlineAsmRegOrRegClass::Reg(reg2)) = op2.reg() else { + unreachable!(); }; let msg = format!( diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index d48ff10b97d91..d64f1a05712a9 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -330,9 +330,8 @@ impl<'hir> LoweringContext<'_, 'hir> { args: Vec>, legacy_args_idx: &[usize], ) -> hir::ExprKind<'hir> { - let path = match f.kind { - ExprKind::Path(None, ref mut path) => path, - _ => unreachable!(), + let ExprKind::Path(None, ref mut path) = f.kind else { + unreachable!(); }; // Split the arguments into const generics and normal arguments diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 6489c729cfe50..e230b2dd49f73 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -1376,9 +1376,8 @@ impl<'hir> LoweringContext<'_, 'hir> { // keep track of the Span info. Now, `add_implicitly_sized` in `AstConv` checks both param bounds and // where clauses for `?Sized`. for pred in &generics.where_clause.predicates { - let bound_pred = match *pred { - WherePredicate::BoundPredicate(ref bound_pred) => bound_pred, - _ => continue, + let WherePredicate::BoundPredicate(ref bound_pred) = *pred else { + continue; }; let compute_is_param = || { // Check if the where clause type is a plain type parameter. diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index eb7c75cac0520..20caed1b230d5 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -482,9 +482,8 @@ impl<'a> AstValidator<'a> { } fn check_foreign_kind_bodyless(&self, ident: Ident, kind: &str, body: Option) { - let body = match body { - None => return, - Some(body) => body, + let Some(body) = body else { + return; }; self.err_handler() .struct_span_err(ident.span, &format!("incorrect `{}` inside `extern` block", kind)) @@ -504,9 +503,8 @@ impl<'a> AstValidator<'a> { /// An `fn` in `extern { ... }` cannot have a body `{ ... }`. fn check_foreign_fn_bodyless(&self, ident: Ident, body: Option<&Block>) { - let body = match body { - None => return, - Some(body) => body, + let Some(body) = body else { + return; }; self.err_handler() .struct_span_err(ident.span, "incorrect function inside `extern` block") diff --git a/compiler/rustc_ast_passes/src/show_span.rs b/compiler/rustc_ast_passes/src/show_span.rs index 6cef26a13e6b0..27637e311f48d 100644 --- a/compiler/rustc_ast_passes/src/show_span.rs +++ b/compiler/rustc_ast_passes/src/show_span.rs @@ -57,9 +57,8 @@ impl<'a> Visitor<'a> for ShowSpanVisitor<'a> { } pub fn run(span_diagnostic: &rustc_errors::Handler, mode: &str, krate: &ast::Crate) { - let mode = match mode.parse().ok() { - Some(mode) => mode, - None => return, + let Ok(mode) = mode.parse() else { + return; }; let mut v = ShowSpanVisitor { span_diagnostic, mode }; visit::walk_crate(&mut v, krate); diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs index 49043e9f5f9d6..8d6c8c247851e 100644 --- a/compiler/rustc_attr/src/builtin.rs +++ b/compiler/rustc_attr/src/builtin.rs @@ -556,17 +556,14 @@ pub fn eval_condition( return false; } }; - let min_version = match parse_version(min_version.as_str(), false) { - Some(ver) => ver, - None => { - sess.span_diagnostic - .struct_span_warn( - *span, - "unknown version literal format, assuming it refers to a future version", - ) - .emit(); - return false; - } + let Some(min_version) = parse_version(min_version.as_str(), false) else { + sess.span_diagnostic + .struct_span_warn( + *span, + "unknown version literal format, assuming it refers to a future version", + ) + .emit(); + return false; }; let rustc_version = parse_version(env!("CFG_RELEASE"), true).unwrap(); @@ -669,9 +666,8 @@ where break; } - let meta = match attr.meta() { - Some(meta) => meta, - None => continue, + let Some(meta) = attr.meta() else { + continue; }; let mut since = None; let mut note = None; diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index fce5ed0ef4239..baa59efbf8df2 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -2071,11 +2071,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { ) = rvalue { for operand in operands { - let assigned_from = match operand { - Operand::Copy(assigned_from) | Operand::Move(assigned_from) => { - assigned_from - } - _ => continue, + let (Operand::Copy(assigned_from) | Operand::Move(assigned_from)) = operand else { + continue; }; debug!( "annotate_argument_and_return_for_borrow: assigned_from={:?}", @@ -2083,10 +2080,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { ); // Find the local from the operand. - let assigned_from_local = match assigned_from.local_or_deref_local() - { - Some(local) => local, - None => continue, + let Some(assigned_from_local) = assigned_from.local_or_deref_local() else { + continue; }; if assigned_from_local != target { @@ -2138,10 +2133,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { ); // Find the local from the rvalue. - let assigned_from_local = match assigned_from.local_or_deref_local() { - Some(local) => local, - None => continue, - }; + let Some(assigned_from_local) = assigned_from.local_or_deref_local() else { continue }; debug!( "annotate_argument_and_return_for_borrow: \ assigned_from_local={:?}", @@ -2189,11 +2181,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { assigned_to, args ); for operand in args { - let assigned_from = match operand { - Operand::Copy(assigned_from) | Operand::Move(assigned_from) => { - assigned_from - } - _ => continue, + let (Operand::Copy(assigned_from) | Operand::Move(assigned_from)) = operand else { + continue; }; debug!( "annotate_argument_and_return_for_borrow: assigned_from={:?}", @@ -2309,7 +2298,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // Closure arguments are wrapped in a tuple, so we need to get the first // from that. if let ty::Tuple(elems) = argument_ty.kind() { - let argument_ty = elems.first()?.expect_ty(); + let &argument_ty = elems.first()?; if let ty::Ref(_, _, _) = argument_ty.kind() { return Some(AnnotatedBorrowFnSignature::Closure { argument_ty, diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs index db8268c8e2e89..b1e5a211cf1cb 100644 --- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs +++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs @@ -650,13 +650,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // The only kind of statement that we care about is assignments... if let StatementKind::Assign(box (place, rvalue)) = &stmt.kind { - let into = match place.local_or_deref_local() { - Some(into) => into, - None => { - // Continue at the next location. - queue.push(current_location.successor_within_block()); - continue; - } + let Some(into) = place.local_or_deref_local() else { + // Continue at the next location. + queue.push(current_location.successor_within_block()); + continue; }; match rvalue { diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs index 73b0d39828504..5f533ddcb82ba 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -444,10 +444,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { debug!("borrowed_content_source: init={:?}", init); // We're only interested in statements that initialized a value, not the // initializations from arguments. - let loc = match init.location { - InitLocation::Statement(stmt) => stmt, - _ => continue, - }; + let InitLocation::Statement(loc) = init.location else { continue }; let bbd = &self.body[loc.block]; let is_terminator = bbd.statements.len() == loc.statement_index; @@ -787,9 +784,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { ) -> UseSpans<'tcx> { use self::UseSpans::*; - let stmt = match self.body[location.block].statements.get(location.statement_index) { - Some(stmt) => stmt, - None => return OtherUse(self.body.source_info(location).span), + let Some(stmt) = self.body[location.block].statements.get(location.statement_index) else { + return OtherUse(self.body.source_info(location).span); }; debug!("move_spans: moved_place={:?} location={:?} stmt={:?}", moved_place, location, stmt); diff --git a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs index cc6566882ad5d..d4f238ff71f25 100644 --- a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs @@ -188,10 +188,9 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { } // Error with the pattern LookupResult::Exact(_) => { - let mpi = match self.move_data.rev_lookup.find(move_from.as_ref()) { - LookupResult::Parent(Some(mpi)) => mpi, + let LookupResult::Parent(Some(mpi)) = self.move_data.rev_lookup.find(move_from.as_ref()) else { // move_from should be a projection from match_place. - _ => unreachable!("Probably not unreachable..."), + unreachable!("Probably not unreachable..."); }; for ge in &mut *grouped_errors { if let GroupedMoveError::MovesFromValue { diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index ca1e77ff8fdc0..e6a323d676e14 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -5,6 +5,7 @@ use rustc_infer::infer::{ error_reporting::nice_region_error::NiceRegionError, error_reporting::unexpected_hidden_region_diagnostic, NllRegionVariableOrigin, }; +use rustc_middle::hir::place::PlaceBase; use rustc_middle::mir::{ConstraintCategory, ReturnConstraint}; use rustc_middle::ty::subst::{InternalSubsts, Subst}; use rustc_middle::ty::{self, RegionVid, Ty}; @@ -421,17 +422,26 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { diag.span_label(*span, message); - // FIXME(project-rfc-2229#48): This should store a captured_place not a hir id - if let ReturnConstraint::ClosureUpvar(upvar) = kind { + if let ReturnConstraint::ClosureUpvar(upvar_field) = kind { let def_id = match self.regioncx.universal_regions().defining_ty { DefiningTy::Closure(def_id, _) => def_id, ty => bug!("unexpected DefiningTy {:?}", ty), }; - let upvar_def_span = self.infcx.tcx.hir().span(upvar); - let upvar_span = self.infcx.tcx.upvars_mentioned(def_id).unwrap()[&upvar].span; - diag.span_label(upvar_def_span, "variable defined here"); - diag.span_label(upvar_span, "variable captured here"); + let captured_place = &self.upvars[upvar_field.index()].place; + let defined_hir = match captured_place.place.base { + PlaceBase::Local(hirid) => Some(hirid), + PlaceBase::Upvar(upvar) => Some(upvar.var_path.hir_id), + _ => None, + }; + + if defined_hir.is_some() { + let upvars_map = self.infcx.tcx.upvars_mentioned(def_id).unwrap(); + let upvar_def_span = self.infcx.tcx.hir().span(defined_hir.unwrap()); + let upvar_span = upvars_map.get(&defined_hir.unwrap()).unwrap().span; + diag.span_label(upvar_def_span, "variable defined here"); + diag.span_label(upvar_span, "variable captured here"); + } } if let Some(fr_span) = self.give_region_a_name(*outlived_fr).unwrap().span() { diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs index 3bcc9f7be384f..5d1d291d3b433 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs @@ -480,7 +480,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { let search_stack: &mut Vec<(Ty<'tcx>, &hir::Ty<'_>)> = &mut vec![(ty, hir_ty)]; while let Some((ty, hir_ty)) = search_stack.pop() { - match (&ty.kind(), &hir_ty.kind) { + match (ty.kind(), &hir_ty.kind) { // Check if the `ty` is `&'X ..` where `'X` // is the region we are looking for -- if so, and we have a `&T` // on the RHS, then we want to highlight the `&` like so: @@ -532,9 +532,8 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { // The following cases don't have lifetimes, so we // just worry about trying to match up the rustc type // with the HIR types: - (ty::Tuple(elem_tys), hir::TyKind::Tup(elem_hir_tys)) => { - search_stack - .extend(iter::zip(elem_tys.iter().map(|k| k.expect_ty()), *elem_hir_tys)); + (&ty::Tuple(elem_tys), hir::TyKind::Tup(elem_hir_tys)) => { + search_stack.extend(iter::zip(elem_tys, *elem_hir_tys)); } (ty::Slice(elem_ty), hir::TyKind::Slice(elem_hir_ty)) diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 459b03b0fad65..719862e67c873 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -1914,10 +1914,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // without going over a Deref. let mut shortest_uninit_seen = None; for prefix in this.prefixes(base, PrefixSet::Shallow) { - let mpi = match this.move_path_for_place(prefix) { - Some(mpi) => mpi, - None => continue, - }; + let Some(mpi) = this.move_path_for_place(prefix) else { continue }; if maybe_uninits.contains(mpi) { debug!( diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index abd6a15334c90..b99fb00599e7f 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -913,9 +913,8 @@ impl<'tcx> RegionInferenceContext<'tcx> { let TypeTest { generic_kind, lower_bound, locations, verify_bound: _ } = type_test; let generic_ty = generic_kind.to_ty(tcx); - let subject = match self.try_promote_type_test_subject(infcx, generic_ty) { - Some(s) => s, - None => return false, + let Some(subject) = self.try_promote_type_test_subject(infcx, generic_ty) else { + return false; }; // For each region outlived by lower_bound find a non-local, @@ -1623,15 +1622,14 @@ impl<'tcx> RegionInferenceContext<'tcx> { // If we have some bound universal region `'a`, then the only // elements it can contain is itself -- we don't know anything // else about it! - let error_element = match { + let Some(error_element) = ({ self.scc_values.elements_contained_in(longer_fr_scc).find(|element| match element { RegionElement::Location(_) => true, RegionElement::RootUniversalRegion(_) => true, RegionElement::PlaceholderRegion(placeholder1) => placeholder != *placeholder1, }) - } { - Some(v) => v, - None => return, + }) else { + return; }; debug!("check_bound_universal_region: error_element = {:?}", error_element); diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 46924f50d2e1b..b87a9e6567bbb 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -810,13 +810,12 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { ty::Adt(adt_def, substs) => (&adt_def.variants[variant_index], substs), ty::Generator(def_id, substs, _) => { let mut variants = substs.as_generator().state_tys(def_id, tcx); - let mut variant = match variants.nth(variant_index.into()) { - Some(v) => v, - None => bug!( + let Some(mut variant) = variants.nth(variant_index.into()) else { + bug!( "variant_index of generator out of range: {:?}/{:?}", variant_index, substs.as_generator().state_tys(def_id, tcx).count() - ), + ); }; return match variant.nth(field.index()) { Some(ty) => Ok(ty), @@ -833,9 +832,10 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { return match substs .as_closure() .tupled_upvars_ty() - .tuple_element_ty(field.index()) + .tuple_fields() + .get(field.index()) { - Some(ty) => Ok(ty), + Some(&ty) => Ok(ty), None => Err(FieldAccessError::OutOfRange { field_count: substs.as_closure().upvar_tys().count(), }), @@ -853,7 +853,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { } ty::Tuple(tys) => { return match tys.get(field.index()) { - Some(&ty) => Ok(ty.expect_ty()), + Some(&ty) => Ok(ty), None => Err(FieldAccessError::OutOfRange { field_count: tys.len() }), }; } @@ -2178,35 +2178,29 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } CastKind::Pointer(PointerCast::MutToConstPointer) => { - let ty_from = match op.ty(body, tcx).kind() { - ty::RawPtr(ty::TypeAndMut { - ty: ty_from, - mutbl: hir::Mutability::Mut, - }) => ty_from, - _ => { - span_mirbug!( - self, - rvalue, - "unexpected base type for cast {:?}", - ty, - ); - return; - } + let ty::RawPtr(ty::TypeAndMut { + ty: ty_from, + mutbl: hir::Mutability::Mut, + }) = op.ty(body, tcx).kind() else { + span_mirbug!( + self, + rvalue, + "unexpected base type for cast {:?}", + ty, + ); + return; }; - let ty_to = match ty.kind() { - ty::RawPtr(ty::TypeAndMut { - ty: ty_to, - mutbl: hir::Mutability::Not, - }) => ty_to, - _ => { - span_mirbug!( - self, - rvalue, - "unexpected target type for cast {:?}", - ty, - ); - return; - } + let ty::RawPtr(ty::TypeAndMut { + ty: ty_to, + mutbl: hir::Mutability::Not, + }) = ty.kind() else { + span_mirbug!( + self, + rvalue, + "unexpected target type for cast {:?}", + ty, + ); + return; }; if let Err(terr) = self.sub_types( *ty_from, @@ -2238,17 +2232,14 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { _ => None, }; - let (ty_elem, ty_mut) = match opt_ty_elem_mut { - Some(ty_elem_mut) => ty_elem_mut, - None => { - span_mirbug!( - self, - rvalue, - "ArrayToPointer cast from unexpected type {:?}", - ty_from, - ); - return; - } + let Some((ty_elem, ty_mut)) = opt_ty_elem_mut else { + span_mirbug!( + self, + rvalue, + "ArrayToPointer cast from unexpected type {:?}", + ty_from, + ); + return; }; let (ty_to, ty_to_mut) = match ty.kind() { @@ -2530,9 +2521,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { body, ); let category = if let Some(field) = field { - let var_hir_id = self.borrowck_context.upvars[field.index()].place.get_root_variable(); - // FIXME(project-rfc-2229#8): Use Place for better diagnostics - ConstraintCategory::ClosureUpvar(var_hir_id) + ConstraintCategory::ClosureUpvar(field) } else { ConstraintCategory::Boring }; diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs index 72de3805467dc..d21a9d86e5b8b 100644 --- a/compiler/rustc_borrowck/src/universal_regions.rs +++ b/compiler/rustc_borrowck/src/universal_regions.rs @@ -641,16 +641,13 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { let (&output, tuplized_inputs) = inputs_and_output.skip_binder().split_last().unwrap(); assert_eq!(tuplized_inputs.len(), 1, "multiple closure inputs"); - let inputs = match tuplized_inputs[0].kind() { - ty::Tuple(inputs) => inputs, - _ => bug!("closure inputs not a tuple: {:?}", tuplized_inputs[0]), + let &ty::Tuple(inputs) = tuplized_inputs[0].kind() else { + bug!("closure inputs not a tuple: {:?}", tuplized_inputs[0]); }; ty::Binder::bind_with_vars( tcx.mk_type_list( - iter::once(closure_ty) - .chain(inputs.iter().map(|k| k.expect_ty())) - .chain(iter::once(output)), + iter::once(closure_ty).chain(inputs).chain(iter::once(output)), ), bound_vars, ) diff --git a/compiler/rustc_builtin_macros/src/cfg_accessible.rs b/compiler/rustc_builtin_macros/src/cfg_accessible.rs index 09ed1af345675..7b7db3eaea613 100644 --- a/compiler/rustc_builtin_macros/src/cfg_accessible.rs +++ b/compiler/rustc_builtin_macros/src/cfg_accessible.rs @@ -44,9 +44,8 @@ impl MultiItemModifier for Expander { template, ); - let path = match validate_input(ecx, meta_item) { - Some(path) => path, - None => return ExpandResult::Ready(Vec::new()), + let Some(path) = validate_input(ecx, meta_item) else { + return ExpandResult::Ready(Vec::new()); }; match ecx.resolver.cfg_accessible(ecx.current_expansion.id, path) { diff --git a/compiler/rustc_builtin_macros/src/compile_error.rs b/compiler/rustc_builtin_macros/src/compile_error.rs index f5955604e5fb2..990b88295690c 100644 --- a/compiler/rustc_builtin_macros/src/compile_error.rs +++ b/compiler/rustc_builtin_macros/src/compile_error.rs @@ -9,9 +9,8 @@ pub fn expand_compile_error<'cx>( sp: Span, tts: TokenStream, ) -> Box { - let var = match get_single_str_from_tts(cx, sp, tts, "compile_error!") { - None => return DummyResult::any(sp), - Some(v) => v, + let Some(var) = get_single_str_from_tts(cx, sp, tts, "compile_error!") else { + return DummyResult::any(sp); }; cx.span_err(sp, &var); diff --git a/compiler/rustc_builtin_macros/src/concat.rs b/compiler/rustc_builtin_macros/src/concat.rs index 59361510a672e..a23dd1d1213b7 100644 --- a/compiler/rustc_builtin_macros/src/concat.rs +++ b/compiler/rustc_builtin_macros/src/concat.rs @@ -10,9 +10,8 @@ pub fn expand_concat( sp: rustc_span::Span, tts: TokenStream, ) -> Box { - let es = match base::get_exprs_from_tts(cx, sp, tts) { - Some(e) => e, - None => return DummyResult::any(sp), + let Some(es) = base::get_exprs_from_tts(cx, sp, tts) else { + return DummyResult::any(sp); }; let mut accumulator = String::new(); let mut missing_literal = vec![]; diff --git a/compiler/rustc_builtin_macros/src/concat_bytes.rs b/compiler/rustc_builtin_macros/src/concat_bytes.rs index c06af5206d5b1..a1afec410c1c5 100644 --- a/compiler/rustc_builtin_macros/src/concat_bytes.rs +++ b/compiler/rustc_builtin_macros/src/concat_bytes.rs @@ -121,9 +121,8 @@ pub fn expand_concat_bytes( sp: rustc_span::Span, tts: TokenStream, ) -> Box { - let es = match base::get_exprs_from_tts(cx, sp, tts) { - Some(e) => e, - None => return DummyResult::any(sp), + let Some(es) = base::get_exprs_from_tts(cx, sp, tts) else { + return DummyResult::any(sp); }; let mut accumulator = Vec::new(); let mut missing_literals = vec![]; diff --git a/compiler/rustc_builtin_macros/src/deriving/clone.rs b/compiler/rustc_builtin_macros/src/deriving/clone.rs index 2e5ad66c60bb8..fd26a376f91aa 100644 --- a/compiler/rustc_builtin_macros/src/deriving/clone.rs +++ b/compiler/rustc_builtin_macros/src/deriving/clone.rs @@ -196,12 +196,11 @@ fn cs_clone( let fields = all_fields .iter() .map(|field| { - let ident = match field.name { - Some(i) => i, - None => cx.span_bug( + let Some(ident) = field.name else { + cx.span_bug( trait_span, &format!("unnamed field in normal struct in `derive({})`", name,), - ), + ); }; let call = subcall(cx, field); cx.field_imm(field.span, ident, call) diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs index f84e6e0762012..2b3ac0a86c16c 100644 --- a/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs +++ b/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs @@ -83,9 +83,8 @@ pub fn cs_cmp(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> P< // } let new = { - let other_f = match other_fs { - [o_f] => o_f, - _ => cx.span_bug(span, "not exactly 2 arguments in `derive(Ord)`"), + let [other_f] = other_fs else { + cx.span_bug(span, "not exactly 2 arguments in `derive(Ord)`"); }; let args = diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs index 8e9f15743cc34..eead8b37024c0 100644 --- a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs +++ b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs @@ -26,9 +26,8 @@ pub fn expand_deriving_partial_eq( base: bool, ) -> P { let op = |cx: &mut ExtCtxt<'_>, span: Span, self_f: P, other_fs: &[P]| { - let other_f = match other_fs { - [o_f] => o_f, - _ => cx.span_bug(span, "not exactly 2 arguments in `derive(PartialEq)`"), + let [other_f] = other_fs else { + cx.span_bug(span, "not exactly 2 arguments in `derive(PartialEq)`"); }; cx.expr_binary(span, op, self_f, other_f.clone()) diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs index 151a919e0293b..d28ac822a1ed9 100644 --- a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs +++ b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs @@ -86,9 +86,8 @@ pub fn cs_partial_cmp(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_ // } let new = { - let other_f = match other_fs { - [o_f] => o_f, - _ => cx.span_bug(span, "not exactly 2 arguments in `derive(PartialOrd)`"), + let [other_f] = other_fs else { + cx.span_bug(span, "not exactly 2 arguments in `derive(PartialOrd)`"); }; let args = diff --git a/compiler/rustc_builtin_macros/src/deriving/default.rs b/compiler/rustc_builtin_macros/src/deriving/default.rs index 1d1eee88a68e6..ca83941f600ca 100644 --- a/compiler/rustc_builtin_macros/src/deriving/default.rs +++ b/compiler/rustc_builtin_macros/src/deriving/default.rs @@ -101,9 +101,8 @@ fn default_enum_substructure( trait_span: Span, enum_def: &EnumDef, ) -> P { - let default_variant = match extract_default_variant(cx, enum_def, trait_span) { - Ok(value) => value, - Err(()) => return DummyResult::raw_expr(trait_span, true), + let Ok(default_variant) = extract_default_variant(cx, enum_def, trait_span) else { + return DummyResult::raw_expr(trait_span, true); }; // At this point, we know that there is exactly one variant with a `#[default]` attribute. The diff --git a/compiler/rustc_builtin_macros/src/deriving/hash.rs b/compiler/rustc_builtin_macros/src/deriving/hash.rs index 7114b98768091..f1d46f03bad8f 100644 --- a/compiler/rustc_builtin_macros/src/deriving/hash.rs +++ b/compiler/rustc_builtin_macros/src/deriving/hash.rs @@ -48,9 +48,8 @@ pub fn expand_deriving_hash( } fn hash_substructure(cx: &mut ExtCtxt<'_>, trait_span: Span, substr: &Substructure<'_>) -> P { - let state_expr = match substr.nonself_args { - [o_f] => o_f, - _ => cx.span_bug(trait_span, "incorrect number of arguments in `derive(Hash)`"), + let [state_expr] = substr.nonself_args else { + cx.span_bug(trait_span, "incorrect number of arguments in `derive(Hash)`"); }; let call_hash = |span, thing_expr| { let hash_path = { diff --git a/compiler/rustc_builtin_macros/src/deriving/mod.rs b/compiler/rustc_builtin_macros/src/deriving/mod.rs index 0ca7988ca152f..812d86af6e8f2 100644 --- a/compiler/rustc_builtin_macros/src/deriving/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/mod.rs @@ -116,9 +116,8 @@ fn inject_impl_of_structural_trait( structural_path: generic::ty::Path, push: &mut dyn FnMut(Annotatable), ) { - let item = match *item { - Annotatable::Item(ref item) => item, - _ => unreachable!(), + let Annotatable::Item(ref item) = *item else { + unreachable!(); }; let generics = match item.kind { diff --git a/compiler/rustc_builtin_macros/src/env.rs b/compiler/rustc_builtin_macros/src/env.rs index 285027fc632d7..66ee93ce3c90e 100644 --- a/compiler/rustc_builtin_macros/src/env.rs +++ b/compiler/rustc_builtin_macros/src/env.rs @@ -16,9 +16,8 @@ pub fn expand_option_env<'cx>( sp: Span, tts: TokenStream, ) -> Box { - let var = match get_single_str_from_tts(cx, sp, tts, "option_env!") { - None => return DummyResult::any(sp), - Some(v) => v, + let Some(var) = get_single_str_from_tts(cx, sp, tts, "option_env!") else { + return DummyResult::any(sp); }; let sp = cx.with_def_site_ctxt(sp); @@ -62,9 +61,8 @@ pub fn expand_env<'cx>( Some(exprs) => exprs.into_iter(), }; - let var = match expr_to_string(cx, exprs.next().unwrap(), "expected string literal") { - None => return DummyResult::any(sp), - Some((v, _style)) => v, + let Some((var, _style)) = expr_to_string(cx, exprs.next().unwrap(), "expected string literal") else { + return DummyResult::any(sp); }; let msg = match exprs.next() { None => Symbol::intern(&format!("environment variable `{}` not defined", var)), diff --git a/compiler/rustc_builtin_macros/src/proc_macro_harness.rs b/compiler/rustc_builtin_macros/src/proc_macro_harness.rs index c9dd114047b76..407ca2301e124 100644 --- a/compiler/rustc_builtin_macros/src/proc_macro_harness.rs +++ b/compiler/rustc_builtin_macros/src/proc_macro_harness.rs @@ -103,11 +103,9 @@ impl<'a> CollectProcMacros<'a> { } fn collect_custom_derive(&mut self, item: &'a ast::Item, attr: &'a ast::Attribute) { - let (trait_name, proc_attrs) = - match parse_macro_name_and_helper_attrs(self.handler, attr, "derive") { - Some(name_and_attrs) => name_and_attrs, - None => return, - }; + let Some((trait_name, proc_attrs)) = parse_macro_name_and_helper_attrs(self.handler, attr, "derive") else { + return; + }; if self.in_root && item.vis.kind.is_pub() { self.macros.push(ProcMacro::Derive(ProcMacroDerive { @@ -219,15 +217,12 @@ impl<'a> Visitor<'a> for CollectProcMacros<'a> { } } - let attr = match found_attr { - None => { - self.check_not_pub_in_root(&item.vis, self.source_map.guess_head_span(item.span)); - let prev_in_root = mem::replace(&mut self.in_root, false); - visit::walk_item(self, item); - self.in_root = prev_in_root; - return; - } - Some(attr) => attr, + let Some(attr) = found_attr else { + self.check_not_pub_in_root(&item.vis, self.source_map.guess_head_span(item.span)); + let prev_in_root = mem::replace(&mut self.in_root, false); + visit::walk_item(self, item); + self.in_root = prev_in_root; + return; }; if !is_fn { diff --git a/compiler/rustc_builtin_macros/src/source_util.rs b/compiler/rustc_builtin_macros/src/source_util.rs index 1ea2c8843d6d7..bbc8e62d68ff0 100644 --- a/compiler/rustc_builtin_macros/src/source_util.rs +++ b/compiler/rustc_builtin_macros/src/source_util.rs @@ -98,9 +98,8 @@ pub fn expand_include<'cx>( tts: TokenStream, ) -> Box { let sp = cx.with_def_site_ctxt(sp); - let file = match get_single_str_from_tts(cx, sp, tts, "include!") { - Some(f) => f, - None => return DummyResult::any(sp), + let Some(file) = get_single_str_from_tts(cx, sp, tts, "include!") else { + return DummyResult::any(sp); }; // The file will be added to the code map by the parser let file = match cx.resolve_path(file, sp) { @@ -169,9 +168,8 @@ pub fn expand_include_str( tts: TokenStream, ) -> Box { let sp = cx.with_def_site_ctxt(sp); - let file = match get_single_str_from_tts(cx, sp, tts, "include_str!") { - Some(f) => f, - None => return DummyResult::any(sp), + let Some(file) = get_single_str_from_tts(cx, sp, tts, "include_str!") else { + return DummyResult::any(sp); }; let file = match cx.resolve_path(file, sp) { Ok(f) => f, @@ -204,9 +202,8 @@ pub fn expand_include_bytes( tts: TokenStream, ) -> Box { let sp = cx.with_def_site_ctxt(sp); - let file = match get_single_str_from_tts(cx, sp, tts, "include_bytes!") { - Some(f) => f, - None => return DummyResult::any(sp), + let Some(file) = get_single_str_from_tts(cx, sp, tts, "include_bytes!") else { + return DummyResult::any(sp); }; let file = match cx.resolve_path(file, sp) { Ok(f) => f, diff --git a/compiler/rustc_codegen_cranelift/src/abi/mod.rs b/compiler/rustc_codegen_cranelift/src/abi/mod.rs index a0550860fa545..a249e5fa8ac9c 100644 --- a/compiler/rustc_codegen_cranelift/src/abi/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/abi/mod.rs @@ -117,7 +117,7 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> { .unzip(); let return_layout = self.layout_of(return_ty); let return_tys = if let ty::Tuple(tup) = return_ty.kind() { - tup.types().map(|ty| AbiParam::new(self.clif_type(ty).unwrap())).collect() + tup.iter().map(|ty| AbiParam::new(self.clif_type(ty).unwrap())).collect() } else { vec![AbiParam::new(self.clif_type(return_ty).unwrap())] }; @@ -199,7 +199,7 @@ pub(crate) fn codegen_fn_prelude<'tcx>(fx: &mut FunctionCx<'_, '_, 'tcx>, start_ }; let mut params = Vec::new(); - for (i, _arg_ty) in tupled_arg_tys.types().enumerate() { + for (i, _arg_ty) in tupled_arg_tys.iter().enumerate() { let arg_abi = arg_abis_iter.next().unwrap(); let param = cvalue_for_param(fx, Some(local), Some(i), arg_abi, &mut block_params_iter); diff --git a/compiler/rustc_codegen_cranelift/src/common.rs b/compiler/rustc_codegen_cranelift/src/common.rs index 50f98965ab5d2..d3e36be3244f1 100644 --- a/compiler/rustc_codegen_cranelift/src/common.rs +++ b/compiler/rustc_codegen_cranelift/src/common.rs @@ -90,10 +90,9 @@ fn clif_pair_type_from_ty<'tcx>( ty: Ty<'tcx>, ) -> Option<(types::Type, types::Type)> { Some(match ty.kind() { - ty::Tuple(substs) if substs.len() == 2 => { - let mut types = substs.types(); - let a = clif_type_from_ty(tcx, types.next().unwrap())?; - let b = clif_type_from_ty(tcx, types.next().unwrap())?; + ty::Tuple(types) if types.len() == 2 => { + let a = clif_type_from_ty(tcx, types[0])?; + let b = clif_type_from_ty(tcx, types[1])?; if a.is_vector() || b.is_vector() { return None; } diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs index 55c9b4d9ba12d..42717ad0ae0e1 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs @@ -779,29 +779,35 @@ pub(crate) fn codegen_intrinsic_call<'tcx>( assert_inhabited | assert_zero_valid | assert_uninit_valid, () { let layout = fx.layout_of(T); if layout.abi.is_uninhabited() { - with_no_trimmed_paths(|| crate::base::codegen_panic( - fx, - &format!("attempted to instantiate uninhabited type `{}`", T), - span, - )); + with_no_trimmed_paths!({ + crate::base::codegen_panic( + fx, + &format!("attempted to instantiate uninhabited type `{}`", T), + span, + ) + }); return; } if intrinsic == sym::assert_zero_valid && !layout.might_permit_raw_init(fx, /*zero:*/ true) { - with_no_trimmed_paths(|| crate::base::codegen_panic( - fx, - &format!("attempted to zero-initialize type `{}`, which is invalid", T), - span, - )); + with_no_trimmed_paths!({ + crate::base::codegen_panic( + fx, + &format!("attempted to zero-initialize type `{}`, which is invalid", T), + span, + ); + }); return; } if intrinsic == sym::assert_uninit_valid && !layout.might_permit_raw_init(fx, /*zero:*/ false) { - with_no_trimmed_paths(|| crate::base::codegen_panic( - fx, - &format!("attempted to leave type `{}` uninitialized, which is invalid", T), - span, - )); + with_no_trimmed_paths!({ + crate::base::codegen_panic( + fx, + &format!("attempted to leave type `{}` uninitialized, which is invalid", T), + span, + ) + }); return; } }; diff --git a/compiler/rustc_codegen_gcc/src/type_of.rs b/compiler/rustc_codegen_gcc/src/type_of.rs index 281e49fa8a35e..0ada20cad2c3b 100644 --- a/compiler/rustc_codegen_gcc/src/type_of.rs +++ b/compiler/rustc_codegen_gcc/src/type_of.rs @@ -52,7 +52,7 @@ pub fn uncached_gcc_type<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, layout: TyAndLa ty::Adt(..) | ty::Closure(..) | ty::Foreign(..) | ty::Generator(..) | ty::Str if !cx.sess().fewer_names() => { - let mut name = with_no_trimmed_paths(|| layout.ty.to_string()); + let mut name = with_no_trimmed_paths!(layout.ty.to_string()); if let (&ty::Adt(def, _), &Variants::Single { index }) = (layout.ty.kind(), &layout.variants) { diff --git a/compiler/rustc_codegen_llvm/src/abi.rs b/compiler/rustc_codegen_llvm/src/abi.rs index 8a11e3e71bc81..c3994cef14fd1 100644 --- a/compiler/rustc_codegen_llvm/src/abi.rs +++ b/compiler/rustc_codegen_llvm/src/abi.rs @@ -599,13 +599,11 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> { if self.conv == Conv::CCmseNonSecureCall { // This will probably get ignored on all targets but those supporting the TrustZone-M // extension (thumbv8m targets). - unsafe { - llvm::AddCallSiteAttrString( - callsite, - llvm::AttributePlace::Function, - cstr::cstr!("cmse_nonsecure_call"), - ); - } + llvm::AddCallSiteAttrString( + callsite, + llvm::AttributePlace::Function, + cstr::cstr!("cmse_nonsecure_call"), + ); } } } diff --git a/compiler/rustc_codegen_llvm/src/back/archive.rs b/compiler/rustc_codegen_llvm/src/back/archive.rs index 21bd1dae7ac47..1a2cec2a0d97f 100644 --- a/compiler/rustc_codegen_llvm/src/back/archive.rs +++ b/compiler/rustc_codegen_llvm/src/back/archive.rs @@ -310,10 +310,7 @@ impl<'a> LlvmArchiveBuilder<'a> { if let Some(archive) = self.src_archive() { for child in archive.iter() { let child = child.map_err(string_to_io_error)?; - let child_name = match child.name() { - Some(s) => s, - None => continue, - }; + let Some(child_name) = child.name() else { continue }; if removals.iter().any(|r| r == child_name) { continue; } diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs index 384596dfff503..e60ad170434c3 100644 --- a/compiler/rustc_codegen_llvm/src/back/write.rs +++ b/compiler/rustc_codegen_llvm/src/back/write.rs @@ -826,20 +826,14 @@ pub(crate) unsafe fn codegen( let input = unsafe { slice::from_raw_parts(input_ptr as *const u8, input_len as usize) }; - let input = match str::from_utf8(input) { - Ok(s) => s, - Err(_) => return 0, - }; + let Ok(input) = str::from_utf8(input) else { return 0 }; let output = unsafe { slice::from_raw_parts_mut(output_ptr as *mut u8, output_len as usize) }; let mut cursor = io::Cursor::new(output); - let demangled = match rustc_demangle::try_demangle(input) { - Ok(d) => d, - Err(_) => return 0, - }; + let Ok(demangled) = rustc_demangle::try_demangle(input) else { return 0 }; if write!(cursor, "{:#}", demangled).is_err() { // Possible only if provided buffer is not big enough diff --git a/compiler/rustc_codegen_llvm/src/base.rs b/compiler/rustc_codegen_llvm/src/base.rs index 7b6ce5ea89bed..e15b86aa84fa4 100644 --- a/compiler/rustc_codegen_llvm/src/base.rs +++ b/compiler/rustc_codegen_llvm/src/base.rs @@ -138,10 +138,7 @@ pub fn compile_codegen_unit(tcx: TyCtxt<'_>, cgu_name: Symbol) -> (ModuleCodegen } pub fn set_link_section(llval: &Value, attrs: &CodegenFnAttrs) { - let sect = match attrs.link_section { - Some(name) => name, - None => return, - }; + let Some(sect) = attrs.link_section else { return }; unsafe { let buf = SmallCStr::new(sect.as_str()); llvm::LLVMSetSection(llval, buf.as_ptr()); diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs index 6707de933522b..51223697dbd85 100644 --- a/compiler/rustc_codegen_llvm/src/consts.rs +++ b/compiler/rustc_codegen_llvm/src/consts.rs @@ -369,10 +369,9 @@ impl<'ll> StaticMethods for CodegenCx<'ll, '_> { unsafe { let attrs = self.tcx.codegen_fn_attrs(def_id); - let (v, alloc) = match codegen_static_initializer(self, def_id) { - Ok(v) => v, + let Ok((v, alloc)) = codegen_static_initializer(self, def_id) else { // Error has already been reported - Err(_) => return, + return; }; let g = self.get_static(def_id); diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index 1abc3fb523d1b..ef87b7b1a7e07 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -752,9 +752,8 @@ pub fn type_metadata<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> &'ll prepare_enum_metadata(cx, t, def.did, unique_type_id, vec![]).finalize(cx) } }, - ty::Tuple(elements) => { - let tys: Vec<_> = elements.iter().map(|k| k.expect_ty()).collect(); - prepare_tuple_metadata(cx, t, &tys, unique_type_id, NO_SCOPE_METADATA).finalize(cx) + ty::Tuple(tys) => { + prepare_tuple_metadata(cx, t, tys, unique_type_id, NO_SCOPE_METADATA).finalize(cx) } // Type parameters from polymorphized functions. ty::Param(_) => MetadataCreationResult::new(param_type_metadata(cx, t), false), @@ -766,18 +765,15 @@ pub fn type_metadata<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> &'ll if already_stored_in_typemap { // Also make sure that we already have a `TypeMap` entry for the unique type ID. - let metadata_for_uid = match type_map.find_metadata_for_unique_id(unique_type_id) { - Some(metadata) => metadata, - None => { - bug!( - "expected type metadata for unique \ - type ID '{}' to already be in \ - the `debuginfo::TypeMap` but it \ - was not. (Ty = {})", - type_map.get_unique_type_id_as_string(unique_type_id), - t - ); - } + let Some(metadata_for_uid) = type_map.find_metadata_for_unique_id(unique_type_id) else { + bug!( + "expected type metadata for unique \ + type ID '{}' to already be in \ + the `debuginfo::TypeMap` but it \ + was not. (Ty = {})", + type_map.get_unique_type_id_as_string(unique_type_id), + t + ); }; match type_map.find_metadata_for_type(t) { diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index cfd23f5c24e05..f471f461e8639 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -88,9 +88,8 @@ impl<'ll, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'_, 'll, 'tcx> { let tcx = self.tcx; let callee_ty = instance.ty(tcx, ty::ParamEnv::reveal_all()); - let (def_id, substs) = match *callee_ty.kind() { - ty::FnDef(def_id, substs) => (def_id, substs), - _ => bug!("expected fn item type, found {}", callee_ty), + let ty::FnDef(def_id, substs) = *callee_ty.kind() else { + bug!("expected fn item type, found {}", callee_ty); }; let sig = callee_ty.fn_sig(tcx); @@ -1000,9 +999,8 @@ fn generic_simd_intrinsic<'ll, 'tcx>( } }) .collect(); - let indices = match indices { - Some(i) => i, - None => return Ok(bx.const_null(llret_ty)), + let Some(indices) = indices else { + return Ok(bx.const_null(llret_ty)); }; return Ok(bx.shuffle_vector( diff --git a/compiler/rustc_codegen_llvm/src/type_of.rs b/compiler/rustc_codegen_llvm/src/type_of.rs index fafb9a6dbdecc..02a263637a6ec 100644 --- a/compiler/rustc_codegen_llvm/src/type_of.rs +++ b/compiler/rustc_codegen_llvm/src/type_of.rs @@ -43,8 +43,7 @@ fn uncached_llvm_type<'a, 'tcx>( // in problematically distinct types due to HRTB and subtyping (see #47638). // ty::Dynamic(..) | ty::Adt(..) | ty::Closure(..) | ty::Foreign(..) | ty::Generator(..) | ty::Str => { - let mut name = - with_no_visible_paths(|| with_no_trimmed_paths(|| layout.ty.to_string())); + let mut name = with_no_visible_paths!(with_no_trimmed_paths!(layout.ty.to_string())); if let (&ty::Adt(def, _), &Variants::Single { index }) = (layout.ty.kind(), &layout.variants) { @@ -339,9 +338,8 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> { _ => {} } - let (a, b) = match self.abi { - Abi::ScalarPair(a, b) => (a, b), - _ => bug!("TyAndLayout::scalar_pair_element_llty({:?}): not applicable", self), + let Abi::ScalarPair(a, b) = self.abi else { + bug!("TyAndLayout::scalar_pair_element_llty({:?}): not applicable", self); }; let scalar = [a, b][index]; diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 58e0667d67898..587453fd8e8d6 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -23,7 +23,7 @@ use rustc_target::spec::{PanicStrategy, RelocModel, RelroLevel, SanitizerSet, Ta use super::archive::{find_library, ArchiveBuilder}; use super::command::Command; use super::linker::{self, Linker}; -use super::metadata::create_rmeta_file; +use super::metadata::{create_rmeta_file, MetadataPosition}; use super::rpath::{self, RPathConfig}; use crate::{ looks_like_rust_object_file, CodegenResults, CompiledModule, CrateInfo, NativeLib, @@ -267,6 +267,28 @@ fn link_rlib<'a, B: ArchiveBuilder<'a>>( let mut ab = ::new(sess, out_filename, None); + let trailing_metadata = match flavor { + RlibFlavor::Normal => { + let (metadata, metadata_position) = + create_rmeta_file(sess, codegen_results.metadata.raw_data()); + let metadata = emit_metadata(sess, &metadata, tmpdir); + match metadata_position { + MetadataPosition::First => { + // Most of the time metadata in rlib files is wrapped in a "dummy" object + // file for the target platform so the rlib can be processed entirely by + // normal linkers for the platform. Sometimes this is not possible however. + // If it is possible however, placing the metadata object first improves + // performance of getting metadata from rlibs. + ab.add_file(&metadata); + None + } + MetadataPosition::Last => Some(metadata), + } + } + + RlibFlavor::StaticlibBase => None, + }; + for m in &codegen_results.modules { if let Some(obj) = m.object.as_ref() { ab.add_file(obj); @@ -277,6 +299,16 @@ fn link_rlib<'a, B: ArchiveBuilder<'a>>( } } + match flavor { + RlibFlavor::Normal => {} + RlibFlavor::StaticlibBase => { + let obj = codegen_results.allocator_module.as_ref().and_then(|m| m.object.as_ref()); + if let Some(obj) = obj { + ab.add_file(obj); + } + } + } + // Note that in this loop we are ignoring the value of `lib.cfg`. That is, // we may not be configured to actually include a static library if we're // adding it here. That's because later when we consume this rlib we'll @@ -334,42 +366,33 @@ fn link_rlib<'a, B: ArchiveBuilder<'a>>( ab.inject_dll_import_lib(&raw_dylib_name, &raw_dylib_imports, tmpdir); } - // Note that it is important that we add all of our non-object "magical - // files" *after* all of the object files in the archive. The reason for - // this is as follows: - // - // * When performing LTO, this archive will be modified to remove - // objects from above. The reason for this is described below. - // - // * When the system linker looks at an archive, it will attempt to - // determine the architecture of the archive in order to see whether its - // linkable. - // - // The algorithm for this detection is: iterate over the files in the - // archive. Skip magical SYMDEF names. Interpret the first file as an - // object file. Read architecture from the object file. - // - // * As one can probably see, if "metadata" and "foo.bc" were placed - // before all of the objects, then the architecture of this archive would - // not be correctly inferred once 'foo.o' is removed. - // - // Basically, all this means is that this code should not move above the - // code above. - match flavor { - RlibFlavor::Normal => { - // metadata in rlib files is wrapped in a "dummy" object file for - // the target platform so the rlib can be processed entirely by - // normal linkers for the platform. - let metadata = create_rmeta_file(sess, codegen_results.metadata.raw_data()); - ab.add_file(&emit_metadata(sess, &metadata, tmpdir)); - } - - RlibFlavor::StaticlibBase => { - let obj = codegen_results.allocator_module.as_ref().and_then(|m| m.object.as_ref()); - if let Some(obj) = obj { - ab.add_file(obj); - } - } + if let Some(trailing_metadata) = trailing_metadata { + // Note that it is important that we add all of our non-object "magical + // files" *after* all of the object files in the archive. The reason for + // this is as follows: + // + // * When performing LTO, this archive will be modified to remove + // objects from above. The reason for this is described below. + // + // * When the system linker looks at an archive, it will attempt to + // determine the architecture of the archive in order to see whether its + // linkable. + // + // The algorithm for this detection is: iterate over the files in the + // archive. Skip magical SYMDEF names. Interpret the first file as an + // object file. Read architecture from the object file. + // + // * As one can probably see, if "metadata" and "foo.bc" were placed + // before all of the objects, then the architecture of this archive would + // not be correctly inferred once 'foo.o' is removed. + // + // * Most of the time metadata in rlib files is wrapped in a "dummy" object + // file for the target platform so the rlib can be processed entirely by + // normal linkers for the platform. Sometimes this is not possible however. + // + // Basically, all this means is that this code should not move above the + // code above. + ab.add_file(&trailing_metadata); } return Ok(ab); @@ -674,9 +697,8 @@ fn link_natively<'a, B: ArchiveBuilder<'a>>( loop { i += 1; prog = sess.time("run_linker", || exec_linker(sess, &cmd, out_filename, tmpdir)); - let output = match prog { - Ok(ref output) => output, - Err(_) => break, + let Ok(ref output) = prog else { + break; }; if output.status.success() { break; @@ -2025,9 +2047,8 @@ fn add_local_native_libraries( let search_path = OnceCell::new(); let mut last = (NativeLibKind::Unspecified, None); for lib in relevant_libs { - let name = match lib.name { - Some(l) => l, - None => continue, + let Some(name) = lib.name else { + continue; }; // Skip if this library is the same as the last. @@ -2382,9 +2403,8 @@ fn add_upstream_native_libraries( let mut last = (NativeLibKind::Unspecified, None); for &cnum in &codegen_results.crate_info.used_crates { for lib in codegen_results.crate_info.native_libraries[&cnum].iter() { - let name = match lib.name { - Some(l) => l, - None => continue, + let Some(name) = lib.name else { + continue; }; if !relevant_lib(sess, &lib) { continue; diff --git a/compiler/rustc_codegen_ssa/src/back/metadata.rs b/compiler/rustc_codegen_ssa/src/back/metadata.rs index 9ebbcac76a28a..c52269805c46f 100644 --- a/compiler/rustc_codegen_ssa/src/back/metadata.rs +++ b/compiler/rustc_codegen_ssa/src/back/metadata.rs @@ -79,15 +79,14 @@ fn search_for_metadata<'a>( bytes: &'a [u8], section: &str, ) -> Result<&'a [u8], String> { - let file = match object::File::parse(bytes) { - Ok(f) => f, + let Ok(file) = object::File::parse(bytes) else { // The parse above could fail for odd reasons like corruption, but for // now we just interpret it as this target doesn't support metadata // emission in object files so the entire byte slice itself is probably // a metadata file. Ideally though if necessary we could at least check // the prefix of bytes to see if it's an actual metadata object and if // not forward the error along here. - Err(_) => return Ok(bytes), + return Ok(bytes); }; file.section_by_name(section) .ok_or_else(|| format!("no `{}` section in '{}'", section, path.display()))? @@ -167,6 +166,11 @@ fn create_object_file(sess: &Session) -> Option> { Some(file) } +pub enum MetadataPosition { + First, + Last, +} + // For rlibs we "pack" rustc metadata into a dummy object file. When rustc // creates a dylib crate type it will pass `--whole-archive` (or the // platform equivalent) to include all object files from an rlib into the @@ -199,7 +203,7 @@ fn create_object_file(sess: &Session) -> Option> { // * ELF - All other targets are similar to Windows in that there's a // `SHF_EXCLUDE` flag we can set on sections in an object file to get // automatically removed from the final output. -pub fn create_rmeta_file(sess: &Session, metadata: &[u8]) -> Vec { +pub fn create_rmeta_file(sess: &Session, metadata: &[u8]) -> (Vec, MetadataPosition) { let Some(mut file) = create_object_file(sess) else { // This is used to handle all "other" targets. This includes targets // in two categories: @@ -217,7 +221,7 @@ pub fn create_rmeta_file(sess: &Session, metadata: &[u8]) -> Vec { // WebAssembly and for targets not supported by the `object` crate // yet it means that work will need to be done in the `object` crate // to add a case above. - return metadata.to_vec(); + return (metadata.to_vec(), MetadataPosition::Last); }; let section = file.add_section( file.segment_name(StandardSegment::Debug).to_vec(), @@ -236,7 +240,7 @@ pub fn create_rmeta_file(sess: &Session, metadata: &[u8]) -> Vec { _ => {} }; file.append_section_data(section, metadata, 1); - file.write().unwrap() + (file.write().unwrap(), MetadataPosition::First) } // Historical note: diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs index aeddd926896e8..8191d8b5e4924 100644 --- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs +++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs @@ -448,10 +448,7 @@ fn wasm_import_module_map(tcx: TyCtxt<'_>, cnum: CrateNum) -> FxHashMap s, - None => continue, - }; + let Some(module) = module else { continue }; ret.extend(lib.foreign_items.iter().map(|id| { assert_eq!(id.krate, cnum); (*id, module.to_string()) diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index 4a5eabc87554c..ed6c156547e29 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -409,18 +409,15 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( // listing. let main_ret_ty = cx.tcx().erase_regions(main_ret_ty.no_bound_vars().unwrap()); - let llfn = match cx.declare_c_main(llfty) { - Some(llfn) => llfn, - None => { - // FIXME: We should be smart and show a better diagnostic here. - let span = cx.tcx().def_span(rust_main_def_id); - cx.sess() - .struct_span_err(span, "entry symbol `main` declared multiple times") - .help("did you use `#[no_mangle]` on `fn main`? Use `#[start]` instead") - .emit(); - cx.sess().abort_if_errors(); - bug!(); - } + let Some(llfn) = cx.declare_c_main(llfty) else { + // FIXME: We should be smart and show a better diagnostic here. + let span = cx.tcx().def_span(rust_main_def_id); + cx.sess() + .struct_span_err(span, "entry symbol `main` declared multiple times") + .help("did you use `#[no_mangle]` on `fn main`? Use `#[start]` instead") + .emit(); + cx.sess().abort_if_errors(); + bug!(); }; // `main` should respect same config for frame pointer elimination as rest of code diff --git a/compiler/rustc_codegen_ssa/src/common.rs b/compiler/rustc_codegen_ssa/src/common.rs index 2df58ecc9f68a..ae54442e884a8 100644 --- a/compiler/rustc_codegen_ssa/src/common.rs +++ b/compiler/rustc_codegen_ssa/src/common.rs @@ -202,11 +202,8 @@ pub fn asm_const_to_str<'tcx>( const_value: ConstValue<'tcx>, ty_and_layout: TyAndLayout<'tcx>, ) -> String { - let scalar = match const_value { - ConstValue::Scalar(s) => s, - _ => { - span_bug!(sp, "expected Scalar for promoted asm const, but got {:#?}", const_value) - } + let ConstValue::Scalar(scalar) = const_value else { + span_bug!(sp, "expected Scalar for promoted asm const, but got {:#?}", const_value) }; let value = scalar.assert_bits(ty_and_layout.size); match ty_and_layout.ty.kind() { diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs index b63851c195de6..1561277b7049f 100644 --- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs +++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs @@ -86,7 +86,7 @@ fn push_debuginfo_type_name<'tcx>( } for component_type in component_types { - push_debuginfo_type_name(tcx, component_type.expect_ty(), true, output, visited); + push_debuginfo_type_name(tcx, component_type, true, output, visited); push_arg_separator(cpp_like_debuginfo, output); } if !component_types.is_empty() { diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index 4c7a09ca1e94b..fa3904576745a 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -135,21 +135,38 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> { // If there is a cleanup block and the function we're calling can unwind, then // do an invoke, otherwise do a call. let fn_ty = bx.fn_decl_backend_type(&fn_abi); - if let Some(cleanup) = cleanup.filter(|_| fn_abi.can_unwind) { + + let unwind_block = if let Some(cleanup) = cleanup.filter(|_| fn_abi.can_unwind) { + Some(self.llblock(fx, cleanup)) + } else if fx.mir[self.bb].is_cleanup + && fn_abi.can_unwind + && !base::wants_msvc_seh(fx.cx.tcx().sess) + { + // Exception must not propagate out of the execution of a cleanup (doing so + // can cause undefined behaviour). We insert a double unwind guard for + // functions that can potentially unwind to protect against this. + // + // This is not necessary for SEH which does not use successive unwinding + // like Itanium EH. EH frames in SEH are different from normal function + // frames and SEH will abort automatically if an exception tries to + // propagate out from cleanup. + Some(fx.double_unwind_guard()) + } else { + None + }; + + if let Some(unwind_block) = unwind_block { let ret_llbb = if let Some((_, target)) = destination { fx.llbb(target) } else { fx.unreachable_block() }; - let invokeret = bx.invoke( - fn_ty, - fn_ptr, - &llargs, - ret_llbb, - self.llblock(fx, cleanup), - self.funclet(fx), - ); + let invokeret = + bx.invoke(fn_ty, fn_ptr, &llargs, ret_llbb, unwind_block, self.funclet(fx)); bx.apply_attrs_callsite(&fn_abi, invokeret); + if fx.mir[self.bb].is_cleanup { + bx.apply_attrs_to_cleanup_callsite(invokeret); + } if let Some((ret_dest, target)) = destination { let mut ret_bx = fx.build_block(target); @@ -486,9 +503,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let span = terminator.source_info.span; self.set_debug_loc(&mut bx, terminator.source_info); - // Get the location information. - let location = self.get_caller_location(&mut bx, terminator.source_info).immediate(); - // Obtain the panic entry point. let def_id = common::langcall(bx.tcx(), Some(span), "", LangItem::PanicNoUnwind); let instance = ty::Instance::mono(bx.tcx(), def_id); @@ -496,7 +510,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let llfn = bx.get_fn_addr(instance); // Codegen the actual panic invoke/call. - helper.do_call(self, &mut bx, fn_abi, llfn, &[location], None, None); + helper.do_call(self, &mut bx, fn_abi, llfn, &[], None, None); } /// Returns `true` if this is indeed a panic intrinsic and codegen is done. @@ -535,8 +549,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { UninitValid => !layout.might_permit_raw_init(bx, /*zero:*/ false), }; if do_panic { - let msg_str = with_no_visible_paths(|| { - with_no_trimmed_paths(|| { + let msg_str = with_no_visible_paths!({ + with_no_trimmed_paths!({ if layout.abi.is_uninhabited() { // Use this error even for the other intrinsics as it is more precise. format!("attempted to instantiate uninhabited type `{}`", ty) @@ -1398,6 +1412,35 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { }) } + fn double_unwind_guard(&mut self) -> Bx::BasicBlock { + self.double_unwind_guard.unwrap_or_else(|| { + assert!(!base::wants_msvc_seh(self.cx.sess())); + + let mut bx = self.new_block("abort"); + self.set_debug_loc(&mut bx, mir::SourceInfo::outermost(self.mir.span)); + + let llpersonality = self.cx.eh_personality(); + let llretty = self.landing_pad_type(); + bx.cleanup_landing_pad(llretty, llpersonality); + + let def_id = common::langcall(bx.tcx(), None, "", LangItem::PanicNoUnwind); + let instance = ty::Instance::mono(bx.tcx(), def_id); + let fn_abi = bx.fn_abi_of_instance(instance, ty::List::empty()); + let fn_ptr = bx.get_fn_addr(instance); + let fn_ty = bx.fn_decl_backend_type(&fn_abi); + + let llret = bx.call(fn_ty, fn_ptr, &[], None); + bx.apply_attrs_callsite(&fn_abi, llret); + bx.apply_attrs_to_cleanup_callsite(llret); + + bx.unreachable(); + let llbb = bx.llbb(); + + self.double_unwind_guard = Some(llbb); + llbb + }) + } + // FIXME(eddyb) replace with `build_sibling_block`/`append_sibling_block` // (which requires having a `Bx` already, and not all callers do). fn new_block(&self, name: &str) -> Bx { diff --git a/compiler/rustc_codegen_ssa/src/mir/constant.rs b/compiler/rustc_codegen_ssa/src/mir/constant.rs index 5cdf131b0b633..479b2b05f4305 100644 --- a/compiler/rustc_codegen_ssa/src/mir/constant.rs +++ b/compiler/rustc_codegen_ssa/src/mir/constant.rs @@ -67,9 +67,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { .map(|field| { if let Some(prim) = field.val().try_to_scalar() { let layout = bx.layout_of(field_ty); - let scalar = match layout.abi { - Abi::Scalar(x) => x, - _ => bug!("from_const: invalid ByVal layout: {:#?}", layout), + let Abi::Scalar(scalar) = layout.abi else { + bug!("from_const: invalid ByVal layout: {:#?}", layout); }; bx.scalar_to_backend(prim, scalar, bx.immediate_backend_type(layout)) } else { diff --git a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs index c710fcc2c1dcb..bb53c722a244a 100644 --- a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs +++ b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs @@ -258,14 +258,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let vars = vars.iter().copied().chain(fallback_var); for var in vars { - let dbg_var = match var.dbg_var { - Some(dbg_var) => dbg_var, - None => continue, - }; - let dbg_loc = match self.dbg_loc(var.source_info) { - Some(dbg_loc) => dbg_loc, - None => continue, - }; + let Some(dbg_var) = var.dbg_var else { continue }; + let Some(dbg_loc) = self.dbg_loc(var.source_info) else { continue }; let mut direct_offset = Size::ZERO; // FIXME(eddyb) use smallvec here. @@ -410,10 +404,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } mir::VarDebugInfoContents::Const(c) => { if let Some(dbg_var) = dbg_var { - let dbg_loc = match self.dbg_loc(var.source_info) { - Some(dbg_loc) => dbg_loc, - None => continue, - }; + let Some(dbg_loc) = self.dbg_loc(var.source_info) else { continue }; if let Ok(operand) = self.eval_mir_constant_to_operand(bx, &c) { let base = Self::spill_operand_to_stack( diff --git a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs index c654232c10a57..f15c469ae5741 100644 --- a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs +++ b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs @@ -58,9 +58,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { ) { let callee_ty = instance.ty(bx.tcx(), ty::ParamEnv::reveal_all()); - let (def_id, substs) = match *callee_ty.kind() { - ty::FnDef(def_id, substs) => (def_id, substs), - _ => bug!("expected fn item type, found {}", callee_ty), + let ty::FnDef(def_id, substs) = *callee_ty.kind() else { + bug!("expected fn item type, found {}", callee_ty); }; let sig = callee_ty.fn_sig(bx.tcx()); @@ -338,21 +337,18 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { ); return; } - let (_width, signed) = match int_type_width_signed(ret_ty, bx.tcx()) { - Some(pair) => pair, - None => { - span_invalid_monomorphization_error( - bx.tcx().sess, - span, - &format!( - "invalid monomorphization of `float_to_int_unchecked` \ - intrinsic: expected basic integer type, \ - found `{}`", - ret_ty - ), - ); - return; - } + let Some((_width, signed)) = int_type_width_signed(ret_ty, bx.tcx()) else { + span_invalid_monomorphization_error( + bx.tcx().sess, + span, + &format!( + "invalid monomorphization of `float_to_int_unchecked` \ + intrinsic: expected basic integer type, \ + found `{}`", + ret_ty + ), + ); + return; }; if signed { bx.fptosi(args[0].immediate(), llret_ty) diff --git a/compiler/rustc_codegen_ssa/src/mir/mod.rs b/compiler/rustc_codegen_ssa/src/mir/mod.rs index 814e4d626e119..adb856ef42e2f 100644 --- a/compiler/rustc_codegen_ssa/src/mir/mod.rs +++ b/compiler/rustc_codegen_ssa/src/mir/mod.rs @@ -62,6 +62,9 @@ pub struct FunctionCx<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> { /// Cached unreachable block unreachable_block: Option, + /// Cached double unwind guarding block + double_unwind_guard: Option, + /// The location where each MIR arg/var/tmp/ret is stored. This is /// usually an `PlaceRef` representing an alloca, but not always: /// sometimes we can skip the alloca and just store the value @@ -169,6 +172,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( personality_slot: None, cached_llbbs, unreachable_block: None, + double_unwind_guard: None, cleanup_kinds, landing_pads: IndexVec::from_elem(None, mir.basic_blocks()), funclets: IndexVec::from_fn_n(|_| None, mir.basic_blocks().len()), @@ -281,9 +285,8 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( // individual LLVM function arguments. let arg_ty = fx.monomorphize(arg_decl.ty); - let tupled_arg_tys = match arg_ty.kind() { - ty::Tuple(tys) => tys, - _ => bug!("spread argument isn't a tuple?!"), + let ty::Tuple(tupled_arg_tys) = arg_ty.kind() else { + bug!("spread argument isn't a tuple?!"); }; let place = PlaceRef::alloca(bx, bx.layout_of(arg_ty)); diff --git a/compiler/rustc_codegen_ssa/src/mir/operand.rs b/compiler/rustc_codegen_ssa/src/mir/operand.rs index 0c526ff13f2ba..66be58cf62ca0 100644 --- a/compiler/rustc_codegen_ssa/src/mir/operand.rs +++ b/compiler/rustc_codegen_ssa/src/mir/operand.rs @@ -78,17 +78,15 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> { let val = match val { ConstValue::Scalar(x) => { - let scalar = match layout.abi { - Abi::Scalar(x) => x, - _ => bug!("from_const: invalid ByVal layout: {:#?}", layout), + let Abi::Scalar(scalar) = layout.abi else { + bug!("from_const: invalid ByVal layout: {:#?}", layout); }; let llval = bx.scalar_to_backend(x, scalar, bx.immediate_backend_type(layout)); OperandValue::Immediate(llval) } ConstValue::Slice { data, start, end } => { - let a_scalar = match layout.abi { - Abi::ScalarPair(a, _) => a, - _ => bug!("from_const: invalid ScalarPair layout: {:#?}", layout), + let Abi::ScalarPair(a_scalar, _) = layout.abi else { + bug!("from_const: invalid ScalarPair layout: {:#?}", layout); }; let a = Scalar::from_pointer( Pointer::new(bx.tcx().create_memory_alloc(data), Size::from_bytes(start)), @@ -307,9 +305,8 @@ impl<'a, 'tcx, V: CodegenObject> OperandValue { bx.store_with_flags(val, dest.llval, dest.align, flags); } OperandValue::Pair(a, b) => { - let (a_scalar, b_scalar) = match dest.layout.abi { - Abi::ScalarPair(a, b) => (a, b), - _ => bug!("store_with_flags: invalid ScalarPair layout: {:#?}", dest.layout), + let Abi::ScalarPair(a_scalar, b_scalar) = dest.layout.abi else { + bug!("store_with_flags: invalid ScalarPair layout: {:#?}", dest.layout); }; let ty = bx.backend_type(dest.layout); let b_offset = a_scalar.value.size(bx).align_to(b_scalar.value.align(bx).abi); diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs index bfb9c40be57df..533c32f807df6 100644 --- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs @@ -53,7 +53,7 @@ fn eval_body_using_ecx<'mir, 'tcx>( trace!( "eval_body_using_ecx: pushing stack frame for global: {}{}", - with_no_trimmed_paths(|| ty::tls::with(|tcx| tcx.def_path_str(cid.instance.def_id()))), + with_no_trimmed_paths!(ty::tls::with(|tcx| tcx.def_path_str(cid.instance.def_id()))), cid.promoted.map_or_else(String::new, |p| format!("::promoted[{:?}]", p)) ); @@ -231,9 +231,8 @@ pub fn eval_to_const_value_raw_provider<'tcx>( // Catch such calls and evaluate them instead of trying to load a constant's MIR. if let ty::InstanceDef::Intrinsic(def_id) = key.value.instance.def { let ty = key.value.instance.ty(tcx, key.param_env); - let substs = match ty.kind() { - ty::FnDef(_, substs) => substs, - _ => bug!("intrinsic with type {:?}", ty), + let ty::FnDef(_, substs) = ty.kind() else { + bug!("intrinsic with type {:?}", ty); }; return eval_nullary_intrinsic(tcx, key.param_env, def_id, substs).map_err(|error| { let span = tcx.def_span(def_id); @@ -274,7 +273,7 @@ pub fn eval_to_allocation_raw_provider<'tcx>( // The next two lines concatenated contain some discussion: // https://rust-lang.zulipchat.com/#narrow/stream/146212-t-compiler.2Fconst-eval/ // subject/anon_const_instance_printing/near/135980032 - let instance = with_no_trimmed_paths(|| key.value.instance.to_string()); + let instance = with_no_trimmed_paths!(key.value.instance.to_string()); trace!("const eval: {:?} ({})", key, instance); } @@ -317,7 +316,7 @@ pub fn eval_to_allocation_raw_provider<'tcx>( // the expression, leading to the const eval error. let instance = &key.value.instance; if !instance.substs.is_empty() { - let instance = with_no_trimmed_paths(|| instance.to_string()); + let instance = with_no_trimmed_paths!(instance.to_string()); let msg = format!("evaluation of `{}` failed", instance); Cow::from(msg) } else { diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index e157b58405212..b2019ce40c3ea 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -318,15 +318,12 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, let intrinsic_name = ecx.tcx.item_name(instance.def_id()); // CTFE-specific intrinsics. - let (dest, ret) = match ret { - None => { - return Err(ConstEvalErrKind::NeedsRfc(format!( - "calling intrinsic `{}`", - intrinsic_name - )) - .into()); - } - Some(p) => p, + let Some((dest, ret)) = ret else { + return Err(ConstEvalErrKind::NeedsRfc(format!( + "calling intrinsic `{}`", + intrinsic_name + )) + .into()); }; match intrinsic_name { sym::ptr_guaranteed_eq | sym::ptr_guaranteed_ne => { diff --git a/compiler/rustc_const_eval/src/const_eval/mod.rs b/compiler/rustc_const_eval/src/const_eval/mod.rs index ba1d5f45bbb10..724f92243d07e 100644 --- a/compiler/rustc_const_eval/src/const_eval/mod.rs +++ b/compiler/rustc_const_eval/src/const_eval/mod.rs @@ -147,6 +147,10 @@ pub(crate) fn try_destructure_const<'tcx>( // We go to `usize` as we cannot allocate anything bigger anyway. let (field_count, variant, down) = match val.ty().kind() { ty::Array(_, len) => (usize::try_from(len.eval_usize(tcx, param_env)).unwrap(), None, op), + // Checks if we have any variants, to avoid downcasting to a non-existing variant (when + // there are no variants `read_discriminant` successfully returns a non-existing variant + // index). + ty::Adt(def, _) if def.variants.is_empty() => throw_ub!(Unreachable), ty::Adt(def, _) => { let variant = ecx.read_discriminant(&op)?.1; let down = ecx.operand_downcast(&op, variant)?; diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs index 1b86bcfa8c9ad..ab50c709143fd 100644 --- a/compiler/rustc_const_eval/src/interpret/eval_context.rs +++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs @@ -631,15 +631,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // the last field). Can't have foreign types here, how would we // adjust alignment and size for them? let field = layout.field(self, layout.fields.count() - 1); - let (unsized_size, unsized_align) = - match self.size_and_align_of(metadata, &field)? { - Some(size_and_align) => size_and_align, - None => { - // A field with an extern type. We don't know the actual dynamic size - // or the alignment. - return Ok(None); - } - }; + let Some((unsized_size, unsized_align)) = self.size_and_align_of(metadata, &field)? else { + // A field with an extern type. We don't know the actual dynamic size + // or the alignment. + return Ok(None); + }; // FIXME (#26403, #27023): We should be adding padding // to `sized_size` (to accommodate the `unsized_align` diff --git a/compiler/rustc_const_eval/src/interpret/intern.rs b/compiler/rustc_const_eval/src/interpret/intern.rs index a1dd587c17ab5..b1f50bc56c908 100644 --- a/compiler/rustc_const_eval/src/interpret/intern.rs +++ b/compiler/rustc_const_eval/src/interpret/intern.rs @@ -84,22 +84,19 @@ fn intern_shallow<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx, const_eval: trace!("intern_shallow {:?} with {:?}", alloc_id, mode); // remove allocation let tcx = ecx.tcx; - let (kind, mut alloc) = match ecx.memory.alloc_map.remove(&alloc_id) { - Some(entry) => entry, - None => { - // Pointer not found in local memory map. It is either a pointer to the global - // map, or dangling. - // If the pointer is dangling (neither in local nor global memory), we leave it - // to validation to error -- it has the much better error messages, pointing out where - // in the value the dangling reference lies. - // The `delay_span_bug` ensures that we don't forget such a check in validation. - if tcx.get_global_alloc(alloc_id).is_none() { - tcx.sess.delay_span_bug(ecx.tcx.span, "tried to intern dangling pointer"); - } - // treat dangling pointers like other statics - // just to stop trying to recurse into them - return Some(IsStaticOrFn); + let Some((kind, mut alloc)) = ecx.memory.alloc_map.remove(&alloc_id) else { + // Pointer not found in local memory map. It is either a pointer to the global + // map, or dangling. + // If the pointer is dangling (neither in local nor global memory), we leave it + // to validation to error -- it has the much better error messages, pointing out where + // in the value the dangling reference lies. + // The `delay_span_bug` ensures that we don't forget such a check in validation. + if tcx.get_global_alloc(alloc_id).is_none() { + tcx.sess.delay_span_bug(ecx.tcx.span, "tried to intern dangling pointer"); } + // treat dangling pointers like other statics + // just to stop trying to recurse into them + return Some(IsStaticOrFn); }; // This match is just a canary for future changes to `MemoryKind`, which most likely need // changes in this function. diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index 4aa3c83cc0243..73e7d862ad641 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -291,21 +291,18 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { ); } - let (alloc_kind, mut alloc) = match self.alloc_map.remove(&alloc_id) { - Some(alloc) => alloc, - None => { - // Deallocating global memory -- always an error - return Err(match self.tcx.get_global_alloc(alloc_id) { - Some(GlobalAlloc::Function(..)) => { - err_ub_format!("deallocating {}, which is a function", alloc_id) - } - Some(GlobalAlloc::Static(..) | GlobalAlloc::Memory(..)) => { - err_ub_format!("deallocating {}, which is static memory", alloc_id) - } - None => err_ub!(PointerUseAfterFree(alloc_id)), + let Some((alloc_kind, mut alloc)) = self.alloc_map.remove(&alloc_id) else { + // Deallocating global memory -- always an error + return Err(match self.tcx.get_global_alloc(alloc_id) { + Some(GlobalAlloc::Function(..)) => { + err_ub_format!("deallocating {}, which is a function", alloc_id) } - .into()); + Some(GlobalAlloc::Static(..) | GlobalAlloc::Memory(..)) => { + err_ub_format!("deallocating {}, which is static memory", alloc_id) + } + None => err_ub!(PointerUseAfterFree(alloc_id)), } + .into()); }; if alloc.mutability == Mutability::Not { @@ -957,9 +954,9 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { ptr: Pointer>, size: Size, ) -> InterpResult<'tcx, &[u8]> { - let alloc_ref = match self.get(ptr, size, Align::ONE)? { - Some(a) => a, - None => return Ok(&[]), // zero-sized access + let Some(alloc_ref) = self.get(ptr, size, Align::ONE)? else { + // zero-sized access + return Ok(&[]); }; // Side-step AllocRef and directly access the underlying bytes more efficiently. // (We are staying inside the bounds here so all is good.) @@ -983,17 +980,14 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { assert_eq!(lower, len, "can only write iterators with a precise length"); let size = Size::from_bytes(len); - let alloc_ref = match self.get_mut(ptr, size, Align::ONE)? { - Some(alloc_ref) => alloc_ref, - None => { - // zero-sized access - assert_matches!( - src.next(), - None, - "iterator said it was empty but returned an element" - ); - return Ok(()); - } + let Some(alloc_ref) = self.get_mut(ptr, size, Align::ONE)? else { + // zero-sized access + assert_matches!( + src.next(), + None, + "iterator said it was empty but returned an element" + ); + return Ok(()); }; // Side-step AllocRef and directly access the underlying bytes more efficiently. @@ -1043,18 +1037,18 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { // and once below to get the underlying `&[mut] Allocation`. // Source alloc preparations and access hooks. - let (src_alloc_id, src_offset, src) = match src_parts { - None => return Ok(()), // Zero-sized *source*, that means dst is also zero-sized and we have nothing to do. - Some(src_ptr) => src_ptr, + let Some((src_alloc_id, src_offset, src)) = src_parts else { + // Zero-sized *source*, that means dst is also zero-sized and we have nothing to do. + return Ok(()); }; let src_alloc = self.get_raw(src_alloc_id)?; let src_range = alloc_range(src_offset, size); M::memory_read(&self.extra, &src_alloc.extra, src.provenance, src_range)?; // We need the `dest` ptr for the next operation, so we get it now. // We already did the source checks and called the hooks so we are good to return early. - let (dest_alloc_id, dest_offset, dest) = match dest_parts { - None => return Ok(()), // Zero-sized *destiantion*. - Some(dest_ptr) => dest_ptr, + let Some((dest_alloc_id, dest_offset, dest)) = dest_parts else { + // Zero-sized *destination*. + return Ok(()); }; // This checks relocation edges on the src, which needs to happen before diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs index ec5eafcd63318..60e915a7eee11 100644 --- a/compiler/rustc_const_eval/src/interpret/operand.rs +++ b/compiler/rustc_const_eval/src/interpret/operand.rs @@ -258,15 +258,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { return Ok(None); } - let alloc = match self.get_alloc(mplace)? { - Some(ptr) => ptr, - None => { - return Ok(Some(ImmTy { - // zero-sized type - imm: Scalar::ZST.into(), - layout: mplace.layout, - })); - } + let Some(alloc) = self.get_alloc(mplace)? else { + return Ok(Some(ImmTy { + // zero-sized type + imm: Scalar::ZST.into(), + layout: mplace.layout, + })); }; match mplace.layout.abi { diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs index 7b06ffaf15d02..e9b2df53a3313 100644 --- a/compiler/rustc_const_eval/src/interpret/place.rs +++ b/compiler/rustc_const_eval/src/interpret/place.rs @@ -420,9 +420,8 @@ where ) -> InterpResult<'tcx, impl Iterator>> + 'a> { let len = base.len(self)?; // also asserts that we have a type where this makes sense - let stride = match base.layout.fields { - FieldsShape::Array { stride, .. } => stride, - _ => span_bug!(self.cur_span(), "mplace_array_fields: expected an array layout"), + let FieldsShape::Array { stride, .. } = base.layout.fields else { + span_bug!(self.cur_span(), "mplace_array_fields: expected an array layout"); }; let layout = base.layout.field(self, 0); let dl = &self.tcx.data_layout; @@ -747,9 +746,9 @@ where // Invalid places are a thing: the return place of a diverging function let tcx = *self.tcx; - let mut alloc = match self.get_alloc_mut(dest)? { - Some(a) => a, - None => return Ok(()), // zero-sized access + let Some(mut alloc) = self.get_alloc_mut(dest)? else { + // zero-sized access + return Ok(()); }; // FIXME: We should check that there are dest.layout.size many bytes available in diff --git a/compiler/rustc_const_eval/src/interpret/step.rs b/compiler/rustc_const_eval/src/interpret/step.rs index 57ba9b4099232..0701e0ded9703 100644 --- a/compiler/rustc_const_eval/src/interpret/step.rs +++ b/compiler/rustc_const_eval/src/interpret/step.rs @@ -46,15 +46,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { return Ok(false); } - let loc = match self.frame().loc { - Ok(loc) => loc, - Err(_) => { - // We are unwinding and this fn has no cleanup code. - // Just go on unwinding. - trace!("unwinding: skipping frame"); - self.pop_stack_frame(/* unwinding */ true)?; - return Ok(true); - } + let Ok(loc) = self.frame().loc else { + // We are unwinding and this fn has no cleanup code. + // Just go on unwinding. + trace!("unwinding: skipping frame"); + self.pop_stack_frame(/* unwinding */ true)?; + return Ok(true); }; let basic_block = &self.body().basic_blocks()[loc.block]; diff --git a/compiler/rustc_const_eval/src/interpret/terminator.rs b/compiler/rustc_const_eval/src/interpret/terminator.rs index f3910c9765d2e..8094bf0cf2e2f 100644 --- a/compiler/rustc_const_eval/src/interpret/terminator.rs +++ b/compiler/rustc_const_eval/src/interpret/terminator.rs @@ -321,10 +321,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { | ty::InstanceDef::CloneShim(..) | ty::InstanceDef::Item(_) => { // We need MIR for this fn - let (body, instance) = - match M::find_mir_or_eval_fn(self, instance, caller_abi, args, ret, unwind)? { - Some(body) => body, - None => return Ok(()), + let Some((body, instance)) = + M::find_mir_or_eval_fn(self, instance, caller_abi, args, ret, unwind)? else { + return Ok(()); }; // Compute callee information using the `instance` returned by diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index 4060bee7e056c..19c6449078d5b 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -33,7 +33,7 @@ macro_rules! throw_validation_failure { msg.push_str(", but expected "); write!(&mut msg, $($expected_fmt),+).unwrap(); )? - let path = rustc_middle::ty::print::with_no_trimmed_paths(|| { + let path = rustc_middle::ty::print::with_no_trimmed_paths!({ let where_ = &$where; if !where_.is_empty() { let mut path = String::new(); @@ -697,7 +697,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M> this.ecx.read_discriminant(op), this.path, err_ub!(InvalidTag(val)) => - { "{}", val } expected { "a valid enum tag" }, + { "{:x}", val } expected { "a valid enum tag" }, err_ub!(InvalidUninitBytes(None)) => { "uninitialized bytes" } expected { "a valid enum tag" }, err_unsup!(ReadPointerAsBytes) => @@ -851,12 +851,9 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M> // to reject those pointers, we just do not have the machinery to // talk about parts of a pointer. // We also accept uninit, for consistency with the slow path. - let alloc = match self.ecx.memory.get(mplace.ptr, size, mplace.align)? { - Some(a) => a, - None => { - // Size 0, nothing more to check. - return Ok(()); - } + let Some(alloc) = self.ecx.memory.get(mplace.ptr, size, mplace.align)? else { + // Size 0, nothing more to check. + return Ok(()); }; let allow_uninit_and_ptr = !M::enforce_number_validity(self.ecx); diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs index 095c8f84f41ad..652f1c94a6149 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs @@ -134,11 +134,8 @@ impl<'mir, 'tcx> Qualifs<'mir, 'tcx> { .find(|(_, block)| matches!(block.terminator().kind, TerminatorKind::Return)) .map(|(bb, _)| bb); - let return_block = match return_block { - None => { - return qualifs::in_any_value_of_ty(ccx, ccx.body.return_ty(), tainted_by_errors); - } - Some(bb) => bb, + let Some(return_block) = return_block else { + return qualifs::in_any_value_of_ty(ccx, ccx.body.return_ty(), tainted_by_errors); }; let return_loc = ccx.body.terminator_loc(return_block); diff --git a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs index 8c3f8e8816464..888c4b997dc30 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs @@ -108,9 +108,10 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> { .as_ref() .and_then(|node| node.generics()) { - let constraint = with_no_trimmed_paths(|| { - format!("~const {}", trait_ref.print_only_trait_path()) - }); + let constraint = with_no_trimmed_paths!(format!( + "~const {}", + trait_ref.print_only_trait_path() + )); suggest_constraining_type_param( tcx, generics, diff --git a/compiler/rustc_const_eval/src/transform/promote_consts.rs b/compiler/rustc_const_eval/src/transform/promote_consts.rs index cacc0018fe937..30764f689c95c 100644 --- a/compiler/rustc_const_eval/src/transform/promote_consts.rs +++ b/compiler/rustc_const_eval/src/transform/promote_consts.rs @@ -747,15 +747,12 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { if loc.statement_index < num_stmts { let (mut rvalue, source_info) = { let statement = &mut self.source[loc.block].statements[loc.statement_index]; - let rhs = match statement.kind { - StatementKind::Assign(box (_, ref mut rhs)) => rhs, - _ => { - span_bug!( - statement.source_info.span, - "{:?} is not an assignment", - statement - ); - } + let StatementKind::Assign(box (_, ref mut rhs)) = statement.kind else { + span_bug!( + statement.source_info.span, + "{:?} is not an assignment", + statement + ); }; ( diff --git a/compiler/rustc_const_eval/src/util/alignment.rs b/compiler/rustc_const_eval/src/util/alignment.rs index 73adc60577bfc..e4528b6890783 100644 --- a/compiler/rustc_const_eval/src/util/alignment.rs +++ b/compiler/rustc_const_eval/src/util/alignment.rs @@ -15,12 +15,9 @@ where L: HasLocalDecls<'tcx>, { debug!("is_disaligned({:?})", place); - let pack = match is_within_packed(tcx, local_decls, place) { - None => { - debug!("is_disaligned({:?}) - not within packed", place); - return false; - } - Some(pack) => pack, + let Some(pack) = is_within_packed(tcx, local_decls, place) else { + debug!("is_disaligned({:?}) - not within packed", place); + return false; }; let ty = place.ty(local_decls, tcx).ty; diff --git a/compiler/rustc_data_structures/src/binary_search_util/mod.rs b/compiler/rustc_data_structures/src/binary_search_util/mod.rs index bf09b2f8eef37..d40172a2e2fe8 100644 --- a/compiler/rustc_data_structures/src/binary_search_util/mod.rs +++ b/compiler/rustc_data_structures/src/binary_search_util/mod.rs @@ -10,9 +10,8 @@ pub fn binary_search_slice<'d, E, K>(data: &'d [E], key_fn: impl Fn(&E) -> K, ke where K: Ord, { - let mid = match data.binary_search_by_key(key, &key_fn) { - Ok(mid) => mid, - Err(_) => return &[], + let Ok(mid) = data.binary_search_by_key(key, &key_fn) else { + return &[]; }; let size = data.len(); diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs index 80f83140f4b41..ea02a73c42204 100644 --- a/compiler/rustc_data_structures/src/lib.rs +++ b/compiler/rustc_data_structures/src/lib.rs @@ -14,6 +14,7 @@ #![feature(control_flow_enum)] #![feature(core_intrinsics)] #![feature(extend_one)] +#![feature(let_else)] #![feature(hash_raw_entry)] #![feature(maybe_uninit_uninit_array)] #![feature(min_specialization)] diff --git a/compiler/rustc_data_structures/src/obligation_forest/mod.rs b/compiler/rustc_data_structures/src/obligation_forest/mod.rs index 25b7a84b3a069..5fe2a1fb84bd7 100644 --- a/compiler/rustc_data_structures/src/obligation_forest/mod.rs +++ b/compiler/rustc_data_structures/src/obligation_forest/mod.rs @@ -132,11 +132,11 @@ type ObligationTreeIdGenerator = std::iter::Map, fn(usize) -> ObligationTreeId>; pub struct ObligationForest { - /// The list of obligations. In between calls to `process_obligations`, + /// The list of obligations. In between calls to [Self::process_obligations], /// this list only contains nodes in the `Pending` or `Waiting` state. /// /// `usize` indices are used here and throughout this module, rather than - /// `rustc_index::newtype_index!` indices, because this code is hot enough + /// [`rustc_index::newtype_index!`] indices, because this code is hot enough /// that the `u32`-to-`usize` conversions that would be required are /// significant, and space considerations are not important. nodes: Vec>, @@ -146,10 +146,11 @@ pub struct ObligationForest { /// A cache of the nodes in `nodes`, indexed by predicate. Unfortunately, /// its contents are not guaranteed to match those of `nodes`. See the - /// comments in `process_obligation` for details. + /// comments in [`Self::process_obligation` for details. active_cache: FxHashMap, - /// A vector reused in compress() and find_cycles_from_node(), to avoid allocating new vectors. + /// A vector reused in [Self::compress()] and [Self::find_cycles_from_node()], + /// to avoid allocating new vectors. reused_node_vec: Vec, obligation_tree_id_generator: ObligationTreeIdGenerator, diff --git a/compiler/rustc_data_structures/src/stack.rs b/compiler/rustc_data_structures/src/stack.rs index a4964b7aa0cc8..3bdd67512321b 100644 --- a/compiler/rustc_data_structures/src/stack.rs +++ b/compiler/rustc_data_structures/src/stack.rs @@ -12,6 +12,7 @@ const STACK_PER_RECURSION: usize = 1 * 1024 * 1024; // 1MB /// from this. /// /// Should not be sprinkled around carelessly, as it causes a little bit of overhead. +#[inline] pub fn ensure_sufficient_stack(f: impl FnOnce() -> R) -> R { stacker::maybe_grow(RED_ZONE, STACK_PER_RECURSION, f) } diff --git a/compiler/rustc_data_structures/src/transitive_relation.rs b/compiler/rustc_data_structures/src/transitive_relation.rs index ccf8bd69ebd06..0af571610fe95 100644 --- a/compiler/rustc_data_structures/src/transitive_relation.rs +++ b/compiler/rustc_data_structures/src/transitive_relation.rs @@ -190,11 +190,8 @@ impl TransitiveRelation { /// /// Note that this set can, in principle, have any size. pub fn minimal_upper_bounds(&self, a: &T, b: &T) -> Vec<&T> { - let (mut a, mut b) = match (self.index(a), self.index(b)) { - (Some(a), Some(b)) => (a, b), - (None, _) | (_, None) => { - return vec![]; - } + let (Some(mut a), Some(mut b)) = (self.index(a), self.index(b)) else { + return vec![]; }; // in some cases, there are some arbitrary choices to be made; @@ -294,9 +291,8 @@ impl TransitiveRelation { /// then `parents(a)` returns `[b, c]`. The `postdom_parent` function /// would further reduce this to just `f`. pub fn parents(&self, a: &T) -> Vec<&T> { - let a = match self.index(a) { - Some(a) => a, - None => return vec![], + let Some(a) = self.index(a) else { + return vec![]; }; // Steal the algorithm for `minimal_upper_bounds` above, but diff --git a/compiler/rustc_driver/src/lib.rs b/compiler/rustc_driver/src/lib.rs index 85826cfbf0168..563ec8b0e3a70 100644 --- a/compiler/rustc_driver/src/lib.rs +++ b/compiler/rustc_driver/src/lib.rs @@ -6,6 +6,7 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![feature(nll)] +#![feature(let_else)] #![feature(once_cell)] #![recursion_limit = "256"] #![cfg_attr(not(bootstrap), allow(rustc::potential_query_instability))] @@ -203,10 +204,7 @@ fn run_compiler( let args = args::arg_expand_all(at_args); let diagnostic_output = emitter.map_or(DiagnosticOutput::Default, DiagnosticOutput::Raw); - let matches = match handle_options(&args) { - Some(matches) => matches, - None => return Ok(()), - }; + let Some(matches) = handle_options(&args) else { return Ok(()) }; let sopts = config::build_session_options(&matches); diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index f90f4d46a9a0b..bfed9211cec34 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -1138,9 +1138,8 @@ impl EmitterWriter { } fn get_multispan_max_line_num(&mut self, msp: &MultiSpan) -> usize { - let sm = match self.sm { - Some(ref sm) => sm, - None => return 0, + let Some(ref sm) = self.sm else { + return 0; }; let mut max = 0; @@ -1590,9 +1589,8 @@ impl EmitterWriter { level: &Level, max_line_num_len: usize, ) -> io::Result<()> { - let sm = match self.sm { - Some(ref sm) => sm, - None => return Ok(()), + let Some(ref sm) = self.sm else { + return Ok(()); }; // Render the replacements for each suggestion diff --git a/compiler/rustc_errors/src/json/tests.rs b/compiler/rustc_errors/src/json/tests.rs index c5b3d2044073f..ed01afe6e303d 100644 --- a/compiler/rustc_errors/src/json/tests.rs +++ b/compiler/rustc_errors/src/json/tests.rs @@ -5,17 +5,12 @@ use rustc_span::source_map::{FilePathMapping, SourceMap}; use crate::emitter::{ColorConfig, HumanReadableErrorType}; use crate::Handler; -use rustc_serialize::json::decode; +use rustc_serialize::json; use rustc_span::{BytePos, Span}; use std::str; -#[derive(Decodable, Debug, PartialEq, Eq)] -struct TestData { - spans: Vec, -} - -#[derive(Decodable, Debug, PartialEq, Eq)] +#[derive(Debug, PartialEq, Eq)] struct SpanTestData { pub byte_start: u32, pub byte_end: u32, @@ -41,8 +36,6 @@ impl Write for Shared { /// Test the span yields correct positions in JSON. fn test_positions(code: &str, span: (u32, u32), expected_output: SpanTestData) { - let expected_output = TestData { spans: vec![expected_output] }; - rustc_span::create_default_session_globals_then(|| { let sm = Lrc::new(SourceMap::new(FilePathMapping::empty())); sm.new_source_file(Path::new("test.rs").to_owned().into(), code.to_owned()); @@ -64,9 +57,19 @@ fn test_positions(code: &str, span: (u32, u32), expected_output: SpanTestData) { let bytes = output.lock().unwrap(); let actual_output = str::from_utf8(&bytes).unwrap(); - let actual_output: TestData = decode(actual_output); - - assert_eq!(expected_output, actual_output) + let actual_output = json::from_str(&actual_output).unwrap(); + let spans = actual_output["spans"].as_array().unwrap(); + assert_eq!(spans.len(), 1); + let obj = &spans[0]; + let actual_output = SpanTestData { + byte_start: obj["byte_start"].as_u64().unwrap() as u32, + byte_end: obj["byte_end"].as_u64().unwrap() as u32, + line_start: obj["line_start"].as_u64().unwrap() as u32, + line_end: obj["line_end"].as_u64().unwrap() as u32, + column_start: obj["column_start"].as_u64().unwrap() as u32, + column_end: obj["column_end"].as_u64().unwrap() as u32, + }; + assert_eq!(expected_output, actual_output); }) } diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index 258320aeb636a..2bdf3b3912619 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -1299,20 +1299,16 @@ pub fn parse_macro_name_and_helper_attrs( // Once we've located the `#[proc_macro_derive]` attribute, verify // that it's of the form `#[proc_macro_derive(Foo)]` or // `#[proc_macro_derive(Foo, attributes(A, ..))]` - let list = match attr.meta_item_list() { - Some(list) => list, - None => return None, + let Some(list) = attr.meta_item_list() else { + return None; }; if list.len() != 1 && list.len() != 2 { diag.span_err(attr.span, "attribute must have either one or two arguments"); return None; } - let trait_attr = match list[0].meta_item() { - Some(meta_item) => meta_item, - _ => { - diag.span_err(list[0].span(), "not a meta item"); - return None; - } + let Some(trait_attr) = list[0].meta_item() else { + diag.span_err(list[0].span(), "not a meta item"); + return None; }; let trait_ident = match trait_attr.ident() { Some(trait_ident) if trait_attr.is_word() => trait_ident, @@ -1341,12 +1337,9 @@ pub fn parse_macro_name_and_helper_attrs( }) .iter() .filter_map(|attr| { - let attr = match attr.meta_item() { - Some(meta_item) => meta_item, - _ => { - diag.span_err(attr.span(), "not a meta item"); - return None; - } + let Some(attr) = attr.meta_item() else { + diag.span_err(attr.span(), "not a meta item"); + return None; }; let ident = match attr.ident() { diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs index 5fa7ffd554ef1..c0d7bc359bf44 100644 --- a/compiler/rustc_expand/src/config.rs +++ b/compiler/rustc_expand/src/config.rs @@ -79,9 +79,8 @@ fn get_features( continue; } - let list = match attr.meta_item_list() { - Some(list) => list, - None => continue, + let Some(list) = attr.meta_item_list() else { + continue; }; for mi in list { @@ -112,9 +111,8 @@ fn get_features( continue; } - let list = match attr.meta_item_list() { - Some(list) => list, - None => continue, + let Some(list) = attr.meta_item_list() else { + continue; }; let bad_input = |span| { @@ -340,10 +338,9 @@ impl<'a> StripUnconfigured<'a> { /// is in the original source file. Gives a compiler error if the syntax of /// the attribute is incorrect. crate fn expand_cfg_attr(&self, attr: Attribute, recursive: bool) -> Vec { - let (cfg_predicate, expanded_attrs) = - match rustc_parse::parse_cfg_attr(&attr, &self.sess.parse_sess) { - None => return vec![], - Some(r) => r, + let Some((cfg_predicate, expanded_attrs)) = + rustc_parse::parse_cfg_attr(&attr, &self.sess.parse_sess) else { + return vec![]; }; // Lint on zero attributes in source. @@ -389,18 +386,16 @@ impl<'a> StripUnconfigured<'a> { // Use the `#` in `#[cfg_attr(pred, attr)]` as the `#` token // for `attr` when we expand it to `#[attr]` let mut orig_trees = orig_tokens.trees(); - let pound_token = match orig_trees.next().unwrap() { - TokenTree::Token(token @ Token { kind: TokenKind::Pound, .. }) => token, - _ => panic!("Bad tokens for attribute {:?}", attr), + let TokenTree::Token(pound_token @ Token { kind: TokenKind::Pound, .. }) = orig_trees.next().unwrap() else { + panic!("Bad tokens for attribute {:?}", attr); }; let pound_span = pound_token.span; let mut trees = vec![(AttrAnnotatedTokenTree::Token(pound_token), Spacing::Alone)]; if attr.style == AttrStyle::Inner { // For inner attributes, we do the same thing for the `!` in `#![some_attr]` - let bang_token = match orig_trees.next().unwrap() { - TokenTree::Token(token @ Token { kind: TokenKind::Not, .. }) => token, - _ => panic!("Bad tokens for attribute {:?}", attr), + let TokenTree::Token(bang_token @ Token { kind: TokenKind::Not, .. }) = orig_trees.next().unwrap() else { + panic!("Bad tokens for attribute {:?}", attr); }; trees.push((AttrAnnotatedTokenTree::Token(bang_token), Spacing::Alone)); } diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index 9a4daa6d7500a..bdc9c064a6f9c 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -641,9 +641,8 @@ impl<'a, 'b> MacroExpander<'a, 'b> { ExpandResult::Ready(match invoc.kind { InvocationKind::Bang { mac, .. } => match ext { SyntaxExtensionKind::Bang(expander) => { - let tok_result = match expander.expand(self.cx, span, mac.args.inner_tokens()) { - Err(_) => return ExpandResult::Ready(fragment_kind.dummy(span)), - Ok(ts) => ts, + let Ok(tok_result) = expander.expand(self.cx, span, mac.args.inner_tokens()) else { + return ExpandResult::Ready(fragment_kind.dummy(span)); }; self.parse_ast_fragment(tok_result, fragment_kind, &mac.path, span) } @@ -698,9 +697,8 @@ impl<'a, 'b> MacroExpander<'a, 'b> { self.cx.span_err(span, "key-value macro attributes are not supported"); } let inner_tokens = attr_item.args.inner_tokens(); - let tok_result = match expander.expand(self.cx, span, inner_tokens, tokens) { - Err(_) => return ExpandResult::Ready(fragment_kind.dummy(span)), - Ok(ts) => ts, + let Ok(tok_result) = expander.expand(self.cx, span, inner_tokens, tokens) else { + return ExpandResult::Ready(fragment_kind.dummy(span)); }; self.parse_ast_fragment(tok_result, fragment_kind, &attr_item.path, span) } diff --git a/compiler/rustc_expand/src/module.rs b/compiler/rustc_expand/src/module.rs index e9532dbe2ceca..aa54bdbd3a73d 100644 --- a/compiler/rustc_expand/src/module.rs +++ b/compiler/rustc_expand/src/module.rs @@ -170,23 +170,20 @@ fn mod_file_path_from_attr( ) -> Option { // Extract path string from first `#[path = "path_string"]` attribute. let first_path = attrs.iter().find(|at| at.has_name(sym::path))?; - let path_sym = match first_path.value_str() { - Some(s) => s, - None => { - // This check is here mainly to catch attempting to use a macro, - // such as #[path = concat!(...)]. This isn't currently supported - // because otherwise the InvocationCollector would need to defer - // loading a module until the #[path] attribute was expanded, and - // it doesn't support that (and would likely add a bit of - // complexity). Usually bad forms are checked in AstValidator (via - // `check_builtin_attribute`), but by the time that runs the macro - // is expanded, and it doesn't give an error. - validate_attr::emit_fatal_malformed_builtin_attribute( - &sess.parse_sess, - first_path, - sym::path, - ); - } + let Some(path_sym) = first_path.value_str() else { + // This check is here mainly to catch attempting to use a macro, + // such as #[path = concat!(...)]. This isn't currently supported + // because otherwise the InvocationCollector would need to defer + // loading a module until the #[path] attribute was expanded, and + // it doesn't support that (and would likely add a bit of + // complexity). Usually bad forms are checked in AstValidator (via + // `check_builtin_attribute`), but by the time that runs the macro + // is expanded, and it doesn't give an error. + validate_attr::emit_fatal_malformed_builtin_attribute( + &sess.parse_sess, + first_path, + sym::path, + ); }; let path_str = path_sym.as_str(); diff --git a/compiler/rustc_expand/src/proc_macro_server.rs b/compiler/rustc_expand/src/proc_macro_server.rs index efbe0b65715f4..99a945b1c913b 100644 --- a/compiler/rustc_expand/src/proc_macro_server.rs +++ b/compiler/rustc_expand/src/proc_macro_server.rs @@ -596,9 +596,8 @@ impl server::Literal for Rustc<'_, '_> { let minus_present = parser.eat(&token::BinOp(token::Minus)); let lit_span = parser.token.span.data(); - let mut lit = match parser.token.kind { - token::Literal(lit) => lit, - _ => return Err(()), + let token::Literal(mut lit) = parser.token.kind else { + return Err(()); }; // Check no comment or whitespace surrounding the (possibly negative) diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs index 32a9d081ed8c5..d43f926d0a56a 100644 --- a/compiler/rustc_feature/src/accepted.rs +++ b/compiler/rustc_feature/src/accepted.rs @@ -70,6 +70,8 @@ declare_features! ( (accepted, cfg_attr_multi, "1.33.0", Some(54881), None), /// Allows the use of `#[cfg(doctest)]`, set when rustdoc is collecting doctests. (accepted, cfg_doctest, "1.40.0", Some(62210), None), + /// Enables `#[cfg(panic = "...")]` config key. + (accepted, cfg_panic, "1.60.0", Some(77443), None), /// Allows `cfg(target_feature = "...")`. (accepted, cfg_target_feature, "1.27.0", Some(29717), None), /// Allows `cfg(target_vendor = "...")`. diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index 9cb12778a561f..5545abc6024af 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -306,8 +306,6 @@ declare_features! ( (active, c_variadic, "1.34.0", Some(44930), None), /// Allows capturing disjoint fields in a closure/generator (RFC 2229). (incomplete, capture_disjoint_fields, "1.49.0", Some(53488), None), - /// Enables `#[cfg(panic = "...")]` config key. - (active, cfg_panic, "1.49.0", Some(77443), None), /// Allows the use of `#[cfg(sanitize = "option")]`; set when -Zsanitizer is used. (active, cfg_sanitize, "1.41.0", Some(39699), None), /// Allows `cfg(target_abi = "...")`. diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index d9a986aba7d08..1fb1a38a927d5 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -34,7 +34,6 @@ const GATED_CFGS: &[GatedCfg] = &[ (sym::target_has_atomic_load_store, sym::cfg_target_has_atomic, cfg_fn!(cfg_target_has_atomic)), (sym::sanitize, sym::cfg_sanitize, cfg_fn!(cfg_sanitize)), (sym::version, sym::cfg_version, cfg_fn!(cfg_version)), - (sym::panic, sym::cfg_panic, cfg_fn!(cfg_panic)), ]; /// Find a gated cfg determined by the `pred`icate which is given the cfg's name. diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 0961d0131d07c..255e661652db9 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -635,9 +635,8 @@ pub struct WhereBoundPredicate<'hir> { impl<'hir> WhereBoundPredicate<'hir> { /// Returns `true` if `param_def_id` matches the `bounded_ty` of this predicate. pub fn is_param_bound(&self, param_def_id: DefId) -> bool { - let path = match self.bounded_ty.kind { - TyKind::Path(QPath::Resolved(None, path)) => path, - _ => return false, + let TyKind::Path(QPath::Resolved(None, path)) = self.bounded_ty.kind else { + return false; }; match path.res { Res::Def(DefKind::TyParam, def_id) diff --git a/compiler/rustc_hir/src/lib.rs b/compiler/rustc_hir/src/lib.rs index f1d62d03cbc98..ba3eeb91fe95f 100644 --- a/compiler/rustc_hir/src/lib.rs +++ b/compiler/rustc_hir/src/lib.rs @@ -5,6 +5,7 @@ #![feature(associated_type_defaults)] #![feature(const_btree_new)] #![feature(crate_visibility_modifier)] +#![feature(let_else)] #![feature(once_cell)] #![feature(min_specialization)] #![feature(never_type)] diff --git a/compiler/rustc_incremental/src/persist/dirty_clean.rs b/compiler/rustc_incremental/src/persist/dirty_clean.rs index 94c149dd23e6f..8a4ed02f6aea1 100644 --- a/compiler/rustc_incremental/src/persist/dirty_clean.rs +++ b/compiler/rustc_incremental/src/persist/dirty_clean.rs @@ -368,9 +368,8 @@ impl<'tcx> DirtyCleanVisitor<'tcx> { fn check_item(&mut self, item_id: LocalDefId, item_span: Span) { let def_path_hash = self.tcx.def_path_hash(item_id.to_def_id()); for attr in self.tcx.get_attrs(item_id.to_def_id()).iter() { - let assertion = match self.assertion_maybe(item_id, attr) { - Some(a) => a, - None => continue, + let Some(assertion) = self.assertion_maybe(item_id, attr) else { + continue; }; self.checked_attrs.insert(attr.id); for label in assertion.clean { diff --git a/compiler/rustc_incremental/src/persist/fs.rs b/compiler/rustc_incremental/src/persist/fs.rs index a49a1554d5bfe..a6da4b0bab683 100644 --- a/compiler/rustc_incremental/src/persist/fs.rs +++ b/compiler/rustc_incremental/src/persist/fs.rs @@ -421,9 +421,8 @@ fn copy_files(sess: &Session, target_dir: &Path, source_dir: &Path) -> Result it, - Err(_) => return Err(()), + let Ok(source_dir_iterator) = source_dir.read_dir() else { + return Err(()); }; let mut files_linked = 0; @@ -700,12 +699,9 @@ pub fn garbage_collect_session_directories(sess: &Session) -> io::Result<()> { let mut lock_files = FxHashSet::default(); for dir_entry in crate_directory.read_dir()? { - let dir_entry = match dir_entry { - Ok(dir_entry) => dir_entry, - _ => { - // Ignore any errors - continue; - } + let Ok(dir_entry) = dir_entry else { + // Ignore any errors + continue; }; let entry_name = dir_entry.file_name(); @@ -740,16 +736,13 @@ pub fn garbage_collect_session_directories(sess: &Session) -> io::Result<()> { // be some kind of leftover for (lock_file_name, directory_name) in &lock_file_to_session_dir { if directory_name.is_none() { - let timestamp = match extract_timestamp_from_session_dir(lock_file_name) { - Ok(timestamp) => timestamp, - Err(()) => { - debug!( - "found lock-file with malformed timestamp: {}", - crate_directory.join(&lock_file_name).display() - ); - // Ignore it - continue; - } + let Ok(timestamp) = extract_timestamp_from_session_dir(lock_file_name) else { + debug!( + "found lock-file with malformed timestamp: {}", + crate_directory.join(&lock_file_name).display() + ); + // Ignore it + continue; }; let lock_file_path = crate_directory.join(&**lock_file_name); @@ -798,16 +791,13 @@ pub fn garbage_collect_session_directories(sess: &Session) -> io::Result<()> { for (lock_file_name, directory_name) in &lock_file_to_session_dir { debug!("garbage_collect_session_directories() - inspecting: {}", directory_name); - let timestamp = match extract_timestamp_from_session_dir(directory_name) { - Ok(timestamp) => timestamp, - Err(()) => { - debug!( - "found session-dir with malformed timestamp: {}", - crate_directory.join(directory_name).display() - ); - // Ignore it - continue; - } + let Ok(timestamp) = extract_timestamp_from_session_dir(directory_name) else { + debug!( + "found session-dir with malformed timestamp: {}", + crate_directory.join(directory_name).display() + ); + // Ignore it + continue; }; if is_finalized(directory_name) { diff --git a/compiler/rustc_index/src/interval.rs b/compiler/rustc_index/src/interval.rs index 6da95053b116d..ed504938e8aa7 100644 --- a/compiler/rustc_index/src/interval.rs +++ b/compiler/rustc_index/src/interval.rs @@ -136,12 +136,9 @@ impl IntervalSet { pub fn contains(&self, needle: I) -> bool { let needle = needle.index() as u32; - let last = match self.map.partition_point(|r| r.0 <= needle).checked_sub(1) { - Some(idx) => idx, - None => { - // All ranges in the map start after the new range's end - return false; - } + let Some(last) = self.map.partition_point(|r| r.0 <= needle).checked_sub(1) else { + // All ranges in the map start after the new range's end + return false; }; let (_, prev_end) = &self.map[last]; needle <= *prev_end @@ -170,12 +167,9 @@ impl IntervalSet { if start > end { return None; } - let last = match self.map.partition_point(|r| r.0 <= end).checked_sub(1) { - Some(idx) => idx, - None => { - // All ranges in the map start after the new range's end - return None; - } + let Some(last) = self.map.partition_point(|r| r.0 <= end).checked_sub(1) else { + // All ranges in the map start after the new range's end + return None; }; let (_, prev_end) = &self.map[last]; if start <= *prev_end { Some(I::new(std::cmp::min(*prev_end, end) as usize)) } else { None } diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index d900379c44c62..c42ff168d8c65 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -69,7 +69,7 @@ use rustc_middle::ty::{ self, error::TypeError, subst::{GenericArgKind, Subst, SubstsRef}, - Binder, Region, Ty, TyCtxt, TypeFoldable, + Binder, List, Region, Ty, TyCtxt, TypeFoldable, }; use rustc_span::{sym, BytePos, DesugaringKind, MultiSpan, Pos, Span}; use rustc_target::spec::abi; @@ -1361,7 +1361,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { let mut values = (DiagnosticStyledString::normal("("), DiagnosticStyledString::normal("(")); let len = substs1.len(); - for (i, (left, right)) in substs1.types().zip(substs2.types()).enumerate() { + for (i, (left, right)) in substs1.iter().zip(substs2).enumerate() { let (x1, x2) = self.cmp(left, right); (values.0).0.extend(x1.0); (values.1).0.extend(x2.0); @@ -2042,8 +2042,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { // If a tuple of length one was expected and the found expression has // parentheses around it, perhaps the user meant to write `(expr,)` to // build a tuple (issue #86100) - (ty::Tuple(_), _) => { - self.emit_tuple_wrap_err(&mut err, span, found, expected) + (ty::Tuple(fields), _) => { + self.emit_tuple_wrap_err(&mut err, span, found, fields) } // If a character was expected and the found expression is a string literal // containing a single character, perhaps the user meant to write `'c'` to @@ -2111,12 +2111,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { err: &mut DiagnosticBuilder<'tcx>, span: Span, found: Ty<'tcx>, - expected: Ty<'tcx>, + expected_fields: &List>, ) { - let [expected_tup_elem] = &expected.tuple_fields().collect::>()[..] - else { return }; + let [expected_tup_elem] = expected_fields[..] else { return }; - if !same_type_modulo_infer(*expected_tup_elem, found) { + if !same_type_modulo_infer(expected_tup_elem, found) { return; } diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs index a61100d907bcf..1f5041301307a 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs @@ -254,7 +254,9 @@ fn closure_args(fn_sig: &ty::PolyFnSig<'_>) -> String { .skip_binder() .iter() .next() - .map(|args| args.tuple_fields().map(|arg| arg.to_string()).collect::>().join(", ")) + .map(|args| { + args.tuple_fields().iter().map(|arg| arg.to_string()).collect::>().join(", ") + }) .unwrap_or_default() } @@ -497,16 +499,32 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { let ty_to_string = |ty: Ty<'tcx>| -> String { let mut s = String::new(); let mut printer = ty::print::FmtPrinter::new(self.tcx, &mut s, Namespace::TypeNS); - let mut inner = self.inner.borrow_mut(); - let ty_vars = inner.type_variables(); - let getter = move |ty_vid| { - let var_origin = ty_vars.var_origin(ty_vid); - if let TypeVariableOriginKind::TypeParameterDefinition(name, _) = var_origin.kind { + let ty_getter = move |ty_vid| { + if let TypeVariableOriginKind::TypeParameterDefinition(name, _) = + self.inner.borrow_mut().type_variables().var_origin(ty_vid).kind + { + Some(name.to_string()) + } else { + None + } + }; + printer.ty_infer_name_resolver = Some(Box::new(ty_getter)); + let const_getter = move |ct_vid| { + if let ConstVariableOriginKind::ConstParameterDefinition(name, _) = self + .inner + .borrow_mut() + .const_unification_table() + .probe_value(ct_vid) + .origin + .kind + { return Some(name.to_string()); + } else { + None } - None }; - printer.name_resolver = Some(Box::new(&getter)); + printer.const_infer_name_resolver = Some(Box::new(const_getter)); + let _ = if let ty::FnDef(..) = ty.kind() { // We don't want the regular output for `fn`s because it includes its path in // invalid pseudo-syntax, we want the `fn`-pointer output instead. diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs index ef4c9c24f3eb9..2bc2f78261df3 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs @@ -18,16 +18,14 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { let error = self.error.as_ref()?; debug!("try_report_mismatched_static_lifetime {:?}", error); - let (origin, sub, sup) = match error.clone() { - RegionResolutionError::ConcreteFailure(origin, sub, sup) => (origin, sub, sup), - _ => return None, + let RegionResolutionError::ConcreteFailure(origin, sub, sup) = error.clone() else { + return None; }; if !sub.is_static() { return None; } - let cause = match origin { - SubregionOrigin::Subtype(box TypeTrace { ref cause, .. }) => cause, - _ => return None, + let SubregionOrigin::Subtype(box TypeTrace { ref cause, .. }) = origin else { + return None; }; // If we added a "points at argument expression" obligation, we remove it here, we care // about the original obligation only. @@ -35,13 +33,11 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { ObligationCauseCode::FunctionArgumentObligation { parent_code, .. } => &*parent_code, _ => cause.code(), }; - let (parent, impl_def_id) = match code { - ObligationCauseCode::MatchImpl(parent, impl_def_id) => (parent, impl_def_id), - _ => return None, + let ObligationCauseCode::MatchImpl(parent, impl_def_id) = code else { + return None; }; - let binding_span = match *parent.code() { - ObligationCauseCode::BindingObligation(_def_id, binding_span) => binding_span, - _ => return None, + let ObligationCauseCode::BindingObligation(_def_id, binding_span) = *parent.code() else { + return None; }; let mut err = self.tcx().sess.struct_span_err(cause.span, "incompatible lifetime on type"); // FIXME: we should point at the lifetime @@ -55,12 +51,11 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { // be as helpful as possible with implicit lifetimes. // First, let's get the hir self type of the impl - let impl_self_ty = match impl_node { - hir::Node::Item(hir::Item { - kind: hir::ItemKind::Impl(hir::Impl { self_ty, .. }), - .. - }) => self_ty, - _ => bug!("Node not an impl."), + let hir::Node::Item(hir::Item { + kind: hir::ItemKind::Impl(hir::Impl { self_ty: impl_self_ty, .. }), + .. + }) = impl_node else { + bug!("Node not an impl."); }; // Next, let's figure out the set of trait objects with implict static bounds diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs index 625fd8642186d..8601180842ccc 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs @@ -490,14 +490,13 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { let tcx = self.tcx(); // Find the method being called. - let instance = match ty::Instance::resolve( + let Ok(Some(instance)) = ty::Instance::resolve( tcx, ctxt.param_env, ctxt.assoc_item.def_id, self.infcx.resolve_vars_if_possible(ctxt.substs), - ) { - Ok(Some(instance)) => instance, - _ => return false, + ) else { + return false; }; let mut v = TraitObjectVisitor(FxHashSet::default()); @@ -505,11 +504,9 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { // Get the `Ident` of the method being called and the corresponding `impl` (to point at // `Bar` in `impl Foo for dyn Bar {}` and the definition of the method being called). - let (ident, self_ty) = - match self.get_impl_ident_and_self_ty_from_trait(instance.def_id(), &v.0) { - Some((ident, self_ty)) => (ident, self_ty), - None => return false, - }; + let Some((ident, self_ty)) = self.get_impl_ident_and_self_ty_from_trait(instance.def_id(), &v.0) else { + return false; + }; // Find the trait object types in the argument, so we point at *only* the trait object. self.suggest_constrain_dyn_trait_in_impl(err, &v.0, ident, self_ty) diff --git a/compiler/rustc_infer/src/infer/higher_ranked/mod.rs b/compiler/rustc_infer/src/infer/higher_ranked/mod.rs index 82454b89156a6..652f5abab151f 100644 --- a/compiler/rustc_infer/src/infer/higher_ranked/mod.rs +++ b/compiler/rustc_infer/src/infer/higher_ranked/mod.rs @@ -123,7 +123,9 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { result } - /// See `infer::region_constraints::RegionConstraintCollector::leak_check`. + /// See [RegionConstraintCollector::leak_check][1]. + /// + /// [1]: crate::infer::region_constraints::RegionConstraintCollector::leak_check pub fn leak_check( &self, overly_polymorphic: bool, diff --git a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs index 4e50585ff524f..c7b4a96fb7853 100644 --- a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs +++ b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs @@ -263,9 +263,8 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> { while let Some(vid) = changes.pop() { constraints[vid].retain(|&(a_vid, b_vid)| { - let a_region = match *var_values.value(a_vid) { - VarValue::ErrorValue => return false, - VarValue::Value(a_region) => a_region, + let VarValue::Value(a_region) = *var_values.value(a_vid) else { + return false; }; let b_data = var_values.value_mut(b_vid); if self.expand_node(a_region, b_vid, b_data) { @@ -485,9 +484,8 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> { let a_data = var_data.value_mut(a_vid); debug!("contraction: {:?} == {:?}, {:?}", a_vid, a_data, b_region); - let a_region = match *a_data { - VarValue::ErrorValue => continue, - VarValue::Value(a_region) => a_region, + let VarValue::Value(a_region) = *a_data else { + continue; }; // Do not report these errors immediately: diff --git a/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs b/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs index 36d18aebfe2a0..817aaf10053ef 100644 --- a/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs +++ b/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs @@ -100,6 +100,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> { struct LeakCheck<'me, 'tcx> { tcx: TyCtxt<'tcx>, universe_at_start_of_snapshot: ty::UniverseIndex, + /// Only used when reporting region errors. overly_polymorphic: bool, mini_graph: &'me MiniGraph<'tcx>, rcc: &'me RegionConstraintCollector<'me, 'tcx>, diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs index 89390ee1d6ccd..4af69f7cd2ee6 100644 --- a/compiler/rustc_interface/src/queries.rs +++ b/compiler/rustc_interface/src/queries.rs @@ -259,10 +259,7 @@ impl<'tcx> Queries<'tcx> { /// to write UI tests that actually test that compilation succeeds without reporting /// an error. fn check_for_rustc_errors_attr(tcx: TyCtxt<'_>) { - let def_id = match tcx.entry_fn(()) { - Some((def_id, _)) => def_id, - _ => return, - }; + let Some((def_id, _)) = tcx.entry_fn(()) else { return }; let attrs = &*tcx.get_attrs(def_id); let attrs = attrs.iter().filter(|attr| attr.has_name(sym::rustc_error)); diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index 46964f5268509..83b54810db2f2 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -430,10 +430,7 @@ fn get_codegen_sysroot(maybe_sysroot: &Option, backend_name: &str) -> M ]; for entry in d.filter_map(|e| e.ok()) { let path = entry.path(); - let filename = match path.file_name().and_then(|s| s.to_str()) { - Some(s) => s, - None => continue, - }; + let Some(filename) = path.file_name().and_then(|s| s.to_str()) else { continue }; if !(filename.starts_with(DLL_PREFIX) && filename.ends_with(DLL_SUFFIX)) { continue; } diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index a397db7f32921..30b5f9b34d099 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -2621,7 +2621,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue { } Tuple(..) => { // Proceed recursively, check all fields. - ty.tuple_fields().find_map(|field| ty_find_init_error(tcx, field, init)) + ty.tuple_fields().iter().find_map(|field| ty_find_init_error(tcx, field, init)) } // Conservative fallback. _ => None, @@ -2634,7 +2634,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue { // We are extremely conservative with what we warn about. let conjured_ty = cx.typeck_results().expr_ty(expr); if let Some((msg, span)) = - with_no_trimmed_paths(|| ty_find_init_error(cx.tcx, conjured_ty, init)) + with_no_trimmed_paths!(ty_find_init_error(cx.tcx, conjured_ty, init)) { cx.struct_span_lint(INVALID_VALUE, expr.span, |lint| { let mut err = lint.build(&format!( @@ -2934,7 +2934,7 @@ impl ClashingExternDeclarations { ) } (Tuple(a_substs), Tuple(b_substs)) => { - a_substs.types().eq_by(b_substs.types(), |a_ty, b_ty| { + a_substs.iter().eq_by(b_substs.iter(), |a_ty, b_ty| { structurally_same_type_impl(seen_types, cx, a_ty, b_ty, ckind) }) } diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index d2d853efda2d2..d8f55292ccd8d 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -278,9 +278,8 @@ impl LintStore { /// This lint has been renamed; warn about using the new name and apply the lint. #[track_caller] pub fn register_renamed(&mut self, old_name: &str, new_name: &str) { - let target = match self.by_name.get(new_name) { - Some(&Id(lint_id)) => lint_id, - _ => bug!("invalid lint renaming of {} to {}", old_name, new_name), + let Some(&Id(target)) = self.by_name.get(new_name) else { + bug!("invalid lint renaming of {} to {}", old_name, new_name); }; self.by_name.insert(old_name.to_string(), Renamed(new_name.to_string(), target)); } @@ -994,7 +993,7 @@ impl<'tcx> LateContext<'tcx> { } // This shouldn't ever be needed, but just in case: - with_no_trimmed_paths(|| { + with_no_trimmed_paths!({ Ok(vec![match trait_ref { Some(trait_ref) => Symbol::intern(&format!("{:?}", trait_ref)), None => Symbol::intern(&format!("<{}>", self_ty)), @@ -1013,15 +1012,15 @@ impl<'tcx> LateContext<'tcx> { // This shouldn't ever be needed, but just in case: path.push(match trait_ref { - Some(trait_ref) => with_no_trimmed_paths(|| { - Symbol::intern(&format!( + Some(trait_ref) => { + with_no_trimmed_paths!(Symbol::intern(&format!( "", trait_ref.print_only_trait_path(), self_ty - )) - }), + ))) + } None => { - with_no_trimmed_paths(|| Symbol::intern(&format!("", self_ty))) + with_no_trimmed_paths!(Symbol::intern(&format!("", self_ty))) } }); diff --git a/compiler/rustc_lint/src/internal.rs b/compiler/rustc_lint/src/internal.rs index 944a099642755..5078c240ec753 100644 --- a/compiler/rustc_lint/src/internal.rs +++ b/compiler/rustc_lint/src/internal.rs @@ -23,10 +23,7 @@ declare_lint_pass!(DefaultHashTypes => [DEFAULT_HASH_TYPES]); impl LateLintPass<'_> for DefaultHashTypes { fn check_path(&mut self, cx: &LateContext<'_>, path: &Path<'_>, hir_id: HirId) { - let def_id = match path.res { - Res::Def(rustc_hir::def::DefKind::Struct, id) => id, - _ => return, - }; + let Res::Def(rustc_hir::def::DefKind::Struct, def_id) = path.res else { return }; if matches!(cx.tcx.hir().get(hir_id), Node::Item(Item { kind: ItemKind::Use(..), .. })) { // don't lint imports, only actual usages return; diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs index 8afbd462c146b..35c7d885e1d74 100644 --- a/compiler/rustc_lint/src/levels.rs +++ b/compiler/rustc_lint/src/levels.rs @@ -95,9 +95,9 @@ impl<'s> LintLevelsBuilder<'s> { let orig_level = level; let lint_flag_val = Symbol::intern(lint_name); - let ids = match store.find_lints(&lint_name) { - Ok(ids) => ids, - Err(_) => continue, // errors handled in check_lint_name_cmdline above + let Ok(ids) = store.find_lints(&lint_name) else { + // errors handled in check_lint_name_cmdline above + continue }; for id in ids { // ForceWarn and Forbid cannot be overriden diff --git a/compiler/rustc_lint/src/non_ascii_idents.rs b/compiler/rustc_lint/src/non_ascii_idents.rs index 2dd6dbd67a8d2..264a80339ccdb 100644 --- a/compiler/rustc_lint/src/non_ascii_idents.rs +++ b/compiler/rustc_lint/src/non_ascii_idents.rs @@ -301,10 +301,7 @@ impl EarlyLintPass for NonAsciiIdents { BTreeMap::new(); 'outerloop: for (augment_script_set, usage) in script_states { - let (mut ch_list, sp) = match usage { - ScriptSetUsage::Verified => continue, - ScriptSetUsage::Suspicious(ch_list, sp) => (ch_list, sp), - }; + let ScriptSetUsage::Suspicious(mut ch_list, sp) = usage else { continue }; if augment_script_set.is_all() { continue; diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index fc88e8cd912ea..5cd3791583f9a 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -1331,14 +1331,7 @@ impl<'tcx> LateLintPass<'tcx> for VariantSizeDifferences { if let hir::ItemKind::Enum(ref enum_definition, _) = it.kind { let t = cx.tcx.type_of(it.def_id); let ty = cx.tcx.erase_regions(t); - let layout = match cx.layout_of(ty) { - Ok(layout) => layout, - Err( - ty::layout::LayoutError::Unknown(_) - | ty::layout::LayoutError::SizeOverflow(_) - | ty::layout::LayoutError::NormalizationFailure(_, _), - ) => return, - }; + let Ok(layout) = cx.layout_of(ty) else { return }; let Variants::Multiple { tag_encoding: TagEncoding::Direct, tag, ref variants, .. } = &layout.variants else { diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index 755e24d541398..b71ffa43d85dc 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -246,7 +246,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { } else { vec![] }; - for (i, ty) in tys.iter().map(|k| k.expect_ty()).enumerate() { + for (i, ty) in tys.iter().enumerate() { let descr_post = &format!(" in tuple element {}", i); let span = *spans.get(i).unwrap_or(&span); if check_must_use_ty(cx, ty, expr, span, descr_pre, descr_post, plural_len) diff --git a/compiler/rustc_macros/src/query.rs b/compiler/rustc_macros/src/query.rs index 478159147acbd..a6912653368b5 100644 --- a/compiler/rustc_macros/src/query.rs +++ b/compiler/rustc_macros/src/query.rs @@ -434,7 +434,9 @@ fn add_query_description_impl( #[allow(unused_variables)] fn describe(tcx: QueryCtxt<$tcx>, key: Self::Key) -> String { let (#tcx, #key) = (*tcx, key); - ::rustc_middle::ty::print::with_no_trimmed_paths(|| format!(#desc).into()) + ::rustc_middle::ty::print::with_no_trimmed_paths!( + format!(#desc) + ) } }; diff --git a/compiler/rustc_macros/src/serialize.rs b/compiler/rustc_macros/src/serialize.rs index 6c5461505fa26..535158ffd8d84 100644 --- a/compiler/rustc_macros/src/serialize.rs +++ b/compiler/rustc_macros/src/serialize.rs @@ -42,51 +42,26 @@ fn decodable_body( } let ty_name = s.ast().ident.to_string(); let decode_body = match s.variants() { - [vi] => { - let construct = vi.construct(|field, index| decode_field(field, index, true)); - quote! { - ::rustc_serialize::Decoder::read_struct( - __decoder, - |__decoder| { #construct }, - ) - } - } + [vi] => vi.construct(|field, _index| decode_field(field)), variants => { let match_inner: TokenStream = variants .iter() .enumerate() .map(|(idx, vi)| { - let construct = vi.construct(|field, index| decode_field(field, index, false)); + let construct = vi.construct(|field, _index| decode_field(field)); quote! { #idx => { #construct } } }) .collect(); - let names: TokenStream = variants - .iter() - .map(|vi| { - let variant_name = vi.ast().ident.to_string(); - quote!(#variant_name,) - }) - .collect(); let message = format!( "invalid enum variant tag while decoding `{}`, expected 0..{}", ty_name, variants.len() ); quote! { - ::rustc_serialize::Decoder::read_enum( - __decoder, - |__decoder| { - ::rustc_serialize::Decoder::read_enum_variant( - __decoder, - &[#names], - |__decoder, __variant_idx| { - match __variant_idx { - #match_inner - _ => panic!(#message), - } - }) - } - ) + match ::rustc_serialize::Decoder::read_usize(__decoder) { + #match_inner + _ => panic!(#message), + } } } }; @@ -101,7 +76,7 @@ fn decodable_body( ) } -fn decode_field(field: &syn::Field, index: usize, is_struct: bool) -> proc_macro2::TokenStream { +fn decode_field(field: &syn::Field) -> proc_macro2::TokenStream { let field_span = field.ident.as_ref().map_or(field.ty.span(), |ident| ident.span()); let decode_inner_method = if let syn::Type::Reference(_) = field.ty { @@ -109,22 +84,10 @@ fn decode_field(field: &syn::Field, index: usize, is_struct: bool) -> proc_macro } else { quote! { ::rustc_serialize::Decodable::decode } }; - let (decode_method, opt_field_name) = if is_struct { - let field_name = field.ident.as_ref().map_or_else(|| index.to_string(), |i| i.to_string()); - (proc_macro2::Ident::new("read_struct_field", field_span), quote! { #field_name, }) - } else { - (proc_macro2::Ident::new("read_enum_variant_arg", field_span), quote! {}) - }; - let __decoder = quote! { __decoder }; // Use the span of the field for the method call, so // that backtraces will point to the field. - let decode_call = quote_spanned! {field_span=> - ::rustc_serialize::Decoder::#decode_method( - #__decoder, #opt_field_name #decode_inner_method) - }; - - quote! { #decode_call } + quote_spanned! {field_span=> #decode_inner_method(#__decoder) } } pub fn type_encodable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream { diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index 36a1798cd6a86..7343f1465f603 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -475,9 +475,8 @@ impl<'a> CrateLoader<'a> { locator.triple = TargetTriple::from_triple(config::host_triple()); locator.filesearch = self.sess.host_filesearch(path_kind); - let host_result = match self.load(locator)? { - Some(host_result) => host_result, - None => return Ok(None), + let Some(host_result) = self.load(locator)? else { + return Ok(None); }; Ok(Some(if self.sess.opts.debugging_opts.dual_proc_macros { @@ -574,9 +573,8 @@ impl<'a> CrateLoader<'a> { } fn load(&self, locator: &mut CrateLocator<'_>) -> Result, CrateError> { - let library = match locator.maybe_load_library_crate()? { - Some(library) => library, - None => return Ok(None), + let Some(library) = locator.maybe_load_library_crate()? else { + return Ok(None); }; // In the case that we're loading a crate, but not matching diff --git a/compiler/rustc_metadata/src/foreign_modules.rs b/compiler/rustc_metadata/src/foreign_modules.rs index c70a691452018..c4ee1e191286d 100644 --- a/compiler/rustc_metadata/src/foreign_modules.rs +++ b/compiler/rustc_metadata/src/foreign_modules.rs @@ -15,9 +15,8 @@ struct Collector { impl<'tcx> ItemLikeVisitor<'tcx> for Collector { fn visit_item(&mut self, it: &'tcx hir::Item<'tcx>) { - let items = match it.kind { - hir::ItemKind::ForeignMod { items, .. } => items, - _ => return, + let hir::ItemKind::ForeignMod { items, .. } = it.kind else { + return; }; let foreign_items = items.iter().map(|it| it.id.def_id.to_def_id()).collect(); diff --git a/compiler/rustc_metadata/src/locator.rs b/compiler/rustc_metadata/src/locator.rs index 550b22a2a3c65..2204b44e3a10d 100644 --- a/compiler/rustc_metadata/src/locator.rs +++ b/compiler/rustc_metadata/src/locator.rs @@ -690,14 +690,11 @@ impl<'a> CrateLocator<'a> { loc.original().clone(), )); } - let file = match loc.original().file_name().and_then(|s| s.to_str()) { - Some(file) => file, - None => { - return Err(CrateError::ExternLocationNotFile( - self.crate_name, - loc.original().clone(), - )); - } + let Some(file) = loc.original().file_name().and_then(|s| s.to_str()) else { + return Err(CrateError::ExternLocationNotFile( + self.crate_name, + loc.original().clone(), + )); }; if file.starts_with("lib") && (file.ends_with(".rlib") || file.ends_with(".rmeta")) diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs index 88292a4422419..0f10c269a04a3 100644 --- a/compiler/rustc_metadata/src/native_libs.rs +++ b/compiler/rustc_metadata/src/native_libs.rs @@ -33,9 +33,8 @@ struct Collector<'tcx> { impl<'tcx> ItemLikeVisitor<'tcx> for Collector<'tcx> { fn visit_item(&mut self, it: &'tcx hir::Item<'tcx>) { - let (abi, foreign_mod_items) = match it.kind { - hir::ItemKind::ForeignMod { abi, items } => (abi, items), - _ => return, + let hir::ItemKind::ForeignMod { abi, items: foreign_mod_items } = it.kind else { + return; }; if abi == Abi::Rust || abi == Abi::RustIntrinsic || abi == Abi::PlatformIntrinsic { @@ -45,9 +44,8 @@ impl<'tcx> ItemLikeVisitor<'tcx> for Collector<'tcx> { // Process all of the #[link(..)]-style arguments let sess = &self.tcx.sess; for m in self.tcx.hir().attrs(it.hir_id()).iter().filter(|a| a.has_name(sym::link)) { - let items = match m.meta_item_list() { - Some(item) => item, - None => continue, + let Some(items) = m.meta_item_list() else { + continue; }; let mut lib = NativeLib { name: None, @@ -63,9 +61,8 @@ impl<'tcx> ItemLikeVisitor<'tcx> for Collector<'tcx> { for item in items.iter() { if item.has_name(sym::kind) { kind_specified = true; - let kind = match item.value_str() { - Some(name) => name, - None => continue, // skip like historical compilers + let Some(kind) = item.value_str() else { + continue; // skip like historical compilers }; lib.kind = match kind.as_str() { "static" => NativeLibKind::Static { bundle: None, whole_archive: None }, @@ -101,9 +98,8 @@ impl<'tcx> ItemLikeVisitor<'tcx> for Collector<'tcx> { } else if item.has_name(sym::name) { lib.name = item.value_str(); } else if item.has_name(sym::cfg) { - let cfg = match item.meta_item_list() { - Some(list) => list, - None => continue, // skip like historical compilers + let Some(cfg) = item.meta_item_list() else { + continue; // skip like historical compilers }; if cfg.is_empty() { sess.span_err(item.span(), "`cfg()` must have an argument"); @@ -262,11 +258,8 @@ impl Collector<'_> { } // this just unwraps lib.name; we already established that it isn't empty above. if let (NativeLibKind::RawDylib, Some(lib_name)) = (lib.kind, lib.name) { - let span = match span { - Some(s) => s, - None => { - bug!("raw-dylib libraries are not supported on the command line"); - } + let Some(span) = span else { + bug!("raw-dylib libraries are not supported on the command line"); }; if !self.tcx.sess.target.options.is_like_windows { diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index 7708b5193f450..ce61fd20a7b1e 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -249,9 +249,8 @@ pub(in crate::rmeta) fn provide(providers: &mut Providers) { .iter() .filter(|lib| native_libs::relevant_lib(&tcx.sess, lib)) .find(|lib| { - let fm_id = match lib.foreign_module { - Some(id) => id, - None => return false, + let Some(fm_id) = lib.foreign_module else { + return false; }; let map = tcx.foreign_modules(id.krate); map.get(&fm_id) diff --git a/compiler/rustc_middle/src/hir/nested_filter.rs b/compiler/rustc_middle/src/hir/nested_filter.rs index 7cfb20745720d..48efae8045bdd 100644 --- a/compiler/rustc_middle/src/hir/nested_filter.rs +++ b/compiler/rustc_middle/src/hir/nested_filter.rs @@ -3,6 +3,10 @@ use rustc_hir::intravisit::nested_filter::NestedFilter; /// Do not visit nested item-like things, but visit nested things /// that are inside of an item-like. /// +/// Notably, possible occurrences of bodies in non-item-like things +/// include: closures/generators, inline `const {}` blocks, and +/// constant arguments of types, e.g. in `let _: [(); /* HERE */];`. +/// /// **This is the most common choice.** A very common pattern is /// to use `visit_all_item_likes()` as an outer loop, /// and to have the visitor that visits the contents of each item diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs index e85cb413deb2a..d3de54b4950f6 100644 --- a/compiler/rustc_middle/src/lib.rs +++ b/compiler/rustc_middle/src/lib.rs @@ -55,6 +55,7 @@ #![feature(try_reserve_kind)] #![feature(nonzero_ops)] #![feature(unwrap_infallible)] +#![feature(decl_macro)] #![recursion_limit = "512"] #![cfg_attr(not(bootstrap), allow(rustc::potential_query_instability))] diff --git a/compiler/rustc_middle/src/lint.rs b/compiler/rustc_middle/src/lint.rs index 17c77c1bbd891..294c70f24f8b1 100644 --- a/compiler/rustc_middle/src/lint.rs +++ b/compiler/rustc_middle/src/lint.rs @@ -202,6 +202,77 @@ impl<'a> LintDiagnosticBuilder<'a> { } } +pub fn explain_lint_level_source<'s>( + sess: &'s Session, + lint: &'static Lint, + level: Level, + src: LintLevelSource, + err: &mut DiagnosticBuilder<'s>, +) { + let name = lint.name_lower(); + match src { + LintLevelSource::Default => { + sess.diag_note_once( + err, + DiagnosticMessageId::from(lint), + &format!("`#[{}({})]` on by default", level.as_str(), name), + ); + } + LintLevelSource::CommandLine(lint_flag_val, orig_level) => { + let flag = match orig_level { + Level::Warn => "-W", + Level::Deny => "-D", + Level::Forbid => "-F", + Level::Allow => "-A", + Level::ForceWarn => "--force-warn", + }; + let hyphen_case_lint_name = name.replace('_', "-"); + if lint_flag_val.as_str() == name { + sess.diag_note_once( + err, + DiagnosticMessageId::from(lint), + &format!( + "requested on the command line with `{} {}`", + flag, hyphen_case_lint_name + ), + ); + } else { + let hyphen_case_flag_val = lint_flag_val.as_str().replace('_', "-"); + sess.diag_note_once( + err, + DiagnosticMessageId::from(lint), + &format!( + "`{} {}` implied by `{} {}`", + flag, hyphen_case_lint_name, flag, hyphen_case_flag_val + ), + ); + } + } + LintLevelSource::Node(lint_attr_name, src, reason) => { + if let Some(rationale) = reason { + err.note(rationale.as_str()); + } + sess.diag_span_note_once( + err, + DiagnosticMessageId::from(lint), + src, + "the lint level is defined here", + ); + if lint_attr_name.as_str() != name { + let level_str = level.as_str(); + sess.diag_note_once( + err, + DiagnosticMessageId::from(lint), + &format!( + "`#[{}({})]` implied by `#[{}({})]`", + level_str, name, level_str, lint_attr_name + ), + ); + } + } + } +} + pub fn struct_lint_level<'s, 'd>( sess: &'s Session, lint: &'static Lint, @@ -277,69 +348,9 @@ pub fn struct_lint_level<'s, 'd>( } } - let name = lint.name_lower(); - match src { - LintLevelSource::Default => { - sess.diag_note_once( - &mut err, - DiagnosticMessageId::from(lint), - &format!("`#[{}({})]` on by default", level.as_str(), name), - ); - } - LintLevelSource::CommandLine(lint_flag_val, orig_level) => { - let flag = match orig_level { - Level::Warn => "-W", - Level::Deny => "-D", - Level::Forbid => "-F", - Level::Allow => "-A", - Level::ForceWarn => "--force-warn", - }; - let hyphen_case_lint_name = name.replace('_', "-"); - if lint_flag_val.as_str() == name { - sess.diag_note_once( - &mut err, - DiagnosticMessageId::from(lint), - &format!( - "requested on the command line with `{} {}`", - flag, hyphen_case_lint_name - ), - ); - } else { - let hyphen_case_flag_val = lint_flag_val.as_str().replace('_', "-"); - sess.diag_note_once( - &mut err, - DiagnosticMessageId::from(lint), - &format!( - "`{} {}` implied by `{} {}`", - flag, hyphen_case_lint_name, flag, hyphen_case_flag_val - ), - ); - } - } - LintLevelSource::Node(lint_attr_name, src, reason) => { - if let Some(rationale) = reason { - err.note(rationale.as_str()); - } - sess.diag_span_note_once( - &mut err, - DiagnosticMessageId::from(lint), - src, - "the lint level is defined here", - ); - if lint_attr_name.as_str() != name { - let level_str = level.as_str(); - sess.diag_note_once( - &mut err, - DiagnosticMessageId::from(lint), - &format!( - "`#[{}({})]` implied by `#[{}({})]`", - level_str, name, level_str, lint_attr_name - ), - ); - } - } - } + explain_lint_level_source(sess, lint, level, src, &mut err); + let name = lint.name_lower(); let is_force_warn = matches!(level, Level::ForceWarn); err.code(DiagnosticId::Lint { name, has_future_breakage, is_force_warn }); diff --git a/compiler/rustc_middle/src/middle/region.rs b/compiler/rustc_middle/src/middle/region.rs index 75dd223d014d4..6124d14070266 100644 --- a/compiler/rustc_middle/src/middle/region.rs +++ b/compiler/rustc_middle/src/middle/region.rs @@ -173,9 +173,8 @@ impl Scope { /// returned span may not correspond to the span of any `NodeId` in /// the AST. pub fn span(&self, tcx: TyCtxt<'_>, scope_tree: &ScopeTree) -> Span { - let hir_id = match self.hir_id(scope_tree) { - Some(hir_id) => hir_id, - None => return DUMMY_SP, + let Some(hir_id) = self.hir_id(scope_tree) else { + return DUMMY_SP; }; let span = tcx.hir().span(hir_id); if let ScopeData::Remainder(first_statement_index) = self.data { diff --git a/compiler/rustc_middle/src/middle/stability.rs b/compiler/rustc_middle/src/middle/stability.rs index fedf456ccc88f..ac4a5985c2f1c 100644 --- a/compiler/rustc_middle/src/middle/stability.rs +++ b/compiler/rustc_middle/src/middle/stability.rs @@ -367,7 +367,7 @@ impl<'tcx> TyCtxt<'tcx> { let is_in_effect = deprecation_in_effect(depr_attr); let lint = deprecation_lint(is_in_effect); if self.lint_level_at_node(lint, id).0 != Level::Allow { - let def_path = &with_no_trimmed_paths(|| self.def_path_str(def_id)); + let def_path = with_no_trimmed_paths!(self.def_path_str(def_id)); let def_kind = self.def_kind(def_id).descr(def_id); late_report_deprecation( @@ -377,7 +377,7 @@ impl<'tcx> TyCtxt<'tcx> { depr_attr.since, depr_attr.note, def_kind, - def_path, + &def_path, ), depr_attr.suggestion, lint, diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs index e9a857d09124f..c5866924eda43 100644 --- a/compiler/rustc_middle/src/mir/interpret/error.rs +++ b/compiler/rustc_middle/src/mir/interpret/error.rs @@ -370,7 +370,7 @@ impl fmt::Display for UndefinedBehaviorInfo<'_> { InvalidChar(c) => { write!(f, "interpreting an invalid 32-bit value as a char: 0x{:08x}", c) } - InvalidTag(val) => write!(f, "enum value has invalid tag: {}", val), + InvalidTag(val) => write!(f, "enum value has invalid tag: {:x}", val), InvalidFunctionPointer(p) => { write!(f, "using {:?} as function pointer but it does not point to a function", p) } diff --git a/compiler/rustc_middle/src/mir/interpret/mod.rs b/compiler/rustc_middle/src/mir/interpret/mod.rs index 66f2c6e78a2e8..4eac0009f69e2 100644 --- a/compiler/rustc_middle/src/mir/interpret/mod.rs +++ b/compiler/rustc_middle/src/mir/interpret/mod.rs @@ -147,7 +147,7 @@ pub struct GlobalId<'tcx> { impl<'tcx> GlobalId<'tcx> { pub fn display(self, tcx: TyCtxt<'tcx>) -> String { - let instance_name = with_no_trimmed_paths(|| tcx.def_path_str(self.instance.def.def_id())); + let instance_name = with_no_trimmed_paths!(tcx.def_path_str(self.instance.def.def_id())); if let Some(promoted) = self.promoted { format!("{}::{:?}", instance_name, promoted) } else { diff --git a/compiler/rustc_middle/src/mir/interpret/value.rs b/compiler/rustc_middle/src/mir/interpret/value.rs index cc31d8c2c1879..acf7847de5416 100644 --- a/compiler/rustc_middle/src/mir/interpret/value.rs +++ b/compiler/rustc_middle/src/mir/interpret/value.rs @@ -153,7 +153,16 @@ impl fmt::Display for Scalar { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { Scalar::Ptr(ptr, _size) => write!(f, "pointer to {:?}", ptr), - Scalar::Int(int) => write!(f, "{:?}", int), + Scalar::Int(int) => write!(f, "{}", int), + } + } +} + +impl fmt::LowerHex for Scalar { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Scalar::Ptr(ptr, _size) => write!(f, "pointer to {:?}", ptr), + Scalar::Int(int) => write!(f, "0x{:x}", int), } } } @@ -370,78 +379,82 @@ impl<'tcx, Tag: Provenance> Scalar { } } + /// Converts the scalar to produce an unsigned integer of the given size. + /// Fails if the scalar is a pointer. #[inline] - fn to_unsigned_with_bit_width(self, bits: u64) -> InterpResult<'static, u128> { - let sz = Size::from_bits(bits); - self.to_bits(sz) + pub fn to_uint(self, size: Size) -> InterpResult<'static, u128> { + self.to_bits(size) } /// Converts the scalar to produce a `u8`. Fails if the scalar is a pointer. pub fn to_u8(self) -> InterpResult<'static, u8> { - self.to_unsigned_with_bit_width(8).map(|v| u8::try_from(v).unwrap()) + self.to_uint(Size::from_bits(8)).map(|v| u8::try_from(v).unwrap()) } /// Converts the scalar to produce a `u16`. Fails if the scalar is a pointer. pub fn to_u16(self) -> InterpResult<'static, u16> { - self.to_unsigned_with_bit_width(16).map(|v| u16::try_from(v).unwrap()) + self.to_uint(Size::from_bits(16)).map(|v| u16::try_from(v).unwrap()) } /// Converts the scalar to produce a `u32`. Fails if the scalar is a pointer. pub fn to_u32(self) -> InterpResult<'static, u32> { - self.to_unsigned_with_bit_width(32).map(|v| u32::try_from(v).unwrap()) + self.to_uint(Size::from_bits(32)).map(|v| u32::try_from(v).unwrap()) } /// Converts the scalar to produce a `u64`. Fails if the scalar is a pointer. pub fn to_u64(self) -> InterpResult<'static, u64> { - self.to_unsigned_with_bit_width(64).map(|v| u64::try_from(v).unwrap()) + self.to_uint(Size::from_bits(64)).map(|v| u64::try_from(v).unwrap()) } /// Converts the scalar to produce a `u128`. Fails if the scalar is a pointer. pub fn to_u128(self) -> InterpResult<'static, u128> { - self.to_unsigned_with_bit_width(128) + self.to_uint(Size::from_bits(128)) } + /// Converts the scalar to produce a machine-pointer-sized unsigned integer. + /// Fails if the scalar is a pointer. pub fn to_machine_usize(self, cx: &impl HasDataLayout) -> InterpResult<'static, u64> { - let b = self.to_bits(cx.data_layout().pointer_size)?; + let b = self.to_uint(cx.data_layout().pointer_size)?; Ok(u64::try_from(b).unwrap()) } + /// Converts the scalar to produce a signed integer of the given size. + /// Fails if the scalar is a pointer. #[inline] - fn to_signed_with_bit_width(self, bits: u64) -> InterpResult<'static, i128> { - let sz = Size::from_bits(bits); - let b = self.to_bits(sz)?; - Ok(sz.sign_extend(b) as i128) + pub fn to_int(self, size: Size) -> InterpResult<'static, i128> { + let b = self.to_bits(size)?; + Ok(size.sign_extend(b) as i128) } /// Converts the scalar to produce an `i8`. Fails if the scalar is a pointer. pub fn to_i8(self) -> InterpResult<'static, i8> { - self.to_signed_with_bit_width(8).map(|v| i8::try_from(v).unwrap()) + self.to_int(Size::from_bits(8)).map(|v| i8::try_from(v).unwrap()) } /// Converts the scalar to produce an `i16`. Fails if the scalar is a pointer. pub fn to_i16(self) -> InterpResult<'static, i16> { - self.to_signed_with_bit_width(16).map(|v| i16::try_from(v).unwrap()) + self.to_int(Size::from_bits(16)).map(|v| i16::try_from(v).unwrap()) } /// Converts the scalar to produce an `i32`. Fails if the scalar is a pointer. pub fn to_i32(self) -> InterpResult<'static, i32> { - self.to_signed_with_bit_width(32).map(|v| i32::try_from(v).unwrap()) + self.to_int(Size::from_bits(32)).map(|v| i32::try_from(v).unwrap()) } /// Converts the scalar to produce an `i64`. Fails if the scalar is a pointer. pub fn to_i64(self) -> InterpResult<'static, i64> { - self.to_signed_with_bit_width(64).map(|v| i64::try_from(v).unwrap()) + self.to_int(Size::from_bits(64)).map(|v| i64::try_from(v).unwrap()) } /// Converts the scalar to produce an `i128`. Fails if the scalar is a pointer. pub fn to_i128(self) -> InterpResult<'static, i128> { - self.to_signed_with_bit_width(128) + self.to_int(Size::from_bits(128)) } + /// Converts the scalar to produce a machine-pointer-sized signed integer. + /// Fails if the scalar is a pointer. pub fn to_machine_isize(self, cx: &impl HasDataLayout) -> InterpResult<'static, i64> { - let sz = cx.data_layout().pointer_size; - let b = self.to_bits(sz)?; - let b = sz.sign_extend(b) as i128; + let b = self.to_int(cx.data_layout().pointer_size)?; Ok(i64::try_from(b).unwrap()) } @@ -489,7 +502,7 @@ impl fmt::Display for ScalarMaybeUninit { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { ScalarMaybeUninit::Uninit => write!(f, "uninitialized bytes"), - ScalarMaybeUninit::Scalar(s) => write!(f, "{}", s), + ScalarMaybeUninit::Scalar(s) => write!(f, "{:x}", s), } } } diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 7e5f8018dfc42..2126487da02fd 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -1841,6 +1841,15 @@ static_assert_size!(PlaceElem<'_>, 24); pub type ProjectionKind = ProjectionElem<(), ()>; rustc_index::newtype_index! { + /// A [newtype'd][wrapper] index type in the MIR [control-flow graph][CFG] + /// + /// A field (e.g., `f` in `_1.f`) is one variant of [`ProjectionElem`]. Conceptually, + /// rustc can identify that a field projection refers to either two different regions of memory + /// or the same one between the base and the 'projection element'. + /// Read more about projections in the [rustc-dev-guide][mir-datatypes] + /// [wrapper]: https://rustc-dev-guide.rust-lang.org/appendix/glossary.html#newtype + /// [CFG]: https://rustc-dev-guide.rust-lang.org/appendix/background.html#cfg + /// [mir-datatypes]: https://rustc-dev-guide.rust-lang.org/mir/index.html#mir-data-types pub struct Field { derive [HashStable] DEBUG_FORMAT = "field[{}]" @@ -2524,7 +2533,7 @@ pub enum ConstantKind<'tcx> { impl<'tcx> Constant<'tcx> { pub fn check_static_ptr(&self, tcx: TyCtxt<'_>) -> Option { - match self.literal.try_to_scalar() { + match self.literal.const_for_ty()?.val().try_to_scalar() { Some(Scalar::Ptr(ptr, _size)) => match tcx.global_alloc(ptr.provenance) { GlobalAlloc::Static(def_id) => { assert!(!tcx.is_thread_local_static(def_id)); diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index 784babffeff42..6886a0f4cf148 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -17,8 +17,9 @@ use rustc_middle::mir::interpret::{ use rustc_middle::mir::visit::Visitor; use rustc_middle::mir::MirSource; use rustc_middle::mir::*; -use rustc_middle::ty::{self, TyCtxt}; +use rustc_middle::ty::{self, TyCtxt, TypeFoldable, TypeVisitor}; use rustc_target::abi::Size; +use std::ops::ControlFlow; const INDENT: &str = " "; /// Alignment for lining up comments following MIR statements @@ -89,14 +90,11 @@ pub fn dump_mir<'tcx, F>( } pub fn dump_enabled<'tcx>(tcx: TyCtxt<'tcx>, pass_name: &str, def_id: DefId) -> bool { - let filters = match tcx.sess.opts.debugging_opts.dump_mir { - None => return false, - Some(ref filters) => filters, + let Some(ref filters) = tcx.sess.opts.debugging_opts.dump_mir else { + return false; }; - let node_path = ty::print::with_forced_impl_filename_line(|| { - // see notes on #41697 below - tcx.def_path_str(def_id) - }); + // see notes on #41697 below + let node_path = ty::print::with_forced_impl_filename_line!(tcx.def_path_str(def_id)); filters.split('|').any(|or_filter| { or_filter.split('&').all(|and_filter| { let and_filter_trimmed = and_filter.trim(); @@ -124,10 +122,9 @@ fn dump_matched_mir_node<'tcx, F>( let _: io::Result<()> = try { let mut file = create_dump_file(tcx, "mir", pass_num, pass_name, disambiguator, body.source)?; - let def_path = ty::print::with_forced_impl_filename_line(|| { - // see notes on #41697 above - tcx.def_path_str(body.source.def_id()) - }); + // see notes on #41697 above + let def_path = + ty::print::with_forced_impl_filename_line!(tcx.def_path_str(body.source.def_id())); write!(file, "// MIR for `{}", def_path)?; match body.source.promoted { None => write!(file, "`")?, @@ -431,7 +428,7 @@ fn use_verbose<'tcx>(ty: Ty<'tcx>, fn_def: bool) -> bool { ty::Int(_) | ty::Uint(_) | ty::Bool | ty::Char | ty::Float(_) => false, // Unit type ty::Tuple(g_args) if g_args.is_empty() => false, - ty::Tuple(g_args) => g_args.iter().any(|g_arg| use_verbose(g_arg.expect_ty(), fn_def)), + ty::Tuple(g_args) => g_args.iter().any(|g_arg| use_verbose(g_arg, fn_def)), ty::Array(ty, _) => use_verbose(ty, fn_def), ty::FnDef(..) => fn_def, _ => true, @@ -439,8 +436,7 @@ fn use_verbose<'tcx>(ty: Ty<'tcx>, fn_def: bool) -> bool { } impl<'tcx> Visitor<'tcx> for ExtraComments<'tcx> { - fn visit_constant(&mut self, constant: &Constant<'tcx>, location: Location) { - self.super_constant(constant, location); + fn visit_constant(&mut self, constant: &Constant<'tcx>, _location: Location) { let Constant { span, user_ty, literal } = constant; if use_verbose(literal.ty(), true) { self.push("mir::Constant"); @@ -451,38 +447,30 @@ impl<'tcx> Visitor<'tcx> for ExtraComments<'tcx> { if let Some(user_ty) = user_ty { self.push(&format!("+ user_ty: {:?}", user_ty)); } - match literal { - ConstantKind::Ty(literal) => self.push(&format!("+ literal: {:?}", literal)), - ConstantKind::Val(val, ty) => { - // To keep the diffs small, we render this almost like we render ty::Const - self.push(&format!("+ literal: Const {{ ty: {}, val: Value({:?}) }}", ty, val)) - } - } - } - } - fn visit_const(&mut self, constant: ty::Const<'tcx>, _: Location) { - self.super_const(constant); - let ty = constant.ty(); - let val = constant.val(); - if use_verbose(ty, false) { - self.push("ty::Const"); - self.push(&format!("+ ty: {:?}", ty)); - let val = match val { - ty::ConstKind::Param(p) => format!("Param({})", p), - ty::ConstKind::Infer(infer) => format!("Infer({:?})", infer), - ty::ConstKind::Bound(idx, var) => format!("Bound({:?}, {:?})", idx, var), - ty::ConstKind::Placeholder(ph) => format!("PlaceHolder({:?})", ph), - ty::ConstKind::Unevaluated(uv) => format!( - "Unevaluated({}, {:?}, {:?})", - self.tcx.def_path_str(uv.def.did), - uv.substs, - uv.promoted, - ), - ty::ConstKind::Value(val) => format!("Value({:?})", val), - ty::ConstKind::Error(_) => "Error".to_string(), + let val = match literal { + ConstantKind::Ty(ct) => match ct.val() { + ty::ConstKind::Param(p) => format!("Param({})", p), + ty::ConstKind::Unevaluated(uv) => format!( + "Unevaluated({}, {:?}, {:?})", + self.tcx.def_path_str(uv.def.did), + uv.substs, + uv.promoted, + ), + ty::ConstKind::Value(val) => format!("Value({:?})", val), + ty::ConstKind::Error(_) => "Error".to_string(), + // These variants shouldn't exist in the MIR. + ty::ConstKind::Placeholder(_) + | ty::ConstKind::Infer(_) + | ty::ConstKind::Bound(..) => bug!("unexpected MIR constant: {:?}", literal), + }, + // To keep the diffs small, we render this like we render `ty::Const::Value`. + // + // This changes once `ty::Const::Value` is represented using valtrees. + ConstantKind::Val(val, _) => format!("Value({:?})", val), }; - self.push(&format!("+ val: {}", val)); + + self.push(&format!("+ literal: Const {{ ty: {}, val: {} }}", literal.ty(), val)); } } @@ -586,9 +574,8 @@ fn write_scope_tree( )?; } - let children = match scope_tree.get(&parent) { - Some(children) => children, - None => return Ok(()), + let Some(children) = scope_tree.get(&parent) else { + return Ok(()); }; for &child in children { @@ -668,7 +655,6 @@ pub fn write_allocations<'tcx>( fn alloc_ids_from_alloc(alloc: &Allocation) -> impl DoubleEndedIterator + '_ { alloc.relocations().values().map(|id| *id) } - fn alloc_ids_from_const(val: ConstValue<'_>) -> impl Iterator + '_ { match val { ConstValue::Scalar(interpret::Scalar::Ptr(ptr, _size)) => { @@ -682,29 +668,17 @@ pub fn write_allocations<'tcx>( } } } - struct CollectAllocIds(BTreeSet); - - impl<'tcx> Visitor<'tcx> for CollectAllocIds { - fn visit_const(&mut self, c: ty::Const<'tcx>, _loc: Location) { + impl<'tcx> TypeVisitor<'tcx> for CollectAllocIds { + fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow { if let ty::ConstKind::Value(val) = c.val() { self.0.extend(alloc_ids_from_const(val)); } - } - - fn visit_constant(&mut self, c: &Constant<'tcx>, loc: Location) { - match c.literal { - ConstantKind::Ty(c) => self.visit_const(c, loc), - ConstantKind::Val(val, _) => { - self.0.extend(alloc_ids_from_const(val)); - } - } + c.super_visit_with(self) } } - let mut visitor = CollectAllocIds(Default::default()); - visitor.visit_body(body); - + body.visit_with(&mut visitor); // `seen` contains all seen allocations, including the ones we have *not* printed yet. // The protocol is to first `insert` into `seen`, and only if that returns `true` // then push to `todo`. @@ -971,10 +945,10 @@ fn write_mir_sig(tcx: TyCtxt<'_>, body: &Body<'_>, w: &mut dyn Write) -> io::Res _ => bug!("Unexpected def kind {:?}", kind), } - ty::print::with_forced_impl_filename_line(|| { + ty::print::with_forced_impl_filename_line! { // see notes on #41697 elsewhere - write!(w, "{}", tcx.def_path_str(def_id)) - })?; + write!(w, "{}", tcx.def_path_str(def_id))? + } if body.source.promoted.is_none() && is_function { write!(w, "(")?; diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs index 5c616425957df..433f69e8da46c 100644 --- a/compiler/rustc_middle/src/mir/query.rs +++ b/compiler/rustc_middle/src/mir/query.rs @@ -2,7 +2,7 @@ use crate::mir::{Body, Promoted}; use crate::ty::{self, Ty, TyCtxt}; -use rustc_data_structures::sync::Lrc; +use rustc_data_structures::stable_map::FxHashMap; use rustc_data_structures::vec_map::VecMap; use rustc_errors::ErrorReported; use rustc_hir as hir; @@ -114,13 +114,44 @@ pub struct UnsafetyViolation { pub details: UnsafetyViolationDetails, } -#[derive(Clone, TyEncodable, TyDecodable, HashStable, Debug)] +#[derive(Copy, Clone, PartialEq, TyEncodable, TyDecodable, HashStable, Debug)] +pub enum UnusedUnsafe { + /// `unsafe` block contains no unsafe operations + /// > ``unnecessary `unsafe` block`` + Unused, + /// `unsafe` block nested under another (used) `unsafe` block + /// > ``… because it's nested under this `unsafe` block`` + InUnsafeBlock(hir::HirId), + /// `unsafe` block nested under `unsafe fn` + /// > ``… because it's nested under this `unsafe fn` `` + /// + /// the second HirId here indicates the first usage of the `unsafe` block, + /// which allows retrival of the LintLevelSource for why that operation would + /// have been permitted without the block + InUnsafeFn(hir::HirId, hir::HirId), +} + +#[derive(Copy, Clone, PartialEq, TyEncodable, TyDecodable, HashStable, Debug)] +pub enum UsedUnsafeBlockData { + SomeDisallowedInUnsafeFn, + // the HirId here indicates the first usage of the `unsafe` block + // (i.e. the one that's first encountered in the MIR traversal of the unsafety check) + AllAllowedInUnsafeFn(hir::HirId), +} + +#[derive(TyEncodable, TyDecodable, HashStable, Debug)] pub struct UnsafetyCheckResult { /// Violations that are propagated *upwards* from this function. - pub violations: Lrc<[UnsafetyViolation]>, - /// `unsafe` blocks in this function, along with whether they are used. This is - /// used for the "unused_unsafe" lint. - pub unsafe_blocks: Lrc<[(hir::HirId, bool)]>, + pub violations: Vec, + + /// Used `unsafe` blocks in this function. This is used for the "unused_unsafe" lint. + /// + /// The keys are the used `unsafe` blocks, the UnusedUnsafeKind indicates whether + /// or not any of the usages happen at a place that doesn't allow `unsafe_op_in_unsafe_fn`. + pub used_unsafe_blocks: FxHashMap, + + /// This is `Some` iff the item is not a closure. + pub unused_unsafes: Option>, } rustc_index::newtype_index! { @@ -341,7 +372,7 @@ pub enum ConstraintCategory { /// like `Foo { field: my_val }`) Usage, OpaqueType, - ClosureUpvar(hir::HirId), + ClosureUpvar(Field), /// A constraint from a user-written predicate /// with the provided span, written on the item @@ -363,7 +394,7 @@ pub enum ConstraintCategory { #[derive(TyEncodable, TyDecodable, HashStable)] pub enum ReturnConstraint { Normal, - ClosureUpvar(hir::HirId), + ClosureUpvar(Field), } /// The subject of a `ClosureOutlivesRequirement` -- that is, the thing diff --git a/compiler/rustc_middle/src/mir/tcx.rs b/compiler/rustc_middle/src/mir/tcx.rs index 302921cc4aa72..23f9849e83171 100644 --- a/compiler/rustc_middle/src/mir/tcx.rs +++ b/compiler/rustc_middle/src/mir/tcx.rs @@ -46,7 +46,7 @@ impl<'tcx> PlaceTy<'tcx> { let field_def = &variant_def.fields[f.index()]; field_def.ty(tcx, substs) } - ty::Tuple(ref tys) => tys[f.index()].expect_ty(), + ty::Tuple(tys) => tys[f.index()], _ => bug!("extracting field of non-tuple non-adt: {:?}", self), }; debug!("field_ty self: {:?} f: {:?} yields: {:?}", self, f, answer); diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 43cfe6f3b8a7a..be86f1e92744e 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1,3 +1,9 @@ +//! Defines the various compiler queries. +//! +//! For more information on the query system, see +//! ["Queries: demand-driven compilation"](https://rustc-dev-guide.rust-lang.org/query.html). +//! This chapter includes instructions for adding new queries. + // Each of these queries corresponds to a function pointer field in the // `Providers` struct for requesting a value of that type, and a method // on `tcx: TyCtxt` (and `tcx.at(span)`) for doing that request in a way diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index 04bc0c8b52114..40dce281c82bf 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -17,7 +17,6 @@ use rustc_index::newtype_index; use rustc_index::vec::IndexVec; use rustc_middle::infer::canonical::Canonical; use rustc_middle::middle::region; -use rustc_middle::mir::interpret::AllocId; use rustc_middle::mir::{ BinOp, BorrowKind, FakeReadCause, Field, Mutability, UnOp, UserTypeProjection, }; @@ -420,8 +419,7 @@ pub enum ExprKind<'tcx> { /// This is only distinguished from `Literal` so that we can register some /// info for diagnostics. StaticRef { - alloc_id: AllocId, - ty: Ty<'tcx>, + literal: Const<'tcx>, def_id: DefId, }, /// Inline assembly, i.e. `asm!()`. diff --git a/compiler/rustc_middle/src/thir/visit.rs b/compiler/rustc_middle/src/thir/visit.rs index b3e2cb132a273..95489ac3ab2c6 100644 --- a/compiler/rustc_middle/src/thir/visit.rs +++ b/compiler/rustc_middle/src/thir/visit.rs @@ -123,7 +123,7 @@ pub fn walk_expr<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, expr: &Exp } Closure { closure_id: _, substs: _, upvars: _, movability: _, fake_reads: _ } => {} Literal { literal, user_ty: _, const_id: _ } => visitor.visit_const(literal), - StaticRef { .. } => {} + StaticRef { literal, def_id: _ } => visitor.visit_const(literal), InlineAsm { ref operands, template: _, options: _, line_spans: _ } => { for op in &**operands { use InlineAsmOperand::*; diff --git a/compiler/rustc_middle/src/ty/consts/int.rs b/compiler/rustc_middle/src/ty/consts/int.rs index de45e1bb851ac..72623ba54eeb4 100644 --- a/compiler/rustc_middle/src/ty/consts/int.rs +++ b/compiler/rustc_middle/src/ty/consts/int.rs @@ -294,12 +294,22 @@ impl From for ScalarInt { } } +/// Error returned when a conversion from ScalarInt to char fails. +#[derive(Debug)] +pub struct CharTryFromScalarInt; + impl TryFrom for char { - type Error = Size; + type Error = CharTryFromScalarInt; + #[inline] - fn try_from(int: ScalarInt) -> Result { - int.to_bits(Size::from_bytes(std::mem::size_of::())) - .map(|u| char::from_u32(u.try_into().unwrap()).unwrap()) + fn try_from(int: ScalarInt) -> Result { + let Ok(bits) = int.to_bits(Size::from_bytes(std::mem::size_of::())) else { + return Err(CharTryFromScalarInt); + }; + match char::from_u32(bits.try_into().unwrap()) { + Some(c) => Ok(c), + None => Err(CharTryFromScalarInt), + } } } @@ -374,3 +384,10 @@ impl fmt::UpperHex for ScalarInt { write!(f, "{:01$X}", { self.data }, self.size as usize * 2) } } + +impl fmt::Display for ScalarInt { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.check_data(); + write!(f, "{}", { self.data }) + } +} diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 41145d250173f..4b4fcaa9c1874 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -101,7 +101,6 @@ pub struct CtxtInterners<'tcx> { // Specifically use a speedy hash algorithm for these hash sets, since // they're accessed quite often. type_: InternedSet<'tcx, TyS<'tcx>>, - type_list: InternedSet<'tcx, List>>, substs: InternedSet<'tcx, InternalSubsts<'tcx>>, canonical_var_infos: InternedSet<'tcx, List>>, region: InternedSet<'tcx, RegionKind>, @@ -129,7 +128,6 @@ impl<'tcx> CtxtInterners<'tcx> { CtxtInterners { arena, type_: Default::default(), - type_list: Default::default(), substs: Default::default(), region: Default::default(), poly_existential_predicates: Default::default(), @@ -1123,9 +1121,8 @@ impl<'tcx> TyCtxt<'tcx> { pub fn layout_scalar_valid_range(self, def_id: DefId) -> (Bound, Bound) { let attrs = self.get_attrs(def_id); let get = |name| { - let attr = match attrs.iter().find(|a| a.has_name(name)) { - Some(attr) => attr, - None => return Bound::Unbounded, + let Some(attr) = attrs.iter().find(|a| a.has_name(name)) else { + return Bound::Unbounded; }; debug!("layout_scalar_valid_range: attr={:?}", attr); if let Some( @@ -1513,9 +1510,8 @@ impl<'tcx> TyCtxt<'tcx> { scope_def_id: LocalDefId, ) -> Vec<&'tcx hir::Ty<'tcx>> { let hir_id = self.hir().local_def_id_to_hir_id(scope_def_id); - let hir_output = match self.hir().fn_decl_by_hir_id(hir_id) { - Some(hir::FnDecl { output: hir::FnRetTy::Return(ty), .. }) => ty, - _ => return vec![], + let Some(hir::FnDecl { output: hir::FnRetTy::Return(hir_output), .. }) = self.hir().fn_decl_by_hir_id(hir_id) else { + return vec![]; }; let mut v = TraitObjectVisitor(vec![], self.hir()); @@ -1659,6 +1655,8 @@ macro_rules! nop_lift { type Lifted = $lifted; fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option { if tcx.interners.$set.contains_pointer_to(&InternedInSet(self.0.0)) { + // SAFETY: `self` is interned and therefore valid + // for the entire lifetime of the `TyCtxt`. Some(unsafe { mem::transmute(self) }) } else { None @@ -1668,6 +1666,25 @@ macro_rules! nop_lift { }; } +// Can't use the macros as we have reuse the `substs` here. +// +// See `intern_type_list` for more info. +impl<'a, 'tcx> Lift<'tcx> for &'a List> { + type Lifted = &'tcx List>; + fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option { + if self.is_empty() { + return Some(List::empty()); + } + if tcx.interners.substs.contains_pointer_to(&InternedInSet(self.as_substs())) { + // SAFETY: `self` is interned and therefore valid + // for the entire lifetime of the `TyCtxt`. + Some(unsafe { mem::transmute::<&'a List>, &'tcx List>>(self) }) + } else { + None + } + } +} + macro_rules! nop_list_lift { ($set:ident; $ty:ty => $lifted:ty) => { impl<'a, 'tcx> Lift<'tcx> for &'a List<$ty> { @@ -1692,7 +1709,6 @@ nop_lift! {const_; Const<'a> => Const<'tcx>} nop_lift_old! {const_allocation; &'a Allocation => &'tcx Allocation} nop_lift! {predicate; Predicate<'a> => Predicate<'tcx>} -nop_list_lift! {type_list; Ty<'a> => Ty<'tcx>} nop_list_lift! {poly_existential_predicates; ty::Binder<'a, ExistentialPredicate<'a>> => ty::Binder<'tcx, ExistentialPredicate<'tcx>>} nop_list_lift! {predicates; Predicate<'a> => Predicate<'tcx>} nop_list_lift! {canonical_var_infos; CanonicalVarInfo<'a> => CanonicalVarInfo<'tcx>} @@ -2191,7 +2207,6 @@ macro_rules! slice_interners { } slice_interners!( - type_list: _intern_type_list(Ty<'tcx>), substs: _intern_substs(GenericArg<'tcx>), canonical_var_infos: _intern_canonical_var_infos(CanonicalVarInfo<'tcx>), poly_existential_predicates: @@ -2261,7 +2276,7 @@ impl<'tcx> TyCtxt<'tcx> { ) -> PolyFnSig<'tcx> { sig.map_bound(|s| { let params_iter = match s.inputs()[0].kind() { - ty::Tuple(params) => params.into_iter().map(|k| k.expect_ty()), + ty::Tuple(params) => params.into_iter(), _ => bug!(), }; self.mk_fn_sig(params_iter, s.output(), s.c_variadic, unsafety, abi::Abi::Rust) @@ -2423,15 +2438,11 @@ impl<'tcx> TyCtxt<'tcx> { #[inline] pub fn intern_tup(self, ts: &[Ty<'tcx>]) -> Ty<'tcx> { - let kinds: Vec<_> = ts.iter().map(|&t| GenericArg::from(t)).collect(); - self.mk_ty(Tuple(self.intern_substs(&kinds))) + self.mk_ty(Tuple(self.intern_type_list(&ts))) } pub fn mk_tup], Ty<'tcx>>>(self, iter: I) -> I::Output { - iter.intern_with(|ts| { - let kinds: Vec<_> = ts.iter().map(|&t| GenericArg::from(t)).collect(); - self.mk_ty(Tuple(self.intern_substs(&kinds))) - }) + iter.intern_with(|ts| self.mk_ty(Tuple(self.intern_type_list(&ts)))) } #[inline] @@ -2613,7 +2624,19 @@ impl<'tcx> TyCtxt<'tcx> { } pub fn intern_type_list(self, ts: &[Ty<'tcx>]) -> &'tcx List> { - if ts.is_empty() { List::empty() } else { self._intern_type_list(ts) } + if ts.is_empty() { + List::empty() + } else { + // Actually intern type lists as lists of `GenericArg`s. + // + // Transmuting from `Ty<'tcx>` to `GenericArg<'tcx>` is sound + // as explained in ty_slice_as_generic_arg`. With this, + // we guarantee that even when transmuting between `List>` + // and `List>`, the uniqueness requirement for + // lists is upheld. + let substs = self._intern_substs(ty::subst::ty_slice_as_generic_args(ts)); + substs.try_as_type_list().unwrap() + } } pub fn intern_substs(self, ts: &[GenericArg<'tcx>]) -> &'tcx List> { diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs index 64b2edd2c3f39..934a6a878feb5 100644 --- a/compiler/rustc_middle/src/ty/diagnostics.rs +++ b/compiler/rustc_middle/src/ty/diagnostics.rs @@ -116,9 +116,10 @@ impl<'tcx> Ty<'tcx> { } _ => true, }), - Projection(ProjectionTy { substs: args, .. }) | Adt(_, args) | Tuple(args) => { + Projection(ProjectionTy { substs: args, .. }) | Adt(_, args) => { args.iter().all(generic_arg_is_suggestible) } + Tuple(args) => args.iter().all(|ty| ty.is_suggestable()), Slice(ty) | RawPtr(TypeAndMut { ty, .. }) | Ref(_, ty, _) => ty.is_suggestable(), Array(ty, c) => ty.is_suggestable() && const_is_suggestable(c.val()), _ => true, diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs index 2ccfeba2b665d..5ceabf99eda96 100644 --- a/compiler/rustc_middle/src/ty/error.rs +++ b/compiler/rustc_middle/src/ty/error.rs @@ -861,11 +861,10 @@ fn foo(&self) -> Self::T { String::new() } body_owner_def_id: DefId, found: Ty<'tcx>, ) -> bool { - let hir_id = - match body_owner_def_id.as_local().map(|id| self.hir().local_def_id_to_hir_id(id)) { - Some(hir_id) => hir_id, - None => return false, - }; + let Some(hir_id) = body_owner_def_id.as_local() else { + return false; + }; + let hir_id = self.hir().local_def_id_to_hir_id(hir_id); // When `body_owner` is an `impl` or `trait` item, look in its associated types for // `expected` and point at it. let parent_id = self.hir().get_parent_item(hir_id); diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs index 948a48c082644..7a3d615862cba 100644 --- a/compiler/rustc_middle/src/ty/flags.rs +++ b/compiler/rustc_middle/src/ty/flags.rs @@ -201,8 +201,8 @@ impl FlagComputation { self.add_ty(ty); } - &ty::Tuple(ref substs) => { - self.add_substs(substs); + &ty::Tuple(types) => { + self.add_tys(types); } &ty::FnDef(_, substs) => { diff --git a/compiler/rustc_middle/src/ty/impls_ty.rs b/compiler/rustc_middle/src/ty/impls_ty.rs index 00ce15bea3f28..54a345daec8a5 100644 --- a/compiler/rustc_middle/src/ty/impls_ty.rs +++ b/compiler/rustc_middle/src/ty/impls_ty.rs @@ -61,6 +61,36 @@ impl<'a, 'tcx> HashStable> for ty::subst::GenericArg<'t } } +impl<'a, 'tcx> HashStable> for ty::subst::GenericArgKind<'tcx> { + fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { + match self { + // WARNING: We dedup cache the `HashStable` results for `List` + // while ignoring types and freely transmute + // between `List>` and `List>`. + // See `fn intern_type_list` for more details. + // + // We therefore hash types without adding a hash for their discriminant. + // + // In order to make it very unlikely for the sequence of bytes being hashed for + // a `GenericArgKind::Type` to be the same as the sequence of bytes being + // hashed for one of the other variants, we hash a `0xFF` byte before hashing + // their discriminant (since the discriminant of `TyKind` is unlikely to ever start + // with 0xFF). + ty::subst::GenericArgKind::Type(ty) => ty.hash_stable(hcx, hasher), + ty::subst::GenericArgKind::Const(ct) => { + 0xFFu8.hash_stable(hcx, hasher); + mem::discriminant(self).hash_stable(hcx, hasher); + ct.hash_stable(hcx, hasher); + } + ty::subst::GenericArgKind::Lifetime(lt) => { + 0xFFu8.hash_stable(hcx, hasher); + mem::discriminant(self).hash_stable(hcx, hasher); + lt.hash_stable(hcx, hasher); + } + } + } +} + impl<'a> HashStable> for ty::RegionKind { fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { mem::discriminant(self).hash_stable(hcx, hasher); diff --git a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs index f2682b8bcd838..e2289b44b5c5b 100644 --- a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs +++ b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs @@ -207,10 +207,9 @@ pub(crate) fn type_uninhabited_from<'tcx>( Never => DefIdForest::full(), - Tuple(ref tys) => DefIdForest::union( - tcx, - tys.iter().map(|ty| ty.expect_ty().uninhabited_from(tcx, param_env)), - ), + Tuple(ref tys) => { + DefIdForest::union(tcx, tys.iter().map(|ty| ty.uninhabited_from(tcx, param_env))) + } Array(ty, len) => match len.try_eval_usize(tcx, param_env) { Some(0) | None => DefIdForest::empty(), diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index 99c595fcdf185..4c4271662032d 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -628,7 +628,7 @@ fn polymorphize<'tcx>( } else { None }; - let has_upvars = upvars_ty.map_or(false, |ty| ty.tuple_fields().count() > 0); + let has_upvars = upvars_ty.map_or(false, |ty| !ty.tuple_fields().is_empty()); debug!("polymorphize: upvars_ty={:?} has_upvars={:?}", upvars_ty, has_upvars); struct PolymorphizationFolder<'tcx> { diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 6d4178c3e753f..b7b36c4945978 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -712,9 +712,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { if tys.len() == 0 { StructKind::AlwaysSized } else { StructKind::MaybeUnsized }; univariant( - &tys.iter() - .map(|k| self.layout_of(k.expect_ty())) - .collect::, _>>()?, + &tys.iter().map(|k| self.layout_of(k)).collect::, _>>()?, &ReprOptions::default(), kind, )? @@ -1319,9 +1317,8 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { // Try to use a ScalarPair for all tagged enums. let mut common_prim = None; for (field_layouts, layout_variant) in iter::zip(&variants, &layout_variants) { - let offsets = match layout_variant.fields { - FieldsShape::Arbitrary { ref offsets, .. } => offsets, - _ => bug!(), + let FieldsShape::Arbitrary { ref offsets, .. } = layout_variant.fields else { + bug!(); }; let mut fields = iter::zip(field_layouts, offsets).filter(|p| !p.0.is_zst()); @@ -1571,9 +1568,8 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { let tcx = self.tcx; let subst_field = |ty: Ty<'tcx>| ty.subst(tcx, substs); - let info = match tcx.generator_layout(def_id) { - None => return Err(LayoutError::Unknown(ty)), - Some(info) => info, + let Some(info) = tcx.generator_layout(def_id) else { + return Err(LayoutError::Unknown(ty)); }; let (ineligible_locals, assignments) = self.generator_saved_local_eligibility(&info); @@ -1676,9 +1672,8 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { )?; variant.variants = Variants::Single { index }; - let (offsets, memory_index) = match variant.fields { - FieldsShape::Arbitrary { offsets, memory_index } => (offsets, memory_index), - _ => bug!(), + let FieldsShape::Arbitrary { offsets, memory_index } = variant.fields else { + bug!(); }; // Now, stitch the promoted and variant-only fields back together in @@ -2385,7 +2380,7 @@ where } }, - ty::Tuple(tys) => TyMaybeWithLayout::Ty(tys[i].expect_ty()), + ty::Tuple(tys) => TyMaybeWithLayout::Ty(tys[i]), // ADTs. ty::Adt(def, substs) => { @@ -3015,7 +3010,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { if let Some(input) = sig.inputs().last() { if let ty::Tuple(tupled_arguments) = input.kind() { inputs = &sig.inputs()[0..sig.inputs().len() - 1]; - tupled_arguments.iter().map(|k| k.expect_ty()).collect() + tupled_arguments } else { bug!( "argument to function with \"rust-call\" ABI \ @@ -3030,7 +3025,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { } } else { assert!(sig.c_variadic || extra_args.is_empty()); - extra_args.to_vec() + extra_args }; let target = &self.tcx.sess.target; @@ -3158,8 +3153,8 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { ret: arg_of(sig.output(), None)?, args: inputs .iter() - .cloned() - .chain(extra_args) + .copied() + .chain(extra_args.iter().copied()) .chain(caller_location) .enumerate() .map(|(i, ty)| arg_of(ty, Some(i))) diff --git a/compiler/rustc_middle/src/ty/print/mod.rs b/compiler/rustc_middle/src/ty/print/mod.rs index 94cea505c32a0..8d7f6d84c7c38 100644 --- a/compiler/rustc_middle/src/ty/print/mod.rs +++ b/compiler/rustc_middle/src/ty/print/mod.rs @@ -287,7 +287,6 @@ fn characteristic_def_id_of_type_cached<'a>( ty::Ref(_, ty, _) => characteristic_def_id_of_type_cached(ty, visited), ty::Tuple(ref tys) => tys.iter().find_map(|ty| { - let ty = ty.expect_ty(); if visited.insert(ty) { return characteristic_def_id_of_type_cached(ty, visited); } diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index ae838a461574b..359e4f5e58147 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -63,66 +63,59 @@ thread_local! { static NO_VISIBLE_PATH: Cell = const { Cell::new(false) }; } -/// Avoids running any queries during any prints that occur -/// during the closure. This may alter the appearance of some -/// types (e.g. forcing verbose printing for opaque types). -/// This method is used during some queries (e.g. `explicit_item_bounds` -/// for opaque types), to ensure that any debug printing that -/// occurs during the query computation does not end up recursively -/// calling the same query. -pub fn with_no_queries R, R>(f: F) -> R { - NO_QUERIES.with(|no_queries| { - let old = no_queries.replace(true); - let result = f(); - no_queries.set(old); - result - }) -} - -/// Force us to name impls with just the filename/line number. We -/// normally try to use types. But at some points, notably while printing -/// cycle errors, this can result in extra or suboptimal error output, -/// so this variable disables that check. -pub fn with_forced_impl_filename_line R, R>(f: F) -> R { - FORCE_IMPL_FILENAME_LINE.with(|force| { - let old = force.replace(true); - let result = f(); - force.set(old); - result - }) -} +macro_rules! define_helper { + ($($(#[$a:meta])* fn $name:ident($helper:ident, $tl:ident);)+) => { + $( + #[must_use] + pub struct $helper(bool); + + impl $helper { + pub fn new() -> $helper { + $helper($tl.with(|c| c.replace(true))) + } + } -/// Adds the `crate::` prefix to paths where appropriate. -pub fn with_crate_prefix R, R>(f: F) -> R { - SHOULD_PREFIX_WITH_CRATE.with(|flag| { - let old = flag.replace(true); - let result = f(); - flag.set(old); - result - }) -} + $(#[$a])* + pub macro $name($e:expr) { + { + let _guard = $helper::new(); + $e + } + } -/// Prevent path trimming if it is turned on. Path trimming affects `Display` impl -/// of various rustc types, for example `std::vec::Vec` would be trimmed to `Vec`, -/// if no other `Vec` is found. -pub fn with_no_trimmed_paths R, R>(f: F) -> R { - NO_TRIMMED_PATH.with(|flag| { - let old = flag.replace(true); - let result = f(); - flag.set(old); - result - }) + impl Drop for $helper { + fn drop(&mut self) { + $tl.with(|c| c.set(self.0)) + } + } + )+ + } } -/// Prevent selection of visible paths. `Display` impl of DefId will prefer visible (public) reexports of types as paths. -pub fn with_no_visible_paths R, R>(f: F) -> R { - NO_VISIBLE_PATH.with(|flag| { - let old = flag.replace(true); - let result = f(); - flag.set(old); - result - }) -} +define_helper!( + /// Avoids running any queries during any prints that occur + /// during the closure. This may alter the appearance of some + /// types (e.g. forcing verbose printing for opaque types). + /// This method is used during some queries (e.g. `explicit_item_bounds` + /// for opaque types), to ensure that any debug printing that + /// occurs during the query computation does not end up recursively + /// calling the same query. + fn with_no_queries(NoQueriesGuard, NO_QUERIES); + /// Force us to name impls with just the filename/line number. We + /// normally try to use types. But at some points, notably while printing + /// cycle errors, this can result in extra or suboptimal error output, + /// so this variable disables that check. + fn with_forced_impl_filename_line(ForcedImplGuard, FORCE_IMPL_FILENAME_LINE); + /// Adds the `crate::` prefix to paths where appropriate. + fn with_crate_prefix(CratePrefixGuard, SHOULD_PREFIX_WITH_CRATE); + /// Prevent path trimming if it is turned on. Path trimming affects `Display` impl + /// of various rustc types, for example `std::vec::Vec` would be trimmed to `Vec`, + /// if no other `Vec` is found. + fn with_no_trimmed_paths(NoTrimmedGuard, NO_TRIMMED_PATH); + /// Prevent selection of visible paths. `Display` impl of DefId will prefer + /// visible (public) reexports of types as paths. + fn with_no_visible_paths(NoVisibleGuard, NO_VISIBLE_PATH); +); /// The "region highlights" are used to control region printing during /// specific error messages. When a "region highlight" is enabled, it @@ -379,7 +372,7 @@ pub trait PrettyPrinter<'tcx>: // in cases where the `extern crate foo` has non-trivial // parents, e.g. it's nested in `impl foo::Trait for Bar` // (see also issues #55779 and #87932). - self = with_no_visible_paths(|| self.print_def_path(def_id, &[]))?; + self = with_no_visible_paths!(self.print_def_path(def_id, &[])?); return Ok((self, true)); } @@ -415,9 +408,8 @@ pub trait PrettyPrinter<'tcx>: cur_def_key = self.tcx().def_key(parent); } - let visible_parent = match visible_parent_map.get(&def_id).cloned() { - Some(parent) => parent, - None => return Ok((self, false)), + let Some(visible_parent) = visible_parent_map.get(&def_id).cloned() else { + return Ok((self, false)); }; let actual_parent = self.tcx().parent(def_id); @@ -606,7 +598,7 @@ pub trait PrettyPrinter<'tcx>: ty::Infer(infer_ty) => { let verbose = self.tcx().sess.verbose(); if let ty::TyVar(ty_vid) = infer_ty { - if let Some(name) = self.infer_ty_name(ty_vid) { + if let Some(name) = self.ty_infer_name(ty_vid) { p!(write("{}", name)) } else { if verbose { @@ -655,7 +647,7 @@ pub trait PrettyPrinter<'tcx>: return Ok(self); } - return with_no_queries(|| { + return with_no_queries!({ let def_key = self.tcx().def_key(def_id); if let Some(name) = def_key.disambiguated_data.data.get_opt_name() { p!(write("{}", name)); @@ -853,7 +845,7 @@ pub trait PrettyPrinter<'tcx>: write("{}{}(", if paren_needed { "(" } else { "" }, name) ); - for (idx, ty) in arg_tys.tuple_fields().enumerate() { + for (idx, ty) in arg_tys.tuple_fields().iter().enumerate() { if idx > 0 { p!(", "); } @@ -1015,7 +1007,11 @@ pub trait PrettyPrinter<'tcx>: } } - fn infer_ty_name(&self, _: ty::TyVid) -> Option { + fn ty_infer_name(&self, _: ty::TyVid) -> Option { + None + } + + fn const_infer_name(&self, _: ty::ConstVid<'tcx>) -> Option { None } @@ -1036,12 +1032,11 @@ pub trait PrettyPrinter<'tcx>: // Special-case `Fn(...) -> ...` and resugar it. let fn_trait_kind = cx.tcx().fn_trait_kind_from_lang_item(principal.def_id); if !cx.tcx().sess.verbose() && fn_trait_kind.is_some() { - if let ty::Tuple(ref args) = principal.substs.type_at(0).kind() { + if let ty::Tuple(tys) = principal.substs.type_at(0).kind() { let mut projections = predicates.projection_bounds(); if let (Some(proj), None) = (projections.next(), projections.next()) { - let tys: Vec<_> = args.iter().map(|k| k.expect_ty()).collect(); p!(pretty_fn_sig( - &tys, + tys, false, proj.skip_binder().term.ty().expect("Return type was a const") )); @@ -1203,7 +1198,14 @@ pub trait PrettyPrinter<'tcx>: } } } - ty::ConstKind::Infer(..) => print_underscore!(), + ty::ConstKind::Infer(infer_ct) => { + match infer_ct { + ty::InferConst::Var(ct_vid) + if let Some(name) = self.const_infer_name(ct_vid) => + p!(write("{}", name)), + _ => print_underscore!(), + } + } ty::ConstKind::Param(ParamConst { name, .. }) => p!(write("{}", name)), ty::ConstKind::Value(value) => { return self.pretty_print_const_value(value, ct.ty(), print_ty); @@ -1433,8 +1435,7 @@ pub trait PrettyPrinter<'tcx>: // relocations (we have an active `str` reference here). We don't use this // result to affect interpreter execution. 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)); + p!(write("{:?}", String::from_utf8_lossy(slice))); Ok(self) } (ConstValue::ByRef { alloc, offset }, ty::Array(t, n)) if *t == u8_type => { @@ -1559,7 +1560,8 @@ pub struct FmtPrinterData<'a, 'tcx, F> { pub region_highlight_mode: RegionHighlightMode<'tcx>, - pub name_resolver: Option Option>>, + pub ty_infer_name_resolver: Option Option + 'a>>, + pub const_infer_name_resolver: Option) -> Option + 'a>>, } impl<'a, 'tcx, F> Deref for FmtPrinter<'a, 'tcx, F> { @@ -1588,7 +1590,8 @@ impl<'a, 'tcx, F> FmtPrinter<'a, 'tcx, F> { binder_depth: 0, printed_type_count: 0, region_highlight_mode: RegionHighlightMode::new(tcx), - name_resolver: None, + ty_infer_name_resolver: None, + const_infer_name_resolver: None, })) } } @@ -1843,8 +1846,12 @@ impl<'tcx, F: fmt::Write> Printer<'tcx> for FmtPrinter<'_, 'tcx, F> { } impl<'tcx, F: fmt::Write> PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx, F> { - fn infer_ty_name(&self, id: ty::TyVid) -> Option { - self.0.name_resolver.as_ref().and_then(|func| func(id)) + fn ty_infer_name(&self, id: ty::TyVid) -> Option { + self.0.ty_infer_name_resolver.as_ref().and_then(|func| func(id)) + } + + fn const_infer_name(&self, id: ty::ConstVid<'tcx>) -> Option { + self.0.const_infer_name_resolver.as_ref().and_then(|func| func(id)) } fn print_value_path( diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs index 7c57d42631ad7..42ddbcc1e2f3b 100644 --- a/compiler/rustc_middle/src/ty/relate.rs +++ b/compiler/rustc_middle/src/ty/relate.rs @@ -501,9 +501,7 @@ pub fn super_relate_tys<'tcx, R: TypeRelation<'tcx>>( (&ty::Tuple(as_), &ty::Tuple(bs)) => { if as_.len() == bs.len() { - Ok(tcx.mk_tup( - iter::zip(as_, bs).map(|(a, b)| relation.relate(a.expect_ty(), b.expect_ty())), - )?) + Ok(tcx.mk_tup(iter::zip(as_, bs).map(|(a, b)| relation.relate(a, b)))?) } else if !(as_.is_empty() || bs.is_empty()) { Err(TypeError::TupleSize(expected_found(relation, as_.len(), bs.len()))) } else { diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index e4691dee7793a..42d7b141166f4 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -22,9 +22,9 @@ use std::sync::Arc; impl fmt::Debug for ty::TraitDef { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { ty::tls::with(|tcx| { - with_no_trimmed_paths(|| { - FmtPrinter::new(tcx, f, Namespace::TypeNS).print_def_path(self.def_id, &[]) - })?; + with_no_trimmed_paths!( + FmtPrinter::new(tcx, f, Namespace::TypeNS).print_def_path(self.def_id, &[])? + ); Ok(()) }) } @@ -33,9 +33,9 @@ impl fmt::Debug for ty::TraitDef { impl fmt::Debug for ty::AdtDef { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { ty::tls::with(|tcx| { - with_no_trimmed_paths(|| { - FmtPrinter::new(tcx, f, Namespace::TypeNS).print_def_path(self.did, &[]) - })?; + with_no_trimmed_paths!( + FmtPrinter::new(tcx, f, Namespace::TypeNS).print_def_path(self.did, &[])? + ); Ok(()) }) } @@ -50,7 +50,7 @@ impl fmt::Debug for ty::UpvarId { impl<'tcx> fmt::Debug for ty::ExistentialTraitRef<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - with_no_trimmed_paths(|| fmt::Display::fmt(self, f)) + with_no_trimmed_paths!(fmt::Display::fmt(self, f)) } } @@ -126,13 +126,13 @@ impl fmt::Debug for ty::RegionVid { impl<'tcx> fmt::Debug for ty::TraitRef<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - with_no_trimmed_paths(|| fmt::Display::fmt(self, f)) + with_no_trimmed_paths!(fmt::Display::fmt(self, f)) } } impl<'tcx> fmt::Debug for Ty<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - with_no_trimmed_paths(|| fmt::Display::fmt(self, f)) + with_no_trimmed_paths!(fmt::Display::fmt(self, f)) } } @@ -889,19 +889,6 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List TypeFoldable<'tcx> for &'tcx ty::List> { - fn try_super_fold_with>( - self, - folder: &mut F, - ) -> Result { - ty::util::fold_list(self, folder, |tcx, v| tcx.intern_type_list(v)) - } - - fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow { - self.iter().try_for_each(|t| t.visit_with(visitor)) - } -} - impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List { fn try_super_fold_with>( self, diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 7c6d6ea1cb6ee..02a4df637d889 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -200,8 +200,7 @@ pub enum TyKind<'tcx> { Never, /// A tuple type. For example, `(i32, bool)`. - /// Use `Ty::tuple_fields` to iterate over the field types. - Tuple(SubstsRef<'tcx>), + Tuple(&'tcx List>), /// The projection of an associated type. For example, /// `>::N`. @@ -2155,18 +2154,9 @@ impl<'tcx> Ty<'tcx> { /// Iterates over tuple fields. /// Panics when called on anything but a tuple. - pub fn tuple_fields(self) -> impl DoubleEndedIterator> { + pub fn tuple_fields(self) -> &'tcx List> { match self.kind() { - Tuple(substs) => substs.iter().map(|field| field.expect_ty()), - _ => bug!("tuple_fields called on non-tuple"), - } - } - - /// Get the `i`-th element of a tuple. - /// Panics when called on anything but a tuple. - pub fn tuple_element_ty(self, i: usize) -> Option> { - match self.kind() { - Tuple(substs) => substs.iter().nth(i).map(|field| field.expect_ty()), + Tuple(substs) => substs, _ => bug!("tuple_fields called on non-tuple"), } } @@ -2367,7 +2357,7 @@ impl<'tcx> Ty<'tcx> { ty::Str | ty::Slice(_) | ty::Dynamic(..) | ty::Foreign(..) => false, - ty::Tuple(tys) => tys.iter().all(|ty| ty.expect_ty().is_trivially_sized(tcx)), + ty::Tuple(tys) => tys.iter().all(|ty| ty.is_trivially_sized(tcx)), ty::Adt(def, _substs) => def.sized_constraint(tcx).is_empty(), diff --git a/compiler/rustc_middle/src/ty/subst.rs b/compiler/rustc_middle/src/ty/subst.rs index 7dccef5e3ef0f..364ba07a44167 100644 --- a/compiler/rustc_middle/src/ty/subst.rs +++ b/compiler/rustc_middle/src/ty/subst.rs @@ -20,6 +20,7 @@ use std::marker::PhantomData; use std::mem; use std::num::NonZeroUsize; use std::ops::ControlFlow; +use std::slice; /// An entity in the Rust type system, which can be one of /// several kinds (types, lifetimes, and consts). @@ -40,13 +41,38 @@ const TYPE_TAG: usize = 0b00; const REGION_TAG: usize = 0b01; const CONST_TAG: usize = 0b10; -#[derive(Debug, TyEncodable, TyDecodable, PartialEq, Eq, PartialOrd, Ord, HashStable)] +#[derive(Debug, TyEncodable, TyDecodable, PartialEq, Eq, PartialOrd, Ord)] pub enum GenericArgKind<'tcx> { Lifetime(ty::Region<'tcx>), Type(Ty<'tcx>), Const(ty::Const<'tcx>), } +/// This function goes from `&'a [Ty<'tcx>]` to `&'a [GenericArg<'tcx>]` +/// +/// This is sound as, for types, `GenericArg` is just +/// `NonZeroUsize::new_unchecked(ty as *const _ as usize)` as +/// long as we use `0` for the `TYPE_TAG`. +pub fn ty_slice_as_generic_args<'a, 'tcx>(ts: &'a [Ty<'tcx>]) -> &'a [GenericArg<'tcx>] { + assert_eq!(TYPE_TAG, 0); + // SAFETY: the whole slice is valid and immutable. + // `Ty` and `GenericArg` is explained above. + unsafe { slice::from_raw_parts(ts.as_ptr().cast(), ts.len()) } +} + +impl<'tcx> List> { + /// Allows to freely switch betwen `List>` and `List>`. + /// + /// As lists are interned, `List>` and `List>` have + /// be interned together, see `intern_type_list` for more details. + #[inline] + pub fn as_substs(&'tcx self) -> SubstsRef<'tcx> { + assert_eq!(TYPE_TAG, 0); + // SAFETY: `List` is `#[repr(C)]`. `Ty` and `GenericArg` is explained above. + unsafe { &*(self as *const List> as *const List>) } + } +} + impl<'tcx> GenericArgKind<'tcx> { #[inline] fn pack(self) -> GenericArg<'tcx> { @@ -208,6 +234,17 @@ pub type InternalSubsts<'tcx> = List>; pub type SubstsRef<'tcx> = &'tcx InternalSubsts<'tcx>; impl<'a, 'tcx> InternalSubsts<'tcx> { + /// Checks whether all elements of this list are types, if so, transmute. + pub fn try_as_type_list(&'tcx self) -> Option<&'tcx List>> { + if self.iter().all(|arg| matches!(arg.unpack(), GenericArgKind::Type(_))) { + assert_eq!(TYPE_TAG, 0); + // SAFETY: All elements are types, see `List>::as_substs`. + Some(unsafe { &*(self as *const List> as *const List>) }) + } else { + None + } + } + /// Interpret these substitutions as the substitutions of a closure type. /// Closure substitutions have a particular structure controlled by the /// compiler that encodes information like the signature and closure kind; @@ -422,6 +459,45 @@ impl<'tcx> TypeFoldable<'tcx> for SubstsRef<'tcx> { } } +impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List> { + fn try_super_fold_with>( + self, + folder: &mut F, + ) -> Result { + // This code is fairly hot, though not as hot as `SubstsRef`. + // + // When compiling stage 2, I get the following results: + // + // len | total | % + // --- | --------- | ----- + // 2 | 15083590 | 48.1 + // 3 | 7540067 | 24.0 + // 1 | 5300377 | 16.9 + // 4 | 1351897 | 4.3 + // 0 | 1256849 | 4.0 + // + // I've tried it with some private repositories and got + // close to the same result, with 4 and 0 swapping places + // sometimes. + match self.len() { + 2 => { + let param0 = self[0].try_fold_with(folder)?; + let param1 = self[1].try_fold_with(folder)?; + if param0 == self[0] && param1 == self[1] { + Ok(self) + } else { + Ok(folder.tcx().intern_type_list(&[param0, param1])) + } + } + _ => ty::util::fold_list(self, folder, |tcx, v| tcx.intern_type_list(v)), + } + } + + fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow { + self.iter().try_for_each(|t| t.visit_with(visitor)) + } +} + /////////////////////////////////////////////////////////////////////////// // Public trait `Subst` // diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index c2a4cea2b1ae6..c13aecd1b14aa 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -17,7 +17,7 @@ use rustc_data_structures::intern::Interned; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_errors::ErrorReported; use rustc_hir as hir; -use rustc_hir::def::DefKind; +use rustc_hir::def::{CtorOf, DefKind, Res}; use rustc_hir::def_id::DefId; use rustc_macros::HashStable; use rustc_query_system::ich::NodeIdHashingMode; @@ -146,6 +146,37 @@ impl<'tcx> TyCtxt<'tcx> { hasher.finish() } + pub fn res_generics_def_id(self, res: Res) -> Option { + match res { + Res::Def(DefKind::Ctor(CtorOf::Variant, _), def_id) => { + Some(self.parent(def_id).and_then(|def_id| self.parent(def_id)).unwrap()) + } + Res::Def(DefKind::Variant | DefKind::Ctor(CtorOf::Struct, _), def_id) => { + Some(self.parent(def_id).unwrap()) + } + // Other `DefKind`s don't have generics and would ICE when calling + // `generics_of`. + Res::Def( + DefKind::Struct + | DefKind::Union + | DefKind::Enum + | DefKind::Trait + | DefKind::OpaqueTy + | DefKind::TyAlias + | DefKind::ForeignTy + | DefKind::TraitAlias + | DefKind::AssocTy + | DefKind::Fn + | DefKind::AssocFn + | DefKind::AssocConst + | DefKind::Impl, + def_id, + ) => Some(def_id), + Res::Err => None, + _ => None, + } + } + pub fn has_error_field(self, ty: Ty<'tcx>) -> bool { if let ty::Adt(def, substs) = *ty.kind() { for field in def.all_fields() { @@ -217,7 +248,7 @@ impl<'tcx> TyCtxt<'tcx> { } ty::Tuple(tys) if let Some((&last_ty, _)) = tys.split_last() => { - ty = last_ty.expect_ty(); + ty = last_ty; } ty::Tuple(_) => break, @@ -288,9 +319,9 @@ impl<'tcx> TyCtxt<'tcx> { } } (&Tuple(a_tys), &Tuple(b_tys)) if a_tys.len() == b_tys.len() => { - if let Some(a_last) = a_tys.last() { - a = a_last.expect_ty(); - b = b_tys.last().unwrap().expect_ty(); + if let Some(&a_last) = a_tys.last() { + a = a_last; + b = *b_tys.last().unwrap(); } else { break; } @@ -715,7 +746,7 @@ impl<'tcx> Ty<'tcx> { | ty::FnDef(..) | ty::Error(_) | ty::FnPtr(_) => true, - ty::Tuple(_) => self.tuple_fields().all(|f| Self::is_trivially_freeze(f)), + ty::Tuple(fields) => fields.iter().all(Self::is_trivially_freeze), ty::Slice(elem_ty) | ty::Array(elem_ty, _) => elem_ty.is_trivially_freeze(), ty::Adt(..) | ty::Bound(..) @@ -755,7 +786,7 @@ impl<'tcx> Ty<'tcx> { | ty::FnDef(..) | ty::Error(_) | ty::FnPtr(_) => true, - ty::Tuple(_) => self.tuple_fields().all(|f| Self::is_trivially_unpin(f)), + ty::Tuple(fields) => fields.iter().all(Self::is_trivially_unpin), ty::Slice(elem_ty) | ty::Array(elem_ty, _) => elem_ty.is_trivially_unpin(), ty::Adt(..) | ty::Bound(..) @@ -1011,7 +1042,7 @@ pub fn needs_drop_components<'tcx>( } } // If any field needs drop, then the whole tuple does. - ty::Tuple(..) => ty.tuple_fields().try_fold(SmallVec::new(), move |mut acc, elem| { + ty::Tuple(fields) => fields.iter().try_fold(SmallVec::new(), move |mut acc, elem| { acc.extend(needs_drop_components(elem, target_layout)?); Ok(acc) }), @@ -1061,7 +1092,7 @@ pub fn is_trivially_const_drop<'tcx>(ty: Ty<'tcx>) -> bool { ty::Array(ty, _) | ty::Slice(ty) => is_trivially_const_drop(ty), - ty::Tuple(tys) => tys.iter().all(|ty| is_trivially_const_drop(ty.expect_ty())), + ty::Tuple(tys) => tys.iter().all(|ty| is_trivially_const_drop(ty)), } } diff --git a/compiler/rustc_middle/src/ty/walk.rs b/compiler/rustc_middle/src/ty/walk.rs index ab70c15160ca6..9f57e1a977a93 100644 --- a/compiler/rustc_middle/src/ty/walk.rs +++ b/compiler/rustc_middle/src/ty/walk.rs @@ -175,10 +175,10 @@ fn push_inner<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent: GenericArg<'tcx>) | ty::Opaque(_, substs) | ty::Closure(_, substs) | ty::Generator(_, substs, _) - | ty::Tuple(substs) | ty::FnDef(_, substs) => { stack.extend(substs.iter().rev()); } + ty::Tuple(ts) => stack.extend(ts.as_substs().iter().rev()), ty::GeneratorWitness(ts) => { stack.extend(ts.skip_binder().iter().rev().map(|ty| ty.into())); } diff --git a/compiler/rustc_mir_build/src/build/block.rs b/compiler/rustc_mir_build/src/build/block.rs index df71379c1d886..f98025f7953f9 100644 --- a/compiler/rustc_mir_build/src/build/block.rs +++ b/compiler/rustc_mir_build/src/build/block.rs @@ -3,8 +3,6 @@ use crate::build::ForGuard::OutsideGuard; use crate::build::{BlockAnd, BlockAndExtension, BlockFrame, Builder}; use rustc_middle::mir::*; use rustc_middle::thir::*; -use rustc_session::lint::builtin::UNSAFE_OP_IN_UNSAFE_FN; -use rustc_session::lint::Level; use rustc_span::Span; impl<'a, 'tcx> Builder<'a, 'tcx> { @@ -209,28 +207,18 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { block.unit() } - /// If we are changing the safety mode, create a new source scope + /// If we are entering an unsafe block, create a new source scope fn update_source_scope_for_safety_mode(&mut self, span: Span, safety_mode: BlockSafety) { debug!("update_source_scope_for({:?}, {:?})", span, safety_mode); let new_unsafety = match safety_mode { - BlockSafety::Safe => None, - BlockSafety::BuiltinUnsafe => Some(Safety::BuiltinUnsafe), + BlockSafety::Safe => return, + BlockSafety::BuiltinUnsafe => Safety::BuiltinUnsafe, BlockSafety::ExplicitUnsafe(hir_id) => { - match self.in_scope_unsafe { - Safety::Safe => {} - // no longer treat `unsafe fn`s as `unsafe` contexts (see RFC #2585) - Safety::FnUnsafe - if self.tcx.lint_level_at_node(UNSAFE_OP_IN_UNSAFE_FN, hir_id).0 - != Level::Allow => {} - _ => return, - } self.in_scope_unsafe = Safety::ExplicitUnsafe(hir_id); - Some(Safety::ExplicitUnsafe(hir_id)) + Safety::ExplicitUnsafe(hir_id) } }; - if let Some(unsafety) = new_unsafety { - self.source_scope = self.new_source_scope(span, LintLevel::Inherited, Some(unsafety)); - } + self.source_scope = self.new_source_scope(span, LintLevel::Inherited, Some(new_unsafety)); } } diff --git a/compiler/rustc_mir_build/src/build/expr/as_constant.rs b/compiler/rustc_mir_build/src/build/expr/as_constant.rs index 0c0b0f2bd05af..79ac09d523d07 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_constant.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_constant.rs @@ -1,7 +1,6 @@ //! See docs in build/expr/mod.rs use crate::build::Builder; -use rustc_middle::mir::interpret::{ConstValue, Scalar}; use rustc_middle::mir::*; use rustc_middle::thir::*; use rustc_middle::ty::CanonicalUserTypeAnnotation; @@ -27,12 +26,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { assert_eq!(literal.ty(), ty); Constant { span, user_ty, literal: literal.into() } } - ExprKind::StaticRef { alloc_id, ty, .. } => { - let const_val = - ConstValue::Scalar(Scalar::from_pointer(alloc_id.into(), &this.tcx)); - let literal = ConstantKind::Val(const_val, ty); - - Constant { span, user_ty: None, literal } + ExprKind::StaticRef { literal, .. } => { + Constant { span, user_ty: None, literal: literal.into() } } ExprKind::ConstBlock { value } => { Constant { span: span, user_ty: None, literal: value.into() } diff --git a/compiler/rustc_mir_build/src/build/expr/as_place.rs b/compiler/rustc_mir_build/src/build/expr/as_place.rs index 1e94c41d88daa..389f711099ba0 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_place.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_place.rs @@ -256,7 +256,7 @@ fn to_upvars_resolved_place_builder<'a, 'tcx>( // We must have inferred the capture types since we are building MIR, therefore // it's safe to call `tuple_element_ty` and we can unwrap here because // we know that the capture exists and is the `capture_index`-th capture. - let var_ty = substs.tupled_upvars_ty().tuple_element_ty(capture_index).unwrap(); + let var_ty = substs.tupled_upvars_ty().tuple_fields()[capture_index]; upvar_resolved_place_builder = upvar_resolved_place_builder.field(Field::new(capture_index), var_ty); diff --git a/compiler/rustc_mir_build/src/build/matches/test.rs b/compiler/rustc_mir_build/src/build/matches/test.rs index ce848773b10cc..da9c4b930df47 100644 --- a/compiler/rustc_mir_build/src/build/matches/test.rs +++ b/compiler/rustc_mir_build/src/build/matches/test.rs @@ -126,11 +126,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { candidate: &Candidate<'pat, 'tcx>, variants: &mut BitSet, ) -> bool { - let match_pair = match candidate.match_pairs.iter().find(|mp| mp.place == *test_place) { - Some(match_pair) => match_pair, - _ => { - return false; - } + let Some(match_pair) = candidate.match_pairs.iter().find(|mp| mp.place == *test_place) else { + return false; }; match *match_pair.pattern.kind { @@ -421,9 +418,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } } - let deref_ty = match *ty.kind() { - ty::Ref(_, deref_ty, _) => deref_ty, - _ => bug!("non_scalar_compare called on non-reference type: {}", ty), + let ty::Ref(_, deref_ty, _) = *ty.kind() else { + bug!("non_scalar_compare called on non-reference type: {}", ty); }; let eq_def_id = self.tcx.require_lang_item(LangItem::PartialEq, None); diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs index fb403615e572f..f2f85043df292 100644 --- a/compiler/rustc_mir_build/src/build/mod.rs +++ b/compiler/rustc_mir_build/src/build/mod.rs @@ -266,9 +266,8 @@ fn liberated_closure_env_ty( ) -> Ty<'_> { let closure_ty = tcx.typeck_body(body_id).node_type(closure_expr_id); - let (closure_def_id, closure_substs) = match *closure_ty.kind() { - ty::Closure(closure_def_id, closure_substs) => (closure_def_id, closure_substs), - _ => bug!("closure expr does not have closure type: {:?}", closure_ty), + let ty::Closure(closure_def_id, closure_substs) = *closure_ty.kind() else { + bug!("closure expr does not have closure type: {:?}", closure_ty); }; let bound_vars = diff --git a/compiler/rustc_mir_build/src/thir/constant.rs b/compiler/rustc_mir_build/src/thir/constant.rs index ec2ff3c37ab73..72c0985a63c33 100644 --- a/compiler/rustc_mir_build/src/thir/constant.rs +++ b/compiler/rustc_mir_build/src/thir/constant.rs @@ -62,10 +62,7 @@ fn parse_float<'tcx>(num: Symbol, fty: ty::FloatTy, neg: bool) -> Option { - let rust_f = match num.parse::() { - Ok(f) => f, - Err(_) => return None, - }; + let Ok(rust_f) = num.parse::() else { return None }; let mut f = num.parse::().unwrap_or_else(|e| { panic!("apfloat::ieee::Single failed to parse `{}`: {:?}", num, e) }); @@ -85,10 +82,7 @@ fn parse_float<'tcx>(num: Symbol, fty: ty::FloatTy, neg: bool) -> Option { - let rust_f = match num.parse::() { - Ok(f) => f, - Err(_) => return None, - }; + let Ok(rust_f) = num.parse::() else { return None }; let mut f = num.parse::().unwrap_or_else(|e| { panic!("apfloat::ieee::Double failed to parse `{}`: {:?}", num, e) }); diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index 829dec74803dd..651edc827c320 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -8,6 +8,7 @@ use rustc_middle::hir::place::Place as HirPlace; use rustc_middle::hir::place::PlaceBase as HirPlaceBase; use rustc_middle::hir::place::ProjectionKind as HirProjectionKind; use rustc_middle::middle::region; +use rustc_middle::mir::interpret::Scalar; use rustc_middle::mir::{BinOp, BorrowKind, Field, UnOp}; use rustc_middle::thir::*; use rustc_middle::ty::adjustment::{ @@ -503,13 +504,12 @@ impl<'tcx> Cx<'tcx> { InlineAsmOperand::Const { value, span } } hir::InlineAsmOperand::Sym { ref expr } => { - let qpath = match expr.kind { - hir::ExprKind::Path(ref qpath) => qpath, - _ => span_bug!( + let hir::ExprKind::Path(ref qpath) = expr.kind else { + span_bug!( expr.span, "asm `sym` operand should be a path, found {:?}", expr.kind - ), + ); }; let temp_lifetime = self.region_scope_tree.temporary_scope(expr.hir_id.local_id); @@ -577,9 +577,8 @@ impl<'tcx> Cx<'tcx> { // Now comes the rote stuff: hir::ExprKind::Repeat(ref v, _) => { let ty = self.typeck_results().expr_ty(expr); - let count = match ty.kind() { - ty::Array(_, ct) => ct, - _ => span_bug!(expr.span, "unexpected repeat expr ty: {:?}", ty), + let ty::Array(_, count) = ty.kind() else { + span_bug!(expr.span, "unexpected repeat expr ty: {:?}", ty); }; ExprKind::Repeat { value: self.mirror_expr(v), count: *count } @@ -942,8 +941,15 @@ impl<'tcx> Cx<'tcx> { let kind = if self.tcx.is_thread_local_static(id) { ExprKind::ThreadLocalRef(id) } else { - let alloc_id = self.tcx.create_static_alloc(id); - ExprKind::StaticRef { alloc_id, ty, def_id: id } + let ptr = self.tcx.create_static_alloc(id); + ExprKind::StaticRef { + literal: ty::Const::from_scalar( + self.tcx, + Scalar::from_pointer(ptr.into(), &self.tcx), + ty, + ), + def_id: id, + } }; ExprKind::Deref { arg: self.thir.exprs.push(Expr { ty, temp_lifetime, span: expr.span, kind }), @@ -1007,9 +1013,8 @@ impl<'tcx> Cx<'tcx> { // Reconstruct the output assuming it's a reference with the // same region and mutability as the receiver. This holds for // `Deref(Mut)::Deref(_mut)` and `Index(Mut)::index(_mut)`. - let (region, mutbl) = match *self.thir[args[0]].ty.kind() { - ty::Ref(region, _, mutbl) => (region, mutbl), - _ => span_bug!(span, "overloaded_place: receiver is not a reference"), + let ty::Ref(region, _, mutbl) = *self.thir[args[0]].ty.kind() else { + span_bug!(span, "overloaded_place: receiver is not a reference"); }; let ref_ty = self.tcx.mk_ref(region, ty::TypeAndMut { ty: place_ty, mutbl }); diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs index 7db71ed598d93..b83cbb753df72 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs @@ -121,7 +121,7 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> { fn search_for_structural_match_violation(&self, ty: Ty<'tcx>) -> Option { traits::search_for_structural_match_violation(self.span, self.tcx(), ty).map(|non_sm_ty| { - with_no_trimmed_paths(|| match non_sm_ty { + with_no_trimmed_paths!(match non_sm_ty { traits::NonStructuralMatchTy::Adt(adt) => self.adt_derive_msg(adt), traits::NonStructuralMatchTy::Dynamic => { "trait objects cannot be used in patterns".to_string() diff --git a/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs index e4d9bd9c237e9..1c4c668c0f273 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs @@ -560,9 +560,9 @@ impl SplitVarLenSlice { /// Pass a set of slices relative to which to split this one. fn split(&mut self, slices: impl Iterator) { - let (max_prefix_len, max_suffix_len) = match &mut self.max_slice { - VarLen(prefix, suffix) => (prefix, suffix), - FixedLen(_) => return, // No need to split + let VarLen(max_prefix_len, max_suffix_len) = &mut self.max_slice else { + // No need to split + return; }; // We grow `self.max_slice` to be larger than all slices encountered, as described above. // For diagnostics, we keep the prefix and suffix lengths separate, but grow them so that @@ -1181,10 +1181,7 @@ impl<'p, 'tcx> Fields<'p, 'tcx> { ty: Ty<'tcx>, variant: &'a VariantDef, ) -> impl Iterator)> + Captures<'a> + Captures<'p> { - let (adt, substs) = match ty.kind() { - ty::Adt(adt, substs) => (adt, substs), - _ => bug!(), - }; + let ty::Adt(adt, substs) = ty.kind() else { bug!() }; // Whether we must not match the fields of this variant exhaustively. let is_non_exhaustive = variant.is_field_list_non_exhaustive() && !adt.did.is_local(); @@ -1212,7 +1209,7 @@ impl<'p, 'tcx> Fields<'p, 'tcx> { ) -> Self { let ret = match constructor { Single | Variant(_) => match ty.kind() { - ty::Tuple(fs) => Fields::wildcards_from_tys(cx, fs.iter().map(|ty| ty.expect_ty())), + ty::Tuple(fs) => Fields::wildcards_from_tys(cx, fs.iter()), ty::Ref(_, rty, _) => Fields::wildcards_from_tys(cx, once(*rty)), ty::Adt(adt, substs) => { if adt.is_box() { @@ -1318,11 +1315,8 @@ impl<'p, 'tcx> DeconstructedPat<'p, 'tcx> { match pat.ty.kind() { ty::Tuple(fs) => { ctor = Single; - let mut wilds: SmallVec<[_; 2]> = fs - .iter() - .map(|ty| ty.expect_ty()) - .map(DeconstructedPat::wildcard) - .collect(); + let mut wilds: SmallVec<[_; 2]> = + fs.iter().map(DeconstructedPat::wildcard).collect(); for pat in subpatterns { wilds[pat.field.index()] = mkpat(&pat.pattern); } @@ -1578,9 +1572,8 @@ impl<'p, 'tcx> DeconstructedPat<'p, 'tcx> { match self_slice.kind { FixedLen(_) => bug!("{:?} doesn't cover {:?}", self_slice, other_slice), VarLen(prefix, suffix) => { - let inner_ty = match *self.ty.kind() { - ty::Slice(ty) | ty::Array(ty, _) => ty, - _ => bug!("bad slice pattern {:?} {:?}", self.ctor, self.ty), + let (ty::Slice(inner_ty) | ty::Array(inner_ty, _)) = *self.ty.kind() else { + bug!("bad slice pattern {:?} {:?}", self.ctor, self.ty); }; let prefix = &self.fields.fields[..prefix]; let suffix = &self.fields.fields[self_slice.arity() - suffix..]; diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index ddf39fb824cda..0c1daa519ab7c 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -245,9 +245,8 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { } hir::PatKind::Tuple(ref pats, ddpos) => { - let tys = match ty.kind() { - ty::Tuple(ref tys) => tys, - _ => span_bug!(pat.span, "unexpected type for tuple pattern: {:?}", ty), + let ty::Tuple(ref tys) = ty.kind() else { + span_bug!(pat.span, "unexpected type for tuple pattern: {:?}", ty); }; let subpatterns = self.lower_tuple_subpats(pats, tys.len(), ddpos); PatKind::Leaf { subpatterns } @@ -294,9 +293,8 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { hir::PatKind::TupleStruct(ref qpath, ref pats, ddpos) => { let res = self.typeck_results.qpath_res(qpath, pat.hir_id); - let adt_def = match ty.kind() { - ty::Adt(adt_def, _) => adt_def, - _ => span_bug!(pat.span, "tuple struct pattern not applied to an ADT {:?}", ty), + let ty::Adt(adt_def, _) = ty.kind() else { + span_bug!(pat.span, "tuple struct pattern not applied to an ADT {:?}", ty); }; let variant_def = adt_def.variant_of_res(res); let subpatterns = self.lower_tuple_subpats(pats, variant_def.fields.len(), ddpos); @@ -576,9 +574,8 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { } hir::ExprKind::Lit(ref lit) => (lit, false), hir::ExprKind::Unary(hir::UnOp::Neg, ref expr) => { - let lit = match expr.kind { - hir::ExprKind::Lit(ref lit) => lit, - _ => span_bug!(expr.span, "not a literal: {:?}", expr), + let hir::ExprKind::Lit(ref lit) = expr.kind else { + span_bug!(expr.span, "not a literal: {:?}", expr); }; (lit, true) } diff --git a/compiler/rustc_mir_dataflow/src/drop_flag_effects.rs b/compiler/rustc_mir_dataflow/src/drop_flag_effects.rs index e2269562b3d9b..f102872cd2d06 100644 --- a/compiler/rustc_mir_dataflow/src/drop_flag_effects.rs +++ b/compiler/rustc_mir_dataflow/src/drop_flag_effects.rs @@ -243,9 +243,8 @@ pub(crate) fn on_all_inactive_variants<'tcx>( active_variant: VariantIdx, mut handle_inactive_variant: impl FnMut(MovePathIndex), ) { - let enum_mpi = match move_data.rev_lookup.find(enum_place.as_ref()) { - LookupResult::Exact(mpi) => mpi, - LookupResult::Parent(_) => return, + let LookupResult::Exact(enum_mpi) = move_data.rev_lookup.find(enum_place.as_ref()) else { + return; }; let enum_path = &move_data.move_paths[enum_mpi]; @@ -256,9 +255,8 @@ pub(crate) fn on_all_inactive_variants<'tcx>( let (downcast, base_proj) = variant_path.place.projection.split_last().unwrap(); assert_eq!(enum_place.projection.len(), base_proj.len()); - let variant_idx = match *downcast { - mir::ProjectionElem::Downcast(_, idx) => idx, - _ => unreachable!(), + let mir::ProjectionElem::Downcast(_, variant_idx) = *downcast else { + unreachable!(); }; if variant_idx != active_variant { diff --git a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs index 3e1013b035152..774df75211364 100644 --- a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs +++ b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs @@ -866,10 +866,7 @@ where let tys: Vec<_> = substs.as_generator().upvar_tys().collect(); self.open_drop_for_tuple(&tys) } - ty::Tuple(..) => { - let tys: Vec<_> = ty.tuple_fields().collect(); - self.open_drop_for_tuple(&tys) - } + ty::Tuple(fields) => self.open_drop_for_tuple(fields), ty::Adt(def, substs) => { if def.is_box() { self.open_drop_for_box(def, substs) diff --git a/compiler/rustc_mir_dataflow/src/framework/engine.rs b/compiler/rustc_mir_dataflow/src/framework/engine.rs index e8a6d8dad439e..e20358ba9896d 100644 --- a/compiler/rustc_mir_dataflow/src/framework/engine.rs +++ b/compiler/rustc_mir_dataflow/src/framework/engine.rs @@ -274,11 +274,9 @@ where use std::io::{self, Write}; let def_id = body.source.def_id(); - let attrs = match RustcMirAttrs::parse(tcx, def_id) { - Ok(attrs) => attrs, - + let Ok(attrs) = RustcMirAttrs::parse(tcx, def_id) else { // Invalid `rustc_mir` attrs are reported in `RustcMirAttrs::parse` - Err(()) => return Ok(()), + return Ok(()); }; let mut file = match attrs.output_path(A::NAME) { diff --git a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs index 34bc157a744a7..599b4087c78e4 100644 --- a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs +++ b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs @@ -628,9 +628,8 @@ where ret }); - let mut html_diff = match html_diff { - Cow::Borrowed(_) => return raw_diff, - Cow::Owned(s) => s, + let Cow::Owned(mut html_diff) = html_diff else { + return raw_diff; }; if inside_font_tag { diff --git a/compiler/rustc_mir_dataflow/src/impls/mod.rs b/compiler/rustc_mir_dataflow/src/impls/mod.rs index 5dc8a003b4778..63d935db8ca13 100644 --- a/compiler/rustc_mir_dataflow/src/impls/mod.rs +++ b/compiler/rustc_mir_dataflow/src/impls/mod.rs @@ -385,16 +385,14 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeInitializedPlaces<'_, 'tcx> { switch_on_enum_discriminant(self.tcx, &self.body, &self.body[block], discr) }); - let (enum_place, enum_def) = match enum_ { - Some(x) => x, - None => return, + let Some((enum_place, enum_def)) = enum_ else { + return; }; let mut discriminants = enum_def.discriminants(self.tcx); edge_effects.apply(|trans, edge| { - let value = match edge.value { - Some(x) => x, - None => return, + let Some(value) = edge.value else { + return; }; // MIR building adds discriminants to the `values` array in the same order as they @@ -507,16 +505,14 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> { switch_on_enum_discriminant(self.tcx, &self.body, &self.body[block], discr) }); - let (enum_place, enum_def) = match enum_ { - Some(x) => x, - None => return, + let Some((enum_place, enum_def)) = enum_ else { + return; }; let mut discriminants = enum_def.discriminants(self.tcx); edge_effects.apply(|trans, edge| { - let value = match edge.value { - Some(x) => x, - None => return, + let Some(value) = edge.value else { + return; }; // MIR building adds discriminants to the `values` array in the same order as they diff --git a/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs b/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs index 1abb64219f6e9..757dc09375584 100644 --- a/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs +++ b/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs @@ -66,10 +66,7 @@ impl<'tcx> MirPass<'tcx> for AbortUnwindingCalls { if block.is_cleanup { continue; } - let terminator = match &block.terminator { - Some(terminator) => terminator, - None => continue, - }; + let Some(terminator) = &block.terminator else { continue }; let span = terminator.source_info.span; let call_can_unwind = match &terminator.kind { diff --git a/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs b/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs index 9eaf2b6a21113..8de0aad041cc3 100644 --- a/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs +++ b/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs @@ -84,9 +84,8 @@ fn add_move_for_packed_drop<'tcx>( is_cleanup: bool, ) { debug!("add_move_for_packed_drop({:?} @ {:?})", terminator, loc); - let (place, target, unwind) = match terminator.kind { - TerminatorKind::Drop { ref place, target, unwind } => (place, target, unwind), - _ => unreachable!(), + let TerminatorKind::Drop { ref place, target, unwind } = terminator.kind else { + unreachable!(); }; let source_info = terminator.source_info; diff --git a/compiler/rustc_mir_transform/src/check_unsafety.rs b/compiler/rustc_mir_transform/src/check_unsafety.rs index fd93744d40091..eaf3f19bff196 100644 --- a/compiler/rustc_mir_transform/src/check_unsafety.rs +++ b/compiler/rustc_mir_transform/src/check_unsafety.rs @@ -1,17 +1,17 @@ -use rustc_data_structures::fx::FxHashSet; +use rustc_data_structures::fx::FxHashMap; use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::hir_id::HirId; use rustc_hir::intravisit; -use rustc_hir::Node; use rustc_middle::mir::visit::{MutatingUseContext, PlaceContext, Visitor}; -use rustc_middle::mir::*; use rustc_middle::ty::query::Providers; use rustc_middle::ty::{self, TyCtxt}; +use rustc_middle::{lint, mir::*}; use rustc_session::lint::builtin::{UNSAFE_OP_IN_UNSAFE_FN, UNUSED_UNSAFE}; use rustc_session::lint::Level; +use std::collections::hash_map; use std::ops::Bound; pub struct UnsafetyChecker<'a, 'tcx> { @@ -21,9 +21,12 @@ pub struct UnsafetyChecker<'a, 'tcx> { source_info: SourceInfo, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, - /// Mark an `unsafe` block as used, so we don't lint it. - used_unsafe: FxHashSet, - inherited_blocks: Vec<(hir::HirId, bool)>, + + /// Used `unsafe` blocks in this function. This is used for the "unused_unsafe" lint. + /// + /// The keys are the used `unsafe` blocks, the UnusedUnsafeKind indicates whether + /// or not any of the usages happen at a place that doesn't allow `unsafe_op_in_unsafe_fn`. + used_unsafe_blocks: FxHashMap, } impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> { @@ -40,8 +43,7 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> { source_info: SourceInfo::outermost(body.span), tcx, param_env, - used_unsafe: Default::default(), - inherited_blocks: vec![], + used_unsafe_blocks: Default::default(), } } } @@ -123,9 +125,9 @@ impl<'tcx> Visitor<'tcx> for UnsafetyChecker<'_, 'tcx> { } } &AggregateKind::Closure(def_id, _) | &AggregateKind::Generator(def_id, _, _) => { - let UnsafetyCheckResult { violations, unsafe_blocks } = + let UnsafetyCheckResult { violations, used_unsafe_blocks, .. } = self.tcx.unsafety_check_result(def_id.expect_local()); - self.register_violations(&violations, &unsafe_blocks); + self.register_violations(violations, used_unsafe_blocks); } }, _ => {} @@ -251,61 +253,72 @@ impl<'tcx> UnsafetyChecker<'_, 'tcx> { .assert_crate_local() .lint_root; self.register_violations( - &[UnsafetyViolation { source_info, lint_root, kind, details }], - &[], + [&UnsafetyViolation { source_info, lint_root, kind, details }], + [], ); } - fn register_violations( + fn register_violations<'a>( &mut self, - violations: &[UnsafetyViolation], - unsafe_blocks: &[(hir::HirId, bool)], + violations: impl IntoIterator, + new_used_unsafe_blocks: impl IntoIterator, ) { + use UsedUnsafeBlockData::{AllAllowedInUnsafeFn, SomeDisallowedInUnsafeFn}; + + let update_entry = |this: &mut Self, hir_id, new_usage| { + match this.used_unsafe_blocks.entry(hir_id) { + hash_map::Entry::Occupied(mut entry) => { + if new_usage == SomeDisallowedInUnsafeFn { + *entry.get_mut() = SomeDisallowedInUnsafeFn; + } + } + hash_map::Entry::Vacant(entry) => { + entry.insert(new_usage); + } + }; + }; let safety = self.body.source_scopes[self.source_info.scope] .local_data .as_ref() .assert_crate_local() .safety; - let within_unsafe = match safety { + match safety { // `unsafe` blocks are required in safe code - Safety::Safe => { - for violation in violations { - match violation.kind { - UnsafetyViolationKind::General => {} - UnsafetyViolationKind::UnsafeFn => { - bug!("`UnsafetyViolationKind::UnsafeFn` in an `Safe` context") - } - } - if !self.violations.contains(violation) { - self.violations.push(*violation) + Safety::Safe => violations.into_iter().for_each(|&violation| { + match violation.kind { + UnsafetyViolationKind::General => {} + UnsafetyViolationKind::UnsafeFn => { + bug!("`UnsafetyViolationKind::UnsafeFn` in an `Safe` context") } } - false - } - // With the RFC 2585, no longer allow `unsafe` operations in `unsafe fn`s - Safety::FnUnsafe => { - for violation in violations { - let mut violation = *violation; - - violation.kind = UnsafetyViolationKind::UnsafeFn; - if !self.violations.contains(&violation) { - self.violations.push(violation) - } + if !self.violations.contains(&violation) { + self.violations.push(violation) } - false - } - Safety::BuiltinUnsafe => true, - Safety::ExplicitUnsafe(hir_id) => { - // mark unsafe block as used if there are any unsafe operations inside - if !violations.is_empty() { - self.used_unsafe.insert(hir_id); + }), + // With the RFC 2585, no longer allow `unsafe` operations in `unsafe fn`s + Safety::FnUnsafe => violations.into_iter().for_each(|&(mut violation)| { + violation.kind = UnsafetyViolationKind::UnsafeFn; + if !self.violations.contains(&violation) { + self.violations.push(violation) } - true - } + }), + Safety::BuiltinUnsafe => {} + Safety::ExplicitUnsafe(hir_id) => violations.into_iter().for_each(|violation| { + update_entry( + self, + hir_id, + match self.tcx.lint_level_at_node(UNSAFE_OP_IN_UNSAFE_FN, violation.lint_root).0 + { + Level::Allow => AllAllowedInUnsafeFn(violation.lint_root), + _ => SomeDisallowedInUnsafeFn, + }, + ) + }), }; - self.inherited_blocks.extend( - unsafe_blocks.iter().map(|&(hir_id, is_used)| (hir_id, is_used && !within_unsafe)), - ); + + new_used_unsafe_blocks + .into_iter() + .for_each(|(&hir_id, &usage_data)| update_entry(self, hir_id, usage_data)); } fn check_mut_borrowing_layout_constrained_field( &mut self, @@ -387,17 +400,64 @@ pub(crate) fn provide(providers: &mut Providers) { }; } -struct UnusedUnsafeVisitor<'a> { - used_unsafe: &'a FxHashSet, - unsafe_blocks: &'a mut Vec<(hir::HirId, bool)>, +/// Context information for [`UnusedUnsafeVisitor`] traversal, +/// saves (innermost) relevant context +#[derive(Copy, Clone, Debug)] +enum Context { + Safe, + /// in an `unsafe fn` + UnsafeFn(HirId), + /// in a *used* `unsafe` block + /// (i.e. a block without unused-unsafe warning) + UnsafeBlock(HirId), +} + +struct UnusedUnsafeVisitor<'a, 'tcx> { + tcx: TyCtxt<'tcx>, + used_unsafe_blocks: &'a FxHashMap, + context: Context, + unused_unsafes: &'a mut Vec<(HirId, UnusedUnsafe)>, } -impl<'tcx> intravisit::Visitor<'tcx> for UnusedUnsafeVisitor<'_> { +impl<'tcx> intravisit::Visitor<'tcx> for UnusedUnsafeVisitor<'_, 'tcx> { fn visit_block(&mut self, block: &'tcx hir::Block<'tcx>) { - intravisit::walk_block(self, block); + use UsedUnsafeBlockData::{AllAllowedInUnsafeFn, SomeDisallowedInUnsafeFn}; if let hir::BlockCheckMode::UnsafeBlock(hir::UnsafeSource::UserProvided) = block.rules { - self.unsafe_blocks.push((block.hir_id, self.used_unsafe.contains(&block.hir_id))); + let used = match self.tcx.lint_level_at_node(UNUSED_UNSAFE, block.hir_id) { + (Level::Allow, _) => Some(SomeDisallowedInUnsafeFn), + _ => self.used_unsafe_blocks.get(&block.hir_id).copied(), + }; + let unused_unsafe = match (self.context, used) { + (_, None) => UnusedUnsafe::Unused, + (Context::Safe, Some(_)) + | (Context::UnsafeFn(_), Some(SomeDisallowedInUnsafeFn)) => { + let previous_context = self.context; + self.context = Context::UnsafeBlock(block.hir_id); + intravisit::walk_block(self, block); + self.context = previous_context; + return; + } + (Context::UnsafeFn(hir_id), Some(AllAllowedInUnsafeFn(lint_root))) => { + UnusedUnsafe::InUnsafeFn(hir_id, lint_root) + } + (Context::UnsafeBlock(hir_id), Some(_)) => UnusedUnsafe::InUnsafeBlock(hir_id), + }; + self.unused_unsafes.push((block.hir_id, unused_unsafe)); + } + intravisit::walk_block(self, block); + } + + fn visit_fn( + &mut self, + fk: intravisit::FnKind<'tcx>, + _fd: &'tcx hir::FnDecl<'tcx>, + b: hir::BodyId, + _s: rustc_span::Span, + _id: HirId, + ) { + if matches!(fk, intravisit::FnKind::Closure) { + self.visit_body(self.tcx.hir().body(b)) } } } @@ -405,23 +465,38 @@ impl<'tcx> intravisit::Visitor<'tcx> for UnusedUnsafeVisitor<'_> { fn check_unused_unsafe( tcx: TyCtxt<'_>, def_id: LocalDefId, - used_unsafe: &FxHashSet, - unsafe_blocks: &mut Vec<(hir::HirId, bool)>, -) { - let body_id = tcx.hir().maybe_body_owned_by(tcx.hir().local_def_id_to_hir_id(def_id)); - - let body_id = match body_id { - Some(body) => body, - None => { - debug!("check_unused_unsafe({:?}) - no body found", def_id); - return; - } + used_unsafe_blocks: &FxHashMap, +) -> Vec<(HirId, UnusedUnsafe)> { + let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); + let body_id = tcx.hir().maybe_body_owned_by(hir_id); + + let Some(body_id) = body_id else { + debug!("check_unused_unsafe({:?}) - no body found", def_id); + return vec![]; }; let body = tcx.hir().body(body_id); - debug!("check_unused_unsafe({:?}, body={:?}, used_unsafe={:?})", def_id, body, used_unsafe); - let mut visitor = UnusedUnsafeVisitor { used_unsafe, unsafe_blocks }; + let context = match tcx.hir().fn_sig_by_hir_id(hir_id) { + Some(sig) if sig.header.unsafety == hir::Unsafety::Unsafe => Context::UnsafeFn(hir_id), + _ => Context::Safe, + }; + + debug!( + "check_unused_unsafe({:?}, context={:?}, body={:?}, used_unsafe_blocks={:?})", + def_id, body, context, used_unsafe_blocks + ); + + let mut unused_unsafes = vec![]; + + let mut visitor = UnusedUnsafeVisitor { + tcx, + used_unsafe_blocks, + context, + unused_unsafes: &mut unused_unsafes, + }; intravisit::Visitor::visit_body(&mut visitor, body); + + unused_unsafes } fn unsafety_check_result<'tcx>( @@ -439,56 +514,52 @@ fn unsafety_check_result<'tcx>( let mut checker = UnsafetyChecker::new(body, def.did, tcx, param_env); checker.visit_body(&body); - check_unused_unsafe(tcx, def.did, &checker.used_unsafe, &mut checker.inherited_blocks); + let unused_unsafes = (!tcx.is_closure(def.did.to_def_id())) + .then(|| check_unused_unsafe(tcx, def.did, &checker.used_unsafe_blocks)); tcx.arena.alloc(UnsafetyCheckResult { - violations: checker.violations.into(), - unsafe_blocks: checker.inherited_blocks.into(), + violations: checker.violations, + used_unsafe_blocks: checker.used_unsafe_blocks, + unused_unsafes, }) } -/// Returns the `HirId` for an enclosing scope that is also `unsafe`. -fn is_enclosed( - tcx: TyCtxt<'_>, - used_unsafe: &FxHashSet, - id: hir::HirId, - unsafe_op_in_unsafe_fn_allowed: bool, -) -> Option<(&'static str, hir::HirId)> { - let parent_id = tcx.hir().get_parent_node(id); - if parent_id != id { - if used_unsafe.contains(&parent_id) { - Some(("block", parent_id)) - } else if let Some(Node::Item(&hir::Item { - kind: hir::ItemKind::Fn(ref sig, _, _), .. - })) = tcx.hir().find(parent_id) - { - if sig.header.unsafety == hir::Unsafety::Unsafe && unsafe_op_in_unsafe_fn_allowed { - Some(("fn", parent_id)) - } else { - None - } - } else { - is_enclosed(tcx, used_unsafe, parent_id, unsafe_op_in_unsafe_fn_allowed) - } - } else { - None - } -} - -fn report_unused_unsafe(tcx: TyCtxt<'_>, used_unsafe: &FxHashSet, id: hir::HirId) { +fn report_unused_unsafe(tcx: TyCtxt<'_>, kind: UnusedUnsafe, id: HirId) { let span = tcx.sess.source_map().guess_head_span(tcx.hir().span(id)); tcx.struct_span_lint_hir(UNUSED_UNSAFE, id, span, |lint| { let msg = "unnecessary `unsafe` block"; let mut db = lint.build(msg); db.span_label(span, msg); - if let Some((kind, id)) = - is_enclosed(tcx, used_unsafe, id, unsafe_op_in_unsafe_fn_allowed(tcx, id)) - { - db.span_label( - tcx.sess.source_map().guess_head_span(tcx.hir().span(id)), - format!("because it's nested under this `unsafe` {}", kind), - ); + match kind { + UnusedUnsafe::Unused => {} + UnusedUnsafe::InUnsafeBlock(id) => { + db.span_label( + tcx.sess.source_map().guess_head_span(tcx.hir().span(id)), + format!("because it's nested under this `unsafe` block"), + ); + } + UnusedUnsafe::InUnsafeFn(id, usage_lint_root) => { + db.span_label( + tcx.sess.source_map().guess_head_span(tcx.hir().span(id)), + format!("because it's nested under this `unsafe` fn"), + ) + .note( + "this `unsafe` block does contain unsafe operations, \ + but those are already allowed in an `unsafe fn`", + ); + let (level, source) = + tcx.lint_level_at_node(UNSAFE_OP_IN_UNSAFE_FN, usage_lint_root); + assert_eq!(level, Level::Allow); + lint::explain_lint_level_source( + tcx.sess, + UNSAFE_OP_IN_UNSAFE_FN, + Level::Allow, + source, + &mut db, + ); + } } + db.emit(); }); } @@ -501,7 +572,7 @@ pub fn check_unsafety(tcx: TyCtxt<'_>, def_id: LocalDefId) { return; } - let UnsafetyCheckResult { violations, unsafe_blocks } = tcx.unsafety_check_result(def_id); + let UnsafetyCheckResult { violations, unused_unsafes, .. } = tcx.unsafety_check_result(def_id); for &UnsafetyViolation { source_info, lint_root, kind, details } in violations.iter() { let (description, note) = details.description_and_note(); @@ -542,20 +613,8 @@ pub fn check_unsafety(tcx: TyCtxt<'_>, def_id: LocalDefId) { } } - let (mut unsafe_used, mut unsafe_unused): (FxHashSet<_>, Vec<_>) = Default::default(); - for &(block_id, is_used) in unsafe_blocks.iter() { - if is_used { - unsafe_used.insert(block_id); - } else { - unsafe_unused.push(block_id); - } - } - // The unused unsafe blocks might not be in source order; sort them so that the unused unsafe - // error messages are properly aligned and the issue-45107 and lint-unused-unsafe tests pass. - unsafe_unused.sort_by_cached_key(|hir_id| tcx.hir().span(*hir_id)); - - for &block_id in &unsafe_unused { - report_unused_unsafe(tcx, &unsafe_used, block_id); + for &(block_id, kind) in unused_unsafes.as_ref().unwrap() { + report_unused_unsafe(tcx, kind, block_id); } } diff --git a/compiler/rustc_mir_transform/src/const_prop.rs b/compiler/rustc_mir_transform/src/const_prop.rs index 5810ce6edc964..6075f572a651c 100644 --- a/compiler/rustc_mir_transform/src/const_prop.rs +++ b/compiler/rustc_mir_transform/src/const_prop.rs @@ -843,12 +843,10 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { // FIXME: enable the general case stated above ^. let ty = value.layout.ty; // Only do it for tuples - if let ty::Tuple(substs) = ty.kind() { + if let ty::Tuple(types) = ty.kind() { // Only do it if tuple is also a pair with two scalars - if substs.len() == 2 { + if let [ty1, ty2] = types[..] { let alloc = self.use_ecx(|this| { - let ty1 = substs[0].expect_ty(); - let ty2 = substs[1].expect_ty(); let ty_is_scalar = |ty| { this.ecx.layout_of(ty).ok().map(|layout| layout.abi.is_scalar()) == Some(true) diff --git a/compiler/rustc_mir_transform/src/deaggregator.rs b/compiler/rustc_mir_transform/src/deaggregator.rs index a5491f0ef4e2d..44753c5f631ca 100644 --- a/compiler/rustc_mir_transform/src/deaggregator.rs +++ b/compiler/rustc_mir_transform/src/deaggregator.rs @@ -26,11 +26,8 @@ impl<'tcx> MirPass<'tcx> for Deaggregator { let stmt = stmt.replace_nop(); let source_info = stmt.source_info; - let (lhs, kind, operands) = match stmt.kind { - StatementKind::Assign(box (lhs, Rvalue::Aggregate(kind, operands))) => { - (lhs, kind, operands) - } - _ => bug!(), + let StatementKind::Assign(box (lhs, Rvalue::Aggregate(kind, operands))) = stmt.kind else { + bug!(); }; Some(expand_aggregate( diff --git a/compiler/rustc_mir_transform/src/elaborate_drops.rs b/compiler/rustc_mir_transform/src/elaborate_drops.rs index 7320b2738a76c..a4b1d86ff610e 100644 --- a/compiler/rustc_mir_transform/src/elaborate_drops.rs +++ b/compiler/rustc_mir_transform/src/elaborate_drops.rs @@ -98,12 +98,9 @@ fn find_dead_unwinds<'tcx>( debug!("find_dead_unwinds @ {:?}: {:?}", bb, bb_data); - let path = match env.move_data.rev_lookup.find(place.as_ref()) { - LookupResult::Exact(e) => e, - LookupResult::Parent(..) => { - debug!("find_dead_unwinds: has parent; skipping"); - continue; - } + let LookupResult::Exact(path) = env.move_data.rev_lookup.find(place.as_ref()) else { + debug!("find_dead_unwinds: has parent; skipping"); + continue; }; flow_inits.seek_before_primary_effect(body.terminator_loc(bb)); diff --git a/compiler/rustc_mir_transform/src/generator.rs b/compiler/rustc_mir_transform/src/generator.rs index 05de52458add2..388bb7d34364a 100644 --- a/compiler/rustc_mir_transform/src/generator.rs +++ b/compiler/rustc_mir_transform/src/generator.rs @@ -1413,22 +1413,16 @@ impl EnsureGeneratorFieldAssignmentsNeverAlias<'_> { impl<'tcx> Visitor<'tcx> for EnsureGeneratorFieldAssignmentsNeverAlias<'_> { fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, location: Location) { - let lhs = match self.assigned_local { - Some(l) => l, - None => { - // This visitor only invokes `visit_place` for the right-hand side of an assignment - // and only after setting `self.assigned_local`. However, the default impl of - // `Visitor::super_body` may call `visit_place` with a `NonUseContext` for places - // with debuginfo. Ignore them here. - assert!(!context.is_use()); - return; - } + let Some(lhs) = self.assigned_local else { + // This visitor only invokes `visit_place` for the right-hand side of an assignment + // and only after setting `self.assigned_local`. However, the default impl of + // `Visitor::super_body` may call `visit_place` with a `NonUseContext` for places + // with debuginfo. Ignore them here. + assert!(!context.is_use()); + return; }; - let rhs = match self.saved_local_for_direct_place(*place) { - Some(l) => l, - None => return, - }; + let Some(rhs) = self.saved_local_for_direct_place(*place) else { return }; if !self.storage_conflicts.contains(lhs, rhs) { bug!( diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index 55ce5910c818b..6078abcbb8f3b 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -118,9 +118,8 @@ impl<'tcx> Inliner<'tcx> { continue; } - let callsite = match self.resolve_callsite(caller_body, bb, bb_data) { - None => continue, - Some(it) => it, + let Some(callsite) = self.resolve_callsite(caller_body, bb, bb_data) else { + continue; }; let span = trace_span!("process_blocks", %callsite.callee, ?bb); @@ -693,8 +692,7 @@ impl<'tcx> Inliner<'tcx> { // The `tmp0`, `tmp1`, and `tmp2` in our example abonve. let tuple_tmp_args = tuple_tys.iter().enumerate().map(|(i, ty)| { // This is e.g., `tuple_tmp.0` in our example above. - let tuple_field = - Operand::Move(tcx.mk_place_field(tuple, Field::new(i), ty.expect_ty())); + let tuple_field = Operand::Move(tcx.mk_place_field(tuple, Field::new(i), ty)); // Spill to a local to make e.g., `tmp0`. self.create_temp_if_necessary(tuple_field, callsite, caller_body) diff --git a/compiler/rustc_mir_transform/src/inline/cycle.rs b/compiler/rustc_mir_transform/src/inline/cycle.rs index 44ded1647fc28..de93ab7059f87 100644 --- a/compiler/rustc_mir_transform/src/inline/cycle.rs +++ b/compiler/rustc_mir_transform/src/inline/cycle.rs @@ -46,12 +46,9 @@ crate fn mir_callgraph_reachable<'tcx>( trace!(%caller); for &(callee, substs) in tcx.mir_inliner_callees(caller.def) { let substs = caller.subst_mir_and_normalize_erasing_regions(tcx, param_env, substs); - let callee = match ty::Instance::resolve(tcx, param_env, callee, substs).unwrap() { - Some(callee) => callee, - None => { - trace!(?callee, "cannot resolve, skipping"); - continue; - } + let Some(callee) = ty::Instance::resolve(tcx, param_env, callee, substs).unwrap() else { + trace!(?callee, "cannot resolve, skipping"); + continue; }; // Found a path. diff --git a/compiler/rustc_mir_transform/src/lower_intrinsics.rs b/compiler/rustc_mir_transform/src/lower_intrinsics.rs index 4c4497ad629da..684d988ee9ed2 100644 --- a/compiler/rustc_mir_transform/src/lower_intrinsics.rs +++ b/compiler/rustc_mir_transform/src/lower_intrinsics.rs @@ -17,9 +17,8 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics { let terminator = block.terminator.as_mut().unwrap(); if let TerminatorKind::Call { func, args, destination, .. } = &mut terminator.kind { let func_ty = func.ty(local_decls, tcx); - let (intrinsic_name, substs) = match resolve_rust_intrinsic(tcx, func_ty) { - None => continue, - Some(it) => it, + let Some((intrinsic_name, substs)) = resolve_rust_intrinsic(tcx, func_ty) else { + continue; }; match intrinsic_name { sym::unreachable => { diff --git a/compiler/rustc_mir_transform/src/lower_slice_len.rs b/compiler/rustc_mir_transform/src/lower_slice_len.rs index c829774487308..43d1d62a21efb 100644 --- a/compiler/rustc_mir_transform/src/lower_slice_len.rs +++ b/compiler/rustc_mir_transform/src/lower_slice_len.rs @@ -61,10 +61,7 @@ fn lower_slice_len_call<'tcx>( if args.len() != 1 { return; } - let arg = match args[0].place() { - Some(arg) => arg, - None => return, - }; + let Some(arg) = args[0].place() else { return }; let func_ty = func.ty(local_decls, tcx); match func_ty.kind() { ty::FnDef(fn_def_id, _) if fn_def_id == &slice_len_fn_item_def_id => { diff --git a/compiler/rustc_mir_transform/src/nrvo.rs b/compiler/rustc_mir_transform/src/nrvo.rs index 797f7ee2685b8..ec25f298d48e0 100644 --- a/compiler/rustc_mir_transform/src/nrvo.rs +++ b/compiler/rustc_mir_transform/src/nrvo.rs @@ -39,12 +39,9 @@ impl<'tcx> MirPass<'tcx> for RenameReturnPlace { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut mir::Body<'tcx>) { let def_id = body.source.def_id(); - let returned_local = match local_eligible_for_nrvo(body) { - Some(l) => l, - None => { - debug!("`{:?}` was ineligible for NRVO", def_id); - return; - } + let Some(returned_local) = local_eligible_for_nrvo(body) else { + debug!("`{:?}` was ineligible for NRVO", def_id); + return; }; if !tcx.consider_optimizing(|| format!("RenameReturnPlace {:?}", def_id)) { diff --git a/compiler/rustc_mir_transform/src/remove_uninit_drops.rs b/compiler/rustc_mir_transform/src/remove_uninit_drops.rs index fc5ac97e3e1dc..6d082748939ac 100644 --- a/compiler/rustc_mir_transform/src/remove_uninit_drops.rs +++ b/compiler/rustc_mir_transform/src/remove_uninit_drops.rs @@ -148,8 +148,8 @@ fn is_needs_drop_and_init<'tcx>( }) } - ty::Tuple(_) => ty - .tuple_fields() + ty::Tuple(fields) => fields + .iter() .enumerate() .map(|(f, f_ty)| (Field::from_usize(f), f_ty, mpi)) .any(field_needs_drop_and_init), diff --git a/compiler/rustc_mir_transform/src/remove_zsts.rs b/compiler/rustc_mir_transform/src/remove_zsts.rs index 1d912e6140989..785716ebecc28 100644 --- a/compiler/rustc_mir_transform/src/remove_zsts.rs +++ b/compiler/rustc_mir_transform/src/remove_zsts.rs @@ -26,9 +26,8 @@ impl<'tcx> MirPass<'tcx> for RemoveZsts { if !maybe_zst(place_ty) { continue; } - let layout = match tcx.layout_of(param_env.and(place_ty)) { - Ok(layout) => layout, - Err(_) => continue, + let Ok(layout) = tcx.layout_of(param_env.and(place_ty)) else { + continue; }; if !layout.is_zst() { continue; diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs index b8feeb993e7c8..9533e869bc596 100644 --- a/compiler/rustc_mir_transform/src/shim.rs +++ b/compiler/rustc_mir_transform/src/shim.rs @@ -461,10 +461,10 @@ impl<'tcx> CloneShimBuilder<'tcx> { fn tuple_like_shim(&mut self, dest: Place<'tcx>, src: Place<'tcx>, tys: I) where - I: Iterator>, + I: IntoIterator>, { let mut previous_field = None; - for (i, ity) in tys.enumerate() { + for (i, ity) in tys.into_iter().enumerate() { let field = Field::new(i); let src_field = self.tcx.mk_place_field(src, field, ity); @@ -734,9 +734,8 @@ pub fn build_adt_ctor(tcx: TyCtxt<'_>, ctor_id: DefId) -> Body<'_> { let sig = tcx.fn_sig(ctor_id).no_bound_vars().expect("LBR in ADT constructor signature"); let sig = tcx.normalize_erasing_regions(param_env, sig); - let (adt_def, substs) = match sig.output().kind() { - ty::Adt(adt_def, substs) => (adt_def, substs), - _ => bug!("unexpected type for ADT ctor {:?}", sig.output()), + let ty::Adt(adt_def, substs) = sig.output().kind() else { + bug!("unexpected type for ADT ctor {:?}", sig.output()); }; debug!("build_ctor: ctor_id={:?} sig={:?}", ctor_id, sig); diff --git a/compiler/rustc_mir_transform/src/simplify.rs b/compiler/rustc_mir_transform/src/simplify.rs index 4651e1f4ed059..d8b58ce53f838 100644 --- a/compiler/rustc_mir_transform/src/simplify.rs +++ b/compiler/rustc_mir_transform/src/simplify.rs @@ -172,9 +172,8 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> { let mut terminators: SmallVec<[_; 1]> = Default::default(); let mut current = *start; while let Some(terminator) = self.take_terminator_if_simple_goto(current) { - let target = match terminator { - Terminator { kind: TerminatorKind::Goto { target }, .. } => target, - _ => unreachable!(), + let Terminator { kind: TerminatorKind::Goto { target }, .. } = terminator else { + unreachable!(); }; terminators.push((current, terminator)); current = target; @@ -182,9 +181,8 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> { let last = current; *start = last; while let Some((current, mut terminator)) = terminators.pop() { - let target = match terminator { - Terminator { kind: TerminatorKind::Goto { ref mut target }, .. } => target, - _ => unreachable!(), + let Terminator { kind: TerminatorKind::Goto { ref mut target }, .. } = terminator else { + unreachable!(); }; *changed |= *target != last; *target = last; diff --git a/compiler/rustc_mir_transform/src/uninhabited_enum_branching.rs b/compiler/rustc_mir_transform/src/uninhabited_enum_branching.rs index cda9ba9dcc87f..7133724d07d95 100644 --- a/compiler/rustc_mir_transform/src/uninhabited_enum_branching.rs +++ b/compiler/rustc_mir_transform/src/uninhabited_enum_branching.rs @@ -3,7 +3,8 @@ use crate::MirPass; use rustc_data_structures::stable_set::FxHashSet; use rustc_middle::mir::{ - BasicBlockData, Body, Local, Operand, Rvalue, StatementKind, SwitchTargets, TerminatorKind, + BasicBlockData, Body, Local, Operand, Rvalue, StatementKind, SwitchTargets, Terminator, + TerminatorKind, }; use rustc_middle::ty::layout::TyAndLayout; use rustc_middle::ty::{Ty, TyCtxt}; @@ -71,6 +72,28 @@ fn variant_discriminants<'tcx>( } } +/// Ensures that the `otherwise` branch leads to an unreachable bb, returning `None` if so and a new +/// bb to use as the new target if not. +fn ensure_otherwise_unreachable<'tcx>( + body: &Body<'tcx>, + targets: &SwitchTargets, +) -> Option> { + let otherwise = targets.otherwise(); + let bb = &body.basic_blocks()[otherwise]; + if bb.terminator().kind == TerminatorKind::Unreachable + && bb.statements.iter().all(|s| matches!(&s.kind, StatementKind::StorageDead(_))) + { + return None; + } + + let mut new_block = BasicBlockData::new(Some(Terminator { + source_info: bb.terminator().source_info, + kind: TerminatorKind::Unreachable, + })); + new_block.is_cleanup = bb.is_cleanup; + Some(new_block) +} + impl<'tcx> MirPass<'tcx> for UninhabitedEnumBranching { fn is_enabled(&self, sess: &rustc_session::Session) -> bool { sess.mir_opt_level() > 0 @@ -99,12 +122,25 @@ impl<'tcx> MirPass<'tcx> for UninhabitedEnumBranching { if let TerminatorKind::SwitchInt { targets, .. } = &mut body.basic_blocks_mut()[bb].terminator_mut().kind { - let new_targets = SwitchTargets::new( + let mut new_targets = SwitchTargets::new( targets.iter().filter(|(val, _)| allowed_variants.contains(val)), targets.otherwise(), ); - *targets = new_targets; + if new_targets.iter().count() == allowed_variants.len() { + if let Some(updated) = ensure_otherwise_unreachable(body, &new_targets) { + let new_otherwise = body.basic_blocks_mut().push(updated); + *new_targets.all_targets_mut().last_mut().unwrap() = new_otherwise; + } + } + + if let TerminatorKind::SwitchInt { targets, .. } = + &mut body.basic_blocks_mut()[bb].terminator_mut().kind + { + *targets = new_targets; + } else { + unreachable!() + } } else { unreachable!() } diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 72c1b3fa6e98c..a517e4879aafa 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -454,7 +454,7 @@ fn collect_items_rec<'tcx>( && starting_point.node.krate() != LOCAL_CRATE && starting_point.node.is_user_defined() { - let formatted_item = with_no_trimmed_paths(|| starting_point.node.to_string()); + let formatted_item = with_no_trimmed_paths!(starting_point.node.to_string()); tcx.sess.span_note_without_error( starting_point.span, &format!("the above error was encountered while instantiating `{}`", formatted_item), @@ -847,14 +847,13 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> { debug!(?source_info); let lint_root = source_info.scope.lint_root(&self.body.source_scopes); debug!(?lint_root); - let lint_root = match lint_root { - Some(lint_root) => lint_root, + let Some(lint_root) = lint_root else { // This happens when the issue is in a function from a foreign crate that // we monomorphized in the current crate. We can't get a `HirId` for things // in other crates. // FIXME: Find out where to report the lint on. Maybe simply crate-level lint root // but correct span? This would make the lint at least accept crate-level lint attributes. - None => return, + return; }; self.tcx.struct_span_lint_hir( LARGE_ASSIGNMENTS, @@ -1256,9 +1255,8 @@ impl<'v> RootCollector<'_, 'v> { /// the return type of `main`. This is not needed when /// the user writes their own `start` manually. fn push_extra_entry_roots(&mut self) { - let main_def_id = match self.entry_fn { - Some((def_id, EntryFnType::Main)) => def_id, - _ => return, + let Some((main_def_id, EntryFnType::Main)) = self.entry_fn else { + return; }; let start_def_id = match self.tcx.lang_items().require(LangItem::Start) { diff --git a/compiler/rustc_monomorphize/src/partitioning/mod.rs b/compiler/rustc_monomorphize/src/partitioning/mod.rs index b8684a09fd7ce..c1992137575bc 100644 --- a/compiler/rustc_monomorphize/src/partitioning/mod.rs +++ b/compiler/rustc_monomorphize/src/partitioning/mod.rs @@ -425,7 +425,7 @@ fn collect_and_partition_mono_items<'tcx>( let mut item_keys: Vec<_> = items .iter() .map(|i| { - let mut output = with_no_trimmed_paths(|| i.to_string()); + let mut output = with_no_trimmed_paths!(i.to_string()); output.push_str(" @@"); let mut empty = Vec::new(); let cgus = item_to_cgus.get_mut(i).unwrap_or(&mut empty); diff --git a/compiler/rustc_parse/src/lexer/unicode_chars.rs b/compiler/rustc_parse/src/lexer/unicode_chars.rs index ccd11f06bc582..c2a75d2bc2c64 100644 --- a/compiler/rustc_parse/src/lexer/unicode_chars.rs +++ b/compiler/rustc_parse/src/lexer/unicode_chars.rs @@ -338,20 +338,16 @@ pub(super) fn check_for_substitution<'a>( ch: char, err: &mut DiagnosticBuilder<'a>, ) -> Option { - let (u_name, ascii_char) = match UNICODE_ARRAY.iter().find(|&&(c, _, _)| c == ch) { - Some(&(_u_char, u_name, ascii_char)) => (u_name, ascii_char), - None => return None, + let Some(&(_u_char, u_name, ascii_char)) = UNICODE_ARRAY.iter().find(|&&(c, _, _)| c == ch) else { + return None; }; let span = Span::with_root_ctxt(pos, pos + Pos::from_usize(ch.len_utf8())); - let (ascii_name, token) = match ASCII_ARRAY.iter().find(|&&(c, _, _)| c == ascii_char) { - Some((_ascii_char, ascii_name, token)) => (ascii_name, token), - None => { - let msg = format!("substitution character not found for '{}'", ch); - reader.sess.span_diagnostic.span_bug_no_panic(span, &msg); - return None; - } + let Some((_ascii_char, ascii_name, token)) = ASCII_ARRAY.iter().find(|&&(c, _, _)| c == ascii_char) else { + let msg = format!("substitution character not found for '{}'", ch); + reader.sess.span_diagnostic.span_bug_no_panic(span, &msg); + return None; }; // special help suggestion for "directed" double quotes diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index e9aa4adcaf79b..7cb8c35b868a5 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -1667,9 +1667,8 @@ impl<'a> Parser<'a> { Err(LitError::NotLiteral) => None, Err(err) => { let span = token.span; - let lit = match token.kind { - token::Literal(lit) => lit, - _ => unreachable!(), + let token::Literal(lit) = token.kind else { + unreachable!(); }; self.bump(); self.report_lit_error(err, lit, span); diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 93f5d79c0db13..20ca8a99ab7e6 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -439,9 +439,8 @@ impl<'a> Parser<'a> { /// Recover if we parsed attributes and expected an item but there was none. fn recover_attrs_no_item(&mut self, attrs: &[Attribute]) -> PResult<'a, ()> { - let (start, end) = match attrs { - [] => return Ok(()), - [x0 @ xn] | [x0, .., xn] => (x0, xn), + let ([start @ end] | [start, .., end]) = attrs else { + return Ok(()); }; let msg = if end.is_doc_comment() { "expected item after doc comment" diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index d3e7d1690ccf6..965e6a6ca3f27 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -103,6 +103,16 @@ impl<'a> Parser<'a> { } else { self.parse_expr_res(Restrictions::STMT_EXPR, Some(attrs)) }?; + if matches!(e.kind, ExprKind::Assign(..)) && self.eat_keyword(kw::Else) { + let bl = self.parse_block()?; + // Destructuring assignment ... else. + // This is not allowed, but point it out in a nice way. + let mut err = self.struct_span_err( + e.span.to(bl.span), + " ... else { ... } is not allowed", + ); + err.emit(); + } self.mk_stmt(lo.to(e.span), StmtKind::Expr(e)) } else { self.error_outer_attrs(&attrs.take_for_recovery()); @@ -524,9 +534,8 @@ impl<'a> Parser<'a> { // Skip looking for a trailing semicolon when we have an interpolated statement. maybe_whole!(self, NtStmt, |x| Some(x)); - let mut stmt = match self.parse_stmt_without_recovery(true, ForceCollect::No)? { - Some(stmt) => stmt, - None => return Ok(None), + let Some(mut stmt) = self.parse_stmt_without_recovery(true, ForceCollect::No)? else { + return Ok(None); }; let mut eat_semi = true; diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 479a08e43c01a..3d69e8ba4e430 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -1318,9 +1318,8 @@ impl CheckAttrVisitor<'_> { return false; } - let list = match attr.meta_item_list() { - None => return false, - Some(it) => it, + let Some(list) = attr.meta_item_list() else { + return false; }; if matches!(&list[..], &[NestedMetaItem::Literal(Lit { kind: LitKind::Int(..), .. })]) { @@ -1352,18 +1351,16 @@ impl CheckAttrVisitor<'_> { return false; } - let list = match attr.meta_item_list() { + let Some(list) = attr.meta_item_list() else { // The attribute form is validated on AST. - None => return false, - Some(it) => it, + return false; }; - let (decl, generics) = match item { - Some(ItemLike::Item(Item { - kind: ItemKind::Fn(FnSig { decl, .. }, generics, _), - .. - })) => (decl, generics), - _ => bug!("should be a function item"), + let Some(ItemLike::Item(Item { + kind: ItemKind::Fn(FnSig { decl, .. }, generics, _), + .. + })) = item else { + bug!("should be a function item"); }; for param in generics.params { diff --git a/compiler/rustc_passes/src/intrinsicck.rs b/compiler/rustc_passes/src/intrinsicck.rs index 1031ba01c1b48..bd772d9975b3a 100644 --- a/compiler/rustc_passes/src/intrinsicck.rs +++ b/compiler/rustc_passes/src/intrinsicck.rs @@ -35,10 +35,7 @@ struct ExprVisitor<'tcx> { /// If the type is `Option`, it will return `T`, otherwise /// the type itself. Works on most `Option`-like types. fn unpack_option_like<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { - let (def, substs) = match *ty.kind() { - ty::Adt(def, substs) => (def, substs), - _ => return ty, - }; + let ty::Adt(def, substs) = *ty.kind() else { return ty }; if def.variants.len() == 2 && !def.repr.c() && def.repr.int.is_none() { let data_idx; @@ -202,18 +199,15 @@ impl<'tcx> ExprVisitor<'tcx> { } _ => None, }; - let asm_ty = match asm_ty { - Some(asm_ty) => asm_ty, - None => { - let msg = &format!("cannot use value of type `{}` for inline assembly", ty); - let mut err = self.tcx.sess.struct_span_err(expr.span, msg); - err.note( - "only integers, floats, SIMD vectors, pointers and function pointers \ - can be used as arguments for inline assembly", - ); - err.emit(); - return None; - } + let Some(asm_ty) = asm_ty else { + let msg = &format!("cannot use value of type `{}` for inline assembly", ty); + let mut err = self.tcx.sess.struct_span_err(expr.span, msg); + err.note( + "only integers, floats, SIMD vectors, pointers and function pointers \ + can be used as arguments for inline assembly", + ); + err.emit(); + return None; }; // Check that the type implements Copy. The only case where this can @@ -260,27 +254,24 @@ impl<'tcx> ExprVisitor<'tcx> { let asm_arch = self.tcx.sess.asm_arch.unwrap(); let reg_class = reg.reg_class(); let supported_tys = reg_class.supported_types(asm_arch); - let feature = match supported_tys.iter().find(|&&(t, _)| t == asm_ty) { - Some((_, feature)) => feature, - None => { - let msg = &format!("type `{}` cannot be used with this register class", ty); - let mut err = self.tcx.sess.struct_span_err(expr.span, msg); - let supported_tys: Vec<_> = - supported_tys.iter().map(|(t, _)| t.to_string()).collect(); - err.note(&format!( - "register class `{}` supports these types: {}", - reg_class.name(), - supported_tys.join(", "), + let Some((_, feature)) = supported_tys.iter().find(|&&(t, _)| t == asm_ty) else { + let msg = &format!("type `{}` cannot be used with this register class", ty); + let mut err = self.tcx.sess.struct_span_err(expr.span, msg); + let supported_tys: Vec<_> = + supported_tys.iter().map(|(t, _)| t.to_string()).collect(); + err.note(&format!( + "register class `{}` supports these types: {}", + reg_class.name(), + supported_tys.join(", "), + )); + if let Some(suggest) = reg_class.suggest_class(asm_arch, asm_ty) { + err.help(&format!( + "consider using the `{}` register class instead", + suggest.name() )); - if let Some(suggest) = reg_class.suggest_class(asm_arch, asm_ty) { - err.help(&format!( - "consider using the `{}` register class instead", - suggest.name() - )); - } - err.emit(); - return Some(asm_ty); } + err.emit(); + return Some(asm_ty); }; // Check whether the selected type requires a target feature. Note that diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs index 69cd1b4fed589..a959089ebb318 100644 --- a/compiler/rustc_passes/src/liveness.rs +++ b/compiler/rustc_passes/src/liveness.rs @@ -1430,9 +1430,8 @@ impl<'tcx> Liveness<'_, 'tcx> { } fn warn_about_unused_upvars(&self, entry_ln: LiveNode) { - let closure_min_captures = match self.closure_min_captures { - None => return, - Some(closure_min_captures) => closure_min_captures, + let Some(closure_min_captures) = self.closure_min_captures else { + return; }; // If closure_min_captures is Some(), upvars must be Some() too. diff --git a/compiler/rustc_passes/src/reachable.rs b/compiler/rustc_passes/src/reachable.rs index 6cd9dc23285a9..adbfb4fcf01ca 100644 --- a/compiler/rustc_passes/src/reachable.rs +++ b/compiler/rustc_passes/src/reachable.rs @@ -354,9 +354,8 @@ impl<'a, 'tcx> ItemLikeVisitor<'tcx> for CollectPrivateImplItemsVisitor<'a, 'tcx let tcx = self.tcx; self.worklist.extend(items.iter().map(|ii_ref| ii_ref.id.def_id)); - let trait_def_id = match trait_ref.path.res { - Res::Def(DefKind::Trait, def_id) => def_id, - _ => unreachable!(), + let Res::Def(DefKind::Trait, trait_def_id) = trait_ref.path.res else { + unreachable!(); }; if !trait_def_id.is_local() { diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs index 136059677c5ae..a55198e6a9fb5 100644 --- a/compiler/rustc_passes/src/stability.rs +++ b/compiler/rustc_passes/src/stability.rs @@ -756,9 +756,8 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> { return; } - let cnum = match self.tcx.extern_mod_stmt_cnum(item.def_id) { - Some(cnum) => cnum, - None => return, + let Some(cnum) = self.tcx.extern_mod_stmt_cnum(item.def_id) else { + return; }; let def_id = DefId { krate: cnum, index: CRATE_DEF_INDEX }; self.tcx.check_stability(def_id, Some(item.hir_id()), item.span, None); @@ -808,10 +807,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> { // so semi-randomly perform it here in stability.rs hir::ItemKind::Union(..) if !self.tcx.features().untagged_unions => { let ty = self.tcx.type_of(item.def_id); - let (adt_def, substs) = match ty.kind() { - ty::Adt(adt_def, substs) => (adt_def, substs), - _ => bug!(), - }; + let ty::Adt(adt_def, substs) = ty.kind() else { bug!() }; // Non-`Copy` fields are unstable, except for `ManuallyDrop`. let param_env = self.tcx.param_env(item.def_id); diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs index 55e95e1a592d3..832540a85e74b 100644 --- a/compiler/rustc_query_impl/src/lib.rs +++ b/compiler/rustc_query_impl/src/lib.rs @@ -44,8 +44,6 @@ pub use on_disk_cache::OnDiskCache; mod profiling_support; pub use self::profiling_support::alloc_self_profile_query_strings; -mod util; - fn describe_as_module(def_id: LocalDefId, tcx: TyCtxt<'_>) -> String { if def_id.is_top_level_module() { "top-level module".to_string() diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index ff9d32a677652..073ddf01afb0e 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -272,11 +272,12 @@ macro_rules! define_queries { let name = stringify!($name); // Disable visible paths printing for performance reasons. // Showing visible path instead of any path is not that important in production. - let description = ty::print::with_no_visible_paths( - || ty::print::with_forced_impl_filename_line( + let description = ty::print::with_no_visible_paths!( // Force filename-line mode to avoid invoking `type_of` query. - || queries::$name::describe(tcx, key) - )); + ty::print::with_forced_impl_filename_line!( + queries::$name::describe(tcx, key) + ) + ); let description = if tcx.sess.verbose() { format!("{} [{}]", description, name) } else { @@ -289,13 +290,11 @@ macro_rules! define_queries { } else { Some(key.default_span(*tcx)) }; - let def_id = key.key_as_def_id(); - let def_kind = def_id + // Use `tcx.hir().opt_def_kind()` to reduce the chance of + // accidentally triggering an infinite query loop. + let def_kind = key.key_as_def_id() .and_then(|def_id| def_id.as_local()) - // Use `tcx.hir().opt_def_kind()` to reduce the chance of - // accidentally triggering an infinite query loop. - .and_then(|def_id| tcx.hir().opt_def_kind(def_id)) - .map(|def_kind| $crate::util::def_kind_to_simple_def_kind(def_kind)); + .and_then(|def_id| tcx.hir().opt_def_kind(def_id)); let hash = || { let mut hcx = tcx.create_stable_hashing_context(); let mut hasher = StableHasher::new(); diff --git a/compiler/rustc_query_impl/src/util.rs b/compiler/rustc_query_impl/src/util.rs deleted file mode 100644 index 517c107b5d9af..0000000000000 --- a/compiler/rustc_query_impl/src/util.rs +++ /dev/null @@ -1,18 +0,0 @@ -use rustc_hir::def::DefKind; -use rustc_query_system::query::SimpleDefKind; - -/// Convert a [`DefKind`] to a [`SimpleDefKind`]. -/// -/// *See [`SimpleDefKind`]'s docs for more information.* -pub(crate) fn def_kind_to_simple_def_kind(def_kind: DefKind) -> SimpleDefKind { - match def_kind { - DefKind::Struct => SimpleDefKind::Struct, - DefKind::Enum => SimpleDefKind::Enum, - DefKind::Union => SimpleDefKind::Union, - DefKind::Trait => SimpleDefKind::Trait, - DefKind::TyAlias => SimpleDefKind::TyAlias, - DefKind::TraitAlias => SimpleDefKind::TraitAlias, - - _ => SimpleDefKind::Other, - } -} diff --git a/compiler/rustc_query_system/src/dep_graph/serialized.rs b/compiler/rustc_query_system/src/dep_graph/serialized.rs index c95dff13d6615..9778f77384cf9 100644 --- a/compiler/rustc_query_system/src/dep_graph/serialized.rs +++ b/compiler/rustc_query_system/src/dep_graph/serialized.rs @@ -122,29 +122,24 @@ impl<'a, K: DepKind + Decodable>> Decodable = d.read_struct_field("node", Decodable::decode); - let _i: SerializedDepNodeIndex = nodes.push(dep_node); - debug_assert_eq!(_i.index(), _index); - - let fingerprint: Fingerprint = - d.read_struct_field("fingerprint", Decodable::decode); - let _i: SerializedDepNodeIndex = fingerprints.push(fingerprint); - debug_assert_eq!(_i.index(), _index); - - d.read_struct_field("edges", |d| { - d.read_seq(|d, len| { - let start = edge_list_data.len().try_into().unwrap(); - for _ in 0..len { - let edge = d.read_seq_elt(Decodable::decode); - edge_list_data.push(edge); - } - let end = edge_list_data.len().try_into().unwrap(); - let _i: SerializedDepNodeIndex = edge_list_indices.push((start, end)); - debug_assert_eq!(_i.index(), _index); - }) - }) - }); + let dep_node: DepNode = Decodable::decode(d); + let _i: SerializedDepNodeIndex = nodes.push(dep_node); + debug_assert_eq!(_i.index(), _index); + + let fingerprint: Fingerprint = Decodable::decode(d); + let _i: SerializedDepNodeIndex = fingerprints.push(fingerprint); + debug_assert_eq!(_i.index(), _index); + + // Deserialize edges -- sequence of DepNodeIndex + let len = d.read_usize(); + let start = edge_list_data.len().try_into().unwrap(); + for _ in 0..len { + let edge = Decodable::decode(d); + edge_list_data.push(edge); + } + let end = edge_list_data.len().try_into().unwrap(); + let _i: SerializedDepNodeIndex = edge_list_indices.push((start, end)); + debug_assert_eq!(_i.index(), _index); } let index: FxHashMap<_, _> = diff --git a/compiler/rustc_query_system/src/query/job.rs b/compiler/rustc_query_system/src/query/job.rs index adf878a7f04c1..4588403925efd 100644 --- a/compiler/rustc_query_system/src/query/job.rs +++ b/compiler/rustc_query_system/src/query/job.rs @@ -1,6 +1,7 @@ use crate::dep_graph::DepContext; use crate::query::plumbing::CycleError; -use crate::query::{QueryContext, QueryStackFrame, SimpleDefKind}; +use crate::query::{QueryContext, QueryStackFrame}; +use rustc_hir::def::DefKind; use rustc_data_structures::fx::FxHashMap; use rustc_errors::{struct_span_err, Diagnostic, DiagnosticBuilder, Handler, Level}; @@ -556,15 +557,13 @@ pub(crate) fn report_cycle<'a>( } if stack.iter().all(|entry| { - entry.query.def_kind.map_or(false, |def_kind| { - matches!(def_kind, SimpleDefKind::TyAlias | SimpleDefKind::TraitAlias) - }) + entry + .query + .def_kind + .map_or(false, |def_kind| matches!(def_kind, DefKind::TyAlias | DefKind::TraitAlias)) }) { if stack.iter().all(|entry| { - entry - .query - .def_kind - .map_or(false, |def_kind| matches!(def_kind, SimpleDefKind::TyAlias)) + entry.query.def_kind.map_or(false, |def_kind| matches!(def_kind, DefKind::TyAlias)) }) { err.note("type aliases cannot be recursive"); err.help("consider using a struct, enum, or union instead to break the cycle"); diff --git a/compiler/rustc_query_system/src/query/mod.rs b/compiler/rustc_query_system/src/query/mod.rs index 361ae3c43527d..de64ebb620301 100644 --- a/compiler/rustc_query_system/src/query/mod.rs +++ b/compiler/rustc_query_system/src/query/mod.rs @@ -19,6 +19,7 @@ use crate::dep_graph::{DepNodeIndex, HasDepContext, SerializedDepNodeIndex}; use rustc_data_structures::sync::Lock; use rustc_data_structures::thin_vec::ThinVec; use rustc_errors::Diagnostic; +use rustc_hir::def::DefKind; use rustc_span::Span; /// Description of a frame in the query stack. @@ -29,46 +30,20 @@ pub struct QueryStackFrame { pub name: &'static str, pub description: String, span: Option, - /// The `DefKind` this query frame is associated with, if applicable. - /// - /// We can't use `rustc_hir::def::DefKind` because `rustc_hir` is not - /// available in `rustc_query_system`. Instead, we have a simplified - /// custom version of it, called [`SimpleDefKind`]. - def_kind: Option, + def_kind: Option, /// This hash is used to deterministically pick /// a query to remove cycles in the parallel compiler. #[cfg(parallel_compiler)] hash: u64, } -/// A simplified version of `rustc_hir::def::DefKind`. -/// -/// It was added to help improve cycle errors caused by recursive type aliases. -/// As of August 2021, `rustc_query_system` cannot depend on `rustc_hir` -/// because it would create a dependency cycle. So, instead, a simplified -/// version of `DefKind` was added to `rustc_query_system`. -/// -/// `DefKind`s are converted to `SimpleDefKind`s in `rustc_query_impl`. -#[derive(Debug, Copy, Clone)] -pub enum SimpleDefKind { - Struct, - Enum, - Union, - Trait, - TyAlias, - TraitAlias, - - // FIXME: add more from `rustc_hir::def::DefKind` and then remove `Other` - Other, -} - impl QueryStackFrame { #[inline] pub fn new( name: &'static str, description: String, span: Option, - def_kind: Option, + def_kind: Option, _hash: impl FnOnce() -> u64, ) -> Self { Self { diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index a8c2a5e1424b8..5e21161f2e06a 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -351,13 +351,11 @@ impl<'a> Resolver<'a> { if !self.is_accessible_from(single_import.vis.get(), parent_scope.module) { continue; } - let module = match single_import.imported_module.get() { - Some(x) => x, - None => return Err((Undetermined, Weak::No)), + let Some(module) = single_import.imported_module.get() else { + return Err((Undetermined, Weak::No)); }; - let ident = match single_import.kind { - ImportKind::Single { source, .. } => source, - _ => unreachable!(), + let ImportKind::Single { source: ident, .. } = single_import.kind else { + unreachable!(); }; match self.resolve_ident_in_module( module, @@ -1347,12 +1345,9 @@ impl<'a, 'b> ImportResolver<'a, 'b> { } fn resolve_glob_import(&mut self, import: &'b Import<'b>) { - let module = match import.imported_module.get().unwrap() { - ModuleOrUniformRoot::Module(module) => module, - _ => { - self.r.session.span_err(import.span, "cannot glob-import all possible crates"); - return; - } + let ModuleOrUniformRoot::Module(module) = import.imported_module.get().unwrap() else { + self.r.session.span_err(import.span, "cannot glob-import all possible crates"); + return; }; if module.is_trait() { diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 129db038f4a5b..f20cf29cc89d1 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -1582,12 +1582,9 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { def_id: DefId, span: Span, ) { - let variants = match self.collect_enum_ctors(def_id) { - Some(variants) => variants, - None => { - err.note("you might have meant to use one of the enum's variants"); - return; - } + let Some(variants) = self.collect_enum_ctors(def_id) else { + err.note("you might have meant to use one of the enum's variants"); + return; }; let suggest_only_tuple_variants = diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs index 3bea95fa1d554..2f0ad60709dac 100644 --- a/compiler/rustc_resolve/src/late/lifetimes.rs +++ b/compiler/rustc_resolve/src/late/lifetimes.rs @@ -1748,10 +1748,7 @@ fn object_lifetime_defaults_for_item<'tcx>( let param_def_id = tcx.hir().local_def_id(param.hir_id); for predicate in generics.where_clause.predicates { // Look for `type: ...` where clauses. - let data = match *predicate { - hir::WherePredicate::BoundPredicate(ref data) => data, - _ => continue, - }; + let hir::WherePredicate::BoundPredicate(ref data) = *predicate else { continue }; // Ignore `for<'a> type: ...` as they can change what // lifetimes mean (although we could "just" handle it). @@ -1976,12 +1973,9 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { } fn check_uses_for_lifetimes_defined_by_scope(&mut self) { - let defined_by = match self.scope { - Scope::Binder { lifetimes, .. } => lifetimes, - _ => { - debug!("check_uses_for_lifetimes_defined_by_scope: not in a binder scope"); - return; - } + let Scope::Binder { lifetimes: defined_by, .. } = self.scope else { + debug!("check_uses_for_lifetimes_defined_by_scope: not in a binder scope"); + return; }; let def_ids: Vec<_> = defined_by @@ -2636,9 +2630,8 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { smallvec![(def_id, smallvec![])]; let mut visited: FxHashSet = FxHashSet::default(); loop { - let (def_id, bound_vars) = match stack.pop() { - Some(next) => next, - None => break None, + let Some((def_id, bound_vars)) = stack.pop() else { + break None; }; // See issue #83753. If someone writes an associated type on a non-trait, just treat it as // there being no supertrait HRTBs. @@ -2723,10 +2716,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { } }); - let output = match output { - Some(ty) => ty, - None => return, - }; + let Some(output) = output else { return }; debug!("determine output"); diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 28d8d9247ac13..04b0a18b12b62 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -3479,16 +3479,15 @@ impl<'a> Resolver<'a> { let ident = Ident::with_dummy_span(sym::main); let parent_scope = &ParentScope::module(module, self); - let name_binding = match self.resolve_ident_in_module( + let Ok(name_binding) = self.resolve_ident_in_module( ModuleOrUniformRoot::Module(module), ident, ValueNS, parent_scope, false, DUMMY_SP, - ) { - Ok(name_binding) => name_binding, - _ => return, + ) else { + return; }; let res = name_binding.res(); diff --git a/compiler/rustc_save_analysis/src/dump_visitor.rs b/compiler/rustc_save_analysis/src/dump_visitor.rs index 0ff56a30ea005..51f73ac2eb199 100644 --- a/compiler/rustc_save_analysis/src/dump_visitor.rs +++ b/compiler/rustc_save_analysis/src/dump_visitor.rs @@ -522,9 +522,8 @@ impl<'tcx> DumpVisitor<'tcx> { ty_params: &'tcx hir::Generics<'tcx>, ) { let enum_data = self.save_ctxt.get_item_data(item); - let enum_data = match enum_data { - None => return, - Some(data) => data, + let Some(enum_data) = enum_data else { + return; }; down_cast_data!(enum_data, DefData, item.span); diff --git a/compiler/rustc_save_analysis/src/lib.rs b/compiler/rustc_save_analysis/src/lib.rs index 8b0adba9fab15..43ec35a843419 100644 --- a/compiler/rustc_save_analysis/src/lib.rs +++ b/compiler/rustc_save_analysis/src/lib.rs @@ -115,12 +115,9 @@ impl<'tcx> SaveContext<'tcx> { let mut result = Vec::with_capacity(self.tcx.crates(()).len()); for &n in self.tcx.crates(()).iter() { - let span = match self.tcx.extern_crate(n.as_def_id()) { - Some(&ExternCrate { span, .. }) => span, - None => { - debug!("skipping crate {}, no data", n); - continue; - } + let Some(&ExternCrate { span, .. }) = self.tcx.extern_crate(n.as_def_id()) else { + debug!("skipping crate {}, no data", n); + continue; }; let lo_loc = self.span_utils.sess.source_map().lookup_char_pos(span.lo()); result.push(ExternalCrateData { @@ -566,12 +563,9 @@ impl<'tcx> SaveContext<'tcx> { } }, hir::ExprKind::MethodCall(ref seg, ..) => { - let method_id = match self.typeck_results().type_dependent_def_id(expr.hir_id) { - Some(id) => id, - None => { - debug!("could not resolve method id for {:?}", expr); - return None; - } + let Some(method_id) = self.typeck_results().type_dependent_def_id(expr.hir_id) else { + debug!("could not resolve method id for {:?}", expr); + return None; }; let (def_id, decl_id) = match self.tcx.associated_item(method_id).container { ty::ImplContainer(_) => (Some(method_id), None), @@ -982,7 +976,7 @@ pub fn process_crate<'l, 'tcx, H: SaveHandler>( config: Option, mut handler: H, ) { - with_no_trimmed_paths(|| { + with_no_trimmed_paths!({ tcx.dep_graph.with_ignore(|| { info!("Dumping crate {}", cratename); diff --git a/compiler/rustc_serialize/src/collection_impls.rs b/compiler/rustc_serialize/src/collection_impls.rs index 02b28f7c62677..dee6dc010feef 100644 --- a/compiler/rustc_serialize/src/collection_impls.rs +++ b/compiler/rustc_serialize/src/collection_impls.rs @@ -18,7 +18,8 @@ impl>> Encodable for SmallVec { impl>> Decodable for SmallVec { fn decode(d: &mut D) -> SmallVec { - d.read_seq(|d, len| (0..len).map(|_| d.read_seq_elt(|d| Decodable::decode(d))).collect()) + let len = d.read_usize(); + (0..len).map(|_| Decodable::decode(d)).collect() } } @@ -35,7 +36,8 @@ impl> Encodable for LinkedList { impl> Decodable for LinkedList { fn decode(d: &mut D) -> LinkedList { - d.read_seq(|d, len| (0..len).map(|_| d.read_seq_elt(|d| Decodable::decode(d))).collect()) + let len = d.read_usize(); + (0..len).map(|_| Decodable::decode(d)).collect() } } @@ -52,7 +54,8 @@ impl> Encodable for VecDeque { impl> Decodable for VecDeque { fn decode(d: &mut D) -> VecDeque { - d.read_seq(|d, len| (0..len).map(|_| d.read_seq_elt(|d| Decodable::decode(d))).collect()) + let len = d.read_usize(); + (0..len).map(|_| Decodable::decode(d)).collect() } } @@ -78,15 +81,14 @@ where V: Decodable, { fn decode(d: &mut D) -> BTreeMap { - d.read_map(|d, len| { - let mut map = BTreeMap::new(); - for _ in 0..len { - let key = d.read_map_elt_key(|d| Decodable::decode(d)); - let val = d.read_map_elt_val(|d| Decodable::decode(d)); - map.insert(key, val); - } - map - }) + let len = d.read_usize(); + let mut map = BTreeMap::new(); + for _ in 0..len { + let key = Decodable::decode(d); + let val = Decodable::decode(d); + map.insert(key, val); + } + map } } @@ -109,13 +111,12 @@ where T: Decodable + PartialEq + Ord, { fn decode(d: &mut D) -> BTreeSet { - d.read_seq(|d, len| { - let mut set = BTreeSet::new(); - for _ in 0..len { - set.insert(d.read_seq_elt(|d| Decodable::decode(d))); - } - set - }) + let len = d.read_usize(); + let mut set = BTreeSet::new(); + for _ in 0..len { + set.insert(Decodable::decode(d)); + } + set } } @@ -143,16 +144,15 @@ where S: BuildHasher + Default, { fn decode(d: &mut D) -> HashMap { - d.read_map(|d, len| { - let state = Default::default(); - let mut map = HashMap::with_capacity_and_hasher(len, state); - for _ in 0..len { - let key = d.read_map_elt_key(|d| Decodable::decode(d)); - let val = d.read_map_elt_val(|d| Decodable::decode(d)); - map.insert(key, val); - } - map - }) + let len = d.read_usize(); + let state = Default::default(); + let mut map = HashMap::with_capacity_and_hasher(len, state); + for _ in 0..len { + let key = Decodable::decode(d); + let val = Decodable::decode(d); + map.insert(key, val); + } + map } } @@ -187,14 +187,13 @@ where S: BuildHasher + Default, { fn decode(d: &mut D) -> HashSet { - d.read_seq(|d, len| { - let state = Default::default(); - let mut set = HashSet::with_capacity_and_hasher(len, state); - for _ in 0..len { - set.insert(d.read_seq_elt(|d| Decodable::decode(d))); - } - set - }) + let len = d.read_usize(); + let state = Default::default(); + let mut set = HashSet::with_capacity_and_hasher(len, state); + for _ in 0..len { + set.insert(Decodable::decode(d)); + } + set } } @@ -222,16 +221,15 @@ where S: BuildHasher + Default, { fn decode(d: &mut D) -> indexmap::IndexMap { - d.read_map(|d, len| { - let state = Default::default(); - let mut map = indexmap::IndexMap::with_capacity_and_hasher(len, state); - for _ in 0..len { - let key = d.read_map_elt_key(|d| Decodable::decode(d)); - let val = d.read_map_elt_val(|d| Decodable::decode(d)); - map.insert(key, val); - } - map - }) + let len = d.read_usize(); + let state = Default::default(); + let mut map = indexmap::IndexMap::with_capacity_and_hasher(len, state); + for _ in 0..len { + let key = Decodable::decode(d); + let val = Decodable::decode(d); + map.insert(key, val); + } + map } } @@ -256,14 +254,13 @@ where S: BuildHasher + Default, { fn decode(d: &mut D) -> indexmap::IndexSet { - d.read_seq(|d, len| { - let state = Default::default(); - let mut set = indexmap::IndexSet::with_capacity_and_hasher(len, state); - for _ in 0..len { - set.insert(d.read_seq_elt(|d| Decodable::decode(d))); - } - set - }) + let len = d.read_usize(); + let state = Default::default(); + let mut set = indexmap::IndexSet::with_capacity_and_hasher(len, state); + for _ in 0..len { + set.insert(Decodable::decode(d)); + } + set } } diff --git a/compiler/rustc_serialize/src/json.rs b/compiler/rustc_serialize/src/json.rs index 6a39854924122..0cbea3a07a8d4 100644 --- a/compiler/rustc_serialize/src/json.rs +++ b/compiler/rustc_serialize/src/json.rs @@ -45,12 +45,9 @@ //! //! # Rust Type-based Encoding and Decoding //! -//! Rust provides a mechanism for low boilerplate encoding & decoding of values to and from JSON via -//! the serialization API. -//! To be able to encode a piece of data, it must implement the `serialize::Encodable` trait. -//! To be able to decode a piece of data, it must implement the `serialize::Decodable` trait. -//! The Rust compiler provides an annotation to automatically generate the code for these traits: -//! `#[derive(Decodable, Encodable)]` +//! To be able to encode a piece of data, it must implement the +//! `serialize::Encodable` trait. The `rustc_macros` crate provides an +//! annotation to automatically generate the code for this trait: `#[derive(Encodable)]`. //! //! The JSON API provides an enum `json::Json` and a trait `ToJson` to encode objects. //! The `ToJson` trait provides a `to_json` method to convert an object into a `json::Json` value. @@ -68,11 +65,11 @@ //! //! ```rust //! # #![feature(rustc_private)] -//! use rustc_macros::{Decodable, Encodable}; +//! use rustc_macros::{Encodable}; //! use rustc_serialize::json; //! -//! // Automatically generate `Decodable` and `Encodable` trait implementations -//! #[derive(Decodable, Encodable)] +//! // Automatically generate `Encodable` trait implementations +//! #[derive(Encodable)] //! pub struct TestStruct { //! data_int: u8, //! data_str: String, @@ -87,9 +84,6 @@ //! //! // Serialize using `json::encode` //! let encoded = json::encode(&object).unwrap(); -//! -//! // Deserialize using `json::decode` -//! let decoded: TestStruct = json::decode(&encoded[..]); //! ``` //! //! ## Using the `ToJson` trait @@ -139,12 +133,9 @@ //! //! ```rust //! # #![feature(rustc_private)] -//! use rustc_macros::Decodable; //! use std::collections::BTreeMap; -//! use rustc_serialize::json::{self, Json, ToJson}; +//! use rustc_serialize::json::{Json, ToJson}; //! -//! // Only generate `Decodable` trait implementation -//! #[derive(Decodable)] //! pub struct TestStruct { //! data_int: u8, //! data_str: String, @@ -171,19 +162,14 @@ //! }; //! let json_obj: Json = input_data.to_json(); //! let json_str: String = json_obj.to_string(); -//! -//! // Deserialize like before -//! let decoded: TestStruct = json::decode(&json_str); //! ``` -use self::DecoderError::*; use self::ErrorCode::*; use self::InternalStackElement::*; use self::JsonEvent::*; use self::ParserError::*; use self::ParserState::*; -use std::borrow::Cow; use std::collections::{BTreeMap, HashMap}; use std::mem::swap; use std::num::FpCategory as Fp; @@ -253,21 +239,6 @@ pub enum ParserError { // Builder and Parser have the same errors. pub type BuilderError = ParserError; -#[derive(Clone, PartialEq, Debug)] -pub enum DecoderError { - ParseError(ParserError), - ExpectedError(string::String, string::String), - MissingFieldError(string::String), - UnknownVariantError(string::String), - ApplicationError(string::String), -} - -macro_rules! bad { - ($e:expr) => {{ - panic!("json decode error: {:?}", $e); - }}; -} - #[derive(Copy, Clone, Debug)] pub enum EncoderError { FmtError(fmt::Error), @@ -297,17 +268,6 @@ pub fn error_str(error: ErrorCode) -> &'static str { } } -/// Shortcut function to decode a JSON `&str` into an object -pub fn decode>(s: &str) -> T { - let json = match from_str(s) { - Ok(x) => x, - Err(e) => bad!(ParseError(e)), - }; - - let mut decoder = Decoder::new(json); - crate::Decodable::decode(&mut decoder) -} - /// Shortcut function to encode a `T` into a JSON `String` pub fn encode crate::Encodable>>( object: &T, @@ -352,7 +312,6 @@ impl From for EncoderError { } pub type EncodeResult = Result<(), EncoderError>; -pub type DecodeResult = Result; fn escape_str(wr: &mut dyn fmt::Write, v: &str) -> EncodeResult { wr.write_str("\"")?; @@ -2162,273 +2121,6 @@ pub fn from_str(s: &str) -> Result { builder.build() } -/// A structure to decode JSON to values in rust. -pub struct Decoder { - stack: Vec, -} - -impl Decoder { - /// Creates a new decoder instance for decoding the specified JSON value. - pub fn new(json: Json) -> Decoder { - Decoder { stack: vec![json] } - } - - fn pop(&mut self) -> Json { - self.stack.pop().unwrap() - } -} - -macro_rules! expect { - ($e:expr, Null) => {{ - match $e { - Json::Null => (), - other => bad!(ExpectedError("Null".to_owned(), other.to_string())), - } - }}; - ($e:expr, $t:ident) => {{ - match $e { - Json::$t(v) => v, - other => bad!(ExpectedError(stringify!($t).to_owned(), other.to_string())), - } - }}; -} - -macro_rules! read_primitive { - ($name:ident, $ty:ty) => { - fn $name(&mut self) -> $ty { - match self.pop() { - Json::I64(f) => f as $ty, - Json::U64(f) => f as $ty, - Json::F64(f) => bad!(ExpectedError("Integer".to_owned(), f.to_string())), - // re: #12967.. a type w/ numeric keys (ie HashMap etc) - // is going to have a string here, as per JSON spec. - Json::String(s) => match s.parse().ok() { - Some(f) => f, - None => bad!(ExpectedError("Number".to_owned(), s)), - }, - value => bad!(ExpectedError("Number".to_owned(), value.to_string())), - } - } - }; -} - -impl crate::Decoder for Decoder { - fn read_unit(&mut self) -> () { - expect!(self.pop(), Null) - } - - read_primitive! { read_usize, usize } - read_primitive! { read_u8, u8 } - read_primitive! { read_u16, u16 } - read_primitive! { read_u32, u32 } - read_primitive! { read_u64, u64 } - read_primitive! { read_u128, u128 } - read_primitive! { read_isize, isize } - read_primitive! { read_i8, i8 } - read_primitive! { read_i16, i16 } - read_primitive! { read_i32, i32 } - read_primitive! { read_i64, i64 } - read_primitive! { read_i128, i128 } - - fn read_f32(&mut self) -> f32 { - self.read_f64() as f32 - } - - fn read_f64(&mut self) -> f64 { - match self.pop() { - Json::I64(f) => f as f64, - Json::U64(f) => f as f64, - Json::F64(f) => f, - Json::String(s) => { - // re: #12967.. a type w/ numeric keys (ie HashMap etc) - // is going to have a string here, as per JSON spec. - match s.parse().ok() { - Some(f) => f, - None => bad!(ExpectedError("Number".to_owned(), s)), - } - } - Json::Null => f64::NAN, - value => bad!(ExpectedError("Number".to_owned(), value.to_string())), - } - } - - fn read_bool(&mut self) -> bool { - expect!(self.pop(), Boolean) - } - - fn read_char(&mut self) -> char { - let s = self.read_str(); - let mut it = s.chars(); - if let (Some(c), None) = (it.next(), it.next()) { - // exactly one character - return c; - } - bad!(ExpectedError("single character string".to_owned(), s.to_string())); - } - - fn read_str(&mut self) -> Cow<'_, str> { - Cow::Owned(expect!(self.pop(), String)) - } - - fn read_raw_bytes_into(&mut self, s: &mut [u8]) { - for c in s.iter_mut() { - *c = self.read_u8(); - } - } - - fn read_enum(&mut self, f: F) -> T - where - F: FnOnce(&mut Decoder) -> T, - { - f(self) - } - - fn read_enum_variant(&mut self, names: &[&str], mut f: F) -> T - where - F: FnMut(&mut Decoder, usize) -> T, - { - let name = match self.pop() { - Json::String(s) => s, - Json::Object(mut o) => { - let n = match o.remove("variant") { - Some(Json::String(s)) => s, - Some(val) => bad!(ExpectedError("String".to_owned(), val.to_string())), - None => bad!(MissingFieldError("variant".to_owned())), - }; - match o.remove("fields") { - Some(Json::Array(l)) => { - self.stack.extend(l.into_iter().rev()); - } - Some(val) => bad!(ExpectedError("Array".to_owned(), val.to_string())), - None => bad!(MissingFieldError("fields".to_owned())), - } - n - } - json => bad!(ExpectedError("String or Object".to_owned(), json.to_string())), - }; - let idx = match names.iter().position(|n| *n == &name[..]) { - Some(idx) => idx, - None => bad!(UnknownVariantError(name)), - }; - f(self, idx) - } - - fn read_enum_variant_arg(&mut self, f: F) -> T - where - F: FnOnce(&mut Decoder) -> T, - { - f(self) - } - - fn read_struct(&mut self, f: F) -> T - where - F: FnOnce(&mut Decoder) -> T, - { - let value = f(self); - self.pop(); - value - } - - fn read_struct_field(&mut self, name: &str, f: F) -> T - where - F: FnOnce(&mut Decoder) -> T, - { - let mut obj = expect!(self.pop(), Object); - - let value = match obj.remove(name) { - None => { - // Add a Null and try to parse it as an Option<_> - // to get None as a default value. - self.stack.push(Json::Null); - f(self) - } - Some(json) => { - self.stack.push(json); - f(self) - } - }; - self.stack.push(Json::Object(obj)); - value - } - - fn read_tuple(&mut self, tuple_len: usize, f: F) -> T - where - F: FnOnce(&mut Decoder) -> T, - { - self.read_seq(move |d, len| { - if len == tuple_len { - f(d) - } else { - bad!(ExpectedError(format!("Tuple{}", tuple_len), format!("Tuple{}", len))); - } - }) - } - - fn read_tuple_arg(&mut self, f: F) -> T - where - F: FnOnce(&mut Decoder) -> T, - { - self.read_seq_elt(f) - } - - fn read_option(&mut self, mut f: F) -> T - where - F: FnMut(&mut Decoder, bool) -> T, - { - match self.pop() { - Json::Null => f(self, false), - value => { - self.stack.push(value); - f(self, true) - } - } - } - - fn read_seq(&mut self, f: F) -> T - where - F: FnOnce(&mut Decoder, usize) -> T, - { - let array = expect!(self.pop(), Array); - let len = array.len(); - self.stack.extend(array.into_iter().rev()); - f(self, len) - } - - fn read_seq_elt(&mut self, f: F) -> T - where - F: FnOnce(&mut Decoder) -> T, - { - f(self) - } - - fn read_map(&mut self, f: F) -> T - where - F: FnOnce(&mut Decoder, usize) -> T, - { - let obj = expect!(self.pop(), Object); - let len = obj.len(); - for (key, value) in obj { - self.stack.push(value); - self.stack.push(Json::String(key)); - } - f(self, len) - } - - fn read_map_elt_key(&mut self, f: F) -> T - where - F: FnOnce(&mut Decoder) -> T, - { - f(self) - } - - fn read_map_elt_val(&mut self, f: F) -> T - where - F: FnOnce(&mut Decoder) -> T, - { - f(self) - } -} - /// A trait for converting values to JSON pub trait ToJson { /// Converts the value of `self` to an instance of JSON diff --git a/compiler/rustc_serialize/src/lib.rs b/compiler/rustc_serialize/src/lib.rs index b31fbab20ac92..bd257dc64646a 100644 --- a/compiler/rustc_serialize/src/lib.rs +++ b/compiler/rustc_serialize/src/lib.rs @@ -15,6 +15,7 @@ Core encoding and decoding interfaces. #![feature(min_specialization)] #![feature(core_intrinsics)] #![feature(maybe_uninit_slice)] +#![feature(let_else)] #![feature(new_uninit)] #![cfg_attr(test, feature(test))] #![allow(rustc::internal)] diff --git a/compiler/rustc_serialize/src/serialize.rs b/compiler/rustc_serialize/src/serialize.rs index a6172403fd63d..a012be2857e1e 100644 --- a/compiler/rustc_serialize/src/serialize.rs +++ b/compiler/rustc_serialize/src/serialize.rs @@ -200,118 +200,6 @@ pub trait Decoder { fn read_char(&mut self) -> char; fn read_str(&mut self) -> Cow<'_, str>; fn read_raw_bytes_into(&mut self, s: &mut [u8]); - - // Compound types: - #[inline] - fn read_enum(&mut self, f: F) -> T - where - F: FnOnce(&mut Self) -> T, - { - f(self) - } - - #[inline] - fn read_enum_variant(&mut self, _names: &[&str], mut f: F) -> T - where - F: FnMut(&mut Self, usize) -> T, - { - let disr = self.read_usize(); - f(self, disr) - } - - #[inline] - fn read_enum_variant_arg(&mut self, f: F) -> T - where - F: FnOnce(&mut Self) -> T, - { - f(self) - } - - #[inline] - fn read_struct(&mut self, f: F) -> T - where - F: FnOnce(&mut Self) -> T, - { - f(self) - } - - #[inline] - fn read_struct_field(&mut self, _f_name: &str, f: F) -> T - where - F: FnOnce(&mut Self) -> T, - { - f(self) - } - - #[inline] - fn read_tuple(&mut self, _len: usize, f: F) -> T - where - F: FnOnce(&mut Self) -> T, - { - f(self) - } - - #[inline] - fn read_tuple_arg(&mut self, f: F) -> T - where - F: FnOnce(&mut Self) -> T, - { - f(self) - } - - // Specialized types: - fn read_option(&mut self, mut f: F) -> T - where - F: FnMut(&mut Self, bool) -> T, - { - self.read_enum(move |this| { - this.read_enum_variant(&["None", "Some"], move |this, idx| match idx { - 0 => f(this, false), - 1 => f(this, true), - _ => panic!("read_option: expected 0 for None or 1 for Some"), - }) - }) - } - - fn read_seq(&mut self, f: F) -> T - where - F: FnOnce(&mut Self, usize) -> T, - { - let len = self.read_usize(); - f(self, len) - } - - #[inline] - fn read_seq_elt(&mut self, f: F) -> T - where - F: FnOnce(&mut Self) -> T, - { - f(self) - } - - fn read_map(&mut self, f: F) -> T - where - F: FnOnce(&mut Self, usize) -> T, - { - let len = self.read_usize(); - f(self, len) - } - - #[inline] - fn read_map_elt_key(&mut self, f: F) -> T - where - F: FnOnce(&mut Self) -> T, - { - f(self) - } - - #[inline] - fn read_map_elt_val(&mut self, f: F) -> T - where - F: FnOnce(&mut Self) -> T, - { - f(self) - } } /// Trait for types that can be serialized @@ -493,22 +381,18 @@ impl> Encodable for Vec { impl> Decodable for Vec { default fn decode(d: &mut D) -> Vec { - d.read_seq(|d, len| { - // SAFETY: we set the capacity in advance, only write elements, and - // only set the length at the end once the writing has succeeded. - let mut vec = Vec::with_capacity(len); - unsafe { - let ptr: *mut T = vec.as_mut_ptr(); - for i in 0..len { - std::ptr::write( - ptr.offset(i as isize), - d.read_seq_elt(|d| Decodable::decode(d)), - ); - } - vec.set_len(len); + let len = d.read_usize(); + // SAFETY: we set the capacity in advance, only write elements, and + // only set the length at the end once the writing has succeeded. + let mut vec = Vec::with_capacity(len); + unsafe { + let ptr: *mut T = vec.as_mut_ptr(); + for i in 0..len { + std::ptr::write(ptr.offset(i as isize), Decodable::decode(d)); } - vec - }) + vec.set_len(len); + } + vec } } @@ -521,14 +405,13 @@ impl, const N: usize> Encodable for [T; N] { impl Decodable for [u8; N] { fn decode(d: &mut D) -> [u8; N] { - d.read_seq(|d, len| { - assert!(len == N); - let mut v = [0u8; N]; - for i in 0..len { - v[i] = d.read_seq_elt(|d| Decodable::decode(d)); - } - v - }) + let len = d.read_usize(); + assert!(len == N); + let mut v = [0u8; N]; + for i in 0..len { + v[i] = Decodable::decode(d); + } + v } } @@ -563,7 +446,11 @@ impl> Encodable for Option { impl> Decodable for Option { fn decode(d: &mut D) -> Option { - d.read_option(|d, b| if b { Some(Decodable::decode(d)) } else { None }) + match d.read_usize() { + 0 => None, + 1 => Some(Decodable::decode(d)), + _ => panic!("Encountered invalid discriminant while decoding `Option`."), + } } } @@ -582,13 +469,11 @@ impl, T2: Encodable> Encodable for Result, T2: Decodable> Decodable for Result { fn decode(d: &mut D) -> Result { - d.read_enum(|d| { - d.read_enum_variant(&["Ok", "Err"], |d, disr| match disr { - 0 => Ok(d.read_enum_variant_arg(|d| T1::decode(d))), - 1 => Err(d.read_enum_variant_arg(|d| T2::decode(d))), - _ => panic!("Encountered invalid discriminant while decoding `Result`."), - }) - }) + match d.read_usize() { + 0 => Ok(T1::decode(d)), + 1 => Err(T2::decode(d)), + _ => panic!("Encountered invalid discriminant while decoding `Result`."), + } } } @@ -613,24 +498,16 @@ macro_rules! tuple { () => (); ( $($name:ident,)+ ) => ( impl),+> Decodable for ($($name,)+) { - #[allow(non_snake_case)] fn decode(d: &mut D) -> ($($name,)+) { - let len: usize = count!($($name)+); - d.read_tuple(len, |d| { - let ret = ($(d.read_tuple_arg(|d| -> $name { - Decodable::decode(d) - }),)+); - ret - }) + ($({ let element: $name = Decodable::decode(d); element },)+) } } impl),+> Encodable for ($($name,)+) { #[allow(non_snake_case)] fn encode(&self, s: &mut S) -> Result<(), S::Error> { let ($(ref $name,)+) = *self; - let mut n = 0; - $(let $name = $name; n += 1;)+ - s.emit_tuple(n, |s| { + let len: usize = count!($($name)+); + s.emit_tuple(len, |s| { let mut i = 0; $(s.emit_tuple_arg({ i+=1; i-1 }, |s| $name.encode(s))?;)+ Ok(()) diff --git a/compiler/rustc_serialize/tests/json.rs b/compiler/rustc_serialize/tests/json.rs index ede912bdfb6ee..944fe46063219 100644 --- a/compiler/rustc_serialize/tests/json.rs +++ b/compiler/rustc_serialize/tests/json.rs @@ -4,61 +4,35 @@ use json::ErrorCode::*; use json::Json::*; use json::JsonEvent::*; use json::ParserError::*; -use json::{from_str, Decoder, Encoder, EncoderError, Json, JsonEvent, Parser, StackElement}; -use rustc_macros::{Decodable, Encodable}; +use json::{from_str, Encoder, EncoderError, Json, JsonEvent, Parser, StackElement}; +use rustc_macros::Encodable; use rustc_serialize::json; -use rustc_serialize::{Decodable, Encodable}; +use rustc_serialize::Encodable; use std::collections::BTreeMap; use std::io::prelude::*; use std::string; use Animal::*; -#[derive(Decodable, Eq, PartialEq, Debug)] +#[derive(Eq, PartialEq, Debug)] struct OptionData { opt: Option, } -#[test] -fn test_decode_option_none() { - let s = "{}"; - let obj: OptionData = json::decode(s); - assert_eq!(obj, OptionData { opt: None }); -} - -#[test] -fn test_decode_option_some() { - let s = "{ \"opt\": 10 }"; - let obj: OptionData = json::decode(s); - assert_eq!(obj, OptionData { opt: Some(10) }); -} - -#[test] -#[should_panic(expected = r#"ExpectedError("Number", "[]")"#)] -fn test_decode_option_malformed1() { - check_err::(r#"{ "opt": [] }"#); -} - -#[test] -#[should_panic(expected = r#"ExpectedError("Number", "false")"#)] -fn test_decode_option_malformed2() { - check_err::(r#"{ "opt": false }"#); -} - -#[derive(PartialEq, Encodable, Decodable, Debug)] +#[derive(PartialEq, Encodable, Debug)] enum Animal { Dog, Frog(string::String, isize), } -#[derive(PartialEq, Encodable, Decodable, Debug)] +#[derive(PartialEq, Encodable, Debug)] struct Inner { a: (), b: usize, c: Vec, } -#[derive(PartialEq, Encodable, Decodable, Debug)] +#[derive(PartialEq, Encodable, Debug)] struct Outer { inner: Vec, } @@ -323,18 +297,6 @@ fn test_read_identifiers() { assert_eq!(from_str(" false "), Ok(Boolean(false))); } -#[test] -fn test_decode_identifiers() { - let v: () = json::decode("null"); - assert_eq!(v, ()); - - let v: bool = json::decode("true"); - assert_eq!(v, true); - - let v: bool = json::decode("false"); - assert_eq!(v, false); -} - #[test] fn test_read_number() { assert_eq!(from_str("+"), Err(SyntaxError(InvalidSyntax, 1, 1))); @@ -363,45 +325,6 @@ fn test_read_number() { assert_eq!(from_str("18446744073709551615"), Ok(U64(u64::MAX))); } -#[test] -#[should_panic(expected = r#"ExpectedError("Integer", "765.25")"#)] -fn test_decode_numbers() { - let v: f64 = json::decode("3"); - assert_eq!(v, 3.0); - - let v: f64 = json::decode("3.1"); - assert_eq!(v, 3.1); - - let v: f64 = json::decode("-1.2"); - assert_eq!(v, -1.2); - - let v: f64 = json::decode("0.4"); - assert_eq!(v, 0.4); - - let v: f64 = json::decode("0.4e5"); - assert_eq!(v, 0.4e5); - - let v: f64 = json::decode("0.4e15"); - assert_eq!(v, 0.4e15); - - let v: f64 = json::decode("0.4e-01"); - assert_eq!(v, 0.4e-01); - - let v: u64 = json::decode("0"); - assert_eq!(v, 0); - - let v: u64 = json::decode("18446744073709551615"); - assert_eq!(v, u64::MAX); - - let v: i64 = json::decode("-9223372036854775808"); - assert_eq!(v, i64::MIN); - - let v: i64 = json::decode("9223372036854775807"); - assert_eq!(v, i64::MAX); - - json::decode::("765.25"); -} - #[test] fn test_read_str() { assert_eq!(from_str("\""), Err(SyntaxError(EOFWhileParsingString, 1, 2))); @@ -419,26 +342,6 @@ fn test_read_str() { assert_eq!(from_str("\"\\uAB12\""), Ok(String("\u{AB12}".to_string()))); } -#[test] -fn test_decode_str() { - let s = [ - ("\"\"", ""), - ("\"foo\"", "foo"), - ("\"\\\"\"", "\""), - ("\"\\b\"", "\x08"), - ("\"\\n\"", "\n"), - ("\"\\r\"", "\r"), - ("\"\\t\"", "\t"), - ("\"\\u12ab\"", "\u{12ab}"), - ("\"\\uAB12\"", "\u{AB12}"), - ]; - - for (i, o) in s { - let v: string::String = json::decode(i); - assert_eq!(v, o); - } -} - #[test] fn test_read_array() { assert_eq!(from_str("["), Err(SyntaxError(EOFWhileParsingValue, 1, 2))); @@ -457,45 +360,6 @@ fn test_read_array() { assert_eq!(from_str("[2, [4, 1]]"), Ok(Array(vec![U64(2), Array(vec![U64(4), U64(1)])]))); } -#[test] -fn test_decode_array() { - let v: Vec<()> = json::decode("[]"); - assert_eq!(v, []); - - let v: Vec<()> = json::decode("[null]"); - assert_eq!(v, [()]); - - let v: Vec = json::decode("[true]"); - assert_eq!(v, [true]); - - let v: Vec = json::decode("[3, 1]"); - assert_eq!(v, [3, 1]); - - let v: Vec> = json::decode("[[3], [1, 2]]"); - assert_eq!(v, [vec![3], vec![1, 2]]); -} - -#[test] -fn test_decode_tuple() { - let t: (usize, usize, usize) = json::decode("[1, 2, 3]"); - assert_eq!(t, (1, 2, 3)); - - let t: (usize, string::String) = json::decode("[1, \"two\"]"); - assert_eq!(t, (1, "two".to_string())); -} - -#[test] -#[should_panic] -fn test_decode_tuple_malformed_types() { - json::decode::<(usize, string::String)>("[1, 2]"); -} - -#[test] -#[should_panic] -fn test_decode_tuple_malformed_length() { - json::decode::<(usize, usize)>("[1, 2, 3]"); -} - #[test] fn test_read_object() { assert_eq!(from_str("{"), Err(SyntaxError(EOFWhileParsingObject, 1, 2))); @@ -552,143 +416,11 @@ fn test_read_object() { ); } -#[test] -fn test_decode_struct() { - let s = "{ - \"inner\": [ - { \"a\": null, \"b\": 2, \"c\": [\"abc\", \"xyz\"] } - ] - }"; - - let v: Outer = json::decode(s); - assert_eq!( - v, - Outer { inner: vec![Inner { a: (), b: 2, c: vec!["abc".to_string(), "xyz".to_string()] }] } - ); -} - -#[derive(Decodable)] -struct FloatStruct { - f: f64, - a: Vec, -} -#[test] -fn test_decode_struct_with_nan() { - let s = "{\"f\":null,\"a\":[null,123]}"; - let obj: FloatStruct = json::decode(s); - assert!(obj.f.is_nan()); - assert!(obj.a[0].is_nan()); - assert_eq!(obj.a[1], 123f64); -} - -#[test] -fn test_decode_option() { - let value: Option = json::decode("null"); - assert_eq!(value, None); - - let value: Option = json::decode("\"jodhpurs\""); - assert_eq!(value, Some("jodhpurs".to_string())); -} - -#[test] -fn test_decode_enum() { - let value: Animal = json::decode("\"Dog\""); - assert_eq!(value, Dog); - - let s = "{\"variant\":\"Frog\",\"fields\":[\"Henry\",349]}"; - let value: Animal = json::decode(s); - assert_eq!(value, Frog("Henry".to_string(), 349)); -} - -#[test] -fn test_decode_map() { - let s = "{\"a\": \"Dog\", \"b\": {\"variant\":\"Frog\",\ - \"fields\":[\"Henry\", 349]}}"; - let mut map: BTreeMap = json::decode(s); - - assert_eq!(map.remove(&"a".to_string()), Some(Dog)); - assert_eq!(map.remove(&"b".to_string()), Some(Frog("Henry".to_string(), 349))); -} - #[test] fn test_multiline_errors() { assert_eq!(from_str("{\n \"foo\":\n \"bar\""), Err(SyntaxError(EOFWhileParsingObject, 3, 8))); } -#[derive(Decodable)] -#[allow(dead_code)] -struct DecodeStruct { - x: f64, - y: bool, - z: string::String, - w: Vec, -} -#[derive(Decodable)] -enum DecodeEnum { - A(f64), - B(string::String), -} -fn check_err>(to_parse: &str) { - let json = from_str(to_parse).unwrap(); - let _: T = Decodable::decode(&mut Decoder::new(json)); -} -#[test] -#[should_panic(expected = r#"ExpectedError("Object", "[]")"#)] -fn test_decode_errors_struct1() { - check_err::("[]"); -} -#[test] -#[should_panic(expected = r#"ExpectedError("Number", "true")"#)] -fn test_decode_errors_struct2() { - check_err::(r#"{"x": true, "y": true, "z": "", "w": []}"#); -} -#[test] -#[should_panic(expected = r#"ExpectedError("Boolean", "[]")"#)] -fn test_decode_errors_struct3() { - check_err::(r#"{"x": 1, "y": [], "z": "", "w": []}"#); -} -#[test] -#[should_panic(expected = r#"ExpectedError("String", "{}")"#)] -fn test_decode_errors_struct4() { - check_err::(r#"{"x": 1, "y": true, "z": {}, "w": []}"#); -} -#[test] -#[should_panic(expected = r#"ExpectedError("Array", "null")"#)] -fn test_decode_errors_struct5() { - check_err::(r#"{"x": 1, "y": true, "z": "", "w": null}"#); -} -#[test] -#[should_panic(expected = r#"ExpectedError("Array", "null")"#)] -fn test_decode_errors_struct6() { - check_err::(r#"{"x": 1, "y": true, "z": ""}"#); -} - -#[test] -#[should_panic(expected = r#"MissingFieldError("variant")"#)] -fn test_decode_errors_enum1() { - check_err::(r#"{}"#); -} -#[test] -#[should_panic(expected = r#"ExpectedError("String", "1")"#)] -fn test_decode_errors_enum2() { - check_err::(r#"{"variant": 1}"#); -} -#[test] -#[should_panic(expected = r#"MissingFieldError("fields")"#)] -fn test_decode_errors_enum3() { - check_err::(r#"{"variant": "A"}"#); -} -#[test] -#[should_panic(expected = r#"ExpectedError("Array", "null")"#)] -fn test_decode_errors_enum4() { - check_err::(r#"{"variant": "A", "fields": null}"#); -} -#[test] -#[should_panic(expected = r#"UnknownVariantError("C")"#)] -fn test_decode_errors_enum5() { - check_err::(r#"{"variant": "C", "fields": []}"#); -} - #[test] fn test_find() { let json_value = from_str("{\"dog\" : \"cat\"}").unwrap(); @@ -938,7 +670,7 @@ fn test_prettyencoder_indent_level_param() { #[test] fn test_hashmap_with_enum_key() { use std::collections::HashMap; - #[derive(Encodable, Eq, Hash, PartialEq, Decodable, Debug)] + #[derive(Encodable, Eq, Hash, PartialEq, Debug)] enum Enum { Foo, #[allow(dead_code)] @@ -948,33 +680,6 @@ fn test_hashmap_with_enum_key() { map.insert(Enum::Foo, 0); let result = json::encode(&map).unwrap(); assert_eq!(&result[..], r#"{"Foo":0}"#); - let decoded: HashMap = json::decode(&result); - assert_eq!(map, decoded); -} - -#[test] -fn test_hashmap_with_numeric_key_can_handle_double_quote_delimited_key() { - use std::collections::HashMap; - let json_str = "{\"1\":true}"; - let json_obj = match from_str(json_str) { - Err(_) => panic!("Unable to parse json_str: {:?}", json_str), - Ok(o) => o, - }; - let mut decoder = Decoder::new(json_obj); - let _hm: HashMap = Decodable::decode(&mut decoder); -} - -#[test] -#[should_panic(expected = r#"ExpectedError("Number", "a")"#)] -fn test_hashmap_with_numeric_key_will_error_with_string_keys() { - use std::collections::HashMap; - let json_str = "{\"a\":true}"; - let json_obj = match from_str(json_str) { - Err(_) => panic!("Unable to parse json_str: {:?}", json_str), - Ok(o) => o, - }; - let mut decoder = Decoder::new(json_obj); - let _: HashMap = Decodable::decode(&mut decoder); } fn assert_stream_equal(src: &str, expected: Vec<(JsonEvent, Vec>)>) { diff --git a/compiler/rustc_session/src/lib.rs b/compiler/rustc_session/src/lib.rs index 383250cd68f17..82a95faa3470a 100644 --- a/compiler/rustc_session/src/lib.rs +++ b/compiler/rustc_session/src/lib.rs @@ -1,5 +1,6 @@ #![feature(crate_visibility_modifier)] #![feature(derive_default_enum)] +#![feature(let_else)] #![feature(min_specialization)] #![feature(once_cell)] #![recursion_limit = "256"] diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 0a4bd23937dec..9a92258f80985 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -763,12 +763,9 @@ mod parse { } } - let v = match v { - None => { - *slot = Some(MirSpanview::Statement); - return true; - } - Some(v) => v, + let Some(v) = v else { + *slot = Some(MirSpanview::Statement); + return true; }; *slot = Some(match v.trim_end_matches('s') { @@ -792,12 +789,9 @@ mod parse { } } - let v = match v { - None => { - *slot = Some(InstrumentCoverage::All); - return true; - } - Some(v) => v, + let Some(v) = v else { + *slot = Some(InstrumentCoverage::All); + return true; }; *slot = Some(match v { diff --git a/compiler/rustc_span/src/def_id.rs b/compiler/rustc_span/src/def_id.rs index 147c1f9e04339..56da7c4372804 100644 --- a/compiler/rustc_span/src/def_id.rs +++ b/compiler/rustc_span/src/def_id.rs @@ -299,10 +299,7 @@ impl Encodable for DefId { impl Decodable for DefId { default fn decode(d: &mut D) -> DefId { - d.read_struct(|d| DefId { - krate: d.read_struct_field("krate", Decodable::decode), - index: d.read_struct_field("index", Decodable::decode), - }) + DefId { krate: Decodable::decode(d), index: Decodable::decode(d) } } } diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index dea2fbf04be59..e51030eedf82f 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -17,6 +17,7 @@ #![feature(array_windows)] #![feature(bool_to_option)] #![feature(crate_visibility_modifier)] +#![feature(let_else)] #![feature(if_let_guard)] #![feature(negative_impls)] #![feature(nll)] @@ -978,12 +979,10 @@ impl Encodable for Span { } impl Decodable for Span { default fn decode(s: &mut D) -> Span { - s.read_struct(|d| { - let lo = d.read_struct_field("lo", Decodable::decode); - let hi = d.read_struct_field("hi", Decodable::decode); + let lo = Decodable::decode(s); + let hi = Decodable::decode(s); - Span::new(lo, hi, SyntaxContext::root(), None) - }) + Span::new(lo, hi, SyntaxContext::root(), None) } } @@ -1439,65 +1438,59 @@ impl Encodable for SourceFile { impl Decodable for SourceFile { fn decode(d: &mut D) -> SourceFile { - d.read_struct(|d| { - let name: FileName = d.read_struct_field("name", |d| Decodable::decode(d)); - let src_hash: SourceFileHash = - d.read_struct_field("src_hash", |d| Decodable::decode(d)); - let start_pos: BytePos = d.read_struct_field("start_pos", |d| Decodable::decode(d)); - let end_pos: BytePos = d.read_struct_field("end_pos", |d| Decodable::decode(d)); - let lines: Vec = d.read_struct_field("lines", |d| { - let num_lines: u32 = Decodable::decode(d); - let mut lines = Vec::with_capacity(num_lines as usize); - - if num_lines > 0 { - // Read the number of bytes used per diff. - let bytes_per_diff: u8 = Decodable::decode(d); - - // Read the first element. - let mut line_start: BytePos = Decodable::decode(d); - lines.push(line_start); - - for _ in 1..num_lines { - let diff = match bytes_per_diff { - 1 => d.read_u8() as u32, - 2 => d.read_u16() as u32, - 4 => d.read_u32(), - _ => unreachable!(), - }; + let name: FileName = Decodable::decode(d); + let src_hash: SourceFileHash = Decodable::decode(d); + let start_pos: BytePos = Decodable::decode(d); + let end_pos: BytePos = Decodable::decode(d); + let lines: Vec = { + let num_lines: u32 = Decodable::decode(d); + let mut lines = Vec::with_capacity(num_lines as usize); + + if num_lines > 0 { + // Read the number of bytes used per diff. + let bytes_per_diff: u8 = Decodable::decode(d); + + // Read the first element. + let mut line_start: BytePos = Decodable::decode(d); + lines.push(line_start); + + for _ in 1..num_lines { + let diff = match bytes_per_diff { + 1 => d.read_u8() as u32, + 2 => d.read_u16() as u32, + 4 => d.read_u32(), + _ => unreachable!(), + }; - line_start = line_start + BytePos(diff); + line_start = line_start + BytePos(diff); - lines.push(line_start); - } + lines.push(line_start); } - - lines - }); - let multibyte_chars: Vec = - d.read_struct_field("multibyte_chars", |d| Decodable::decode(d)); - let non_narrow_chars: Vec = - d.read_struct_field("non_narrow_chars", |d| Decodable::decode(d)); - let name_hash: u128 = d.read_struct_field("name_hash", |d| Decodable::decode(d)); - let normalized_pos: Vec = - d.read_struct_field("normalized_pos", |d| Decodable::decode(d)); - let cnum: CrateNum = d.read_struct_field("cnum", |d| Decodable::decode(d)); - SourceFile { - name, - start_pos, - end_pos, - src: None, - src_hash, - // Unused - the metadata decoder will construct - // a new SourceFile, filling in `external_src` properly - external_src: Lock::new(ExternalSource::Unneeded), - lines, - multibyte_chars, - non_narrow_chars, - normalized_pos, - name_hash, - cnum, } - }) + + lines + }; + let multibyte_chars: Vec = Decodable::decode(d); + let non_narrow_chars: Vec = Decodable::decode(d); + let name_hash: u128 = Decodable::decode(d); + let normalized_pos: Vec = Decodable::decode(d); + let cnum: CrateNum = Decodable::decode(d); + SourceFile { + name, + start_pos, + end_pos, + src: None, + src_hash, + // Unused - the metadata decoder will construct + // a new SourceFile, filling in `external_src` properly + external_src: Lock::new(ExternalSource::Unneeded), + lines, + multibyte_chars, + non_narrow_chars, + normalized_pos, + name_hash, + cnum, + } } } @@ -2103,13 +2096,9 @@ where // If this is not an empty or invalid span, we want to hash the last // position that belongs to it, as opposed to hashing the first // position past it. - let (file, line_lo, col_lo, line_hi, col_hi) = match ctx.span_data_to_lines_and_cols(&span) - { - Some(pos) => pos, - None => { - Hash::hash(&TAG_INVALID_SPAN, hasher); - return; - } + let Some((file, line_lo, col_lo, line_hi, col_hi)) = ctx.span_data_to_lines_and_cols(&span) else { + Hash::hash(&TAG_INVALID_SPAN, hasher); + return; }; Hash::hash(&TAG_VALID_SPAN, hasher); diff --git a/compiler/rustc_symbol_mangling/src/test.rs b/compiler/rustc_symbol_mangling/src/test.rs index 700765a351ce1..611943652a6a1 100644 --- a/compiler/rustc_symbol_mangling/src/test.rs +++ b/compiler/rustc_symbol_mangling/src/test.rs @@ -48,7 +48,7 @@ impl SymbolNamesTest<'_> { tcx.sess.span_err(attr.span, &format!("demangling-alt({:#})", demangling)); } } else if attr.has_name(DEF_PATH) { - let path = with_no_trimmed_paths(|| tcx.def_path_str(def_id.to_def_id())); + let path = with_no_trimmed_paths!(tcx.def_path_str(def_id.to_def_id())); tcx.sess.span_err(attr.span, &format!("def-path({})", path)); } diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index c21c3d3ac330f..62b5436142f5a 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -446,7 +446,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> { ty::Tuple(tys) => { self.push("T"); - for ty in tys.iter().map(|k| k.expect_ty()) { + for ty in tys.iter() { self = ty.print(self)?; } self.push("E"); diff --git a/compiler/rustc_target/src/abi/mod.rs b/compiler/rustc_target/src/abi/mod.rs index 7f1fd28b30df8..4ef863712983f 100644 --- a/compiler/rustc_target/src/abi/mod.rs +++ b/compiler/rustc_target/src/abi/mod.rs @@ -121,12 +121,9 @@ impl TargetDataLayout { dl.pointer_align = align(a, p)?; } [s, ref a @ ..] if s.starts_with('i') => { - let bits = match s[1..].parse::() { - Ok(bits) => bits, - Err(_) => { - size(&s[1..], "i")?; // For the user error. - continue; - } + let Ok(bits) = s[1..].parse::() else { + size(&s[1..], "i")?; // For the user error. + continue; }; let a = align(a, s)?; match bits { diff --git a/compiler/rustc_target/src/lib.rs b/compiler/rustc_target/src/lib.rs index b18d17c1b7d1f..2919743e4996f 100644 --- a/compiler/rustc_target/src/lib.rs +++ b/compiler/rustc_target/src/lib.rs @@ -9,6 +9,7 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![feature(bool_to_option)] +#![feature(let_else)] #![feature(nll)] #![feature(never_type)] #![feature(associated_type_bounds)] diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index b2aa72e0e6741..8b76f3f715106 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -160,20 +160,12 @@ fn overlap<'cx, 'tcx>( ); selcx.infcx().probe_maybe_skip_leak_check(skip_leak_check.is_yes(), |snapshot| { - overlap_within_probe( - selcx, - skip_leak_check, - impl1_def_id, - impl2_def_id, - overlap_mode, - snapshot, - ) + overlap_within_probe(selcx, impl1_def_id, impl2_def_id, overlap_mode, snapshot) }) } fn overlap_within_probe<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, - skip_leak_check: SkipLeakCheck, impl1_def_id: DefId, impl2_def_id: DefId, overlap_mode: OverlapMode, @@ -207,11 +199,11 @@ fn overlap_within_probe<'cx, 'tcx>( } } - if !skip_leak_check.is_yes() { - if infcx.leak_check(true, snapshot).is_err() { - debug!("overlap: leak check failed"); - return None; - } + // We disable the leak when when creating the `snapshot` by using + // `infcx.probe_maybe_disable_leak_check`. + if infcx.leak_check(true, snapshot).is_err() { + debug!("overlap: leak check failed"); + return None; } let intercrate_ambiguity_causes = selcx.take_intercrate_ambiguity_causes(); diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index c3df17c83bbf9..8746d66ebb6e5 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -834,10 +834,9 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { let expected_ty = expected_trait_ref.skip_binder().substs.type_at(1); let expected = match expected_ty.kind() { - ty::Tuple(ref tys) => tys - .iter() - .map(|t| ArgKind::from_expected_ty(t.expect_ty(), Some(span))) - .collect(), + ty::Tuple(ref tys) => { + tys.iter().map(|t| ArgKind::from_expected_ty(t, Some(span))).collect() + } _ => vec![ArgKind::Arg("_".to_owned(), expected_ty.to_string())], }; diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs index 6c8a08c09e777..a277f74f7a43f 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs @@ -161,7 +161,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { } // Add all types without trimmed paths. - ty::print::with_no_trimmed_paths(|| { + ty::print::with_no_trimmed_paths!({ let generics = self.tcx.generics_of(def_id); let self_ty = trait_ref.self_ty(); // This is also included through the generics list as `Self`, diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 7df880a7cc055..e162e943e363b 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -443,9 +443,9 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { { // Missing generic type parameter bound. let param_name = self_ty.to_string(); - let constraint = with_no_trimmed_paths(|| { + let constraint = with_no_trimmed_paths!( trait_pred.print_modifiers_and_trait_path().to_string() - }); + ); if suggest_constraining_type_param( self.tcx, generics, @@ -1301,7 +1301,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { if tcx.fn_trait_kind_from_lang_item(trait_ref.def_id()).is_some() => { tcx.mk_fn_sig( - inputs.iter().map(|k| k.expect_ty()), + inputs.iter(), tcx.mk_ty_infer(ty::TyVar(ty::TyVid::from_u32(0))), false, hir::Unsafety::Normal, diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index 1989184f48f0e..362d669f867e0 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -314,7 +314,7 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> { return ProcessResult::Unchanged; } - self.progress_changed_obligations(pending_obligation) + self.process_changed_obligations(pending_obligation) } fn process_backedge<'c, I>( @@ -338,7 +338,7 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> { // actually uses this, so move this part of the code // out of that loop. #[inline(never)] - fn progress_changed_obligations( + fn process_changed_obligations( &mut self, pending_obligation: &mut PendingPredicateObligation<'tcx>, ) -> ProcessResult, FulfillmentErrorCode<'tcx>> { diff --git a/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs b/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs index 55903a3c36a29..066f3ffada57a 100644 --- a/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs +++ b/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs @@ -108,7 +108,7 @@ pub fn trivial_dropck_outlives<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool { // (T1..Tn) and closures have same properties as T1..Tn -- // check if *any* of those are trivial. - ty::Tuple(ref tys) => tys.iter().all(|t| trivial_dropck_outlives(tcx, t.expect_ty())), + ty::Tuple(tys) => tys.iter().all(|t| trivial_dropck_outlives(tcx, t)), ty::Closure(_, ref substs) => { trivial_dropck_outlives(tcx, substs.as_closure().tupled_upvars_ty()) } diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index db86041f6180b..4d7c9ef89e62b 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -92,7 +92,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { if !candidate_set.ambiguous && no_candidates_apply { let trait_ref = stack.obligation.predicate.skip_binder().trait_ref; let self_ty = trait_ref.self_ty(); - let (trait_desc, self_desc) = with_no_trimmed_paths(|| { + let (trait_desc, self_desc) = with_no_trimmed_paths!({ let trait_desc = trait_ref.print_only_trait_path().to_string(); let self_desc = if self_ty.has_concrete_skeleton() { Some(self_ty.to_string()) @@ -389,7 +389,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { for bound in matching_bounds { // FIXME(oli-obk): it is suspicious that we are dropping the constness and // polarity here. - let wc = self.evaluate_where_clause(stack, bound.map_bound(|t| t.trait_ref))?; + let wc = self.where_clause_may_apply(stack, bound.map_bound(|t| t.trait_ref))?; if wc.may_apply() { candidates.vec.push(ParamCandidate(bound)); } diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 84bc7cdff2890..56d7f301b854e 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -553,23 +553,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ) .map_bound(|(trait_ref, _)| trait_ref); - let Normalized { value: trait_ref, mut obligations } = ensure_sufficient_stack(|| { - normalize_with_depth( - self, - obligation.param_env, - obligation.cause.clone(), - obligation.recursion_depth + 1, - trait_ref, - ) - }); - - obligations.extend(self.confirm_poly_trait_refs( - obligation.cause.clone(), - obligation.param_env, - obligation.predicate.to_poly_trait_ref(), - trait_ref, - )?); - Ok(ImplSourceFnPointerData { fn_ty: self_ty, nested: obligations }) + let nested = self.confirm_poly_trait_refs(obligation, trait_ref)?; + Ok(ImplSourceFnPointerData { fn_ty: self_ty, nested }) } fn confirm_trait_alias_candidate( @@ -616,26 +601,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { debug!(?obligation, ?generator_def_id, ?substs, "confirm_generator_candidate"); let trait_ref = self.generator_trait_ref_unnormalized(obligation, substs); - let Normalized { value: trait_ref, mut obligations } = ensure_sufficient_stack(|| { - normalize_with_depth( - self, - obligation.param_env, - obligation.cause.clone(), - obligation.recursion_depth + 1, - trait_ref, - ) - }); - debug!(?trait_ref, ?obligations, "generator candidate obligations"); - - obligations.extend(self.confirm_poly_trait_refs( - obligation.cause.clone(), - obligation.param_env, - obligation.predicate.to_poly_trait_ref(), - trait_ref, - )?); + let nested = self.confirm_poly_trait_refs(obligation, trait_ref)?; + debug!(?trait_ref, ?nested, "generator candidate obligations"); - Ok(ImplSourceGeneratorData { generator_def_id, substs, nested: obligations }) + Ok(ImplSourceGeneratorData { generator_def_id, substs, nested }) } #[instrument(skip(self), level = "debug")] @@ -657,44 +627,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { _ => bug!("closure candidate for non-closure {:?}", obligation), }; - let obligation_predicate = obligation.predicate; - let Normalized { value: obligation_predicate, mut obligations } = - ensure_sufficient_stack(|| { - normalize_with_depth( - self, - obligation.param_env, - obligation.cause.clone(), - obligation.recursion_depth + 1, - obligation_predicate, - ) - }); - let trait_ref = self.closure_trait_ref_unnormalized(obligation, substs); - let Normalized { value: trait_ref, obligations: trait_ref_obligations } = - ensure_sufficient_stack(|| { - normalize_with_depth( - self, - obligation.param_env, - obligation.cause.clone(), - obligation.recursion_depth + 1, - trait_ref, - ) - }); + let mut nested = self.confirm_poly_trait_refs(obligation, trait_ref)?; - debug!(?closure_def_id, ?trait_ref, ?obligations, "confirm closure candidate obligations"); - - obligations.extend(trait_ref_obligations); - obligations.extend(self.confirm_poly_trait_refs( - obligation.cause.clone(), - obligation.param_env, - obligation_predicate.to_poly_trait_ref(), - trait_ref, - )?); + debug!(?closure_def_id, ?trait_ref, ?nested, "confirm closure candidate obligations"); // FIXME: Chalk if !self.tcx().sess.opts.debugging_opts.chalk { - obligations.push(Obligation::new( + nested.push(Obligation::new( obligation.cause.clone(), obligation.param_env, ty::Binder::dummy(ty::PredicateKind::ClosureKind(closure_def_id, substs, kind)) @@ -702,7 +643,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { )); } - Ok(ImplSourceClosureData { closure_def_id, substs, nested: obligations }) + Ok(ImplSourceClosureData { closure_def_id, substs, nested }) } /// In the case of closure types and fn pointers, @@ -733,15 +674,31 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { #[instrument(skip(self), level = "trace")] fn confirm_poly_trait_refs( &mut self, - obligation_cause: ObligationCause<'tcx>, - obligation_param_env: ty::ParamEnv<'tcx>, - obligation_trait_ref: ty::PolyTraitRef<'tcx>, + obligation: &TraitObligation<'tcx>, expected_trait_ref: ty::PolyTraitRef<'tcx>, ) -> Result>, SelectionError<'tcx>> { + let obligation_trait_ref = obligation.predicate.to_poly_trait_ref(); + // Normalize the obligation and expected trait refs together, because why not + let Normalized { obligations: nested, value: (obligation_trait_ref, expected_trait_ref) } = + ensure_sufficient_stack(|| { + self.infcx.commit_unconditionally(|_| { + normalize_with_depth( + self, + obligation.param_env, + obligation.cause.clone(), + obligation.recursion_depth + 1, + (obligation_trait_ref, expected_trait_ref), + ) + }) + }); + self.infcx - .at(&obligation_cause, obligation_param_env) + .at(&obligation.cause, obligation.param_env) .sup(obligation_trait_ref, expected_trait_ref) - .map(|InferOk { obligations, .. }| obligations) + .map(|InferOk { mut obligations, .. }| { + obligations.extend(nested); + obligations + }) .map_err(|e| OutputTypeParameterMismatch(expected_trait_ref, obligation_trait_ref, e)) } @@ -1058,9 +1015,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // Check that the source tuple with the target's // last element is equal to the target. - let new_tuple = tcx.mk_tup( - a_mid.iter().map(|k| k.expect_ty()).chain(iter::once(b_last.expect_ty())), - ); + let new_tuple = tcx.mk_tup(a_mid.iter().copied().chain(iter::once(b_last))); let InferOk { obligations, .. } = self .infcx .at(&obligation.cause, obligation.param_env) @@ -1076,8 +1031,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligation.cause.clone(), obligation.predicate.def_id(), obligation.recursion_depth + 1, - a_last.expect_ty(), - &[b_last], + a_last, + &[b_last.into()], ) })); } @@ -1140,7 +1095,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { stack.push(ty); } ty::Tuple(tys) => { - stack.extend(tys.iter().map(|ty| ty.expect_ty())); + stack.extend(tys.iter()); } ty::Closure(_, substs) => { stack.push(substs.as_closure().tupled_upvars_ty()); diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 3b69700530b85..5b646c6d4477c 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -922,7 +922,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { if !candidate_set.ambiguous && candidate_set.vec.is_empty() { let trait_ref = stack.obligation.predicate.skip_binder().trait_ref; let self_ty = trait_ref.self_ty(); - let cause = with_no_trimmed_paths(|| { + let cause = with_no_trimmed_paths!({ IntercrateAmbiguityCause::DownstreamCrate { trait_desc: trait_ref.print_only_trait_path().to_string(), self_desc: if self_ty.has_concrete_skeleton() { @@ -1481,7 +1481,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { .map_err(|_| ()) } - fn evaluate_where_clause<'o>( + fn where_clause_may_apply<'o>( &mut self, stack: &TraitObligationStack<'o, 'tcx>, where_clause_trait_ref: ty::PolyTraitRef<'tcx>, @@ -1852,9 +1852,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ty::Str | ty::Slice(_) | ty::Dynamic(..) | ty::Foreign(..) => None, ty::Tuple(tys) => Where( - obligation - .predicate - .rebind(tys.last().into_iter().map(|k| k.expect_ty()).collect()), + obligation.predicate.rebind(tys.last().map_or_else(Vec::new, |&last| vec![last])), ), ty::Adt(def, substs) => { @@ -1917,7 +1915,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ty::Tuple(tys) => { // (*) binder moved here - Where(obligation.predicate.rebind(tys.iter().map(|k| k.expect_ty()).collect())) + Where(obligation.predicate.rebind(tys.iter().collect())) } ty::Closure(_, substs) => { @@ -1997,7 +1995,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ty::Tuple(ref tys) => { // (T1, ..., Tn) -- meets any bound that all of T1...Tn meet - t.rebind(tys.iter().map(|k| k.expect_ty()).collect()) + t.rebind(tys.iter().collect()) } ty::Closure(_, ref substs) => { diff --git a/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs b/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs index 497ac207bbe4f..e31a9b200e873 100644 --- a/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs +++ b/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs @@ -106,7 +106,7 @@ impl ChildrenExt<'_> for Children { let self_ty = trait_ref.self_ty(); // FIXME: should postpone string formatting until we decide to actually emit. - with_no_trimmed_paths(|| { + with_no_trimmed_paths!({ OverlapError { with_impl: possible_sibling, trait_desc: trait_ref.print_only_trait_path().to_string(), diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index 2dd3b77a73cdf..7da5c50d2307d 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -529,8 +529,8 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { ty::Tuple(ref tys) => { if let Some((_last, rest)) = tys.split_last() { - for elem in rest { - self.require_sized(elem.expect_ty(), traits::TupleElem); + for &elem in rest { + self.require_sized(elem, traits::TupleElem); } } } diff --git a/compiler/rustc_traits/src/chalk/db.rs b/compiler/rustc_traits/src/chalk/db.rs index 51b66e1bb6503..8d4b97571a6a3 100644 --- a/compiler/rustc_traits/src/chalk/db.rs +++ b/compiler/rustc_traits/src/chalk/db.rs @@ -72,9 +72,8 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t ) -> Arc>> { let def_id = assoc_type_id.0; let assoc_item = self.interner.tcx.associated_item(def_id); - let trait_def_id = match assoc_item.container { - AssocItemContainer::TraitContainer(def_id) => def_id, - _ => unimplemented!("Not possible??"), + let AssocItemContainer::TraitContainer(trait_def_id) = assoc_item.container else { + unimplemented!("Not possible??"); }; match assoc_item.kind { AssocKind::Type => {} @@ -566,7 +565,7 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t // FIXME(chalk): actually get hidden ty self.interner .tcx - .mk_ty(ty::Tuple(self.interner.tcx.intern_substs(&[]))) + .mk_ty(ty::Tuple(self.interner.tcx.intern_type_list(&[]))) .lower_into(self.interner) } diff --git a/compiler/rustc_traits/src/chalk/lowering.rs b/compiler/rustc_traits/src/chalk/lowering.rs index 9d810d0881b5f..2cd179526bf13 100644 --- a/compiler/rustc_traits/src/chalk/lowering.rs +++ b/compiler/rustc_traits/src/chalk/lowering.rs @@ -326,7 +326,9 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Ty>> for Ty<'tcx> { ty::Generator(_def_id, _substs, _) => unimplemented!(), ty::GeneratorWitness(_) => unimplemented!(), ty::Never => chalk_ir::TyKind::Never, - ty::Tuple(substs) => chalk_ir::TyKind::Tuple(substs.len(), substs.lower_into(interner)), + ty::Tuple(types) => { + chalk_ir::TyKind::Tuple(types.len(), types.as_substs().lower_into(interner)) + } ty::Projection(proj) => chalk_ir::TyKind::Alias(proj.lower_into(interner)), ty::Opaque(def_id, substs) => { chalk_ir::TyKind::Alias(chalk_ir::AliasTy::Opaque(chalk_ir::OpaqueTy { @@ -398,7 +400,9 @@ impl<'tcx> LowerInto<'tcx, Ty<'tcx>> for &chalk_ir::Ty> { TyKind::Generator(..) => unimplemented!(), TyKind::GeneratorWitness(..) => unimplemented!(), TyKind::Never => ty::Never, - TyKind::Tuple(_len, substitution) => ty::Tuple(substitution.lower_into(interner)), + TyKind::Tuple(_len, substitution) => { + ty::Tuple(substitution.lower_into(interner).try_as_type_list().unwrap()) + } TyKind::Slice(ty) => ty::Slice(ty.lower_into(interner)), TyKind::Raw(mutbl, ty) => ty::RawPtr(ty::TypeAndMut { ty: ty.lower_into(interner), diff --git a/compiler/rustc_traits/src/dropck_outlives.rs b/compiler/rustc_traits/src/dropck_outlives.rs index 455fc46a42e84..3658f8e57356b 100644 --- a/compiler/rustc_traits/src/dropck_outlives.rs +++ b/compiler/rustc_traits/src/dropck_outlives.rs @@ -198,14 +198,7 @@ fn dtorck_constraint_for_ty<'tcx>( ty::Tuple(tys) => rustc_data_structures::stack::ensure_sufficient_stack(|| { for ty in tys.iter() { - dtorck_constraint_for_ty( - tcx, - span, - for_ty, - depth + 1, - ty.expect_ty(), - constraints, - )?; + dtorck_constraint_for_ty(tcx, span, for_ty, depth + 1, ty, constraints)?; } Ok::<_, NoSolution>(()) })?, diff --git a/compiler/rustc_traits/src/lib.rs b/compiler/rustc_traits/src/lib.rs index b814b984daeef..73fd95e98ca54 100644 --- a/compiler/rustc_traits/src/lib.rs +++ b/compiler/rustc_traits/src/lib.rs @@ -2,6 +2,7 @@ //! the guts are broken up into modules; see the comments in those modules. #![feature(crate_visibility_modifier)] +#![feature(let_else)] #![feature(nll)] #![recursion_limit = "256"] diff --git a/compiler/rustc_ty_utils/src/lib.rs b/compiler/rustc_ty_utils/src/lib.rs index 55e199907617c..702a9513b4402 100644 --- a/compiler/rustc_ty_utils/src/lib.rs +++ b/compiler/rustc_ty_utils/src/lib.rs @@ -6,6 +6,7 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![feature(control_flow_enum)] +#![feature(let_else)] #![feature(nll)] #![recursion_limit = "256"] diff --git a/compiler/rustc_ty_utils/src/representability.rs b/compiler/rustc_ty_utils/src/representability.rs index b08f8f6230837..11a57688580a6 100644 --- a/compiler/rustc_ty_utils/src/representability.rs +++ b/compiler/rustc_ty_utils/src/representability.rs @@ -70,9 +70,9 @@ fn are_inner_types_recursive<'tcx>( ) -> Representability { debug!("are_inner_types_recursive({:?}, {:?}, {:?})", ty, seen, shadow_seen); match ty.kind() { - ty::Tuple(..) => { + ty::Tuple(fields) => { // Find non representable - fold_repr(ty.tuple_fields().map(|ty| { + fold_repr(fields.iter().map(|ty| { is_type_structurally_recursive( tcx, sp, diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index e44f80d5ac3f2..e6ce3447548de 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -24,7 +24,7 @@ fn sized_constraint_for_ty<'tcx>( Tuple(ref tys) => match tys.last() { None => vec![], - Some(ty) => sized_constraint_for_ty(tcx, adtdef, ty.expect_ty()), + Some(&ty) => sized_constraint_for_ty(tcx, adtdef, ty), }, Adt(adt, substs) => { @@ -49,10 +49,7 @@ fn sized_constraint_for_ty<'tcx>( // we know that `T` is Sized and do not need to check // it on the impl. - let sized_trait = match tcx.lang_items().sized_trait() { - Some(x) => x, - _ => return vec![ty], - }; + let Some(sized_trait) = tcx.lang_items().sized_trait() else { return vec![ty] }; let sized_predicate = ty::Binder::dummy(ty::TraitRef { def_id: sized_trait, substs: tcx.mk_substs_trait(ty, &[]), @@ -464,9 +461,9 @@ pub fn conservative_is_privately_uninhabited_raw<'tcx>( }) }) } - ty::Tuple(..) => { + ty::Tuple(fields) => { debug!("ty::Tuple(..) =>"); - ty.tuple_fields().any(|ty| tcx.conservative_is_privately_uninhabited(param_env.and(ty))) + fields.iter().any(|ty| tcx.conservative_is_privately_uninhabited(param_env.and(ty))) } ty::Array(ty, len) => { debug!("ty::Array(ty, len) =>"); diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs index 96f9204998327..dbe7ddeb6a824 100644 --- a/compiler/rustc_typeck/src/astconv/mod.rs +++ b/compiler/rustc_typeck/src/astconv/mod.rs @@ -1808,12 +1808,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { (_, Res::SelfTy { trait_: Some(_), alias_to: Some((impl_def_id, _)) }) => { // `Self` in an impl of a trait -- we have a concrete self type and a // trait reference. - let trait_ref = match tcx.impl_trait_ref(impl_def_id) { - Some(trait_ref) => trait_ref, - None => { - // A cycle error occurred, most likely. - return Err(ErrorReported); - } + let Some(trait_ref) = tcx.impl_trait_ref(impl_def_id) else { + // A cycle error occurred, most likely. + return Err(ErrorReported); }; self.one_bound_for_assoc_type( diff --git a/compiler/rustc_typeck/src/check/callee.rs b/compiler/rustc_typeck/src/check/callee.rs index f64a90ed10e22..679cac0b82a52 100644 --- a/compiler/rustc_typeck/src/check/callee.rs +++ b/compiler/rustc_typeck/src/check/callee.rs @@ -219,10 +219,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { (self.tcx.lang_items().fn_mut_trait(), Ident::with_dummy_span(sym::call_mut), true), (self.tcx.lang_items().fn_once_trait(), Ident::with_dummy_span(sym::call_once), false), ] { - let trait_def_id = match opt_trait_def_id { - Some(def_id) => def_id, - None => continue, - }; + let Some(trait_def_id) = opt_trait_def_id else { continue }; let opt_input_types = opt_arg_exprs.map(|arg_exprs| { [self.tcx.mk_tup(arg_exprs.iter().map(|e| { @@ -246,11 +243,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if borrow { // Check for &self vs &mut self in the method signature. Since this is either // the Fn or FnMut trait, it should be one of those. - let (region, mutbl) = if let ty::Ref(r, _, mutbl) = - method.sig.inputs()[0].kind() - { - (r, mutbl) - } else { + let ty::Ref(region, _, mutbl) = method.sig.inputs()[0].kind() else { // The `fn`/`fn_mut` lang item is ill-formed, which should have // caused an error elsewhere. self.tcx diff --git a/compiler/rustc_typeck/src/check/cast.rs b/compiler/rustc_typeck/src/check/cast.rs index 56b6c09069027..57076d9724678 100644 --- a/compiler/rustc_typeck/src/check/cast.rs +++ b/compiler/rustc_typeck/src/check/cast.rs @@ -111,7 +111,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }, ty::Tuple(fields) => match fields.last() { None => Some(PointerKind::Thin), - Some(f) => self.pointer_kind(f.expect_ty(), span)?, + Some(&f) => self.pointer_kind(f, span)?, }, // Pointers to foreign types are thin, despite being unsized @@ -799,10 +799,9 @@ impl<'a, 'tcx> CastCheck<'tcx> { let expr_kind = fcx.pointer_kind(m_expr.ty, self.span)?; let cast_kind = fcx.pointer_kind(m_cast.ty, self.span)?; - let cast_kind = match cast_kind { + let Some(cast_kind) = cast_kind else { // We can't cast if target pointer kind is unknown - None => return Err(CastError::UnknownCastPtrKind), - Some(cast_kind) => cast_kind, + return Err(CastError::UnknownCastPtrKind); }; // Cast to thin pointer is OK @@ -810,10 +809,9 @@ impl<'a, 'tcx> CastCheck<'tcx> { return Ok(CastKind::PtrPtrCast); } - let expr_kind = match expr_kind { + let Some(expr_kind) = expr_kind else { // We can't cast to fat pointer if source pointer kind is unknown - None => return Err(CastError::UnknownExprPtrKind), - Some(expr_kind) => expr_kind, + return Err(CastError::UnknownExprPtrKind); }; // thin -> fat? report invalid cast (don't complain about vtable kinds) diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs index 1650a62f79f29..30ae382de4278 100644 --- a/compiler/rustc_typeck/src/check/check.rs +++ b/compiler/rustc_typeck/src/check/check.rs @@ -415,13 +415,10 @@ fn check_static_inhabited<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId, span: Spa // have UB during initialization if they are uninhabited, but there also seems to be no good // reason to allow any statics to be uninhabited. let ty = tcx.type_of(def_id); - let layout = match tcx.layout_of(ParamEnv::reveal_all().and(ty)) { - Ok(l) => l, - Err(_) => { - // Generic statics are rejected, but we still reach this case. - tcx.sess.delay_span_bug(span, "generic static must be rejected"); - return; - } + let Ok(layout) = tcx.layout_of(ParamEnv::reveal_all().and(ty)) else { + // Generic statics are rejected, but we still reach this case. + tcx.sess.delay_span_bug(span, "generic static must be rejected"); + return; }; if layout.abi.is_uninhabited() { tcx.struct_span_lint_hir( @@ -852,10 +849,7 @@ pub(super) fn check_specialization_validity<'tcx>( impl_id: DefId, impl_item: &hir::ImplItemRef, ) { - let ancestors = match trait_def.ancestors(tcx, impl_id) { - Ok(ancestors) => ancestors, - Err(_) => return, - }; + let Ok(ancestors) = trait_def.ancestors(tcx, impl_id) else { return }; let mut ancestor_impls = ancestors.skip(1).filter_map(|parent| { if parent.is_from_trait() { None diff --git a/compiler/rustc_typeck/src/check/closure.rs b/compiler/rustc_typeck/src/check/closure.rs index 3c626837ef1a3..59c8febdc30da 100644 --- a/compiler/rustc_typeck/src/check/closure.rs +++ b/compiler/rustc_typeck/src/check/closure.rs @@ -270,7 +270,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { debug!("deduce_sig_from_projection: arg_param_ty={:?}", arg_param_ty); match arg_param_ty.kind() { - ty::Tuple(tys) => tys.into_iter().map(|k| k.expect_ty()).collect::>(), + &ty::Tuple(tys) => tys, _ => return None, } } else { @@ -286,7 +286,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let sig = projection.rebind(self.tcx.mk_fn_sig( input_tys.iter(), - &ret_param_ty, + ret_param_ty, false, hir::Unsafety::Normal, Abi::Rust, @@ -676,12 +676,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // We do not expect any bound regions in our predicate, so // skip past the bound vars. - let predicate = match predicate.no_bound_vars() { - Some(p) => p, - None => { - debug!("deduce_future_output_from_projection: has late-bound regions"); - return None; - } + let Some(predicate) = predicate.no_bound_vars() else { + debug!("deduce_future_output_from_projection: has late-bound regions"); + return None; }; // Check that this is a projection from the `Future` trait. diff --git a/compiler/rustc_typeck/src/check/coercion.rs b/compiler/rustc_typeck/src/check/coercion.rs index be7ac006926a9..b011fb8804d3d 100644 --- a/compiler/rustc_typeck/src/check/coercion.rs +++ b/compiler/rustc_typeck/src/check/coercion.rs @@ -429,13 +429,10 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { // (e.g., in example above, the failure from relating `Vec` // to the target type), since that should be the least // confusing. - let InferOk { value: ty, mut obligations } = match found { - Some(d) => d, - None => { - let err = first_error.expect("coerce_borrowed_pointer had no error"); - debug!("coerce_borrowed_pointer: failed with err = {:?}", err); - return Err(err); - } + let Some(InferOk { value: ty, mut obligations }) = found else { + let err = first_error.expect("coerce_borrowed_pointer had no error"); + debug!("coerce_borrowed_pointer: failed with err = {:?}", err); + return Err(err); }; if ty == a && mt_a.mutbl == hir::Mutability::Not && autoderef.step_count() == 1 { @@ -461,9 +458,8 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { // Now apply the autoref. We have to extract the region out of // the final ref type we got. - let r_borrow = match ty.kind() { - ty::Ref(r_borrow, _, _) => r_borrow, - _ => span_bug!(span, "expected a ref type, got {:?}", ty), + let ty::Ref(r_borrow, _, _) = ty.kind() else { + span_bug!(span, "expected a ref type, got {:?}", ty); }; let mutbl = match mutbl_b { hir::Mutability::Not => AutoBorrowMutability::Not, @@ -944,9 +940,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // We don't ever need two-phase here since we throw out the result of the coercion let coerce = Coerce::new(self, cause, AllowTwoPhase::No); self.probe(|_| { - let ok = match coerce.coerce(source, target) { - Ok(ok) => ok, - _ => return false, + let Ok(ok) = coerce.coerce(source, target) else { + return false; }; let mut fcx = traits::FulfillmentContext::new_in_snapshot(); fcx.register_predicate_obligations(self, ok.obligations); diff --git a/compiler/rustc_typeck/src/check/demand.rs b/compiler/rustc_typeck/src/check/demand.rs index e7eadb760c7c0..466f32aa800f9 100644 --- a/compiler/rustc_typeck/src/check/demand.rs +++ b/compiler/rustc_typeck/src/check/demand.rs @@ -324,7 +324,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let sole_field_ty = sole_field.ty(self.tcx, substs); if self.can_coerce(expr_ty, sole_field_ty) { let variant_path = - with_no_trimmed_paths(|| self.tcx.def_path_str(variant.def_id)); + with_no_trimmed_paths!(self.tcx.def_path_str(variant.def_id)); // FIXME #56861: DRYer prelude filtering if let Some(path) = variant_path.strip_prefix("std::prelude::") { if let Some((_, path)) = path.split_once("::") { @@ -435,44 +435,39 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// opt.map(|param| { takes_ref(param) }); /// ``` fn can_use_as_ref(&self, expr: &hir::Expr<'_>) -> Option<(Span, &'static str, String)> { - let path = match expr.kind { - hir::ExprKind::Path(hir::QPath::Resolved(_, ref path)) => path, - _ => return None, + let hir::ExprKind::Path(hir::QPath::Resolved(_, ref path)) = expr.kind else { + return None; }; - let local_id = match path.res { - hir::def::Res::Local(id) => id, - _ => return None, + let hir::def::Res::Local(local_id) = path.res else { + return None; }; let local_parent = self.tcx.hir().get_parent_node(local_id); - let param_hir_id = match self.tcx.hir().find(local_parent) { - Some(Node::Param(hir::Param { hir_id, .. })) => hir_id, - _ => return None, + let Some(Node::Param(hir::Param { hir_id: param_hir_id, .. })) = self.tcx.hir().find(local_parent) else { + return None; }; let param_parent = self.tcx.hir().get_parent_node(*param_hir_id); - let (expr_hir_id, closure_fn_decl) = match self.tcx.hir().find(param_parent) { - Some(Node::Expr(hir::Expr { - hir_id, - kind: hir::ExprKind::Closure(_, decl, ..), - .. - })) => (hir_id, decl), - _ => return None, + let Some(Node::Expr(hir::Expr { + hir_id: expr_hir_id, + kind: hir::ExprKind::Closure(_, closure_fn_decl, ..), + .. + })) = self.tcx.hir().find(param_parent) else { + return None; }; let expr_parent = self.tcx.hir().get_parent_node(*expr_hir_id); let hir = self.tcx.hir().find(expr_parent); let closure_params_len = closure_fn_decl.inputs.len(); - let (method_path, method_expr) = match (hir, closure_params_len) { - ( - Some(Node::Expr(hir::Expr { - kind: hir::ExprKind::MethodCall(segment, expr, _), - .. - })), - 1, - ) => (segment, expr), - _ => return None, + let ( + Some(Node::Expr(hir::Expr { + kind: hir::ExprKind::MethodCall(method_path, method_expr, _), + .. + })), + 1, + ) = (hir, closure_params_len) else { + return None; }; let self_ty = self.typeck_results.borrow().node_type(method_expr[0].hir_id); diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs index 4869d193d8056..b08ee414fa7b4 100644 --- a/compiler/rustc_typeck/src/check/expr.rs +++ b/compiler/rustc_typeck/src/check/expr.rs @@ -622,15 +622,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // the `enclosing_loops` field and let's coerce the // type of `expr_opt` into what is expected. let mut enclosing_breakables = self.enclosing_breakables.borrow_mut(); - let ctxt = match enclosing_breakables.opt_find_breakable(target_id) { - Some(ctxt) => ctxt, - None => { - // Avoid ICE when `break` is inside a closure (#65383). - return tcx.ty_error_with_message( - expr.span, - "break was outside loop, but no error was emitted", - ); - } + let Some(ctxt) = enclosing_breakables.opt_find_breakable(target_id) else { + // Avoid ICE when `break` is inside a closure (#65383). + return tcx.ty_error_with_message( + expr.span, + "break was outside loop, but no error was emitted", + ); }; if let Some(ref mut coerce) = ctxt.coerce { @@ -1294,7 +1291,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let elt_ts_iter = elts.iter().enumerate().map(|(i, e)| match flds { Some(fs) if i < fs.len() => { - let ety = fs[i].expect_ty(); + let ety = fs[i]; self.check_expr_coercable_to_type(&e, ety, None); ety } @@ -1880,13 +1877,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let fstr = field.as_str(); if let Ok(index) = fstr.parse::() { if fstr == index.to_string() { - if let Some(field_ty) = tys.get(index) { + if let Some(&field_ty) = tys.get(index) { let adjustments = self.adjust_steps(&autoderef); self.apply_adjustments(base, adjustments); self.register_predicates(autoderef.into_obligations()); self.write_field_index(expr.hir_id, index); - return field_ty.expect_ty(); + return field_ty; } } } diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs index 96bbc2800d50a..f6cd136940333 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs @@ -745,10 +745,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { formal_args: &[Ty<'tcx>], ) -> Vec> { let formal_ret = self.resolve_vars_with_obligations(formal_ret); - let ret_ty = match expected_ret.only_has_type(self) { - Some(ret) => ret, - None => return Vec::new(), - }; + let Some(ret_ty) = expected_ret.only_has_type(self) else { return Vec::new() }; let expect_args = self .fudge_inference_if_ok(|| { // Attempt to apply a subtyping relationship between the formal @@ -1044,9 +1041,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Be helpful when the user wrote `{... expr;}` and // taking the `;` off is enough to fix the error. let last_stmt = blk.stmts.last()?; - let last_expr = match last_stmt.kind { - hir::StmtKind::Semi(ref e) => e, - _ => return None, + let hir::StmtKind::Semi(ref last_expr) = last_stmt.kind else { + return None; }; let last_expr_ty = self.node_ty(last_expr.hir_id); let needs_box = match (last_expr_ty.kind(), expected_ty.kind()) { @@ -1061,11 +1057,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { last_def_id, last_bounds, exp_def_id, exp_bounds ); - let (last_local_id, exp_local_id) = - match (last_def_id.as_local(), exp_def_id.as_local()) { - (Some(last_hir_id), Some(exp_hir_id)) => (last_hir_id, exp_hir_id), - (_, _) => return None, - }; + let last_local_id = last_def_id.as_local()?; + let exp_local_id = exp_def_id.as_local()?; match ( &self.tcx.hir().expect_item(last_local_id).kind, diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs index d05dd517f1ea3..d3d42a1f37c75 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs @@ -147,12 +147,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } let expected_input_tys = match expected_input_tys.get(0) { Some(&ty) => match ty.kind() { - ty::Tuple(ref tys) => tys.iter().map(|k| k.expect_ty()).collect(), + ty::Tuple(tys) => tys.iter().collect(), _ => vec![], }, None => vec![], }; - (arg_types.iter().map(|k| k.expect_ty()).collect(), expected_input_tys) + (arg_types.iter().collect(), expected_input_tys) } _ => { // Otherwise, there's a mismatch, so clear out what we're expecting, and set @@ -495,12 +495,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expected_input_tys: &[Ty<'tcx>], provided_args: &'tcx [hir::Expr<'tcx>], ) -> Option> { - let [expected_arg_type] = &expected_input_tys[..] else { return None }; + let [expected_arg_type] = expected_input_tys[..] else { return None }; - let ty::Tuple(expected_elems) = self.resolve_vars_if_possible(*expected_arg_type).kind() + let &ty::Tuple(expected_types) = self.resolve_vars_if_possible(expected_arg_type).kind() else { return None }; - let expected_types: Vec<_> = expected_elems.iter().map(|k| k.expect_ty()).collect(); let supplied_types: Vec<_> = provided_args.iter().map(|arg| self.check_expr(arg)).collect(); let all_match = iter::zip(expected_types, supplied_types) diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs b/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs index f9c482713f1fe..f6a2447572ffd 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs @@ -438,9 +438,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // is and we were expecting a Box, ergo Pin>, we // can suggest Box::pin. let parent = self.tcx.hir().get_parent_node(expr.hir_id); - let fn_name = match self.tcx.hir().find(parent) { - Some(Node::Expr(Expr { kind: ExprKind::Call(fn_name, _), .. })) => fn_name, - _ => return false, + let Some(Node::Expr(Expr { kind: ExprKind::Call(fn_name, _), .. })) = self.tcx.hir().find(parent) else { + return false; }; match fn_name.kind { ExprKind::Path(QPath::TypeRelative( diff --git a/compiler/rustc_typeck/src/check/generator_interior.rs b/compiler/rustc_typeck/src/check/generator_interior.rs index d360f34ae709c..9684237be8313 100644 --- a/compiler/rustc_typeck/src/check/generator_interior.rs +++ b/compiler/rustc_typeck/src/check/generator_interior.rs @@ -539,16 +539,16 @@ pub fn check_must_not_suspend_ty<'tcx>( } has_emitted } - ty::Tuple(_) => { + ty::Tuple(fields) => { let mut has_emitted = false; let comps = match data.expr.map(|e| &e.kind) { Some(hir::ExprKind::Tup(comps)) => { - debug_assert_eq!(comps.len(), ty.tuple_fields().count()); + debug_assert_eq!(comps.len(), fields.len()); Some(comps) } _ => None, }; - for (i, ty) in ty.tuple_fields().enumerate() { + for (i, ty) in fields.iter().enumerate() { let descr_post = &format!(" in tuple element {}", i); let span = comps.and_then(|c| c.get(i)).map(|e| e.span).unwrap_or(data.source_span); if check_must_not_suspend_ty( diff --git a/compiler/rustc_typeck/src/check/method/confirm.rs b/compiler/rustc_typeck/src/check/method/confirm.rs index fdc3ba17e3ccf..3fa873e46abbb 100644 --- a/compiler/rustc_typeck/src/check/method/confirm.rs +++ b/compiler/rustc_typeck/src/check/method/confirm.rs @@ -149,14 +149,11 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { // time writing the results into the various typeck results. let mut autoderef = self.autoderef_overloaded_span(self.span, unadjusted_self_ty, self.call_expr.span); - let (ty, n) = match autoderef.nth(pick.autoderefs) { - Some(n) => n, - None => { - return self.tcx.ty_error_with_message( - rustc_span::DUMMY_SP, - &format!("failed autoderef {}", pick.autoderefs), - ); - } + let Some((ty, n)) = autoderef.nth(pick.autoderefs) else { + return self.tcx.ty_error_with_message( + rustc_span::DUMMY_SP, + &format!("failed autoderef {}", pick.autoderefs), + ); }; assert_eq!(n, pick.autoderefs); @@ -520,10 +517,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { &self, predicates: &ty::InstantiatedPredicates<'tcx>, ) -> Option { - let sized_def_id = match self.tcx.lang_items().sized_trait() { - Some(def_id) => def_id, - None => return None, - }; + let sized_def_id = self.tcx.lang_items().sized_trait()?; traits::elaborate_predicates(self.tcx, predicates.predicates.iter().copied()) // We don't care about regions here. diff --git a/compiler/rustc_typeck/src/check/method/mod.rs b/compiler/rustc_typeck/src/check/method/mod.rs index e5ef52e0324e7..780a57278c5b0 100644 --- a/compiler/rustc_typeck/src/check/method/mod.rs +++ b/compiler/rustc_typeck/src/check/method/mod.rs @@ -371,15 +371,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Trait must have a method named `m_name` and it should not have // type parameters or early-bound regions. let tcx = self.tcx; - let method_item = match self.associated_value(trait_def_id, m_name) { - Some(method_item) => method_item, - None => { - tcx.sess.delay_span_bug( - span, - "operator trait does not have corresponding operator method", - ); - return None; - } + let Some(method_item) = self.associated_value(trait_def_id, m_name) else { + tcx.sess.delay_span_bug( + span, + "operator trait does not have corresponding operator method", + ); + return None; }; let def_id = method_item.def_id; let generics = tcx.generics_of(def_id); diff --git a/compiler/rustc_typeck/src/check/method/probe.rs b/compiler/rustc_typeck/src/check/method/probe.rs index c429e0f165370..876c575781cf6 100644 --- a/compiler/rustc_typeck/src/check/method/probe.rs +++ b/compiler/rustc_typeck/src/check/method/probe.rs @@ -1246,9 +1246,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { return None; } - let ty = match self_ty.kind() { - &ty::RawPtr(ty::TypeAndMut { ty, mutbl: hir::Mutability::Mut }) => ty, - _ => return None, + let &ty::RawPtr(ty::TypeAndMut { ty, mutbl: hir::Mutability::Mut }) = self_ty.kind() else { + return None; }; let const_self_ty = ty::TypeAndMut { ty, mutbl: hir::Mutability::Not }; diff --git a/compiler/rustc_typeck/src/check/method/suggest.rs b/compiler/rustc_typeck/src/check/method/suggest.rs index a523ba286ec84..cbbb47ecaae1c 100644 --- a/compiler/rustc_typeck/src/check/method/suggest.rs +++ b/compiler/rustc_typeck/src/check/method/suggest.rs @@ -37,9 +37,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ty::Closure(..) | ty::FnDef(..) | ty::FnPtr(_) => true, // If it's not a simple function, look for things which implement `FnOnce`. _ => { - let fn_once = match tcx.lang_items().require(LangItem::FnOnce) { - Ok(fn_once) => fn_once, - Err(..) => return false, + let Some(fn_once) = tcx.lang_items().fn_once_trait() else { + return false; }; // This conditional prevents us from asking to call errors and unresolved types. @@ -112,12 +111,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { CandidateSource::ImplSource(impl_did) => { // Provide the best span we can. Use the item, if local to crate, else // the impl, if local to crate (item may be defaulted), else nothing. - let item = match self.associated_value(impl_did, item_name).or_else(|| { + let Some(item) = self.associated_value(impl_did, item_name).or_else(|| { let impl_trait_ref = self.tcx.impl_trait_ref(impl_did)?; self.associated_value(impl_trait_ref.def_id, item_name) - }) { - Some(item) => item, - None => continue, + }) else { + continue; }; let note_span = self .tcx @@ -194,10 +192,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } CandidateSource::TraitSource(trait_did) => { - let item = match self.associated_value(trait_did, item_name) { - Some(item) => item, - None => continue, - }; + let Some(item) = self.associated_value(trait_did, item_name) else { continue }; let item_span = self .tcx .sess @@ -1202,10 +1197,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut derives = Vec::<(String, Span, String)>::new(); let mut traits = Vec::::new(); for (pred, _, _) in unsatisfied_predicates { - let trait_pred = match pred.kind().skip_binder() { - ty::PredicateKind::Trait(trait_pred) => trait_pred, - _ => continue, - }; + let ty::PredicateKind::Trait(trait_pred) = pred.kind().skip_binder() else { continue }; let adt = match trait_pred.self_ty().ty_adt_def() { Some(adt) if adt.did.is_local() => adt, _ => continue, @@ -1354,7 +1346,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let additional_newline = if found_use { "" } else { "\n" }; format!( "use {};\n{}", - with_crate_prefix(|| self.tcx.def_path_str(*trait_did)), + with_crate_prefix!(self.tcx.def_path_str(*trait_did)), additional_newline ) }); @@ -1367,7 +1359,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let additional_newline = if found_use { "" } else { "\n" }; format!( "use {}::*; // trait {}\n{}", - with_crate_prefix(|| self.tcx.def_path_str(*parent_did)), + with_crate_prefix!(self.tcx.def_path_str(*parent_did)), self.tcx.item_name(*trait_did), additional_newline ) @@ -1386,12 +1378,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { msg.push_str(&format!( "\ncandidate #{}: `use {};`", i + 1, - with_crate_prefix(|| self.tcx.def_path_str(*trait_did)) + with_crate_prefix!(self.tcx.def_path_str(*trait_did)) )); } else { msg.push_str(&format!( "\n`use {};`", - with_crate_prefix(|| self.tcx.def_path_str(*trait_did)) + with_crate_prefix!(self.tcx.def_path_str(*trait_did)) )); } } @@ -1404,13 +1396,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { msg.push_str(&format!( "\ncandidate #{}: `use {}::*; // trait {}`", candidates.len() + i + 1, - with_crate_prefix(|| self.tcx.def_path_str(*parent_did)), + with_crate_prefix!(self.tcx.def_path_str(*parent_did)), self.tcx.item_name(*trait_did), )); } else { msg.push_str(&format!( "\n`use {}::*; // trait {}`", - with_crate_prefix(|| self.tcx.def_path_str(*parent_did)), + with_crate_prefix!(self.tcx.def_path_str(*parent_did)), self.tcx.item_name(*trait_did), )); } @@ -1450,7 +1442,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let Some(did) = edition_fix { err.note(&format!( "'{}' is included in the prelude starting in Edition 2021", - with_crate_prefix(|| self.tcx.def_path_str(did)) + with_crate_prefix!(self.tcx.def_path_str(did)) )); } diff --git a/compiler/rustc_typeck/src/check/pat.rs b/compiler/rustc_typeck/src/check/pat.rs index e034adde1be86..77ab1d1de4211 100644 --- a/compiler/rustc_typeck/src/check/pat.rs +++ b/compiler/rustc_typeck/src/check/pat.rs @@ -9,7 +9,6 @@ use rustc_hir::pat_util::EnumerateAndAdjustIterator; use rustc_hir::{HirId, Pat, PatKind}; use rustc_infer::infer; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; -use rustc_middle::ty::subst::GenericArg; use rustc_middle::ty::{self, Adt, BindingMode, Ty, TypeFoldable}; use rustc_session::lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS; use rustc_span::hygiene::DesugaringKind; @@ -981,9 +980,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if subpats.len() == variant.fields.len() || subpats.len() < variant.fields.len() && ddpos.is_some() { - let substs = match pat_ty.kind() { - ty::Adt(_, substs) => substs, - _ => bug!("unexpected pattern type {:?}", pat_ty), + let ty::Adt(_, substs) = pat_ty.kind() else { + bug!("unexpected pattern type {:?}", pat_ty); }; for (i, subpat) in subpats.iter().enumerate_and_adjust(variant.fields.len(), ddpos) { let field_ty = self.field_ty(subpat.span, &variant.fields[i], substs); @@ -1073,7 +1071,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { (ty::Adt(_, substs), [field], false) => { let field_ty = self.field_ty(pat_span, field, substs); match field_ty.kind() { - ty::Tuple(_) => field_ty.tuple_fields().count() == subpats.len(), + ty::Tuple(fields) => fields.len() == subpats.len(), _ => false, } } @@ -1184,13 +1182,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let max_len = cmp::max(expected_len, elements.len()); let element_tys_iter = (0..max_len).map(|_| { - GenericArg::from(self.next_ty_var( + self.next_ty_var( // FIXME: `MiscVariable` for now -- obtaining the span and name information // from all tuple elements isn't trivial. TypeVariableOrigin { kind: TypeVariableOriginKind::TypeInference, span }, - )) + ) }); - let element_tys = tcx.mk_substs(element_tys_iter); + let element_tys = tcx.mk_type_list(element_tys_iter); let pat_ty = tcx.mk_ty(ty::Tuple(element_tys)); if let Some(mut err) = self.demand_eqtype_pat_diag(span, expected, pat_ty, ti) { err.emit(); @@ -1203,7 +1201,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { tcx.mk_tup(element_tys_iter) } else { for (i, elem) in elements.iter().enumerate_and_adjust(max_len, ddpos) { - self.check_pat(elem, element_tys[i].expect_ty(), def_bm, ti); + self.check_pat(elem, element_tys[i], def_bm, ti); } pat_ty } @@ -1221,9 +1219,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) -> bool { let tcx = self.tcx; - let (substs, adt) = match adt_ty.kind() { - ty::Adt(adt, substs) => (substs, adt), - _ => span_bug!(pat.span, "struct pattern is not an ADT"), + let ty::Adt(adt, substs) = adt_ty.kind() else { + span_bug!(pat.span, "struct pattern is not an ADT"); }; // Index the struct fields' types. diff --git a/compiler/rustc_typeck/src/check/upvar.rs b/compiler/rustc_typeck/src/check/upvar.rs index 949d857bff462..257846324b888 100644 --- a/compiler/rustc_typeck/src/check/upvar.rs +++ b/compiler/rustc_typeck/src/check/upvar.rs @@ -533,19 +533,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { base => bug!("Expected upvar, found={:?}", base), }; - let min_cap_list = match root_var_min_capture_list.get_mut(&var_hir_id) { - None => { - let mutability = self.determine_capture_mutability(&typeck_results, &place); - let min_cap_list = vec![ty::CapturedPlace { - place, - info: capture_info, - mutability, - region: None, - }]; - root_var_min_capture_list.insert(var_hir_id, min_cap_list); - continue; - } - Some(min_cap_list) => min_cap_list, + let Some(min_cap_list) = root_var_min_capture_list.get_mut(&var_hir_id) else { + let mutability = self.determine_capture_mutability(&typeck_results, &place); + let min_cap_list = vec![ty::CapturedPlace { + place, + info: capture_info, + mutability, + region: None, + }]; + root_var_min_capture_list.insert(var_hir_id, min_cap_list); + continue; }; // Go through each entry in the current list of min_captures @@ -1451,7 +1448,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) } - ty::Tuple(..) => { + ty::Tuple(fields) => { // Only Field projections can be applied to a tuple. assert!( captured_by_move_projs.iter().all(|projs| matches!( @@ -1460,7 +1457,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { )) ); - base_path_ty.tuple_fields().enumerate().any(|(i, element_ty)| { + fields.iter().enumerate().any(|(i, element_ty)| { let paths_using_field = captured_by_move_projs .iter() .filter_map(|projs| { diff --git a/compiler/rustc_typeck/src/coherence/inherent_impls.rs b/compiler/rustc_typeck/src/coherence/inherent_impls.rs index f4e5cce0129c9..78e5499740301 100644 --- a/compiler/rustc_typeck/src/coherence/inherent_impls.rs +++ b/compiler/rustc_typeck/src/coherence/inherent_impls.rs @@ -40,11 +40,8 @@ struct InherentCollect<'tcx> { impl<'tcx> ItemLikeVisitor<'_> for InherentCollect<'tcx> { fn visit_item(&mut self, item: &hir::Item<'_>) { - let (ty, assoc_items) = match item.kind { - hir::ItemKind::Impl(hir::Impl { of_trait: None, ref self_ty, items, .. }) => { - (self_ty, items) - } - _ => return, + let hir::ItemKind::Impl(hir::Impl { of_trait: None, self_ty: ty, items: assoc_items, .. }) = item.kind else { + return; }; let self_ty = self.tcx.type_of(item.def_id); diff --git a/compiler/rustc_typeck/src/coherence/orphan.rs b/compiler/rustc_typeck/src/coherence/orphan.rs index 9bb3100379655..54fffeb3cdaa6 100644 --- a/compiler/rustc_typeck/src/coherence/orphan.rs +++ b/compiler/rustc_typeck/src/coherence/orphan.rs @@ -38,9 +38,8 @@ fn orphan_check_impl(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), ErrorRep let trait_def_id = trait_ref.def_id; let item = tcx.hir().item(hir::ItemId { def_id }); - let impl_ = match item.kind { - hir::ItemKind::Impl(ref impl_) => impl_, - _ => bug!("{:?} is not an impl: {:?}", def_id, item), + let hir::ItemKind::Impl(ref impl_) = item.kind else { + bug!("{:?} is not an impl: {:?}", def_id, item); }; let sp = tcx.sess.source_map().guess_head_span(item.span); let tr = impl_.of_trait.as_ref().unwrap(); diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index 18f54eb2246bc..19b3d35566b24 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -1,4 +1,3 @@ -// ignore-tidy-filelength //! "Collection" is the process of determining the type and other external //! details of each item in Rust. Collection is specifically concerned //! with *inter-procedural* things -- for example, for a function @@ -1018,9 +1017,8 @@ fn adt_def(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::AdtDef { let def_id = def_id.expect_local(); let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); - let item = match tcx.hir().get(hir_id) { - Node::Item(item) => item, - _ => bug!(), + let Node::Item(item) = tcx.hir().get(hir_id) else { + bug!(); }; let repr = ReprOptions::new(tcx, def_id.to_def_id()); @@ -1122,9 +1120,8 @@ fn super_predicates_that_define_assoc_type( debug!("super_predicates_that_define_assoc_type: local trait_def_id={:?}", trait_def_id); let trait_hir_id = tcx.hir().local_def_id_to_hir_id(trait_def_id.expect_local()); - let item = match tcx.hir().get(trait_hir_id) { - Node::Item(item) => item, - _ => bug!("trait_node_id {} is not an item", trait_hir_id), + let Node::Item(item) = tcx.hir().get(trait_hir_id) else { + bug!("trait_node_id {} is not an item", trait_hir_id); }; let (generics, bounds) = match item.kind { @@ -2637,10 +2634,7 @@ fn from_target_feature( supported_target_features: &FxHashMap>, target_features: &mut Vec, ) { - let list = match attr.meta_item_list() { - Some(list) => list, - None => return, - }; + let Some(list) = attr.meta_item_list() else { return }; let bad_item = |span| { let msg = "malformed `target_feature` attribute input"; let code = "enable = \"..\"".to_owned(); @@ -2658,35 +2652,29 @@ fn from_target_feature( } // Must be of the form `enable = "..."` (a string). - let value = match item.value_str() { - Some(value) => value, - None => { - bad_item(item.span()); - continue; - } + let Some(value) = item.value_str() else { + bad_item(item.span()); + continue; }; // We allow comma separation to enable multiple features. target_features.extend(value.as_str().split(',').filter_map(|feature| { - let feature_gate = match supported_target_features.get(feature) { - Some(g) => g, - None => { - let msg = - format!("the feature named `{}` is not valid for this target", feature); - let mut err = tcx.sess.struct_span_err(item.span(), &msg); - err.span_label( - item.span(), - format!("`{}` is not valid for this target", feature), - ); - if let Some(stripped) = feature.strip_prefix('+') { - let valid = supported_target_features.contains_key(stripped); - if valid { - err.help("consider removing the leading `+` in the feature name"); - } + let Some(feature_gate) = supported_target_features.get(feature) else { + let msg = + format!("the feature named `{}` is not valid for this target", feature); + let mut err = tcx.sess.struct_span_err(item.span(), &msg); + err.span_label( + item.span(), + format!("`{}` is not valid for this target", feature), + ); + if let Some(stripped) = feature.strip_prefix('+') { + let valid = supported_target_features.contains_key(stripped); + if valid { + err.help("consider removing the leading `+` in the feature name"); } - err.emit(); - return None; } + err.emit(); + return None; }; // Only allow features whose feature gates have been enabled. diff --git a/compiler/rustc_typeck/src/collect/item_bounds.rs b/compiler/rustc_typeck/src/collect/item_bounds.rs index 87a67c4a4e060..8801d0260bffc 100644 --- a/compiler/rustc_typeck/src/collect/item_bounds.rs +++ b/compiler/rustc_typeck/src/collect/item_bounds.rs @@ -59,7 +59,7 @@ fn opaque_type_bounds<'tcx>( ast_bounds: &'tcx [hir::GenericBound<'tcx>], span: Span, ) -> &'tcx [(ty::Predicate<'tcx>, Span)] { - ty::print::with_no_queries(|| { + ty::print::with_no_queries!({ let item_ty = tcx.mk_opaque(opaque_def_id, InternalSubsts::identity_for_item(tcx, opaque_def_id)); diff --git a/compiler/rustc_typeck/src/collect/type_of.rs b/compiler/rustc_typeck/src/collect/type_of.rs index cd7343a3211e3..39da7c82c4eec 100644 --- a/compiler/rustc_typeck/src/collect/type_of.rs +++ b/compiler/rustc_typeck/src/collect/type_of.rs @@ -1,7 +1,6 @@ use rustc_errors::{Applicability, ErrorReported, StashKey}; use rustc_hir as hir; -use rustc_hir::def::CtorOf; -use rustc_hir::def::{DefKind, Res}; +use rustc_hir::def::Res; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::intravisit; use rustc_hir::intravisit::Visitor; @@ -9,7 +8,7 @@ use rustc_hir::{HirId, Node}; use rustc_middle::hir::nested_filter; use rustc_middle::ty::subst::InternalSubsts; use rustc_middle::ty::util::IntTypeExt; -use rustc_middle::ty::{self, DefIdTree, Ty, TyCtxt, TypeFoldable, TypeFolder}; +use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeFolder}; use rustc_span::symbol::Ident; use rustc_span::{Span, DUMMY_SP}; @@ -198,38 +197,9 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option< // Try to use the segment resolution if it is valid, otherwise we // default to the path resolution. let res = segment.res.filter(|&r| r != Res::Err).unwrap_or(path.res); - let generics = match res { - Res::Def(DefKind::Ctor(CtorOf::Variant, _), def_id) => tcx - .generics_of(tcx.parent(def_id).and_then(|def_id| tcx.parent(def_id)).unwrap()), - Res::Def(DefKind::Variant | DefKind::Ctor(CtorOf::Struct, _), def_id) => { - tcx.generics_of(tcx.parent(def_id).unwrap()) - } - // Other `DefKind`s don't have generics and would ICE when calling - // `generics_of`. - Res::Def( - DefKind::Struct - | DefKind::Union - | DefKind::Enum - | DefKind::Trait - | DefKind::OpaqueTy - | DefKind::TyAlias - | DefKind::ForeignTy - | DefKind::TraitAlias - | DefKind::AssocTy - | DefKind::Fn - | DefKind::AssocFn - | DefKind::AssocConst - | DefKind::Impl, - def_id, - ) => tcx.generics_of(def_id), - Res::Err => { - tcx.sess.delay_span_bug(tcx.def_span(def_id), "anon const with Res::Err"); - return None; - } - _ => { - // If the user tries to specify generics on a type that does not take them, - // e.g. `usize`, we may hit this branch, in which case we treat it as if - // no arguments have been passed. An error should already have been emitted. + let generics = match tcx.res_generics_def_id(res) { + Some(def_id) => tcx.generics_of(def_id), + None => { tcx.sess.delay_span_bug( tcx.def_span(def_id), &format!("unexpected anon const res {:?} in path: {:?}", res, path), diff --git a/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs b/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs index 92f88a15ee416..78097e3697fb9 100644 --- a/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs +++ b/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs @@ -164,12 +164,9 @@ fn get_impl_substs<'tcx>( // Conservatively use an empty `ParamEnv`. let outlives_env = OutlivesEnvironment::new(ty::ParamEnv::empty()); infcx.resolve_regions_and_report_errors(impl1_def_id, &outlives_env, RegionckMode::default()); - let impl2_substs = match infcx.fully_resolve(impl2_substs) { - Ok(s) => s, - Err(_) => { - tcx.sess.struct_span_err(span, "could not resolve substs on overridden impl").emit(); - return None; - } + let Ok(impl2_substs) = infcx.fully_resolve(impl2_substs) else { + tcx.sess.struct_span_err(span, "could not resolve substs on overridden impl").emit(); + return None; }; Some((impl1_substs, impl2_substs)) } diff --git a/compiler/rustc_typeck/src/mem_categorization.rs b/compiler/rustc_typeck/src/mem_categorization.rs index 1bbd6d29294a6..876b1ae72ad96 100644 --- a/compiler/rustc_typeck/src/mem_categorization.rs +++ b/compiler/rustc_typeck/src/mem_categorization.rs @@ -484,9 +484,8 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { let place_ty = self.expr_ty(expr)?; let base_ty = self.expr_ty_adjusted(base)?; - let (region, mutbl) = match *base_ty.kind() { - ty::Ref(region, _, mutbl) => (region, mutbl), - _ => span_bug!(expr.span, "cat_overloaded_place: base is not a reference"), + let ty::Ref(region, _, mutbl) = *base_ty.kind() else { + span_bug!(expr.span, "cat_overloaded_place: base is not a reference"); }; let ref_ty = self.tcx().mk_ref(region, ty::TypeAndMut { ty: place_ty, mutbl }); @@ -544,14 +543,11 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { ) -> McResult { let res = self.typeck_results.qpath_res(qpath, pat_hir_id); let ty = self.typeck_results.node_type(pat_hir_id); - let adt_def = match ty.kind() { - ty::Adt(adt_def, _) => adt_def, - _ => { - self.tcx() - .sess - .delay_span_bug(span, "struct or tuple struct pattern not applied to an ADT"); - return Err(()); - } + let ty::Adt(adt_def, _) = ty.kind() else { + self.tcx() + .sess + .delay_span_bug(span, "struct or tuple struct pattern not applied to an ADT"); + return Err(()); }; match res { @@ -744,12 +740,9 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { } PatKind::Slice(before, ref slice, after) => { - let element_ty = match place_with_id.place.ty().builtin_index() { - Some(ty) => ty, - None => { - debug!("explicit index of non-indexable type {:?}", place_with_id); - return Err(()); - } + let Some(element_ty) = place_with_id.place.ty().builtin_index() else { + debug!("explicit index of non-indexable type {:?}", place_with_id); + return Err(()); }; let elt_place = self.cat_projection( pat, diff --git a/compiler/rustc_typeck/src/outlives/outlives_bounds.rs b/compiler/rustc_typeck/src/outlives/outlives_bounds.rs index 91727d57ddf4e..435df9c00f466 100644 --- a/compiler/rustc_typeck/src/outlives/outlives_bounds.rs +++ b/compiler/rustc_typeck/src/outlives/outlives_bounds.rs @@ -71,12 +71,9 @@ impl<'cx, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'cx, 'tcx> { result, ); debug!("implied_outlives_bounds for {:?}: {:#?}", ty, result); - let result = match result { - Ok(v) => v, - Err(_) => { - self.tcx.sess.delay_span_bug(span, "implied_outlives_bounds failed to instantiate"); - return vec![]; - } + let Ok(result) = result else { + self.tcx.sess.delay_span_bug(span, "implied_outlives_bounds failed to instantiate"); + return vec![]; }; // Instantiation may have produced new inference variables and constraints on those diff --git a/compiler/rustc_typeck/src/variance/constraints.rs b/compiler/rustc_typeck/src/variance/constraints.rs index 1c8f848cf2893..196e476b0e37a 100644 --- a/compiler/rustc_typeck/src/variance/constraints.rs +++ b/compiler/rustc_typeck/src/variance/constraints.rs @@ -278,7 +278,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { ty::Tuple(subtys) => { for subty in subtys { - self.add_constraints_from_ty(current, subty.expect_ty(), variance); + self.add_constraints_from_ty(current, subty, variance); } } diff --git a/library/alloc/src/collections/binary_heap.rs b/library/alloc/src/collections/binary_heap.rs index 56a4700181199..e18cd8cd46427 100644 --- a/library/alloc/src/collections/binary_heap.rs +++ b/library/alloc/src/collections/binary_heap.rs @@ -746,9 +746,12 @@ impl BinaryHeap { self.rebuild_tail(start); } - /// Returns an iterator which retrieves elements in heap order. - /// The retrieved elements are removed from the original heap. - /// The remaining elements will be removed on drop in heap order. + /// Clears the binary heap, returning an iterator over the removed elements + /// in heap order. If the iterator is dropped before being fully consumed, + /// it drops the remaining elements in heap order. + /// + /// The returned iterator keeps a mutable borrow on the heap to optimize + /// its implementation. /// /// Note: /// * `.drain_sorted()` is *O*(*n* \* log(*n*)); much slower than `.drain()`. @@ -1158,9 +1161,12 @@ impl BinaryHeap { self.len() == 0 } - /// Clears the binary heap, returning an iterator over the removed elements. + /// Clears the binary heap, returning an iterator over the removed elements + /// in arbitrary order. If the iterator is dropped before being fully + /// consumed, it drops the remaining elements in arbitrary order. /// - /// The elements are removed in arbitrary order. + /// The returned iterator keeps a mutable borrow on the heap to optimize + /// its implementation. /// /// # Examples /// diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs index 763175fc0451f..7139a0fb94d76 100644 --- a/library/alloc/src/collections/vec_deque/mod.rs +++ b/library/alloc/src/collections/vec_deque/mod.rs @@ -1215,21 +1215,25 @@ impl VecDeque { unsafe { IterMut::new(ring, tail, head, PhantomData) } } - /// Creates a draining iterator that removes the specified range in the - /// deque and yields the removed items. + /// Removes the specified range from the deque in bulk, returning all + /// removed elements as an iterator. If the iterator is dropped before + /// being fully consumed, it drops the remaining removed elements. /// - /// Note 1: The element range is removed even if the iterator is not - /// consumed until the end. + /// The returned iterator keeps a mutable borrow on the queue to optimize + /// its implementation. /// - /// Note 2: It is unspecified how many elements are removed from the deque, - /// if the `Drain` value is not dropped, but the borrow it holds expires - /// (e.g., due to `mem::forget`). /// /// # Panics /// /// Panics if the starting point is greater than the end point or if /// the end point is greater than the length of the deque. /// + /// # Leaking + /// + /// If the returned iterator goes out of scope without being dropped (due to + /// [`mem::forget`], for example), the deque may have lost and leaked + /// elements arbitrarily, including elements outside the range. + /// /// # Examples /// /// ``` @@ -1240,7 +1244,7 @@ impl VecDeque { /// assert_eq!(drained, [3]); /// assert_eq!(deque, [1, 2]); /// - /// // A full range clears all contents + /// // A full range clears all contents, like `clear()` does /// deque.drain(..); /// assert!(deque.is_empty()); /// ``` diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs index 7c0faf0659a2c..716bb4983a651 100644 --- a/library/alloc/src/string.rs +++ b/library/alloc/src/string.rs @@ -1628,17 +1628,24 @@ impl String { self.vec.clear() } - /// Creates a draining iterator that removes the specified range in the `String` - /// and yields the removed `chars`. + /// Removes the specified range from the string in bulk, returning all + /// removed characters as an iterator. /// - /// Note: The element range is removed even if the iterator is not - /// consumed until the end. + /// The returned iterator keeps a mutable borrow on the string to optimize + /// its implementation. /// /// # Panics /// /// Panics if the starting point or end point do not lie on a [`char`] /// boundary, or if they're out of bounds. /// + /// # Leaking + /// + /// If the returned iterator goes out of scope without being dropped (due to + /// [`core::mem::forget`], for example), the string may still contain a copy + /// of any drained characters, or may have lost characters arbitrarily, + /// including characters outside the range. + /// /// # Examples /// /// Basic usage: @@ -1652,7 +1659,7 @@ impl String { /// assert_eq!(t, "α is alpha, "); /// assert_eq!(s, "β is beta"); /// - /// // A full range clears the string + /// // A full range clears the string, like `clear()` does /// s.drain(..); /// assert_eq!(s, ""); /// ``` diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 3dc3eee4133b6..c29aa0fec5b87 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -1799,19 +1799,24 @@ impl Vec { self.len += count; } - /// Creates a draining iterator that removes the specified range in the vector - /// and yields the removed items. + /// Removes the specified range from the vector in bulk, returning all + /// removed elements as an iterator. If the iterator is dropped before + /// being fully consumed, it drops the remaining removed elements. /// - /// When the iterator **is** dropped, all elements in the range are removed - /// from the vector, even if the iterator was not fully consumed. If the - /// iterator **is not** dropped (with [`mem::forget`] for example), it is - /// unspecified how many elements are removed. + /// The returned iterator keeps a mutable borrow on the vector to optimize + /// its implementation. /// /// # Panics /// /// Panics if the starting point is greater than the end point or if /// the end point is greater than the length of the vector. /// + /// # Leaking + /// + /// If the returned iterator goes out of scope without being dropped (due to + /// [`mem::forget`], for example), the vector may have lost and leaked + /// elements arbitrarily, including elements outside the range. + /// /// # Examples /// /// ``` @@ -1820,7 +1825,7 @@ impl Vec { /// assert_eq!(v, &[1]); /// assert_eq!(u, &[2, 3]); /// - /// // A full range clears the vector + /// // A full range clears the vector, like `clear()` does /// v.drain(..); /// assert_eq!(v, &[]); /// ``` diff --git a/library/core/src/char/convert.rs b/library/core/src/char/convert.rs index 1774ddd7cbb2c..139841368d6a1 100644 --- a/library/core/src/char/convert.rs +++ b/library/core/src/char/convert.rs @@ -6,8 +6,6 @@ use crate::fmt; use crate::mem::transmute; use crate::str::FromStr; -use super::MAX; - /// Converts a `u32` to a `char`. /// /// Note that all [`char`]s are valid [`u32`]s, and can be cast to one with @@ -271,7 +269,20 @@ impl FromStr for char { #[inline] const fn char_try_from_u32(i: u32) -> Result { - if (i > MAX as u32) || (i >= 0xD800 && i <= 0xDFFF) { + // This is an optimized version of the check + // (i > MAX as u32) || (i >= 0xD800 && i <= 0xDFFF), + // which can also be written as + // i >= 0x110000 || (i >= 0xD800 && i < 0xE000). + // + // The XOR with 0xD800 permutes the ranges such that 0xD800..0xE000 is + // mapped to 0x0000..0x0800, while keeping all the high bits outside 0xFFFF the same. + // In particular, numbers >= 0x110000 stay in this range. + // + // Subtracting 0x800 causes 0x0000..0x0800 to wrap, meaning that a single + // unsigned comparison against 0x110000 - 0x800 will detect both the wrapped + // surrogate range as well as the numbers originally larger than 0x110000. + // + if (i ^ 0xD800).wrapping_sub(0x800) >= 0x110000 - 0x800 { Err(CharTryFromError(())) } else { // SAFETY: checked that it's a legal unicode value diff --git a/library/core/src/future/future.rs b/library/core/src/future/future.rs index 6b62236b32faf..f29d3e1e98b72 100644 --- a/library/core/src/future/future.rs +++ b/library/core/src/future/future.rs @@ -5,7 +5,7 @@ use crate::ops; use crate::pin::Pin; use crate::task::{Context, Poll}; -/// A future represents an asynchronous computation. +/// A future represents an asynchronous computation obtained by use of [`async`]. /// /// A future is a value that might not have finished computing yet. This kind of /// "asynchronous value" makes it possible for a thread to continue doing useful @@ -23,6 +23,7 @@ use crate::task::{Context, Poll}; /// When using a future, you generally won't call `poll` directly, but instead /// `.await` the value. /// +/// [`async`]: ../../std/keyword.async.html /// [`Waker`]: crate::task::Waker #[doc(notable_trait)] #[must_use = "futures do nothing unless you `.await` or poll them"] diff --git a/library/core/src/future/mod.rs b/library/core/src/future/mod.rs index 88db584aefd08..9b89f766c67bf 100644 --- a/library/core/src/future/mod.rs +++ b/library/core/src/future/mod.rs @@ -1,6 +1,13 @@ #![stable(feature = "futures_api", since = "1.36.0")] -//! Asynchronous values. +//! Asynchronous basic functionality. +//! +//! Please see the fundamental [`async`] and [`await`] keywords and the [async book] +//! for more information on asynchronous programming in Rust. +//! +//! [`async`]: ../../std/keyword.async.html +//! [`await`]: ../../std/keyword.await.html +//! [async book]: https://rust-lang.github.io/async-book/ use crate::{ ops::{Generator, GeneratorState}, diff --git a/library/core/src/panicking.rs b/library/core/src/panicking.rs index 0798076411ac4..2b720fc4192a7 100644 --- a/library/core/src/panicking.rs +++ b/library/core/src/panicking.rs @@ -87,8 +87,7 @@ fn panic_bounds_check(index: usize, len: usize) -> ! { #[cfg(not(bootstrap))] #[cold] -#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))] -#[track_caller] +#[inline(never)] #[lang = "panic_no_unwind"] // needed by codegen for panic in nounwind function fn panic_no_unwind() -> ! { if cfg!(feature = "panic_immediate_abort") { diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs index dec1b5270d58b..e2b0e90e2bf7d 100644 --- a/library/core/src/pin.rs +++ b/library/core/src/pin.rs @@ -805,7 +805,7 @@ impl Pin<&'static T> { /// /// This is safe, because `T` is borrowed for the `'static` lifetime, which /// never ends. - #[unstable(feature = "pin_static_ref", issue = "78186")] + #[stable(feature = "pin_static_ref", since = "1.61.0")] #[rustc_const_unstable(feature = "const_pin", issue = "76654")] pub const fn static_ref(r: &'static T) -> Pin<&'static T> { // SAFETY: The 'static borrow guarantees the data will not be @@ -858,7 +858,7 @@ impl Pin<&'static mut T> { /// /// This is safe, because `T` is borrowed for the `'static` lifetime, which /// never ends. - #[unstable(feature = "pin_static_ref", issue = "78186")] + #[stable(feature = "pin_static_ref", since = "1.61.0")] #[rustc_const_unstable(feature = "const_pin", issue = "76654")] pub const fn static_mut(r: &'static mut T) -> Pin<&'static mut T> { // SAFETY: The 'static borrow guarantees the data will not be diff --git a/library/core/src/slice/ascii.rs b/library/core/src/slice/ascii.rs index 304ba7ee5544f..1dba24dd14907 100644 --- a/library/core/src/slice/ascii.rs +++ b/library/core/src/slice/ascii.rs @@ -79,6 +79,84 @@ impl [u8] { pub fn escape_ascii(&self) -> EscapeAscii<'_> { EscapeAscii { inner: self.iter().flat_map(EscapeByte) } } + + /// Returns a byte slice with leading ASCII whitespace bytes removed. + /// + /// 'Whitespace' refers to the definition used by + /// `u8::is_ascii_whitespace`. + /// + /// # Examples + /// + /// ``` + /// #![feature(byte_slice_trim_ascii)] + /// + /// assert_eq!(b" \t hello world\n".trim_ascii_start(), b"hello world\n"); + /// assert_eq!(b" ".trim_ascii_start(), b""); + /// assert_eq!(b"".trim_ascii_start(), b""); + /// ``` + #[unstable(feature = "byte_slice_trim_ascii", issue = "94035")] + pub const fn trim_ascii_start(&self) -> &[u8] { + let mut bytes = self; + // Note: A pattern matching based approach (instead of indexing) allows + // making the function const. + while let [first, rest @ ..] = bytes { + if first.is_ascii_whitespace() { + bytes = rest; + } else { + break; + } + } + bytes + } + + /// Returns a byte slice with trailing ASCII whitespace bytes removed. + /// + /// 'Whitespace' refers to the definition used by + /// `u8::is_ascii_whitespace`. + /// + /// # Examples + /// + /// ``` + /// #![feature(byte_slice_trim_ascii)] + /// + /// assert_eq!(b"\r hello world\n ".trim_ascii_end(), b"\r hello world"); + /// assert_eq!(b" ".trim_ascii_end(), b""); + /// assert_eq!(b"".trim_ascii_end(), b""); + /// ``` + #[unstable(feature = "byte_slice_trim_ascii", issue = "94035")] + pub const fn trim_ascii_end(&self) -> &[u8] { + let mut bytes = self; + // Note: A pattern matching based approach (instead of indexing) allows + // making the function const. + while let [rest @ .., last] = bytes { + if last.is_ascii_whitespace() { + bytes = rest; + } else { + break; + } + } + bytes + } + + /// Returns a byte slice with leading and trailing ASCII whitespace bytes + /// removed. + /// + /// 'Whitespace' refers to the definition used by + /// `u8::is_ascii_whitespace`. + /// + /// # Examples + /// + /// ``` + /// #![feature(byte_slice_trim_ascii)] + /// + /// assert_eq!(b"\r hello world\n ".trim_ascii(), b"hello world"); + /// assert_eq!(b" ".trim_ascii(), b""); + /// assert_eq!(b"".trim_ascii(), b""); + /// ``` + #[unstable(feature = "byte_slice_trim_ascii", issue = "94035")] + pub const fn trim_ascii(&self) -> &[u8] { + self.trim_ascii_start().trim_ascii_end() + } } impl_fn_for_zst! { diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index 32f3405243cea..06c7be054a038 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -6,7 +6,7 @@ #![feature(bool_to_option)] #![feature(box_syntax)] #![feature(cell_update)] -#![feature(cfg_panic)] +#![cfg_attr(bootstrap, feature(cfg_panic))] #![cfg_attr(bootstrap, feature(cfg_target_has_atomic))] #![feature(const_assume)] #![feature(const_black_box)] diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index 146096535dbbe..dd9b035e86df1 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -41,8 +41,8 @@ dlmalloc = { version = "0.2.3", features = ['rustc-dep-of-std'] } [target.x86_64-fortanix-unknown-sgx.dependencies] fortanix-sgx-abi = { version = "0.3.2", features = ['rustc-dep-of-std'] } -[target.'cfg(all(any(target_arch = "x86_64", target_arch = "aarch64"), target_os = "hermit"))'.dependencies] -hermit-abi = { version = "0.1.19", features = ['rustc-dep-of-std'] } +[target.'cfg(target_os = "hermit")'.dependencies] +hermit-abi = { version = "0.2.0", features = ['rustc-dep-of-std'] } [target.wasm32-wasi.dependencies] wasi = { version = "0.11.0", features = ['rustc-dep-of-std'], default-features = false } diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs index 9e61defc31e97..53b43455b5a61 100644 --- a/library/std/src/collections/hash/map.rs +++ b/library/std/src/collections/hash/map.rs @@ -547,6 +547,10 @@ impl HashMap { /// Clears the map, returning all key-value pairs as an iterator. Keeps the /// allocated memory for reuse. /// + /// If the returned iterator is dropped before being fully consumed, it + /// drops the remaining key-value pairs. The returned iterator keeps a + /// mutable borrow on the vector to optimize its implementation. + /// /// # Examples /// /// ``` @@ -2472,6 +2476,7 @@ impl<'a, K, V> Entry<'a, K, V> { /// # Examples /// /// ``` + /// #![feature(entry_insert)] /// use std::collections::HashMap; /// /// let mut map: HashMap<&str, String> = HashMap::new(); @@ -2480,7 +2485,7 @@ impl<'a, K, V> Entry<'a, K, V> { /// assert_eq!(entry.key(), &"poneyland"); /// ``` #[inline] - #[stable(feature = "entry_insert", since = "1.59.0")] + #[unstable(feature = "entry_insert", issue = "65225")] pub fn insert_entry(self, value: V) -> OccupiedEntry<'a, K, V> { match self { Occupied(mut entry) => { @@ -2814,6 +2819,7 @@ impl<'a, K: 'a, V: 'a> VacantEntry<'a, K, V> { /// # Examples /// /// ``` + /// #![feature(entry_insert)] /// use std::collections::HashMap; /// use std::collections::hash_map::Entry; /// @@ -2825,7 +2831,7 @@ impl<'a, K: 'a, V: 'a> VacantEntry<'a, K, V> { /// assert_eq!(map["poneyland"], 37); /// ``` #[inline] - #[stable(feature = "entry_insert", since = "1.59.0")] + #[unstable(feature = "entry_insert", issue = "65225")] pub fn insert_entry(self, value: V) -> OccupiedEntry<'a, K, V> { let base = self.base.insert_entry(value); OccupiedEntry { base } diff --git a/library/std/src/collections/hash/set.rs b/library/std/src/collections/hash/set.rs index d1450987e7374..200667ae39069 100644 --- a/library/std/src/collections/hash/set.rs +++ b/library/std/src/collections/hash/set.rs @@ -227,7 +227,12 @@ impl HashSet { self.base.is_empty() } - /// Clears the set, returning all elements in an iterator. + /// Clears the set, returning all elements as an iterator. Keeps the + /// allocated memory for reuse. + /// + /// If the returned iterator is dropped before being fully consumed, it + /// drops the remaining elements. The returned iterator keeps a mutable + /// borrow on the vector to optimize its implementation. /// /// # Examples /// diff --git a/library/std/src/ffi/c_str.rs b/library/std/src/ffi/c_str.rs index 6e70d5ca02d75..1678367290e51 100644 --- a/library/std/src/ffi/c_str.rs +++ b/library/std/src/ffi/c_str.rs @@ -382,7 +382,7 @@ impl CString { let bytes: Vec = self.into(); match memchr::memchr(0, &bytes) { Some(i) => Err(NulError(i, bytes)), - None => Ok(unsafe { CString::from_vec_unchecked(bytes) }), + None => Ok(unsafe { CString::_from_vec_unchecked(bytes) }), } } } @@ -405,7 +405,7 @@ impl CString { // This allows better optimizations if lto enabled. match memchr::memchr(0, bytes) { Some(i) => Err(NulError(i, buffer)), - None => Ok(unsafe { CString::from_vec_unchecked(buffer) }), + None => Ok(unsafe { CString::_from_vec_unchecked(buffer) }), } } @@ -451,10 +451,15 @@ impl CString { /// ``` #[must_use] #[stable(feature = "rust1", since = "1.0.0")] - pub unsafe fn from_vec_unchecked(mut v: Vec) -> CString { + pub unsafe fn from_vec_unchecked(v: Vec) -> Self { + debug_assert!(memchr::memchr(0, &v).is_none()); + unsafe { Self::_from_vec_unchecked(v) } + } + + unsafe fn _from_vec_unchecked(mut v: Vec) -> Self { v.reserve_exact(1); v.push(0); - CString { inner: v.into_boxed_slice() } + Self { inner: v.into_boxed_slice() } } /// Retakes ownership of a `CString` that was transferred to C via @@ -578,7 +583,7 @@ impl CString { pub fn into_string(self) -> Result { String::from_utf8(self.into_bytes()).map_err(|e| IntoStringError { error: e.utf8_error(), - inner: unsafe { CString::from_vec_unchecked(e.into_bytes()) }, + inner: unsafe { Self::_from_vec_unchecked(e.into_bytes()) }, }) } @@ -735,6 +740,11 @@ impl CString { #[must_use] #[stable(feature = "cstring_from_vec_with_nul", since = "1.58.0")] pub unsafe fn from_vec_with_nul_unchecked(v: Vec) -> Self { + debug_assert!(memchr::memchr(0, &v).unwrap() + 1 == v.len()); + unsafe { Self::_from_vec_with_nul_unchecked(v) } + } + + unsafe fn _from_vec_with_nul_unchecked(v: Vec) -> Self { Self { inner: v.into_boxed_slice() } } @@ -778,7 +788,7 @@ impl CString { Some(nul_pos) if nul_pos + 1 == v.len() => { // SAFETY: We know there is only one nul byte, at the end // of the vec. - Ok(unsafe { Self::from_vec_with_nul_unchecked(v) }) + Ok(unsafe { Self::_from_vec_with_nul_unchecked(v) }) } Some(nul_pos) => Err(FromVecWithNulError { error_kind: FromBytesWithNulErrorKind::InteriorNul(nul_pos), @@ -811,7 +821,7 @@ impl ops::Deref for CString { #[inline] fn deref(&self) -> &CStr { - unsafe { CStr::from_bytes_with_nul_unchecked(self.as_bytes_with_nul()) } + unsafe { CStr::_from_bytes_with_nul_unchecked(self.as_bytes_with_nul()) } } } @@ -928,7 +938,7 @@ impl From> for CString { }; // SAFETY: `v` cannot contain null bytes, given the type-level // invariant of `NonZeroU8`. - CString::from_vec_unchecked(v) + Self::_from_vec_unchecked(v) } } } @@ -1225,7 +1235,7 @@ impl CStr { unsafe { let len = sys::strlen(ptr); let ptr = ptr as *const u8; - CStr::from_bytes_with_nul_unchecked(slice::from_raw_parts(ptr, len as usize + 1)) + Self::_from_bytes_with_nul_unchecked(slice::from_raw_parts(ptr, len as usize + 1)) } } @@ -1268,7 +1278,7 @@ impl CStr { Some(nul_pos) if nul_pos + 1 == bytes.len() => { // SAFETY: We know there is only one nul byte, at the end // of the byte slice. - Ok(unsafe { Self::from_bytes_with_nul_unchecked(bytes) }) + Ok(unsafe { Self::_from_bytes_with_nul_unchecked(bytes) }) } Some(nul_pos) => Err(FromBytesWithNulError::interior_nul(nul_pos)), None => Err(FromBytesWithNulError::not_nul_terminated()), @@ -1297,12 +1307,19 @@ impl CStr { #[stable(feature = "cstr_from_bytes", since = "1.10.0")] #[rustc_const_stable(feature = "const_cstr_unchecked", since = "1.59.0")] pub const unsafe fn from_bytes_with_nul_unchecked(bytes: &[u8]) -> &CStr { + // We're in a const fn, so this is the best we can do + debug_assert!(!bytes.is_empty() && bytes[bytes.len() - 1] == 0); + unsafe { Self::_from_bytes_with_nul_unchecked(bytes) } + } + + #[inline] + const unsafe fn _from_bytes_with_nul_unchecked(bytes: &[u8]) -> &Self { // SAFETY: Casting to CStr is safe because its internal representation // is a [u8] too (safe only inside std). // Dereferencing the obtained pointer is safe because it comes from a // reference. Making a reference is then safe because its lifetime // is bound by the lifetime of the given `bytes`. - unsafe { &*(bytes as *const [u8] as *const CStr) } + unsafe { &*(bytes as *const [u8] as *const Self) } } /// Returns the inner pointer to this C string. @@ -1566,7 +1583,7 @@ impl ops::Index> for CStr { // byte, since otherwise we could get an empty string that doesn't end // in a null. if index.start < bytes.len() { - unsafe { CStr::from_bytes_with_nul_unchecked(&bytes[index.start..]) } + unsafe { CStr::_from_bytes_with_nul_unchecked(&bytes[index.start..]) } } else { panic!( "index out of bounds: the len is {} but the index is {}", diff --git a/library/std/src/ffi/c_str/tests.rs b/library/std/src/ffi/c_str/tests.rs index 4f7ba9ad43756..00ba5460821ff 100644 --- a/library/std/src/ffi/c_str/tests.rs +++ b/library/std/src/ffi/c_str/tests.rs @@ -32,14 +32,6 @@ fn build_with_zero2() { assert!(CString::new(vec![0]).is_err()); } -#[test] -fn build_with_zero3() { - unsafe { - let s = CString::from_vec_unchecked(vec![0]); - assert_eq!(s.as_bytes(), b"\0"); - } -} - #[test] fn formatted() { let s = CString::new(&b"abc\x01\x02\n\xE2\x80\xA6\xFF"[..]).unwrap(); diff --git a/library/std/src/keyword_docs.rs b/library/std/src/keyword_docs.rs index 35d230eee9627..5b76259afc11d 100644 --- a/library/std/src/keyword_docs.rs +++ b/library/std/src/keyword_docs.rs @@ -2203,17 +2203,18 @@ mod where_keyword {} /// /// Use `async` in front of `fn`, `closure`, or a `block` to turn the marked code into a `Future`. /// As such the code will not be run immediately, but will only be evaluated when the returned -/// future is `.await`ed. +/// future is [`.await`]ed. /// -/// We have written an [async book] detailing async/await and trade-offs compared to using threads. +/// We have written an [async book] detailing `async`/`await` and trade-offs compared to using threads. /// /// ## Editions /// /// `async` is a keyword from the 2018 edition onwards. /// -/// It is available for use in stable rust from version 1.39 onwards. +/// It is available for use in stable Rust from version 1.39 onwards. /// /// [`Future`]: future::Future +/// [`.await`]: ../std/keyword.await.html /// [async book]: https://rust-lang.github.io/async-book/ mod async_keyword {} @@ -2221,19 +2222,20 @@ mod async_keyword {} // /// Suspend execution until the result of a [`Future`] is ready. /// -/// `.await`ing a future will suspend the current function's execution until the `executor` +/// `.await`ing a future will suspend the current function's execution until the executor /// has run the future to completion. /// -/// Read the [async book] for details on how async/await and executors work. +/// Read the [async book] for details on how [`async`]/`await` and executors work. /// /// ## Editions /// /// `await` is a keyword from the 2018 edition onwards. /// -/// It is available for use in stable rust from version 1.39 onwards. +/// It is available for use in stable Rust from version 1.39 onwards. /// /// [`Future`]: future::Future /// [async book]: https://rust-lang.github.io/async-book/ +/// [`async`]: ../std/keyword.async.html mod await_keyword {} #[doc(keyword = "dyn")] diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 8c38db9b62cdc..5dc586d3a2adf 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -311,7 +311,6 @@ #![feature(panic_internals)] #![feature(panic_can_unwind)] #![feature(panic_unwind)] -#![feature(pin_static_ref)] #![feature(platform_intrinsics)] #![feature(portable_simd)] #![feature(prelude_import)] @@ -365,6 +364,11 @@ extern crate libc; #[allow(unused_extern_crates)] extern crate unwind; +#[doc(masked)] +#[allow(unused_extern_crates)] +#[cfg(feature = "miniz_oxide")] +extern crate miniz_oxide; + // During testing, this crate is not actually the "real" std library, but rather // it links to the real std library, which was compiled from this same source // code. So any lang items std defines are conditionally excluded (or else they diff --git a/library/std/src/sys/hermit/fd.rs b/library/std/src/sys/hermit/fd.rs index 1179a49c22fd0..c400f5f2c2e84 100644 --- a/library/std/src/sys/hermit/fd.rs +++ b/library/std/src/sys/hermit/fd.rs @@ -1,6 +1,6 @@ #![unstable(reason = "not public", issue = "none", feature = "fd")] -use crate::io::{self, Read, ReadBuf}; +use crate::io::{self, Read}; use crate::mem; use crate::sys::cvt; use crate::sys::hermit::abi; diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index e17de0ba49ebc..53226977fd881 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -17,7 +17,6 @@ use std::process::{exit, Command, Stdio}; use std::str; use build_helper::{output, t, up_to_date}; -use filetime::FileTime; use serde::Deserialize; use crate::builder::Cargo; @@ -1334,8 +1333,9 @@ pub fn run_cargo( .map(|s| s.starts_with('-') && s.ends_with(&extension[..])) .unwrap_or(false) }); - let max = candidates - .max_by_key(|&&(_, _, ref metadata)| FileTime::from_last_modification_time(metadata)); + let max = candidates.max_by_key(|&&(_, _, ref metadata)| { + metadata.modified().expect("mtime should be available on all relevant OSes") + }); let path_to_add = match max { Some(triple) => triple.0.to_str().unwrap(), None => panic!("no output generated for {:?} {:?}", prefix, extension), diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index 029049d543435..8693e85e4742f 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -2056,6 +2056,7 @@ impl Step for RustDev { "llvm-bcanalyzer", "llvm-cov", "llvm-dwp", + "llvm-nm", ] { tarball.add_file(src_bindir.join(exe(bin, target)), "bin", 0o755); } diff --git a/src/doc/unstable-book/src/language-features/cfg-panic.md b/src/doc/unstable-book/src/language-features/cfg-panic.md deleted file mode 100644 index f5b73128ad6c2..0000000000000 --- a/src/doc/unstable-book/src/language-features/cfg-panic.md +++ /dev/null @@ -1,38 +0,0 @@ -# `cfg_panic` - -The tracking issue for this feature is: [#77443] - -[#77443]: https://github.com/rust-lang/rust/issues/77443 - ------------------------- - -The `cfg_panic` feature makes it possible to execute different code -depending on the panic strategy. - -Possible values at the moment are `"unwind"` or `"abort"`, although -it is possible that new panic strategies may be added to Rust in the -future. - -## Examples - -```rust -#![feature(cfg_panic)] - -#[cfg(panic = "unwind")] -fn a() { - // ... -} - -#[cfg(not(panic = "unwind"))] -fn a() { - // ... -} - -fn b() { - if cfg!(panic = "abort") { - // ... - } else { - // ... - } -} -``` diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 187bc13357a90..76994f2ee1712 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1543,7 +1543,7 @@ impl<'tcx> Clean for Ty<'tcx> { DynTrait(bounds, lifetime) } - ty::Tuple(t) => Tuple(t.iter().map(|t| t.expect_ty().clean(cx)).collect()), + ty::Tuple(t) => Tuple(t.iter().map(|t| t.clean(cx)).collect()), ty::Projection(ref data) => data.clean(cx), diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index 1d312df1f7858..20eea32560b27 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -109,7 +109,7 @@ fn external_generic_args( if cx.tcx.fn_trait_kind_from_lang_item(did).is_some() { let inputs = match ty_kind.unwrap() { - ty::Tuple(tys) => tys.iter().map(|t| t.expect_ty().clean(cx)).collect(), + ty::Tuple(tys) => tys.iter().map(|t| t.clean(cx)).collect(), _ => return GenericArgs::AngleBracketed { args, bindings: bindings.into() }, }; let output = None; diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs index 2455d56bd2b3f..a7f852a432c82 100644 --- a/src/librustdoc/html/render/context.rs +++ b/src/librustdoc/html/render/context.rs @@ -250,6 +250,8 @@ impl<'tcx> Context<'tcx> { fn build_sidebar_items(&self, m: &clean::Module) -> BTreeMap> { // BTreeMap instead of HashMap to get a sorted output let mut map: BTreeMap<_, Vec<_>> = BTreeMap::new(); + let mut inserted: FxHashMap> = FxHashMap::default(); + for item in &m.items { if item.is_stripped() { continue; @@ -258,13 +260,16 @@ impl<'tcx> Context<'tcx> { let short = item.type_(); let myname = match item.name { None => continue, - Some(ref s) => s.to_string(), + Some(s) => s, }; - let short = short.to_string(); - map.entry(short).or_default().push(( - myname, - Some(item.doc_value().map_or_else(String::new, |s| plain_text_summary(&s))), - )); + if inserted.entry(short).or_default().insert(myname) { + let short = short.to_string(); + let myname = myname.to_string(); + map.entry(short).or_default().push(( + myname, + Some(item.doc_value().map_or_else(String::new, |s| plain_text_summary(&s))), + )); + } } if self.shared.sort_modules_alphabetically { diff --git a/src/librustdoc/json/mod.rs b/src/librustdoc/json/mod.rs index f9e9fe0d3cf20..52980e07b8ca3 100644 --- a/src/librustdoc/json/mod.rs +++ b/src/librustdoc/json/mod.rs @@ -8,6 +8,7 @@ mod conversions; use std::cell::RefCell; use std::fs::{create_dir_all, File}; +use std::io::{BufWriter, Write}; use std::path::PathBuf; use std::rc::Rc; @@ -213,7 +214,7 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> { let mut index = (*self.index).clone().into_inner(); index.extend(self.get_trait_items()); // This needs to be the default HashMap for compatibility with the public interface for - // rustdoc-json + // rustdoc-json-types #[allow(rustc::default_hash_types)] let output = types::Crate { root: types::Id(String::from("0:0")), @@ -263,8 +264,10 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> { let mut p = out_dir; p.push(output.index.get(&output.root).unwrap().name.clone().unwrap()); p.set_extension("json"); - let file = try_err!(File::create(&p), p); - serde_json::ser::to_writer(&file, &output).unwrap(); + let mut file = BufWriter::new(try_err!(File::create(&p), p)); + serde_json::ser::to_writer(&mut file, &output).unwrap(); + try_err!(file.flush(), p); + Ok(()) } diff --git a/src/librustdoc/passes/html_tags.rs b/src/librustdoc/passes/html_tags.rs index 9caadef3dec7c..f047f6bb1699b 100644 --- a/src/librustdoc/passes/html_tags.rs +++ b/src/librustdoc/passes/html_tags.rs @@ -5,7 +5,7 @@ use crate::core::DocContext; use crate::html::markdown::main_body_opts; use crate::visit::DocVisitor; -use pulldown_cmark::{Event, Parser, Tag}; +use pulldown_cmark::{BrokenLink, Event, LinkType, Parser, Tag}; use std::iter::Peekable; use std::ops::Range; @@ -249,7 +249,31 @@ impl<'a, 'tcx> DocVisitor for InvalidHtmlTagsLinter<'a, 'tcx> { let mut is_in_comment = None; let mut in_code_block = false; - let p = Parser::new_ext(&dox, main_body_opts()).into_offset_iter(); + let link_names = item.link_names(&self.cx.cache); + + let mut replacer = |broken_link: BrokenLink<'_>| { + if let Some(link) = + link_names.iter().find(|link| *link.original_text == *broken_link.reference) + { + Some((link.href.as_str().into(), link.new_text.as_str().into())) + } else if matches!( + &broken_link.link_type, + LinkType::Reference | LinkType::ReferenceUnknown + ) { + // If the link is shaped [like][this], suppress any broken HTML in the [this] part. + // The `broken_intra_doc_links` will report typos in there anyway. + Some(( + broken_link.reference.to_string().into(), + broken_link.reference.to_string().into(), + )) + } else { + None + } + }; + + let p = + Parser::new_with_broken_link_callback(&dox, main_body_opts(), Some(&mut replacer)) + .into_offset_iter(); for (event, range) in p { match event { diff --git a/src/test/codegen/drop.rs b/src/test/codegen/drop.rs index 543b81b0b6246..994028271583f 100644 --- a/src/test/codegen/drop.rs +++ b/src/test/codegen/drop.rs @@ -23,17 +23,7 @@ pub fn droppy() { // FIXME(eddyb) the `void @` forces a match on the instruction, instead of the // comment, that's `; call core::ptr::drop_in_place::` // for the `v0` mangling, should switch to matching on that once `legacy` is gone. -// CHECK-NOT: invoke void @{{.*}}drop_in_place{{.*}}SomeUniqueName -// CHECK: call void @{{.*}}drop_in_place{{.*}}SomeUniqueName -// CHECK: call void @{{.*}}drop_in_place{{.*}}SomeUniqueName -// CHECK-NOT: call void @{{.*}}drop_in_place{{.*}}SomeUniqueName -// CHECK: invoke void @{{.*}}drop_in_place{{.*}}SomeUniqueName -// CHECK-NOT: invoke void @{{.*}}drop_in_place{{.*}}SomeUniqueName -// CHECK: call void @{{.*}}drop_in_place{{.*}}SomeUniqueName -// CHECK-NOT: call void @{{.*}}drop_in_place{{.*}}SomeUniqueName -// CHECK: invoke void @{{.*}}drop_in_place{{.*}}SomeUniqueName -// CHECK-NOT: invoke void @{{.*}}drop_in_place{{.*}}SomeUniqueName -// CHECK: call void @{{.*}}drop_in_place{{.*}}SomeUniqueName +// CHECK-COUNT-6: {{(call|invoke) void @.*}}drop_in_place{{.*}}SomeUniqueName // CHECK-NOT: {{(call|invoke) void @.*}}drop_in_place{{.*}}SomeUniqueName // The next line checks for the } that ends the function definition // CHECK-LABEL: {{^[}]}} diff --git a/src/test/codegen/unwind-landingpad-cold.rs b/src/test/codegen/unwind-landingpad-cold.rs index 650d5b230f4c2..aa00b7936541e 100644 --- a/src/test/codegen/unwind-landingpad-cold.rs +++ b/src/test/codegen/unwind-landingpad-cold.rs @@ -6,7 +6,7 @@ // get the `cold` attribute. // CHECK-LABEL: @check_cold -// CHECK: call void {{.+}}drop_in_place{{.+}} [[ATTRIBUTES:#[0-9]+]] +// CHECK: {{(call|invoke) void .+}}drop_in_place{{.+}} [[ATTRIBUTES:#[0-9]+]] // CHECK: attributes [[ATTRIBUTES]] = { cold } #[no_mangle] pub fn check_cold(f: fn(), x: Box) { diff --git a/src/test/mir-opt/box_expr.main.ElaborateDrops.before.mir b/src/test/mir-opt/box_expr.main.ElaborateDrops.before.mir index c6187879ab0a9..5b1ffc76fe5b3 100644 --- a/src/test/mir-opt/box_expr.main.ElaborateDrops.before.mir +++ b/src/test/mir-opt/box_expr.main.ElaborateDrops.before.mir @@ -47,7 +47,7 @@ fn main() -> () { _6 = std::mem::drop::>(move _7) -> [return: bb4, unwind: bb6]; // scope 1 at $DIR/box_expr.rs:8:5: 8:12 // mir::Constant // + span: $DIR/box_expr.rs:8:5: 8:9 - // + literal: Const { ty: fn(std::boxed::Box) {std::mem::drop::>}, val: Value(Scalar()) } + // + literal: Const { ty: fn(Box) {std::mem::drop::>}, val: Value(Scalar()) } } bb4: { diff --git a/src/test/mir-opt/byte_slice.main.SimplifyCfg-elaborate-drops.after.mir b/src/test/mir-opt/byte_slice.main.SimplifyCfg-elaborate-drops.after.mir index e22adae815c02..073cba5acf407 100644 --- a/src/test/mir-opt/byte_slice.main.SimplifyCfg-elaborate-drops.after.mir +++ b/src/test/mir-opt/byte_slice.main.SimplifyCfg-elaborate-drops.after.mir @@ -14,9 +14,6 @@ fn main() -> () { bb0: { StorageLive(_1); // scope 0 at $DIR/byte_slice.rs:5:9: 5:10 _1 = const b"foo"; // scope 0 at $DIR/byte_slice.rs:5:13: 5:19 - // ty::Const - // + ty: &[u8; 3] - // + val: Value(Scalar(alloc1)) // mir::Constant // + span: $DIR/byte_slice.rs:5:13: 5:19 // + literal: Const { ty: &[u8; 3], val: Value(Scalar(alloc1)) } diff --git a/src/test/mir-opt/const_debuginfo.main.ConstDebugInfo.diff b/src/test/mir-opt/const_debuginfo.main.ConstDebugInfo.diff index 8714a8992d7e0..7ed25c6c09e96 100644 --- a/src/test/mir-opt/const_debuginfo.main.ConstDebugInfo.diff +++ b/src/test/mir-opt/const_debuginfo.main.ConstDebugInfo.diff @@ -75,9 +75,6 @@ StorageDead(_5); // scope 3 at $DIR/const_debuginfo.rs:12:23: 12:24 StorageLive(_9); // scope 4 at $DIR/const_debuginfo.rs:14:9: 14:10 _9 = const "hello, world!"; // scope 4 at $DIR/const_debuginfo.rs:14:13: 14:28 - // ty::Const - // + ty: &str - // + val: Value(Slice { data: Allocation { bytes: [104, 101, 108, 108, 111, 44, 32, 119, 111, 114, 108, 100, 33], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [8191], len: Size { raw: 13 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 13 }) // mir::Constant // + span: $DIR/const_debuginfo.rs:14:13: 14:28 // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [104, 101, 108, 108, 111, 44, 32, 119, 111, 114, 108, 100, 33], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [8191], len: Size { raw: 13 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 13 }) } diff --git a/src/test/mir-opt/const_promotion_extern_static.BAR.PromoteTemps.diff b/src/test/mir-opt/const_promotion_extern_static.BAR.PromoteTemps.diff index ad83e9c276e66..816c598059dd5 100644 --- a/src/test/mir-opt/const_promotion_extern_static.BAR.PromoteTemps.diff +++ b/src/test/mir-opt/const_promotion_extern_static.BAR.PromoteTemps.diff @@ -18,9 +18,6 @@ - StorageLive(_5); // scope 0 at $DIR/const-promotion-extern-static.rs:9:33: 9:34 - _5 = const {alloc1: &i32}; // scope 0 at $DIR/const-promotion-extern-static.rs:9:33: 9:34 + _6 = const BAR::promoted[0]; // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:44 -+ // ty::Const -+ // + ty: &[&i32; 1] -+ // + val: Unevaluated(BAR, [], Some(promoted[0])) // mir::Constant - // + span: $DIR/const-promotion-extern-static.rs:9:33: 9:34 - // + literal: Const { ty: &i32, val: Value(Scalar(alloc1)) } @@ -28,7 +25,7 @@ - _3 = [move _4]; // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35 - _2 = &_3; // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:44 + // + span: $DIR/const-promotion-extern-static.rs:9:31: 9:44 -+ // + literal: Const { ty: &[&i32; 1], val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:6 ~ const_promotion_extern_static[e01c]::BAR), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) } ++ // + literal: Const { ty: &[&i32; 1], val: Unevaluated(BAR, [], Some(promoted[0])) } + _2 = &(*_6); // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:44 _1 = move _2 as &[&i32] (Pointer(Unsize)); // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:44 - StorageDead(_4); // scope 0 at $DIR/const-promotion-extern-static.rs:9:34: 9:35 diff --git a/src/test/mir-opt/const_promotion_extern_static.FOO.PromoteTemps.diff b/src/test/mir-opt/const_promotion_extern_static.FOO.PromoteTemps.diff index a9cf3ca976797..096b427bb758b 100644 --- a/src/test/mir-opt/const_promotion_extern_static.FOO.PromoteTemps.diff +++ b/src/test/mir-opt/const_promotion_extern_static.FOO.PromoteTemps.diff @@ -20,9 +20,6 @@ - StorageLive(_5); // scope 1 at $DIR/const-promotion-extern-static.rs:13:42: 13:43 - _5 = const {alloc3: *const i32}; // scope 1 at $DIR/const-promotion-extern-static.rs:13:42: 13:43 + _6 = const FOO::promoted[0]; // scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:55 -+ // ty::Const -+ // + ty: &[&i32; 1] -+ // + val: Unevaluated(FOO, [], Some(promoted[0])) // mir::Constant - // + span: $DIR/const-promotion-extern-static.rs:13:42: 13:43 - // + literal: Const { ty: *const i32, val: Value(Scalar(alloc3)) } @@ -30,7 +27,7 @@ - _3 = [move _4]; // scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:46 - _2 = &_3; // scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:55 + // + span: $DIR/const-promotion-extern-static.rs:13:31: 13:55 -+ // + literal: Const { ty: &[&i32; 1], val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:7 ~ const_promotion_extern_static[e01c]::FOO), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) } ++ // + literal: Const { ty: &[&i32; 1], val: Unevaluated(FOO, [], Some(promoted[0])) } + _2 = &(*_6); // scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:55 _1 = move _2 as &[&i32] (Pointer(Unsize)); // scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:55 - StorageDead(_4); // scope 0 at $DIR/const-promotion-extern-static.rs:13:45: 13:46 diff --git a/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.32bit.diff b/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.32bit.diff index 553011f1aaab8..cda6e751c8ef5 100644 --- a/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.32bit.diff +++ b/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.32bit.diff @@ -26,12 +26,9 @@ StorageLive(_2); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35 StorageLive(_3); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35 _9 = const main::promoted[0]; // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35 - // ty::Const - // + ty: &[i32; 3] - // + val: Unevaluated(main, [], Some(promoted[0])) // mir::Constant // + span: $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35 - // + literal: Const { ty: &[i32; 3], val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ bad_op_unsafe_oob_for_slices[fbcf]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) } + // + literal: Const { ty: &[i32; 3], val: Unevaluated(main, [], Some(promoted[0])) } _3 = _9; // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35 _2 = &raw const (*_3); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35 _1 = move _2 as *const [i32] (Pointer(Unsize)); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35 diff --git a/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.64bit.diff b/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.64bit.diff index 553011f1aaab8..cda6e751c8ef5 100644 --- a/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.64bit.diff +++ b/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.64bit.diff @@ -26,12 +26,9 @@ StorageLive(_2); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35 StorageLive(_3); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35 _9 = const main::promoted[0]; // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35 - // ty::Const - // + ty: &[i32; 3] - // + val: Unevaluated(main, [], Some(promoted[0])) // mir::Constant // + span: $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35 - // + literal: Const { ty: &[i32; 3], val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ bad_op_unsafe_oob_for_slices[fbcf]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) } + // + literal: Const { ty: &[i32; 3], val: Unevaluated(main, [], Some(promoted[0])) } _3 = _9; // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35 _2 = &raw const (*_3); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35 _1 = move _2 as *const [i32] (Pointer(Unsize)); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35 diff --git a/src/test/mir-opt/const_prop/const_prop_fails_gracefully.main.ConstProp.diff b/src/test/mir-opt/const_prop/const_prop_fails_gracefully.main.ConstProp.diff index 44273b763be3e..466c286c9d7c9 100644 --- a/src/test/mir-opt/const_prop/const_prop_fails_gracefully.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/const_prop_fails_gracefully.main.ConstProp.diff @@ -17,12 +17,9 @@ StorageLive(_2); // scope 0 at $DIR/const_prop_fails_gracefully.rs:7:13: 7:30 StorageLive(_3); // scope 0 at $DIR/const_prop_fails_gracefully.rs:7:13: 7:16 _3 = const FOO; // scope 0 at $DIR/const_prop_fails_gracefully.rs:7:13: 7:16 - // ty::Const - // + ty: &i32 - // + val: Unevaluated(FOO, [], None) // mir::Constant // + span: $DIR/const_prop_fails_gracefully.rs:7:13: 7:16 - // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:5 ~ const_prop_fails_gracefully[809a]::main::FOO), const_param_did: None }, substs: [], promoted: None }) } + // + literal: Const { ty: &i32, val: Unevaluated(FOO, [], None) } _2 = &raw const (*_3); // scope 0 at $DIR/const_prop_fails_gracefully.rs:7:13: 7:16 _1 = move _2 as usize (Misc); // scope 0 at $DIR/const_prop_fails_gracefully.rs:7:13: 7:39 StorageDead(_2); // scope 0 at $DIR/const_prop_fails_gracefully.rs:7:38: 7:39 diff --git a/src/test/mir-opt/const_prop/control_flow_simplification.hello.ConstProp.diff b/src/test/mir-opt/const_prop/control_flow_simplification.hello.ConstProp.diff index 1eb40e50d7aa0..49f6c10415763 100644 --- a/src/test/mir-opt/const_prop/control_flow_simplification.hello.ConstProp.diff +++ b/src/test/mir-opt/const_prop/control_flow_simplification.hello.ConstProp.diff @@ -19,10 +19,7 @@ begin_panic::<&str>(const "explicit panic"); // scope 0 at $SRC_DIR/std/src/panic.rs:LL:COL // mir::Constant // + span: $SRC_DIR/std/src/panic.rs:LL:COL - // + literal: Const { ty: fn(&str) -> ! {std::rt::begin_panic::<&str>}, val: Value(Scalar()) } - // ty::Const - // + ty: &str - // + val: Value(Slice { data: Allocation { bytes: [101, 120, 112, 108, 105, 99, 105, 116, 32, 112, 97, 110, 105, 99], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [16383], len: Size { raw: 14 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 14 }) + // + literal: Const { ty: fn(&str) -> ! {begin_panic::<&str>}, val: Value(Scalar()) } // mir::Constant // + span: $SRC_DIR/std/src/panic.rs:LL:COL // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [101, 120, 112, 108, 105, 99, 105, 116, 32, 112, 97, 110, 105, 99], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [16383], len: Size { raw: 14 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 14 }) } diff --git a/src/test/mir-opt/const_prop/invalid_constant.main.ConstProp.diff b/src/test/mir-opt/const_prop/invalid_constant.main.ConstProp.diff index ee6c3b5f36fd4..f2a1b9d69e1ad 100644 --- a/src/test/mir-opt/const_prop/invalid_constant.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/invalid_constant.main.ConstProp.diff @@ -3,53 +3,58 @@ fn main() -> () { let mut _0: (); // return place in scope 0 at $DIR/invalid_constant.rs:15:11: 15:11 - let _1: std::option::Option<()>; // in scope 0 at $DIR/invalid_constant.rs:16:5: 16:12 - let mut _2: std::option::Option>; // in scope 0 at $DIR/invalid_constant.rs:16:7: 16:11 - scope 1 (inlined f) { // at $DIR/invalid_constant.rs:16:5: 16:12 - debug x => _2; // in scope 1 at $DIR/invalid_constant.rs:16:5: 16:12 - let mut _3: isize; // in scope 1 at $DIR/invalid_constant.rs:16:5: 16:12 - let _4: std::option::Option<()>; // in scope 1 at $DIR/invalid_constant.rs:16:5: 16:12 + let _1: main::InvalidChar; // in scope 0 at $DIR/invalid_constant.rs:21:9: 21:22 + let mut _3: main::InvalidTag; // in scope 0 at $DIR/invalid_constant.rs:28:25: 28:46 + let mut _5: main::NoVariants; // in scope 0 at $DIR/invalid_constant.rs:35:35: 35:56 + scope 1 { + debug _invalid_char => _1; // in scope 1 at $DIR/invalid_constant.rs:21:9: 21:22 + let _2: [main::InvalidTag; 1]; // in scope 1 at $DIR/invalid_constant.rs:28:9: 28:21 scope 2 { - debug y => _4; // in scope 2 at $DIR/invalid_constant.rs:16:5: 16:12 + debug _invalid_tag => _2; // in scope 2 at $DIR/invalid_constant.rs:28:9: 28:21 + let _4: [main::NoVariants; 1]; // in scope 2 at $DIR/invalid_constant.rs:35:9: 35:31 + scope 3 { + debug _enum_without_variants => _4; // in scope 3 at $DIR/invalid_constant.rs:35:9: 35:31 + let _6: main::Str<"���">; // in scope 3 at $DIR/invalid_constant.rs:39:9: 39:22 + scope 4 { + debug _non_utf8_str => _6; // in scope 4 at $DIR/invalid_constant.rs:39:9: 39:22 + } + } } } bb0: { - discriminant(_2) = 0; // scope 0 at $DIR/invalid_constant.rs:16:7: 16:11 -- _3 = discriminant(_2); // scope 1 at $DIR/invalid_constant.rs:16:5: 16:12 -- switchInt(move _3) -> [0_isize: bb3, otherwise: bb2]; // scope 1 at $DIR/invalid_constant.rs:16:5: 16:12 -+ _3 = const 0_isize; // scope 1 at $DIR/invalid_constant.rs:16:5: 16:12 -+ switchInt(const 0_isize) -> [0_isize: bb3, otherwise: bb2]; // scope 1 at $DIR/invalid_constant.rs:16:5: 16:12 - } - - bb1: { - nop; // scope 0 at $DIR/invalid_constant.rs:15:11: 17:2 - return; // scope 0 at $DIR/invalid_constant.rs:17:2: 17:2 - } - - bb2: { -- _4 = ((_2 as Some).0: std::option::Option<()>); // scope 1 at $DIR/invalid_constant.rs:16:5: 16:12 -- _1 = _4; // scope 2 at $DIR/invalid_constant.rs:16:5: 16:12 -+ _4 = const Scalar(0x02): Option::<()>; // scope 1 at $DIR/invalid_constant.rs:16:5: 16:12 -+ // ty::Const -+ // + ty: std::option::Option<()> -+ // + val: Value(Scalar(0x02)) + StorageLive(_1); // scope 0 at $DIR/invalid_constant.rs:21:9: 21:22 +- _1 = const { InvalidChar { int: 0x110001 } }; // scope 0 at $DIR/invalid_constant.rs:21:25: 21:64 ++ _1 = const InvalidChar { int: 1114113_u32, chr: {transmute(0x00110001): char} }; // scope 0 at $DIR/invalid_constant.rs:21:25: 21:64 + // mir::Constant + // + span: $DIR/invalid_constant.rs:21:25: 21:64 +- // + literal: Const { ty: InvalidChar, val: Unevaluated(main::{constant#0}, [main::InvalidChar], None) } ++ // + literal: Const { ty: InvalidChar, val: Value(Scalar(0x00110001)) } + StorageLive(_2); // scope 1 at $DIR/invalid_constant.rs:28:9: 28:21 + StorageLive(_3); // scope 1 at $DIR/invalid_constant.rs:28:25: 28:46 + (_3.0: u32) = const 4_u32; // scope 1 at $DIR/invalid_constant.rs:28:25: 28:46 +- _2 = [move _3]; // scope 1 at $DIR/invalid_constant.rs:28:24: 28:47 ++ _2 = [const InvalidTag { int: 4_u32, e: Scalar(0x00000004): E }]; // scope 1 at $DIR/invalid_constant.rs:28:24: 28:47 + // mir::Constant -+ // + span: $DIR/invalid_constant.rs:16:5: 16:12 -+ // + literal: Const { ty: std::option::Option<()>, val: Value(Scalar(0x02)) } -+ _1 = const Scalar(0x02): Option::<()>; // scope 2 at $DIR/invalid_constant.rs:16:5: 16:12 -+ // ty::Const -+ // + ty: std::option::Option<()> -+ // + val: Value(Scalar(0x02)) ++ // + span: $DIR/invalid_constant.rs:28:24: 28:47 ++ // + literal: Const { ty: InvalidTag, val: Value(Scalar(0x00000004)) } + StorageDead(_3); // scope 1 at $DIR/invalid_constant.rs:28:46: 28:47 + StorageLive(_4); // scope 2 at $DIR/invalid_constant.rs:35:9: 35:31 + StorageLive(_5); // scope 2 at $DIR/invalid_constant.rs:35:35: 35:56 + (_5.0: u32) = const 0_u32; // scope 2 at $DIR/invalid_constant.rs:35:35: 35:56 +- _4 = [move _5]; // scope 2 at $DIR/invalid_constant.rs:35:34: 35:57 ++ _4 = [const NoVariants { int: 0_u32, empty: Scalar(): Empty }]; // scope 2 at $DIR/invalid_constant.rs:35:34: 35:57 + // mir::Constant -+ // + span: $DIR/invalid_constant.rs:16:5: 16:12 -+ // + literal: Const { ty: std::option::Option<()>, val: Value(Scalar(0x02)) } - goto -> bb1; // scope 0 at $DIR/invalid_constant.rs:10:20: 10:21 - } - - bb3: { - discriminant(_1) = 0; // scope 1 at $DIR/invalid_constant.rs:16:5: 16:12 - goto -> bb1; // scope 0 at $DIR/invalid_constant.rs:9:17: 9:21 ++ // + span: $DIR/invalid_constant.rs:35:34: 35:57 ++ // + literal: Const { ty: NoVariants, val: Value(Scalar(0x00000000)) } + StorageDead(_5); // scope 2 at $DIR/invalid_constant.rs:35:56: 35:57 + StorageLive(_6); // scope 3 at $DIR/invalid_constant.rs:39:9: 39:22 + nop; // scope 0 at $DIR/invalid_constant.rs:15:11: 42:2 + StorageDead(_6); // scope 3 at $DIR/invalid_constant.rs:42:1: 42:2 + StorageDead(_4); // scope 2 at $DIR/invalid_constant.rs:42:1: 42:2 + StorageDead(_2); // scope 1 at $DIR/invalid_constant.rs:42:1: 42:2 + StorageDead(_1); // scope 0 at $DIR/invalid_constant.rs:42:1: 42:2 + return; // scope 0 at $DIR/invalid_constant.rs:42:2: 42:2 } } diff --git a/src/test/mir-opt/const_prop/invalid_constant.rs b/src/test/mir-opt/const_prop/invalid_constant.rs index 1eb6f37df5968..492ef404916d4 100644 --- a/src/test/mir-opt/const_prop/invalid_constant.rs +++ b/src/test/mir-opt/const_prop/invalid_constant.rs @@ -1,17 +1,42 @@ -// Verify that we can pretty print invalid constant introduced -// by constant propagation. Regression test for issue #93688. -// -// compile-flags: -Copt-level=0 -Zinline-mir +// Verify that we can pretty print invalid constants. -#[inline(always)] -pub fn f(x: Option>) -> Option<()> { - match x { - None => None, - Some(y) => y, - } -} +#![feature(adt_const_params)] +#![feature(inline_const)] +#![allow(incomplete_features)] + +#[derive(Copy, Clone)] +#[repr(u32)] +enum E { A, B, C } + +#[derive(Copy, Clone)] +enum Empty {} // EMIT_MIR invalid_constant.main.ConstProp.diff fn main() { - f(None); + // An invalid char. + union InvalidChar { + int: u32, + chr: char, + } + let _invalid_char = const { InvalidChar { int: 0x110001 } }; + + // An enum with an invalid tag. Regression test for #93688. + union InvalidTag { + int: u32, + e: E, + } + let _invalid_tag = [InvalidTag { int: 4 }]; + + // An enum without variants. Regression test for #94073. + union NoVariants { + int: u32, + empty: Empty, + } + let _enum_without_variants = [NoVariants { int: 0 }]; + + // A non-UTF-8 string slice. Regression test for #75763 and #78520. + struct Str; + let _non_utf8_str: Str::<{ + unsafe { std::mem::transmute::<&[u8], &str>(&[0xC0, 0xC1, 0xF5]) } + }>; } diff --git a/src/test/mir-opt/const_prop/ref_deref.main.ConstProp.diff b/src/test/mir-opt/const_prop/ref_deref.main.ConstProp.diff index 2864e01d9dc53..07ace0d6b576d 100644 --- a/src/test/mir-opt/const_prop/ref_deref.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/ref_deref.main.ConstProp.diff @@ -12,12 +12,9 @@ StorageLive(_1); // scope 0 at $DIR/ref_deref.rs:5:5: 5:10 StorageLive(_2); // scope 0 at $DIR/ref_deref.rs:5:6: 5:10 _4 = const main::promoted[0]; // scope 0 at $DIR/ref_deref.rs:5:6: 5:10 - // ty::Const - // + ty: &i32 - // + val: Unevaluated(main, [], Some(promoted[0])) // mir::Constant // + span: $DIR/ref_deref.rs:5:6: 5:10 - // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ ref_deref[d561]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) } + // + literal: Const { ty: &i32, val: Unevaluated(main, [], Some(promoted[0])) } _2 = _4; // scope 0 at $DIR/ref_deref.rs:5:6: 5:10 - _1 = (*_2); // scope 0 at $DIR/ref_deref.rs:5:5: 5:10 + _1 = const 4_i32; // scope 0 at $DIR/ref_deref.rs:5:5: 5:10 diff --git a/src/test/mir-opt/const_prop/ref_deref.main.PromoteTemps.diff b/src/test/mir-opt/const_prop/ref_deref.main.PromoteTemps.diff index 5a678616f63ef..aed13d8ec02ec 100644 --- a/src/test/mir-opt/const_prop/ref_deref.main.PromoteTemps.diff +++ b/src/test/mir-opt/const_prop/ref_deref.main.PromoteTemps.diff @@ -15,12 +15,9 @@ - _3 = const 4_i32; // scope 0 at $DIR/ref_deref.rs:5:8: 5:9 - _2 = &_3; // scope 0 at $DIR/ref_deref.rs:5:6: 5:10 + _4 = const main::promoted[0]; // scope 0 at $DIR/ref_deref.rs:5:6: 5:10 -+ // ty::Const -+ // + ty: &i32 -+ // + val: Unevaluated(main, [], Some(promoted[0])) + // mir::Constant + // + span: $DIR/ref_deref.rs:5:6: 5:10 -+ // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ ref_deref[d561]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) } ++ // + literal: Const { ty: &i32, val: Unevaluated(main, [], Some(promoted[0])) } + _2 = &(*_4); // scope 0 at $DIR/ref_deref.rs:5:6: 5:10 _1 = (*_2); // scope 0 at $DIR/ref_deref.rs:5:5: 5:10 - StorageDead(_3); // scope 0 at $DIR/ref_deref.rs:5:10: 5:11 diff --git a/src/test/mir-opt/const_prop/ref_deref_project.main.ConstProp.diff b/src/test/mir-opt/const_prop/ref_deref_project.main.ConstProp.diff index 53f9daa09da74..bbd0ec1a33687 100644 --- a/src/test/mir-opt/const_prop/ref_deref_project.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/ref_deref_project.main.ConstProp.diff @@ -12,12 +12,9 @@ StorageLive(_1); // scope 0 at $DIR/ref_deref_project.rs:5:5: 5:17 StorageLive(_2); // scope 0 at $DIR/ref_deref_project.rs:5:6: 5:17 _4 = const main::promoted[0]; // scope 0 at $DIR/ref_deref_project.rs:5:6: 5:17 - // ty::Const - // + ty: &(i32, i32) - // + val: Unevaluated(main, [], Some(promoted[0])) // mir::Constant // + span: $DIR/ref_deref_project.rs:5:6: 5:17 - // + literal: Const { ty: &(i32, i32), val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ ref_deref_project[d1f7]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) } + // + literal: Const { ty: &(i32, i32), val: Unevaluated(main, [], Some(promoted[0])) } _2 = &((*_4).1: i32); // scope 0 at $DIR/ref_deref_project.rs:5:6: 5:17 _1 = (*_2); // scope 0 at $DIR/ref_deref_project.rs:5:5: 5:17 StorageDead(_2); // scope 0 at $DIR/ref_deref_project.rs:5:17: 5:18 diff --git a/src/test/mir-opt/const_prop/ref_deref_project.main.PromoteTemps.diff b/src/test/mir-opt/const_prop/ref_deref_project.main.PromoteTemps.diff index d5235a1d02528..2df963556a9ee 100644 --- a/src/test/mir-opt/const_prop/ref_deref_project.main.PromoteTemps.diff +++ b/src/test/mir-opt/const_prop/ref_deref_project.main.PromoteTemps.diff @@ -15,12 +15,9 @@ - _3 = (const 4_i32, const 5_i32); // scope 0 at $DIR/ref_deref_project.rs:5:8: 5:14 - _2 = &(_3.1: i32); // scope 0 at $DIR/ref_deref_project.rs:5:6: 5:17 + _4 = const main::promoted[0]; // scope 0 at $DIR/ref_deref_project.rs:5:6: 5:17 -+ // ty::Const -+ // + ty: &(i32, i32) -+ // + val: Unevaluated(main, [], Some(promoted[0])) + // mir::Constant + // + span: $DIR/ref_deref_project.rs:5:6: 5:17 -+ // + literal: Const { ty: &(i32, i32), val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ ref_deref_project[d1f7]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) } ++ // + literal: Const { ty: &(i32, i32), val: Unevaluated(main, [], Some(promoted[0])) } + _2 = &((*_4).1: i32); // scope 0 at $DIR/ref_deref_project.rs:5:6: 5:17 _1 = (*_2); // scope 0 at $DIR/ref_deref_project.rs:5:5: 5:17 - StorageDead(_3); // scope 0 at $DIR/ref_deref_project.rs:5:17: 5:18 diff --git a/src/test/mir-opt/const_prop/slice_len.main.ConstProp.32bit.diff b/src/test/mir-opt/const_prop/slice_len.main.ConstProp.32bit.diff index 339c3d13b8d67..5366d233505d2 100644 --- a/src/test/mir-opt/const_prop/slice_len.main.ConstProp.32bit.diff +++ b/src/test/mir-opt/const_prop/slice_len.main.ConstProp.32bit.diff @@ -20,12 +20,9 @@ StorageLive(_3); // scope 0 at $DIR/slice_len.rs:5:6: 5:19 StorageLive(_4); // scope 0 at $DIR/slice_len.rs:5:6: 5:19 _9 = const main::promoted[0]; // scope 0 at $DIR/slice_len.rs:5:6: 5:19 - // ty::Const - // + ty: &[u32; 3] - // + val: Unevaluated(main, [], Some(promoted[0])) // mir::Constant // + span: $DIR/slice_len.rs:5:6: 5:19 - // + literal: Const { ty: &[u32; 3], val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ slice_len[7261]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) } + // + literal: Const { ty: &[u32; 3], val: Unevaluated(main, [], Some(promoted[0])) } _4 = _9; // scope 0 at $DIR/slice_len.rs:5:6: 5:19 _3 = _4; // scope 0 at $DIR/slice_len.rs:5:6: 5:19 StorageLive(_10); // scope 0 at $DIR/slice_len.rs:5:6: 5:19 diff --git a/src/test/mir-opt/const_prop/slice_len.main.ConstProp.64bit.diff b/src/test/mir-opt/const_prop/slice_len.main.ConstProp.64bit.diff index 339c3d13b8d67..5366d233505d2 100644 --- a/src/test/mir-opt/const_prop/slice_len.main.ConstProp.64bit.diff +++ b/src/test/mir-opt/const_prop/slice_len.main.ConstProp.64bit.diff @@ -20,12 +20,9 @@ StorageLive(_3); // scope 0 at $DIR/slice_len.rs:5:6: 5:19 StorageLive(_4); // scope 0 at $DIR/slice_len.rs:5:6: 5:19 _9 = const main::promoted[0]; // scope 0 at $DIR/slice_len.rs:5:6: 5:19 - // ty::Const - // + ty: &[u32; 3] - // + val: Unevaluated(main, [], Some(promoted[0])) // mir::Constant // + span: $DIR/slice_len.rs:5:6: 5:19 - // + literal: Const { ty: &[u32; 3], val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ slice_len[7261]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) } + // + literal: Const { ty: &[u32; 3], val: Unevaluated(main, [], Some(promoted[0])) } _4 = _9; // scope 0 at $DIR/slice_len.rs:5:6: 5:19 _3 = _4; // scope 0 at $DIR/slice_len.rs:5:6: 5:19 StorageLive(_10); // scope 0 at $DIR/slice_len.rs:5:6: 5:19 diff --git a/src/test/mir-opt/deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.diff b/src/test/mir-opt/deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.diff index 7695afded3da3..01714c0a46c72 100644 --- a/src/test/mir-opt/deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.diff +++ b/src/test/mir-opt/deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.diff @@ -27,7 +27,7 @@ + _2 = transmute::<&str, &[u8]>(move _8) -> bb12; // scope 2 at $DIR/deduplicate_blocks.rs:3:11: 3:23 // mir::Constant // + span: $DIR/deduplicate_blocks.rs:3:11: 3:23 - // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(&str) -> &[u8] {std::intrinsics::transmute::<&str, &[u8]>}, val: Value(Scalar()) } + // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(&str) -> &[u8] {transmute::<&str, &[u8]>}, val: Value(Scalar()) } } bb1: { diff --git a/src/test/mir-opt/early_otherwise_branch.opt2.EarlyOtherwiseBranch.diff b/src/test/mir-opt/early_otherwise_branch.opt2.EarlyOtherwiseBranch.diff index 6d149b89edbb9..79b923a28894b 100644 --- a/src/test/mir-opt/early_otherwise_branch.opt2.EarlyOtherwiseBranch.diff +++ b/src/test/mir-opt/early_otherwise_branch.opt2.EarlyOtherwiseBranch.diff @@ -31,7 +31,7 @@ StorageDead(_5); // scope 0 at $DIR/early_otherwise_branch.rs:12:16: 12:17 StorageDead(_4); // scope 0 at $DIR/early_otherwise_branch.rs:12:16: 12:17 _8 = discriminant((_3.0: std::option::Option)); // scope 0 at $DIR/early_otherwise_branch.rs:12:11: 12:17 -- switchInt(move _8) -> [0_isize: bb1, 1_isize: bb3, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch.rs:12:5: 12:17 +- switchInt(move _8) -> [0_isize: bb1, 1_isize: bb3, otherwise: bb7]; // scope 0 at $DIR/early_otherwise_branch.rs:12:5: 12:17 + StorageLive(_11); // scope 0 at $DIR/early_otherwise_branch.rs:12:5: 12:17 + _11 = discriminant((_3.1: std::option::Option)); // scope 0 at $DIR/early_otherwise_branch.rs:12:5: 12:17 + StorageLive(_12); // scope 0 at $DIR/early_otherwise_branch.rs:12:5: 12:17 @@ -81,8 +81,10 @@ + bb4: { StorageDead(_3); // scope 0 at $DIR/early_otherwise_branch.rs:17:1: 17:2 return; // scope 0 at $DIR/early_otherwise_branch.rs:17:2: 17:2 -+ } -+ + } + +- bb7: { +- unreachable; // scope 0 at $DIR/early_otherwise_branch.rs:15:14: 15:15 + bb5: { + StorageDead(_12); // scope 0 at $DIR/early_otherwise_branch.rs:12:5: 12:17 + switchInt(_8) -> [0_isize: bb3, 1_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:12:5: 12:17 diff --git a/src/test/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.before-SimplifyConstCondition-final.after.diff b/src/test/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.before-SimplifyConstCondition-final.after.diff index fc2dcb251099f..db6794db29819 100644 --- a/src/test/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.before-SimplifyConstCondition-final.after.diff +++ b/src/test/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.before-SimplifyConstCondition-final.after.diff @@ -81,7 +81,7 @@ - StorageDead(_5); // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:23: 21:24 + nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:23: 21:24 _11 = discriminant((*(_4.0: &ViewportPercentageLength))); // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:14: 21:24 -- switchInt(move _11) -> [0_isize: bb1, 1_isize: bb3, 2_isize: bb4, 3_isize: bb5, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 21:24 +- switchInt(move _11) -> [0_isize: bb1, 1_isize: bb3, 2_isize: bb4, 3_isize: bb5, otherwise: bb11]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 21:24 + StorageLive(_34); // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 21:24 + _34 = discriminant((*(_4.1: &ViewportPercentageLength))); // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 21:24 + StorageLive(_35); // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 21:24 @@ -217,14 +217,9 @@ - StorageDead(_13); // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:49: 22:50 - StorageDead(_12); // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:49: 22:50 - goto -> bb10; // scope 0 at $DIR/early_otherwise_branch_68867.rs:22:49: 22:50 -+ nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:5: 27:7 -+ discriminant(_0) = 0; // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:5: 27:7 -+ nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:27:6: 27:7 -+ nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:28:1: 28:2 -+ return; // scope 0 at $DIR/early_otherwise_branch_68867.rs:28:2: 28:2 - } - - bb7: { +- } +- +- bb7: { - StorageLive(_17); // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:14: 23:17 - _17 = (((*(_4.0: &ViewportPercentageLength)) as Vh).0: f32); // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:14: 23:17 - StorageLive(_18); // scope 0 at $DIR/early_otherwise_branch_68867.rs:23:24: 23:29 @@ -289,10 +284,18 @@ - - bb10: { - ((_0 as Ok).0: ViewportPercentageLength) = move _3; // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:5: 27:7 -- discriminant(_0) = 0; // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:5: 27:7 ++ nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:5: 27:7 + discriminant(_0) = 0; // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:5: 27:7 - StorageDead(_3); // scope 0 at $DIR/early_otherwise_branch_68867.rs:27:6: 27:7 - StorageDead(_4); // scope 0 at $DIR/early_otherwise_branch_68867.rs:28:1: 28:2 -- return; // scope 0 at $DIR/early_otherwise_branch_68867.rs:28:2: 28:2 ++ nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:27:6: 27:7 ++ nop; // scope 0 at $DIR/early_otherwise_branch_68867.rs:28:1: 28:2 + return; // scope 0 at $DIR/early_otherwise_branch_68867.rs:28:2: 28:2 + } + +- bb11: { +- unreachable; // scope 0 at $DIR/early_otherwise_branch_68867.rs:28:2: 28:2 ++ bb7: { + StorageDead(_35); // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 21:24 + switchInt(_11) -> [0_isize: bb2, 1_isize: bb3, 2_isize: bb4, 3_isize: bb5, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 21:24 } diff --git a/src/test/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.diff b/src/test/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.diff index 28c650d72dc1d..c8d8ae7766d2a 100644 --- a/src/test/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.diff +++ b/src/test/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.diff @@ -67,7 +67,7 @@ StorageDead(_6); // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:23: 21:24 StorageDead(_5); // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:23: 21:24 _11 = discriminant((*(_4.0: &ViewportPercentageLength))); // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:14: 21:24 -- switchInt(move _11) -> [0_isize: bb1, 1_isize: bb3, 2_isize: bb4, 3_isize: bb5, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 21:24 +- switchInt(move _11) -> [0_isize: bb1, 1_isize: bb3, 2_isize: bb4, 3_isize: bb5, otherwise: bb11]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 21:24 + StorageLive(_34); // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 21:24 + _34 = discriminant((*(_4.1: &ViewportPercentageLength))); // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 21:24 + StorageLive(_35); // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 21:24 @@ -206,8 +206,10 @@ StorageDead(_3); // scope 0 at $DIR/early_otherwise_branch_68867.rs:27:6: 27:7 StorageDead(_4); // scope 0 at $DIR/early_otherwise_branch_68867.rs:28:1: 28:2 return; // scope 0 at $DIR/early_otherwise_branch_68867.rs:28:2: 28:2 -+ } -+ + } + +- bb11: { +- unreachable; // scope 0 at $DIR/early_otherwise_branch_68867.rs:28:2: 28:2 + bb7: { + StorageDead(_35); // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 21:24 + switchInt(_11) -> [0_isize: bb2, 1_isize: bb3, 2_isize: bb4, 3_isize: bb5, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:21:8: 21:24 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 index 000bc6343257b..92024692472ae 100644 --- 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 @@ -41,7 +41,7 @@ _4 = Formatter::sign_plus(move _5) -> bb1; // scope 0 at $DIR/funky_arms.rs:15:22: 15:37 // 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()) } + // + literal: Const { ty: for<'r> fn(&'r Formatter) -> bool {Formatter::sign_plus}, val: Value(Scalar()) } } bb1: { @@ -67,7 +67,7 @@ _7 = Formatter::precision(move _8) -> bb5; // scope 2 at $DIR/funky_arms.rs:24:30: 24:45 // 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()) } + // + literal: Const { ty: for<'r> fn(&'r Formatter) -> Option {Formatter::precision}, val: Value(Scalar()) } } bb5: { @@ -98,7 +98,7 @@ _0 = float_to_exponential_common_exact::(move _11, move _12, move _13, move _14, move _17) -> bb7; // scope 2 at $DIR/funky_arms.rs:26:9: 26:87 // 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()) } + // + literal: Const { ty: for<'r, 's, 't0> fn(&'r mut Formatter<'s>, &'t0 T, Sign, u32, bool) -> Result<(), std::fmt::Error> {float_to_exponential_common_exact::}, val: Value(Scalar()) } } bb7: { @@ -123,7 +123,7 @@ _0 = 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 // 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()) } + // + literal: Const { ty: for<'r, 's, 't0> fn(&'r mut Formatter<'s>, &'t0 T, Sign, bool) -> Result<(), std::fmt::Error> {float_to_exponential_common_shortest::}, val: Value(Scalar()) } } bb9: { diff --git a/src/test/mir-opt/inline/cycle.f.Inline.diff b/src/test/mir-opt/inline/cycle.f.Inline.diff index 54dd545dfb9a6..5624e379bfd27 100644 --- a/src/test/mir-opt/inline/cycle.f.Inline.diff +++ b/src/test/mir-opt/inline/cycle.f.Inline.diff @@ -16,7 +16,7 @@ _2 = >::call(move _3, move _4) -> [return: bb1, unwind: bb3]; // scope 0 at $DIR/cycle.rs:6:5: 6:8 // mir::Constant // + span: $DIR/cycle.rs:6:5: 6:6 - // + literal: Const { ty: for<'r> extern "rust-call" fn(&'r impl Fn(), ()) -> >::Output {>::call}, val: Value(Scalar()) } + // + literal: Const { ty: for<'r> extern "rust-call" fn(&'r impl Fn(), ()) -> >::Output {>::call}, val: Value(Scalar()) } } bb1: { diff --git a/src/test/mir-opt/inline/inline_diverging.g.Inline.diff b/src/test/mir-opt/inline/inline_diverging.g.Inline.diff index ce30b050d67d9..d4f078e2a8a84 100644 --- a/src/test/mir-opt/inline/inline_diverging.g.Inline.diff +++ b/src/test/mir-opt/inline/inline_diverging.g.Inline.diff @@ -40,10 +40,7 @@ - // + span: $DIR/inline-diverging.rs:16:9: 16:14 - // + literal: Const { ty: fn() -> ! {panic}, val: Value(Scalar()) } + // + span: $DIR/inline-diverging.rs:16:9: 16:16 -+ // + literal: Const { ty: fn(&str) -> ! {std::rt::begin_panic::<&str>}, val: Value(Scalar()) } -+ // ty::Const -+ // + ty: &str -+ // + val: Value(Slice { data: Allocation { bytes: [101, 120, 112, 108, 105, 99, 105, 116, 32, 112, 97, 110, 105, 99], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [16383], len: Size { raw: 14 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 14 }) ++ // + literal: Const { ty: fn(&str) -> ! {begin_panic::<&str>}, val: Value(Scalar()) } + // mir::Constant + // + span: $DIR/inline-diverging.rs:16:9: 16:16 + // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [101, 120, 112, 108, 105, 99, 105, 116, 32, 112, 97, 110, 105, 99], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [16383], len: Size { raw: 14 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 14 }) } diff --git a/src/test/mir-opt/inline/inline_generator.main.Inline.diff b/src/test/mir-opt/inline/inline_generator.main.Inline.diff index 29243c9aa75d2..3effe92d314a3 100644 --- a/src/test/mir-opt/inline/inline_generator.main.Inline.diff +++ b/src/test/mir-opt/inline/inline_generator.main.Inline.diff @@ -40,7 +40,7 @@ - _4 = g() -> bb1; // scope 0 at $DIR/inline-generator.rs:9:28: 9:31 - // mir::Constant - // + span: $DIR/inline-generator.rs:9:28: 9:29 -- // + literal: Const { ty: fn() -> impl std::ops::Generator {g}, val: Value(Scalar()) } +- // + literal: Const { ty: fn() -> impl Generator {g}, val: Value(Scalar()) } - } - - bb1: { @@ -50,7 +50,7 @@ - // mir::Constant - // + span: $DIR/inline-generator.rs:9:14: 9:22 - // + user_ty: UserType(0) -- // + literal: Const { ty: fn(&mut impl std::ops::Generator) -> std::pin::Pin<&mut impl std::ops::Generator> {std::pin::Pin::<&mut impl std::ops::Generator>::new}, val: Value(Scalar()) } +- // + literal: Const { ty: fn(&mut impl Generator) -> Pin<&mut impl Generator> {Pin::<&mut impl Generator>::new}, val: Value(Scalar()) } - } - - bb2: { @@ -65,7 +65,7 @@ - _1 = as Generator>::resume(move _2, const false) -> [return: bb3, unwind: bb4]; // scope 0 at $DIR/inline-generator.rs:9:14: 9:46 - // mir::Constant - // + span: $DIR/inline-generator.rs:9:33: 9:39 -- // + literal: Const { ty: for<'r> fn(std::pin::Pin<&'r mut impl std::ops::Generator>, bool) -> std::ops::GeneratorState< as std::ops::Generator>::Yield, as std::ops::Generator>::Return> { as std::ops::Generator>::resume}, val: Value(Scalar()) } +- // + literal: Const { ty: for<'r> fn(Pin<&'r mut impl Generator>, bool) -> GeneratorState< as Generator>::Yield, as Generator>::Return> { as Generator>::resume}, val: Value(Scalar()) } + StorageLive(_7); // scope 0 at $DIR/inline-generator.rs:9:14: 9:46 + _7 = const false; // scope 0 at $DIR/inline-generator.rs:9:14: 9:46 + StorageLive(_10); // scope 0 at $DIR/inline-generator.rs:9:14: 9:46 diff --git a/src/test/mir-opt/inline/inline_into_box_place.main.Inline.32bit.diff b/src/test/mir-opt/inline/inline_into_box_place.main.Inline.32bit.diff index 137a1de522b83..337b9c596852c 100644 --- a/src/test/mir-opt/inline/inline_into_box_place.main.Inline.32bit.diff +++ b/src/test/mir-opt/inline/inline_into_box_place.main.Inline.32bit.diff @@ -35,13 +35,10 @@ + StorageLive(_7); // scope 0 at $DIR/inline-into-box-place.rs:8:33: 8:43 + _7 = &mut (*_5); // scope 0 at $DIR/inline-into-box-place.rs:8:33: 8:43 + ((*_7).0: alloc::raw_vec::RawVec) = const alloc::raw_vec::RawVec:: { ptr: Unique:: { pointer: {0x4 as *const u32}, _marker: PhantomData:: }, cap: 0_usize, alloc: std::alloc::Global }; // scope 3 at $DIR/inline-into-box-place.rs:8:33: 8:43 -+ // ty::Const -+ // + ty: alloc::raw_vec::RawVec -+ // + val: Value(ByRef { alloc: Allocation { bytes: [4, 0, 0, 0, 0, 0, 0, 0], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [255], len: Size { raw: 8 } }, align: Align { pow2: 2 }, mutability: Not, extra: () }, offset: Size { raw: 0 } }) // mir::Constant - // + span: $DIR/inline-into-box-place.rs:8:33: 8:41 - // + user_ty: UserType(1) -- // + literal: Const { ty: fn() -> std::vec::Vec {std::vec::Vec::::new}, val: Value(Scalar()) } +- // + literal: Const { ty: fn() -> Vec {Vec::::new}, val: Value(Scalar()) } - } - - bb2: { @@ -72,7 +69,7 @@ - _6 = alloc::alloc::box_free::, std::alloc::Global>(move (_5.0: std::ptr::Unique>), move (_5.1: std::alloc::Global)) -> bb4; // scope 0 at $DIR/inline-into-box-place.rs:8:42: 8:43 - // mir::Constant - // + span: $DIR/inline-into-box-place.rs:8:42: 8:43 -- // + literal: Const { ty: unsafe fn(std::ptr::Unique>, std::alloc::Global) {alloc::alloc::box_free::, std::alloc::Global>}, val: Value(Scalar()) } +- // + literal: Const { ty: unsafe fn(Unique>, std::alloc::Global) {alloc::alloc::box_free::, std::alloc::Global>}, val: Value(Scalar()) } } } diff --git a/src/test/mir-opt/inline/inline_into_box_place.main.Inline.64bit.diff b/src/test/mir-opt/inline/inline_into_box_place.main.Inline.64bit.diff index 26327d0557461..4c7734a27b7f5 100644 --- a/src/test/mir-opt/inline/inline_into_box_place.main.Inline.64bit.diff +++ b/src/test/mir-opt/inline/inline_into_box_place.main.Inline.64bit.diff @@ -35,13 +35,10 @@ + StorageLive(_7); // scope 0 at $DIR/inline-into-box-place.rs:8:33: 8:43 + _7 = &mut (*_5); // scope 0 at $DIR/inline-into-box-place.rs:8:33: 8:43 + ((*_7).0: alloc::raw_vec::RawVec) = const alloc::raw_vec::RawVec:: { ptr: Unique:: { pointer: {0x4 as *const u32}, _marker: PhantomData:: }, cap: 0_usize, alloc: std::alloc::Global }; // scope 3 at $DIR/inline-into-box-place.rs:8:33: 8:43 -+ // ty::Const -+ // + ty: alloc::raw_vec::RawVec -+ // + val: Value(ByRef { alloc: Allocation { bytes: [4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [65535], len: Size { raw: 16 } }, align: Align { pow2: 3 }, mutability: Not, extra: () }, offset: Size { raw: 0 } }) // mir::Constant - // + span: $DIR/inline-into-box-place.rs:8:33: 8:41 - // + user_ty: UserType(1) -- // + literal: Const { ty: fn() -> std::vec::Vec {std::vec::Vec::::new}, val: Value(Scalar()) } +- // + literal: Const { ty: fn() -> Vec {Vec::::new}, val: Value(Scalar()) } - } - - bb2: { @@ -72,7 +69,7 @@ - _6 = alloc::alloc::box_free::, std::alloc::Global>(move (_5.0: std::ptr::Unique>), move (_5.1: std::alloc::Global)) -> bb4; // scope 0 at $DIR/inline-into-box-place.rs:8:42: 8:43 - // mir::Constant - // + span: $DIR/inline-into-box-place.rs:8:42: 8:43 -- // + literal: Const { ty: unsafe fn(std::ptr::Unique>, std::alloc::Global) {alloc::alloc::box_free::, std::alloc::Global>}, val: Value(Scalar()) } +- // + literal: Const { ty: unsafe fn(Unique>, std::alloc::Global) {alloc::alloc::box_free::, std::alloc::Global>}, val: Value(Scalar()) } } } diff --git a/src/test/mir-opt/inline/inline_retag.bar.Inline.after.mir b/src/test/mir-opt/inline/inline_retag.bar.Inline.after.mir index 5e3ec0889e9d4..53c2c22182f08 100644 --- a/src/test/mir-opt/inline/inline_retag.bar.Inline.after.mir +++ b/src/test/mir-opt/inline/inline_retag.bar.Inline.after.mir @@ -33,12 +33,9 @@ fn bar() -> bool { StorageLive(_3); // scope 1 at $DIR/inline-retag.rs:12:7: 12:9 StorageLive(_4); // scope 1 at $DIR/inline-retag.rs:12:7: 12:9 _10 = const bar::promoted[1]; // scope 1 at $DIR/inline-retag.rs:12:7: 12:9 - // ty::Const - // + ty: &i32 - // + val: Unevaluated(bar, [], Some(promoted[1])) // mir::Constant // + span: $DIR/inline-retag.rs:12:7: 12:9 - // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:4 ~ inline_retag[86d7]::bar), const_param_did: None }, substs: [], promoted: Some(promoted[1]) }) } + // + literal: Const { ty: &i32, val: Unevaluated(bar, [], Some(promoted[1])) } Retag(_10); // scope 1 at $DIR/inline-retag.rs:12:7: 12:9 _4 = &(*_10); // scope 1 at $DIR/inline-retag.rs:12:7: 12:9 Retag(_4); // scope 1 at $DIR/inline-retag.rs:12:7: 12:9 @@ -47,12 +44,9 @@ fn bar() -> bool { StorageLive(_6); // scope 1 at $DIR/inline-retag.rs:12:11: 12:14 StorageLive(_7); // scope 1 at $DIR/inline-retag.rs:12:11: 12:14 _9 = const bar::promoted[0]; // scope 1 at $DIR/inline-retag.rs:12:11: 12:14 - // ty::Const - // + ty: &i32 - // + val: Unevaluated(bar, [], Some(promoted[0])) // mir::Constant // + span: $DIR/inline-retag.rs:12:11: 12:14 - // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:4 ~ inline_retag[86d7]::bar), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) } + // + literal: Const { ty: &i32, val: Unevaluated(bar, [], Some(promoted[0])) } Retag(_9); // scope 1 at $DIR/inline-retag.rs:12:11: 12:14 _7 = &(*_9); // scope 1 at $DIR/inline-retag.rs:12:11: 12:14 Retag(_7); // scope 1 at $DIR/inline-retag.rs:12:11: 12:14 diff --git a/src/test/mir-opt/inline/inline_shims.clone.Inline.diff b/src/test/mir-opt/inline/inline_shims.clone.Inline.diff index 7379d5f219c48..c53e79707876e 100644 --- a/src/test/mir-opt/inline/inline_shims.clone.Inline.diff +++ b/src/test/mir-opt/inline/inline_shims.clone.Inline.diff @@ -14,7 +14,7 @@ - _0 = ::clone(move _2) -> bb1; // scope 0 at $DIR/inline-shims.rs:6:5: 6:14 - // mir::Constant - // + span: $DIR/inline-shims.rs:6:7: 6:12 -- // + literal: Const { ty: for<'r> fn(&'r fn(A, B)) -> fn(A, B) {::clone}, val: Value(Scalar()) } +- // + literal: Const { ty: for<'r> fn(&'r fn(A, B)) -> fn(A, B) {::clone}, val: Value(Scalar()) } - } - - bb1: { diff --git a/src/test/mir-opt/inline/inline_shims.drop.Inline.diff b/src/test/mir-opt/inline/inline_shims.drop.Inline.diff index 9494c4c64184f..d287d3c7a8943 100644 --- a/src/test/mir-opt/inline/inline_shims.drop.Inline.diff +++ b/src/test/mir-opt/inline/inline_shims.drop.Inline.diff @@ -24,7 +24,7 @@ _3 = std::ptr::drop_in_place::>(move _4) -> bb1; // scope 1 at $DIR/inline-shims.rs:11:14: 11:40 // mir::Constant // + span: $DIR/inline-shims.rs:11:14: 11:37 - // + literal: Const { ty: unsafe fn(*mut std::vec::Vec) {std::ptr::drop_in_place::>}, val: Value(Scalar()) } + // + literal: Const { ty: unsafe fn(*mut Vec) {std::ptr::drop_in_place::>}, val: Value(Scalar()) } } bb1: { @@ -35,7 +35,7 @@ - _0 = std::ptr::drop_in_place::>(move _5) -> bb2; // scope 2 at $DIR/inline-shims.rs:12:14: 12:40 - // mir::Constant - // + span: $DIR/inline-shims.rs:12:14: 12:37 -- // + literal: Const { ty: unsafe fn(*mut std::option::Option) {std::ptr::drop_in_place::>}, val: Value(Scalar()) } +- // + literal: Const { ty: unsafe fn(*mut Option) {std::ptr::drop_in_place::>}, val: Value(Scalar()) } + StorageLive(_6); // scope 2 at $DIR/inline-shims.rs:12:14: 12:40 + StorageLive(_7); // scope 2 at $DIR/inline-shims.rs:12:14: 12:40 + _6 = discriminant((*_5)); // scope 3 at $DIR/inline-shims.rs:12:14: 12:40 diff --git a/src/test/mir-opt/inline/inline_specialization.main.Inline.diff b/src/test/mir-opt/inline/inline_specialization.main.Inline.diff index 2a9ce446e307c..4be00dfacb3ee 100644 --- a/src/test/mir-opt/inline/inline_specialization.main.Inline.diff +++ b/src/test/mir-opt/inline/inline_specialization.main.Inline.diff @@ -15,7 +15,7 @@ - _1 = as Foo>::bar() -> bb1; // scope 0 at $DIR/inline-specialization.rs:5:13: 5:38 - // mir::Constant - // + span: $DIR/inline-specialization.rs:5:13: 5:36 -- // + literal: Const { ty: fn() -> u32 { as Foo>::bar}, val: Value(Scalar()) } +- // + literal: Const { ty: fn() -> u32 { as Foo>::bar}, val: Value(Scalar()) } - } - - bb1: { diff --git a/src/test/mir-opt/inline/issue_78442.bar.Inline.diff b/src/test/mir-opt/inline/issue_78442.bar.Inline.diff index 045bc720ca701..0a30bd3d8cafd 100644 --- a/src/test/mir-opt/inline/issue_78442.bar.Inline.diff +++ b/src/test/mir-opt/inline/issue_78442.bar.Inline.diff @@ -28,7 +28,7 @@ - _2 = >::call(move _3, move _5) -> [return: bb2, unwind: bb4]; // scope 0 at $DIR/issue-78442.rs:11:5: 11:17 - // mir::Constant - // + span: $DIR/issue-78442.rs:11:5: 11:15 -- // + literal: Const { ty: for<'r> extern "rust-call" fn(&'r impl Fn(), ()) -> >::Output {>::call}, val: Value(Scalar()) } +- // + literal: Const { ty: for<'r> extern "rust-call" fn(&'r impl Fn(), ()) -> >::Output {>::call}, val: Value(Scalar()) } + _2 = move (*_3)() -> [return: bb5, unwind: bb3]; // scope 1 at $DIR/issue-78442.rs:11:5: 11:17 } diff --git a/src/test/mir-opt/inline/issue_78442.bar.RevealAll.diff b/src/test/mir-opt/inline/issue_78442.bar.RevealAll.diff index 3190db52286bc..a8ae4008cbc96 100644 --- a/src/test/mir-opt/inline/issue_78442.bar.RevealAll.diff +++ b/src/test/mir-opt/inline/issue_78442.bar.RevealAll.diff @@ -28,7 +28,7 @@ _2 = >::call(move _3, move _5) -> [return: bb2, unwind: bb4]; // scope 0 at $DIR/issue-78442.rs:11:5: 11:17 // mir::Constant // + span: $DIR/issue-78442.rs:11:5: 11:15 - // + literal: Const { ty: for<'r> extern "rust-call" fn(&'r impl Fn(), ()) -> >::Output {>::call}, val: Value(Scalar()) } + // + literal: Const { ty: for<'r> extern "rust-call" fn(&'r impl Fn(), ()) -> >::Output {>::call}, val: Value(Scalar()) } } bb2: { diff --git a/src/test/mir-opt/issue_62289.test.ElaborateDrops.before.mir b/src/test/mir-opt/issue_62289.test.ElaborateDrops.before.mir index dde49c77ae7f5..4d06b91e6dc61 100644 --- a/src/test/mir-opt/issue_62289.test.ElaborateDrops.before.mir +++ b/src/test/mir-opt/issue_62289.test.ElaborateDrops.before.mir @@ -46,7 +46,7 @@ fn test() -> Option> { _6 = as Try>::branch(move _7) -> [return: bb2, unwind: bb12]; // scope 0 at $DIR/issue-62289.rs:9:15: 9:20 // mir::Constant // + span: $DIR/issue-62289.rs:9:15: 9:20 - // + literal: Const { ty: fn(std::option::Option) -> std::ops::ControlFlow< as std::ops::Try>::Residual, as std::ops::Try>::Output> { as std::ops::Try>::branch}, val: Value(Scalar()) } + // + literal: Const { ty: fn(Option) -> ControlFlow< as Try>::Residual, as Try>::Output> { as Try>::branch}, val: Value(Scalar()) } } bb2: { @@ -76,7 +76,7 @@ fn test() -> Option> { _0 = > as FromResidual>>::from_residual(move _11) -> [return: bb6, unwind: bb12]; // scope 3 at $DIR/issue-62289.rs:9:15: 9:20 // mir::Constant // + span: $DIR/issue-62289.rs:9:19: 9:20 - // + literal: Const { ty: fn(std::option::Option) -> std::option::Option> {> as std::ops::FromResidual>>::from_residual}, val: Value(Scalar()) } + // + literal: Const { ty: fn(Option) -> Option> {> as FromResidual>>::from_residual}, val: Value(Scalar()) } } bb6: { diff --git a/src/test/mir-opt/issue_72181_1.main.mir_map.0.mir b/src/test/mir-opt/issue_72181_1.main.mir_map.0.mir index 3c26b20c35e2d..5fb57c285beca 100644 --- a/src/test/mir-opt/issue_72181_1.main.mir_map.0.mir +++ b/src/test/mir-opt/issue_72181_1.main.mir_map.0.mir @@ -24,7 +24,7 @@ fn main() -> () { _2 = transmute::<(), Void>(move _3) -> [return: bb1, unwind: bb4]; // scope 2 at $DIR/issue-72181-1.rs:17:9: 17:44 // mir::Constant // + span: $DIR/issue-72181-1.rs:17:9: 17:40 - // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(()) -> Void {std::intrinsics::transmute::<(), Void>}, val: Value(Scalar()) } + // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(()) -> Void {transmute::<(), Void>}, val: Value(Scalar()) } } bb1: { diff --git a/src/test/mir-opt/issue_73223.main.PreCodegen.32bit.diff b/src/test/mir-opt/issue_73223.main.PreCodegen.32bit.diff index 016e0cb590173..240da5577dee5 100644 --- a/src/test/mir-opt/issue_73223.main.PreCodegen.32bit.diff +++ b/src/test/mir-opt/issue_73223.main.PreCodegen.32bit.diff @@ -61,12 +61,9 @@ _7 = &_1; // 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 _20 = const main::promoted[0]; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - // ty::Const - // + ty: &i32 - // + val: Unevaluated(main, [], Some(promoted[0])) // mir::Constant // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL - // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ issue_73223[9565]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) } + // + literal: Const { ty: &i32, val: Unevaluated(main, [], Some(promoted[0])) } _8 = _20; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL (_6.0: &i32) = move _7; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL (_6.1: &i32) = move _8; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL @@ -103,10 +100,7 @@ core::panicking::assert_failed::(const core::panicking::AssertKind::Eq, move _15, move _17, move _19); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL // mir::Constant // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL - // + literal: Const { ty: for<'r, 's, 't0> fn(core::panicking::AssertKind, &'r i32, &'s i32, std::option::Option>) -> ! {core::panicking::assert_failed::}, val: Value(Scalar()) } - // ty::Const - // + ty: core::panicking::AssertKind - // + val: Value(Scalar(0x00)) + // + literal: Const { ty: for<'r, 's, 't0> fn(core::panicking::AssertKind, &'r i32, &'s i32, Option>) -> ! {core::panicking::assert_failed::}, val: Value(Scalar()) } // mir::Constant // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL // + literal: Const { ty: core::panicking::AssertKind, val: Value(Scalar(0x00)) } diff --git a/src/test/mir-opt/issue_73223.main.PreCodegen.64bit.diff b/src/test/mir-opt/issue_73223.main.PreCodegen.64bit.diff index 016e0cb590173..240da5577dee5 100644 --- a/src/test/mir-opt/issue_73223.main.PreCodegen.64bit.diff +++ b/src/test/mir-opt/issue_73223.main.PreCodegen.64bit.diff @@ -61,12 +61,9 @@ _7 = &_1; // 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 _20 = const main::promoted[0]; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - // ty::Const - // + ty: &i32 - // + val: Unevaluated(main, [], Some(promoted[0])) // mir::Constant // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL - // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ issue_73223[9565]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) } + // + literal: Const { ty: &i32, val: Unevaluated(main, [], Some(promoted[0])) } _8 = _20; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL (_6.0: &i32) = move _7; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL (_6.1: &i32) = move _8; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL @@ -103,10 +100,7 @@ core::panicking::assert_failed::(const core::panicking::AssertKind::Eq, move _15, move _17, move _19); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL // mir::Constant // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL - // + literal: Const { ty: for<'r, 's, 't0> fn(core::panicking::AssertKind, &'r i32, &'s i32, std::option::Option>) -> ! {core::panicking::assert_failed::}, val: Value(Scalar()) } - // ty::Const - // + ty: core::panicking::AssertKind - // + val: Value(Scalar(0x00)) + // + literal: Const { ty: for<'r, 's, 't0> fn(core::panicking::AssertKind, &'r i32, &'s i32, Option>) -> ! {core::panicking::assert_failed::}, val: Value(Scalar()) } // mir::Constant // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL // + literal: Const { ty: core::panicking::AssertKind, val: Value(Scalar(0x00)) } diff --git a/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.32bit.diff b/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.32bit.diff index 59daeb1e997ba..1e8b681dfad46 100644 --- a/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.32bit.diff +++ b/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.32bit.diff @@ -82,12 +82,9 @@ _10 = &_1; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageLive(_11); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL _28 = const main::promoted[0]; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - // ty::Const - // + ty: &i32 - // + val: Unevaluated(main, [], Some(promoted[0])) // mir::Constant // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL - // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ issue_73223[9565]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) } + // + literal: Const { ty: &i32, val: Unevaluated(main, [], Some(promoted[0])) } _11 = _28; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL (_9.0: &i32) = move _10; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL (_9.1: &i32) = move _11; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL @@ -117,9 +114,6 @@ StorageLive(_21); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageLive(_22); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL _22 = const core::panicking::AssertKind::Eq; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - // ty::Const - // + ty: core::panicking::AssertKind - // + val: Value(Scalar(0x00)) // mir::Constant // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL // + literal: Const { ty: core::panicking::AssertKind, val: Value(Scalar(0x00)) } @@ -136,10 +130,7 @@ core::panicking::assert_failed::(const core::panicking::AssertKind::Eq, move _23, move _25, move _27); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL // mir::Constant // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL - // + literal: Const { ty: for<'r, 's, 't0> fn(core::panicking::AssertKind, &'r i32, &'s i32, std::option::Option>) -> ! {core::panicking::assert_failed::}, val: Value(Scalar()) } - // ty::Const - // + ty: core::panicking::AssertKind - // + val: Value(Scalar(0x00)) + // + literal: Const { ty: for<'r, 's, 't0> fn(core::panicking::AssertKind, &'r i32, &'s i32, Option>) -> ! {core::panicking::assert_failed::}, val: Value(Scalar()) } // mir::Constant // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL // + literal: Const { ty: core::panicking::AssertKind, val: Value(Scalar(0x00)) } diff --git a/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.64bit.diff b/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.64bit.diff index 59daeb1e997ba..1e8b681dfad46 100644 --- a/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.64bit.diff +++ b/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.64bit.diff @@ -82,12 +82,9 @@ _10 = &_1; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageLive(_11); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL _28 = const main::promoted[0]; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - // ty::Const - // + ty: &i32 - // + val: Unevaluated(main, [], Some(promoted[0])) // mir::Constant // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL - // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ issue_73223[9565]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) } + // + literal: Const { ty: &i32, val: Unevaluated(main, [], Some(promoted[0])) } _11 = _28; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL (_9.0: &i32) = move _10; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL (_9.1: &i32) = move _11; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL @@ -117,9 +114,6 @@ StorageLive(_21); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageLive(_22); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL _22 = const core::panicking::AssertKind::Eq; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - // ty::Const - // + ty: core::panicking::AssertKind - // + val: Value(Scalar(0x00)) // mir::Constant // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL // + literal: Const { ty: core::panicking::AssertKind, val: Value(Scalar(0x00)) } @@ -136,10 +130,7 @@ core::panicking::assert_failed::(const core::panicking::AssertKind::Eq, move _23, move _25, move _27); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL // mir::Constant // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL - // + literal: Const { ty: for<'r, 's, 't0> fn(core::panicking::AssertKind, &'r i32, &'s i32, std::option::Option>) -> ! {core::panicking::assert_failed::}, val: Value(Scalar()) } - // ty::Const - // + ty: core::panicking::AssertKind - // + val: Value(Scalar(0x00)) + // + literal: Const { ty: for<'r, 's, 't0> fn(core::panicking::AssertKind, &'r i32, &'s i32, Option>) -> ! {core::panicking::assert_failed::}, val: Value(Scalar()) } // mir::Constant // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL // + literal: Const { ty: core::panicking::AssertKind, val: Value(Scalar(0x00)) } diff --git a/src/test/mir-opt/issue_76432.test.SimplifyComparisonIntegral.diff b/src/test/mir-opt/issue_76432.test.SimplifyComparisonIntegral.diff index 1a454bab4d0d9..c1a4fc301d7cd 100644 --- a/src/test/mir-opt/issue_76432.test.SimplifyComparisonIntegral.diff +++ b/src/test/mir-opt/issue_76432.test.SimplifyComparisonIntegral.diff @@ -71,9 +71,6 @@ // mir::Constant // + span: $SRC_DIR/core/src/panic.rs:LL:COL // + literal: Const { ty: fn(&'static str) -> ! {core::panicking::panic}, val: Value(Scalar()) } - // ty::Const - // + ty: &str - // + val: Value(Slice { data: Allocation { bytes: [105, 110, 116, 101, 114, 110, 97, 108, 32, 101, 114, 114, 111, 114, 58, 32, 101, 110, 116, 101, 114, 101, 100, 32, 117, 110, 114, 101, 97, 99, 104, 97, 98, 108, 101, 32, 99, 111, 100, 101], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1099511627775], len: Size { raw: 40 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 40 }) // mir::Constant // + span: $SRC_DIR/core/src/panic.rs:LL:COL // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [105, 110, 116, 101, 114, 110, 97, 108, 32, 101, 114, 114, 111, 114, 58, 32, 101, 110, 116, 101, 114, 101, 100, 32, 117, 110, 114, 101, 97, 99, 104, 97, 98, 108, 101, 32, 99, 111, 100, 101], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1099511627775], len: Size { raw: 40 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 40 }) } diff --git a/src/test/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.mir b/src/test/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.mir index d028f0b989a68..1c3df5e90cc32 100644 --- a/src/test/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.mir +++ b/src/test/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.mir @@ -39,7 +39,7 @@ fn num_to_digit(_1: char) -> u32 { _7 = char::methods::::to_digit(move _8, const 8_u32) -> bb5; // scope 1 at $DIR/issue-59352.rs:14:8: 14:23 // mir::Constant // + span: $DIR/issue-59352.rs:14:8: 14:23 - // + literal: Const { ty: fn(char, u32) -> std::option::Option {std::char::methods::::to_digit}, val: Value(Scalar()) } + // + literal: Const { ty: fn(char, u32) -> Option {char::methods::::to_digit}, val: Value(Scalar()) } } bb1: { @@ -50,7 +50,7 @@ fn num_to_digit(_1: char) -> u32 { _3 = char::methods::::to_digit(move _4, const 8_u32) -> bb2; // scope 0 at $DIR/issue-59352.rs:14:26: 14:41 // mir::Constant // + span: $DIR/issue-59352.rs:14:30: 14:38 - // + literal: Const { ty: fn(char, u32) -> std::option::Option {std::char::methods::::to_digit}, val: Value(Scalar()) } + // + literal: Const { ty: fn(char, u32) -> Option {char::methods::::to_digit}, val: Value(Scalar()) } } bb2: { @@ -90,9 +90,6 @@ fn num_to_digit(_1: char) -> u32 { // mir::Constant // + span: $DIR/issue-59352.rs:14:26: 14:50 // + literal: Const { ty: fn(&'static str) -> ! {core::panicking::panic}, val: Value(Scalar()) } - // ty::Const - // + ty: &str - // + val: Value(Slice { data: Allocation { bytes: [99, 97, 108, 108, 101, 100, 32, 96, 79, 112, 116, 105, 111, 110, 58, 58, 117, 110, 119, 114, 97, 112, 40, 41, 96, 32, 111, 110, 32, 97, 32, 96, 78, 111, 110, 101, 96, 32, 118, 97, 108, 117, 101], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [8796093022207], len: Size { raw: 43 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 43 }) // mir::Constant // + span: $DIR/issue-59352.rs:14:26: 14:50 // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [99, 97, 108, 108, 101, 100, 32, 96, 79, 112, 116, 105, 111, 110, 58, 58, 117, 110, 119, 114, 97, 112, 40, 41, 96, 32, 111, 110, 32, 97, 32, 96, 78, 111, 110, 101, 96, 32, 118, 97, 108, 117, 101], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [8796093022207], len: Size { raw: 43 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 43 }) } diff --git a/src/test/mir-opt/issues/issue_75439.foo.MatchBranchSimplification.diff b/src/test/mir-opt/issues/issue_75439.foo.MatchBranchSimplification.diff index 4630c40875014..39448a16f1aba 100644 --- a/src/test/mir-opt/issues/issue_75439.foo.MatchBranchSimplification.diff +++ b/src/test/mir-opt/issues/issue_75439.foo.MatchBranchSimplification.diff @@ -27,7 +27,7 @@ _2 = transmute::<[u8; 16], [u32; 4]>(move _3) -> bb1; // scope 2 at $DIR/issue-75439.rs:7:37: 7:53 // mir::Constant // + span: $DIR/issue-75439.rs:7:37: 7:46 - // + literal: Const { ty: unsafe extern "rust-intrinsic" fn([u8; 16]) -> [u32; 4] {std::intrinsics::transmute::<[u8; 16], [u32; 4]>}, val: Value(Scalar()) } + // + literal: Const { ty: unsafe extern "rust-intrinsic" fn([u8; 16]) -> [u32; 4] {transmute::<[u8; 16], [u32; 4]>}, val: Value(Scalar()) } } bb1: { @@ -50,7 +50,7 @@ _5 = transmute::(move _6) -> bb7; // scope 4 at $DIR/issue-75439.rs:10:23: 10:36 // mir::Constant // + span: $DIR/issue-75439.rs:10:23: 10:32 - // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(u32) -> [u8; 4] {std::intrinsics::transmute::}, val: Value(Scalar()) } + // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(u32) -> [u8; 4] {transmute::}, val: Value(Scalar()) } } bb5: { diff --git a/src/test/mir-opt/lower_intrinsics.discriminant.LowerIntrinsics.diff b/src/test/mir-opt/lower_intrinsics.discriminant.LowerIntrinsics.diff index 644a5593a9db1..88d2867fc42ab 100644 --- a/src/test/mir-opt/lower_intrinsics.discriminant.LowerIntrinsics.diff +++ b/src/test/mir-opt/lower_intrinsics.discriminant.LowerIntrinsics.diff @@ -32,7 +32,7 @@ - _2 = discriminant_value::(move _3) -> bb1; // scope 0 at $DIR/lower_intrinsics.rs:74:5: 74:45 - // mir::Constant - // + span: $DIR/lower_intrinsics.rs:74:5: 74:41 -- // + literal: Const { ty: for<'r> extern "rust-intrinsic" fn(&'r T) -> ::Discriminant {std::intrinsics::discriminant_value::}, val: Value(Scalar()) } +- // + literal: Const { ty: for<'r> extern "rust-intrinsic" fn(&'r T) -> ::Discriminant {discriminant_value::}, val: Value(Scalar()) } + _2 = discriminant((*_3)); // scope 0 at $DIR/lower_intrinsics.rs:74:5: 74:45 + goto -> bb1; // scope 0 at $DIR/lower_intrinsics.rs:74:5: 74:45 } @@ -45,18 +45,15 @@ StorageLive(_6); // scope 0 at $DIR/lower_intrinsics.rs:75:42: 75:44 StorageLive(_7); // scope 0 at $DIR/lower_intrinsics.rs:75:42: 75:44 _19 = const discriminant::::promoted[2]; // scope 0 at $DIR/lower_intrinsics.rs:75:42: 75:44 - // ty::Const - // + ty: &i32 - // + val: Unevaluated(discriminant, [T], Some(promoted[2])) // mir::Constant // + span: $DIR/lower_intrinsics.rs:75:42: 75:44 - // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:29 ~ lower_intrinsics[49eb]::discriminant), const_param_did: None }, substs: [T], promoted: Some(promoted[2]) }) } + // + literal: Const { ty: &i32, val: Unevaluated(discriminant, [T], Some(promoted[2])) } _7 = &(*_19); // scope 0 at $DIR/lower_intrinsics.rs:75:42: 75:44 _6 = &(*_7); // scope 0 at $DIR/lower_intrinsics.rs:75:42: 75:44 - _5 = discriminant_value::(move _6) -> bb2; // scope 0 at $DIR/lower_intrinsics.rs:75:5: 75:45 - // mir::Constant - // + span: $DIR/lower_intrinsics.rs:75:5: 75:41 -- // + literal: Const { ty: for<'r> extern "rust-intrinsic" fn(&'r i32) -> ::Discriminant {std::intrinsics::discriminant_value::}, val: Value(Scalar()) } +- // + literal: Const { ty: for<'r> extern "rust-intrinsic" fn(&'r i32) -> ::Discriminant {discriminant_value::}, val: Value(Scalar()) } + _5 = discriminant((*_6)); // scope 0 at $DIR/lower_intrinsics.rs:75:5: 75:45 + goto -> bb2; // scope 0 at $DIR/lower_intrinsics.rs:75:5: 75:45 } @@ -69,18 +66,15 @@ StorageLive(_10); // scope 0 at $DIR/lower_intrinsics.rs:76:42: 76:45 StorageLive(_11); // scope 0 at $DIR/lower_intrinsics.rs:76:42: 76:45 _18 = const discriminant::::promoted[1]; // scope 0 at $DIR/lower_intrinsics.rs:76:42: 76:45 - // ty::Const - // + ty: &() - // + val: Unevaluated(discriminant, [T], Some(promoted[1])) // mir::Constant // + span: $DIR/lower_intrinsics.rs:76:42: 76:45 - // + literal: Const { ty: &(), val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:29 ~ lower_intrinsics[49eb]::discriminant), const_param_did: None }, substs: [T], promoted: Some(promoted[1]) }) } + // + literal: Const { ty: &(), val: Unevaluated(discriminant, [T], Some(promoted[1])) } _11 = &(*_18); // scope 0 at $DIR/lower_intrinsics.rs:76:42: 76:45 _10 = &(*_11); // scope 0 at $DIR/lower_intrinsics.rs:76:42: 76:45 - _9 = discriminant_value::<()>(move _10) -> bb3; // scope 0 at $DIR/lower_intrinsics.rs:76:5: 76:46 - // mir::Constant - // + span: $DIR/lower_intrinsics.rs:76:5: 76:41 -- // + literal: Const { ty: for<'r> extern "rust-intrinsic" fn(&'r ()) -> <() as std::marker::DiscriminantKind>::Discriminant {std::intrinsics::discriminant_value::<()>}, val: Value(Scalar()) } +- // + literal: Const { ty: for<'r> extern "rust-intrinsic" fn(&'r ()) -> <() as DiscriminantKind>::Discriminant {discriminant_value::<()>}, val: Value(Scalar()) } + _9 = discriminant((*_10)); // scope 0 at $DIR/lower_intrinsics.rs:76:5: 76:46 + goto -> bb3; // scope 0 at $DIR/lower_intrinsics.rs:76:5: 76:46 } @@ -93,18 +87,15 @@ StorageLive(_14); // scope 0 at $DIR/lower_intrinsics.rs:77:42: 77:47 StorageLive(_15); // scope 0 at $DIR/lower_intrinsics.rs:77:42: 77:47 _17 = const discriminant::::promoted[0]; // scope 0 at $DIR/lower_intrinsics.rs:77:42: 77:47 - // ty::Const - // + ty: &E - // + val: Unevaluated(discriminant, [T], Some(promoted[0])) // mir::Constant // + span: $DIR/lower_intrinsics.rs:77:42: 77:47 - // + literal: Const { ty: &E, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:29 ~ lower_intrinsics[49eb]::discriminant), const_param_did: None }, substs: [T], promoted: Some(promoted[0]) }) } + // + literal: Const { ty: &E, val: Unevaluated(discriminant, [T], Some(promoted[0])) } _15 = &(*_17); // scope 0 at $DIR/lower_intrinsics.rs:77:42: 77:47 _14 = &(*_15); // scope 0 at $DIR/lower_intrinsics.rs:77:42: 77:47 - _13 = discriminant_value::(move _14) -> bb4; // scope 0 at $DIR/lower_intrinsics.rs:77:5: 77:48 - // mir::Constant - // + span: $DIR/lower_intrinsics.rs:77:5: 77:41 -- // + literal: Const { ty: for<'r> extern "rust-intrinsic" fn(&'r E) -> ::Discriminant {std::intrinsics::discriminant_value::}, val: Value(Scalar()) } +- // + literal: Const { ty: for<'r> extern "rust-intrinsic" fn(&'r E) -> ::Discriminant {discriminant_value::}, val: Value(Scalar()) } + _13 = discriminant((*_14)); // scope 0 at $DIR/lower_intrinsics.rs:77:5: 77:48 + goto -> bb4; // scope 0 at $DIR/lower_intrinsics.rs:77:5: 77:48 } diff --git a/src/test/mir-opt/lower_intrinsics.wrapping.LowerIntrinsics.diff b/src/test/mir-opt/lower_intrinsics.wrapping.LowerIntrinsics.diff index badfef30e6fc5..a531a19bd7820 100644 --- a/src/test/mir-opt/lower_intrinsics.wrapping.LowerIntrinsics.diff +++ b/src/test/mir-opt/lower_intrinsics.wrapping.LowerIntrinsics.diff @@ -33,7 +33,7 @@ - _3 = wrapping_add::(move _4, move _5) -> bb1; // scope 0 at $DIR/lower_intrinsics.rs:7:14: 7:50 - // mir::Constant - // + span: $DIR/lower_intrinsics.rs:7:14: 7:44 -- // + literal: Const { ty: extern "rust-intrinsic" fn(T, T) -> T {std::intrinsics::wrapping_add::}, val: Value(Scalar()) } +- // + literal: Const { ty: extern "rust-intrinsic" fn(T, T) -> T {wrapping_add::}, val: Value(Scalar()) } + _3 = Add(move _4, move _5); // scope 0 at $DIR/lower_intrinsics.rs:7:14: 7:50 + goto -> bb1; // scope 0 at $DIR/lower_intrinsics.rs:7:14: 7:50 } @@ -49,7 +49,7 @@ - _6 = wrapping_sub::(move _7, move _8) -> bb2; // scope 1 at $DIR/lower_intrinsics.rs:8:14: 8:50 - // mir::Constant - // + span: $DIR/lower_intrinsics.rs:8:14: 8:44 -- // + literal: Const { ty: extern "rust-intrinsic" fn(T, T) -> T {std::intrinsics::wrapping_sub::}, val: Value(Scalar()) } +- // + literal: Const { ty: extern "rust-intrinsic" fn(T, T) -> T {wrapping_sub::}, val: Value(Scalar()) } + _6 = Sub(move _7, move _8); // scope 1 at $DIR/lower_intrinsics.rs:8:14: 8:50 + goto -> bb2; // scope 1 at $DIR/lower_intrinsics.rs:8:14: 8:50 } @@ -65,7 +65,7 @@ - _9 = wrapping_mul::(move _10, move _11) -> bb3; // scope 2 at $DIR/lower_intrinsics.rs:9:14: 9:50 - // mir::Constant - // + span: $DIR/lower_intrinsics.rs:9:14: 9:44 -- // + literal: Const { ty: extern "rust-intrinsic" fn(T, T) -> T {std::intrinsics::wrapping_mul::}, val: Value(Scalar()) } +- // + literal: Const { ty: extern "rust-intrinsic" fn(T, T) -> T {wrapping_mul::}, val: Value(Scalar()) } + _9 = Mul(move _10, move _11); // scope 2 at $DIR/lower_intrinsics.rs:9:14: 9:50 + goto -> bb3; // scope 2 at $DIR/lower_intrinsics.rs:9:14: 9:50 } diff --git a/src/test/mir-opt/match_false_edges.full_tested_match.PromoteTemps.after.mir b/src/test/mir-opt/match_false_edges.full_tested_match.PromoteTemps.after.mir index b3a9365396c9a..e49b9898dfac7 100644 --- a/src/test/mir-opt/match_false_edges.full_tested_match.PromoteTemps.after.mir +++ b/src/test/mir-opt/match_false_edges.full_tested_match.PromoteTemps.after.mir @@ -52,12 +52,9 @@ fn full_tested_match() -> () { bb5: { StorageLive(_6); // scope 0 at $DIR/match_false_edges.rs:16:14: 16:15 _11 = const full_tested_match::promoted[0]; // scope 0 at $DIR/match_false_edges.rs:16:14: 16:15 - // ty::Const - // + ty: &std::option::Option - // + val: Unevaluated(full_tested_match, [], Some(promoted[0])) // mir::Constant // + span: $DIR/match_false_edges.rs:16:14: 16:15 - // + literal: Const { ty: &std::option::Option, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:5 ~ match_false_edges[5411]::full_tested_match), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) } + // + literal: Const { ty: &Option, val: Unevaluated(full_tested_match, [], Some(promoted[0])) } _6 = &(((*_11) as Some).0: i32); // scope 0 at $DIR/match_false_edges.rs:16:14: 16:15 _4 = &shallow _2; // scope 0 at $DIR/match_false_edges.rs:15:19: 15:27 StorageLive(_7); // scope 0 at $DIR/match_false_edges.rs:16:20: 16:27 diff --git a/src/test/mir-opt/no_drop_for_inactive_variant.unwrap.SimplifyCfg-elaborate-drops.after.mir b/src/test/mir-opt/no_drop_for_inactive_variant.unwrap.SimplifyCfg-elaborate-drops.after.mir index cc4457cc5f3ff..d562f04560c34 100644 --- a/src/test/mir-opt/no_drop_for_inactive_variant.unwrap.SimplifyCfg-elaborate-drops.after.mir +++ b/src/test/mir-opt/no_drop_for_inactive_variant.unwrap.SimplifyCfg-elaborate-drops.after.mir @@ -23,10 +23,7 @@ fn unwrap(_1: Option) -> T { begin_panic::<&str>(const "explicit panic") -> bb4; // scope 0 at $SRC_DIR/std/src/panic.rs:LL:COL // mir::Constant // + span: $SRC_DIR/std/src/panic.rs:LL:COL - // + literal: Const { ty: fn(&str) -> ! {std::rt::begin_panic::<&str>}, val: Value(Scalar()) } - // ty::Const - // + ty: &str - // + val: Value(Slice { data: Allocation { bytes: [101, 120, 112, 108, 105, 99, 105, 116, 32, 112, 97, 110, 105, 99], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [16383], len: Size { raw: 14 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 14 }) + // + literal: Const { ty: fn(&str) -> ! {begin_panic::<&str>}, val: Value(Scalar()) } // mir::Constant // + span: $SRC_DIR/std/src/panic.rs:LL:COL // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [101, 120, 112, 108, 105, 99, 105, 116, 32, 112, 97, 110, 105, 99], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [16383], len: Size { raw: 14 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 14 }) } diff --git a/src/test/mir-opt/no_spurious_drop_after_call.main.ElaborateDrops.before.mir b/src/test/mir-opt/no_spurious_drop_after_call.main.ElaborateDrops.before.mir index 5c55ee4b9bb40..22bf1acc57d72 100644 --- a/src/test/mir-opt/no_spurious_drop_after_call.main.ElaborateDrops.before.mir +++ b/src/test/mir-opt/no_spurious_drop_after_call.main.ElaborateDrops.before.mir @@ -13,9 +13,6 @@ fn main() -> () { StorageLive(_3); // scope 0 at $DIR/no-spurious-drop-after-call.rs:9:20: 9:34 StorageLive(_4); // scope 0 at $DIR/no-spurious-drop-after-call.rs:9:20: 9:22 _4 = const ""; // scope 0 at $DIR/no-spurious-drop-after-call.rs:9:20: 9:22 - // ty::Const - // + ty: &str - // + val: Value(Slice { data: Allocation { bytes: [], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [], len: Size { raw: 0 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 0 }) // mir::Constant // + span: $DIR/no-spurious-drop-after-call.rs:9:20: 9:22 // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [], len: Size { raw: 0 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 0 }) } @@ -23,7 +20,7 @@ fn main() -> () { _2 = ::to_string(move _3) -> bb1; // scope 0 at $DIR/no-spurious-drop-after-call.rs:9:20: 9:34 // mir::Constant // + span: $DIR/no-spurious-drop-after-call.rs:9:23: 9:32 - // + literal: Const { ty: for<'r> fn(&'r str) -> std::string::String {::to_string}, val: Value(Scalar()) } + // + literal: Const { ty: for<'r> fn(&'r str) -> String {::to_string}, val: Value(Scalar()) } } bb1: { @@ -31,7 +28,7 @@ fn main() -> () { _1 = std::mem::drop::(move _2) -> [return: bb2, unwind: bb3]; // scope 0 at $DIR/no-spurious-drop-after-call.rs:9:5: 9:35 // mir::Constant // + span: $DIR/no-spurious-drop-after-call.rs:9:5: 9:19 - // + literal: Const { ty: fn(std::string::String) {std::mem::drop::}, val: Value(Scalar()) } + // + literal: Const { ty: fn(String) {std::mem::drop::}, val: Value(Scalar()) } } bb2: { diff --git a/src/test/mir-opt/receiver_ptr_mutability.main.mir_map.0.mir b/src/test/mir-opt/receiver_ptr_mutability.main.mir_map.0.mir index f1a1f388c501a..945290b6a82e0 100644 --- a/src/test/mir-opt/receiver_ptr_mutability.main.mir_map.0.mir +++ b/src/test/mir-opt/receiver_ptr_mutability.main.mir_map.0.mir @@ -32,7 +32,7 @@ fn main() -> () { _1 = null_mut::() -> [return: bb1, unwind: bb4]; // scope 0 at $DIR/receiver-ptr-mutability.rs:14:26: 14:46 // mir::Constant // + span: $DIR/receiver-ptr-mutability.rs:14:26: 14:44 - // + literal: Const { ty: fn() -> *mut Test {std::ptr::null_mut::}, val: Value(Scalar()) } + // + literal: Const { ty: fn() -> *mut Test {null_mut::}, val: Value(Scalar()) } } bb1: { diff --git a/src/test/mir-opt/remove_storage_markers.main.RemoveStorageMarkers.diff b/src/test/mir-opt/remove_storage_markers.main.RemoveStorageMarkers.diff index 2dfc94f21868e..f1435f4c40a4c 100644 --- a/src/test/mir-opt/remove_storage_markers.main.RemoveStorageMarkers.diff +++ b/src/test/mir-opt/remove_storage_markers.main.RemoveStorageMarkers.diff @@ -59,7 +59,7 @@ _7 = as iter::range::RangeIteratorImpl>::spec_next(move _14) -> bb4; // scope 5 at $DIR/remove_storage_markers.rs:8:14: 8:19 // mir::Constant // + span: $DIR/remove_storage_markers.rs:8:14: 8:19 - // + literal: Const { ty: for<'r> fn(&'r mut std::ops::Range) -> std::option::Option< as std::iter::range::RangeIteratorImpl>::Item> { as std::iter::range::RangeIteratorImpl>::spec_next}, val: Value(Scalar()) } + // + literal: Const { ty: for<'r> fn(&'r mut std::ops::Range) -> Option< as iter::range::RangeIteratorImpl>::Item> { as iter::range::RangeIteratorImpl>::spec_next}, val: Value(Scalar()) } } bb2: { diff --git a/src/test/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.mir b/src/test/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.mir index 54d836ba609c8..5c2a7e2f253f6 100644 --- a/src/test/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.mir +++ b/src/test/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.mir @@ -81,7 +81,7 @@ fn array_casts() -> () { _6 = ptr::mut_ptr::::add(move _7, const 1_usize) -> bb1; // scope 3 at $DIR/retag.rs:60:15: 60:23 // mir::Constant // + span: $DIR/retag.rs:60:17: 60:20 - // + literal: Const { ty: unsafe fn(*mut usize, usize) -> *mut usize {std::ptr::mut_ptr::::add}, val: Value(Scalar()) } + // + literal: Const { ty: unsafe fn(*mut usize, usize) -> *mut usize {ptr::mut_ptr::::add}, val: Value(Scalar()) } } bb1: { @@ -112,7 +112,7 @@ fn array_casts() -> () { _16 = ptr::const_ptr::::add(move _17, const 1_usize) -> bb2; // scope 6 at $DIR/retag.rs:64:26: 64:34 // mir::Constant // + span: $DIR/retag.rs:64:28: 64:31 - // + literal: Const { ty: unsafe fn(*const usize, usize) -> *const usize {std::ptr::const_ptr::::add}, val: Value(Scalar()) } + // + literal: Const { ty: unsafe fn(*const usize, usize) -> *const usize {ptr::const_ptr::::add}, val: Value(Scalar()) } } bb2: { @@ -122,12 +122,9 @@ fn array_casts() -> () { Retag(_14); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageLive(_18); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL _35 = const array_casts::promoted[0]; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - // ty::Const - // + ty: &usize - // + val: Unevaluated(array_casts, [], Some(promoted[0])) // mir::Constant // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL - // + literal: Const { ty: &usize, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:15 ~ retag[4622]::array_casts), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) } + // + literal: Const { ty: &usize, val: Unevaluated(array_casts, [], Some(promoted[0])) } Retag(_35); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL _18 = &(*_35); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL Retag(_18); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL @@ -177,7 +174,7 @@ fn array_casts() -> () { core::panicking::assert_failed::(move _29, move _30, move _32, move _34); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL // mir::Constant // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL - // + literal: Const { ty: for<'r, 's, 't0> fn(core::panicking::AssertKind, &'r usize, &'s usize, std::option::Option>) -> ! {core::panicking::assert_failed::}, val: Value(Scalar()) } + // + literal: Const { ty: for<'r, 's, 't0> fn(core::panicking::AssertKind, &'r usize, &'s usize, Option>) -> ! {core::panicking::assert_failed::}, val: Value(Scalar()) } } bb4: { diff --git a/src/test/mir-opt/retag.core.ptr-drop_in_place.Test.SimplifyCfg-make_shim.after.mir b/src/test/mir-opt/retag.core.ptr-drop_in_place.Test.SimplifyCfg-make_shim.after.mir index aadc1db0e0d3a..09cf06cacd920 100644 --- a/src/test/mir-opt/retag.core.ptr-drop_in_place.Test.SimplifyCfg-make_shim.after.mir +++ b/src/test/mir-opt/retag.core.ptr-drop_in_place.Test.SimplifyCfg-make_shim.after.mir @@ -11,7 +11,7 @@ fn std::ptr::drop_in_place(_1: *mut Test) -> () { _3 = ::drop(move _2) -> bb1; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL // mir::Constant // + span: $SRC_DIR/core/src/ptr/mod.rs:LL:COL - // + literal: Const { ty: for<'r> fn(&'r mut Test) {::drop}, val: Value(Scalar()) } + // + literal: Const { ty: for<'r> fn(&'r mut Test) {::drop}, val: Value(Scalar()) } } bb1: { diff --git a/src/test/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.mir b/src/test/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.mir index 29a72feed7d30..2fda8c949b00c 100644 --- a/src/test/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.mir +++ b/src/test/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.mir @@ -148,12 +148,9 @@ fn main() -> () { StorageLive(_22); // scope 7 at $DIR/retag.rs:47:21: 47:23 StorageLive(_23); // scope 7 at $DIR/retag.rs:47:21: 47:23 _28 = const main::promoted[0]; // scope 7 at $DIR/retag.rs:47:21: 47:23 - // ty::Const - // + ty: &i32 - // + val: Unevaluated(main, [], Some(promoted[0])) // mir::Constant // + span: $DIR/retag.rs:47:21: 47:23 - // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:13 ~ retag[4622]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) } + // + literal: Const { ty: &i32, val: Unevaluated(main, [], Some(promoted[0])) } Retag(_28); // scope 7 at $DIR/retag.rs:47:21: 47:23 _23 = &(*_28); // scope 7 at $DIR/retag.rs:47:21: 47:23 Retag(_23); // scope 7 at $DIR/retag.rs:47:21: 47:23 diff --git a/src/test/mir-opt/simplify_locals.d2.SimplifyLocals.diff b/src/test/mir-opt/simplify_locals.d2.SimplifyLocals.diff index 1448001dd415c..cf20e83ef06b7 100644 --- a/src/test/mir-opt/simplify_locals.d2.SimplifyLocals.diff +++ b/src/test/mir-opt/simplify_locals.d2.SimplifyLocals.diff @@ -15,17 +15,11 @@ - discriminant(_3) = 0; // scope 0 at $DIR/simplify-locals.rs:28:11: 28:15 - (_2.0: i32) = const 10_i32; // scope 0 at $DIR/simplify-locals.rs:28:6: 28:16 - (_2.1: E) = const E::A; // scope 0 at $DIR/simplify-locals.rs:28:6: 28:16 -- // ty::Const -- // + ty: E -- // + val: Value(Scalar(0x00)) - // mir::Constant - // + span: $DIR/simplify-locals.rs:28:6: 28:16 - // + literal: Const { ty: E, val: Value(Scalar(0x00)) } - StorageDead(_3); // scope 0 at $DIR/simplify-locals.rs:28:15: 28:16 - (_2.1: E) = const E::B; // scope 0 at $DIR/simplify-locals.rs:28:5: 28:26 -- // ty::Const -- // + ty: E -- // + val: Value(Scalar(0x01)) - // mir::Constant - // + span: $DIR/simplify-locals.rs:28:5: 28:26 - // + literal: Const { ty: E, val: Value(Scalar(0x01)) } diff --git a/src/test/mir-opt/storage_live_dead_in_statics.XXX.mir_map.0.mir b/src/test/mir-opt/storage_live_dead_in_statics.XXX.mir_map.0.mir index 258347ec2dc16..62fbcaaa28938 100644 --- a/src/test/mir-opt/storage_live_dead_in_statics.XXX.mir_map.0.mir +++ b/src/test/mir-opt/storage_live_dead_in_statics.XXX.mir_map.0.mir @@ -190,9 +190,6 @@ static XXX: &Foo = { _3 = move _4 as &[(u32, u32)] (Pointer(Unsize)); // scope 0 at $DIR/storage_live_dead_in_statics.rs:7:11: 22:6 StorageDead(_4); // scope 0 at $DIR/storage_live_dead_in_statics.rs:22:5: 22:6 _2 = Foo { tup: const "hi", data: move _3 }; // scope 0 at $DIR/storage_live_dead_in_statics.rs:5:29: 23:2 - // ty::Const - // + ty: &str - // + val: Value(Slice { data: Allocation { bytes: [104, 105], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [3], len: Size { raw: 2 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 2 }) // mir::Constant // + span: $DIR/storage_live_dead_in_statics.rs:6:10: 6:14 // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [104, 105], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [3], len: Size { raw: 2 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 2 }) } 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 bdcb9357308ec..75cc100def580 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 @@ -19,9 +19,6 @@ fn main() -> () { _3 = discriminant(_2); // scope 0 at $DIR/uninhabited_enum_branching.rs:20:11: 20:19 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 - // ty::Const - // + ty: &str - // + val: Value(Slice { data: Allocation { bytes: [67], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1], len: Size { raw: 1 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) // mir::Constant // + span: $DIR/uninhabited_enum_branching.rs:23:21: 23:24 // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [67], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1], len: Size { raw: 1 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) } @@ -39,9 +36,6 @@ fn main() -> () { bb1: { StorageLive(_9); // scope 0 at $DIR/uninhabited_enum_branching.rs:28:21: 28:24 _9 = const "E"; // scope 0 at $DIR/uninhabited_enum_branching.rs:28:21: 28:24 - // ty::Const - // + ty: &str - // + val: Value(Slice { data: Allocation { bytes: [69], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1], len: Size { raw: 1 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) // mir::Constant // + span: $DIR/uninhabited_enum_branching.rs:28:21: 28:24 // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [69], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1], len: Size { raw: 1 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) } @@ -52,9 +46,6 @@ fn main() -> () { bb2: { _6 = const "D"; // scope 0 at $DIR/uninhabited_enum_branching.rs:27:21: 27:24 - // ty::Const - // + ty: &str - // + val: Value(Slice { data: Allocation { bytes: [68], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1], len: Size { raw: 1 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) // mir::Constant // + span: $DIR/uninhabited_enum_branching.rs:27:21: 27:24 // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [68], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1], len: Size { raw: 1 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) } 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 d8410caa7cd56..f173d002e2d75 100644 --- a/src/test/mir-opt/uninhabited_enum_branching.main.UninhabitedEnumBranching.diff +++ b/src/test/mir-opt/uninhabited_enum_branching.main.UninhabitedEnumBranching.diff @@ -25,9 +25,6 @@ bb1: { 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 - // ty::Const - // + ty: &str - // + val: Value(Slice { data: Allocation { bytes: [67], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1], len: Size { raw: 1 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) // mir::Constant // + span: $DIR/uninhabited_enum_branching.rs:23:21: 23:24 // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [67], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1], len: Size { raw: 1 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) } @@ -38,9 +35,6 @@ bb2: { _1 = const "A(Empty)"; // scope 0 at $DIR/uninhabited_enum_branching.rs:21:24: 21:34 - // ty::Const - // + ty: &str - // + val: Value(Slice { data: Allocation { bytes: [65, 40, 69, 109, 112, 116, 121, 41], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [255], len: Size { raw: 8 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 8 }) // mir::Constant // + span: $DIR/uninhabited_enum_branching.rs:21:24: 21:34 // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [65, 40, 69, 109, 112, 116, 121, 41], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [255], len: Size { raw: 8 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 8 }) } @@ -50,9 +44,6 @@ bb3: { StorageLive(_4); // scope 0 at $DIR/uninhabited_enum_branching.rs:22:24: 22:34 _4 = const "B(Empty)"; // scope 0 at $DIR/uninhabited_enum_branching.rs:22:24: 22:34 - // ty::Const - // + ty: &str - // + val: Value(Slice { data: Allocation { bytes: [66, 40, 69, 109, 112, 116, 121, 41], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [255], len: Size { raw: 8 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 8 }) // mir::Constant // + span: $DIR/uninhabited_enum_branching.rs:22:24: 22:34 // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [66, 40, 69, 109, 112, 116, 121, 41], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [255], len: Size { raw: 8 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 8 }) } @@ -74,9 +65,6 @@ bb5: { StorageLive(_9); // scope 0 at $DIR/uninhabited_enum_branching.rs:28:21: 28:24 _9 = const "E"; // scope 0 at $DIR/uninhabited_enum_branching.rs:28:21: 28:24 - // ty::Const - // + ty: &str - // + val: Value(Slice { data: Allocation { bytes: [69], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1], len: Size { raw: 1 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) // mir::Constant // + span: $DIR/uninhabited_enum_branching.rs:28:21: 28:24 // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [69], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1], len: Size { raw: 1 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) } @@ -87,9 +75,6 @@ bb6: { _6 = const "D"; // scope 0 at $DIR/uninhabited_enum_branching.rs:27:21: 27:24 - // ty::Const - // + ty: &str - // + val: Value(Slice { data: Allocation { bytes: [68], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1], len: Size { raw: 1 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) // mir::Constant // + span: $DIR/uninhabited_enum_branching.rs:27:21: 27:24 // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [68], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1], len: Size { raw: 1 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) } diff --git a/src/test/mir-opt/uninhabited_enum_branching2.main.SimplifyCfg-after-uninhabited-enum-branching.after.mir b/src/test/mir-opt/uninhabited_enum_branching2.main.SimplifyCfg-after-uninhabited-enum-branching.after.mir index e20faa5247499..94fba142e001f 100644 --- a/src/test/mir-opt/uninhabited_enum_branching2.main.SimplifyCfg-after-uninhabited-enum-branching.after.mir +++ b/src/test/mir-opt/uninhabited_enum_branching2.main.SimplifyCfg-after-uninhabited-enum-branching.after.mir @@ -36,9 +36,6 @@ fn main() -> () { bb1: { StorageLive(_8); // scope 1 at $DIR/uninhabited_enum_branching2.rs:25:21: 25:24 _8 = const "D"; // scope 1 at $DIR/uninhabited_enum_branching2.rs:25:21: 25:24 - // ty::Const - // + ty: &str - // + val: Value(Slice { data: Allocation { bytes: [68], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1], len: Size { raw: 1 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) // mir::Constant // + span: $DIR/uninhabited_enum_branching2.rs:25:21: 25:24 // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [68], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1], len: Size { raw: 1 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) } @@ -50,9 +47,6 @@ fn main() -> () { bb2: { StorageLive(_7); // scope 1 at $DIR/uninhabited_enum_branching2.rs:24:21: 24:24 _7 = const "C"; // scope 1 at $DIR/uninhabited_enum_branching2.rs:24:21: 24:24 - // ty::Const - // + ty: &str - // + val: Value(Slice { data: Allocation { bytes: [67], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1], len: Size { raw: 1 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) // mir::Constant // + span: $DIR/uninhabited_enum_branching2.rs:24:21: 24:24 // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [67], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1], len: Size { raw: 1 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) } @@ -72,9 +66,6 @@ fn main() -> () { bb4: { StorageLive(_13); // scope 1 at $DIR/uninhabited_enum_branching2.rs:32:21: 32:24 _13 = const "D"; // scope 1 at $DIR/uninhabited_enum_branching2.rs:32:21: 32:24 - // ty::Const - // + ty: &str - // + val: Value(Slice { data: Allocation { bytes: [68], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1], len: Size { raw: 1 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) // mir::Constant // + span: $DIR/uninhabited_enum_branching2.rs:32:21: 32:24 // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [68], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1], len: Size { raw: 1 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) } @@ -86,9 +77,6 @@ fn main() -> () { bb5: { StorageLive(_12); // scope 1 at $DIR/uninhabited_enum_branching2.rs:31:21: 31:24 _12 = const "C"; // scope 1 at $DIR/uninhabited_enum_branching2.rs:31:21: 31:24 - // ty::Const - // + ty: &str - // + val: Value(Slice { data: Allocation { bytes: [67], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1], len: Size { raw: 1 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) // mir::Constant // + span: $DIR/uninhabited_enum_branching2.rs:31:21: 31:24 // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [67], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1], len: Size { raw: 1 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) } diff --git a/src/test/mir-opt/uninhabited_enum_branching2.main.UninhabitedEnumBranching.diff b/src/test/mir-opt/uninhabited_enum_branching2.main.UninhabitedEnumBranching.diff index 77507ef1ee02d..84ee885d1f5ee 100644 --- a/src/test/mir-opt/uninhabited_enum_branching2.main.UninhabitedEnumBranching.diff +++ b/src/test/mir-opt/uninhabited_enum_branching2.main.UninhabitedEnumBranching.diff @@ -38,9 +38,6 @@ bb1: { StorageLive(_8); // scope 1 at $DIR/uninhabited_enum_branching2.rs:25:21: 25:24 _8 = const "D"; // scope 1 at $DIR/uninhabited_enum_branching2.rs:25:21: 25:24 - // ty::Const - // + ty: &str - // + val: Value(Slice { data: Allocation { bytes: [68], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1], len: Size { raw: 1 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) // mir::Constant // + span: $DIR/uninhabited_enum_branching2.rs:25:21: 25:24 // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [68], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1], len: Size { raw: 1 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) } @@ -51,9 +48,6 @@ bb2: { _3 = const "A(Empty)"; // scope 1 at $DIR/uninhabited_enum_branching2.rs:22:24: 22:34 - // ty::Const - // + ty: &str - // + val: Value(Slice { data: Allocation { bytes: [65, 40, 69, 109, 112, 116, 121, 41], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [255], len: Size { raw: 8 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 8 }) // mir::Constant // + span: $DIR/uninhabited_enum_branching2.rs:22:24: 22:34 // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [65, 40, 69, 109, 112, 116, 121, 41], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [255], len: Size { raw: 8 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 8 }) } @@ -63,9 +57,6 @@ bb3: { StorageLive(_6); // scope 1 at $DIR/uninhabited_enum_branching2.rs:23:24: 23:34 _6 = const "B(Empty)"; // scope 1 at $DIR/uninhabited_enum_branching2.rs:23:24: 23:34 - // ty::Const - // + ty: &str - // + val: Value(Slice { data: Allocation { bytes: [66, 40, 69, 109, 112, 116, 121, 41], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [255], len: Size { raw: 8 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 8 }) // mir::Constant // + span: $DIR/uninhabited_enum_branching2.rs:23:24: 23:34 // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [66, 40, 69, 109, 112, 116, 121, 41], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [255], len: Size { raw: 8 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 8 }) } @@ -77,9 +68,6 @@ bb4: { StorageLive(_7); // scope 1 at $DIR/uninhabited_enum_branching2.rs:24:21: 24:24 _7 = const "C"; // scope 1 at $DIR/uninhabited_enum_branching2.rs:24:21: 24:24 - // ty::Const - // + ty: &str - // + val: Value(Slice { data: Allocation { bytes: [67], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1], len: Size { raw: 1 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) // mir::Constant // + span: $DIR/uninhabited_enum_branching2.rs:24:21: 24:24 // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [67], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1], len: Size { raw: 1 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) } @@ -100,9 +88,6 @@ bb6: { StorageLive(_13); // scope 1 at $DIR/uninhabited_enum_branching2.rs:32:21: 32:24 _13 = const "D"; // scope 1 at $DIR/uninhabited_enum_branching2.rs:32:21: 32:24 - // ty::Const - // + ty: &str - // + val: Value(Slice { data: Allocation { bytes: [68], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1], len: Size { raw: 1 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) // mir::Constant // + span: $DIR/uninhabited_enum_branching2.rs:32:21: 32:24 // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [68], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1], len: Size { raw: 1 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) } @@ -113,9 +98,6 @@ bb7: { _9 = const "A(Empty)"; // scope 1 at $DIR/uninhabited_enum_branching2.rs:29:24: 29:34 - // ty::Const - // + ty: &str - // + val: Value(Slice { data: Allocation { bytes: [65, 40, 69, 109, 112, 116, 121, 41], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [255], len: Size { raw: 8 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 8 }) // mir::Constant // + span: $DIR/uninhabited_enum_branching2.rs:29:24: 29:34 // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [65, 40, 69, 109, 112, 116, 121, 41], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [255], len: Size { raw: 8 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 8 }) } @@ -125,9 +107,6 @@ bb8: { StorageLive(_11); // scope 1 at $DIR/uninhabited_enum_branching2.rs:30:24: 30:34 _11 = const "B(Empty)"; // scope 1 at $DIR/uninhabited_enum_branching2.rs:30:24: 30:34 - // ty::Const - // + ty: &str - // + val: Value(Slice { data: Allocation { bytes: [66, 40, 69, 109, 112, 116, 121, 41], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [255], len: Size { raw: 8 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 8 }) // mir::Constant // + span: $DIR/uninhabited_enum_branching2.rs:30:24: 30:34 // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [66, 40, 69, 109, 112, 116, 121, 41], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [255], len: Size { raw: 8 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 8 }) } @@ -139,9 +118,6 @@ bb9: { StorageLive(_12); // scope 1 at $DIR/uninhabited_enum_branching2.rs:31:21: 31:24 _12 = const "C"; // scope 1 at $DIR/uninhabited_enum_branching2.rs:31:21: 31:24 - // ty::Const - // + ty: &str - // + val: Value(Slice { data: Allocation { bytes: [67], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1], len: Size { raw: 1 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) // mir::Constant // + span: $DIR/uninhabited_enum_branching2.rs:31:21: 31:24 // + literal: Const { ty: &str, val: Value(Slice { data: Allocation { bytes: [67], relocations: Relocations(SortedMap { data: [] }), init_mask: InitMask { blocks: [1], len: Size { raw: 1 } }, align: Align { pow2: 0 }, mutability: Not, extra: () }, start: 0, end: 1 }) } diff --git a/src/test/mir-opt/uninhabited_fallthrough_elimination.eliminate_fallthrough.UninhabitedEnumBranching.diff b/src/test/mir-opt/uninhabited_fallthrough_elimination.eliminate_fallthrough.UninhabitedEnumBranching.diff new file mode 100644 index 0000000000000..7e843b65e88fc --- /dev/null +++ b/src/test/mir-opt/uninhabited_fallthrough_elimination.eliminate_fallthrough.UninhabitedEnumBranching.diff @@ -0,0 +1,38 @@ +- // MIR for `eliminate_fallthrough` before UninhabitedEnumBranching ++ // MIR for `eliminate_fallthrough` after UninhabitedEnumBranching + + fn eliminate_fallthrough(_1: S) -> u32 { + debug s => _1; // in scope 0 at $DIR/uninhabited_fallthrough_elimination.rs:21:26: 21:27 + let mut _0: u32; // return place in scope 0 at $DIR/uninhabited_fallthrough_elimination.rs:21:35: 21:38 + let mut _2: isize; // in scope 0 at $DIR/uninhabited_fallthrough_elimination.rs:23:9: 23:10 + + bb0: { + _2 = discriminant(_1); // scope 0 at $DIR/uninhabited_fallthrough_elimination.rs:22:11: 22:12 +- switchInt(move _2) -> [1_isize: bb3, 2_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/uninhabited_fallthrough_elimination.rs:22:5: 22:12 ++ switchInt(move _2) -> [1_isize: bb3, 2_isize: bb2, otherwise: bb5]; // scope 0 at $DIR/uninhabited_fallthrough_elimination.rs:22:5: 22:12 + } + + bb1: { + _0 = const 3_u32; // scope 0 at $DIR/uninhabited_fallthrough_elimination.rs:25:14: 25:15 + goto -> bb4; // scope 0 at $DIR/uninhabited_fallthrough_elimination.rs:25:14: 25:15 + } + + bb2: { + _0 = const 1_u32; // scope 0 at $DIR/uninhabited_fallthrough_elimination.rs:23:14: 23:15 + goto -> bb4; // scope 0 at $DIR/uninhabited_fallthrough_elimination.rs:23:14: 23:15 + } + + bb3: { + _0 = const 2_u32; // scope 0 at $DIR/uninhabited_fallthrough_elimination.rs:24:14: 24:15 + goto -> bb4; // scope 0 at $DIR/uninhabited_fallthrough_elimination.rs:24:14: 24:15 + } + + bb4: { + return; // scope 0 at $DIR/uninhabited_fallthrough_elimination.rs:27:2: 27:2 ++ } ++ ++ bb5: { ++ unreachable; // scope 0 at $DIR/uninhabited_fallthrough_elimination.rs:25:14: 25:15 + } + } + diff --git a/src/test/mir-opt/uninhabited_fallthrough_elimination.keep_fallthrough.UninhabitedEnumBranching.diff b/src/test/mir-opt/uninhabited_fallthrough_elimination.keep_fallthrough.UninhabitedEnumBranching.diff new file mode 100644 index 0000000000000..5da011d427a2c --- /dev/null +++ b/src/test/mir-opt/uninhabited_fallthrough_elimination.keep_fallthrough.UninhabitedEnumBranching.diff @@ -0,0 +1,34 @@ +- // MIR for `keep_fallthrough` before UninhabitedEnumBranching ++ // MIR for `keep_fallthrough` after UninhabitedEnumBranching + + fn keep_fallthrough(_1: S) -> u32 { + debug s => _1; // in scope 0 at $DIR/uninhabited_fallthrough_elimination.rs:12:21: 12:22 + let mut _0: u32; // return place in scope 0 at $DIR/uninhabited_fallthrough_elimination.rs:12:30: 12:33 + let mut _2: isize; // in scope 0 at $DIR/uninhabited_fallthrough_elimination.rs:14:9: 14:13 + + bb0: { + _2 = discriminant(_1); // scope 0 at $DIR/uninhabited_fallthrough_elimination.rs:13:11: 13:12 +- switchInt(move _2) -> [0_isize: bb2, 1_isize: bb3, otherwise: bb1]; // scope 0 at $DIR/uninhabited_fallthrough_elimination.rs:13:5: 13:12 ++ switchInt(move _2) -> [1_isize: bb3, otherwise: bb1]; // scope 0 at $DIR/uninhabited_fallthrough_elimination.rs:13:5: 13:12 + } + + bb1: { + _0 = const 3_u32; // scope 0 at $DIR/uninhabited_fallthrough_elimination.rs:16:14: 16:15 + goto -> bb4; // scope 0 at $DIR/uninhabited_fallthrough_elimination.rs:16:14: 16:15 + } + + bb2: { + _0 = const 1_u32; // scope 0 at $DIR/uninhabited_fallthrough_elimination.rs:14:17: 14:18 + goto -> bb4; // scope 0 at $DIR/uninhabited_fallthrough_elimination.rs:14:17: 14:18 + } + + bb3: { + _0 = const 2_u32; // scope 0 at $DIR/uninhabited_fallthrough_elimination.rs:15:14: 15:15 + goto -> bb4; // scope 0 at $DIR/uninhabited_fallthrough_elimination.rs:15:14: 15:15 + } + + bb4: { + return; // scope 0 at $DIR/uninhabited_fallthrough_elimination.rs:18:2: 18:2 + } + } + diff --git a/src/test/mir-opt/uninhabited_fallthrough_elimination.rs b/src/test/mir-opt/uninhabited_fallthrough_elimination.rs new file mode 100644 index 0000000000000..0853883f8b841 --- /dev/null +++ b/src/test/mir-opt/uninhabited_fallthrough_elimination.rs @@ -0,0 +1,32 @@ +enum Empty {} + +enum S { + A(Empty), + B, + C, +} + +use S::*; + +// EMIT_MIR uninhabited_fallthrough_elimination.keep_fallthrough.UninhabitedEnumBranching.diff +fn keep_fallthrough(s: S) -> u32 { + match s { + A(_) => 1, + B => 2, + _ => 3, + } +} + +// EMIT_MIR uninhabited_fallthrough_elimination.eliminate_fallthrough.UninhabitedEnumBranching.diff +fn eliminate_fallthrough(s: S) -> u32 { + match s { + C => 1, + B => 2, + _ => 3, + } +} + +fn main() { + keep_fallthrough(B); + eliminate_fallthrough(B); +} diff --git a/src/test/mir-opt/unreachable.main.UnreachablePropagation.diff b/src/test/mir-opt/unreachable.main.UnreachablePropagation.diff index 63356a400d29a..08312bde20f51 100644 --- a/src/test/mir-opt/unreachable.main.UnreachablePropagation.diff +++ b/src/test/mir-opt/unreachable.main.UnreachablePropagation.diff @@ -22,7 +22,7 @@ _1 = empty() -> bb1; // scope 0 at $DIR/unreachable.rs:9:23: 9:30 // mir::Constant // + span: $DIR/unreachable.rs:9:23: 9:28 - // + literal: Const { ty: fn() -> std::option::Option {empty}, val: Value(Scalar()) } + // + literal: Const { ty: fn() -> Option {empty}, val: Value(Scalar()) } } bb1: { diff --git a/src/test/mir-opt/unreachable_diverging.main.UnreachablePropagation.diff b/src/test/mir-opt/unreachable_diverging.main.UnreachablePropagation.diff index 3e93ae7b19887..e5867ccfc5cb6 100644 --- a/src/test/mir-opt/unreachable_diverging.main.UnreachablePropagation.diff +++ b/src/test/mir-opt/unreachable_diverging.main.UnreachablePropagation.diff @@ -24,7 +24,7 @@ _2 = empty() -> bb1; // scope 1 at $DIR/unreachable_diverging.rs:14:25: 14:32 // mir::Constant // + span: $DIR/unreachable_diverging.rs:14:25: 14:30 - // + literal: Const { ty: fn() -> std::option::Option {empty}, val: Value(Scalar()) } + // + literal: Const { ty: fn() -> Option {empty}, val: Value(Scalar()) } } bb1: { diff --git a/src/test/mir-opt/unusual_item_types.core.ptr-drop_in_place.Vec_i32_.AddMovesForPackedDrops.before.32bit.mir b/src/test/mir-opt/unusual_item_types.core.ptr-drop_in_place.Vec_i32_.AddMovesForPackedDrops.before.32bit.mir index 97c83010e22d0..5dc81b787a9fa 100644 --- a/src/test/mir-opt/unusual_item_types.core.ptr-drop_in_place.Vec_i32_.AddMovesForPackedDrops.before.32bit.mir +++ b/src/test/mir-opt/unusual_item_types.core.ptr-drop_in_place.Vec_i32_.AddMovesForPackedDrops.before.32bit.mir @@ -34,6 +34,6 @@ fn std::ptr::drop_in_place(_1: *mut Vec) -> () { _3 = as Drop>::drop(move _2) -> [return: bb5, unwind: bb4]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL // mir::Constant // + span: $SRC_DIR/core/src/ptr/mod.rs:LL:COL - // + literal: Const { ty: for<'r> fn(&'r mut std::vec::Vec) { as std::ops::Drop>::drop}, val: Value(Scalar()) } + // + literal: Const { ty: for<'r> fn(&'r mut Vec) { as Drop>::drop}, val: Value(Scalar()) } } } diff --git a/src/test/mir-opt/unusual_item_types.core.ptr-drop_in_place.Vec_i32_.AddMovesForPackedDrops.before.64bit.mir b/src/test/mir-opt/unusual_item_types.core.ptr-drop_in_place.Vec_i32_.AddMovesForPackedDrops.before.64bit.mir index 97c83010e22d0..5dc81b787a9fa 100644 --- a/src/test/mir-opt/unusual_item_types.core.ptr-drop_in_place.Vec_i32_.AddMovesForPackedDrops.before.64bit.mir +++ b/src/test/mir-opt/unusual_item_types.core.ptr-drop_in_place.Vec_i32_.AddMovesForPackedDrops.before.64bit.mir @@ -34,6 +34,6 @@ fn std::ptr::drop_in_place(_1: *mut Vec) -> () { _3 = as Drop>::drop(move _2) -> [return: bb5, unwind: bb4]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL // mir::Constant // + span: $SRC_DIR/core/src/ptr/mod.rs:LL:COL - // + literal: Const { ty: for<'r> fn(&'r mut std::vec::Vec) { as std::ops::Drop>::drop}, val: Value(Scalar()) } + // + literal: Const { ty: for<'r> fn(&'r mut Vec) { as Drop>::drop}, val: Value(Scalar()) } } } diff --git a/src/test/run-make-fulldeps/foreign-double-unwind/Makefile b/src/test/run-make-fulldeps/foreign-double-unwind/Makefile new file mode 100644 index 0000000000000..27cf4d19ce067 --- /dev/null +++ b/src/test/run-make-fulldeps/foreign-double-unwind/Makefile @@ -0,0 +1,10 @@ +-include ../tools.mk + +all: foo + $(call RUN,foo) | $(CGREP) -v unreachable + +foo: foo.rs $(call NATIVE_STATICLIB,foo) + $(RUSTC) $< -lfoo $(EXTRARSCXXFLAGS) + +$(TMPDIR)/libfoo.o: foo.cpp + $(call COMPILE_OBJ_CXX,$@,$<) diff --git a/src/test/run-make-fulldeps/foreign-double-unwind/foo.cpp b/src/test/run-make-fulldeps/foreign-double-unwind/foo.cpp new file mode 100644 index 0000000000000..69a8f11c2db78 --- /dev/null +++ b/src/test/run-make-fulldeps/foreign-double-unwind/foo.cpp @@ -0,0 +1,33 @@ +#include +#include + +void println(const char* s) { + puts(s); + fflush(stdout); +} + +struct outer_exception {}; +struct inner_exception {}; + +extern "C" { + void throw_cxx_exception() { + if (std::uncaught_exception()) { + println("throwing inner C++ exception"); + throw inner_exception(); + } else { + println("throwing outer C++ exception"); + throw outer_exception(); + } + } + + void cxx_catch_callback(void (*cb)()) { + try { + cb(); + println("unreachable: callback returns"); + } catch (outer_exception) { + println("unreachable: caught outer exception in catch (...)"); + } catch (inner_exception) { + println("unreachable: caught inner exception in catch (...)"); + } + } +} diff --git a/src/test/run-make-fulldeps/foreign-double-unwind/foo.rs b/src/test/run-make-fulldeps/foreign-double-unwind/foo.rs new file mode 100644 index 0000000000000..cae8aa9402d88 --- /dev/null +++ b/src/test/run-make-fulldeps/foreign-double-unwind/foo.rs @@ -0,0 +1,26 @@ +// Tests that C++ double unwinding through Rust code will be properly guarded +// against instead of exhibiting undefined behaviour. + +#![feature(c_unwind)] + +extern "C-unwind" { + fn throw_cxx_exception(); + fn cxx_catch_callback(cb: extern "C-unwind" fn()); +} + +struct ThrowOnDrop; + +impl Drop for ThrowOnDrop { + fn drop(&mut self) { + unsafe { throw_cxx_exception() }; + } +} + +extern "C-unwind" fn test_double_unwind() { + let _a = ThrowOnDrop; + let _b = ThrowOnDrop; +} + +fn main() { + unsafe { cxx_catch_callback(test_double_unwind) }; +} diff --git a/src/test/run-make-fulldeps/static-nobundle/Makefile b/src/test/run-make-fulldeps/static-nobundle/Makefile index 8f78c401a1141..001081798a6e4 100644 --- a/src/test/run-make-fulldeps/static-nobundle/Makefile +++ b/src/test/run-make-fulldeps/static-nobundle/Makefile @@ -9,8 +9,10 @@ all: $(call NATIVE_STATICLIB,aaa) $(RUSTC) bbb.rs --crate-type=rlib # Check that bbb does NOT contain the definition of `native_func` - nm $(TMPDIR)/libbbb.rlib | $(CGREP) -ve "T _*native_func" - nm $(TMPDIR)/libbbb.rlib | $(CGREP) -e "U _*native_func" + # We're using the llvm-nm instead of the system nm to ensure it + # is compatible with the LLVM bitcode generated by rustc. + "$(LLVM_BIN_DIR)/llvm-nm" $(TMPDIR)/libbbb.rlib | $(CGREP) -ve "T _*native_func" + "$(LLVM_BIN_DIR)/llvm-nm" $(TMPDIR)/libbbb.rlib | $(CGREP) -e "U _*native_func" # Check that aaa gets linked (either as `-l aaa` or `aaa.lib`) when building ccc. $(RUSTC) ccc.rs -C prefer-dynamic --crate-type=dylib --print link-args | $(CGREP) -e '-l[" ]*aaa|aaa\.lib' diff --git a/src/test/rustdoc-gui/duplicate-macro-reexport.goml b/src/test/rustdoc-gui/duplicate-macro-reexport.goml new file mode 100644 index 0000000000000..c79b3a220c42c --- /dev/null +++ b/src/test/rustdoc-gui/duplicate-macro-reexport.goml @@ -0,0 +1,14 @@ +// This test ensures that there is no macro duplicates in the sidebar. +goto: file://|DOC_PATH|/test_docs/macro.a.html +// Waiting for the elements in the sidebar to be rendered. +wait-for: ".sidebar-elems .others .macro" +// Check there is only one macro named "a" listed in the sidebar. +assert-count: ( + "//*[@class='sidebar-elems']//*[@class='others']/*[@class='block macro']//li/a[text()='a']", + 1, +) +// Check there is only one macro named "b" listed in the sidebar. +assert-count: ( + "//*[@class='sidebar-elems']//*[@class='others']/*[@class='block macro']//li/a[text()='b']", + 1, +) diff --git a/src/test/rustdoc-gui/src/test_docs/lib.rs b/src/test/rustdoc-gui/src/test_docs/lib.rs index 2068d1d6f39af..348b1a65c786c 100644 --- a/src/test/rustdoc-gui/src/test_docs/lib.rs +++ b/src/test/rustdoc-gui/src/test_docs/lib.rs @@ -271,3 +271,6 @@ impl EmptyTrait1 for HasEmptyTraits {} impl EmptyTrait2 for HasEmptyTraits {} #[doc(cfg(feature = "some-feature"))] impl EmptyTrait3 for HasEmptyTraits {} + +mod macros; +pub use macros::*; diff --git a/src/test/rustdoc-gui/src/test_docs/macros.rs b/src/test/rustdoc-gui/src/test_docs/macros.rs new file mode 100644 index 0000000000000..07b2b97926d43 --- /dev/null +++ b/src/test/rustdoc-gui/src/test_docs/macros.rs @@ -0,0 +1,4 @@ +#[macro_export] +macro_rules! a{ () => {}} +#[macro_export] +macro_rules! b{ () => {}} diff --git a/src/test/rustdoc-ui/intra-doc/html-as-generics-intra-doc.rs b/src/test/rustdoc-ui/intra-doc/html-as-generics-intra-doc.rs new file mode 100644 index 0000000000000..b5470c859fdf4 --- /dev/null +++ b/src/test/rustdoc-ui/intra-doc/html-as-generics-intra-doc.rs @@ -0,0 +1,25 @@ +#![deny(rustdoc::invalid_html_tags)] +#![deny(rustdoc::broken_intra_doc_links)] + +pub struct ExistentStruct(T); + +/// This [test][ExistentStruct] thing! +pub struct NoError; + +/// This [ExistentStruct] thing! +//~^ ERROR unclosed HTML tag `i32` +pub struct PartialErrorOnlyHtml; + +/// This [test][NonExistentStruct] thing! +//~^ ERROR unresolved link +pub struct PartialErrorOnlyResolve; + +/// This [NonExistentStruct2] thing! +//~^ ERROR unclosed HTML tag `i32` +//~| ERROR unresolved link +pub struct YesError; + +/// This [NonExistentStruct3][] thing! +//~^ ERROR unclosed HTML tag `i32` +//~| ERROR unresolved link +pub struct YesErrorCollapsed; diff --git a/src/test/rustdoc-ui/intra-doc/html-as-generics-intra-doc.stderr b/src/test/rustdoc-ui/intra-doc/html-as-generics-intra-doc.stderr new file mode 100644 index 0000000000000..00fe229da40ce --- /dev/null +++ b/src/test/rustdoc-ui/intra-doc/html-as-generics-intra-doc.stderr @@ -0,0 +1,69 @@ +error: unresolved link to `NonExistentStruct` + --> $DIR/html-as-generics-intra-doc.rs:13:17 + | +LL | /// This [test][NonExistentStruct] thing! + | ^^^^^^^^^^^^^^^^^^^^^^ no item named `NonExistentStruct` in scope + | +note: the lint level is defined here + --> $DIR/html-as-generics-intra-doc.rs:2:9 + | +LL | #![deny(rustdoc::broken_intra_doc_links)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` + +error: unresolved link to `NonExistentStruct2` + --> $DIR/html-as-generics-intra-doc.rs:17:11 + | +LL | /// This [NonExistentStruct2] thing! + | ^^^^^^^^^^^^^^^^^^^^^^^ no item named `NonExistentStruct2` in scope + | + = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` + +error: unresolved link to `NonExistentStruct3` + --> $DIR/html-as-generics-intra-doc.rs:22:11 + | +LL | /// This [NonExistentStruct3][] thing! + | ^^^^^^^^^^^^^^^^^^^^^^^ no item named `NonExistentStruct3` in scope + | + = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` + +error: unclosed HTML tag `i32` + --> $DIR/html-as-generics-intra-doc.rs:9:25 + | +LL | /// This [ExistentStruct] thing! + | ^^^^^ + | +note: the lint level is defined here + --> $DIR/html-as-generics-intra-doc.rs:1:9 + | +LL | #![deny(rustdoc::invalid_html_tags)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: try marking as source code + | +LL | /// This [`ExistentStruct`] thing! + | + + + +error: unclosed HTML tag `i32` + --> $DIR/html-as-generics-intra-doc.rs:17:29 + | +LL | /// This [NonExistentStruct2] thing! + | ^^^^^ + | +help: try marking as source code + | +LL | /// This [`NonExistentStruct2`] thing! + | + + + +error: unclosed HTML tag `i32` + --> $DIR/html-as-generics-intra-doc.rs:22:29 + | +LL | /// This [NonExistentStruct3][] thing! + | ^^^^^ + | +help: try marking as source code + | +LL | /// This [`NonExistentStruct3`][] thing! + | + + + +error: aborting due to 6 previous errors + diff --git a/src/test/rustdoc/const-value-display.rs b/src/test/rustdoc/const-value-display.rs new file mode 100644 index 0000000000000..0ae52592b64ba --- /dev/null +++ b/src/test/rustdoc/const-value-display.rs @@ -0,0 +1,9 @@ +#![crate_name = "foo"] + +// @has 'foo/constant.HOUR_IN_SECONDS.html' +// @has - '//*[@class="docblock item-decl"]//code' 'pub const HOUR_IN_SECONDS: u64 = 60 * 60; // 3_600u64' +pub const HOUR_IN_SECONDS: u64 = 60 * 60; + +// @has 'foo/constant.NEGATIVE.html' +// @has - '//*[@class="docblock item-decl"]//code' 'pub const NEGATIVE: i64 = -60 * 60; // -3_600i64' +pub const NEGATIVE: i64 = -60 * 60; diff --git a/src/test/ui-fulldeps/deriving-encodable-decodable-box.rs b/src/test/ui-fulldeps/deriving-encodable-decodable-box.rs index dd20eef070084..678ba18bf045d 100644 --- a/src/test/ui-fulldeps/deriving-encodable-decodable-box.rs +++ b/src/test/ui-fulldeps/deriving-encodable-decodable-box.rs @@ -7,7 +7,7 @@ extern crate rustc_macros; extern crate rustc_serialize; use rustc_macros::{Decodable, Encodable}; -use rustc_serialize::json; +use rustc_serialize::opaque; use rustc_serialize::{Decodable, Encodable}; #[derive(Encodable, Decodable)] @@ -17,7 +17,9 @@ struct A { fn main() { let obj = A { foo: Box::new([true, false]) }; - let s = json::encode(&obj).unwrap(); - let obj2: A = json::decode(&s); + let mut encoder = opaque::Encoder::new(vec![]); + obj.encode(&mut encoder).unwrap(); + let mut decoder = opaque::Decoder::new(&encoder.data, 0); + let obj2 = A::decode(&mut decoder); assert_eq!(obj.foo, obj2.foo); } diff --git a/src/test/ui-fulldeps/deriving-encodable-decodable-cell-refcell.rs b/src/test/ui-fulldeps/deriving-encodable-decodable-cell-refcell.rs index 18aa974c31dbe..5cc5c41364a66 100644 --- a/src/test/ui-fulldeps/deriving-encodable-decodable-cell-refcell.rs +++ b/src/test/ui-fulldeps/deriving-encodable-decodable-cell-refcell.rs @@ -9,7 +9,7 @@ extern crate rustc_macros; extern crate rustc_serialize; use rustc_macros::{Decodable, Encodable}; -use rustc_serialize::json; +use rustc_serialize::opaque; use rustc_serialize::{Decodable, Encodable}; use std::cell::{Cell, RefCell}; @@ -26,8 +26,10 @@ struct B { fn main() { let obj = B { foo: Cell::new(true), bar: RefCell::new(A { baz: 2 }) }; - let s = json::encode(&obj).unwrap(); - let obj2: B = json::decode(&s); + let mut encoder = opaque::Encoder::new(vec![]); + obj.encode(&mut encoder).unwrap(); + let mut decoder = opaque::Decoder::new(&encoder.data, 0); + let obj2 = B::decode(&mut decoder); assert_eq!(obj.foo.get(), obj2.foo.get()); assert_eq!(obj.bar.borrow().baz, obj2.bar.borrow().baz); } diff --git a/src/test/ui-fulldeps/issue-14021.rs b/src/test/ui-fulldeps/issue-14021.rs index acd75170d68b2..f7e0043f52168 100644 --- a/src/test/ui-fulldeps/issue-14021.rs +++ b/src/test/ui-fulldeps/issue-14021.rs @@ -8,7 +8,7 @@ extern crate rustc_macros; extern crate rustc_serialize; use rustc_macros::{Decodable, Encodable}; -use rustc_serialize::json; +use rustc_serialize::opaque; use rustc_serialize::{Decodable, Encodable}; #[derive(Encodable, Decodable, PartialEq, Debug)] @@ -16,11 +16,9 @@ struct UnitLikeStruct; pub fn main() { let obj = UnitLikeStruct; - let json_str: String = json::encode(&obj).unwrap(); - - let json_object = json::from_str(&json_str); - let mut decoder = json::Decoder::new(json_object.unwrap()); - let mut decoded_obj: UnitLikeStruct = Decodable::decode(&mut decoder); - - assert_eq!(obj, decoded_obj); + let mut encoder = opaque::Encoder::new(vec![]); + obj.encode(&mut encoder).unwrap(); + let mut decoder = opaque::Decoder::new(&encoder.data, 0); + let obj2 = UnitLikeStruct::decode(&mut decoder); + assert_eq!(obj, obj2); } diff --git a/src/test/ui-fulldeps/issue-24972.rs b/src/test/ui-fulldeps/issue-24972.rs deleted file mode 100644 index 044a0c5000e31..0000000000000 --- a/src/test/ui-fulldeps/issue-24972.rs +++ /dev/null @@ -1,39 +0,0 @@ -// run-pass - -#![allow(dead_code)] -#![feature(rustc_private)] - -extern crate rustc_serialize; - -use rustc_serialize::{json, Decodable, Encodable}; -use std::fmt::Display; - -pub trait Entity: Decodable + for<'a> Encodable> + Sized { - type Key: Clone - + Decodable - + for<'a> Encodable> - + ToString - + Display - + Eq - + Ord - + Sized; - - fn id(&self) -> Self::Key; - - fn find_by_id(id: Self::Key) -> Option; -} - -pub struct DbRef { - pub id: E::Key, -} - -impl DbRef -where - E: Entity, -{ - fn get(self) -> Option { - E::find_by_id(self.id) - } -} - -fn main() {} diff --git a/src/test/ui-fulldeps/issue-4016.rs b/src/test/ui-fulldeps/issue-4016.rs deleted file mode 100644 index 65dab8d770476..0000000000000 --- a/src/test/ui-fulldeps/issue-4016.rs +++ /dev/null @@ -1,19 +0,0 @@ -// run-pass - -#![allow(dead_code)] -#![feature(rustc_private)] - -extern crate rustc_serialize; - -use rustc_serialize::{json, Decodable}; - -trait JD: Decodable {} - -fn exec() { - let doc = json::from_str("").unwrap(); - let mut decoder = json::Decoder::new(doc); - let _v: T = Decodable::decode(&mut decoder); - panic!() -} - -pub fn main() {} diff --git a/src/test/ui-fulldeps/issue-4036.rs b/src/test/ui-fulldeps/issue-4036.rs deleted file mode 100644 index 702bb2d6ef6cb..0000000000000 --- a/src/test/ui-fulldeps/issue-4036.rs +++ /dev/null @@ -1,17 +0,0 @@ -// run-pass -// Issue #4036: Test for an issue that arose around fixing up type inference -// byproducts in vtable records. - -// pretty-expanded FIXME #23616 - -#![feature(rustc_private)] - -extern crate rustc_serialize; - -use rustc_serialize::{json, Decodable}; - -pub fn main() { - let json = json::from_str("[1]").unwrap(); - let mut decoder = json::Decoder::new(json); - let _x: Vec = Decodable::decode(&mut decoder); -} diff --git a/src/test/ui/cfg/cfg-panic-abort.rs b/src/test/ui/cfg/cfg-panic-abort.rs index 9b88eff12ed38..3853b598a7a79 100644 --- a/src/test/ui/cfg/cfg-panic-abort.rs +++ b/src/test/ui/cfg/cfg-panic-abort.rs @@ -1,7 +1,7 @@ // build-pass // compile-flags: -C panic=abort // no-prefer-dynamic -#![feature(cfg_panic)] + #[cfg(panic = "unwind")] pub fn bad() -> i32 { } diff --git a/src/test/ui/cfg/cfg-panic.rs b/src/test/ui/cfg/cfg-panic.rs index d2113e4f5ecc6..fb3e5059c8199 100644 --- a/src/test/ui/cfg/cfg-panic.rs +++ b/src/test/ui/cfg/cfg-panic.rs @@ -4,7 +4,7 @@ // ignore-emscripten no panic_unwind implementation // ignore-wasm32 no panic_unwind implementation // ignore-wasm64 no panic_unwind implementation -#![feature(cfg_panic)] + #[cfg(panic = "abort")] pub fn bad() -> i32 { } diff --git a/src/test/ui/const-generics/defaults/doesnt_infer.rs b/src/test/ui/const-generics/defaults/doesnt_infer.rs index cd533b57bc31f..9c59e672d8e4c 100644 --- a/src/test/ui/const-generics/defaults/doesnt_infer.rs +++ b/src/test/ui/const-generics/defaults/doesnt_infer.rs @@ -9,5 +9,5 @@ impl Foo { fn main() { let foo = Foo::<1>::foo(); let foo = Foo::foo(); - //~^ error: type annotations needed for `Foo<{_: u32}>` + //~^ error: type annotations needed for `Foo` } diff --git a/src/test/ui/const-generics/defaults/doesnt_infer.stderr b/src/test/ui/const-generics/defaults/doesnt_infer.stderr index 1551e81ea7577..cccf433e32864 100644 --- a/src/test/ui/const-generics/defaults/doesnt_infer.stderr +++ b/src/test/ui/const-generics/defaults/doesnt_infer.stderr @@ -1,4 +1,4 @@ -error[E0282]: type annotations needed for `Foo<{_: u32}>` +error[E0282]: type annotations needed for `Foo` --> $DIR/doesnt_infer.rs:11:15 | LL | let foo = Foo::foo(); diff --git a/src/test/ui/const-generics/generic_arg_infer/issue-91614.rs b/src/test/ui/const-generics/generic_arg_infer/issue-91614.rs index 413cc1539248a..b45e2cbc7372b 100644 --- a/src/test/ui/const-generics/generic_arg_infer/issue-91614.rs +++ b/src/test/ui/const-generics/generic_arg_infer/issue-91614.rs @@ -4,5 +4,5 @@ use std::simd::Mask; fn main() { let y = Mask::<_, _>::splat(false); - //~^ error: type annotations needed for `Mask<_, {_: usize}>` + //~^ ERROR: type annotations needed for } diff --git a/src/test/ui/const-generics/generic_arg_infer/issue-91614.stderr b/src/test/ui/const-generics/generic_arg_infer/issue-91614.stderr index 71a5ff79280fd..347cd2364b266 100644 --- a/src/test/ui/const-generics/generic_arg_infer/issue-91614.stderr +++ b/src/test/ui/const-generics/generic_arg_infer/issue-91614.stderr @@ -1,4 +1,4 @@ -error[E0283]: type annotations needed for `Mask<_, {_: usize}>` +error[E0283]: type annotations needed for `Mask<_, LANES>` --> $DIR/issue-91614.rs:6:13 | LL | let y = Mask::<_, _>::splat(false); diff --git a/src/test/ui/const-generics/issues/issue-75763.rs b/src/test/ui/const-generics/issues/issue-75763.rs deleted file mode 100644 index 214a04b8a6bed..0000000000000 --- a/src/test/ui/const-generics/issues/issue-75763.rs +++ /dev/null @@ -1,16 +0,0 @@ -// ignore-test -// FIXME(const_generics): This test causes an ICE after reverting #76030. -#![feature(adt_const_params)] -#![allow(incomplete_features)] - - -struct Bug; - -fn main() { - let b: Bug::<{ - unsafe { - // FIXME(adt_const_params): Decide on how to deal with invalid values as const params. - std::mem::transmute::<&[u8], &str>(&[0xC0, 0xC1, 0xF5]) - } - }>; -} diff --git a/src/test/ui/feature-gates/feature-gate-cfg-panic.rs b/src/test/ui/feature-gates/feature-gate-cfg-panic.rs deleted file mode 100644 index 1508374d94266..0000000000000 --- a/src/test/ui/feature-gates/feature-gate-cfg-panic.rs +++ /dev/null @@ -1,11 +0,0 @@ -#[cfg(panic = "unwind")] -//~^ ERROR `cfg(panic)` is experimental and subject to change -fn foo() -> bool { true } -#[cfg(not(panic = "unwind"))] -//~^ ERROR `cfg(panic)` is experimental and subject to change -fn foo() -> bool { false } - - -fn main() { - assert!(foo()); -} diff --git a/src/test/ui/feature-gates/feature-gate-cfg-panic.stderr b/src/test/ui/feature-gates/feature-gate-cfg-panic.stderr deleted file mode 100644 index ea5cd54fa90f0..0000000000000 --- a/src/test/ui/feature-gates/feature-gate-cfg-panic.stderr +++ /dev/null @@ -1,21 +0,0 @@ -error[E0658]: `cfg(panic)` is experimental and subject to change - --> $DIR/feature-gate-cfg-panic.rs:1:7 - | -LL | #[cfg(panic = "unwind")] - | ^^^^^^^^^^^^^^^^ - | - = note: see issue #77443 for more information - = help: add `#![feature(cfg_panic)]` to the crate attributes to enable - -error[E0658]: `cfg(panic)` is experimental and subject to change - --> $DIR/feature-gate-cfg-panic.rs:4:11 - | -LL | #[cfg(not(panic = "unwind"))] - | ^^^^^^^^^^^^^^^^ - | - = note: see issue #77443 for more information - = help: add `#![feature(cfg_panic)]` to the crate attributes to enable - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/fmt/format-args-capture.rs b/src/test/ui/fmt/format-args-capture.rs index d31d2a6c33657..560352b5cb958 100644 --- a/src/test/ui/fmt/format-args-capture.rs +++ b/src/test/ui/fmt/format-args-capture.rs @@ -1,5 +1,4 @@ // run-pass -#![feature(cfg_panic)] fn main() { named_argument_takes_precedence_to_captured(); diff --git a/src/test/ui/generic-associated-types/bugs/issue-88382.stderr b/src/test/ui/generic-associated-types/bugs/issue-88382.stderr index d06c3ec8de75e..ce196dcbd863d 100644 --- a/src/test/ui/generic-associated-types/bugs/issue-88382.stderr +++ b/src/test/ui/generic-associated-types/bugs/issue-88382.stderr @@ -2,18 +2,18 @@ error[E0631]: type mismatch in function arguments --> $DIR/issue-88382.rs:28:40 | LL | do_something(SomeImplementation(), test); - | ------------ ^^^^ expected signature of `for<'a> fn(&mut ::Iterator<'a>) -> _` + | ------------ ^^^^ expected signature of `for<'r> fn(&'r mut std::iter::Empty) -> _` | | | required by a bound introduced by this call ... LL | fn test<'a, I: Iterable>(_: &mut I::Iterator<'a>) {} - | ------------------------------------------------- found signature of `for<'r> fn(&'r mut std::iter::Empty) -> _` + | ------------------------------------------------- found signature of `for<'r, 'a> fn(&'r mut <_ as Iterable>::Iterator<'a>) -> _` | note: required by a bound in `do_something` - --> $DIR/issue-88382.rs:22:56 + --> $DIR/issue-88382.rs:22:48 | LL | fn do_something(i: I, mut f: impl for<'a> Fn(&mut I::Iterator<'a>)) { - | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `do_something` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `do_something` error: aborting due to previous error diff --git a/src/test/ui/higher-rank-trait-bounds/issue-60283.rs b/src/test/ui/higher-rank-trait-bounds/issue-60283.rs index c63b1544a5379..05315b3f9f5e9 100644 --- a/src/test/ui/higher-rank-trait-bounds/issue-60283.rs +++ b/src/test/ui/higher-rank-trait-bounds/issue-60283.rs @@ -1,3 +1,5 @@ +// check-pass + pub trait Trait<'a> { type Item; } @@ -15,6 +17,4 @@ where fn main() { foo((), drop) - //~^ ERROR type mismatch in function arguments - //~| ERROR size for values of type `<() as Trait<'_>>::Item` cannot be known at compilation time } diff --git a/src/test/ui/higher-rank-trait-bounds/issue-60283.stderr b/src/test/ui/higher-rank-trait-bounds/issue-60283.stderr deleted file mode 100644 index 34893cd8f19d9..0000000000000 --- a/src/test/ui/higher-rank-trait-bounds/issue-60283.stderr +++ /dev/null @@ -1,42 +0,0 @@ -error[E0631]: type mismatch in function arguments - --> $DIR/issue-60283.rs:17:13 - | -LL | foo((), drop) - | --- ^^^^ - | | | - | | expected signature of `for<'a> fn(<() as Trait<'a>>::Item) -> _` - | | found signature of `fn(()) -> _` - | required by a bound introduced by this call - | -note: required by a bound in `foo` - --> $DIR/issue-60283.rs:12:16 - | -LL | pub fn foo(_: T, _: F) - | --- required by a bound in this -... -LL | F: for<'a> FnMut(>::Item), - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `foo` - -error[E0277]: the size for values of type `<() as Trait<'_>>::Item` cannot be known at compilation time - --> $DIR/issue-60283.rs:17:13 - | -LL | foo((), drop) - | --- ^^^^ doesn't have a size known at compile-time - | | - | required by a bound introduced by this call - | - = help: the trait `Sized` is not implemented for `<() as Trait<'_>>::Item` -note: required by a bound in `std::mem::drop` - --> $SRC_DIR/core/src/mem/mod.rs:LL:COL - | -LL | pub fn drop(_x: T) {} - | ^ required by this bound in `std::mem::drop` -help: consider further restricting the associated type - | -LL | fn main() where <() as Trait<'_>>::Item: Sized { - | ++++++++++++++++++++++++++++++++++++ - -error: aborting due to 2 previous errors - -Some errors have detailed explanations: E0277, E0631. -For more information about an error, try `rustc --explain E0277`. diff --git a/src/test/ui/issues/issue-68696-catch-during-unwind.rs b/src/test/ui/issues/issue-68696-catch-during-unwind.rs index f25a78f59cd20..2b12a62d0eb25 100644 --- a/src/test/ui/issues/issue-68696-catch-during-unwind.rs +++ b/src/test/ui/issues/issue-68696-catch-during-unwind.rs @@ -4,7 +4,6 @@ // entering the catch_unwind. // // run-pass -#![feature(cfg_panic)] use std::panic::catch_unwind; diff --git a/src/test/ui/let-else/let-else-destructuring.rs b/src/test/ui/let-else/let-else-destructuring.rs new file mode 100644 index 0000000000000..9a09c414ac80f --- /dev/null +++ b/src/test/ui/let-else/let-else-destructuring.rs @@ -0,0 +1,18 @@ +#![feature(let_else)] +#[derive(Debug)] +enum Foo { + Done, + Nested(Option<&'static Foo>), +} + +fn walk(mut value: &Foo) { + loop { + println!("{:?}", value); + &Foo::Nested(Some(value)) = value else { break }; //~ ERROR invalid left-hand side of assignment + //~^ERROR ... else { ... } is not allowed + } +} + +fn main() { + walk(&Foo::Done); +} diff --git a/src/test/ui/let-else/let-else-destructuring.stderr b/src/test/ui/let-else/let-else-destructuring.stderr new file mode 100644 index 0000000000000..95efb7116829e --- /dev/null +++ b/src/test/ui/let-else/let-else-destructuring.stderr @@ -0,0 +1,17 @@ +error: ... else { ... } is not allowed + --> $DIR/let-else-destructuring.rs:11:9 + | +LL | &Foo::Nested(Some(value)) = value else { break }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0070]: invalid left-hand side of assignment + --> $DIR/let-else-destructuring.rs:11:35 + | +LL | &Foo::Nested(Some(value)) = value else { break }; + | ------------------------- ^ + | | + | cannot assign to this expression + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0070`. diff --git a/src/test/ui/span/lint-unused-unsafe-thir.rs b/src/test/ui/span/lint-unused-unsafe-thir.rs new file mode 100644 index 0000000000000..95a537ed28230 --- /dev/null +++ b/src/test/ui/span/lint-unused-unsafe-thir.rs @@ -0,0 +1,61 @@ +// FIXME: This file is tracking old lint behavior that's still unchanged in the +// unstable -Zthir-unsafeck implementation. See lint-unused-unsafe.rs for more details. +// +// Exercise the unused_unsafe attribute in some positive and negative cases + +// compile-flags: -Zthir-unsafeck + +#![allow(dead_code)] +#![deny(unused_unsafe)] + + +mod foo { + extern "C" { + pub fn bar(); + } +} + +fn callback(_f: F) -> T where F: FnOnce() -> T { panic!() } +unsafe fn unsf() {} + +fn bad1() { unsafe {} } //~ ERROR: unnecessary `unsafe` block +fn bad2() { unsafe { bad1() } } //~ ERROR: unnecessary `unsafe` block +unsafe fn bad3() { unsafe {} } //~ ERROR: unnecessary `unsafe` block +fn bad4() { unsafe { callback(||{}) } } //~ ERROR: unnecessary `unsafe` block +unsafe fn bad5() { unsafe { unsf() } } //~ ERROR: unnecessary `unsafe` block +fn bad6() { + unsafe { // don't put the warning here + unsafe { //~ ERROR: unnecessary `unsafe` block + unsf() + } + } +} +unsafe fn bad7() { + unsafe { //~ ERROR: unnecessary `unsafe` block + unsafe { //~ ERROR: unnecessary `unsafe` block + unsf() + } + } +} + +unsafe fn good0() { unsf() } +fn good1() { unsafe { unsf() } } +fn good2() { + /* bug uncovered when implementing warning about unused unsafe blocks. Be + sure that when purity is inherited that the source of the unsafe-ness + is tracked correctly */ + unsafe { + unsafe fn what() -> Vec { panic!() } + + callback(|| { + what(); + }); + } +} + +unsafe fn good3() { foo::bar() } +fn good4() { unsafe { foo::bar() } } + +#[allow(unused_unsafe)] fn allowed() { unsafe {} } + +fn main() {} diff --git a/src/test/ui/span/lint-unused-unsafe.thir.stderr b/src/test/ui/span/lint-unused-unsafe-thir.stderr similarity index 79% rename from src/test/ui/span/lint-unused-unsafe.thir.stderr rename to src/test/ui/span/lint-unused-unsafe-thir.stderr index dda45c3679ab6..6654910c5cdc3 100644 --- a/src/test/ui/span/lint-unused-unsafe.thir.stderr +++ b/src/test/ui/span/lint-unused-unsafe-thir.stderr @@ -1,23 +1,23 @@ error: unnecessary `unsafe` block - --> $DIR/lint-unused-unsafe.rs:19:13 + --> $DIR/lint-unused-unsafe-thir.rs:21:13 | LL | fn bad1() { unsafe {} } | ^^^^^^ unnecessary `unsafe` block | note: the lint level is defined here - --> $DIR/lint-unused-unsafe.rs:7:9 + --> $DIR/lint-unused-unsafe-thir.rs:9:9 | LL | #![deny(unused_unsafe)] | ^^^^^^^^^^^^^ error: unnecessary `unsafe` block - --> $DIR/lint-unused-unsafe.rs:20:13 + --> $DIR/lint-unused-unsafe-thir.rs:22:13 | LL | fn bad2() { unsafe { bad1() } } | ^^^^^^ unnecessary `unsafe` block error: unnecessary `unsafe` block - --> $DIR/lint-unused-unsafe.rs:21:20 + --> $DIR/lint-unused-unsafe-thir.rs:23:20 | LL | unsafe fn bad3() { unsafe {} } | ---------------- ^^^^^^ unnecessary `unsafe` block @@ -25,13 +25,13 @@ LL | unsafe fn bad3() { unsafe {} } | because it's nested under this `unsafe` fn error: unnecessary `unsafe` block - --> $DIR/lint-unused-unsafe.rs:22:13 + --> $DIR/lint-unused-unsafe-thir.rs:24:13 | LL | fn bad4() { unsafe { callback(||{}) } } | ^^^^^^ unnecessary `unsafe` block error: unnecessary `unsafe` block - --> $DIR/lint-unused-unsafe.rs:23:20 + --> $DIR/lint-unused-unsafe-thir.rs:25:20 | LL | unsafe fn bad5() { unsafe { unsf() } } | ---------------- ^^^^^^ unnecessary `unsafe` block @@ -39,7 +39,7 @@ LL | unsafe fn bad5() { unsafe { unsf() } } | because it's nested under this `unsafe` fn error: unnecessary `unsafe` block - --> $DIR/lint-unused-unsafe.rs:26:9 + --> $DIR/lint-unused-unsafe-thir.rs:28:9 | LL | unsafe { // don't put the warning here | ------ because it's nested under this `unsafe` block @@ -47,7 +47,7 @@ LL | unsafe { | ^^^^^^ unnecessary `unsafe` block error: unnecessary `unsafe` block - --> $DIR/lint-unused-unsafe.rs:33:9 + --> $DIR/lint-unused-unsafe-thir.rs:35:9 | LL | unsafe { | ------ because it's nested under this `unsafe` block @@ -55,7 +55,7 @@ LL | unsafe { | ^^^^^^ unnecessary `unsafe` block error: unnecessary `unsafe` block - --> $DIR/lint-unused-unsafe.rs:32:5 + --> $DIR/lint-unused-unsafe-thir.rs:34:5 | LL | unsafe fn bad7() { | ---------------- because it's nested under this `unsafe` fn diff --git a/src/test/ui/span/lint-unused-unsafe.mir.stderr b/src/test/ui/span/lint-unused-unsafe.mir.stderr index c2adb7be7a220..850550a1d8f70 100644 --- a/src/test/ui/span/lint-unused-unsafe.mir.stderr +++ b/src/test/ui/span/lint-unused-unsafe.mir.stderr @@ -1,67 +1,1824 @@ error: unnecessary `unsafe` block - --> $DIR/lint-unused-unsafe.rs:19:13 + --> $DIR/lint-unused-unsafe.rs:26:13 | LL | fn bad1() { unsafe {} } | ^^^^^^ unnecessary `unsafe` block | note: the lint level is defined here - --> $DIR/lint-unused-unsafe.rs:7:9 + --> $DIR/lint-unused-unsafe.rs:14:9 | LL | #![deny(unused_unsafe)] | ^^^^^^^^^^^^^ error: unnecessary `unsafe` block - --> $DIR/lint-unused-unsafe.rs:20:13 + --> $DIR/lint-unused-unsafe.rs:27:13 | LL | fn bad2() { unsafe { bad1() } } | ^^^^^^ unnecessary `unsafe` block error: unnecessary `unsafe` block - --> $DIR/lint-unused-unsafe.rs:21:20 + --> $DIR/lint-unused-unsafe.rs:28:20 | LL | unsafe fn bad3() { unsafe {} } - | ---------------- ^^^^^^ unnecessary `unsafe` block - | | - | because it's nested under this `unsafe` fn + | ^^^^^^ unnecessary `unsafe` block error: unnecessary `unsafe` block - --> $DIR/lint-unused-unsafe.rs:22:13 + --> $DIR/lint-unused-unsafe.rs:29:13 | LL | fn bad4() { unsafe { callback(||{}) } } | ^^^^^^ unnecessary `unsafe` block error: unnecessary `unsafe` block - --> $DIR/lint-unused-unsafe.rs:23:20 + --> $DIR/lint-unused-unsafe.rs:30:20 | LL | unsafe fn bad5() { unsafe { unsf() } } | ---------------- ^^^^^^ unnecessary `unsafe` block | | | because it's nested under this `unsafe` fn + | + = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn` + = note: `#[allow(unsafe_op_in_unsafe_fn)]` on by default error: unnecessary `unsafe` block - --> $DIR/lint-unused-unsafe.rs:26:9 + --> $DIR/lint-unused-unsafe.rs:32:5 | -LL | unsafe { // don't put the warning here - | ------ because it's nested under this `unsafe` block -LL | unsafe { - | ^^^^^^ unnecessary `unsafe` block +LL | unsafe { + | ^^^^^^ unnecessary `unsafe` block error: unnecessary `unsafe` block - --> $DIR/lint-unused-unsafe.rs:32:5 + --> $DIR/lint-unused-unsafe.rs:39:5 | -LL | unsafe fn bad7() { - | ---------------- because it's nested under this `unsafe` fn LL | unsafe { | ^^^^^^ unnecessary `unsafe` block error: unnecessary `unsafe` block - --> $DIR/lint-unused-unsafe.rs:33:9 + --> $DIR/lint-unused-unsafe.rs:40:9 | LL | unsafe fn bad7() { | ---------------- because it's nested under this `unsafe` fn LL | unsafe { LL | unsafe { | ^^^^^^ unnecessary `unsafe` block + | + = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn` + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:74:9 + | +LL | unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:83:9 + | +LL | unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:84:13 + | +LL | unsafe {} + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:85:13 + | +LL | unsafe {} + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:90:9 + | +LL | unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:100:13 + | +LL | unsafe { + | ------ because it's nested under this `unsafe` block +LL | unsf(); +LL | unsafe { unsf() } + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:101:13 + | +LL | unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | unsafe { unsf() } + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:102:13 + | +LL | unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | unsafe { unsf() } + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:112:17 + | +LL | unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | unsafe { unsf() } + | ^^^^^^ unnecessary `unsafe` block + | +note: the lint level is defined here + --> $DIR/lint-unused-unsafe.rs:110:20 + | +LL | #[deny(unused_unsafe)] + | ^^^^^^^^^^^^^ + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:113:17 + | +LL | unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | unsafe { unsf() } + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:114:17 + | +LL | unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | unsafe { unsf() } + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:124:9 + | +LL | unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:134:9 + | +LL | unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:135:13 + | +LL | unsafe {} + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:136:13 + | +LL | unsafe {} + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:142:9 + | +LL | unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:153:13 + | +LL | unsafe { + | ------ because it's nested under this `unsafe` block +LL | unsf(); +LL | unsafe { unsf() } + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:154:13 + | +LL | unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | unsafe { unsf() } + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:155:13 + | +LL | unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | unsafe { unsf() } + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:166:17 + | +LL | unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | unsafe { unsf() } + | ^^^^^^ unnecessary `unsafe` block + | +note: the lint level is defined here + --> $DIR/lint-unused-unsafe.rs:164:20 + | +LL | #[deny(unused_unsafe)] + | ^^^^^^^^^^^^^ + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:167:17 + | +LL | unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | unsafe { unsf() } + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:168:17 + | +LL | unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | unsafe { unsf() } + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:178:9 + | +LL | unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:188:9 + | +LL | unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:189:13 + | +LL | unsafe {} + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:190:13 + | +LL | unsafe {} + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:196:9 + | +LL | unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:197:13 + | +LL | unsafe fn granularity_2() { + | ------------------------- because it's nested under this `unsafe` fn +LL | unsafe { +LL | unsafe { unsf() } + | ^^^^^^ unnecessary `unsafe` block + | + = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn` +note: the lint level is defined here + --> $DIR/lint-unused-unsafe.rs:194:13 + | +LL | #[allow(unsafe_op_in_unsafe_fn)] + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:198:13 + | +LL | unsafe fn granularity_2() { + | ------------------------- because it's nested under this `unsafe` fn +... +LL | unsafe { unsf() } + | ^^^^^^ unnecessary `unsafe` block + | + = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn` + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:199:13 + | +LL | unsafe fn granularity_2() { + | ------------------------- because it's nested under this `unsafe` fn +... +LL | unsafe { unsf() } + | ^^^^^^ unnecessary `unsafe` block + | + = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn` + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:205:9 + | +LL | unsafe fn top_level_used_2() { + | ---------------------------- because it's nested under this `unsafe` fn +LL | unsafe { + | ^^^^^^ unnecessary `unsafe` block + | + = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn` +note: the lint level is defined here + --> $DIR/lint-unused-unsafe.rs:203:13 + | +LL | #[allow(unsafe_op_in_unsafe_fn)] + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:207:13 + | +LL | unsafe fn top_level_used_2() { + | ---------------------------- because it's nested under this `unsafe` fn +... +LL | unsafe { unsf() } + | ^^^^^^ unnecessary `unsafe` block + | + = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn` + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:208:13 + | +LL | unsafe fn top_level_used_2() { + | ---------------------------- because it's nested under this `unsafe` fn +... +LL | unsafe { unsf() } + | ^^^^^^ unnecessary `unsafe` block + | + = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn` + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:209:13 + | +LL | unsafe fn top_level_used_2() { + | ---------------------------- because it's nested under this `unsafe` fn +... +LL | unsafe { unsf() } + | ^^^^^^ unnecessary `unsafe` block + | + = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn` + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:220:17 + | +LL | unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | unsafe { unsf() } + | ^^^^^^ unnecessary `unsafe` block + | +note: the lint level is defined here + --> $DIR/lint-unused-unsafe.rs:218:20 + | +LL | #[deny(unused_unsafe)] + | ^^^^^^^^^^^^^ + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:221:17 + | +LL | unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | unsafe { unsf() } + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:222:17 + | +LL | unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | unsafe { unsf() } + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:242:9 + | +LL | unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:254:9 + | +LL | unsafe fn granular_disallow_op_in_unsafe_fn_3() { + | ----------------------------------------------- because it's nested under this `unsafe` fn +LL | unsafe { + | ^^^^^^ unnecessary `unsafe` block + | + = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn` +note: the lint level is defined here + --> $DIR/lint-unused-unsafe.rs:252:13 + | +LL | #[allow(unsafe_op_in_unsafe_fn)] + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:268:13 + | +LL | unsafe { + | ------ because it's nested under this `unsafe` block +LL | unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:286:20 + | +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:295:20 + | +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:296:24 + | +LL | let _ = || unsafe {}; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:297:24 + | +LL | let _ = || unsafe {}; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:302:20 + | +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:312:24 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +LL | unsf(); +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:313:24 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:314:24 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:324:28 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + | +note: the lint level is defined here + --> $DIR/lint-unused-unsafe.rs:322:20 + | +LL | #[deny(unused_unsafe)] + | ^^^^^^^^^^^^^ + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:325:28 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:326:28 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:336:20 + | +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:346:20 + | +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:347:24 + | +LL | let _ = || unsafe {}; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:348:24 + | +LL | let _ = || unsafe {}; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:354:20 + | +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:365:24 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +LL | unsf(); +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:366:24 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:367:24 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:378:28 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + | +note: the lint level is defined here + --> $DIR/lint-unused-unsafe.rs:376:20 + | +LL | #[deny(unused_unsafe)] + | ^^^^^^^^^^^^^ + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:379:28 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:380:28 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:390:20 + | +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:400:20 + | +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:401:24 + | +LL | let _ = || unsafe {}; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:402:24 + | +LL | let _ = || unsafe {}; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:408:20 + | +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:409:24 + | +LL | unsafe fn granularity_2() { + | ------------------------- because it's nested under this `unsafe` fn +LL | let _ = || unsafe { +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + | + = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn` +note: the lint level is defined here + --> $DIR/lint-unused-unsafe.rs:406:13 + | +LL | #[allow(unsafe_op_in_unsafe_fn)] + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:410:24 + | +LL | unsafe fn granularity_2() { + | ------------------------- because it's nested under this `unsafe` fn +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + | + = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn` + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:411:24 + | +LL | unsafe fn granularity_2() { + | ------------------------- because it's nested under this `unsafe` fn +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + | + = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn` + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:417:20 + | +LL | unsafe fn top_level_used_2() { + | ---------------------------- because it's nested under this `unsafe` fn +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + | + = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn` +note: the lint level is defined here + --> $DIR/lint-unused-unsafe.rs:415:13 + | +LL | #[allow(unsafe_op_in_unsafe_fn)] + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:419:24 + | +LL | unsafe fn top_level_used_2() { + | ---------------------------- because it's nested under this `unsafe` fn +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + | + = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn` + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:420:24 + | +LL | unsafe fn top_level_used_2() { + | ---------------------------- because it's nested under this `unsafe` fn +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + | + = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn` + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:421:24 + | +LL | unsafe fn top_level_used_2() { + | ---------------------------- because it's nested under this `unsafe` fn +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + | + = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn` + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:432:28 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + | +note: the lint level is defined here + --> $DIR/lint-unused-unsafe.rs:430:20 + | +LL | #[deny(unused_unsafe)] + | ^^^^^^^^^^^^^ + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:433:28 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:434:28 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:454:20 + | +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:466:20 + | +LL | unsafe fn granular_disallow_op_in_unsafe_fn_3() { + | ----------------------------------------------- because it's nested under this `unsafe` fn +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + | + = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn` +note: the lint level is defined here + --> $DIR/lint-unused-unsafe.rs:464:13 + | +LL | #[allow(unsafe_op_in_unsafe_fn)] + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:480:24 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:499:20 + | +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:508:20 + | +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:509:24 + | +LL | let _ = || unsafe {}; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:510:24 + | +LL | let _ = || unsafe {}; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:515:20 + | +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:525:24 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +LL | let _ = || unsf(); +LL | let _ = || unsafe { let _ = || unsf(); }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:526:24 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { let _ = || unsf(); }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:527:24 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { let _ = || unsf(); }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:537:28 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { let _ = || unsf(); }; + | ^^^^^^ unnecessary `unsafe` block + | +note: the lint level is defined here + --> $DIR/lint-unused-unsafe.rs:535:20 + | +LL | #[deny(unused_unsafe)] + | ^^^^^^^^^^^^^ + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:538:28 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { let _ = || unsf(); }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:539:28 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { let _ = || unsf(); }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:549:20 + | +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:559:20 + | +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:560:24 + | +LL | let _ = || unsafe {}; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:561:24 + | +LL | let _ = || unsafe {}; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:567:20 + | +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:578:24 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +LL | let _ = || unsf(); +LL | let _ = || unsafe { let _ = || unsf(); }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:579:24 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { let _ = || unsf(); }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:580:24 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { let _ = || unsf(); }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:591:28 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { let _ = || unsf(); }; + | ^^^^^^ unnecessary `unsafe` block + | +note: the lint level is defined here + --> $DIR/lint-unused-unsafe.rs:589:20 + | +LL | #[deny(unused_unsafe)] + | ^^^^^^^^^^^^^ + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:592:28 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { let _ = || unsf(); }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:593:28 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { let _ = || unsf(); }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:603:20 + | +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:613:20 + | +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:614:24 + | +LL | let _ = || unsafe {}; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:615:24 + | +LL | let _ = || unsafe {}; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:621:20 + | +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:622:24 + | +LL | unsafe fn granularity_2() { + | ------------------------- because it's nested under this `unsafe` fn +LL | let _ = || unsafe { +LL | let _ = || unsafe { let _ = || unsf(); }; + | ^^^^^^ unnecessary `unsafe` block + | + = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn` +note: the lint level is defined here + --> $DIR/lint-unused-unsafe.rs:619:13 + | +LL | #[allow(unsafe_op_in_unsafe_fn)] + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:623:24 + | +LL | unsafe fn granularity_2() { + | ------------------------- because it's nested under this `unsafe` fn +... +LL | let _ = || unsafe { let _ = || unsf(); }; + | ^^^^^^ unnecessary `unsafe` block + | + = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn` + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:624:24 + | +LL | unsafe fn granularity_2() { + | ------------------------- because it's nested under this `unsafe` fn +... +LL | let _ = || unsafe { let _ = || unsf(); }; + | ^^^^^^ unnecessary `unsafe` block + | + = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn` + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:630:20 + | +LL | unsafe fn top_level_used_2() { + | ---------------------------- because it's nested under this `unsafe` fn +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + | + = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn` +note: the lint level is defined here + --> $DIR/lint-unused-unsafe.rs:628:13 + | +LL | #[allow(unsafe_op_in_unsafe_fn)] + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:632:24 + | +LL | unsafe fn top_level_used_2() { + | ---------------------------- because it's nested under this `unsafe` fn +... +LL | let _ = || unsafe { let _ = || unsf(); }; + | ^^^^^^ unnecessary `unsafe` block + | + = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn` + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:633:24 + | +LL | unsafe fn top_level_used_2() { + | ---------------------------- because it's nested under this `unsafe` fn +... +LL | let _ = || unsafe { let _ = || unsf(); }; + | ^^^^^^ unnecessary `unsafe` block + | + = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn` + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:634:24 + | +LL | unsafe fn top_level_used_2() { + | ---------------------------- because it's nested under this `unsafe` fn +... +LL | let _ = || unsafe { let _ = || unsf(); }; + | ^^^^^^ unnecessary `unsafe` block + | + = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn` + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:645:28 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { let _ = || unsf(); }; + | ^^^^^^ unnecessary `unsafe` block + | +note: the lint level is defined here + --> $DIR/lint-unused-unsafe.rs:643:20 + | +LL | #[deny(unused_unsafe)] + | ^^^^^^^^^^^^^ + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:646:28 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { let _ = || unsf(); }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:647:28 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { let _ = || unsf(); }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:667:20 + | +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:679:20 + | +LL | unsafe fn granular_disallow_op_in_unsafe_fn_3() { + | ----------------------------------------------- because it's nested under this `unsafe` fn +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + | + = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn` +note: the lint level is defined here + --> $DIR/lint-unused-unsafe.rs:677:13 + | +LL | #[allow(unsafe_op_in_unsafe_fn)] + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:693:24 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:711:24 + | +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:721:24 + | +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:722:28 + | +LL | let _ = || unsafe {}; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:723:28 + | +LL | let _ = || unsafe {}; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:729:24 + | +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:740:28 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +LL | unsf(); +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:741:28 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:742:28 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:753:32 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + | +note: the lint level is defined here + --> $DIR/lint-unused-unsafe.rs:751:24 + | +LL | #[deny(unused_unsafe)] + | ^^^^^^^^^^^^^ + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:754:32 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:755:32 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:765:24 + | +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:775:24 + | +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:776:28 + | +LL | let _ = || unsafe {}; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:777:28 + | +LL | let _ = || unsafe {}; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:783:24 + | +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:784:28 + | +LL | unsafe fn granularity_2() { + | ------------------------- because it's nested under this `unsafe` fn +LL | let _ = || unsafe { +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + | + = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn` +note: the lint level is defined here + --> $DIR/lint-unused-unsafe.rs:781:17 + | +LL | #[allow(unsafe_op_in_unsafe_fn)] + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:785:28 + | +LL | unsafe fn granularity_2() { + | ------------------------- because it's nested under this `unsafe` fn +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + | + = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn` + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:786:28 + | +LL | unsafe fn granularity_2() { + | ------------------------- because it's nested under this `unsafe` fn +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + | + = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn` + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:792:24 + | +LL | unsafe fn top_level_used_2() { + | ---------------------------- because it's nested under this `unsafe` fn +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + | + = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn` +note: the lint level is defined here + --> $DIR/lint-unused-unsafe.rs:790:17 + | +LL | #[allow(unsafe_op_in_unsafe_fn)] + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:794:28 + | +LL | unsafe fn top_level_used_2() { + | ---------------------------- because it's nested under this `unsafe` fn +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + | + = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn` + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:795:28 + | +LL | unsafe fn top_level_used_2() { + | ---------------------------- because it's nested under this `unsafe` fn +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + | + = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn` + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:796:28 + | +LL | unsafe fn top_level_used_2() { + | ---------------------------- because it's nested under this `unsafe` fn +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + | + = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn` + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:807:32 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + | +note: the lint level is defined here + --> $DIR/lint-unused-unsafe.rs:805:24 + | +LL | #[deny(unused_unsafe)] + | ^^^^^^^^^^^^^ + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:808:32 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:809:32 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:829:24 + | +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:841:24 + | +LL | unsafe fn granular_disallow_op_in_unsafe_fn_3() { + | ----------------------------------------------- because it's nested under this `unsafe` fn +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + | + = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn` +note: the lint level is defined here + --> $DIR/lint-unused-unsafe.rs:839:17 + | +LL | #[allow(unsafe_op_in_unsafe_fn)] + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:855:28 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:869:24 + | +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:879:24 + | +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:880:28 + | +LL | let _ = || unsafe {}; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:881:28 + | +LL | let _ = || unsafe {}; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:887:24 + | +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:898:28 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +LL | unsf(); +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:899:28 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:900:28 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:911:32 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + | +note: the lint level is defined here + --> $DIR/lint-unused-unsafe.rs:909:24 + | +LL | #[deny(unused_unsafe)] + | ^^^^^^^^^^^^^ + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:912:32 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:913:32 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:923:24 + | +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:933:24 + | +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:934:28 + | +LL | let _ = || unsafe {}; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:935:28 + | +LL | let _ = || unsafe {}; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:941:24 + | +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:942:28 + | +LL | unsafe fn granularity_2() { + | ------------------------- because it's nested under this `unsafe` fn +LL | let _ = || unsafe { +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + | + = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn` +note: the lint level is defined here + --> $DIR/lint-unused-unsafe.rs:939:17 + | +LL | #[allow(unsafe_op_in_unsafe_fn)] + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:943:28 + | +LL | unsafe fn granularity_2() { + | ------------------------- because it's nested under this `unsafe` fn +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + | + = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn` + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:944:28 + | +LL | unsafe fn granularity_2() { + | ------------------------- because it's nested under this `unsafe` fn +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + | + = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn` + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:950:24 + | +LL | unsafe fn top_level_used_2() { + | ---------------------------- because it's nested under this `unsafe` fn +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + | + = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn` +note: the lint level is defined here + --> $DIR/lint-unused-unsafe.rs:948:17 + | +LL | #[allow(unsafe_op_in_unsafe_fn)] + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:952:28 + | +LL | unsafe fn top_level_used_2() { + | ---------------------------- because it's nested under this `unsafe` fn +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + | + = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn` + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:953:28 + | +LL | unsafe fn top_level_used_2() { + | ---------------------------- because it's nested under this `unsafe` fn +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + | + = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn` + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:954:28 + | +LL | unsafe fn top_level_used_2() { + | ---------------------------- because it's nested under this `unsafe` fn +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + | + = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn` + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:965:32 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + | +note: the lint level is defined here + --> $DIR/lint-unused-unsafe.rs:963:24 + | +LL | #[deny(unused_unsafe)] + | ^^^^^^^^^^^^^ + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:966:32 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:967:32 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = || unsafe { unsf() }; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:987:24 + | +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:999:24 + | +LL | unsafe fn granular_disallow_op_in_unsafe_fn_3() { + | ----------------------------------------------- because it's nested under this `unsafe` fn +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + | + = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn` +note: the lint level is defined here + --> $DIR/lint-unused-unsafe.rs:997:17 + | +LL | #[allow(unsafe_op_in_unsafe_fn)] + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:1013:28 + | +LL | let _ = || unsafe { + | ------ because it's nested under this `unsafe` block +LL | let _ = || unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:1044:9 + | +LL | unsafe fn multiple_unsafe_op_in_unsafe_fn_allows() { + | -------------------------------------------------- because it's nested under this `unsafe` fn +LL | unsafe { + | ^^^^^^ unnecessary `unsafe` block + | + = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn` +note: the lint level is defined here + --> $DIR/lint-unused-unsafe.rs:1045:21 + | +LL | #[allow(unsafe_op_in_unsafe_fn)] + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:1059:29 + | +LL | let _ = async { unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:1066:33 + | +LL | let _ = async { unsafe { + | ------ because it's nested under this `unsafe` block +LL | let _ = async { unsf() }; +LL | let _ = async { unsafe { let _ = async { unsf() }; }}; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:1067:33 + | +LL | let _ = async { unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = async { unsafe { let _ = async { unsf() }; }}; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:1068:33 + | +LL | let _ = async { unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | let _ = async { unsafe { let _ = async { unsf() }; }}; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:1073:29 + | +LL | let _ = async { unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:1074:33 + | +LL | async unsafe fn async_blocks() { + | ------------------------------ because it's nested under this `unsafe` fn +... +LL | let _ = async { unsafe { let _ = async { unsf() }; }}; + | ^^^^^^ unnecessary `unsafe` block + | + = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn` +note: the lint level is defined here + --> $DIR/lint-unused-unsafe.rs:1071:17 + | +LL | #[allow(unsafe_op_in_unsafe_fn)] + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:1075:33 + | +LL | async unsafe fn async_blocks() { + | ------------------------------ because it's nested under this `unsafe` fn +... +LL | let _ = async { unsafe { let _ = async { unsf() }; }}; + | ^^^^^^ unnecessary `unsafe` block + | + = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn` + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:1076:33 + | +LL | async unsafe fn async_blocks() { + | ------------------------------ because it's nested under this `unsafe` fn +... +LL | let _ = async { unsafe { let _ = async { unsf() }; }}; + | ^^^^^^ unnecessary `unsafe` block + | + = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn` + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:1078:29 + | +LL | async unsafe fn async_blocks() { + | ------------------------------ because it's nested under this `unsafe` fn +... +LL | let _ = async { unsafe { + | ^^^^^^ unnecessary `unsafe` block + | + = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn` + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:1080:33 + | +LL | async unsafe fn async_blocks() { + | ------------------------------ because it's nested under this `unsafe` fn +... +LL | let _ = async { unsafe { let _ = async { unsf() }; }}; + | ^^^^^^ unnecessary `unsafe` block + | + = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn` + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:1081:33 + | +LL | async unsafe fn async_blocks() { + | ------------------------------ because it's nested under this `unsafe` fn +... +LL | let _ = async { unsafe { let _ = async { unsf() }; }}; + | ^^^^^^ unnecessary `unsafe` block + | + = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn` + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:1082:33 + | +LL | async unsafe fn async_blocks() { + | ------------------------------ because it's nested under this `unsafe` fn +... +LL | let _ = async { unsafe { let _ = async { unsf() }; }}; + | ^^^^^^ unnecessary `unsafe` block + | + = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn` + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:1092:22 + | +LL | let _x: [(); unsafe { 0 }] = []; + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:1096:22 + | +LL | let _x: [(); unsafe { unsafe { size() } }] = []; + | ^^^^^^ unnecessary `unsafe` block -error: aborting due to 8 previous errors +error: aborting due to 201 previous errors diff --git a/src/test/ui/span/lint-unused-unsafe.rs b/src/test/ui/span/lint-unused-unsafe.rs index b889cc981cad1..f8d1dff3572be 100644 --- a/src/test/ui/span/lint-unused-unsafe.rs +++ b/src/test/ui/span/lint-unused-unsafe.rs @@ -1,7 +1,14 @@ // Exercise the unused_unsafe attribute in some positive and negative cases -// revisions: mir thir -// [thir]compile-flags: -Zthir-unsafeck + +// edition:2018 + +// revisions: mir + +// FIXME: Adapt -Zthir-unsafeck to behave the same as the mir version after #93678, +// then delete lint-unused-unsafe-thir.rs, and go back to using the settings below +// // revisions: mir thir +// // [thir]compile-flags: -Zthir-unsafeck #![allow(dead_code)] #![deny(unused_unsafe)] @@ -22,8 +29,8 @@ unsafe fn bad3() { unsafe {} } //~ ERROR: unnecessary `unsafe` block fn bad4() { unsafe { callback(||{}) } } //~ ERROR: unnecessary `unsafe` block unsafe fn bad5() { unsafe { unsf() } } //~ ERROR: unnecessary `unsafe` block fn bad6() { - unsafe { // don't put the warning here - unsafe { //~ ERROR: unnecessary `unsafe` block + unsafe { //~ ERROR: unnecessary `unsafe` block + unsafe { // don't put the warning here unsf() } } @@ -57,3 +64,1037 @@ fn good4() { unsafe { foo::bar() } } #[allow(unused_unsafe)] fn allowed() { unsafe {} } fn main() {} + +mod additional_tests { + unsafe fn unsf() {} + + // some tests + + fn inner_ignored() { + unsafe { //~ ERROR: unnecessary `unsafe` block + #[allow(unused_unsafe)] + unsafe { + unsf() + } + } + } + + fn multi_level_unused() { + unsafe { //~ ERROR: unnecessary `unsafe` block + unsafe {} //~ ERROR: unnecessary `unsafe` block + unsafe {} //~ ERROR: unnecessary `unsafe` block + } + } + + fn granularity() { + unsafe { //~ ERROR: unnecessary `unsafe` block + unsafe { unsf() } + unsafe { unsf() } + unsafe { unsf() } + } + } + + fn top_level_used() { + unsafe { + unsf(); + unsafe { unsf() } //~ ERROR: unnecessary `unsafe` block + unsafe { unsf() } //~ ERROR: unnecessary `unsafe` block + unsafe { unsf() } //~ ERROR: unnecessary `unsafe` block + } + + } + + fn top_level_ignored() { + #[allow(unused_unsafe)] + unsafe { + #[deny(unused_unsafe)] + { + unsafe { unsf() } //~ ERROR: unnecessary `unsafe` block + unsafe { unsf() } //~ ERROR: unnecessary `unsafe` block + unsafe { unsf() } //~ ERROR: unnecessary `unsafe` block + } + } + + } + + // same tests in unsafe fn without unsafe_op_in_unsafe_fn allowed + + #[deny(unsafe_op_in_unsafe_fn)] + unsafe fn inner_ignored_1() { + unsafe { //~ ERROR: unnecessary `unsafe` block + #[allow(unused_unsafe)] + unsafe { + unsf() + } + } + } + + #[deny(unsafe_op_in_unsafe_fn)] + unsafe fn multi_level_unused_1() { + unsafe { //~ ERROR: unnecessary `unsafe` block + unsafe {} //~ ERROR: unnecessary `unsafe` block + unsafe {} //~ ERROR: unnecessary `unsafe` block + } + } + + #[deny(unsafe_op_in_unsafe_fn)] + unsafe fn granularity_1() { + unsafe { //~ ERROR: unnecessary `unsafe` block + unsafe { unsf() } + unsafe { unsf() } + unsafe { unsf() } + } + } + + #[deny(unsafe_op_in_unsafe_fn)] + unsafe fn top_level_used_1() { + unsafe { + unsf(); + unsafe { unsf() } //~ ERROR: unnecessary `unsafe` block + unsafe { unsf() } //~ ERROR: unnecessary `unsafe` block + unsafe { unsf() } //~ ERROR: unnecessary `unsafe` block + } + + } + + #[deny(unsafe_op_in_unsafe_fn)] + unsafe fn top_level_ignored_1() { + #[allow(unused_unsafe)] + unsafe { + #[deny(unused_unsafe)] + { + unsafe { unsf() } //~ ERROR: unnecessary `unsafe` block + unsafe { unsf() } //~ ERROR: unnecessary `unsafe` block + unsafe { unsf() } //~ ERROR: unnecessary `unsafe` block + } + } + } + + // same tests, but unsafe_op_in_unsafe_fn allowed, + // so that *all* unsafe blocks are unused + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn inner_ignored_2() { + unsafe { //~ ERROR: unnecessary `unsafe` block + #[allow(unused_unsafe)] + unsafe { + unsf() + } + } + } + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn multi_level_unused_2() { + unsafe { //~ ERROR: unnecessary `unsafe` block + unsafe {} //~ ERROR: unnecessary `unsafe` block + unsafe {} //~ ERROR: unnecessary `unsafe` block + } + } + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn granularity_2() { + unsafe { //~ ERROR: unnecessary `unsafe` block + unsafe { unsf() } //~ ERROR: unnecessary `unsafe` block + unsafe { unsf() } //~ ERROR: unnecessary `unsafe` block + unsafe { unsf() } //~ ERROR: unnecessary `unsafe` block + } + } + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn top_level_used_2() { + unsafe { //~ ERROR: unnecessary `unsafe` block + unsf(); + unsafe { unsf() } //~ ERROR: unnecessary `unsafe` block + unsafe { unsf() } //~ ERROR: unnecessary `unsafe` block + unsafe { unsf() } //~ ERROR: unnecessary `unsafe` block + } + + } + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn top_level_ignored_2() { + #[allow(unused_unsafe)] + unsafe { + #[deny(unused_unsafe)] + { + unsafe { unsf() } //~ ERROR: unnecessary `unsafe` block + unsafe { unsf() } //~ ERROR: unnecessary `unsafe` block + unsafe { unsf() } //~ ERROR: unnecessary `unsafe` block + } + } + } + + // additional tests when using unsafe_op_in_unsafe_fn + // in more complex ways + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn granular_disallow_op_in_unsafe_fn() { + unsafe { + #[deny(unsafe_op_in_unsafe_fn)] + { + unsf(); + } + } + } + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn granular_disallow_op_in_unsafe_fn_2() { + unsafe { //~ ERROR: unnecessary `unsafe` block + unsafe { + #[deny(unsafe_op_in_unsafe_fn)] + { + unsf(); + } + } + } + } + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn granular_disallow_op_in_unsafe_fn_3() { + unsafe { //~ ERROR: unnecessary `unsafe` block + unsafe { + #[deny(unsafe_op_in_unsafe_fn)] + { + unsf(); + } + } + unsf(); + } + } + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn granular_disallow_op_in_unsafe_fn_4() { + unsafe { + unsafe { //~ ERROR: unnecessary `unsafe` block + unsf(); + } + #[deny(unsafe_op_in_unsafe_fn)] + { + unsf(); + } + } + } +} + +// the same set of tests, with closures everywhere +mod additional_tests_closures { + unsafe fn unsf() {} + + // some tests + + fn inner_ignored() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + #[allow(unused_unsafe)] + let _ = || unsafe { + unsf() + }; + }; + } + + fn multi_level_unused() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe {}; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe {}; //~ ERROR: unnecessary `unsafe` block + }; + } + + fn granularity() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; + let _ = || unsafe { unsf() }; + let _ = || unsafe { unsf() }; + }; + } + + fn top_level_used() { + let _ = || unsafe { + unsf(); + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + }; + + } + + fn top_level_ignored() { + #[allow(unused_unsafe)] + let _ = || unsafe { + #[deny(unused_unsafe)] + { + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + } + }; + + } + + // same tests in unsafe fn without unsafe_op_in_unsafe_fn allowed + + #[deny(unsafe_op_in_unsafe_fn)] + unsafe fn inner_ignored_1() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + #[allow(unused_unsafe)] + let _ = || unsafe { + unsf() + }; + }; + } + + #[deny(unsafe_op_in_unsafe_fn)] + unsafe fn multi_level_unused_1() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe {}; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe {}; //~ ERROR: unnecessary `unsafe` block + }; + } + + #[deny(unsafe_op_in_unsafe_fn)] + unsafe fn granularity_1() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; + let _ = || unsafe { unsf() }; + let _ = || unsafe { unsf() }; + }; + } + + #[deny(unsafe_op_in_unsafe_fn)] + unsafe fn top_level_used_1() { + let _ = || unsafe { + unsf(); + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + }; + + } + + #[deny(unsafe_op_in_unsafe_fn)] + unsafe fn top_level_ignored_1() { + #[allow(unused_unsafe)] + let _ = || unsafe { + #[deny(unused_unsafe)] + { + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + } + }; + } + + // same tests, but unsafe_op_in_unsafe_fn allowed, + // so that *all* unsafe blocks are unused + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn inner_ignored_2() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + #[allow(unused_unsafe)] + let _ = || unsafe { + unsf() + }; + }; + } + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn multi_level_unused_2() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe {}; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe {}; //~ ERROR: unnecessary `unsafe` block + }; + } + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn granularity_2() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + }; + } + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn top_level_used_2() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + unsf(); + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + }; + + } + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn top_level_ignored_2() { + #[allow(unused_unsafe)] + let _ = || unsafe { + #[deny(unused_unsafe)] + { + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + } + }; + } + + // additional tests when using unsafe_op_in_unsafe_fn + // in more complex ways + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn granular_disallow_op_in_unsafe_fn() { + let _ = || unsafe { + #[deny(unsafe_op_in_unsafe_fn)] + { + unsf(); + } + }; + } + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn granular_disallow_op_in_unsafe_fn_2() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { + #[deny(unsafe_op_in_unsafe_fn)] + { + unsf(); + } + }; + }; + } + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn granular_disallow_op_in_unsafe_fn_3() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { + #[deny(unsafe_op_in_unsafe_fn)] + { + unsf(); + } + }; + unsf(); + }; + } + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn granular_disallow_op_in_unsafe_fn_4() { + let _ = || unsafe { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + unsf(); + }; + #[deny(unsafe_op_in_unsafe_fn)] + { + unsf(); + } + }; + } +} + +// the same set of tests, with closures everywhere +// and closures on the unsafe fn calls +mod additional_tests_even_more_closures { + unsafe fn unsf() {} + + // some tests + + fn inner_ignored() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + #[allow(unused_unsafe)] + let _ = || unsafe { + let _ = || unsf(); + }; + }; + } + + fn multi_level_unused() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe {}; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe {}; //~ ERROR: unnecessary `unsafe` block + }; + } + + fn granularity() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { let _ = || unsf(); }; + let _ = || unsafe { let _ = || unsf(); }; + let _ = || unsafe { let _ = || unsf(); }; + }; + } + + fn top_level_used() { + let _ = || unsafe { + let _ = || unsf(); + let _ = || unsafe { let _ = || unsf(); }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { let _ = || unsf(); }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { let _ = || unsf(); }; //~ ERROR: unnecessary `unsafe` block + }; + + } + + fn top_level_ignored() { + #[allow(unused_unsafe)] + let _ = || unsafe { + #[deny(unused_unsafe)] + { + let _ = || unsafe { let _ = || unsf(); }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { let _ = || unsf(); }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { let _ = || unsf(); }; //~ ERROR: unnecessary `unsafe` block + } + }; + + } + + // same tests in unsafe fn without unsafe_op_in_unsafe_fn allowed + + #[deny(unsafe_op_in_unsafe_fn)] + unsafe fn inner_ignored_1() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + #[allow(unused_unsafe)] + let _ = || unsafe { + let _ = || unsf(); + }; + }; + } + + #[deny(unsafe_op_in_unsafe_fn)] + unsafe fn multi_level_unused_1() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe {}; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe {}; //~ ERROR: unnecessary `unsafe` block + }; + } + + #[deny(unsafe_op_in_unsafe_fn)] + unsafe fn granularity_1() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { let _ = || unsf(); }; + let _ = || unsafe { let _ = || unsf(); }; + let _ = || unsafe { let _ = || unsf(); }; + }; + } + + #[deny(unsafe_op_in_unsafe_fn)] + unsafe fn top_level_used_1() { + let _ = || unsafe { + let _ = || unsf(); + let _ = || unsafe { let _ = || unsf(); }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { let _ = || unsf(); }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { let _ = || unsf(); }; //~ ERROR: unnecessary `unsafe` block + }; + + } + + #[deny(unsafe_op_in_unsafe_fn)] + unsafe fn top_level_ignored_1() { + #[allow(unused_unsafe)] + let _ = || unsafe { + #[deny(unused_unsafe)] + { + let _ = || unsafe { let _ = || unsf(); }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { let _ = || unsf(); }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { let _ = || unsf(); }; //~ ERROR: unnecessary `unsafe` block + } + }; + } + + // same tests, but unsafe_op_in_unsafe_fn allowed, + // so that *all* unsafe blocks are unused + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn inner_ignored_2() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + #[allow(unused_unsafe)] + let _ = || unsafe { + let _ = || unsf(); + }; + }; + } + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn multi_level_unused_2() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe {}; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe {}; //~ ERROR: unnecessary `unsafe` block + }; + } + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn granularity_2() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { let _ = || unsf(); }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { let _ = || unsf(); }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { let _ = || unsf(); }; //~ ERROR: unnecessary `unsafe` block + }; + } + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn top_level_used_2() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + let _ = || unsf(); + let _ = || unsafe { let _ = || unsf(); }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { let _ = || unsf(); }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { let _ = || unsf(); }; //~ ERROR: unnecessary `unsafe` block + }; + + } + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn top_level_ignored_2() { + #[allow(unused_unsafe)] + let _ = || unsafe { + #[deny(unused_unsafe)] + { + let _ = || unsafe { let _ = || unsf(); }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { let _ = || unsf(); }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { let _ = || unsf(); }; //~ ERROR: unnecessary `unsafe` block + } + }; + } + + // additional tests when using unsafe_op_in_unsafe_fn + // in more complex ways + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn granular_disallow_op_in_unsafe_fn() { + let _ = || unsafe { + #[deny(unsafe_op_in_unsafe_fn)] + { + let _ = || unsf(); + } + }; + } + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn granular_disallow_op_in_unsafe_fn_2() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { + #[deny(unsafe_op_in_unsafe_fn)] + { + let _ = || unsf(); + } + }; + }; + } + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn granular_disallow_op_in_unsafe_fn_3() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { + #[deny(unsafe_op_in_unsafe_fn)] + { + let _ = || unsf(); + } + }; + let _ = || unsf(); + }; + } + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn granular_disallow_op_in_unsafe_fn_4() { + let _ = || unsafe { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + let _ = || unsf(); + }; + #[deny(unsafe_op_in_unsafe_fn)] + { + let _ = || unsf(); + } + }; + } +} + +mod item_likes { + unsafe fn unsf() {} + + struct S; + impl S { + #[deny(unsafe_op_in_unsafe_fn)] + unsafe fn inner_ignored_1() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + #[allow(unused_unsafe)] + let _ = || unsafe { + unsf() + }; + }; + } + + #[deny(unsafe_op_in_unsafe_fn)] + unsafe fn multi_level_unused_1() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe {}; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe {}; //~ ERROR: unnecessary `unsafe` block + }; + } + + #[deny(unsafe_op_in_unsafe_fn)] + unsafe fn granularity_1() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; + let _ = || unsafe { unsf() }; + let _ = || unsafe { unsf() }; + }; + } + + #[deny(unsafe_op_in_unsafe_fn)] + unsafe fn top_level_used_1() { + let _ = || unsafe { + unsf(); + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + }; + + } + + #[deny(unsafe_op_in_unsafe_fn)] + unsafe fn top_level_ignored_1() { + #[allow(unused_unsafe)] + let _ = || unsafe { + #[deny(unused_unsafe)] + { + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + } + }; + } + + // same tests, but unsafe_op_in_unsafe_fn allowed, + // so that *all* unsafe blocks are unused + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn inner_ignored_2() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + #[allow(unused_unsafe)] + let _ = || unsafe { + unsf() + }; + }; + } + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn multi_level_unused_2() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe {}; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe {}; //~ ERROR: unnecessary `unsafe` block + }; + } + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn granularity_2() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + }; + } + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn top_level_used_2() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + unsf(); + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + }; + + } + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn top_level_ignored_2() { + #[allow(unused_unsafe)] + let _ = || unsafe { + #[deny(unused_unsafe)] + { + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + } + }; + } + + // additional tests when using unsafe_op_in_unsafe_fn + // in more complex ways + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn granular_disallow_op_in_unsafe_fn() { + let _ = || unsafe { + #[deny(unsafe_op_in_unsafe_fn)] + { + unsf(); + } + }; + } + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn granular_disallow_op_in_unsafe_fn_2() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { + #[deny(unsafe_op_in_unsafe_fn)] + { + unsf(); + } + }; + }; + } + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn granular_disallow_op_in_unsafe_fn_3() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { + #[deny(unsafe_op_in_unsafe_fn)] + { + unsf(); + } + }; + unsf(); + }; + } + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn granular_disallow_op_in_unsafe_fn_4() { + let _ = || unsafe { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + unsf(); + }; + #[deny(unsafe_op_in_unsafe_fn)] + { + unsf(); + } + }; + } + } + + trait T { + #[deny(unsafe_op_in_unsafe_fn)] + unsafe fn inner_ignored_1() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + #[allow(unused_unsafe)] + let _ = || unsafe { + unsf() + }; + }; + } + + #[deny(unsafe_op_in_unsafe_fn)] + unsafe fn multi_level_unused_1() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe {}; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe {}; //~ ERROR: unnecessary `unsafe` block + }; + } + + #[deny(unsafe_op_in_unsafe_fn)] + unsafe fn granularity_1() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; + let _ = || unsafe { unsf() }; + let _ = || unsafe { unsf() }; + }; + } + + #[deny(unsafe_op_in_unsafe_fn)] + unsafe fn top_level_used_1() { + let _ = || unsafe { + unsf(); + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + }; + + } + + #[deny(unsafe_op_in_unsafe_fn)] + unsafe fn top_level_ignored_1() { + #[allow(unused_unsafe)] + let _ = || unsafe { + #[deny(unused_unsafe)] + { + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + } + }; + } + + // same tests, but unsafe_op_in_unsafe_fn allowed, + // so that *all* unsafe blocks are unused + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn inner_ignored_2() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + #[allow(unused_unsafe)] + let _ = || unsafe { + unsf() + }; + }; + } + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn multi_level_unused_2() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe {}; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe {}; //~ ERROR: unnecessary `unsafe` block + }; + } + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn granularity_2() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + }; + } + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn top_level_used_2() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + unsf(); + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + }; + + } + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn top_level_ignored_2() { + #[allow(unused_unsafe)] + let _ = || unsafe { + #[deny(unused_unsafe)] + { + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block + } + }; + } + + // additional tests when using unsafe_op_in_unsafe_fn + // in more complex ways + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn granular_disallow_op_in_unsafe_fn() { + let _ = || unsafe { + #[deny(unsafe_op_in_unsafe_fn)] + { + unsf(); + } + }; + } + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn granular_disallow_op_in_unsafe_fn_2() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { + #[deny(unsafe_op_in_unsafe_fn)] + { + unsf(); + } + }; + }; + } + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn granular_disallow_op_in_unsafe_fn_3() { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + let _ = || unsafe { + #[deny(unsafe_op_in_unsafe_fn)] + { + unsf(); + } + }; + unsf(); + }; + } + + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn granular_disallow_op_in_unsafe_fn_4() { + let _ = || unsafe { + let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block + unsf(); + }; + #[deny(unsafe_op_in_unsafe_fn)] + { + unsf(); + } + }; + } + } +} + +mod additional_tests_extra { + unsafe fn unsf() {} + + // multiple uses with different `unsafe_op_in_unsafe_fn` in the same closure + #[allow(unsafe_op_in_unsafe_fn)] + unsafe fn granular_disallow_op_in_unsafe_fn() { + let _ = || unsafe { + let _ = || { + unsf(); + #[deny(unsafe_op_in_unsafe_fn)] + { + unsf(); + } + }; + }; + } + + #[warn(unsafe_op_in_unsafe_fn)] + unsafe fn multiple_unsafe_op_in_unsafe_fn_allows() { + unsafe { //~ ERROR: unnecessary `unsafe` block + #[allow(unsafe_op_in_unsafe_fn)] + { + unsf(); + } + #[allow(unsafe_op_in_unsafe_fn)] + { + unsf(); + } + } + } + + async unsafe fn async_blocks() { + #[deny(unsafe_op_in_unsafe_fn)] + { + let _ = async { unsafe { //~ ERROR: unnecessary `unsafe` block + let _ = async { unsafe { let _ = async { unsf() }; }}; + let _ = async { unsafe { let _ = async { unsf() }; }}; + let _ = async { unsafe { let _ = async { unsf() }; }}; + }}; + let _ = async { unsafe { + let _ = async { unsf() }; + let _ = async { unsafe { let _ = async { unsf() }; }}; //~ ERROR: unnecessary `unsafe` block + let _ = async { unsafe { let _ = async { unsf() }; }}; //~ ERROR: unnecessary `unsafe` block + let _ = async { unsafe { let _ = async { unsf() }; }}; //~ ERROR: unnecessary `unsafe` block + }}; + } + #[allow(unsafe_op_in_unsafe_fn)] + { + let _ = async { unsafe { //~ ERROR: unnecessary `unsafe` block + let _ = async { unsafe { let _ = async { unsf() }; }}; //~ ERROR: unnecessary `unsafe` block + let _ = async { unsafe { let _ = async { unsf() }; }}; //~ ERROR: unnecessary `unsafe` block + let _ = async { unsafe { let _ = async { unsf() }; }}; //~ ERROR: unnecessary `unsafe` block + }}; + let _ = async { unsafe { //~ ERROR: unnecessary `unsafe` block + let _ = async { unsf() }; + let _ = async { unsafe { let _ = async { unsf() }; }}; //~ ERROR: unnecessary `unsafe` block + let _ = async { unsafe { let _ = async { unsf() }; }}; //~ ERROR: unnecessary `unsafe` block + let _ = async { unsafe { let _ = async { unsf() }; }}; //~ ERROR: unnecessary `unsafe` block + }}; + } + } + + fn used_unsafe_in_const() { + let _x: [(); unsafe { size() }] = []; + } + + fn unused_unsafe_in_const_1() { + let _x: [(); unsafe { 0 }] = []; //~ ERROR: unnecessary `unsafe` block + } + + fn unused_unsafe_in_const_2() { + let _x: [(); unsafe { unsafe { size() } }] = []; //~ ERROR: unnecessary `unsafe` block + } + + const unsafe fn size() -> usize { 0 } +} diff --git a/src/test/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.mir.stderr b/src/test/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.mir.stderr index 9a522fac65fad..163c101772c47 100644 --- a/src/test/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.mir.stderr +++ b/src/test/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.mir.stderr @@ -76,12 +76,10 @@ LL | unsafe {} | ^^^^^^ unnecessary `unsafe` block error: unnecessary `unsafe` block - --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:47:14 + --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:47:5 | LL | unsafe { unsafe { unsf() } } - | ------ ^^^^^^ unnecessary `unsafe` block - | | - | because it's nested under this `unsafe` block + | ^^^^^^ unnecessary `unsafe` block error: unnecessary `unsafe` block --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:58:5 @@ -91,6 +89,13 @@ LL | unsafe fn allow_level() { ... LL | unsafe { unsf() } | ^^^^^^ unnecessary `unsafe` block + | + = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn` +note: the lint level is defined here + --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:51:9 + | +LL | #[allow(unsafe_op_in_unsafe_fn)] + | ^^^^^^^^^^^^^^^^^^^^^^ error: unnecessary `unsafe` block --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:70:9 @@ -100,6 +105,13 @@ LL | unsafe fn nested_allow_level() { ... LL | unsafe { unsf() } | ^^^^^^ unnecessary `unsafe` block + | + = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn` +note: the lint level is defined here + --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:63:13 + | +LL | #[allow(unsafe_op_in_unsafe_fn)] + | ^^^^^^^^^^^^^^^^^^^^^^ error[E0133]: call to unsafe function is unsafe and requires unsafe block --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:76:5 diff --git a/src/tools/clippy/clippy_lints/src/functions/must_use.rs b/src/tools/clippy/clippy_lints/src/functions/must_use.rs index 3e3718b9445f7..ea9b68d1a40e3 100644 --- a/src/tools/clippy/clippy_lints/src/functions/must_use.rs +++ b/src/tools/clippy/clippy_lints/src/functions/must_use.rs @@ -193,7 +193,7 @@ fn is_mutable_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, span: Span, tys: &m || KNOWN_WRAPPER_TYS.iter().any(|path| match_def_path(cx, adt.did, path)) && substs.types().any(|ty| is_mutable_ty(cx, ty, span, tys)) }, - ty::Tuple(substs) => substs.types().any(|ty| is_mutable_ty(cx, ty, span, tys)), + ty::Tuple(substs) => substs.iter().any(|ty| is_mutable_ty(cx, ty, span, tys)), ty::Array(ty, _) | ty::Slice(ty) => is_mutable_ty(cx, ty, span, tys), ty::RawPtr(ty::TypeAndMut { ty, mutbl }) | ty::Ref(_, ty, mutbl) => { mutbl == hir::Mutability::Mut || is_mutable_ty(cx, ty, span, tys) diff --git a/src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs b/src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs index e195fddefaba3..677b8cdf2ba0c 100644 --- a/src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs +++ b/src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs @@ -58,8 +58,8 @@ fn type_needs_ordered_drop_inner<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, see // This type doesn't implement drop, so no side effects here. // Check if any component type has any. match ty.kind() { - ty::Tuple(_) => ty.tuple_fields().any(|ty| type_needs_ordered_drop_inner(cx, ty, seen)), - ty::Array(ty, _) => type_needs_ordered_drop_inner(cx, *ty, seen), + ty::Tuple(fields) => fields.iter().any(|ty| type_needs_ordered_drop_inner(cx, ty, seen)), + &ty::Array(ty, _) => type_needs_ordered_drop_inner(cx, ty, seen), ty::Adt(adt, subs) => adt .all_fields() .map(|f| f.ty(cx.tcx, subs)) diff --git a/src/tools/clippy/clippy_lints/src/mut_key.rs b/src/tools/clippy/clippy_lints/src/mut_key.rs index b4e29101b3961..ce9ca15430e42 100644 --- a/src/tools/clippy/clippy_lints/src/mut_key.rs +++ b/src/tools/clippy/clippy_lints/src/mut_key.rs @@ -142,7 +142,7 @@ fn is_interior_mutable_type<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, span: Sp size.try_eval_usize(cx.tcx, cx.param_env).map_or(true, |u| u != 0) && is_interior_mutable_type(cx, inner_ty, span) }, - Tuple(..) => ty.tuple_fields().any(|ty| is_interior_mutable_type(cx, ty, span)), + Tuple(fields) => fields.iter().any(|ty| is_interior_mutable_type(cx, ty, span)), Adt(def, substs) => { // Special case for collections in `std` who's impl of `Hash` or `Ord` delegates to // that of their type parameters. Note: we don't include `HashSet` and `HashMap` diff --git a/src/tools/clippy/clippy_lints/src/non_send_fields_in_send_ty.rs b/src/tools/clippy/clippy_lints/src/non_send_fields_in_send_ty.rs index f4de999a9281a..5168ca67b6abb 100644 --- a/src/tools/clippy/clippy_lints/src/non_send_fields_in_send_ty.rs +++ b/src/tools/clippy/clippy_lints/src/non_send_fields_in_send_ty.rs @@ -202,8 +202,8 @@ fn ty_allowed_with_raw_pointer_heuristic<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'t // The type is known to be `!Send` and `!Copy` match ty.kind() { - ty::Tuple(_) => ty - .tuple_fields() + ty::Tuple(fields) => fields + .iter() .all(|ty| ty_allowed_with_raw_pointer_heuristic(cx, ty, send_trait)), ty::Array(ty, _) | ty::Slice(ty) => ty_allowed_with_raw_pointer_heuristic(cx, *ty, send_trait), ty::Adt(_, substs) => { diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs index 9ed5952a109a5..a57c819cb2256 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs @@ -2,7 +2,7 @@ use super::TRANSMUTE_UNDEFINED_REPR; use clippy_utils::diagnostics::span_lint_and_then; use rustc_hir::Expr; use rustc_lint::LateContext; -use rustc_middle::ty::subst::{GenericArg, Subst}; +use rustc_middle::ty::subst::Subst; use rustc_middle::ty::{self, Ty, TypeAndMut}; use rustc_span::Span; @@ -246,11 +246,10 @@ fn reduce_ty<'tcx>(cx: &LateContext<'tcx>, mut ty: Ty<'tcx>) -> ReducedTy<'tcx> continue; }, ty::Tuple(args) => { - let mut iter = args.iter().map(GenericArg::expect_ty); - let Some(sized_ty) = iter.find(|ty| !is_zero_sized_ty(cx, *ty)) else { + let Some(sized_ty) = args.iter().find(|&ty| !is_zero_sized_ty(cx, ty)) else { return ReducedTy::OrderedFields(ty); }; - if iter.all(|ty| is_zero_sized_ty(cx, ty)) { + if args.iter().all(|ty| is_zero_sized_ty(cx, ty)) { ty = sized_ty; continue; } diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs index b44899e6bd587..0d39226d97035 100644 --- a/src/tools/clippy/clippy_utils/src/ty.rs +++ b/src/tools/clippy/clippy_utils/src/ty.rs @@ -169,7 +169,7 @@ pub fn is_must_use_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { // because we don't want to lint functions returning empty arrays is_must_use_ty(cx, *ty) }, - ty::Tuple(substs) => substs.types().any(|ty| is_must_use_ty(cx, ty)), + ty::Tuple(substs) => substs.iter().any(|ty| is_must_use_ty(cx, ty)), ty::Opaque(ref def_id, _) => { for (predicate, _) in cx.tcx.explicit_item_bounds(*def_id) { if let ty::PredicateKind::Trait(trait_predicate) = predicate.kind().skip_binder() { @@ -249,11 +249,11 @@ pub fn is_non_aggregate_primitive_type(ty: Ty<'_>) -> bool { /// Returns `true` if the given type is a primitive (a `bool` or `char`, any integer or /// floating-point number type, a `str`, or an array, slice, or tuple of those types). pub fn is_recursively_primitive_type(ty: Ty<'_>) -> bool { - match ty.kind() { + match *ty.kind() { ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Str => true, ty::Ref(_, inner, _) if *inner.kind() == ty::Str => true, - ty::Array(inner_type, _) | ty::Slice(inner_type) => is_recursively_primitive_type(*inner_type), - ty::Tuple(inner_types) => inner_types.types().all(is_recursively_primitive_type), + ty::Array(inner_type, _) | ty::Slice(inner_type) => is_recursively_primitive_type(inner_type), + ty::Tuple(inner_types) => inner_types.iter().all(is_recursively_primitive_type), _ => false, } } @@ -393,9 +393,9 @@ pub fn same_type_and_consts<'tcx>(a: Ty<'tcx>, b: Ty<'tcx>) -> bool { /// Checks if a given type looks safe to be uninitialized. pub fn is_uninit_value_valid_for_ty(cx: &LateContext<'_>, ty: Ty<'_>) -> bool { - match ty.kind() { - ty::Array(component, _) => is_uninit_value_valid_for_ty(cx, *component), - ty::Tuple(types) => types.types().all(|ty| is_uninit_value_valid_for_ty(cx, ty)), + match *ty.kind() { + ty::Array(component, _) => is_uninit_value_valid_for_ty(cx, component), + ty::Tuple(types) => types.iter().all(|ty| is_uninit_value_valid_for_ty(cx, ty)), ty::Adt(adt, _) => cx.tcx.lang_items().maybe_uninit() == Some(adt.did), _ => false, } @@ -426,8 +426,8 @@ impl<'tcx> ExprFnSig<'tcx> { pub fn input(self, i: usize) -> Binder<'tcx, Ty<'tcx>> { match self { Self::Sig(sig) => sig.input(i), - Self::Closure(sig) => sig.input(0).map_bound(|ty| ty.tuple_element_ty(i).unwrap()), - Self::Trait(inputs, _) => inputs.map_bound(|ty| ty.tuple_element_ty(i).unwrap()), + Self::Closure(sig) => sig.input(0).map_bound(|ty| ty.tuple_fields()[i]), + Self::Trait(inputs, _) => inputs.map_bound(|ty| ty.tuple_fields()[i]), } } diff --git a/src/version b/src/version index 4d5fde5bd1654..91951fd8ad700 100644 --- a/src/version +++ b/src/version @@ -1 +1 @@ -1.60.0 +1.61.0