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:
commit
34a5ea911c
46 changed files with 225 additions and 556 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
},
|
||||
|
|
|
@ -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)]
|
||||
|
|
|
@ -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 { .. });
|
||||
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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<()>
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>,
|
||||
>()];
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 => "-",
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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,
|
||||
|
|
|
@ -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:?}",
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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`.
|
||||
//!
|
||||
|
|
|
@ -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)?)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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))]
|
||||
|
|
|
@ -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>>(
|
||||
|
|
|
@ -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
|
||||
///
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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`.
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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");
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue