Auto merge of #138747 - matthiaskrgr:rollup-68x44rw, r=matthiaskrgr
Rollup of 8 pull requests Successful merges: - #138435 (Add support for postfix yield expressions) - #138685 (Use `Option<Ident>` for lowered param names.) - #138700 (Suggest `-Whelp` when pass `--print lints` to rustc) - #138727 (Do not rely on `type_var_origin` in `OrphanCheckErr::NonLocalInputType`) - #138729 (Clean up `FnCtxt::resolve_coroutine_interiors`) - #138731 (coverage: Add LLVM plumbing for expansion regions) - #138732 (Use `def_path_str` for def id arg in `UnsupportedOpInfo`) - #138735 (Remove `llvm` and `llvms` triagebot ping aliases for `icebreakers-llvm` ping group) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
eda7820be5
62 changed files with 499 additions and 240 deletions
|
@ -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 {
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)),
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}))
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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}`"));
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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)]
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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 } => {
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 =
|
||||
|
|
|
@ -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));
|
||||
}),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 });
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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")]
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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>)>>,
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -77,6 +77,13 @@ struct LLVMRustCoverageCodeRegion {
|
|||
LLVMRustCounter Count;
|
||||
};
|
||||
|
||||
// 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 {
|
||||
|
@ -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(
|
||||
|
|
|
@ -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> {
|
||||
|
|
|
@ -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>,
|
||||
|
|
|
@ -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,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 });
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
)+
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue