diff options
| author | bors <bors@rust-lang.org> | 2025-06-22 17:10:28 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2025-06-22 17:10:28 +0000 |
| commit | 111e9bc64bbdce14122e3676978f2ceefa5bff1a (patch) | |
| tree | 28ed5aecce63ba1a3279eaa86a818cf899cd4dba /compiler | |
| parent | c2ec7532eed172e79800d28f087727c4b048badd (diff) | |
| parent | 8da1a6290d0a097a497e109e70651c4f55e0fadb (diff) | |
| download | rust-111e9bc64bbdce14122e3676978f2ceefa5bff1a.tar.gz rust-111e9bc64bbdce14122e3676978f2ceefa5bff1a.zip | |
Auto merge of #142878 - GuillaumeGomez:rollup-53dohob, r=GuillaumeGomez
Rollup of 10 pull requests Successful merges: - rust-lang/rust#142458 (Merge unboxed trait object error suggestion into regular dyn incompat error) - rust-lang/rust#142593 (Add a warning to LateContext::get_def_path) - rust-lang/rust#142594 (Add DesugaringKind::FormatLiteral) - rust-lang/rust#142740 (Clean-up `FnCtxt::is_destruct_assignment_desugaring`) - rust-lang/rust#142780 (Port `#[must_use]` to new attribute parsing infrastructure) - rust-lang/rust#142798 (Don't fail to parse a struct if a semicolon is used to separate fields) - rust-lang/rust#142856 (Add a few inline directives in rustc_serialize.) - rust-lang/rust#142868 (remove few allow(dead_code)) - rust-lang/rust#142874 (cranelift: fix target feature name typo: "fxsr") - rust-lang/rust#142877 (Document why tidy checks if `eslint` is installed via `npm`) r? `@ghost` `@rustbot` modify labels: rollup
Diffstat (limited to 'compiler')
27 files changed, 203 insertions, 133 deletions
diff --git a/compiler/rustc_ast/src/format.rs b/compiler/rustc_ast/src/format.rs index b611ddea1d9..28d260419c5 100644 --- a/compiler/rustc_ast/src/format.rs +++ b/compiler/rustc_ast/src/format.rs @@ -50,6 +50,14 @@ pub struct FormatArgs { /// /// Generally only useful for lints that care about the raw bytes the user wrote. pub uncooked_fmt_str: (LitKind, Symbol), + /// Was the format literal written in the source? + /// - `format!("boo")` => true, + /// - `format!(concat!("b", "o", "o"))` => false, + /// - `format!(include_str!("boo.txt"))` => false, + /// + /// If it wasn't written in the source then we have to be careful with spans pointing into it + /// and suggestions about rewriting it. + pub is_source_literal: bool, } /// A piece of a format template string. diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index 1d437e5c2af..d0c2b2bf68b 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -1566,7 +1566,7 @@ macro_rules! common_visitor_and_walkers { // FIXME: visit the template exhaustively. pub fn walk_format_args<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, fmt: &$($lt)? $($mut)? FormatArgs) -> V::Result { - let FormatArgs { span, template: _, arguments, uncooked_fmt_str: _ } = fmt; + let FormatArgs { span, template: _, arguments, uncooked_fmt_str: _, is_source_literal: _ } = fmt; let args = $(${ignore($mut)} arguments.all_args_mut())? $(${ignore($lt)} arguments.all_args())? ; for FormatArgument { kind, expr } in args { match kind { diff --git a/compiler/rustc_ast_lowering/src/format.rs b/compiler/rustc_ast_lowering/src/format.rs index 12f0af75486..943cde90dd2 100644 --- a/compiler/rustc_ast_lowering/src/format.rs +++ b/compiler/rustc_ast_lowering/src/format.rs @@ -4,7 +4,7 @@ use rustc_ast::*; use rustc_data_structures::fx::FxIndexMap; use rustc_hir as hir; use rustc_session::config::FmtDebug; -use rustc_span::{Ident, Span, Symbol, sym}; +use rustc_span::{DesugaringKind, Ident, Span, Symbol, sym}; use super::LoweringContext; @@ -14,6 +14,13 @@ impl<'hir> LoweringContext<'_, 'hir> { // format_args!() had any arguments _before_ flattening/inlining. let allow_const = fmt.arguments.all_args().is_empty(); let mut fmt = Cow::Borrowed(fmt); + + let sp = self.mark_span_with_reason( + DesugaringKind::FormatLiteral { source: fmt.is_source_literal }, + sp, + sp.ctxt().outer_expn_data().allow_internal_unstable, + ); + if self.tcx.sess.opts.unstable_opts.flatten_format_args { fmt = flatten_format_args(fmt); fmt = self.inline_literals(fmt); diff --git a/compiler/rustc_attr_data_structures/src/attributes.rs b/compiler/rustc_attr_data_structures/src/attributes.rs index f0f5cc4db07..ce1d8080262 100644 --- a/compiler/rustc_attr_data_structures/src/attributes.rs +++ b/compiler/rustc_attr_data_structures/src/attributes.rs @@ -237,6 +237,13 @@ pub enum AttributeKind { /// Represents [`#[may_dangle]`](https://std-dev-guide.rust-lang.org/tricky/may-dangle.html). MayDangle(Span), + /// Represents `#[must_use]`. + MustUse { + span: Span, + /// must_use can optionally have a reason: `#[must_use = "reason this must be used"]` + reason: Option<Symbol>, + }, + /// Represents `#[optimize(size|speed)]` Optimize(OptimizeAttr, Span), diff --git a/compiler/rustc_attr_parsing/src/attributes/mod.rs b/compiler/rustc_attr_parsing/src/attributes/mod.rs index 1bb5edba326..3162c1fc727 100644 --- a/compiler/rustc_attr_parsing/src/attributes/mod.rs +++ b/compiler/rustc_attr_parsing/src/attributes/mod.rs @@ -33,6 +33,7 @@ pub(crate) mod confusables; pub(crate) mod deprecation; pub(crate) mod inline; pub(crate) mod lint_helpers; +pub(crate) mod must_use; pub(crate) mod repr; pub(crate) mod semantics; pub(crate) mod stability; diff --git a/compiler/rustc_attr_parsing/src/attributes/must_use.rs b/compiler/rustc_attr_parsing/src/attributes/must_use.rs new file mode 100644 index 00000000000..a672d956127 --- /dev/null +++ b/compiler/rustc_attr_parsing/src/attributes/must_use.rs @@ -0,0 +1,40 @@ +use rustc_attr_data_structures::AttributeKind; +use rustc_errors::DiagArgValue; +use rustc_feature::{AttributeTemplate, template}; +use rustc_span::{Symbol, sym}; + +use crate::attributes::{AttributeOrder, OnDuplicate, SingleAttributeParser}; +use crate::context::{AcceptContext, Stage}; +use crate::parser::ArgParser; +use crate::session_diagnostics; + +pub(crate) struct MustUseParser; + +impl<S: Stage> SingleAttributeParser<S> for MustUseParser { + const PATH: &[Symbol] = &[sym::must_use]; + const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepLast; + const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError; + const TEMPLATE: AttributeTemplate = template!(Word, NameValueStr: "reason"); + + fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> { + Some(AttributeKind::MustUse { + span: cx.attr_span, + reason: match args { + ArgParser::NoArgs => None, + ArgParser::NameValue(name_value) => name_value.value_as_str(), + ArgParser::List(_) => { + let suggestions = + <Self as SingleAttributeParser<S>>::TEMPLATE.suggestions(false, "must_use"); + cx.emit_err(session_diagnostics::MustUseIllFormedAttributeInput { + num_suggestions: suggestions.len(), + suggestions: DiagArgValue::StrListSepByAnd( + suggestions.into_iter().map(|s| format!("`{s}`").into()).collect(), + ), + span: cx.attr_span, + }); + return None; + } + }, + }) + } +} diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index b95ea598e72..fbe874d606c 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -20,6 +20,7 @@ use crate::attributes::confusables::ConfusablesParser; use crate::attributes::deprecation::DeprecationParser; use crate::attributes::inline::{InlineParser, RustcForceInlineParser}; use crate::attributes::lint_helpers::{AsPtrParser, PubTransparentParser}; +use crate::attributes::must_use::MustUseParser; use crate::attributes::repr::{AlignParser, ReprParser}; use crate::attributes::semantics::MayDangleParser; use crate::attributes::stability::{ @@ -112,6 +113,7 @@ attribute_parsers!( Single<DeprecationParser>, Single<InlineParser>, Single<MayDangleParser>, + Single<MustUseParser>, Single<OptimizeParser>, Single<PubTransparentParser>, Single<RustcForceInlineParser>, diff --git a/compiler/rustc_attr_parsing/src/session_diagnostics.rs b/compiler/rustc_attr_parsing/src/session_diagnostics.rs index 29f2e44a98a..2a020770e5d 100644 --- a/compiler/rustc_attr_parsing/src/session_diagnostics.rs +++ b/compiler/rustc_attr_parsing/src/session_diagnostics.rs @@ -437,6 +437,15 @@ pub(crate) struct IllFormedAttributeInput { } #[derive(Diagnostic)] +#[diag(attr_parsing_ill_formed_attribute_input)] +pub(crate) struct MustUseIllFormedAttributeInput { + #[primary_span] + pub span: Span, + pub num_suggestions: usize, + pub suggestions: DiagArgValue, +} + +#[derive(Diagnostic)] #[diag(attr_parsing_stability_outside_std, code = E0734)] pub(crate) struct StabilityOutsideStd { #[primary_span] diff --git a/compiler/rustc_builtin_macros/src/format.rs b/compiler/rustc_builtin_macros/src/format.rs index 39f9d5f9005..6785cb6aef5 100644 --- a/compiler/rustc_builtin_macros/src/format.rs +++ b/compiler/rustc_builtin_macros/src/format.rs @@ -606,6 +606,7 @@ fn make_format_args( template, arguments: args, uncooked_fmt_str, + is_source_literal, })) } diff --git a/compiler/rustc_codegen_cranelift/src/lib.rs b/compiler/rustc_codegen_cranelift/src/lib.rs index 07ea29f3024..8e34436fb5e 100644 --- a/compiler/rustc_codegen_cranelift/src/lib.rs +++ b/compiler/rustc_codegen_cranelift/src/lib.rs @@ -184,7 +184,7 @@ impl CodegenBackend for CraneliftCodegenBackend { // FIXME return the actually used target features. this is necessary for #[cfg(target_feature)] let target_features = if sess.target.arch == "x86_64" && sess.target.os != "none" { // x86_64 mandates SSE2 support and rustc requires the x87 feature to be enabled - vec![sym::fsxr, sym::sse, sym::sse2, Symbol::intern("x87")] + vec![sym::fxsr, sym::sse, sym::sse2, Symbol::intern("x87")] } else if sess.target.arch == "aarch64" { match &*sess.target.os { "none" => vec![], diff --git a/compiler/rustc_data_structures/src/sync/lock.rs b/compiler/rustc_data_structures/src/sync/lock.rs index 2ccf06ccd4f..a8161c51511 100644 --- a/compiler/rustc_data_structures/src/sync/lock.rs +++ b/compiler/rustc_data_structures/src/sync/lock.rs @@ -1,8 +1,6 @@ //! This module implements a lock which only uses synchronization if `might_be_dyn_thread_safe` is true. //! It implements `DynSend` and `DynSync` instead of the typical `Send` and `Sync` traits. -#![allow(dead_code)] - use std::fmt; #[derive(Clone, Copy, PartialEq)] diff --git a/compiler/rustc_data_structures/src/sync/parallel.rs b/compiler/rustc_data_structures/src/sync/parallel.rs index ff4b60a1031..b515c0bee8a 100644 --- a/compiler/rustc_data_structures/src/sync/parallel.rs +++ b/compiler/rustc_data_structures/src/sync/parallel.rs @@ -1,8 +1,6 @@ //! This module defines parallel operations that are implemented in //! one way for the serial compiler, and another way the parallel compiler. -#![allow(dead_code)] - use std::any::Any; use std::panic::{AssertUnwindSafe, catch_unwind, resume_unwind}; diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 13f95024e5a..d05e381f8c8 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -382,8 +382,6 @@ fn check_trait_item<'tcx>( _ => (None, trait_item.span), }; - check_dyn_incompatible_self_trait_by_name(tcx, trait_item); - // Check that an item definition in a subtrait is shadowing a supertrait item. lint_item_shadowing_supertrait_item(tcx, def_id); @@ -832,70 +830,6 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for GATArgsCollector<'tcx> { } } -fn could_be_self(trait_def_id: LocalDefId, ty: &hir::Ty<'_>) -> bool { - match ty.kind { - hir::TyKind::TraitObject([trait_ref], ..) => match trait_ref.trait_ref.path.segments { - [s] => s.res.opt_def_id() == Some(trait_def_id.to_def_id()), - _ => false, - }, - _ => false, - } -} - -/// Detect when a dyn-incompatible trait is referring to itself in one of its associated items. -/// -/// In such cases, suggest using `Self` instead. -fn check_dyn_incompatible_self_trait_by_name(tcx: TyCtxt<'_>, item: &hir::TraitItem<'_>) { - let (trait_ident, trait_def_id) = - match tcx.hir_node_by_def_id(tcx.hir_get_parent_item(item.hir_id()).def_id) { - hir::Node::Item(item) => match item.kind { - hir::ItemKind::Trait(_, _, ident, ..) => (ident, item.owner_id), - _ => return, - }, - _ => return, - }; - let mut trait_should_be_self = vec![]; - match &item.kind { - hir::TraitItemKind::Const(ty, _) | hir::TraitItemKind::Type(_, Some(ty)) - if could_be_self(trait_def_id.def_id, ty) => - { - trait_should_be_self.push(ty.span) - } - hir::TraitItemKind::Fn(sig, _) => { - for ty in sig.decl.inputs { - if could_be_self(trait_def_id.def_id, ty) { - trait_should_be_self.push(ty.span); - } - } - match sig.decl.output { - hir::FnRetTy::Return(ty) if could_be_self(trait_def_id.def_id, ty) => { - trait_should_be_self.push(ty.span); - } - _ => {} - } - } - _ => {} - } - if !trait_should_be_self.is_empty() { - if tcx.is_dyn_compatible(trait_def_id) { - return; - } - let sugg = trait_should_be_self.iter().map(|span| (*span, "Self".to_string())).collect(); - tcx.dcx() - .struct_span_err( - trait_should_be_self, - "associated item referring to unboxed trait object for its own trait", - ) - .with_span_label(trait_ident.span, "in this trait") - .with_multipart_suggestion( - "you might have meant to use `Self` to refer to the implementing type", - sugg, - Applicability::MachineApplicable, - ) - .emit(); - } -} - fn lint_item_shadowing_supertrait_item<'tcx>(tcx: TyCtxt<'tcx>, trait_item_def_id: LocalDefId) { let item_name = tcx.item_name(trait_item_def_id.to_def_id()); let trait_def_id = tcx.local_parent(trait_item_def_id); diff --git a/compiler/rustc_hir_analysis/src/hir_wf_check.rs b/compiler/rustc_hir_analysis/src/hir_wf_check.rs index 4633f3951a7..fef0dbf2ece 100644 --- a/compiler/rustc_hir_analysis/src/hir_wf_check.rs +++ b/compiler/rustc_hir_analysis/src/hir_wf_check.rs @@ -1,7 +1,8 @@ +use rustc_hir::def::DefKind; use rustc_hir::intravisit::{self, Visitor, VisitorExt}; use rustc_hir::{self as hir, AmbigArg, ForeignItem, ForeignItemKind}; use rustc_infer::infer::TyCtxtInferExt; -use rustc_infer::traits::{ObligationCause, WellFormedLoc}; +use rustc_infer::traits::{ObligationCause, ObligationCauseCode, WellFormedLoc}; use rustc_middle::bug; use rustc_middle::query::Providers; use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt, TypingMode, fold_regions}; @@ -107,6 +108,17 @@ fn diagnostic_hir_wf_check<'tcx>( // over less-specific types (e.g. `Option<MyStruct<u8>>`) if self.depth >= self.cause_depth { self.cause = Some(error.obligation.cause); + if let hir::TyKind::TraitObject(..) = ty.kind { + if let DefKind::AssocTy | DefKind::AssocConst | DefKind::AssocFn = + self.tcx.def_kind(self.def_id) + { + self.cause = Some(ObligationCause::new( + ty.span, + self.def_id, + ObligationCauseCode::DynCompatible(ty.span), + )); + } + } self.cause_depth = self.depth } } diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index 5b55fbe9150..e5684f8cbe6 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -1110,27 +1110,26 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - // Returns whether the given expression is a destruct assignment desugaring. - // For example, `(a, b) = (1, &2);` - // Here we try to find the pattern binding of the expression, - // `default_binding_modes` is false only for destruct assignment desugaring. + /// Returns whether the given expression is a destruct assignment desugaring. + /// For example, `(a, b) = (1, &2);` + /// Here we try to find the pattern binding of the expression, + /// `default_binding_modes` is false only for destruct assignment desugaring. pub(crate) fn is_destruct_assignment_desugaring(&self, expr: &hir::Expr<'_>) -> bool { if let hir::ExprKind::Path(hir::QPath::Resolved( _, hir::Path { res: hir::def::Res::Local(bind_hir_id), .. }, )) = expr.kind - { - let bind = self.tcx.hir_node(*bind_hir_id); - let parent = self.tcx.parent_hir_node(*bind_hir_id); - if let hir::Node::Pat(hir::Pat { + && let bind = self.tcx.hir_node(*bind_hir_id) + && let parent = self.tcx.parent_hir_node(*bind_hir_id) + && let hir::Node::Pat(hir::Pat { kind: hir::PatKind::Binding(_, _hir_id, _, _), .. }) = bind - && let hir::Node::Pat(hir::Pat { default_binding_modes: false, .. }) = parent - { - return true; - } + && let hir::Node::Pat(hir::Pat { default_binding_modes: false, .. }) = parent + { + true + } else { + false } - false } fn explain_self_literal( diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index 414f2a1846b..297b8ef7e76 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -711,6 +711,15 @@ impl<'tcx> LateContext<'tcx> { /// Gets the absolute path of `def_id` as a vector of `Symbol`. /// + /// Note that this is kinda expensive because it has to + /// travel the tree and pretty-print. Use sparingly. + /// + /// If you're trying to match for an item given by its path, use a + /// diagnostic item. If you're only interested in given sections, use more + /// specific functions, such as [`TyCtxt::crate_name`] + /// + /// FIXME: It would be great if this could be optimized. + /// /// # Examples /// /// ```rust,ignore (no context or def id available) diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index 1620f425794..a868c887493 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -2,6 +2,7 @@ use std::iter; use rustc_ast::util::{classify, parser}; use rustc_ast::{self as ast, ExprKind, HasAttrs as _, StmtKind}; +use rustc_attr_data_structures::{AttributeKind, find_attr}; use rustc_errors::{MultiSpan, pluralize}; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::DefId; @@ -368,10 +369,12 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { } fn is_def_must_use(cx: &LateContext<'_>, def_id: DefId, span: Span) -> Option<MustUsePath> { - if let Some(attr) = cx.tcx.get_attr(def_id, sym::must_use) { + if let Some(reason) = find_attr!( + cx.tcx.get_all_attrs(def_id), + AttributeKind::MustUse { reason, .. } => reason + ) { // check for #[must_use = "..."] - let reason = attr.value_str(); - Some(MustUsePath::Def(span, def_id, reason)) + Some(MustUsePath::Def(span, def_id, *reason)) } else { None } diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index 27079af06fc..d877bd5c626 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -397,6 +397,8 @@ pub enum ObligationCauseCode<'tcx> { RustCall, + DynCompatible(Span), + /// Obligations to prove that a `Drop` or negative auto trait impl is not stronger than /// the ADT it's being implemented for. AlwaysApplicableImpl, diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 658ed4bd41c..5088caa80f8 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -1781,7 +1781,7 @@ impl<'a> Parser<'a> { let mut recovered = Recovered::No; if self.eat(exp!(OpenBrace)) { while self.token != token::CloseBrace { - match self.parse_field_def(adt_ty) { + match self.parse_field_def(adt_ty, ident_span) { Ok(field) => { fields.push(field); } @@ -1894,7 +1894,7 @@ impl<'a> Parser<'a> { } /// Parses an element of a struct declaration. - fn parse_field_def(&mut self, adt_ty: &str) -> PResult<'a, FieldDef> { + fn parse_field_def(&mut self, adt_ty: &str, ident_span: Span) -> PResult<'a, FieldDef> { self.recover_vcs_conflict_marker(); let attrs = self.parse_outer_attributes()?; self.recover_vcs_conflict_marker(); @@ -1902,7 +1902,7 @@ impl<'a> Parser<'a> { let lo = this.token.span; let vis = this.parse_visibility(FollowedByType::No)?; let safety = this.parse_unsafe_field(); - this.parse_single_struct_field(adt_ty, lo, vis, safety, attrs) + this.parse_single_struct_field(adt_ty, lo, vis, safety, attrs, ident_span) .map(|field| (field, Trailing::No, UsePreAttrPos::No)) }) } @@ -1915,28 +1915,27 @@ impl<'a> Parser<'a> { vis: Visibility, safety: Safety, attrs: AttrVec, + ident_span: Span, ) -> PResult<'a, FieldDef> { - let mut seen_comma: bool = false; let a_var = self.parse_name_and_ty(adt_ty, lo, vis, safety, attrs)?; - if self.token == token::Comma { - seen_comma = true; - } - if self.eat(exp!(Semi)) { - let sp = self.prev_token.span; - let mut err = - self.dcx().struct_span_err(sp, format!("{adt_ty} fields are separated by `,`")); - err.span_suggestion_short( - sp, - "replace `;` with `,`", - ",", - Applicability::MachineApplicable, - ); - return Err(err); - } match self.token.kind { token::Comma => { self.bump(); } + token::Semi => { + self.bump(); + let sp = self.prev_token.span; + let mut err = + self.dcx().struct_span_err(sp, format!("{adt_ty} fields are separated by `,`")); + err.span_suggestion_short( + sp, + "replace `;` with `,`", + ",", + Applicability::MachineApplicable, + ); + err.span_label(ident_span, format!("while parsing this {adt_ty}")); + err.emit(); + } token::CloseBrace => {} token::DocComment(..) => { let previous_span = self.prev_token.span; @@ -1945,19 +1944,11 @@ impl<'a> Parser<'a> { missing_comma: None, }; self.bump(); // consume the doc comment - let comma_after_doc_seen = self.eat(exp!(Comma)); - // `seen_comma` is always false, because we are inside doc block - // condition is here to make code more readable - if !seen_comma && comma_after_doc_seen { - seen_comma = true; - } - if comma_after_doc_seen || self.token == token::CloseBrace { + if self.eat(exp!(Comma)) || self.token == token::CloseBrace { self.dcx().emit_err(err); } else { - if !seen_comma { - let sp = previous_span.shrink_to_hi(); - err.missing_comma = Some(sp); - } + let sp = previous_span.shrink_to_hi(); + err.missing_comma = Some(sp); return Err(self.dcx().create_err(err)); } } diff --git a/compiler/rustc_parse/src/validate_attr.rs b/compiler/rustc_parse/src/validate_attr.rs index ed1737bee33..8e6442353c3 100644 --- a/compiler/rustc_parse/src/validate_attr.rs +++ b/compiler/rustc_parse/src/validate_attr.rs @@ -293,6 +293,7 @@ fn emit_malformed_attribute( | sym::deprecated | sym::optimize | sym::cold + | sym::must_use ) { return; } diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index d802bf4df19..e11ec2ed47a 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -171,6 +171,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> { Attribute::Parsed(AttributeKind::MayDangle(attr_span)) => { self.check_may_dangle(hir_id, *attr_span) } + Attribute::Parsed(AttributeKind::MustUse { span, .. }) => { + self.check_must_use(hir_id, *span, target) + } Attribute::Unparsed(attr_item) => { style = Some(attr_item.style); match attr.path().as_slice() { @@ -245,7 +248,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | [sym::const_trait, ..] => self.check_must_be_applied_to_trait(attr, span, target), [sym::collapse_debuginfo, ..] => self.check_collapse_debuginfo(attr, span, target), [sym::must_not_suspend, ..] => self.check_must_not_suspend(attr, span, target), - [sym::must_use, ..] => self.check_must_use(hir_id, attr, target), [sym::rustc_pass_by_value, ..] => self.check_pass_by_value(attr, span, target), [sym::rustc_allow_incoherent_impl, ..] => { self.check_allow_incoherent_impl(attr, span, target) @@ -696,7 +698,8 @@ impl<'tcx> CheckAttrVisitor<'tcx> { AttributeKind::Deprecation { .. } | AttributeKind::Repr { .. } | AttributeKind::Align { .. } - | AttributeKind::Cold(..), + | AttributeKind::Cold(..) + | AttributeKind::MustUse { .. }, ) => { continue; } @@ -1576,7 +1579,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } /// Warns against some misuses of `#[must_use]` - fn check_must_use(&self, hir_id: HirId, attr: &Attribute, target: Target) { + fn check_must_use(&self, hir_id: HirId, attr_span: Span, target: Target) { if matches!( target, Target::Fn @@ -1616,7 +1619,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { self.tcx.emit_node_span_lint( UNUSED_ATTRIBUTES, hir_id, - attr.span(), + attr_span, errors::MustUseNoEffect { article, target }, ); } diff --git a/compiler/rustc_serialize/src/int_overflow.rs b/compiler/rustc_serialize/src/int_overflow.rs index f2aac2ef711..6782fbc33da 100644 --- a/compiler/rustc_serialize/src/int_overflow.rs +++ b/compiler/rustc_serialize/src/int_overflow.rs @@ -20,6 +20,7 @@ macro_rules! impl_debug_strict_add { ($( $ty:ty )*) => { $( impl DebugStrictAdd for $ty { + #[inline] fn debug_strict_add(self, other: Self) -> Self { if cfg!(debug_assertions) { self + other @@ -42,6 +43,7 @@ macro_rules! impl_debug_strict_sub { ($( $ty:ty )*) => { $( impl DebugStrictSub for $ty { + #[inline] fn debug_strict_sub(self, other: Self) -> Self { if cfg!(debug_assertions) { self - other diff --git a/compiler/rustc_serialize/src/opaque.rs b/compiler/rustc_serialize/src/opaque.rs index 00bad8e70cf..4242642c664 100644 --- a/compiler/rustc_serialize/src/opaque.rs +++ b/compiler/rustc_serialize/src/opaque.rs @@ -89,10 +89,12 @@ impl FileEncoder { self.buffered = 0; } + #[inline] pub fn file(&self) -> &File { &self.file } + #[inline] pub fn path(&self) -> &Path { &self.path } diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs index 315dedec107..29be3b73ee9 100644 --- a/compiler/rustc_span/src/hygiene.rs +++ b/compiler/rustc_span/src/hygiene.rs @@ -1213,6 +1213,17 @@ pub enum DesugaringKind { Contract, /// A pattern type range start/end PatTyRange, + /// A format literal. + FormatLiteral { + /// Was this format literal written in the source? + /// - `format!("boo")` => Yes, + /// - `format!(concat!("b", "o", "o"))` => No, + /// - `format!(include_str!("boo.txt"))` => No, + /// + /// If it wasn't written in the source then we have to be careful with suggestions about + /// rewriting it. + source: bool, + }, } impl DesugaringKind { @@ -1231,6 +1242,10 @@ impl DesugaringKind { DesugaringKind::BoundModifier => "trait bound modifier", DesugaringKind::Contract => "contract check", DesugaringKind::PatTyRange => "pattern type", + DesugaringKind::FormatLiteral { source: true } => "format string literal", + DesugaringKind::FormatLiteral { source: false } => { + "expression that expanded into a format string literal" + } } } @@ -1250,6 +1265,7 @@ impl DesugaringKind { DesugaringKind::BoundModifier => value == "BoundModifier", DesugaringKind::Contract => value == "Contract", DesugaringKind::PatTyRange => value == "PatTyRange", + DesugaringKind::FormatLiteral { .. } => value == "FormatLiteral", } } } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index da69f6c4492..684b1781b44 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1080,7 +1080,6 @@ symbols! { fs_create_dir, fsub_algebraic, fsub_fast, - fsxr, full, fundamental, fused_iterator, @@ -1088,6 +1087,7 @@ symbols! { future_drop_poll, future_output, future_trait, + fxsr, gdb_script_file, ge, gen_blocks, diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index 6d07ae021ae..2bbf90ed3ed 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -2721,6 +2721,13 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { ObligationCauseCode::TupleElem => { err.note("only the last element of a tuple may have a dynamically sized type"); } + ObligationCauseCode::DynCompatible(span) => { + err.multipart_suggestion( + "you might have meant to use `Self` to refer to the implementing type", + vec![(span, "Self".into())], + Applicability::MachineApplicable, + ); + } ObligationCauseCode::WhereClause(item_def_id, span) | ObligationCauseCode::WhereClauseInExpr(item_def_id, span, ..) | ObligationCauseCode::HostEffectInExpr(item_def_id, span, ..) @@ -2872,13 +2879,23 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { _ => (), } } - let descr = format!("required by {a} bound in `{item_name}`"); - if span.is_visible(sm) { - let msg = format!("required by {this} in `{short_item_name}`"); - multispan.push_span_label(span, msg); - err.span_note(multispan, descr); + + // If this is from a format string literal desugaring, + // we've already said "required by this formatting parameter" + let is_in_fmt_lit = if let Some(s) = err.span.primary_span() { + matches!(s.desugaring_kind(), Some(DesugaringKind::FormatLiteral { .. })) } else { - err.span_note(tcx.def_span(item_def_id), descr); + false + }; + if !is_in_fmt_lit { + let descr = format!("required by {a} bound in `{item_name}`"); + if span.is_visible(sm) { + let msg = format!("required by {this} in `{short_item_name}`"); + multispan.push_span_label(span, msg); + err.span_note(multispan, descr); + } else { + err.span_note(tcx.def_span(item_def_id), descr); + } } if let Some(note) = note { err.note(note); @@ -3973,7 +3990,15 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { ) = expr.kind { if Some(*span) != err.span.primary_span() { - err.span_label(*span, "required by a bound introduced by this call"); + let msg = if span.is_desugaring(DesugaringKind::FormatLiteral { source: true }) + { + "required by this formatting parameter" + } else if span.is_desugaring(DesugaringKind::FormatLiteral { source: false }) { + "required by a formatting parameter in this expression" + } else { + "required by a bound introduced by this call" + }; + err.span_label(*span, msg); } } diff --git a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs index ee30956295a..bdfe48a3928 100644 --- a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs +++ b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs @@ -31,7 +31,7 @@ use crate::traits::{ /// /// Currently that is `Self` in supertraits. This is needed /// because `dyn_compatibility_violations` can't be used during -/// type collection. +/// type collection, as type collection is needed for `dyn_compatiblity_violations` itself. #[instrument(level = "debug", skip(tcx), ret)] pub fn hir_ty_lowering_dyn_compatibility_violations( tcx: TyCtxt<'_>, |
