Auto merge of #91656 - matthiaskrgr:rollup-lk96y6d, r=matthiaskrgr

Rollup of 7 pull requests

Successful merges:

 - #83744 (Deprecate crate_type and crate_name nested inside #![cfg_attr])
 - #90550 (Update certificates in some Ubuntu 16 images.)
 - #91272 (Print a suggestion when comparing references to primitive types in `const fn`)
 - #91467 (Emphasise that an OsStr[ing] is not necessarily a platform string)
 - #91531 (Do not add `;` to expected tokens list when it's wrong)
 - #91577 (Address some FIXMEs left over from #91475)
 - #91638 (Remove `in_band_lifetimes` from `rustc_mir_transform`)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2021-12-08 11:22:02 +00:00
commit 4459e720be
70 changed files with 624 additions and 219 deletions

View File

@ -801,7 +801,7 @@ impl Visitor<'tcx> for Checker<'mir, 'tcx> {
if let Some(trait_id) = tcx.trait_of_item(callee) {
trace!("attempting to call a trait method");
if !self.tcx.features().const_trait_impl {
self.check_op(ops::FnCallNonConst);
self.check_op(ops::FnCallNonConst(Some((callee, substs))));
return;
}
@ -857,7 +857,7 @@ impl Visitor<'tcx> for Checker<'mir, 'tcx> {
}
if !nonconst_call_permission {
self.check_op(ops::FnCallNonConst);
self.check_op(ops::FnCallNonConst(None));
return;
}
}
@ -926,7 +926,7 @@ impl Visitor<'tcx> for Checker<'mir, 'tcx> {
}
if !nonconst_call_permission {
self.check_op(ops::FnCallNonConst);
self.check_op(ops::FnCallNonConst(None));
return;
}
}

View File

@ -1,12 +1,14 @@
//! Concrete error types for all operations which may be invalid in a certain const context.
use rustc_errors::{struct_span_err, DiagnosticBuilder};
use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder};
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_middle::mir;
use rustc_middle::ty::subst::{GenericArgKind, SubstsRef};
use rustc_middle::{mir, ty::AssocKind};
use rustc_session::parse::feature_err;
use rustc_span::symbol::sym;
use rustc_span::{Span, Symbol};
use rustc_span::{symbol::Ident, Span, Symbol};
use rustc_span::{BytePos, Pos};
use super::ConstCx;
@ -72,17 +74,71 @@ impl NonConstOp for FnCallIndirect {
/// A function call where the callee is not marked as `const`.
#[derive(Debug)]
pub struct FnCallNonConst;
impl NonConstOp for FnCallNonConst {
pub struct FnCallNonConst<'tcx>(pub Option<(DefId, SubstsRef<'tcx>)>);
impl<'a> NonConstOp for FnCallNonConst<'a> {
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
struct_span_err!(
let mut err = struct_span_err!(
ccx.tcx.sess,
span,
E0015,
"calls in {}s are limited to constant functions, \
tuple structs and tuple variants",
ccx.const_kind(),
)
);
if let FnCallNonConst(Some((callee, substs))) = *self {
if let Some(trait_def_id) = ccx.tcx.lang_items().eq_trait() {
if let Some(eq_item) = ccx.tcx.associated_items(trait_def_id).find_by_name_and_kind(
ccx.tcx,
Ident::with_dummy_span(sym::eq),
AssocKind::Fn,
trait_def_id,
) {
if callee == eq_item.def_id && substs.len() == 2 {
match (substs[0].unpack(), substs[1].unpack()) {
(GenericArgKind::Type(self_ty), GenericArgKind::Type(rhs_ty))
if self_ty == rhs_ty
&& self_ty.is_ref()
&& self_ty.peel_refs().is_primitive() =>
{
let mut num_refs = 0;
let mut tmp_ty = self_ty;
while let rustc_middle::ty::Ref(_, inner_ty, _) = tmp_ty.kind() {
num_refs += 1;
tmp_ty = inner_ty;
}
let deref = "*".repeat(num_refs);
if let Ok(call_str) =
ccx.tcx.sess.source_map().span_to_snippet(span)
{
if let Some(eq_idx) = call_str.find("==") {
if let Some(rhs_idx) = call_str[(eq_idx + 2)..]
.find(|c: char| !c.is_whitespace())
{
let rhs_pos = span.lo()
+ BytePos::from_usize(eq_idx + 2 + rhs_idx);
let rhs_span = span.with_lo(rhs_pos).with_hi(rhs_pos);
err.multipart_suggestion(
"consider dereferencing here",
vec![
(span.shrink_to_lo(), deref.clone()),
(rhs_span, deref),
],
Applicability::MachineApplicable,
);
}
}
}
}
_ => {}
}
}
}
}
}
err
}
}

View File

@ -402,7 +402,24 @@ impl<'a> StripUnconfigured<'a> {
);
trees.push((bracket_group, Spacing::Alone));
let tokens = Some(LazyTokenStream::new(AttrAnnotatedTokenStream::new(trees)));
self.process_cfg_attr(attr::mk_attr_from_item(item, tokens, attr.style, span))
let attr = attr::mk_attr_from_item(item, tokens, attr.style, span);
if attr.has_name(sym::crate_type) {
self.sess.parse_sess.buffer_lint(
rustc_lint_defs::builtin::DEPRECATED_CFG_ATTR_CRATE_TYPE_NAME,
attr.span,
ast::CRATE_NODE_ID,
"`crate_type` within an `#![cfg_attr] attribute is deprecated`",
);
}
if attr.has_name(sym::crate_name) {
self.sess.parse_sess.buffer_lint(
rustc_lint_defs::builtin::DEPRECATED_CFG_ATTR_CRATE_TYPE_NAME,
attr.span,
ast::CRATE_NODE_ID,
"`crate_name` within an `#![cfg_attr] attribute is deprecated`",
);
}
self.process_cfg_attr(attr)
})
.collect()
}

View File

@ -2960,6 +2960,41 @@ declare_lint! {
"detects large moves or copies",
}
declare_lint! {
/// The `deprecated_cfg_attr_crate_type_name` lint detects uses of the
/// `#![cfg_attr(..., crate_type = "...")]` and
/// `#![cfg_attr(..., crate_name = "...")]` attributes to conditionally
/// specify the crate type and name in the source code.
///
/// ### Example
///
/// ```rust
/// #![cfg_attr(debug_assertions, crate_type = "lib")]
/// ```
///
/// {{produces}}
///
///
/// ### Explanation
///
/// The `#![crate_type]` and `#![crate_name]` attributes require a hack in
/// the compiler to be able to change the used crate type and crate name
/// after macros have been expanded. Neither attribute works in combination
/// with Cargo as it explicitly passes `--crate-type` and `--crate-name` on
/// the commandline. These values must match the value used in the source
/// code to prevent an error.
///
/// To fix the warning use `--crate-type` on the commandline when running
/// rustc instead of `#![cfg_attr(..., crate_type = "...")]` and
/// `--crate-name` instead of `#![cfg_attr(..., crate_name = "...")]`.
pub DEPRECATED_CFG_ATTR_CRATE_TYPE_NAME,
Warn,
"detects usage of `#![cfg_attr(..., crate_type/crate_name = \"...\")]`",
@future_incompatible = FutureIncompatibleInfo {
reference: "issue #91632 <https://github.com/rust-lang/rust/issues/91632>",
};
}
declare_lint_pass! {
/// Does nothing as a lint pass, but registers some `Lint`s
/// that are used by other parts of the compiler.
@ -3056,6 +3091,7 @@ declare_lint_pass! {
NON_EXHAUSTIVE_OMITTED_PATTERNS,
TEXT_DIRECTION_CODEPOINT_IN_COMMENT,
DEREF_INTO_DYN_SUPERTRAIT,
DEPRECATED_CFG_ATTR_CRATE_TYPE_NAME,
]
}

View File

@ -34,7 +34,7 @@ fn is_stable(place: PlaceRef<'_>) -> bool {
}
/// Determine whether this type may be a reference (or box), and thus needs retagging.
fn may_be_reference(ty: Ty<'tcx>) -> bool {
fn may_be_reference(ty: Ty<'_>) -> bool {
match ty.kind() {
// Primitive types that are not references
ty::Bool

View File

@ -23,7 +23,7 @@ struct ConstMutationChecker<'a, 'tcx> {
target_local: Option<Local>,
}
impl<'a, 'tcx> ConstMutationChecker<'a, 'tcx> {
impl<'tcx> ConstMutationChecker<'_, 'tcx> {
fn is_const_item(&self, local: Local) -> Option<DefId> {
if let Some(box LocalInfo::ConstRef { def_id }) = self.body.local_decls[local].local_info {
Some(def_id)
@ -95,7 +95,7 @@ impl<'a, 'tcx> ConstMutationChecker<'a, 'tcx> {
}
}
impl<'a, 'tcx> Visitor<'tcx> for ConstMutationChecker<'a, 'tcx> {
impl<'tcx> Visitor<'tcx> for ConstMutationChecker<'_, 'tcx> {
fn visit_statement(&mut self, stmt: &Statement<'tcx>, loc: Location) {
if let StatementKind::Assign(box (lhs, _)) = &stmt.kind {
// Check for assignment to fields of a constant

View File

@ -66,7 +66,7 @@ fn builtin_derive_def_id(tcx: TyCtxt<'_>, def_id: DefId) -> Option<DefId> {
}
}
impl<'a, 'tcx> Visitor<'tcx> for PackedRefChecker<'a, 'tcx> {
impl<'tcx> Visitor<'tcx> for PackedRefChecker<'_, 'tcx> {
fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) {
// Make sure we know where in the MIR we are.
self.source_info = terminator.source_info;

View File

@ -46,7 +46,7 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> {
}
}
impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
impl<'tcx> Visitor<'tcx> for UnsafetyChecker<'_, 'tcx> {
fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) {
self.source_info = terminator.source_info;
match terminator.kind {
@ -244,7 +244,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
}
}
impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> {
impl<'tcx> UnsafetyChecker<'_, 'tcx> {
fn require_unsafe(&mut self, kind: UnsafetyViolationKind, details: UnsafetyViolationDetails) {
// Violations can turn out to be `UnsafeFn` during analysis, but they should not start out as such.
assert_ne!(kind, UnsafetyViolationKind::UnsafeFn);
@ -397,7 +397,7 @@ struct UnusedUnsafeVisitor<'a> {
unsafe_blocks: &'a mut Vec<(hir::HirId, bool)>,
}
impl<'a, 'tcx> intravisit::Visitor<'tcx> for UnusedUnsafeVisitor<'a> {
impl<'tcx> intravisit::Visitor<'tcx> for UnusedUnsafeVisitor<'_> {
type Map = intravisit::ErasedMap<'tcx>;
fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<Self::Map> {

View File

@ -89,7 +89,7 @@ fn find_optimization_oportunities<'tcx>(body: &Body<'tcx>) -> Vec<(Local, Consta
eligable_locals
}
impl<'tcx> Visitor<'tcx> for LocalUseVisitor {
impl Visitor<'_> for LocalUseVisitor {
fn visit_local(&mut self, local: &Local, context: PlaceContext, location: Location) {
if context.is_mutating_use() {
self.local_mutating_uses[*local] = self.local_mutating_uses[*local].saturating_add(1);

View File

@ -54,7 +54,7 @@ impl<'tcx> MirPass<'tcx> for ConstGoto {
}
}
impl<'a, 'tcx> Visitor<'tcx> for ConstGotoOptimizationFinder<'a, 'tcx> {
impl<'tcx> Visitor<'tcx> for ConstGotoOptimizationFinder<'_, 'tcx> {
fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) {
let _: Option<_> = try {
let target = terminator.kind.as_goto()?;

View File

@ -171,7 +171,7 @@ struct ConstPropMachine<'mir, 'tcx> {
can_const_prop: IndexVec<Local, ConstPropMode>,
}
impl<'mir, 'tcx> ConstPropMachine<'mir, 'tcx> {
impl ConstPropMachine<'_, '_> {
fn new(
only_propagate_inside_block_locals: BitSet<Local>,
can_const_prop: IndexVec<Local, ConstPropMode>,
@ -308,14 +308,14 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine<'mir, 'tcx>
}
#[inline(always)]
fn stack(
fn stack<'a>(
ecx: &'a InterpCx<'mir, 'tcx, Self>,
) -> &'a [Frame<'mir, 'tcx, Self::PointerTag, Self::FrameExtra>] {
&ecx.machine.stack
}
#[inline(always)]
fn stack_mut(
fn stack_mut<'a>(
ecx: &'a mut InterpCx<'mir, 'tcx, Self>,
) -> &'a mut Vec<Frame<'mir, 'tcx, Self::PointerTag, Self::FrameExtra>> {
&mut ecx.machine.stack
@ -336,7 +336,7 @@ struct ConstPropagator<'mir, 'tcx> {
source_info: Option<SourceInfo>,
}
impl<'mir, 'tcx> LayoutOfHelpers<'tcx> for ConstPropagator<'mir, 'tcx> {
impl<'tcx> LayoutOfHelpers<'tcx> for ConstPropagator<'_, 'tcx> {
type LayoutOfResult = Result<TyAndLayout<'tcx>, LayoutError<'tcx>>;
#[inline]
@ -345,21 +345,21 @@ impl<'mir, 'tcx> LayoutOfHelpers<'tcx> for ConstPropagator<'mir, 'tcx> {
}
}
impl<'mir, 'tcx> HasDataLayout for ConstPropagator<'mir, 'tcx> {
impl HasDataLayout for ConstPropagator<'_, '_> {
#[inline]
fn data_layout(&self) -> &TargetDataLayout {
&self.tcx.data_layout
}
}
impl<'mir, 'tcx> ty::layout::HasTyCtxt<'tcx> for ConstPropagator<'mir, 'tcx> {
impl<'tcx> ty::layout::HasTyCtxt<'tcx> for ConstPropagator<'_, 'tcx> {
#[inline]
fn tcx(&self) -> TyCtxt<'tcx> {
self.tcx
}
}
impl<'mir, 'tcx> ty::layout::HasParamEnv<'tcx> for ConstPropagator<'mir, 'tcx> {
impl<'tcx> ty::layout::HasParamEnv<'tcx> for ConstPropagator<'_, 'tcx> {
#[inline]
fn param_env(&self) -> ty::ParamEnv<'tcx> {
self.param_env
@ -971,7 +971,7 @@ struct CanConstProp {
impl CanConstProp {
/// Returns true if `local` can be propagated
fn check(
fn check<'tcx>(
tcx: TyCtxt<'tcx>,
param_env: ParamEnv<'tcx>,
body: &Body<'tcx>,
@ -1019,7 +1019,7 @@ impl CanConstProp {
}
}
impl<'tcx> Visitor<'tcx> for CanConstProp {
impl Visitor<'_> for CanConstProp {
fn visit_local(&mut self, &local: &Local, context: PlaceContext, _: Location) {
use rustc_middle::mir::visit::PlaceContext::*;
match context {
@ -1079,7 +1079,7 @@ impl<'tcx> Visitor<'tcx> for CanConstProp {
}
}
impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> {
impl<'tcx> MutVisitor<'tcx> for ConstPropagator<'_, 'tcx> {
fn tcx(&self) -> TyCtxt<'tcx> {
self.tcx
}

View File

@ -629,7 +629,7 @@ impl UsedExpressions {
}
/// Generates the MIR pass `CoverageSpan`-specific spanview dump file.
pub(super) fn dump_coverage_spanview(
pub(super) fn dump_coverage_spanview<'tcx>(
tcx: TyCtxt<'tcx>,
mir_body: &mir::Body<'tcx>,
basic_coverage_blocks: &CoverageGraph,
@ -651,7 +651,7 @@ pub(super) fn dump_coverage_spanview(
}
/// Converts the computed `BasicCoverageBlockData`s into `SpanViewable`s.
fn span_viewables(
fn span_viewables<'tcx>(
tcx: TyCtxt<'tcx>,
mir_body: &mir::Body<'tcx>,
basic_coverage_blocks: &CoverageGraph,
@ -670,7 +670,7 @@ fn span_viewables(
}
/// Generates the MIR pass coverage-specific graphviz dump file.
pub(super) fn dump_coverage_graphviz(
pub(super) fn dump_coverage_graphviz<'tcx>(
tcx: TyCtxt<'tcx>,
mir_body: &mir::Body<'tcx>,
pass_name: &str,
@ -750,7 +750,7 @@ pub(super) fn dump_coverage_graphviz(
.expect("Unexpected error writing BasicCoverageBlock graphviz DOT file");
}
fn bcb_to_string_sections(
fn bcb_to_string_sections<'tcx>(
tcx: TyCtxt<'tcx>,
mir_body: &mir::Body<'tcx>,
debug_counters: &DebugCounters,
@ -817,7 +817,7 @@ fn bcb_to_string_sections(
/// Returns a simple string representation of a `TerminatorKind` variant, independent of any
/// values it might hold.
pub(super) fn term_type(kind: &TerminatorKind<'tcx>) -> &'static str {
pub(super) fn term_type(kind: &TerminatorKind<'_>) -> &'static str {
match kind {
TerminatorKind::Goto { .. } => "Goto",
TerminatorKind::SwitchInt { .. } => "SwitchInt",

View File

@ -27,7 +27,7 @@ pub(super) struct CoverageGraph {
}
impl CoverageGraph {
pub fn from_mir(mir_body: &mir::Body<'tcx>) -> Self {
pub fn from_mir(mir_body: &mir::Body<'_>) -> Self {
let (bcbs, bb_to_bcb) = Self::compute_basic_coverage_blocks(mir_body);
// Pre-transform MIR `BasicBlock` successors and predecessors into the BasicCoverageBlock
@ -74,7 +74,7 @@ impl CoverageGraph {
}
fn compute_basic_coverage_blocks(
mir_body: &mir::Body<'tcx>,
mir_body: &mir::Body<'_>,
) -> (
IndexVec<BasicCoverageBlock, BasicCoverageBlockData>,
IndexVec<BasicBlock, Option<BasicCoverageBlock>>,
@ -267,7 +267,7 @@ impl graph::WithSuccessors for CoverageGraph {
}
}
impl graph::GraphPredecessors<'graph> for CoverageGraph {
impl<'graph> graph::GraphPredecessors<'graph> for CoverageGraph {
type Item = BasicCoverageBlock;
type Iter = std::iter::Copied<std::slice::Iter<'graph, BasicCoverageBlock>>;
}

View File

@ -443,7 +443,7 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
}
fn inject_edge_counter_basic_block(
mir_body: &mut mir::Body<'tcx>,
mir_body: &mut mir::Body<'_>,
from_bb: BasicBlock,
to_bb: BasicBlock,
) -> BasicBlock {
@ -466,7 +466,7 @@ fn inject_edge_counter_basic_block(
}
fn inject_statement(
mir_body: &mut mir::Body<'tcx>,
mir_body: &mut mir::Body<'_>,
counter_kind: CoverageKind,
bb: BasicBlock,
some_code_region: Option<CodeRegion>,
@ -488,7 +488,7 @@ fn inject_statement(
}
// Non-code expressions are injected into the coverage map, without generating executable code.
fn inject_intermediate_expression(mir_body: &mut mir::Body<'tcx>, expression: CoverageKind) {
fn inject_intermediate_expression(mir_body: &mut mir::Body<'_>, expression: CoverageKind) {
debug_assert!(matches!(expression, CoverageKind::Expression { .. }));
debug!(" injecting non-code expression {:?}", expression);
let inject_in_bb = mir::START_BLOCK;

View File

@ -137,7 +137,7 @@ fn coverageinfo<'tcx>(tcx: TyCtxt<'tcx>, instance_def: ty::InstanceDef<'tcx>) ->
coverage_visitor.info
}
fn covered_file_name<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Option<Symbol> {
fn covered_file_name(tcx: TyCtxt<'_>, def_id: DefId) -> Option<Symbol> {
if tcx.is_mir_available(def_id) {
let body = mir_body(tcx, def_id);
for bb_data in body.basic_blocks().iter() {

View File

@ -21,7 +21,7 @@ pub(super) enum CoverageStatement {
}
impl CoverageStatement {
pub fn format(&self, tcx: TyCtxt<'tcx>, mir_body: &'a mir::Body<'tcx>) -> String {
pub fn format<'tcx>(&self, tcx: TyCtxt<'tcx>, mir_body: &mir::Body<'tcx>) -> String {
match *self {
Self::Statement(bb, span, stmt_index) => {
let stmt = &mir_body[bb].statements[stmt_index];
@ -86,7 +86,7 @@ impl CoverageSpan {
}
pub fn for_statement(
statement: &Statement<'tcx>,
statement: &Statement<'_>,
span: Span,
expn_span: Span,
bcb: BasicCoverageBlock,
@ -151,7 +151,7 @@ impl CoverageSpan {
self.bcb == other.bcb
}
pub fn format(&self, tcx: TyCtxt<'tcx>, mir_body: &'a mir::Body<'tcx>) -> String {
pub fn format<'tcx>(&self, tcx: TyCtxt<'tcx>, mir_body: &mir::Body<'tcx>) -> String {
format!(
"{}\n {}",
source_range_no_file(tcx, &self.span),
@ -159,10 +159,10 @@ impl CoverageSpan {
)
}
pub fn format_coverage_statements(
pub fn format_coverage_statements<'tcx>(
&self,
tcx: TyCtxt<'tcx>,
mir_body: &'a mir::Body<'tcx>,
mir_body: &mir::Body<'tcx>,
) -> String {
let mut sorted_coverage_statements = self.coverage_statements.clone();
sorted_coverage_statements.sort_unstable_by_key(|covstmt| match *covstmt {
@ -803,7 +803,7 @@ impl<'a, 'tcx> CoverageSpans<'a, 'tcx> {
/// If the MIR `Statement` has a span contributive to computing coverage spans,
/// return it; otherwise return `None`.
pub(super) fn filtered_statement_span(statement: &'a Statement<'tcx>) -> Option<Span> {
pub(super) fn filtered_statement_span(statement: &Statement<'_>) -> Option<Span> {
match statement.kind {
// These statements have spans that are often outside the scope of the executed source code
// for their parent `BasicBlock`.
@ -847,7 +847,7 @@ pub(super) fn filtered_statement_span(statement: &'a Statement<'tcx>) -> Option<
/// If the MIR `Terminator` has a span contributive to computing coverage spans,
/// return it; otherwise return `None`.
pub(super) fn filtered_terminator_span(terminator: &'a Terminator<'tcx>) -> Option<Span> {
pub(super) fn filtered_terminator_span(terminator: &Terminator<'_>) -> Option<Span> {
match terminator.kind {
// These terminators have spans that don't positively contribute to computing a reasonable
// span of actually executed source code. (For example, SwitchInt terminators extracted from

View File

@ -180,7 +180,7 @@ impl<'tcx> MockBlocks<'tcx> {
}
}
fn debug_basic_blocks(mir_body: &Body<'tcx>) -> String {
fn debug_basic_blocks<'tcx>(mir_body: &Body<'tcx>) -> String {
format!(
"{:?}",
mir_body
@ -273,7 +273,7 @@ fn print_coverage_graphviz(
}
/// Create a mock `Body` with a simple flow.
fn goto_switchint() -> Body<'a> {
fn goto_switchint<'a>() -> Body<'a> {
let mut blocks = MockBlocks::new();
let start = blocks.call(None);
let goto = blocks.goto(Some(start));
@ -363,7 +363,7 @@ fn test_covgraph_goto_switchint() {
}
/// Create a mock `Body` with a loop.
fn switchint_then_loop_else_return() -> Body<'a> {
fn switchint_then_loop_else_return<'a>() -> Body<'a> {
let mut blocks = MockBlocks::new();
let start = blocks.call(None);
let switchint = blocks.switchint(Some(start));
@ -449,7 +449,7 @@ fn test_covgraph_switchint_then_loop_else_return() {
}
/// Create a mock `Body` with nested loops.
fn switchint_loop_then_inner_loop_else_break() -> Body<'a> {
fn switchint_loop_then_inner_loop_else_break<'a>() -> Body<'a> {
let mut blocks = MockBlocks::new();
let start = blocks.call(None);
let switchint = blocks.switchint(Some(start));

View File

@ -54,7 +54,7 @@ impl<'tcx> MutVisitor<'tcx> for OptApplier<'tcx> {
}
}
fn find_duplicates<'a, 'tcx>(body: &'a Body<'tcx>) -> FxHashMap<BasicBlock, BasicBlock> {
fn find_duplicates(body: &Body<'_>) -> FxHashMap<BasicBlock, BasicBlock> {
let mut duplicates = FxHashMap::default();
let bbs_to_go_through =
@ -102,7 +102,7 @@ struct BasicBlockHashable<'tcx, 'a> {
basic_block_data: &'a BasicBlockData<'tcx>,
}
impl<'tcx, 'a> Hash for BasicBlockHashable<'tcx, 'a> {
impl Hash for BasicBlockHashable<'_, '_> {
fn hash<H: Hasher>(&self, state: &mut H) {
hash_statements(state, self.basic_block_data.statements.iter());
// Note that since we only hash the kind, we lose span information if we deduplicate the blocks
@ -110,9 +110,9 @@ impl<'tcx, 'a> Hash for BasicBlockHashable<'tcx, 'a> {
}
}
impl<'tcx, 'a> Eq for BasicBlockHashable<'tcx, 'a> {}
impl Eq for BasicBlockHashable<'_, '_> {}
impl<'tcx, 'a> PartialEq for BasicBlockHashable<'tcx, 'a> {
impl PartialEq for BasicBlockHashable<'_, '_> {
fn eq(&self, other: &Self) -> bool {
self.basic_block_data.statements.len() == other.basic_block_data.statements.len()
&& &self.basic_block_data.terminator().kind == &other.basic_block_data.terminator().kind
@ -132,7 +132,7 @@ fn hash_statements<'a, 'tcx, H: Hasher>(
}
}
fn statement_hash<'tcx, H: Hasher>(hasher: &mut H, stmt: &StatementKind<'tcx>) {
fn statement_hash<H: Hasher>(hasher: &mut H, stmt: &StatementKind<'_>) {
match stmt {
StatementKind::Assign(box (place, rvalue)) => {
place.hash(hasher);
@ -142,14 +142,14 @@ fn statement_hash<'tcx, H: Hasher>(hasher: &mut H, stmt: &StatementKind<'tcx>) {
};
}
fn rvalue_hash<H: Hasher>(hasher: &mut H, rvalue: &Rvalue<'tcx>) {
fn rvalue_hash<H: Hasher>(hasher: &mut H, rvalue: &Rvalue<'_>) {
match rvalue {
Rvalue::Use(op) => operand_hash(hasher, op),
x => x.hash(hasher),
};
}
fn operand_hash<H: Hasher>(hasher: &mut H, operand: &Operand<'tcx>) {
fn operand_hash<H: Hasher>(hasher: &mut H, operand: &Operand<'_>) {
match operand {
Operand::Constant(box Constant { user_ty: _, literal, span: _ }) => literal.hash(hasher),
x => x.hash(hasher),
@ -168,7 +168,7 @@ fn statement_eq<'tcx>(lhs: &StatementKind<'tcx>, rhs: &StatementKind<'tcx>) -> b
res
}
fn rvalue_eq(lhs: &Rvalue<'tcx>, rhs: &Rvalue<'tcx>) -> bool {
fn rvalue_eq<'tcx>(lhs: &Rvalue<'tcx>, rhs: &Rvalue<'tcx>) -> bool {
let res = match (lhs, rhs) {
(Rvalue::Use(op1), Rvalue::Use(op2)) => operand_eq(op1, op2),
(x, y) => x == y,
@ -177,7 +177,7 @@ fn rvalue_eq(lhs: &Rvalue<'tcx>, rhs: &Rvalue<'tcx>) -> bool {
res
}
fn operand_eq(lhs: &Operand<'tcx>, rhs: &Operand<'tcx>) -> bool {
fn operand_eq<'tcx>(lhs: &Operand<'tcx>, rhs: &Operand<'tcx>) -> bool {
let res = match (lhs, rhs) {
(
Operand::Constant(box Constant { user_ty: _, literal, span: _ }),

View File

@ -241,7 +241,7 @@ struct Replacements<'tcx> {
kill: BitSet<Local>,
}
impl Replacements<'tcx> {
impl<'tcx> Replacements<'tcx> {
fn new(locals: usize) -> Self {
Self { map: IndexVec::from_elem_n(None, locals), kill: BitSet::new_empty(locals) }
}
@ -298,7 +298,7 @@ struct Replacer<'tcx> {
}
impl<'tcx> MutVisitor<'tcx> for Replacer<'tcx> {
fn tcx<'a>(&'a self) -> TyCtxt<'tcx> {
fn tcx(&self) -> TyCtxt<'tcx> {
self.tcx
}
@ -372,7 +372,7 @@ struct Conflicts<'a> {
unified_locals: InPlaceUnificationTable<UnifyLocal>,
}
impl Conflicts<'a> {
impl<'a> Conflicts<'a> {
fn build<'tcx>(
tcx: TyCtxt<'tcx>,
body: &'_ Body<'tcx>,
@ -820,10 +820,7 @@ struct CandidateAssignment<'tcx> {
/// comment) and also throw out assignments that involve a local that has its address taken or is
/// otherwise ineligible (eg. locals used as array indices are ignored because we cannot propagate
/// arbitrary places into array indices).
fn find_candidates<'a, 'tcx>(
tcx: TyCtxt<'tcx>,
body: &'a Body<'tcx>,
) -> Vec<CandidateAssignment<'tcx>> {
fn find_candidates<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) -> Vec<CandidateAssignment<'tcx>> {
let mut visitor = FindAssignments {
tcx,
body,
@ -843,7 +840,7 @@ struct FindAssignments<'a, 'tcx> {
locals_used_as_array_index: BitSet<Local>,
}
impl<'a, 'tcx> Visitor<'tcx> for FindAssignments<'a, 'tcx> {
impl<'tcx> Visitor<'tcx> for FindAssignments<'_, 'tcx> {
fn visit_statement(&mut self, statement: &Statement<'tcx>, location: Location) {
if let StatementKind::Assign(box (
dest,

View File

@ -167,7 +167,7 @@ impl<'tcx> MirPass<'tcx> for EarlyOtherwiseBranch {
}
}
fn is_switch<'tcx>(terminator: &Terminator<'tcx>) -> bool {
fn is_switch(terminator: &Terminator<'_>) -> bool {
matches!(terminator.kind, TerminatorKind::SwitchInt { .. })
}
@ -208,7 +208,7 @@ struct OptimizationInfo<'tcx> {
second_switch_info: SwitchDiscriminantInfo<'tcx>,
}
impl<'a, 'tcx> Helper<'a, 'tcx> {
impl<'tcx> Helper<'_, 'tcx> {
pub fn go(
&self,
bb: &BasicBlockData<'tcx>,

View File

@ -149,13 +149,13 @@ struct Elaborator<'a, 'b, 'tcx> {
ctxt: &'a mut ElaborateDropsCtxt<'b, 'tcx>,
}
impl<'a, 'b, 'tcx> fmt::Debug for Elaborator<'a, 'b, 'tcx> {
impl fmt::Debug for Elaborator<'_, '_, '_> {
fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
Ok(())
}
}
impl<'a, 'b, 'tcx> DropElaborator<'a, 'tcx> for Elaborator<'a, 'b, 'tcx> {
impl<'a, 'tcx> DropElaborator<'a, 'tcx> for Elaborator<'a, '_, 'tcx> {
type Path = MovePathIndex;
fn patch(&mut self) -> &mut MirPatch<'tcx> {

View File

@ -27,7 +27,7 @@ struct FunctionItemRefChecker<'a, 'tcx> {
body: &'a Body<'tcx>,
}
impl<'a, 'tcx> Visitor<'tcx> for FunctionItemRefChecker<'a, 'tcx> {
impl<'tcx> Visitor<'tcx> for FunctionItemRefChecker<'_, 'tcx> {
/// Emits a lint for function reference arguments bound by `fmt::Pointer` or passed to
/// `transmute`. This only handles arguments in calls outside macro expansions to avoid double
/// counting function references formatted as pointers by macros.
@ -92,7 +92,7 @@ impl<'a, 'tcx> Visitor<'tcx> for FunctionItemRefChecker<'a, 'tcx> {
}
}
impl<'a, 'tcx> FunctionItemRefChecker<'a, 'tcx> {
impl<'tcx> FunctionItemRefChecker<'_, 'tcx> {
/// Emits a lint for function reference arguments bound by `fmt::Pointer` in calls to the
/// function defined by `def_id` with the substitutions `substs_ref`.
fn check_bound_args(

View File

@ -233,7 +233,7 @@ struct TransformVisitor<'tcx> {
new_ret_local: Local,
}
impl TransformVisitor<'tcx> {
impl<'tcx> TransformVisitor<'tcx> {
// Make a GeneratorState variant assignment. `core::ops::GeneratorState` only has single
// element tuple variants, so we can just write to the downcasted first field and then set the
// discriminant to the appropriate variant.
@ -295,7 +295,7 @@ impl TransformVisitor<'tcx> {
}
}
impl MutVisitor<'tcx> for TransformVisitor<'tcx> {
impl<'tcx> MutVisitor<'tcx> for TransformVisitor<'tcx> {
fn tcx(&self) -> TyCtxt<'tcx> {
self.tcx
}
@ -446,7 +446,7 @@ struct LivenessInfo {
storage_liveness: IndexVec<BasicBlock, Option<BitSet<Local>>>,
}
fn locals_live_across_suspend_points(
fn locals_live_across_suspend_points<'tcx>(
tcx: TyCtxt<'tcx>,
body: &Body<'tcx>,
always_live_locals: &storage::AlwaysLiveLocals,
@ -613,7 +613,7 @@ impl ops::Deref for GeneratorSavedLocals {
/// time. Generates a bitset for every local of all the other locals that may be
/// StorageLive simultaneously with that local. This is used in the layout
/// computation; see `GeneratorLayout` for more.
fn compute_storage_conflicts(
fn compute_storage_conflicts<'mir, 'tcx>(
body: &'mir Body<'tcx>,
saved_locals: &GeneratorSavedLocals,
always_live_locals: storage::AlwaysLiveLocals,
@ -672,7 +672,9 @@ struct StorageConflictVisitor<'mir, 'tcx, 's> {
local_conflicts: BitMatrix<Local, Local>,
}
impl rustc_mir_dataflow::ResultsVisitor<'mir, 'tcx> for StorageConflictVisitor<'mir, 'tcx, '_> {
impl<'mir, 'tcx> rustc_mir_dataflow::ResultsVisitor<'mir, 'tcx>
for StorageConflictVisitor<'mir, 'tcx, '_>
{
type FlowState = BitSet<Local>;
fn visit_statement_before_primary_effect(
@ -694,7 +696,7 @@ impl rustc_mir_dataflow::ResultsVisitor<'mir, 'tcx> for StorageConflictVisitor<'
}
}
impl<'body, 'tcx, 's> StorageConflictVisitor<'body, 'tcx, 's> {
impl StorageConflictVisitor<'_, '_, '_> {
fn apply_state(&mut self, flow_state: &BitSet<Local>, loc: Location) {
// Ignore unreachable blocks.
if self.body.basic_blocks()[loc.block].terminator().kind == TerminatorKind::Unreachable {
@ -1398,7 +1400,7 @@ impl EnsureGeneratorFieldAssignmentsNeverAlias<'_> {
self.saved_locals.get(place.local)
}
fn check_assigned_place(&mut self, place: Place<'tcx>, f: impl FnOnce(&mut Self)) {
fn check_assigned_place(&mut self, place: Place<'_>, f: impl FnOnce(&mut Self)) {
if let Some(assigned_local) = self.saved_local_for_direct_place(place) {
assert!(self.assigned_local.is_none(), "`check_assigned_place` must not recurse");
@ -1409,7 +1411,7 @@ impl EnsureGeneratorFieldAssignmentsNeverAlias<'_> {
}
}
impl Visitor<'tcx> for EnsureGeneratorFieldAssignmentsNeverAlias<'_> {
impl<'tcx> Visitor<'tcx> for EnsureGeneratorFieldAssignmentsNeverAlias<'_> {
fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, location: Location) {
let lhs = match self.assigned_local {
Some(l) => l,

View File

@ -57,7 +57,7 @@ impl<'tcx> MirPass<'tcx> for Inline {
}
}
fn inline(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) -> bool {
fn inline<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) -> bool {
let def_id = body.source.def_id();
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
@ -95,7 +95,7 @@ struct Inliner<'tcx> {
changed: bool,
}
impl Inliner<'tcx> {
impl<'tcx> Inliner<'tcx> {
fn process_blocks(&mut self, caller_body: &mut Body<'tcx>, blocks: Range<BasicBlock>) {
for bb in blocks {
let bb_data = &caller_body[bb];
@ -786,7 +786,7 @@ struct Integrator<'a, 'tcx> {
always_live_locals: BitSet<Local>,
}
impl<'a, 'tcx> Integrator<'a, 'tcx> {
impl Integrator<'_, '_> {
fn map_local(&self, local: Local) -> Local {
let new = if local == RETURN_PLACE {
self.destination.local
@ -815,7 +815,7 @@ impl<'a, 'tcx> Integrator<'a, 'tcx> {
}
}
impl<'a, 'tcx> MutVisitor<'tcx> for Integrator<'a, 'tcx> {
impl<'tcx> MutVisitor<'tcx> for Integrator<'_, 'tcx> {
fn tcx(&self) -> TyCtxt<'tcx> {
self.tcx
}

View File

@ -10,7 +10,7 @@ use rustc_session::Limit;
// FIXME: check whether it is cheaper to precompute the entire call graph instead of invoking
// this query riddiculously often.
#[instrument(level = "debug", skip(tcx, root, target))]
crate fn mir_callgraph_reachable(
crate fn mir_callgraph_reachable<'tcx>(
tcx: TyCtxt<'tcx>,
(root, target): (ty::Instance<'tcx>, LocalDefId),
) -> bool {
@ -33,7 +33,7 @@ crate fn mir_callgraph_reachable(
level = "debug",
skip(tcx, param_env, target, stack, seen, recursion_limiter, caller, recursion_limit)
)]
fn process(
fn process<'tcx>(
tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
caller: ty::Instance<'tcx>,

View File

@ -38,7 +38,7 @@ struct InstCombineContext<'tcx, 'a> {
local_decls: &'a LocalDecls<'tcx>,
}
impl<'tcx, 'a> InstCombineContext<'tcx, 'a> {
impl<'tcx> InstCombineContext<'tcx, '_> {
fn should_combine(&self, source_info: &SourceInfo, rvalue: &Rvalue<'tcx>) -> bool {
self.tcx.consider_optimizing(|| {
format!("InstCombine - Rvalue: {:?} SourceInfo: {:?}", rvalue, source_info)

View File

@ -1,7 +1,6 @@
#![feature(box_patterns)]
#![feature(box_syntax)]
#![feature(crate_visibility_modifier)]
#![feature(in_band_lifetimes)]
#![feature(iter_zip)]
#![feature(let_else)]
#![feature(map_try_insert)]
@ -150,7 +149,7 @@ fn mir_keys(tcx: TyCtxt<'_>, (): ()) -> FxHashSet<LocalDefId> {
tcx: TyCtxt<'tcx>,
set: &'a mut FxHashSet<LocalDefId>,
}
impl<'a, 'tcx> Visitor<'tcx> for GatherCtors<'a, 'tcx> {
impl<'tcx> Visitor<'tcx> for GatherCtors<'_, 'tcx> {
fn visit_variant_data(
&mut self,
v: &'tcx hir::VariantData<'tcx>,
@ -243,7 +242,7 @@ fn mir_const<'tcx>(
}
/// Compute the main MIR body and the list of MIR bodies of the promoteds.
fn mir_promoted(
fn mir_promoted<'tcx>(
tcx: TyCtxt<'tcx>,
def: ty::WithOptConstParam<LocalDefId>,
) -> (&'tcx Steal<Body<'tcx>>, &'tcx Steal<IndexVec<Promoted, Body<'tcx>>>) {
@ -480,8 +479,7 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
// FIXME(#70073): This pass is responsible for both optimization as well as some lints.
&const_prop::ConstProp,
//
// FIXME: The old pass manager ran this only at mir-opt-level >= 1, but
// const-prop runs unconditionally. Should this run unconditionally as well?
// Const-prop runs unconditionally, but doesn't mutate the MIR at mir-opt-level=0.
&o1(simplify_branches::SimplifyConstCondition::new("after-const-prop")),
&early_otherwise_branch::EarlyOtherwiseBranch,
&simplify_comparison_integral::SimplifyComparisonIntegral,

View File

@ -135,7 +135,7 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics {
}
}
fn resolve_rust_intrinsic(
fn resolve_rust_intrinsic<'tcx>(
tcx: TyCtxt<'tcx>,
func_ty: Ty<'tcx>,
) -> Option<(Symbol, SubstsRef<'tcx>)> {
@ -148,7 +148,7 @@ fn resolve_rust_intrinsic(
None
}
fn validate_simd_shuffle(tcx: TyCtxt<'tcx>, args: &[Operand<'tcx>], span: Span) {
fn validate_simd_shuffle<'tcx>(tcx: TyCtxt<'tcx>, args: &[Operand<'tcx>], span: Span) {
match &args[2] {
Operand::Constant(_) => {} // all good
_ => {

View File

@ -85,7 +85,7 @@ struct Patcher<'a, 'tcx> {
statement_idx: usize,
}
impl<'a, 'tcx> Patcher<'a, 'tcx> {
impl<'tcx> Patcher<'_, 'tcx> {
fn patch_expand_statement(
&mut self,
statement: &mut Statement<'tcx>,

View File

@ -165,7 +165,7 @@ struct RenameToReturnPlace<'tcx> {
}
/// Replaces all uses of `self.to_rename` with `_0`.
impl MutVisitor<'tcx> for RenameToReturnPlace<'tcx> {
impl<'tcx> MutVisitor<'tcx> for RenameToReturnPlace<'tcx> {
fn tcx(&self) -> TyCtxt<'tcx> {
self.tcx
}
@ -221,7 +221,7 @@ impl IsReturnPlaceRead {
}
}
impl Visitor<'tcx> for IsReturnPlaceRead {
impl<'tcx> Visitor<'tcx> for IsReturnPlaceRead {
fn visit_local(&mut self, &l: &Local, ctxt: PlaceContext, _: Location) {
if l == mir::RETURN_PLACE && ctxt.is_use() && !ctxt.is_place_assignment() {
self.0 = true;

View File

@ -28,7 +28,7 @@ pub trait MirLint<'tcx> {
#[derive(Debug, Clone)]
pub struct Lint<T>(pub T);
impl<T> MirPass<'tcx> for Lint<T>
impl<'tcx, T> MirPass<'tcx> for Lint<T>
where
T: MirLint<'tcx>,
{
@ -51,7 +51,7 @@ where
pub struct WithMinOptLevel<T>(pub u32, pub T);
impl<T> MirPass<'tcx> for WithMinOptLevel<T>
impl<'tcx, T> MirPass<'tcx> for WithMinOptLevel<T>
where
T: MirPass<'tcx>,
{
@ -72,7 +72,7 @@ where
}
}
pub fn run_passes(tcx: TyCtxt<'tcx>, body: &'mir mut Body<'tcx>, passes: &[&dyn MirPass<'tcx>]) {
pub fn run_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, passes: &[&dyn MirPass<'tcx>]) {
let start_phase = body.phase;
let mut cnt = 0;
@ -119,11 +119,11 @@ pub fn run_passes(tcx: TyCtxt<'tcx>, body: &'mir mut Body<'tcx>, passes: &[&dyn
}
}
pub fn validate_body(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, when: String) {
pub fn validate_body<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, when: String) {
validate::Validator { when, mir_phase: body.phase }.run_pass(tcx, body);
}
pub fn dump_mir(
pub fn dump_mir<'tcx>(
tcx: TyCtxt<'tcx>,
body: &Body<'tcx>,
phase: MirPhase,

View File

@ -86,7 +86,7 @@ impl<'tcx> MirPass<'tcx> for RemoveUninitDrops {
}
}
fn is_needs_drop_and_init(
fn is_needs_drop_and_init<'tcx>(
tcx: TyCtxt<'tcx>,
param_env: ParamEnv<'tcx>,
maybe_inits: &BitSet<MovePathIndex>,
@ -158,7 +158,7 @@ fn is_needs_drop_and_init(
}
}
fn variant_needs_drop(
fn variant_needs_drop<'tcx>(
tcx: TyCtxt<'tcx>,
param_env: ParamEnv<'tcx>,
substs: SubstsRef<'tcx>,

View File

@ -12,7 +12,7 @@ impl<'a, 'tcx> RequiredConstsVisitor<'a, 'tcx> {
}
}
impl<'a, 'tcx> Visitor<'tcx> for RequiredConstsVisitor<'a, 'tcx> {
impl<'tcx> Visitor<'tcx> for RequiredConstsVisitor<'_, 'tcx> {
fn visit_constant(&mut self, constant: &Constant<'tcx>, _: Location) {
if let Some(ct) = constant.literal.const_for_ty() {
if let ConstKind::Unevaluated(_) = ct.val {

View File

@ -59,7 +59,7 @@ impl<'tcx> MirPass<'tcx> for SeparateConstSwitch {
}
/// Returns the amount of blocks that were duplicated
pub fn separate_const_switch<'tcx>(body: &mut Body<'tcx>) -> usize {
pub fn separate_const_switch(body: &mut Body<'_>) -> usize {
let mut new_blocks: SmallVec<[(BasicBlock, BasicBlock); 6]> = SmallVec::new();
let predecessors = body.predecessors();
'block_iter: for (block_id, block) in body.basic_blocks().iter_enumerated() {

View File

@ -64,7 +64,19 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> Body<'
build_call_shim(tcx, instance, Some(Adjustment::RefMut), CallKind::Direct(call_mut))
}
ty::InstanceDef::DropGlue(def_id, ty) => build_drop_shim(tcx, def_id, ty),
ty::InstanceDef::DropGlue(def_id, ty) => {
// FIXME(#91576): Drop shims for generators aren't subject to the MIR passes at the end
// of this function. Is this intentional?
if let Some(ty::Generator(gen_def_id, substs, _)) = ty.map(ty::TyS::kind) {
let body = tcx.optimized_mir(*gen_def_id).generator_drop().unwrap();
let body = body.clone().subst(tcx, substs);
debug!("make_shim({:?}) = {:?}", instance, body);
return body;
}
build_drop_shim(tcx, def_id, ty)
}
ty::InstanceDef::CloneShim(def_id, ty) => build_clone_shim(tcx, def_id, ty),
ty::InstanceDef::Virtual(..) => {
bug!("InstanceDef::Virtual ({:?}) is for direct calls only", instance)
@ -75,14 +87,6 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> Body<'
};
debug!("make_shim({:?}) = untransformed {:?}", instance, result);
// In some of the above cases, we seem to be invoking the passes for non-shim MIR bodies.
// If that happens, there's no need to run them again.
//
// FIXME: Is this intentional?
if result.phase >= MirPhase::Const {
return result;
}
pm::run_passes(
tcx,
&mut result,
@ -140,11 +144,7 @@ fn local_decls_for_sig<'tcx>(
fn build_drop_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, ty: Option<Ty<'tcx>>) -> Body<'tcx> {
debug!("build_drop_shim(def_id={:?}, ty={:?})", def_id, ty);
// Check if this is a generator, if so, return the drop glue for it
if let Some(&ty::Generator(gen_def_id, substs, _)) = ty.map(|ty| ty.kind()) {
let body = tcx.optimized_mir(gen_def_id).generator_drop().unwrap();
return body.clone().subst(tcx, substs);
}
assert!(!matches!(ty, Some(ty) if ty.is_generator()));
let substs = if let Some(ty) = ty {
tcx.intern_substs(&[ty.into()])
@ -247,7 +247,7 @@ pub struct DropShimElaborator<'a, 'tcx> {
pub param_env: ty::ParamEnv<'tcx>,
}
impl<'a, 'tcx> fmt::Debug for DropShimElaborator<'a, 'tcx> {
impl fmt::Debug for DropShimElaborator<'_, '_> {
fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
Ok(())
}
@ -337,7 +337,7 @@ struct CloneShimBuilder<'tcx> {
sig: ty::FnSig<'tcx>,
}
impl CloneShimBuilder<'tcx> {
impl<'tcx> CloneShimBuilder<'tcx> {
fn new(tcx: TyCtxt<'tcx>, def_id: DefId, self_ty: Ty<'tcx>) -> Self {
// we must subst the self_ty because it's
// otherwise going to be TySelf and we can't index

View File

@ -47,7 +47,7 @@ impl SimplifyCfg {
}
}
pub fn simplify_cfg(tcx: TyCtxt<'tcx>, body: &mut Body<'_>) {
pub fn simplify_cfg<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
CfgSimplifier::new(body).simplify();
remove_dead_blocks(tcx, body);
@ -262,7 +262,7 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> {
}
}
pub fn remove_dead_blocks(tcx: TyCtxt<'tcx>, body: &mut Body<'_>) {
pub fn remove_dead_blocks<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
let reachable = traversal::reachable_as_bitset(body);
let num_blocks = body.basic_blocks().len();
if num_blocks == reachable.count() {
@ -454,7 +454,7 @@ impl UsedLocals {
}
/// Updates the use counts to reflect the removal of given statement.
fn statement_removed(&mut self, statement: &Statement<'tcx>) {
fn statement_removed(&mut self, statement: &Statement<'_>) {
self.increment = false;
// The location of the statement is irrelevant.
@ -463,7 +463,7 @@ impl UsedLocals {
}
/// Visits a left-hand side of an assignment.
fn visit_lhs(&mut self, place: &Place<'tcx>, location: Location) {
fn visit_lhs(&mut self, place: &Place<'_>, location: Location) {
if place.is_indirect() {
// A use, not a definition.
self.visit_place(place, PlaceContext::MutatingUse(MutatingUseContext::Store), location);
@ -480,7 +480,7 @@ impl UsedLocals {
}
}
impl Visitor<'_> for UsedLocals {
impl<'tcx> Visitor<'tcx> for UsedLocals {
fn visit_statement(&mut self, statement: &Statement<'tcx>, location: Location) {
match statement.kind {
StatementKind::LlvmInlineAsm(..)
@ -518,7 +518,7 @@ impl Visitor<'_> for UsedLocals {
}
/// Removes unused definitions. Updates the used locals to reflect the changes made.
fn remove_unused_definitions<'a, 'tcx>(used_locals: &'a mut UsedLocals, body: &mut Body<'tcx>) {
fn remove_unused_definitions(used_locals: &mut UsedLocals, body: &mut Body<'_>) {
// The use counts are updated as we remove the statements. A local might become unused
// during the retain operation, leading to a temporary inconsistency (storage statements or
// definitions referencing the local might remain). For correctness it is crucial that this

View File

@ -148,7 +148,7 @@ struct OptimizationFinder<'a, 'tcx> {
body: &'a Body<'tcx>,
}
impl<'a, 'tcx> OptimizationFinder<'a, 'tcx> {
impl<'tcx> OptimizationFinder<'_, 'tcx> {
fn find_optimizations(&self) -> Vec<OptimizationInfo<'tcx>> {
self.body
.basic_blocks()

View File

@ -102,7 +102,7 @@ fn get_arm_identity_info<'a, 'tcx>(
type StmtIter<'a, 'tcx> = Peekable<Enumerate<Iter<'a, Statement<'tcx>>>>;
fn is_storage_stmt<'tcx>(stmt: &Statement<'tcx>) -> bool {
fn is_storage_stmt(stmt: &Statement<'_>) -> bool {
matches!(stmt.kind, StatementKind::StorageLive(_) | StatementKind::StorageDead(_))
}
@ -122,8 +122,8 @@ fn get_arm_identity_info<'a, 'tcx>(
/// Eats consecutive `StorageLive` and `StorageDead` Statements.
/// The iterator `stmt_iter` is not advanced if none were found.
fn try_eat_storage_stmts<'a, 'tcx>(
stmt_iter: &mut StmtIter<'a, 'tcx>,
fn try_eat_storage_stmts(
stmt_iter: &mut StmtIter<'_, '_>,
storage_live_stmts: &mut Vec<(usize, Local)>,
storage_dead_stmts: &mut Vec<(usize, Local)>,
) {
@ -136,7 +136,7 @@ fn get_arm_identity_info<'a, 'tcx>(
})
}
fn is_tmp_storage_stmt<'tcx>(stmt: &Statement<'tcx>) -> bool {
fn is_tmp_storage_stmt(stmt: &Statement<'_>) -> bool {
use rustc_middle::mir::StatementKind::Assign;
if let Assign(box (place, Rvalue::Use(Operand::Copy(p) | Operand::Move(p)))) = &stmt.kind {
place.as_local().is_some() && p.as_local().is_some()
@ -147,8 +147,8 @@ fn get_arm_identity_info<'a, 'tcx>(
/// Eats consecutive `Assign` Statements.
// The iterator `stmt_iter` is not advanced if none were found.
fn try_eat_assign_tmp_stmts<'a, 'tcx>(
stmt_iter: &mut StmtIter<'a, 'tcx>,
fn try_eat_assign_tmp_stmts(
stmt_iter: &mut StmtIter<'_, '_>,
tmp_assigns: &mut Vec<(Local, Local)>,
nop_stmts: &mut Vec<usize>,
) {
@ -163,9 +163,9 @@ fn get_arm_identity_info<'a, 'tcx>(
})
}
fn find_storage_live_dead_stmts_for_local<'tcx>(
fn find_storage_live_dead_stmts_for_local(
local: Local,
stmts: &[Statement<'tcx>],
stmts: &[Statement<'_>],
) -> Option<(usize, usize)> {
trace!("looking for {:?}", local);
let mut storage_live_stmt = None;
@ -452,14 +452,14 @@ struct LocalUseCounter {
}
impl LocalUseCounter {
fn get_local_uses<'tcx>(body: &Body<'tcx>) -> IndexVec<Local, usize> {
fn get_local_uses(body: &Body<'_>) -> IndexVec<Local, usize> {
let mut counter = LocalUseCounter { local_uses: IndexVec::from_elem(0, &body.local_decls) };
counter.visit_body(body);
counter.local_uses
}
}
impl<'tcx> Visitor<'tcx> for LocalUseCounter {
impl Visitor<'_> for LocalUseCounter {
fn visit_local(&mut self, local: &Local, context: PlaceContext, _location: Location) {
if context.is_storage_marker()
|| context == PlaceContext::NonUse(NonUseContext::VarDebugInfo)
@ -510,7 +510,7 @@ fn match_set_variant_field<'tcx>(stmt: &Statement<'tcx>) -> Option<(Local, Local
/// ```rust
/// discriminant(_LOCAL_TO_SET) = VAR_IDX;
/// ```
fn match_set_discr<'tcx>(stmt: &Statement<'tcx>) -> Option<(Local, VariantIdx)> {
fn match_set_discr(stmt: &Statement<'_>) -> Option<(Local, VariantIdx)> {
match &stmt.kind {
StatementKind::SetDiscriminant { place, variant_index } => {
Some((place.as_local()?, *variant_index))
@ -588,7 +588,7 @@ struct SimplifyBranchSameOptimizationFinder<'a, 'tcx> {
tcx: TyCtxt<'tcx>,
}
impl<'a, 'tcx> SimplifyBranchSameOptimizationFinder<'a, 'tcx> {
impl<'tcx> SimplifyBranchSameOptimizationFinder<'_, 'tcx> {
fn find(&self) -> Vec<SimplifyBranchSameOptimization> {
self.body
.basic_blocks()

View File

@ -64,7 +64,7 @@ impl MirPass<'_> for UnreachablePropagation {
}
}
fn remove_successors<F>(
fn remove_successors<'tcx, F>(
terminator_kind: &TerminatorKind<'tcx>,
predicate: F,
) -> Option<TerminatorKind<'tcx>>

View File

@ -1,4 +1,4 @@
use super::{AttrWrapper, Capturing, ForceCollect, Parser, PathStyle};
use super::{AttrWrapper, Capturing, FnParseMode, ForceCollect, Parser, PathStyle};
use rustc_ast as ast;
use rustc_ast::attr;
use rustc_ast::token::{self, Nonterminal};
@ -177,7 +177,7 @@ impl<'a> Parser<'a> {
AttrWrapper::empty(),
true,
false,
|_| true,
FnParseMode { req_name: |_| true, req_body: true },
ForceCollect::No,
) {
Ok(Some(item)) => {

View File

@ -1129,7 +1129,8 @@ impl<'a> Parser<'a> {
}
pub fn maybe_consume_incorrect_semicolon(&mut self, items: &[P<Item>]) -> bool {
if self.eat(&token::Semi) {
if self.token.kind == TokenKind::Semi {
self.bump();
let mut err = self.struct_span_err(self.prev_token.span, "expected item, found `;`");
err.span_suggestion_short(
self.prev_token.span,

View File

@ -78,16 +78,17 @@ pub(super) type ItemInfo = (Ident, ItemKind);
impl<'a> Parser<'a> {
pub fn parse_item(&mut self, force_collect: ForceCollect) -> PResult<'a, Option<P<Item>>> {
self.parse_item_(|_| true, force_collect).map(|i| i.map(P))
let fn_parse_mode = FnParseMode { req_name: |_| true, req_body: true };
self.parse_item_(fn_parse_mode, force_collect).map(|i| i.map(P))
}
fn parse_item_(
&mut self,
req_name: ReqName,
fn_parse_mode: FnParseMode,
force_collect: ForceCollect,
) -> PResult<'a, Option<Item>> {
let attrs = self.parse_outer_attributes()?;
self.parse_item_common(attrs, true, false, req_name, force_collect)
self.parse_item_common(attrs, true, false, fn_parse_mode, force_collect)
}
pub(super) fn parse_item_common(
@ -95,7 +96,7 @@ impl<'a> Parser<'a> {
attrs: AttrWrapper,
mac_allowed: bool,
attrs_allowed: bool,
req_name: ReqName,
fn_parse_mode: FnParseMode,
force_collect: ForceCollect,
) -> PResult<'a, Option<Item>> {
// Don't use `maybe_whole` so that we have precise control
@ -113,7 +114,8 @@ impl<'a> Parser<'a> {
let mut unclosed_delims = vec![];
let item =
self.collect_tokens_trailing_token(attrs, force_collect, |this: &mut Self, attrs| {
let item = this.parse_item_common_(attrs, mac_allowed, attrs_allowed, req_name);
let item =
this.parse_item_common_(attrs, mac_allowed, attrs_allowed, fn_parse_mode);
unclosed_delims.append(&mut this.unclosed_delims);
Ok((item?, TrailingToken::None))
})?;
@ -127,12 +129,13 @@ impl<'a> Parser<'a> {
mut attrs: Vec<Attribute>,
mac_allowed: bool,
attrs_allowed: bool,
req_name: ReqName,
fn_parse_mode: FnParseMode,
) -> PResult<'a, Option<Item>> {
let lo = self.token.span;
let vis = self.parse_visibility(FollowedByType::No)?;
let mut def = self.parse_defaultness();
let kind = self.parse_item_kind(&mut attrs, mac_allowed, lo, &vis, &mut def, req_name)?;
let kind =
self.parse_item_kind(&mut attrs, mac_allowed, lo, &vis, &mut def, fn_parse_mode)?;
if let Some((ident, kind)) = kind {
self.error_on_unconsumed_default(def, &kind);
let span = lo.to(self.prev_token.span);
@ -192,7 +195,7 @@ impl<'a> Parser<'a> {
lo: Span,
vis: &Visibility,
def: &mut Defaultness,
req_name: ReqName,
fn_parse_mode: FnParseMode,
) -> PResult<'a, Option<ItemInfo>> {
let def_final = def == &Defaultness::Final;
let mut def = || mem::replace(def, Defaultness::Final);
@ -219,7 +222,7 @@ impl<'a> Parser<'a> {
(Ident::empty(), ItemKind::Use(tree))
} else if self.check_fn_front_matter(def_final) {
// FUNCTION ITEM
let (ident, sig, generics, body) = self.parse_fn(attrs, req_name, lo)?;
let (ident, sig, generics, body) = self.parse_fn(attrs, fn_parse_mode, lo)?;
(ident, ItemKind::Fn(Box::new(Fn { defaultness: def(), sig, generics, body })))
} else if self.eat_keyword(kw::Extern) {
if self.eat_keyword(kw::Crate) {
@ -733,23 +736,26 @@ impl<'a> Parser<'a> {
&mut self,
force_collect: ForceCollect,
) -> PResult<'a, Option<Option<P<AssocItem>>>> {
self.parse_assoc_item(|_| true, force_collect)
let fn_parse_mode = FnParseMode { req_name: |_| true, req_body: true };
self.parse_assoc_item(fn_parse_mode, force_collect)
}
pub fn parse_trait_item(
&mut self,
force_collect: ForceCollect,
) -> PResult<'a, Option<Option<P<AssocItem>>>> {
self.parse_assoc_item(|edition| edition >= Edition::Edition2018, force_collect)
let fn_parse_mode =
FnParseMode { req_name: |edition| edition >= Edition::Edition2018, req_body: false };
self.parse_assoc_item(fn_parse_mode, force_collect)
}
/// Parses associated items.
fn parse_assoc_item(
&mut self,
req_name: ReqName,
fn_parse_mode: FnParseMode,
force_collect: ForceCollect,
) -> PResult<'a, Option<Option<P<AssocItem>>>> {
Ok(self.parse_item_(req_name, force_collect)?.map(
Ok(self.parse_item_(fn_parse_mode, force_collect)?.map(
|Item { attrs, id, span, vis, ident, kind, tokens }| {
let kind = match AssocItemKind::try_from(kind) {
Ok(kind) => kind,
@ -944,7 +950,8 @@ impl<'a> Parser<'a> {
&mut self,
force_collect: ForceCollect,
) -> PResult<'a, Option<Option<P<ForeignItem>>>> {
Ok(self.parse_item_(|_| true, force_collect)?.map(
let fn_parse_mode = FnParseMode { req_name: |_| true, req_body: false };
Ok(self.parse_item_(fn_parse_mode, force_collect)?.map(
|Item { attrs, id, span, vis, ident, kind, tokens }| {
let kind = match ForeignItemKind::try_from(kind) {
Ok(kind) => kind,
@ -1484,7 +1491,8 @@ impl<'a> Parser<'a> {
if !is_raw && ident.is_reserved() {
let err = if self.check_fn_front_matter(false) {
// We use `parse_fn` to get a span for the function
if let Err(mut db) = self.parse_fn(&mut Vec::new(), |_| true, lo) {
let fn_parse_mode = FnParseMode { req_name: |_| true, req_body: true };
if let Err(mut db) = self.parse_fn(&mut Vec::new(), fn_parse_mode, lo) {
db.delay_as_bug();
}
let mut err = self.struct_span_err(
@ -1698,25 +1706,82 @@ impl<'a> Parser<'a> {
/// The parsing configuration used to parse a parameter list (see `parse_fn_params`).
///
/// The function decides if, per-parameter `p`, `p` must have a pattern or just a type.
///
/// This function pointer accepts an edition, because in edition 2015, trait declarations
/// were allowed to omit parameter names. In 2018, they became required.
type ReqName = fn(Edition) -> bool;
/// Parsing configuration for functions.
///
/// The syntax of function items is slightly different within trait definitions,
/// impl blocks, and modules. It is still parsed using the same code, just with
/// different flags set, so that even when the input is wrong and produces a parse
/// error, it still gets into the AST and the rest of the parser and
/// type checker can run.
#[derive(Clone, Copy)]
pub(crate) struct FnParseMode {
/// A function pointer that decides if, per-parameter `p`, `p` must have a
/// pattern or just a type. This field affects parsing of the parameters list.
///
/// ```text
/// fn foo(alef: A) -> X { X::new() }
/// -----^^ affects parsing this part of the function signature
/// |
/// if req_name returns false, then this name is optional
///
/// fn bar(A) -> X;
/// ^
/// |
/// if req_name returns true, this is an error
/// ```
///
/// Calling this function pointer should only return false if:
///
/// * The item is being parsed inside of a trait definition.
/// Within an impl block or a module, it should always evaluate
/// to true.
/// * The span is from Edition 2015. In particular, you can get a
/// 2015 span inside a 2021 crate using macros.
pub req_name: ReqName,
/// If this flag is set to `true`, then plain, semicolon-terminated function
/// prototypes are not allowed here.
///
/// ```text
/// fn foo(alef: A) -> X { X::new() }
/// ^^^^^^^^^^^^
/// |
/// this is always allowed
///
/// fn bar(alef: A, bet: B) -> X;
/// ^
/// |
/// if req_body is set to true, this is an error
/// ```
///
/// This field should only be set to false if the item is inside of a trait
/// definition or extern block. Within an impl block or a module, it should
/// always be set to true.
pub req_body: bool,
}
/// Parsing of functions and methods.
impl<'a> Parser<'a> {
/// Parse a function starting from the front matter (`const ...`) to the body `{ ... }` or `;`.
fn parse_fn(
&mut self,
attrs: &mut Vec<Attribute>,
req_name: ReqName,
fn_parse_mode: FnParseMode,
sig_lo: Span,
) -> PResult<'a, (Ident, FnSig, Generics, Option<P<Block>>)> {
let header = self.parse_fn_front_matter()?; // `const ... fn`
let ident = self.parse_ident()?; // `foo`
let mut generics = self.parse_generics()?; // `<'a, T, ...>`
let decl = self.parse_fn_decl(req_name, AllowPlus::Yes, RecoverReturnSign::Yes)?; // `(p: u8, ...)`
let decl =
self.parse_fn_decl(fn_parse_mode.req_name, AllowPlus::Yes, RecoverReturnSign::Yes)?; // `(p: u8, ...)`
generics.where_clause = self.parse_where_clause()?; // `where T: Ord`
let mut sig_hi = self.prev_token.span;
let body = self.parse_fn_body(attrs, &ident, &mut sig_hi)?; // `;` or `{ ... }`.
let body = self.parse_fn_body(attrs, &ident, &mut sig_hi, fn_parse_mode.req_body)?; // `;` or `{ ... }`.
let fn_sig_span = sig_lo.to(sig_hi);
Ok((ident, FnSig { header, decl, span: fn_sig_span }, generics, body))
}
@ -1729,9 +1794,17 @@ impl<'a> Parser<'a> {
attrs: &mut Vec<Attribute>,
ident: &Ident,
sig_hi: &mut Span,
req_body: bool,
) -> PResult<'a, Option<P<Block>>> {
let (inner_attrs, body) = if self.eat(&token::Semi) {
let has_semi = if req_body {
self.token.kind == TokenKind::Semi
} else {
// Only include `;` in list of expected tokens if body is not required
self.check(&TokenKind::Semi)
};
let (inner_attrs, body) = if has_semi {
// Include the trailing semicolon in the span of the signature
self.expect_semi()?;
*sig_hi = self.prev_token.span;
(Vec::new(), None)
} else if self.check(&token::OpenDelim(token::Brace)) || self.token.is_whole_block() {
@ -1752,9 +1825,12 @@ impl<'a> Parser<'a> {
.emit();
(Vec::new(), Some(self.mk_block_err(span)))
} else {
if let Err(mut err) =
self.expected_one_of_not_found(&[], &[token::Semi, token::OpenDelim(token::Brace)])
{
let expected = if req_body {
&[token::OpenDelim(token::Brace)][..]
} else {
&[token::Semi, token::OpenDelim(token::Brace)]
};
if let Err(mut err) = self.expected_one_of_not_found(&[], &expected) {
if self.token.kind == token::CloseDelim(token::Brace) {
// The enclosing `mod`, `trait` or `impl` is being closed, so keep the `fn` in
// the AST for typechecking.

View File

@ -14,6 +14,7 @@ use crate::lexer::UnmatchedBrace;
pub use attr_wrapper::AttrWrapper;
pub use diagnostics::AttemptLocalParseRecovery;
use diagnostics::Error;
pub(crate) use item::FnParseMode;
pub use pat::{RecoverColon, RecoverComma};
pub use path::PathStyle;

View File

@ -4,7 +4,9 @@ use super::expr::LhsExpr;
use super::pat::RecoverComma;
use super::path::PathStyle;
use super::TrailingToken;
use super::{AttrWrapper, BlockMode, ForceCollect, Parser, Restrictions, SemiColonMode};
use super::{
AttrWrapper, BlockMode, FnParseMode, ForceCollect, Parser, Restrictions, SemiColonMode,
};
use crate::maybe_whole;
use rustc_ast as ast;
@ -79,9 +81,13 @@ impl<'a> Parser<'a> {
} else {
self.parse_stmt_path_start(lo, attrs)
}?
} else if let Some(item) =
self.parse_item_common(attrs.clone(), false, true, |_| true, force_collect)?
{
} else if let Some(item) = self.parse_item_common(
attrs.clone(),
false,
true,
FnParseMode { req_name: |_| true, req_body: true },
force_collect,
)? {
// FIXME: Bad copy of attrs
self.mk_stmt(lo.to(item.span), StmtKind::Item(P(item)))
} else if self.eat(&token::Semi) {

View File

@ -81,9 +81,9 @@
//! [`OsStr`] and Rust strings work similarly to those for [`CString`]
//! and [`CStr`].
//!
//! * [`OsString`] represents an owned string in whatever
//! representation the operating system prefers. In the Rust standard
//! library, various APIs that transfer strings to/from the operating
//! * [`OsString`] losslessly represents an owned platform string. However, this
//! representation is not necessarily in a form native to the platform.
//! In the Rust standard library, various APIs that transfer strings to/from the operating
//! system use [`OsString`] instead of plain strings. For example,
//! [`env::var_os()`] is used to query environment variables; it
//! returns an <code>[Option]<[OsString]></code>. If the environment variable
@ -92,9 +92,9 @@
//! your code can detect errors in case the environment variable did
//! not in fact contain valid Unicode data.
//!
//! * [`OsStr`] represents a borrowed reference to a string in a
//! format that can be passed to the operating system. It can be
//! converted into a UTF-8 Rust string slice in a similar way to
//! * [`OsStr`] losslessly represents a borrowed reference to a platform string.
//! However, this representation is not necessarily in a form native to the platform.
//! It can be converted into a UTF-8 Rust string slice in a similar way to
//! [`OsString`].
//!
//! # Conversions
@ -113,16 +113,19 @@
//!
//! ## On Windows
//!
//! An [`OsStr`] can be losslessly converted to a native Windows string. And
//! a native Windows string can be losslessly converted to an [`OsString`].
//!
//! On Windows, [`OsStr`] implements the
//! <code>std::os::windows::ffi::[OsStrExt][windows.OsStrExt]</code> trait,
//! which provides an [`encode_wide`] method. This provides an
//! iterator that can be [`collect`]ed into a vector of [`u16`].
//! iterator that can be [`collect`]ed into a vector of [`u16`]. After a nul
//! characters is appended, this is the same as a native Windows string.
//!
//! Additionally, on Windows [`OsString`] implements the
//! <code>std::os::windows:ffi::[OsStringExt][windows.OsStringExt]</code>
//! trait, which provides a [`from_wide`] method. The result of this
//! method is an [`OsString`] which can be round-tripped to a Windows
//! string losslessly.
//! trait, which provides a [`from_wide`] method to convert a native Windows
//! string (without the terminating nul character) to an [`OsString`].
//!
//! [Unicode scalar value]: https://www.unicode.org/glossary/#unicode_scalar_value
//! [Unicode code point]: https://www.unicode.org/glossary/#code_point

View File

@ -1,5 +1,18 @@
FROM ubuntu:20.04
RUN apt-get update && \
apt-get install -y --no-install-recommends \
curl \
ca-certificates
WORKDIR /tmp
RUN curl -f https://curl.se/ca/cacert.pem -o cacert.pem
FROM ubuntu:16.04
# The ca-certificates in ubuntu-16 is too old, so update the certificates
# with something more recent.
COPY --from=0 /tmp/cacert.pem /tmp/cacert.pem
ENV CURL_CA_BUNDLE /tmp/cacert.pem
COPY scripts/cross-apt-packages.sh /scripts/
RUN sh /scripts/cross-apt-packages.sh

View File

@ -1,5 +1,18 @@
FROM ubuntu:20.04
RUN apt-get update && \
apt-get install -y --no-install-recommends \
curl \
ca-certificates
WORKDIR /tmp
RUN curl -f https://curl.se/ca/cacert.pem -o cacert.pem
FROM ubuntu:16.04
# The ca-certificates in ubuntu-16 is too old, so update the certificates
# with something more recent.
COPY --from=0 /tmp/cacert.pem /tmp/cacert.pem
ENV CURL_CA_BUNDLE /tmp/cacert.pem
COPY scripts/cross-apt-packages.sh /scripts/
RUN sh /scripts/cross-apt-packages.sh

View File

@ -1,5 +1,18 @@
FROM ubuntu:20.04
RUN apt-get update && \
apt-get install -y --no-install-recommends \
curl \
ca-certificates
WORKDIR /tmp
RUN curl -f https://curl.se/ca/cacert.pem -o cacert.pem
FROM ubuntu:16.04
# The ca-certificates in ubuntu-16 is too old, so update the certificates
# with something more recent.
COPY --from=0 /tmp/cacert.pem /tmp/cacert.pem
ENV CURL_CA_BUNDLE /tmp/cacert.pem
COPY scripts/cross-apt-packages.sh /scripts/
RUN sh /scripts/cross-apt-packages.sh

View File

@ -1,5 +1,18 @@
FROM ubuntu:20.04
RUN apt-get update && \
apt-get install -y --no-install-recommends \
curl \
ca-certificates
WORKDIR /tmp
RUN curl -f https://curl.se/ca/cacert.pem -o cacert.pem
FROM ubuntu:16.04
# The ca-certificates in ubuntu-16 is too old, so update the certificates
# with something more recent.
COPY --from=0 /tmp/cacert.pem /tmp/cacert.pem
ENV CURL_CA_BUNDLE /tmp/cacert.pem
COPY scripts/cross-apt-packages.sh /scripts/
RUN sh /scripts/cross-apt-packages.sh

View File

@ -1,6 +0,0 @@
// no-prefer-dynamic
// compile-flags: --cfg foo
#![cfg_attr(foo, crate_type="lib")]
pub fn foo() {}

View File

@ -1,6 +0,0 @@
// run-pass
// aux-build:crate-attributes-using-cfg_attr.rs
extern crate crate_attributes_using_cfg_attr;
pub fn main() {}

View File

@ -0,0 +1,12 @@
// check-fail
// compile-flags:--cfg foo
#![deny(warnings)]
#![cfg_attr(foo, crate_type="bin")]
//~^ERROR `crate_type` within
//~| WARN this was previously accepted
#![cfg_attr(foo, crate_name="bar")]
//~^ERROR `crate_name` within
//~| WARN this was previously accepted
fn main() {}

View File

@ -0,0 +1,26 @@
error: `crate_type` within an `#![cfg_attr] attribute is deprecated`
--> $DIR/future-compat-crate-attributes-using-cfg_attr.rs:5:18
|
LL | #![cfg_attr(foo, crate_type="bin")]
| ^^^^^^^^^^^^^^^^
|
note: the lint level is defined here
--> $DIR/future-compat-crate-attributes-using-cfg_attr.rs:4:9
|
LL | #![deny(warnings)]
| ^^^^^^^^
= note: `#[deny(deprecated_cfg_attr_crate_type_name)]` implied by `#[deny(warnings)]`
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #91632 <https://github.com/rust-lang/rust/issues/91632>
error: `crate_name` within an `#![cfg_attr] attribute is deprecated`
--> $DIR/future-compat-crate-attributes-using-cfg_attr.rs:8:18
|
LL | #![cfg_attr(foo, crate_name="bar")]
| ^^^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #91632 <https://github.com/rust-lang/rust/issues/91632>
error: aborting due to 2 previous errors

View File

@ -0,0 +1,34 @@
// Regression test for issue #90870.
// run-rustfix
#![allow(dead_code)]
const fn f(a: &u8, b: &u8) -> bool {
*a == *b
//~^ ERROR: calls in constant functions are limited to constant functions, tuple structs and tuple variants [E0015]
//~| HELP: consider dereferencing here
}
const fn g(a: &&&&i64, b: &&&&i64) -> bool {
****a == ****b
//~^ ERROR: calls in constant functions are limited to constant functions, tuple structs and tuple variants [E0015]
//~| HELP: consider dereferencing here
}
const fn h(mut a: &[u8], mut b: &[u8]) -> bool {
while let ([l, at @ ..], [r, bt @ ..]) = (a, b) {
if *l == *r {
//~^ ERROR: calls in constant functions are limited to constant functions, tuple structs and tuple variants [E0015]
//~| HELP: consider dereferencing here
a = at;
b = bt;
} else {
return false;
}
}
a.is_empty() && b.is_empty()
}
fn main() {}

View File

@ -0,0 +1,34 @@
// Regression test for issue #90870.
// run-rustfix
#![allow(dead_code)]
const fn f(a: &u8, b: &u8) -> bool {
a == b
//~^ ERROR: calls in constant functions are limited to constant functions, tuple structs and tuple variants [E0015]
//~| HELP: consider dereferencing here
}
const fn g(a: &&&&i64, b: &&&&i64) -> bool {
a == b
//~^ ERROR: calls in constant functions are limited to constant functions, tuple structs and tuple variants [E0015]
//~| HELP: consider dereferencing here
}
const fn h(mut a: &[u8], mut b: &[u8]) -> bool {
while let ([l, at @ ..], [r, bt @ ..]) = (a, b) {
if l == r {
//~^ ERROR: calls in constant functions are limited to constant functions, tuple structs and tuple variants [E0015]
//~| HELP: consider dereferencing here
a = at;
b = bt;
} else {
return false;
}
}
a.is_empty() && b.is_empty()
}
fn main() {}

View File

@ -0,0 +1,36 @@
error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants
--> $DIR/issue-90870.rs:8:5
|
LL | a == b
| ^^^^^^
|
help: consider dereferencing here
|
LL | *a == *b
| + +
error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants
--> $DIR/issue-90870.rs:14:5
|
LL | a == b
| ^^^^^^
|
help: consider dereferencing here
|
LL | ****a == ****b
| ++++ ++++
error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants
--> $DIR/issue-90870.rs:21:12
|
LL | if l == r {
| ^^^^^^
|
help: consider dereferencing here
|
LL | if *l == *r {
| + +
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0015`.

View File

@ -3,6 +3,6 @@
fn foo() => impl Fn() => bool {
//~^ ERROR return types are denoted using `->`
//~| ERROR expected one of `+`, `->`, `::`, `;`, `where`, or `{`, found `=>`
//~| ERROR expected one of `+`, `->`, `::`, `where`, or `{`, found `=>`
unimplemented!()
}

View File

@ -4,11 +4,11 @@ error: return types are denoted using `->`
LL | fn foo() => impl Fn() => bool {
| ^^ help: use `->` instead
error: expected one of `+`, `->`, `::`, `;`, `where`, or `{`, found `=>`
error: expected one of `+`, `->`, `::`, `where`, or `{`, found `=>`
--> $DIR/fn-recover-return-sign2.rs:4:23
|
LL | fn foo() => impl Fn() => bool {
| ^^ expected one of `+`, `->`, `::`, `;`, `where`, or `{`
| ^^ expected one of `+`, `->`, `::`, `where`, or `{`
error: aborting due to 2 previous errors

View File

@ -2,7 +2,7 @@
// to happen in #24780. For example, following should be an error:
// expected one of ..., `>`, ... found `>`.
fn foo() -> Vec<usize>> { //~ ERROR expected one of `!`, `+`, `::`, `;`, `where`, or `{`, found `>`
fn foo() -> Vec<usize>> { //~ ERROR expected one of `!`, `+`, `::`, `where`, or `{`, found `>`
Vec::new()
}

View File

@ -1,8 +1,8 @@
error: expected one of `!`, `+`, `::`, `;`, `where`, or `{`, found `>`
error: expected one of `!`, `+`, `::`, `where`, or `{`, found `>`
--> $DIR/issue-24780.rs:5:23
|
LL | fn foo() -> Vec<usize>> {
| ^ expected one of `!`, `+`, `::`, `;`, `where`, or `{`
| ^ expected one of `!`, `+`, `::`, `where`, or `{`
error: aborting due to previous error

View File

@ -2,7 +2,7 @@ impl A {
//~^ ERROR cannot find type `A` in this scope
fn b(self>
//~^ ERROR expected one of `)`, `,`, or `:`, found `>`
//~| ERROR expected one of `->`, `;`, `where`, or `{`, found `>`
//~| ERROR expected one of `->`, `where`, or `{`, found `>`
}
fn main() {}

View File

@ -6,14 +6,14 @@ LL | fn b(self>
| |
| unclosed delimiter
error: expected one of `->`, `;`, `where`, or `{`, found `>`
error: expected one of `->`, `where`, or `{`, found `>`
--> $DIR/issue-58856-1.rs:3:14
|
LL | impl A {
| - while parsing this item list starting here
LL |
LL | fn b(self>
| ^ expected one of `->`, `;`, `where`, or `{`
| ^ expected one of `->`, `where`, or `{`
...
LL | }
| - the item list ends here

View File

@ -13,11 +13,11 @@ LL | fn f(t:for<>t?)
| expected one of `(`, `)`, `+`, `,`, `::`, or `<`
| help: missing `,`
error: expected one of `->`, `;`, `where`, or `{`, found `<eof>`
error: expected one of `->`, `where`, or `{`, found `<eof>`
--> $DIR/issue-84148-1.rs:1:15
|
LL | fn f(t:for<>t?)
| ^ expected one of `->`, `;`, `where`, or `{`
| ^ expected one of `->`, `where`, or `{`
error: aborting due to 3 previous errors

View File

@ -21,11 +21,11 @@ LL | fn f(t:for<>t?
| expected one of `(`, `)`, `+`, `,`, `::`, or `<`
| help: missing `,`
error: expected one of `->`, `;`, `where`, or `{`, found `<eof>`
error: expected one of `->`, `where`, or `{`, found `<eof>`
--> $DIR/issue-84148-2.rs:4:16
|
LL | fn f(t:for<>t?
| ^ expected one of `->`, `;`, `where`, or `{`
| ^ expected one of `->`, `where`, or `{`
error: aborting due to 4 previous errors

View File

@ -2,8 +2,8 @@ struct Foo {}
impl Foo {
pub fn bar()
//~^ ERROR: expected `;`, found `}`
//~| ERROR: associated function in `impl` without body
//~^ ERROR: associated function in `impl` without body
}
//~^ERROR expected one of `->`, `where`, or `{`, found `}`
fn main() {}

View File

@ -1,11 +1,13 @@
error: expected `;`, found `}`
--> $DIR/issue-87635.rs:4:17
error: expected one of `->`, `where`, or `{`, found `}`
--> $DIR/issue-87635.rs:6:1
|
LL | pub fn bar()
| ^ help: add `;` here
...
| --- - expected one of `->`, `where`, or `{`
| |
| while parsing this `fn`
LL |
LL | }
| - unexpected token
| ^ unexpected token
error: associated function in `impl` without body
--> $DIR/issue-87635.rs:4:5

View File

@ -22,11 +22,11 @@ error: expected one of `:` or `|`, found `)`
LL | fn main((ؼ
| ^ expected one of `:` or `|`
error: expected one of `->`, `;`, `where`, or `{`, found `<eof>`
error: expected one of `->`, `where`, or `{`, found `<eof>`
--> $DIR/missing_right_paren.rs:3:11
|
LL | fn main((ؼ
| ^ expected one of `->`, `;`, `where`, or `{`
| ^ expected one of `->`, `where`, or `{`
error: aborting due to 4 previous errors

View File

@ -0,0 +1,9 @@
// run-rustfix
#[allow(dead_code)]
extern "C" {
fn foo(); //~ERROR expected `;`
}
fn main() {}

View File

@ -0,0 +1,9 @@
// run-rustfix
#[allow(dead_code)]
extern "C" {
fn foo() //~ERROR expected `;`
}
fn main() {}

View File

@ -0,0 +1,10 @@
error: expected `;`, found `}`
--> $DIR/suggest-semicolon-for-fn-in-extern-block.rs:6:11
|
LL | fn foo()
| ^ help: add `;` here
LL | }
| - unexpected token
error: aborting due to previous error