diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs index 031c6cae793e2..5aa8011ca5eb6 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_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_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_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_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_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"), } @@ -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 { @@ -1114,7 +1102,7 @@ fn check_matcher_core<'tt>( 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_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 8340a0b360ef7..f3d4c8ab43843 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_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index ff8b13d31122e..68ae2441af797 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -2557,11 +2557,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)] @@ -3059,8 +3065,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_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_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_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/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index 65796fbc698d8..08cd40f38efce 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -584,7 +584,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), } } @@ -1012,7 +1012,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_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs index fd2b5f5335f69..199b5fa0314b3 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_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_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/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_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/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(..)); 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_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_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_session/src/session.rs b/compiler/rustc_session/src/session.rs index c461b26788a2f..b4548129689b1 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 \ @@ -991,6 +991,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 45b0e0c2dd1f8..b132c0a2132b7 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -684,6 +684,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 dc4d10f699c75..f6acb3c76fe58 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1149,6 +1149,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/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/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/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_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index 06f5824099237..dbb6c54fcd93b 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/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/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 diff --git a/compiler/rustc_typeck/src/check/generator_interior.rs b/compiler/rustc_typeck/src/check/generator_interior.rs index e584c9ad201f7..15edc11a4974d 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); } @@ -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/method/suggest.rs b/compiler/rustc_typeck/src/check/method/suggest.rs index e6560ca4d9b90..2921176ca4b38 100644 --- a/compiler/rustc_typeck/src/check/method/suggest.rs +++ b/compiler/rustc_typeck/src/check/method/suggest.rs @@ -8,7 +8,7 @@ use rustc_errors::{ MultiSpan, }; 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( @@ -2106,53 +2049,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/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 } diff --git a/library/alloc/src/collections/btree/set/tests.rs b/library/alloc/src/collections/btree/set/tests.rs index 00a2a0aaa14ce..429b1644976c7 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]); @@ -391,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() { 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 diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 78d01c268f53e..8aa355a554d70 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/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 039e3d59a4d40..da7753216d063 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/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, 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 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/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/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/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/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/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); | ^^^^^^^^ 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/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` 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`. 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) } 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, } } }