diff options
Diffstat (limited to 'compiler')
39 files changed, 313 insertions, 171 deletions
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 1b831c454e6..5b7545b3396 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -1657,7 +1657,7 @@ pub enum ExprKind { Try(P<Expr>), /// A `yield`, with an optional value to be yielded. - Yield(Option<P<Expr>>), + Yield(YieldKind), /// A `do yeet` (aka `throw`/`fail`/`bail`/`raise`/whatever), /// with an optional value to be returned. @@ -1903,6 +1903,44 @@ pub enum MatchKind { Postfix, } +/// The kind of yield expression +#[derive(Clone, Encodable, Decodable, Debug)] +pub enum YieldKind { + /// yield expr { ... } + Prefix(Option<P<Expr>>), + /// expr.yield { ... } + Postfix(P<Expr>), +} + +impl YieldKind { + /// Returns the expression inside the yield expression, if any. + /// + /// For postfix yields, this is guaranteed to be `Some`. + pub const fn expr(&self) -> Option<&P<Expr>> { + match self { + YieldKind::Prefix(expr) => expr.as_ref(), + YieldKind::Postfix(expr) => Some(expr), + } + } + + /// Returns a mutable reference to the expression being yielded, if any. + pub const fn expr_mut(&mut self) -> Option<&mut P<Expr>> { + match self { + YieldKind::Prefix(expr) => expr.as_mut(), + YieldKind::Postfix(expr) => Some(expr), + } + } + + /// Returns true if both yields are prefix or both are postfix. + pub const fn same_kind(&self, other: &Self) -> bool { + match (self, other) { + (YieldKind::Prefix(_), YieldKind::Prefix(_)) => true, + (YieldKind::Postfix(_), YieldKind::Postfix(_)) => true, + _ => false, + } + } +} + /// A literal in a meta item. #[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)] pub struct MetaItemLit { diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 4a1636e6aec..b159e136245 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -1813,8 +1813,11 @@ pub fn walk_expr<T: MutVisitor>(vis: &mut T, Expr { kind, id, span, attrs, token ExprKind::Paren(expr) => { vis.visit_expr(expr); } - ExprKind::Yield(expr) => { - visit_opt(expr, |expr| vis.visit_expr(expr)); + ExprKind::Yield(kind) => { + let expr = kind.expr_mut(); + if let Some(expr) = expr { + vis.visit_expr(expr); + } } ExprKind::Try(expr) => vis.visit_expr(expr), ExprKind::TryBlock(body) => vis.visit_block(body), diff --git a/compiler/rustc_ast/src/util/classify.rs b/compiler/rustc_ast/src/util/classify.rs index e43d78f6e72..989ebe14bf8 100644 --- a/compiler/rustc_ast/src/util/classify.rs +++ b/compiler/rustc_ast/src/util/classify.rs @@ -182,11 +182,14 @@ pub fn expr_trailing_brace(mut expr: &ast::Expr) -> Option<TrailingBrace<'_>> { | Range(_, Some(e), _) | Ret(Some(e)) | Unary(_, e) - | Yield(Some(e)) | Yeet(Some(e)) | Become(e) => { expr = e; } + Yield(kind) => match kind.expr() { + Some(e) => expr = e, + None => break None, + }, Closure(closure) => { expr = &closure.body; } @@ -217,7 +220,6 @@ pub fn expr_trailing_brace(mut expr: &ast::Expr) -> Option<TrailingBrace<'_>> { Break(_, None) | Range(_, None, _) | Ret(None) - | Yield(None) | Array(_) | Call(_, _) | MethodCall(_) @@ -237,7 +239,9 @@ pub fn expr_trailing_brace(mut expr: &ast::Expr) -> Option<TrailingBrace<'_>> { | Yeet(None) | UnsafeBinderCast(..) | Err(_) - | Dummy => break None, + | Dummy => { + break None; + } } } } diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index cfcb0e23cb5..ce8d6df75af 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -1269,8 +1269,8 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) -> V try_visit!(visitor.visit_ty(container)); walk_list!(visitor, visit_ident, fields.iter()); } - ExprKind::Yield(optional_expression) => { - visit_opt!(visitor, visit_expr, optional_expression); + ExprKind::Yield(kind) => { + visit_opt!(visitor, visit_expr, kind.expr()); } ExprKind::Try(subexpression) => try_visit!(visitor.visit_expr(subexpression)), ExprKind::TryBlock(body) => try_visit!(visitor.visit_block(body)), diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 5bb6704dde4..7f3d060bb8a 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -351,7 +351,7 @@ impl<'hir> LoweringContext<'_, 'hir> { rest, ) } - ExprKind::Yield(opt_expr) => self.lower_expr_yield(e.span, opt_expr.as_deref()), + ExprKind::Yield(kind) => self.lower_expr_yield(e.span, kind.expr().map(|x| &**x)), ExprKind::Err(guar) => hir::ExprKind::Err(*guar), ExprKind::UnsafeBinderCast(kind, expr, ty) => hir::ExprKind::UnsafeBinderCast( diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index e24b45c5b19..e08850da4a7 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1513,16 +1513,22 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { })) } - fn lower_fn_params_to_names(&mut self, decl: &FnDecl) -> &'hir [Ident] { + fn lower_fn_params_to_names(&mut self, decl: &FnDecl) -> &'hir [Option<Ident>] { self.arena.alloc_from_iter(decl.inputs.iter().map(|param| match param.pat.kind { - PatKind::Ident(_, ident, _) => self.lower_ident(ident), - PatKind::Wild => Ident::new(kw::Underscore, self.lower_span(param.pat.span)), + PatKind::Ident(_, ident, _) => { + if ident.name != kw::Empty { + Some(self.lower_ident(ident)) + } else { + None + } + } + PatKind::Wild => Some(Ident::new(kw::Underscore, self.lower_span(param.pat.span))), _ => { self.dcx().span_delayed_bug( param.pat.span, "non-ident/wild param pat must trigger an error", ); - Ident::new(kw::Empty, self.lower_span(param.pat.span)) + None } })) } diff --git a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs index e3c41f117ab..7d9dc89bd75 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs @@ -8,7 +8,7 @@ use rustc_ast::util::literal::escape_byte_str_symbol; use rustc_ast::util::parser::{self, ExprPrecedence, Fixity}; use rustc_ast::{ self as ast, BlockCheckMode, FormatAlignment, FormatArgPosition, FormatArgsPiece, FormatCount, - FormatDebugHex, FormatSign, FormatTrait, token, + FormatDebugHex, FormatSign, FormatTrait, YieldKind, token, }; use crate::pp::Breaks::Inconsistent; @@ -761,7 +761,7 @@ impl<'a> State<'a> { self.print_expr(e, FixupContext::default()); self.pclose(); } - ast::ExprKind::Yield(e) => { + ast::ExprKind::Yield(YieldKind::Prefix(e)) => { self.word("yield"); if let Some(expr) = e { @@ -773,6 +773,14 @@ impl<'a> State<'a> { ); } } + ast::ExprKind::Yield(YieldKind::Postfix(e)) => { + self.print_expr_cond_paren( + e, + e.precedence() < ExprPrecedence::Unambiguous, + fixup.leftmost_subexpression_with_dot(), + ); + self.word(".yield"); + } ast::ExprKind::Try(e) => { self.print_expr_cond_paren( e, diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 2694a1eda78..978186f76a1 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -2514,12 +2514,12 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { let ty::Tuple(params) = tupled_params.kind() else { return }; // Find the first argument with a matching type, get its name - let Some((_, this_name)) = - params.iter().zip(tcx.hir_body_param_names(closure.body)).find(|(param_ty, name)| { + let Some(this_name) = params.iter().zip(tcx.hir_body_param_names(closure.body)).find_map( + |(param_ty, name)| { // FIXME: also support deref for stuff like `Rc` arguments - param_ty.peel_refs() == local_ty && name != &Ident::empty() - }) - else { + if param_ty.peel_refs() == local_ty { name } else { None } + }, + ) else { return; }; @@ -3787,7 +3787,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { method_args, *fn_span, call_source.from_hir_call(), - Some(self.infcx.tcx.fn_arg_names(method_did)[0]), + self.infcx.tcx.fn_arg_names(method_did)[0], ) { err.note(format!("borrow occurs due to deref coercion to `{deref_target_ty}`")); diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs index 208d510db2e..899e145c2c0 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -1029,7 +1029,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { method_args, *fn_span, call_source.from_hir_call(), - Some(self.infcx.tcx.fn_arg_names(method_did)[0]), + self.infcx.tcx.fn_arg_names(method_did)[0], ); return FnSelfUse { diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs index b617f4d37f5..f6000e72840 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs @@ -146,6 +146,7 @@ pub(crate) struct CoverageSpan { #[derive(Clone, Debug, Default)] pub(crate) struct Regions { pub(crate) code_regions: Vec<CodeRegion>, + pub(crate) expansion_regions: Vec<ExpansionRegion>, pub(crate) branch_regions: Vec<BranchRegion>, pub(crate) mcdc_branch_regions: Vec<MCDCBranchRegion>, pub(crate) mcdc_decision_regions: Vec<MCDCDecisionRegion>, @@ -154,10 +155,16 @@ pub(crate) struct Regions { impl Regions { /// Returns true if none of this structure's tables contain any regions. pub(crate) fn has_no_regions(&self) -> bool { - let Self { code_regions, branch_regions, mcdc_branch_regions, mcdc_decision_regions } = - self; + let Self { + code_regions, + expansion_regions, + branch_regions, + mcdc_branch_regions, + mcdc_decision_regions, + } = self; code_regions.is_empty() + && expansion_regions.is_empty() && branch_regions.is_empty() && mcdc_branch_regions.is_empty() && mcdc_decision_regions.is_empty() @@ -172,6 +179,14 @@ pub(crate) struct CodeRegion { pub(crate) counter: Counter, } +/// Must match the layout of `LLVMRustCoverageExpansionRegion`. +#[derive(Clone, Debug)] +#[repr(C)] +pub(crate) struct ExpansionRegion { + pub(crate) cov_span: CoverageSpan, + pub(crate) expanded_file_id: u32, +} + /// Must match the layout of `LLVMRustCoverageBranchRegion`. #[derive(Clone, Debug)] #[repr(C)] diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/llvm_cov.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/llvm_cov.rs index 2cd7fa3225a..907d6d41a1f 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/llvm_cov.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/llvm_cov.rs @@ -63,8 +63,18 @@ pub(crate) fn write_function_mappings_to_buffer( expressions: &[ffi::CounterExpression], regions: &ffi::Regions, ) -> Vec<u8> { - let ffi::Regions { code_regions, branch_regions, mcdc_branch_regions, mcdc_decision_regions } = - regions; + let ffi::Regions { + code_regions, + expansion_regions, + branch_regions, + mcdc_branch_regions, + mcdc_decision_regions, + } = regions; + + // SAFETY: + // - All types are FFI-compatible and have matching representations in Rust/C++. + // - For pointer/length pairs, the pointer and length come from the same vector or slice. + // - C++ code does not retain any pointers after the call returns. llvm::build_byte_buffer(|buffer| unsafe { llvm::LLVMRustCoverageWriteFunctionMappingsToBuffer( virtual_file_mapping.as_ptr(), @@ -73,6 +83,8 @@ pub(crate) fn write_function_mappings_to_buffer( expressions.len(), code_regions.as_ptr(), code_regions.len(), + expansion_regions.as_ptr(), + expansion_regions.len(), branch_regions.as_ptr(), branch_regions.len(), mcdc_branch_regions.as_ptr(), diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/covfun.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/covfun.rs index 5b487bc1a8b..048e1988c32 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/covfun.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/covfun.rs @@ -120,12 +120,22 @@ fn fill_region_tables<'tcx>( // Associate that global file ID with a local file ID for this function. let local_file_id = covfun.virtual_file_mapping.local_id_for_global(global_file_id); - let ffi::Regions { code_regions, branch_regions, mcdc_branch_regions, mcdc_decision_regions } = - &mut covfun.regions; - - let make_cov_span = - |span: Span| spans::make_coverage_span(local_file_id, source_map, &source_file, span); + // In rare cases, _all_ of a function's spans are discarded, and coverage + // codegen needs to handle that gracefully to avoid #133606. + // It's hard for tests to trigger this organically, so instead we set + // `-Zcoverage-options=discard-all-spans-in-codegen` to force it to occur. let discard_all = tcx.sess.coverage_discard_all_spans_in_codegen(); + let make_coords = |span: Span| { + if discard_all { None } else { spans::make_coords(source_map, &source_file, span) } + }; + + let ffi::Regions { + code_regions, + expansion_regions: _, // FIXME(Zalathar): Fill out support for expansion regions + branch_regions, + mcdc_branch_regions, + mcdc_decision_regions, + } = &mut covfun.regions; // For each counter/region pair in this function+file, convert it to a // form suitable for FFI. @@ -140,17 +150,8 @@ fn fill_region_tables<'tcx>( ffi::Counter::from_term(term) }; - // Convert the `Span` into coordinates that we can pass to LLVM, or - // discard the span if conversion fails. In rare, cases _all_ of a - // function's spans are discarded, and the rest of coverage codegen - // needs to handle that gracefully to avoid a repeat of #133606. - // We don't have a good test case for triggering that organically, so - // instead we set `-Zcoverage-options=discard-all-spans-in-codegen` - // to force it to occur. - let Some(cov_span) = make_cov_span(span) else { continue }; - if discard_all { - continue; - } + let Some(coords) = make_coords(span) else { continue }; + let cov_span = coords.make_coverage_span(local_file_id); match *kind { MappingKind::Code { bcb } => { diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/spans.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/spans.rs index 3193be31ada..39a59560c9d 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/spans.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/spans.rs @@ -5,22 +5,40 @@ use tracing::debug; use crate::coverageinfo::ffi; use crate::coverageinfo::mapgen::LocalFileId; +/// Line and byte-column coordinates of a source code span within some file. +/// The file itself must be tracked separately. +#[derive(Clone, Copy, Debug)] +pub(crate) struct Coords { + /// 1-based starting line of the source code span. + pub(crate) start_line: u32, + /// 1-based starting column (in bytes) of the source code span. + pub(crate) start_col: u32, + /// 1-based ending line of the source code span. + pub(crate) end_line: u32, + /// 1-based ending column (in bytes) of the source code span. High bit must be unset. + pub(crate) end_col: u32, +} + +impl Coords { + /// Attaches a local file ID to these coordinates to produce an `ffi::CoverageSpan`. + pub(crate) fn make_coverage_span(&self, local_file_id: LocalFileId) -> ffi::CoverageSpan { + let &Self { start_line, start_col, end_line, end_col } = self; + let file_id = local_file_id.as_u32(); + ffi::CoverageSpan { file_id, start_line, start_col, end_line, end_col } + } +} + /// Converts the span into its start line and column, and end line and column. /// /// Line numbers and column numbers are 1-based. Unlike most column numbers emitted by /// the compiler, these column numbers are denoted in **bytes**, because that's what /// LLVM's `llvm-cov` tool expects to see in coverage maps. /// -/// Returns `None` if the conversion failed for some reason. This shouldn't happen, +/// Returns `None` if the conversion failed for some reason. This should be uncommon, /// but it's hard to rule out entirely (especially in the presence of complex macros /// or other expansions), and if it does happen then skipping a span or function is /// better than an ICE or `llvm-cov` failure that the user might have no way to avoid. -pub(crate) fn make_coverage_span( - file_id: LocalFileId, - source_map: &SourceMap, - file: &SourceFile, - span: Span, -) -> Option<ffi::CoverageSpan> { +pub(crate) fn make_coords(source_map: &SourceMap, file: &SourceFile, span: Span) -> Option<Coords> { let span = ensure_non_empty_span(source_map, span)?; let lo = span.lo(); @@ -44,8 +62,7 @@ pub(crate) fn make_coverage_span( start_line = source_map.doctest_offset_line(&file.name, start_line); end_line = source_map.doctest_offset_line(&file.name, end_line); - check_coverage_span(ffi::CoverageSpan { - file_id: file_id.as_u32(), + check_coords(Coords { start_line: start_line as u32, start_col: start_col as u32, end_line: end_line as u32, @@ -80,8 +97,8 @@ fn ensure_non_empty_span(source_map: &SourceMap, span: Span) -> Option<Span> { /// it will immediately exit with a fatal error. To prevent that from happening, /// discard regions that are improperly ordered, or might be interpreted in a /// way that makes them improperly ordered. -fn check_coverage_span(cov_span: ffi::CoverageSpan) -> Option<ffi::CoverageSpan> { - let ffi::CoverageSpan { file_id: _, start_line, start_col, end_line, end_col } = cov_span; +fn check_coords(coords: Coords) -> Option<Coords> { + let Coords { start_line, start_col, end_line, end_col } = coords; // Line/column coordinates are supposed to be 1-based. If we ever emit // coordinates of 0, `llvm-cov` might misinterpret them. @@ -94,17 +111,17 @@ fn check_coverage_span(cov_span: ffi::CoverageSpan) -> Option<ffi::CoverageSpan> let is_ordered = (start_line, start_col) <= (end_line, end_col); if all_nonzero && end_col_has_high_bit_unset && is_ordered { - Some(cov_span) + Some(coords) } else { debug!( - ?cov_span, + ?coords, ?all_nonzero, ?end_col_has_high_bit_unset, ?is_ordered, "Skipping source region that would be misinterpreted or rejected by LLVM" ); // If this happens in a debug build, ICE to make it easier to notice. - debug_assert!(false, "Improper source region: {cov_span:?}"); + debug_assert!(false, "Improper source region: {coords:?}"); None } } diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 39087a4d6f4..83efb3ea660 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -2019,6 +2019,8 @@ unsafe extern "C" { NumExpressions: size_t, CodeRegions: *const crate::coverageinfo::ffi::CodeRegion, NumCodeRegions: size_t, + ExpansionRegions: *const crate::coverageinfo::ffi::ExpansionRegion, + NumExpansionRegions: size_t, BranchRegions: *const crate::coverageinfo::ffi::BranchRegion, NumBranchRegions: size_t, MCDCBranchRegions: *const crate::coverageinfo::ffi::MCDCBranchRegion, diff --git a/compiler/rustc_const_eval/messages.ftl b/compiler/rustc_const_eval/messages.ftl index ccf9b240d40..dd481e04abb 100644 --- a/compiler/rustc_const_eval/messages.ftl +++ b/compiler/rustc_const_eval/messages.ftl @@ -93,7 +93,7 @@ const_eval_expected_inbounds_pointer = } const_eval_extern_static = - cannot access extern static ({$did}) + cannot access extern static `{$did}` const_eval_extern_type_field = `extern type` field does not have a known offset const_eval_fn_ptr_call = @@ -381,7 +381,7 @@ const_eval_thread_local_access = thread-local statics cannot be accessed at compile-time const_eval_thread_local_static = - cannot access thread local static ({$did}) + cannot access thread local static `{$did}` const_eval_too_generic = encountered overly generic constant const_eval_too_many_caller_args = diff --git a/compiler/rustc_const_eval/src/errors.rs b/compiler/rustc_const_eval/src/errors.rs index b020eeccf71..e2675e2f4c9 100644 --- a/compiler/rustc_const_eval/src/errors.rs +++ b/compiler/rustc_const_eval/src/errors.rs @@ -898,6 +898,7 @@ impl ReportErrorExt for UnsupportedOpInfo { UnsupportedOpInfo::ExternStatic(_) => const_eval_extern_static, } } + fn add_args<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) { use UnsupportedOpInfo::*; @@ -917,9 +918,9 @@ impl ReportErrorExt for UnsupportedOpInfo { OverwritePartialPointer(ptr) | ReadPartialPointer(ptr) => { diag.arg("ptr", ptr); } - ThreadLocalStatic(did) | ExternStatic(did) => { - diag.arg("did", format!("{did:?}")); - } + ThreadLocalStatic(did) | ExternStatic(did) => rustc_middle::ty::tls::with(|tcx| { + diag.arg("did", tcx.def_path_str(did)); + }), } } } diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index b5857e359a2..751c379b21a 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -2949,7 +2949,7 @@ impl<'hir> TraitItem<'hir> { #[derive(Debug, Clone, Copy, HashStable_Generic)] pub enum TraitFn<'hir> { /// No default body in the trait, just a signature. - Required(&'hir [Ident]), + Required(&'hir [Option<Ident>]), /// Both signature and body are provided in the trait. Provided(BodyId), @@ -3354,7 +3354,9 @@ pub struct BareFnTy<'hir> { pub abi: ExternAbi, pub generic_params: &'hir [GenericParam<'hir>], pub decl: &'hir FnDecl<'hir>, - pub param_names: &'hir [Ident], + // `Option` because bare fn parameter names are optional. We also end up + // with `None` in some error cases, e.g. invalid parameter patterns. + pub param_names: &'hir [Option<Ident>], } #[derive(Debug, Clone, Copy, HashStable_Generic)] @@ -4335,7 +4337,12 @@ impl ForeignItem<'_> { #[derive(Debug, Clone, Copy, HashStable_Generic)] pub enum ForeignItemKind<'hir> { /// A foreign function. - Fn(FnSig<'hir>, &'hir [Ident], &'hir Generics<'hir>), + /// + /// All argument idents are actually always present (i.e. `Some`), but + /// `&[Option<Ident>]` is used because of code paths shared with `TraitFn` + /// and `BareFnTy`. The sharing is due to all of these cases not allowing + /// arbitrary patterns for parameters. + Fn(FnSig<'hir>, &'hir [Option<Ident>], &'hir Generics<'hir>), /// A foreign static item (`static ext: u8`). Static(&'hir Ty<'hir>, Mutability, Safety), /// A foreign type. diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index b79ae1e7cc2..506358341b5 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -655,7 +655,9 @@ pub fn walk_foreign_item<'v, V: Visitor<'v>>( ForeignItemKind::Fn(ref sig, param_names, ref generics) => { try_visit!(visitor.visit_generics(generics)); try_visit!(visitor.visit_fn_decl(sig.decl)); - walk_list!(visitor, visit_ident, param_names.iter().copied()); + for ident in param_names.iter().copied() { + visit_opt!(visitor, visit_ident, ident); + } } ForeignItemKind::Static(ref typ, _, _) => { try_visit!(visitor.visit_ty_unambig(typ)); @@ -1169,7 +1171,9 @@ pub fn walk_trait_item<'v, V: Visitor<'v>>( } TraitItemKind::Fn(ref sig, TraitFn::Required(param_names)) => { try_visit!(visitor.visit_fn_decl(sig.decl)); - walk_list!(visitor, visit_ident, param_names.iter().copied()); + for ident in param_names.iter().copied() { + visit_opt!(visitor, visit_ident, ident); + } } TraitItemKind::Fn(ref sig, TraitFn::Provided(body_id)) => { try_visit!(visitor.visit_fn( diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index ca820deebdf..84d07c711fa 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -1034,7 +1034,13 @@ fn report_trait_method_mismatch<'tcx>( let span = tcx .hir_body_param_names(body) .zip(sig.decl.inputs.iter()) - .map(|(param, ty)| param.span.to(ty.span)) + .map(|(param_name, ty)| { + if let Some(param_name) = param_name { + param_name.span.to(ty.span) + } else { + ty.span + } + }) .next() .unwrap_or(impl_err_span); diff --git a/compiler/rustc_hir_analysis/src/coherence/orphan.rs b/compiler/rustc_hir_analysis/src/coherence/orphan.rs index 0b7fc44460e..74ba4ffe25e 100644 --- a/compiler/rustc_hir_analysis/src/coherence/orphan.rs +++ b/compiler/rustc_hir_analysis/src/coherence/orphan.rs @@ -3,11 +3,10 @@ use rustc_data_structures::fx::FxIndexSet; use rustc_errors::ErrorGuaranteed; -use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; +use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, TyCtxtInferExt}; use rustc_lint_defs::builtin::UNCOVERED_PARAM_IN_PROJECTION; use rustc_middle::ty::{ - self, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeSuperVisitable, - TypeVisitable, TypeVisitableExt, TypeVisitor, TypingMode, + self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, TypingMode, }; use rustc_middle::{bug, span_bug}; use rustc_span::def_id::{DefId, LocalDefId}; @@ -356,13 +355,20 @@ fn orphan_check<'tcx>( }) } OrphanCheckErr::NonLocalInputType(tys) => { - let generics = tcx.generics_of(impl_def_id); - let tys = tys - .into_iter() - .map(|(ty, is_target_ty)| { - (ty.fold_with(&mut TyVarReplacer { infcx: &infcx, generics }), is_target_ty) - }) - .collect(); + let tys = infcx.probe(|_| { + // Map the unconstrained args back to their params, + // ignoring any type unification errors. + for (arg, id_arg) in + std::iter::zip(args, ty::GenericArgs::identity_for_item(tcx, impl_def_id)) + { + let _ = infcx.at(&cause, ty::ParamEnv::empty()).eq( + DefineOpaqueTypes::No, + arg, + id_arg, + ); + } + infcx.resolve_vars_if_possible(tys) + }); OrphanCheckErr::NonLocalInputType(tys) } }) @@ -536,40 +542,3 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for UncoveredTyParamCollector<'_, 'tcx> { } } } - -struct TyVarReplacer<'cx, 'tcx> { - infcx: &'cx InferCtxt<'tcx>, - generics: &'tcx ty::Generics, -} - -impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for TyVarReplacer<'cx, 'tcx> { - fn cx(&self) -> TyCtxt<'tcx> { - self.infcx.tcx - } - - fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { - if !ty.has_type_flags(ty::TypeFlags::HAS_TY_INFER) { - return ty; - } - let ty::Infer(ty::TyVar(vid)) = *ty.kind() else { - return ty.super_fold_with(self); - }; - let origin = self.infcx.type_var_origin(vid); - if let Some(def_id) = origin.param_def_id { - // The generics of an `impl` don't have a parent, we can index directly. - let index = self.generics.param_def_id_to_index[&def_id]; - let name = self.generics.own_params[index as usize].name; - - Ty::new_param(self.infcx.tcx, index, name) - } else { - ty - } - } - - fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> { - if !ct.has_type_flags(ty::TypeFlags::HAS_TY_INFER) { - return ct; - } - ct.super_fold_with(self) - } -} diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs index 5fed2e35287..170500c7a16 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs @@ -49,10 +49,12 @@ pub(crate) fn validate_cmse_abi<'tcx>( Ok(Err(index)) => { // fn(x: u32, u32, u32, u16, y: u16) -> u32, // ^^^^^^ - let span = bare_fn_ty.param_names[index] - .span - .to(bare_fn_ty.decl.inputs[index].span) - .to(bare_fn_ty.decl.inputs.last().unwrap().span); + let span = if let Some(ident) = bare_fn_ty.param_names[index] { + ident.span.to(bare_fn_ty.decl.inputs[index].span) + } else { + bare_fn_ty.decl.inputs[index].span + } + .to(bare_fn_ty.decl.inputs.last().unwrap().span); let plural = bare_fn_ty.param_names.len() - index != 1; dcx.emit_err(errors::CmseInputsStackSpill { span, plural, abi }); } diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 98b81dd3def..ddaca89ccf8 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -2,6 +2,7 @@ //! the definitions in this file have equivalents in `rustc_ast_pretty`. // tidy-alphabetical-start +#![feature(let_chains)] #![recursion_limit = "256"] // tidy-alphabetical-end @@ -898,7 +899,7 @@ impl<'a> State<'a> { ident: Ident, m: &hir::FnSig<'_>, generics: &hir::Generics<'_>, - arg_names: &[Ident], + arg_names: &[Option<Ident>], body_id: Option<hir::BodyId>, ) { self.print_fn(m.decl, m.header, Some(ident.name), generics, arg_names, body_id); @@ -2121,7 +2122,7 @@ impl<'a> State<'a> { header: hir::FnHeader, name: Option<Symbol>, generics: &hir::Generics<'_>, - arg_names: &[Ident], + arg_names: &[Option<Ident>], body_id: Option<hir::BodyId>, ) { self.print_fn_header_info(header); @@ -2141,7 +2142,7 @@ impl<'a> State<'a> { s.print_implicit_self(&decl.implicit_self); } else { if let Some(arg_name) = arg_names.get(i) { - if arg_name.name != kw::Empty { + if let Some(arg_name) = arg_name { s.word(arg_name.to_string()); s.word(":"); s.space(); @@ -2451,7 +2452,7 @@ impl<'a> State<'a> { decl: &hir::FnDecl<'_>, name: Option<Symbol>, generic_params: &[hir::GenericParam<'_>], - arg_names: &[Ident], + arg_names: &[Option<Ident>], ) { self.ibox(INDENT_UNIT); self.print_formal_generic_params(generic_params); diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs index fc1f9a7f2e0..a4776338f6c 100644 --- a/compiler/rustc_hir_typeck/src/closure.rs +++ b/compiler/rustc_hir_typeck/src/closure.rs @@ -164,11 +164,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let resume_ty = liberated_sig.inputs().get(0).copied().unwrap_or(tcx.types.unit); let interior = self.next_ty_var(expr_span); - self.deferred_coroutine_interiors.borrow_mut().push(( - expr_def_id, - body.id(), - interior, - )); + self.deferred_coroutine_interiors.borrow_mut().push((expr_def_id, interior)); // Coroutines that come from coroutine closures have not yet determined // their kind ty, so make a fresh infer var which will be constrained diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index 64886957ff3..d75c2853ba0 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -633,18 +633,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let coroutines = std::mem::take(&mut *self.deferred_coroutine_interiors.borrow_mut()); debug!(?coroutines); - for &(expr_def_id, body_id, interior) in coroutines.iter() { - debug!(?expr_def_id); + let mut obligations = vec![]; + + for &(coroutine_def_id, interior) in coroutines.iter() { + debug!(?coroutine_def_id); // Create the `CoroutineWitness` type that we will unify with `interior`. let args = ty::GenericArgs::identity_for_item( self.tcx, - self.tcx.typeck_root_def_id(expr_def_id.to_def_id()), + self.tcx.typeck_root_def_id(coroutine_def_id.to_def_id()), ); - let witness = Ty::new_coroutine_witness(self.tcx, expr_def_id.to_def_id(), args); + let witness = Ty::new_coroutine_witness(self.tcx, coroutine_def_id.to_def_id(), args); // Unify `interior` with `witness` and collect all the resulting obligations. - let span = self.tcx.hir_body(body_id).value.span; + let span = self.tcx.hir_body_owned_by(coroutine_def_id).value.span; let ty::Infer(ty::InferTy::TyVar(_)) = interior.kind() else { span_bug!(span, "coroutine interior witness not infer: {:?}", interior.kind()) }; @@ -653,15 +655,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Will never define opaque types, as all we do is instantiate a type variable. .eq(DefineOpaqueTypes::Yes, interior, witness) .expect("Failed to unify coroutine interior type"); - let mut obligations = ok.obligations; - // Also collect the obligations that were unstalled by this unification. + obligations.extend(ok.obligations); + } + + // FIXME: Use a real visitor for unstalled obligations in the new solver. + if !coroutines.is_empty() { obligations .extend(self.fulfillment_cx.borrow_mut().drain_unstalled_obligations(&self.infcx)); - - let obligations = obligations.into_iter().map(|o| (o.predicate, o.cause)); - self.typeck_results.borrow_mut().coroutine_stalled_predicates.extend(obligations); } + + self.typeck_results + .borrow_mut() + .coroutine_stalled_predicates + .extend(obligations.into_iter().map(|o| (o.predicate, o.cause))); } #[instrument(skip(self), level = "debug")] diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 90bdb3c4b37..f4bd7ec701f 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -1135,7 +1135,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { && self.tcx.def_kind(fn_def_id).is_fn_like() && let self_implicit = matches!(call_expr.kind, hir::ExprKind::MethodCall(..)) as usize - && let Some(arg) = + && let Some(Some(arg)) = self.tcx.fn_arg_names(fn_def_id).get(expected_idx.as_usize() + self_implicit) && arg.name != kw::SelfLower { @@ -2678,7 +2678,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { params.get(is_method as usize..params.len() - sig.decl.c_variadic as usize)?; debug_assert_eq!(params.len(), fn_inputs.len()); Some(( - fn_inputs.zip(params.iter().map(|¶m| FnParam::Name(param))).collect(), + fn_inputs.zip(params.iter().map(|&ident| FnParam::Name(ident))).collect(), generics, )) } @@ -2709,14 +2709,20 @@ impl<'tcx> Visitor<'tcx> for FindClosureArg<'tcx> { #[derive(Clone, Copy)] enum FnParam<'hir> { Param(&'hir hir::Param<'hir>), - Name(Ident), + Name(Option<Ident>), } impl FnParam<'_> { fn span(&self) -> Span { match self { Self::Param(param) => param.span, - Self::Name(ident) => ident.span, + Self::Name(ident) => { + if let Some(ident) = ident { + ident.span + } else { + DUMMY_SP + } + } } } @@ -2733,7 +2739,8 @@ impl FnParam<'_> { Some(ident.name) } FnParam::Name(ident) - if ident.name != kw::Empty && ident.name != kw::Underscore => + if let Some(ident) = ident + && ident.name != kw::Underscore => { Some(ident.name) } diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index cdfae51583b..908c3ee2eb8 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -3766,7 +3766,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { { let self_first_arg = match method { hir::TraitFn::Required([ident, ..]) => { - ident.name == kw::SelfLower + matches!(ident, Some(Ident { name: kw::SelfLower, .. })) } hir::TraitFn::Provided(body_id) => { self.tcx.hir_body(*body_id).params.first().is_some_and( diff --git a/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs b/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs index 88f4f7caa95..5b4fc51cec8 100644 --- a/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs +++ b/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs @@ -59,7 +59,7 @@ pub(crate) struct TypeckRootCtxt<'tcx> { pub(super) deferred_asm_checks: RefCell<Vec<(&'tcx hir::InlineAsm<'tcx>, HirId)>>, - pub(super) deferred_coroutine_interiors: RefCell<Vec<(LocalDefId, hir::BodyId, Ty<'tcx>)>>, + pub(super) deferred_coroutine_interiors: RefCell<Vec<(LocalDefId, Ty<'tcx>)>>, pub(super) deferred_repeat_expr_checks: RefCell<Vec<(&'tcx hir::Expr<'tcx>, Ty<'tcx>, ty::Const<'tcx>)>>, diff --git a/compiler/rustc_lint/src/nonstandard_style.rs b/compiler/rustc_lint/src/nonstandard_style.rs index 715e3506ab8..752636ccaf0 100644 --- a/compiler/rustc_lint/src/nonstandard_style.rs +++ b/compiler/rustc_lint/src/nonstandard_style.rs @@ -424,7 +424,9 @@ impl<'tcx> LateLintPass<'tcx> for NonSnakeCase { if let hir::TraitItemKind::Fn(_, hir::TraitFn::Required(pnames)) = item.kind { self.check_snake_case(cx, "trait method", &item.ident); for param_name in pnames { - self.check_snake_case(cx, "variable", param_name); + if let Some(param_name) = param_name { + self.check_snake_case(cx, "variable", param_name); + } } } } diff --git a/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp index 0471baa1f9c..b8884486c33 100644 --- a/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp @@ -78,6 +78,13 @@ struct LLVMRustCoverageCodeRegion { }; // Must match the layout of +// `rustc_codegen_llvm::coverageinfo::ffi::ExpansionRegion`. +struct LLVMRustCoverageExpansionRegion { + LLVMRustCoverageSpan Span; + uint32_t ExpandedFileID; +}; + +// Must match the layout of // `rustc_codegen_llvm::coverageinfo::ffi::BranchRegion`. struct LLVMRustCoverageBranchRegion { LLVMRustCoverageSpan Span; @@ -151,6 +158,8 @@ extern "C" void LLVMRustCoverageWriteFunctionMappingsToBuffer( const unsigned *VirtualFileMappingIDs, size_t NumVirtualFileMappingIDs, const LLVMRustCounterExpression *RustExpressions, size_t NumExpressions, const LLVMRustCoverageCodeRegion *CodeRegions, size_t NumCodeRegions, + const LLVMRustCoverageExpansionRegion *ExpansionRegions, + size_t NumExpansionRegions, const LLVMRustCoverageBranchRegion *BranchRegions, size_t NumBranchRegions, const LLVMRustCoverageMCDCBranchRegion *MCDCBranchRegions, size_t NumMCDCBranchRegions, @@ -179,6 +188,13 @@ extern "C" void LLVMRustCoverageWriteFunctionMappingsToBuffer( Region.Span.ColumnStart, Region.Span.LineEnd, Region.Span.ColumnEnd)); } + // Expansion regions: + for (const auto &Region : ArrayRef(ExpansionRegions, NumExpansionRegions)) { + MappingRegions.push_back(coverage::CounterMappingRegion::makeExpansion( + Region.Span.FileID, Region.ExpandedFileID, Region.Span.LineStart, + Region.Span.ColumnStart, Region.Span.LineEnd, Region.Span.ColumnEnd)); + } + // Branch regions: for (const auto &Region : ArrayRef(BranchRegions, NumBranchRegions)) { MappingRegions.push_back(coverage::CounterMappingRegion::makeBranchRegion( diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index f6cf218db9d..4610a571da0 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -1318,7 +1318,7 @@ impl<'a> CrateMetadataRef<'a> { .expect("argument names not encoded for a function") .decode((self, sess)) .nth(0) - .is_some_and(|ident| ident.name == kw::SelfLower) + .is_some_and(|ident| matches!(ident, Some(Ident { name: kw::SelfLower, .. }))) } fn get_associated_item_or_field_def_ids(self, id: DefIndex) -> impl Iterator<Item = DefId> { diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index 5536c93f84a..dc453b1e747 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -443,7 +443,7 @@ define_tables! { rendered_const: Table<DefIndex, LazyValue<String>>, rendered_precise_capturing_args: Table<DefIndex, LazyArray<PreciseCapturingArgKind<Symbol, Symbol>>>, asyncness: Table<DefIndex, ty::Asyncness>, - fn_arg_names: Table<DefIndex, LazyArray<Ident>>, + fn_arg_names: Table<DefIndex, LazyArray<Option<Ident>>>, coroutine_kind: Table<DefIndex, hir::CoroutineKind>, coroutine_for_closure: Table<DefIndex, RawDefId>, coroutine_by_move_body_def_id: Table<DefIndex, RawDefId>, diff --git a/compiler/rustc_middle/src/hir/map.rs b/compiler/rustc_middle/src/hir/map.rs index 2e589150d3e..f17efab81ec 100644 --- a/compiler/rustc_middle/src/hir/map.rs +++ b/compiler/rustc_middle/src/hir/map.rs @@ -280,11 +280,11 @@ impl<'tcx> TyCtxt<'tcx> { }) } - pub fn hir_body_param_names(self, id: BodyId) -> impl Iterator<Item = Ident> { + pub fn hir_body_param_names(self, id: BodyId) -> impl Iterator<Item = Option<Ident>> { self.hir_body(id).params.iter().map(|param| match param.pat.kind { - PatKind::Binding(_, _, ident, _) => ident, - PatKind::Wild => Ident::new(kw::Underscore, param.pat.span), - _ => Ident::empty(), + PatKind::Binding(_, _, ident, _) => Some(ident), + PatKind::Wild => Some(Ident::new(kw::Underscore, param.pat.span)), + _ => None, }) } diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 94a5a3769a3..527c18addbe 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1410,7 +1410,7 @@ rustc_queries! { desc { |tcx| "computing target features for inline asm of `{}`", tcx.def_path_str(def_id) } } - query fn_arg_names(def_id: DefId) -> &'tcx [rustc_span::Ident] { + query fn_arg_names(def_id: DefId) -> &'tcx [Option<rustc_span::Ident>] { desc { |tcx| "looking up function parameter names for `{}`", tcx.def_path_str(def_id) } separate_provide_extern } diff --git a/compiler/rustc_next_trait_solver/src/coherence.rs b/compiler/rustc_next_trait_solver/src/coherence.rs index 53290203600..f8215a228f5 100644 --- a/compiler/rustc_next_trait_solver/src/coherence.rs +++ b/compiler/rustc_next_trait_solver/src/coherence.rs @@ -4,7 +4,8 @@ use std::ops::ControlFlow; use derive_where::derive_where; use rustc_type_ir::inherent::*; use rustc_type_ir::{ - self as ty, InferCtxtLike, Interner, TypeVisitable, TypeVisitableExt, TypeVisitor, + self as ty, InferCtxtLike, Interner, TrivialTypeTraversalImpls, TypeVisitable, + TypeVisitableExt, TypeVisitor, }; use tracing::instrument; @@ -95,6 +96,8 @@ pub fn trait_ref_is_local_or_fundamental<I: Interner>(tcx: I, trait_ref: ty::Tra trait_ref.def_id.is_local() || tcx.trait_is_fundamental(trait_ref.def_id) } +TrivialTypeTraversalImpls! { IsFirstInputType, } + #[derive(Debug, Copy, Clone)] pub enum IsFirstInputType { No, diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index cd931888fba..c48f91643e8 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -17,6 +17,7 @@ use rustc_ast::{ self as ast, AnonConst, Arm, AttrStyle, AttrVec, BinOp, BinOpKind, BlockCheckMode, CaptureBy, ClosureBinder, DUMMY_NODE_ID, Expr, ExprField, ExprKind, FnDecl, FnRetTy, Label, MacCall, MetaItemLit, Movability, Param, RangeLimits, StmtKind, Ty, TyKind, UnOp, UnsafeBinderCastKind, + YieldKind, }; use rustc_ast_pretty::pprust; use rustc_data_structures::stack::ensure_sufficient_stack; @@ -1310,6 +1311,15 @@ impl<'a> Parser<'a> { return self.parse_match_block(lo, match_span, self_arg, MatchKind::Postfix); } + // Parse a postfix `yield`. + if self.eat_keyword(exp!(Yield)) { + let yield_span = self.prev_token.span; + self.psess.gated_spans.gate(sym::yield_expr, yield_span); + return Ok( + self.mk_expr(lo.to(yield_span), ExprKind::Yield(YieldKind::Postfix(self_arg))) + ); + } + let fn_span_lo = self.token.span; let mut seg = self.parse_path_segment(PathStyle::Expr, None)?; self.check_trailing_angle_brackets(&seg, &[exp!(OpenParen)]); @@ -1884,7 +1894,7 @@ impl<'a> Parser<'a> { /// Parse `"yield" expr?`. fn parse_expr_yield(&mut self) -> PResult<'a, P<Expr>> { let lo = self.prev_token.span; - let kind = ExprKind::Yield(self.parse_expr_opt()?); + let kind = ExprKind::Yield(YieldKind::Prefix(self.parse_expr_opt()?)); let span = lo.to(self.prev_token.span); self.psess.gated_spans.gate(sym::yield_expr, span); let expr = self.mk_expr(span, kind); diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index bcfcc8000c7..3d666055a94 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -2217,12 +2217,11 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { .delegation_fn_sigs .get(&def_id) .is_some_and(|sig| sig.has_self), - None => self - .r - .tcx - .fn_arg_names(def_id) - .first() - .is_some_and(|ident| ident.name == kw::SelfLower), + None => { + self.r.tcx.fn_arg_names(def_id).first().is_some_and(|&ident| { + matches!(ident, Some(Ident { name: kw::SelfLower, .. })) + }) + } }; if has_self { return Some(AssocSuggestion::MethodWithSelf { called }); diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 701d06e4fd4..43b78423c72 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -2082,6 +2082,12 @@ fn emit_unknown_print_request_help(early_dcx: &EarlyDiagCtxt, req: &str) -> ! { let mut diag = early_dcx.early_struct_fatal(format!("unknown print request: `{req}`")); #[allow(rustc::diagnostic_outside_of_impl)] diag.help(format!("valid print requests are: {prints}")); + + if req == "lints" { + diag.help(format!("use `-Whelp` to print a list of lints")); + } + + diag.help(format!("for more information, see the rustc book: https://doc.rust-lang.org/rustc/command-line-arguments.html#--print-print-compiler-information")); diag.emit() } 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 393d175ea4c..dc8022b95c3 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -1992,13 +1992,12 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { .iter() .enumerate() .map(|(i, ident)| { - if ident.name.is_empty() - || ident.name == kw::Underscore - || ident.name == kw::SelfLower + if let Some(ident) = ident + && !matches!(ident, Ident { name: kw::Underscore | kw::SelfLower, .. }) { - format!("arg{i}") - } else { format!("{ident}") + } else { + format!("arg{i}") } }) .collect(); diff --git a/compiler/rustc_type_ir/src/macros.rs b/compiler/rustc_type_ir/src/macros.rs index fab1a11304d..c8c293121ca 100644 --- a/compiler/rustc_type_ir/src/macros.rs +++ b/compiler/rustc_type_ir/src/macros.rs @@ -1,10 +1,11 @@ /// Used for types that are `Copy` and which **do not care arena /// allocated data** (i.e., don't need to be folded). +#[macro_export] macro_rules! TrivialTypeTraversalImpls { ($($ty:ty,)+) => { $( - impl<I: $crate::Interner> $crate::fold::TypeFoldable<I> for $ty { - fn try_fold_with<F: $crate::fold::FallibleTypeFolder<I>>( + impl<I: $crate::Interner> $crate::TypeFoldable<I> for $ty { + fn try_fold_with<F: $crate::FallibleTypeFolder<I>>( self, _: &mut F, ) -> ::std::result::Result<Self, F::Error> { @@ -12,7 +13,7 @@ macro_rules! TrivialTypeTraversalImpls { } #[inline] - fn fold_with<F: $crate::fold::TypeFolder<I>>( + fn fold_with<F: $crate::TypeFolder<I>>( self, _: &mut F, ) -> Self { @@ -20,14 +21,14 @@ macro_rules! TrivialTypeTraversalImpls { } } - impl<I: $crate::Interner> $crate::visit::TypeVisitable<I> for $ty { + impl<I: $crate::Interner> $crate::TypeVisitable<I> for $ty { #[inline] - fn visit_with<F: $crate::visit::TypeVisitor<I>>( + fn visit_with<F: $crate::TypeVisitor<I>>( &self, _: &mut F) -> F::Result { - <F::Result as rustc_ast_ir::visit::VisitorResult>::output() + <F::Result as $crate::VisitorResult>::output() } } )+ |
