1
Fork 0

Auto merge of #136878 - matthiaskrgr:rollup-opilhjv, r=matthiaskrgr

Rollup of 8 pull requests

Successful merges:

 - #135285 (it-self → itself, build-system → build system, type-alias → type alias)
 - #135677 (Small `rustc_resolve` cleanups)
 - #136239 (show supported register classes in error message)
 - #136246 (include note on variance and example)
 - #136354 (Update docs for impl keyword)
 - #136786 (Remove the deduplicate_blocks pass)
 - #136833 (compiler: die immediately instead of handling unknown target codegen)
 - #136847 (Simplify intra-crate qualifiers.)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2025-02-11 23:55:03 +00:00
commit 34a5ea911c
46 changed files with 225 additions and 556 deletions

View file

@ -112,7 +112,8 @@ ast_lowering_invalid_register =
invalid register `{$reg}`: {$error}
ast_lowering_invalid_register_class =
invalid register class `{$reg_class}`: {$error}
invalid register class `{$reg_class}`: unknown register class
.note = the following register classes are supported on this target: {$supported_register_classes}
ast_lowering_match_arm_with_no_body =
`match` arm with no body

View file

@ -152,11 +152,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
InlineAsmRegOrRegClass::RegClass(reg_class) => {
asm::InlineAsmRegOrRegClass::RegClass(if let Some(asm_arch) = asm_arch {
asm::InlineAsmRegClass::parse(asm_arch, reg_class).unwrap_or_else(
|error| {
|supported_register_classes| {
let mut register_classes =
format!("`{}`", supported_register_classes[0]);
for m in &supported_register_classes[1..] {
let _ = write!(register_classes, ", `{m}`");
}
self.dcx().emit_err(InvalidRegisterClass {
op_span: *op_sp,
reg_class,
error,
supported_register_classes: register_classes,
});
asm::InlineAsmRegClass::Err
},

View file

@ -197,12 +197,13 @@ pub(crate) struct InvalidRegister<'a> {
}
#[derive(Diagnostic)]
#[note]
#[diag(ast_lowering_invalid_register_class)]
pub(crate) struct InvalidRegisterClass<'a> {
pub(crate) struct InvalidRegisterClass {
#[primary_span]
pub op_span: Span,
pub reg_class: Symbol,
pub error: &'a str,
pub supported_register_classes: String,
}
#[derive(Diagnostic)]

View file

@ -400,7 +400,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
conv: Conv::C,
can_unwind: false,
};
fn_abi.adjust_for_foreign_abi(self.cx, ExternAbi::C { unwind: false }).unwrap();
fn_abi.adjust_for_foreign_abi(self.cx, ExternAbi::C { unwind: false });
let ret_indirect = matches!(fn_abi.ret.mode, PassMode::Indirect { .. });

View file

@ -16,7 +16,6 @@ use rustc_middle::mir::interpret::{
};
use rustc_middle::ty::{self, Mutability, Ty};
use rustc_span::{Span, Symbol};
use rustc_target::callconv::AdjustForForeignAbiError;
use crate::interpret::InternKind;
@ -936,9 +935,6 @@ impl<'tcx> ReportErrorExt for InvalidProgramInfo<'tcx> {
InvalidProgramInfo::TooGeneric => const_eval_too_generic,
InvalidProgramInfo::AlreadyReported(_) => const_eval_already_reported,
InvalidProgramInfo::Layout(e) => e.diagnostic_message(),
InvalidProgramInfo::FnAbiAdjustForForeignAbi(_) => {
rustc_middle::error::middle_adjust_for_foreign_abi_error
}
}
}
fn add_args<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
@ -953,12 +949,6 @@ impl<'tcx> ReportErrorExt for InvalidProgramInfo<'tcx> {
}
dummy_diag.cancel();
}
InvalidProgramInfo::FnAbiAdjustForForeignAbi(
AdjustForForeignAbiError::Unsupported { arch, abi },
) => {
diag.arg("arch", arch);
diag.arg("abi", abi.name());
}
}
}
}

View file

@ -106,9 +106,6 @@ impl<'tcx, M: Machine<'tcx>> FnAbiOfHelpers<'tcx> for InterpCx<'tcx, M> {
) -> InterpErrorKind<'tcx> {
match err {
FnAbiError::Layout(err) => err_inval!(Layout(err)),
FnAbiError::AdjustForForeignAbi(err) => {
err_inval!(FnAbiAdjustForForeignAbi(err))
}
}
}
}

View file

@ -108,13 +108,13 @@ impl<I: rustc_type_ir::Interner> IntoDiagArg for rustc_type_ir::ExistentialTrait
}
impl<I: rustc_type_ir::Interner> IntoDiagArg for rustc_type_ir::UnevaluatedConst<I> {
fn into_diag_arg(self) -> rustc_errors::DiagArgValue {
fn into_diag_arg(self) -> DiagArgValue {
format!("{self:?}").into_diag_arg()
}
}
impl<I: rustc_type_ir::Interner> IntoDiagArg for rustc_type_ir::FnSig<I> {
fn into_diag_arg(self) -> rustc_errors::DiagArgValue {
fn into_diag_arg(self) -> DiagArgValue {
format!("{self:?}").into_diag_arg()
}
}

View file

@ -10,11 +10,10 @@ use rustc_hir::definitions::{DefKey, DefPath, DefPathHash};
use rustc_hir::intravisit::Visitor;
use rustc_hir::*;
use rustc_hir_pretty as pprust_hir;
use rustc_middle::hir::nested_filter;
use rustc_span::def_id::StableCrateId;
use rustc_span::{ErrorGuaranteed, Ident, Span, Symbol, kw, sym, with_metavar_spans};
use crate::hir::ModuleItems;
use crate::hir::{ModuleItems, nested_filter};
use crate::middle::debugger_visualizer::DebuggerVisualizerFile;
use crate::query::LocalCrate;
use crate::ty::TyCtxt;

View file

@ -13,7 +13,6 @@ use rustc_feature::GateIssue;
use rustc_hir::def_id::{DefId, LocalDefId, LocalDefIdMap};
use rustc_hir::{self as hir, HirId};
use rustc_macros::{Decodable, Encodable, HashStable, Subdiagnostic};
use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_session::Session;
use rustc_session::lint::builtin::{DEPRECATED, DEPRECATED_IN_FUTURE, SOFT_UNSTABLE};
use rustc_session::lint::{BuiltinLintDiag, DeprecatedSinceKind, Level, Lint, LintBuffer};
@ -23,6 +22,7 @@ use tracing::debug;
pub use self::StabilityLevel::*;
use crate::ty::TyCtxt;
use crate::ty::print::with_no_trimmed_paths;
#[derive(PartialEq, Clone, Copy, Debug)]
pub enum StabilityLevel {

View file

@ -1,5 +1,6 @@
use gsgdt::{Edge, Graph, Node, NodeStyle};
use rustc_middle::mir::*;
use crate::mir::*;
/// Convert an MIR function into a gsgdt Graph
pub(crate) fn mir_fn_to_generic_graph<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'_>) -> Graph {

View file

@ -2,7 +2,8 @@ use std::io::{self, Write};
use rustc_data_structures::graph::{self, iterate};
use rustc_graphviz as dot;
use rustc_middle::ty::TyCtxt;
use crate::ty::TyCtxt;
pub struct GraphvizWriter<
'a,

View file

@ -2,10 +2,10 @@ use std::io::{self, Write};
use gsgdt::GraphvizSettings;
use rustc_graphviz as dot;
use rustc_middle::mir::*;
use super::generic_graph::mir_fn_to_generic_graph;
use super::pretty::dump_mir_def_ids;
use crate::mir::*;
/// Write a graphviz DOT graph of a list of MIRs.
pub fn write_mir_graphviz<W>(tcx: TyCtxt<'_>, single: Option<DefId>, w: &mut W) -> io::Result<()>

View file

@ -216,10 +216,6 @@ pub enum InvalidProgramInfo<'tcx> {
AlreadyReported(ReportedErrorInfo),
/// An error occurred during layout computation.
Layout(layout::LayoutError<'tcx>),
/// An error occurred during FnAbi computation: the passed --target lacks FFI support
/// (which unfortunately typeck does not reject).
/// Not using `FnAbiError` as that contains a nested `LayoutError`.
FnAbiAdjustForForeignAbi(rustc_target::callconv::AdjustForForeignAbiError),
}
/// Details of why a pointer had to be in-bounds.

View file

@ -20,7 +20,6 @@ use rustc_data_structures::sync::{AtomicU64, Lock};
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable};
use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_serialize::{Decodable, Encodable};
use tracing::{debug, trace};
// Also make the error macros available from this module.
@ -46,6 +45,7 @@ pub use self::pointer::{CtfeProvenance, Pointer, PointerArithmetic, Provenance};
pub use self::value::Scalar;
use crate::mir;
use crate::ty::codec::{TyDecoder, TyEncoder};
use crate::ty::print::with_no_trimmed_paths;
use crate::ty::{self, Instance, Ty, TyCtxt};
/// Uniquely identifies one of the following:

View file

@ -1,6 +1,7 @@
use rustc_middle::mir::*;
use tracing::debug;
use crate::mir::*;
/// This struct represents a patch to MIR, which can add
/// new statements and basic blocks and patch over block
/// terminators.

View file

@ -5,17 +5,16 @@ use std::{fs, io};
use rustc_abi::Size;
use rustc_ast::InlineAsmTemplatePiece;
use rustc_middle::mir::interpret::{
AllocBytes, AllocId, Allocation, GlobalAlloc, Pointer, Provenance, alloc_range,
read_target_uint,
};
use rustc_middle::mir::visit::Visitor;
use rustc_middle::mir::*;
use tracing::trace;
use ty::print::PrettyPrinter;
use super::graphviz::write_mir_fn_graphviz;
use crate::mir::interpret::ConstAllocation;
use crate::mir::interpret::{
AllocBytes, AllocId, Allocation, ConstAllocation, GlobalAlloc, Pointer, Provenance,
alloc_range, read_target_uint,
};
use crate::mir::visit::Visitor;
use crate::mir::*;
const INDENT: &str = " ";
/// Alignment for lining up comments following MIR statements

View file

@ -101,9 +101,9 @@ impl<T> EraseType for Result<&'_ T, &'_ ty::layout::FnAbiError<'_>> {
type Result = [u8; size_of::<Result<&'static (), &'static ty::layout::FnAbiError<'static>>>()];
}
impl<T> EraseType for Result<(&'_ T, rustc_middle::thir::ExprId), rustc_errors::ErrorGuaranteed> {
impl<T> EraseType for Result<(&'_ T, crate::thir::ExprId), rustc_errors::ErrorGuaranteed> {
type Result = [u8; size_of::<
Result<(&'static (), rustc_middle::thir::ExprId), rustc_errors::ErrorGuaranteed>,
Result<(&'static (), crate::thir::ExprId), rustc_errors::ErrorGuaranteed>,
>()];
}

View file

@ -11,12 +11,6 @@ use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE, LocalDefId, Stab
use rustc_hir::definitions::DefPathHash;
use rustc_index::{Idx, IndexVec};
use rustc_macros::{Decodable, Encodable};
use rustc_middle::dep_graph::{DepNodeIndex, SerializedDepNodeIndex};
use rustc_middle::mir::interpret::{AllocDecodingSession, AllocDecodingState};
use rustc_middle::mir::mono::MonoItem;
use rustc_middle::mir::{self, interpret};
use rustc_middle::ty::codec::{RefDecodable, TyDecoder, TyEncoder};
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_query_system::query::QuerySideEffects;
use rustc_serialize::opaque::{FileEncodeResult, FileEncoder, IntEncodedWithFixedSize, MemDecoder};
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
@ -30,6 +24,13 @@ use rustc_span::{
SpanDecoder, SpanEncoder, StableSourceFileId, Symbol,
};
use crate::dep_graph::{DepNodeIndex, SerializedDepNodeIndex};
use crate::mir::interpret::{AllocDecodingSession, AllocDecodingState};
use crate::mir::mono::MonoItem;
use crate::mir::{self, interpret};
use crate::ty::codec::{RefDecodable, TyDecoder, TyEncoder};
use crate::ty::{self, Ty, TyCtxt};
const TAG_FILE_FOOTER: u128 = 0xC0FFEE_C0FFEE_C0FFEE_C0FFEE_C0FFEE;
// A normal span encoded with both location information and a `SyntaxContext`
@ -563,7 +564,7 @@ impl<'a, 'tcx> TyDecoder for CacheDecoder<'a, 'tcx> {
}
}
rustc_middle::implement_ty_decoder!(CacheDecoder<'a, 'tcx>);
crate::implement_ty_decoder!(CacheDecoder<'a, 'tcx>);
// This ensures that the `Decodable<opaque::Decoder>::decode` specialization for `Vec<u8>` is used
// when a `CacheDecoder` is passed to `Decodable::decode`. Unfortunately, we have to manually opt

View file

@ -20,20 +20,21 @@ use rustc_hir::def_id::DefId;
use rustc_hir::{BindingMode, ByRef, HirId, MatchSource, RangeEnd};
use rustc_index::{IndexVec, newtype_index};
use rustc_macros::{HashStable, TypeVisitable};
use rustc_middle::middle::region;
use rustc_middle::mir::interpret::AllocId;
use rustc_middle::mir::{self, BinOp, BorrowKind, FakeReadCause, UnOp};
use rustc_middle::ty::adjustment::PointerCoercion;
use rustc_middle::ty::layout::IntegerExt;
use rustc_middle::ty::{
self, AdtDef, CanonicalUserType, CanonicalUserTypeAnnotation, FnSig, GenericArgsRef, List, Ty,
TyCtxt, UpvarArgs,
};
use rustc_span::def_id::LocalDefId;
use rustc_span::{ErrorGuaranteed, Span, Symbol};
use rustc_target::asm::InlineAsmRegOrRegClass;
use tracing::instrument;
use crate::middle::region;
use crate::mir::interpret::AllocId;
use crate::mir::{self, BinOp, BorrowKind, FakeReadCause, UnOp};
use crate::ty::adjustment::PointerCoercion;
use crate::ty::layout::IntegerExt;
use crate::ty::{
self, AdtDef, CanonicalUserType, CanonicalUserTypeAnnotation, FnSig, GenericArgsRef, List, Ty,
TyCtxt, UpvarArgs,
};
pub mod visit;
macro_rules! thir_with_elements {

View file

@ -2,8 +2,8 @@
// typeck and codegen.
use rustc_macros::{HashStable, TyDecodable, TyEncodable};
use rustc_middle::mir;
use crate::mir;
use crate::ty::{self, Ty};
/// Types that are represented as ints.

View file

@ -13,8 +13,6 @@ use std::marker::DiscriminantKind;
use rustc_abi::{FieldIdx, VariantIdx};
use rustc_data_structures::fx::FxHashMap;
use rustc_hir::def_id::LocalDefId;
use rustc_middle::mir::mono::MonoItem;
use rustc_middle::ty::TyCtxt;
use rustc_serialize::{Decodable, Encodable};
use rustc_span::Span;
use rustc_span::source_map::Spanned;
@ -23,9 +21,10 @@ pub use rustc_type_ir::{TyDecoder, TyEncoder};
use crate::arena::ArenaAllocatable;
use crate::infer::canonical::{CanonicalVarInfo, CanonicalVarInfos};
use crate::mir::interpret::{AllocId, ConstAllocation, CtfeProvenance};
use crate::mir::mono::MonoItem;
use crate::mir::{self};
use crate::traits;
use crate::ty::{self, AdtDef, GenericArgsRef, Ty};
use crate::ty::{self, AdtDef, GenericArgsRef, Ty, TyCtxt};
/// The shorthand encoding uses an enum's variant index `usize`
/// and is offset by this value so it never matches a real variant.

View file

@ -10,13 +10,13 @@ use rustc_hir::def_id::{CrateNum, DefId};
use rustc_hir::lang_items::LangItem;
use rustc_index::bit_set::FiniteBitSet;
use rustc_macros::{Decodable, Encodable, HashStable, Lift, TyDecodable, TyEncodable};
use rustc_middle::ty::normalize_erasing_regions::NormalizationError;
use rustc_span::def_id::LOCAL_CRATE;
use rustc_span::{DUMMY_SP, Span, Symbol};
use tracing::{debug, instrument};
use crate::error;
use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use crate::ty::normalize_erasing_regions::NormalizationError;
use crate::ty::print::{FmtPrinter, Printer, shrunk_instance_name};
use crate::ty::{
self, EarlyBinder, GenericArgs, GenericArgsRef, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable,

View file

@ -24,7 +24,6 @@ use rustc_target::spec::{
use tracing::debug;
use {rustc_abi as abi, rustc_hir as hir};
use crate::error::UnsupportedFnAbi;
use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use crate::query::TyCtxtAt;
use crate::ty::normalize_erasing_regions::NormalizationError;
@ -1275,18 +1274,12 @@ pub fn fn_can_unwind(tcx: TyCtxt<'_>, fn_def_id: Option<DefId>, abi: ExternAbi)
pub enum FnAbiError<'tcx> {
/// Error produced by a `layout_of` call, while computing `FnAbi` initially.
Layout(LayoutError<'tcx>),
/// Error produced by attempting to adjust a `FnAbi`, for a "foreign" ABI.
AdjustForForeignAbi(rustc_target::callconv::AdjustForForeignAbiError),
}
impl<'a, 'b, G: EmissionGuarantee> Diagnostic<'a, G> for FnAbiError<'b> {
fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G> {
match self {
Self::Layout(e) => e.into_diagnostic().into_diag(dcx, level),
Self::AdjustForForeignAbi(
rustc_target::callconv::AdjustForForeignAbiError::Unsupported { arch, abi },
) => UnsupportedFnAbi { arch, abi: abi.name() }.into_diag(dcx, level),
}
}
}

View file

@ -1512,7 +1512,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
ty::ExprKind::Binop(op) => {
let (_, _, c1, c2) = expr.binop_args();
let precedence = |binop: rustc_middle::mir::BinOp| {
let precedence = |binop: crate::mir::BinOp| {
use rustc_ast::util::parser::AssocOp;
AssocOp::from_ast_binop(binop.to_hir_binop()).precedence()
};
@ -1558,7 +1558,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
ty::ExprKind::UnOp(op) => {
let (_, ct) = expr.unop_args();
use rustc_middle::mir::UnOp;
use crate::mir::UnOp;
let formatted_op = match op {
UnOp::Not => "!",
UnOp::Neg => "-",

View file

@ -14,13 +14,13 @@ use rustc_hir::{
};
use rustc_index::IndexVec;
use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable};
use rustc_middle::mir::FakeReadCause;
use rustc_session::Session;
use rustc_span::Span;
use super::RvalueScopes;
use crate::hir::place::Place as HirPlace;
use crate::infer::canonical::Canonical;
use crate::mir::FakeReadCause;
use crate::traits::ObligationCause;
use crate::ty::{
self, BoundVar, CanonicalPolyFnSig, ClosureSizeProfileData, GenericArgKind, GenericArgs,

View file

@ -2,9 +2,9 @@ pub mod bug;
#[derive(Default, Copy, Clone)]
pub struct Providers {
pub queries: rustc_middle::query::Providers,
pub extern_queries: rustc_middle::query::ExternProviders,
pub hooks: rustc_middle::hooks::Providers,
pub queries: crate::query::Providers,
pub extern_queries: crate::query::ExternProviders,
pub hooks: crate::hooks::Providers,
}
/// Backwards compatibility hack to keep the diff small. This
@ -17,7 +17,7 @@ impl std::ops::DerefMut for Providers {
}
impl std::ops::Deref for Providers {
type Target = rustc_middle::query::Providers;
type Target = crate::query::Providers;
fn deref(&self) -> &Self::Target {
&self.queries

View file

@ -7,7 +7,6 @@ use rustc_errors::codes::*;
use rustc_errors::{Applicability, MultiSpan, pluralize, struct_span_code_err};
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
use rustc_middle::ty::{self, Representability, Ty, TyCtxt};
use rustc_query_system::Value;
use rustc_query_system::query::{CycleError, report_cycle};
use rustc_span::def_id::LocalDefId;
@ -15,6 +14,7 @@ use rustc_span::{ErrorGuaranteed, Span};
use crate::dep_graph::dep_kinds;
use crate::query::plumbing::CyclePlaceholder;
use crate::ty::{self, Representability, Ty, TyCtxt};
impl<'tcx> Value<TyCtxt<'tcx>> for Ty<'_> {
fn from_cycle_error(tcx: TyCtxt<'tcx>, _: &CycleError, guar: ErrorGuaranteed) -> Self {

View file

@ -1,195 +0,0 @@
//! This pass finds basic blocks that are completely equal,
//! and replaces all uses with just one of them.
use std::collections::hash_map::Entry;
use std::hash::{Hash, Hasher};
use std::iter;
use rustc_data_structures::fx::FxHashMap;
use rustc_middle::mir::visit::MutVisitor;
use rustc_middle::mir::*;
use rustc_middle::ty::TyCtxt;
use tracing::debug;
use super::simplify::simplify_cfg;
pub(super) struct DeduplicateBlocks;
impl<'tcx> crate::MirPass<'tcx> for DeduplicateBlocks {
fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
sess.mir_opt_level() >= 4
}
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
debug!("Running DeduplicateBlocks on `{:?}`", body.source);
let duplicates = find_duplicates(body);
let has_opts_to_apply = !duplicates.is_empty();
if has_opts_to_apply {
let mut opt_applier = OptApplier { tcx, duplicates };
opt_applier.visit_body(body);
simplify_cfg(body);
}
}
fn is_required(&self) -> bool {
false
}
}
struct OptApplier<'tcx> {
tcx: TyCtxt<'tcx>,
duplicates: FxHashMap<BasicBlock, BasicBlock>,
}
impl<'tcx> MutVisitor<'tcx> for OptApplier<'tcx> {
fn tcx(&self) -> TyCtxt<'tcx> {
self.tcx
}
fn visit_terminator(&mut self, terminator: &mut Terminator<'tcx>, location: Location) {
for target in terminator.successors_mut() {
if let Some(replacement) = self.duplicates.get(target) {
debug!("SUCCESS: Replacing: `{:?}` with `{:?}`", target, replacement);
*target = *replacement;
}
}
self.super_terminator(terminator, location);
}
}
fn find_duplicates(body: &Body<'_>) -> FxHashMap<BasicBlock, BasicBlock> {
let mut duplicates = FxHashMap::default();
let bbs_to_go_through =
body.basic_blocks.iter_enumerated().filter(|(_, bbd)| !bbd.is_cleanup).count();
let mut same_hashes =
FxHashMap::with_capacity_and_hasher(bbs_to_go_through, Default::default());
// Go through the basic blocks backwards. This means that in case of duplicates,
// we can use the basic block with the highest index as the replacement for all lower ones.
// For example, if bb1, bb2 and bb3 are duplicates, we will first insert bb3 in same_hashes.
// Then we will see that bb2 is a duplicate of bb3,
// and insert bb2 with the replacement bb3 in the duplicates list.
// When we see bb1, we see that it is a duplicate of bb3, and therefore insert it in the
// duplicates list with replacement bb3.
// When the duplicates are removed, we will end up with only bb3.
for (bb, bbd) in body.basic_blocks.iter_enumerated().rev().filter(|(_, bbd)| !bbd.is_cleanup) {
// Basic blocks can get really big, so to avoid checking for duplicates in basic blocks
// that are unlikely to have duplicates, we stop early. The early bail number has been
// found experimentally by eprintln while compiling the crates in the rustc-perf suite.
if bbd.statements.len() > 10 {
continue;
}
let to_hash = BasicBlockHashable { basic_block_data: bbd };
let entry = same_hashes.entry(to_hash);
match entry {
Entry::Occupied(occupied) => {
// The basic block was already in the hashmap, which means we have a duplicate
let value = *occupied.get();
debug!("Inserting {:?} -> {:?}", bb, value);
duplicates.try_insert(bb, value).expect("key was already inserted");
}
Entry::Vacant(vacant) => {
vacant.insert(bb);
}
}
}
duplicates
}
struct BasicBlockHashable<'a, 'tcx> {
basic_block_data: &'a BasicBlockData<'tcx>,
}
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.
self.basic_block_data.terminator().kind.hash(state);
}
}
impl Eq for BasicBlockHashable<'_, '_> {}
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
&& iter::zip(&self.basic_block_data.statements, &other.basic_block_data.statements)
.all(|(x, y)| statement_eq(&x.kind, &y.kind))
}
}
fn hash_statements<'a, 'tcx, H: Hasher>(
hasher: &mut H,
iter: impl Iterator<Item = &'a Statement<'tcx>>,
) where
'tcx: 'a,
{
for stmt in iter {
statement_hash(hasher, &stmt.kind);
}
}
fn statement_hash<H: Hasher>(hasher: &mut H, stmt: &StatementKind<'_>) {
match stmt {
StatementKind::Assign(box (place, rvalue)) => {
place.hash(hasher);
rvalue_hash(hasher, rvalue)
}
x => x.hash(hasher),
};
}
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<'_>) {
match operand {
Operand::Constant(box ConstOperand { user_ty: _, const_, span: _ }) => const_.hash(hasher),
x => x.hash(hasher),
};
}
fn statement_eq<'tcx>(lhs: &StatementKind<'tcx>, rhs: &StatementKind<'tcx>) -> bool {
let res = match (lhs, rhs) {
(
StatementKind::Assign(box (place, rvalue)),
StatementKind::Assign(box (place2, rvalue2)),
) => place == place2 && rvalue_eq(rvalue, rvalue2),
(x, y) => x == y,
};
debug!("statement_eq lhs: `{:?}` rhs: `{:?}` result: {:?}", lhs, rhs, res);
res
}
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,
};
debug!("rvalue_eq lhs: `{:?}` rhs: `{:?}` result: {:?}", lhs, rhs, res);
res
}
fn operand_eq<'tcx>(lhs: &Operand<'tcx>, rhs: &Operand<'tcx>) -> bool {
let res = match (lhs, rhs) {
(
Operand::Constant(box ConstOperand { user_ty: _, const_, span: _ }),
Operand::Constant(box ConstOperand { user_ty: _, const_: const2, span: _ }),
) => const_ == const2,
(x, y) => x == y,
};
debug!("operand_eq lhs: `{:?}` rhs: `{:?}` result: {:?}", lhs, rhs, res);
res
}

View file

@ -135,7 +135,6 @@ declare_passes! {
Initial,
Final
};
mod deduplicate_blocks : DeduplicateBlocks;
mod deref_separator : Derefer;
mod dest_prop : DestinationPropagation;
pub mod dump_mir : Marker;
@ -700,7 +699,6 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
&nrvo::RenameReturnPlace,
&simplify::SimplifyLocals::Final,
&multiple_return_terminators::MultipleReturnTerminators,
&deduplicate_blocks::DeduplicateBlocks,
&large_enums::EnumSizeOpt { discrepancy: 128 },
// Some cleanup necessary at least for LLVM and potentially other codegen backends.
&add_call_guards::CriticalCallEdges,

View file

@ -46,15 +46,6 @@ fn unwrap_fn_abi<'tcx>(
span: tcx.def_span(item_def_id),
});
}
Err(FnAbiError::AdjustForForeignAbi(e)) => {
// Sadly there seems to be no `into_diagnostic` for this case... and I am not sure if
// this can even be reached. Anyway this is a perma-unstable debug attribute, an ICE
// isn't the worst thing. Also this matches what codegen does.
span_bug!(
tcx.def_span(item_def_id),
"error computing fn_abi_of_instance, cannot adjust for foreign ABI: {e:?}",
)
}
}
}

View file

@ -1127,7 +1127,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
});
// Make sure error reporting is deterministic.
suggestions.sort_by(|a, b| a.candidate.as_str().partial_cmp(b.candidate.as_str()).unwrap());
suggestions.sort_by(|a, b| a.candidate.as_str().cmp(b.candidate.as_str()));
match find_best_match_for_name(
&suggestions.iter().map(|suggestion| suggestion.candidate).collect::<Vec<Symbol>>(),
@ -2256,14 +2256,15 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
mut path: Vec<Segment>,
parent_scope: &ParentScope<'ra>,
) -> Option<(Vec<Segment>, Option<String>)> {
match (path.get(0), path.get(1)) {
match path[..] {
// `{{root}}::ident::...` on both editions.
// On 2015 `{{root}}` is usually added implicitly.
(Some(fst), Some(snd))
if fst.ident.name == kw::PathRoot && !snd.ident.is_path_segment_keyword() => {}
[first, second, ..]
if first.ident.name == kw::PathRoot && !second.ident.is_path_segment_keyword() => {}
// `ident::...` on 2018.
(Some(fst), _)
if fst.ident.span.at_least_rust_2018() && !fst.ident.is_path_segment_keyword() =>
[first, ..]
if first.ident.span.at_least_rust_2018()
&& !first.ident.is_path_segment_keyword() =>
{
// Insert a placeholder that's later replaced by `self`/`super`/etc.
path.insert(0, Segment::from_ident(Ident::empty()));
@ -2374,7 +2375,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
// 2) `std` suggestions before `core` suggestions.
let mut extern_crate_names =
self.extern_prelude.keys().map(|ident| ident.name).collect::<Vec<_>>();
extern_crate_names.sort_by(|a, b| b.as_str().partial_cmp(a.as_str()).unwrap());
extern_crate_names.sort_by(|a, b| b.as_str().cmp(a.as_str()));
for name in extern_crate_names.into_iter() {
// Replace first ident with a crate name and check if that is valid.

View file

@ -9,7 +9,7 @@
//!
//! ## Adding a new cfg
//!
//! Adding a new feature requires two new symbols one for the cfg it-self
//! Adding a new feature requires two new symbols one for the cfg itself
//! and the second one for the unstable feature gate, those are defined in
//! `rustc_span::symbol`.
//!

View file

@ -39,12 +39,12 @@ macro_rules! def_reg_class {
}
}
pub fn parse(name: rustc_span::Symbol) -> Result<Self, &'static str> {
pub fn parse(name: rustc_span::Symbol) -> Result<Self, &'static [rustc_span::Symbol]> {
match name {
$(
rustc_span::sym::$class => Ok(Self::$class),
)*
_ => Err("unknown register class"),
_ => Err(&[$(rustc_span::sym::$class),*]),
}
}
}
@ -635,7 +635,7 @@ impl InlineAsmRegClass {
}
}
pub fn parse(arch: InlineAsmArch, name: Symbol) -> Result<Self, &'static str> {
pub fn parse(arch: InlineAsmArch, name: Symbol) -> Result<Self, &'static [rustc_span::Symbol]> {
Ok(match arch {
InlineAsmArch::X86 | InlineAsmArch::X86_64 => {
Self::X86(X86InlineAsmRegClass::parse(name)?)

View file

@ -6,7 +6,6 @@ use rustc_abi::{
Size, TyAbiInterface, TyAndLayout,
};
use rustc_macros::HashStable_Generic;
use rustc_span::Symbol;
use crate::spec::{HasTargetSpec, HasWasmCAbiOpt, HasX86AbiOpt, WasmCAbi};
@ -623,19 +622,8 @@ impl<'a, Ty: fmt::Display> fmt::Debug for FnAbi<'a, Ty> {
}
}
/// Error produced by attempting to adjust a `FnAbi`, for a "foreign" ABI.
#[derive(Copy, Clone, Debug, HashStable_Generic)]
pub enum AdjustForForeignAbiError {
/// Target architecture doesn't support "foreign" (i.e. non-Rust) ABIs.
Unsupported { arch: Symbol, abi: ExternAbi },
}
impl<'a, Ty> FnAbi<'a, Ty> {
pub fn adjust_for_foreign_abi<C>(
&mut self,
cx: &C,
abi: ExternAbi,
) -> Result<(), AdjustForForeignAbiError>
pub fn adjust_for_foreign_abi<C>(&mut self, cx: &C, abi: ExternAbi)
where
Ty: TyAbiInterface<'a, C> + Copy,
C: HasDataLayout + HasTargetSpec + HasWasmCAbiOpt + HasX86AbiOpt,
@ -644,7 +632,7 @@ impl<'a, Ty> FnAbi<'a, Ty> {
if let Some(arg) = self.args.first_mut() {
arg.pass_by_stack_offset(None);
}
return Ok(());
return;
}
let spec = cx.target_spec();
@ -719,15 +707,8 @@ impl<'a, Ty> FnAbi<'a, Ty> {
}
"wasm64" => wasm::compute_c_abi_info(cx, self),
"bpf" => bpf::compute_abi_info(self),
arch => {
return Err(AdjustForForeignAbiError::Unsupported {
arch: Symbol::intern(arch),
abi,
});
}
arch => panic!("no lowering implemented for {arch}"),
}
Ok(())
}
pub fn adjust_for_rust_abi<C>(&mut self, cx: &C, abi: ExternAbi)

View file

@ -650,7 +650,7 @@ fn fn_abi_new_uncached<'tcx>(
conv,
can_unwind: fn_can_unwind(cx.tcx(), fn_def_id, sig.abi),
};
fn_abi_adjust_for_abi(cx, &mut fn_abi, sig.abi, fn_def_id)?;
fn_abi_adjust_for_abi(cx, &mut fn_abi, sig.abi, fn_def_id);
debug!("fn_abi_new_uncached = {:?}", fn_abi);
fn_abi_sanity_check(cx, &fn_abi, sig.abi);
Ok(tcx.arena.alloc(fn_abi))
@ -662,7 +662,7 @@ fn fn_abi_adjust_for_abi<'tcx>(
fn_abi: &mut FnAbi<'tcx, Ty<'tcx>>,
abi: ExternAbi,
fn_def_id: Option<DefId>,
) -> Result<(), &'tcx FnAbiError<'tcx>> {
) {
if abi == ExternAbi::Unadjusted {
// The "unadjusted" ABI passes aggregates in "direct" mode. That's fragile but needed for
// some LLVM intrinsics.
@ -682,7 +682,7 @@ fn fn_abi_adjust_for_abi<'tcx>(
for arg in fn_abi.args.iter_mut() {
unadjust(arg);
}
return Ok(());
return;
}
let tcx = cx.tcx();
@ -723,12 +723,8 @@ fn fn_abi_adjust_for_abi<'tcx>(
}
}
} else {
fn_abi
.adjust_for_foreign_abi(cx, abi)
.map_err(|err| &*tcx.arena.alloc(FnAbiError::AdjustForForeignAbi(err)))?;
fn_abi.adjust_for_foreign_abi(cx, abi);
}
Ok(())
}
#[tracing::instrument(level = "debug", skip(cx))]

View file

@ -1,10 +1,10 @@
pub use rustc_type_ir::relate::*;
use rustc_type_ir::solve::Goal;
use rustc_type_ir::{self as ty, InferCtxtLike, Interner};
use tracing::{debug, instrument};
use self::combine::{PredicateEmittingRelation, super_combine_consts, super_combine_tys};
use crate::data_structures::DelayedSet;
pub use crate::relate::*;
use crate::solve::Goal;
use crate::{self as ty, InferCtxtLike, Interner};
pub trait RelateExt: InferCtxtLike {
fn relate<T: Relate<Self::Interner>>(

View file

@ -610,6 +610,101 @@ impl dyn Any + Send + Sync {
/// While `TypeId` implements `Hash`, `PartialOrd`, and `Ord`, it is worth
/// noting that the hashes and ordering will vary between Rust releases. Beware
/// of relying on them inside of your code!
///
/// # Danger of Improper Variance
///
/// You might think that subtyping is impossible between two static types,
/// but this is false; there exists a static type with a static subtype.
/// To wit, `fn(&str)`, which is short for `for<'any> fn(&'any str)`, and
/// `fn(&'static str)`, are two distinct, static types, and yet,
/// `fn(&str)` is a subtype of `fn(&'static str)`, since any value of type
/// `fn(&str)` can be used where a value of type `fn(&'static str)` is needed.
///
/// This means that abstractions around `TypeId`, despite its
/// `'static` bound on arguments, still need to worry about unnecessary
/// and improper variance: it is advisable to strive for invariance
/// first. The usability impact will be negligible, while the reduction
/// in the risk of unsoundness will be most welcome.
///
/// ## Examples
///
/// Suppose `SubType` is a subtype of `SuperType`, that is,
/// a value of type `SubType` can be used wherever
/// a value of type `SuperType` is expected.
/// Suppose also that `CoVar<T>` is a generic type, which is covariant over `T`
/// (like many other types, including `PhantomData<T>` and `Vec<T>`).
///
/// Then, by covariance, `CoVar<SubType>` is a subtype of `CoVar<SuperType>`,
/// that is, a value of type `CoVar<SubType>` can be used wherever
/// a value of type `CoVar<SuperType>` is expected.
///
/// Then if `CoVar<SuperType>` relies on `TypeId::of::<SuperType>()` to uphold any invariants,
/// those invariants may be broken because a value of type `CoVar<SuperType>` can be created
/// without going through any of its methods, like so:
/// ```
/// type SubType = fn(&());
/// type SuperType = fn(&'static ());
/// type CoVar<T> = Vec<T>; // imagine something more complicated
///
/// let sub: CoVar<SubType> = CoVar::new();
/// // we have a `CoVar<SuperType>` instance without
/// // *ever* having called `CoVar::<SuperType>::new()`!
/// let fake_super: CoVar<SuperType> = sub;
/// ```
///
/// The following is an example program that tries to use `TypeId::of` to
/// implement a generic type `Unique<T>` that guarantees unique instances for each `Unique<T>`,
/// that is, and for each type `T` there can be at most one value of type `Unique<T>` at any time.
///
/// ```
/// mod unique {
/// use std::any::TypeId;
/// use std::collections::BTreeSet;
/// use std::marker::PhantomData;
/// use std::sync::Mutex;
///
/// static ID_SET: Mutex<BTreeSet<TypeId>> = Mutex::new(BTreeSet::new());
///
/// // TypeId has only covariant uses, which makes Unique covariant over TypeAsId 🚨
/// #[derive(Debug, PartialEq)]
/// pub struct Unique<TypeAsId: 'static>(
/// // private field prevents creation without `new` outside this module
/// PhantomData<TypeAsId>,
/// );
///
/// impl<TypeAsId: 'static> Unique<TypeAsId> {
/// pub fn new() -> Option<Self> {
/// let mut set = ID_SET.lock().unwrap();
/// (set.insert(TypeId::of::<TypeAsId>())).then(|| Self(PhantomData))
/// }
/// }
///
/// impl<TypeAsId: 'static> Drop for Unique<TypeAsId> {
/// fn drop(&mut self) {
/// let mut set = ID_SET.lock().unwrap();
/// (!set.remove(&TypeId::of::<TypeAsId>())).then(|| panic!("duplicity detected"));
/// }
/// }
/// }
///
/// use unique::Unique;
///
/// // `OtherRing` is a subtype of `TheOneRing`. Both are 'static, and thus have a TypeId.
/// type TheOneRing = fn(&'static ());
/// type OtherRing = fn(&());
///
/// fn main() {
/// let the_one_ring: Unique<TheOneRing> = Unique::new().unwrap();
/// assert_eq!(Unique::<TheOneRing>::new(), None);
///
/// let other_ring: Unique<OtherRing> = Unique::new().unwrap();
/// // Use that `Unique<OtherRing>` is a subtype of `Unique<TheOneRing>` 🚨
/// let fake_one_ring: Unique<TheOneRing> = other_ring;
/// assert_eq!(fake_one_ring, the_one_ring);
///
/// std::mem::forget(fake_one_ring);
/// }
/// ```
#[derive(Clone, Copy, Eq, PartialOrd, Ord)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct TypeId {
@ -627,8 +722,7 @@ impl PartialEq for TypeId {
}
impl TypeId {
/// Returns the `TypeId` of the type this generic function has been
/// instantiated with.
/// Returns the `TypeId` of the generic type parameter.
///
/// # Examples
///

View file

@ -651,16 +651,24 @@ mod if_keyword {}
#[doc(keyword = "impl")]
//
/// Implement some functionality for a type.
/// Implementations of functionality for a type, or a type implementing some functionality.
///
/// There are two uses of the keyword `impl`:
/// * An `impl` block is an item that is used to implement some functionality for a type.
/// * An `impl Trait` in a type-position can be used to designate a type that implements a trait called `Trait`.
///
/// # Implementing Functionality for a Type
///
/// The `impl` keyword is primarily used to define implementations on types. Inherent
/// implementations are standalone, while trait implementations are used to implement traits for
/// types, or other traits.
///
/// Functions and consts can both be defined in an implementation. A function defined in an
/// `impl` block can be standalone, meaning it would be called like `Foo::bar()`. If the function
/// An implementation consists of definitions of functions and consts. A function defined in an
/// `impl` block can be standalone, meaning it would be called like `Vec::new()`. If the function
/// takes `self`, `&self`, or `&mut self` as its first argument, it can also be called using
/// method-call syntax, a familiar feature to any object oriented programmer, like `foo.bar()`.
/// method-call syntax, a familiar feature to any object-oriented programmer, like `vec.len()`.
///
/// ## Inherent Implementations
///
/// ```rust
/// struct Example {
@ -680,6 +688,17 @@ mod if_keyword {}
/// self.number
/// }
/// }
/// ```
///
/// It matters little where an inherent implementation is defined;
/// its functionality is in scope wherever its implementing type is.
///
/// ## Trait Implementations
///
/// ```rust
/// struct Example {
/// number: i32,
/// }
///
/// trait Thingy {
/// fn do_thingy(&self);
@ -692,11 +711,19 @@ mod if_keyword {}
/// }
/// ```
///
/// It matters little where a trait implementation is defined;
/// its functionality can be brought into scope by importing the trait it implements.
///
/// For more information on implementations, see the [Rust book][book1] or the [Reference].
///
/// The other use of the `impl` keyword is in `impl Trait` syntax, which can be seen as a shorthand
/// for "a concrete type that implements this trait". Its primary use is working with closures,
/// which have type definitions generated at compile time that can't be simply typed out.
/// # Designating a Type that Implements Some Functionality
///
/// The other use of the `impl` keyword is in `impl Trait` syntax, which can be understood to mean
/// "any (or some) concrete type that implements Trait".
/// It can be used as the type of a variable declaration,
/// in [argument position](https://rust-lang.github.io/rfcs/1951-expand-impl-trait.html)
/// or in [return position](https://rust-lang.github.io/rfcs/3425-return-position-impl-trait-in-traits.html).
/// One pertinent use case is in working with closures, which have unnameable types.
///
/// ```rust
/// fn thing_returning_closure() -> impl Fn(i32) -> bool {

View file

@ -135,7 +135,7 @@ As of `2025-01-02T`, the list of known names is as follows:
- `windows`
> Starting with 1.85.0, the `test` cfg is consider to be a "userspace" config
> despite being also set by `rustc` and should be managed by the build-system it-self.
> despite being also set by `rustc` and should be managed by the build system itself.
Like with `values(any())`, well known names checking can be disabled by passing `cfg(any())`
as argument to `--check-cfg`.

View file

@ -26,7 +26,7 @@ impl DocFolder for AliasedNonLocalStripper<'_> {
Some(match i.kind {
clean::TypeAliasItem(..) => {
let mut stripper = NonLocalStripper { tcx: self.tcx };
// don't call `fold_item` as that could strip the type-alias it-self
// don't call `fold_item` as that could strip the type alias itself
// which we don't want to strip out
stripper.fold_item_recur(i)
}

View file

@ -1,100 +0,0 @@
- // MIR for `is_line_doc_comment_2` before DeduplicateBlocks
+ // MIR for `is_line_doc_comment_2` after DeduplicateBlocks
fn is_line_doc_comment_2(_1: &str) -> bool {
debug s => _1;
let mut _0: bool;
let mut _2: &[u8];
let mut _3: &str;
let mut _4: usize;
let mut _5: usize;
let mut _6: bool;
let mut _7: usize;
let mut _8: usize;
let mut _9: bool;
bb0: {
StorageLive(_2);
StorageLive(_3);
_3 = &(*_1);
_2 = core::str::<impl str>::as_bytes(move _3) -> [return: bb1, unwind unreachable];
}
bb1: {
StorageDead(_3);
_4 = Len((*_2));
_5 = const 4_usize;
_6 = Ge(move _4, move _5);
switchInt(move _6) -> [0: bb2, otherwise: bb3];
}
bb2: {
_7 = Len((*_2));
_8 = const 3_usize;
_9 = Ge(move _7, move _8);
- switchInt(move _9) -> [0: bb7, otherwise: bb8];
+ switchInt(move _9) -> [0: bb11, otherwise: bb7];
}
bb3: {
switchInt(copy (*_2)[0 of 4]) -> [47: bb4, otherwise: bb2];
}
bb4: {
switchInt(copy (*_2)[1 of 4]) -> [47: bb5, otherwise: bb2];
}
bb5: {
switchInt(copy (*_2)[2 of 4]) -> [47: bb6, otherwise: bb2];
}
bb6: {
- switchInt(copy (*_2)[3 of 4]) -> [47: bb13, otherwise: bb2];
+ switchInt(copy (*_2)[3 of 4]) -> [47: bb11, otherwise: bb2];
}
bb7: {
- _0 = const false;
- goto -> bb14;
+ switchInt(copy (*_2)[0 of 3]) -> [47: bb8, otherwise: bb11];
}
bb8: {
- switchInt(copy (*_2)[0 of 3]) -> [47: bb9, otherwise: bb7];
+ switchInt(copy (*_2)[1 of 3]) -> [47: bb9, otherwise: bb11];
}
bb9: {
- switchInt(copy (*_2)[1 of 3]) -> [47: bb10, otherwise: bb7];
+ switchInt(copy (*_2)[2 of 3]) -> [47: bb10, 33: bb10, otherwise: bb11];
}
bb10: {
- switchInt(copy (*_2)[2 of 3]) -> [47: bb12, 33: bb11, otherwise: bb7];
- }
-
- bb11: {
_0 = const true;
- goto -> bb14;
+ goto -> bb12;
}
- bb12: {
- _0 = const true;
- goto -> bb14;
- }
-
- bb13: {
+ bb11: {
_0 = const false;
- goto -> bb14;
+ goto -> bb12;
}
- bb14: {
+ bb12: {
StorageDead(_2);
return;
}
}

View file

@ -1,100 +0,0 @@
- // MIR for `is_line_doc_comment_2` before DeduplicateBlocks
+ // MIR for `is_line_doc_comment_2` after DeduplicateBlocks
fn is_line_doc_comment_2(_1: &str) -> bool {
debug s => _1;
let mut _0: bool;
let mut _2: &[u8];
let mut _3: &str;
let mut _4: usize;
let mut _5: usize;
let mut _6: bool;
let mut _7: usize;
let mut _8: usize;
let mut _9: bool;
bb0: {
StorageLive(_2);
StorageLive(_3);
_3 = &(*_1);
_2 = core::str::<impl str>::as_bytes(move _3) -> [return: bb1, unwind continue];
}
bb1: {
StorageDead(_3);
_4 = Len((*_2));
_5 = const 4_usize;
_6 = Ge(move _4, move _5);
switchInt(move _6) -> [0: bb2, otherwise: bb3];
}
bb2: {
_7 = Len((*_2));
_8 = const 3_usize;
_9 = Ge(move _7, move _8);
- switchInt(move _9) -> [0: bb7, otherwise: bb8];
+ switchInt(move _9) -> [0: bb11, otherwise: bb7];
}
bb3: {
switchInt(copy (*_2)[0 of 4]) -> [47: bb4, otherwise: bb2];
}
bb4: {
switchInt(copy (*_2)[1 of 4]) -> [47: bb5, otherwise: bb2];
}
bb5: {
switchInt(copy (*_2)[2 of 4]) -> [47: bb6, otherwise: bb2];
}
bb6: {
- switchInt(copy (*_2)[3 of 4]) -> [47: bb13, otherwise: bb2];
+ switchInt(copy (*_2)[3 of 4]) -> [47: bb11, otherwise: bb2];
}
bb7: {
- _0 = const false;
- goto -> bb14;
+ switchInt(copy (*_2)[0 of 3]) -> [47: bb8, otherwise: bb11];
}
bb8: {
- switchInt(copy (*_2)[0 of 3]) -> [47: bb9, otherwise: bb7];
+ switchInt(copy (*_2)[1 of 3]) -> [47: bb9, otherwise: bb11];
}
bb9: {
- switchInt(copy (*_2)[1 of 3]) -> [47: bb10, otherwise: bb7];
+ switchInt(copy (*_2)[2 of 3]) -> [47: bb10, 33: bb10, otherwise: bb11];
}
bb10: {
- switchInt(copy (*_2)[2 of 3]) -> [47: bb12, 33: bb11, otherwise: bb7];
- }
-
- bb11: {
_0 = const true;
- goto -> bb14;
+ goto -> bb12;
}
- bb12: {
- _0 = const true;
- goto -> bb14;
- }
-
- bb13: {
+ bb11: {
_0 = const false;
- goto -> bb14;
+ goto -> bb12;
}
- bb14: {
+ bb12: {
StorageDead(_2);
return;
}
}

View file

@ -1,17 +0,0 @@
// skip-filecheck
// EMIT_MIR_FOR_EACH_PANIC_STRATEGY
//@ test-mir-pass: DeduplicateBlocks
// EMIT_MIR deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.diff
pub const fn is_line_doc_comment_2(s: &str) -> bool {
match s.as_bytes() {
[b'/', b'/', b'/', b'/', ..] => false,
[b'/', b'/', b'/', ..] => true,
[b'/', b'/', b'!', ..] => true,
_ => false,
}
}
fn main() {
is_line_doc_comment_2("asd");
}

View file

@ -3,6 +3,8 @@ error: invalid register class `foo`: unknown register class
|
LL | asm!("{}", in(foo) foo);
| ^^^^^^^^^^^
|
= note: the following register classes are supported on this target: `reg`, `vreg`, `vreg_low16`, `preg`
error: invalid register `foo`: unknown register
--> $DIR/bad-reg.rs:14:18

View file

@ -3,6 +3,8 @@ error: invalid register class `foo`: unknown register class
|
LL | asm!("{}", in(foo) foo);
| ^^^^^^^^^^^
|
= note: the following register classes are supported on this target: `reg`, `reg_abcd`, `reg_byte`, `xmm_reg`, `ymm_reg`, `zmm_reg`, `kreg`, `kreg0`, `mmx_reg`, `x87_reg`, `tmm_reg`
error: invalid register `foo`: unknown register
--> $DIR/bad-reg.rs:14:18

View file

@ -3,12 +3,16 @@ error: invalid register class `vreg`: unknown register class
|
LL | asm!("add {:d}, {:d}, d0", out(vreg) c, in(vreg) a, in("d0") {
| ^^^^^^^^^^^
|
= note: the following register classes are supported on this target: `reg`, `reg_abcd`, `reg_byte`, `xmm_reg`, `ymm_reg`, `zmm_reg`, `kreg`, `kreg0`, `mmx_reg`, `x87_reg`, `tmm_reg`
error: invalid register class `vreg`: unknown register class
--> $DIR/issue-82869.rs:11:45
|
LL | asm!("add {:d}, {:d}, d0", out(vreg) c, in(vreg) a, in("d0") {
| ^^^^^^^^^^
|
= note: the following register classes are supported on this target: `reg`, `reg_abcd`, `reg_byte`, `xmm_reg`, `ymm_reg`, `zmm_reg`, `kreg`, `kreg0`, `mmx_reg`, `x87_reg`, `tmm_reg`
error: invalid register `d0`: unknown register
--> $DIR/issue-82869.rs:11:57