diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index 3ea7902d5712d..b056fdc73d40b 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -51,7 +51,7 @@ use rustc_data_structures::stable_hash::StableOrd; #[cfg(feature = "nightly")] use rustc_error_messages::{DiagArgValue, IntoDiagArg}; #[cfg(feature = "nightly")] -use rustc_errors::{Diag, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level, msg}; +use rustc_errors::{Diag, DiagCtxtHandle, Diagnostic, Level, msg}; use rustc_hashes::Hash64; use rustc_index::{Idx, IndexSlice, IndexVec}; #[cfg(feature = "nightly")] @@ -399,7 +399,7 @@ pub enum TargetDataLayoutError<'a> { } #[cfg(feature = "nightly")] -impl Diagnostic<'_, G> for TargetDataLayoutError<'_> { +impl Diagnostic<'_, G> for TargetDataLayoutError<'_> { fn into_diag(self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_, G> { match self { TargetDataLayoutError::InvalidAddressSpace { addr_space, err, cause } => { diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 947f2cc93b2ab..809b8b7f6a74d 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -255,7 +255,7 @@ impl PathSegment { pub enum GenericArgs { /// The `<'a, A, B, C>` in `foo::bar::baz::<'a, A, B, C>`. AngleBracketed(AngleBracketedArgs), - /// The `(A, B)` and `C` in `Foo(A, B) -> C`. + /// The `(A, B)` and `C` in `Foo(A, B) -> C`, used for the `Fn` trait among others. Parenthesized(ParenthesizedArgs), /// `(..)` in return type notation. ParenthesizedElided(Span), diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index d987bb69b0c53..b8baf21898a96 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -800,9 +800,7 @@ impl<'hir> LoweringContext<'_, 'hir> { fn lower_variant(&mut self, item_kind: &ItemKind, v: &Variant) -> hir::Variant<'hir> { if v.ident.name == kw::Underscore && self.tcx.features().unnamed_enum_variants() { // FIXME(#156628): lower unnamed enum variants to HIR. - self.dcx() - .struct_span_fatal(v.span, "unnamed enum variants are not yet implemented") - .emit() + self.dcx().span_fatal(v.span, "unnamed enum variants are not yet implemented"); } let hir_id = self.lower_node_id(v.id); self.lower_attrs(hir_id, &v.attrs, v.span, Target::Variant); diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index aa58ac4a62eca..1a351cc1420f3 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1798,9 +1798,9 @@ impl<'hir> LoweringContext<'_, 'hir> { if expr::WillCreateDefIdsVisitor.visit_expr(expr).is_break() { // FIXME(mgca): make this non-fatal once we have a better way to handle // nested items in invalid `direct_const_arg!()` arguments. - self.dcx().struct_span_fatal(span, msg).emit() + self.dcx().span_fatal(span, msg) } else { - self.dcx().struct_span_err(span, msg).emit() + self.dcx().span_err(span, msg) } } @@ -2960,9 +2960,8 @@ impl<'hir> LoweringContext<'_, 'hir> { let literal = self.lower_lit(literal, span); let kind = if !matches!(literal.node, LitKind::Int(..)) { - let err = - self.dcx().struct_span_err(expr.span, "negated literal must be an integer"); - hir::ConstArgKind::Error(err.emit()) + let err = self.dcx().span_err(expr.span, "negated literal must be an integer"); + hir::ConstArgKind::Error(err) } else { hir::ConstArgKind::Literal { lit: literal.node, negated: true } }; @@ -3366,9 +3365,9 @@ impl UnrepresentableConstArgError { // FIXME(mgca): make this non-fatal once we have a better way to handle // nested items in const args // Issue: https://github.com/rust-lang/rust/issues/154539 - lowering_context.dcx().struct_span_fatal(self.span, msg).emit() + lowering_context.dcx().span_fatal(self.span, msg) } else { - lowering_context.dcx().struct_span_err(self.span, msg).emit() + lowering_context.dcx().span_err(self.span, msg) }; ConstArg { diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index fe5c604544448..010afc6be5534 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -291,8 +291,11 @@ impl<'a> AstValidator<'a> { }); } - fn check_decl_no_pat(decl: &FnDecl, mut report_err: impl FnMut(Span, Option, bool)) { - for Param { pat, .. } in &decl.inputs { + fn check_decl_no_pat( + fn_inputs: &[Param], + mut report_err: impl FnMut(Span, Option, bool), + ) { + for Param { pat, .. } in fn_inputs { match pat.kind { PatKind::Missing | PatKind::Ident(BindingMode::NONE, _, None) | PatKind::Wild => {} PatKind::Ident(BindingMode::MUT, ident, None) => { @@ -397,7 +400,7 @@ impl<'a> AstValidator<'a> { let c_variadic_span = self.check_decl_cvariadic_pos(fn_decl); self.check_decl_splatting(fn_decl, c_variadic_span, splat_semantic); self.check_decl_attrs(fn_decl); - self.check_decl_self_param(fn_decl, self_semantic); + self.check_decl_self_param(&fn_decl.inputs, self_semantic); } /// Emits fatal error if function declaration has more than `u16::MAX` arguments @@ -544,8 +547,8 @@ impl<'a> AstValidator<'a> { }); } - fn check_decl_self_param(&self, fn_decl: &FnDecl, self_semantic: SelfSemantic) { - if let (SelfSemantic::No, [param, ..]) = (self_semantic, &*fn_decl.inputs) { + fn check_decl_self_param(&self, fn_inputs: &[Param], self_semantic: SelfSemantic) { + if let (SelfSemantic::No, [param, ..]) = (self_semantic, fn_inputs) { if param.is_self() { self.dcx().emit_err(diagnostics::FnParamForbiddenSelf { span: param.span }); } @@ -1200,7 +1203,7 @@ impl<'a> AstValidator<'a> { SelfSemantic::No, SplatSemantic::from_extern(bfty.ext), ); - Self::check_decl_no_pat(&bfty.decl, |span, _, _| { + Self::check_decl_no_pat(&bfty.decl.inputs, |span, _, _| { self.dcx().emit_err(diagnostics::PatternFnPointer { span }); }); if let Extern::Implicit(extern_span) = bfty.ext { @@ -2009,7 +2012,7 @@ impl Visitor<'_> for AstValidator<'_> { // Functions without bodies cannot have patterns. if let FnKind::Fn(ctxt, _, Fn { body: None, sig, .. }) = fk { - Self::check_decl_no_pat(&sig.decl, |span, ident, mut_ident| { + Self::check_decl_no_pat(&sig.decl.inputs, |span, ident, mut_ident| { if mut_ident && matches!(ctxt, FnCtxt::Assoc(_)) { if let Some(ident) = ident { let is_foreign = matches!(ctxt, FnCtxt::Foreign); @@ -2208,6 +2211,16 @@ impl Visitor<'_> for AstValidator<'_> { |this| visit::walk_anon_const(this, anon_const), ) } + + fn visit_path_segment(&mut self, seg: &PathSegment) -> Self::Result { + if let Some(Parenthesized(args)) = &seg.args { + self.check_decl_self_param(&args.inputs, SelfSemantic::No); + Self::check_decl_no_pat(&args.inputs, |span, _, _| { + self.dcx().emit_err(diagnostics::PatternParenthesizedArgList { span }); + }); + } + visit::walk_path_segment(self, seg); + } } pub fn check_crate( diff --git a/compiler/rustc_ast_passes/src/diagnostics.rs b/compiler/rustc_ast_passes/src/diagnostics.rs index 5ab905b5df52b..4771a87335954 100644 --- a/compiler/rustc_ast_passes/src/diagnostics.rs +++ b/compiler/rustc_ast_passes/src/diagnostics.rs @@ -2,7 +2,7 @@ use rustc_abi::ExternAbi; use rustc_errors::codes::*; -use rustc_errors::{Applicability, Diag, EmissionGuarantee, Subdiagnostic}; +use rustc_errors::{Applicability, Diag, Subdiagnostic}; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_span::{Ident, Span, Symbol}; @@ -663,7 +663,7 @@ pub(crate) struct EmptyLabelManySpans(pub Vec); // The derive for `Vec` does multiple calls to `span_label`, adding commas between each impl Subdiagnostic for EmptyLabelManySpans { - fn add_to_diag(self, diag: &mut Diag<'_, G>) { + fn add_to_diag(self, diag: &mut Diag<'_, G>) { diag.span_labels(self.0, ""); } } @@ -675,6 +675,13 @@ pub(crate) struct PatternFnPointer { pub span: Span, } +#[derive(Diagnostic)] +#[diag("patterns aren't allowed in parenthesized argument lists", code = E0561)] +pub(crate) struct PatternParenthesizedArgList { + #[primary_span] + pub span: Span, +} + #[derive(Diagnostic)] #[diag("only a single explicit lifetime bound is permitted", code = E0226)] pub(crate) struct TraitObjectBound { diff --git a/compiler/rustc_attr_parsing/src/diagnostics.rs b/compiler/rustc_attr_parsing/src/diagnostics.rs index aeaada0e61409..e5f49690f71dc 100644 --- a/compiler/rustc_attr_parsing/src/diagnostics.rs +++ b/compiler/rustc_attr_parsing/src/diagnostics.rs @@ -3,8 +3,7 @@ use std::num::IntErrorKind; use rustc_attr_ir::{AttrPath, MirDialect, MirPhase}; use rustc_errors::codes::*; use rustc_errors::{ - Applicability, Diag, DiagArgValue, DiagCtxtHandle, Diagnostic, E0264, EmissionGuarantee, Level, - MultiSpan, + Applicability, Diag, DiagArgValue, DiagCtxtHandle, Diagnostic, E0264, Level, MultiSpan, }; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_span::{Ident, Span, Symbol}; @@ -1482,9 +1481,7 @@ impl<'a> AttributeParseError<'a> { diag: &mut Diag<'_, G>, possibilities: &[Symbol], strings: bool, - ) where - G: EmissionGuarantee, - { + ) { let quote = if strings { '"' } else { '`' }; match possibilities { &[] => {} @@ -1517,9 +1514,7 @@ impl<'a> AttributeParseError<'a> { diag: &mut Diag<'_, G>, possibilities: &[Symbol], strings: bool, - ) where - G: EmissionGuarantee, - { + ) { let description = self.description(); let quote = if strings { '"' } else { '`' }; @@ -1548,10 +1543,7 @@ impl<'a> AttributeParseError<'a> { } } - fn render_suggestions(&self, diag: &mut Diag<'_, G>) - where - G: EmissionGuarantee, - { + fn render_suggestions(&self, diag: &mut Diag<'_, G>) { let description = self.description(); match &self.suggestions { @@ -1600,7 +1592,7 @@ impl AttributeParseErrorSuggestions { } } -impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for AttributeParseError<'_> { +impl<'a, G> Diagnostic<'a, G> for AttributeParseError<'_> { fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G> { let name = self.path.to_string(); diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs index 1b633aefc22f8..429eb85ed9e11 100644 --- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs +++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs @@ -2,7 +2,7 @@ use std::assert_matches; -use rustc_errors::{Applicability, Diag, EmissionGuarantee}; +use rustc_errors::{Applicability, Diag}; use rustc_hir as hir; use rustc_hir::intravisit::Visitor; use rustc_infer::infer::NllRegionVariableOrigin; @@ -55,7 +55,7 @@ impl<'tcx> BorrowExplanation<'tcx> { pub(crate) fn is_explained(&self) -> bool { !matches!(self, BorrowExplanation::Unexplained) } - pub(crate) fn add_explanation_to_diagnostic( + pub(crate) fn add_explanation_to_diagnostic( &self, cx: &MirBorrowckCtxt<'_, '_, 'tcx>, err: &mut Diag<'_, G>, @@ -437,7 +437,7 @@ impl<'tcx> BorrowExplanation<'tcx> { } } - fn add_object_lifetime_default_note( + fn add_object_lifetime_default_note( &self, tcx: TyCtxt<'tcx>, err: &mut Diag<'_, G>, @@ -494,7 +494,7 @@ impl<'tcx> BorrowExplanation<'tcx> { } } - fn add_lifetime_bound_suggestion_to_diagnostic( + fn add_lifetime_bound_suggestion_to_diagnostic( &self, err: &mut Diag<'_, G>, category: &ConstraintCategory<'tcx>, @@ -523,7 +523,7 @@ impl<'tcx> BorrowExplanation<'tcx> { } } -fn suggest_rewrite_if_let( +fn suggest_rewrite_if_let( tcx: TyCtxt<'_>, expr: &hir::Expr<'_>, pat: &str, diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs index 0e5ab5c00bd76..c5cf8d36abf1f 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -5,7 +5,7 @@ use std::collections::BTreeMap; use rustc_abi::{FieldIdx, VariantIdx}; use rustc_data_structures::fx::FxIndexMap; use rustc_errors::formatting::DiagMessageAddArg; -use rustc_errors::{Applicability, Diag, DiagMessage, EmissionGuarantee, MultiSpan, listify, msg}; +use rustc_errors::{Applicability, Diag, DiagMessage, MultiSpan, listify, msg}; use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::def::{CtorKind, Namespace}; use rustc_hir::{ @@ -669,7 +669,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> { /// /// This is very similar to `fn suggest_static_lifetime_for_gat_from_hrtb` which handles this /// note for failed type tests instead of outlives errors. - fn add_placeholder_from_predicate_note( + fn add_placeholder_from_predicate_note( &self, diag: &mut Diag<'_, G>, path: &[OutlivesConstraint<'tcx>], @@ -731,7 +731,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> { /// Add a label to region errors and borrow explanations when outlives constraints arise from /// proving a type implements `Sized` or `Copy`. - fn add_sized_or_copy_bound_info( + fn add_sized_or_copy_bound_info( &self, err: &mut Diag<'_, G>, blamed_category: ConstraintCategory<'tcx>, diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs index 4e8237178d0fc..3b457d10f51bd 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs @@ -2,7 +2,7 @@ use std::fmt::{self, Display}; use std::iter; use rustc_data_structures::fx::IndexEntry; -use rustc_errors::{Diag, EmissionGuarantee}; +use rustc_errors::Diag; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_middle::ty::print::RegionHighlightMode; @@ -105,7 +105,7 @@ impl RegionName { } } - pub(crate) fn highlight_region_name(&self, diag: &mut Diag<'_, G>) { + pub(crate) fn highlight_region_name(&self, diag: &mut Diag<'_, G>) { match &self.source { RegionNameSource::NamedLateParamRegion(span) | RegionNameSource::NamedEarlyParamRegion(span) => { diff --git a/compiler/rustc_builtin_macros/src/diagnostics.rs b/compiler/rustc_builtin_macros/src/diagnostics.rs index 4ebc39f1976fb..604341c3e7bbf 100644 --- a/compiler/rustc_builtin_macros/src/diagnostics.rs +++ b/compiler/rustc_builtin_macros/src/diagnostics.rs @@ -1,8 +1,7 @@ use rustc_errors::codes::*; use rustc_errors::formatting::DiagMessageAddArg; use rustc_errors::{ - Diag, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level, MultiSpan, SingleLabelManySpans, - Subdiagnostic, msg, + Diag, DiagCtxtHandle, Diagnostic, Level, MultiSpan, SingleLabelManySpans, Subdiagnostic, msg, }; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_span::{Ident, Span, Symbol}; @@ -543,7 +542,7 @@ pub(crate) struct EnvNotDefinedWithUserMessage { } // Hand-written implementation to support custom user messages. -impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for EnvNotDefinedWithUserMessage { +impl<'a, G> Diagnostic<'a, G> for EnvNotDefinedWithUserMessage { #[track_caller] fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G> { let mut diag = Diag::new(dcx, level, self.msg_from_user.to_string()); @@ -774,7 +773,7 @@ pub(crate) struct FormatUnusedArg { // Allow the singular form to be a subdiagnostic of the multiple-unused // form of diagnostic. impl Subdiagnostic for FormatUnusedArg { - fn add_to_diag(self, diag: &mut Diag<'_, G>) { + fn add_to_diag(self, diag: &mut Diag<'_, G>) { diag.span_label( self.span, msg!( @@ -958,7 +957,7 @@ pub(crate) struct AsmClobberNoReg { pub(crate) clobbers: Vec, } -impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for AsmClobberNoReg { +impl<'a, G> Diagnostic<'a, G> for AsmClobberNoReg { fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G> { Diag::new( dcx, diff --git a/compiler/rustc_codegen_cranelift/josh-sync.toml b/compiler/rustc_codegen_cranelift/josh-sync.toml new file mode 100644 index 0000000000000..2de9f9489cce3 --- /dev/null +++ b/compiler/rustc_codegen_cranelift/josh-sync.toml @@ -0,0 +1,3 @@ +repo = "rustc_codegen_cranelift" +filter = ":~(history=\"keep-trivial-merges,no-splice\")[:rev(<=5e120485964f4857f1ad70f7d661fd244d087668:prefix=compiler/rustc_codegen_cranelift,<=7bd21608dfab11ea536f7be8936cc7dfac5864fb:SQUASH)]:/compiler/rustc_codegen_cranelift" +filter-version = 2 diff --git a/compiler/rustc_codegen_cranelift/rust-toolchain.toml b/compiler/rustc_codegen_cranelift/rust-toolchain.toml index b83354ee49fb9..d7e313a7a33ed 100644 --- a/compiler/rustc_codegen_cranelift/rust-toolchain.toml +++ b/compiler/rustc_codegen_cranelift/rust-toolchain.toml @@ -1,4 +1,4 @@ [toolchain] -channel = "nightly-2026-09-10" +channel = "nightly-2026-09-11" components = ["rust-src", "rustc-dev", "llvm-tools", "rustfmt"] profile = "minimal" diff --git a/compiler/rustc_codegen_cranelift/rust-version b/compiler/rustc_codegen_cranelift/rust-version new file mode 100644 index 0000000000000..4dce5836595b5 --- /dev/null +++ b/compiler/rustc_codegen_cranelift/rust-version @@ -0,0 +1 @@ +ca0a6473ffde01deb7fce24cc04864cf723e14a0 diff --git a/compiler/rustc_codegen_llvm/src/back/mod.rs b/compiler/rustc_codegen_llvm/src/back/mod.rs index 6cb89f80ab89a..de6007c17bfff 100644 --- a/compiler/rustc_codegen_llvm/src/back/mod.rs +++ b/compiler/rustc_codegen_llvm/src/back/mod.rs @@ -1,5 +1,6 @@ pub(crate) mod archive; pub(crate) mod lto; +pub(crate) mod owned_mc_subtarget_info; pub(crate) mod owned_target_machine; mod profiling; pub(crate) mod write; diff --git a/compiler/rustc_codegen_llvm/src/back/owned_mc_subtarget_info.rs b/compiler/rustc_codegen_llvm/src/back/owned_mc_subtarget_info.rs new file mode 100644 index 0000000000000..f57368e755add --- /dev/null +++ b/compiler/rustc_codegen_llvm/src/back/owned_mc_subtarget_info.rs @@ -0,0 +1,49 @@ +use std::ffi::CStr; +use std::ptr::NonNull; + +use rustc_data_structures::small_c_str::SmallCStr; + +use crate::diagnostics::LlvmError; +use crate::llvm; + +/// Responsible for safely creating and disposing llvm::MCSubtargetInfo via ffi functions. +/// Not cloneable as there is no clone function for llvm::MCSubtargetInfo. +pub(crate) struct OwnedMCSubtargetInfo { + info_unique: NonNull, +} + +impl OwnedMCSubtargetInfo { + pub(crate) fn new( + triple: &CStr, + cpu: &CStr, + features: &CStr, + ) -> Result> { + // SAFETY: llvm::LLVMRustCreateMCSubtargetInfo copies pointed-to data. + let info_ptr = unsafe { + llvm::LLVMRustCreateMCSubtargetInfo(triple.as_ptr(), cpu.as_ptr(), features.as_ptr()) + }; + + NonNull::new(info_ptr) + .map(|info_unique| Self { info_unique }) + .ok_or_else(|| LlvmError::CreateMCSubtargetInfo { triple: SmallCStr::from(triple) }) + } + + pub(crate) fn has_feature(&self, feature: &CStr) -> bool { + // SAFETY: `new` ensures we have a valid pointer created by + // `llvm::LLVMRustCreateMCSubtargetInfo`. + unsafe { + llvm::LLVMRustMCSubtargetInfoHasFeature(self.info_unique.as_ref(), feature.as_ptr()) + } + } +} + +impl Drop for OwnedMCSubtargetInfo { + fn drop(&mut self) { + // SAFETY: `new` ensures we have a valid pointer created by + // `llvm::LLVMRustCreateMCSubtargetInfo` and `OwnedMCSubtargetInfo` is not copyable so + // there is no double free or use after free. + unsafe { + llvm::LLVMRustDisposeMCSubtargetInfo(self.info_unique); + } + } +} diff --git a/compiler/rustc_codegen_llvm/src/back/owned_target_machine.rs b/compiler/rustc_codegen_llvm/src/back/owned_target_machine.rs index 350d4ce9ee331..5a1dc8080c2c1 100644 --- a/compiler/rustc_codegen_llvm/src/back/owned_target_machine.rs +++ b/compiler/rustc_codegen_llvm/src/back/owned_target_machine.rs @@ -1,5 +1,4 @@ use std::ffi::CStr; -use std::marker::PhantomData; use std::ptr::NonNull; use rustc_data_structures::small_c_str::SmallCStr; @@ -9,10 +8,8 @@ use crate::llvm; /// Responsible for safely creating and disposing llvm::TargetMachine via ffi functions. /// Not cloneable as there is no clone function for llvm::TargetMachine. -#[repr(transparent)] pub struct OwnedTargetMachine { tm_unique: NonNull, - phantom: PhantomData, } impl OwnedTargetMachine { @@ -41,7 +38,7 @@ impl OwnedTargetMachine { use_wasm_eh: bool, large_data_threshold: u64, ) -> Result> { - // SAFETY: llvm::LLVMRustCreateTargetMachine copies pointed to data + // SAFETY: llvm::LLVMRustCreateTargetMachine copies pointed-to data. let tm_ptr = unsafe { llvm::LLVMRustCreateTargetMachine( triple.as_ptr(), @@ -71,7 +68,7 @@ impl OwnedTargetMachine { }; NonNull::new(tm_ptr) - .map(|tm_unique| Self { tm_unique, phantom: PhantomData }) + .map(|tm_unique| Self { tm_unique }) .ok_or_else(|| LlvmError::CreateTargetMachine { triple: SmallCStr::from(triple) }) } diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs index 90b2cab5b63e2..bdf1bb2f24f6d 100644 --- a/compiler/rustc_codegen_llvm/src/back/write.rs +++ b/compiler/rustc_codegen_llvm/src/back/write.rs @@ -100,17 +100,12 @@ fn write_output_file<'ll>( result.into_result().unwrap_or_else(|()| llvm_err(dcx, LlvmError::WriteOutput { path: output })) } -/// If `for_cfg` is `true` then we are creating this machine for the purpose of populating -/// [`rustc_codegen_ssa::TargetConfig`] based on what LLVM actually enables in this configuration. -/// `-Ctarget-feature` should be ignored in that case since it is already processed separately. -pub(crate) fn create_informational_target_machine( - sess: &Session, - for_cfg: bool, -) -> OwnedTargetMachine { +pub(crate) fn create_informational_target_machine(sess: &Session) -> OwnedTargetMachine { let config = TargetMachineFactoryConfig { split_dwarf_file: None, output_obj_file: None }; // Can't use query system here quite yet because this function is invoked before the query // system/tcx is set up. - let features = llvm_util::global_llvm_features(sess, for_cfg); + let features = llvm_util::global_llvm_features(sess, /* for_cfg */ false); + target_machine_factory(sess, config::OptLevel::No, &features)(sess.dcx(), config) } @@ -212,7 +207,6 @@ pub(crate) fn target_machine_factory( let code_model = to_llvm_code_model(sess.code_model()); - // This is used to set cfg_has_threads, so all logic must be in this method. let singlethread = sess.target.singlethread(&sess.internal_target_features); let triple = SmallCStr::new(&versioned_llvm_target(sess)); diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index 3b58a7f00146b..d4d1c950ec3f8 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -232,7 +232,7 @@ pub(crate) unsafe fn create_module<'ll>( // Ensure the data-layout values hardcoded remain the defaults. { - let tm = crate::back::write::create_informational_target_machine(sess, false); + let tm = crate::back::write::create_informational_target_machine(sess); unsafe { llvm::LLVMRustSetDataLayoutFromTargetMachine(llmod, tm.raw()); } diff --git a/compiler/rustc_codegen_llvm/src/diagnostics.rs b/compiler/rustc_codegen_llvm/src/diagnostics.rs index 70a14288aec0c..78e502f13af75 100644 --- a/compiler/rustc_codegen_llvm/src/diagnostics.rs +++ b/compiler/rustc_codegen_llvm/src/diagnostics.rs @@ -2,9 +2,7 @@ use std::ffi::{CString, c_uint}; use std::path::Path; use rustc_data_structures::small_c_str::SmallCStr; -use rustc_errors::{ - Diag, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level, format_diag_message, msg, -}; +use rustc_errors::{Diag, DiagCtxtHandle, Diagnostic, Level, format_diag_message, msg}; use rustc_macros::Diagnostic; use rustc_span::Span; @@ -22,7 +20,7 @@ pub(crate) struct SanitizerMemtagRequiresMte; pub(crate) struct ParseTargetMachineConfig<'a>(pub LlvmError<'a>); -impl Diagnostic<'_, G> for ParseTargetMachineConfig<'_> { +impl Diagnostic<'_, G> for ParseTargetMachineConfig<'_> { fn into_diag(self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_, G> { // Reuse the formatted primary message from `LlvmError` without emitting it. let diag: Diag<'_, ()> = self.0.into_diag(dcx, level); @@ -123,6 +121,8 @@ pub(crate) enum LlvmError<'a> { WriteOutput { path: &'a Path }, #[diag("could not create LLVM TargetMachine for triple: {$triple}")] CreateTargetMachine { triple: SmallCStr }, + #[diag("could not create LLVM MCSubtargetInfo for triple: {$triple}")] + CreateMCSubtargetInfo { triple: SmallCStr }, #[diag("failed to run LLVM passes")] RunLlvmPasses, #[diag("failed to write LLVM IR to {$path}")] @@ -141,7 +141,7 @@ pub(crate) enum LlvmError<'a> { pub(crate) struct WithLlvmError<'a>(pub LlvmError<'a>, pub String); -impl Diagnostic<'_, G> for WithLlvmError<'_> { +impl Diagnostic<'_, G> for WithLlvmError<'_> { fn into_diag(self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_, G> { use LlvmError::*; let msg_with_llvm_err = match &self.0 { @@ -149,6 +149,9 @@ impl Diagnostic<'_, G> for WithLlvmError<'_> { CreateTargetMachine { .. } => { msg!("could not create LLVM TargetMachine for triple: {$triple}: {$llvm_err}") } + CreateMCSubtargetInfo { .. } => { + msg!("could not create LLVM MCSubtargetInfo for triple: {$triple}: {$llvm_err}") + } RunLlvmPasses => msg!("failed to run LLVM passes: {$llvm_err}"), WriteIr { .. } => msg!("failed to write LLVM IR to {$path}: {$llvm_err}"), PrepareThinLtoContext => { diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs index ca16d33b90256..ddc5db619ea5f 100644 --- a/compiler/rustc_codegen_llvm/src/lib.rs +++ b/compiler/rustc_codegen_llvm/src/lib.rs @@ -248,7 +248,7 @@ impl CodegenBackend for LlvmCodegenBackend { fn provide(&self, providers: &mut Providers) { providers.queries.global_backend_features = - |tcx, ()| llvm_util::global_llvm_features(tcx.sess, false) + |tcx, ()| llvm_util::global_llvm_features(tcx.sess, /* for_cfg */ false) } fn print(&self, req: &PrintRequest, out: &mut String, sess: &Session) { @@ -496,7 +496,7 @@ impl ModuleLlvm { ModuleLlvm { llmod_raw, llcx, - tm: ManuallyDrop::new(create_informational_target_machine(tcx.sess, false)), + tm: ManuallyDrop::new(create_informational_target_machine(tcx.sess)), } } } diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index abacef3710f4e..d1cdf7bada0b1 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -720,6 +720,7 @@ unsafe extern "C" { pub type TargetMachine; } unsafe extern "C" { + pub(crate) type MCSubtargetInfo; pub(crate) type Twine; pub(crate) type DiagnosticInfo; pub(crate) type SMDiagnostic; @@ -2372,7 +2373,6 @@ unsafe extern "C" { pub(crate) fn LLVMRustWriteTypeToString(Type: &Type, s: &RustString); pub(crate) fn LLVMRustWriteValueToString(value_ref: &Value, s: &RustString); - pub(crate) fn LLVMRustHasFeature(T: &TargetMachine, s: *const c_char) -> bool; pub(crate) fn LLVMRustTargetHasMnemonic(T: &TargetMachine, s: *const c_char) -> bool; pub(crate) fn LLVMRustPrintTargetCPUs(TM: &TargetMachine, OutStr: &RustString); @@ -2414,6 +2414,19 @@ unsafe extern "C" { LargeDataThreshold: u64, ) -> *mut TargetMachine; + pub(crate) fn LLVMRustCreateMCSubtargetInfo( + TripleStr: *const c_char, + CPU: *const c_char, + Features: *const c_char, + ) -> *mut MCSubtargetInfo; + + pub(crate) fn LLVMRustMCSubtargetInfoHasFeature( + MCInfo: &MCSubtargetInfo, + Feature: *const c_char, + ) -> bool; + + pub(crate) fn LLVMRustDisposeMCSubtargetInfo(MCInfo: ptr::NonNull); + pub(crate) fn LLVMRustAddLibraryInfo<'a>( T: &TargetMachine, PM: &PassManager<'a>, diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index 223cbf2aae31f..677058ff80d67 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -6,6 +6,7 @@ use std::sync::Once; use std::{ptr, slice, str}; use libc::c_int; +use rustc_codegen_ssa::back::versioned_llvm_target; use rustc_codegen_ssa::base::wants_wasm_eh; use rustc_codegen_ssa::target_features::internal_target_features; use rustc_codegen_ssa::{TargetConfig, target_features}; @@ -20,7 +21,8 @@ use rustc_target::spec::{ }; use smallvec::{SmallVec, smallvec}; -use crate::back::write::create_informational_target_machine; +use crate::back::owned_mc_subtarget_info::OwnedMCSubtargetInfo; +use crate::back::write::{create_informational_target_machine, llvm_err}; use crate::{diagnostics, llvm}; static INIT: Once = Once::new(); @@ -337,7 +339,14 @@ pub(crate) fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> Option TargetConfig { - let target_machine = create_informational_target_machine(sess, true); + require_inited(); + let target_features = global_llvm_features(sess, /* for_cfg */ true); + + let triple = SmallCStr::new(&versioned_llvm_target(sess)); + let cpu = SmallCStr::new(target_cpu(sess)); + let features = CString::new(target_features.join(",")).unwrap(); + let mc_subtarget_info = OwnedMCSubtargetInfo::new(&triple, &cpu, &features) + .unwrap_or_else(|err| llvm_err(sess.dcx(), err)); let internal_target_features = internal_target_features( sess, @@ -348,16 +357,17 @@ pub(crate) fn target_config(sess: &Session) -> TargetConfig { }, |feature| { // This closure determines whether the target CPU has the feature according to LLVM. We - // do *not* consider the `-Ctarget-feature`s here, as that will be handled later in + // do *not* consider the `-Ctarget-feature`s here (that's why we passed `for_cfg: true` + // to `global_llvm_features` above) because that will be handled later in // `internal_target_features`. if let Some(feat) = to_llvm_features(sess, feature) { // All the LLVM features this expands to must be enabled. for llvm_feature in feat { let cstr = SmallCStr::new(llvm_feature); - // `LLVMRustHasFeature` is moderately expensive. On targets with many + // `has_feature` is moderately expensive. On targets with many // features (e.g. x86) these calls take a non-trivial fraction of runtime // when compiling very small programs. - if !unsafe { llvm::LLVMRustHasFeature(target_machine.raw(), cstr.as_ptr()) } { + if !mc_subtarget_info.has_feature(&cstr) { return false; } } @@ -500,7 +510,7 @@ fn llvm_target_features(tm: &llvm::TargetMachine) -> Vec<(&str, &str)> { pub(crate) fn print(req: &PrintRequest, out: &mut String, sess: &Session) { require_inited(); - let tm = create_informational_target_machine(sess, false); + let tm = create_informational_target_machine(sess); match req.kind { PrintKind::TargetCPUs => print_target_cpus(sess, tm.raw(), out), PrintKind::TargetFeatures => print_target_features(sess, tm.raw(), out), @@ -518,10 +528,11 @@ fn print_target_cpus(sess: &Session, tm: &llvm::TargetMachine, out: &mut String) cpu_name: &'a str, remark: String, } - // Compare CPU against current target to label the default. + // Compare CPU against current target to label the default. Do not print it if + // `need_explicit_cpu` is set, because in that case the concept of default makes less sense. let target_cpu = handle_native(&sess.target.cpu); let make_remark = |cpu_name| { - if cpu_name == target_cpu { + if cpu_name == target_cpu && !sess.target.need_explicit_cpu { // FIXME(#132514): This prints the LLVM target string, which can be // different from the Rust target string. Is that intended? let target = &sess.target.llvm_target; @@ -797,7 +808,7 @@ pub(crate) fn tune_cpu(sess: &Session) -> Option<&str> { pub(crate) fn target_has_mnemonic(sess: &Session, mnemonic: &str) -> bool { require_inited(); - let tm = create_informational_target_machine(sess, false); + let tm = create_informational_target_machine(sess); let cstr = SmallCStr::new(mnemonic); unsafe { llvm::LLVMRustTargetHasMnemonic(tm.raw(), cstr.as_ptr()) } } diff --git a/compiler/rustc_codegen_ssa/src/diagnostics.rs b/compiler/rustc_codegen_ssa/src/diagnostics.rs index 4c9c78f909230..8aa2da904bd07 100644 --- a/compiler/rustc_codegen_ssa/src/diagnostics.rs +++ b/compiler/rustc_codegen_ssa/src/diagnostics.rs @@ -9,8 +9,7 @@ use std::process::ExitStatus; use rustc_abi::NumScalableVectors; use rustc_errors::codes::*; use rustc_errors::{ - Diag, DiagArgValue, DiagCtxtHandle, DiagSymbolList, Diagnostic, EmissionGuarantee, IntoDiagArg, - Level, msg, + Diag, DiagArgValue, DiagCtxtHandle, DiagSymbolList, Diagnostic, IntoDiagArg, Level, msg, }; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_middle::ty::Ty; @@ -203,7 +202,7 @@ pub enum LinkRlibError { pub(crate) struct ThorinErrorWrapper(pub thorin::Error); -impl Diagnostic<'_, G> for ThorinErrorWrapper { +impl Diagnostic<'_, G> for ThorinErrorWrapper { fn into_diag(self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_, G> { let build = |msg| Diag::new(dcx, level, msg); match self.0 { @@ -335,7 +334,7 @@ pub(crate) struct LinkingFailed<'a> { pub sysroot_dir: PathBuf, } -impl Diagnostic<'_, G> for LinkingFailed<'_> { +impl Diagnostic<'_, G> for LinkingFailed<'_> { fn into_diag(mut self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_, G> { let mut diag = Diag::new(dcx, level, msg!("linking with `{$linker_path}` failed: {$exit_status}")); @@ -464,7 +463,7 @@ pub(crate) struct LinkExeUnexpectedError; pub(crate) struct LinkExeStatusStackBufferOverrun; -impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for LinkExeStatusStackBufferOverrun { +impl<'a, G> Diagnostic<'a, G> for LinkExeStatusStackBufferOverrun { fn into_diag(self, dcx: rustc_errors::DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G> { let mut diag = Diag::new(dcx, level, msg!("0xc0000409 is `STATUS_STACK_BUFFER_OVERRUN`")); diag.note(msg!( @@ -1266,7 +1265,7 @@ pub(crate) struct TargetFeatureDisableOrEnable<'a> { #[help("add the missing features in a `target_feature` attribute")] pub(crate) struct MissingFeatures; -impl Diagnostic<'_, G> for TargetFeatureDisableOrEnable<'_> { +impl Diagnostic<'_, G> for TargetFeatureDisableOrEnable<'_> { fn into_diag(self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_, G> { let mut diag = Diag::new( dcx, diff --git a/compiler/rustc_const_eval/src/diagnostics.rs b/compiler/rustc_const_eval/src/diagnostics.rs index 9faf9a59fc22a..b4dd468d7c9ee 100644 --- a/compiler/rustc_const_eval/src/diagnostics.rs +++ b/compiler/rustc_const_eval/src/diagnostics.rs @@ -2,7 +2,7 @@ use std::borrow::Cow; use rustc_errors::codes::*; use rustc_errors::formatting::DiagMessageAddArg; -use rustc_errors::{Diag, DiagArgValue, EmissionGuarantee, MultiSpan, Subdiagnostic, msg}; +use rustc_errors::{Diag, DiagArgValue, MultiSpan, Subdiagnostic, msg}; use rustc_hir::ConstContext; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_middle::ty::{Mutability, Ty}; @@ -317,7 +317,7 @@ pub(crate) struct FrameNote { } impl Subdiagnostic for FrameNote { - fn add_to_diag(self, diag: &mut Diag<'_, G>) { + fn add_to_diag(self, diag: &mut Diag<'_, G>) { let mut span: MultiSpan = self.span.into(); if self.has_label && !self.span.is_dummy() { span.push_span_label(self.span, msg!("the failure occurred here")); diff --git a/compiler/rustc_error_codes/src/error_codes/E0588.md b/compiler/rustc_error_codes/src/error_codes/E0588.md index 995d945f1589e..6bb4cafc331a6 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0588.md +++ b/compiler/rustc_error_codes/src/error_codes/E0588.md @@ -1,9 +1,11 @@ +#### Note: this error code is no longer emitted by the compiler. + A type with `packed` representation hint has a field with `align` representation hint. Erroneous code example: -```compile_fail,E0588 +```ignore (no longer emitted) #[repr(align(16))] struct Aligned(i32); diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index d935299769871..ae4bd0426545d 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -20,67 +20,23 @@ use crate::{ Suggestions, }; -/// Trait for types that `Diag::emit` can return as a "guarantee" (or "proof") -/// token that the emission happened. -pub trait EmissionGuarantee: Sized { - /// This exists so that bugs and fatal errors can both result in `!` (an - /// abort) when emitted, but have different aborting behaviour. - type EmitResult = Self; - - /// Implementation of `Diag::emit`, fully controlled by each `impl` of - /// `EmissionGuarantee`, to make it impossible to create a value of - /// `Self::EmitResult` without actually performing the emission. - #[track_caller] - fn emit_producing_guarantee(diag: Diag<'_, Self>) -> Self::EmitResult; -} - -impl EmissionGuarantee for ErrorGuaranteed { - fn emit_producing_guarantee(diag: Diag<'_, Self>) -> Self::EmitResult { - diag.emit_producing_error_guaranteed() - } -} - -impl EmissionGuarantee for () { - fn emit_producing_guarantee(diag: Diag<'_, Self>) -> Self::EmitResult { - diag.emit_producing_nothing(); - } -} - /// Marker type which enables implementation of `create_bug` and `emit_bug` functions for /// bug diagnostics. #[derive(Copy, Clone)] pub struct BugAbort; -impl EmissionGuarantee for BugAbort { - type EmitResult = !; - - fn emit_producing_guarantee(diag: Diag<'_, Self>) -> Self::EmitResult { - diag.emit_producing_nothing(); - panic::panic_any(ExplicitBug); - } -} - /// Marker type which enables implementation of `create_fatal` and `emit_fatal` functions for /// fatal diagnostics. #[derive(Copy, Clone)] pub struct FatalAbort; -impl EmissionGuarantee for FatalAbort { - type EmitResult = !; - - fn emit_producing_guarantee(diag: Diag<'_, Self>) -> Self::EmitResult { - diag.emit_producing_nothing(); - crate::FatalError.raise() - } -} - /// Trait implemented by error types. This is rarely implemented manually. Instead, use /// `#[derive(Diagnostic)]` -- see [rustc_macros::Diagnostic]. /// /// When implemented manually, it should be generic over the emission /// guarantee, i.e.: /// ```ignore (fragment) -/// impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for Foo { ... } +/// impl<'a, G> Diagnostic<'a, G> for Foo { ... } /// ``` /// rather than being specific: /// ```ignore (fragment) @@ -95,7 +51,7 @@ impl EmissionGuarantee for FatalAbort { /// rather than the `Diagnostic` impl. /// - Derived impls are always generic, and it's good for the hand-written /// impls to be consistent with them. -pub trait Diagnostic<'a, G: EmissionGuarantee = ErrorGuaranteed> { +pub trait Diagnostic<'a, G = ErrorGuaranteed> { /// Write out as a diagnostic out of `DiagCtxt`. #[must_use] #[track_caller] @@ -105,7 +61,6 @@ pub trait Diagnostic<'a, G: EmissionGuarantee = ErrorGuaranteed> { impl<'a, T, G> Diagnostic<'a, G> for Spanned where T: Diagnostic<'a, G>, - G: EmissionGuarantee, { fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G> { self.node.into_diag(dcx, level).with_span(self.span) @@ -127,7 +82,7 @@ impl<'a, F: FnOnce(&mut Diag<'_, ()>)> Diagnostic<'a, ()> for DiagDecorator { /// `#[derive(Subdiagnostic)]` -- see [rustc_macros::Subdiagnostic]. pub trait Subdiagnostic { /// Add a subdiagnostic to an existing diagnostic. - fn add_to_diag(self, diag: &mut Diag<'_, G>); + fn add_to_diag(self, diag: &mut Diag<'_, G>); } #[derive(Clone, Debug, Encodable, Decodable)] @@ -433,16 +388,16 @@ pub struct Subdiag { /// Wraps a `DiagInner`, adding some useful things. /// - The `dcx` field, allowing it to (a) emit itself, and (b) do a drop check /// that it has been emitted or cancelled. -/// - The `EmissionGuarantee`, which determines the type returned from `emit`. +/// - `G`, which determines the type returned from `emit`. /// /// Each constructed `Diag` must be consumed by a function such as `emit`, -/// `cancel`, `delay_as_bug`, or `into_diag`. A panic occurs if a `Diag` -/// is dropped without being consumed by one of these functions. +/// `cancel`, or `delay_as_bug`. A panic occurs if a `Diag` is dropped without +/// being consumed by one of these functions. /// /// If there is some state in a downstream crate you would like to access in /// the methods of `Diag` here, consider extending `DiagCtxtFlags`. #[must_use] -pub struct Diag<'a, G: EmissionGuarantee = ErrorGuaranteed> { +pub struct Diag<'a, G = ErrorGuaranteed> { pub dcx: DiagCtxtHandle<'a>, /// Why the `Option`? It is always `Some` until the `Diag` is consumed via @@ -465,7 +420,7 @@ impl !Clone for Diag<'_, G> {} rustc_data_structures::static_assert_size!(Diag<'_, ()>, 3 * size_of::()); -impl Deref for Diag<'_, G> { +impl Deref for Diag<'_, G> { type Target = DiagInner; fn deref(&self) -> &DiagInner { @@ -473,18 +428,80 @@ impl Deref for Diag<'_, G> { } } -impl DerefMut for Diag<'_, G> { +impl DerefMut for Diag<'_, G> { fn deref_mut(&mut self) -> &mut DiagInner { self.diag.as_mut().unwrap() } } -impl Debug for Diag<'_, G> { +impl Debug for Diag<'_, G> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { self.diag.fmt(f) } } +impl Diag<'_, BugAbort> { + #[track_caller] + pub fn emit(self) -> ! { + assert_eq!(self.level, Level::Bug); + self.emit_producing_nothing(); + panic::panic_any(ExplicitBug); + } +} + +impl Diag<'_, FatalAbort> { + #[track_caller] + pub fn emit(self) -> ! { + assert_eq!(self.level, Level::Fatal); + self.emit_producing_nothing(); + crate::FatalError.raise() + } +} + +impl Diag<'_, ErrorGuaranteed> { + #[track_caller] + pub fn emit(self) -> ErrorGuaranteed { + self.emit_producing_error_guaranteed() + } + + /// Emit the diagnostic unless `delay` is true, + /// in which case the emission will be delayed as a bug. + /// + /// See `emit` and `delay_as_bug` for details. + #[track_caller] + pub fn emit_unless_delay(mut self, delay: bool) -> ErrorGuaranteed { + if delay { + self.downgrade_to_delayed_bug(); + } + self.emit() + } + + /// Delay emission of this diagnostic as a bug. + /// + /// This can be useful in contexts where an error indicates a bug but + /// typically this only happens when other compilation errors have already + /// happened. In those cases this can be used to defer emission of this + /// diagnostic as a bug in the compiler only if no other errors have been + /// emitted. + /// + /// In the meantime, though, callsites are required to deal with the "bug" + /// locally in whichever way makes the most sense. + #[track_caller] + pub fn delay_as_bug(mut self) -> ErrorGuaranteed { + self.downgrade_to_delayed_bug(); + self.emit() + } +} + +impl Diag<'_, ()> { + #[track_caller] + pub fn emit(self) { + assert_ne!(self.level, Level::Bug); + assert_ne!(self.level, Level::Fatal); + self.emit_producing_nothing(); + } +} + /// `Diag` impls many `&mut self -> &mut Self` methods. Each one modifies an /// existing diagnostic, either in a standalone fashion, e.g. /// `err.code(code);`, or in a chained fashion to make multiple modifications, @@ -528,7 +545,7 @@ macro_rules! with_fn { }; } -impl<'a, G: EmissionGuarantee> Diag<'a, G> { +impl<'a, G> Diag<'a, G> { #[track_caller] pub fn new(dcx: DiagCtxtHandle<'a>, level: Level, message: impl Into) -> Self { Self::new_diagnostic(dcx, DiagInner::new(level, message)) @@ -566,13 +583,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { self.level = Level::DelayedBug; } - /// Make emitting this diagnostic fatal - /// - /// Changes the level of this diagnostic to Fatal, and importantly also changes the emission guarantee. - /// This is sound for errors that would otherwise be printed, but now simply exit the process instead. - /// This function still gives an emission guarantee, the guarantee is now just that it exits fatally. - /// For delayed bugs this is different, since those are buffered. If we upgrade one to fatal, another - /// might now be ignored. + /// Make emitting this diagnostic fatal. #[track_caller] pub fn upgrade_to_fatal(mut self) -> Diag<'a, FatalAbort> { assert!( @@ -1282,13 +1293,13 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { self } - /// Most `emit_producing_guarantee` functions use this as a starting point. + /// Most `emit` methods use this as a starting point. fn emit_producing_nothing(mut self) { let diag = self.take_diag(); self.dcx.emit_diagnostic(diag); } - /// `ErrorGuaranteed::emit_producing_guarantee` uses this. + /// `Diag<'_, ErrorGuaranteed>::emit` uses this. fn emit_producing_error_guaranteed(mut self) -> ErrorGuaranteed { let diag = self.take_diag(); @@ -1310,24 +1321,6 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { guar.unwrap() } - /// Emit and consume the diagnostic. - #[track_caller] - pub fn emit(self) -> G::EmitResult { - G::emit_producing_guarantee(self) - } - - /// Emit the diagnostic unless `delay` is true, - /// in which case the emission will be delayed as a bug. - /// - /// See `emit` and `delay_as_bug` for details. - #[track_caller] - pub fn emit_unless_delay(mut self, delay: bool) -> G::EmitResult { - if delay { - self.downgrade_to_delayed_bug(); - } - self.emit() - } - /// Cancel and consume the diagnostic. (A diagnostic must either be emitted or /// cancelled or it will panic when dropped). pub fn cancel(mut self) { @@ -1347,27 +1340,11 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { let diag = self.take_diag(); self.dcx.stash_diagnostic(span, key, diag) } - - /// Delay emission of this diagnostic as a bug. - /// - /// This can be useful in contexts where an error indicates a bug but - /// typically this only happens when other compilation errors have already - /// happened. In those cases this can be used to defer emission of this - /// diagnostic as a bug in the compiler only if no other errors have been - /// emitted. - /// - /// In the meantime, though, callsites are required to deal with the "bug" - /// locally in whichever way makes the most sense. - #[track_caller] - pub fn delay_as_bug(mut self) -> G::EmitResult { - self.downgrade_to_delayed_bug(); - self.emit() - } } /// Destructor bomb: every `Diag` must be consumed (emitted, cancelled, etc.) /// or we emit a bug. -impl Drop for Diag<'_, G> { +impl Drop for Diag<'_, G> { fn drop(&mut self) { match self.diag.take() { Some(diag) if !panicking() => { diff --git a/compiler/rustc_errors/src/diagnostic_impls.rs b/compiler/rustc_errors/src/diagnostic_impls.rs index ba7569c51a07b..b002b8932a239 100644 --- a/compiler/rustc_errors/src/diagnostic_impls.rs +++ b/compiler/rustc_errors/src/diagnostic_impls.rs @@ -5,7 +5,7 @@ use rustc_macros::Subdiagnostic; use rustc_span::{Span, Symbol}; use crate::diagnostic::DiagLocation; -use crate::{Diag, EmissionGuarantee, Subdiagnostic}; +use crate::{Diag, Subdiagnostic}; impl IntoDiagArg for DiagLocation { fn into_diag_arg(self, _: &mut Option) -> DiagArgValue { @@ -42,7 +42,7 @@ pub struct SingleLabelManySpans { pub label: &'static str, } impl Subdiagnostic for SingleLabelManySpans { - fn add_to_diag(self, diag: &mut Diag<'_, G>) { + fn add_to_diag(self, diag: &mut Diag<'_, G>) { diag.span_labels(self.spans, self.label); } } diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 3374d71461cfa..9ca0344058d7f 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -3,8 +3,6 @@ //! This module contains the code for creating and emitting diagnostics. // tidy-alphabetical-start -#![cfg_attr(bootstrap, feature(never_type))] -#![feature(associated_type_defaults)] #![feature(default_field_values)] #![feature(macro_metavar_expr_concat)] #![feature(negative_impls)] @@ -35,7 +33,7 @@ pub use codes::*; pub use decorate_diag::{BufferedEarlyLint, DecorateDiagCompat, LintBuffer}; pub use diagnostic::{ BugAbort, Diag, DiagDecorator, DiagInner, DiagLocation, DiagStyledString, Diagnostic, - EmissionGuarantee, FatalAbort, StringPart, Subdiag, Subdiagnostic, + FatalAbort, StringPart, Subdiag, Subdiagnostic, }; pub use diagnostic_impls::{ DiagSymbolList, ElidedLifetimeInPathSubdiag, ExpectedLifetimeParameter, @@ -1565,19 +1563,19 @@ impl DelayedDiagInner { } } -/// | Level | is_error | EmissionGuarantee | Top-level | Used in lints? -/// | ----- | -------- | ----------------- | --------- | -------------- -/// | Bug | yes | BugAbort | yes | - -/// | Fatal | yes | FatalAbort | yes | - -/// | Error | yes | ErrorGuaranteed | yes | yes -/// | DelayedBug | yes | ErrorGuaranteed | yes | - -/// | ForceWarning | - | () | yes | lint-only -/// | Warning | - | () | yes | yes -/// | Note | - | () | rare | - -/// | Help | - | () | rare | - -/// | FailureNote | - | () | rare | - -/// | Allow | - | () | yes | lint-only -/// | Expect | - | () | yes | lint-only +/// | Level | is_error | emit return type | Top-level | Used in lints? +/// | ----- | -------- | ---------------- | --------- | -------------- +/// | Bug | yes | BugAbort | yes | - +/// | Fatal | yes | FatalAbort | yes | - +/// | Error | yes | ErrorGuaranteed | yes | yes +/// | DelayedBug | yes | ErrorGuaranteed | yes | - +/// | ForceWarning | - | () | yes | lint-only +/// | Warning | - | () | yes | yes +/// | Note | - | () | rare | - +/// | Help | - | () | rare | - +/// | FailureNote | - | () | rare | - +/// | Allow | - | () | yes | lint-only +/// | Expect | - | () | yes | lint-only /// #[derive(Copy, PartialEq, Eq, Clone, Hash, Debug, Encodable, Decodable)] pub enum Level { diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 8d2184dcc1b0c..a7138a88ee399 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -643,7 +643,7 @@ declare_features! ( /// Allows using `#[target_feature(enable = "...")]` on `#[naked]` on functions. (unstable, naked_functions_target_feature, "1.86.0", Some(138568)), /// Allows providing names to parameters of `impl Fn` etc - (incomplete, named_fn_trait_parameters, "1.99.0", Some(158499)), + (unstable, named_fn_trait_parameters, "1.99.0", Some(158499)), /// Allows specifying the as-needed link modifier (unstable, native_link_modifiers_as_needed, "1.53.0", Some(81490)), /// Allow negative trait implementations. diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index fef10d297236f..8fde417b764d8 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -4,7 +4,7 @@ use std::ops::ControlFlow; use rustc_abi::{ExternAbi, FieldIdx, MAX_SIMD_LANES, ScalableElt}; use rustc_data_structures::unord::{UnordMap, UnordSet}; use rustc_errors::codes::*; -use rustc_errors::{Diag, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level, MultiSpan}; +use rustc_errors::{Diag, DiagCtxtHandle, Diagnostic, Level, MultiSpan}; use rustc_hir as hir; use rustc_hir::attrs::ReprAttr::ReprPacked; use rustc_hir::attrs::lang_items::LangItem; @@ -12,7 +12,9 @@ use rustc_hir::def::{CtorKind, DefKind}; use rustc_hir::{Node, find_attr, intravisit}; use rustc_infer::infer::{RegionVariableOrigin, TyCtxtInferExt}; use rustc_infer::traits::{Obligation, ObligationCauseCode, TraitErrors, WellFormedLoc}; -use rustc_lint_defs::builtin::{DEAD_CODE, UNINHABITED_STATIC, UNSUPPORTED_CALLING_CONVENTIONS}; +use rustc_lint_defs::builtin::{ + ALIGNED_FIELDS_IN_PACKED, DEAD_CODE, UNINHABITED_STATIC, UNSUPPORTED_CALLING_CONVENTIONS, +}; use rustc_macros::Diagnostic; use rustc_middle::hir::nested_filter; use rustc_middle::middle::resolve_bound_vars::ResolvedArg; @@ -41,7 +43,7 @@ use crate::check::wfcheck::{ use crate::collect::ItemCtxt; use crate::diagnostics; -fn add_abi_diag_help(abi: ExternAbi, diag: &mut Diag<'_, T>) { +fn add_abi_diag_help(abi: ExternAbi, diag: &mut Diag<'_, G>) { if let ExternAbi::Cdecl { unwind } = abi { let c_abi = ExternAbi::C { unwind }; diag.help(format!("use `extern {c_abi}` instead",)); @@ -105,7 +107,7 @@ fn check_struct(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), ErrorGuarante } check_transparent(tcx, def); - check_packed(tcx, span, def); + check_packed(tcx, span, def_id); check_type_defn(tcx, def_id, false) } @@ -115,7 +117,7 @@ fn check_union(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), ErrorGuarantee def.destructor(tcx); // force the destructor to be evaluated check_transparent(tcx, def); check_union_fields(tcx, span, def_id); - check_packed(tcx, span, def); + check_packed(tcx, span, def_id); check_type_defn(tcx, def_id, true) } @@ -256,7 +258,7 @@ fn check_opaque(tcx: TyCtxt<'_>, def_id: LocalDefId) { } /// Checks that an opaque type does not contain cycles. -pub(super) fn check_opaque_for_cycles<'tcx>( +fn check_opaque_for_cycles<'tcx>( tcx: TyCtxt<'tcx>, def_id: LocalDefId, ) -> Result<(), ErrorGuaranteed> { @@ -1207,7 +1209,7 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), }) } -pub(super) fn check_specialization_validity<'tcx>( +fn check_specialization_validity<'tcx>( tcx: TyCtxt<'tcx>, trait_def: &ty::TraitDef, trait_item: ty::AssocItem, @@ -1560,7 +1562,7 @@ fn check_scalable_vector(tcx: TyCtxt<'_>, span: Span, def_id: LocalDefId, scalab return; } ScalableElt::ElementCount(..) if fields.len() >= 2 => { - tcx.dcx().struct_span_err(span, "scalable vectors cannot have multiple fields").emit(); + tcx.dcx().span_err(span, "scalable vectors cannot have multiple fields"); return; } ScalableElt::Container if fields.is_empty() => { @@ -1644,7 +1646,8 @@ fn check_scalable_vector(tcx: TyCtxt<'_>, span: Span, def_id: LocalDefId, scalab } } -pub(super) fn check_packed(tcx: TyCtxt<'_>, sp: Span, def: ty::AdtDef<'_>) { +fn check_packed(tcx: TyCtxt<'_>, sp: Span, def_id: LocalDefId) { + let def = tcx.adt_def(def_id); let repr = def.repr(); if repr.packed() { // `#[pin_v2]` on a packed type is unsound: drop glue for a packed type moves an @@ -1673,6 +1676,7 @@ pub(super) fn check_packed(tcx: TyCtxt<'_>, sp: Span, def: ty::AdtDef<'_>) { } } } + if repr.align.is_some() { struct_span_code_err!( tcx.dcx(), @@ -1681,51 +1685,62 @@ pub(super) fn check_packed(tcx: TyCtxt<'_>, sp: Span, def: ty::AdtDef<'_>) { "type has conflicting packed and align representation hints" ) .emit(); - } else if let Some(def_spans) = check_packed_inner(tcx, def.did(), &mut vec![]) { - let mut err = struct_span_code_err!( - tcx.dcx(), + } else if repr.c() + && let Some(def_spans) = check_packed_inner(tcx, def.did(), &mut vec![]) + { + tcx.emit_node_span_lint( + ALIGNED_FIELDS_IN_PACKED, + tcx.local_def_id_to_hir_id(def_id), sp, - E0588, - "packed type cannot transitively contain a `#[repr(align)]` type" - ); - - err.span_note( - tcx.def_span(def_spans[0].0), - format!("`{}` has a `#[repr(align)]` attribute", tcx.item_name(def_spans[0].0)), - ); + rustc_errors::DiagDecorator(|diag| { + diag.primary_message( + "packed type cannot transitively contain a `#[repr(align)]` type", + ); - if def_spans.len() > 2 { - let mut first = true; - for (adt_def, span) in def_spans.iter().skip(1).rev() { - let ident = tcx.item_name(*adt_def); - err.span_note( - *span, - if first { - format!( - "`{}` contains a field of type `{}`", - tcx.type_of(def.did()).instantiate_identity().skip_norm_wip(), - ident - ) - } else { - format!("...which contains a field of type `{ident}`") - }, + diag.span_note( + tcx.def_span(def_spans[0].0), + format!( + "`{}` has a `#[repr(align)]` attribute", + tcx.item_name(def_spans[0].0) + ), ); - first = false; - } - } - err.emit(); + if def_spans.len() <= 2 { + // 2 spans means aligned type is directly inside packed type, no need to add + // extra notes. + return; + } + + let mut first = true; + for (adt_def, span) in def_spans.iter().skip(1).rev() { + let ident = tcx.item_name(*adt_def); + diag.span_note( + *span, + if first { + format!( + "`{}` contains a field of type `{}`", + tcx.type_of(def.did()).instantiate_identity().skip_norm_wip(), + ident + ) + } else { + format!("...which contains a field of type `{ident}`") + }, + ); + first = false; + } + }), + ); } } } -pub(super) fn check_packed_inner( +fn check_packed_inner( tcx: TyCtxt<'_>, def_id: DefId, stack: &mut Vec, ) -> Option> { if let ty::Adt(def, args) = tcx.type_of(def_id).instantiate_identity().skip_norm_wip().kind() { - if def.is_struct() || def.is_union() { + if def.repr().c() && (def.is_struct() || def.is_union()) { if def.repr().align.is_some() { return Some(vec![(def.did(), DUMMY_SP)]); } @@ -1747,7 +1762,7 @@ pub(super) fn check_packed_inner( None } -pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>) { +fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>) { if !adt.repr().transparent() { return; } diff --git a/compiler/rustc_hir_analysis/src/diagnostics.rs b/compiler/rustc_hir_analysis/src/diagnostics.rs index a50aefd016059..1f0c493b881f1 100644 --- a/compiler/rustc_hir_analysis/src/diagnostics.rs +++ b/compiler/rustc_hir_analysis/src/diagnostics.rs @@ -3,8 +3,7 @@ use rustc_abi::ExternAbi; use rustc_errors::codes::*; use rustc_errors::{ - Applicability, Diag, DiagCtxtHandle, DiagSymbolList, Diagnostic, EmissionGuarantee, Level, - MultiSpan, listify, msg, + Applicability, Diag, DiagCtxtHandle, DiagSymbolList, Diagnostic, Level, MultiSpan, listify, msg, }; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_middle::ty::{self, Ty}; @@ -468,7 +467,7 @@ pub(crate) struct MissingGenericParams { } // FIXME: This doesn't need to be a manual impl! -impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for MissingGenericParams { +impl<'a, G> Diagnostic<'a, G> for MissingGenericParams { #[track_caller] fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G> { let mut err = Diag::new( @@ -2070,7 +2069,7 @@ pub(crate) struct UncoveredTyParam<'tcx> { pub(crate) local_ty: Option>, } -impl Diagnostic<'_, G> for UncoveredTyParam<'_> { +impl Diagnostic<'_, G> for UncoveredTyParam<'_> { fn into_diag(self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_, G> { let Self { param, local_ty } = self; diff --git a/compiler/rustc_hir_analysis/src/diagnostics/wrong_number_of_generic_args.rs b/compiler/rustc_hir_analysis/src/diagnostics/wrong_number_of_generic_args.rs index 8a38207884184..e995d4fdf697b 100644 --- a/compiler/rustc_hir_analysis/src/diagnostics/wrong_number_of_generic_args.rs +++ b/compiler/rustc_hir_analysis/src/diagnostics/wrong_number_of_generic_args.rs @@ -1,6 +1,6 @@ use GenericArgsInfo::*; use rustc_errors::codes::*; -use rustc_errors::{Applicability, Diag, Diagnostic, EmissionGuarantee, MultiSpan, pluralize}; +use rustc_errors::{Applicability, Diag, Diagnostic, MultiSpan, pluralize}; use rustc_hir as hir; use rustc_middle::ty::{self as ty, AssocItem, AssocItems, TyCtxt}; use rustc_span::def_id::DefId; @@ -543,7 +543,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> { } /// Builds the `expected 1 type argument / supplied 2 type arguments` message. - fn notify(&self, err: &mut Diag<'_, impl EmissionGuarantee>) { + fn notify(&self, err: &mut Diag<'_, G>) { let (quantifier, bound) = self.get_quantifier_and_bound(); let provided_args = self.num_provided_args(); @@ -595,7 +595,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> { } } - fn suggest(&self, err: &mut Diag<'_, impl EmissionGuarantee>) { + fn suggest(&self, err: &mut Diag<'_, G>) { debug!( "suggest(self.provided {:?}, self.gen_args.span(): {:?})", self.num_provided_args(), @@ -623,7 +623,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> { /// ```text /// type Map = HashMap; /// ``` - fn suggest_adding_args(&self, err: &mut Diag<'_, impl EmissionGuarantee>) { + fn suggest_adding_args(&self, err: &mut Diag<'_, G>) { if self.gen_args.parenthesized != hir::GenericArgsParentheses::No { return; } @@ -650,7 +650,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> { } } - fn suggest_adding_lifetime_args(&self, err: &mut Diag<'_, impl EmissionGuarantee>) { + fn suggest_adding_lifetime_args(&self, err: &mut Diag<'_, G>) { debug!("suggest_adding_lifetime_args(path_segment: {:?})", self.path_segment); let num_missing_args = self.num_missing_lifetime_args(); let num_params_to_take = num_missing_args; @@ -704,7 +704,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> { } } - fn suggest_adding_type_and_const_args(&self, err: &mut Diag<'_, impl EmissionGuarantee>) { + fn suggest_adding_type_and_const_args(&self, err: &mut Diag<'_, G>) { let num_missing_args = self.num_missing_type_or_const_args(); let msg = format!("add missing {} argument{}", self.kind(), pluralize!(num_missing_args)); @@ -764,10 +764,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> { /// ```compile_fail /// Into::into::>(42) // suggests considering `Into::>::into(42)` /// ``` - fn suggest_moving_args_from_assoc_fn_to_trait( - &self, - err: &mut Diag<'_, impl EmissionGuarantee>, - ) { + fn suggest_moving_args_from_assoc_fn_to_trait(&self, err: &mut Diag<'_, G>) { let Some(trait_) = self.tcx.trait_of_assoc(self.def_id) else { return; }; @@ -820,9 +817,9 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> { } } - fn suggest_moving_args_from_assoc_fn_to_trait_for_qualified_path( + fn suggest_moving_args_from_assoc_fn_to_trait_for_qualified_path( &self, - err: &mut Diag<'_, impl EmissionGuarantee>, + err: &mut Diag<'_, G>, qpath: &'tcx hir::QPath<'tcx>, msg: String, num_assoc_fn_excess_args: usize, @@ -851,9 +848,9 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> { } } - fn suggest_moving_args_from_assoc_fn_to_trait_for_method_call( + fn suggest_moving_args_from_assoc_fn_to_trait_for_method_call( &self, - err: &mut Diag<'_, impl EmissionGuarantee>, + err: &mut Diag<'_, G>, trait_def_id: DefId, expr: &'tcx hir::Expr<'tcx>, msg: String, @@ -907,7 +904,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> { /// ```text /// type Map = HashMap; /// ``` - fn suggest_removing_args_or_generics(&self, err: &mut Diag<'_, impl EmissionGuarantee>) { + fn suggest_removing_args_or_generics(&self, err: &mut Diag<'_, G>) { let num_provided_lt_args = self.num_provided_lifetime_args(); let num_provided_type_const_args = self.num_provided_type_or_const_args(); let unbound_assoc_items = self.get_unbound_associated_item(); @@ -1099,7 +1096,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> { } /// Builds the `type defined here` message. - fn show_definition(&self, err: &mut Diag<'_, impl EmissionGuarantee>) { + fn show_definition(&self, err: &mut Diag<'_, G>) { let Some(def_span) = self.tcx.def_ident_span(self.def_id) else { return }; if !self.tcx.sess.source_map().is_span_accessible(def_span) { return; @@ -1146,7 +1143,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> { } /// Add note if `impl Trait` is explicitly specified. - fn note_synth_provided(&self, err: &mut Diag<'_, impl EmissionGuarantee>) { + fn note_synth_provided(&self, err: &mut Diag<'_, G>) { if !self.is_synth_provided() { return; } @@ -1155,7 +1152,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> { } } -impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for WrongNumberOfGenericArgs<'_, '_> { +impl<'a, G> Diagnostic<'a, G> for WrongNumberOfGenericArgs<'_, '_> { fn into_diag( self, dcx: rustc_errors::DiagCtxtHandle<'a>, diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs index 102a3013b38ad..beacb3f188cd9 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs @@ -2,8 +2,8 @@ use rustc_ast::TraitObjectSyntax; use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; use rustc_errors::codes::*; use rustc_errors::{ - Applicability, Diag, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level, StashKey, - Suggestions, struct_span_code_err, + Applicability, Diag, DiagCtxtHandle, Diagnostic, Level, StashKey, Suggestions, + struct_span_code_err, }; use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::def::{DefKind, Res}; @@ -739,7 +739,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } /// Make sure that we are in the condition to suggest the blanket implementation. - fn maybe_suggest_blanket_trait_impl( + fn maybe_suggest_blanket_trait_impl( &self, span: Span, hir_id: hir::HirId, diff --git a/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs b/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs index 131812a364ebd..ca7e246a9e05b 100644 --- a/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs +++ b/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs @@ -97,12 +97,10 @@ pub(super) fn infer_clauses( } else { "overflow computing implied lifetime bounds".to_string() }; - tcx.dcx() - .struct_span_fatal( - clauses_added.iter().map(|id| tcx.def_span(*id)).collect::>(), - msg, - ) - .emit(); + tcx.dcx().span_fatal( + clauses_added.iter().map(|id| tcx.def_span(*id)).collect::>(), + msg, + ); } } diff --git a/compiler/rustc_hir_typeck/src/diagnostics.rs b/compiler/rustc_hir_typeck/src/diagnostics.rs index 2d4cf3d9b400d..3b7de7790ac02 100644 --- a/compiler/rustc_hir_typeck/src/diagnostics.rs +++ b/compiler/rustc_hir_typeck/src/diagnostics.rs @@ -6,8 +6,8 @@ use rustc_abi::ExternAbi; use rustc_ast::{AssignOpKind, Label}; use rustc_errors::codes::*; use rustc_errors::{ - Applicability, Diag, DiagArgValue, DiagCtxtHandle, DiagSymbolList, Diagnostic, - EmissionGuarantee, IntoDiagArg, Level, MultiSpan, Subdiagnostic, msg, + Applicability, Diag, DiagArgValue, DiagCtxtHandle, DiagSymbolList, Diagnostic, IntoDiagArg, + Level, MultiSpan, Subdiagnostic, msg, }; use rustc_hir as hir; use rustc_hir::ExprKind; @@ -275,7 +275,7 @@ pub(crate) struct SuggestAnnotations { pub suggestions: Vec, } impl Subdiagnostic for SuggestAnnotations { - fn add_to_diag(self, diag: &mut Diag<'_, G>) { + fn add_to_diag(self, diag: &mut Diag<'_, G>) { if self.suggestions.is_empty() { return; } @@ -338,7 +338,7 @@ pub(crate) struct TypeMismatchFruTypo { } impl Subdiagnostic for TypeMismatchFruTypo { - fn add_to_diag(self, diag: &mut Diag<'_, G>) { + fn add_to_diag(self, diag: &mut Diag<'_, G>) { diag.arg("expr", self.expr.as_deref().unwrap_or("NONE")); // Only explain that `a ..b` is a range if it's split up @@ -561,7 +561,7 @@ pub(crate) struct RemoveSemiForCoerce { } impl Subdiagnostic for RemoveSemiForCoerce { - fn add_to_diag(self, diag: &mut Diag<'_, G>) { + fn add_to_diag(self, diag: &mut Diag<'_, G>) { let mut multispan: MultiSpan = self.semi.into(); multispan.push_span_label( self.expr, @@ -704,7 +704,7 @@ pub(crate) struct BreakNonLoop<'a> { pub break_expr_span: Span, } -impl<'a, G: EmissionGuarantee> Diagnostic<'_, G> for BreakNonLoop<'a> { +impl<'a, G> Diagnostic<'_, G> for BreakNonLoop<'a> { #[track_caller] fn into_diag(self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_, G> { let mut diag = Diag::new(dcx, level, msg!("`break` with value from a `{$kind}` loop")); @@ -906,7 +906,7 @@ pub(crate) enum CastUnknownPointerSub { } impl rustc_errors::Subdiagnostic for CastUnknownPointerSub { - fn add_to_diag(self, diag: &mut Diag<'_, G>) { + fn add_to_diag(self, diag: &mut Diag<'_, G>) { match self { CastUnknownPointerSub::To(span) => { let msg = msg!("needs more type information"); @@ -1202,7 +1202,7 @@ pub(crate) struct NakedFunctionsAsmBlock { pub non_asms: Vec, } -impl Diagnostic<'_, G> for NakedFunctionsAsmBlock { +impl Diagnostic<'_, G> for NakedFunctionsAsmBlock { #[track_caller] fn into_diag(self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_, G> { let mut diag = Diag::new( diff --git a/compiler/rustc_hir_typeck/src/intrinsicck.rs b/compiler/rustc_hir_typeck/src/intrinsicck.rs index d63bffab88221..989c63ac2f34b 100644 --- a/compiler/rustc_hir_typeck/src/intrinsicck.rs +++ b/compiler/rustc_hir_typeck/src/intrinsicck.rs @@ -78,7 +78,7 @@ fn check_transmute<'tcx>( let normalize = |ty: Unnormalized<'tcx, Ty<'tcx>>| -> Result, ErrorGuaranteed> { tcx.try_normalize_erasing_regions(typing_env, ty).map_err(|err| { let err = LayoutError::NormalizationFailure(ty.skip_normalization(), err); - tcx.dcx().struct_span_err(span, err.to_string()).emit() + tcx.dcx().span_err(span, err.to_string()) }) }; diff --git a/compiler/rustc_incremental/src/persist/fs.rs b/compiler/rustc_incremental/src/persist/fs.rs index de543ef0c53bc..5254123b1ca11 100644 --- a/compiler/rustc_incremental/src/persist/fs.rs +++ b/compiler/rustc_incremental/src/persist/fs.rs @@ -702,29 +702,6 @@ pub(crate) fn garbage_collect_session_directories( lock_file_to_session_dir.items().filter_map(|(lock_file_name, directory_name)| { debug!("garbage_collect_session_directories() - inspecting: {}", directory_name); - if directory_name.as_str() == current_session_directory_name { - // Skipping our own directory is, unfortunately, important for correctness. - // - // To summarize #147821: we will try to lock directories before deciding they can be - // garbage collected, but the ability of `flock::Lock` to detect a lock held *by the - // same process* varies across file locking APIs. Then, if our own session directory - // has become old enough to be eligible for GC, we are beholden to platform-specific - // details about detecting the our own lock on the session directory. - // - // POSIX `fcntl(F_SETLK)`-style file locks are maintained across a process. On - // systems where this is the mechanism for `flock::Lock`, there is no way to - // discover if an `flock::Lock` has been created in the same process on the same - // file. Attempting to set a lock on the lockfile again will succeed, even if the - // lock was set by another thread, on another file descriptor. Then we would - // garbage collect our own live directory, unable to tell it was locked perhaps by - // this same thread. - // - // It's not clear that `flock::Lock` can be fixed for this in general, and our own - // incremental session directory is the only one which this process may own, so skip - // it here and avoid the problem. We know it's not garbage anyway: we're using it. - return None; - } - let Ok(timestamp) = extract_timestamp_from_session_dir(directory_name) else { debug!( "found session-dir with malformed timestamp: {}", @@ -768,6 +745,31 @@ pub(crate) fn garbage_collect_session_directories( } } } else if is_old_enough_to_be_collected(timestamp) { + if directory_name.as_str() == current_session_directory_name { + // Skipping our own active directory is important for correctness. + // + // To summarize #147821: we will try to lock directories before deciding they can be + // garbage collected, but the ability of `flock::Lock` to detect a lock held *by the + // same process* varies across file locking APIs. Then, if our own session directory + // has become old enough to be eligible for GC, we are beholden to platform-specific + // details about detecting the our own lock on the session directory. + // + // POSIX `fcntl(F_SETLK)`-style file locks are maintained across a process. On + // systems where this is the mechanism for `flock::Lock`, there is no way to + // discover if an `flock::Lock` has been created in the same process on the same + // file. Attempting to set a lock on the lockfile again will succeed, even if the + // lock was set by another thread, on another file descriptor. Then we would + // garbage collect our own live directory, unable to tell it was locked perhaps by + // this same thread. + // + // It's not clear that `flock::Lock` can be fixed for this in general, and our own + // incremental session directory is the only one which this process may own, so skip + // it here and avoid the problem. We know it's not garbage anyway: we're using it. + // Once finalized, its lock is released. Include it in collection so we keep + // the newest completed session. + return None; + } + // When cleaning out "-working" session directories, i.e. // session directories that might still be in use by another // compiler instance, we only look a directories that are @@ -818,6 +820,10 @@ pub(crate) fn garbage_collect_session_directories( // Delete all but the most recent of the candidates all_except_most_recent(deletion_candidates).into_items().all(|(path, lock)| { + if path.file_name() == Some(current_session_directory_name) { + return true; + } + debug!("garbage_collect_session_directories() - deleting `{}`", path.display()); if let Err(err) = std_fs::remove_dir_all(&path) { diff --git a/compiler/rustc_lint/src/diagnostics.rs b/compiler/rustc_lint/src/diagnostics.rs index cfae7afd8f4f3..d96cadaca87eb 100644 --- a/compiler/rustc_lint/src/diagnostics.rs +++ b/compiler/rustc_lint/src/diagnostics.rs @@ -5,8 +5,8 @@ use rustc_data_structures::fx::FxIndexMap; use rustc_errors::codes::*; use rustc_errors::formatting::DiagMessageAddArg; use rustc_errors::{ - Applicability, Diag, DiagCtxtHandle, DiagMessage, DiagStyledString, Diagnostic, - EmissionGuarantee, Level, Subdiagnostic, SuggestionStyle, msg, + Applicability, Diag, DiagCtxtHandle, DiagMessage, DiagStyledString, Diagnostic, Level, + Subdiagnostic, SuggestionStyle, msg, }; use rustc_hir as hir; use rustc_hir::def_id::DefId; @@ -42,7 +42,7 @@ pub(crate) enum OverruledAttributeSub { } impl Subdiagnostic for OverruledAttributeSub { - fn add_to_diag(self, diag: &mut Diag<'_, G>) { + fn add_to_diag(self, diag: &mut Diag<'_, G>) { match self { OverruledAttributeSub::DefaultSource { id } => { diag.note(msg!("`forbid` lint level is the default for {$id}")); @@ -638,7 +638,7 @@ pub(crate) struct BuiltinUnpermittedTypeInitSub { } impl Subdiagnostic for BuiltinUnpermittedTypeInitSub { - fn add_to_diag(self, diag: &mut Diag<'_, G>) { + fn add_to_diag(self, diag: &mut Diag<'_, G>) { let mut err = self.err; loop { if let Some(span) = err.span { @@ -689,7 +689,7 @@ pub(crate) struct BuiltinClashingExternSub<'a> { } impl Subdiagnostic for BuiltinClashingExternSub<'_> { - fn add_to_diag(self, diag: &mut Diag<'_, G>) { + fn add_to_diag(self, diag: &mut Diag<'_, G>) { let mut expected_str = DiagStyledString::new(); expected_str.push(self.expected.fn_sig(self.tcx).to_string(), false); let mut found_str = DiagStyledString::new(); @@ -1363,7 +1363,7 @@ pub(crate) struct NonBindingLetSub { } impl Subdiagnostic for NonBindingLetSub { - fn add_to_diag(self, diag: &mut Diag<'_, G>) { + fn add_to_diag(self, diag: &mut Diag<'_, G>) { let can_suggest_binding = self.drop_fn_start_end.is_some() || !self.is_assign_desugar; if can_suggest_binding { @@ -1740,7 +1740,7 @@ pub(crate) enum NonSnakeCaseDiagSub { } impl Subdiagnostic for NonSnakeCaseDiagSub { - fn add_to_diag(self, diag: &mut Diag<'_, G>) { + fn add_to_diag(self, diag: &mut Diag<'_, G>) { match self { NonSnakeCaseDiagSub::Label { span } => { diag.span_label(span, msg!("should have a snake_case name")); @@ -2924,7 +2924,7 @@ pub(crate) struct MismatchedLifetimeSyntaxes { pub suggestions: Vec, } -impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for MismatchedLifetimeSyntaxes { +impl<'a, G> Diagnostic<'a, G> for MismatchedLifetimeSyntaxes { fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G> { let counts = self.inputs.len() + self.outputs.len(); let message = match counts { @@ -3037,7 +3037,7 @@ impl MismatchedLifetimeSyntaxesSuggestion { } impl Subdiagnostic for MismatchedLifetimeSyntaxesSuggestion { - fn add_to_diag(self, diag: &mut Diag<'_, G>) { + fn add_to_diag(self, diag: &mut Diag<'_, G>) { use MismatchedLifetimeSyntaxesSuggestion::*; let style = |optional_alternative| { diff --git a/compiler/rustc_lint/src/if_let_rescope.rs b/compiler/rustc_lint/src/if_let_rescope.rs index 47a3f528b9854..1cd701db7d10e 100644 --- a/compiler/rustc_lint/src/if_let_rescope.rs +++ b/compiler/rustc_lint/src/if_let_rescope.rs @@ -3,7 +3,7 @@ use std::ops::ControlFlow; use hir::intravisit::{self, Visitor}; use rustc_ast::Recovered; -use rustc_errors::{Applicability, Diag, EmissionGuarantee, Subdiagnostic, SuggestionStyle, msg}; +use rustc_errors::{Applicability, Diag, Subdiagnostic, SuggestionStyle, msg}; use rustc_hir::{self as hir, HirIdSet}; use rustc_lint_defs::{LintId, declare_lint, fcw, impl_lint_pass}; use rustc_macros::{Diagnostic, Subdiagnostic}; @@ -324,7 +324,7 @@ struct IfLetRescopeRewrite { } impl Subdiagnostic for IfLetRescopeRewrite { - fn add_to_diag(self, diag: &mut Diag<'_, G>) { + fn add_to_diag(self, diag: &mut Diag<'_, G>) { let mut suggestions = vec![]; for match_head in self.match_heads { match match_head { diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index e1184d91377be..7769f59210d56 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -17,6 +17,7 @@ pub mod hardwired { // tidy-alphabetical-start AARCH64_SOFTFLOAT_NEON, ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE, + ALIGNED_FIELDS_IN_PACKED, AMBIGUOUS_ASSOCIATED_ITEMS, AMBIGUOUS_DERIVE_HELPERS, AMBIGUOUS_GLOB_IMPORTED_TRAITS, @@ -5824,3 +5825,32 @@ declare_lint! { "duplicate tools found in crate-level `#[register_tools]` directives", @feature_gate = register_tool; } + +declare_lint! { + /// The `aligned_fields_in_packed` lint detects fields with `align` representation hints + /// inside `repr(C)` types with `packed` representation hint. + /// + /// ### Example + /// + /// ```rust,compile_fail + /// #[repr(C, align(16))] + /// struct Aligned(i32); + /// + /// #[repr(C, packed)] // error! + /// struct Packed(Aligned); + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// The behavior of this combination of hints is inconsistent across C compilers. The layout + /// computed for these types by Rust may thus not match the layout actually used by C. + /// Specifically, Rust always follows the GCC convention, which makes it incompatible with MSVC + /// for these types. This may change in the future for targets where GCC is not the default C + /// compiler. + pub ALIGNED_FIELDS_IN_PACKED, + Deny, + "`repr(C, align)` types nested inside `repr(C, packed)` types \ + do not always have a C-compatible layout", +} diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp index 1bd5094c38f02..d181891cdfa54 100644 --- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp @@ -89,15 +89,31 @@ extern "C" void LLVMRustTimeTraceProfilerFinish(const char *FileName) { timeTraceProfilerCleanup(); } -extern "C" bool LLVMRustHasFeature(LLVMTargetMachineRef TM, - const char *Feature) { - TargetMachine *Target = unwrap(TM); -#if LLVM_VERSION_GE(23, 0) - const MCSubtargetInfo &MCInfo = Target->getMCSubtargetInfo(); +extern "C" MCSubtargetInfo * +LLVMRustCreateMCSubtargetInfo(const char *TripleStr, const char *CPU, + const char *Features) { + std::string Error; + auto Trip = Triple(Triple::normalize(TripleStr)); + const llvm::Target *TheTarget = TargetRegistry::lookupTarget(Trip, Error); + if (TheTarget == nullptr) { + LLVMRustSetLastError(Error.c_str()); + return nullptr; + } + +#if LLVM_VERSION_GE(22, 0) + return TheTarget->createMCSubtargetInfo(Trip, CPU, Features); #else - const MCSubtargetInfo &MCInfo = *Target->getMCSubtargetInfo(); + return TheTarget->createMCSubtargetInfo(Trip.str(), CPU, Features); #endif - return MCInfo.checkFeatures(std::string("+") + Feature); +} + +extern "C" bool LLVMRustMCSubtargetInfoHasFeature(MCSubtargetInfo *MCInfo, + const char *Feature) { + return MCInfo->checkFeatures(std::string("+") + Feature); +} + +extern "C" void LLVMRustDisposeMCSubtargetInfo(MCSubtargetInfo *MCInfo) { + delete MCInfo; } /// Check whether the target has a specific assembly mnemonic like `ret` or diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic.rs b/compiler/rustc_macros/src/diagnostics/diagnostic.rs index ac777b37a4303..72e7423fc2d88 100644 --- a/compiler/rustc_macros/src/diagnostics/diagnostic.rs +++ b/compiler/rustc_macros/src/diagnostics/diagnostic.rs @@ -48,9 +48,7 @@ impl<'a> DiagnosticDerive<'a> { // A lifetime of `'a` causes conflicts, but `_sess` is fine. structure.gen_impl(quote! { - gen impl<'_sess, G> rustc_errors::Diagnostic<'_sess, G> for @Self - where G: rustc_errors::EmissionGuarantee - { + gen impl<'_sess, G> rustc_errors::Diagnostic<'_sess, G> for @Self { #[track_caller] fn into_diag( self, diff --git a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs index c99575ff7431d..d6b101ca0addf 100644 --- a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs +++ b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs @@ -97,9 +97,7 @@ impl SubdiagnosticDerive { fn add_to_diag<__G>( self, #diag: &mut rustc_errors::Diag<'_, __G>, - ) where - __G: rustc_errors::EmissionGuarantee, - { + ) { #implementation } } diff --git a/compiler/rustc_metadata/src/diagnostics.rs b/compiler/rustc_metadata/src/diagnostics.rs index b98a0ce25af37..a093e7990ea28 100644 --- a/compiler/rustc_metadata/src/diagnostics.rs +++ b/compiler/rustc_metadata/src/diagnostics.rs @@ -2,7 +2,7 @@ use std::io::Error; use std::path::{Path, PathBuf}; use rustc_errors::codes::*; -use rustc_errors::{Diag, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level, msg}; +use rustc_errors::{Diag, DiagCtxtHandle, Diagnostic, Level, msg}; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_span::{Span, Symbol, sym}; use rustc_target::spec::{PanicStrategy, TargetTuple}; @@ -305,7 +305,7 @@ pub(crate) struct MultipleCandidates { pub candidates: Vec, } -impl Diagnostic<'_, G> for MultipleCandidates { +impl Diagnostic<'_, G> for MultipleCandidates { fn into_diag(self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_, G> { let mut diag = Diag::new( dcx, @@ -418,7 +418,7 @@ pub(crate) struct InvalidMetadataFiles { pub crate_rejections: Vec, } -impl Diagnostic<'_, G> for InvalidMetadataFiles { +impl Diagnostic<'_, G> for InvalidMetadataFiles { #[track_caller] fn into_diag(self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_, G> { let mut diag = Diag::new( @@ -450,7 +450,7 @@ pub(crate) struct CannotFindCrate { pub is_tier_3: bool, } -impl Diagnostic<'_, G> for CannotFindCrate { +impl Diagnostic<'_, G> for CannotFindCrate { #[track_caller] fn into_diag(self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_, G> { let mut diag = diff --git a/compiler/rustc_middle/src/middle/stability.rs b/compiler/rustc_middle/src/middle/stability.rs index 8dafdc9cc7d33..2ad73c8894da5 100644 --- a/compiler/rustc_middle/src/middle/stability.rs +++ b/compiler/rustc_middle/src/middle/stability.rs @@ -7,7 +7,7 @@ use rustc_ast::NodeId; use rustc_attr_ir::{ ConstStability, DefaultBodyStability, DeprecatedSince, Deprecation, Stability, StabilityLevel, }; -use rustc_errors::{Applicability, Diag, Diagnostic, EmissionGuarantee, LintBuffer, msg}; +use rustc_errors::{Applicability, Diag, Diagnostic, LintBuffer, msg}; use rustc_feature::GateIssue; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::{self as hir, HirId}; @@ -114,7 +114,7 @@ pub(crate) struct Deprecated { pub since_kind: DeprecatedSinceKind, } -impl<'a, G: EmissionGuarantee> rustc_errors::Diagnostic<'a, G> for Deprecated { +impl<'a, G> rustc_errors::Diagnostic<'a, G> for Deprecated { fn into_diag( self, dcx: rustc_errors::DiagCtxtHandle<'a>, diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index 01614692c9ed2..f88b7ff0f8a85 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -13,7 +13,7 @@ use std::borrow::Cow; use std::hash::{Hash, Hasher}; use std::sync::Arc; -use rustc_errors::{Applicability, Diag, EmissionGuarantee, ErrorGuaranteed}; +use rustc_errors::{Applicability, Diag, ErrorGuaranteed}; use rustc_hir as hir; use rustc_hir::HirId; use rustc_hir::def_id::DefId; @@ -914,7 +914,7 @@ pub enum DynCompatibilityViolationSolution { } impl DynCompatibilityViolationSolution { - pub fn add_to(self, err: &mut Diag<'_, G>) { + pub fn add_to(self, err: &mut Diag<'_, G>) { match self { DynCompatibilityViolationSolution::None => {} DynCompatibilityViolationSolution::AddSelfOrMakeSized { diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 9242d7101e916..71fb96ac43575 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -2622,9 +2622,9 @@ impl<'tcx> TyCtxt<'tcx> { m.spans.inject_use_span.shrink_to_lo() } - pub fn disabled_nightly_features( + pub fn disabled_nightly_features( self, - diag: &mut Diag<'_, E>, + diag: &mut Diag<'_, G>, features: impl IntoIterator, ) { if !self.sess.is_nightly_build() { diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 85e1df8b057a0..7006568a2ef33 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -6,9 +6,7 @@ use rustc_abi::{ PointerKind, Primitive, ReprFlags, ReprOptions, Scalar, Size, TagEncoding, TargetDataLayout, TyAbiInterface, VariantIdx, Variants, }; -use rustc_errors::{ - Diag, DiagArgValue, DiagCtxtHandle, Diagnostic, EmissionGuarantee, IntoDiagArg, Level, -}; +use rustc_errors::{Diag, DiagArgValue, DiagCtxtHandle, Diagnostic, IntoDiagArg, Level}; use rustc_hir as hir; use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::def_id::DefId; @@ -1344,7 +1342,7 @@ pub enum FnAbiError<'tcx> { Layout(LayoutError<'tcx>), } -impl<'a, 'b, G: EmissionGuarantee> Diagnostic<'a, G> for FnAbiError<'b> { +impl<'a, 'b, G> Diagnostic<'a, G> for FnAbiError<'b> { fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G> { match self { Self::Layout(e) => Diag::new(dcx, level, e.to_string()), diff --git a/compiler/rustc_mir_build/src/diagnostics.rs b/compiler/rustc_mir_build/src/diagnostics.rs index 154edfdf4a577..83bfd322d6444 100644 --- a/compiler/rustc_mir_build/src/diagnostics.rs +++ b/compiler/rustc_mir_build/src/diagnostics.rs @@ -1,7 +1,7 @@ use rustc_errors::codes::*; use rustc_errors::{ - Applicability, Diag, DiagArgValue, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level, - MultiSpan, Subdiagnostic, msg, + Applicability, Diag, DiagArgValue, DiagCtxtHandle, Diagnostic, Level, MultiSpan, Subdiagnostic, + msg, }; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_middle::ty::{self, Ty}; @@ -585,7 +585,7 @@ pub(crate) struct UnsafeNotInheritedLintNote { } impl Subdiagnostic for UnsafeNotInheritedLintNote { - fn add_to_diag(self, diag: &mut Diag<'_, G>) { + fn add_to_diag(self, diag: &mut Diag<'_, G>) { diag.span_note( self.signature_span, msg!("an unsafe function restricts its caller, but its body is safe by default"), @@ -625,7 +625,7 @@ pub(crate) struct NonExhaustivePatternsTypeNotEmpty<'a, 'tcx> { pub(crate) ty: Ty<'tcx>, } -impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for NonExhaustivePatternsTypeNotEmpty<'_, '_> { +impl<'a, G> Diagnostic<'a, G> for NonExhaustivePatternsTypeNotEmpty<'_, '_> { fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G> { let mut diag = Diag::new(dcx, level, msg!("non-exhaustive patterns: type `{$ty}` is non-empty")); @@ -730,7 +730,7 @@ pub(crate) struct UnreachablePattern<'tcx> { pub(crate) inner: UnreachablePatternInner<'tcx>, } -impl<'a, 'tcx, G: EmissionGuarantee> Diagnostic<'a, G> for UnreachablePattern<'tcx> { +impl<'a, 'tcx, G> Diagnostic<'a, G> for UnreachablePattern<'tcx> { #[track_caller] fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G> { let mut diag = self.inner.into_diag(dcx, level); @@ -1260,7 +1260,7 @@ pub(crate) struct Variant { } impl<'tcx> Subdiagnostic for AdtDefinedHere<'tcx> { - fn add_to_diag(self, diag: &mut Diag<'_, G>) { + fn add_to_diag(self, diag: &mut Diag<'_, G>) { diag.arg("ty", self.ty); let mut spans = MultiSpan::from(self.adt_def_span); diff --git a/compiler/rustc_mir_build/src/thir/pattern/migration.rs b/compiler/rustc_mir_build/src/thir/pattern/migration.rs index 75e23c3a2ff16..e6db030557703 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/migration.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/migration.rs @@ -1,7 +1,7 @@ //! Automatic migration of Rust 2021 patterns to a form valid in both Editions 2021 and 2024. use rustc_data_structures::fx::FxIndexMap; -use rustc_errors::{Applicability, Diag, EmissionGuarantee, MultiSpan, pluralize}; +use rustc_errors::{Applicability, Diag, MultiSpan, pluralize}; use rustc_hir::{BindingMode, ByRef, HirId, Mutability}; use rustc_lint_defs::builtin::RUST_2024_INCOMPATIBLE_PAT; use rustc_middle::ty::{self, Rust2024IncompatiblePatInfo, TyCtxt}; @@ -90,7 +90,7 @@ impl<'a> PatMigration<'a> { format!("cannot {verb1}{or_verb2} within an implicitly-borrowing pattern{in_rust_2024}") } - fn format_subdiagnostics(self, diag: &mut Diag<'_, impl EmissionGuarantee>) { + fn format_subdiagnostics(self, diag: &mut Diag<'_, G>) { // Format and emit explanatory notes about default binding modes. Reversing the spans' order // means if we have nested spans, the innermost ones will be visited first. for (span, def_br_mutbl) in self.default_mode_labels.into_iter().rev() { diff --git a/compiler/rustc_mir_transform/src/diagnostics.rs b/compiler/rustc_mir_transform/src/diagnostics.rs index e9150049c6741..c851b55f9623a 100644 --- a/compiler/rustc_mir_transform/src/diagnostics.rs +++ b/compiler/rustc_mir_transform/src/diagnostics.rs @@ -1,7 +1,6 @@ use rustc_errors::codes::*; use rustc_errors::{ - Applicability, Diag, DiagCtxtHandle, DiagSymbolList, Diagnostic, EmissionGuarantee, Level, - Subdiagnostic, msg, + Applicability, Diag, DiagCtxtHandle, DiagSymbolList, Diagnostic, Level, Subdiagnostic, msg, }; use rustc_lint_defs::Lint; use rustc_lint_defs::builtin::{ARITHMETIC_OVERFLOW, UNCONDITIONAL_PANIC}; @@ -219,7 +218,7 @@ pub(crate) struct UnusedAssignOverwrite { } impl Subdiagnostic for UnusedAssignOverwrite { - fn add_to_diag(self, diag: &mut Diag<'_, G>) { + fn add_to_diag(self, diag: &mut Diag<'_, G>) { diag.span_label(self.assigned_span, "this value is reassigned later and never used"); diag.span_label( self.overwrite_span, @@ -298,7 +297,7 @@ pub(crate) struct UnusedVariableStringInterp { } impl Subdiagnostic for UnusedVariableStringInterp { - fn add_to_diag(self, diag: &mut Diag<'_, G>) { + fn add_to_diag(self, diag: &mut Diag<'_, G>) { diag.span_label( self.lit, msg!("you might have meant to use string interpolation in this string literal"), diff --git a/compiler/rustc_mir_transform/src/lint_tail_expr_drop_order.rs b/compiler/rustc_mir_transform/src/lint_tail_expr_drop_order.rs index eb6921e438528..0b8cdbb2d2696 100644 --- a/compiler/rustc_mir_transform/src/lint_tail_expr_drop_order.rs +++ b/compiler/rustc_mir_transform/src/lint_tail_expr_drop_order.rs @@ -524,7 +524,7 @@ struct LocalLabel<'a> { /// A custom `Subdiagnostic` implementation so that the notes are delivered in a specific order impl Subdiagnostic for LocalLabel<'_> { - fn add_to_diag(self, diag: &mut rustc_errors::Diag<'_, G>) { + fn add_to_diag(self, diag: &mut rustc_errors::Diag<'_, G>) { diag.span_label( self.span, msg!( diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs index c5665246710a3..3a4875c1d0951 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs @@ -1614,74 +1614,7 @@ where r.retain(|(outlives, _)| !outlives.is_trivial() && unique.insert(*outlives)); } - #[derive(Default)] - struct NonTrivialVars { - vars: HashSet, - } - impl TypeVisitor for NonTrivialVars - where - I: Interner, - { - type Result = (); - fn visit_ty(&mut self, t: I::Ty) { - // If a nested type doesn't have any `ReVar`s, then we won't insert - // anything into `vars` anyway, so skip for better perf. - if !t.has_infer_regions() { - return; - } - t.super_visit_with(self); - } - fn visit_const(&mut self, c: I::Const) { - // The same goes for consts. - if !c.has_infer_regions() { - return; - } - c.super_visit_with(self); - } - fn visit_region(&mut self, r: Region) { - if let ty::ReVar(vid) = r.kind() { - self.vars.insert(vid); - } - } - } - - // If we have a constraint like `'re: '?1`, where '?1 can name 're and '?1 appears - // only on the RHS of region constraints, then this kind of constraint is also trivial, - // since we're able to pick '?1 := 'empty, and 're: 'empty is always true for any 're. - if let ExternalRegionConstraints::Old(r) = &mut external_constraints.region_constraints - && !r.is_empty() - { - let mut vis = NonTrivialVars::default(); - var_values.visit_with(&mut vis); - // We have to visit each component of `external_constraints` individually here - // because we skip the RHS of outlives constraints, and `TypeVisitor` doesn't - // have a method we can easily override in order to do this. - external_constraints.opaque_types.visit_with(&mut vis); - external_constraints.normalization_nested_goals.visit_with(&mut vis); - for (constraint, _) in r.iter() { - match constraint { - ty::RegionConstraint::Outlives(ty::OutlivesClause(sup, _)) => { - sup.visit_with(&mut vis) - } - ty::RegionConstraint::Eq(eq) => eq.visit_with(&mut vis), - } - } - - r.retain(|(outlives, _)| { - if let ty::RegionConstraint::Outlives(ty::OutlivesClause(sup, re)) = *outlives - && let Some(sup_re) = sup.as_region() - && let ty::RegionKind::ReVar(vid) = re.kind() - // This is only safe if we call `eager_resolve_vars` beforehand, - // which we do. - && self.delegate.universe_of_region(vid).unwrap() - .can_name(max_universe(&**self.delegate, sup_re)) - { - vis.vars.contains(&vid) - } else { - true - } - }); - } + filter_irrelevant_region_constraints(self.delegate, &var_values, &mut external_constraints); let canonical = canonicalize_response( self.delegate, @@ -1802,6 +1735,88 @@ where } } +fn filter_irrelevant_region_constraints( + delegate: &D, + var_values: &CanonicalVarValues, + external_constraints: &mut ExternalConstraintsData, +) where + D: SolverDelegate, + I: Interner, +{ + #[derive(Default)] + struct NonTrivialVars { + vars: HashSet, + } + impl TypeVisitor for NonTrivialVars + where + I: Interner, + { + type Result = (); + fn visit_ty(&mut self, t: I::Ty) { + // If a nested type doesn't have any `ReVar`s, then we won't insert + // anything into `vars` anyway, so skip for better perf. + if !t.has_infer_regions() { + return; + } + t.super_visit_with(self); + } + fn visit_const(&mut self, c: I::Const) { + // The same goes for consts. + if !c.has_infer_regions() { + return; + } + c.super_visit_with(self); + } + fn visit_region(&mut self, r: Region) { + if let ty::ReVar(vid) = r.kind() { + self.vars.insert(vid); + } + } + } + + let ExternalConstraintsData { region_constraints, opaque_types, normalization_nested_goals } = + external_constraints; + + // If we have a constraint like `'re: '?1`, where '?1 can name 're and '?1 appears + // only on the RHS of region constraints, then this kind of constraint is also trivial, + // since we're able to pick '?1 := glb('re, other_regions), and by definition of glb, + // `'re: glb`. + if let ExternalRegionConstraints::Old(r) = region_constraints + && !r.is_empty() + { + let mut vis = NonTrivialVars::default(); + var_values.visit_with(&mut vis); + // We have to visit each component of `external_constraints` individually here + // because we skip the RHS of outlives constraints, and `TypeVisitor` doesn't + // have a method we can easily override in order to do this. + opaque_types.visit_with(&mut vis); + normalization_nested_goals.visit_with(&mut vis); + for (constraint, _) in r.iter() { + match constraint { + ty::RegionConstraint::Outlives(ty::OutlivesClause(sup, _)) => { + sup.visit_with(&mut vis) + } + ty::RegionConstraint::Eq(eq) => eq.visit_with(&mut vis), + } + } + + r.retain(|(outlives, _)| { + if let ty::RegionConstraint::Outlives(ty::OutlivesClause(sup, re)) = *outlives + && let Some(sup_re) = sup.as_region() + && let ty::RegionKind::ReVar(vid) = re.kind() + // This is only safe if we call `eager_resolve_vars` before calling, + // this function, which we do. + && delegate.universe_of_region(vid).unwrap() + .can_name(max_universe(&**delegate, sup_re)) + { + vis.vars.contains(&vid) + } else { + true + } + }); + } +} + #[derive(Debug)] enum RerunDecision { Yes, diff --git a/compiler/rustc_parse/src/diagnostics.rs b/compiler/rustc_parse/src/diagnostics.rs index 1dc2d625fe0e0..829fc5a600e8a 100644 --- a/compiler/rustc_parse/src/diagnostics.rs +++ b/compiler/rustc_parse/src/diagnostics.rs @@ -7,8 +7,8 @@ use rustc_ast::token::{self, InvisibleOrigin, MetaVarKind, Token}; use rustc_ast_pretty::pprust; use rustc_errors::codes::*; use rustc_errors::{ - Applicability, Diag, DiagArgValue, DiagCtxtHandle, Diagnostic, EmissionGuarantee, IntoDiagArg, - Level, Subdiagnostic, SuggestionStyle, msg, + Applicability, Diag, DiagArgValue, DiagCtxtHandle, Diagnostic, IntoDiagArg, Level, + Subdiagnostic, SuggestionStyle, msg, }; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_span::edition::{Edition, LATEST_STABLE_EDITION}; @@ -1537,7 +1537,7 @@ pub(crate) struct ExpectedIdentifier { pub help_cannot_start_number: Option, } -impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for ExpectedIdentifier { +impl<'a, G> Diagnostic<'a, G> for ExpectedIdentifier { #[track_caller] fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G> { let token_descr = TokenDescription::from_token(&self.token); @@ -1603,7 +1603,7 @@ pub(crate) struct ExpectedSemi { pub sugg: ExpectedSemiSugg, } -impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for ExpectedSemi { +impl<'a, G> Diagnostic<'a, G> for ExpectedSemi { #[track_caller] fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G> { let token_descr = TokenDescription::from_token(&self.token); @@ -2010,7 +2010,7 @@ pub(crate) struct FnTraitMissingParen { } impl Subdiagnostic for FnTraitMissingParen { - fn add_to_diag(self, diag: &mut Diag<'_, G>) { + fn add_to_diag(self, diag: &mut Diag<'_, G>) { diag.span_label(self.span, msg!("`Fn` bounds require arguments in parentheses")); diag.span_suggestion_short( self.span.shrink_to_hi(), @@ -3697,7 +3697,7 @@ pub(crate) struct UseDerefMacro { } impl Subdiagnostic for UseDerefMacro { - fn add_to_diag(self, diag: &mut Diag<'_, G>) { + fn add_to_diag(self, diag: &mut Diag<'_, G>) { let Self { field, before, after } = self; let mut parts = Vec::new(); @@ -4355,7 +4355,7 @@ pub(crate) struct HiddenUnicodeCodepointsDiagLabels { } impl Subdiagnostic for HiddenUnicodeCodepointsDiagLabels { - fn add_to_diag(self, diag: &mut Diag<'_, G>) { + fn add_to_diag(self, diag: &mut Diag<'_, G>) { for (c, span) in self.spans { diag.span_label(span, format!("{c:?}")); } @@ -4369,7 +4369,7 @@ pub(crate) enum HiddenUnicodeCodepointsDiagSub { // Used because of multiple multipart_suggestion and note impl Subdiagnostic for HiddenUnicodeCodepointsDiagSub { - fn add_to_diag(self, diag: &mut Diag<'_, G>) { + fn add_to_diag(self, diag: &mut Diag<'_, G>) { match self { HiddenUnicodeCodepointsDiagSub::Escape { spans } => { diag.multipart_suggestion_with_style( diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs index 6ed61a9f4e01d..2afb55b02e2e6 100644 --- a/compiler/rustc_parse/src/lexer/mod.rs +++ b/compiler/rustc_parse/src/lexer/mod.rs @@ -1007,7 +1007,7 @@ impl<'psess, 'src> Lexer<'psess, 'src> { err.emit() } - fn report_unterminated_block_comment(&self, start: BytePos, doc_style: Option) { + fn report_unterminated_block_comment(&self, start: BytePos, doc_style: Option) -> ! { let msg = match doc_style { Some(_) => "unterminated block doc-comment", None => "unterminated block comment", diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs index 539c15f18a9a4..16a438b5387ee 100644 --- a/compiler/rustc_parse/src/lib.rs +++ b/compiler/rustc_parse/src/lib.rs @@ -17,7 +17,7 @@ use rustc_ast as ast; use rustc_ast::token; use rustc_ast::tokenstream::{DelimSpacing, DelimSpan, Spacing, TokenStream, TokenTree}; use rustc_ast_pretty::pprust; -use rustc_errors::{Diag, EmissionGuarantee, FatalError, PResult, pluralize}; +use rustc_errors::{Diag, FatalError, PResult, pluralize}; pub use rustc_lexer::UNICODE_VERSION; use rustc_session::parse::ParseSess; use rustc_span::edit_distance::find_best_match_for_name; @@ -165,11 +165,11 @@ pub fn new_parser_from_file<'a>( new_parser_from_source_file(psess, source_file, strip_tokens) } -pub fn utf8_error( +pub fn utf8_error( sm: &SourceMap, path: &str, sp: Option, - err: &mut Diag<'_, E>, + err: &mut Diag<'_, G>, utf8err: Utf8Error, contents: &[u8], ) { diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 6d4a0215eb7b3..5a2540f05c53b 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -1720,7 +1720,7 @@ impl<'a> Parser<'a> { ); err.span_label(op_span, format!("not a valid {} operator", kind.fixity)); - let help_base_case = |mut err: Diag<'_, _>, base| { + let help_base_case = |mut err: Diag<'_, ErrorGuaranteed>, base| { err.help(format!("use `{}= 1` instead", kind.op.chr())); err.emit(); Ok(base) @@ -2379,6 +2379,7 @@ impl<'a> Parser<'a> { target: match context { FnContext::Trait => "methods without bodies", FnContext::FunctionPtrType => "function pointer types", + FnContext::ParenthesizedArgumentList => "parenthesized argument list", FnContext::Free => unreachable!("This method is not called in free functions, as patterns are always allowed there"), FnContext::Impl => unreachable!("This method is not called in impls, as patterns are always allowed there"), }, diff --git a/compiler/rustc_parse/src/parser/function.rs b/compiler/rustc_parse/src/parser/function.rs index 57fe19226066c..220cc5a3bc069 100644 --- a/compiler/rustc_parse/src/parser/function.rs +++ b/compiler/rustc_parse/src/parser/function.rs @@ -103,6 +103,8 @@ pub(crate) enum FnContext { Free, /// A Function Pointer Type `fn(..)`. FunctionPtrType, + /// A Parenthesized Argument List `impl Fn(...)` + ParenthesizedArgumentList, /// A Trait context. Trait, /// An Impl block. @@ -691,7 +693,7 @@ impl<'a> Parser<'a> { let (mut params, _) = self.parse_paren_comma_seq(|p| { p.recover_vcs_conflict_marker(); let snapshot = p.create_snapshot_for_diagnostic(); - let param = p.parse_param_general(fn_parse_mode, first_param, true).or_else(|e| { + let param = p.parse_param_general(fn_parse_mode, first_param).or_else(|e| { let guar = e.emit(); // When parsing a param failed, we should check to make the span of the param // not contain '(' before it. @@ -724,7 +726,6 @@ impl<'a> Parser<'a> { &mut self, fn_parse_mode: &FnParseMode, first_param: bool, - recover_arg_parse: bool, ) -> PResult<'a, Param> { let lo = self.token.span; let attrs = self.parse_outer_attributes()?; @@ -812,13 +813,22 @@ impl<'a> Parser<'a> { // If this is a C-variadic argument and we hit an error, return the error. Err(err) if this.token == token::DotDotDot => return Err(err), Err(err) if this.unmatched_angle_bracket_count > 0 => return Err(err), - Err(err) if recover_arg_parse => { + Err(err) => { // Recover from attempting to parse the argument as a type without pattern. - err.cancel(); this.restore_snapshot(parser_snapshot_before_ty); - this.recover_arg_parse(fn_parse_mode.context)? + match this.recover_arg_parse(fn_parse_mode.context) { + Ok(res) => { + // We managed to parse the argument as a pattern, cancel the original error and emit a better one + err.cancel(); + res + } + Err(new_err) => { + // We did not manage to parse the argument as a pattern, avoid suggesting a pattern and emit the original error + new_err.cancel(); + return Err(err); + } + } } - Err(err) => return Err(err), } }; diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs index cbd0891c7fe9a..6bc7195b8371c 100644 --- a/compiler/rustc_parse/src/parser/path.rs +++ b/compiler/rustc_parse/src/parser/path.rs @@ -397,14 +397,16 @@ impl<'a> Parser<'a> { } let dcx = self.dcx(); + let mut first_param = true; let parse_params_result = self.parse_paren_comma_seq(|p| { // Inside parenthesized type arguments, we want types only, not names. let mode = FnParseMode { - context: FnContext::Free, + context: FnContext::ParenthesizedArgumentList, req_name: |_, _| false, req_body: false, }; - let param = p.parse_param_general(&mode, false, false)?; + let param = p.parse_param_general(&mode, first_param)?; + first_param = false; if !matches!(param.pat.kind, PatKind::Missing) { self.psess .gated_spans diff --git a/compiler/rustc_passes/src/diagnostics.rs b/compiler/rustc_passes/src/diagnostics.rs index a396695ba6d52..6ea0dc2c8f244 100644 --- a/compiler/rustc_passes/src/diagnostics.rs +++ b/compiler/rustc_passes/src/diagnostics.rs @@ -2,9 +2,7 @@ use std::io::Error; use std::path::{Path, PathBuf}; use rustc_errors::codes::*; -use rustc_errors::{ - Diag, DiagCtxtHandle, DiagSymbolList, Diagnostic, EmissionGuarantee, Level, MultiSpan, msg, -}; +use rustc_errors::{Diag, DiagCtxtHandle, DiagSymbolList, Diagnostic, Level, MultiSpan, msg}; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_middle::middle::resolve::MainDefinition; use rustc_middle::ty::Ty; @@ -414,7 +412,7 @@ pub(crate) struct NoMainErr { pub add_teach_note: bool, } -impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for NoMainErr { +impl<'a, G> Diagnostic<'a, G> for NoMainErr { #[track_caller] fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G> { let mut diag = @@ -480,7 +478,7 @@ pub(crate) struct DuplicateLangItem { pub(crate) duplicate: Duplicate, } -impl Diagnostic<'_, G> for DuplicateLangItem { +impl Diagnostic<'_, G> for DuplicateLangItem { #[track_caller] fn into_diag(self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_, G> { let mut diag = Diag::new( diff --git a/compiler/rustc_resolve/src/diagnostics/mod.rs b/compiler/rustc_resolve/src/diagnostics/mod.rs index dfa58ab73778f..b581777901195 100644 --- a/compiler/rustc_resolve/src/diagnostics/mod.rs +++ b/compiler/rustc_resolve/src/diagnostics/mod.rs @@ -2,7 +2,7 @@ use rustc_errors::codes::*; use rustc_errors::formatting::DiagMessageAddArg; use rustc_errors::{ Applicability, Diag, DiagArgValue, DiagCtxtHandle, Diagnostic, ElidedLifetimeInPathSubdiag, - EmissionGuarantee, IntoDiagArg, Level, MultiSpan, Subdiagnostic, msg, + IntoDiagArg, Level, MultiSpan, Subdiagnostic, msg, }; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_span::{Ident, Span, Spanned, Symbol}; @@ -1380,7 +1380,7 @@ pub(crate) enum ItemWas { } impl Subdiagnostic for FoundItemConfigureOut { - fn add_to_diag(self, diag: &mut Diag<'_, G>) { + fn add_to_diag(self, diag: &mut Diag<'_, G>) { let mut multispan: MultiSpan = self.span.into(); match self.item_was { ItemWas::BehindFeature { feature, span } => { @@ -1522,7 +1522,7 @@ pub(crate) struct Ambiguity { pub is_error: bool, } -impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for Ambiguity { +impl<'a, G> Diagnostic<'a, G> for Ambiguity { fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G> { let Self { ident, diff --git a/compiler/rustc_session/src/diagnostics.rs b/compiler/rustc_session/src/diagnostics.rs index 3cae99b483872..a2bf9a0d2dfc3 100644 --- a/compiler/rustc_session/src/diagnostics.rs +++ b/compiler/rustc_session/src/diagnostics.rs @@ -4,8 +4,7 @@ use rustc_ast::token; use rustc_ast::util::literal::LitError; use rustc_errors::codes::*; use rustc_errors::{ - Diag, DiagCtxtHandle, DiagMessage, Diagnostic, EmissionGuarantee, ErrorGuaranteed, Level, - MultiSpan, StashKey, + Diag, DiagCtxtHandle, DiagMessage, Diagnostic, ErrorGuaranteed, Level, MultiSpan, StashKey, }; use rustc_feature::{GateIssue, find_feature_issue}; use rustc_macros::{Diagnostic, Subdiagnostic}; @@ -96,11 +95,7 @@ pub fn feature_warn_issue( /// Adds the diagnostics for a feature to an existing error. /// Must be a language feature! -pub fn add_feature_diagnostics( - err: &mut Diag<'_, G>, - sess: &Session, - feature: Symbol, -) { +pub fn add_feature_diagnostics(err: &mut Diag<'_, G>, sess: &Session, feature: Symbol) { add_feature_diagnostics_for_issue(err, sess, feature, GateIssue::Language, false, None); } @@ -109,7 +104,7 @@ pub fn add_feature_diagnostics( /// This variant allows you to control whether it is a library or language feature. /// Almost always, you want to use this for a language feature. If so, prefer /// `add_feature_diagnostics`. -pub fn add_feature_diagnostics_for_issue( +pub fn add_feature_diagnostics_for_issue( err: &mut Diag<'_, G>, sess: &Session, feature: Symbol, @@ -197,7 +192,7 @@ pub(crate) struct FeatureGateError { pub(crate) explain: DiagMessage, } -impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for FeatureGateError { +impl<'a, G> Diagnostic<'a, G> for FeatureGateError { #[track_caller] fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G> { Diag::new(dcx, level, self.explain).with_span(self.span).with_code(E0658) diff --git a/compiler/rustc_target/src/callconv/mod.rs b/compiler/rustc_target/src/callconv/mod.rs index 26fedbd8a5481..9fe22a3a174b6 100644 --- a/compiler/rustc_target/src/callconv/mod.rs +++ b/compiler/rustc_target/src/callconv/mod.rs @@ -845,7 +845,7 @@ impl<'a, Ty> FnAbi<'a, Ty> { // an LLVM aggregate type for this leads to bad optimizations, // so we pick an appropriately sized integer type instead. arg.cast_to_maybe_noundef(Reg { kind: RegKind::Integer, size }, cx); - } else if self.conv == CanonAbi::RustTail { + } else if self.conv == CanonAbi::RustTail && arg_idx.is_some() { assert!(arg.layout.is_sized(), "extern \"tail\" arguments must be sized"); arg.pass_by_stack_offset(None); } diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 0f192379ce7fc..9f97a33bfdc75 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -2262,11 +2262,12 @@ pub struct TargetOptions { /// Extra arguments to pass to the external assembler (when used) pub asm_args: StaticCow<[StaticCow]>, - /// Default CPU to pass to LLVM. Corresponds to `llc -mcpu=$cpu`. Defaults - /// to "generic". + /// Default CPU to pass to LLVM. Corresponds to `llc -mcpu=$cpu`. Must be a name the backend + /// accepts. Defaults to "generic" (which some backends won't accept). pub cpu: StaticCow, - /// Whether a cpu needs to be explicitly set. - /// Set to true if there is no default cpu. Defaults to false. + /// Whether a cpu needs to be explicitly set via `-Ctarget-cpu` for codegen to run. (Even if + /// true, `cpu` is still consulted on non-codegen paths such as cfg/feature computation.) + /// Defaults to false. pub need_explicit_cpu: bool, /// Whether `-Ctarget-cpu` is treated as a target modifier. If this is set /// all crates that are linked together must have been compiled with the diff --git a/compiler/rustc_target/src/spec/targets/avr_none.rs b/compiler/rustc_target/src/spec/targets/avr_none.rs index 0dcd2428fc703..d4b0bf64206c7 100644 --- a/compiler/rustc_target/src/spec/targets/avr_none.rs +++ b/compiler/rustc_target/src/spec/targets/avr_none.rs @@ -14,6 +14,7 @@ pub(crate) fn target() -> Target { pointer_width: 16, options: TargetOptions { c_int_width: 16, + cpu: "avr2".into(), exe_suffix: ".elf".into(), linker: Some("avr-gcc".into()), eh_frame_header: false, diff --git a/compiler/rustc_trait_selection/src/diagnostics.rs b/compiler/rustc_trait_selection/src/diagnostics.rs index 6e2a4f10fb458..02a181adfadb7 100644 --- a/compiler/rustc_trait_selection/src/diagnostics.rs +++ b/compiler/rustc_trait_selection/src/diagnostics.rs @@ -2,8 +2,8 @@ use rustc_data_structures::fx::{FxHashSet, FxIndexSet}; use rustc_errors::codes::*; use rustc_errors::formatting::DiagMessageAddArg; use rustc_errors::{ - Applicability, Diag, DiagCtxtHandle, DiagMessage, DiagStyledString, Diagnostic, - EmissionGuarantee, IntoDiagArg, Level, MultiSpan, Subdiagnostic, msg, + Applicability, Diag, DiagCtxtHandle, DiagMessage, DiagStyledString, Diagnostic, IntoDiagArg, + Level, MultiSpan, Subdiagnostic, msg, }; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; @@ -36,7 +36,7 @@ pub(crate) struct NegativePositiveConflict<'tcx> { pub positive_impl_span: Result, } -impl Diagnostic<'_, G> for NegativePositiveConflict<'_> { +impl Diagnostic<'_, G> for NegativePositiveConflict<'_> { #[track_caller] fn into_diag(self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_, G> { let mut diag = Diag::new( @@ -89,7 +89,7 @@ pub(crate) enum AdjustSignatureBorrow { } impl Subdiagnostic for AdjustSignatureBorrow { - fn add_to_diag(self, diag: &mut Diag<'_, G>) { + fn add_to_diag(self, diag: &mut Diag<'_, G>) { match self { AdjustSignatureBorrow::Borrow { to_borrow } => { diag.arg("borrow_len", to_borrow.len()); @@ -437,7 +437,7 @@ pub(crate) enum RegionOriginNote<'a> { } impl Subdiagnostic for RegionOriginNote<'_> { - fn add_to_diag(self, diag: &mut Diag<'_, G>) { + fn add_to_diag(self, diag: &mut Diag<'_, G>) { let label_or_note = |diag: &mut Diag<'_, G>, span, msg: DiagMessage| { let sub_count = diag.children.iter().filter(|d| d.span.is_dummy()).count(); let expanded_sub_count = diag.children.iter().filter(|d| !d.span.is_dummy()).count(); @@ -532,7 +532,7 @@ pub(crate) enum LifetimeMismatchLabels { } impl Subdiagnostic for LifetimeMismatchLabels { - fn add_to_diag(self, diag: &mut Diag<'_, G>) { + fn add_to_diag(self, diag: &mut Diag<'_, G>) { match self { LifetimeMismatchLabels::InRet { param_span, ret_span, span, label_var1 } => { diag.span_label(param_span, msg!("this parameter and the return type are declared with different lifetimes...")); @@ -605,7 +605,7 @@ pub(crate) struct AddLifetimeParamsSuggestion<'a> { } impl Subdiagnostic for AddLifetimeParamsSuggestion<'_> { - fn add_to_diag(self, diag: &mut Diag<'_, G>) { + fn add_to_diag(self, diag: &mut Diag<'_, G>) { let mut mk_suggestion = || { let Some(anon_reg) = self.tcx.is_suitable_region(self.generic_param_scope, self.sub) else { @@ -789,7 +789,7 @@ pub(crate) struct IntroducesStaticBecauseUnmetLifetimeReq { } impl Subdiagnostic for IntroducesStaticBecauseUnmetLifetimeReq { - fn add_to_diag(mut self, diag: &mut Diag<'_, G>) { + fn add_to_diag(mut self, diag: &mut Diag<'_, G>) { self.unmet_requirements.push_span_label( self.binding_span, msg!("introduces a `'static` lifetime requirement"), @@ -1184,7 +1184,7 @@ pub(crate) struct ConsiderBorrowingParamHelp { } impl Subdiagnostic for ConsiderBorrowingParamHelp { - fn add_to_diag(self, diag: &mut Diag<'_, G>) { + fn add_to_diag(self, diag: &mut Diag<'_, G>) { let mut type_param_span: MultiSpan = self.spans.clone().into(); for &span in &self.spans { // Seems like we can't call f() here as Into is required @@ -1661,7 +1661,7 @@ pub(crate) struct SuggestTuplePatternMany { } impl Subdiagnostic for SuggestTuplePatternMany { - fn add_to_diag(self, diag: &mut Diag<'_, G>) { + fn add_to_diag(self, diag: &mut Diag<'_, G>) { diag.arg("path", self.path); let message = msg!("try wrapping the pattern in a variant of `{$path}`"); diag.multipart_suggestions( @@ -1907,7 +1907,7 @@ pub(crate) struct AddPreciseCapturingAndParams { } impl Subdiagnostic for AddPreciseCapturingAndParams { - fn add_to_diag(self, diag: &mut Diag<'_, G>) { + fn add_to_diag(self, diag: &mut Diag<'_, G>) { diag.arg("new_lifetime", self.new_lifetime); diag.multipart_suggestion( msg!("add a `use<...>` bound to explicitly capture `{$new_lifetime}` after turning all argument-position `impl Trait` into type parameters, noting that this possibly affects the API of this crate"), @@ -2047,7 +2047,7 @@ pub struct AddPreciseCapturingForOvercapture { } impl Subdiagnostic for AddPreciseCapturingForOvercapture { - fn add_to_diag(self, diag: &mut Diag<'_, G>) { + fn add_to_diag(self, diag: &mut Diag<'_, G>) { let applicability = if self.apit_spans.is_empty() { Applicability::MachineApplicable } else { diff --git a/compiler/rustc_trait_selection/src/diagnostics/note_and_explain.rs b/compiler/rustc_trait_selection/src/diagnostics/note_and_explain.rs index 07b8adb898aa6..32a35b58f3186 100644 --- a/compiler/rustc_trait_selection/src/diagnostics/note_and_explain.rs +++ b/compiler/rustc_trait_selection/src/diagnostics/note_and_explain.rs @@ -1,5 +1,5 @@ use rustc_errors::formatting::DiagMessageAddArg; -use rustc_errors::{Diag, EmissionGuarantee, IntoDiagArg, Subdiagnostic, msg}; +use rustc_errors::{Diag, IntoDiagArg, Subdiagnostic, msg}; use rustc_hir::def_id::LocalDefId; use rustc_middle::bug; use rustc_middle::ty::{self, TyCtxt}; @@ -163,7 +163,7 @@ impl RegionExplanation<'_> { } impl Subdiagnostic for RegionExplanation<'_> { - fn add_to_diag(self, diag: &mut Diag<'_, G>) { + fn add_to_diag(self, diag: &mut Diag<'_, G>) { let msg = msg!( "{$pref_kind -> *[should_not_happen] [{$pref_kind}] diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/overflow.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/overflow.rs index e8765e3b0ad27..cea5c2f5a3d53 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/overflow.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/overflow.rs @@ -1,6 +1,6 @@ use std::fmt; -use rustc_errors::{Diag, E0275, EmissionGuarantee, ErrorGuaranteed, struct_span_code_err}; +use rustc_errors::{Diag, E0275, ErrorGuaranteed, struct_span_code_err}; use rustc_hir::def::Namespace; use rustc_hir::def_id::LOCAL_CRATE; use rustc_infer::traits::{Obligation, PredicateObligation}; @@ -17,10 +17,7 @@ pub enum OverflowCause<'tcx> { TraitSolver(ty::Predicate<'tcx>), } -pub fn suggest_new_overflow_limit<'tcx, G: EmissionGuarantee>( - tcx: TyCtxt<'tcx>, - err: &mut Diag<'_, G>, -) { +pub fn suggest_new_overflow_limit<'tcx, G>(tcx: TyCtxt<'tcx>, err: &mut Diag<'_, G>) { let suggested_limit = match tcx.recursion_limit() { Limit(0) => Limit(2), limit => limit * 2, 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 0b178f86249a9..06efc92d9e727 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -9,8 +9,7 @@ use rustc_abi::ExternAbi; use rustc_data_structures::fx::FxHashSet; use rustc_errors::codes::*; use rustc_errors::{ - Applicability, Diag, EmissionGuarantee, MultiSpan, Style, SuggestionStyle, pluralize, - struct_span_code_err, + Applicability, Diag, MultiSpan, Style, SuggestionStyle, pluralize, struct_span_code_err, }; use rustc_hir::attrs::lang_items::{self, LangItem}; use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res}; @@ -120,7 +119,7 @@ fn predicate_constraint(generics: &hir::Generics<'_>, pred: ty::Predicate<'_>) - /// Type parameter needs more bounds. The trivial case is `T` `where T: Bound`, but /// it can also be an `impl Trait` param that needs to be decomposed to a type /// param for cleaner code. -pub fn suggest_restriction<'tcx, G: EmissionGuarantee>( +pub fn suggest_restriction<'tcx, G>( tcx: TyCtxt<'tcx>, item_id: LocalDefId, hir_generics: &hir::Generics<'tcx>, @@ -2752,7 +2751,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { false } - pub(super) fn suggest_borrow_for_unsized_closure_return( + pub(super) fn suggest_borrow_for_unsized_closure_return( &self, body_def_id: LocalDefId, err: &mut Diag<'_, G>, @@ -3297,7 +3296,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { /// /// Returns `true` if an async-await specific note was added to the diagnostic. #[instrument(level = "debug", skip_all, fields(?obligation.predicate, ?obligation.cause.span))] - pub fn maybe_note_obligation_cause_for_async_await( + pub fn maybe_note_obligation_cause_for_async_await( &self, err: &mut Diag<'_, G>, obligation: &PredicateObligation<'tcx>, @@ -3529,7 +3528,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { /// Unconditionally adds the diagnostic note described in /// `maybe_note_obligation_cause_for_async_await`'s documentation comment. #[instrument(level = "debug", skip_all)] - fn note_obligation_cause_for_async_await( + fn note_obligation_cause_for_async_await( &self, err: &mut Diag<'_, G>, interior_or_upvar_span: CoroutineInteriorOrUpvar, @@ -3763,7 +3762,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { ); } - fn note_closure_capture( + fn note_closure_capture( &self, err: &mut Diag<'_, G>, closure_def_id: DefId, @@ -3816,7 +3815,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { true } - pub(super) fn note_obligation_cause_code( + pub(super) fn note_obligation_cause_code( &self, body_def_id: LocalDefId, err: &mut Diag<'_, G>, @@ -3845,7 +3844,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { ); } - fn note_obligation_cause_code_inner( + fn note_obligation_cause_code_inner( &self, body_def_id: LocalDefId, err: &mut Diag<'_, G>, @@ -5202,7 +5201,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } } - fn note_function_argument_obligation( + fn note_function_argument_obligation( &self, body_def_id: LocalDefId, err: &mut Diag<'_, G>, @@ -5441,7 +5440,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } } - fn suggest_option_method_if_applicable( + fn suggest_option_method_if_applicable( &self, failed_pred: ty::Predicate<'tcx>, param_env: ty::ParamEnv<'tcx>, @@ -5516,7 +5515,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } } - fn look_for_iterator_item_mistakes( + fn look_for_iterator_item_mistakes( &self, assocs_in_this_method: &[Option<(Span, (DefId, Ty<'tcx>))>], typeck_results: &TypeckResults<'tcx>, @@ -5665,7 +5664,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } } - fn point_at_chain( + fn point_at_chain( &self, expr: &hir::Expr<'_>, typeck_results: &TypeckResults<'tcx>, @@ -5914,7 +5913,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { /// | | `Iterator::Item` is `&mut Vec` here /// | this expression has type `Vec>` /// ``` - fn point_at_chain_in_return_position( + fn point_at_chain_in_return_position( &self, body_def_id: LocalDefId, expr: &hir::Expr<'_>, @@ -7102,7 +7101,7 @@ pub fn suggest_desugaring_async_fn_to_impl_future_in_trait<'tcx>( /// On `impl` evaluation cycles, look for `Self::AssocTy` restrictions in `where` clauses, explain /// they are not allowed and if possible suggest alternatives. -fn point_at_assoc_type_restriction( +fn point_at_assoc_type_restriction( tcx: TyCtxt<'_>, err: &mut Diag<'_, G>, self_ty_str: &str, diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index 5605325309275..e69b1d6188576 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -7,7 +7,7 @@ use std::fmt::Debug; use rustc_data_structures::fx::{FxHashSet, FxIndexSet}; -use rustc_errors::{Diag, EmissionGuarantee}; +use rustc_errors::Diag; use rustc_hir::def_id::{CRATE_DEF_ID, DefId}; use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, TyCtxtInferExt}; use rustc_infer::traits::{PredicateObligations, TraitErrors}; @@ -61,14 +61,14 @@ pub struct OverlapResult<'tcx> { pub overflowing_predicates: Vec>, } -pub fn add_placeholder_note(err: &mut Diag<'_, G>) { +pub fn add_placeholder_note(err: &mut Diag<'_, G>) { err.note( "this behavior recently changed as a result of a bug fix; \ see rust-lang/rust#56105 for details", ); } -pub(crate) fn suggest_increasing_recursion_limit<'tcx, G: EmissionGuarantee>( +pub(crate) fn suggest_increasing_recursion_limit<'tcx, G>( tcx: TyCtxt<'tcx>, err: &mut Diag<'_, G>, overflowing_predicates: &[ty::Predicate<'tcx>], diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index a9ac96424d018..0b870f0d72e37 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -9,7 +9,7 @@ use std::ops::ControlFlow; use hir::def::DefKind; use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; -use rustc_errors::{Diag, EmissionGuarantee}; +use rustc_errors::Diag; use rustc_hir as hir; use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::def_id::DefId; @@ -63,7 +63,7 @@ pub enum IntercrateAmbiguityCause<'tcx> { impl<'tcx> IntercrateAmbiguityCause<'tcx> { /// Emits notes when the overlap is caused by complex intercrate ambiguities. /// See #23980 for details. - pub fn add_intercrate_ambiguity_hint(&self, err: &mut Diag<'_, G>) { + pub fn add_intercrate_ambiguity_hint(&self, err: &mut Diag<'_, G>) { err.note(self.intercrate_ambiguity_hint()); } diff --git a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs index 9a0894891f625..f1626d1c69759 100644 --- a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs @@ -12,8 +12,8 @@ pub mod specialization_graph; use rustc_data_structures::fx::FxIndexSet; +use rustc_errors::Diag; use rustc_errors::codes::*; -use rustc_errors::{Diag, EmissionGuarantee}; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_infer::traits::Obligation; use rustc_lint_defs::builtin::COHERENCE_LEAK_CHECK; @@ -528,7 +528,7 @@ fn report_conflicting_impls<'tcx>( // Work to be done after we've built the Diag. We have to define it now // because the lint emit methods don't return back the Diag that's passed // in. - fn decorate<'tcx, G: EmissionGuarantee>( + fn decorate<'tcx, G>( tcx: TyCtxt<'tcx>, overlap: &OverlapError<'tcx>, impl_span: Span, diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index bf77b477eef70..734c114d74d91 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -448,10 +448,7 @@ impl Box { #[unstable(feature = "allocator_api", issue = "32838")] #[must_use] #[inline] - pub fn new_in(x: T, alloc: A) -> Self - where - A: Allocator, - { + pub fn new_in(x: T, alloc: A) -> Self { let mut boxed = Self::new_uninit_in(alloc); boxed.write(x); // SAFETY: Initialised by the above. @@ -475,10 +472,7 @@ impl Box { /// ``` #[unstable(feature = "allocator_api", issue = "32838")] #[inline] - pub fn try_new_in(x: T, alloc: A) -> Result - where - A: Allocator, - { + pub fn try_new_in(x: T, alloc: A) -> Result { let mut boxed = Self::try_new_uninit_in(alloc)?; boxed.write(x); // SAFETY: Initialised by the above. @@ -504,10 +498,7 @@ impl Box { #[unstable(feature = "allocator_api", issue = "32838")] #[cfg(not(no_global_oom_handling))] #[must_use] - pub fn new_uninit_in(alloc: A) -> Box, A> - where - A: Allocator, - { + pub fn new_uninit_in(alloc: A) -> Box, A> { let layout = Layout::new::>(); // NOTE: Prefer match over unwrap_or_else since closure sometimes not inlineable. // That would make code size bigger. @@ -536,10 +527,7 @@ impl Box { /// # Ok::<(), std::alloc::AllocError>(()) /// ``` #[unstable(feature = "allocator_api", issue = "32838")] - pub fn try_new_uninit_in(alloc: A) -> Result, A>, AllocError> - where - A: Allocator, - { + pub fn try_new_uninit_in(alloc: A) -> Result, A>, AllocError> { let ptr = if T::IS_ZST { NonNull::dangling() } else { @@ -573,10 +561,7 @@ impl Box { #[unstable(feature = "allocator_api", issue = "32838")] #[cfg(not(no_global_oom_handling))] #[must_use] - pub fn new_zeroed_in(alloc: A) -> Box, A> - where - A: Allocator, - { + pub fn new_zeroed_in(alloc: A) -> Box, A> { let layout = Layout::new::>(); // NOTE: Prefer match over unwrap_or_else since closure sometimes not inlineable. // That would make code size bigger. @@ -609,10 +594,7 @@ impl Box { /// /// [zeroed]: mem::MaybeUninit::zeroed #[unstable(feature = "allocator_api", issue = "32838")] - pub fn try_new_zeroed_in(alloc: A) -> Result, A>, AllocError> - where - A: Allocator, - { + pub fn try_new_zeroed_in(alloc: A) -> Result, A>, AllocError> { let ptr = if T::IS_ZST { NonNull::dangling() } else { diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index d332908954b8f..47312b2bd5649 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -2368,7 +2368,6 @@ impl UnsafeCell { /// # Examples /// /// ``` - /// #![feature(unsafe_cell_access)] /// use std::cell::UnsafeCell; /// /// let uc = UnsafeCell::new(5); @@ -2377,7 +2376,8 @@ impl UnsafeCell { /// assert_eq!(old, 5); /// ``` #[inline] - #[unstable(feature = "unsafe_cell_access", issue = "136327")] + #[stable(feature = "unsafe_cell_access", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "unsafe_cell_access", since = "CURRENT_RUSTC_VERSION")] #[rustc_should_not_be_called_on_const_items] pub const unsafe fn replace(&self, value: T) -> T { // SAFETY: pointer comes from `&self` so naturally satisfies invariants. @@ -2510,7 +2510,6 @@ impl UnsafeCell { /// # Examples /// /// ``` - /// #![feature(unsafe_cell_access)] /// use std::cell::UnsafeCell; /// /// let uc = UnsafeCell::new(5); @@ -2519,7 +2518,8 @@ impl UnsafeCell { /// assert_eq!(val, &5); /// ``` #[inline] - #[unstable(feature = "unsafe_cell_access", issue = "136327")] + #[stable(feature = "unsafe_cell_access", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "unsafe_cell_access", since = "CURRENT_RUSTC_VERSION")] #[rustc_should_not_be_called_on_const_items] pub const unsafe fn as_ref_unchecked(&self) -> &T { // SAFETY: pointer comes from `&self` so naturally satisfies ptr-to-ref invariants. @@ -2538,7 +2538,6 @@ impl UnsafeCell { /// # Examples /// /// ``` - /// #![feature(unsafe_cell_access)] /// use std::cell::UnsafeCell; /// /// let uc = UnsafeCell::new(5); @@ -2547,7 +2546,8 @@ impl UnsafeCell { /// assert_eq!(uc.into_inner(), 6); /// ``` #[inline] - #[unstable(feature = "unsafe_cell_access", issue = "136327")] + #[stable(feature = "unsafe_cell_access", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "unsafe_cell_access", since = "CURRENT_RUSTC_VERSION")] #[allow(clippy::mut_from_ref)] #[rustc_should_not_be_called_on_const_items] pub const unsafe fn as_mut_unchecked(&self) -> &mut T { diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs index 9b55d70fecb9a..a30940bf2db71 100644 --- a/library/core/src/intrinsics/mod.rs +++ b/library/core/src/intrinsics/mod.rs @@ -10,6 +10,30 @@ //! and , //! and for const evaluation in . //! +//! Intrinsics don't need a body. However, they optionally can have a body, which we call the +//! "fallback body". This will be used by codegen backends that do not have a dedicated +//! implementation of the intrinsic, making it easier to add new intrinsics for specific operations +//! without having to implement them in each codegen backend. The fallback body obviously has to be +//! a valid implementation of the documented specification of the intrinsic. In some cases, the +//! fallback body will be *equivalent* to the specification. Note that this is a strong requirement: +//! if the spec says "UB if input `x` is even", then a valid implementation can just ignore this and +//! do whatever it wants in that case; an *equivalent* implementation needs to actually check this +//! condition and trigger UB in that case (e.g. by using `hint::assert_unchecked()`). Similar, if +//! the spec says "returns `x` or `y` non-deterministically", then an *equivalent* implementation +//! must actually do non-deterministic choice and return either value (e.g. by invoking some other +//! language operation that has the same non-determinism). Intrinsics with such a fallback body that +//! is equivalent to the spec may be marked with `#[miri::intrinsic_fallback_is_spec]`; the fallback +//! body will then also be used by Miri for UB checking. When in doubt, do not use this attribute or +//! ask the Miri maintainers for advice. +//! +//! Intrinsics are, in general, language extensions. Therefore, t-lang should be involved whenever a +//! new intrinsic is exposed to stable code. However, if an intrinsic is marked +//! `#[miri::intrinsic_fallback_is_spec]` with a fallback body that only uses stable features (or if +//! such a fallback body could be written, but for one reason or another the actual fallback body is +//! different), and if it also does not make other promises that go beyond observable program +//! behavior (such as steering the optimizer in a particular direction), then an intrinsic may be +//! used without t-lang involvement. +//! //! # Const intrinsics //! //! In order to make an intrinsic unstable usable at compile-time, copy the implementation from @@ -19,9 +43,10 @@ //! wg-const-eval. //! //! If an intrinsic is supposed to be used from a `const fn` with a `rustc_const_stable` attribute, -//! `#[rustc_intrinsic_const_stable_indirect]` needs to be added to the intrinsic. Such a change requires -//! T-lang approval, because it may bake a feature into the language that cannot be replicated in -//! user code without compiler support. +//! `#[rustc_intrinsic_const_stable_indirect]` needs to be added to the intrinsic. Such a change +//! requires T-lang approval, because it may bake a feature into the language that cannot be +//! replicated in user code without compiler support. The same exception as above applies for +//! `#[miri::intrinsic_fallback_is_spec]` intrinsics. //! //! # Volatiles //! diff --git a/src/doc/rustc-dev-guide/src/diagnostics/diagnostic-structs.md b/src/doc/rustc-dev-guide/src/diagnostics/diagnostic-structs.md index d5a218dfa87c0..7ca97b7b059e4 100644 --- a/src/doc/rustc-dev-guide/src/diagnostics/diagnostic-structs.md +++ b/src/doc/rustc-dev-guide/src/diagnostics/diagnostic-structs.md @@ -93,7 +93,7 @@ In the end, the `Diagnostic` derive will generate an implementation of `Diagnostic` that looks like the following: ```rust,ignore -impl<'a, G: EmissionGuarantee> Diagnostic<'a> for FieldAlreadyDeclared { +impl<'a, G> Diagnostic<'a> for FieldAlreadyDeclared { fn into_diag(self, dcx: &'a DiagCtxt, level: Level) -> Diag<'a, G> { let mut diag = Diag::new(dcx, level, "field `{$field_name}` is already declared"); diag.set_span(self.span); diff --git a/src/tools/clippy/clippy_utils/src/diagnostics.rs b/src/tools/clippy/clippy_utils/src/diagnostics.rs index 39c0e424b6585..4cda9c4aeb568 100644 --- a/src/tools/clippy/clippy_utils/src/diagnostics.rs +++ b/src/tools/clippy/clippy_utils/src/diagnostics.rs @@ -10,7 +10,7 @@ use rustc_errors::{Applicability, Diag, DiagCtxtHandle, DiagMessage, Diagnostic, Level, MultiSpan}; #[cfg(debug_assertions)] -use rustc_errors::{EmissionGuarantee, SubstitutionPart, Suggestions}; +use rustc_errors::{SubstitutionPart, Suggestions}; use rustc_hir::HirId; use rustc_lint::{LateContext, Lint, LintContext}; use rustc_span::Span; @@ -43,7 +43,7 @@ fn docs_link(diag: &mut Diag<'_, ()>, lint: &'static Lint) { /// /// This function makes sure we also validate them in debug clippy builds. #[cfg(debug_assertions)] -fn validate_diag(diag: &Diag<'_, impl EmissionGuarantee>) { +fn validate_diag(diag: &Diag<'_, G>) { let suggestions = match &diag.suggestions { Suggestions::Enabled(suggs) => &**suggs, Suggestions::Sealed(suggs) => &**suggs, diff --git a/src/tools/rust-analyzer/.github/workflows/gen-lints.yml b/src/tools/rust-analyzer/.github/workflows/gen-lints.yml index c978e3571c40d..05dfdc2fc4534 100644 --- a/src/tools/rust-analyzer/.github/workflows/gen-lints.yml +++ b/src/tools/rust-analyzer/.github/workflows/gen-lints.yml @@ -11,6 +11,7 @@ defaults: jobs: lints-gen: + if: ${{ github.repository == 'rust-lang/rust-analyzer' || github.event_name == 'workflow_dispatch' }} name: Generate lints runs-on: ubuntu-latest permissions: diff --git a/src/tools/rust-analyzer/Cargo.lock b/src/tools/rust-analyzer/Cargo.lock index 5835ed9e552e7..cf4ba4404b367 100644 --- a/src/tools/rust-analyzer/Cargo.lock +++ b/src/tools/rust-analyzer/Cargo.lock @@ -1889,6 +1889,7 @@ dependencies = [ "line-index 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "paths", "proc-macro-test", + "rustc-hash 2.1.2", "span", "stdx", ] diff --git a/src/tools/rust-analyzer/clippy.toml b/src/tools/rust-analyzer/clippy.toml index 1046cb3d56bc6..f0a8a6132c6a2 100644 --- a/src/tools/rust-analyzer/clippy.toml +++ b/src/tools/rust-analyzer/clippy.toml @@ -1,9 +1,9 @@ disallowed-types = [ - { path = "std::collections::HashMap", reason = "use FxHashMap" }, - { path = "std::collections::HashSet", reason = "use FxHashSet" }, - { path = "std::collections::hash_map::RandomState", reason = "use BuildHasherDefault"} + { path = "std::collections::HashMap", replacement = "rustc_hash::FxHashMap" }, + { path = "std::collections::HashSet", replacement = "rustc_hash::FxHashSet" }, + { path = "std::collections::hash_map::RandomState", replacement = "std::hash::BuildHasherDefault"} ] disallowed-methods = [ - { path = "std::process::Command::new", reason = "use `toolchain::command` instead as it forces the choice of a working directory" }, + { path = "std::process::Command::new", replacement = "toolchain::command", reason = "the latter forces the choice of a working directory" }, ] diff --git a/src/tools/rust-analyzer/crates/base-db/src/input.rs b/src/tools/rust-analyzer/crates/base-db/src/input.rs index 230b7cbed680f..229ed82e06cc2 100644 --- a/src/tools/rust-analyzer/crates/base-db/src/input.rs +++ b/src/tools/rust-analyzer/crates/base-db/src/input.rs @@ -8,6 +8,7 @@ use std::error::Error; use std::hash::BuildHasherDefault; +use std::str::FromStr; use std::{fmt, mem, ops}; use cfg::{CfgOptions, HashableCfgOptions}; @@ -315,14 +316,17 @@ impl ReleaseChannel { ReleaseChannel::Nightly => "nightly", } } +} + +impl FromStr for ReleaseChannel { + type Err = (); - #[allow(clippy::should_implement_trait)] - pub fn from_str(str: &str) -> Option { - Some(match str { + fn from_str(str: &str) -> Result { + Ok(match str { "" | "stable" => ReleaseChannel::Stable, "nightly" => ReleaseChannel::Nightly, _ if str.starts_with("beta") => ReleaseChannel::Beta, - _ => return None, + _ => return Err(()), }) } } diff --git a/src/tools/rust-analyzer/crates/base-db/src/lib.rs b/src/tools/rust-analyzer/crates/base-db/src/lib.rs index 0da1faba676c0..1ce5f17e0e26c 100644 --- a/src/tools/rust-analyzer/crates/base-db/src/lib.rs +++ b/src/tools/rust-analyzer/crates/base-db/src/lib.rs @@ -19,6 +19,7 @@ use std::{ cell::RefCell, hash::BuildHasherDefault, panic, + str::FromStr as _, sync::{Once, atomic::AtomicUsize}, }; @@ -327,7 +328,7 @@ impl CrateWorkspaceData { } pub fn toolchain_channel(db: &dyn salsa::Database, krate: Crate) -> Option { - krate.workspace_data(db).toolchain.as_ref().and_then(|v| ReleaseChannel::from_str(&v.pre)) + krate.workspace_data(db).toolchain.as_ref().and_then(|v| ReleaseChannel::from_str(&v.pre).ok()) } #[salsa::input(singleton, debug)] diff --git a/src/tools/rust-analyzer/crates/hir-def/src/attrs/docs.rs b/src/tools/rust-analyzer/crates/hir-def/src/attrs/docs.rs index ac8ca70ccc4b9..583bde92679dd 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/attrs/docs.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/attrs/docs.rs @@ -608,6 +608,7 @@ fn expand_doc_macro_call<'db>( ExpandTo::Expr, expander.krate, expander.macro_depth + 1, + expander.recursion_limit, |path| { expander.resolver.resolve_path_as_macro_def(expander.db, path, Some(MacroSubNs::Bang)) }, diff --git a/src/tools/rust-analyzer/crates/hir-def/src/dyn_map.rs b/src/tools/rust-analyzer/crates/hir-def/src/dyn_map.rs index c38ceccd1fc09..92400d0715395 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/dyn_map.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/dyn_map.rs @@ -119,10 +119,6 @@ pub struct Key { } impl Key { - #[allow( - clippy::new_without_default, - reason = "this a const fn, so it can't be default yet. See " - )] pub(crate) const fn new() -> Key { Key { _phantom: PhantomData } } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/expr_store.rs b/src/tools/rust-analyzer/crates/hir-def/src/expr_store.rs index 3a63ca80ffc68..7d01a7c436e28 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/expr_store.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/expr_store.rs @@ -624,7 +624,6 @@ impl ExpressionStore { visitor.on_expr_opt(*end); } Pat::Lit(expr) | Pat::Expr(expr) => visitor.on_expr(*expr), - Pat::ConstBlock(expr) => visitor.on_anon_const_expr(*expr), Pat::Path(path) => visitor.on_path(path), Pat::Wild | Pat::Missing | Pat::Rest | Pat::NotNull => {} &Pat::Bind { subpat, id: _ } => visitor.on_pat_opt(subpat), diff --git a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/expander.rs b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/expander.rs index a974815cc6423..12a2263697908 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/expander.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/expander.rs @@ -111,7 +111,8 @@ impl<'db> Expander<'db> { call_site.ctx, expands_to, krate, - this.macro_depth, + this.macro_depth + 1, + this.recursion_limit, |path| resolver(path).map(|it| it.definition(db)), eager_callback, ) { diff --git a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs index bb60766197b37..b5d5145927702 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs @@ -3082,16 +3082,7 @@ impl<'db> ExprCollector<'db> { Pat::Deref { inner } } ast::Pat::NotNull(_) => Pat::NotNull, - ast::Pat::ConstBlockPat(const_block_pat) => { - if let Some(block) = const_block_pat.block_expr() { - let expr_id = self.with_label_rib(RibKind::Constant, |this| { - this.with_binding_owner(|this| this.collect_block(block)) - }); - Pat::ConstBlock(expr_id) - } else { - Pat::Missing - } - } + ast::Pat::ConstBlockPat(_) => Pat::Missing, ast::Pat::MacroPat(mac) => { return self.collect_macro_pat_with(mac.clone(), |this, expanded_pat| { this.collect_pat(expanded_pat, binding_list) @@ -3277,16 +3268,6 @@ impl<'db> ExprCollector<'db> { let Some((literal, _)) = pat_literal_to_hir(it) else { return self.missing_expr() }; self.alloc_expr_from_pat(Expr::Literal(literal), ptr) } - ast::Pat::ConstBlockPat(it) => { - if let Some(block) = it.block_expr() { - let expr_id = self.with_label_rib(RibKind::Constant, |this| { - this.with_binding_owner(|this| this.collect_block(block)) - }); - self.alloc_expr_from_pat(Expr::Const(expr_id), ptr) - } else { - self.missing_expr() - } - } ast::Pat::PathPat(it) => { let path = it .path() diff --git a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/pretty.rs b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/pretty.rs index 7d7b948d34149..1d01605695a74 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/pretty.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/pretty.rs @@ -1033,10 +1033,6 @@ impl Printer<'_> { self.print_pat(*inner); w!(self, ")"); } - Pat::ConstBlock(c) => { - w!(self, "const "); - self.print_expr(*c); - } Pat::Expr(expr) => { self.print_expr_in(prec, *expr); } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/scope.rs b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/scope.rs index 24baa0f8c8d89..a7403a0e555b9 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/scope.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/scope.rs @@ -115,7 +115,10 @@ impl ExprScopes { } /// If `scope` refers to a macro def scope, returns the corresponding `MacroId`. - #[allow(clippy::borrowed_box)] // If we return `&MacroDefId` we need to move it, this way we just clone the `Box`. + #[expect( + clippy::borrowed_box, + reason = "If we return `&MacroDefId` we need to move it, this way we just clone the `Box`." + )] pub fn macro_def(&self, scope: ScopeId) -> Option<&Box> { match &self.scopes[scope].kind { ScopeKind::MacroDef(macro_def) => Some(macro_def), @@ -818,66 +821,4 @@ fn test() { 100, ); } - #[test] - fn pattern_const_block_expressions_have_scopes() { - do_check( - r#" -fn foo() { - match () { - const { |x: i32| { let y = x; $0 } } => (), - } -} -"#, - &["y", "x"], - ); - } - - #[test] - fn let_pattern_expr_scope() { - do_check( - r#" -fn foo(param: usize) { - let local = 0; - let const { $0 } = (); -} -"#, - &["param"], - ); - } - - #[test] - fn closure_param_pattern_expr_scope() { - do_check( - r#" -fn foo(param: usize) { - let local = 0; - let _ = |const { $0 }: ()| (); -} -"#, - &["param"], - ); - } - - #[test] - fn fn_param_pattern_expr_scope() { - do_check( - r#" -fn foo(param: usize, const { $0 }: ()) {} -"#, - &["param"], - ); - } - - #[test] - fn if_let_pattern_expr_scope() { - do_check( - r#" -fn foo(param: usize) { - let local = 0; - if let const { $0 } = () {} -} -"#, - &["param"], - ); - } } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/hir.rs b/src/tools/rust-analyzer/crates/hir-def/src/hir.rs index 5785a546513c9..85a41c6495159 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/hir.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/hir.rs @@ -800,7 +800,6 @@ pub enum Pat { inner: PatId, }, NotNull, - ConstBlock(ExprId), /// An expression inside a pattern. That can only occur inside assignments. /// /// E.g. in `(a, *b) = (1, &mut 2)`, `*b` is an expression. @@ -813,7 +812,6 @@ impl Pat { Pat::Range { .. } | Pat::Lit(..) | Pat::Path(..) - | Pat::ConstBlock(..) | Pat::Wild | Pat::Missing | Pat::Rest diff --git a/src/tools/rust-analyzer/crates/hir-def/src/hir/format_args.rs b/src/tools/rust-analyzer/crates/hir-def/src/hir/format_args.rs index 366857f233168..855b16bc28673 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/hir/format_args.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/hir/format_args.rs @@ -169,7 +169,6 @@ enum PositionUsedAs { } use PositionUsedAs::*; -#[allow(clippy::unnecessary_lazy_evaluations)] pub(crate) fn parse( s: &ast::String, string_ptr: AstPtr, diff --git a/src/tools/rust-analyzer/crates/hir-def/src/lib.rs b/src/tools/rust-analyzer/crates/hir-def/src/lib.rs index 0712a025b49cb..77d00072fd2df 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/lib.rs @@ -1442,6 +1442,7 @@ pub fn macro_call_as_call_id( expand_to: ExpandTo, krate: Crate, macro_depth: u32, + recursion_limit: u32, resolver: impl Fn(&ModPath) -> Option + Copy, eager_callback: &mut dyn FnMut( InFile<(syntax::AstPtr, span::FileAstId)>, @@ -1459,6 +1460,7 @@ pub fn macro_call_as_call_id( def, call_site, macro_depth, + recursion_limit, &|path| resolver(path).filter(MacroDefId::is_fn_like), eager_callback, ), diff --git a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs index 7120980dd30cf..1ba636ee901c5 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs @@ -628,3 +628,34 @@ const _: bool = foo::<(), fn() -> Foo>(1, ); "#]], ); } + +#[test] +fn eager_recursion_limit() { + check( + r#" +//- minicore: concat + +macro_rules! concat_separator { + () => { + concat!("", concat_separator!()) + }; +} + +fn main() { + concat_separator!() +} + "#, + expect![[r#" + +macro_rules! concat_separator { + () => { + concat!("", concat_separator!()) + }; +} + +fn main() { + concat!("", concat_separator!()) +} + "#]], + ); +} diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/assoc.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/assoc.rs index 8dea9a4eda1da..0e27d74516007 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/assoc.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/assoc.rs @@ -323,6 +323,7 @@ impl<'db> AssocItemCollector<'db> { ExpandTo::Items, self.module_id.krate(self.db), self.macro_depth + 1, + self.def_map.recursion_limit(), resolver, &mut |ptr, call_id| { self.macro_calls.push((ptr.map(|(_, it)| it.upcast()), call_id)) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs index ce359ebda6af2..e40e4d99bdbd0 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs @@ -1360,6 +1360,7 @@ impl<'db> DefCollector<'db> { *expand_to, self.def_map.krate, directive.depth, + self.def_map.recursion_limit(), resolver_def_id, &mut |ptr, call_id| { eager_callback_buffer.push((directive.module_id, ptr, call_id)); @@ -1793,6 +1794,7 @@ impl<'db> DefCollector<'db> { *expand_to, self.def_map.krate, directive.depth, + self.def_map.recursion_limit(), |path| { let resolved_res = self.def_map.resolve_path_fp_with_macro( self.crate_local_def_map.unwrap_or(&self.local_def_map), @@ -2698,6 +2700,7 @@ impl ModCollector<'_, '_> { expand_to, self.def_collector.def_map.krate, self.macro_depth + 1, + self.def_collector.def_map.recursion_limit(), |path| { path.as_ident().and_then(|name| { let def_map = &self.def_collector.def_map; diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/builtin/quote.rs b/src/tools/rust-analyzer/crates/hir-expand/src/builtin/quote.rs index d84756377fc75..a7fcbc6f9f535 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/builtin/quote.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/builtin/quote.rs @@ -1,5 +1,4 @@ //! A simplified version of quote-crate like quasi quote macro -#![allow(clippy::crate_in_macro_def)] use intern::{Symbol, sym}; use span::Span; @@ -185,7 +184,7 @@ macro_rules! impl_to_to_tokentrees { $( impl ToTokenTree for $ty { fn to_tokens($this, $span: Span, builder: &mut TopSubtreeBuilder) { - let leaf: crate::tt::Leaf = $im.into(); + let leaf: $crate::tt::Leaf = $im.into(); builder.push(leaf); } } diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/eager.rs b/src/tools/rust-analyzer/crates/hir-expand/src/eager.rs index 7002b70a7687b..bddec50c91c04 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/eager.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/eager.rs @@ -26,8 +26,8 @@ use syntax::{ use syntax_bridge::DocCommentDesugarMode; use crate::{ - AstId, EagerCallInfo, ExpandError, ExpandResult, ExpandTo, ExpansionSpanMap, InFile, - MacroCallId, MacroCallKind, MacroCallLoc, MacroDefId, MacroDefKind, + AstId, EagerCallInfo, ExpandError, ExpandErrorKind, ExpandResult, ExpandTo, ExpansionSpanMap, + InFile, MacroCallId, MacroCallKind, MacroCallLoc, MacroDefId, MacroDefKind, ast::{self, AstNode}, mod_path::ModPath, }; @@ -45,6 +45,7 @@ pub fn expand_eager_macro_input( def: MacroDefId, call_site: SyntaxContext, macro_depth: u32, + recursion_limit: u32, resolver: &dyn Fn(&ModPath) -> Option, eager_callback: EagerCallBackFn<'_>, ) -> ExpandResult> { @@ -62,7 +63,7 @@ pub fn expand_eager_macro_input( macro_depth, }; let arg_id = MacroCallId::new(db, loc); - #[allow(deprecated)] // builtin eager macros are never derives + #[expect(deprecated, reason = "builtin eager macros are never derives")] let (_, _, span) = arg_id.macro_arg(db); let ExpandResult { value: (arg_exp, arg_exp_map), err: parse_err } = arg_id.parse_macro_expansion(db); @@ -79,6 +80,7 @@ pub fn expand_eager_macro_input( krate, call_site, macro_depth, + recursion_limit, resolver, eager_callback, ) @@ -155,6 +157,7 @@ fn eager_macro_recur( krate: Crate, call_site: SyntaxContext, macro_depth: u32, + recursion_limit: u32, macro_resolver: &dyn Fn(&ModPath) -> Option, eager_callback: EagerCallBackFn<'_>, ) -> ExpandResult> { @@ -213,6 +216,14 @@ fn eager_macro_recur( } }; let ast_id = curr.file_id.ast_id_map(db).ast_id(&call); + + if macro_depth > recursion_limit { + return ExpandResult::only_err(ExpandError::new( + span_map.span_at(call.syntax().text_range().start()), + ExpandErrorKind::RecursionOverflow, + )); + } + let ExpandResult { value, err } = match def.kind { MacroDefKind::BuiltInEager(..) => { let ExpandResult { value, err } = expand_eager_macro_input( @@ -223,6 +234,7 @@ fn eager_macro_recur( def, call_site, macro_depth + 1, + recursion_limit, macro_resolver, eager_callback, ); @@ -277,6 +289,7 @@ fn eager_macro_recur( krate, call_site, macro_depth + 1, + recursion_limit, macro_resolver, eager_callback, ); diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/fixup.rs b/src/tools/rust-analyzer/crates/hir-expand/src/fixup.rs index 8781358822064..2fda00d6af8d0 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/fixup.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/fixup.rs @@ -343,7 +343,6 @@ pub(crate) fn reverse_fixups(tt: &mut TopSubtree, undo_info: &SyntaxFixupUndoInf let top_subtree = tt.top_subtree(); let open_span = top_subtree.delimiter.open; let close_span = top_subtree.delimiter.close; - #[allow(deprecated)] if never!( close_span.anchor.ast_id == FIXUP_DUMMY_AST_ID || open_span.anchor.ast_id == FIXUP_DUMMY_AST_ID diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs b/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs index f7ac3f1c02694..e646c21ec8c5e 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs @@ -519,7 +519,7 @@ impl MacroCallId { /// This is not connected to the database so it does not cache the result. However, the inner [macro_arg] query is /// /// [macro_arg]: Self::macro_arg - #[allow(deprecated)] // we are macro_arg_considering_derives + #[expect(deprecated, reason = "we are `macro_arg_considering_derives`")] pub fn macro_arg_considering_derives<'db>( self, db: &'db dyn SourceDatabase, @@ -537,6 +537,12 @@ impl MacroCallId { /// query, only typing in the macro call itself changes the returned /// subtree. #[salsa::tracked(returns(ref))] + #[allow( + useless_deprecated, + unused_attributes, + reason = "salsa bug, see https://github.com/salsa-rs/salsa/issues/1307" + )] + #[deprecated = "calling this is incorrect, call `macro_arg_considering_derives` instead"] fn macro_arg(self, db: &dyn SourceDatabase) -> MacroArgResult { let loc = self.loc(db); diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/builtin_derive.rs b/src/tools/rust-analyzer/crates/hir-ty/src/builtin_derive.rs index baa7b87e457f9..53a232adfc7ac 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/builtin_derive.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/builtin_derive.rs @@ -195,7 +195,7 @@ pub fn predicates(db: &dyn HirDatabase, impl_: BuiltinDeriveImplId) -> GenericPr else { // Malformed derive. return GenericPredicates::from_explicit_own_predicates(StoredEarlyBinder::bind( - Clauses::empty(interner).store(), + Clauses::empty().store(), )); }; let duplicated_bounds = diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs b/src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs index d65f76cdf1ceb..a1ed1e71aecc3 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs @@ -253,7 +253,7 @@ pub fn try_const_usize<'db>(db: &'db dyn HirDatabase, c: Const<'db>) -> Option { - if val.ty == default_types(db).types.usize { + if val.ty == default_types().types.usize { Some(val.value.inner().to_leaf().to_uint_unchecked()) } else { None @@ -291,7 +291,7 @@ pub fn try_const_isize<'db>(db: &'db dyn HirDatabase, c: Const<'db>) -> Option { - if val.ty == default_types(db).types.isize { + if val.ty == default_types().types.isize { Some(val.value.inner().to_leaf().to_int_unchecked()) } else { None @@ -347,7 +347,7 @@ pub(crate) fn path_to_const<'a, 'db>( | ValueNs::StructId(_) | ValueNs::EnumVariantId(_) => return Err(CreateConstError::ResolveToNonConst), }; - let args = GenericArgs::empty(interner); + let args = GenericArgs::empty(); Ok(Const::new_unevaluated(interner, UnevaluatedConst { def: konst.into(), args })) } @@ -411,7 +411,7 @@ pub(crate) fn create_anon_const<'a, 'db>( let args = if allow_using_generic_params { GenericArgs::identity_for_item(interner, owner.generic_def(interner.db).into()) } else { - GenericArgs::empty(interner) + GenericArgs::empty() }; Ok(Const::new_unevaluated( interner, @@ -426,7 +426,6 @@ pub(crate) fn const_eval_discriminant_variant<'db>( db: &'db dyn HirDatabase, variant_id: EnumVariantId, ) -> Result> { - let interner = DbInterner::new_no_crate(db); let def = variant_id.into(); let body = Body::of(db, def); let loc = variant_id.lookup(db); @@ -446,7 +445,7 @@ pub(crate) fn const_eval_discriminant_variant<'db>( let mir_body = db.monomorphized_mir_body( def.into(), - GenericArgs::empty(interner).store(), + GenericArgs::empty().store(), ParamEnvAndCrate { param_env: db.trait_environment(def.generic_def(db)), krate: def.krate(db), @@ -561,10 +560,9 @@ pub(crate) fn const_eval_static<'db>( db: &'db dyn HirDatabase, def: StaticId, ) -> Result> { - let interner = DbInterner::new_no_crate(db); let body = db.monomorphized_mir_body( def.into(), - GenericArgs::empty(interner).store(), + GenericArgs::empty().store(), ParamEnvAndCrate { param_env: db.trait_environment(def.into()), krate: def.krate(db) } .store(), )?; diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs b/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs index 6ea8376e48743..b17df991f7afe 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs @@ -14,7 +14,7 @@ use crate::{ db::HirDatabase, display::DisplayTarget, mir::{IsSigned, pad16}, - next_solver::{Allocation, DbInterner, GenericArgs}, + next_solver::{Allocation, GenericArgs}, setup_tracing, test_db::TestDB, }; @@ -120,7 +120,6 @@ fn pretty_print_err(e: ConstEvalError<'_>, db: &TestDB) -> String { fn eval_goal(db: &TestDB, file_id: EditionedFileId) -> Result, ConstEvalError<'_>> { let _tracing = setup_tracing(); - let interner = DbInterner::new_no_crate(db); let module_id = db.module_for_file(file_id.file_id(db)); let def_map = module_id.def_map(db); let scope = &def_map[module_id].scope; @@ -143,7 +142,7 @@ fn eval_goal(db: &TestDB, file_id: EditionedFileId) -> Result, Co _ => None, }) .expect("No const named GOAL found in the test"); - db.const_eval(const_id, GenericArgs::empty(interner), None) + db.const_eval(const_id, GenericArgs::empty(), None) } #[test] diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests/intrinsics.rs b/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests/intrinsics.rs index 898d9ea8edf3d..ab6294cb375df 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests/intrinsics.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests/intrinsics.rs @@ -469,7 +469,8 @@ fn floating_point() { IsSigned::Yes, )), ); - #[allow(unknown_lints, clippy::unnecessary_min_or_max)] + // FIXME: this should be an `expect`, but that currently results in `lint_expectation_unfulfilled` + #[allow(clippy::unnecessary_min_or_max, reason = "for symmetry with the expression in `GOAL`")] check_number( r#" #[rustc_intrinsic] diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics.rs b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics.rs index 047a348fb09a7..17ec211bb579c 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics.rs @@ -9,8 +9,5 @@ pub use crate::diagnostics::{ expr::{ BodyValidationDiagnostic, record_literal_missing_fields, record_pattern_missing_fields, }, - unsafe_check::{ - InsideUnsafeBlock, UnsafetyReason, missing_unsafe, unsafe_operations, - unsafe_operations_for_body, - }, + unsafe_check::{InsideUnsafeBlock, UnsafetyReason, missing_unsafe, unsafe_operations}, }; diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/decl_check.rs b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/decl_check.rs index a465f8be4e175..cccefbc8639ac 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/decl_check.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/decl_check.rs @@ -507,17 +507,14 @@ impl<'a> DeclValidator<'a> { self.validate_enum_variant_fields(*variant_id); } - let edition = self.edition(enum_id); let mut enum_variants_replacements = data .variants .keys() .filter_map(|name| { - to_camel_case(&name.display_no_db(edition).to_smolstr()).map(|new_name| { - Replacement { - current_name: name.clone(), - suggested_text: new_name, - expected_case: CaseType::UpperCamelCase, - } + to_camel_case(name.as_str()).map(|new_name| Replacement { + current_name: name.clone(), + suggested_text: new_name, + expected_case: CaseType::UpperCamelCase, }) }) .peekable(); @@ -717,11 +714,12 @@ impl<'a> DeclValidator<'a> { CaseType::UpperCamelCase => to_camel_case, }; let edition = self.edition(item_id); - let Some(replacement) = - to_expected_case_type(&name.display(self.db, edition).to_smolstr()).map(|new_name| { - Replacement { current_name: name.clone(), suggested_text: new_name, expected_case } - }) - else { + let Some(replacement) = to_expected_case_type(name.as_str()).map(|mut new_name| { + if is_raw_identifier(&new_name, edition) { + new_name.insert_str(0, "r#"); + } + Replacement { current_name: name.clone(), suggested_text: new_name, expected_case } + }) else { return; }; diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs index 94b1ec331f87d..1eb2bf0f85bff 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs @@ -703,7 +703,7 @@ fn types_of_subpatterns_do_match(pat: PatId, body: &Body, infer: &InferenceResul false if *has_type_mismatches => (), false => { let pat = &body[pat]; - if let Pat::ConstBlock(expr) | Pat::Lit(expr) = *pat { + if let Pat::Lit(expr) = *pat { *has_type_mismatches |= infer.expr_has_type_mismatch(expr); if *has_type_mismatches { return; diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/unsafe_check.rs b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/unsafe_check.rs index ca843c8690f28..4818b2f49bf73 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/unsafe_check.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/unsafe_check.rs @@ -101,25 +101,6 @@ enum UnsafeDiagnostic { DeprecatedSafe2024 { node: ExprId, inside_unsafe_block: InsideUnsafeBlock }, } -pub fn unsafe_operations_for_body( - db: &dyn HirDatabase, - infer: &InferenceResult<'_>, - def: DefWithBodyId, - body: &Body, - callback: &mut dyn FnMut(ExprOrPatId), -) { - let mut visitor_callback = |diag| { - if let UnsafeDiagnostic::UnsafeOperation { node, .. } = diag { - callback(node); - } - }; - let mut visitor = UnsafeVisitor::new(db, infer, body, def.into(), &mut visitor_callback); - visitor.walk_expr(body.root_expr()); - for param in &body.params { - visitor.walk_pat(param.formal); - } -} - pub fn unsafe_operations( db: &dyn HirDatabase, infer: &InferenceResult<'_>, @@ -258,7 +239,6 @@ impl<'db> UnsafeVisitor<'db> { | Pat::Box { .. } | Pat::Deref { .. } | Pat::Expr(..) - | Pat::ConstBlock(..) | Pat::NotNull => self.on_unsafe_op(current.into(), UnsafetyReason::UnionField), // `Or` only wraps other patterns, and `Missing`/`Wild` do not constitute a read. Pat::Missing | Pat::Rest | Pat::Wild | Pat::Or(_) => {} @@ -276,11 +256,6 @@ impl<'db> UnsafeVisitor<'db> { } } Pat::Path(path) => self.mark_unsafe_path(current.into(), path), - &Pat::ConstBlock(expr) => { - let old_inside_assignment = mem::replace(&mut self.inside_assignment, false); - self.walk_expr(expr); - self.inside_assignment = old_inside_assignment; - } &Pat::Expr(expr) => self.walk_expr(expr), _ => {} } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs index a87a55b3c8980..e83962ec25ec2 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs @@ -811,7 +811,7 @@ fn render_const_scalar<'db>( memory_map: &MemoryMap<'db>, ty: Ty<'db>, ) -> Result { - let param_env = ParamEnv::empty(f.interner); + let param_env = ParamEnv::empty(); let infcx = f.interner.infer_ctxt().build(TypingMode::PostAnalysis); let ty = infcx.at(&ObligationCause::dummy(), param_env).deeply_normalize(ty).unwrap_or(ty); render_const_scalar_inner(f, b, memory_map, ty, param_env) @@ -1086,7 +1086,7 @@ fn render_const_scalar_from_valtree<'db>( ty: Ty<'db>, valtree: ValTree<'db>, ) -> Result { - let param_env = ParamEnv::empty(f.interner); + let param_env = ParamEnv::empty(); let infcx = f.interner.infer_ctxt().build(TypingMode::PostAnalysis); let ty = infcx.at(&ObligationCause::dummy(), param_env).deeply_normalize(ty).unwrap_or(ty); render_const_scalar_from_valtree_inner(f, ty, valtree, param_env) diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility/tests.rs b/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility/tests.rs index a70f98a0fe7bb..241beea6779e7 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility/tests.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility/tests.rs @@ -14,14 +14,13 @@ use super::{ use DynCompatibilityViolationKind::*; -#[allow(clippy::upper_case_acronyms)] #[derive(Debug, Clone, PartialEq, Eq, Hash)] enum DynCompatibilityViolationKind { SizedSelf, SelfReferential, Method(MethodViolationCode), AssocConst, - GAT, + Gat, HasNonCompatibleSuperTrait, } @@ -63,7 +62,7 @@ fn check_dyn_compatibility<'a>( DynCompatibilityViolation::SelfReferential => SelfReferential, DynCompatibilityViolation::Method(_, mvc) => Method(mvc), DynCompatibilityViolation::AssocConst(_) => AssocConst, - DynCompatibilityViolation::GAT(_) => GAT, + DynCompatibilityViolation::GAT(_) => Gat, DynCompatibilityViolation::HasNonCompatibleSuperTrait(_) => { HasNonCompatibleSuperTrait } @@ -236,7 +235,7 @@ trait GatTrait { trait SuperTrait: GatTrait {} "#, - [("GatTrait", vec![GAT]), ("SuperTrait", vec![HasNonCompatibleSuperTrait])], + [("GatTrait", vec![Gat]), ("SuperTrait", vec![HasNonCompatibleSuperTrait])], ); } @@ -396,6 +395,6 @@ trait Foo { type Bar<'a>; } "#, - [("Foo", vec![DynCompatibilityViolationKind::GAT])], + [("Foo", vec![DynCompatibilityViolationKind::Gat])], ); } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs index 0ab147096a749..cbe5b671fe83a 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs @@ -109,12 +109,7 @@ use crate::{ utils::TargetFeatureIsSafeInTarget, }; -// This lint has a false positive here. See the link below for details. -// -// https://github.com/rust-lang/rust/issues/57411 -#[allow(unreachable_pub)] pub use coerce::could_coerce; -#[allow(unreachable_pub)] pub use unify::{could_unify, could_unify_deeply}; use cast::{CastCheck, CastError}; @@ -1429,7 +1424,7 @@ impl<'db> InferenceContext<'db> { ) -> Self { let trait_env = db.trait_environment(generic_def); let table = unify::InferenceTable::new(db, trait_env, resolver.krate(), owner); - let types = crate::next_solver::default_types(db); + let types = crate::next_solver::default_types(); InferenceContext { result: InferenceResult::new(types.types.error), return_ty: types.types.error, // set in collect_* calls diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure/analysis/expr_use_visitor.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure/analysis/expr_use_visitor.rs index da9c5ab10fc46..6a4e38c5264a7 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure/analysis/expr_use_visitor.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure/analysis/expr_use_visitor.rs @@ -976,7 +976,7 @@ impl<'a, 'db, D: Delegate<'db>> ExprUseVisitor<'a, 'db, D> { read_discriminant(this); } } - Pat::Lit(_) | Pat::ConstBlock(_) | Pat::Range { .. } => { + Pat::Lit(_) | Pat::Range { .. } => { // When matching against a literal or range, we need to // borrow the place to compare it against the pattern. // @@ -1690,7 +1690,6 @@ impl<'db, D: Delegate<'db>> ExprUseVisitor<'_, 'db, D> { | Pat::Expr(..) | Pat::Path(_) | Pat::Lit(..) - | Pat::ConstBlock(..) | Pat::Range { .. } | Pat::Missing | Pat::Rest diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs index af301731c7156..8c9e814015897 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs @@ -192,7 +192,6 @@ impl<'db> InferenceContext<'db> { | Pat::Lit(_) | Pat::Range { .. } | Pat::Slice { .. } - | Pat::ConstBlock(_) | Pat::Record { .. } | Pat::NotNull | Pat::Missing => true, diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/mutability.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/mutability.rs index 09b0d3c03d5b8..9d55bf36e5468 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/mutability.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/mutability.rs @@ -171,7 +171,6 @@ impl<'db> InferenceContext<'db> { &Expr::Assignment { target, value } => { self.store.walk_pats(target, &mut |pat| match self.store[pat] { Pat::Expr(expr) => self.infer_mut_expr(expr, Mutability::Mut), - Pat::ConstBlock(block) => self.infer_mut_expr(block, Mutability::Not), _ => {} }); self.infer_mut_expr(value, Mutability::Not); diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/pat.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/pat.rs index 3a867286eec53..17c198879f265 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/pat.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/pat.rs @@ -530,9 +530,6 @@ impl<'db> InferenceContext<'db> { self.infer_slice_pat(pat, before, slice, after, expected, pat_info) } Pat::Expr(expr) => self.infer_destructuring_assignment_expr(expr, expected), - Pat::ConstBlock(expr) => { - self.infer_expr(expr, &Expectation::has_type(expected), ExprIsRead::Yes) - } } } @@ -634,9 +631,8 @@ impl<'db> InferenceContext<'db> { // All other literals result in non-reference types. // As a result, we allow `if let 0 = &&0 {}` but not `if let "foo" = &&"foo" {}` unless // `deref_patterns` is enabled. - &Pat::Lit(expr) | &Pat::ConstBlock(expr) => { + &Pat::Lit(expr) => { let lit_ty = self.infer_expr_pat_unadjusted(expr); - // Call `resolve_vars_if_possible` here for inline const blocks. let lit_ty = self.infcx().resolve_vars_if_possible(lit_ty); // If `deref_patterns` is enabled, allow `if let "foo" = &&"foo" {}`. if self.features.deref_patterns { diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/layout/tests.rs b/src/tools/rust-analyzer/crates/hir-ty/src/layout/tests.rs index 5098b38c4380c..2a6e8a396279b 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/layout/tests.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/layout/tests.rs @@ -211,9 +211,7 @@ macro_rules! size_and_align { macro_rules! size_and_align_expr { (minicore: $($x:tt),*; stmts: [$($s:tt)*] $($t:tt)*) => { { - #[allow(dead_code)] - #[allow(unused_must_use)] - #[allow(path_statements)] + #[allow(dead_code, unused_must_use, path_statements)] { $($s)* let val = { $($t)* }; diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs index b86585231cca1..04e453fde3b93 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs @@ -252,7 +252,7 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> { db, // Can provide no block since we don't use it for trait solving. interner, - types: crate::next_solver::default_types(db), + types: crate::next_solver::default_types(), lang_items: interner.lang_items(), resolver, def, @@ -635,7 +635,7 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> { // place even if we encounter more opaque types while // lowering the bounds let idx = self.impl_trait_mode.opaque_type_data.alloc(ImplTrait { - predicates: StoredEarlyBinder::bind(Clauses::empty(interner).store()), + predicates: StoredEarlyBinder::bind(Clauses::empty().store()), assoc_ty_bounds_start: 0, }); @@ -2372,12 +2372,12 @@ impl<'db> GenericPredicates { /// A cycle can occur from malformed code. fn generic_predicates_cycle_result<'db>( - db: &'db dyn HirDatabase, + _db: &'db dyn HirDatabase, _: salsa::Id, _def: GenericDefId, ) -> TyLoweringResult<'db, GenericPredicates> { TyLoweringResult::empty(GenericPredicates::from_explicit_own_predicates( - StoredEarlyBinder::bind(Clauses::empty(DbInterner::new_no_crate(db)).store()), + StoredEarlyBinder::bind(Clauses::empty().store()), )) } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lower/path.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lower/path.rs index c67c69520db10..7e55ef2963169 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/lower/path.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/lower/path.rs @@ -576,7 +576,6 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> { lowering_assoc_type_generics: bool, span: Span, ) -> GenericArgs<'db> { - let interner = self.ctx.interner; let prev_current_segment_idx = self.current_segment_idx; let prev_current_segment = self.current_or_prev_segment; @@ -586,7 +585,7 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> { ValueTyDefId::UnionId(it) => it.into(), ValueTyDefId::ConstId(it) => it.into(), ValueTyDefId::StaticId(_) => { - return GenericArgs::empty(interner); + return GenericArgs::empty(); } ValueTyDefId::EnumVariantId(var) => { // the generic args for an enum variant may be either specified diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs index d6db51dec52b9..37f3e27631810 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs @@ -309,7 +309,6 @@ const STACK_OFFSET: usize = 1 << 30; const HEAP_OFFSET: usize = 1 << 29; impl Address { - #[allow(clippy::double_parens)] fn from_bytes<'db>(it: &[u8]) -> Result<'db, Self> { Ok(Address::from_usize(from_bytes!(usize, it))) } @@ -1504,8 +1503,7 @@ impl<'a, 'db> Evaluator<'a, 'db> { )?) } AggregateKind::Union(it, f) => { - let layout = - self.layout_adt((*it).into(), GenericArgs::empty(self.interner()))?; + let layout = self.layout_adt((*it).into(), GenericArgs::empty())?; let offset = layout .fields .offset(u32::from(f.local_id.into_raw()) as usize) @@ -2093,7 +2091,6 @@ impl<'a, 'db> Evaluator<'a, 'db> { } } - #[allow(clippy::double_parens)] fn allocate_const_in_heap( &mut self, locals: &Locals<'a, 'db>, diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs index 5a43696233079..ca7c5c7366803 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs @@ -1246,7 +1246,7 @@ impl<'a, 'db> Evaluator<'a, 'db> { def, &args, // FIXME: wrong for manual impls of `FnOnce` - GenericArgs::empty(self.interner()), + GenericArgs::empty(), locals, destination, None, diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/tests.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/tests.rs index f09ac6f20d271..2ac3811f1769a 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/tests.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/tests.rs @@ -5,19 +5,14 @@ use syntax::{TextRange, TextSize}; use test_fixture::WithFixture; use crate::{ - db::HirDatabase, - display::DisplayTarget, - mir::MirLowerError, - next_solver::{DbInterner, GenericArgs}, - setup_tracing, - test_db::TestDB, + db::HirDatabase, display::DisplayTarget, mir::MirLowerError, next_solver::GenericArgs, + setup_tracing, test_db::TestDB, }; use super::{MirEvalError, interpret_mir}; fn eval_main(db: &TestDB, file_id: EditionedFileId) -> Result<(String, String), MirEvalError<'_>> { crate::attach_db(db, || { - let interner = DbInterner::new_no_crate(db); let module_id = db.module_for_file(file_id.file_id(db)); let def_map = module_id.def_map(db); let scope = &def_map[module_id].scope; @@ -39,7 +34,7 @@ fn eval_main(db: &TestDB, file_id: EditionedFileId) -> Result<(String, String), let body = db .monomorphized_mir_body( func_id.into(), - GenericArgs::empty(interner).store(), + GenericArgs::empty().store(), crate::ParamEnvAndCrate { param_env: db.trait_environment(func_id.into()), krate: func_id.krate(db), diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs index da631c0d595ea..3b82ed6f798e4 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs @@ -324,7 +324,7 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> { db, infer, store, - types: crate::next_solver::default_types(db), + types: crate::next_solver::default_types(), owner, store_owner, resolver, @@ -547,7 +547,7 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> { const_id.into(), current, place, - GenericArgs::empty(self.interner()), + GenericArgs::empty(), expr_id.into(), )?; Ok(Some(current)) @@ -1377,10 +1377,7 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> { match pr { ResolveValueResult::ValueNs(v) => { if let ValueNs::ConstId(c) = v { - self.lower_const_to_operand( - GenericArgs::empty(self.interner()), - c.into(), - ) + self.lower_const_to_operand(GenericArgs::empty(), c.into()) } else { not_supported!("bad path in range pattern"); } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower/pattern_matching.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower/pattern_matching.rs index 682ae827db67d..ecc013506689d 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower/pattern_matching.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower/pattern_matching.rs @@ -413,7 +413,7 @@ impl<'db> MirLowerCtx<'_, 'db> { break 'b (c, x.1); } if let ResolveValueResult::ValueNs(ValueNs::ConstId(c)) = pr { - break 'b (c, GenericArgs::empty(self.interner())); + break 'b (c, GenericArgs::empty()); } not_supported!("path in pattern position that is not const or variant") }; @@ -519,7 +519,6 @@ impl<'db> MirLowerCtx<'_, 'db> { } Pat::Box { .. } => not_supported!("box pattern"), Pat::Deref { .. } => not_supported!("deref pattern"), - Pat::ConstBlock(_) => not_supported!("const block pattern"), }) } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/next_solver.rs b/src/tools/rust-analyzer/crates/hir-ty/src/next_solver.rs index 42fd31f2594da..6263571286721 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/next_solver.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/next_solver.rs @@ -43,7 +43,6 @@ use rustc_type_ir::MayBeErased; pub use solver::*; pub use ty::*; -use crate::db::HirDatabase; pub use crate::lower::ImplTraitIdx; pub use rustc_ast_ir::Mutability; @@ -143,25 +142,24 @@ impl std::fmt::Debug for DefaultAny<'_> { } #[inline] -pub fn default_types<'db>(db: &'db dyn HirDatabase) -> &'db DefaultAny<'db> { +pub fn default_types<'db>() -> &'db DefaultAny<'db> { static TYPES: OnceLock> = OnceLock::new(); - let interner = DbInterner::new_no_crate(db); TYPES.get_or_init(|| { let create_ty = |kind| { - let ty = Ty::new(interner, kind); + let ty = Ty::new_without_interner(kind); // We need to increase the refcount (forever), so that the types won't be freed. let ty = ManuallyDrop::new(ty.store()); ty.as_ref() }; let create_const = |kind| { - let ty = Const::new(interner, kind); + let ty = Const::new_without_interner(kind); // We need to increase the refcount (forever), so that the types won't be freed. let ty = ManuallyDrop::new(ty.store()); ty.as_ref() }; let create_region = |kind| { - let ty = Region::new(interner, kind); + let ty = Region::new_without_interner(kind); // We need to increase the refcount (forever), so that the types won't be freed. let ty = ManuallyDrop::new(ty.store()); ty.as_ref() diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/consts.rs b/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/consts.rs index 1cabafa89bc4e..a9cfafb2e4890 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/consts.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/consts.rs @@ -48,7 +48,10 @@ const _: () = { }; impl<'db> Const<'db> { - pub fn new(_interner: DbInterner<'db>, kind: ConstKind<'db>) -> Self { + /// You should avoid using this if you can, since we want `Ty` to be defined in `rustc_type_ir` and then this method + /// will become more difficult to use. + #[inline] + pub fn new_without_interner(kind: ConstKind<'db>) -> Self { let kind = unsafe { std::mem::transmute::, ConstKind<'static>>(kind) }; let flags = FlagComputation::for_const_kind(&kind); let cached = WithCachedTypeInfo { @@ -59,6 +62,10 @@ impl<'db> Const<'db> { Self { interned: Interned::new_gc(ConstInterned(cached)) } } + pub fn new(_interner: DbInterner<'db>, kind: ConstKind<'db>) -> Self { + Self::new_without_interner(kind) + } + pub fn inner(&self) -> &WithCachedTypeInfo> { let inner = &self.interned.0; unsafe { diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/infer/canonical/canonicalizer.rs b/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/infer/canonical/canonicalizer.rs index 33e4c175d0635..e6416eadc05ec 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/infer/canonical/canonicalizer.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/infer/canonical/canonicalizer.rs @@ -498,7 +498,7 @@ impl<'cx, 'db> Canonicalizer<'cx, 'db> { { let base = Canonical { max_universe: UniverseIndex::ROOT, - var_kinds: CanonicalVarKinds::empty(tcx), + var_kinds: CanonicalVarKinds::empty(), value: (), }; Canonicalizer::canonicalize_with_base( diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/interner.rs b/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/interner.rs index 7b2a811a01afe..df7c9bfe1ec44 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/interner.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/interner.rs @@ -90,8 +90,8 @@ macro_rules! interned_slice { impl<'db> $name<'db> { #[inline] - pub fn empty(interner: DbInterner<'db>) -> Self { - interner.default_types().empty.$default_types_field + pub fn empty() -> Self { + $crate::next_solver::default_types().empty.$default_types_field } #[inline] @@ -168,7 +168,7 @@ macro_rules! interned_slice { impl<'db> Default for $name<'db> { #[inline] fn default() -> Self { - $name::empty(DbInterner::conjure()) + $name::empty() } } @@ -399,7 +399,7 @@ impl<'db> DbInterner<'db> { #[inline] pub fn default_types(&self) -> &'db crate::next_solver::DefaultAny<'db> { - crate::next_solver::default_types(self.db) + crate::next_solver::default_types() } #[inline] @@ -1092,7 +1092,7 @@ impl<'db> Interner for DbInterner<'db> { | SolverDefId::InternedCoroutineId(_) | SolverDefId::InternedCoroutineClosureId(_) | SolverDefId::AnonConstId(_) => { - return VariancesOf::empty(self); + return VariancesOf::empty(); } }; self.db.variances_of(generic_def) @@ -1345,7 +1345,7 @@ impl<'db> Interner for DbInterner<'db> { let own_bounds: FxHashSet<_> = self.item_self_bounds(def_id).skip_binder().into_iter().collect(); if all_bounds.len() == own_bounds.len() { - EarlyBinder::bind(Clauses::empty(self)) + EarlyBinder::bind(Clauses::empty()) } else { EarlyBinder::bind(Clauses::new_from_iter( self, @@ -2172,7 +2172,7 @@ impl<'db> Interner for DbInterner<'db> { }; EarlyBinder::bind(Const::new_unevaluated( self, - UnevaluatedConst { def: GeneralConstIdWrapper(id), args: GenericArgs::empty(self) }, + UnevaluatedConst { def: GeneralConstIdWrapper(id), args: GenericArgs::empty() }, )) } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/predicate.rs b/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/predicate.rs index cf492e65c3ff3..a1e249eaf9517 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/predicate.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/predicate.rs @@ -16,8 +16,8 @@ use rustc_type_ir::{ }; use crate::next_solver::{ - GenericArg, TraitIdWrapper, impl_foldable_for_interned_slice, impl_stored_interned_slice, - interned_slice, + GenericArg, TraitIdWrapper, default_types, impl_foldable_for_interned_slice, + impl_stored_interned_slice, interned_slice, }; use super::{Binder, BoundVarKinds, DbInterner, Region, Ty}; @@ -274,8 +274,8 @@ impl<'db> std::fmt::Debug for Clauses<'db> { impl<'db> Clauses<'db> { #[inline] - pub fn empty(interner: DbInterner<'db>) -> Self { - interner.default_types().empty.clauses + pub fn empty() -> Self { + default_types().empty.clauses } #[inline] @@ -321,6 +321,13 @@ impl<'db> Clauses<'db> { } } +impl Default for Clauses<'_> { + #[inline] + fn default() -> Self { + Self::empty() + } +} + impl<'db> IntoIterator for Clauses<'db> { type IntoIter = ::std::iter::Copied<::std::slice::Iter<'db, Clause<'db>>>; type Item = Clause<'db>; @@ -437,8 +444,9 @@ pub struct ParamEnv<'db> { } impl<'db> ParamEnv<'db> { - pub fn empty(interner: DbInterner<'db>) -> Self { - ParamEnv { clauses: Clauses::empty(interner) } + #[inline] + pub fn empty() -> Self { + ParamEnv { clauses: Clauses::empty() } } pub fn clauses(self) -> Clauses<'db> { diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/region.rs b/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/region.rs index a6facff7623d8..53099f67fcd5a 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/region.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/region.rs @@ -38,11 +38,17 @@ const _: () = { }; impl<'db> Region<'db> { - pub fn new(_interner: DbInterner<'db>, kind: RegionKind<'db>) -> Self { + /// You should avoid using this if you can, since we want `Region` to be defined in `rustc_type_ir` and then this method + /// will become more difficult to use. + pub fn new_without_interner(kind: RegionKind<'db>) -> Self { let kind = unsafe { std::mem::transmute::, RegionKind<'static>>(kind) }; Self { interned: Interned::new_gc(RegionInterned(kind)) } } + pub fn new(_interner: DbInterner<'db>, kind: RegionKind<'db>) -> Self { + Self::new_without_interner(kind) + } + pub fn inner(&self) -> &RegionKind<'db> { let inner = &self.interned.0; unsafe { std::mem::transmute::<&RegionKind<'static>, &RegionKind<'db>>(inner) } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/ty.rs b/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/ty.rs index 6faf0357e3583..c1810bc659c01 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/ty.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/ty.rs @@ -70,8 +70,10 @@ const _: () = { }; impl<'db> Ty<'db> { + /// You should avoid using this if you can, since we want `Const` to be defined in `rustc_type_ir` and then this method + /// will become more difficult to use. #[inline] - pub fn new(_interner: DbInterner<'db>, kind: TyKind<'db>) -> Self { + pub fn new_without_interner(kind: TyKind<'db>) -> Self { let kind = unsafe { std::mem::transmute::, TyKind<'static>>(kind) }; let flags = FlagComputation::for_kind(&kind); let cached = WithCachedTypeInfo { @@ -82,6 +84,11 @@ impl<'db> Ty<'db> { Self { interned: Interned::new_gc(TyInterned(cached)) } } + #[inline] + pub fn new(_interner: DbInterner<'db>, kind: TyKind<'db>) -> Self { + Self::new_without_interner(kind) + } + #[inline] pub fn inner(&self) -> &WithCachedTypeInfo> { let inner = &self.interned.0; @@ -784,7 +791,7 @@ impl<'db> Ty<'db> { let impl_bound = TraitRef::new_from_args( interner, future_trait.into(), - GenericArgs::empty(interner), + GenericArgs::empty(), ) .upcast(interner); Some(vec![impl_bound]) diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/patterns.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/patterns.rs index a6e864916f40f..b10f2df273b44 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/patterns.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/patterns.rs @@ -938,36 +938,6 @@ fn foo(tuple: Tuple) { ); } -#[test] -fn const_block_pattern() { - check_infer( - r#" -struct Foo(usize); -fn foo(foo: Foo) { - match foo { - const { Foo(15 + 32) } => {}, - _ => {} - } -}"#, - expect![[r#" - 26..29 'foo': Foo - 36..115 '{ ... } }': () - 42..113 'match ... }': () - 48..51 'foo': Foo - 62..84 'const ... 32) }': Foo - 68..84 '{ Foo(... 32) }': Foo - 70..73 'Foo': fn Foo(usize) -> Foo - 70..82 'Foo(15 + 32)': Foo - 74..76 '15': usize - 74..81 '15 + 32': usize - 79..81 '32': usize - 88..90 '{}': () - 100..101 '_': Foo - 105..107 '{}': () - "#]], - ); -} - #[test] fn macro_pat() { check_types( diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/regression.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/regression.rs index 7934ffec28745..a6c8b4ac6a271 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/regression.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/regression.rs @@ -3135,22 +3135,6 @@ fn f() -> impl Sized { ); } -#[test] -fn regression_22836() { - check( - r#" -fn main() { - match () { - const { - async | v | () - // ^^^^^^^^^^^^^^ expected (), got impl AsyncFn({unknown}) - } - } -} - "#, - ); -} - #[test] fn regression_22986() { check_no_mismatches( diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/traits.rs b/src/tools/rust-analyzer/crates/hir-ty/src/traits.rs index f3aa024399e06..61f0e17cc9984 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/traits.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/traits.rs @@ -391,6 +391,6 @@ pub fn check_orphan_rules<'db>(db: &'db dyn HirDatabase, impl_: ImplId) -> bool } _ => false, }); - #[allow(clippy::let_and_return)] + #[allow(clippy::let_and_return, reason = "the name clarifies the meaning of the boolean")] is_not_orphan } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/variance.rs b/src/tools/rust-analyzer/crates/hir-ty/src/variance.rs index 2690297283988..cce1b4caf44a7 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/variance.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/variance.rs @@ -46,7 +46,7 @@ fn variances_of_query(db: &dyn HirDatabase, def: GenericDefId) -> StoredVariance GenericDefId::AdtId(adt) => { if let AdtId::StructId(id) = adt { let flags = &StructSignature::of(db, id).flags; - let types = || crate::next_solver::default_types(db); + let types = || crate::next_solver::default_types(); if flags.contains(StructFlags::IS_UNSAFE_CELL) { return types().one_invariant.store(); } else if flags.intersects( @@ -56,13 +56,13 @@ fn variances_of_query(db: &dyn HirDatabase, def: GenericDefId) -> StoredVariance } } } - _ => return VariancesOf::empty(DbInterner::new_no_crate(db)).store(), + _ => return VariancesOf::empty().store(), } let generics = generics(db, def); let count = generics.len(true); if count == 0 { - return VariancesOf::empty(DbInterner::new_no_crate(db)).store(); + return VariancesOf::empty().store(); } let variances = Context { generics, variances: vec![Variance::Bivariant; count].into_boxed_slice(), db } diff --git a/src/tools/rust-analyzer/crates/hir/src/diagnostics.rs b/src/tools/rust-analyzer/crates/hir/src/diagnostics.rs index 5c3b628f386d5..a1ff564edcf56 100644 --- a/src/tools/rust-analyzer/crates/hir/src/diagnostics.rs +++ b/src/tools/rust-analyzer/crates/hir/src/diagnostics.rs @@ -1175,7 +1175,11 @@ impl<'a, 'db> DiagnosticsCollector<'a, 'db> { } fn collect_anon_const(&mut self, source_map: &ExpressionStoreSourceMap, def: AnonConstId<'db>) { - self.emit_inference_errors(def.into(), source_map, def.into()); + self.emit_inference_errors( + def.into(), + source_map, + TypeOwnerId::from_anon_const(def, self.db), + ); } fn collect_enum(&mut self, def: EnumId) { @@ -1232,7 +1236,7 @@ impl<'a, 'db> DiagnosticsCollector<'a, 'db> { } } - fn collect_def_with_body(&mut self, def: DefWithBodyId, type_owner: TypeOwnerId<'db>) { + fn collect_def_with_body(&mut self, def: DefWithBodyId, type_owner: TypeOwnerId) { let (body, source_map) = Body::with_source_map(self.db, def); self.collect_expr_store(body, source_map); @@ -1284,7 +1288,7 @@ impl<'a, 'db> DiagnosticsCollector<'a, 'db> { &mut self, def: InferBodyId<'db>, source_map: &ExpressionStoreSourceMap, - type_owner: TypeOwnerId<'db>, + type_owner: TypeOwnerId, ) { let infer = InferenceResult::of(self.db, def); @@ -1548,7 +1552,7 @@ impl<'db> AnyDiagnostic<'db> { edition: Edition, d: &'db InferenceDiagnostic, source_map: &ExpressionStoreSourceMap, - type_owner: TypeOwnerId<'db>, + type_owner: TypeOwnerId, ) -> Option> { let expr_syntax = |expr| Self::expr_syntax(expr, source_map); let pat_syntax = |pat| Self::pat_syntax(pat, source_map); @@ -1918,7 +1922,7 @@ impl<'db> AnyDiagnostic<'db> { db: &'db dyn HirDatabase, d: &'db SolverDiagnosticKind, span: SpanSyntax, - type_owner: TypeOwnerId<'db>, + type_owner: TypeOwnerId, ) -> Option> { let interner = DbInterner::new_no_crate(db); Some(match d { diff --git a/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs index 34b9ede4985a6..f9073138e32dd 100644 --- a/src/tools/rust-analyzer/crates/hir/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir/src/lib.rs @@ -1299,16 +1299,15 @@ impl<'db> AnonConst<'db> { pub fn ty(self, db: &'db dyn HirDatabase) -> Type<'db> { let loc = self.id.loc(db); - Type { owner: self.id.into(), ty: loc.ty.get() } + Type { owner: TypeOwnerId::from_anon_const(self.id, db), ty: loc.ty.get() } } pub fn eval( self, db: &'db dyn HirDatabase, ) -> Result, ConstEvalError<'db>> { - let interner = DbInterner::new_no_crate(db); let ty = self.id.loc(db).ty.get().instantiate_identity().skip_norm_wip(); - db.anon_const_eval(self.id, GenericArgs::empty(interner), None).map(|it| EvaluatedConst { + db.anon_const_eval(self.id, GenericArgs::empty(), None).map(|it| EvaluatedConst { allocation: it, def: self.id.into(), ty, @@ -1550,7 +1549,7 @@ impl Function { } } - fn fn_sig<'db>(self, db: &'db dyn HirDatabase) -> (TypeOwnerId<'db>, PolyFnSig<'db>) { + fn fn_sig<'db>(self, db: &'db dyn HirDatabase) -> (TypeOwnerId, PolyFnSig<'db>) { let fn_ptr = self.fn_ptr_type(db); let TyKind::FnPtr(sig_tys, hdr) = fn_ptr.ty.skip_binder().kind() else { unreachable!(); @@ -1558,7 +1557,7 @@ impl Function { (fn_ptr.owner, sig_tys.with(hdr)) } - fn erased_fn_sig<'db>(self, db: &'db dyn HirDatabase) -> (TypeOwnerId<'db>, FnSig<'db>) { + fn erased_fn_sig<'db>(self, db: &'db dyn HirDatabase) -> (TypeOwnerId, FnSig<'db>) { let (owner, sig) = self.fn_sig(db); let sig = DbInterner::new_no_crate(db).instantiate_bound_regions_with_erased(sig); (owner, sig) @@ -1827,10 +1826,9 @@ impl Function { "evaluation of builtin derive impl methods is not supported".to_owned(), ))); }; - let interner = DbInterner::new_no_crate(db); let body = db.monomorphized_mir_body( id.into(), - GenericArgs::empty(interner).store(), + GenericArgs::empty().store(), ParamEnvAndCrate { param_env: db.trait_environment(id.into()), krate: id.module(db).krate(db), @@ -2109,9 +2107,8 @@ impl Const { /// Evaluate the constant. pub fn eval(self, db: &dyn HirDatabase) -> Result, ConstEvalError<'_>> { - let interner = DbInterner::new_no_crate(db); let ty = db.value_ty(self.id.into()).unwrap().instantiate_identity().skip_norm_wip(); - db.const_eval(self.id, GenericArgs::empty(interner), None).map(|it| EvaluatedConst { + db.const_eval(self.id, GenericArgs::empty(), None).map(|it| EvaluatedConst { allocation: it, def: self.id.into(), ty, @@ -3124,21 +3121,17 @@ impl GenericDef { // We cannot call this `Substitution` unfortunately... #[derive(Debug)] pub struct GenericSubstitution<'db> { - owner: TypeOwnerId<'db>, + owner: TypeOwnerId, def: GenericDefId, subst: GenericArgs<'db>, } impl<'db> GenericSubstitution<'db> { - fn new(def: GenericDefId, subst: GenericArgs<'db>, owner: TypeOwnerId<'db>) -> Self { + fn new(def: GenericDefId, subst: GenericArgs<'db>, owner: TypeOwnerId) -> Self { Self { owner, def, subst } } - fn new_from_fn( - def: Function, - subst: GenericArgs<'db>, - owner: TypeOwnerId<'db>, - ) -> Option { + fn new_from_fn(def: Function, subst: GenericArgs<'db>, owner: TypeOwnerId) -> Option { match def.id { AnyFunctionId::FunctionId(def) => Some(Self::new(def.into(), subst, owner)), AnyFunctionId::BuiltinDeriveImplMethod { .. } => None, @@ -3965,7 +3958,7 @@ impl Impl { #[derive(Clone, PartialEq, Eq, Debug, Hash)] pub struct TraitRef<'db> { - owner: TypeOwnerId<'db>, + owner: TypeOwnerId, trait_ref: hir_ty::next_solver::TraitRef<'db>, } @@ -4003,7 +3996,7 @@ enum AnyClosureId<'db> { #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct Closure<'db> { - owner: TypeOwnerId<'db>, + owner: TypeOwnerId, id: AnyClosureId<'db>, subst: GenericArgs<'db>, } @@ -4347,23 +4340,26 @@ impl CaptureUsageSource { } #[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)] -enum TypeOwnerId<'db> { +enum TypeOwnerId { GenericDefId(GenericDefId), BuiltinDeriveImplId(BuiltinDeriveImplId), - AnonConstId(AnonConstId<'db>), // FIXME: What do when we unify two different crates? Currently we just randomly keep one. NoParams(base_db::Crate), } impl_from!( - impl<'db> GenericDefId, - BuiltinDeriveImplId, - AnonConstId<'db> - for TypeOwnerId<'db> + BuiltinDeriveImplId + for TypeOwnerId ); -impl TypeOwnerId<'_> { +impl TypeOwnerId { + /// We associated anon consts with their parent, because they can never have generics of their own. + /// It can have *less* than the parent, but providing more generic args is not a problem. + fn from_anon_const<'db>(id: AnonConstId<'db>, db: &'db dyn HirDatabase) -> TypeOwnerId { + TypeOwnerId::GenericDefId(id.loc(db).owner.generic_def(db)) + } + fn unify(self, other: Self) -> Option { match (self, other) { (TypeOwnerId::NoParams(_), owner) => Some(owner), @@ -4394,7 +4390,7 @@ impl TypeOwnerId<'_> { } let self_def = match self { TypeOwnerId::GenericDefId(def) => def, - TypeOwnerId::BuiltinDeriveImplId(_) | TypeOwnerId::AnonConstId(_) => return false, + TypeOwnerId::BuiltinDeriveImplId(_) => return false, TypeOwnerId::NoParams(_) => return true, }; let self_def = match self_def { @@ -4408,9 +4404,7 @@ impl TypeOwnerId<'_> { }; let rebase_into_def = match rebase_into { TypeOwnerId::GenericDefId(def) => def, - TypeOwnerId::BuiltinDeriveImplId(_) - | TypeOwnerId::AnonConstId(_) - | TypeOwnerId::NoParams(_) => return false, + TypeOwnerId::BuiltinDeriveImplId(_) | TypeOwnerId::NoParams(_) => return false, }; let rebase_into_parent = match rebase_into_def { GenericDefId::ConstId(def) => def.loc(db).container, @@ -4429,7 +4423,7 @@ impl TypeOwnerId<'_> { /// with types of different origins will cause errors or panics. Instead, use the `instantiate` methods. #[derive(Clone, Debug)] pub struct Type<'db> { - owner: TypeOwnerId<'db>, + owner: TypeOwnerId, ty: EarlyBinder<'db, Ty<'db>>, } @@ -4513,8 +4507,7 @@ impl<'db> Type<'db> { TypeOwnerId::BuiltinDeriveImplId(def) => { GenericArgs::error_for_item(interner, def.into()) } - TypeOwnerId::AnonConstId(def) => GenericArgs::error_for_item(interner, def.into()), - TypeOwnerId::NoParams(_) => GenericArgs::empty(interner), + TypeOwnerId::NoParams(_) => GenericArgs::empty(), }; Type::no_params(krate, self.ty.instantiate(interner, args).skip_norm_wip()) } @@ -4527,10 +4520,7 @@ impl<'db> Type<'db> { TypeOwnerId::BuiltinDeriveImplId(def) => { generic_args_from_tys(interner, def.into(), args) } - TypeOwnerId::AnonConstId(def) => generic_args_from_tys(interner, def.into(), args), - TypeOwnerId::NoParams(krate) => { - (GenericArgs::empty(interner), TypeOwnerId::NoParams(krate)) - } + TypeOwnerId::NoParams(krate) => (GenericArgs::empty(), TypeOwnerId::NoParams(krate)), }; Type { owner, ty: EarlyBinder::bind(self.ty.instantiate(interner, args).skip_norm_wip()) } } @@ -4546,7 +4536,6 @@ impl<'db> Type<'db> { let owner = match ty.owner { TypeOwnerId::GenericDefId(def) => def.into(), TypeOwnerId::BuiltinDeriveImplId(def) => def.into(), - TypeOwnerId::AnonConstId(def) => def.into(), TypeOwnerId::NoParams(_) => return ty.ty.skip_binder(), }; let args = GenericArgs::for_item(infcx.interner, owner, |_, param, _, _| { @@ -4624,7 +4613,7 @@ impl<'db> Type<'db> { tys: impl IntoIterator>>, ) -> Self { let interner = DbInterner::new_no_crate(db); - let mut owner = None::>; + let mut owner = None::; let ty = EarlyBinder::bind(Ty::new_tup_from_iter( interner, tys.into_iter().map(|ty| { @@ -4840,29 +4829,21 @@ impl<'db> Type<'db> { TypeOwnerId::BuiltinDeriveImplId(def) => { hir_def::HasModule::krate(&def.loc(db).adt, db) } - TypeOwnerId::AnonConstId(def) => hir_def::HasModule::krate(&def, db), TypeOwnerId::NoParams(krate) => krate, } } fn param_env(&self, db: &'db dyn HirDatabase) -> ParamEnvAndCrate<'db> { - let interner = DbInterner::new_no_crate(db); let krate = self.krate(db); match self.owner { TypeOwnerId::GenericDefId(def) => { ParamEnvAndCrate { param_env: db.trait_environment(def), krate } } TypeOwnerId::BuiltinDeriveImplId(def) => ParamEnvAndCrate { - param_env: hir_ty::builtin_derive::param_env(interner, def), - krate, - }, - TypeOwnerId::AnonConstId(def) => ParamEnvAndCrate { - param_env: db.trait_environment(def.loc(db).owner.generic_def(db)), + param_env: hir_ty::builtin_derive::param_env(DbInterner::new_with(db, krate), def), krate, }, - TypeOwnerId::NoParams(_) => { - ParamEnvAndCrate { param_env: ParamEnv::empty(interner), krate } - } + TypeOwnerId::NoParams(_) => ParamEnvAndCrate { param_env: ParamEnv::empty(), krate }, } } @@ -4986,8 +4967,7 @@ impl<'db> Type<'db> { trait_: Trait, args: &[Type<'db>], ) -> bool { - let interner = DbInterner::new_no_crate(db); - let env = ParamEnvAndCrate { param_env: ParamEnv::empty(interner), krate: self.krate(db) }; + let env = ParamEnvAndCrate { param_env: ParamEnv::empty(), krate: self.krate(db) }; traits::implements_trait_unique_with_infcx(db, env, trait_.id, &mut |infcx| { let mut args = Self::instantiate_many_with_infer(iter::once(self).chain(args), infcx); GenericArgs::for_item(infcx.interner, trait_.id.into(), |_, param, _, _| { @@ -5681,7 +5661,7 @@ impl<'db> Type<'db> { pub fn walk(&self, db: &'db dyn HirDatabase, callback: impl FnMut(Type<'db>)) { struct Visitor<'db, F> { db: &'db dyn HirDatabase, - owner: TypeOwnerId<'db>, + owner: TypeOwnerId, callback: F, visited: FxHashSet>, } @@ -6144,7 +6124,7 @@ pub enum PredicatePolarity { #[derive(Debug, Clone, PartialEq, Eq)] pub struct TraitPredicate<'db> { inner: hir_ty::next_solver::TraitPredicate<'db>, - owner: TypeOwnerId<'db>, + owner: TypeOwnerId, } impl<'db> TraitPredicate<'db> { @@ -6549,8 +6529,8 @@ fn generic_args_from_tys<'db>( interner: DbInterner<'db>, def_id: SolverDefId<'db>, args: impl IntoIterator>>, -) -> (GenericArgs<'db>, TypeOwnerId<'db>) { - let mut owner = None::>; +) -> (GenericArgs<'db>, TypeOwnerId) { + let mut owner = None::; let mut args = args.into_iter(); let args = GenericArgs::for_item(interner, def_id, |_, id, _, _| { if matches!(id, GenericParamId::TypeParamId(_)) diff --git a/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs b/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs index 907193fe1d7ff..368e5e3c147fd 100644 --- a/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs +++ b/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs @@ -78,7 +78,7 @@ pub(crate) struct SourceAnalyzer<'db> { pub(crate) file_id: HirFileId, pub(crate) resolver: Resolver<'db>, pub(crate) body_or_sig: Option>, - pub(crate) type_owner: TypeOwnerId<'db>, + pub(crate) type_owner: TypeOwnerId, pub(crate) infer_body: Option>, } @@ -350,21 +350,18 @@ impl<'db> SourceAnalyzer<'db> { } fn trait_environment(&self, db: &'db dyn HirDatabase) -> ParamEnvAndCrate<'db> { - self.param_and(self.body_or_sig.as_ref().map_or_else( - || ParamEnv::empty(DbInterner::new_no_crate(db)), - |body_or_sig| { - let def = match *body_or_sig { - BodyOrSig::Body { def, .. } => def.generic_def(db), - BodyOrSig::VariantFields { def, .. } => match def { - VariantId::EnumVariantId(def) => def.loc(db).parent.into(), - VariantId::StructId(def) => def.into(), - VariantId::UnionId(def) => def.into(), - }, - BodyOrSig::Sig { def, .. } => def, - }; - db.trait_environment(def) - }, - )) + self.param_and(self.body_or_sig.as_ref().map_or_else(ParamEnv::empty, |body_or_sig| { + let def = match *body_or_sig { + BodyOrSig::Body { def, .. } => def.generic_def(db), + BodyOrSig::VariantFields { def, .. } => match def { + VariantId::EnumVariantId(def) => def.loc(db).parent.into(), + VariantId::StructId(def) => def.into(), + VariantId::UnionId(def) => def.into(), + }, + BodyOrSig::Sig { def, .. } => def, + }; + db.trait_environment(def) + })) } pub(crate) fn evaluate_where_clause( diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_impl_members.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_impl_members.rs index 9f9bb1d131548..67fa68df1e9df 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_impl_members.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_impl_members.rs @@ -140,6 +140,7 @@ fn add_missing_impl_members_inner( let missing_items = filter_assoc_items( &ctx.sema, + trait_, &ide_db::traits::get_missing_assoc_items(&ctx.sema, &impl_def), mode, ign_item, @@ -161,6 +162,7 @@ fn add_missing_impl_members_inner( trait_, &impl_def, &target_scope, + mode, ); let Some((first_new_item, other_items)) = new_item.split_first() else { @@ -2747,7 +2749,9 @@ pub trait Read { } impl Read for () { - $0fn read_buf() {} + fn read_buf() { + ${0:todo!()} + } } "#, ); @@ -2887,7 +2891,9 @@ pub trait Read { } impl Read for () { - $0fn read() {} + fn read() { + ${0:todo!()} + } } "#, ); @@ -2918,7 +2924,198 @@ pub trait Read { } impl Read for () { - $0fn read_buf() {} + fn read_buf() { + ${0:todo!()} + } +} + "#, + ); + } + + #[test] + fn required_method_with_body() { + check_assist( + add_missing_impl_members, + r#" +//- minicore: drop, pin +struct Foo; + +impl Drop for Foo { + $0 +} + "#, + r#" +struct Foo; + +impl Drop for Foo { + fn drop(&mut self) { + ${0:todo!()} + } +} + "#, + ); + + check_assist( + add_missing_impl_members, + r#" +#[rustc_must_implement_one_of(read_buf, read)] +pub trait Read { + fn read() { + Self::read_buf() + } + fn read_buf() { + Self::read(); + } +} + +impl Read for () { + $0 +} + "#, + r#" +#[rustc_must_implement_one_of(read_buf, read)] +pub trait Read { + fn read() { + Self::read_buf() + } + fn read_buf() { + Self::read(); + } +} + +impl Read for () { + fn read_buf() { + ${0:todo!()} + } +} + "#, + ); + check_assist( + add_missing_default_members, + r#" +#[rustc_must_implement_one_of(read_buf, read)] +pub trait Read { + fn read() { + Self::read_buf() + } + fn read_buf() { + Self::read(); + } +} + +impl Read for () { + $0 +} + "#, + r#" +#[rustc_must_implement_one_of(read_buf, read)] +pub trait Read { + fn read() { + Self::read_buf() + } + fn read_buf() { + Self::read(); + } +} + +impl Read for () { + $0fn read() { + Self::read_buf() + } +} + "#, + ); + } + + #[test] + fn unstable_item() { + check_assist( + add_missing_impl_members, + r#" +trait Foo { + #[unstable(feature = "foobar")] + fn foobar(); +} + +impl Foo for () { + $0 +} + "#, + r#" +trait Foo { + #[unstable(feature = "foobar")] + fn foobar(); +} + +impl Foo for () { + fn foobar() { + ${0:todo!()} + } +} + "#, + ); + check_assist_not_applicable( + add_missing_default_members, + r#" +trait Foo { + #[unstable(feature = "foobar")] + fn foobar() {} +} + +impl Foo for () { + $0 +} + "#, + ); + check_assist( + add_missing_default_members, + r#" +#![feature(foobar)] + +trait Foo { + #[unstable(feature = "foobar")] + fn foobar() {} +} + +impl Foo for () { + $0 +} + "#, + r#" +#![feature(foobar)] + +trait Foo { + #[unstable(feature = "foobar")] + fn foobar() {} +} + +impl Foo for () { + $0fn foobar() {} +} + "#, + ); + check_assist( + add_missing_default_members, + r#" +#[unstable(feature = "foobar")] +trait Foo { + #[unstable(feature = "foobar")] + fn foobar() {} +} + +impl Foo for () { + $0 +} + "#, + r#" +#[unstable(feature = "foobar")] +trait Foo { + #[unstable(feature = "foobar")] + fn foobar() {} +} + +impl Foo for () { + $0fn foobar() {} } "#, ); diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_impl.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_impl.rs index d88a94e2f7307..9fa9a0461eaa2 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_impl.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_impl.rs @@ -167,6 +167,7 @@ pub(crate) fn generate_impl_trait(acc: &mut Assists, ctx: &AssistContext<'_, '_> let holder_arg = ast::GenericArg::TypeArg(make.type_arg(make.ty_placeholder())); let missing_items = utils::filter_assoc_items( &ctx.sema, + hir_trait, &ide_db::traits::trait_items_with_required(ctx.db(), hir_trait), DefaultMethods::No, IgnoreAssocItems::DocHiddenAttrPresent, @@ -205,6 +206,7 @@ pub(crate) fn generate_impl_trait(acc: &mut Assists, ctx: &AssistContext<'_, '_> hir_trait, &impl_, &target_scope, + DefaultMethods::No, ); let assoc_item_list = make.assoc_item_list(assoc_items); make_impl_(Some(assoc_item_list)) diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs index 8648a013438e7..3e98aadb695c3 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs @@ -233,6 +233,7 @@ fn impl_def_from_trait( let trait_items = filter_assoc_items( sema, + trait_, &ide_db::traits::trait_items_with_required(sema.db, trait_), DefaultMethods::No, ignore_items, @@ -252,6 +253,7 @@ fn impl_def_from_trait( trait_, &impl_def, &target_scope, + DefaultMethods::No, ); let assoc_item_list = if let Some((first, other)) = assoc_items.split_first() { let first_item = if let ast::AssocItem::Fn(func) = first diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/utils.rs b/src/tools/rust-analyzer/crates/ide-assists/src/utils.rs index e5e735faf6f93..8acb887133e0f 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/utils.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/utils.rs @@ -4,7 +4,7 @@ use std::slice; pub(crate) use gen_trait_fn_body::gen_trait_fn_body; use hir::{ - HasAttrs as HirHasAttrs, HirDisplay, InFile, ModuleDef, PathResolution, Semantics, + HasAttrs as HirHasAttrs, HasCrate, HirDisplay, InFile, ModuleDef, PathResolution, Semantics, db::HirDatabase, }; use ide_db::{ @@ -158,11 +158,12 @@ pub enum DefaultMethods { pub fn filter_assoc_items( sema: &Semantics<'_, RootDatabase>, + trait_: hir::Trait, items: &[(hir::AssocItem, IsRequiredAssocItem)], default_methods: DefaultMethods, ignore_items: IgnoreAssocItems, ) -> Vec> { - items + let mut result = items .iter() .copied() .filter(|(assoc_item, is_required)| { @@ -179,16 +180,33 @@ pub fn filter_assoc_items( is_required.0 == (default_methods == DefaultMethods::No) }) + .map(|(item, _)| (item, item.attrs(sema.db).unstable_feature(sema.db))) // Note: This throws away items with no source. - .filter_map(|(assoc_item, _)| { + .filter_map(|(assoc_item, unstable_feature)| { let item = match assoc_item { hir::AssocItem::Function(it) => sema.source(it)?.map(ast::AssocItem::Fn), hir::AssocItem::TypeAlias(it) => sema.source(it)?.map(ast::AssocItem::TypeAlias), hir::AssocItem::Const(it) => sema.source(it)?.map(ast::AssocItem::Const), }; - Some(item) + Some((item, unstable_feature)) }) - .collect() + .collect::>(); + + // Now, we want to filter unstable assoc items whose feature is not enabled, unless: + // - it's required, or + // - the trait has the same feature, so the user probably intends to enable it. + if default_methods == DefaultMethods::Only { + let trait_unstable_feature = trait_.attrs(sema.db).unstable_feature(sema.db); + let krate = trait_.krate(sema.db); + result.retain(|(_, item_unstable_feature)| { + *item_unstable_feature == trait_unstable_feature + || item_unstable_feature + .as_ref() + .is_none_or(|feature| krate.is_unstable_feature_enabled(sema.db, feature)) + }); + } + + result.into_iter().map(|(item, _)| item).collect() } /// Given `original_items` retrieved from the trait definition (usually by @@ -204,6 +222,7 @@ pub fn add_trait_assoc_items_to_impl( trait_: hir::Trait, impl_: &ast::Impl, target_scope: &hir::SemanticsScope<'_>, + default_mode: DefaultMethods, ) -> Vec { let new_indent_level = IndentLevel::from_node(impl_.syntax()) + 1; original_items @@ -240,7 +259,10 @@ pub fn add_trait_assoc_items_to_impl( ast::AssocItem::cast(editor.finish().new_root().clone()).unwrap() }) .filter_map(|item| match item { - ast::AssocItem::Fn(fn_) if fn_.body().is_none() => { + // We can check `fn_.body().is_none()`, but this is actually not what we want to check: some functions (`Drop::drop()` + // or `#[rustc_must_implement_one_of]`) have a default body that should be ignored. So the criteria is whether + // we requested required or defaulted methods, and not whether the method actually has a body. + ast::AssocItem::Fn(fn_) if default_mode == DefaultMethods::No => { let (fn_editor, fn_) = SyntaxEditor::with_ast_node(&fn_); let fill_expr: ast::Expr = match config.expr_fill_default { ExprFillDefaultMode::Todo | ExprFillDefaultMode::Default => make.expr_todo(), diff --git a/src/tools/rust-analyzer/crates/ide-db/src/ra_fixture.rs b/src/tools/rust-analyzer/crates/ide-db/src/ra_fixture.rs index 09a270c143888..ee61cab4828c5 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/ra_fixture.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/ra_fixture.rs @@ -307,7 +307,7 @@ impl IsEmpty for SmallVec<[T; N]> { } } -#[allow(clippy::disallowed_types)] +#[expect(clippy::disallowed_types, reason = "generic allows for `FxHashMap`")] impl IsEmpty for std::collections::HashMap { fn is_empty(&self) -> bool { self.is_empty() @@ -376,7 +376,7 @@ impl UpmapFromRaFixture for SmallVec<[T; } } -#[allow(clippy::disallowed_types)] +#[expect(clippy::disallowed_types, reason = "generic allows for `FxHashMap`")] impl UpmapFromRaFixture for std::collections::HashMap { @@ -391,7 +391,7 @@ impl UpmapFromRaFixture for std::collections::HashMap { diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/incorrect_case.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/incorrect_case.rs index a72da8e7722a5..e13693df99560 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/incorrect_case.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/incorrect_case.rs @@ -247,6 +247,16 @@ struct SCREAMING_CASE {} ); } + #[test] + fn incorrect_raw_struct_name() { + check_diagnostics( + r#" +struct r#pub {} + // ^^^^^ 💡 warn: Structure `r#pub` should have UpperCamelCase name, e.g. `Pub` +"#, + ); + } + #[test] fn no_diagnostic_for_camel_cased_acronyms_in_struct_name() { check_diagnostics( @@ -340,6 +350,16 @@ enum SomeEnum { SOME_VARIANT(u8) } ); } + #[test] + fn incorrect_raw_enum_variant_name() { + check_diagnostics( + r#" +enum SomeEnum { r#pub } + // ^^^^^ 💡 warn: Variant `r#pub` should have UpperCamelCase name, e.g. `Pub` +"#, + ); + } + #[test] fn incorrect_const_name() { check_diagnostics( diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/json_is_not_rust.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/json_is_not_rust.rs index 24f1e3ad836a0..52532172ccda0 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/json_is_not_rust.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/json_is_not_rust.rs @@ -23,9 +23,21 @@ struct State { has_serialize: bool, has_deserialize: bool, names: FxHashMap, + edition: Option, } impl State { + fn make_name(&self, name: &str) -> ast::Name { + let edition = self.edition.unwrap(); + if syntax::utils::is_identifier(name, edition) + || syntax::utils::is_raw_identifier(name, edition) + { + make::name(name) + } else { + make::name("INVALID") + } + } + fn generate_new_name(&mut self, name: &str) -> ast::Name { let name = stdx::to_camel_case(name); let count = if let Some(count) = self.names.get_mut(&name) { @@ -35,7 +47,7 @@ impl State { self.names.insert(name.clone(), 1); 1 }; - make::name(&format!("{name}{count}")) + self.make_name(&format!("{name}{count}")) } fn serde_derive(&self) -> String { @@ -70,7 +82,7 @@ impl State { None, make::record_field_list(value.iter().sorted_unstable_by_key(|x| x.0).map( |(name, value)| { - make::record_field(None, make::name(name), self.type_of(name, value)) + make::record_field(None, self.make_name(name), self.type_of(name, value)) }, )) .into(), @@ -125,6 +137,7 @@ pub(crate) fn json_in_items( let serialize_resolved = scope_resolve("::serde::Serialize"); state.has_deserialize = deserialize_resolved.is_some(); state.has_serialize = serialize_resolved.is_some(); + state.edition = Some(edition); state.build_struct("Root", &it); edit.insert(range.start(), state.result); let vfs_file_id = file_id.file_id(sema.db); @@ -342,6 +355,36 @@ mod tests { ); } + #[test] + fn invalid_fields() { + check_fix( + r#" + //- /lib.rs crate:lib deps:serde + {$0 + "$": "", + "self": "", + "valided": "" + } + //- /serde.rs crate:serde + + pub trait Serialize { + fn serialize() -> u8; + } + pub trait Deserialize { + fn deserialize() -> u8; + } + "#, + r#" + use serde::Serialize; + use serde::Deserialize; + + #[derive(Serialize, Deserialize)] + struct Root1 { INVALID: String, INVALID: String, valided: String } + + "#, + ); + } + #[test] fn no_emit_outside_of_item_position() { check_no_fix( diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/type_mismatch.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/type_mismatch.rs index f70795ed29bde..1e92a795e47a9 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/type_mismatch.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/type_mismatch.rs @@ -2019,4 +2019,25 @@ fn test(_: Result) { "#, ); } + + #[test] + fn regression_23313() { + check_diagnostics( + r#" +fn hello_world() {} + +struct Wrapper ()>; + +impl ()> Wrapper<{ + Wrapper::<{hello_world}>::call(); + // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: no such associated item + }> { +//^ 💡 error: expected fn(), found () + fn hello_world() { + F(); + } +} + "#, + ); + } } diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/typed_hole.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/typed_hole.rs index e2d31503f1d08..e93e74177abe8 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/typed_hole.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/typed_hole.rs @@ -464,6 +464,20 @@ fn main() { m!(generic::); } } +"#, + ); + } + + #[test] + fn term_search_lookup_const() { + check_diagnostics( + r#" +struct S { f: i32 } +const C: i32 = 0; +fn main() { + let _: S = _; + //^ 💡 error: invalid `_` expression, expected type `S` +} "#, ); } diff --git a/src/tools/rust-analyzer/crates/ide-ssr/src/matching.rs b/src/tools/rust-analyzer/crates/ide-ssr/src/matching.rs index ab5a0f70f5a69..c87a10d8e85b7 100644 --- a/src/tools/rust-analyzer/crates/ide-ssr/src/matching.rs +++ b/src/tools/rust-analyzer/crates/ide-ssr/src/matching.rs @@ -315,7 +315,6 @@ impl<'db, 'sema> Matcher<'db, 'sema> { Ok(()) } - #[allow(clippy::only_used_in_recursion)] fn check_constraint( &self, constraint: &Constraint, diff --git a/src/tools/rust-analyzer/crates/ide/src/doc_links.rs b/src/tools/rust-analyzer/crates/ide/src/doc_links.rs index c152d7e9cc964..94e7db9390bc3 100644 --- a/src/tools/rust-analyzer/crates/ide/src/doc_links.rs +++ b/src/tools/rust-analyzer/crates/ide/src/doc_links.rs @@ -312,7 +312,10 @@ impl DocCommentToken { let DocCommentToken { prefix_len, doc_token } = self; // offset relative to the comments contents let original_start = doc_token.text_range().start(); - let relative_comment_offset = offset - original_start - prefix_len; + // If the cursor points inside the comment like `///` or to the first quote in `#[doc = "..."]` + // (i.e. relative_comment_offset is None) then we return w/o definition. + let relative_comment_offset = + offset.checked_sub(original_start)?.checked_sub(prefix_len)?; sema.descend_into_macros(doc_token).into_iter().find_map(|t| { let (node, descended_prefix_len, is_inner) = match_ast!{ diff --git a/src/tools/rust-analyzer/crates/ide/src/goto_definition.rs b/src/tools/rust-analyzer/crates/ide/src/goto_definition.rs index 033de7dcc20b4..bb317525dd5d8 100644 --- a/src/tools/rust-analyzer/crates/ide/src/goto_definition.rs +++ b/src/tools/rust-analyzer/crates/ide/src/goto_definition.rs @@ -723,6 +723,13 @@ mod tests { assert!(navs.is_empty(), "didn't expect this to resolve anywhere: {navs:?}") } + #[track_caller] + fn check_no_definition(#[rust_analyzer::rust_fixture] ra_fixture: &str) { + let (analysis, position) = fixture::position(ra_fixture); + let navs = analysis.goto_definition(position, &TEST_CONFIG).unwrap(); + assert!(navs.is_none(), "didn't expect this to resolve anywhere: {navs:?}"); + } + fn check_name(expected_name: &str, #[rust_analyzer::rust_fixture] ra_fixture: &str) { let (analysis, position, _) = fixture::annotations(ra_fixture); let navs = analysis @@ -2132,6 +2139,30 @@ pub fn foo() { } ) } + #[test] + fn no_panic_on_offset_inside_doc_comment_prefix() { + // If the cursor (offset) points inside `///`/`//!`/the opening quote, i.e. before the docs' contents, + // this should not create navigation. + check_no_definition( + r#" +$0/// [`S`] +struct S; +"#, + ); + check_no_definition( + r#" +//$0! [`S`] +struct S; +"#, + ); + check_no_definition( + r#" +#[doc = $0"[`S`]"] +struct S; +"#, + ); + } + #[test] fn goto_def_for_intra_doc_link_outer_same_file() { check( diff --git a/src/tools/rust-analyzer/crates/ide/src/hover.rs b/src/tools/rust-analyzer/crates/ide/src/hover.rs index 92473de4e634f..6f5878071aaa8 100644 --- a/src/tools/rust-analyzer/crates/ide/src/hover.rs +++ b/src/tools/rust-analyzer/crates/ide/src/hover.rs @@ -156,7 +156,6 @@ pub(crate) fn hover( Some(res) } -#[allow(clippy::field_reassign_with_default)] fn hover_offset( sema: &Semantics<'_, RootDatabase>, FilePosition { file_id, offset }: FilePosition, diff --git a/src/tools/rust-analyzer/crates/proc-macro-api/src/bidirectional_protocol/msg.rs b/src/tools/rust-analyzer/crates/proc-macro-api/src/bidirectional_protocol/msg.rs index e516297f06196..22aac04c28e09 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-api/src/bidirectional_protocol/msg.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-api/src/bidirectional_protocol/msg.rs @@ -1,13 +1,11 @@ //! Bidirectional protocol messages -#![expect(clippy::disallowed_types)] - use std::{ - collections::{HashMap, HashSet}, io::{self, BufRead, Write}, ops::Range, }; use paths::Utf8PathBuf; +use rustc_hash::{FxHashMap, FxHashSet}; use serde::{Deserialize, Serialize}; use crate::{ @@ -122,7 +120,6 @@ pub struct SpanJoin { pub ctx: u32, } -#[expect(clippy::large_enum_variant)] #[derive(Debug, Serialize, Deserialize)] pub enum BidirectionalMessage { Request(Request), @@ -139,7 +136,6 @@ pub enum Request { SetConfig(ServerConfig), } -#[expect(clippy::large_enum_variant)] #[derive(Debug, Serialize, Deserialize)] pub enum Response { ListMacros(Result, String>), @@ -168,8 +164,8 @@ pub struct ExpandMacro { pub struct ExpandMacroResponse { pub tree: FlatTree, pub span_data_table: Vec, - pub tracked_env_vars: HashMap, Option>>, - pub tracked_paths: HashSet>, + pub tracked_env_vars: FxHashMap, Option>>, + pub tracked_paths: FxHashSet>, } #[derive(Debug, Serialize, Deserialize)] diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/Cargo.toml b/src/tools/rust-analyzer/crates/proc-macro-srv/Cargo.toml index 05e0012586d5f..0427d0ee74a6e 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv/Cargo.toml +++ b/src/tools/rust-analyzer/crates/proc-macro-srv/Cargo.toml @@ -14,6 +14,7 @@ doctest = false [dependencies] paths.workspace = true +rustc-hash.workspace = true # span = {workspace = true, default-features = false} does not work span = { path = "../span", version = "0.0.0", default-features = false} intern.workspace = true diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/lib.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/lib.rs index 7fc04a05155f8..e38d2ac11bce8 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/lib.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/lib.rs @@ -10,7 +10,7 @@ #![cfg(feature = "in-rust-tree")] #![feature(proc_macro_internals, proc_macro_diagnostic, proc_macro_span, rustc_private)] -#![expect(internal_features, clippy::disallowed_types, clippy::print_stderr)] +#![expect(internal_features)] #![allow(unused_features, unused_crate_dependencies)] #![deny(deprecated_safe, clippy::undocumented_unsafe_blocks)] #![cfg_attr(test, expect(unreachable_pub))] @@ -29,7 +29,7 @@ mod server_impl; mod token_stream; use std::{ - collections::{HashMap, HashSet, hash_map::Entry}, + collections::hash_map::Entry, env, ffi::OsString, fs, @@ -40,6 +40,7 @@ use std::{ }; use paths::{Utf8Path, Utf8PathBuf}; +use rustc_hash::{FxHashMap, FxHashSet}; use span::{FIXUP_ERASED_FILE_AST_ID_MARKER, Span}; pub use crate::server_impl::token_id::SpanId; @@ -61,7 +62,7 @@ pub enum ProcMacroKind { pub const RUSTC_VERSION_STRING: &str = env!("RUSTC_VERSION"); pub struct ProcMacroSrv<'env> { - expanders: Mutex>>, + expanders: Mutex>>, env: &'env EnvSnapshot, } @@ -226,8 +227,8 @@ impl ProcMacroSrv<'_> { #[derive(Default)] pub struct TrackedEnv { - pub env_vars: HashMap, Option>>, - pub paths: HashSet>, + pub env_vars: FxHashMap, Option>>, + pub paths: FxHashSet>, } pub trait ProcMacroSrvSpan: Copy + Send + Sync { @@ -289,7 +290,7 @@ impl PanicMessage { } pub struct EnvSnapshot { - vars: HashMap, + vars: FxHashMap, } impl Default for EnvSnapshot { diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs index 6cbb0c718c3e6..8c8ad34f6c441 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs @@ -19,10 +19,7 @@ use hir_def::{ expr_store::{Body, BodySourceMap, ExpressionStore}, hir::{ExprId, PatId, generics::GenericParams}, }; -use hir_ty::{ - InferenceResult, - next_solver::{DbInterner, GenericArgs}, -}; +use hir_ty::{InferenceResult, next_solver::GenericArgs}; use ide::{ Analysis, AnalysisHost, AnnotationConfig, DiagnosticsConfig, Edition, InlayFieldsToResolve, InlayHintsConfig, LineCol, RaFixtureConfig, RootDatabase, @@ -411,7 +408,6 @@ impl flags::AnalysisStats { let mut all = 0; let mut fail = 0; for &a in adts { - let interner = DbInterner::new_no_crate(db); let generic_params = GenericParams::of(db, a.into()); if generic_params.iter_type_or_consts().next().is_some() || generic_params.iter_lt().next().is_some() @@ -422,7 +418,7 @@ impl flags::AnalysisStats { all += 1; let Err(e) = db.layout_of_adt( hir_def::AdtId::from(a), - GenericArgs::empty(interner).store(), + GenericArgs::empty().store(), hir_ty::ParamEnvAndCrate { param_env: db.trait_environment(a.into()), krate: a.krate(db).into(), diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/discover.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/discover.rs index 04d0cedb3eca2..f9491af71e7e1 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/discover.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/discover.rs @@ -68,7 +68,7 @@ impl DiscoverCommand { Ok(DiscoverHandle { handle: CommandHandle::spawn(cmd, DiscoverProjectParser, self.sender.clone(), None)?, - span: info_span!("discover_command").entered(), + _span: info_span!("discover_command").entered(), }) } } @@ -77,8 +77,8 @@ impl DiscoverCommand { #[derive(Debug)] pub(crate) struct DiscoverHandle { pub(crate) handle: CommandHandle, - #[allow(dead_code)] // not accessed, but used to log on drop. - span: EnteredSpan, + // not accessed, but used to log on drop. + _span: EnteredSpan, } /// An enum containing either progress messages, an error, diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/flycheck.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/flycheck.rs index 85edb239e3f57..7f1f4ef137054 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/flycheck.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/flycheck.rs @@ -490,7 +490,7 @@ impl<'a> Substitutions<'a> { /// /// Same for {saved_file}. /// - #[allow(clippy::disallowed_types)] /* generic parameter allows for FxHashMap */ + #[expect(clippy::disallowed_types, reason = "generic parameter allows for `FxHashMap`")] fn substitute( self, template: &project_json::Runnable, diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/ext.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/ext.rs index 8e0bb285c2318..19e067334e008 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/ext.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/ext.rs @@ -4,7 +4,12 @@ // might strip `false` values from the JSON payload due to their reserialization logic turning false // into null which will then cause them to be omitted in the resolve request. See https://github.com/rust-lang/rust-analyzer/issues/18767 -#![allow(clippy::disallowed_types)] +// FIXME: ideally we'd put this on `SnippetWorkspaceEdit.change_annotations`, but that doesn't work, +// most likely because the lint fires in the impls generated by the derives as well. +#![expect( + clippy::disallowed_types, + reason = "`SnippetWorkspaceEdit.change_annotations` needs to match `lsp_types::WorkspaceEdit.change_annotations` for the `From` impl" +)] use std::ops; diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/main.rs b/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/main.rs index 56629f79ea216..4199cb29e66d2 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/main.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/main.rs @@ -8,7 +8,6 @@ //! specific JSON shapes here -- there's little value in such tests, as we can't //! be sure without a real client anyway. -#![allow(clippy::disallowed_types)] #![cfg_attr(feature = "in-rust-tree", feature(rustc_private))] #[cfg(feature = "in-rust-tree")] diff --git a/src/tools/rust-analyzer/crates/stdx/src/rand.rs b/src/tools/rust-analyzer/crates/stdx/src/rand.rs index e028990900af6..07dfa6ef8877c 100644 --- a/src/tools/rust-analyzer/crates/stdx/src/rand.rs +++ b/src/tools/rust-analyzer/crates/stdx/src/rand.rs @@ -14,6 +14,6 @@ pub fn shuffle(slice: &mut [T], mut rand_index: impl FnMut(usize) -> usize) { pub fn seed() -> u64 { use std::hash::{BuildHasher, Hasher}; - #[allow(clippy::disallowed_types)] + #[expect(clippy::disallowed_types, reason = "we need a source of randomness for the seed")] std::collections::hash_map::RandomState::new().build_hasher().finish() } diff --git a/src/tools/rust-analyzer/crates/stdx/src/variance.rs b/src/tools/rust-analyzer/crates/stdx/src/variance.rs index 8465d72bf3719..0f87d1bd9bcc6 100644 --- a/src/tools/rust-analyzer/crates/stdx/src/variance.rs +++ b/src/tools/rust-analyzer/crates/stdx/src/variance.rs @@ -70,12 +70,11 @@ macro_rules! phantom_type { impl Eq for $name where T: ?Sized {} - #[allow(clippy::non_canonical_partial_ord_impl)] impl PartialOrd for $name where T: ?Sized { - fn partial_cmp(&self, _: &Self) -> Option { - Some(Ordering::Equal) + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) } } diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/expr_ext.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/expr_ext.rs index ced9163f661af..2b1c91f20517d 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/ast/expr_ext.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/ast/expr_ext.rs @@ -335,7 +335,7 @@ impl ast::Literal { pub fn token(&self) -> SyntaxToken { self.syntax() .children_with_tokens() - .find(|e| e.kind() != ATTR && !e.kind().is_trivia()) + .find(|e| !ast::AnyAttr::can_cast(e.kind()) && !e.kind().is_trivia()) .and_then(|e| e.into_token()) .unwrap() } diff --git a/src/tools/rust-analyzer/crates/syntax/src/tests.rs b/src/tools/rust-analyzer/crates/syntax/src/tests.rs index e5beb44f42ec7..1002fdd902d29 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/tests.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/tests.rs @@ -126,6 +126,12 @@ fn self_hosting_parsing() { } } +#[test] +fn doc_comment_on_literal_expr() { + let parse = SourceFile::parse("fn f() { ///\n0..0; }", parser::Edition::CURRENT); + assert!(parse.errors().is_empty()); +} + fn test_data_dir() -> PathBuf { project_root().into_std_path_buf().join("crates/syntax/test_data") } diff --git a/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs b/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs index 0d9bb4f92bdc0..129e63d3988b5 100644 --- a/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs +++ b/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs @@ -670,7 +670,11 @@ pub mod ops { // region:drop #[lang = "drop"] pub trait Drop { - fn drop(&mut self); + fn drop(&mut self) { + // region:pin + Drop::pin_drop(crate::pin::Pin::new(self)) + // endregion:pin + } // region:pin fn pin_drop(self: crate::pin::Pin<&mut Self>) {} diff --git a/src/tools/rust-analyzer/crates/toolchain/src/lib.rs b/src/tools/rust-analyzer/crates/toolchain/src/lib.rs index 6bed98f4cd2d7..26883add08699 100644 --- a/src/tools/rust-analyzer/crates/toolchain/src/lib.rs +++ b/src/tools/rust-analyzer/crates/toolchain/src/lib.rs @@ -74,7 +74,7 @@ impl Tool { // Prevent rustup from automatically installing toolchains, see https://github.com/rust-lang/rust-analyzer/issues/20719. pub const NO_RUSTUP_AUTO_INSTALL_ENV: (&str, &str) = ("RUSTUP_AUTO_INSTALL", "0"); -#[allow(clippy::disallowed_types)] /* generic parameter allows for FxHashMap */ +#[expect(clippy::disallowed_types, reason = "generic parameter allows for `FxHashMap`")] pub fn command( cmd: impl AsRef, working_directory: impl AsRef, diff --git a/src/tools/rust-analyzer/docs/book/src/contributing/lsp-extensions.md b/src/tools/rust-analyzer/docs/book/src/contributing/lsp-extensions.md index da4a5aaa686c5..42bdb5dc1055a 100644 --- a/src/tools/rust-analyzer/docs/book/src/contributing/lsp-extensions.md +++ b/src/tools/rust-analyzer/docs/book/src/contributing/lsp-extensions.md @@ -1,5 +1,5 @@ $DIR/unexpected-type-for-constructor.rs:7:35 + | +LL | const C_INNER: (*const u8, u8) = (None::, None::); + | ^^^^^^^^^^ expected `*const u8`, found `Option` + | + = note: expected raw pointer `*const u8` + found enum `Option` + +error[E0308]: mismatched types + --> $DIR/unexpected-type-for-constructor.rs:7:47 + | +LL | const C_INNER: (*const u8, u8) = (None::, None::); + | ^^^^^^^^^^ expected `u8`, found `Option` + | + = note: expected type `u8` + found enum `Option` + +error: could not evaluate constant pattern + --> $DIR/unexpected-type-for-constructor.rs:13:9 + | +LL | const C_INNER: (*const u8, u8) = (None::, None::); + | ------------------------------ constant defined here +... +LL | C_INNER => {} + | ^^^^^^^ could not evaluate constant + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/mgca/valtree-leaf-const.rs b/tests/ui/const-generics/mgca/valtree-leaf-const.rs new file mode 100644 index 0000000000000..e372e89fe5e50 --- /dev/null +++ b/tests/ui/const-generics/mgca/valtree-leaf-const.rs @@ -0,0 +1,12 @@ +//@ compile-flags: -Znext-solver + +#![feature(macroless_generic_const_args)] +#![feature(generic_const_args)] +#![feature(min_generic_const_args)] + +const TUPLE: (&'static str, &'static str) = ("a", true); +//~^ ERROR mismatched type + +fn main() { + TUPLE; +} diff --git a/tests/ui/const-generics/mgca/valtree-leaf-const.stderr b/tests/ui/const-generics/mgca/valtree-leaf-const.stderr new file mode 100644 index 0000000000000..db45a82198752 --- /dev/null +++ b/tests/ui/const-generics/mgca/valtree-leaf-const.stderr @@ -0,0 +1,9 @@ +error[E0308]: mismatched types + --> $DIR/valtree-leaf-const.rs:7:51 + | +LL | const TUPLE: (&'static str, &'static str) = ("a", true); + | ^^^^ expected `&str`, found `bool` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/explicit-tail-calls/tailcc-no-signature-restriction.rs b/tests/ui/explicit-tail-calls/tailcc-no-signature-restriction.rs index 64cea66c1d565..e32aaa6b6966e 100644 --- a/tests/ui/explicit-tail-calls/tailcc-no-signature-restriction.rs +++ b/tests/ui/explicit-tail-calls/tailcc-no-signature-restriction.rs @@ -40,10 +40,32 @@ pub extern "tail" fn pass_struct(a: u64, d: u64) -> u64 { become add(large); } +#[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), not(windows)))] +#[inline(never)] +pub extern "tail" fn pass_vector(x: [f32; 4]) -> [f32; 4] { + #[derive(Clone, Copy)] + pub struct F32x4([f32; 4]); + + #[inline(never)] + extern "tail" fn identity(x: F32x4) -> F32x4 { + x + } + + #[inline(never)] + extern "tail" fn forward(x: F32x4) -> F32x4 { + become identity(x); + } + + forward(F32x4(x)).0 +} + fn main() { assert_eq!(add(), 3); - // Windows and Aarch64 in LLVM 23 does not support byval arguments. + // Windows and Aarch64 in LLVM 23 do not support byval arguments. #[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), not(windows)))] - assert_eq!(pass_struct(5, 6), 5 + 6); + { + assert_eq!(pass_struct(5, 6), 5 + 6); + assert_eq!(pass_vector([1.0, 2.0, 3.0, 4.0]), [1.0, 2.0, 3.0, 4.0]); + } } diff --git a/tests/ui/fn/fn-ptr-pattern.rs b/tests/ui/fn/fn-ptr-pattern.rs index 9bf759af19af7..4260a5095048e 100644 --- a/tests/ui/fn/fn-ptr-pattern.rs +++ b/tests/ui/fn/fn-ptr-pattern.rs @@ -42,6 +42,8 @@ fn semantics( //~^ ERROR patterns aren't allowed in function pointer types restricted_pat6: fn(&true: ()), //~^ ERROR patterns aren't allowed in function pointer types + + duplicate_names: fn(x: usize, x: usize), ) { } // Patterns are also syntactically rejected, but restricted patterns are not diff --git a/tests/ui/fn/fn-ptr-pattern.stderr b/tests/ui/fn/fn-ptr-pattern.stderr index 4425caee39e3f..27982d26dbc54 100644 --- a/tests/ui/fn/fn-ptr-pattern.stderr +++ b/tests/ui/fn/fn-ptr-pattern.stderr @@ -71,7 +71,7 @@ LL | self3: fn(bool, self), | ^^^^ must be the first parameter of an associated function error[E0642]: patterns aren't allowed in function pointer types - --> $DIR/fn-ptr-pattern.rs:50:14 + --> $DIR/fn-ptr-pattern.rs:52:14 | LL | pat1: fn(1..3: bool), | ^^^^ @@ -83,7 +83,7 @@ LL + pat1: fn(_: bool), | error[E0642]: patterns aren't allowed in function pointer types - --> $DIR/fn-ptr-pattern.rs:52:14 + --> $DIR/fn-ptr-pattern.rs:54:14 | LL | pat2: fn((x, y): (bool, bool)), | ^^^^^^ @@ -95,7 +95,7 @@ LL + pat2: fn(_: (bool, bool)), | error[E0642]: patterns aren't allowed in function pointer types - --> $DIR/fn-ptr-pattern.rs:54:14 + --> $DIR/fn-ptr-pattern.rs:56:14 | LL | pat3: fn(Thing { a, b }: Thing), | ^^^^^^^^^^^^^^ @@ -107,7 +107,7 @@ LL + pat3: fn(_: Thing), | error[E0642]: patterns aren't allowed in function pointer types - --> $DIR/fn-ptr-pattern.rs:56:14 + --> $DIR/fn-ptr-pattern.rs:58:14 | LL | pat4: fn(NoThing { a, b }: NoThing), | ^^^^^^^^^^^^^^^^ @@ -119,7 +119,7 @@ LL + pat4: fn(_: NoThing), | error[E0642]: patterns aren't allowed in function pointer types - --> $DIR/fn-ptr-pattern.rs:58:14 + --> $DIR/fn-ptr-pattern.rs:60:14 | LL | pat5: fn((((((x))))): bool), | ^^^^^^^^^^^ @@ -131,13 +131,13 @@ LL + pat5: fn(_: bool), | error: unexpected `self` parameter in function - --> $DIR/fn-ptr-pattern.rs:62:21 + --> $DIR/fn-ptr-pattern.rs:64:21 | LL | self2: fn(self, self), | ^^^^ must be the first parameter of an associated function error: unexpected `self` parameter in function - --> $DIR/fn-ptr-pattern.rs:64:21 + --> $DIR/fn-ptr-pattern.rs:66:21 | LL | self3: fn(bool, self), | ^^^^ must be the first parameter of an associated function @@ -201,7 +201,7 @@ LL | pat4: fn(NoThing { a, b }: NoThing), | ^^^^^^^ not found in this scope | note: similarly named struct `Thing` defined here - --> $DIR/fn-ptr-pattern.rs:75:1 + --> $DIR/fn-ptr-pattern.rs:77:1 | LL | struct Thing { a: bool, b: bool } | ^^^^^^^^^^^^ diff --git a/tests/ui/fn/named-fn-trait-parameters.rs b/tests/ui/fn/named-fn-trait-parameters.rs index 00b00b53a94d6..103ce5902048e 100644 --- a/tests/ui/fn/named-fn-trait-parameters.rs +++ b/tests/ui/fn/named-fn-trait-parameters.rs @@ -15,52 +15,58 @@ fn allowed( // Patterns are semantically rejected fn semantics( pat1: impl Fn(1..3: bool), - //~^ ERROR expected type, found `1` + //~^ ERROR patterns aren't allowed in parenthesized argument list pat2: impl Fn((x, y): (bool, bool)), - //~^ ERROR unexpected token: `:` + //~^ ERROR patterns aren't allowed in parenthesized argument list pat3: impl Fn(Thing { a, b }: Thing), - //~^ ERROR expected one of `!`, `(`, `+`, `::`, or `<`, found `{` + //~^ ERROR patterns aren't allowed in parenthesized argument list pat4: impl Fn(NoThing { a, b }: NoThing), - //~^ ERROR expected one of `!`, `(`, `+`, `::`, or `<`, found `{` + //~^ ERROR patterns aren't allowed in parenthesized argument list + //~| ERROR cannot find type `NoThing` in this scope pat5: impl Fn((((((x))))): bool), - //~^ ERROR unexpected token: `:` + //~^ ERROR patterns aren't allowed in parenthesized argument list self1: impl Fn(self), - //~^ ERROR unexpected `self` parameter in function + //~^ ERROR `self` parameter is only allowed in associated functions self2: impl Fn(self, self), - //~^ ERROR unexpected `self` parameter in function + //~^ ERROR `self` parameter is only allowed in associated functions //~| ERROR unexpected `self` parameter in function self3: impl Fn(bool, self), //~^ ERROR unexpected `self` parameter in function - // FIXME should be rejected restricted_pat1: impl Fn(mut x: ()), + //~^ ERROR patterns aren't allowed in parenthesized argument lists restricted_pat2: impl Fn(&x: ()), + //~^ ERROR patterns aren't allowed in parenthesized argument lists restricted_pat3: impl Fn(&&x: ()), + //~^ ERROR patterns aren't allowed in parenthesized argument lists restricted_pat4: impl Fn(false: ()), + //~^ ERROR patterns aren't allowed in parenthesized argument lists restricted_pat5: impl Fn(&_: ()), + //~^ ERROR patterns aren't allowed in parenthesized argument lists restricted_pat6: impl Fn(&true: ()), + //~^ ERROR patterns aren't allowed in parenthesized argument lists + + duplicate_names: impl Fn(x: usize, x: usize), ) { } // Patterns are also syntactically rejected, but restricted patterns are not #[cfg(false)] fn syntax( pat1: impl Fn(1..3: bool), - //~^ ERROR expected type, found `1` + //~^ ERROR patterns aren't allowed in parenthesized argument list pat2: impl Fn((x, y): (bool, bool)), - //~^ ERROR unexpected token: `:` + //~^ ERROR patterns aren't allowed in parenthesized argument list pat3: impl Fn(Thing { a, b }: Thing), - //~^ ERROR expected one of `!`, `(`, `+`, `::`, or `<`, found `{` + //~^ ERROR patterns aren't allowed in parenthesized argument list pat4: impl Fn(NoThing { a, b }: NoThing), - //~^ ERROR expected one of `!`, `(`, `+`, `::`, or `<`, found `{` + //~^ ERROR patterns aren't allowed in parenthesized argument list pat5: impl Fn((((((x))))): bool), - //~^ ERROR unexpected token: `:` + //~^ ERROR patterns aren't allowed in parenthesized argument list - self1: impl Fn(self), // FIXME should be accepted - //~^ ERROR unexpected `self` parameter in function + self1: impl Fn(self), self2: impl Fn(self, self), //~^ ERROR unexpected `self` parameter in function - //~| ERROR unexpected `self` parameter in function self3: impl Fn(bool, self), //~^ ERROR unexpected `self` parameter in function diff --git a/tests/ui/fn/named-fn-trait-parameters.stderr b/tests/ui/fn/named-fn-trait-parameters.stderr index fa583ec52c543..d675826ff8559 100644 --- a/tests/ui/fn/named-fn-trait-parameters.stderr +++ b/tests/ui/fn/named-fn-trait-parameters.stderr @@ -1,110 +1,217 @@ -error: expected type, found `1` +error[E0642]: patterns aren't allowed in parenthesized argument list --> $DIR/named-fn-trait-parameters.rs:17:19 | LL | pat1: impl Fn(1..3: bool), - | ^ expected type + | ^^^^ + | +help: give this argument a name or use an underscore to ignore it + | +LL - pat1: impl Fn(1..3: bool), +LL + pat1: impl Fn(_: bool), + | -error: unexpected token: `:` - --> $DIR/named-fn-trait-parameters.rs:19:25 +error[E0642]: patterns aren't allowed in parenthesized argument list + --> $DIR/named-fn-trait-parameters.rs:19:19 | LL | pat2: impl Fn((x, y): (bool, bool)), - | ^ unexpected token after this + | ^^^^^^ + | +help: give this argument a name or use an underscore to ignore it + | +LL - pat2: impl Fn((x, y): (bool, bool)), +LL + pat2: impl Fn(_: (bool, bool)), + | -error: expected one of `!`, `(`, `+`, `::`, or `<`, found `{` - --> $DIR/named-fn-trait-parameters.rs:21:25 +error[E0642]: patterns aren't allowed in parenthesized argument list + --> $DIR/named-fn-trait-parameters.rs:21:19 | LL | pat3: impl Fn(Thing { a, b }: Thing), - | ^ expected one of `!`, `(`, `+`, `::`, or `<` + | ^^^^^^^^^^^^^^ + | +help: give this argument a name or use an underscore to ignore it + | +LL - pat3: impl Fn(Thing { a, b }: Thing), +LL + pat3: impl Fn(_: Thing), + | -error: expected one of `!`, `(`, `+`, `::`, or `<`, found `{` - --> $DIR/named-fn-trait-parameters.rs:23:27 +error[E0642]: patterns aren't allowed in parenthesized argument list + --> $DIR/named-fn-trait-parameters.rs:23:19 | LL | pat4: impl Fn(NoThing { a, b }: NoThing), - | ^ expected one of `!`, `(`, `+`, `::`, or `<` + | ^^^^^^^^^^^^^^^^ + | +help: give this argument a name or use an underscore to ignore it + | +LL - pat4: impl Fn(NoThing { a, b }: NoThing), +LL + pat4: impl Fn(_: NoThing), + | -error: unexpected token: `:` - --> $DIR/named-fn-trait-parameters.rs:25:30 +error[E0642]: patterns aren't allowed in parenthesized argument list + --> $DIR/named-fn-trait-parameters.rs:26:19 | LL | pat5: impl Fn((((((x))))): bool), - | ^ unexpected token after this - -error: unexpected `self` parameter in function - --> $DIR/named-fn-trait-parameters.rs:28:20 + | ^^^^^^^^^^^ | -LL | self1: impl Fn(self), - | ^^^^ must be the first parameter of an associated function - -error: unexpected `self` parameter in function - --> $DIR/named-fn-trait-parameters.rs:30:20 +help: give this argument a name or use an underscore to ignore it + | +LL - pat5: impl Fn((((((x))))): bool), +LL + pat5: impl Fn(_: bool), | -LL | self2: impl Fn(self, self), - | ^^^^ must be the first parameter of an associated function error: unexpected `self` parameter in function - --> $DIR/named-fn-trait-parameters.rs:30:26 + --> $DIR/named-fn-trait-parameters.rs:31:26 | LL | self2: impl Fn(self, self), | ^^^^ must be the first parameter of an associated function error: unexpected `self` parameter in function - --> $DIR/named-fn-trait-parameters.rs:33:26 + --> $DIR/named-fn-trait-parameters.rs:34:26 | LL | self3: impl Fn(bool, self), | ^^^^ must be the first parameter of an associated function -error: expected type, found `1` - --> $DIR/named-fn-trait-parameters.rs:48:19 +error[E0642]: patterns aren't allowed in parenthesized argument list + --> $DIR/named-fn-trait-parameters.rs:56:19 | LL | pat1: impl Fn(1..3: bool), - | ^ expected type + | ^^^^ + | +help: give this argument a name or use an underscore to ignore it + | +LL - pat1: impl Fn(1..3: bool), +LL + pat1: impl Fn(_: bool), + | -error: unexpected token: `:` - --> $DIR/named-fn-trait-parameters.rs:50:25 +error[E0642]: patterns aren't allowed in parenthesized argument list + --> $DIR/named-fn-trait-parameters.rs:58:19 | LL | pat2: impl Fn((x, y): (bool, bool)), - | ^ unexpected token after this + | ^^^^^^ + | +help: give this argument a name or use an underscore to ignore it + | +LL - pat2: impl Fn((x, y): (bool, bool)), +LL + pat2: impl Fn(_: (bool, bool)), + | -error: expected one of `!`, `(`, `+`, `::`, or `<`, found `{` - --> $DIR/named-fn-trait-parameters.rs:52:25 +error[E0642]: patterns aren't allowed in parenthesized argument list + --> $DIR/named-fn-trait-parameters.rs:60:19 | LL | pat3: impl Fn(Thing { a, b }: Thing), - | ^ expected one of `!`, `(`, `+`, `::`, or `<` + | ^^^^^^^^^^^^^^ + | +help: give this argument a name or use an underscore to ignore it + | +LL - pat3: impl Fn(Thing { a, b }: Thing), +LL + pat3: impl Fn(_: Thing), + | -error: expected one of `!`, `(`, `+`, `::`, or `<`, found `{` - --> $DIR/named-fn-trait-parameters.rs:54:27 +error[E0642]: patterns aren't allowed in parenthesized argument list + --> $DIR/named-fn-trait-parameters.rs:62:19 | LL | pat4: impl Fn(NoThing { a, b }: NoThing), - | ^ expected one of `!`, `(`, `+`, `::`, or `<` + | ^^^^^^^^^^^^^^^^ + | +help: give this argument a name or use an underscore to ignore it + | +LL - pat4: impl Fn(NoThing { a, b }: NoThing), +LL + pat4: impl Fn(_: NoThing), + | -error: unexpected token: `:` - --> $DIR/named-fn-trait-parameters.rs:56:30 +error[E0642]: patterns aren't allowed in parenthesized argument list + --> $DIR/named-fn-trait-parameters.rs:64:19 | LL | pat5: impl Fn((((((x))))): bool), - | ^ unexpected token after this - -error: unexpected `self` parameter in function - --> $DIR/named-fn-trait-parameters.rs:59:20 + | ^^^^^^^^^^^ | -LL | self1: impl Fn(self), // FIXME should be accepted - | ^^^^ must be the first parameter of an associated function - -error: unexpected `self` parameter in function - --> $DIR/named-fn-trait-parameters.rs:61:20 +help: give this argument a name or use an underscore to ignore it + | +LL - pat5: impl Fn((((((x))))): bool), +LL + pat5: impl Fn(_: bool), | -LL | self2: impl Fn(self, self), - | ^^^^ must be the first parameter of an associated function error: unexpected `self` parameter in function - --> $DIR/named-fn-trait-parameters.rs:61:26 + --> $DIR/named-fn-trait-parameters.rs:68:26 | LL | self2: impl Fn(self, self), | ^^^^ must be the first parameter of an associated function error: unexpected `self` parameter in function - --> $DIR/named-fn-trait-parameters.rs:64:26 + --> $DIR/named-fn-trait-parameters.rs:70:26 | LL | self3: impl Fn(bool, self), | ^^^^ must be the first parameter of an associated function -error: aborting due to 18 previous errors +error: `self` parameter is only allowed in associated functions + --> $DIR/named-fn-trait-parameters.rs:29:20 + | +LL | self1: impl Fn(self), + | ^^^^ not semantically valid as function parameter + | + = note: associated functions are those in `impl` or `trait` definitions + +error: `self` parameter is only allowed in associated functions + --> $DIR/named-fn-trait-parameters.rs:31:20 + | +LL | self2: impl Fn(self, self), + | ^^^^ not semantically valid as function parameter + | + = note: associated functions are those in `impl` or `trait` definitions + +error[E0561]: patterns aren't allowed in parenthesized argument lists + --> $DIR/named-fn-trait-parameters.rs:37:30 + | +LL | restricted_pat1: impl Fn(mut x: ()), + | ^^^^^ + +error[E0561]: patterns aren't allowed in parenthesized argument lists + --> $DIR/named-fn-trait-parameters.rs:39:30 + | +LL | restricted_pat2: impl Fn(&x: ()), + | ^^ + +error[E0561]: patterns aren't allowed in parenthesized argument lists + --> $DIR/named-fn-trait-parameters.rs:41:30 + | +LL | restricted_pat3: impl Fn(&&x: ()), + | ^^^ + +error[E0561]: patterns aren't allowed in parenthesized argument lists + --> $DIR/named-fn-trait-parameters.rs:43:30 + | +LL | restricted_pat4: impl Fn(false: ()), + | ^^^^^ + +error[E0561]: patterns aren't allowed in parenthesized argument lists + --> $DIR/named-fn-trait-parameters.rs:45:30 + | +LL | restricted_pat5: impl Fn(&_: ()), + | ^^ + +error[E0561]: patterns aren't allowed in parenthesized argument lists + --> $DIR/named-fn-trait-parameters.rs:47:30 + | +LL | restricted_pat6: impl Fn(&true: ()), + | ^^^^^ + +error[E0425]: cannot find type `NoThing` in this scope + --> $DIR/named-fn-trait-parameters.rs:23:37 + | +LL | pat4: impl Fn(NoThing { a, b }: NoThing), + | ^^^^^^^ not found in this scope + | +note: similarly named struct `Thing` defined here + --> $DIR/named-fn-trait-parameters.rs:82:1 + | +LL | struct Thing { a: bool, b: bool } + | ^^^^^^^^^^^^ +help: a struct with a similar name exists + | +LL - pat4: impl Fn(NoThing { a, b }: NoThing), +LL + pat4: impl Fn(NoThing { a, b }: Thing), + | + +error: aborting due to 23 previous errors +Some errors have detailed explanations: E0425, E0561, E0642. +For more information about an error, try `rustc --explain E0425`. diff --git a/tests/ui/generic-associated-types/trait-method-requires-gat-impl-trait.rs b/tests/ui/generic-associated-types/trait-method-requires-gat-impl-trait.rs new file mode 100644 index 0000000000000..3477f579cd0dd --- /dev/null +++ b/tests/ui/generic-associated-types/trait-method-requires-gat-impl-trait.rs @@ -0,0 +1,17 @@ +//! Regression test for . +//@compile-flags: -Znext-solver=globally +//@ check-pass + +trait Trait { + type Assoc; + fn foo() + where + Self::Assoc: Trait; +} + +impl Trait for T { + type Assoc = T; + fn foo() {} +} + +fn main() {} diff --git a/tests/ui/lint/const-item-interior-mutations-const-cell.rs b/tests/ui/lint/const-item-interior-mutations-const-cell.rs index 22b465fa0a951..a5a9d6565d1fe 100644 --- a/tests/ui/lint/const-item-interior-mutations-const-cell.rs +++ b/tests/ui/lint/const-item-interior-mutations-const-cell.rs @@ -1,6 +1,6 @@ //@ check-pass -#![feature(unsafe_cell_access)] + #![feature(sync_unsafe_cell)] #![feature(once_cell_try_insert)] #![feature(once_cell_try)] diff --git a/tests/ui/parser/dotdotdot-rest-pattern-suggestion-span.rs b/tests/ui/parser/dotdotdot-rest-pattern-suggestion-span.rs index 0db10726c5dc4..36091b480d3c3 100644 --- a/tests/ui/parser/dotdotdot-rest-pattern-suggestion-span.rs +++ b/tests/ui/parser/dotdotdot-rest-pattern-suggestion-span.rs @@ -10,7 +10,7 @@ impl S { fn f(···>) } //~| ERROR unknown start of token //~| ERROR unknown start of token //~| ERROR unexpected `...` -//~| ERROR expected `:`, found `>` +//~| ERROR unexpected token: `>` //~| ERROR expected one of //~| ERROR associated function in `impl` without body //~| ERROR cannot find type `S` in this scope diff --git a/tests/ui/parser/dotdotdot-rest-pattern-suggestion-span.stderr b/tests/ui/parser/dotdotdot-rest-pattern-suggestion-span.stderr index d483c40ca5e0b..0889ca8a495af 100644 --- a/tests/ui/parser/dotdotdot-rest-pattern-suggestion-span.stderr +++ b/tests/ui/parser/dotdotdot-rest-pattern-suggestion-span.stderr @@ -48,11 +48,11 @@ LL - impl S { fn f(···>) } LL + impl S { fn f(..>) } | -error: expected `:`, found `>` +error: unexpected token: `>` --> $DIR/dotdotdot-rest-pattern-suggestion-span.rs:8:18 | LL | impl S { fn f(···>) } - | ^ expected `:` + | ^ unexpected token after this error: expected one of `->`, `where`, or `{`, found `}` --> $DIR/dotdotdot-rest-pattern-suggestion-span.rs:8:21 diff --git a/tests/ui/parser/issue-116781.rs b/tests/ui/parser/issue-116781.rs index 176350fe2eec6..5ff0989b3df00 100644 --- a/tests/ui/parser/issue-116781.rs +++ b/tests/ui/parser/issue-116781.rs @@ -1,8 +1,8 @@ #[derive(Debug)] struct Foo { #[cfg(true)] - field: fn(($),), //~ ERROR expected pattern, found `$` - //~^ ERROR expected pattern, found `$` + field: fn(($),), //~ ERROR expected type, found `$` + //~^ ERROR expected type, found `$` } fn main() {} diff --git a/tests/ui/parser/issue-116781.stderr b/tests/ui/parser/issue-116781.stderr index 1a77b60a50dc8..fdfadf4a9e313 100644 --- a/tests/ui/parser/issue-116781.stderr +++ b/tests/ui/parser/issue-116781.stderr @@ -1,14 +1,14 @@ -error: expected pattern, found `$` +error: expected type, found `$` --> $DIR/issue-116781.rs:4:16 | LL | field: fn(($),), - | ^ expected pattern + | ^ expected type -error: expected pattern, found `$` +error: expected type, found `$` --> $DIR/issue-116781.rs:4:16 | LL | field: fn(($),), - | ^ expected pattern + | ^ expected type | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` diff --git a/tests/ui/parser/issues/issue-103748-ICE-wrong-braces.rs b/tests/ui/parser/issues/issue-103748-ICE-wrong-braces.rs index 60dd88e65400a..08997f8a6afd0 100644 --- a/tests/ui/parser/issues/issue-103748-ICE-wrong-braces.rs +++ b/tests/ui/parser/issues/issue-103748-ICE-wrong-braces.rs @@ -3,3 +3,4 @@ struct Apple((Apple, Option(Banana ? Citron))); //~^ ERROR invalid `?` in type //~| ERROR unexpected token: `Citron` +//~| ERROR expected a pattern, found an expression diff --git a/tests/ui/parser/issues/issue-103748-ICE-wrong-braces.stderr b/tests/ui/parser/issues/issue-103748-ICE-wrong-braces.stderr index c92535c3906bc..fff09d19772f5 100644 --- a/tests/ui/parser/issues/issue-103748-ICE-wrong-braces.stderr +++ b/tests/ui/parser/issues/issue-103748-ICE-wrong-braces.stderr @@ -16,5 +16,13 @@ error: unexpected token: `Citron` LL | struct Apple((Apple, Option(Banana ? Citron))); | ^^^^^^ unexpected token after this -error: aborting due to 2 previous errors +error: expected a pattern, found an expression + --> $DIR/issue-103748-ICE-wrong-braces.rs:3:29 + | +LL | struct Apple((Apple, Option(Banana ? Citron))); + | ^^^^^^^^ not a pattern + | + = note: arbitrary expressions are not allowed in patterns: + +error: aborting due to 3 previous errors diff --git a/tests/ui/repr/packed-struct-contains-aligned-type-73112.rs b/tests/ui/repr/packed-struct-contains-aligned-type-73112.rs index baeb75beb0aa1..f8272e6f652e5 100644 --- a/tests/ui/repr/packed-struct-contains-aligned-type-73112.rs +++ b/tests/ui/repr/packed-struct-contains-aligned-type-73112.rs @@ -8,7 +8,7 @@ fn main() { #[repr(C, packed)] struct SomeStruct { - //~^ ERROR packed type cannot transitively contain a `#[repr(align)]` type [E0588] + //~^ ERROR packed type cannot transitively contain a `#[repr(align)]` type page_table: PageTable, } } diff --git a/tests/ui/repr/packed-struct-contains-aligned-type-73112.stderr b/tests/ui/repr/packed-struct-contains-aligned-type-73112.stderr index 237c357db22ba..8cba8bf75c437 100644 --- a/tests/ui/repr/packed-struct-contains-aligned-type-73112.stderr +++ b/tests/ui/repr/packed-struct-contains-aligned-type-73112.stderr @@ -1,4 +1,4 @@ -error[E0588]: packed type cannot transitively contain a `#[repr(align)]` type +error: packed type cannot transitively contain a `#[repr(align)]` type --> $DIR/packed-struct-contains-aligned-type-73112.rs:10:5 | LL | struct SomeStruct { @@ -9,7 +9,7 @@ note: `PageTable` has a `#[repr(align)]` attribute | LL | pub struct PageTable { | ^^^^^^^^^^^^^^^^^^^^ + = note: `#[deny(aligned_fields_in_packed)]` on by default error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0588`. diff --git a/tests/ui/repr/repr-packed-contains-align.rs b/tests/ui/repr/repr-packed-contains-align.rs index bef5c7d8c62fc..06c8e92249866 100644 --- a/tests/ui/repr/repr-packed-contains-align.rs +++ b/tests/ui/repr/repr-packed-contains-align.rs @@ -1,53 +1,66 @@ #![allow(dead_code)] -#[repr(align(16))] +#[repr(C, align(16))] #[derive(Clone, Copy)] struct SA(i32); +#[repr(align(16))] +#[derive(Clone, Copy)] +struct SARust(i32); + +#[repr(C)] #[derive(Clone, Copy)] struct SB(SA); -#[repr(align(16))] +#[repr(C, align(16))] #[derive(Clone, Copy)] union UA { i: i32 } +#[repr(C)] #[derive(Clone, Copy)] union UB { a: UA } -#[repr(packed)] +#[repr(C, packed)] struct SC(SA); //~ ERROR: packed type cannot transitively contain a `#[repr(align)]` type -#[repr(packed)] +#[repr(C, packed)] struct SD(SB); //~ ERROR: packed type cannot transitively contain a `#[repr(align)]` type -#[repr(packed)] +#[repr(C, packed)] struct SE(UA); //~ ERROR: packed type cannot transitively contain a `#[repr(align)]` type -#[repr(packed)] +#[repr(C, packed)] struct SF(UB); //~ ERROR: packed type cannot transitively contain a `#[repr(align)]` type -#[repr(packed)] +#[repr(C, packed)] union UC { //~ ERROR: packed type cannot transitively contain a `#[repr(align)]` type a: UA } -#[repr(packed)] +#[repr(C, packed)] union UD { //~ ERROR: packed type cannot transitively contain a `#[repr(align)]` type n: UB } -#[repr(packed)] +#[repr(C, packed)] union UE { //~ ERROR: packed type cannot transitively contain a `#[repr(align)]` type a: SA } -#[repr(packed)] +#[repr(C, packed)] union UF { //~ ERROR: packed type cannot transitively contain a `#[repr(align)]` type n: SB } +#[repr(packed)] +struct SG(SA); // outer type not `repr(C)`, no lint +#[repr(C, packed)] +struct SH(SARust); // inner type not `repr(C)`, no lint + + + fn main() {} diff --git a/tests/ui/repr/repr-packed-contains-align.stderr b/tests/ui/repr/repr-packed-contains-align.stderr index 4c3a960cad2a6..4c94cda745d2e 100644 --- a/tests/ui/repr/repr-packed-contains-align.stderr +++ b/tests/ui/repr/repr-packed-contains-align.stderr @@ -1,5 +1,5 @@ -error[E0588]: packed type cannot transitively contain a `#[repr(align)]` type - --> $DIR/repr-packed-contains-align.rs:22:1 +error: packed type cannot transitively contain a `#[repr(align)]` type + --> $DIR/repr-packed-contains-align.rs:28:1 | LL | struct SC(SA); | ^^^^^^^^^ @@ -9,9 +9,10 @@ note: `SA` has a `#[repr(align)]` attribute | LL | struct SA(i32); | ^^^^^^^^^ + = note: `#[deny(aligned_fields_in_packed)]` on by default -error[E0588]: packed type cannot transitively contain a `#[repr(align)]` type - --> $DIR/repr-packed-contains-align.rs:25:1 +error: packed type cannot transitively contain a `#[repr(align)]` type + --> $DIR/repr-packed-contains-align.rs:31:1 | LL | struct SD(SB); | ^^^^^^^^^ @@ -22,86 +23,86 @@ note: `SA` has a `#[repr(align)]` attribute LL | struct SA(i32); | ^^^^^^^^^ note: `SD` contains a field of type `SB` - --> $DIR/repr-packed-contains-align.rs:25:11 + --> $DIR/repr-packed-contains-align.rs:31:11 | LL | struct SD(SB); | ^^ note: ...which contains a field of type `SA` - --> $DIR/repr-packed-contains-align.rs:8:11 + --> $DIR/repr-packed-contains-align.rs:13:11 | LL | struct SB(SA); | ^^ -error[E0588]: packed type cannot transitively contain a `#[repr(align)]` type - --> $DIR/repr-packed-contains-align.rs:28:1 +error: packed type cannot transitively contain a `#[repr(align)]` type + --> $DIR/repr-packed-contains-align.rs:34:1 | LL | struct SE(UA); | ^^^^^^^^^ | note: `UA` has a `#[repr(align)]` attribute - --> $DIR/repr-packed-contains-align.rs:12:1 + --> $DIR/repr-packed-contains-align.rs:17:1 | LL | union UA { | ^^^^^^^^ -error[E0588]: packed type cannot transitively contain a `#[repr(align)]` type - --> $DIR/repr-packed-contains-align.rs:31:1 +error: packed type cannot transitively contain a `#[repr(align)]` type + --> $DIR/repr-packed-contains-align.rs:37:1 | LL | struct SF(UB); | ^^^^^^^^^ | note: `UA` has a `#[repr(align)]` attribute - --> $DIR/repr-packed-contains-align.rs:12:1 + --> $DIR/repr-packed-contains-align.rs:17:1 | LL | union UA { | ^^^^^^^^ note: `SF` contains a field of type `UB` - --> $DIR/repr-packed-contains-align.rs:31:11 + --> $DIR/repr-packed-contains-align.rs:37:11 | LL | struct SF(UB); | ^^ note: ...which contains a field of type `UA` - --> $DIR/repr-packed-contains-align.rs:18:5 + --> $DIR/repr-packed-contains-align.rs:24:5 | LL | a: UA | ^ -error[E0588]: packed type cannot transitively contain a `#[repr(align)]` type - --> $DIR/repr-packed-contains-align.rs:34:1 +error: packed type cannot transitively contain a `#[repr(align)]` type + --> $DIR/repr-packed-contains-align.rs:40:1 | LL | union UC { | ^^^^^^^^ | note: `UA` has a `#[repr(align)]` attribute - --> $DIR/repr-packed-contains-align.rs:12:1 + --> $DIR/repr-packed-contains-align.rs:17:1 | LL | union UA { | ^^^^^^^^ -error[E0588]: packed type cannot transitively contain a `#[repr(align)]` type - --> $DIR/repr-packed-contains-align.rs:39:1 +error: packed type cannot transitively contain a `#[repr(align)]` type + --> $DIR/repr-packed-contains-align.rs:45:1 | LL | union UD { | ^^^^^^^^ | note: `UA` has a `#[repr(align)]` attribute - --> $DIR/repr-packed-contains-align.rs:12:1 + --> $DIR/repr-packed-contains-align.rs:17:1 | LL | union UA { | ^^^^^^^^ note: `UD` contains a field of type `UB` - --> $DIR/repr-packed-contains-align.rs:40:5 + --> $DIR/repr-packed-contains-align.rs:46:5 | LL | n: UB | ^ note: ...which contains a field of type `UA` - --> $DIR/repr-packed-contains-align.rs:18:5 + --> $DIR/repr-packed-contains-align.rs:24:5 | LL | a: UA | ^ -error[E0588]: packed type cannot transitively contain a `#[repr(align)]` type - --> $DIR/repr-packed-contains-align.rs:44:1 +error: packed type cannot transitively contain a `#[repr(align)]` type + --> $DIR/repr-packed-contains-align.rs:50:1 | LL | union UE { | ^^^^^^^^ @@ -112,8 +113,8 @@ note: `SA` has a `#[repr(align)]` attribute LL | struct SA(i32); | ^^^^^^^^^ -error[E0588]: packed type cannot transitively contain a `#[repr(align)]` type - --> $DIR/repr-packed-contains-align.rs:49:1 +error: packed type cannot transitively contain a `#[repr(align)]` type + --> $DIR/repr-packed-contains-align.rs:55:1 | LL | union UF { | ^^^^^^^^ @@ -124,16 +125,15 @@ note: `SA` has a `#[repr(align)]` attribute LL | struct SA(i32); | ^^^^^^^^^ note: `UF` contains a field of type `SB` - --> $DIR/repr-packed-contains-align.rs:50:5 + --> $DIR/repr-packed-contains-align.rs:56:5 | LL | n: SB | ^ note: ...which contains a field of type `SA` - --> $DIR/repr-packed-contains-align.rs:8:11 + --> $DIR/repr-packed-contains-align.rs:13:11 | LL | struct SB(SA); | ^^ error: aborting due to 8 previous errors -For more information about this error, try `rustc --explain E0588`. diff --git a/tests/ui/rfcs/rfc-2565-param-attrs/attr-without-param.rs b/tests/ui/rfcs/rfc-2565-param-attrs/attr-without-param.rs index 14402eaeecac1..d775545dd571c 100644 --- a/tests/ui/rfcs/rfc-2565-param-attrs/attr-without-param.rs +++ b/tests/ui/rfcs/rfc-2565-param-attrs/attr-without-param.rs @@ -11,7 +11,7 @@ impl T for S { #[cfg(false)] trait T { - fn f(#[attr]); //~ ERROR expected argument name, found `)` + fn f(#[attr]); //~ ERROR expected type, found `)` } fn main() {} diff --git a/tests/ui/rfcs/rfc-2565-param-attrs/attr-without-param.stderr b/tests/ui/rfcs/rfc-2565-param-attrs/attr-without-param.stderr index 2fa03f3cb0bba..65b265fb6289a 100644 --- a/tests/ui/rfcs/rfc-2565-param-attrs/attr-without-param.stderr +++ b/tests/ui/rfcs/rfc-2565-param-attrs/attr-without-param.stderr @@ -10,11 +10,11 @@ error: expected parameter name, found `)` LL | fn f(#[attr]) {} | ^ expected parameter name -error: expected argument name, found `)` +error: expected type, found `)` --> $DIR/attr-without-param.rs:14:17 | LL | fn f(#[attr]); - | ^ expected argument name + | ^ expected type error: aborting due to 3 previous errors