From 8c2353b6c142d5665006cf79cbec511f666dbed2 Mon Sep 17 00:00:00 2001 From: Fausto Date: Fri, 18 Mar 2022 17:13:38 -0400 Subject: [PATCH 01/15] remove find_use_placement A more robust solution to finding where to place use suggestions was added. The algorithm uses the AST to find the span for the suggestion so we pass this span down to the HIR during lowering and use it. Signed-off-by: Miguel Guarniz --- compiler/rustc_ast_lowering/src/index.rs | 4 +- compiler/rustc_ast_lowering/src/item.rs | 13 +- compiler/rustc_hir/src/hir.rs | 14 +- compiler/rustc_middle/src/hir/map/mod.rs | 4 +- .../rustc_save_analysis/src/dump_visitor.rs | 4 +- compiler/rustc_save_analysis/src/lib.rs | 2 +- .../rustc_typeck/src/check/method/suggest.rs | 146 +++--------------- src/librustdoc/html/render/span_map.rs | 7 +- src/librustdoc/visit_ast.rs | 2 +- src/test/ui/imports/overlapping_pub_trait.rs | 4 +- src/test/ui/imports/unnamed_pub_trait.rs | 4 +- .../ui/suggestions/use-placement-typeck.fixed | 1 - 12 files changed, 57 insertions(+), 148 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/index.rs b/compiler/rustc_ast_lowering/src/index.rs index 62935a2b1f718..5eab21bf79a90 100644 --- a/compiler/rustc_ast_lowering/src/index.rs +++ b/compiler/rustc_ast_lowering/src/index.rs @@ -52,7 +52,9 @@ pub(super) fn index_hir<'hir>( }; match item { - OwnerNode::Crate(citem) => collector.visit_mod(&citem, citem.inner, hir::CRATE_HIR_ID), + OwnerNode::Crate(citem) => { + collector.visit_mod(&citem, citem.spans.inner_span, hir::CRATE_HIR_ID) + } OwnerNode::Item(item) => collector.visit_item(item), OwnerNode::TraitItem(item) => collector.visit_trait_item(item), OwnerNode::ImplItem(item) => collector.visit_impl_item(item), diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index c8fd96309a6cd..a8bd8c92a41c4 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -124,7 +124,7 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> { debug_assert_eq!(self.resolver.local_def_id(CRATE_NODE_ID), CRATE_DEF_ID); self.with_lctx(CRATE_NODE_ID, |lctx| { - let module = lctx.lower_mod(&c.items, c.spans.inner_span); + let module = lctx.lower_mod(&c.items, &c.spans); lctx.lower_attrs(hir::CRATE_HIR_ID, &c.attrs); hir::OwnerNode::Crate(lctx.arena.alloc(module)) }) @@ -186,9 +186,12 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> { } impl<'hir> LoweringContext<'_, 'hir> { - pub(super) fn lower_mod(&mut self, items: &[P], inner: Span) -> hir::Mod<'hir> { + pub(super) fn lower_mod(&mut self, items: &[P], spans: &ModSpans) -> hir::Mod<'hir> { hir::Mod { - inner: self.lower_span(inner), + spans: hir::ModSpans { + inner_span: self.lower_span(spans.inner_span), + inject_use_span: self.lower_span(spans.inject_use_span), + }, item_ids: self.arena.alloc_from_iter(items.iter().flat_map(|x| self.lower_item_ref(x))), } } @@ -308,8 +311,8 @@ impl<'hir> LoweringContext<'_, 'hir> { }) } ItemKind::Mod(_, ref mod_kind) => match mod_kind { - ModKind::Loaded(items, _, ModSpans { inner_span, inject_use_span: _ }) => { - hir::ItemKind::Mod(self.lower_mod(items, *inner_span)) + ModKind::Loaded(items, _, spans) => { + hir::ItemKind::Mod(self.lower_mod(items, spans)) } ModKind::Unloaded => panic!("`mod` items should have been loaded by now"), }, diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 10871df3ab9d0..5e55ca7790180 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -2522,11 +2522,17 @@ impl FnRetTy<'_> { #[derive(Encodable, Debug, HashStable_Generic)] pub struct Mod<'hir> { + pub spans: ModSpans, + pub item_ids: &'hir [ItemId], +} + +#[derive(Copy, Clone, Debug, HashStable_Generic, Encodable)] +pub struct ModSpans { /// A span from the first token past `{` to the last token until `}`. /// For `mod foo;`, the inner span ranges from the first token /// to the last token in the external file. - pub inner: Span, - pub item_ids: &'hir [ItemId], + pub inner_span: Span, + pub inject_use_span: Span, } #[derive(Debug, HashStable_Generic)] @@ -3024,8 +3030,8 @@ impl<'hir> OwnerNode<'hir> { OwnerNode::Item(Item { span, .. }) | OwnerNode::ForeignItem(ForeignItem { span, .. }) | OwnerNode::ImplItem(ImplItem { span, .. }) - | OwnerNode::TraitItem(TraitItem { span, .. }) - | OwnerNode::Crate(Mod { inner: span, .. }) => *span, + | OwnerNode::TraitItem(TraitItem { span, .. }) => *span, + OwnerNode::Crate(Mod { spans: ModSpans { inner_span, .. }, .. }) => *inner_span, } } diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index 561653f3bebf7..8c3b1730b1341 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -586,7 +586,7 @@ impl<'hir> Map<'hir> { Some(OwnerNode::Item(&Item { span, kind: ItemKind::Mod(ref m), .. })) => { (m, span, hir_id) } - Some(OwnerNode::Crate(item)) => (item, item.inner, hir_id), + Some(OwnerNode::Crate(item)) => (item, item.spans.inner_span, hir_id), node => panic!("not a module: {:?}", node), } } @@ -1014,7 +1014,7 @@ impl<'hir> Map<'hir> { Node::Infer(i) => i.span, Node::Visibility(v) => bug!("unexpected Visibility {:?}", v), Node::Local(local) => local.span, - Node::Crate(item) => item.inner, + Node::Crate(item) => item.spans.inner_span, }; Some(span) } diff --git a/compiler/rustc_save_analysis/src/dump_visitor.rs b/compiler/rustc_save_analysis/src/dump_visitor.rs index 1eb575e0db2a6..22d0a20395ec7 100644 --- a/compiler/rustc_save_analysis/src/dump_visitor.rs +++ b/compiler/rustc_save_analysis/src/dump_visitor.rs @@ -1095,11 +1095,11 @@ impl<'tcx> DumpVisitor<'tcx> { let sm = self.tcx.sess.source_map(); let krate_mod = self.tcx.hir().root_module(); - let filename = sm.span_to_filename(krate_mod.inner); + let filename = sm.span_to_filename(krate_mod.spans.inner_span); let data_id = id_from_hir_id(id, &self.save_ctxt); let children = krate_mod.item_ids.iter().map(|i| id_from_def_id(i.def_id.to_def_id())).collect(); - let span = self.span_from_span(krate_mod.inner); + let span = self.span_from_span(krate_mod.spans.inner_span); let attrs = self.tcx.hir().attrs(id); self.dumper.dump_def( diff --git a/compiler/rustc_save_analysis/src/lib.rs b/compiler/rustc_save_analysis/src/lib.rs index 08a990c65fff7..102268c6ca352 100644 --- a/compiler/rustc_save_analysis/src/lib.rs +++ b/compiler/rustc_save_analysis/src/lib.rs @@ -282,7 +282,7 @@ impl<'tcx> SaveContext<'tcx> { let qualname = format!("::{}", self.tcx.def_path_str(def_id)); let sm = self.tcx.sess.source_map(); - let filename = sm.span_to_filename(m.inner); + let filename = sm.span_to_filename(m.spans.inner_span); filter!(self.span_utils, item.ident.span); diff --git a/compiler/rustc_typeck/src/check/method/suggest.rs b/compiler/rustc_typeck/src/check/method/suggest.rs index b05f0e4d3c389..83c6b6362fece 100644 --- a/compiler/rustc_typeck/src/check/method/suggest.rs +++ b/compiler/rustc_typeck/src/check/method/suggest.rs @@ -7,7 +7,7 @@ use rustc_errors::{ pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, }; use rustc_hir as hir; -use rustc_hir::def_id::{DefId, LocalDefId}; +use rustc_hir::def_id::DefId; use rustc_hir::lang_items::LangItem; use rustc_hir::{ExprKind, Node, QPath}; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; @@ -1473,12 +1473,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - fn suggest_use_candidates( - &self, - err: &mut Diagnostic, - mut msg: String, - candidates: Vec, - ) { + fn suggest_use_candidates(&self, err: &mut Diagnostic, msg: String, candidates: Vec) { let parent_map = self.tcx.visible_parent_map(()); // Separate out candidates that must be imported with a glob, because they are named `_` @@ -1502,80 +1497,28 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }); let module_did = self.tcx.parent_module(self.body_id); - let (span, found_use) = find_use_placement(self.tcx, module_did); - if let Some(span) = span { - let path_strings = candidates.iter().map(|trait_did| { - // Produce an additional newline to separate the new use statement - // from the directly following item. - let additional_newline = if found_use { "" } else { "\n" }; - format!( - "use {};\n{}", - with_crate_prefix!(self.tcx.def_path_str(*trait_did)), - additional_newline - ) - }); + let (module, _, _) = self.tcx.hir().get_module(module_did); + let span = module.spans.inject_use_span; - let glob_path_strings = globs.iter().map(|trait_did| { - let parent_did = parent_map.get(trait_did).unwrap(); + let path_strings = candidates.iter().map(|trait_did| { + format!("use {};\n", with_crate_prefix!(self.tcx.def_path_str(*trait_did)),) + }); - // Produce an additional newline to separate the new use statement - // from the directly following item. - let additional_newline = if found_use { "" } else { "\n" }; - format!( - "use {}::*; // trait {}\n{}", - with_crate_prefix!(self.tcx.def_path_str(*parent_did)), - self.tcx.item_name(*trait_did), - additional_newline - ) - }); + let glob_path_strings = globs.iter().map(|trait_did| { + let parent_did = parent_map.get(trait_did).unwrap(); + format!( + "use {}::*; // trait {}\n", + with_crate_prefix!(self.tcx.def_path_str(*parent_did)), + self.tcx.item_name(*trait_did), + ) + }); - err.span_suggestions( - span, - &msg, - path_strings.chain(glob_path_strings), - Applicability::MaybeIncorrect, - ); - } else { - let limit = if candidates.len() + globs.len() == 5 { 5 } else { 4 }; - for (i, trait_did) in candidates.iter().take(limit).enumerate() { - if candidates.len() + globs.len() > 1 { - msg.push_str(&format!( - "\ncandidate #{}: `use {};`", - i + 1, - 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)) - )); - } - } - for (i, trait_did) in - globs.iter().take(limit.saturating_sub(candidates.len())).enumerate() - { - let parent_did = parent_map.get(trait_did).unwrap(); - - if candidates.len() + globs.len() > 1 { - msg.push_str(&format!( - "\ncandidate #{}: `use {}::*; // trait {}`", - candidates.len() + i + 1, - 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)), - self.tcx.item_name(*trait_did), - )); - } - } - if candidates.len() > limit { - msg.push_str(&format!("\nand {} others", candidates.len() + globs.len() - limit)); - } - err.note(&msg); - } + err.span_suggestions( + span, + &msg, + path_strings.chain(glob_path_strings), + Applicability::MaybeIncorrect, + ); } fn suggest_valid_traits( @@ -2100,53 +2043,6 @@ pub fn all_traits(tcx: TyCtxt<'_>) -> Vec { tcx.all_traits().map(|def_id| TraitInfo { def_id }).collect() } -fn find_use_placement<'tcx>(tcx: TyCtxt<'tcx>, target_module: LocalDefId) -> (Option, bool) { - // FIXME(#94854): this code uses an out-of-date method for inferring a span - // to suggest. It would be better to thread the ModSpans from the AST into - // the HIR, and then use that to drive the suggestion here. - - let mut span = None; - let mut found_use = false; - let (module, _, _) = tcx.hir().get_module(target_module); - - // Find a `use` statement. - for &item_id in module.item_ids { - let item = tcx.hir().item(item_id); - match item.kind { - hir::ItemKind::Use(..) => { - // Don't suggest placing a `use` before the prelude - // import or other generated ones. - if !item.span.from_expansion() { - span = Some(item.span.shrink_to_lo()); - found_use = true; - break; - } - } - // Don't place `use` before `extern crate`... - hir::ItemKind::ExternCrate(_) => {} - // ...but do place them before the first other item. - _ => { - if span.map_or(true, |span| item.span < span) { - if !item.span.from_expansion() { - span = Some(item.span.shrink_to_lo()); - // Don't insert between attributes and an item. - let attrs = tcx.hir().attrs(item.hir_id()); - // Find the first attribute on the item. - // FIXME: This is broken for active attributes. - for attr in attrs { - if !attr.span.is_dummy() && span.map_or(true, |span| attr.span < span) { - span = Some(attr.span.shrink_to_lo()); - } - } - } - } - } - } - } - - (span, found_use) -} - fn print_disambiguation_help<'tcx>( item_name: Ident, args: Option<&'tcx [hir::Expr<'tcx>]>, diff --git a/src/librustdoc/html/render/span_map.rs b/src/librustdoc/html/render/span_map.rs index 731e18b1eec2c..06c63ec97d7f2 100644 --- a/src/librustdoc/html/render/span_map.rs +++ b/src/librustdoc/html/render/span_map.rs @@ -119,11 +119,14 @@ impl<'tcx> Visitor<'tcx> for SpanMapVisitor<'tcx> { fn visit_mod(&mut self, m: &'tcx Mod<'tcx>, span: Span, id: HirId) { // To make the difference between "mod foo {}" and "mod foo;". In case we "import" another // file, we want to link to it. Otherwise no need to create a link. - if !span.overlaps(m.inner) { + if !span.overlaps(m.spans.inner_span) { // Now that we confirmed it's a file import, we want to get the span for the module // name only and not all the "mod foo;". if let Some(Node::Item(item)) = self.tcx.hir().find(id) { - self.matches.insert(item.ident.span, LinkFromSrc::Local(clean::Span::new(m.inner))); + self.matches.insert( + item.ident.span, + LinkFromSrc::Local(clean::Span::new(m.spans.inner_span)), + ); } } intravisit::walk_mod(self, m, id); diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index e793ee75fd2e0..75276d18fe5e9 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -154,7 +154,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { m: &'tcx hir::Mod<'tcx>, name: Symbol, ) -> Module<'tcx> { - let mut om = Module::new(name, id, m.inner); + let mut om = Module::new(name, id, m.spans.inner_span); let def_id = self.cx.tcx.hir().local_def_id(id).to_def_id(); // Keep track of if there were any private modules in the path. let orig_inside_public_path = self.inside_public_path; diff --git a/src/test/ui/imports/overlapping_pub_trait.rs b/src/test/ui/imports/overlapping_pub_trait.rs index f5f5d4ed3804f..69aba3ae9b4e7 100644 --- a/src/test/ui/imports/overlapping_pub_trait.rs +++ b/src/test/ui/imports/overlapping_pub_trait.rs @@ -4,10 +4,10 @@ * This crate declares two public paths, `m::Tr` and `prelude::_`. Make sure we prefer the former. */ extern crate overlapping_pub_trait_source; +//~^ HELP the following trait is implemented but not in scope; perhaps add a `use` for it: +//~| SUGGESTION overlapping_pub_trait_source::m::Tr fn main() { - //~^ HELP the following trait is implemented but not in scope; perhaps add a `use` for it: - //~| SUGGESTION overlapping_pub_trait_source::m::Tr use overlapping_pub_trait_source::S; S.method(); //~^ ERROR no method named `method` found for struct `S` in the current scope [E0599] diff --git a/src/test/ui/imports/unnamed_pub_trait.rs b/src/test/ui/imports/unnamed_pub_trait.rs index b06b1e1d07dce..c38fb17b97649 100644 --- a/src/test/ui/imports/unnamed_pub_trait.rs +++ b/src/test/ui/imports/unnamed_pub_trait.rs @@ -5,10 +5,10 @@ * importing it by name, and instead we suggest importing it by glob. */ extern crate unnamed_pub_trait_source; +//~^ HELP the following trait is implemented but not in scope; perhaps add a `use` for it: +//~| SUGGESTION unnamed_pub_trait_source::prelude::*; // trait Tr fn main() { - //~^ HELP the following trait is implemented but not in scope; perhaps add a `use` for it: - //~| SUGGESTION unnamed_pub_trait_source::prelude::*; // trait Tr use unnamed_pub_trait_source::S; S.method(); //~^ ERROR no method named `method` found for struct `S` in the current scope [E0599] diff --git a/src/test/ui/suggestions/use-placement-typeck.fixed b/src/test/ui/suggestions/use-placement-typeck.fixed index 40c55d1dd06bc..37335da060e42 100644 --- a/src/test/ui/suggestions/use-placement-typeck.fixed +++ b/src/test/ui/suggestions/use-placement-typeck.fixed @@ -7,7 +7,6 @@ #![allow(unused)] use m::Foo; - fn main() { let s = m::S; s.abc(); //~ ERROR no method named `abc` From 6b75406f5a7b006f7c724c08c6a00d7696a3620d Mon Sep 17 00:00:00 2001 From: Jacob Pratt Date: Mon, 28 Feb 2022 18:13:24 -0500 Subject: [PATCH 02/15] Create 2024 edition --- compiler/rustc_ast/src/token.rs | 2 +- .../src/standard_library_imports.rs | 1 + compiler/rustc_expand/src/mbe/macro_rules.rs | 2 +- compiler/rustc_session/src/session.rs | 5 ++++ compiler/rustc_span/src/edition.rs | 30 +++++++++++++++++-- compiler/rustc_span/src/lib.rs | 5 ++++ compiler/rustc_span/src/symbol.rs | 2 ++ library/core/src/prelude/mod.rs | 10 +++++++ library/std/src/lib.rs | 1 + library/std/src/prelude/mod.rs | 14 +++++++++ src/test/ui/hello.rs | 11 +++++-- src/test/ui/hello2021.rs | 6 ---- src/tools/rustfmt/src/bin/main.rs | 1 + src/tools/rustfmt/src/config/options.rs | 5 ++++ 14 files changed, 83 insertions(+), 12 deletions(-) delete mode 100644 src/test/ui/hello2021.rs diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs index 2132cdfc001b6..3e274107e7fb6 100644 --- a/compiler/rustc_ast/src/token.rs +++ b/compiler/rustc_ast/src/token.rs @@ -722,7 +722,7 @@ impl NonterminalKind { Edition::Edition2015 | Edition::Edition2018 => { NonterminalKind::PatParam { inferred: true } } - Edition::Edition2021 => NonterminalKind::PatWithOr, + Edition::Edition2021 | Edition::Edition2024 => NonterminalKind::PatWithOr, }, sym::pat_param => NonterminalKind::PatParam { inferred: false }, sym::expr => NonterminalKind::Expr, diff --git a/compiler/rustc_builtin_macros/src/standard_library_imports.rs b/compiler/rustc_builtin_macros/src/standard_library_imports.rs index 3571517d2b258..09ad5f9b3eaa9 100644 --- a/compiler/rustc_builtin_macros/src/standard_library_imports.rs +++ b/compiler/rustc_builtin_macros/src/standard_library_imports.rs @@ -70,6 +70,7 @@ pub fn inject( Edition2015 => sym::rust_2015, Edition2018 => sym::rust_2018, Edition2021 => sym::rust_2021, + Edition2024 => sym::rust_2024, }]) .map(|&symbol| Ident::new(symbol, span)) .collect(); diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs index 10b2b9f07e2a5..058b03530a39f 100644 --- a/compiler/rustc_expand/src/mbe/macro_rules.rs +++ b/compiler/rustc_expand/src/mbe/macro_rules.rs @@ -1033,7 +1033,7 @@ fn check_matcher_core( err.span_label(sp, format!("not allowed after `{}` fragments", kind)); if kind == NonterminalKind::PatWithOr - && sess.edition == Edition::Edition2021 + && sess.edition.rust_2021() && next_token.is_token(&BinOp(token::BinOpToken::Or)) { let suggestion = quoted_tt_to_string(&TokenTree::MetaVarDecl( diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index eed0f1e09fffe..8ba859bed4d08 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -945,6 +945,11 @@ impl Session { self.opts.edition >= Edition::Edition2021 } + /// Are we allowed to use features from the Rust 2024 edition? + pub fn rust_2024(&self) -> bool { + self.opts.edition >= Edition::Edition2024 + } + pub fn edition(&self) -> Edition { self.opts.edition } diff --git a/compiler/rustc_span/src/edition.rs b/compiler/rustc_span/src/edition.rs index 511c2e8662697..065d3660e5008 100644 --- a/compiler/rustc_span/src/edition.rs +++ b/compiler/rustc_span/src/edition.rs @@ -22,13 +22,15 @@ pub enum Edition { Edition2018, /// The 2021 edition Edition2021, + /// The 2024 edition + Edition2024, } // Must be in order from oldest to newest. pub const ALL_EDITIONS: &[Edition] = - &[Edition::Edition2015, Edition::Edition2018, Edition::Edition2021]; + &[Edition::Edition2015, Edition::Edition2018, Edition::Edition2021, Edition::Edition2024]; -pub const EDITION_NAME_LIST: &str = "2015|2018|2021"; +pub const EDITION_NAME_LIST: &str = "2015|2018|2021|2024"; pub const DEFAULT_EDITION: Edition = Edition::Edition2015; @@ -40,6 +42,7 @@ impl fmt::Display for Edition { Edition::Edition2015 => "2015", Edition::Edition2018 => "2018", Edition::Edition2021 => "2021", + Edition::Edition2024 => "2024", }; write!(f, "{}", s) } @@ -51,6 +54,7 @@ impl Edition { Edition::Edition2015 => "rust_2015_compatibility", Edition::Edition2018 => "rust_2018_compatibility", Edition::Edition2021 => "rust_2021_compatibility", + Edition::Edition2024 => "rust_2024_compatibility", } } @@ -59,6 +63,7 @@ impl Edition { Edition::Edition2015 => sym::rust_2015_preview, Edition::Edition2018 => sym::rust_2018_preview, Edition::Edition2021 => sym::rust_2021_preview, + Edition::Edition2024 => sym::rust_2024_preview, } } @@ -67,8 +72,28 @@ impl Edition { Edition::Edition2015 => true, Edition::Edition2018 => true, Edition::Edition2021 => true, + Edition::Edition2024 => false, } } + + pub fn rust_2015(&self) -> bool { + *self == Edition::Edition2015 + } + + /// Are we allowed to use features from the Rust 2018 edition? + pub fn rust_2018(&self) -> bool { + *self >= Edition::Edition2018 + } + + /// Are we allowed to use features from the Rust 2021 edition? + pub fn rust_2021(&self) -> bool { + *self >= Edition::Edition2021 + } + + /// Are we allowed to use features from the Rust 2024 edition? + pub fn rust_2024(&self) -> bool { + *self >= Edition::Edition2024 + } } impl FromStr for Edition { @@ -78,6 +103,7 @@ impl FromStr for Edition { "2015" => Ok(Edition::Edition2015), "2018" => Ok(Edition::Edition2018), "2021" => Ok(Edition::Edition2021), + "2024" => Ok(Edition::Edition2024), _ => Err(()), } } diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index 6d7377927c291..9ae366a5fe811 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -698,6 +698,11 @@ impl Span { self.edition() >= edition::Edition::Edition2021 } + #[inline] + pub fn rust_2024(self) -> bool { + self.edition() >= edition::Edition::Edition2024 + } + /// Returns the source callee. /// /// Returns `None` if the supplied span has no expansion trace, diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 2737c26708bc4..443f0a6db89ce 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1145,6 +1145,8 @@ symbols! { rust_2018_preview, rust_2021, rust_2021_preview, + rust_2024, + rust_2024_preview, rust_begin_unwind, rust_eh_catch_typeinfo, rust_eh_personality, diff --git a/library/core/src/prelude/mod.rs b/library/core/src/prelude/mod.rs index ccd36a428e296..3cd3a3b780e9c 100644 --- a/library/core/src/prelude/mod.rs +++ b/library/core/src/prelude/mod.rs @@ -45,3 +45,13 @@ pub mod rust_2021 { #[doc(no_inline)] pub use crate::convert::{TryFrom, TryInto}; } + +/// The 2024 edition of the core prelude. +/// +/// See the [module-level documentation](self) for more. +#[unstable(feature = "prelude_2024", issue = "none")] +pub mod rust_2024 { + #[unstable(feature = "prelude_2024", issue = "none")] + #[doc(no_inline)] + pub use super::rust_2021::*; +} diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 819ec10a4b4b6..a5cdc89c5b60e 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -279,6 +279,7 @@ #![feature(panic_info_message)] #![feature(panic_internals)] #![feature(portable_simd)] +#![feature(prelude_2024)] #![feature(ptr_as_uninit)] #![feature(raw_os_nonzero)] #![feature(slice_internals)] diff --git a/library/std/src/prelude/mod.rs b/library/std/src/prelude/mod.rs index d4bf6aeefee57..c314bbbb68e57 100644 --- a/library/std/src/prelude/mod.rs +++ b/library/std/src/prelude/mod.rs @@ -132,3 +132,17 @@ pub mod rust_2021 { #[doc(no_inline)] pub use core::prelude::rust_2021::*; } + +/// The 2024 version of the prelude of The Rust Standard Library. +/// +/// See the [module-level documentation](self) for more. +#[unstable(feature = "prelude_2024", issue = "none")] +pub mod rust_2024 { + #[unstable(feature = "prelude_2024", issue = "none")] + #[doc(no_inline)] + pub use super::v1::*; + + #[unstable(feature = "prelude_2024", issue = "none")] + #[doc(no_inline)] + pub use core::prelude::rust_2024::*; +} diff --git a/src/test/ui/hello.rs b/src/test/ui/hello.rs index c207c25545eca..c66b7c60fb4ea 100644 --- a/src/test/ui/hello.rs +++ b/src/test/ui/hello.rs @@ -1,5 +1,12 @@ // run-pass +// revisions: e2015 e2018 e2021 e2024 -pub fn main() { - println!("hello, world"); +//[e2018] edition:2018 +//[e2021] edition:2021 +//[e2024] edition:2024 + +//[e2024] compile-flags: -Zunstable-options + +fn main() { + println!("hello"); } diff --git a/src/test/ui/hello2021.rs b/src/test/ui/hello2021.rs deleted file mode 100644 index 134d8af5bfb8a..0000000000000 --- a/src/test/ui/hello2021.rs +++ /dev/null @@ -1,6 +0,0 @@ -// run-pass -// edition:2021 - -fn main() { - println!("hello, 2021"); -} diff --git a/src/tools/rustfmt/src/bin/main.rs b/src/tools/rustfmt/src/bin/main.rs index ad10b9ede608f..8e871e61f2683 100644 --- a/src/tools/rustfmt/src/bin/main.rs +++ b/src/tools/rustfmt/src/bin/main.rs @@ -693,6 +693,7 @@ fn edition_from_edition_str(edition_str: &str) -> Result { "2015" => Ok(Edition::Edition2015), "2018" => Ok(Edition::Edition2018), "2021" => Ok(Edition::Edition2021), + "2024" => Ok(Edition::Edition2024), _ => Err(format_err!("Invalid value for `--edition`")), } } diff --git a/src/tools/rustfmt/src/config/options.rs b/src/tools/rustfmt/src/config/options.rs index d857c29be29c6..257a17b2703a9 100644 --- a/src/tools/rustfmt/src/config/options.rs +++ b/src/tools/rustfmt/src/config/options.rs @@ -423,6 +423,10 @@ pub enum Edition { #[doc_hint = "2021"] /// Edition 2021. Edition2021, + #[value = "2024"] + #[doc_hint = "2024"] + /// Edition 2024. + Edition2024, } impl Default for Edition { @@ -437,6 +441,7 @@ impl From for rustc_span::edition::Edition { Edition::Edition2015 => Self::Edition2015, Edition::Edition2018 => Self::Edition2018, Edition::Edition2021 => Self::Edition2021, + Edition::Edition2024 => Self::Edition2024, } } } From 7bd22e29d0d604e594ba03b51bd8c3fc82959215 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 6 Apr 2022 21:10:43 -0700 Subject: [PATCH 03/15] only downgrade Error -> Ambiguous if type error is in predicate --- .../src/traits/select/candidate_assembly.rs | 4 ++-- ...n-help-with-err-generic-is-not-function.rs | 8 -------- ...lp-with-err-generic-is-not-function.stderr | 19 ++----------------- .../typeck/autoderef-with-param-env-error.rs | 9 +++++++++ .../autoderef-with-param-env-error.stderr | 12 ++++++++++++ 5 files changed, 25 insertions(+), 27 deletions(-) create mode 100644 src/test/ui/typeck/autoderef-with-param-env-error.rs create mode 100644 src/test/ui/typeck/autoderef-with-param-env-error.stderr 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 cf472813e9e32..4bb0ce29b637b 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -231,8 +231,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // `Err(Unimplemented)` to `Ok(None)`. This helps us avoid // emitting additional spurious errors, since we're guaranteed // to have emitted at least one. - if stack.obligation.references_error() { - debug!("no results for error type, treating as ambiguous"); + if stack.obligation.predicate.references_error() { + debug!(?stack.obligation.predicate, "found error type in predicate, treating as ambiguous"); return Ok(None); } return Err(Unimplemented); diff --git a/src/test/ui/functions-closures/fn-help-with-err-generic-is-not-function.rs b/src/test/ui/functions-closures/fn-help-with-err-generic-is-not-function.rs index 26deb59876268..e48ab4aa96fb9 100644 --- a/src/test/ui/functions-closures/fn-help-with-err-generic-is-not-function.rs +++ b/src/test/ui/functions-closures/fn-help-with-err-generic-is-not-function.rs @@ -8,15 +8,7 @@ where //~^ ERROR cannot find type `T` in this scope //~| NOTE not found in this scope { - // The part where it claims that there is no method named `len` is a bug. Feel free to fix it. - // This test is intended to ensure that a different bug, where it claimed - // that `v` was a function, does not regress. fn method(v: Vec) { v.len(); } - //~^ ERROR type annotations needed - //~| NOTE cannot infer type - //~| NOTE type must be known at this point - //~| ERROR no method named `len` - //~| NOTE private field, not a method } fn main() {} diff --git a/src/test/ui/functions-closures/fn-help-with-err-generic-is-not-function.stderr b/src/test/ui/functions-closures/fn-help-with-err-generic-is-not-function.stderr index 958ce3c25d027..26bdf460f5e4d 100644 --- a/src/test/ui/functions-closures/fn-help-with-err-generic-is-not-function.stderr +++ b/src/test/ui/functions-closures/fn-help-with-err-generic-is-not-function.stderr @@ -12,21 +12,6 @@ error[E0412]: cannot find type `T` in this scope LL | T: Copy, | ^ not found in this scope -error[E0282]: type annotations needed - --> $DIR/fn-help-with-err-generic-is-not-function.rs:14:31 - | -LL | fn method(v: Vec) { v.len(); } - | ^^^ cannot infer type - | - = note: type must be known at this point - -error[E0599]: no method named `len` found for struct `Vec` in the current scope - --> $DIR/fn-help-with-err-generic-is-not-function.rs:14:31 - | -LL | fn method(v: Vec) { v.len(); } - | ^^^ private field, not a method - -error: aborting due to 4 previous errors +error: aborting due to 2 previous errors -Some errors have detailed explanations: E0282, E0412, E0599. -For more information about an error, try `rustc --explain E0282`. +For more information about this error, try `rustc --explain E0412`. diff --git a/src/test/ui/typeck/autoderef-with-param-env-error.rs b/src/test/ui/typeck/autoderef-with-param-env-error.rs new file mode 100644 index 0000000000000..ec96c61c63e3a --- /dev/null +++ b/src/test/ui/typeck/autoderef-with-param-env-error.rs @@ -0,0 +1,9 @@ +fn foo() +where + T: Send, + //~^ cannot find type `T` in this scope +{ + let s = "abc".to_string(); +} + +fn main() {} diff --git a/src/test/ui/typeck/autoderef-with-param-env-error.stderr b/src/test/ui/typeck/autoderef-with-param-env-error.stderr new file mode 100644 index 0000000000000..cde800336dd3d --- /dev/null +++ b/src/test/ui/typeck/autoderef-with-param-env-error.stderr @@ -0,0 +1,12 @@ +error[E0412]: cannot find type `T` in this scope + --> $DIR/autoderef-with-param-env-error.rs:3:5 + | +LL | fn foo() + | - help: you might be missing a type parameter: `` +LL | where +LL | T: Send, + | ^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0412`. From abf2b4c04d4d6a0a2c49562fde33ae1d46e6ead7 Mon Sep 17 00:00:00 2001 From: Jacob Pratt Date: Mon, 28 Feb 2022 15:33:50 -0500 Subject: [PATCH 04/15] Stabilize `derive_default_enum` --- .../src/deriving/default.rs | 13 +---- compiler/rustc_feature/src/accepted.rs | 2 + compiler/rustc_feature/src/active.rs | 2 - compiler/rustc_feature/src/lib.rs | 2 +- compiler/rustc_infer/src/lib.rs | 2 +- compiler/rustc_middle/src/lib.rs | 2 +- compiler/rustc_session/src/lib.rs | 2 +- compiler/rustc_trait_selection/src/lib.rs | 2 +- library/core/src/lib.rs | 2 +- src/test/ui/deriving/deriving-default-enum.rs | 2 - src/test/ui/deriving/deriving-with-helper.rs | 1 - .../feature-gate-derive_default_enum.rs | 7 --- .../feature-gate-derive_default_enum.stderr | 13 ----- src/test/ui/macros/macros-nonfatal-errors.rs | 1 - .../ui/macros/macros-nonfatal-errors.stderr | 58 +++++++++---------- 15 files changed, 38 insertions(+), 73 deletions(-) delete mode 100644 src/test/ui/feature-gates/feature-gate-derive_default_enum.rs delete mode 100644 src/test/ui/feature-gates/feature-gate-derive_default_enum.stderr diff --git a/compiler/rustc_builtin_macros/src/deriving/default.rs b/compiler/rustc_builtin_macros/src/deriving/default.rs index ca83941f600ca..2c5260616c7da 100644 --- a/compiler/rustc_builtin_macros/src/deriving/default.rs +++ b/compiler/rustc_builtin_macros/src/deriving/default.rs @@ -46,18 +46,7 @@ pub fn expand_deriving_default( StaticStruct(_, fields) => { default_struct_substructure(cx, trait_span, substr, fields) } - StaticEnum(enum_def, _) => { - if !cx.sess.features_untracked().derive_default_enum { - rustc_session::parse::feature_err( - cx.parse_sess(), - sym::derive_default_enum, - span, - "deriving `Default` on enums is experimental", - ) - .emit(); - } - default_enum_substructure(cx, trait_span, enum_def) - } + StaticEnum(enum_def, _) => default_enum_substructure(cx, trait_span, enum_def), _ => cx.span_bug(trait_span, "method in `derive(Default)`"), } })), diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs index e37251c9c2439..048039343a7a2 100644 --- a/compiler/rustc_feature/src/accepted.rs +++ b/compiler/rustc_feature/src/accepted.rs @@ -126,6 +126,8 @@ declare_features! ( (accepted, default_type_params, "1.0.0", None, None), /// Allows `#[deprecated]` attribute. (accepted, deprecated, "1.9.0", Some(29935), None), + /// Allows `#[derive(Default)]` and `#[default]` on enums. + (accepted, derive_default_enum, "1.62.0", Some(86985), None), /// Allows the use of destructuring assignments. (accepted, destructuring_assignment, "1.59.0", Some(71126), None), /// Allows `#[doc(alias = "...")]`. diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index 28466315c8687..81863162df318 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -368,8 +368,6 @@ declare_features! ( (active, deprecated_safe, "1.61.0", Some(94978), None), /// Allows having using `suggestion` in the `#[deprecated]` attribute. (active, deprecated_suggestion, "1.61.0", Some(94785), None), - /// Allows `#[derive(Default)]` and `#[default]` on enums. - (active, derive_default_enum, "1.56.0", Some(86985), None), /// Tells rustdoc to automatically generate `#[doc(cfg(...))]`. (active, doc_auto_cfg, "1.58.0", Some(43781), None), /// Allows `#[doc(cfg(...))]`. diff --git a/compiler/rustc_feature/src/lib.rs b/compiler/rustc_feature/src/lib.rs index bfc537cfae2cb..940c4ecdcc23a 100644 --- a/compiler/rustc_feature/src/lib.rs +++ b/compiler/rustc_feature/src/lib.rs @@ -11,7 +11,7 @@ //! even if it is stabilized or removed, *do not remove it*. Instead, move the //! symbol to the `accepted` or `removed` modules respectively. -#![feature(derive_default_enum)] +#![cfg_attr(bootstrap, feature(derive_default_enum))] #![feature(once_cell)] mod accepted; diff --git a/compiler/rustc_infer/src/lib.rs b/compiler/rustc_infer/src/lib.rs index 08e005364ce64..e859bcaec1206 100644 --- a/compiler/rustc_infer/src/lib.rs +++ b/compiler/rustc_infer/src/lib.rs @@ -17,7 +17,7 @@ #![feature(bool_to_option)] #![feature(box_patterns)] #![feature(control_flow_enum)] -#![feature(derive_default_enum)] +#![cfg_attr(bootstrap, feature(derive_default_enum))] #![feature(extend_one)] #![feature(label_break_value)] #![feature(let_chains)] diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs index fa2dad5ce25f0..cffcd6699b6e4 100644 --- a/compiler/rustc_middle/src/lib.rs +++ b/compiler/rustc_middle/src/lib.rs @@ -30,7 +30,7 @@ #![feature(bool_to_option)] #![feature(box_patterns)] #![feature(core_intrinsics)] -#![feature(derive_default_enum)] +#![cfg_attr(bootstrap, feature(derive_default_enum))] #![feature(discriminant_kind)] #![feature(exhaustive_patterns)] #![feature(get_mut_unchecked)] diff --git a/compiler/rustc_session/src/lib.rs b/compiler/rustc_session/src/lib.rs index 3151b025ffff7..054b18b6b633a 100644 --- a/compiler/rustc_session/src/lib.rs +++ b/compiler/rustc_session/src/lib.rs @@ -1,7 +1,7 @@ #![feature(crate_visibility_modifier)] -#![feature(derive_default_enum)] #![feature(if_let_guard)] #![feature(let_chains)] +#![cfg_attr(bootstrap, feature(derive_default_enum))] #![feature(let_else)] #![feature(min_specialization)] #![feature(never_type)] diff --git a/compiler/rustc_trait_selection/src/lib.rs b/compiler/rustc_trait_selection/src/lib.rs index 7523b8441013a..2ae7f34a91e00 100644 --- a/compiler/rustc_trait_selection/src/lib.rs +++ b/compiler/rustc_trait_selection/src/lib.rs @@ -16,7 +16,7 @@ #![feature(box_patterns)] #![feature(control_flow_enum)] #![feature(crate_visibility_modifier)] -#![feature(derive_default_enum)] +#![cfg_attr(bootstrap, feature(derive_default_enum))] #![feature(drain_filter)] #![feature(hash_drain_filter)] #![feature(label_break_value)] diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 660f6d92fe184..dc6bec246b9fe 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -167,7 +167,7 @@ #![feature(const_precise_live_drops)] #![feature(const_refs_to_cell)] #![feature(decl_macro)] -#![feature(derive_default_enum)] +#![cfg_attr(bootstrap, feature(derive_default_enum))] #![feature(deprecated_suggestion)] #![feature(doc_cfg)] #![feature(doc_notable_trait)] diff --git a/src/test/ui/deriving/deriving-default-enum.rs b/src/test/ui/deriving/deriving-default-enum.rs index 931ff1a5847d4..d1a81c72c2fdc 100644 --- a/src/test/ui/deriving/deriving-default-enum.rs +++ b/src/test/ui/deriving/deriving-default-enum.rs @@ -1,7 +1,5 @@ // run-pass -#![feature(derive_default_enum)] - // nb: does not impl Default #[derive(Debug, PartialEq)] struct NotDefault; diff --git a/src/test/ui/deriving/deriving-with-helper.rs b/src/test/ui/deriving/deriving-with-helper.rs index d8f0b27a2e5f6..1c30b0b6fba75 100644 --- a/src/test/ui/deriving/deriving-with-helper.rs +++ b/src/test/ui/deriving/deriving-with-helper.rs @@ -5,7 +5,6 @@ #![feature(lang_items)] #![feature(no_core)] #![feature(rustc_attrs)] -#![feature(derive_default_enum)] #![no_core] diff --git a/src/test/ui/feature-gates/feature-gate-derive_default_enum.rs b/src/test/ui/feature-gates/feature-gate-derive_default_enum.rs deleted file mode 100644 index 05a5d4e14223a..0000000000000 --- a/src/test/ui/feature-gates/feature-gate-derive_default_enum.rs +++ /dev/null @@ -1,7 +0,0 @@ -#[derive(Default)] //~ ERROR deriving `Default` on enums is experimental -enum Foo { - #[default] - Alpha, -} - -fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-derive_default_enum.stderr b/src/test/ui/feature-gates/feature-gate-derive_default_enum.stderr deleted file mode 100644 index 58dd4d508a709..0000000000000 --- a/src/test/ui/feature-gates/feature-gate-derive_default_enum.stderr +++ /dev/null @@ -1,13 +0,0 @@ -error[E0658]: deriving `Default` on enums is experimental - --> $DIR/feature-gate-derive_default_enum.rs:1:10 - | -LL | #[derive(Default)] - | ^^^^^^^ - | - = note: see issue #86985 for more information - = help: add `#![feature(derive_default_enum)]` to the crate attributes to enable - = note: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/macros/macros-nonfatal-errors.rs b/src/test/ui/macros/macros-nonfatal-errors.rs index 98f64aa6f8025..e7a01f105de0b 100644 --- a/src/test/ui/macros/macros-nonfatal-errors.rs +++ b/src/test/ui/macros/macros-nonfatal-errors.rs @@ -5,7 +5,6 @@ #![feature(trace_macros, concat_idents)] #![feature(stmt_expr_attributes, arbitrary_enum_discriminant)] -#![feature(derive_default_enum)] use std::arch::asm; diff --git a/src/test/ui/macros/macros-nonfatal-errors.stderr b/src/test/ui/macros/macros-nonfatal-errors.stderr index 79e8db9c1d429..b3c6d07f96763 100644 --- a/src/test/ui/macros/macros-nonfatal-errors.stderr +++ b/src/test/ui/macros/macros-nonfatal-errors.stderr @@ -1,41 +1,41 @@ error: the `#[default]` attribute may only be used on unit enum variants - --> $DIR/macros-nonfatal-errors.rs:14:5 + --> $DIR/macros-nonfatal-errors.rs:13:5 | LL | #[default] | ^^^^^^^^^^ error: the `#[default]` attribute may only be used on unit enum variants - --> $DIR/macros-nonfatal-errors.rs:19:36 + --> $DIR/macros-nonfatal-errors.rs:18:36 | LL | struct DefaultInnerAttrTupleStruct(#[default] ()); | ^^^^^^^^^^ error: the `#[default]` attribute may only be used on unit enum variants - --> $DIR/macros-nonfatal-errors.rs:23:1 + --> $DIR/macros-nonfatal-errors.rs:22:1 | LL | #[default] | ^^^^^^^^^^ error: the `#[default]` attribute may only be used on unit enum variants - --> $DIR/macros-nonfatal-errors.rs:27:1 + --> $DIR/macros-nonfatal-errors.rs:26:1 | LL | #[default] | ^^^^^^^^^^ error: the `#[default]` attribute may only be used on unit enum variants - --> $DIR/macros-nonfatal-errors.rs:37:11 + --> $DIR/macros-nonfatal-errors.rs:36:11 | LL | Foo = #[default] 0, | ^^^^^^^^^^ error: the `#[default]` attribute may only be used on unit enum variants - --> $DIR/macros-nonfatal-errors.rs:38:14 + --> $DIR/macros-nonfatal-errors.rs:37:14 | LL | Bar([u8; #[default] 1]), | ^^^^^^^^^^ error: no default declared - --> $DIR/macros-nonfatal-errors.rs:43:10 + --> $DIR/macros-nonfatal-errors.rs:42:10 | LL | #[derive(Default)] | ^^^^^^^ @@ -44,7 +44,7 @@ LL | #[derive(Default)] = note: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info) error: multiple declared defaults - --> $DIR/macros-nonfatal-errors.rs:49:10 + --> $DIR/macros-nonfatal-errors.rs:48:10 | LL | #[derive(Default)] | ^^^^^^^ @@ -62,7 +62,7 @@ LL | Baz, = note: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info) error: `#[default]` attribute does not accept a value - --> $DIR/macros-nonfatal-errors.rs:61:5 + --> $DIR/macros-nonfatal-errors.rs:60:5 | LL | #[default = 1] | ^^^^^^^^^^^^^^ @@ -70,7 +70,7 @@ LL | #[default = 1] = help: try using `#[default]` error: multiple `#[default]` attributes - --> $DIR/macros-nonfatal-errors.rs:69:5 + --> $DIR/macros-nonfatal-errors.rs:68:5 | LL | #[default] | ---------- `#[default]` used here @@ -81,13 +81,13 @@ LL | Foo, | = note: only one `#[default]` attribute is needed help: try removing this - --> $DIR/macros-nonfatal-errors.rs:68:5 + --> $DIR/macros-nonfatal-errors.rs:67:5 | LL | #[default] | ^^^^^^^^^^ error: multiple `#[default]` attributes - --> $DIR/macros-nonfatal-errors.rs:79:5 + --> $DIR/macros-nonfatal-errors.rs:78:5 | LL | #[default] | ---------- `#[default]` used here @@ -99,7 +99,7 @@ LL | Foo, | = note: only one `#[default]` attribute is needed help: try removing these - --> $DIR/macros-nonfatal-errors.rs:76:5 + --> $DIR/macros-nonfatal-errors.rs:75:5 | LL | #[default] | ^^^^^^^^^^ @@ -109,7 +109,7 @@ LL | #[default] | ^^^^^^^^^^ error: the `#[default]` attribute may only be used on unit enum variants - --> $DIR/macros-nonfatal-errors.rs:86:5 + --> $DIR/macros-nonfatal-errors.rs:85:5 | LL | Foo {}, | ^^^ @@ -117,7 +117,7 @@ LL | Foo {}, = help: consider a manual implementation of `Default` error: default variant must be exhaustive - --> $DIR/macros-nonfatal-errors.rs:94:5 + --> $DIR/macros-nonfatal-errors.rs:93:5 | LL | #[non_exhaustive] | ----------------- declared `#[non_exhaustive]` here @@ -127,37 +127,37 @@ LL | Foo, = help: consider a manual implementation of `Default` error: asm template must be a string literal - --> $DIR/macros-nonfatal-errors.rs:99:10 + --> $DIR/macros-nonfatal-errors.rs:98:10 | LL | asm!(invalid); | ^^^^^^^ error: concat_idents! requires ident args - --> $DIR/macros-nonfatal-errors.rs:102:5 + --> $DIR/macros-nonfatal-errors.rs:101:5 | LL | concat_idents!("not", "idents"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: argument must be a string literal - --> $DIR/macros-nonfatal-errors.rs:104:17 + --> $DIR/macros-nonfatal-errors.rs:103:17 | LL | option_env!(invalid); | ^^^^^^^ error: expected string literal - --> $DIR/macros-nonfatal-errors.rs:105:10 + --> $DIR/macros-nonfatal-errors.rs:104:10 | LL | env!(invalid); | ^^^^^^^ error: expected string literal - --> $DIR/macros-nonfatal-errors.rs:106:10 + --> $DIR/macros-nonfatal-errors.rs:105:10 | LL | env!(foo, abr, baz); | ^^^ error: environment variable `RUST_HOPEFULLY_THIS_DOESNT_EXIST` not defined - --> $DIR/macros-nonfatal-errors.rs:107:5 + --> $DIR/macros-nonfatal-errors.rs:106:5 | LL | env!("RUST_HOPEFULLY_THIS_DOESNT_EXIST"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -165,7 +165,7 @@ LL | env!("RUST_HOPEFULLY_THIS_DOESNT_EXIST"); = note: this error originates in the macro `env` (in Nightly builds, run with -Z macro-backtrace for more info) error: format argument must be a string literal - --> $DIR/macros-nonfatal-errors.rs:109:13 + --> $DIR/macros-nonfatal-errors.rs:108:13 | LL | format!(invalid); | ^^^^^^^ @@ -176,19 +176,19 @@ LL | format!("{}", invalid); | +++++ error: argument must be a string literal - --> $DIR/macros-nonfatal-errors.rs:111:14 + --> $DIR/macros-nonfatal-errors.rs:110:14 | LL | include!(invalid); | ^^^^^^^ error: argument must be a string literal - --> $DIR/macros-nonfatal-errors.rs:113:18 + --> $DIR/macros-nonfatal-errors.rs:112:18 | LL | include_str!(invalid); | ^^^^^^^ error: couldn't read $DIR/i'd be quite surprised if a file with this name existed: $FILE_NOT_FOUND_MSG (os error 2) - --> $DIR/macros-nonfatal-errors.rs:114:5 + --> $DIR/macros-nonfatal-errors.rs:113:5 | LL | include_str!("i'd be quite surprised if a file with this name existed"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -196,13 +196,13 @@ LL | include_str!("i'd be quite surprised if a file with this name existed") = note: this error originates in the macro `include_str` (in Nightly builds, run with -Z macro-backtrace for more info) error: argument must be a string literal - --> $DIR/macros-nonfatal-errors.rs:115:20 + --> $DIR/macros-nonfatal-errors.rs:114:20 | LL | include_bytes!(invalid); | ^^^^^^^ error: couldn't read $DIR/i'd be quite surprised if a file with this name existed: $FILE_NOT_FOUND_MSG (os error 2) - --> $DIR/macros-nonfatal-errors.rs:116:5 + --> $DIR/macros-nonfatal-errors.rs:115:5 | LL | include_bytes!("i'd be quite surprised if a file with this name existed"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -210,13 +210,13 @@ LL | include_bytes!("i'd be quite surprised if a file with this name existed = note: this error originates in the macro `include_bytes` (in Nightly builds, run with -Z macro-backtrace for more info) error: trace_macros! accepts only `true` or `false` - --> $DIR/macros-nonfatal-errors.rs:118:5 + --> $DIR/macros-nonfatal-errors.rs:117:5 | LL | trace_macros!(invalid); | ^^^^^^^^^^^^^^^^^^^^^^ error: cannot find macro `llvm_asm` in this scope - --> $DIR/macros-nonfatal-errors.rs:100:5 + --> $DIR/macros-nonfatal-errors.rs:99:5 | LL | llvm_asm!(invalid); | ^^^^^^^^ From a3dd654ae9f9002d3ff47e45a9a9b6afcb484d2f Mon Sep 17 00:00:00 2001 From: Jacob Pratt Date: Tue, 8 Mar 2022 15:44:52 -0500 Subject: [PATCH 05/15] Add documentation --- library/core/src/default.rs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/library/core/src/default.rs b/library/core/src/default.rs index fb862f7df947b..1ce00828bf344 100644 --- a/library/core/src/default.rs +++ b/library/core/src/default.rs @@ -52,6 +52,23 @@ /// This trait can be used with `#[derive]` if all of the type's fields implement /// `Default`. When `derive`d, it will use the default value for each field's type. /// +/// ### `enum`s +/// +/// When using `#[derive(Default)]` on an `enum`, you need to choose which unit variant will be +/// default. You do this by placing the `#[default]` attribute on the variant. +/// +/// ``` +/// #[derive(Default)] +/// enum Kind { +/// #[default] +/// A, +/// B, +/// C, +/// } +/// ``` +/// +/// You cannot use the `#[default]` attribute on non-unit or non-exhaustive variants. +/// /// ## How can I implement `Default`? /// /// Provide an implementation for the `default()` method that returns the value of From 7c2d57e0fa1615d993a4b4166163fb0b3ec7d395 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Wed, 13 Apr 2022 22:51:34 +0200 Subject: [PATCH 06/15] couple of clippy::complexity fixes --- compiler/rustc_errors/src/diagnostic.rs | 2 +- compiler/rustc_expand/src/mbe/macro_check.rs | 2 +- compiler/rustc_infer/src/infer/at.rs | 6 +++--- compiler/rustc_macros/src/lib.rs | 2 +- compiler/rustc_middle/src/ty/inhabitedness/mod.rs | 2 +- compiler/rustc_mir_build/src/build/expr/as_constant.rs | 2 +- compiler/rustc_mir_build/src/build/expr/into.rs | 6 +----- compiler/rustc_mir_build/src/build/matches/test.rs | 2 +- compiler/rustc_mir_transform/src/check_unsafety.rs | 4 ++-- compiler/rustc_parse/src/lexer/mod.rs | 6 +++--- compiler/rustc_passes/src/stability.rs | 4 ++-- compiler/rustc_session/src/session.rs | 2 +- compiler/rustc_target/src/abi/call/sparc64.rs | 6 +++--- .../rustc_trait_selection/src/traits/on_unimplemented.rs | 2 +- compiler/rustc_typeck/src/check/fn_ctxt/checks.rs | 4 ++-- compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs | 2 +- 16 files changed, 25 insertions(+), 29 deletions(-) diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index ecb3cdd627cec..9cd072c8b4cdf 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -832,7 +832,7 @@ impl Diagnostic { name: impl Into>, arg: DiagnosticArgValue<'static>, ) -> &mut Self { - self.args.push((name.into(), arg.into())); + self.args.push((name.into(), arg)); self } diff --git a/compiler/rustc_expand/src/mbe/macro_check.rs b/compiler/rustc_expand/src/mbe/macro_check.rs index 4298475767e6f..c6a6e3d125f70 100644 --- a/compiler/rustc_expand/src/mbe/macro_check.rs +++ b/compiler/rustc_expand/src/mbe/macro_check.rs @@ -270,7 +270,7 @@ fn check_binders( MISSING_FRAGMENT_SPECIFIER, span, node_id, - &format!("missing fragment specifier"), + "missing fragment specifier", ); } if !macros.is_empty() { diff --git a/compiler/rustc_infer/src/infer/at.rs b/compiler/rustc_infer/src/infer/at.rs index 09b02ba74a8de..58c309a5c52ea 100644 --- a/compiler/rustc_infer/src/infer/at.rs +++ b/compiler/rustc_infer/src/infer/at.rs @@ -63,9 +63,9 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { /// common state. Used in coherence. pub fn fork(&self) -> Self { Self { - tcx: self.tcx.clone(), - defining_use_anchor: self.defining_use_anchor.clone(), - in_progress_typeck_results: self.in_progress_typeck_results.clone(), + tcx: self.tcx, + defining_use_anchor: self.defining_use_anchor, + in_progress_typeck_results: self.in_progress_typeck_results, inner: self.inner.clone(), skip_leak_check: self.skip_leak_check.clone(), lexical_region_resolutions: self.lexical_region_resolutions.clone(), diff --git a/compiler/rustc_macros/src/lib.rs b/compiler/rustc_macros/src/lib.rs index 3589860eb0eac..b53ef8161359a 100644 --- a/compiler/rustc_macros/src/lib.rs +++ b/compiler/rustc_macros/src/lib.rs @@ -44,7 +44,7 @@ pub fn symbols(input: TokenStream) -> TokenStream { #[proc_macro] #[allow_internal_unstable(step_trait, rustc_attrs, trusted_step)] pub fn newtype_index(input: TokenStream) -> TokenStream { - newtype::newtype(input).into() + newtype::newtype(input) } decl_derive!([HashStable, attributes(stable_hasher)] => hash_stable::hash_stable_derive); diff --git a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs index 2c78c1f63d8ff..226456588e75d 100644 --- a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs +++ b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs @@ -191,7 +191,7 @@ impl<'tcx> Ty<'tcx> { tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, ) -> DefIdForest<'tcx> { - tcx.type_uninhabited_from(param_env.and(self)).clone() + tcx.type_uninhabited_from(param_env.and(self)) } } 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 8b9b1847e7f0e..3a6e59db90b91 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_constant.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_constant.rs @@ -39,7 +39,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } }; - Constant { span, user_ty: None, literal: literal.into() } + Constant { span, user_ty: None, literal } } ExprKind::NonHirLiteral { lit, user_ty } => { let user_ty = user_ty.map(|user_ty| { diff --git a/compiler/rustc_mir_build/src/build/expr/into.rs b/compiler/rustc_mir_build/src/build/expr/into.rs index a8f623dbe4693..823f5f4cf12c4 100644 --- a/compiler/rustc_mir_build/src/build/expr/into.rs +++ b/compiler/rustc_mir_build/src/build/expr/into.rs @@ -423,11 +423,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } thir::InlineAsmOperand::Const { value, span } => { mir::InlineAsmOperand::Const { - value: Box::new(Constant { - span, - user_ty: None, - literal: value.into(), - }), + value: Box::new(Constant { span, user_ty: None, literal: value }), } } thir::InlineAsmOperand::SymFn { expr } => mir::InlineAsmOperand::SymFn { diff --git a/compiler/rustc_mir_build/src/build/matches/test.rs b/compiler/rustc_mir_build/src/build/matches/test.rs index 806c260d110ea..0e9e986937660 100644 --- a/compiler/rustc_mir_build/src/build/matches/test.rs +++ b/compiler/rustc_mir_build/src/build/matches/test.rs @@ -441,7 +441,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // Need to experiment. user_ty: None, - literal: method.into(), + literal: method, })), args: vec![val, expect], destination: Some((eq_result, eq_block)), diff --git a/compiler/rustc_mir_transform/src/check_unsafety.rs b/compiler/rustc_mir_transform/src/check_unsafety.rs index d1d6e7cfe2fed..1b4510b622068 100644 --- a/compiler/rustc_mir_transform/src/check_unsafety.rs +++ b/compiler/rustc_mir_transform/src/check_unsafety.rs @@ -539,13 +539,13 @@ fn report_unused_unsafe(tcx: TyCtxt<'_>, kind: UnusedUnsafe, id: HirId) { 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"), + "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"), + "because it's nested under this `unsafe` fn", ) .note( "this `unsafe` block does contain unsafe operations, \ diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs index 5ab412dc777de..79f0237fd9b74 100644 --- a/compiler/rustc_parse/src/lexer/mod.rs +++ b/compiler/rustc_parse/src/lexer/mod.rs @@ -234,13 +234,13 @@ impl<'a> StringReader<'a> { rustc_lexer::TokenKind::InvalidIdent // Do not recover an identifier with emoji if the codepoint is a confusable // with a recoverable substitution token, like `➖`. - if UNICODE_ARRAY + if !UNICODE_ARRAY .iter() - .find(|&&(c, _, _)| { + .any(|&(c, _, _)| { let sym = self.str_from(start); sym.chars().count() == 1 && c == sym.chars().next().unwrap() }) - .is_none() => + => { let sym = nfc_normalize(self.str_from(start)); let span = self.mk_sp(start, self.pos); diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs index ff033cbb57299..01ba9e35c24dc 100644 --- a/compiler/rustc_passes/src/stability.rs +++ b/compiler/rustc_passes/src/stability.rs @@ -133,9 +133,9 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> { } // `Deprecation` is just two pointers, no need to intern it - let depr_entry = DeprecationEntry::local(depr.clone(), def_id); + let depr_entry = DeprecationEntry::local(*depr, def_id); self.index.depr_map.insert(def_id, depr_entry); - } else if let Some(parent_depr) = self.parent_depr.clone() { + } else if let Some(parent_depr) = self.parent_depr { if inherit_deprecation.yes() { is_deprecated = true; info!("tagging child {:?} as deprecated from parent", def_id); diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index d70f89760a1ff..3fdceadf1919a 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -238,7 +238,7 @@ impl Session { } diag.emit(); // If we should err, make sure we did. - if must_err && !self.has_errors().is_some() { + if must_err && self.has_errors().is_none() { // We have skipped a feature gate, and not run into other errors... reject. self.err( "`-Zunleash-the-miri-inside-of-you` may not be used to circumvent feature \ diff --git a/compiler/rustc_target/src/abi/call/sparc64.rs b/compiler/rustc_target/src/abi/call/sparc64.rs index 5a92ebdd9e843..cc3a0a69999b0 100644 --- a/compiler/rustc_target/src/abi/call/sparc64.rs +++ b/compiler/rustc_target/src/abi/call/sparc64.rs @@ -113,11 +113,11 @@ where data = arg_scalar(cx, &scalar, offset, data); } abi::Abi::Aggregate { .. } => { - for i in 0..layout.fields.count().clone() { + for i in 0..layout.fields.count() { if offset < layout.fields.offset(i) { offset = layout.fields.offset(i); } - data = parse_structure(cx, layout.field(cx, i).clone(), data.clone(), offset); + data = parse_structure(cx, layout.field(cx, i), data.clone(), offset); } } _ => { @@ -161,7 +161,7 @@ where let mut data = parse_structure( cx, - arg.layout.clone(), + arg.layout, Sdata { prefix: [None; 8], prefix_index: 0, diff --git a/compiler/rustc_trait_selection/src/traits/on_unimplemented.rs b/compiler/rustc_trait_selection/src/traits/on_unimplemented.rs index 38be28c07ff18..ce0e0a21ff516 100644 --- a/compiler/rustc_trait_selection/src/traits/on_unimplemented.rs +++ b/compiler/rustc_trait_selection/src/traits/on_unimplemented.rs @@ -258,7 +258,7 @@ impl<'tcx> OnUnimplementedDirective { enclosing_scope = Some(enclosing_scope_.clone()); } - append_const_msg = command.append_const_msg.clone(); + append_const_msg = command.append_const_msg; } OnUnimplementedNote { diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs index f6a5243274cd2..9c70261088880 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs @@ -415,8 +415,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .get_if_local(def_id) .and_then(|node| node.body_id()) .into_iter() - .map(|id| tcx.hir().body(id).params) - .flatten(); + .flat_map(|id| tcx.hir().body(id).params) + ; for param in params { spans.push_span_label(param.span, String::new()); diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs b/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs index 93a0900c7e80d..62518408b8b30 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs @@ -646,7 +646,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // now get all predicates in the same types as the where bounds, so we can chain them let predicates_from_where = - where_predicates.iter().flatten().map(|bounds| bounds.iter()).flatten(); + where_predicates.iter().flatten().flat_map(|bounds| bounds.iter()); // extract all bounds from the source code using their spans let all_matching_bounds_strs = expected_generic_param From 21d3f8444ab21c7bfc4a2b78d429f1ab161708c9 Mon Sep 17 00:00:00 2001 From: Keita Nonaka Date: Wed, 13 Apr 2022 22:09:03 -0700 Subject: [PATCH 07/15] test: add is_superset test cases for BTreeSet --- .../alloc/src/collections/btree/set/tests.rs | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/library/alloc/src/collections/btree/set/tests.rs b/library/alloc/src/collections/btree/set/tests.rs index 00a2a0aaa14ce..a56916081b748 100644 --- a/library/alloc/src/collections/btree/set/tests.rs +++ b/library/alloc/src/collections/btree/set/tests.rs @@ -319,6 +319,42 @@ fn test_is_subset() { assert_eq!(is_subset(&[99, 100], &large), false); } +#[test] +fn test_is_superset() { + fn is_superset(a: &[i32], b: &[i32]) -> bool { + let set_a = BTreeSet::from_iter(a.iter()); + let set_b = BTreeSet::from_iter(b.iter()); + set_a.is_superset(&set_b) + } + + assert_eq!(is_superset(&[], &[]), true); + assert_eq!(is_superset(&[], &[1, 2]), false); + assert_eq!(is_superset(&[0], &[1, 2]), false); + assert_eq!(is_superset(&[1], &[1, 2]), false); + assert_eq!(is_superset(&[4], &[1, 2]), false); + assert_eq!(is_superset(&[1, 4], &[1, 2]), false); + assert_eq!(is_superset(&[1, 2], &[1, 2]), true); + assert_eq!(is_superset(&[1, 2, 3], &[1, 3]), true); + assert_eq!(is_superset(&[1, 2, 3], &[]), true); + assert_eq!(is_superset(&[-1, 1, 2, 3], &[-1, 3]), true); + + if cfg!(miri) { + // Miri is too slow + return; + } + + let large = Vec::from_iter(0..100); + assert_eq!(is_superset(&[], &large), false); + assert_eq!(is_superset(&large, &[]), true); + assert_eq!(is_superset(&large, &[1]), true); + assert_eq!(is_superset(&large, &[50, 99]), true); + assert_eq!(is_superset(&large, &[100]), false); + assert_eq!(is_superset(&large, &[0, 99]), true); + assert_eq!(is_superset(&[-1], &large), false); + assert_eq!(is_superset(&[0], &large), false); + assert_eq!(is_superset(&[99, 100], &large), false); +} + #[test] fn test_retain() { let mut set = BTreeSet::from([1, 2, 3, 4, 5, 6]); From 50c339e8f5e5516c9ba4938979e787c0a0a8e081 Mon Sep 17 00:00:00 2001 From: Keita Nonaka Date: Wed, 13 Apr 2022 22:19:08 -0700 Subject: [PATCH 08/15] test: add remove() test cases for BTreeSet --- .../alloc/src/collections/btree/set/tests.rs | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/library/alloc/src/collections/btree/set/tests.rs b/library/alloc/src/collections/btree/set/tests.rs index a56916081b748..429b1644976c7 100644 --- a/library/alloc/src/collections/btree/set/tests.rs +++ b/library/alloc/src/collections/btree/set/tests.rs @@ -427,6 +427,26 @@ fn test_clear() { x.clear(); assert!(x.is_empty()); } +#[test] +fn test_remove() { + let mut x = BTreeSet::new(); + assert!(x.is_empty()); + + x.insert(1); + x.insert(2); + x.insert(3); + x.insert(4); + + assert_eq!(x.remove(&2), true); + assert_eq!(x.remove(&0), false); + assert_eq!(x.remove(&5), false); + assert_eq!(x.remove(&1), true); + assert_eq!(x.remove(&2), false); + assert_eq!(x.remove(&3), true); + assert_eq!(x.remove(&4), true); + assert_eq!(x.remove(&4), false); + assert!(x.is_empty()); +} #[test] fn test_zip() { From 7a35c0f52d2a37d3ce10772b07d7a45a445ebbf0 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Thu, 14 Apr 2022 09:51:25 +0200 Subject: [PATCH 09/15] Use u32 instead of i32 for futexes. --- library/std/src/sys/unix/futex.rs | 30 +++++++------- library/std/src/sys/unix/locks/futex.rs | 12 +++--- .../std/src/sys/unix/locks/futex_rwlock.rs | 40 +++++++++---------- library/std/src/sys/wasm/atomics/futex.rs | 14 ++++--- .../std/src/sys_common/thread_parker/futex.rs | 12 +++--- 5 files changed, 55 insertions(+), 53 deletions(-) diff --git a/library/std/src/sys/unix/futex.rs b/library/std/src/sys/unix/futex.rs index b45d1c0149cb4..62760373a6aff 100644 --- a/library/std/src/sys/unix/futex.rs +++ b/library/std/src/sys/unix/futex.rs @@ -4,7 +4,7 @@ all(target_os = "emscripten", target_feature = "atomics") ))] -use crate::sync::atomic::AtomicI32; +use crate::sync::atomic::AtomicU32; use crate::time::Duration; /// Wait for a futex_wake operation to wake us. @@ -13,7 +13,7 @@ use crate::time::Duration; /// /// Returns false on timeout, and true in all other cases. #[cfg(any(target_os = "linux", target_os = "android"))] -pub fn futex_wait(futex: &AtomicI32, expected: i32, timeout: Option) -> bool { +pub fn futex_wait(futex: &AtomicU32, expected: u32, timeout: Option) -> bool { use super::time::Timespec; use crate::ptr::null; use crate::sync::atomic::Ordering::Relaxed; @@ -35,7 +35,7 @@ pub fn futex_wait(futex: &AtomicI32, expected: i32, timeout: Option) - let r = unsafe { libc::syscall( libc::SYS_futex, - futex as *const AtomicI32, + futex as *const AtomicU32, libc::FUTEX_WAIT_BITSET | libc::FUTEX_PRIVATE_FLAG, expected, timespec.as_ref().map_or(null(), |t| &t.t as *const libc::timespec), @@ -53,10 +53,10 @@ pub fn futex_wait(futex: &AtomicI32, expected: i32, timeout: Option) - } #[cfg(target_os = "emscripten")] -pub fn futex_wait(futex: &AtomicI32, expected: i32, timeout: Option) { +pub fn futex_wait(futex: &AtomicU32, expected: u32, timeout: Option) { extern "C" { fn emscripten_futex_wait( - addr: *const AtomicI32, + addr: *const AtomicU32, val: libc::c_uint, max_wait_ms: libc::c_double, ) -> libc::c_int; @@ -64,10 +64,8 @@ pub fn futex_wait(futex: &AtomicI32, expected: i32, timeout: Option) { unsafe { emscripten_futex_wait( - futex as *const AtomicI32, - // `val` is declared unsigned to match the Emscripten headers, but since it's used as - // an opaque value, we can ignore the meaning of signed vs. unsigned and cast here. - expected as libc::c_uint, + futex, + expected, timeout.map_or(crate::f64::INFINITY, |d| d.as_secs_f64() * 1000.0), ); } @@ -78,11 +76,11 @@ pub fn futex_wait(futex: &AtomicI32, expected: i32, timeout: Option) { /// Returns true if this actually woke up such a thread, /// or false if no thread was waiting on this futex. #[cfg(any(target_os = "linux", target_os = "android"))] -pub fn futex_wake(futex: &AtomicI32) -> bool { +pub fn futex_wake(futex: &AtomicU32) -> bool { unsafe { libc::syscall( libc::SYS_futex, - futex as *const AtomicI32, + futex as *const AtomicU32, libc::FUTEX_WAKE | libc::FUTEX_PRIVATE_FLAG, 1, ) > 0 @@ -91,11 +89,11 @@ pub fn futex_wake(futex: &AtomicI32) -> bool { /// Wake up all threads that are waiting on futex_wait on this futex. #[cfg(any(target_os = "linux", target_os = "android"))] -pub fn futex_wake_all(futex: &AtomicI32) { +pub fn futex_wake_all(futex: &AtomicU32) { unsafe { libc::syscall( libc::SYS_futex, - futex as *const AtomicI32, + futex as *const AtomicU32, libc::FUTEX_WAKE | libc::FUTEX_PRIVATE_FLAG, i32::MAX, ); @@ -103,10 +101,10 @@ pub fn futex_wake_all(futex: &AtomicI32) { } #[cfg(target_os = "emscripten")] -pub fn futex_wake(futex: &AtomicI32) -> bool { +pub fn futex_wake(futex: &AtomicU32) -> bool { extern "C" { - fn emscripten_futex_wake(addr: *const AtomicI32, count: libc::c_int) -> libc::c_int; + fn emscripten_futex_wake(addr: *const AtomicU32, count: libc::c_int) -> libc::c_int; } - unsafe { emscripten_futex_wake(futex as *const AtomicI32, 1) > 0 } + unsafe { emscripten_futex_wake(futex, 1) > 0 } } diff --git a/library/std/src/sys/unix/locks/futex.rs b/library/std/src/sys/unix/locks/futex.rs index d97777e4da29d..b166e7c453cad 100644 --- a/library/std/src/sys/unix/locks/futex.rs +++ b/library/std/src/sys/unix/locks/futex.rs @@ -1,6 +1,6 @@ use crate::cell::UnsafeCell; use crate::sync::atomic::{ - AtomicI32, AtomicUsize, + AtomicU32, AtomicUsize, Ordering::{Acquire, Relaxed, Release}, }; use crate::sys::futex::{futex_wait, futex_wake, futex_wake_all}; @@ -13,13 +13,13 @@ pub struct Mutex { /// 0: unlocked /// 1: locked, no other threads waiting /// 2: locked, and other threads waiting (contended) - futex: AtomicI32, + futex: AtomicU32, } impl Mutex { #[inline] pub const fn new() -> Self { - Self { futex: AtomicI32::new(0) } + Self { futex: AtomicU32::new(0) } } #[inline] @@ -71,7 +71,7 @@ impl Mutex { } } - fn spin(&self) -> i32 { + fn spin(&self) -> u32 { let mut spin = 100; loop { // We only use `load` (and not `swap` or `compare_exchange`) @@ -110,13 +110,13 @@ pub struct Condvar { // The value of this atomic is simply incremented on every notification. // This is used by `.wait()` to not miss any notifications after // unlocking the mutex and before waiting for notifications. - futex: AtomicI32, + futex: AtomicU32, } impl Condvar { #[inline] pub const fn new() -> Self { - Self { futex: AtomicI32::new(0) } + Self { futex: AtomicU32::new(0) } } #[inline] diff --git a/library/std/src/sys/unix/locks/futex_rwlock.rs b/library/std/src/sys/unix/locks/futex_rwlock.rs index aa16da97e4c19..e42edb2585834 100644 --- a/library/std/src/sys/unix/locks/futex_rwlock.rs +++ b/library/std/src/sys/unix/locks/futex_rwlock.rs @@ -1,5 +1,5 @@ use crate::sync::atomic::{ - AtomicI32, + AtomicU32, Ordering::{Acquire, Relaxed, Release}, }; use crate::sys::futex::{futex_wait, futex_wake, futex_wake_all}; @@ -14,36 +14,36 @@ pub struct RwLock { // 0x3FFF_FFFF: Write locked // Bit 30: Readers are waiting on this futex. // Bit 31: Writers are waiting on the writer_notify futex. - state: AtomicI32, + state: AtomicU32, // The 'condition variable' to notify writers through. // Incremented on every signal. - writer_notify: AtomicI32, + writer_notify: AtomicU32, } -const READ_LOCKED: i32 = 1; -const MASK: i32 = (1 << 30) - 1; -const WRITE_LOCKED: i32 = MASK; -const MAX_READERS: i32 = MASK - 1; -const READERS_WAITING: i32 = 1 << 30; -const WRITERS_WAITING: i32 = 1 << 31; +const READ_LOCKED: u32 = 1; +const MASK: u32 = (1 << 30) - 1; +const WRITE_LOCKED: u32 = MASK; +const MAX_READERS: u32 = MASK - 1; +const READERS_WAITING: u32 = 1 << 30; +const WRITERS_WAITING: u32 = 1 << 31; -fn is_unlocked(state: i32) -> bool { +fn is_unlocked(state: u32) -> bool { state & MASK == 0 } -fn is_write_locked(state: i32) -> bool { +fn is_write_locked(state: u32) -> bool { state & MASK == WRITE_LOCKED } -fn has_readers_waiting(state: i32) -> bool { +fn has_readers_waiting(state: u32) -> bool { state & READERS_WAITING != 0 } -fn has_writers_waiting(state: i32) -> bool { +fn has_writers_waiting(state: u32) -> bool { state & WRITERS_WAITING != 0 } -fn is_read_lockable(state: i32) -> bool { +fn is_read_lockable(state: u32) -> bool { // This also returns false if the counter could overflow if we tried to read lock it. // // We don't allow read-locking if there's readers waiting, even if the lock is unlocked @@ -53,14 +53,14 @@ fn is_read_lockable(state: i32) -> bool { state & MASK < MAX_READERS && !has_readers_waiting(state) && !has_writers_waiting(state) } -fn has_reached_max_readers(state: i32) -> bool { +fn has_reached_max_readers(state: u32) -> bool { state & MASK == MAX_READERS } impl RwLock { #[inline] pub const fn new() -> Self { - Self { state: AtomicI32::new(0), writer_notify: AtomicI32::new(0) } + Self { state: AtomicU32::new(0), writer_notify: AtomicU32::new(0) } } #[inline] @@ -227,7 +227,7 @@ impl RwLock { /// If both are waiting, this will wake up only one writer, but will fall /// back to waking up readers if there was no writer to wake up. #[cold] - fn wake_writer_or_readers(&self, mut state: i32) { + fn wake_writer_or_readers(&self, mut state: u32) { assert!(is_unlocked(state)); // The readers waiting bit might be turned on at any point now, @@ -287,7 +287,7 @@ impl RwLock { } /// Spin for a while, but stop directly at the given condition. - fn spin_until(&self, f: impl Fn(i32) -> bool) -> i32 { + fn spin_until(&self, f: impl Fn(u32) -> bool) -> u32 { let mut spin = 100; // Chosen by fair dice roll. loop { let state = self.state.load(Relaxed); @@ -299,12 +299,12 @@ impl RwLock { } } - fn spin_write(&self) -> i32 { + fn spin_write(&self) -> u32 { // Stop spinning when it's unlocked or when there's waiting writers, to keep things somewhat fair. self.spin_until(|state| is_unlocked(state) || has_writers_waiting(state)) } - fn spin_read(&self) -> i32 { + fn spin_read(&self) -> u32 { // Stop spinning when it's unlocked or read locked, or when there's waiting threads. self.spin_until(|state| { !is_write_locked(state) || has_readers_waiting(state) || has_writers_waiting(state) diff --git a/library/std/src/sys/wasm/atomics/futex.rs b/library/std/src/sys/wasm/atomics/futex.rs index 3d8bf42f7255e..bbe9bd6951af9 100644 --- a/library/std/src/sys/wasm/atomics/futex.rs +++ b/library/std/src/sys/wasm/atomics/futex.rs @@ -1,17 +1,21 @@ use crate::arch::wasm32; use crate::convert::TryInto; -use crate::sync::atomic::AtomicI32; +use crate::sync::atomic::AtomicU32; use crate::time::Duration; -pub fn futex_wait(futex: &AtomicI32, expected: i32, timeout: Option) { +pub fn futex_wait(futex: &AtomicU32, expected: u32, timeout: Option) { let timeout = timeout.and_then(|t| t.as_nanos().try_into().ok()).unwrap_or(-1); unsafe { - wasm32::memory_atomic_wait32(futex as *const AtomicI32 as *mut i32, expected, timeout); + wasm32::memory_atomic_wait32( + futex as *const AtomicU32 as *mut i32, + expected as i32, + timeout, + ); } } -pub fn futex_wake(futex: &AtomicI32) { +pub fn futex_wake(futex: &AtomicU32) { unsafe { - wasm32::memory_atomic_notify(futex as *const AtomicI32 as *mut i32, 1); + wasm32::memory_atomic_notify(futex as *const AtomicU32 as *mut i32, 1); } } diff --git a/library/std/src/sys_common/thread_parker/futex.rs b/library/std/src/sys_common/thread_parker/futex.rs index 0132743b24404..fbf6231ff4ab3 100644 --- a/library/std/src/sys_common/thread_parker/futex.rs +++ b/library/std/src/sys_common/thread_parker/futex.rs @@ -1,14 +1,14 @@ -use crate::sync::atomic::AtomicI32; +use crate::sync::atomic::AtomicU32; use crate::sync::atomic::Ordering::{Acquire, Release}; use crate::sys::futex::{futex_wait, futex_wake}; use crate::time::Duration; -const PARKED: i32 = -1; -const EMPTY: i32 = 0; -const NOTIFIED: i32 = 1; +const PARKED: u32 = u32::MAX; +const EMPTY: u32 = 0; +const NOTIFIED: u32 = 1; pub struct Parker { - state: AtomicI32, + state: AtomicU32, } // Notes about memory ordering: @@ -34,7 +34,7 @@ pub struct Parker { impl Parker { #[inline] pub const fn new() -> Self { - Parker { state: AtomicI32::new(EMPTY) } + Parker { state: AtomicU32::new(EMPTY) } } // Assumes this is only called by the thread that owns the Parker, From 75287dd73d09a0712a7196d0604ee05d23908f59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Wed, 13 Apr 2022 22:59:45 +0200 Subject: [PATCH 10/15] remove function param that is only used in recursive of fn inner() --- compiler/rustc_expand/src/mbe/macro_parser.rs | 10 ++++------ compiler/rustc_expand/src/mbe/macro_rules.rs | 4 ++-- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_expand/src/mbe/macro_parser.rs b/compiler/rustc_expand/src/mbe/macro_parser.rs index 74b8450f756d3..63aac64989dfa 100644 --- a/compiler/rustc_expand/src/mbe/macro_parser.rs +++ b/compiler/rustc_expand/src/mbe/macro_parser.rs @@ -77,7 +77,6 @@ use crate::mbe::{KleeneOp, TokenTree}; use rustc_ast::token::{self, DocComment, Nonterminal, NonterminalKind, Token}; use rustc_parse::parser::{NtOrTt, Parser}; -use rustc_session::parse::ParseSess; use rustc_span::symbol::MacroRulesNormalizedIdent; use rustc_span::Span; @@ -128,9 +127,8 @@ pub(super) enum MatcherLoc { Eof, } -pub(super) fn compute_locs(sess: &ParseSess, matcher: &[TokenTree]) -> Vec { +pub(super) fn compute_locs(matcher: &[TokenTree]) -> Vec { fn inner( - sess: &ParseSess, tts: &[TokenTree], locs: &mut Vec, next_metavar: &mut usize, @@ -147,7 +145,7 @@ pub(super) fn compute_locs(sess: &ParseSess, matcher: &[TokenTree]) -> Vec { @@ -162,7 +160,7 @@ pub(super) fn compute_locs(sess: &ParseSess, matcher: &[TokenTree]) -> Vec Vec { - mbe::macro_parser::compute_locs(&sess.parse_sess, &delimited.tts) + mbe::macro_parser::compute_locs(&delimited.tts) } _ => sess.parse_sess.span_diagnostic.span_bug(def.span, "malformed macro lhs"), } From 15abc81967b1c8ed4cde8b0e3aa726aaa9323c0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Wed, 13 Apr 2022 23:03:11 +0200 Subject: [PATCH 11/15] remove reudndant function param in check_matcher_core() --- compiler/rustc_expand/src/mbe/macro_rules.rs | 26 ++++++-------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs index 009b6bb150519..e2b82580342e8 100644 --- a/compiler/rustc_expand/src/mbe/macro_rules.rs +++ b/compiler/rustc_expand/src/mbe/macro_rules.rs @@ -478,7 +478,7 @@ pub fn compile_declarative_macro( ) .pop() .unwrap(); - valid &= check_lhs_nt_follows(&sess.parse_sess, features, &def, &tt); + valid &= check_lhs_nt_follows(&sess.parse_sess, &def, &tt); return tt; } sess.parse_sess.span_diagnostic.span_bug(def.span, "wrong-structured lhs") @@ -563,16 +563,11 @@ pub fn compile_declarative_macro( })) } -fn check_lhs_nt_follows( - sess: &ParseSess, - features: &Features, - def: &ast::Item, - lhs: &mbe::TokenTree, -) -> bool { +fn check_lhs_nt_follows(sess: &ParseSess, def: &ast::Item, lhs: &mbe::TokenTree) -> bool { // lhs is going to be like TokenTree::Delimited(...), where the // entire lhs is those tts. Or, it can be a "bare sequence", not wrapped in parens. if let mbe::TokenTree::Delimited(_, delimited) = lhs { - check_matcher(sess, features, def, &delimited.tts) + check_matcher(sess, def, &delimited.tts) } else { let msg = "invalid macro matcher; matchers must be contained in balanced delimiters"; sess.span_diagnostic.span_err(lhs.span(), msg); @@ -632,16 +627,11 @@ fn check_rhs(sess: &ParseSess, rhs: &mbe::TokenTree) -> bool { false } -fn check_matcher( - sess: &ParseSess, - features: &Features, - def: &ast::Item, - matcher: &[mbe::TokenTree], -) -> bool { +fn check_matcher(sess: &ParseSess, def: &ast::Item, matcher: &[mbe::TokenTree]) -> bool { let first_sets = FirstSets::new(matcher); let empty_suffix = TokenSet::empty(); let err = sess.span_diagnostic.err_count(); - check_matcher_core(sess, features, def, &first_sets, matcher, &empty_suffix); + check_matcher_core(sess, def, &first_sets, matcher, &empty_suffix); err == sess.span_diagnostic.err_count() } @@ -955,7 +945,6 @@ impl<'tt> TokenSet<'tt> { // see `FirstSets::new`. fn check_matcher_core<'tt>( sess: &ParseSess, - features: &Features, def: &ast::Item, first_sets: &FirstSets<'tt>, matcher: &'tt [mbe::TokenTree], @@ -1008,7 +997,7 @@ fn check_matcher_core<'tt>( token::CloseDelim(d.delim), span.close, )); - check_matcher_core(sess, features, def, first_sets, &d.tts, &my_suffix); + check_matcher_core(sess, def, first_sets, &d.tts, &my_suffix); // don't track non NT tokens last.replace_with_irrelevant(); @@ -1040,8 +1029,7 @@ fn check_matcher_core<'tt>( // At this point, `suffix_first` is built, and // `my_suffix` is some TokenSet that we can use // for checking the interior of `seq_rep`. - let next = - check_matcher_core(sess, features, def, first_sets, &seq_rep.tts, my_suffix); + let next = check_matcher_core(sess, def, first_sets, &seq_rep.tts, my_suffix); if next.maybe_empty { last.add_all(&next); } else { From 65119765155bcf9e89d3b5c6c6d054254e343e1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Wed, 13 Apr 2022 23:07:20 +0200 Subject: [PATCH 12/15] remove redundant function param in check_for_self_assign_helper() --- compiler/rustc_passes/src/dead.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index c777074df4641..8c979a124667c 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -158,7 +158,6 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { #[allow(dead_code)] // FIXME(81658): should be used + lint reinstated after #83171 relands. fn check_for_self_assign(&mut self, assign: &'tcx hir::Expr<'tcx>) { fn check_for_self_assign_helper<'tcx>( - tcx: TyCtxt<'tcx>, typeck_results: &'tcx ty::TypeckResults<'tcx>, lhs: &'tcx hir::Expr<'tcx>, rhs: &'tcx hir::Expr<'tcx>, @@ -177,7 +176,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { } (hir::ExprKind::Field(lhs_l, ident_l), hir::ExprKind::Field(lhs_r, ident_r)) => { if ident_l == ident_r { - return check_for_self_assign_helper(tcx, typeck_results, lhs_l, lhs_r); + return check_for_self_assign_helper(typeck_results, lhs_l, lhs_r); } return false; } @@ -188,7 +187,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { } if let hir::ExprKind::Assign(lhs, rhs, _) = assign.kind { - if check_for_self_assign_helper(self.tcx, self.typeck_results(), lhs, rhs) + if check_for_self_assign_helper(self.typeck_results(), lhs, rhs) && !assign.span.from_expansion() { let is_field_assign = matches!(lhs.kind, hir::ExprKind::Field(..)); From c20bb1d59f17c6329ea922c4bb2ccec5d46e7e00 Mon Sep 17 00:00:00 2001 From: ouz-a Date: Thu, 14 Apr 2022 23:42:15 +0300 Subject: [PATCH 13/15] Update issue-92893.stderr --- compiler/rustc_middle/src/middle/region.rs | 9 +++------ .../rustc_mir_build/src/build/matches/mod.rs | 10 ++++++---- .../src/check/generator_interior.rs | 2 +- src/test/ui/mir/issue-92893.rs | 7 +++++++ src/test/ui/mir/issue-92893.stderr | 20 +++++++++++++++++++ .../src/loops/needless_range_loop.rs | 4 ++-- src/tools/clippy/clippy_lints/src/shadow.rs | 4 ++-- 7 files changed, 41 insertions(+), 15 deletions(-) create mode 100644 src/test/ui/mir/issue-92893.rs create mode 100644 src/test/ui/mir/issue-92893.stderr diff --git a/compiler/rustc_middle/src/middle/region.rs b/compiler/rustc_middle/src/middle/region.rs index 98da20baf026b..af16e5e3fc871 100644 --- a/compiler/rustc_middle/src/middle/region.rs +++ b/compiler/rustc_middle/src/middle/region.rs @@ -362,12 +362,9 @@ impl ScopeTree { self.parent_map.get(&id).cloned().map(|(p, _)| p) } - /// Returns the lifetime of the local variable `var_id` - pub fn var_scope(&self, var_id: hir::ItemLocalId) -> Scope { - self.var_map - .get(&var_id) - .cloned() - .unwrap_or_else(|| bug!("no enclosing scope for id {:?}", var_id)) + /// Returns the lifetime of the local variable `var_id`, if any. + pub fn var_scope(&self, var_id: hir::ItemLocalId) -> Option { + self.var_map.get(&var_id).cloned() } /// Returns the scope when the temp created by `expr_id` will be cleaned up. diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs index 219d101aa7ccf..d45ae19752e8c 100644 --- a/compiler/rustc_mir_build/src/build/matches/mod.rs +++ b/compiler/rustc_mir_build/src/build/matches/mod.rs @@ -701,8 +701,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let local_id = self.var_local_id(var, for_guard); let source_info = self.source_info(span); self.cfg.push(block, Statement { source_info, kind: StatementKind::StorageLive(local_id) }); - let region_scope = self.region_scope_tree.var_scope(var.local_id); - if schedule_drop { + // Altough there is almost always scope for given variable in corner cases + // like #92893 we might get variable with no scope. + if let Some(region_scope) = self.region_scope_tree.var_scope(var.local_id) && schedule_drop{ self.schedule_drop(span, region_scope, local_id, DropKind::Storage); } Place::from(local_id) @@ -710,8 +711,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { crate fn schedule_drop_for_binding(&mut self, var: HirId, span: Span, for_guard: ForGuard) { let local_id = self.var_local_id(var, for_guard); - let region_scope = self.region_scope_tree.var_scope(var.local_id); - self.schedule_drop(span, region_scope, local_id, DropKind::Value); + if let Some(region_scope) = self.region_scope_tree.var_scope(var.local_id) { + self.schedule_drop(span, region_scope, local_id, DropKind::Value); + } } /// Visit all of the primary bindings in a patterns, that is, visit the diff --git a/compiler/rustc_typeck/src/check/generator_interior.rs b/compiler/rustc_typeck/src/check/generator_interior.rs index e584c9ad201f7..a4ae89ecada08 100644 --- a/compiler/rustc_typeck/src/check/generator_interior.rs +++ b/compiler/rustc_typeck/src/check/generator_interior.rs @@ -319,7 +319,7 @@ impl<'a, 'tcx> Visitor<'tcx> for InteriorVisitor<'a, 'tcx> { self.expr_count += 1; if let PatKind::Binding(..) = pat.kind { - let scope = self.region_scope_tree.var_scope(pat.hir_id.local_id); + let scope = self.region_scope_tree.var_scope(pat.hir_id.local_id).unwrap(); let ty = self.fcx.typeck_results.borrow().pat_ty(pat); self.record(ty, pat.hir_id, Some(scope), None, pat.span, false); } diff --git a/src/test/ui/mir/issue-92893.rs b/src/test/ui/mir/issue-92893.rs new file mode 100644 index 0000000000000..d2bbb4f110114 --- /dev/null +++ b/src/test/ui/mir/issue-92893.rs @@ -0,0 +1,7 @@ +struct Bug { + //~^ `let` expressions are not supported here + //~^^ `let` expressions in this position are unstable [E0658] + a: A +} + +fn main() {} diff --git a/src/test/ui/mir/issue-92893.stderr b/src/test/ui/mir/issue-92893.stderr new file mode 100644 index 0000000000000..063b5d66feb45 --- /dev/null +++ b/src/test/ui/mir/issue-92893.stderr @@ -0,0 +1,20 @@ +error: `let` expressions are not supported here + --> $DIR/issue-92893.rs:1:22 + | +LL | struct Bug { + | ^^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error[E0658]: `let` expressions in this position are unstable + --> $DIR/issue-92893.rs:1:22 + | +LL | struct Bug { + | ^^^^^^^^^^ + | + = note: see issue #53667 for more information + = help: add `#![feature(let_chains)]` 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/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs b/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs index 72e86804ed2c3..6ed141fa4a5a6 100644 --- a/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs +++ b/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs @@ -59,7 +59,7 @@ pub(super) fn check<'tcx>( if let Some(indexed_extent) = indexed_extent { let parent_def_id = cx.tcx.hir().get_parent_item(expr.hir_id); let region_scope_tree = cx.tcx.region_scope_tree(parent_def_id); - let pat_extent = region_scope_tree.var_scope(pat.hir_id.local_id); + let pat_extent = region_scope_tree.var_scope(pat.hir_id.local_id).unwrap(); if region_scope_tree.is_subscope_of(indexed_extent, pat_extent) { return; } @@ -262,7 +262,7 @@ impl<'a, 'tcx> VarVisitor<'a, 'tcx> { match res { Res::Local(hir_id) => { let parent_def_id = self.cx.tcx.hir().get_parent_item(expr.hir_id); - let extent = self.cx.tcx.region_scope_tree(parent_def_id).var_scope(hir_id.local_id); + let extent = self.cx.tcx.region_scope_tree(parent_def_id).var_scope(hir_id.local_id).unwrap(); if index_used_directly { self.indexed_directly.insert( seqvar.segments[0].ident.name, diff --git a/src/tools/clippy/clippy_lints/src/shadow.rs b/src/tools/clippy/clippy_lints/src/shadow.rs index 1188258504461..1ab7f52110ce7 100644 --- a/src/tools/clippy/clippy_lints/src/shadow.rs +++ b/src/tools/clippy/clippy_lints/src/shadow.rs @@ -160,8 +160,8 @@ impl<'tcx> LateLintPass<'tcx> for Shadow { fn is_shadow(cx: &LateContext<'_>, owner: LocalDefId, first: ItemLocalId, second: ItemLocalId) -> bool { let scope_tree = cx.tcx.region_scope_tree(owner.to_def_id()); - let first_scope = scope_tree.var_scope(first); - let second_scope = scope_tree.var_scope(second); + let first_scope = scope_tree.var_scope(first).unwrap(); + let second_scope = scope_tree.var_scope(second).unwrap(); scope_tree.is_subscope_of(second_scope, first_scope) } From 5459e6637ae4cd86367927753df6e7fbe1c503e1 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Thu, 14 Apr 2022 16:42:49 -0700 Subject: [PATCH 14/15] docs: Update tests chapter for Termination stabilization --- src/doc/rustc/src/tests/index.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/doc/rustc/src/tests/index.md b/src/doc/rustc/src/tests/index.md index 0e0eb85db746a..32baed9c94498 100644 --- a/src/doc/rustc/src/tests/index.md +++ b/src/doc/rustc/src/tests/index.md @@ -15,7 +15,8 @@ fn it_works() { ``` Tests "pass" if they return without an error. They "fail" if they [panic], or -return a [`Result`] with an error. +return a type such as [`Result`] that implements the [`Termination`] trait +with a non-zero value. By passing the [`--test` option] to `rustc`, the compiler will build the crate in a special mode to construct an executable that will run the tests in the @@ -304,6 +305,7 @@ Experimental support for using custom test harnesses is available on the [`libtest`]: ../../test/index.html [`main` function]: ../../reference/crates-and-source-files.html#main-functions [`Result`]: ../../std/result/index.html +[`Termination`]: ../../std/process/trait.Termination.html [`test` cfg option]: ../../reference/conditional-compilation.html#test [attribute-ignore]: ../../reference/attributes/testing.html#the-ignore-attribute [attribute-should_panic]: ../../reference/attributes/testing.html#the-should_panic-attribute From f9188ccef6d7754ccc4d48ce1ecca1af1d7270c9 Mon Sep 17 00:00:00 2001 From: Takayuki Maeda <41065217+TaKO8Ki@users.noreply.github.com> Date: Fri, 15 Apr 2022 15:56:32 +0900 Subject: [PATCH 15/15] use `format-args-capture` and remove unnecessary nested block --- compiler/rustc_typeck/src/check/_match.rs | 10 +- compiler/rustc_typeck/src/check/callee.rs | 51 ++- compiler/rustc_typeck/src/check/cast.rs | 146 ++++----- compiler/rustc_typeck/src/check/check.rs | 310 +++++++++--------- compiler/rustc_typeck/src/check/coercion.rs | 83 +++-- .../rustc_typeck/src/check/compare_method.rs | 26 +- compiler/rustc_typeck/src/check/demand.rs | 272 ++++++++------- compiler/rustc_typeck/src/check/dropck.rs | 9 +- compiler/rustc_typeck/src/check/expr.rs | 123 +++---- .../src/check/generator_interior.rs | 2 +- compiler/rustc_typeck/src/check/intrinsic.rs | 4 +- compiler/rustc_typeck/src/check/mod.rs | 56 ++-- compiler/rustc_typeck/src/check/pat.rs | 56 ++-- compiler/rustc_typeck/src/check/place_op.rs | 53 ++- compiler/rustc_typeck/src/check/regionck.rs | 18 +- compiler/rustc_typeck/src/check/upvar.rs | 26 +- compiler/rustc_typeck/src/check/wfcheck.rs | 36 +- 17 files changed, 605 insertions(+), 676 deletions(-) diff --git a/compiler/rustc_typeck/src/check/_match.rs b/compiler/rustc_typeck/src/check/_match.rs index 26f7c267ed1c4..1c7e7c935c4a1 100644 --- a/compiler/rustc_typeck/src/check/_match.rs +++ b/compiler/rustc_typeck/src/check/_match.rs @@ -260,10 +260,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &mut |err| { if let Some((span, msg)) = &ret_reason { err.span_label(*span, msg.as_str()); - } else if let ExprKind::Block(block, _) = &then_expr.kind { - if let Some(expr) = &block.expr { - err.span_label(expr.span, "found here".to_string()); - } + } else if let ExprKind::Block(block, _) = &then_expr.kind + && let Some(expr) = &block.expr + { + err.span_label(expr.span, "found here".to_string()); } err.note("`if` expressions without `else` evaluate to `()`"); err.help("consider adding an `else` block that evaluates to the expected type"); @@ -293,7 +293,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return self.get_fn_decl(hir_id).and_then(|(fn_decl, _)| { let span = fn_decl.output.span(); let snippet = self.tcx.sess.source_map().span_to_snippet(span).ok()?; - Some((span, format!("expected `{}` because of this return type", snippet))) + Some((span, format!("expected `{snippet}` because of this return type"))) }); } } diff --git a/compiler/rustc_typeck/src/check/callee.rs b/compiler/rustc_typeck/src/check/callee.rs index 2a5cf03e9d0ba..580fb7c3e0f06 100644 --- a/compiler/rustc_typeck/src/check/callee.rs +++ b/compiler/rustc_typeck/src/check/callee.rs @@ -43,7 +43,7 @@ pub fn check_legal_trait_for_method_call( let (sp, suggestion) = receiver .and_then(|s| tcx.sess.source_map().span_to_snippet(s).ok()) .filter(|snippet| !snippet.is_empty()) - .map(|snippet| (expr_span, format!("drop({})", snippet))) + .map(|snippet| (expr_span, format!("drop({snippet})"))) .unwrap_or_else(|| (span, "drop".to_string())); err.span_suggestion( @@ -315,17 +315,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { hir::ExprKind::Tup(exp), hir::ExprKind::Call(_, args), ) = (parent_node, &callee_expr.kind, &call_expr.kind) + && args.len() == exp.len() { - if args.len() == exp.len() { - let start = callee_expr.span.shrink_to_hi(); - err.span_suggestion( - start, - "consider separating array elements with a comma", - ",".to_string(), - Applicability::MaybeIncorrect, - ); - return true; - } + let start = callee_expr.span.shrink_to_hi(); + err.span_suggestion( + start, + "consider separating array elements with a comma", + ",".to_string(), + Applicability::MaybeIncorrect, + ); + return true; } false } @@ -373,15 +372,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ref t => { let mut unit_variant = None; let mut removal_span = call_expr.span; - if let ty::Adt(adt_def, ..) = t { - if adt_def.is_enum() { - if let hir::ExprKind::Call(expr, _) = call_expr.kind { - removal_span = - expr.span.shrink_to_hi().to(call_expr.span.shrink_to_hi()); - unit_variant = - self.tcx.sess.source_map().span_to_snippet(expr.span).ok(); - } - } + if let ty::Adt(adt_def, ..) = t + && adt_def.is_enum() + && let hir::ExprKind::Call(expr, _) = call_expr.kind + { + removal_span = + expr.span.shrink_to_hi().to(call_expr.span.shrink_to_hi()); + unit_variant = + self.tcx.sess.source_map().span_to_snippet(expr.span).ok(); } let callee_ty = self.resolve_vars_if_possible(callee_ty); @@ -392,8 +390,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { E0618, "expected function, found {}", match unit_variant { - Some(ref path) => format!("enum variant `{}`", path), - None => format!("`{}`", callee_ty), + Some(ref path) => format!("enum variant `{path}`"), + None => format!("`{callee_ty}`"), } ); @@ -408,8 +406,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err.span_suggestion_verbose( removal_span, &format!( - "`{}` is a unit variant, you need to write it without the parentheses", - path + "`{path}` is a unit variant, you need to write it without the parentheses", ), String::new(), Applicability::MachineApplicable, @@ -452,14 +449,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let Some(span) = self.tcx.hir().res_span(def) { let callee_ty = callee_ty.to_string(); let label = match (unit_variant, inner_callee_path) { - (Some(path), _) => Some(format!("`{}` defined here", path)), + (Some(path), _) => Some(format!("`{path}` defined here")), (_, Some(hir::QPath::Resolved(_, path))) => self .tcx .sess .source_map() .span_to_snippet(path.span) .ok() - .map(|p| format!("`{}` defined here returns `{}`", p, callee_ty)), + .map(|p| format!("`{p}` defined here returns `{callee_ty}`")), _ => { match def { // Emit a different diagnostic for local variables, as they are not @@ -475,7 +472,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.tcx.def_path_str(def_id), )) } - _ => Some(format!("`{}` defined here", callee_ty)), + _ => Some(format!("`{callee_ty}` defined here")), } } }; diff --git a/compiler/rustc_typeck/src/check/cast.rs b/compiler/rustc_typeck/src/check/cast.rs index 47292b3e339e5..049940d19a651 100644 --- a/compiler/rustc_typeck/src/check/cast.rs +++ b/compiler/rustc_typeck/src/check/cast.rs @@ -322,7 +322,7 @@ impl<'a, 'tcx> CastCheck<'tcx> { err.span_suggestion( self.span, "compare with zero instead", - format!("{} != 0", snippet), + format!("{snippet} != 0"), Applicability::MachineApplicable, ); } @@ -373,8 +373,8 @@ impl<'a, 'tcx> CastCheck<'tcx> { let mut sugg = None; let mut sugg_mutref = false; if let ty::Ref(reg, cast_ty, mutbl) = *self.cast_ty.kind() { - if let ty::RawPtr(TypeAndMut { ty: expr_ty, .. }) = *self.expr_ty.kind() { - if fcx + if let ty::RawPtr(TypeAndMut { ty: expr_ty, .. }) = *self.expr_ty.kind() + && fcx .try_coerce( self.expr, fcx.tcx.mk_ref( @@ -386,27 +386,25 @@ impl<'a, 'tcx> CastCheck<'tcx> { None, ) .is_ok() - { - sugg = Some((format!("&{}*", mutbl.prefix_str()), cast_ty == expr_ty)); - } - } else if let ty::Ref(expr_reg, expr_ty, expr_mutbl) = *self.expr_ty.kind() { - if expr_mutbl == Mutability::Not - && mutbl == Mutability::Mut - && fcx - .try_coerce( - self.expr, - fcx.tcx.mk_ref( - expr_reg, - TypeAndMut { ty: expr_ty, mutbl: Mutability::Mut }, - ), - self.cast_ty, - AllowTwoPhase::No, - None, - ) - .is_ok() - { - sugg_mutref = true; - } + { + sugg = Some((format!("&{}*", mutbl.prefix_str()), cast_ty == expr_ty)); + } else if let ty::Ref(expr_reg, expr_ty, expr_mutbl) = *self.expr_ty.kind() + && expr_mutbl == Mutability::Not + && mutbl == Mutability::Mut + && fcx + .try_coerce( + self.expr, + fcx.tcx.mk_ref( + expr_reg, + TypeAndMut { ty: expr_ty, mutbl: Mutability::Mut }, + ), + self.cast_ty, + AllowTwoPhase::No, + None, + ) + .is_ok() + { + sugg_mutref = true; } if !sugg_mutref @@ -423,8 +421,8 @@ impl<'a, 'tcx> CastCheck<'tcx> { { sugg = Some((format!("&{}", mutbl.prefix_str()), false)); } - } else if let ty::RawPtr(TypeAndMut { mutbl, .. }) = *self.cast_ty.kind() { - if fcx + } else if let ty::RawPtr(TypeAndMut { mutbl, .. }) = *self.cast_ty.kind() + && fcx .try_coerce( self.expr, fcx.tcx.mk_ref( @@ -436,9 +434,8 @@ impl<'a, 'tcx> CastCheck<'tcx> { None, ) .is_ok() - { - sugg = Some((format!("&{}", mutbl.prefix_str()), false)); - } + { + sugg = Some((format!("&{}", mutbl.prefix_str()), false)); } if sugg_mutref { err.span_label(self.span, "invalid cast"); @@ -483,28 +480,28 @@ impl<'a, 'tcx> CastCheck<'tcx> { ) { let mut label = true; // Check `impl From for self.cast_ty {}` for accurate suggestion: - if let Ok(snippet) = fcx.tcx.sess.source_map().span_to_snippet(self.expr_span) { - if let Some(from_trait) = fcx.tcx.get_diagnostic_item(sym::From) { - let ty = fcx.resolve_vars_if_possible(self.cast_ty); - // Erase regions to avoid panic in `prove_value` when calling - // `type_implements_trait`. - let ty = fcx.tcx.erase_regions(ty); - let expr_ty = fcx.resolve_vars_if_possible(self.expr_ty); - let expr_ty = fcx.tcx.erase_regions(expr_ty); - let ty_params = fcx.tcx.mk_substs_trait(expr_ty, &[]); - if fcx - .infcx - .type_implements_trait(from_trait, ty, ty_params, fcx.param_env) - .must_apply_modulo_regions() - { - label = false; - err.span_suggestion( - self.span, - "consider using the `From` trait instead", - format!("{}::from({})", self.cast_ty, snippet), - Applicability::MaybeIncorrect, - ); - } + if let Ok(snippet) = fcx.tcx.sess.source_map().span_to_snippet(self.expr_span) + && let Some(from_trait) = fcx.tcx.get_diagnostic_item(sym::From) + { + let ty = fcx.resolve_vars_if_possible(self.cast_ty); + // Erase regions to avoid panic in `prove_value` when calling + // `type_implements_trait`. + let ty = fcx.tcx.erase_regions(ty); + let expr_ty = fcx.resolve_vars_if_possible(self.expr_ty); + let expr_ty = fcx.tcx.erase_regions(expr_ty); + let ty_params = fcx.tcx.mk_substs_trait(expr_ty, &[]); + if fcx + .infcx + .type_implements_trait(from_trait, ty, ty_params, fcx.param_env) + .must_apply_modulo_regions() + { + label = false; + err.span_suggestion( + self.span, + "consider using the `From` trait instead", + format!("{}::from({})", self.cast_ty, snippet), + Applicability::MaybeIncorrect, + ); } } let msg = "an `as` expression can only be used to convert between primitive \ @@ -627,10 +624,8 @@ impl<'a, 'tcx> CastCheck<'tcx> { } } } else { - let msg = &format!( - "consider using an implicit coercion to `&{}{}` instead", - mtstr, tstr - ); + let msg = + &format!("consider using an implicit coercion to `&{mtstr}{tstr}` instead"); err.span_help(self.span, msg); } } @@ -640,14 +635,14 @@ impl<'a, 'tcx> CastCheck<'tcx> { err.span_suggestion( self.cast_span, "you can cast to a `Box` instead", - format!("Box<{}>", s), + format!("Box<{s}>"), Applicability::MachineApplicable, ); } Err(_) => { err.span_help( self.cast_span, - &format!("you might have meant `Box<{}>`", tstr), + &format!("you might have meant `Box<{tstr}>`"), ); } } @@ -678,8 +673,7 @@ impl<'a, 'tcx> CastCheck<'tcx> { )) .help(&format!( "cast can be replaced by coercion; this might \ - require {}a temporary variable", - type_asc_or + require {type_asc_or}a temporary variable" )) .emit(); }); @@ -969,21 +963,21 @@ impl<'a, 'tcx> CastCheck<'tcx> { } fn cenum_impl_drop_lint(&self, fcx: &FnCtxt<'a, 'tcx>) { - if let ty::Adt(d, _) = self.expr_ty.kind() { - if d.has_dtor(fcx.tcx) { - fcx.tcx.struct_span_lint_hir( - lint::builtin::CENUM_IMPL_DROP_CAST, - self.expr.hir_id, - self.span, - |err| { - err.build(&format!( - "cannot cast enum `{}` into integer `{}` because it implements `Drop`", - self.expr_ty, self.cast_ty - )) - .emit(); - }, - ); - } + if let ty::Adt(d, _) = self.expr_ty.kind() + && d.has_dtor(fcx.tcx) + { + fcx.tcx.struct_span_lint_hir( + lint::builtin::CENUM_IMPL_DROP_CAST, + self.expr.hir_id, + self.span, + |err| { + err.build(&format!( + "cannot cast enum `{}` into integer `{}` because it implements `Drop`", + self.expr_ty, self.cast_ty + )) + .emit(); + }, + ); } } @@ -1007,7 +1001,7 @@ impl<'a, 'tcx> CastCheck<'tcx> { err.span_suggestion( self.span, msg, - format!("({}).addr(){}", snippet, scalar_cast), + format!("({snippet}).addr(){scalar_cast}"), Applicability::MaybeIncorrect ); } else { @@ -1038,7 +1032,7 @@ impl<'a, 'tcx> CastCheck<'tcx> { err.span_suggestion( self.span, msg, - format!("(...).with_addr({})", snippet), + format!("(...).with_addr({snippet})"), Applicability::HasPlaceholders, ); } else { diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs index 1841451580f48..314236b1cdfbc 100644 --- a/compiler/rustc_typeck/src/check/check.rs +++ b/compiler/rustc_typeck/src/check/check.rs @@ -43,8 +43,7 @@ pub(super) fn check_abi(tcx: TyCtxt<'_>, hir_id: hir::HirId, span: Span, abi: Ab tcx.sess, span, E0570, - "`{}` is not a supported ABI for the current target", - abi + "`{abi}` is not a supported ABI for the current target", ) .emit(); } @@ -249,84 +248,84 @@ pub(super) fn check_fn<'a, 'tcx>( fcx.demand_suptype(span, declared_ret_ty, actual_return_ty); // Check that a function marked as `#[panic_handler]` has signature `fn(&PanicInfo) -> !` - if let Some(panic_impl_did) = tcx.lang_items().panic_impl() { - if panic_impl_did == hir.local_def_id(fn_id).to_def_id() { - if let Some(panic_info_did) = tcx.lang_items().panic_info() { - if *declared_ret_ty.kind() != ty::Never { - sess.span_err(decl.output.span(), "return type should be `!`"); - } + if let Some(panic_impl_did) = tcx.lang_items().panic_impl() + && panic_impl_did == hir.local_def_id(fn_id).to_def_id() + { + if let Some(panic_info_did) = tcx.lang_items().panic_info() { + if *declared_ret_ty.kind() != ty::Never { + sess.span_err(decl.output.span(), "return type should be `!`"); + } - let inputs = fn_sig.inputs(); - let span = hir.span(fn_id); - if inputs.len() == 1 { - let arg_is_panic_info = match *inputs[0].kind() { - ty::Ref(region, ty, mutbl) => match *ty.kind() { - ty::Adt(ref adt, _) => { - adt.did() == panic_info_did - && mutbl == hir::Mutability::Not - && !region.is_static() - } - _ => false, - }, + let inputs = fn_sig.inputs(); + let span = hir.span(fn_id); + if inputs.len() == 1 { + let arg_is_panic_info = match *inputs[0].kind() { + ty::Ref(region, ty, mutbl) => match *ty.kind() { + ty::Adt(ref adt, _) => { + adt.did() == panic_info_did + && mutbl == hir::Mutability::Not + && !region.is_static() + } _ => false, - }; - - if !arg_is_panic_info { - sess.span_err(decl.inputs[0].span, "argument should be `&PanicInfo`"); - } + }, + _ => false, + }; - if let Node::Item(item) = hir.get(fn_id) - && let ItemKind::Fn(_, ref generics, _) = item.kind - && !generics.params.is_empty() - { - sess.span_err(span, "should have no type parameters"); - } - } else { - let span = sess.source_map().guess_head_span(span); - sess.span_err(span, "function should have one argument"); + if !arg_is_panic_info { + sess.span_err(decl.inputs[0].span, "argument should be `&PanicInfo`"); } + + if let Node::Item(item) = hir.get(fn_id) + && let ItemKind::Fn(_, ref generics, _) = item.kind + && !generics.params.is_empty() + { + sess.span_err(span, "should have no type parameters"); + } } else { - sess.err("language item required, but not found: `panic_info`"); + let span = sess.source_map().guess_head_span(span); + sess.span_err(span, "function should have one argument"); } + } else { + sess.err("language item required, but not found: `panic_info`"); } } // Check that a function marked as `#[alloc_error_handler]` has signature `fn(Layout) -> !` - if let Some(alloc_error_handler_did) = tcx.lang_items().oom() { - if alloc_error_handler_did == hir.local_def_id(fn_id).to_def_id() { - if let Some(alloc_layout_did) = tcx.lang_items().alloc_layout() { - if *declared_ret_ty.kind() != ty::Never { - sess.span_err(decl.output.span(), "return type should be `!`"); - } - - let inputs = fn_sig.inputs(); - let span = hir.span(fn_id); - if inputs.len() == 1 { - let arg_is_alloc_layout = match inputs[0].kind() { - ty::Adt(ref adt, _) => adt.did() == alloc_layout_did, - _ => false, - }; + if let Some(alloc_error_handler_did) = tcx.lang_items().oom() + && alloc_error_handler_did == hir.local_def_id(fn_id).to_def_id() + { + if let Some(alloc_layout_did) = tcx.lang_items().alloc_layout() { + if *declared_ret_ty.kind() != ty::Never { + sess.span_err(decl.output.span(), "return type should be `!`"); + } - if !arg_is_alloc_layout { - sess.span_err(decl.inputs[0].span, "argument should be `Layout`"); - } + let inputs = fn_sig.inputs(); + let span = hir.span(fn_id); + if inputs.len() == 1 { + let arg_is_alloc_layout = match inputs[0].kind() { + ty::Adt(ref adt, _) => adt.did() == alloc_layout_did, + _ => false, + }; - if let Node::Item(item) = hir.get(fn_id) - && let ItemKind::Fn(_, ref generics, _) = item.kind - && !generics.params.is_empty() - { - sess.span_err( - span, - "`#[alloc_error_handler]` function should have no type parameters", - ); - } - } else { - let span = sess.source_map().guess_head_span(span); - sess.span_err(span, "function should have one argument"); + if !arg_is_alloc_layout { + sess.span_err(decl.inputs[0].span, "argument should be `Layout`"); } + + if let Node::Item(item) = hir.get(fn_id) + && let ItemKind::Fn(_, ref generics, _) = item.kind + && !generics.params.is_empty() + { + sess.span_err( + span, + "`#[alloc_error_handler]` function should have no type parameters", + ); + } } else { - sess.err("language item required, but not found: `alloc_layout`"); + let span = sess.source_map().guess_head_span(span); + sess.span_err(span, "function should have one argument"); } + } else { + sess.err("language item required, but not found: `alloc_layout`"); } } @@ -670,7 +669,7 @@ fn check_opaque_meets_bounds<'tcx>( Err(ty_err) => { tcx.sess.delay_span_bug( span, - &format!("could not unify `{}` with revealed type:\n{}", hidden_type, ty_err,), + &format!("could not unify `{hidden_type}` with revealed type:\n{ty_err}"), ); } } @@ -817,10 +816,9 @@ pub fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, it: &'tcx hir::Item<'tcx>) { tcx.sess, item.span, E0044, - "foreign items may not have {} parameters", - kinds, + "foreign items may not have {kinds} parameters", ) - .span_label(item.span, &format!("can't have {} parameters", kinds)) + .span_label(item.span, &format!("can't have {kinds} parameters")) .help( // FIXME: once we start storing spans for type arguments, turn this // into a suggestion. @@ -1065,68 +1063,67 @@ pub(super) fn check_representable(tcx: TyCtxt<'_>, sp: Span, item_def_id: LocalD pub fn check_simd(tcx: TyCtxt<'_>, sp: Span, def_id: LocalDefId) { let t = tcx.type_of(def_id); - if let ty::Adt(def, substs) = t.kind() { - if def.is_struct() { - let fields = &def.non_enum_variant().fields; - if fields.is_empty() { + if let ty::Adt(def, substs) = t.kind() + && def.is_struct() + { + let fields = &def.non_enum_variant().fields; + if fields.is_empty() { + struct_span_err!(tcx.sess, sp, E0075, "SIMD vector cannot be empty").emit(); + return; + } + let e = fields[0].ty(tcx, substs); + if !fields.iter().all(|f| f.ty(tcx, substs) == e) { + struct_span_err!(tcx.sess, sp, E0076, "SIMD vector should be homogeneous") + .span_label(sp, "SIMD elements must have the same type") + .emit(); + return; + } + + let len = if let ty::Array(_ty, c) = e.kind() { + c.try_eval_usize(tcx, tcx.param_env(def.did())) + } else { + Some(fields.len() as u64) + }; + if let Some(len) = len { + if len == 0 { struct_span_err!(tcx.sess, sp, E0075, "SIMD vector cannot be empty").emit(); return; - } - let e = fields[0].ty(tcx, substs); - if !fields.iter().all(|f| f.ty(tcx, substs) == e) { - struct_span_err!(tcx.sess, sp, E0076, "SIMD vector should be homogeneous") - .span_label(sp, "SIMD elements must have the same type") - .emit(); + } else if len > MAX_SIMD_LANES { + struct_span_err!( + tcx.sess, + sp, + E0075, + "SIMD vector cannot have more than {MAX_SIMD_LANES} elements", + ) + .emit(); return; } + } - let len = if let ty::Array(_ty, c) = e.kind() { - c.try_eval_usize(tcx, tcx.param_env(def.did())) - } else { - Some(fields.len() as u64) - }; - if let Some(len) = len { - if len == 0 { - struct_span_err!(tcx.sess, sp, E0075, "SIMD vector cannot be empty").emit(); - return; - } else if len > MAX_SIMD_LANES { - struct_span_err!( - tcx.sess, - sp, - E0075, - "SIMD vector cannot have more than {} elements", - MAX_SIMD_LANES, - ) - .emit(); - return; - } - } - - // Check that we use types valid for use in the lanes of a SIMD "vector register" - // These are scalar types which directly match a "machine" type - // Yes: Integers, floats, "thin" pointers - // No: char, "fat" pointers, compound types - match e.kind() { - ty::Param(_) => (), // pass struct(T, T, T, T) through, let monomorphization catch errors - ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::RawPtr(_) => (), // struct(u8, u8, u8, u8) is ok - ty::Array(t, _) if matches!(t.kind(), ty::Param(_)) => (), // pass struct([T; N]) through, let monomorphization catch errors - ty::Array(t, _clen) - if matches!( - t.kind(), - ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::RawPtr(_) - ) => - { /* struct([f32; 4]) is ok */ } - _ => { - struct_span_err!( - tcx.sess, - sp, - E0077, - "SIMD vector element type should be a \ - primitive scalar (integer/float/pointer) type" - ) - .emit(); - return; - } + // Check that we use types valid for use in the lanes of a SIMD "vector register" + // These are scalar types which directly match a "machine" type + // Yes: Integers, floats, "thin" pointers + // No: char, "fat" pointers, compound types + match e.kind() { + ty::Param(_) => (), // pass struct(T, T, T, T) through, let monomorphization catch errors + ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::RawPtr(_) => (), // struct(u8, u8, u8, u8) is ok + ty::Array(t, _) if matches!(t.kind(), ty::Param(_)) => (), // pass struct([T; N]) through, let monomorphization catch errors + ty::Array(t, _clen) + if matches!( + t.kind(), + ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::RawPtr(_) + ) => + { /* struct([f32; 4]) is ok */ } + _ => { + struct_span_err!( + tcx.sess, + sp, + E0077, + "SIMD vector element type should be a \ + primitive scalar (integer/float/pointer) type" + ) + .emit(); + return; } } } @@ -1189,7 +1186,7 @@ pub(super) fn check_packed(tcx: TyCtxt<'_>, sp: Span, def: ty::AdtDef<'_>) { ident ) } else { - format!("...which contains a field of type `{}`", ident) + format!("...which contains a field of type `{ident}`") }, ); first = false; @@ -1215,13 +1212,12 @@ pub(super) fn check_packed_inner( stack.push(def_id); for field in &def.non_enum_variant().fields { - if let ty::Adt(def, _) = field.ty(tcx, substs).kind() { - if !stack.contains(&def.did()) { - if let Some(mut defs) = check_packed_inner(tcx, def.did(), stack) { - defs.push((def.did(), field.ident(tcx).span)); - return Some(defs); - } - } + if let ty::Adt(def, _) = field.ty(tcx, substs).kind() + && !stack.contains(&def.did()) + && let Some(mut defs) = check_packed_inner(tcx, def.did(), stack) + { + defs.push((def.did(), field.ident(tcx).span)); + return Some(defs); } } stack.pop(); @@ -1370,8 +1366,8 @@ fn check_enum<'tcx>( "discriminant value `{}` already exists", discr.val, ) - .span_label(i_span, format!("first use of {}", display_discr_i)) - .span_label(span, format!("enum already has {}", display_discr)) + .span_label(i_span, format!("first use of {display_discr_i}")) + .span_label(span, format!("enum already has {display_discr}")) .emit(); } disr_vals.push(discr); @@ -1393,7 +1389,7 @@ fn display_discriminant_value<'tcx>( && let rustc_ast::LitKind::Int(lit_value, _int_kind) = &lit.node && evaluated != *lit_value { - return format!("`{}` (overflowed from `{}`)", evaluated, lit_value); + return format!("`{evaluated}` (overflowed from `{lit_value}`)"); } } format!("`{}`", evaluated) @@ -1422,28 +1418,28 @@ pub(super) fn check_type_params_are_used<'tcx>( } for leaf in ty.walk() { - if let GenericArgKind::Type(leaf_ty) = leaf.unpack() { - if let ty::Param(param) = leaf_ty.kind() { - debug!("found use of ty param {:?}", param); - params_used.insert(param.index); - } + if let GenericArgKind::Type(leaf_ty) = leaf.unpack() + && let ty::Param(param) = leaf_ty.kind() + { + debug!("found use of ty param {:?}", param); + params_used.insert(param.index); } } for param in &generics.params { - if !params_used.contains(param.index) { - if let ty::GenericParamDefKind::Type { .. } = param.kind { - let span = tcx.def_span(param.def_id); - struct_span_err!( - tcx.sess, - span, - E0091, - "type parameter `{}` is unused", - param.name, - ) - .span_label(span, "unused type parameter") - .emit(); - } + if !params_used.contains(param.index) + && let ty::GenericParamDefKind::Type { .. } = param.kind + { + let span = tcx.def_span(param.def_id); + struct_span_err!( + tcx.sess, + span, + E0091, + "type parameter `{}` is unused", + param.name, + ) + .span_label(span, "unused type parameter") + .emit(); } } } @@ -1534,10 +1530,10 @@ fn opaque_type_cycle_error(tcx: TyCtxt<'_>, def_id: LocalDefId, span: Span) -> E for def_id in visitor.0 { let ty_span = tcx.def_span(def_id); if !seen.contains(&ty_span) { - err.span_label(ty_span, &format!("returning this opaque type `{}`", ty)); + err.span_label(ty_span, &format!("returning this opaque type `{ty}`")); seen.insert(ty_span); } - err.span_label(sp, &format!("returning here with type `{}`", ty)); + err.span_label(sp, &format!("returning here with type `{ty}`")); } } } diff --git a/compiler/rustc_typeck/src/check/coercion.rs b/compiler/rustc_typeck/src/check/coercion.rs index 34fc177de6de0..3162de38aaea1 100644 --- a/compiler/rustc_typeck/src/check/coercion.rs +++ b/compiler/rustc_typeck/src/check/coercion.rs @@ -632,11 +632,10 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { let unsize_ty = trait_pred.trait_ref.substs[1].expect_ty(); if let (ty::Dynamic(ref data_a, ..), ty::Dynamic(ref data_b, ..)) = (self_ty.kind(), unsize_ty.kind()) + && data_a.principal_def_id() != data_b.principal_def_id() { - if data_a.principal_def_id() != data_b.principal_def_id() { - debug!("coerce_unsized: found trait upcasting coercion"); - has_trait_upcasting_coercion = true; - } + debug!("coerce_unsized: found trait upcasting coercion"); + has_trait_upcasting_coercion = true; } if let ty::Tuple(..) = unsize_ty.kind() { debug!("coerce_unsized: found unsized tuple coercion"); @@ -732,13 +731,12 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { F: FnOnce(Ty<'tcx>) -> Vec>, G: FnOnce(Ty<'tcx>) -> Vec>, { - if let ty::FnPtr(fn_ty_b) = b.kind() { - if let (hir::Unsafety::Normal, hir::Unsafety::Unsafe) = + if let ty::FnPtr(fn_ty_b) = b.kind() + && let (hir::Unsafety::Normal, hir::Unsafety::Unsafe) = (fn_ty_a.unsafety(), fn_ty_b.unsafety()) - { - let unsafe_a = self.tcx.safe_to_unsafe_fn_ty(fn_ty_a); - return self.unify_and(unsafe_a, b, to_unsafe); - } + { + let unsafe_a = self.tcx.safe_to_unsafe_fn_ty(fn_ty_a); + return self.unify_and(unsafe_a, b, to_unsafe); } self.unify_and(a, b, normal) } @@ -783,12 +781,11 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { } // Safe `#[target_feature]` functions are not assignable to safe fn pointers (RFC 2396). - if let ty::FnDef(def_id, _) = *a.kind() { - if b_sig.unsafety() == hir::Unsafety::Normal - && !self.tcx.codegen_fn_attrs(def_id).target_features.is_empty() - { - return Err(TypeError::TargetFeatureCast(def_id)); - } + if let ty::FnDef(def_id, _) = *a.kind() + && b_sig.unsafety() == hir::Unsafety::Normal + && !self.tcx.codegen_fn_attrs(def_id).target_features.is_empty() + { + return Err(TypeError::TargetFeatureCast(def_id)); } let InferOk { value: a_sig, obligations: o1 } = @@ -1540,11 +1537,11 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { fcx.tcx.hir().get_if_cause(expr.hir_id), expected.is_unit(), pointing_at_return_type, - ) { + ) // If the block is from an external macro or try (`?`) desugaring, then // do not suggest adding a semicolon, because there's nowhere to put it. // See issues #81943 and #87051. - if matches!( + && matches!( cond_expr.span.desugaring_kind(), None | Some(DesugaringKind::WhileLoop) ) && !in_external_macro(fcx.tcx.sess, cond_expr.span) @@ -1552,11 +1549,10 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { cond_expr.kind, hir::ExprKind::Match(.., hir::MatchSource::TryDesugar) ) - { - err.span_label(cond_expr.span, "expected this to be `()`"); - if expr.can_have_side_effects() { - fcx.suggest_semicolon_at_end(cond_expr.span, &mut err); - } + { + err.span_label(cond_expr.span, "expected this to be `()`"); + if expr.can_have_side_effects() { + fcx.suggest_semicolon_at_end(cond_expr.span, &mut err); } } fcx.get_node_fn_decl(parent).map(|(fn_decl, _, is_main)| (fn_decl, is_main)) @@ -1636,28 +1632,27 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { let has_impl = snippet_iter.next().map_or(false, |s| s == "impl"); // Only suggest `Box` if `Trait` in `impl Trait` is object safe. let mut is_object_safe = false; - if let hir::FnRetTy::Return(ty) = fn_output { + if let hir::FnRetTy::Return(ty) = fn_output // Get the return type. - if let hir::TyKind::OpaqueDef(..) = ty.kind { - let ty = >::ast_ty_to_ty(fcx, ty); - // Get the `impl Trait`'s `DefId`. - if let ty::Opaque(def_id, _) = ty.kind() { - // Get the `impl Trait`'s `Item` so that we can get its trait bounds and - // get the `Trait`'s `DefId`. - if let hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds, .. }) = - fcx.tcx.hir().expect_item(def_id.expect_local()).kind - { - // Are of this `impl Trait`'s traits object safe? - is_object_safe = bounds.iter().all(|bound| { - bound - .trait_ref() - .and_then(|t| t.trait_def_id()) - .map_or(false, |def_id| { - fcx.tcx.object_safety_violations(def_id).is_empty() - }) + && let hir::TyKind::OpaqueDef(..) = ty.kind + { + let ty = >::ast_ty_to_ty(fcx, ty); + // Get the `impl Trait`'s `DefId`. + if let ty::Opaque(def_id, _) = ty.kind() + // Get the `impl Trait`'s `Item` so that we can get its trait bounds and + // get the `Trait`'s `DefId`. + && let hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds, .. }) = + fcx.tcx.hir().expect_item(def_id.expect_local()).kind + { + // Are of this `impl Trait`'s traits object safe? + is_object_safe = bounds.iter().all(|bound| { + bound + .trait_ref() + .and_then(|t| t.trait_def_id()) + .map_or(false, |def_id| { + fcx.tcx.object_safety_violations(def_id).is_empty() }) - } - } + }) } }; if has_impl { @@ -1703,7 +1698,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { && let ty = >::ast_ty_to_ty(fcx, ty) && let ty::Dynamic(..) = ty.kind() { - return true; + return true; } false } diff --git a/compiler/rustc_typeck/src/check/compare_method.rs b/compiler/rustc_typeck/src/check/compare_method.rs index 0bd5e018f4a38..4aa46c21fce91 100644 --- a/compiler/rustc_typeck/src/check/compare_method.rs +++ b/compiler/rustc_typeck/src/check/compare_method.rs @@ -315,7 +315,7 @@ fn compare_predicate_entailment<'tcx>( ExplicitSelf::ByReference(_, hir::Mutability::Mut) => { "&mut self".to_owned() } - _ => format!("self: {}", ty), + _ => format!("self: {ty}"), }; // When the `impl` receiver is an arbitrary self type, like `self: Box`, the @@ -526,7 +526,7 @@ fn compare_self_type<'tcx>( ExplicitSelf::ByValue => "self".to_owned(), ExplicitSelf::ByReference(_, hir::Mutability::Not) => "&self".to_owned(), ExplicitSelf::ByReference(_, hir::Mutability::Mut) => "&mut self".to_owned(), - _ => format!("self: {}", self_arg_ty), + _ => format!("self: {self_arg_ty}"), } }) }; @@ -544,9 +544,9 @@ fn compare_self_type<'tcx>( trait_m.name, self_descr ); - err.span_label(impl_m_span, format!("`{}` used in impl", self_descr)); + err.span_label(impl_m_span, format!("`{self_descr}` used in impl")); if let Some(span) = tcx.hir().span_if_local(trait_m.def_id) { - err.span_label(span, format!("trait method declared without `{}`", self_descr)); + err.span_label(span, format!("trait method declared without `{self_descr}`")); } else { err.note_trait_signature(trait_m.name.to_string(), trait_m.signature(tcx)); } @@ -564,9 +564,9 @@ fn compare_self_type<'tcx>( trait_m.name, self_descr ); - err.span_label(impl_m_span, format!("expected `{}` in impl", self_descr)); + err.span_label(impl_m_span, format!("expected `{self_descr}` in impl")); if let Some(span) = tcx.hir().span_if_local(trait_m.def_id) { - err.span_label(span, format!("`{}` used in trait", self_descr)); + err.span_label(span, format!("`{self_descr}` used in trait")); } else { err.note_trait_signature(trait_m.name.to_string(), trait_m.signature(tcx)); } @@ -668,7 +668,7 @@ fn compare_number_of_generics<'tcx>( err.span_label(*span, ""); } } else { - suffix = Some(format!(", expected {}", trait_count)); + suffix = Some(format!(", expected {trait_count}")); } if let Some(span) = span { @@ -873,12 +873,10 @@ fn compare_synthetic_generics<'tcx>( intravisit::walk_ty(self, ty); if let hir::TyKind::Path(hir::QPath::Resolved(None, ref path)) = ty.kind + && let Res::Def(DefKind::TyParam, def_id) = path.res + && def_id == self.1 { - if let Res::Def(DefKind::TyParam, def_id) = path.res { - if def_id == self.1 { - self.0 = Some(ty.span); - } - } + self.0 = Some(ty.span); } } } @@ -908,7 +906,7 @@ fn compare_synthetic_generics<'tcx>( // delete generic parameters (impl_m.generics.span, String::new()), // replace param usage with `impl Trait` - (span, format!("impl {}", bounds)), + (span, format!("impl {bounds}")), ], Applicability::MaybeIncorrect, ); @@ -972,7 +970,7 @@ fn compare_const_param_types<'tcx>( &format!( "the const parameter{} has type `{}`, but the declaration \ in trait `{}` has type `{}`", - &impl_ident.map_or_else(|| "".to_string(), |ident| format!(" `{}`", ident)), + &impl_ident.map_or_else(|| "".to_string(), |ident| format!(" `{ident}`")), impl_ty, tcx.def_path_str(trait_m.def_id), trait_ty diff --git a/compiler/rustc_typeck/src/check/demand.rs b/compiler/rustc_typeck/src/check/demand.rs index 83e535b3c3247..7c5a312c40e62 100644 --- a/compiler/rustc_typeck/src/check/demand.rs +++ b/compiler/rustc_typeck/src/check/demand.rs @@ -241,13 +241,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // We are pointing at the binding's type or initializer value, but it's pattern // is in a different line, so we point at both. err.span_label(secondary_span, "expected due to the type of this binding"); - err.span_label(primary_span, &format!("expected due to this{}", post_message)); + err.span_label(primary_span, &format!("expected due to this{post_message}")); } else if post_message == "" { // We are pointing at either the assignment lhs or the binding def pattern. err.span_label(primary_span, "expected due to the type of this binding"); } else { // We are pointing at the binding's type or initializer value. - err.span_label(primary_span, &format!("expected due to this{}", post_message)); + err.span_label(primary_span, &format!("expected due to this{post_message}")); } if !lhs.is_syntactic_place_expr() { @@ -321,7 +321,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { "try adding an expression at the end of the block", return_suggestions .into_iter() - .map(|r| format!("{}\n{}{}", semicolon, indent, r)), + .map(|r| format!("{semicolon}\n{indent}{r}")), Applicability::MaybeIncorrect, ); } @@ -344,10 +344,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let variant_path = 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("::") { - return Some(path.to_string()); - } + if let Some(path) = variant_path.strip_prefix("std::prelude::") + && let Some((_, path)) = path.split_once("::") + { + return Some(path.to_string()); } Some(variant_path) } else { @@ -357,7 +357,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .collect(); let prefix = match self.maybe_get_struct_pattern_shorthand_field(expr) { - Some(ident) => format!("{}: ", ident), + Some(ident) => format!("{ident}: "), None => String::new(), }; @@ -366,9 +366,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { [variant] => { // Just a single matching variant. err.multipart_suggestion_verbose( - &format!("try wrapping the expression in `{}`", variant), + &format!("try wrapping the expression in `{variant}`"), vec![ - (expr.span.shrink_to_lo(), format!("{}{}(", prefix, variant)), + (expr.span.shrink_to_lo(), format!("{prefix}{variant}(")), (expr.span.shrink_to_hi(), ")".to_string()), ], Applicability::MaybeIncorrect, @@ -383,7 +383,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ), compatible_variants.into_iter().map(|variant| { vec![ - (expr.span.shrink_to_lo(), format!("{}{}(", prefix, variant)), + (expr.span.shrink_to_lo(), format!("{prefix}{variant}(")), (expr.span.shrink_to_hi(), ")".to_string()), ] }), @@ -680,7 +680,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { _ if is_range_literal(expr) => true, _ => false, }; - let sugg_expr = if needs_parens { format!("({})", src) } else { src }; + let sugg_expr = if needs_parens { format!("({src})") } else { src }; if let Some(sugg) = self.can_use_as_ref(expr) { return Some(( @@ -693,7 +693,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } let prefix = match self.maybe_get_struct_pattern_shorthand_field(expr) { - Some(ident) => format!("{}: ", ident), + Some(ident) => format!("{ident}: "), None => String::new(), }; @@ -727,14 +727,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { hir::Mutability::Mut => ( sp, "consider mutably borrowing here".to_string(), - format!("{}&mut {}", prefix, sugg_expr), + format!("{prefix}&mut {sugg_expr}"), Applicability::MachineApplicable, false, ), hir::Mutability::Not => ( sp, "consider borrowing here".to_string(), - format!("{}&{}", prefix, sugg_expr), + format!("{prefix}&{sugg_expr}"), Applicability::MachineApplicable, false, ), @@ -758,29 +758,28 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let Some(call_span) = iter::successors(Some(expr.span), |s| s.parent_callsite()) .find(|&s| sp.contains(s)) + && sm.span_to_snippet(call_span).is_ok() { - if sm.span_to_snippet(call_span).is_ok() { - return Some(( - sp.with_hi(call_span.lo()), - "consider removing the borrow".to_string(), - String::new(), - Applicability::MachineApplicable, - true, - )); - } - } - return None; - } - if sp.contains(expr.span) { - if sm.span_to_snippet(expr.span).is_ok() { return Some(( - sp.with_hi(expr.span.lo()), + sp.with_hi(call_span.lo()), "consider removing the borrow".to_string(), String::new(), Applicability::MachineApplicable, true, )); } + return None; + } + if sp.contains(expr.span) + && sm.span_to_snippet(expr.span).is_ok() + { + return Some(( + sp.with_hi(expr.span.lo()), + "consider removing the borrow".to_string(), + String::new(), + Applicability::MachineApplicable, + true, + )); } } ( @@ -788,66 +787,65 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &ty::RawPtr(TypeAndMut { ty: ty_b, mutbl: mutbl_b }), &ty::Ref(_, ty_a, mutbl_a), ) => { - if let Some(steps) = self.deref_steps(ty_a, ty_b) { + if let Some(steps) = self.deref_steps(ty_a, ty_b) // Only suggest valid if dereferencing needed. - if steps > 0 { - // The pointer type implements `Copy` trait so the suggestion is always valid. - if let Ok(src) = sm.span_to_snippet(sp) { - let derefs = "*".repeat(steps); - if let Some((span, src, applicability)) = match mutbl_b { + && steps > 0 + // The pointer type implements `Copy` trait so the suggestion is always valid. + && let Ok(src) = sm.span_to_snippet(sp) + { + let derefs = "*".repeat(steps); + if let Some((span, src, applicability)) = match mutbl_b { + hir::Mutability::Mut => { + let new_prefix = "&mut ".to_owned() + &derefs; + match mutbl_a { hir::Mutability::Mut => { - let new_prefix = "&mut ".to_owned() + &derefs; - match mutbl_a { - hir::Mutability::Mut => { - replace_prefix(&src, "&mut ", &new_prefix).map(|_| { - let pos = sp.lo() + BytePos(5); - let sp = sp.with_lo(pos).with_hi(pos); - (sp, derefs, Applicability::MachineApplicable) - }) - } - hir::Mutability::Not => { - replace_prefix(&src, "&", &new_prefix).map(|_| { - let pos = sp.lo() + BytePos(1); - let sp = sp.with_lo(pos).with_hi(pos); - ( - sp, - format!("mut {}", derefs), - Applicability::Unspecified, - ) - }) - } - } + replace_prefix(&src, "&mut ", &new_prefix).map(|_| { + let pos = sp.lo() + BytePos(5); + let sp = sp.with_lo(pos).with_hi(pos); + (sp, derefs, Applicability::MachineApplicable) + }) } hir::Mutability::Not => { - let new_prefix = "&".to_owned() + &derefs; - match mutbl_a { - hir::Mutability::Mut => { - replace_prefix(&src, "&mut ", &new_prefix).map(|_| { - let lo = sp.lo() + BytePos(1); - let hi = sp.lo() + BytePos(5); - let sp = sp.with_lo(lo).with_hi(hi); - (sp, derefs, Applicability::MachineApplicable) - }) - } - hir::Mutability::Not => { - replace_prefix(&src, "&", &new_prefix).map(|_| { - let pos = sp.lo() + BytePos(1); - let sp = sp.with_lo(pos).with_hi(pos); - (sp, derefs, Applicability::MachineApplicable) - }) - } - } + replace_prefix(&src, "&", &new_prefix).map(|_| { + let pos = sp.lo() + BytePos(1); + let sp = sp.with_lo(pos).with_hi(pos); + ( + sp, + format!("mut {derefs}"), + Applicability::Unspecified, + ) + }) } - } { - return Some(( - span, - "consider dereferencing".to_string(), - src, - applicability, - true, - )); } } + hir::Mutability::Not => { + let new_prefix = "&".to_owned() + &derefs; + match mutbl_a { + hir::Mutability::Mut => { + replace_prefix(&src, "&mut ", &new_prefix).map(|_| { + let lo = sp.lo() + BytePos(1); + let hi = sp.lo() + BytePos(5); + let sp = sp.with_lo(lo).with_hi(hi); + (sp, derefs, Applicability::MachineApplicable) + }) + } + hir::Mutability::Not => { + replace_prefix(&src, "&", &new_prefix).map(|_| { + let pos = sp.lo() + BytePos(1); + let sp = sp.with_lo(pos).with_hi(pos); + (sp, derefs, Applicability::MachineApplicable) + }) + } + } + } + } { + return Some(( + span, + "consider dereferencing".to_string(), + src, + applicability, + true, + )); } } } @@ -908,7 +906,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Suggest removing `&` if we have removed any, otherwise suggest just // dereferencing the remaining number of steps. let message = if remove.is_empty() { - format!("consider {}", deref_kind) + format!("consider {deref_kind}") } else { format!( "consider removing the `{}` and {} instead", @@ -918,7 +916,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; let prefix = match self.maybe_get_struct_pattern_shorthand_field(expr) { - Some(ident) => format!("{}: ", ident), + Some(ident) => format!("{ident}: "), None => String::new(), }; @@ -994,35 +992,32 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } }; - if let hir::ExprKind::Call(path, args) = &expr.kind { - if let (hir::ExprKind::Path(hir::QPath::TypeRelative(base_ty, path_segment)), 1) = + if let hir::ExprKind::Call(path, args) = &expr.kind + && let (hir::ExprKind::Path(hir::QPath::TypeRelative(base_ty, path_segment)), 1) = (&path.kind, args.len()) - { - // `expr` is a conversion like `u32::from(val)`, do not suggest anything (#63697). - if let (hir::TyKind::Path(hir::QPath::Resolved(None, base_ty_path)), sym::from) = - (&base_ty.kind, path_segment.ident.name) - { - if let Some(ident) = &base_ty_path.segments.iter().map(|s| s.ident).next() { - match ident.name { - sym::i128 - | sym::i64 - | sym::i32 - | sym::i16 - | sym::i8 - | sym::u128 - | sym::u64 - | sym::u32 - | sym::u16 - | sym::u8 - | sym::isize - | sym::usize - if base_ty_path.segments.len() == 1 => - { - return false; - } - _ => {} - } + // `expr` is a conversion like `u32::from(val)`, do not suggest anything (#63697). + && let (hir::TyKind::Path(hir::QPath::Resolved(None, base_ty_path)), sym::from) = + (&base_ty.kind, path_segment.ident.name) + { + if let Some(ident) = &base_ty_path.segments.iter().map(|s| s.ident).next() { + match ident.name { + sym::i128 + | sym::i64 + | sym::i32 + | sym::i16 + | sym::i8 + | sym::u128 + | sym::u64 + | sym::u32 + | sym::u16 + | sym::u8 + | sym::isize + | sym::usize + if base_ty_path.segments.len() == 1 => + { + return false; } + _ => {} } } } @@ -1042,8 +1037,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expected_ty, ); let lit_msg = format!( - "change the type of the numeric literal from `{}` to `{}`", - checked_ty, expected_ty, + "change the type of the numeric literal from `{checked_ty}` to `{expected_ty}`", ); let close_paren = if expr.precedence().order() < PREC_POSTFIX { @@ -1054,10 +1048,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; let mut cast_suggestion = sugg.clone(); - cast_suggestion - .push((expr.span.shrink_to_hi(), format!("{} as {}", close_paren, expected_ty))); + cast_suggestion.push((expr.span.shrink_to_hi(), format!("{close_paren} as {expected_ty}"))); let mut into_suggestion = sugg.clone(); - into_suggestion.push((expr.span.shrink_to_hi(), format!("{}.into()", close_paren))); + into_suggestion.push((expr.span.shrink_to_hi(), format!("{close_paren}.into()"))); let mut suffix_suggestion = sugg.clone(); suffix_suggestion.push(( if matches!( @@ -1074,7 +1067,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }, if expr.precedence().order() < PREC_POSTFIX { // Readd `)` - format!("{})", expected_ty) + format!("{expected_ty})") } else { expected_ty.to_string() }, @@ -1108,20 +1101,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { (lhs_expr_and_src, exp_to_found_is_fallible) { let msg = format!( - "you can convert `{}` from `{}` to `{}`, matching the type of `{}`", - lhs_src, expected_ty, checked_ty, src + "you can convert `{lhs_src}` from `{expected_ty}` to `{checked_ty}`, matching the type of `{src}`", ); let suggestion = vec![ - (lhs_expr.span.shrink_to_lo(), format!("{}::from(", checked_ty)), + (lhs_expr.span.shrink_to_lo(), format!("{checked_ty}::from(")), (lhs_expr.span.shrink_to_hi(), ")".to_string()), ]; (msg, suggestion) } else { - let msg = format!("{} and panic if the converted value doesn't fit", msg); + let msg = format!("{msg} and panic if the converted value doesn't fit"); let mut suggestion = sugg.clone(); suggestion.push(( expr.span.shrink_to_hi(), - format!("{}.try_into().unwrap()", close_paren), + format!("{close_paren}.try_into().unwrap()"), )); (msg, suggestion) }; @@ -1151,7 +1143,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // We now know that converting either the lhs or rhs is fallible. Before we // suggest a fallible conversion, check if the value can never fit in the // expected type. - let msg = format!("`{}` cannot fit into type `{}`", src, expected_ty); + let msg = format!("`{src}` cannot fit into type `{expected_ty}`"); err.note(&msg); return; } else if in_const_context { @@ -1229,7 +1221,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } else if can_cast { // Missing try_into implementation for `f64` to `f32` err.multipart_suggestion_verbose( - &format!("{}, producing the closest possible value", cast_msg), + &format!("{cast_msg}, producing the closest possible value"), cast_suggestion, Applicability::MaybeIncorrect, // lossy conversion ); @@ -1246,7 +1238,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } else if can_cast { // Missing try_into implementation for `{float}` to `{integer}` err.multipart_suggestion_verbose( - &format!("{}, rounding the float towards zero", msg), + &format!("{msg}, rounding the float towards zero"), cast_suggestion, Applicability::MaybeIncorrect, // lossy conversion ); @@ -1258,8 +1250,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if exp.bit_width() > found.bit_width().unwrap_or(256) { err.multipart_suggestion_verbose( &format!( - "{}, producing the floating point representation of the integer", - msg, + "{msg}, producing the floating point representation of the integer", ), into_suggestion, Applicability::MachineApplicable, @@ -1274,9 +1265,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Missing try_into implementation for `{integer}` to `{float}` err.multipart_suggestion_verbose( &format!( - "{}, producing the floating point representation of the integer, \ + "{cast_msg}, producing the floating point representation of the integer, \ rounded if necessary", - cast_msg, ), cast_suggestion, Applicability::MaybeIncorrect, // lossy conversion @@ -1321,7 +1311,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &ty::Char, ) => { err.multipart_suggestion_verbose( - &format!("{}, since a `char` always occupies 4 bytes", cast_msg,), + &format!("{cast_msg}, since a `char` always occupies 4 bytes"), cast_suggestion, Applicability::MachineApplicable, ); @@ -1333,22 +1323,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Report the type inferred by the return statement. fn report_closure_inferred_return_type(&self, err: &mut Diagnostic, expected: Ty<'tcx>) { - if let Some(sp) = self.ret_coercion_span.get() { + if let Some(sp) = self.ret_coercion_span.get() // If the closure has an explicit return type annotation, or if // the closure's return type has been inferred from outside // requirements (such as an Fn* trait bound), then a type error // may occur at the first return expression we see in the closure // (if it conflicts with the declared return type). Skip adding a // note in this case, since it would be incorrect. - if !self.return_type_pre_known { - err.span_note( - sp, - &format!( - "return type inferred to be `{}` here", - self.resolve_vars_if_possible(expected) - ), - ); - } + && !self.return_type_pre_known + { + err.span_note( + sp, + &format!( + "return type inferred to be `{}` here", + self.resolve_vars_if_possible(expected) + ), + ); } } } diff --git a/compiler/rustc_typeck/src/check/dropck.rs b/compiler/rustc_typeck/src/check/dropck.rs index 4ab94f39357d8..3bc92166543d4 100644 --- a/compiler/rustc_typeck/src/check/dropck.rs +++ b/compiler/rustc_typeck/src/check/dropck.rs @@ -57,7 +57,7 @@ pub fn check_drop_impl(tcx: TyCtxt<'_>, drop_impl_did: DefId) -> Result<(), Erro let span = tcx.def_span(drop_impl_did); let reported = tcx.sess.delay_span_bug( span, - &format!("should have been rejected by coherence check: {}", dtor_self_type), + &format!("should have been rejected by coherence check: {dtor_self_type}"), ); Err(reported) } @@ -104,8 +104,7 @@ fn ensure_drop_params_and_item_params_correspond<'tcx>( item_span, &format!( "use the same sequence of generic type, lifetime and const parameters \ - as the {} definition", - self_descr, + as the {self_descr} definition", ), ) .emit(); @@ -262,9 +261,7 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>( tcx.sess, predicate_sp, E0367, - "`Drop` impl requires `{}` but the {} it is implemented for does not", - predicate, - self_descr, + "`Drop` impl requires `{predicate}` but the {self_descr} it is implemented for does not", ) .span_note(item_span, "the implementor must specify the same requirement") .emit(); diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs index 669521bc4725e..4d15dd715f1fc 100644 --- a/compiler/rustc_typeck/src/check/expr.rs +++ b/compiler/rustc_typeck/src/check/expr.rs @@ -181,13 +181,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // make this code only run with -Zverbose because it is probably slow if let Ok(lint_str) = self.tcx.sess.source_map().span_to_snippet(expr.span) { if !lint_str.contains('\n') { - debug!("expr text: {}", lint_str); + debug!("expr text: {lint_str}"); } else { let mut lines = lint_str.lines(); if let Some(line0) = lines.next() { let remaining_lines = lines.count(); - debug!("expr text: {}", line0); - debug!("expr text: ...(and {} more lines)", remaining_lines); + debug!("expr text: {line0}"); + debug!("expr text: ...(and {remaining_lines} more lines)"); } } } @@ -375,8 +375,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expr.span, oprnd_t, E0614, - "type `{}` cannot be dereferenced", - oprnd_t, + "type `{oprnd_t}` cannot be dereferenced", ); let sp = tcx.sess.source_map().start_point(expr.span); if let Some(sp) = @@ -652,7 +651,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err.span_suggestion( expr.span, "give it a value of the expected type", - format!("break{} {}", label, val), + format!("break{label} {val}"), Applicability::HasPlaceholders, ); } @@ -780,7 +779,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) { db.span_label( span, - format!("expected `{}` because of this return type", snippet), + format!("expected `{snippet}` because of this return type"), ); } }, @@ -1611,15 +1610,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut truncated_fields_error = String::new(); let remaining_fields_names = match &displayable_field_names[..] { [field1] => format!("`{}`", field1), - [field1, field2] => format!("`{}` and `{}`", field1, field2), - [field1, field2, field3] => format!("`{}`, `{}` and `{}`", field1, field2, field3), + [field1, field2] => format!("`{field1}` and `{field2}`"), + [field1, field2, field3] => format!("`{field1}`, `{field2}` and `{field3}`"), _ => { truncated_fields_error = format!(" and {} other field{}", len - 3, pluralize!(len - 3)); displayable_field_names .iter() .take(3) - .map(|n| format!("`{}`", n)) + .map(|n| format!("`{n}`")) .collect::>() .join(", ") } @@ -1635,10 +1634,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { truncated_fields_error, adt_ty ); - err.span_label( - span, - format!("missing {}{}", remaining_fields_names, truncated_fields_error), - ); + err.span_label(span, format!("missing {remaining_fields_names}{truncated_fields_error}")); // If the last field is a range literal, but it isn't supposed to be, then they probably // meant to use functional update syntax. @@ -1693,8 +1689,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.tcx.sess.span_err( span, &format!( - "cannot construct `{}` with struct literal syntax due to inaccessible fields", - adt_ty, + "cannot construct `{adt_ty}` with struct literal syntax due to inaccessible fields", ), ); } @@ -1807,7 +1802,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } else { err.span_label( field.ident.span, - format!("`{}` does not have this field", ty), + format!("`{ty}` does not have this field"), ); } let available_field_names = @@ -1973,8 +1968,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { field.span, expr_t, E0610, - "`{}` is a primitive type and therefore doesn't have fields", - expr_t + "`{expr_t}` is a primitive type and therefore doesn't have fields", ) .emit(); } @@ -2018,7 +2012,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } if add_label { - err.span_label(field_ident.span, &format!("field not found in `{}`", ty)); + err.span_label(field_ident.span, &format!("field not found in `{ty}`")); } } @@ -2077,10 +2071,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.tcx().sess, field.span, E0616, - "field `{}` of {} `{}` is private", - field, - kind_name, - struct_path + "field `{field}` of {kind_name} `{struct_path}` is private", ); err.span_label(field.span, "private field"); // Also check if an accessible method exists, which is often what is meant. @@ -2088,7 +2079,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { { self.suggest_method_call( &mut err, - &format!("a method `{}` also exists, call it with parentheses", field), + &format!("a method `{field}` also exists, call it with parentheses"), field, expr_t, expr, @@ -2104,9 +2095,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { field.span, expr_t, E0615, - "attempted to take value of method `{}` on type `{}`", - field, - expr_t + "attempted to take value of method `{field}` on type `{expr_t}`", ); err.span_label(field.span, "method, not a field"); let expr_is_call = @@ -2150,27 +2139,27 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } else { let mut found = false; - if let ty::RawPtr(ty_and_mut) = expr_t.kind() { - if let ty::Adt(adt_def, _) = ty_and_mut.ty.kind() { - if adt_def.variants().len() == 1 - && adt_def - .variants() - .iter() - .next() - .unwrap() - .fields - .iter() - .any(|f| f.ident(self.tcx) == field) - { - if let Some(dot_loc) = expr_snippet.rfind('.') { - found = true; - err.span_suggestion( - expr.span.with_hi(expr.span.lo() + BytePos::from_usize(dot_loc)), - "to access the field, dereference first", - format!("(*{})", &expr_snippet[0..dot_loc]), - Applicability::MaybeIncorrect, - ); - } + if let ty::RawPtr(ty_and_mut) = expr_t.kind() + && let ty::Adt(adt_def, _) = ty_and_mut.ty.kind() + { + if adt_def.variants().len() == 1 + && adt_def + .variants() + .iter() + .next() + .unwrap() + .fields + .iter() + .any(|f| f.ident(self.tcx) == field) + { + if let Some(dot_loc) = expr_snippet.rfind('.') { + found = true; + err.span_suggestion( + expr.span.with_hi(expr.span.lo() + BytePos::from_usize(dot_loc)), + "to access the field, dereference first", + format!("(*{})", &expr_snippet[0..dot_loc]), + Applicability::MaybeIncorrect, + ); } } } @@ -2197,7 +2186,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let param_span = self.tcx.hir().span(param_hir_id); let param_name = self.tcx.hir().ty_param_name(param_def_id.expect_local()); - err.span_label(param_span, &format!("type parameter '{}' declared here", param_name)); + err.span_label(param_span, &format!("type parameter '{param_name}' declared here")); } fn suggest_fields_on_recordish( @@ -2239,17 +2228,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) { if let (Some(len), Ok(user_index)) = (len.try_eval_usize(self.tcx, self.param_env), field.as_str().parse::()) + && let Ok(base) = self.tcx.sess.source_map().span_to_snippet(base.span) { - if let Ok(base) = self.tcx.sess.source_map().span_to_snippet(base.span) { - let help = "instead of using tuple indexing, use array indexing"; - let suggestion = format!("{}[{}]", base, field); - let applicability = if len < user_index { - Applicability::MachineApplicable - } else { - Applicability::MaybeIncorrect - }; - err.span_suggestion(expr.span, help, suggestion, applicability); - } + let help = "instead of using tuple indexing, use array indexing"; + let suggestion = format!("{base}[{field}]"); + let applicability = if len < user_index { + Applicability::MachineApplicable + } else { + Applicability::MaybeIncorrect + }; + err.span_suggestion(expr.span, help, suggestion, applicability); } } @@ -2261,8 +2249,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { field: Ident, ) { if let Ok(base) = self.tcx.sess.source_map().span_to_snippet(base.span) { - let msg = format!("`{}` is a raw pointer; try dereferencing it", base); - let suggestion = format!("(*{}).{}", base, field); + let msg = format!("`{base}` is a raw pointer; try dereferencing it"); + let suggestion = format!("(*{base}).{field}"); err.span_suggestion(expr.span, &msg, suggestion, Applicability::MaybeIncorrect); } } @@ -2281,9 +2269,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { field.span, expr_t, E0609, - "no field `{}` on type `{}`", - field, - expr_t + "no field `{field}` on type `{expr_t}`", ); // try to add a suggestion in case the field is a nested field of a field of the Adt @@ -2307,7 +2293,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err.span_suggestion_verbose( field.span.shrink_to_lo(), "one of the expressions' fields has a field of the same name", - format!("{}.", field_path_str), + format!("{field_path_str}."), Applicability::MaybeIncorrect, ); } @@ -2419,8 +2405,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expr.span, base_t, E0608, - "cannot index into a value of type `{}`", - base_t + "cannot index into a value of type `{base_t}`", ); // Try to give some advice about indexing tuples. if let ty::Tuple(..) = base_t.kind() { @@ -2434,7 +2419,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err.span_suggestion( expr.span, "to access tuple elements, use", - format!("{}.{}", snip, i), + format!("{snip}.{i}"), Applicability::MachineApplicable, ); needs_note = false; diff --git a/compiler/rustc_typeck/src/check/generator_interior.rs b/compiler/rustc_typeck/src/check/generator_interior.rs index e584c9ad201f7..fc12865dabe9a 100644 --- a/compiler/rustc_typeck/src/check/generator_interior.rs +++ b/compiler/rustc_typeck/src/check/generator_interior.rs @@ -567,7 +567,7 @@ pub fn check_must_not_suspend_ty<'tcx>( _ => None, }; for (i, ty) in fields.iter().enumerate() { - let descr_post = &format!(" in tuple element {}", i); + 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( fcx, diff --git a/compiler/rustc_typeck/src/check/intrinsic.rs b/compiler/rustc_typeck/src/check/intrinsic.rs index cd6b1115ed806..78e7758067942 100644 --- a/compiler/rustc_typeck/src/check/intrinsic.rs +++ b/compiler/rustc_typeck/src/check/intrinsic.rs @@ -484,14 +484,14 @@ pub fn check_platform_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) } Err(_) => { let msg = - format!("unrecognized platform-specific intrinsic function: `{}`", name); + format!("unrecognized platform-specific intrinsic function: `{name}`"); tcx.sess.struct_span_err(it.span, &msg).emit(); return; } } } _ => { - let msg = format!("unrecognized platform-specific intrinsic function: `{}`", name); + let msg = format!("unrecognized platform-specific intrinsic function: `{name}`"); tcx.sess.struct_span_err(it.span, &msg).emit(); return; } diff --git a/compiler/rustc_typeck/src/check/mod.rs b/compiler/rustc_typeck/src/check/mod.rs index 19d52f430fcd5..043472e37f5f4 100644 --- a/compiler/rustc_typeck/src/check/mod.rs +++ b/compiler/rustc_typeck/src/check/mod.rs @@ -553,13 +553,13 @@ fn maybe_check_static_with_link_section(tcx: TyCtxt<'_>, id: LocalDefId, span: S // `#[link_section]` may contain arbitrary, or even undefined bytes, but it is // the consumer's responsibility to ensure all bytes that have been read // have defined values. - if let Ok(alloc) = tcx.eval_static_initializer(id.to_def_id()) { - if alloc.inner().relocations().len() != 0 { - let msg = "statics with a custom `#[link_section]` must be a \ - simple list of bytes on the wasm target with no \ - extra levels of indirection such as references"; - tcx.sess.span_err(span, msg); - } + if let Ok(alloc) = tcx.eval_static_initializer(id.to_def_id()) + && alloc.inner().relocations().len() != 0 + { + let msg = "statics with a custom `#[link_section]` must be a \ + simple list of bytes on the wasm target with no \ + extra levels of indirection such as references"; + tcx.sess.span_err(span, msg); } } @@ -587,7 +587,7 @@ fn report_forbidden_specialization( )); } Err(cname) => { - err.note(&format!("parent implementation is in crate `{}`", cname)); + err.note(&format!("parent implementation is in crate `{cname}`")); } } @@ -610,10 +610,9 @@ fn missing_items_err( tcx.sess, impl_span, E0046, - "not all trait items implemented, missing: `{}`", - missing_items_msg + "not all trait items implemented, missing: `{missing_items_msg}`", ); - err.span_label(impl_span, format!("missing `{}` in implementation", missing_items_msg)); + err.span_label(impl_span, format!("missing `{missing_items_msg}` in implementation")); // `Span` before impl block closing brace. let hi = full_impl_span.hi() - BytePos(1); @@ -628,7 +627,7 @@ fn missing_items_err( for trait_item in missing_items { let snippet = suggestion_signature(trait_item, tcx); let code = format!("{}{}\n{}", padding, snippet, padding); - let msg = format!("implement the missing item: `{}`", snippet); + let msg = format!("implement the missing item: `{snippet}`"); let appl = Applicability::HasPlaceholders; if let Some(span) = tcx.hir().span_if_local(trait_item.def_id) { err.span_label(span, format!("`{}` from trait", trait_item.name)); @@ -653,10 +652,9 @@ fn missing_items_must_implement_one_of_err( tcx.sess, impl_span, E0046, - "not all trait items implemented, missing one of: `{}`", - missing_items_msg + "not all trait items implemented, missing one of: `{missing_items_msg}`", ); - err.span_label(impl_span, format!("missing one of `{}` in implementation", missing_items_msg)); + err.span_label(impl_span, format!("missing one of `{missing_items_msg}` in implementation")); if let Some(annotation_span) = annotation_span { err.span_note(annotation_span, "required because of this annotation"); @@ -749,9 +747,10 @@ fn fn_sig_suggestion<'tcx>( Some(match ty.kind() { ty::Param(_) if assoc.fn_has_self_parameter && i == 0 => "self".to_string(), ty::Ref(reg, ref_ty, mutability) if i == 0 => { - let reg = match &format!("{}", reg)[..] { - "'_" | "" => String::new(), - reg => format!("{} ", reg), + let reg = format!("{reg} "); + let reg = match ®[..] { + "'_ " | " " => "", + reg => reg, }; if assoc.fn_has_self_parameter { match ref_ty.kind() { @@ -759,17 +758,17 @@ fn fn_sig_suggestion<'tcx>( format!("&{}{}self", reg, mutability.prefix_str()) } - _ => format!("self: {}", ty), + _ => format!("self: {ty}"), } } else { - format!("_: {}", ty) + format!("_: {ty}") } } _ => { if assoc.fn_has_self_parameter && i == 0 { - format!("self: {}", ty) + format!("self: {ty}") } else { - format!("_: {}", ty) + format!("_: {ty}") } } }) @@ -779,7 +778,7 @@ fn fn_sig_suggestion<'tcx>( .collect::>() .join(", "); let output = sig.output(); - let output = if !output.is_unit() { format!(" -> {}", output) } else { String::new() }; + let output = if !output.is_unit() { format!(" -> {output}") } else { String::new() }; let unsafety = sig.unsafety.prefix_str(); let (generics, where_clauses) = bounds_from_generic_predicates(tcx, predicates); @@ -789,10 +788,7 @@ fn fn_sig_suggestion<'tcx>( // lifetimes between the `impl` and the `trait`, but this should be good enough to // fill in a significant portion of the missing code, and other subsequent // suggestions can help the user fix the code. - format!( - "{}fn {}{}({}){}{} {{ todo!() }}", - unsafety, ident, generics, args, output, where_clauses - ) + format!("{unsafety}fn {ident}{generics}({args}){output}{where_clauses} {{ todo!() }}") } /// Return placeholder code for the given associated item. @@ -830,7 +826,7 @@ fn bad_variant_count<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>, sp: Span, d .map(|variant| tcx.hir().span_if_local(variant.def_id).unwrap()) .collect(); let msg = format!("needs exactly one variant, but has {}", adt.variants().len(),); - let mut err = struct_span_err!(tcx.sess, sp, E0731, "transparent enum {}", msg); + let mut err = struct_span_err!(tcx.sess, sp, E0731, "transparent enum {msg}"); err.span_label(sp, &msg); if let [start @ .., end] = &*variant_spans { for variant_span in start { @@ -850,7 +846,7 @@ fn bad_non_zero_sized_fields<'tcx>( field_spans: impl Iterator, sp: Span, ) { - let msg = format!("needs at most one non-zero-sized field, but has {}", field_count); + let msg = format!("needs at most one non-zero-sized field, but has {field_count}"); let mut err = struct_span_err!( tcx.sess, sp, @@ -877,7 +873,7 @@ fn report_unexpected_variant_res(tcx: TyCtxt<'_>, res: Res, span: Span) { tcx.sess .source_map() .span_to_snippet(span) - .map_or_else(|_| String::new(), |s| format!(" `{}`", s)), + .map_or_else(|_| String::new(), |s| format!(" `{s}`",)), ) .emit(); } diff --git a/compiler/rustc_typeck/src/check/pat.rs b/compiler/rustc_typeck/src/check/pat.rs index 0baca9048b4cd..f3dcf5fff74cc 100644 --- a/compiler/rustc_typeck/src/check/pat.rs +++ b/compiler/rustc_typeck/src/check/pat.rs @@ -405,16 +405,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut pat_ty = ty; if let hir::ExprKind::Lit(Spanned { node: ast::LitKind::ByteStr(_), .. }) = lt.kind { let expected = self.structurally_resolved_type(span, expected); - if let ty::Ref(_, inner_ty, _) = expected.kind() { - if matches!(inner_ty.kind(), ty::Slice(_)) { - let tcx = self.tcx; - trace!(?lt.hir_id.local_id, "polymorphic byte string lit"); - self.typeck_results - .borrow_mut() - .treat_byte_string_as_slice - .insert(lt.hir_id.local_id); - pat_ty = tcx.mk_imm_ref(tcx.lifetimes.re_static, tcx.mk_slice(tcx.types.u8)); - } + if let ty::Ref(_, inner_ty, _) = expected.kind() + && matches!(inner_ty.kind(), ty::Slice(_)) + { + let tcx = self.tcx; + trace!(?lt.hir_id.local_id, "polymorphic byte string lit"); + self.typeck_results + .borrow_mut() + .treat_byte_string_as_slice + .insert(lt.hir_id.local_id); + pat_ty = tcx.mk_imm_ref(tcx.lifetimes.re_static, tcx.mk_slice(tcx.types.u8)); } } @@ -481,14 +481,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Unify each side with `expected`. // Subtyping doesn't matter here, as the value is some kind of scalar. let demand_eqtype = |x: &mut _, y| { - if let Some((ref mut fail, x_ty, x_span)) = *x { - if let Some(mut err) = self.demand_eqtype_pat_diag(x_span, expected, x_ty, ti) { - if let Some((_, y_ty, y_span)) = y { - self.endpoint_has_type(&mut err, y_span, y_ty); - } - err.emit(); - *fail = true; - }; + if let Some((ref mut fail, x_ty, x_span)) = *x + && let Some(mut err) = self.demand_eqtype_pat_diag(x_span, expected, x_ty, ti) + { + if let Some((_, y_ty, y_span)) = y { + self.endpoint_has_type(&mut err, y_span, y_ty); + } + err.emit(); + *fail = true; } }; demand_eqtype(&mut lhs, rhs); @@ -630,7 +630,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let Some(mut err) = self.demand_eqtype_pat_diag(span, var_ty, ty, ti) { let hir = self.tcx.hir(); let var_ty = self.resolve_vars_with_obligations(var_ty); - let msg = format!("first introduced with type `{}` here", var_ty); + let msg = format!("first introduced with type `{var_ty}` here"); err.span_label(hir.span(var_id), msg); let in_match = hir.parent_iter(var_id).any(|(_, n)| { matches!( @@ -665,8 +665,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { { err.span_suggestion( *span, - &format!("did you mean `{}`", snippet), - format!(" &{}", expected), + &format!("did you mean `{snippet}`"), + format!(" &{expected}"), Applicability::MachineApplicable, ); } @@ -701,7 +701,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { "type `{}` cannot be dereferenced", type_str ); - err.span_label(span, format!("type `{}` cannot be dereferenced", type_str)); + err.span_label(span, format!("type `{type_str}` cannot be dereferenced")); if self.tcx.sess.teach(&err.get_code().unwrap()) { err.note(CANNOT_IMPLICITLY_DEREF_POINTER_TRAIT_OBJ); } @@ -918,7 +918,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { path_str ); - let mut err = struct_span_err!(tcx.sess, pat.span, E0164, "{}", msg); + let mut err = struct_span_err!(tcx.sess, pat.span, E0164, "{msg}"); match res { Res::Def(DefKind::Fn | DefKind::AssocFn, _) => { err.span_label(pat.span, "`fn` calls are not allowed in patterns"); @@ -1396,8 +1396,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.tcx.sess, pat.span, E0769, - "tuple variant `{}` written as struct variant", - path + "tuple variant `{path}` written as struct variant", ); err.span_suggestion_verbose( qpath.span().shrink_to_hi().to(pat.span.shrink_to_hi()), @@ -1422,8 +1421,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { sess, pat.span, E0638, - "`..` required with {} marked as non-exhaustive", - descr + "`..` required with {descr} marked as non-exhaustive", ); err.span_suggestion_verbose( sp_comma, @@ -1442,8 +1440,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { "field `{}` bound multiple times in the pattern", ident ) - .span_label(span, format!("multiple uses of `{}` in pattern", ident)) - .span_label(other_field, format!("first use of `{}`", ident)) + .span_label(span, format!("multiple uses of `{ident}` in pattern")) + .span_label(other_field, format!("first use of `{ident}`")) .emit(); } diff --git a/compiler/rustc_typeck/src/check/place_op.rs b/compiler/rustc_typeck/src/check/place_op.rs index 5dab0bb7a1375..2e0f37eba232d 100644 --- a/compiler/rustc_typeck/src/check/place_op.rs +++ b/compiler/rustc_typeck/src/check/place_op.rs @@ -74,9 +74,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let ty = self.resolve_vars_if_possible(ty); let mut err = self.tcx.sess.struct_span_err( span, - &format!("negative integers cannot be used to index on a `{}`", ty), + &format!("negative integers cannot be used to index on a `{ty}`"), ); - err.span_label(span, &format!("cannot use a negative integer for indexing on `{}`", ty)); + err.span_label(span, &format!("cannot use a negative integer for indexing on `{ty}`")); if let (hir::ExprKind::Path(..), Ok(snippet)) = (&base_expr.kind, self.tcx.sess.source_map().span_to_snippet(base_expr.span)) { @@ -84,10 +84,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err.span_suggestion_verbose( span.shrink_to_lo(), &format!( - "to access an element starting from the end of the `{}`, compute the index", - ty, + "to access an element starting from the end of the `{ty}`, compute the index", ), - format!("{}.len() ", snippet), + format!("{snippet}.len() "), Applicability::MachineApplicable, ); } @@ -314,32 +313,32 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.typeck_results.borrow_mut().adjustments_mut().remove(expr.hir_id); if let Some(mut adjustments) = previous_adjustments { for adjustment in &mut adjustments { - if let Adjust::Deref(Some(ref mut deref)) = adjustment.kind { - if let Some(ok) = self.try_mutable_overloaded_place_op( + if let Adjust::Deref(Some(ref mut deref)) = adjustment.kind + && let Some(ok) = self.try_mutable_overloaded_place_op( expr.span, source, &[], PlaceOp::Deref, - ) { - let method = self.register_infer_ok_obligations(ok); - if let ty::Ref(region, _, mutbl) = *method.sig.output().kind() { - *deref = OverloadedDeref { region, mutbl, span: deref.span }; - } - // If this is a union field, also throw an error for `DerefMut` of `ManuallyDrop` (see RFC 2514). - // This helps avoid accidental drops. - if inside_union - && source.ty_adt_def().map_or(false, |adt| adt.is_manually_drop()) - { - let mut err = self.tcx.sess.struct_span_err( - expr.span, - "not automatically applying `DerefMut` on `ManuallyDrop` union field", - ); - err.help( - "writing to this reference calls the destructor for the old value", - ); - err.help("add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor"); - err.emit(); - } + ) + { + let method = self.register_infer_ok_obligations(ok); + if let ty::Ref(region, _, mutbl) = *method.sig.output().kind() { + *deref = OverloadedDeref { region, mutbl, span: deref.span }; + } + // If this is a union field, also throw an error for `DerefMut` of `ManuallyDrop` (see RFC 2514). + // This helps avoid accidental drops. + if inside_union + && source.ty_adt_def().map_or(false, |adt| adt.is_manually_drop()) + { + let mut err = self.tcx.sess.struct_span_err( + expr.span, + "not automatically applying `DerefMut` on `ManuallyDrop` union field", + ); + err.help( + "writing to this reference calls the destructor for the old value", + ); + err.help("add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor"); + err.emit(); } } source = adjustment.target; diff --git a/compiler/rustc_typeck/src/check/regionck.rs b/compiler/rustc_typeck/src/check/regionck.rs index e18cb31acbdf0..e37e83e748733 100644 --- a/compiler/rustc_typeck/src/check/regionck.rs +++ b/compiler/rustc_typeck/src/check/regionck.rs @@ -317,13 +317,8 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> { self.body_id = body_id.hir_id; self.body_owner = self.tcx.hir().body_owner_def_id(body_id); - let fn_sig = { - match self.typeck_results.borrow().liberated_fn_sigs().get(id) { - Some(f) => *f, - None => { - bug!("No fn-sig entry for id={:?}", id); - } - } + let Some(fn_sig) = self.typeck_results.borrow().liberated_fn_sigs().get(id) else { + bug!("No fn-sig entry for id={:?}", id); }; // Collect the types from which we create inferred bounds. @@ -642,12 +637,9 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> { ignore_err!(self.with_mc(|mc| { mc.cat_pattern(discr_cmt, root_pat, |sub_cmt, hir::Pat { kind, span, hir_id, .. }| { // `ref x` pattern - if let PatKind::Binding(..) = kind { - if let Some(ty::BindByReference(mutbl)) = - mc.typeck_results.extract_binding_mode(self.tcx.sess, *hir_id, *span) - { - self.link_region_from_node_type(*span, *hir_id, mutbl, sub_cmt); - } + if let PatKind::Binding(..) = kind + && let Some(ty::BindByReference(mutbl)) = mc.typeck_results.extract_binding_mode(self.tcx.sess, *hir_id, *span) { + self.link_region_from_node_type(*span, *hir_id, mutbl, sub_cmt); } }) })); diff --git a/compiler/rustc_typeck/src/check/upvar.rs b/compiler/rustc_typeck/src/check/upvar.rs index 1118e96770735..9dbb813293263 100644 --- a/compiler/rustc_typeck/src/check/upvar.rs +++ b/compiler/rustc_typeck/src/check/upvar.rs @@ -862,7 +862,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { diagnostics_builder.span_suggestion( closure_body_span.with_lo(closure_body_span.lo() + BytePos::from_usize(line1.len())).shrink_to_lo(), &diagnostic_msg, - format!("\n{}{};", indent, migration_string), + format!("\n{indent}{migration_string};"), Applicability::MachineApplicable, ); } else if line1.starts_with('{') { @@ -873,7 +873,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { diagnostics_builder.span_suggestion( closure_body_span.with_lo(closure_body_span.lo() + BytePos(1)).shrink_to_lo(), &diagnostic_msg, - format!(" {};", migration_string), + format!(" {migration_string};"), Applicability::MachineApplicable, ); } else { @@ -882,7 +882,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { diagnostics_builder.multipart_suggestion( &diagnostic_msg, vec![ - (closure_body_span.shrink_to_lo(), format!("{{ {}; ", migration_string)), + (closure_body_span.shrink_to_lo(), format!("{{ {migration_string}; ")), (closure_body_span.shrink_to_hi(), " }".to_string()), ], Applicability::MachineApplicable @@ -1527,7 +1527,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.tcx.sess.struct_span_err(closure_span, "First Pass analysis includes:"); for (place, capture_info) in capture_information { let capture_str = construct_capture_info_string(self.tcx, place, capture_info); - let output_str = format!("Capturing {}", capture_str); + let output_str = format!("Capturing {capture_str}"); let span = capture_info.path_expr_id.map_or(closure_span, |e| self.tcx.hir().span(e)); @@ -1552,7 +1552,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let capture_str = construct_capture_info_string(self.tcx, place, capture_info); - let output_str = format!("Min Capture {}", capture_str); + let output_str = format!("Min Capture {capture_str}"); if capture.info.path_expr_id != capture.info.capture_kind_expr_id { let path_span = capture_info @@ -1969,7 +1969,7 @@ fn construct_place_string<'tcx>(tcx: TyCtxt<'_>, place: &Place<'tcx>) -> String projections_str.push_str(proj.as_str()); } - format!("{}[{}]", variable_name, projections_str) + format!("{variable_name}[{projections_str}]") } fn construct_capture_kind_reason_string<'tcx>( @@ -1984,13 +1984,13 @@ fn construct_capture_kind_reason_string<'tcx>( ty::UpvarCapture::ByRef(kind) => format!("{:?}", kind), }; - format!("{} captured as {} here", place_str, capture_kind_str) + format!("{place_str} captured as {capture_kind_str} here") } fn construct_path_string<'tcx>(tcx: TyCtxt<'_>, place: &Place<'tcx>) -> String { let place_str = construct_place_string(tcx, place); - format!("{} used here", place_str) + format!("{place_str} used here") } fn construct_capture_info_string<'tcx>( @@ -2004,7 +2004,7 @@ fn construct_capture_info_string<'tcx>( ty::UpvarCapture::ByValue => "ByValue".into(), ty::UpvarCapture::ByRef(kind) => format!("{:?}", kind), }; - format!("{} -> {}", place_str, capture_kind_str) + format!("{place_str} -> {capture_kind_str}") } fn var_name(tcx: TyCtxt<'_>, var_hir_id: hir::HirId) -> Symbol { @@ -2035,16 +2035,16 @@ fn migration_suggestion_for_2229( .collect::>(); let migration_ref_concat = - need_migrations_variables.iter().map(|v| format!("&{}", v)).collect::>().join(", "); + need_migrations_variables.iter().map(|v| format!("&{v}")).collect::>().join(", "); let migration_string = if 1 == need_migrations.len() { - format!("let _ = {}", migration_ref_concat) + format!("let _ = {migration_ref_concat}") } else { - format!("let _ = ({})", migration_ref_concat) + format!("let _ = ({migration_ref_concat})") }; let migrated_variables_concat = - need_migrations_variables.iter().map(|v| format!("`{}`", v)).collect::>().join(", "); + need_migrations_variables.iter().map(|v| format!("`{v}`")).collect::>().join(", "); (migration_string, migrated_variables_concat) } diff --git a/compiler/rustc_typeck/src/check/wfcheck.rs b/compiler/rustc_typeck/src/check/wfcheck.rs index f9664a9b99155..4e3e32670e96e 100644 --- a/compiler/rustc_typeck/src/check/wfcheck.rs +++ b/compiler/rustc_typeck/src/check/wfcheck.rs @@ -230,8 +230,7 @@ pub fn check_trait_item(tcx: TyCtxt<'_>, def_id: LocalDefId) { .struct_span_err( self_ty.span, &format!( - "first argument of `call` in `{}` lang item must be a reference", - fn_lang_item_name + "first argument of `call` in `{fn_lang_item_name}` lang item must be a reference", ), ) .emit(); @@ -241,8 +240,7 @@ pub fn check_trait_item(tcx: TyCtxt<'_>, def_id: LocalDefId) { .struct_span_err( *span, &format!( - "`call` function in `{}` lang item takes exactly two arguments", - fn_lang_item_name + "`call` function in `{fn_lang_item_name}` lang item takes exactly two arguments", ), ) .emit(); @@ -252,8 +250,7 @@ pub fn check_trait_item(tcx: TyCtxt<'_>, def_id: LocalDefId) { .struct_span_err( trait_item.span, &format!( - "`call` trait item in `{}` lang item must be a function", - fn_lang_item_name + "`call` trait item in `{fn_lang_item_name}` lang item must be a function", ), ) .emit(); @@ -432,7 +429,7 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, associated_items: &[hir::TraitItemRe ); err.span_suggestion( gat_item_hir.generics.where_clause.tail_span_for_suggestion(), - &format!("add the required where clause{}", plural), + &format!("add the required where clause{plural}"), suggestion, Applicability::MachineApplicable, ); @@ -523,7 +520,7 @@ fn gather_gat_bounds<'tcx, T: TypeFoldable<'tcx>>( // In our example, requires that `Self: 'a` if ty_known_to_outlive(tcx, item_hir, param_env, &wf_tys, *ty, *region_a) { debug!(?ty_idx, ?region_a_idx); - debug!("required clause: {} must outlive {}", ty, region_a); + debug!("required clause: {ty} must outlive {region_a}"); // Translate into the generic parameters of the GAT. In // our example, the type was `Self`, which will also be // `Self` in the GAT. @@ -560,7 +557,7 @@ fn gather_gat_bounds<'tcx, T: TypeFoldable<'tcx>>( } if region_known_to_outlive(tcx, item_hir, param_env, &wf_tys, *region_a, *region_b) { debug!(?region_a_idx, ?region_b_idx); - debug!("required clause: {} must outlive {}", region_a, region_b); + debug!("required clause: {region_a} must outlive {region_b}"); // Translate into the generic parameters of the GAT. let region_a_param = gat_generics.param_at(*region_a_idx, tcx); let region_a_param = @@ -869,7 +866,7 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) { ) .span_label( hir_ty.span, - format!("`{}` doesn't derive both `PartialEq` and `Eq`", ty), + format!("`{ty}` doesn't derive both `PartialEq` and `Eq`"), ) .emit(); } @@ -884,7 +881,7 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) { ty::RawPtr(_) => Some("raw pointers"), _ => { is_ptr = false; - err_ty_str = format!("`{}`", ty); + err_ty_str = format!("`{ty}`"); Some(err_ty_str.as_str()) } }; @@ -894,16 +891,14 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) { tcx.sess.span_err( hir_ty.span, &format!( - "using {} as const generic parameters is forbidden", - unsupported_type + "using {unsupported_type} as const generic parameters is forbidden", ), ); } else { let mut err = tcx.sess.struct_span_err( hir_ty.span, &format!( - "{} is forbidden as the type of a const generic parameter", - unsupported_type + "{unsupported_type} is forbidden as the type of a const generic parameter", ), ); err.note("the only supported types are integers, `bool` and `char`"); @@ -1567,9 +1562,8 @@ fn check_method_receiver<'fcx, 'tcx>( sym::arbitrary_self_types, span, &format!( - "`{}` cannot be used as the type of `self` without \ + "`{receiver_ty}` cannot be used as the type of `self` without \ the `arbitrary_self_types` feature", - receiver_ty, ), ) .help(HELP_FOR_SELF_TYPE) @@ -1587,8 +1581,7 @@ fn e0307<'tcx>(fcx: &FnCtxt<'_, 'tcx>, span: Span, receiver_ty: Ty<'_>) { fcx.tcx.sess.diagnostic(), span, E0307, - "invalid `self` parameter type: {}", - receiver_ty, + "invalid `self` parameter type: {receiver_ty}" ) .note("type of `self` must be `Self` or a type that dereferences to it") .help(HELP_FOR_SELF_TYPE) @@ -1793,7 +1786,7 @@ fn report_bivariance( tcx.def_path_str(def_id), ) } else { - format!("consider removing `{}` or referring to it in a field", param_name) + format!("consider removing `{param_name}` or referring to it in a field") }; err.help(&msg); @@ -1993,8 +1986,7 @@ fn error_392( span: Span, param_name: Symbol, ) -> DiagnosticBuilder<'_, ErrorGuaranteed> { - let mut err = - struct_span_err!(tcx.sess, span, E0392, "parameter `{}` is never used", param_name); + let mut err = struct_span_err!(tcx.sess, span, E0392, "parameter `{param_name}` is never used"); err.span_label(span, "unused parameter"); err }