Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rollup of 8 pull requests #138760

Merged
merged 24 commits into from
Mar 21, 2025
Merged
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
edf65e7
Add support for postfix yield expressions
eholk Mar 12, 2025
1c0916a
Preserve yield position during pretty printing
eholk Mar 12, 2025
635eae2
Teach rustfmt to handle postfix yield
eholk Mar 13, 2025
c5093ac
Fix clippy
eholk Mar 13, 2025
9b0e7f6
Teach rustfmt to handle postfix yield
eholk Mar 18, 2025
299e5d0
Apply suggestions from code review
eholk Mar 18, 2025
2bd7f73
Refactor YieldKind so postfix yield must have an expression
eholk Mar 18, 2025
f27cab8
Use `Option<Ident>` for lowered param names.
nnethercote Mar 13, 2025
5a52b5d
Suggest `-Whelp` when pass `--print lints` to rustc
xizheyin Mar 19, 2025
d07ef5b
coverage: Add LLVM plumbing for expansion regions
Zalathar Mar 4, 2025
220851c
Do not rely on type_var_origin in OrphanCheckErr::NonLocalInputType
compiler-errors Mar 20, 2025
b14de91
Pre cleanups
compiler-errors Mar 18, 2025
2e36990
coverage: Convert and check span coordinates without a local file ID
Zalathar Mar 20, 2025
e6004cc
Use def_path_str for def id arg in UnsupportedOpInfo
compiler-errors Mar 20, 2025
974f759
Remove `llvm` and `llvms` triagebot ping aliases for icebreakers-llvm
jieyouxu Mar 20, 2025
496c251
Disambiguate between wg-llvm and icebreakers-llvm in rustc-dev-guide
jieyouxu Mar 20, 2025
b3c5caf
Rollup merge of #138435 - eholk:prefix-yield, r=oli-obk
matthiaskrgr Mar 20, 2025
00f3ad0
Rollup merge of #138685 - nnethercote:use-Option-Ident-for-lowered-pa…
matthiaskrgr Mar 20, 2025
d4218c2
Rollup merge of #138700 - xizheyin:issue-138612, r=Nadrieril
matthiaskrgr Mar 20, 2025
4659493
Rollup merge of #138727 - compiler-errors:ty-var-origin, r=fmease
matthiaskrgr Mar 20, 2025
84a2bb9
Rollup merge of #138729 - compiler-errors:gen, r=lcnr
matthiaskrgr Mar 20, 2025
7df0170
Rollup merge of #138731 - Zalathar:llvm-expansion, r=jieyouxu
matthiaskrgr Mar 20, 2025
73ed8b3
Rollup merge of #138732 - compiler-errors:did, r=jieyouxu
matthiaskrgr Mar 20, 2025
4a87516
Rollup merge of #138735 - jieyouxu:drop-llvm-alias, r=nikic
matthiaskrgr Mar 20, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 39 additions & 1 deletion compiler/rustc_ast/src/ast.rs
Original file line number Diff line number Diff line change
@@ -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 {
7 changes: 5 additions & 2 deletions compiler/rustc_ast/src/mut_visit.rs
Original file line number Diff line number Diff line change
@@ -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),
10 changes: 7 additions & 3 deletions compiler/rustc_ast/src/util/classify.rs
Original file line number Diff line number Diff line change
@@ -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;
}
}
}
}
4 changes: 2 additions & 2 deletions compiler/rustc_ast/src/visit.rs
Original file line number Diff line number Diff line change
@@ -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)),
2 changes: 1 addition & 1 deletion compiler/rustc_ast_lowering/src/expr.rs
Original file line number Diff line number Diff line change
@@ -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(
14 changes: 10 additions & 4 deletions compiler/rustc_ast_lowering/src/lib.rs
Original file line number Diff line number Diff line change
@@ -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
}
}))
}
12 changes: 10 additions & 2 deletions compiler/rustc_ast_pretty/src/pprust/state/expr.rs
Original file line number Diff line number Diff line change
@@ -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,
12 changes: 6 additions & 6 deletions compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
Original file line number Diff line number Diff line change
@@ -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}`"));
2 changes: 1 addition & 1 deletion compiler/rustc_borrowck/src/diagnostics/mod.rs
Original file line number Diff line number Diff line change
@@ -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 {
19 changes: 17 additions & 2 deletions compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs
Original file line number Diff line number Diff line change
@@ -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)]
16 changes: 14 additions & 2 deletions compiler/rustc_codegen_llvm/src/coverageinfo/llvm_cov.rs
Original file line number Diff line number Diff line change
@@ -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(),
33 changes: 17 additions & 16 deletions compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/covfun.rs
Original file line number Diff line number Diff line change
@@ -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 } => {
Loading
Loading