"jemalloc-sys",
"rustc_codegen_ssa",
"rustc_driver",
+ "rustc_driver_impl",
"rustc_smir",
]
[[package]]
name = "rustc_driver"
version = "0.0.0"
+dependencies = [
+ "rustc_driver_impl",
+]
+
+[[package]]
+name = "rustc_driver_impl"
+version = "0.0.0"
dependencies = [
"libc",
"rustc_ast",
[dependencies]
rustc_driver = { path = "../rustc_driver" }
+rustc_driver_impl = { path = "../rustc_driver_impl" }
# Make sure rustc_codegen_ssa ends up in the sysroot, because this
# crate is intended to be used by codegen backends, which may not be in-tree.
[features]
jemalloc = ['jemalloc-sys']
-llvm = ['rustc_driver/llvm']
-max_level_info = ['rustc_driver/max_level_info']
-rustc_use_parallel_compiler = ['rustc_driver/rustc_use_parallel_compiler']
+llvm = ['rustc_driver_impl/llvm']
+max_level_info = ['rustc_driver_impl/max_level_info']
+rustc_use_parallel_compiler = ['rustc_driver_impl/rustc_use_parallel_compiler']
operands,
) = rvalue
{
+ let def_id = def_id.expect_local();
for operand in operands {
let (Operand::Copy(assigned_from) | Operand::Move(assigned_from)) = operand else {
continue;
// into a place then we should annotate the closure in
// case it ends up being assigned into the return place.
annotated_closure =
- self.annotate_fn_sig(*def_id, substs.as_closure().sig());
+ self.annotate_fn_sig(def_id, substs.as_closure().sig());
debug!(
"annotate_argument_and_return_for_borrow: \
annotated_closure={:?} assigned_from_local={:?} \
&& let AggregateKind::Closure(def_id, _) | AggregateKind::Generator(def_id, _, _) = **kind
{
debug!("move_spans: def_id={:?} places={:?}", def_id, places);
+ let def_id = def_id.expect_local();
if let Some((args_span, generator_kind, capture_kind_span, path_span)) =
self.closure_span(def_id, moved_place, places)
{
box AggregateKind::Generator(def_id, _, _) => (def_id, true),
_ => continue,
};
+ let def_id = def_id.expect_local();
debug!(
"borrow_spans: def_id={:?} is_generator={:?} places={:?}",
}
}
Some((false, err_label_span, message)) => {
- err.span_label(
- err_label_span,
- &format!(
- "consider changing this binding's type to be: `{message}`"
- ),
- );
+ struct BindingFinder {
+ span: Span,
+ hir_id: Option<hir::HirId>,
+ }
+
+ impl<'tcx> Visitor<'tcx> for BindingFinder {
+ fn visit_stmt(&mut self, s: &'tcx hir::Stmt<'tcx>) {
+ if let hir::StmtKind::Local(local) = s.kind {
+ if local.pat.span == self.span {
+ self.hir_id = Some(local.hir_id);
+ }
+ }
+ hir::intravisit::walk_stmt(self, s);
+ }
+ }
+ let hir_map = self.infcx.tcx.hir();
+ let def_id = self.body.source.def_id();
+ let hir_id = hir_map.local_def_id_to_hir_id(def_id.expect_local());
+ let node = hir_map.find(hir_id);
+ let hir_id = if let Some(hir::Node::Item(item)) = node
+ && let hir::ItemKind::Fn(.., body_id) = item.kind
+ {
+ let body = hir_map.body(body_id);
+ let mut v = BindingFinder {
+ span: err_label_span,
+ hir_id: None,
+ };
+ v.visit_body(body);
+ v.hir_id
+ } else {
+ None
+ };
+ if let Some(hir_id) = hir_id
+ && let Some(hir::Node::Local(local)) = hir_map.find(hir_id)
+ {
+ let (changing, span, sugg) = match local.ty {
+ Some(ty) => ("changing", ty.span, message),
+ None => (
+ "specifying",
+ local.pat.span.shrink_to_hi(),
+ format!(": {message}"),
+ ),
+ };
+ err.span_suggestion_verbose(
+ span,
+ &format!("consider {changing} this binding's type"),
+ sugg,
+ Applicability::HasPlaceholders,
+ );
+ } else {
+ err.span_label(
+ err_label_span,
+ &format!(
+ "consider changing this binding's type to be: `{message}`"
+ ),
+ );
+ }
}
None => {}
}
// in order to populate our used_mut set.
match **aggregate_kind {
AggregateKind::Closure(def_id, _) | AggregateKind::Generator(def_id, _, _) => {
+ let def_id = def_id.expect_local();
let BorrowCheckResult { used_mut_upvars, .. } =
self.infcx.tcx.mir_borrowck(def_id);
debug!("{:?} used_mut_upvars={:?}", def_id, used_mut_upvars);
// clauses on the struct.
AggregateKind::Closure(def_id, substs)
| AggregateKind::Generator(def_id, substs, _) => {
- (def_id.to_def_id(), self.prove_closure_bounds(tcx, def_id, substs, location))
+ (def_id, self.prove_closure_bounds(tcx, def_id.expect_local(), substs, location))
}
AggregateKind::Array(_) | AggregateKind::Tuple => {
use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf};
use rustc_middle::ty::{self, adjustment::PointerCast, Instance, Ty, TyCtxt};
use rustc_span::source_map::{Span, DUMMY_SP};
+use rustc_target::abi::VariantIdx;
impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
#[instrument(level = "trace", skip(self, bx))]
}
mir::Rvalue::Aggregate(ref kind, ref operands) => {
- let (dest, active_field_index) = match **kind {
- mir::AggregateKind::Adt(adt_did, variant_index, _, _, active_field_index) => {
- dest.codegen_set_discr(bx, variant_index);
- if bx.tcx().adt_def(adt_did).is_enum() {
- (dest.project_downcast(bx, variant_index), active_field_index)
- } else {
- (dest, active_field_index)
- }
+ let (variant_index, variant_dest, active_field_index) = match **kind {
+ mir::AggregateKind::Adt(_, variant_index, _, _, active_field_index) => {
+ let variant_dest = dest.project_downcast(bx, variant_index);
+ (variant_index, variant_dest, active_field_index)
}
- _ => (dest, None),
+ _ => (VariantIdx::from_u32(0), dest, None),
};
+ if active_field_index.is_some() {
+ assert_eq!(operands.len(), 1);
+ }
for (i, operand) in operands.iter().enumerate() {
let op = self.codegen_operand(bx, operand);
// Do not generate stores and GEPis for zero-sized fields.
let field_index = active_field_index.unwrap_or(i);
let field = if let mir::AggregateKind::Array(_) = **kind {
let llindex = bx.cx().const_usize(field_index as u64);
- dest.project_index(bx, llindex)
+ variant_dest.project_index(bx, llindex)
} else {
- dest.project_field(bx, field_index)
+ variant_dest.project_field(bx, field_index)
};
op.val.store(bx, field);
}
}
+ dest.codegen_set_discr(bx, variant_index);
}
_ => {
variant_index: VariantIdx,
dest: &PlaceTy<'tcx, M::Provenance>,
) -> InterpResult<'tcx> {
- // This must be an enum or generator.
- match dest.layout.ty.kind() {
- ty::Adt(adt, _) => assert!(adt.is_enum()),
- ty::Generator(..) => {}
- _ => span_bug!(
- self.cur_span(),
- "write_discriminant called on non-variant-type (neither enum nor generator)"
- ),
- }
// Layout computation excludes uninhabited variants from consideration
// therefore there's no way to represent those variants in the given layout.
// Essentially, uninhabited variants do not have a tag that corresponds to their
Ok(())
}
+ /// Writes the discriminant of the given variant.
+ #[instrument(skip(self), level = "debug")]
+ pub fn write_aggregate(
+ &mut self,
+ kind: &mir::AggregateKind<'tcx>,
+ operands: &[mir::Operand<'tcx>],
+ dest: &PlaceTy<'tcx, M::Provenance>,
+ ) -> InterpResult<'tcx> {
+ self.write_uninit(&dest)?;
+ let (variant_index, variant_dest, active_field_index) = match *kind {
+ mir::AggregateKind::Adt(_, variant_index, _, _, active_field_index) => {
+ let variant_dest = self.place_downcast(&dest, variant_index)?;
+ (variant_index, variant_dest, active_field_index)
+ }
+ _ => (VariantIdx::from_u32(0), dest.clone(), None),
+ };
+ if active_field_index.is_some() {
+ assert_eq!(operands.len(), 1);
+ }
+ for (field_index, operand) in operands.iter().enumerate() {
+ let field_index = active_field_index.unwrap_or(field_index);
+ let field_dest = self.place_field(&variant_dest, field_index)?;
+ let op = self.eval_operand(operand, Some(field_dest.layout))?;
+ self.copy_op(&op, &field_dest, /*allow_transmute*/ false)?;
+ }
+ self.write_discriminant(variant_index, &dest)
+ }
+
pub fn raw_const_to_mplace(
&self,
raw: ConstAlloc<'tcx>,
}
Aggregate(box ref kind, ref operands) => {
- assert!(matches!(kind, mir::AggregateKind::Array(..)));
-
- for (field_index, operand) in operands.iter().enumerate() {
- let op = self.eval_operand(operand, None)?;
- let field_dest = self.place_field(&dest, field_index)?;
- self.copy_op(&op, &field_dest, /*allow_transmute*/ false)?;
- }
+ self.write_aggregate(kind, operands, &dest)?;
}
Repeat(ref operand, _) => {
Rvalue::Aggregate(kind, ..) => {
if let AggregateKind::Generator(def_id, ..) = kind.as_ref()
- && let Some(generator_kind @ hir::GeneratorKind::Async(..)) = self.tcx.generator_kind(def_id.to_def_id())
+ && let Some(generator_kind @ hir::GeneratorKind::Async(..)) = self.tcx.generator_kind(def_id)
{
self.check_op(ops::Generator(generator_kind));
}
use rustc_trait_selection::traits::SelectionContext;
use super::ConstCx;
-use crate::errors::{
- InteriorMutabilityBorrow, InteriorMutableDataRefer, MutDerefErr, NonConstFmtMacroCall,
- NonConstFnCall, NonConstOpErr, PanicNonStrErr, RawPtrToIntErr, StaticAccessErr,
- TransientMutBorrowErr, TransientMutBorrowErrRaw, UnallowedFnPointerCall,
- UnallowedHeapAllocations, UnallowedInlineAsm, UnallowedMutableRefs, UnallowedMutableRefsRaw,
- UnallowedOpInConstContext, UnstableConstFn,
-};
+use crate::errors;
use crate::util::{call_kind, CallDesugaringKind, CallKind};
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
ccx: &ConstCx<'_, 'tcx>,
span: Span,
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
- ccx.tcx.sess.create_err(UnallowedFnPointerCall { span, kind: ccx.const_kind() })
+ ccx.tcx.sess.create_err(errors::UnallowedFnPointerCall { span, kind: ccx.const_kind() })
}
}
diag_trait(&mut err, self_ty, tcx.require_lang_item(LangItem::Deref, Some(span)));
err
}
- _ if tcx.opt_parent(callee) == tcx.get_diagnostic_item(sym::ArgumentV1Methods) => {
- ccx.tcx.sess.create_err(NonConstFmtMacroCall { span, kind: ccx.const_kind() })
- }
- _ => ccx.tcx.sess.create_err(NonConstFnCall {
+ _ if tcx.opt_parent(callee) == tcx.get_diagnostic_item(sym::ArgumentV1Methods) => ccx
+ .tcx
+ .sess
+ .create_err(errors::NonConstFmtMacroCall { span, kind: ccx.const_kind() }),
+ _ => ccx.tcx.sess.create_err(errors::NonConstFnCall {
span,
def_path_str: ccx.tcx.def_path_str_with_substs(callee, substs),
kind: ccx.const_kind(),
let mut err = ccx
.tcx
.sess
- .create_err(UnstableConstFn { span, def_path: ccx.tcx.def_path_str(def_id) });
+ .create_err(errors::UnstableConstFn { span, def_path: ccx.tcx.def_path_str(def_id) });
if ccx.is_const_stable_const_fn() {
err.help("const-stable functions can only call other const-stable functions");
let msg = format!("{}s are not allowed in {}s", self.0.descr(), ccx.const_kind());
if let hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Block) = self.0 {
ccx.tcx.sess.create_feature_err(
- UnallowedOpInConstContext { span, msg },
+ errors::UnallowedOpInConstContext { span, msg },
sym::const_async_blocks,
)
} else {
- ccx.tcx.sess.create_err(UnallowedOpInConstContext { span, msg })
+ ccx.tcx.sess.create_err(errors::UnallowedOpInConstContext { span, msg })
}
}
}
ccx: &ConstCx<'_, 'tcx>,
span: Span,
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
- ccx.tcx.sess.create_err(UnallowedHeapAllocations {
+ ccx.tcx.sess.create_err(errors::UnallowedHeapAllocations {
span,
kind: ccx.const_kind(),
teach: ccx.tcx.sess.teach(&error_code!(E0010)).then_some(()),
ccx: &ConstCx<'_, 'tcx>,
span: Span,
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
- ccx.tcx.sess.create_err(UnallowedInlineAsm { span, kind: ccx.const_kind() })
+ ccx.tcx.sess.create_err(errors::UnallowedInlineAsm { span, kind: ccx.const_kind() })
}
}
ccx: &ConstCx<'_, 'tcx>,
span: Span,
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
- ccx.tcx.sess.create_feature_err(InteriorMutabilityBorrow { span }, sym::const_refs_to_cell)
+ ccx.tcx
+ .sess
+ .create_feature_err(errors::InteriorMutabilityBorrow { span }, sym::const_refs_to_cell)
}
}
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
// FIXME: Maybe a more elegant solution to this if else case
if let hir::ConstContext::Static(_) = ccx.const_kind() {
- ccx.tcx.sess.create_err(InteriorMutableDataRefer {
+ ccx.tcx.sess.create_err(errors::InteriorMutableDataRefer {
span,
opt_help: Some(()),
kind: ccx.const_kind(),
teach: ccx.tcx.sess.teach(&error_code!(E0492)).then_some(()),
})
} else {
- ccx.tcx.sess.create_err(InteriorMutableDataRefer {
+ ccx.tcx.sess.create_err(errors::InteriorMutableDataRefer {
span,
opt_help: None,
kind: ccx.const_kind(),
span: Span,
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
match self.0 {
- hir::BorrowKind::Raw => ccx.tcx.sess.create_err(UnallowedMutableRefsRaw {
+ hir::BorrowKind::Raw => ccx.tcx.sess.create_err(errors::UnallowedMutableRefsRaw {
span,
kind: ccx.const_kind(),
teach: ccx.tcx.sess.teach(&error_code!(E0764)).then_some(()),
}),
- hir::BorrowKind::Ref => ccx.tcx.sess.create_err(UnallowedMutableRefs {
+ hir::BorrowKind::Ref => ccx.tcx.sess.create_err(errors::UnallowedMutableRefs {
span,
kind: ccx.const_kind(),
teach: ccx.tcx.sess.teach(&error_code!(E0764)).then_some(()),
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
let kind = ccx.const_kind();
match self.0 {
- hir::BorrowKind::Raw => ccx
- .tcx
- .sess
- .create_feature_err(TransientMutBorrowErrRaw { span, kind }, sym::const_mut_refs),
- hir::BorrowKind::Ref => ccx
- .tcx
- .sess
- .create_feature_err(TransientMutBorrowErr { span, kind }, sym::const_mut_refs),
+ hir::BorrowKind::Raw => ccx.tcx.sess.create_feature_err(
+ errors::TransientMutBorrowErrRaw { span, kind },
+ sym::const_mut_refs,
+ ),
+ hir::BorrowKind::Ref => ccx.tcx.sess.create_feature_err(
+ errors::TransientMutBorrowErr { span, kind },
+ sym::const_mut_refs,
+ ),
}
}
}
ccx: &ConstCx<'_, 'tcx>,
span: Span,
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
- ccx.tcx
- .sess
- .create_feature_err(MutDerefErr { span, kind: ccx.const_kind() }, sym::const_mut_refs)
+ ccx.tcx.sess.create_feature_err(
+ errors::MutDerefErr { span, kind: ccx.const_kind() },
+ sym::const_mut_refs,
+ )
}
}
ccx: &ConstCx<'_, 'tcx>,
span: Span,
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
- ccx.tcx.sess.create_err(PanicNonStrErr { span })
+ ccx.tcx.sess.create_err(errors::PanicNonStrErr { span })
}
}
ccx: &ConstCx<'_, 'tcx>,
span: Span,
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
- ccx.tcx.sess.create_err(RawPtrToIntErr { span })
+ ccx.tcx.sess.create_err(errors::RawPtrToIntErr { span })
}
}
ccx: &ConstCx<'_, 'tcx>,
span: Span,
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
- ccx.tcx.sess.create_err(StaticAccessErr {
+ ccx.tcx.sess.create_err(errors::StaticAccessErr {
span,
kind: ccx.const_kind(),
teach: ccx.tcx.sess.teach(&error_code!(E0013)).then_some(()),
ccx: &ConstCx<'_, 'tcx>,
span: Span,
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
- ccx.tcx.sess.create_err(NonConstOpErr { span })
+ ccx.tcx.sess.create_err(errors::NonConstOpErr { span })
}
}
use rustc_middle::mir::visit::NonUseContext::VarDebugInfo;
use rustc_middle::mir::visit::{PlaceContext, Visitor};
use rustc_middle::mir::{
- traversal, AggregateKind, BasicBlock, BinOp, Body, BorrowKind, CastKind, CopyNonOverlapping,
- Local, Location, MirPass, MirPhase, NonDivergingIntrinsic, Operand, Place, PlaceElem, PlaceRef,
- ProjectionElem, RetagKind, RuntimePhase, Rvalue, SourceScope, Statement, StatementKind,
- Terminator, TerminatorKind, UnOp, START_BLOCK,
+ traversal, BasicBlock, BinOp, Body, BorrowKind, CastKind, CopyNonOverlapping, Local, Location,
+ MirPass, MirPhase, NonDivergingIntrinsic, Operand, Place, PlaceElem, PlaceRef, ProjectionElem,
+ RetagKind, RuntimePhase, Rvalue, SourceScope, Statement, StatementKind, Terminator,
+ TerminatorKind, UnOp, START_BLOCK,
};
use rustc_middle::ty::{self, InstanceDef, ParamEnv, Ty, TyCtxt};
use rustc_mir_dataflow::impls::MaybeStorageLive;
};
}
match rvalue {
- Rvalue::Use(_) | Rvalue::CopyForDeref(_) => {}
- Rvalue::Aggregate(agg_kind, _) => {
- let disallowed = match **agg_kind {
- AggregateKind::Array(..) => false,
- _ => self.mir_phase >= MirPhase::Runtime(RuntimePhase::PostCleanup),
- };
- if disallowed {
- self.fail(
- location,
- format!("{:?} have been lowered to field assignments", rvalue),
- )
- }
- }
+ Rvalue::Use(_) | Rvalue::CopyForDeref(_) | Rvalue::Aggregate(..) => {}
Rvalue::Ref(_, BorrowKind::Shallow, _) => {
if self.mir_phase >= MirPhase::Runtime(RuntimePhase::Initial) {
self.fail(
+++ /dev/null
-use rustc_index::vec::Idx;
-use rustc_middle::mir::*;
-use rustc_middle::ty::{Ty, TyCtxt};
-use rustc_target::abi::VariantIdx;
-
-use std::iter::TrustedLen;
-
-/// Expand `lhs = Rvalue::Aggregate(kind, operands)` into assignments to the fields.
-///
-/// Produces something like
-/// ```ignore (ilustrative)
-/// (lhs as Variant).field0 = arg0; // We only have a downcast if this is an enum
-/// (lhs as Variant).field1 = arg1;
-/// discriminant(lhs) = variant_index; // If lhs is an enum or generator.
-/// ```
-pub fn expand_aggregate<'tcx>(
- orig_lhs: Place<'tcx>,
- operands: impl Iterator<Item = (Operand<'tcx>, Ty<'tcx>)> + TrustedLen,
- kind: AggregateKind<'tcx>,
- source_info: SourceInfo,
- tcx: TyCtxt<'tcx>,
-) -> impl Iterator<Item = Statement<'tcx>> + TrustedLen {
- let mut lhs = orig_lhs;
- let mut set_discriminant = None;
- let active_field_index = match kind {
- AggregateKind::Adt(adt_did, variant_index, _, _, active_field_index) => {
- let adt_def = tcx.adt_def(adt_did);
- if adt_def.is_enum() {
- set_discriminant = Some(Statement {
- kind: StatementKind::SetDiscriminant {
- place: Box::new(orig_lhs),
- variant_index,
- },
- source_info,
- });
- lhs = tcx.mk_place_downcast(orig_lhs, adt_def, variant_index);
- }
- active_field_index
- }
- AggregateKind::Generator(..) => {
- // Right now we only support initializing generators to
- // variant 0 (Unresumed).
- let variant_index = VariantIdx::new(0);
- set_discriminant = Some(Statement {
- kind: StatementKind::SetDiscriminant { place: Box::new(orig_lhs), variant_index },
- source_info,
- });
-
- // Operands are upvars stored on the base place, so no
- // downcast is necessary.
-
- None
- }
- _ => None,
- };
-
- let operands = operands.enumerate().map(move |(i, (op, ty))| {
- let lhs_field = if let AggregateKind::Array(_) = kind {
- let offset = u64::try_from(i).unwrap();
- tcx.mk_place_elem(
- lhs,
- ProjectionElem::ConstantIndex { offset, min_length: offset + 1, from_end: false },
- )
- } else {
- let field = Field::new(active_field_index.unwrap_or(i));
- tcx.mk_place_field(lhs, field, ty)
- };
- Statement {
- source_info,
- kind: StatementKind::Assign(Box::new((lhs_field, Rvalue::Use(op)))),
- }
- });
- [Statement { source_info, kind: StatementKind::Deinit(Box::new(orig_lhs)) }]
- .into_iter()
- .chain(operands)
- .chain(set_discriminant)
-}
-pub mod aggregate;
mod alignment;
mod call_kind;
pub mod collect_writes;
mod might_permit_raw_init;
mod type_name;
-pub use self::aggregate::expand_aggregate;
pub use self::alignment::is_disaligned;
pub use self::call_kind::{call_kind, CallDesugaringKind, CallKind};
pub use self::compare_types::{is_equal_up_to_subtyping, is_subtype};
crate-type = ["dylib"]
[dependencies]
-tracing = { version = "0.1.35" }
-serde_json = "1.0.59"
-rustc_log = { path = "../rustc_log" }
-rustc_middle = { path = "../rustc_middle" }
-rustc_ast_pretty = { path = "../rustc_ast_pretty" }
-rustc_target = { path = "../rustc_target" }
-rustc_lint = { path = "../rustc_lint" }
-rustc_data_structures = { path = "../rustc_data_structures" }
-rustc_errors = { path = "../rustc_errors" }
-rustc_feature = { path = "../rustc_feature" }
-rustc_hir = { path = "../rustc_hir" }
-rustc_hir_pretty = { path = "../rustc_hir_pretty" }
-rustc_macros = { path = "../rustc_macros" }
-rustc_metadata = { path = "../rustc_metadata" }
-rustc_parse = { path = "../rustc_parse" }
-rustc_plugin_impl = { path = "../rustc_plugin_impl" }
-rustc_save_analysis = { path = "../rustc_save_analysis" }
-rustc_codegen_ssa = { path = "../rustc_codegen_ssa" }
-rustc_session = { path = "../rustc_session" }
-rustc_error_codes = { path = "../rustc_error_codes" }
-rustc_interface = { path = "../rustc_interface" }
-rustc_ast = { path = "../rustc_ast" }
-rustc_span = { path = "../rustc_span" }
-rustc_hir_analysis = { path = "../rustc_hir_analysis" }
-
-[target.'cfg(unix)'.dependencies]
-libc = "0.2"
-
-[target.'cfg(windows)'.dependencies]
-winapi = { version = "0.3", features = ["consoleapi", "debugapi", "processenv"] }
-
-[features]
-llvm = ['rustc_interface/llvm']
-max_level_info = ['rustc_log/max_level_info']
-rustc_use_parallel_compiler = ['rustc_data_structures/rustc_use_parallel_compiler', 'rustc_interface/rustc_use_parallel_compiler',
- 'rustc_middle/rustc_use_parallel_compiler']
+rustc_driver_impl = { path = "../rustc_driver_impl" }
+++ /dev/null
-The `driver` crate is effectively the "main" function for the rust
-compiler. It orchestrates the compilation process and "knits together"
-the code from the other crates within rustc. This crate itself does
-not contain any of the "main logic" of the compiler (though it does
-have some code related to pretty printing or other minor compiler
-options).
-
-For more information about how the driver works, see the [rustc dev guide].
-
-[rustc dev guide]: https://rustc-dev-guide.rust-lang.org/rustc-driver.html
+++ /dev/null
-use std::error;
-use std::fmt;
-use std::fs;
-use std::io;
-
-fn arg_expand(arg: String) -> Result<Vec<String>, Error> {
- if let Some(path) = arg.strip_prefix('@') {
- let file = match fs::read_to_string(path) {
- Ok(file) => file,
- Err(ref err) if err.kind() == io::ErrorKind::InvalidData => {
- return Err(Error::Utf8Error(Some(path.to_string())));
- }
- Err(err) => return Err(Error::IOError(path.to_string(), err)),
- };
- Ok(file.lines().map(ToString::to_string).collect())
- } else {
- Ok(vec![arg])
- }
-}
-
-pub fn arg_expand_all(at_args: &[String]) -> Vec<String> {
- let mut args = Vec::new();
- for arg in at_args {
- match arg_expand(arg.clone()) {
- Ok(arg) => args.extend(arg),
- Err(err) => rustc_session::early_error(
- rustc_session::config::ErrorOutputType::default(),
- &format!("Failed to load argument file: {err}"),
- ),
- }
- }
- args
-}
-
-#[derive(Debug)]
-pub enum Error {
- Utf8Error(Option<String>),
- IOError(String, io::Error),
-}
-
-impl fmt::Display for Error {
- fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
- match self {
- Error::Utf8Error(None) => write!(fmt, "Utf8 error"),
- Error::Utf8Error(Some(path)) => write!(fmt, "Utf8 error in {path}"),
- Error::IOError(path, err) => write!(fmt, "IO Error: {path}: {err}"),
- }
- }
-}
-
-impl error::Error for Error {}
-//! The Rust compiler.
-//!
-//! # Note
-//!
-//! This API is completely unstable and subject to change.
+// This crate is intentionally empty and a rexport of `rustc_driver_impl` to allow the code in
+// `rustc_driver_impl` to be compiled in parallel with other crates.
-#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
-#![feature(is_terminal)]
-#![feature(once_cell)]
-#![feature(decl_macro)]
-#![recursion_limit = "256"]
-#![allow(rustc::potential_query_instability)]
-#![deny(rustc::untranslatable_diagnostic)]
-#![deny(rustc::diagnostic_outside_of_impl)]
-
-#[macro_use]
-extern crate tracing;
-
-pub extern crate rustc_plugin_impl as plugin;
-
-use rustc_ast as ast;
-use rustc_codegen_ssa::{traits::CodegenBackend, CodegenErrors, CodegenResults};
-use rustc_data_structures::profiling::{get_resident_set_size, print_time_passes_entry};
-use rustc_data_structures::sync::SeqCst;
-use rustc_errors::registry::{InvalidErrorCode, Registry};
-use rustc_errors::{ErrorGuaranteed, PResult};
-use rustc_feature::find_gated_cfg;
-use rustc_hir::def_id::LOCAL_CRATE;
-use rustc_interface::util::{self, collect_crate_types, get_codegen_backend};
-use rustc_interface::{interface, Queries};
-use rustc_lint::LintStore;
-use rustc_metadata::locator;
-use rustc_save_analysis as save;
-use rustc_save_analysis::DumpHandler;
-use rustc_session::config::{nightly_options, CG_OPTIONS, Z_OPTIONS};
-use rustc_session::config::{ErrorOutputType, Input, OutputType, PrintRequest, TrimmedDefPaths};
-use rustc_session::cstore::MetadataLoader;
-use rustc_session::getopts;
-use rustc_session::lint::{Lint, LintId};
-use rustc_session::{config, Session};
-use rustc_session::{early_error, early_error_no_abort, early_warn};
-use rustc_span::source_map::{FileLoader, FileName};
-use rustc_span::symbol::sym;
-use rustc_target::json::ToJson;
-
-use std::cmp::max;
-use std::env;
-use std::ffi::OsString;
-use std::fs;
-use std::io::{self, IsTerminal, Read, Write};
-use std::panic::{self, catch_unwind};
-use std::path::PathBuf;
-use std::process::{self, Command, Stdio};
-use std::str;
-use std::sync::LazyLock;
-use std::time::Instant;
-
-pub mod args;
-pub mod pretty;
-mod session_diagnostics;
-
-use crate::session_diagnostics::{
- RLinkEmptyVersionNumber, RLinkEncodingVersionMismatch, RLinkRustcVersionMismatch,
- RLinkWrongFileType, RlinkNotAFile, RlinkUnableToRead,
-};
-
-/// Exit status code used for successful compilation and help output.
-pub const EXIT_SUCCESS: i32 = 0;
-
-/// Exit status code used for compilation failures and invalid flags.
-pub const EXIT_FAILURE: i32 = 1;
-
-const BUG_REPORT_URL: &str = "https://github.com/rust-lang/rust/issues/new\
- ?labels=C-bug%2C+I-ICE%2C+T-compiler&template=ice.md";
-
-const ICE_REPORT_COMPILER_FLAGS: &[&str] = &["-Z", "-C", "--crate-type"];
-
-const ICE_REPORT_COMPILER_FLAGS_EXCLUDE: &[&str] = &["metadata", "extra-filename"];
-
-const ICE_REPORT_COMPILER_FLAGS_STRIP_VALUE: &[&str] = &["incremental"];
-
-pub fn abort_on_err<T>(result: Result<T, ErrorGuaranteed>, sess: &Session) -> T {
- match result {
- Err(..) => {
- sess.abort_if_errors();
- panic!("error reported but abort_if_errors didn't abort???");
- }
- Ok(x) => x,
- }
-}
-
-pub trait Callbacks {
- /// Called before creating the compiler instance
- fn config(&mut self, _config: &mut interface::Config) {}
- /// Called after parsing. Return value instructs the compiler whether to
- /// continue the compilation afterwards (defaults to `Compilation::Continue`)
- fn after_parsing<'tcx>(
- &mut self,
- _compiler: &interface::Compiler,
- _queries: &'tcx Queries<'tcx>,
- ) -> Compilation {
- Compilation::Continue
- }
- /// Called after expansion. Return value instructs the compiler whether to
- /// continue the compilation afterwards (defaults to `Compilation::Continue`)
- fn after_expansion<'tcx>(
- &mut self,
- _compiler: &interface::Compiler,
- _queries: &'tcx Queries<'tcx>,
- ) -> Compilation {
- Compilation::Continue
- }
- /// Called after analysis. Return value instructs the compiler whether to
- /// continue the compilation afterwards (defaults to `Compilation::Continue`)
- fn after_analysis<'tcx>(
- &mut self,
- _compiler: &interface::Compiler,
- _queries: &'tcx Queries<'tcx>,
- ) -> Compilation {
- Compilation::Continue
- }
-}
-
-#[derive(Default)]
-pub struct TimePassesCallbacks {
- time_passes: bool,
-}
-
-impl Callbacks for TimePassesCallbacks {
- // JUSTIFICATION: the session doesn't exist at this point.
- #[allow(rustc::bad_opt_access)]
- fn config(&mut self, config: &mut interface::Config) {
- // If a --print=... option has been given, we don't print the "total"
- // time because it will mess up the --print output. See #64339.
- //
- self.time_passes = config.opts.prints.is_empty() && config.opts.unstable_opts.time_passes;
- config.opts.trimmed_def_paths = TrimmedDefPaths::GoodPath;
- }
-}
-
-pub fn diagnostics_registry() -> Registry {
- Registry::new(rustc_error_codes::DIAGNOSTICS)
-}
-
-/// This is the primary entry point for rustc.
-pub struct RunCompiler<'a, 'b> {
- at_args: &'a [String],
- callbacks: &'b mut (dyn Callbacks + Send),
- file_loader: Option<Box<dyn FileLoader + Send + Sync>>,
- make_codegen_backend:
- Option<Box<dyn FnOnce(&config::Options) -> Box<dyn CodegenBackend> + Send>>,
-}
-
-impl<'a, 'b> RunCompiler<'a, 'b> {
- pub fn new(at_args: &'a [String], callbacks: &'b mut (dyn Callbacks + Send)) -> Self {
- Self { at_args, callbacks, file_loader: None, make_codegen_backend: None }
- }
-
- /// Set a custom codegen backend.
- ///
- /// Has no uses within this repository, but is used by bjorn3 for "the
- /// hotswapping branch of cg_clif" for "setting the codegen backend from a
- /// custom driver where the custom codegen backend has arbitrary data."
- /// (See #102759.)
- pub fn set_make_codegen_backend(
- &mut self,
- make_codegen_backend: Option<
- Box<dyn FnOnce(&config::Options) -> Box<dyn CodegenBackend> + Send>,
- >,
- ) -> &mut Self {
- self.make_codegen_backend = make_codegen_backend;
- self
- }
-
- /// Load files from sources other than the file system.
- ///
- /// Has no uses within this repository, but may be used in the future by
- /// bjorn3 for "hooking rust-analyzer's VFS into rustc at some point for
- /// running rustc without having to save". (See #102759.)
- pub fn set_file_loader(
- &mut self,
- file_loader: Option<Box<dyn FileLoader + Send + Sync>>,
- ) -> &mut Self {
- self.file_loader = file_loader;
- self
- }
-
- /// Parse args and run the compiler.
- pub fn run(self) -> interface::Result<()> {
- run_compiler(self.at_args, self.callbacks, self.file_loader, self.make_codegen_backend)
- }
-}
-
-fn run_compiler(
- at_args: &[String],
- callbacks: &mut (dyn Callbacks + Send),
- file_loader: Option<Box<dyn FileLoader + Send + Sync>>,
- make_codegen_backend: Option<
- Box<dyn FnOnce(&config::Options) -> Box<dyn CodegenBackend> + Send>,
- >,
-) -> interface::Result<()> {
- let args = args::arg_expand_all(at_args);
-
- let Some(matches) = handle_options(&args) else { return Ok(()) };
-
- let sopts = config::build_session_options(&matches);
-
- if let Some(ref code) = matches.opt_str("explain") {
- handle_explain(diagnostics_registry(), code, sopts.error_format);
- return Ok(());
- }
-
- let cfg = interface::parse_cfgspecs(matches.opt_strs("cfg"));
- let check_cfg = interface::parse_check_cfg(matches.opt_strs("check-cfg"));
- let (odir, ofile) = make_output(&matches);
- let mut config = interface::Config {
- opts: sopts,
- crate_cfg: cfg,
- crate_check_cfg: check_cfg,
- input: Input::File(PathBuf::new()),
- output_file: ofile,
- output_dir: odir,
- file_loader,
- lint_caps: Default::default(),
- parse_sess_created: None,
- register_lints: None,
- override_queries: None,
- make_codegen_backend,
- registry: diagnostics_registry(),
- };
-
- if !tracing::dispatcher::has_been_set() {
- init_rustc_env_logger_with_backtrace_option(&config.opts.unstable_opts.log_backtrace);
- }
-
- match make_input(config.opts.error_format, &matches.free) {
- Err(reported) => return Err(reported),
- Ok(Some(input)) => {
- config.input = input;
-
- callbacks.config(&mut config);
- }
- Ok(None) => match matches.free.len() {
- 0 => {
- callbacks.config(&mut config);
- interface::run_compiler(config, |compiler| {
- let sopts = &compiler.session().opts;
- if sopts.describe_lints {
- let mut lint_store =
- rustc_lint::new_lint_store(compiler.session().enable_internal_lints());
- let registered_lints =
- if let Some(register_lints) = compiler.register_lints() {
- register_lints(compiler.session(), &mut lint_store);
- true
- } else {
- false
- };
- describe_lints(compiler.session(), &lint_store, registered_lints);
- return;
- }
- let should_stop =
- print_crate_info(&***compiler.codegen_backend(), compiler.session(), false);
-
- if should_stop == Compilation::Stop {
- return;
- }
- early_error(sopts.error_format, "no input filename given")
- });
- return Ok(());
- }
- 1 => panic!("make_input should have provided valid inputs"),
- _ => early_error(
- config.opts.error_format,
- &format!(
- "multiple input filenames provided (first two filenames are `{}` and `{}`)",
- matches.free[0], matches.free[1],
- ),
- ),
- },
- };
-
- interface::run_compiler(config, |compiler| {
- let sess = compiler.session();
- let should_stop = print_crate_info(&***compiler.codegen_backend(), sess, true)
- .and_then(|| list_metadata(sess, &*compiler.codegen_backend().metadata_loader()))
- .and_then(|| try_process_rlink(sess, compiler));
-
- if should_stop == Compilation::Stop {
- return sess.compile_status();
- }
-
- let linker = compiler.enter(|queries| {
- let early_exit = || sess.compile_status().map(|_| None);
- queries.parse()?;
-
- if let Some(ppm) = &sess.opts.pretty {
- if ppm.needs_ast_map() {
- queries.global_ctxt()?.enter(|tcx| {
- pretty::print_after_hir_lowering(tcx, *ppm);
- Ok(())
- })?;
- } else {
- let krate = queries.parse()?.steal();
- pretty::print_after_parsing(sess, &krate, *ppm);
- }
- trace!("finished pretty-printing");
- return early_exit();
- }
-
- if callbacks.after_parsing(compiler, queries) == Compilation::Stop {
- return early_exit();
- }
-
- if sess.opts.unstable_opts.parse_only || sess.opts.unstable_opts.show_span.is_some() {
- return early_exit();
- }
-
- {
- let plugins = queries.register_plugins()?;
- let (_, lint_store) = &*plugins.borrow();
-
- // Lint plugins are registered; now we can process command line flags.
- if sess.opts.describe_lints {
- describe_lints(sess, lint_store, true);
- return early_exit();
- }
- }
-
- let mut gctxt = queries.global_ctxt()?;
- if callbacks.after_expansion(compiler, queries) == Compilation::Stop {
- return early_exit();
- }
-
- // Make sure the `output_filenames` query is run for its side
- // effects of writing the dep-info and reporting errors.
- gctxt.enter(|tcx| tcx.output_filenames(()));
-
- if sess.opts.output_types.contains_key(&OutputType::DepInfo)
- && sess.opts.output_types.len() == 1
- {
- return early_exit();
- }
-
- if sess.opts.unstable_opts.no_analysis {
- return early_exit();
- }
-
- gctxt.enter(|tcx| {
- let result = tcx.analysis(());
- if sess.opts.unstable_opts.save_analysis {
- let crate_name = tcx.crate_name(LOCAL_CRATE);
- sess.time("save_analysis", || {
- save::process_crate(
- tcx,
- crate_name,
- &sess.io.input,
- None,
- DumpHandler::new(sess.io.output_dir.as_deref(), crate_name),
- )
- });
- }
- result
- })?;
-
- drop(gctxt);
-
- if callbacks.after_analysis(compiler, queries) == Compilation::Stop {
- return early_exit();
- }
-
- queries.ongoing_codegen()?;
-
- if sess.opts.unstable_opts.print_type_sizes {
- sess.code_stats.print_type_sizes();
- }
-
- let linker = queries.linker()?;
- Ok(Some(linker))
- })?;
-
- if let Some(linker) = linker {
- let _timer = sess.timer("link");
- linker.link()?
- }
-
- if sess.opts.unstable_opts.perf_stats {
- sess.print_perf_stats();
- }
-
- if sess.opts.unstable_opts.print_fuel.is_some() {
- eprintln!(
- "Fuel used by {}: {}",
- sess.opts.unstable_opts.print_fuel.as_ref().unwrap(),
- sess.print_fuel.load(SeqCst)
- );
- }
-
- Ok(())
- })
-}
-
-// Extract output directory and file from matches.
-fn make_output(matches: &getopts::Matches) -> (Option<PathBuf>, Option<PathBuf>) {
- let odir = matches.opt_str("out-dir").map(|o| PathBuf::from(&o));
- let ofile = matches.opt_str("o").map(|o| PathBuf::from(&o));
- (odir, ofile)
-}
-
-// Extract input (string or file and optional path) from matches.
-fn make_input(
- error_format: ErrorOutputType,
- free_matches: &[String],
-) -> Result<Option<Input>, ErrorGuaranteed> {
- if free_matches.len() == 1 {
- let ifile = &free_matches[0];
- if ifile == "-" {
- let mut src = String::new();
- if io::stdin().read_to_string(&mut src).is_err() {
- // Immediately stop compilation if there was an issue reading
- // the input (for example if the input stream is not UTF-8).
- let reported = early_error_no_abort(
- error_format,
- "couldn't read from stdin, as it did not contain valid UTF-8",
- );
- return Err(reported);
- }
- if let Ok(path) = env::var("UNSTABLE_RUSTDOC_TEST_PATH") {
- let line = env::var("UNSTABLE_RUSTDOC_TEST_LINE").expect(
- "when UNSTABLE_RUSTDOC_TEST_PATH is set \
- UNSTABLE_RUSTDOC_TEST_LINE also needs to be set",
- );
- let line = isize::from_str_radix(&line, 10)
- .expect("UNSTABLE_RUSTDOC_TEST_LINE needs to be an number");
- let file_name = FileName::doc_test_source_code(PathBuf::from(path), line);
- Ok(Some(Input::Str { name: file_name, input: src }))
- } else {
- Ok(Some(Input::Str { name: FileName::anon_source_code(&src), input: src }))
- }
- } else {
- Ok(Some(Input::File(PathBuf::from(ifile))))
- }
- } else {
- Ok(None)
- }
-}
-
-/// Whether to stop or continue compilation.
-#[derive(Copy, Clone, Debug, Eq, PartialEq)]
-pub enum Compilation {
- Stop,
- Continue,
-}
-
-impl Compilation {
- pub fn and_then<F: FnOnce() -> Compilation>(self, next: F) -> Compilation {
- match self {
- Compilation::Stop => Compilation::Stop,
- Compilation::Continue => next(),
- }
- }
-}
-
-fn handle_explain(registry: Registry, code: &str, output: ErrorOutputType) {
- let upper_cased_code = code.to_ascii_uppercase();
- let normalised =
- if upper_cased_code.starts_with('E') { upper_cased_code } else { format!("E{code:0>4}") };
- match registry.try_find_description(&normalised) {
- Ok(Some(description)) => {
- let mut is_in_code_block = false;
- let mut text = String::new();
- // Slice off the leading newline and print.
- for line in description.lines() {
- let indent_level =
- line.find(|c: char| !c.is_whitespace()).unwrap_or_else(|| line.len());
- let dedented_line = &line[indent_level..];
- if dedented_line.starts_with("```") {
- is_in_code_block = !is_in_code_block;
- text.push_str(&line[..(indent_level + 3)]);
- } else if is_in_code_block && dedented_line.starts_with("# ") {
- continue;
- } else {
- text.push_str(line);
- }
- text.push('\n');
- }
- if io::stdout().is_terminal() {
- show_content_with_pager(&text);
- } else {
- print!("{text}");
- }
- }
- Ok(None) => {
- early_error(output, &format!("no extended information for {code}"));
- }
- Err(InvalidErrorCode) => {
- early_error(output, &format!("{code} is not a valid error code"));
- }
- }
-}
-
-fn show_content_with_pager(content: &str) {
- let pager_name = env::var_os("PAGER").unwrap_or_else(|| {
- if cfg!(windows) { OsString::from("more.com") } else { OsString::from("less") }
- });
-
- let mut fallback_to_println = false;
-
- match Command::new(pager_name).stdin(Stdio::piped()).spawn() {
- Ok(mut pager) => {
- if let Some(pipe) = pager.stdin.as_mut() {
- if pipe.write_all(content.as_bytes()).is_err() {
- fallback_to_println = true;
- }
- }
-
- if pager.wait().is_err() {
- fallback_to_println = true;
- }
- }
- Err(_) => {
- fallback_to_println = true;
- }
- }
-
- // If pager fails for whatever reason, we should still print the content
- // to standard output
- if fallback_to_println {
- print!("{content}");
- }
-}
-
-pub fn try_process_rlink(sess: &Session, compiler: &interface::Compiler) -> Compilation {
- if sess.opts.unstable_opts.link_only {
- if let Input::File(file) = &sess.io.input {
- // FIXME: #![crate_type] and #![crate_name] support not implemented yet
- sess.init_crate_types(collect_crate_types(sess, &[]));
- let outputs = compiler.build_output_filenames(sess, &[]);
- let rlink_data = fs::read(file).unwrap_or_else(|err| {
- sess.emit_fatal(RlinkUnableToRead { err });
- });
- let codegen_results = match CodegenResults::deserialize_rlink(rlink_data) {
- Ok(codegen) => codegen,
- Err(err) => {
- match err {
- CodegenErrors::WrongFileType => sess.emit_fatal(RLinkWrongFileType),
- CodegenErrors::EmptyVersionNumber => {
- sess.emit_fatal(RLinkEmptyVersionNumber)
- }
- CodegenErrors::EncodingVersionMismatch { version_array, rlink_version } => {
- sess.emit_fatal(RLinkEncodingVersionMismatch {
- version_array,
- rlink_version,
- })
- }
- CodegenErrors::RustcVersionMismatch { rustc_version, current_version } => {
- sess.emit_fatal(RLinkRustcVersionMismatch {
- rustc_version,
- current_version,
- })
- }
- };
- }
- };
- let result = compiler.codegen_backend().link(sess, codegen_results, &outputs);
- abort_on_err(result, sess);
- } else {
- sess.emit_fatal(RlinkNotAFile {})
- }
- Compilation::Stop
- } else {
- Compilation::Continue
- }
-}
-
-pub fn list_metadata(sess: &Session, metadata_loader: &dyn MetadataLoader) -> Compilation {
- if sess.opts.unstable_opts.ls {
- match sess.io.input {
- Input::File(ref ifile) => {
- let path = &(*ifile);
- let mut v = Vec::new();
- locator::list_file_metadata(&sess.target, path, metadata_loader, &mut v).unwrap();
- println!("{}", String::from_utf8(v).unwrap());
- }
- Input::Str { .. } => {
- early_error(ErrorOutputType::default(), "cannot list metadata for stdin");
- }
- }
- return Compilation::Stop;
- }
-
- Compilation::Continue
-}
-
-fn print_crate_info(
- codegen_backend: &dyn CodegenBackend,
- sess: &Session,
- parse_attrs: bool,
-) -> Compilation {
- use rustc_session::config::PrintRequest::*;
- // NativeStaticLibs and LinkArgs are special - printed during linking
- // (empty iterator returns true)
- if sess.opts.prints.iter().all(|&p| p == NativeStaticLibs || p == LinkArgs) {
- return Compilation::Continue;
- }
-
- let attrs = if parse_attrs {
- let result = parse_crate_attrs(sess);
- match result {
- Ok(attrs) => Some(attrs),
- Err(mut parse_error) => {
- parse_error.emit();
- return Compilation::Stop;
- }
- }
- } else {
- None
- };
- for req in &sess.opts.prints {
- match *req {
- TargetList => {
- let mut targets = rustc_target::spec::TARGETS.to_vec();
- targets.sort_unstable();
- println!("{}", targets.join("\n"));
- }
- Sysroot => println!("{}", sess.sysroot.display()),
- TargetLibdir => println!("{}", sess.target_tlib_path.dir.display()),
- TargetSpec => {
- println!("{}", serde_json::to_string_pretty(&sess.target.to_json()).unwrap());
- }
- FileNames | CrateName => {
- let attrs = attrs.as_ref().unwrap();
- let t_outputs = rustc_interface::util::build_output_filenames(attrs, sess);
- let id = rustc_session::output::find_crate_name(sess, attrs);
- if *req == PrintRequest::CrateName {
- println!("{id}");
- continue;
- }
- let crate_types = collect_crate_types(sess, attrs);
- for &style in &crate_types {
- let fname =
- rustc_session::output::filename_for_input(sess, style, id, &t_outputs);
- println!("{}", fname.file_name().unwrap().to_string_lossy());
- }
- }
- Cfg => {
- let mut cfgs = sess
- .parse_sess
- .config
- .iter()
- .filter_map(|&(name, value)| {
- // Note that crt-static is a specially recognized cfg
- // directive that's printed out here as part of
- // rust-lang/rust#37406, but in general the
- // `target_feature` cfg is gated under
- // rust-lang/rust#29717. For now this is just
- // specifically allowing the crt-static cfg and that's
- // it, this is intended to get into Cargo and then go
- // through to build scripts.
- if (name != sym::target_feature || value != Some(sym::crt_dash_static))
- && !sess.is_nightly_build()
- && find_gated_cfg(|cfg_sym| cfg_sym == name).is_some()
- {
- return None;
- }
-
- if let Some(value) = value {
- Some(format!("{name}=\"{value}\""))
- } else {
- Some(name.to_string())
- }
- })
- .collect::<Vec<String>>();
-
- cfgs.sort();
- for cfg in cfgs {
- println!("{cfg}");
- }
- }
- CallingConventions => {
- let mut calling_conventions = rustc_target::spec::abi::all_names();
- calling_conventions.sort_unstable();
- println!("{}", calling_conventions.join("\n"));
- }
- RelocationModels
- | CodeModels
- | TlsModels
- | TargetCPUs
- | StackProtectorStrategies
- | TargetFeatures => {
- codegen_backend.print(*req, sess);
- }
- // Any output here interferes with Cargo's parsing of other printed output
- NativeStaticLibs => {}
- LinkArgs => {}
- SplitDebuginfo => {
- use rustc_target::spec::SplitDebuginfo::{Off, Packed, Unpacked};
-
- for split in &[Off, Packed, Unpacked] {
- let stable = sess.target.options.supported_split_debuginfo.contains(split);
- let unstable_ok = sess.unstable_options();
- if stable || unstable_ok {
- println!("{split}");
- }
- }
- }
- }
- }
- Compilation::Stop
-}
-
-/// Prints version information
-///
-/// NOTE: this is a macro to support drivers built at a different time than the main `rustc_driver` crate.
-pub macro version($binary: literal, $matches: expr) {
- fn unw(x: Option<&str>) -> &str {
- x.unwrap_or("unknown")
- }
- $crate::version_at_macro_invocation(
- $binary,
- $matches,
- unw(option_env!("CFG_VERSION")),
- unw(option_env!("CFG_VER_HASH")),
- unw(option_env!("CFG_VER_DATE")),
- unw(option_env!("CFG_RELEASE")),
- )
-}
-
-#[doc(hidden)] // use the macro instead
-pub fn version_at_macro_invocation(
- binary: &str,
- matches: &getopts::Matches,
- version: &str,
- commit_hash: &str,
- commit_date: &str,
- release: &str,
-) {
- let verbose = matches.opt_present("verbose");
-
- println!("{binary} {version}");
-
- if verbose {
- println!("binary: {binary}");
- println!("commit-hash: {commit_hash}");
- println!("commit-date: {commit_date}");
- println!("host: {}", config::host_triple());
- println!("release: {release}");
-
- let debug_flags = matches.opt_strs("Z");
- let backend_name = debug_flags.iter().find_map(|x| x.strip_prefix("codegen-backend="));
- get_codegen_backend(&None, backend_name).print_version();
- }
-}
-
-fn usage(verbose: bool, include_unstable_options: bool, nightly_build: bool) {
- let groups = if verbose { config::rustc_optgroups() } else { config::rustc_short_optgroups() };
- let mut options = getopts::Options::new();
- for option in groups.iter().filter(|x| include_unstable_options || x.is_stable()) {
- (option.apply)(&mut options);
- }
- let message = "Usage: rustc [OPTIONS] INPUT";
- let nightly_help = if nightly_build {
- "\n -Z help Print unstable compiler options"
- } else {
- ""
- };
- let verbose_help = if verbose {
- ""
- } else {
- "\n --help -v Print the full set of options rustc accepts"
- };
- let at_path = if verbose {
- " @path Read newline separated options from `path`\n"
- } else {
- ""
- };
- println!(
- "{options}{at_path}\nAdditional help:
- -C help Print codegen options
- -W help \
- Print 'lint' options and default settings{nightly}{verbose}\n",
- options = options.usage(message),
- at_path = at_path,
- nightly = nightly_help,
- verbose = verbose_help
- );
-}
-
-fn print_wall_help() {
- println!(
- "
-The flag `-Wall` does not exist in `rustc`. Most useful lints are enabled by
-default. Use `rustc -W help` to see all available lints. It's more common to put
-warning settings in the crate root using `#![warn(LINT_NAME)]` instead of using
-the command line flag directly.
-"
- );
-}
-
-/// Write to stdout lint command options, together with a list of all available lints
-pub fn describe_lints(sess: &Session, lint_store: &LintStore, loaded_plugins: bool) {
- println!(
- "
-Available lint options:
- -W <foo> Warn about <foo>
- -A <foo> \
- Allow <foo>
- -D <foo> Deny <foo>
- -F <foo> Forbid <foo> \
- (deny <foo> and all attempts to override)
-
-"
- );
-
- fn sort_lints(sess: &Session, mut lints: Vec<&'static Lint>) -> Vec<&'static Lint> {
- // The sort doesn't case-fold but it's doubtful we care.
- lints.sort_by_cached_key(|x: &&Lint| (x.default_level(sess.edition()), x.name));
- lints
- }
-
- fn sort_lint_groups(
- lints: Vec<(&'static str, Vec<LintId>, bool)>,
- ) -> Vec<(&'static str, Vec<LintId>)> {
- let mut lints: Vec<_> = lints.into_iter().map(|(x, y, _)| (x, y)).collect();
- lints.sort_by_key(|l| l.0);
- lints
- }
-
- let (plugin, builtin): (Vec<_>, _) =
- lint_store.get_lints().iter().cloned().partition(|&lint| lint.is_plugin);
- let plugin = sort_lints(sess, plugin);
- let builtin = sort_lints(sess, builtin);
-
- let (plugin_groups, builtin_groups): (Vec<_>, _) =
- lint_store.get_lint_groups().partition(|&(.., p)| p);
- let plugin_groups = sort_lint_groups(plugin_groups);
- let builtin_groups = sort_lint_groups(builtin_groups);
-
- let max_name_len =
- plugin.iter().chain(&builtin).map(|&s| s.name.chars().count()).max().unwrap_or(0);
- let padded = |x: &str| {
- let mut s = " ".repeat(max_name_len - x.chars().count());
- s.push_str(x);
- s
- };
-
- println!("Lint checks provided by rustc:\n");
-
- let print_lints = |lints: Vec<&Lint>| {
- println!(" {} {:7.7} {}", padded("name"), "default", "meaning");
- println!(" {} {:7.7} {}", padded("----"), "-------", "-------");
- for lint in lints {
- let name = lint.name_lower().replace('_', "-");
- println!(
- " {} {:7.7} {}",
- padded(&name),
- lint.default_level(sess.edition()).as_str(),
- lint.desc
- );
- }
- println!("\n");
- };
-
- print_lints(builtin);
-
- let max_name_len = max(
- "warnings".len(),
- plugin_groups
- .iter()
- .chain(&builtin_groups)
- .map(|&(s, _)| s.chars().count())
- .max()
- .unwrap_or(0),
- );
-
- let padded = |x: &str| {
- let mut s = " ".repeat(max_name_len - x.chars().count());
- s.push_str(x);
- s
- };
-
- println!("Lint groups provided by rustc:\n");
-
- let print_lint_groups = |lints: Vec<(&'static str, Vec<LintId>)>, all_warnings| {
- println!(" {} sub-lints", padded("name"));
- println!(" {} ---------", padded("----"));
-
- if all_warnings {
- println!(" {} all lints that are set to issue warnings", padded("warnings"));
- }
-
- for (name, to) in lints {
- let name = name.to_lowercase().replace('_', "-");
- let desc = to
- .into_iter()
- .map(|x| x.to_string().replace('_', "-"))
- .collect::<Vec<String>>()
- .join(", ");
- println!(" {} {}", padded(&name), desc);
- }
- println!("\n");
- };
-
- print_lint_groups(builtin_groups, true);
-
- match (loaded_plugins, plugin.len(), plugin_groups.len()) {
- (false, 0, _) | (false, _, 0) => {
- println!("Lint tools like Clippy can provide additional lints and lint groups.");
- }
- (false, ..) => panic!("didn't load lint plugins but got them anyway!"),
- (true, 0, 0) => println!("This crate does not load any lint plugins or lint groups."),
- (true, l, g) => {
- if l > 0 {
- println!("Lint checks provided by plugins loaded by this crate:\n");
- print_lints(plugin);
- }
- if g > 0 {
- println!("Lint groups provided by plugins loaded by this crate:\n");
- print_lint_groups(plugin_groups, false);
- }
- }
- }
-}
-
-fn describe_debug_flags() {
- println!("\nAvailable options:\n");
- print_flag_list("-Z", config::Z_OPTIONS);
-}
-
-fn describe_codegen_flags() {
- println!("\nAvailable codegen options:\n");
- print_flag_list("-C", config::CG_OPTIONS);
-}
-
-pub fn print_flag_list<T>(
- cmdline_opt: &str,
- flag_list: &[(&'static str, T, &'static str, &'static str)],
-) {
- let max_len = flag_list.iter().map(|&(name, _, _, _)| name.chars().count()).max().unwrap_or(0);
-
- for &(name, _, _, desc) in flag_list {
- println!(
- " {} {:>width$}=val -- {}",
- cmdline_opt,
- name.replace('_', "-"),
- desc,
- width = max_len
- );
- }
-}
-
-/// Process command line options. Emits messages as appropriate. If compilation
-/// should continue, returns a getopts::Matches object parsed from args,
-/// otherwise returns `None`.
-///
-/// The compiler's handling of options is a little complicated as it ties into
-/// our stability story. The current intention of each compiler option is to
-/// have one of two modes:
-///
-/// 1. An option is stable and can be used everywhere.
-/// 2. An option is unstable, and can only be used on nightly.
-///
-/// Like unstable library and language features, however, unstable options have
-/// always required a form of "opt in" to indicate that you're using them. This
-/// provides the easy ability to scan a code base to check to see if anything
-/// unstable is being used. Currently, this "opt in" is the `-Z` "zed" flag.
-///
-/// All options behind `-Z` are considered unstable by default. Other top-level
-/// options can also be considered unstable, and they were unlocked through the
-/// `-Z unstable-options` flag. Note that `-Z` remains to be the root of
-/// instability in both cases, though.
-///
-/// So with all that in mind, the comments below have some more detail about the
-/// contortions done here to get things to work out correctly.
-pub fn handle_options(args: &[String]) -> Option<getopts::Matches> {
- // Throw away the first argument, the name of the binary
- let args = &args[1..];
-
- if args.is_empty() {
- // user did not write `-v` nor `-Z unstable-options`, so do not
- // include that extra information.
- let nightly_build =
- rustc_feature::UnstableFeatures::from_environment(None).is_nightly_build();
- usage(false, false, nightly_build);
- return None;
- }
-
- // Parse with *all* options defined in the compiler, we don't worry about
- // option stability here we just want to parse as much as possible.
- let mut options = getopts::Options::new();
- for option in config::rustc_optgroups() {
- (option.apply)(&mut options);
- }
- let matches = options.parse(args).unwrap_or_else(|e| {
- let msg = match e {
- getopts::Fail::UnrecognizedOption(ref opt) => CG_OPTIONS
- .iter()
- .map(|&(name, ..)| ('C', name))
- .chain(Z_OPTIONS.iter().map(|&(name, ..)| ('Z', name)))
- .find(|&(_, name)| *opt == name.replace('_', "-"))
- .map(|(flag, _)| format!("{e}. Did you mean `-{flag} {opt}`?")),
- _ => None,
- };
- early_error(ErrorOutputType::default(), &msg.unwrap_or_else(|| e.to_string()));
- });
-
- // For all options we just parsed, we check a few aspects:
- //
- // * If the option is stable, we're all good
- // * If the option wasn't passed, we're all good
- // * If `-Z unstable-options` wasn't passed (and we're not a -Z option
- // ourselves), then we require the `-Z unstable-options` flag to unlock
- // this option that was passed.
- // * If we're a nightly compiler, then unstable options are now unlocked, so
- // we're good to go.
- // * Otherwise, if we're an unstable option then we generate an error
- // (unstable option being used on stable)
- nightly_options::check_nightly_options(&matches, &config::rustc_optgroups());
-
- if matches.opt_present("h") || matches.opt_present("help") {
- // Only show unstable options in --help if we accept unstable options.
- let unstable_enabled = nightly_options::is_unstable_enabled(&matches);
- let nightly_build = nightly_options::match_is_nightly_build(&matches);
- usage(matches.opt_present("verbose"), unstable_enabled, nightly_build);
- return None;
- }
-
- // Handle the special case of -Wall.
- let wall = matches.opt_strs("W");
- if wall.iter().any(|x| *x == "all") {
- print_wall_help();
- rustc_errors::FatalError.raise();
- }
-
- // Don't handle -W help here, because we might first load plugins.
- let debug_flags = matches.opt_strs("Z");
- if debug_flags.iter().any(|x| *x == "help") {
- describe_debug_flags();
- return None;
- }
-
- let cg_flags = matches.opt_strs("C");
-
- if cg_flags.iter().any(|x| *x == "help") {
- describe_codegen_flags();
- return None;
- }
-
- if cg_flags.iter().any(|x| *x == "no-stack-check") {
- early_warn(
- ErrorOutputType::default(),
- "the --no-stack-check flag is deprecated and does nothing",
- );
- }
-
- if cg_flags.iter().any(|x| *x == "passes=list") {
- let backend_name = debug_flags.iter().find_map(|x| x.strip_prefix("codegen-backend="));
- get_codegen_backend(&None, backend_name).print_passes();
- return None;
- }
-
- if matches.opt_present("version") {
- version!("rustc", &matches);
- return None;
- }
-
- Some(matches)
-}
-
-fn parse_crate_attrs<'a>(sess: &'a Session) -> PResult<'a, ast::AttrVec> {
- match &sess.io.input {
- Input::File(ifile) => rustc_parse::parse_crate_attrs_from_file(ifile, &sess.parse_sess),
- Input::Str { name, input } => rustc_parse::parse_crate_attrs_from_source_str(
- name.clone(),
- input.clone(),
- &sess.parse_sess,
- ),
- }
-}
-
-/// Gets a list of extra command-line flags provided by the user, as strings.
-///
-/// This function is used during ICEs to show more information useful for
-/// debugging, since some ICEs only happens with non-default compiler flags
-/// (and the users don't always report them).
-fn extra_compiler_flags() -> Option<(Vec<String>, bool)> {
- let mut args = env::args_os().map(|arg| arg.to_string_lossy().to_string()).peekable();
-
- let mut result = Vec::new();
- let mut excluded_cargo_defaults = false;
- while let Some(arg) = args.next() {
- if let Some(a) = ICE_REPORT_COMPILER_FLAGS.iter().find(|a| arg.starts_with(*a)) {
- let content = if arg.len() == a.len() {
- // A space-separated option, like `-C incremental=foo` or `--crate-type rlib`
- match args.next() {
- Some(arg) => arg.to_string(),
- None => continue,
- }
- } else if arg.get(a.len()..a.len() + 1) == Some("=") {
- // An equals option, like `--crate-type=rlib`
- arg[a.len() + 1..].to_string()
- } else {
- // A non-space option, like `-Cincremental=foo`
- arg[a.len()..].to_string()
- };
- let option = content.split_once('=').map(|s| s.0).unwrap_or(&content);
- if ICE_REPORT_COMPILER_FLAGS_EXCLUDE.iter().any(|exc| option == *exc) {
- excluded_cargo_defaults = true;
- } else {
- result.push(a.to_string());
- match ICE_REPORT_COMPILER_FLAGS_STRIP_VALUE.iter().find(|s| option == **s) {
- Some(s) => result.push(format!("{s}=[REDACTED]")),
- None => result.push(content),
- }
- }
- }
- }
-
- if !result.is_empty() { Some((result, excluded_cargo_defaults)) } else { None }
-}
-
-/// Runs a closure and catches unwinds triggered by fatal errors.
-///
-/// The compiler currently unwinds with a special sentinel value to abort
-/// compilation on fatal errors. This function catches that sentinel and turns
-/// the panic into a `Result` instead.
-pub fn catch_fatal_errors<F: FnOnce() -> R, R>(f: F) -> Result<R, ErrorGuaranteed> {
- catch_unwind(panic::AssertUnwindSafe(f)).map_err(|value| {
- if value.is::<rustc_errors::FatalErrorMarker>() {
- ErrorGuaranteed::unchecked_claim_error_was_emitted()
- } else {
- panic::resume_unwind(value);
- }
- })
-}
-
-/// Variant of `catch_fatal_errors` for the `interface::Result` return type
-/// that also computes the exit code.
-pub fn catch_with_exit_code(f: impl FnOnce() -> interface::Result<()>) -> i32 {
- let result = catch_fatal_errors(f).and_then(|result| result);
- match result {
- Ok(()) => EXIT_SUCCESS,
- Err(_) => EXIT_FAILURE,
- }
-}
-
-static DEFAULT_HOOK: LazyLock<Box<dyn Fn(&panic::PanicInfo<'_>) + Sync + Send + 'static>> =
- LazyLock::new(|| {
- let hook = panic::take_hook();
- panic::set_hook(Box::new(|info| {
- // If the error was caused by a broken pipe then this is not a bug.
- // Write the error and return immediately. See #98700.
- #[cfg(windows)]
- if let Some(msg) = info.payload().downcast_ref::<String>() {
- if msg.starts_with("failed printing to stdout: ") && msg.ends_with("(os error 232)")
- {
- early_error_no_abort(ErrorOutputType::default(), &msg);
- return;
- }
- };
-
- // Invoke the default handler, which prints the actual panic message and optionally a backtrace
- // Don't do this for delayed bugs, which already emit their own more useful backtrace.
- if !info.payload().is::<rustc_errors::DelayedBugPanic>() {
- (*DEFAULT_HOOK)(info);
-
- // Separate the output with an empty line
- eprintln!();
- }
-
- // Print the ICE message
- report_ice(info, BUG_REPORT_URL);
- }));
- hook
- });
-
-/// Prints the ICE message, including query stack, but without backtrace.
-///
-/// The message will point the user at `bug_report_url` to report the ICE.
-///
-/// When `install_ice_hook` is called, this function will be called as the panic
-/// hook.
-pub fn report_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str) {
- let fallback_bundle =
- rustc_errors::fallback_fluent_bundle(rustc_errors::DEFAULT_LOCALE_RESOURCES, false);
- let emitter = Box::new(rustc_errors::emitter::EmitterWriter::stderr(
- rustc_errors::ColorConfig::Auto,
- None,
- None,
- fallback_bundle,
- false,
- false,
- None,
- false,
- false,
- ));
- let handler = rustc_errors::Handler::with_emitter(true, None, emitter);
-
- // a .span_bug or .bug call has already printed what
- // it wants to print.
- if !info.payload().is::<rustc_errors::ExplicitBug>()
- && !info.payload().is::<rustc_errors::DelayedBugPanic>()
- {
- let mut d = rustc_errors::Diagnostic::new(rustc_errors::Level::Bug, "unexpected panic");
- handler.emit_diagnostic(&mut d);
- }
-
- handler.emit_note(session_diagnostics::Ice);
- handler.emit_note(session_diagnostics::IceBugReport { bug_report_url });
- handler.emit_note(session_diagnostics::IceVersion {
- version: util::version_str!().unwrap_or("unknown_version"),
- triple: config::host_triple(),
- });
-
- if let Some((flags, excluded_cargo_defaults)) = extra_compiler_flags() {
- handler.emit_note(session_diagnostics::IceFlags { flags: flags.join(" ") });
- if excluded_cargo_defaults {
- handler.emit_note(session_diagnostics::IceExcludeCargoDefaults);
- }
- }
-
- // If backtraces are enabled, also print the query stack
- let backtrace = env::var_os("RUST_BACKTRACE").map_or(false, |x| &x != "0");
-
- let num_frames = if backtrace { None } else { Some(2) };
-
- interface::try_print_query_stack(&handler, num_frames);
-
- #[cfg(windows)]
- unsafe {
- if env::var("RUSTC_BREAK_ON_ICE").is_ok() {
- // Trigger a debugger if we crashed during bootstrap
- winapi::um::debugapi::DebugBreak();
- }
- }
-}
-
-/// Installs a panic hook that will print the ICE message on unexpected panics.
-///
-/// A custom rustc driver can skip calling this to set up a custom ICE hook.
-pub fn install_ice_hook() {
- // If the user has not explicitly overridden "RUST_BACKTRACE", then produce
- // full backtraces. When a compiler ICE happens, we want to gather
- // as much information as possible to present in the issue opened
- // by the user. Compiler developers and other rustc users can
- // opt in to less-verbose backtraces by manually setting "RUST_BACKTRACE"
- // (e.g. `RUST_BACKTRACE=1`)
- if std::env::var("RUST_BACKTRACE").is_err() {
- std::env::set_var("RUST_BACKTRACE", "full");
- }
- LazyLock::force(&DEFAULT_HOOK);
-}
-
-/// This allows tools to enable rust logging without having to magically match rustc's
-/// tracing crate version.
-pub fn init_rustc_env_logger() {
- init_rustc_env_logger_with_backtrace_option(&None);
-}
-
-/// This allows tools to enable rust logging without having to magically match rustc's
-/// tracing crate version. In contrast to `init_rustc_env_logger` it allows you to
-/// choose a target module you wish to show backtraces along with its logging.
-pub fn init_rustc_env_logger_with_backtrace_option(backtrace_target: &Option<String>) {
- if let Err(error) = rustc_log::init_rustc_env_logger_with_backtrace_option(backtrace_target) {
- early_error(ErrorOutputType::default(), &error.to_string());
- }
-}
-
-/// This allows tools to enable rust logging without having to magically match rustc's
-/// tracing crate version. In contrast to `init_rustc_env_logger` it allows you to choose an env var
-/// other than `RUSTC_LOG`.
-pub fn init_env_logger(env: &str) {
- if let Err(error) = rustc_log::init_env_logger(env) {
- early_error(ErrorOutputType::default(), &error.to_string());
- }
-}
-
-#[cfg(all(unix, any(target_env = "gnu", target_os = "macos")))]
-mod signal_handler {
- extern "C" {
- fn backtrace_symbols_fd(
- buffer: *const *mut libc::c_void,
- size: libc::c_int,
- fd: libc::c_int,
- );
- }
-
- extern "C" fn print_stack_trace(_: libc::c_int) {
- const MAX_FRAMES: usize = 256;
- static mut STACK_TRACE: [*mut libc::c_void; MAX_FRAMES] =
- [std::ptr::null_mut(); MAX_FRAMES];
- unsafe {
- let depth = libc::backtrace(STACK_TRACE.as_mut_ptr(), MAX_FRAMES as i32);
- if depth == 0 {
- return;
- }
- backtrace_symbols_fd(STACK_TRACE.as_ptr(), depth, 2);
- }
- }
-
- /// When an error signal (such as SIGABRT or SIGSEGV) is delivered to the
- /// process, print a stack trace and then exit.
- pub(super) fn install() {
- unsafe {
- const ALT_STACK_SIZE: usize = libc::MINSIGSTKSZ + 64 * 1024;
- let mut alt_stack: libc::stack_t = std::mem::zeroed();
- alt_stack.ss_sp =
- std::alloc::alloc(std::alloc::Layout::from_size_align(ALT_STACK_SIZE, 1).unwrap())
- as *mut libc::c_void;
- alt_stack.ss_size = ALT_STACK_SIZE;
- libc::sigaltstack(&alt_stack, std::ptr::null_mut());
-
- let mut sa: libc::sigaction = std::mem::zeroed();
- sa.sa_sigaction = print_stack_trace as libc::sighandler_t;
- sa.sa_flags = libc::SA_NODEFER | libc::SA_RESETHAND | libc::SA_ONSTACK;
- libc::sigemptyset(&mut sa.sa_mask);
- libc::sigaction(libc::SIGSEGV, &sa, std::ptr::null_mut());
- }
- }
-}
-
-#[cfg(not(all(unix, any(target_env = "gnu", target_os = "macos"))))]
-mod signal_handler {
- pub(super) fn install() {}
-}
-
-pub fn main() -> ! {
- let start_time = Instant::now();
- let start_rss = get_resident_set_size();
- signal_handler::install();
- let mut callbacks = TimePassesCallbacks::default();
- install_ice_hook();
- let exit_code = catch_with_exit_code(|| {
- let args = env::args_os()
- .enumerate()
- .map(|(i, arg)| {
- arg.into_string().unwrap_or_else(|arg| {
- early_error(
- ErrorOutputType::default(),
- &format!("argument {i} is not valid Unicode: {arg:?}"),
- )
- })
- })
- .collect::<Vec<_>>();
- RunCompiler::new(&args, &mut callbacks).run()
- });
-
- if callbacks.time_passes {
- let end_rss = get_resident_set_size();
- print_time_passes_entry("total", start_time.elapsed(), start_rss, end_rss);
- }
-
- process::exit(exit_code)
-}
+pub use rustc_driver_impl::*;
+++ /dev/null
-//! The various pretty-printing routines.
-
-use crate::session_diagnostics::UnprettyDumpFail;
-use rustc_ast as ast;
-use rustc_ast_pretty::pprust;
-use rustc_errors::ErrorGuaranteed;
-use rustc_hir as hir;
-use rustc_hir_pretty as pprust_hir;
-use rustc_middle::hir::map as hir_map;
-use rustc_middle::mir::{write_mir_graphviz, write_mir_pretty};
-use rustc_middle::ty::{self, TyCtxt};
-use rustc_session::config::{PpAstTreeMode, PpHirMode, PpMode, PpSourceMode};
-use rustc_session::Session;
-use rustc_span::symbol::Ident;
-use rustc_span::FileName;
-
-use std::cell::Cell;
-use std::fmt::Write;
-
-pub use self::PpMode::*;
-pub use self::PpSourceMode::*;
-use crate::abort_on_err;
-
-// This slightly awkward construction is to allow for each PpMode to
-// choose whether it needs to do analyses (which can consume the
-// Session) and then pass through the session (now attached to the
-// analysis results) on to the chosen pretty-printer, along with the
-// `&PpAnn` object.
-//
-// Note that since the `&PrinterSupport` is freshly constructed on each
-// call, it would not make sense to try to attach the lifetime of `self`
-// to the lifetime of the `&PrinterObject`.
-
-/// Constructs a `PrinterSupport` object and passes it to `f`.
-fn call_with_pp_support<'tcx, A, F>(
- ppmode: &PpSourceMode,
- sess: &'tcx Session,
- tcx: Option<TyCtxt<'tcx>>,
- f: F,
-) -> A
-where
- F: FnOnce(&dyn PrinterSupport) -> A,
-{
- match *ppmode {
- Normal | Expanded => {
- let annotation = NoAnn { sess, tcx };
- f(&annotation)
- }
-
- Identified | ExpandedIdentified => {
- let annotation = IdentifiedAnnotation { sess, tcx };
- f(&annotation)
- }
- ExpandedHygiene => {
- let annotation = HygieneAnnotation { sess };
- f(&annotation)
- }
- }
-}
-fn call_with_pp_support_hir<A, F>(ppmode: &PpHirMode, tcx: TyCtxt<'_>, f: F) -> A
-where
- F: FnOnce(&dyn HirPrinterSupport<'_>, hir_map::Map<'_>) -> A,
-{
- match *ppmode {
- PpHirMode::Normal => {
- let annotation = NoAnn { sess: tcx.sess, tcx: Some(tcx) };
- f(&annotation, tcx.hir())
- }
-
- PpHirMode::Identified => {
- let annotation = IdentifiedAnnotation { sess: tcx.sess, tcx: Some(tcx) };
- f(&annotation, tcx.hir())
- }
- PpHirMode::Typed => {
- abort_on_err(tcx.analysis(()), tcx.sess);
-
- let annotation = TypedAnnotation { tcx, maybe_typeck_results: Cell::new(None) };
- tcx.dep_graph.with_ignore(|| f(&annotation, tcx.hir()))
- }
- }
-}
-
-trait PrinterSupport: pprust::PpAnn {
- /// Provides a uniform interface for re-extracting a reference to a
- /// `Session` from a value that now owns it.
- fn sess(&self) -> &Session;
-
- /// Produces the pretty-print annotation object.
- ///
- /// (Rust does not yet support upcasting from a trait object to
- /// an object for one of its supertraits.)
- fn pp_ann(&self) -> &dyn pprust::PpAnn;
-}
-
-trait HirPrinterSupport<'hir>: pprust_hir::PpAnn {
- /// Provides a uniform interface for re-extracting a reference to a
- /// `Session` from a value that now owns it.
- fn sess(&self) -> &Session;
-
- /// Provides a uniform interface for re-extracting a reference to an
- /// `hir_map::Map` from a value that now owns it.
- fn hir_map(&self) -> Option<hir_map::Map<'hir>>;
-
- /// Produces the pretty-print annotation object.
- ///
- /// (Rust does not yet support upcasting from a trait object to
- /// an object for one of its supertraits.)
- fn pp_ann(&self) -> &dyn pprust_hir::PpAnn;
-}
-
-struct NoAnn<'hir> {
- sess: &'hir Session,
- tcx: Option<TyCtxt<'hir>>,
-}
-
-impl<'hir> PrinterSupport for NoAnn<'hir> {
- fn sess(&self) -> &Session {
- self.sess
- }
-
- fn pp_ann(&self) -> &dyn pprust::PpAnn {
- self
- }
-}
-
-impl<'hir> HirPrinterSupport<'hir> for NoAnn<'hir> {
- fn sess(&self) -> &Session {
- self.sess
- }
-
- fn hir_map(&self) -> Option<hir_map::Map<'hir>> {
- self.tcx.map(|tcx| tcx.hir())
- }
-
- fn pp_ann(&self) -> &dyn pprust_hir::PpAnn {
- self
- }
-}
-
-impl<'hir> pprust::PpAnn for NoAnn<'hir> {}
-impl<'hir> pprust_hir::PpAnn for NoAnn<'hir> {
- fn nested(&self, state: &mut pprust_hir::State<'_>, nested: pprust_hir::Nested) {
- if let Some(tcx) = self.tcx {
- pprust_hir::PpAnn::nested(&(&tcx.hir() as &dyn hir::intravisit::Map<'_>), state, nested)
- }
- }
-}
-
-struct IdentifiedAnnotation<'hir> {
- sess: &'hir Session,
- tcx: Option<TyCtxt<'hir>>,
-}
-
-impl<'hir> PrinterSupport for IdentifiedAnnotation<'hir> {
- fn sess(&self) -> &Session {
- self.sess
- }
-
- fn pp_ann(&self) -> &dyn pprust::PpAnn {
- self
- }
-}
-
-impl<'hir> pprust::PpAnn for IdentifiedAnnotation<'hir> {
- fn pre(&self, s: &mut pprust::State<'_>, node: pprust::AnnNode<'_>) {
- if let pprust::AnnNode::Expr(_) = node {
- s.popen();
- }
- }
- fn post(&self, s: &mut pprust::State<'_>, node: pprust::AnnNode<'_>) {
- match node {
- pprust::AnnNode::Crate(_) | pprust::AnnNode::Ident(_) | pprust::AnnNode::Name(_) => {}
-
- pprust::AnnNode::Item(item) => {
- s.s.space();
- s.synth_comment(item.id.to_string())
- }
- pprust::AnnNode::SubItem(id) => {
- s.s.space();
- s.synth_comment(id.to_string())
- }
- pprust::AnnNode::Block(blk) => {
- s.s.space();
- s.synth_comment(format!("block {}", blk.id))
- }
- pprust::AnnNode::Expr(expr) => {
- s.s.space();
- s.synth_comment(expr.id.to_string());
- s.pclose()
- }
- pprust::AnnNode::Pat(pat) => {
- s.s.space();
- s.synth_comment(format!("pat {}", pat.id));
- }
- }
- }
-}
-
-impl<'hir> HirPrinterSupport<'hir> for IdentifiedAnnotation<'hir> {
- fn sess(&self) -> &Session {
- self.sess
- }
-
- fn hir_map(&self) -> Option<hir_map::Map<'hir>> {
- self.tcx.map(|tcx| tcx.hir())
- }
-
- fn pp_ann(&self) -> &dyn pprust_hir::PpAnn {
- self
- }
-}
-
-impl<'hir> pprust_hir::PpAnn for IdentifiedAnnotation<'hir> {
- fn nested(&self, state: &mut pprust_hir::State<'_>, nested: pprust_hir::Nested) {
- if let Some(ref tcx) = self.tcx {
- pprust_hir::PpAnn::nested(&(&tcx.hir() as &dyn hir::intravisit::Map<'_>), state, nested)
- }
- }
- fn pre(&self, s: &mut pprust_hir::State<'_>, node: pprust_hir::AnnNode<'_>) {
- if let pprust_hir::AnnNode::Expr(_) = node {
- s.popen();
- }
- }
- fn post(&self, s: &mut pprust_hir::State<'_>, node: pprust_hir::AnnNode<'_>) {
- match node {
- pprust_hir::AnnNode::Name(_) => {}
- pprust_hir::AnnNode::Item(item) => {
- s.s.space();
- s.synth_comment(format!("hir_id: {}", item.hir_id()));
- }
- pprust_hir::AnnNode::SubItem(id) => {
- s.s.space();
- s.synth_comment(id.to_string());
- }
- pprust_hir::AnnNode::Block(blk) => {
- s.s.space();
- s.synth_comment(format!("block hir_id: {}", blk.hir_id));
- }
- pprust_hir::AnnNode::Expr(expr) => {
- s.s.space();
- s.synth_comment(format!("expr hir_id: {}", expr.hir_id));
- s.pclose();
- }
- pprust_hir::AnnNode::Pat(pat) => {
- s.s.space();
- s.synth_comment(format!("pat hir_id: {}", pat.hir_id));
- }
- pprust_hir::AnnNode::Arm(arm) => {
- s.s.space();
- s.synth_comment(format!("arm hir_id: {}", arm.hir_id));
- }
- }
- }
-}
-
-struct HygieneAnnotation<'a> {
- sess: &'a Session,
-}
-
-impl<'a> PrinterSupport for HygieneAnnotation<'a> {
- fn sess(&self) -> &Session {
- self.sess
- }
-
- fn pp_ann(&self) -> &dyn pprust::PpAnn {
- self
- }
-}
-
-impl<'a> pprust::PpAnn for HygieneAnnotation<'a> {
- fn post(&self, s: &mut pprust::State<'_>, node: pprust::AnnNode<'_>) {
- match node {
- pprust::AnnNode::Ident(&Ident { name, span }) => {
- s.s.space();
- s.synth_comment(format!("{}{:?}", name.as_u32(), span.ctxt()))
- }
- pprust::AnnNode::Name(&name) => {
- s.s.space();
- s.synth_comment(name.as_u32().to_string())
- }
- pprust::AnnNode::Crate(_) => {
- s.s.hardbreak();
- let verbose = self.sess.verbose();
- s.synth_comment(rustc_span::hygiene::debug_hygiene_data(verbose));
- s.s.hardbreak_if_not_bol();
- }
- _ => {}
- }
- }
-}
-
-struct TypedAnnotation<'tcx> {
- tcx: TyCtxt<'tcx>,
- maybe_typeck_results: Cell<Option<&'tcx ty::TypeckResults<'tcx>>>,
-}
-
-impl<'tcx> HirPrinterSupport<'tcx> for TypedAnnotation<'tcx> {
- fn sess(&self) -> &Session {
- self.tcx.sess
- }
-
- fn hir_map(&self) -> Option<hir_map::Map<'tcx>> {
- Some(self.tcx.hir())
- }
-
- fn pp_ann(&self) -> &dyn pprust_hir::PpAnn {
- self
- }
-}
-
-impl<'tcx> pprust_hir::PpAnn for TypedAnnotation<'tcx> {
- fn nested(&self, state: &mut pprust_hir::State<'_>, nested: pprust_hir::Nested) {
- let old_maybe_typeck_results = self.maybe_typeck_results.get();
- if let pprust_hir::Nested::Body(id) = nested {
- self.maybe_typeck_results.set(Some(self.tcx.typeck_body(id)));
- }
- let pp_ann = &(&self.tcx.hir() as &dyn hir::intravisit::Map<'_>);
- pprust_hir::PpAnn::nested(pp_ann, state, nested);
- self.maybe_typeck_results.set(old_maybe_typeck_results);
- }
- fn pre(&self, s: &mut pprust_hir::State<'_>, node: pprust_hir::AnnNode<'_>) {
- if let pprust_hir::AnnNode::Expr(_) = node {
- s.popen();
- }
- }
- fn post(&self, s: &mut pprust_hir::State<'_>, node: pprust_hir::AnnNode<'_>) {
- if let pprust_hir::AnnNode::Expr(expr) = node {
- let typeck_results = self.maybe_typeck_results.get().or_else(|| {
- self.tcx
- .hir()
- .maybe_body_owned_by(expr.hir_id.owner.def_id)
- .map(|body_id| self.tcx.typeck_body(body_id))
- });
-
- if let Some(typeck_results) = typeck_results {
- s.s.space();
- s.s.word("as");
- s.s.space();
- s.s.word(typeck_results.expr_ty(expr).to_string());
- }
-
- s.pclose();
- }
- }
-}
-
-fn get_source(sess: &Session) -> (String, FileName) {
- let src_name = sess.io.input.source_name();
- let src = String::clone(
- sess.source_map()
- .get_source_file(&src_name)
- .expect("get_source_file")
- .src
- .as_ref()
- .expect("src"),
- );
- (src, src_name)
-}
-
-fn write_or_print(out: &str, sess: &Session) {
- match &sess.io.output_file {
- None => print!("{out}"),
- Some(p) => {
- if let Err(e) = std::fs::write(p, out) {
- sess.emit_fatal(UnprettyDumpFail {
- path: p.display().to_string(),
- err: e.to_string(),
- });
- }
- }
- }
-}
-
-pub fn print_after_parsing(sess: &Session, krate: &ast::Crate, ppm: PpMode) {
- let (src, src_name) = get_source(sess);
-
- let out = match ppm {
- Source(s) => {
- // Silently ignores an identified node.
- call_with_pp_support(&s, sess, None, move |annotation| {
- debug!("pretty printing source code {:?}", s);
- let sess = annotation.sess();
- let parse = &sess.parse_sess;
- pprust::print_crate(
- sess.source_map(),
- krate,
- src_name,
- src,
- annotation.pp_ann(),
- false,
- parse.edition,
- &sess.parse_sess.attr_id_generator,
- )
- })
- }
- AstTree(PpAstTreeMode::Normal) => {
- debug!("pretty printing AST tree");
- format!("{krate:#?}")
- }
- _ => unreachable!(),
- };
-
- write_or_print(&out, sess);
-}
-
-pub fn print_after_hir_lowering<'tcx>(tcx: TyCtxt<'tcx>, ppm: PpMode) {
- if ppm.needs_analysis() {
- abort_on_err(print_with_analysis(tcx, ppm), tcx.sess);
- return;
- }
-
- let (src, src_name) = get_source(tcx.sess);
-
- let out = match ppm {
- Source(s) => {
- // Silently ignores an identified node.
- call_with_pp_support(&s, tcx.sess, Some(tcx), move |annotation| {
- debug!("pretty printing source code {:?}", s);
- let sess = annotation.sess();
- let parse = &sess.parse_sess;
- pprust::print_crate(
- sess.source_map(),
- &tcx.resolver_for_lowering(()).borrow().1,
- src_name,
- src,
- annotation.pp_ann(),
- true,
- parse.edition,
- &sess.parse_sess.attr_id_generator,
- )
- })
- }
-
- AstTree(PpAstTreeMode::Expanded) => {
- debug!("pretty-printing expanded AST");
- format!("{:#?}", tcx.resolver_for_lowering(()).borrow().1)
- }
-
- Hir(s) => call_with_pp_support_hir(&s, tcx, move |annotation, hir_map| {
- debug!("pretty printing HIR {:?}", s);
- let sess = annotation.sess();
- let sm = sess.source_map();
- let attrs = |id| hir_map.attrs(id);
- pprust_hir::print_crate(
- sm,
- hir_map.root_module(),
- src_name,
- src,
- &attrs,
- annotation.pp_ann(),
- )
- }),
-
- HirTree => {
- call_with_pp_support_hir(&PpHirMode::Normal, tcx, move |_annotation, hir_map| {
- debug!("pretty printing HIR tree");
- format!("{:#?}", hir_map.krate())
- })
- }
-
- _ => unreachable!(),
- };
-
- write_or_print(&out, tcx.sess);
-}
-
-// In an ideal world, this would be a public function called by the driver after
-// analysis is performed. However, we want to call `phase_3_run_analysis_passes`
-// with a different callback than the standard driver, so that isn't easy.
-// Instead, we call that function ourselves.
-fn print_with_analysis(tcx: TyCtxt<'_>, ppm: PpMode) -> Result<(), ErrorGuaranteed> {
- tcx.analysis(())?;
- let out = match ppm {
- Mir => {
- let mut out = Vec::new();
- write_mir_pretty(tcx, None, &mut out).unwrap();
- String::from_utf8(out).unwrap()
- }
-
- MirCFG => {
- let mut out = Vec::new();
- write_mir_graphviz(tcx, None, &mut out).unwrap();
- String::from_utf8(out).unwrap()
- }
-
- ThirTree => {
- let mut out = String::new();
- abort_on_err(rustc_hir_analysis::check_crate(tcx), tcx.sess);
- debug!("pretty printing THIR tree");
- for did in tcx.hir().body_owners() {
- let _ = writeln!(
- out,
- "{:?}:\n{}\n",
- did,
- tcx.thir_tree(ty::WithOptConstParam::unknown(did))
- );
- }
- out
- }
-
- ThirFlat => {
- let mut out = String::new();
- abort_on_err(rustc_hir_analysis::check_crate(tcx), tcx.sess);
- debug!("pretty printing THIR flat");
- for did in tcx.hir().body_owners() {
- let _ = writeln!(
- out,
- "{:?}:\n{}\n",
- did,
- tcx.thir_flat(ty::WithOptConstParam::unknown(did))
- );
- }
- out
- }
-
- _ => unreachable!(),
- };
-
- write_or_print(&out, tcx.sess);
-
- Ok(())
-}
+++ /dev/null
-use rustc_macros::Diagnostic;
-
-#[derive(Diagnostic)]
-#[diag(driver_rlink_unable_to_read)]
-pub(crate) struct RlinkUnableToRead {
- pub err: std::io::Error,
-}
-
-#[derive(Diagnostic)]
-#[diag(driver_rlink_wrong_file_type)]
-pub(crate) struct RLinkWrongFileType;
-
-#[derive(Diagnostic)]
-#[diag(driver_rlink_empty_version_number)]
-pub(crate) struct RLinkEmptyVersionNumber;
-
-#[derive(Diagnostic)]
-#[diag(driver_rlink_encoding_version_mismatch)]
-pub(crate) struct RLinkEncodingVersionMismatch {
- pub version_array: String,
- pub rlink_version: u32,
-}
-
-#[derive(Diagnostic)]
-#[diag(driver_rlink_rustc_version_mismatch)]
-pub(crate) struct RLinkRustcVersionMismatch<'a> {
- pub rustc_version: String,
- pub current_version: &'a str,
-}
-
-#[derive(Diagnostic)]
-#[diag(driver_rlink_no_a_file)]
-pub(crate) struct RlinkNotAFile;
-
-#[derive(Diagnostic)]
-#[diag(driver_unpretty_dump_fail)]
-pub(crate) struct UnprettyDumpFail {
- pub path: String,
- pub err: String,
-}
-
-#[derive(Diagnostic)]
-#[diag(driver_ice)]
-pub(crate) struct Ice;
-
-#[derive(Diagnostic)]
-#[diag(driver_ice_bug_report)]
-pub(crate) struct IceBugReport<'a> {
- pub bug_report_url: &'a str,
-}
-
-#[derive(Diagnostic)]
-#[diag(driver_ice_version)]
-pub(crate) struct IceVersion<'a> {
- pub version: &'a str,
- pub triple: &'a str,
-}
-
-#[derive(Diagnostic)]
-#[diag(driver_ice_flags)]
-pub(crate) struct IceFlags {
- pub flags: String,
-}
-
-#[derive(Diagnostic)]
-#[diag(driver_ice_exclude_cargo_defaults)]
-pub(crate) struct IceExcludeCargoDefaults;
--- /dev/null
+[package]
+name = "rustc_driver_impl"
+version = "0.0.0"
+edition = "2021"
+
+[lib]
+
+[dependencies]
+tracing = { version = "0.1.35" }
+serde_json = "1.0.59"
+rustc_log = { path = "../rustc_log" }
+rustc_middle = { path = "../rustc_middle" }
+rustc_ast_pretty = { path = "../rustc_ast_pretty" }
+rustc_target = { path = "../rustc_target" }
+rustc_lint = { path = "../rustc_lint" }
+rustc_data_structures = { path = "../rustc_data_structures" }
+rustc_errors = { path = "../rustc_errors" }
+rustc_feature = { path = "../rustc_feature" }
+rustc_hir = { path = "../rustc_hir" }
+rustc_hir_pretty = { path = "../rustc_hir_pretty" }
+rustc_macros = { path = "../rustc_macros" }
+rustc_metadata = { path = "../rustc_metadata" }
+rustc_parse = { path = "../rustc_parse" }
+rustc_plugin_impl = { path = "../rustc_plugin_impl" }
+rustc_save_analysis = { path = "../rustc_save_analysis" }
+rustc_codegen_ssa = { path = "../rustc_codegen_ssa" }
+rustc_session = { path = "../rustc_session" }
+rustc_error_codes = { path = "../rustc_error_codes" }
+rustc_interface = { path = "../rustc_interface" }
+rustc_ast = { path = "../rustc_ast" }
+rustc_span = { path = "../rustc_span" }
+rustc_hir_analysis = { path = "../rustc_hir_analysis" }
+
+[target.'cfg(unix)'.dependencies]
+libc = "0.2"
+
+[target.'cfg(windows)'.dependencies]
+winapi = { version = "0.3", features = ["consoleapi", "debugapi", "processenv"] }
+
+[features]
+llvm = ['rustc_interface/llvm']
+max_level_info = ['rustc_log/max_level_info']
+rustc_use_parallel_compiler = ['rustc_data_structures/rustc_use_parallel_compiler', 'rustc_interface/rustc_use_parallel_compiler',
+ 'rustc_middle/rustc_use_parallel_compiler']
--- /dev/null
+The `driver` crate is effectively the "main" function for the rust
+compiler. It orchestrates the compilation process and "knits together"
+the code from the other crates within rustc. This crate itself does
+not contain any of the "main logic" of the compiler (though it does
+have some code related to pretty printing or other minor compiler
+options).
+
+For more information about how the driver works, see the [rustc dev guide].
+
+[rustc dev guide]: https://rustc-dev-guide.rust-lang.org/rustc-driver.html
--- /dev/null
+use std::error;
+use std::fmt;
+use std::fs;
+use std::io;
+
+fn arg_expand(arg: String) -> Result<Vec<String>, Error> {
+ if let Some(path) = arg.strip_prefix('@') {
+ let file = match fs::read_to_string(path) {
+ Ok(file) => file,
+ Err(ref err) if err.kind() == io::ErrorKind::InvalidData => {
+ return Err(Error::Utf8Error(Some(path.to_string())));
+ }
+ Err(err) => return Err(Error::IOError(path.to_string(), err)),
+ };
+ Ok(file.lines().map(ToString::to_string).collect())
+ } else {
+ Ok(vec![arg])
+ }
+}
+
+pub fn arg_expand_all(at_args: &[String]) -> Vec<String> {
+ let mut args = Vec::new();
+ for arg in at_args {
+ match arg_expand(arg.clone()) {
+ Ok(arg) => args.extend(arg),
+ Err(err) => rustc_session::early_error(
+ rustc_session::config::ErrorOutputType::default(),
+ &format!("Failed to load argument file: {err}"),
+ ),
+ }
+ }
+ args
+}
+
+#[derive(Debug)]
+pub enum Error {
+ Utf8Error(Option<String>),
+ IOError(String, io::Error),
+}
+
+impl fmt::Display for Error {
+ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+ match self {
+ Error::Utf8Error(None) => write!(fmt, "Utf8 error"),
+ Error::Utf8Error(Some(path)) => write!(fmt, "Utf8 error in {path}"),
+ Error::IOError(path, err) => write!(fmt, "IO Error: {path}: {err}"),
+ }
+ }
+}
+
+impl error::Error for Error {}
--- /dev/null
+//! The Rust compiler.
+//!
+//! # Note
+//!
+//! This API is completely unstable and subject to change.
+
+#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
+#![feature(is_terminal)]
+#![feature(once_cell)]
+#![feature(decl_macro)]
+#![recursion_limit = "256"]
+#![allow(rustc::potential_query_instability)]
+#![deny(rustc::untranslatable_diagnostic)]
+#![deny(rustc::diagnostic_outside_of_impl)]
+
+#[macro_use]
+extern crate tracing;
+
+pub extern crate rustc_plugin_impl as plugin;
+
+use rustc_ast as ast;
+use rustc_codegen_ssa::{traits::CodegenBackend, CodegenErrors, CodegenResults};
+use rustc_data_structures::profiling::{get_resident_set_size, print_time_passes_entry};
+use rustc_data_structures::sync::SeqCst;
+use rustc_errors::registry::{InvalidErrorCode, Registry};
+use rustc_errors::{ErrorGuaranteed, PResult};
+use rustc_feature::find_gated_cfg;
+use rustc_hir::def_id::LOCAL_CRATE;
+use rustc_interface::util::{self, collect_crate_types, get_codegen_backend};
+use rustc_interface::{interface, Queries};
+use rustc_lint::LintStore;
+use rustc_metadata::locator;
+use rustc_save_analysis as save;
+use rustc_save_analysis::DumpHandler;
+use rustc_session::config::{nightly_options, CG_OPTIONS, Z_OPTIONS};
+use rustc_session::config::{ErrorOutputType, Input, OutputType, PrintRequest, TrimmedDefPaths};
+use rustc_session::cstore::MetadataLoader;
+use rustc_session::getopts;
+use rustc_session::lint::{Lint, LintId};
+use rustc_session::{config, Session};
+use rustc_session::{early_error, early_error_no_abort, early_warn};
+use rustc_span::source_map::{FileLoader, FileName};
+use rustc_span::symbol::sym;
+use rustc_target::json::ToJson;
+
+use std::cmp::max;
+use std::env;
+use std::ffi::OsString;
+use std::fs;
+use std::io::{self, IsTerminal, Read, Write};
+use std::panic::{self, catch_unwind};
+use std::path::PathBuf;
+use std::process::{self, Command, Stdio};
+use std::str;
+use std::sync::LazyLock;
+use std::time::Instant;
+
+pub mod args;
+pub mod pretty;
+mod session_diagnostics;
+
+use crate::session_diagnostics::{
+ RLinkEmptyVersionNumber, RLinkEncodingVersionMismatch, RLinkRustcVersionMismatch,
+ RLinkWrongFileType, RlinkNotAFile, RlinkUnableToRead,
+};
+
+/// Exit status code used for successful compilation and help output.
+pub const EXIT_SUCCESS: i32 = 0;
+
+/// Exit status code used for compilation failures and invalid flags.
+pub const EXIT_FAILURE: i32 = 1;
+
+const BUG_REPORT_URL: &str = "https://github.com/rust-lang/rust/issues/new\
+ ?labels=C-bug%2C+I-ICE%2C+T-compiler&template=ice.md";
+
+const ICE_REPORT_COMPILER_FLAGS: &[&str] = &["-Z", "-C", "--crate-type"];
+
+const ICE_REPORT_COMPILER_FLAGS_EXCLUDE: &[&str] = &["metadata", "extra-filename"];
+
+const ICE_REPORT_COMPILER_FLAGS_STRIP_VALUE: &[&str] = &["incremental"];
+
+pub fn abort_on_err<T>(result: Result<T, ErrorGuaranteed>, sess: &Session) -> T {
+ match result {
+ Err(..) => {
+ sess.abort_if_errors();
+ panic!("error reported but abort_if_errors didn't abort???");
+ }
+ Ok(x) => x,
+ }
+}
+
+pub trait Callbacks {
+ /// Called before creating the compiler instance
+ fn config(&mut self, _config: &mut interface::Config) {}
+ /// Called after parsing. Return value instructs the compiler whether to
+ /// continue the compilation afterwards (defaults to `Compilation::Continue`)
+ fn after_parsing<'tcx>(
+ &mut self,
+ _compiler: &interface::Compiler,
+ _queries: &'tcx Queries<'tcx>,
+ ) -> Compilation {
+ Compilation::Continue
+ }
+ /// Called after expansion. Return value instructs the compiler whether to
+ /// continue the compilation afterwards (defaults to `Compilation::Continue`)
+ fn after_expansion<'tcx>(
+ &mut self,
+ _compiler: &interface::Compiler,
+ _queries: &'tcx Queries<'tcx>,
+ ) -> Compilation {
+ Compilation::Continue
+ }
+ /// Called after analysis. Return value instructs the compiler whether to
+ /// continue the compilation afterwards (defaults to `Compilation::Continue`)
+ fn after_analysis<'tcx>(
+ &mut self,
+ _compiler: &interface::Compiler,
+ _queries: &'tcx Queries<'tcx>,
+ ) -> Compilation {
+ Compilation::Continue
+ }
+}
+
+#[derive(Default)]
+pub struct TimePassesCallbacks {
+ time_passes: bool,
+}
+
+impl Callbacks for TimePassesCallbacks {
+ // JUSTIFICATION: the session doesn't exist at this point.
+ #[allow(rustc::bad_opt_access)]
+ fn config(&mut self, config: &mut interface::Config) {
+ // If a --print=... option has been given, we don't print the "total"
+ // time because it will mess up the --print output. See #64339.
+ //
+ self.time_passes = config.opts.prints.is_empty() && config.opts.unstable_opts.time_passes;
+ config.opts.trimmed_def_paths = TrimmedDefPaths::GoodPath;
+ }
+}
+
+pub fn diagnostics_registry() -> Registry {
+ Registry::new(rustc_error_codes::DIAGNOSTICS)
+}
+
+/// This is the primary entry point for rustc.
+pub struct RunCompiler<'a, 'b> {
+ at_args: &'a [String],
+ callbacks: &'b mut (dyn Callbacks + Send),
+ file_loader: Option<Box<dyn FileLoader + Send + Sync>>,
+ make_codegen_backend:
+ Option<Box<dyn FnOnce(&config::Options) -> Box<dyn CodegenBackend> + Send>>,
+}
+
+impl<'a, 'b> RunCompiler<'a, 'b> {
+ pub fn new(at_args: &'a [String], callbacks: &'b mut (dyn Callbacks + Send)) -> Self {
+ Self { at_args, callbacks, file_loader: None, make_codegen_backend: None }
+ }
+
+ /// Set a custom codegen backend.
+ ///
+ /// Has no uses within this repository, but is used by bjorn3 for "the
+ /// hotswapping branch of cg_clif" for "setting the codegen backend from a
+ /// custom driver where the custom codegen backend has arbitrary data."
+ /// (See #102759.)
+ pub fn set_make_codegen_backend(
+ &mut self,
+ make_codegen_backend: Option<
+ Box<dyn FnOnce(&config::Options) -> Box<dyn CodegenBackend> + Send>,
+ >,
+ ) -> &mut Self {
+ self.make_codegen_backend = make_codegen_backend;
+ self
+ }
+
+ /// Load files from sources other than the file system.
+ ///
+ /// Has no uses within this repository, but may be used in the future by
+ /// bjorn3 for "hooking rust-analyzer's VFS into rustc at some point for
+ /// running rustc without having to save". (See #102759.)
+ pub fn set_file_loader(
+ &mut self,
+ file_loader: Option<Box<dyn FileLoader + Send + Sync>>,
+ ) -> &mut Self {
+ self.file_loader = file_loader;
+ self
+ }
+
+ /// Parse args and run the compiler.
+ pub fn run(self) -> interface::Result<()> {
+ run_compiler(self.at_args, self.callbacks, self.file_loader, self.make_codegen_backend)
+ }
+}
+
+fn run_compiler(
+ at_args: &[String],
+ callbacks: &mut (dyn Callbacks + Send),
+ file_loader: Option<Box<dyn FileLoader + Send + Sync>>,
+ make_codegen_backend: Option<
+ Box<dyn FnOnce(&config::Options) -> Box<dyn CodegenBackend> + Send>,
+ >,
+) -> interface::Result<()> {
+ let args = args::arg_expand_all(at_args);
+
+ let Some(matches) = handle_options(&args) else { return Ok(()) };
+
+ let sopts = config::build_session_options(&matches);
+
+ if let Some(ref code) = matches.opt_str("explain") {
+ handle_explain(diagnostics_registry(), code, sopts.error_format);
+ return Ok(());
+ }
+
+ let cfg = interface::parse_cfgspecs(matches.opt_strs("cfg"));
+ let check_cfg = interface::parse_check_cfg(matches.opt_strs("check-cfg"));
+ let (odir, ofile) = make_output(&matches);
+ let mut config = interface::Config {
+ opts: sopts,
+ crate_cfg: cfg,
+ crate_check_cfg: check_cfg,
+ input: Input::File(PathBuf::new()),
+ output_file: ofile,
+ output_dir: odir,
+ file_loader,
+ lint_caps: Default::default(),
+ parse_sess_created: None,
+ register_lints: None,
+ override_queries: None,
+ make_codegen_backend,
+ registry: diagnostics_registry(),
+ };
+
+ if !tracing::dispatcher::has_been_set() {
+ init_rustc_env_logger_with_backtrace_option(&config.opts.unstable_opts.log_backtrace);
+ }
+
+ match make_input(config.opts.error_format, &matches.free) {
+ Err(reported) => return Err(reported),
+ Ok(Some(input)) => {
+ config.input = input;
+
+ callbacks.config(&mut config);
+ }
+ Ok(None) => match matches.free.len() {
+ 0 => {
+ callbacks.config(&mut config);
+ interface::run_compiler(config, |compiler| {
+ let sopts = &compiler.session().opts;
+ if sopts.describe_lints {
+ let mut lint_store =
+ rustc_lint::new_lint_store(compiler.session().enable_internal_lints());
+ let registered_lints =
+ if let Some(register_lints) = compiler.register_lints() {
+ register_lints(compiler.session(), &mut lint_store);
+ true
+ } else {
+ false
+ };
+ describe_lints(compiler.session(), &lint_store, registered_lints);
+ return;
+ }
+ let should_stop =
+ print_crate_info(&***compiler.codegen_backend(), compiler.session(), false);
+
+ if should_stop == Compilation::Stop {
+ return;
+ }
+ early_error(sopts.error_format, "no input filename given")
+ });
+ return Ok(());
+ }
+ 1 => panic!("make_input should have provided valid inputs"),
+ _ => early_error(
+ config.opts.error_format,
+ &format!(
+ "multiple input filenames provided (first two filenames are `{}` and `{}`)",
+ matches.free[0], matches.free[1],
+ ),
+ ),
+ },
+ };
+
+ interface::run_compiler(config, |compiler| {
+ let sess = compiler.session();
+ let should_stop = print_crate_info(&***compiler.codegen_backend(), sess, true)
+ .and_then(|| list_metadata(sess, &*compiler.codegen_backend().metadata_loader()))
+ .and_then(|| try_process_rlink(sess, compiler));
+
+ if should_stop == Compilation::Stop {
+ return sess.compile_status();
+ }
+
+ let linker = compiler.enter(|queries| {
+ let early_exit = || sess.compile_status().map(|_| None);
+ queries.parse()?;
+
+ if let Some(ppm) = &sess.opts.pretty {
+ if ppm.needs_ast_map() {
+ queries.global_ctxt()?.enter(|tcx| {
+ pretty::print_after_hir_lowering(tcx, *ppm);
+ Ok(())
+ })?;
+ } else {
+ let krate = queries.parse()?.steal();
+ pretty::print_after_parsing(sess, &krate, *ppm);
+ }
+ trace!("finished pretty-printing");
+ return early_exit();
+ }
+
+ if callbacks.after_parsing(compiler, queries) == Compilation::Stop {
+ return early_exit();
+ }
+
+ if sess.opts.unstable_opts.parse_only || sess.opts.unstable_opts.show_span.is_some() {
+ return early_exit();
+ }
+
+ {
+ let plugins = queries.register_plugins()?;
+ let (_, lint_store) = &*plugins.borrow();
+
+ // Lint plugins are registered; now we can process command line flags.
+ if sess.opts.describe_lints {
+ describe_lints(sess, lint_store, true);
+ return early_exit();
+ }
+ }
+
+ let mut gctxt = queries.global_ctxt()?;
+ if callbacks.after_expansion(compiler, queries) == Compilation::Stop {
+ return early_exit();
+ }
+
+ // Make sure the `output_filenames` query is run for its side
+ // effects of writing the dep-info and reporting errors.
+ gctxt.enter(|tcx| tcx.output_filenames(()));
+
+ if sess.opts.output_types.contains_key(&OutputType::DepInfo)
+ && sess.opts.output_types.len() == 1
+ {
+ return early_exit();
+ }
+
+ if sess.opts.unstable_opts.no_analysis {
+ return early_exit();
+ }
+
+ gctxt.enter(|tcx| {
+ let result = tcx.analysis(());
+ if sess.opts.unstable_opts.save_analysis {
+ let crate_name = tcx.crate_name(LOCAL_CRATE);
+ sess.time("save_analysis", || {
+ save::process_crate(
+ tcx,
+ crate_name,
+ &sess.io.input,
+ None,
+ DumpHandler::new(sess.io.output_dir.as_deref(), crate_name),
+ )
+ });
+ }
+ result
+ })?;
+
+ drop(gctxt);
+
+ if callbacks.after_analysis(compiler, queries) == Compilation::Stop {
+ return early_exit();
+ }
+
+ queries.ongoing_codegen()?;
+
+ if sess.opts.unstable_opts.print_type_sizes {
+ sess.code_stats.print_type_sizes();
+ }
+
+ let linker = queries.linker()?;
+ Ok(Some(linker))
+ })?;
+
+ if let Some(linker) = linker {
+ let _timer = sess.timer("link");
+ linker.link()?
+ }
+
+ if sess.opts.unstable_opts.perf_stats {
+ sess.print_perf_stats();
+ }
+
+ if sess.opts.unstable_opts.print_fuel.is_some() {
+ eprintln!(
+ "Fuel used by {}: {}",
+ sess.opts.unstable_opts.print_fuel.as_ref().unwrap(),
+ sess.print_fuel.load(SeqCst)
+ );
+ }
+
+ Ok(())
+ })
+}
+
+// Extract output directory and file from matches.
+fn make_output(matches: &getopts::Matches) -> (Option<PathBuf>, Option<PathBuf>) {
+ let odir = matches.opt_str("out-dir").map(|o| PathBuf::from(&o));
+ let ofile = matches.opt_str("o").map(|o| PathBuf::from(&o));
+ (odir, ofile)
+}
+
+// Extract input (string or file and optional path) from matches.
+fn make_input(
+ error_format: ErrorOutputType,
+ free_matches: &[String],
+) -> Result<Option<Input>, ErrorGuaranteed> {
+ if free_matches.len() == 1 {
+ let ifile = &free_matches[0];
+ if ifile == "-" {
+ let mut src = String::new();
+ if io::stdin().read_to_string(&mut src).is_err() {
+ // Immediately stop compilation if there was an issue reading
+ // the input (for example if the input stream is not UTF-8).
+ let reported = early_error_no_abort(
+ error_format,
+ "couldn't read from stdin, as it did not contain valid UTF-8",
+ );
+ return Err(reported);
+ }
+ if let Ok(path) = env::var("UNSTABLE_RUSTDOC_TEST_PATH") {
+ let line = env::var("UNSTABLE_RUSTDOC_TEST_LINE").expect(
+ "when UNSTABLE_RUSTDOC_TEST_PATH is set \
+ UNSTABLE_RUSTDOC_TEST_LINE also needs to be set",
+ );
+ let line = isize::from_str_radix(&line, 10)
+ .expect("UNSTABLE_RUSTDOC_TEST_LINE needs to be an number");
+ let file_name = FileName::doc_test_source_code(PathBuf::from(path), line);
+ Ok(Some(Input::Str { name: file_name, input: src }))
+ } else {
+ Ok(Some(Input::Str { name: FileName::anon_source_code(&src), input: src }))
+ }
+ } else {
+ Ok(Some(Input::File(PathBuf::from(ifile))))
+ }
+ } else {
+ Ok(None)
+ }
+}
+
+/// Whether to stop or continue compilation.
+#[derive(Copy, Clone, Debug, Eq, PartialEq)]
+pub enum Compilation {
+ Stop,
+ Continue,
+}
+
+impl Compilation {
+ pub fn and_then<F: FnOnce() -> Compilation>(self, next: F) -> Compilation {
+ match self {
+ Compilation::Stop => Compilation::Stop,
+ Compilation::Continue => next(),
+ }
+ }
+}
+
+fn handle_explain(registry: Registry, code: &str, output: ErrorOutputType) {
+ let upper_cased_code = code.to_ascii_uppercase();
+ let normalised =
+ if upper_cased_code.starts_with('E') { upper_cased_code } else { format!("E{code:0>4}") };
+ match registry.try_find_description(&normalised) {
+ Ok(Some(description)) => {
+ let mut is_in_code_block = false;
+ let mut text = String::new();
+ // Slice off the leading newline and print.
+ for line in description.lines() {
+ let indent_level =
+ line.find(|c: char| !c.is_whitespace()).unwrap_or_else(|| line.len());
+ let dedented_line = &line[indent_level..];
+ if dedented_line.starts_with("```") {
+ is_in_code_block = !is_in_code_block;
+ text.push_str(&line[..(indent_level + 3)]);
+ } else if is_in_code_block && dedented_line.starts_with("# ") {
+ continue;
+ } else {
+ text.push_str(line);
+ }
+ text.push('\n');
+ }
+ if io::stdout().is_terminal() {
+ show_content_with_pager(&text);
+ } else {
+ print!("{text}");
+ }
+ }
+ Ok(None) => {
+ early_error(output, &format!("no extended information for {code}"));
+ }
+ Err(InvalidErrorCode) => {
+ early_error(output, &format!("{code} is not a valid error code"));
+ }
+ }
+}
+
+fn show_content_with_pager(content: &str) {
+ let pager_name = env::var_os("PAGER").unwrap_or_else(|| {
+ if cfg!(windows) { OsString::from("more.com") } else { OsString::from("less") }
+ });
+
+ let mut fallback_to_println = false;
+
+ match Command::new(pager_name).stdin(Stdio::piped()).spawn() {
+ Ok(mut pager) => {
+ if let Some(pipe) = pager.stdin.as_mut() {
+ if pipe.write_all(content.as_bytes()).is_err() {
+ fallback_to_println = true;
+ }
+ }
+
+ if pager.wait().is_err() {
+ fallback_to_println = true;
+ }
+ }
+ Err(_) => {
+ fallback_to_println = true;
+ }
+ }
+
+ // If pager fails for whatever reason, we should still print the content
+ // to standard output
+ if fallback_to_println {
+ print!("{content}");
+ }
+}
+
+pub fn try_process_rlink(sess: &Session, compiler: &interface::Compiler) -> Compilation {
+ if sess.opts.unstable_opts.link_only {
+ if let Input::File(file) = &sess.io.input {
+ // FIXME: #![crate_type] and #![crate_name] support not implemented yet
+ sess.init_crate_types(collect_crate_types(sess, &[]));
+ let outputs = compiler.build_output_filenames(sess, &[]);
+ let rlink_data = fs::read(file).unwrap_or_else(|err| {
+ sess.emit_fatal(RlinkUnableToRead { err });
+ });
+ let codegen_results = match CodegenResults::deserialize_rlink(rlink_data) {
+ Ok(codegen) => codegen,
+ Err(err) => {
+ match err {
+ CodegenErrors::WrongFileType => sess.emit_fatal(RLinkWrongFileType),
+ CodegenErrors::EmptyVersionNumber => {
+ sess.emit_fatal(RLinkEmptyVersionNumber)
+ }
+ CodegenErrors::EncodingVersionMismatch { version_array, rlink_version } => {
+ sess.emit_fatal(RLinkEncodingVersionMismatch {
+ version_array,
+ rlink_version,
+ })
+ }
+ CodegenErrors::RustcVersionMismatch { rustc_version, current_version } => {
+ sess.emit_fatal(RLinkRustcVersionMismatch {
+ rustc_version,
+ current_version,
+ })
+ }
+ };
+ }
+ };
+ let result = compiler.codegen_backend().link(sess, codegen_results, &outputs);
+ abort_on_err(result, sess);
+ } else {
+ sess.emit_fatal(RlinkNotAFile {})
+ }
+ Compilation::Stop
+ } else {
+ Compilation::Continue
+ }
+}
+
+pub fn list_metadata(sess: &Session, metadata_loader: &dyn MetadataLoader) -> Compilation {
+ if sess.opts.unstable_opts.ls {
+ match sess.io.input {
+ Input::File(ref ifile) => {
+ let path = &(*ifile);
+ let mut v = Vec::new();
+ locator::list_file_metadata(&sess.target, path, metadata_loader, &mut v).unwrap();
+ println!("{}", String::from_utf8(v).unwrap());
+ }
+ Input::Str { .. } => {
+ early_error(ErrorOutputType::default(), "cannot list metadata for stdin");
+ }
+ }
+ return Compilation::Stop;
+ }
+
+ Compilation::Continue
+}
+
+fn print_crate_info(
+ codegen_backend: &dyn CodegenBackend,
+ sess: &Session,
+ parse_attrs: bool,
+) -> Compilation {
+ use rustc_session::config::PrintRequest::*;
+ // NativeStaticLibs and LinkArgs are special - printed during linking
+ // (empty iterator returns true)
+ if sess.opts.prints.iter().all(|&p| p == NativeStaticLibs || p == LinkArgs) {
+ return Compilation::Continue;
+ }
+
+ let attrs = if parse_attrs {
+ let result = parse_crate_attrs(sess);
+ match result {
+ Ok(attrs) => Some(attrs),
+ Err(mut parse_error) => {
+ parse_error.emit();
+ return Compilation::Stop;
+ }
+ }
+ } else {
+ None
+ };
+ for req in &sess.opts.prints {
+ match *req {
+ TargetList => {
+ let mut targets = rustc_target::spec::TARGETS.to_vec();
+ targets.sort_unstable();
+ println!("{}", targets.join("\n"));
+ }
+ Sysroot => println!("{}", sess.sysroot.display()),
+ TargetLibdir => println!("{}", sess.target_tlib_path.dir.display()),
+ TargetSpec => {
+ println!("{}", serde_json::to_string_pretty(&sess.target.to_json()).unwrap());
+ }
+ FileNames | CrateName => {
+ let attrs = attrs.as_ref().unwrap();
+ let t_outputs = rustc_interface::util::build_output_filenames(attrs, sess);
+ let id = rustc_session::output::find_crate_name(sess, attrs);
+ if *req == PrintRequest::CrateName {
+ println!("{id}");
+ continue;
+ }
+ let crate_types = collect_crate_types(sess, attrs);
+ for &style in &crate_types {
+ let fname =
+ rustc_session::output::filename_for_input(sess, style, id, &t_outputs);
+ println!("{}", fname.file_name().unwrap().to_string_lossy());
+ }
+ }
+ Cfg => {
+ let mut cfgs = sess
+ .parse_sess
+ .config
+ .iter()
+ .filter_map(|&(name, value)| {
+ // Note that crt-static is a specially recognized cfg
+ // directive that's printed out here as part of
+ // rust-lang/rust#37406, but in general the
+ // `target_feature` cfg is gated under
+ // rust-lang/rust#29717. For now this is just
+ // specifically allowing the crt-static cfg and that's
+ // it, this is intended to get into Cargo and then go
+ // through to build scripts.
+ if (name != sym::target_feature || value != Some(sym::crt_dash_static))
+ && !sess.is_nightly_build()
+ && find_gated_cfg(|cfg_sym| cfg_sym == name).is_some()
+ {
+ return None;
+ }
+
+ if let Some(value) = value {
+ Some(format!("{name}=\"{value}\""))
+ } else {
+ Some(name.to_string())
+ }
+ })
+ .collect::<Vec<String>>();
+
+ cfgs.sort();
+ for cfg in cfgs {
+ println!("{cfg}");
+ }
+ }
+ CallingConventions => {
+ let mut calling_conventions = rustc_target::spec::abi::all_names();
+ calling_conventions.sort_unstable();
+ println!("{}", calling_conventions.join("\n"));
+ }
+ RelocationModels
+ | CodeModels
+ | TlsModels
+ | TargetCPUs
+ | StackProtectorStrategies
+ | TargetFeatures => {
+ codegen_backend.print(*req, sess);
+ }
+ // Any output here interferes with Cargo's parsing of other printed output
+ NativeStaticLibs => {}
+ LinkArgs => {}
+ SplitDebuginfo => {
+ use rustc_target::spec::SplitDebuginfo::{Off, Packed, Unpacked};
+
+ for split in &[Off, Packed, Unpacked] {
+ let stable = sess.target.options.supported_split_debuginfo.contains(split);
+ let unstable_ok = sess.unstable_options();
+ if stable || unstable_ok {
+ println!("{split}");
+ }
+ }
+ }
+ }
+ }
+ Compilation::Stop
+}
+
+/// Prints version information
+///
+/// NOTE: this is a macro to support drivers built at a different time than the main `rustc_driver` crate.
+pub macro version($binary: literal, $matches: expr) {
+ fn unw(x: Option<&str>) -> &str {
+ x.unwrap_or("unknown")
+ }
+ $crate::version_at_macro_invocation(
+ $binary,
+ $matches,
+ unw(option_env!("CFG_VERSION")),
+ unw(option_env!("CFG_VER_HASH")),
+ unw(option_env!("CFG_VER_DATE")),
+ unw(option_env!("CFG_RELEASE")),
+ )
+}
+
+#[doc(hidden)] // use the macro instead
+pub fn version_at_macro_invocation(
+ binary: &str,
+ matches: &getopts::Matches,
+ version: &str,
+ commit_hash: &str,
+ commit_date: &str,
+ release: &str,
+) {
+ let verbose = matches.opt_present("verbose");
+
+ println!("{binary} {version}");
+
+ if verbose {
+ println!("binary: {binary}");
+ println!("commit-hash: {commit_hash}");
+ println!("commit-date: {commit_date}");
+ println!("host: {}", config::host_triple());
+ println!("release: {release}");
+
+ let debug_flags = matches.opt_strs("Z");
+ let backend_name = debug_flags.iter().find_map(|x| x.strip_prefix("codegen-backend="));
+ get_codegen_backend(&None, backend_name).print_version();
+ }
+}
+
+fn usage(verbose: bool, include_unstable_options: bool, nightly_build: bool) {
+ let groups = if verbose { config::rustc_optgroups() } else { config::rustc_short_optgroups() };
+ let mut options = getopts::Options::new();
+ for option in groups.iter().filter(|x| include_unstable_options || x.is_stable()) {
+ (option.apply)(&mut options);
+ }
+ let message = "Usage: rustc [OPTIONS] INPUT";
+ let nightly_help = if nightly_build {
+ "\n -Z help Print unstable compiler options"
+ } else {
+ ""
+ };
+ let verbose_help = if verbose {
+ ""
+ } else {
+ "\n --help -v Print the full set of options rustc accepts"
+ };
+ let at_path = if verbose {
+ " @path Read newline separated options from `path`\n"
+ } else {
+ ""
+ };
+ println!(
+ "{options}{at_path}\nAdditional help:
+ -C help Print codegen options
+ -W help \
+ Print 'lint' options and default settings{nightly}{verbose}\n",
+ options = options.usage(message),
+ at_path = at_path,
+ nightly = nightly_help,
+ verbose = verbose_help
+ );
+}
+
+fn print_wall_help() {
+ println!(
+ "
+The flag `-Wall` does not exist in `rustc`. Most useful lints are enabled by
+default. Use `rustc -W help` to see all available lints. It's more common to put
+warning settings in the crate root using `#![warn(LINT_NAME)]` instead of using
+the command line flag directly.
+"
+ );
+}
+
+/// Write to stdout lint command options, together with a list of all available lints
+pub fn describe_lints(sess: &Session, lint_store: &LintStore, loaded_plugins: bool) {
+ println!(
+ "
+Available lint options:
+ -W <foo> Warn about <foo>
+ -A <foo> \
+ Allow <foo>
+ -D <foo> Deny <foo>
+ -F <foo> Forbid <foo> \
+ (deny <foo> and all attempts to override)
+
+"
+ );
+
+ fn sort_lints(sess: &Session, mut lints: Vec<&'static Lint>) -> Vec<&'static Lint> {
+ // The sort doesn't case-fold but it's doubtful we care.
+ lints.sort_by_cached_key(|x: &&Lint| (x.default_level(sess.edition()), x.name));
+ lints
+ }
+
+ fn sort_lint_groups(
+ lints: Vec<(&'static str, Vec<LintId>, bool)>,
+ ) -> Vec<(&'static str, Vec<LintId>)> {
+ let mut lints: Vec<_> = lints.into_iter().map(|(x, y, _)| (x, y)).collect();
+ lints.sort_by_key(|l| l.0);
+ lints
+ }
+
+ let (plugin, builtin): (Vec<_>, _) =
+ lint_store.get_lints().iter().cloned().partition(|&lint| lint.is_plugin);
+ let plugin = sort_lints(sess, plugin);
+ let builtin = sort_lints(sess, builtin);
+
+ let (plugin_groups, builtin_groups): (Vec<_>, _) =
+ lint_store.get_lint_groups().partition(|&(.., p)| p);
+ let plugin_groups = sort_lint_groups(plugin_groups);
+ let builtin_groups = sort_lint_groups(builtin_groups);
+
+ let max_name_len =
+ plugin.iter().chain(&builtin).map(|&s| s.name.chars().count()).max().unwrap_or(0);
+ let padded = |x: &str| {
+ let mut s = " ".repeat(max_name_len - x.chars().count());
+ s.push_str(x);
+ s
+ };
+
+ println!("Lint checks provided by rustc:\n");
+
+ let print_lints = |lints: Vec<&Lint>| {
+ println!(" {} {:7.7} {}", padded("name"), "default", "meaning");
+ println!(" {} {:7.7} {}", padded("----"), "-------", "-------");
+ for lint in lints {
+ let name = lint.name_lower().replace('_', "-");
+ println!(
+ " {} {:7.7} {}",
+ padded(&name),
+ lint.default_level(sess.edition()).as_str(),
+ lint.desc
+ );
+ }
+ println!("\n");
+ };
+
+ print_lints(builtin);
+
+ let max_name_len = max(
+ "warnings".len(),
+ plugin_groups
+ .iter()
+ .chain(&builtin_groups)
+ .map(|&(s, _)| s.chars().count())
+ .max()
+ .unwrap_or(0),
+ );
+
+ let padded = |x: &str| {
+ let mut s = " ".repeat(max_name_len - x.chars().count());
+ s.push_str(x);
+ s
+ };
+
+ println!("Lint groups provided by rustc:\n");
+
+ let print_lint_groups = |lints: Vec<(&'static str, Vec<LintId>)>, all_warnings| {
+ println!(" {} sub-lints", padded("name"));
+ println!(" {} ---------", padded("----"));
+
+ if all_warnings {
+ println!(" {} all lints that are set to issue warnings", padded("warnings"));
+ }
+
+ for (name, to) in lints {
+ let name = name.to_lowercase().replace('_', "-");
+ let desc = to
+ .into_iter()
+ .map(|x| x.to_string().replace('_', "-"))
+ .collect::<Vec<String>>()
+ .join(", ");
+ println!(" {} {}", padded(&name), desc);
+ }
+ println!("\n");
+ };
+
+ print_lint_groups(builtin_groups, true);
+
+ match (loaded_plugins, plugin.len(), plugin_groups.len()) {
+ (false, 0, _) | (false, _, 0) => {
+ println!("Lint tools like Clippy can provide additional lints and lint groups.");
+ }
+ (false, ..) => panic!("didn't load lint plugins but got them anyway!"),
+ (true, 0, 0) => println!("This crate does not load any lint plugins or lint groups."),
+ (true, l, g) => {
+ if l > 0 {
+ println!("Lint checks provided by plugins loaded by this crate:\n");
+ print_lints(plugin);
+ }
+ if g > 0 {
+ println!("Lint groups provided by plugins loaded by this crate:\n");
+ print_lint_groups(plugin_groups, false);
+ }
+ }
+ }
+}
+
+fn describe_debug_flags() {
+ println!("\nAvailable options:\n");
+ print_flag_list("-Z", config::Z_OPTIONS);
+}
+
+fn describe_codegen_flags() {
+ println!("\nAvailable codegen options:\n");
+ print_flag_list("-C", config::CG_OPTIONS);
+}
+
+pub fn print_flag_list<T>(
+ cmdline_opt: &str,
+ flag_list: &[(&'static str, T, &'static str, &'static str)],
+) {
+ let max_len = flag_list.iter().map(|&(name, _, _, _)| name.chars().count()).max().unwrap_or(0);
+
+ for &(name, _, _, desc) in flag_list {
+ println!(
+ " {} {:>width$}=val -- {}",
+ cmdline_opt,
+ name.replace('_', "-"),
+ desc,
+ width = max_len
+ );
+ }
+}
+
+/// Process command line options. Emits messages as appropriate. If compilation
+/// should continue, returns a getopts::Matches object parsed from args,
+/// otherwise returns `None`.
+///
+/// The compiler's handling of options is a little complicated as it ties into
+/// our stability story. The current intention of each compiler option is to
+/// have one of two modes:
+///
+/// 1. An option is stable and can be used everywhere.
+/// 2. An option is unstable, and can only be used on nightly.
+///
+/// Like unstable library and language features, however, unstable options have
+/// always required a form of "opt in" to indicate that you're using them. This
+/// provides the easy ability to scan a code base to check to see if anything
+/// unstable is being used. Currently, this "opt in" is the `-Z` "zed" flag.
+///
+/// All options behind `-Z` are considered unstable by default. Other top-level
+/// options can also be considered unstable, and they were unlocked through the
+/// `-Z unstable-options` flag. Note that `-Z` remains to be the root of
+/// instability in both cases, though.
+///
+/// So with all that in mind, the comments below have some more detail about the
+/// contortions done here to get things to work out correctly.
+pub fn handle_options(args: &[String]) -> Option<getopts::Matches> {
+ // Throw away the first argument, the name of the binary
+ let args = &args[1..];
+
+ if args.is_empty() {
+ // user did not write `-v` nor `-Z unstable-options`, so do not
+ // include that extra information.
+ let nightly_build =
+ rustc_feature::UnstableFeatures::from_environment(None).is_nightly_build();
+ usage(false, false, nightly_build);
+ return None;
+ }
+
+ // Parse with *all* options defined in the compiler, we don't worry about
+ // option stability here we just want to parse as much as possible.
+ let mut options = getopts::Options::new();
+ for option in config::rustc_optgroups() {
+ (option.apply)(&mut options);
+ }
+ let matches = options.parse(args).unwrap_or_else(|e| {
+ let msg = match e {
+ getopts::Fail::UnrecognizedOption(ref opt) => CG_OPTIONS
+ .iter()
+ .map(|&(name, ..)| ('C', name))
+ .chain(Z_OPTIONS.iter().map(|&(name, ..)| ('Z', name)))
+ .find(|&(_, name)| *opt == name.replace('_', "-"))
+ .map(|(flag, _)| format!("{e}. Did you mean `-{flag} {opt}`?")),
+ _ => None,
+ };
+ early_error(ErrorOutputType::default(), &msg.unwrap_or_else(|| e.to_string()));
+ });
+
+ // For all options we just parsed, we check a few aspects:
+ //
+ // * If the option is stable, we're all good
+ // * If the option wasn't passed, we're all good
+ // * If `-Z unstable-options` wasn't passed (and we're not a -Z option
+ // ourselves), then we require the `-Z unstable-options` flag to unlock
+ // this option that was passed.
+ // * If we're a nightly compiler, then unstable options are now unlocked, so
+ // we're good to go.
+ // * Otherwise, if we're an unstable option then we generate an error
+ // (unstable option being used on stable)
+ nightly_options::check_nightly_options(&matches, &config::rustc_optgroups());
+
+ if matches.opt_present("h") || matches.opt_present("help") {
+ // Only show unstable options in --help if we accept unstable options.
+ let unstable_enabled = nightly_options::is_unstable_enabled(&matches);
+ let nightly_build = nightly_options::match_is_nightly_build(&matches);
+ usage(matches.opt_present("verbose"), unstable_enabled, nightly_build);
+ return None;
+ }
+
+ // Handle the special case of -Wall.
+ let wall = matches.opt_strs("W");
+ if wall.iter().any(|x| *x == "all") {
+ print_wall_help();
+ rustc_errors::FatalError.raise();
+ }
+
+ // Don't handle -W help here, because we might first load plugins.
+ let debug_flags = matches.opt_strs("Z");
+ if debug_flags.iter().any(|x| *x == "help") {
+ describe_debug_flags();
+ return None;
+ }
+
+ let cg_flags = matches.opt_strs("C");
+
+ if cg_flags.iter().any(|x| *x == "help") {
+ describe_codegen_flags();
+ return None;
+ }
+
+ if cg_flags.iter().any(|x| *x == "no-stack-check") {
+ early_warn(
+ ErrorOutputType::default(),
+ "the --no-stack-check flag is deprecated and does nothing",
+ );
+ }
+
+ if cg_flags.iter().any(|x| *x == "passes=list") {
+ let backend_name = debug_flags.iter().find_map(|x| x.strip_prefix("codegen-backend="));
+ get_codegen_backend(&None, backend_name).print_passes();
+ return None;
+ }
+
+ if matches.opt_present("version") {
+ version!("rustc", &matches);
+ return None;
+ }
+
+ Some(matches)
+}
+
+fn parse_crate_attrs<'a>(sess: &'a Session) -> PResult<'a, ast::AttrVec> {
+ match &sess.io.input {
+ Input::File(ifile) => rustc_parse::parse_crate_attrs_from_file(ifile, &sess.parse_sess),
+ Input::Str { name, input } => rustc_parse::parse_crate_attrs_from_source_str(
+ name.clone(),
+ input.clone(),
+ &sess.parse_sess,
+ ),
+ }
+}
+
+/// Gets a list of extra command-line flags provided by the user, as strings.
+///
+/// This function is used during ICEs to show more information useful for
+/// debugging, since some ICEs only happens with non-default compiler flags
+/// (and the users don't always report them).
+fn extra_compiler_flags() -> Option<(Vec<String>, bool)> {
+ let mut args = env::args_os().map(|arg| arg.to_string_lossy().to_string()).peekable();
+
+ let mut result = Vec::new();
+ let mut excluded_cargo_defaults = false;
+ while let Some(arg) = args.next() {
+ if let Some(a) = ICE_REPORT_COMPILER_FLAGS.iter().find(|a| arg.starts_with(*a)) {
+ let content = if arg.len() == a.len() {
+ // A space-separated option, like `-C incremental=foo` or `--crate-type rlib`
+ match args.next() {
+ Some(arg) => arg.to_string(),
+ None => continue,
+ }
+ } else if arg.get(a.len()..a.len() + 1) == Some("=") {
+ // An equals option, like `--crate-type=rlib`
+ arg[a.len() + 1..].to_string()
+ } else {
+ // A non-space option, like `-Cincremental=foo`
+ arg[a.len()..].to_string()
+ };
+ let option = content.split_once('=').map(|s| s.0).unwrap_or(&content);
+ if ICE_REPORT_COMPILER_FLAGS_EXCLUDE.iter().any(|exc| option == *exc) {
+ excluded_cargo_defaults = true;
+ } else {
+ result.push(a.to_string());
+ match ICE_REPORT_COMPILER_FLAGS_STRIP_VALUE.iter().find(|s| option == **s) {
+ Some(s) => result.push(format!("{s}=[REDACTED]")),
+ None => result.push(content),
+ }
+ }
+ }
+ }
+
+ if !result.is_empty() { Some((result, excluded_cargo_defaults)) } else { None }
+}
+
+/// Runs a closure and catches unwinds triggered by fatal errors.
+///
+/// The compiler currently unwinds with a special sentinel value to abort
+/// compilation on fatal errors. This function catches that sentinel and turns
+/// the panic into a `Result` instead.
+pub fn catch_fatal_errors<F: FnOnce() -> R, R>(f: F) -> Result<R, ErrorGuaranteed> {
+ catch_unwind(panic::AssertUnwindSafe(f)).map_err(|value| {
+ if value.is::<rustc_errors::FatalErrorMarker>() {
+ ErrorGuaranteed::unchecked_claim_error_was_emitted()
+ } else {
+ panic::resume_unwind(value);
+ }
+ })
+}
+
+/// Variant of `catch_fatal_errors` for the `interface::Result` return type
+/// that also computes the exit code.
+pub fn catch_with_exit_code(f: impl FnOnce() -> interface::Result<()>) -> i32 {
+ let result = catch_fatal_errors(f).and_then(|result| result);
+ match result {
+ Ok(()) => EXIT_SUCCESS,
+ Err(_) => EXIT_FAILURE,
+ }
+}
+
+static DEFAULT_HOOK: LazyLock<Box<dyn Fn(&panic::PanicInfo<'_>) + Sync + Send + 'static>> =
+ LazyLock::new(|| {
+ let hook = panic::take_hook();
+ panic::set_hook(Box::new(|info| {
+ // If the error was caused by a broken pipe then this is not a bug.
+ // Write the error and return immediately. See #98700.
+ #[cfg(windows)]
+ if let Some(msg) = info.payload().downcast_ref::<String>() {
+ if msg.starts_with("failed printing to stdout: ") && msg.ends_with("(os error 232)")
+ {
+ early_error_no_abort(ErrorOutputType::default(), &msg);
+ return;
+ }
+ };
+
+ // Invoke the default handler, which prints the actual panic message and optionally a backtrace
+ // Don't do this for delayed bugs, which already emit their own more useful backtrace.
+ if !info.payload().is::<rustc_errors::DelayedBugPanic>() {
+ (*DEFAULT_HOOK)(info);
+
+ // Separate the output with an empty line
+ eprintln!();
+ }
+
+ // Print the ICE message
+ report_ice(info, BUG_REPORT_URL);
+ }));
+ hook
+ });
+
+/// Prints the ICE message, including query stack, but without backtrace.
+///
+/// The message will point the user at `bug_report_url` to report the ICE.
+///
+/// When `install_ice_hook` is called, this function will be called as the panic
+/// hook.
+pub fn report_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str) {
+ let fallback_bundle =
+ rustc_errors::fallback_fluent_bundle(rustc_errors::DEFAULT_LOCALE_RESOURCES, false);
+ let emitter = Box::new(rustc_errors::emitter::EmitterWriter::stderr(
+ rustc_errors::ColorConfig::Auto,
+ None,
+ None,
+ fallback_bundle,
+ false,
+ false,
+ None,
+ false,
+ false,
+ ));
+ let handler = rustc_errors::Handler::with_emitter(true, None, emitter);
+
+ // a .span_bug or .bug call has already printed what
+ // it wants to print.
+ if !info.payload().is::<rustc_errors::ExplicitBug>()
+ && !info.payload().is::<rustc_errors::DelayedBugPanic>()
+ {
+ let mut d = rustc_errors::Diagnostic::new(rustc_errors::Level::Bug, "unexpected panic");
+ handler.emit_diagnostic(&mut d);
+ }
+
+ handler.emit_note(session_diagnostics::Ice);
+ handler.emit_note(session_diagnostics::IceBugReport { bug_report_url });
+ handler.emit_note(session_diagnostics::IceVersion {
+ version: util::version_str!().unwrap_or("unknown_version"),
+ triple: config::host_triple(),
+ });
+
+ if let Some((flags, excluded_cargo_defaults)) = extra_compiler_flags() {
+ handler.emit_note(session_diagnostics::IceFlags { flags: flags.join(" ") });
+ if excluded_cargo_defaults {
+ handler.emit_note(session_diagnostics::IceExcludeCargoDefaults);
+ }
+ }
+
+ // If backtraces are enabled, also print the query stack
+ let backtrace = env::var_os("RUST_BACKTRACE").map_or(false, |x| &x != "0");
+
+ let num_frames = if backtrace { None } else { Some(2) };
+
+ interface::try_print_query_stack(&handler, num_frames);
+
+ #[cfg(windows)]
+ unsafe {
+ if env::var("RUSTC_BREAK_ON_ICE").is_ok() {
+ // Trigger a debugger if we crashed during bootstrap
+ winapi::um::debugapi::DebugBreak();
+ }
+ }
+}
+
+/// Installs a panic hook that will print the ICE message on unexpected panics.
+///
+/// A custom rustc driver can skip calling this to set up a custom ICE hook.
+pub fn install_ice_hook() {
+ // If the user has not explicitly overridden "RUST_BACKTRACE", then produce
+ // full backtraces. When a compiler ICE happens, we want to gather
+ // as much information as possible to present in the issue opened
+ // by the user. Compiler developers and other rustc users can
+ // opt in to less-verbose backtraces by manually setting "RUST_BACKTRACE"
+ // (e.g. `RUST_BACKTRACE=1`)
+ if std::env::var("RUST_BACKTRACE").is_err() {
+ std::env::set_var("RUST_BACKTRACE", "full");
+ }
+ LazyLock::force(&DEFAULT_HOOK);
+}
+
+/// This allows tools to enable rust logging without having to magically match rustc's
+/// tracing crate version.
+pub fn init_rustc_env_logger() {
+ init_rustc_env_logger_with_backtrace_option(&None);
+}
+
+/// This allows tools to enable rust logging without having to magically match rustc's
+/// tracing crate version. In contrast to `init_rustc_env_logger` it allows you to
+/// choose a target module you wish to show backtraces along with its logging.
+pub fn init_rustc_env_logger_with_backtrace_option(backtrace_target: &Option<String>) {
+ if let Err(error) = rustc_log::init_rustc_env_logger_with_backtrace_option(backtrace_target) {
+ early_error(ErrorOutputType::default(), &error.to_string());
+ }
+}
+
+/// This allows tools to enable rust logging without having to magically match rustc's
+/// tracing crate version. In contrast to `init_rustc_env_logger` it allows you to choose an env var
+/// other than `RUSTC_LOG`.
+pub fn init_env_logger(env: &str) {
+ if let Err(error) = rustc_log::init_env_logger(env) {
+ early_error(ErrorOutputType::default(), &error.to_string());
+ }
+}
+
+#[cfg(all(unix, any(target_env = "gnu", target_os = "macos")))]
+mod signal_handler {
+ extern "C" {
+ fn backtrace_symbols_fd(
+ buffer: *const *mut libc::c_void,
+ size: libc::c_int,
+ fd: libc::c_int,
+ );
+ }
+
+ extern "C" fn print_stack_trace(_: libc::c_int) {
+ const MAX_FRAMES: usize = 256;
+ static mut STACK_TRACE: [*mut libc::c_void; MAX_FRAMES] =
+ [std::ptr::null_mut(); MAX_FRAMES];
+ unsafe {
+ let depth = libc::backtrace(STACK_TRACE.as_mut_ptr(), MAX_FRAMES as i32);
+ if depth == 0 {
+ return;
+ }
+ backtrace_symbols_fd(STACK_TRACE.as_ptr(), depth, 2);
+ }
+ }
+
+ /// When an error signal (such as SIGABRT or SIGSEGV) is delivered to the
+ /// process, print a stack trace and then exit.
+ pub(super) fn install() {
+ unsafe {
+ const ALT_STACK_SIZE: usize = libc::MINSIGSTKSZ + 64 * 1024;
+ let mut alt_stack: libc::stack_t = std::mem::zeroed();
+ alt_stack.ss_sp =
+ std::alloc::alloc(std::alloc::Layout::from_size_align(ALT_STACK_SIZE, 1).unwrap())
+ as *mut libc::c_void;
+ alt_stack.ss_size = ALT_STACK_SIZE;
+ libc::sigaltstack(&alt_stack, std::ptr::null_mut());
+
+ let mut sa: libc::sigaction = std::mem::zeroed();
+ sa.sa_sigaction = print_stack_trace as libc::sighandler_t;
+ sa.sa_flags = libc::SA_NODEFER | libc::SA_RESETHAND | libc::SA_ONSTACK;
+ libc::sigemptyset(&mut sa.sa_mask);
+ libc::sigaction(libc::SIGSEGV, &sa, std::ptr::null_mut());
+ }
+ }
+}
+
+#[cfg(not(all(unix, any(target_env = "gnu", target_os = "macos"))))]
+mod signal_handler {
+ pub(super) fn install() {}
+}
+
+pub fn main() -> ! {
+ let start_time = Instant::now();
+ let start_rss = get_resident_set_size();
+ signal_handler::install();
+ let mut callbacks = TimePassesCallbacks::default();
+ install_ice_hook();
+ let exit_code = catch_with_exit_code(|| {
+ let args = env::args_os()
+ .enumerate()
+ .map(|(i, arg)| {
+ arg.into_string().unwrap_or_else(|arg| {
+ early_error(
+ ErrorOutputType::default(),
+ &format!("argument {i} is not valid Unicode: {arg:?}"),
+ )
+ })
+ })
+ .collect::<Vec<_>>();
+ RunCompiler::new(&args, &mut callbacks).run()
+ });
+
+ if callbacks.time_passes {
+ let end_rss = get_resident_set_size();
+ print_time_passes_entry("total", start_time.elapsed(), start_rss, end_rss);
+ }
+
+ process::exit(exit_code)
+}
--- /dev/null
+//! The various pretty-printing routines.
+
+use crate::session_diagnostics::UnprettyDumpFail;
+use rustc_ast as ast;
+use rustc_ast_pretty::pprust;
+use rustc_errors::ErrorGuaranteed;
+use rustc_hir as hir;
+use rustc_hir_pretty as pprust_hir;
+use rustc_middle::hir::map as hir_map;
+use rustc_middle::mir::{write_mir_graphviz, write_mir_pretty};
+use rustc_middle::ty::{self, TyCtxt};
+use rustc_session::config::{PpAstTreeMode, PpHirMode, PpMode, PpSourceMode};
+use rustc_session::Session;
+use rustc_span::symbol::Ident;
+use rustc_span::FileName;
+
+use std::cell::Cell;
+use std::fmt::Write;
+
+pub use self::PpMode::*;
+pub use self::PpSourceMode::*;
+use crate::abort_on_err;
+
+// This slightly awkward construction is to allow for each PpMode to
+// choose whether it needs to do analyses (which can consume the
+// Session) and then pass through the session (now attached to the
+// analysis results) on to the chosen pretty-printer, along with the
+// `&PpAnn` object.
+//
+// Note that since the `&PrinterSupport` is freshly constructed on each
+// call, it would not make sense to try to attach the lifetime of `self`
+// to the lifetime of the `&PrinterObject`.
+
+/// Constructs a `PrinterSupport` object and passes it to `f`.
+fn call_with_pp_support<'tcx, A, F>(
+ ppmode: &PpSourceMode,
+ sess: &'tcx Session,
+ tcx: Option<TyCtxt<'tcx>>,
+ f: F,
+) -> A
+where
+ F: FnOnce(&dyn PrinterSupport) -> A,
+{
+ match *ppmode {
+ Normal | Expanded => {
+ let annotation = NoAnn { sess, tcx };
+ f(&annotation)
+ }
+
+ Identified | ExpandedIdentified => {
+ let annotation = IdentifiedAnnotation { sess, tcx };
+ f(&annotation)
+ }
+ ExpandedHygiene => {
+ let annotation = HygieneAnnotation { sess };
+ f(&annotation)
+ }
+ }
+}
+fn call_with_pp_support_hir<A, F>(ppmode: &PpHirMode, tcx: TyCtxt<'_>, f: F) -> A
+where
+ F: FnOnce(&dyn HirPrinterSupport<'_>, hir_map::Map<'_>) -> A,
+{
+ match *ppmode {
+ PpHirMode::Normal => {
+ let annotation = NoAnn { sess: tcx.sess, tcx: Some(tcx) };
+ f(&annotation, tcx.hir())
+ }
+
+ PpHirMode::Identified => {
+ let annotation = IdentifiedAnnotation { sess: tcx.sess, tcx: Some(tcx) };
+ f(&annotation, tcx.hir())
+ }
+ PpHirMode::Typed => {
+ abort_on_err(tcx.analysis(()), tcx.sess);
+
+ let annotation = TypedAnnotation { tcx, maybe_typeck_results: Cell::new(None) };
+ tcx.dep_graph.with_ignore(|| f(&annotation, tcx.hir()))
+ }
+ }
+}
+
+trait PrinterSupport: pprust::PpAnn {
+ /// Provides a uniform interface for re-extracting a reference to a
+ /// `Session` from a value that now owns it.
+ fn sess(&self) -> &Session;
+
+ /// Produces the pretty-print annotation object.
+ ///
+ /// (Rust does not yet support upcasting from a trait object to
+ /// an object for one of its supertraits.)
+ fn pp_ann(&self) -> &dyn pprust::PpAnn;
+}
+
+trait HirPrinterSupport<'hir>: pprust_hir::PpAnn {
+ /// Provides a uniform interface for re-extracting a reference to a
+ /// `Session` from a value that now owns it.
+ fn sess(&self) -> &Session;
+
+ /// Provides a uniform interface for re-extracting a reference to an
+ /// `hir_map::Map` from a value that now owns it.
+ fn hir_map(&self) -> Option<hir_map::Map<'hir>>;
+
+ /// Produces the pretty-print annotation object.
+ ///
+ /// (Rust does not yet support upcasting from a trait object to
+ /// an object for one of its supertraits.)
+ fn pp_ann(&self) -> &dyn pprust_hir::PpAnn;
+}
+
+struct NoAnn<'hir> {
+ sess: &'hir Session,
+ tcx: Option<TyCtxt<'hir>>,
+}
+
+impl<'hir> PrinterSupport for NoAnn<'hir> {
+ fn sess(&self) -> &Session {
+ self.sess
+ }
+
+ fn pp_ann(&self) -> &dyn pprust::PpAnn {
+ self
+ }
+}
+
+impl<'hir> HirPrinterSupport<'hir> for NoAnn<'hir> {
+ fn sess(&self) -> &Session {
+ self.sess
+ }
+
+ fn hir_map(&self) -> Option<hir_map::Map<'hir>> {
+ self.tcx.map(|tcx| tcx.hir())
+ }
+
+ fn pp_ann(&self) -> &dyn pprust_hir::PpAnn {
+ self
+ }
+}
+
+impl<'hir> pprust::PpAnn for NoAnn<'hir> {}
+impl<'hir> pprust_hir::PpAnn for NoAnn<'hir> {
+ fn nested(&self, state: &mut pprust_hir::State<'_>, nested: pprust_hir::Nested) {
+ if let Some(tcx) = self.tcx {
+ pprust_hir::PpAnn::nested(&(&tcx.hir() as &dyn hir::intravisit::Map<'_>), state, nested)
+ }
+ }
+}
+
+struct IdentifiedAnnotation<'hir> {
+ sess: &'hir Session,
+ tcx: Option<TyCtxt<'hir>>,
+}
+
+impl<'hir> PrinterSupport for IdentifiedAnnotation<'hir> {
+ fn sess(&self) -> &Session {
+ self.sess
+ }
+
+ fn pp_ann(&self) -> &dyn pprust::PpAnn {
+ self
+ }
+}
+
+impl<'hir> pprust::PpAnn for IdentifiedAnnotation<'hir> {
+ fn pre(&self, s: &mut pprust::State<'_>, node: pprust::AnnNode<'_>) {
+ if let pprust::AnnNode::Expr(_) = node {
+ s.popen();
+ }
+ }
+ fn post(&self, s: &mut pprust::State<'_>, node: pprust::AnnNode<'_>) {
+ match node {
+ pprust::AnnNode::Crate(_) | pprust::AnnNode::Ident(_) | pprust::AnnNode::Name(_) => {}
+
+ pprust::AnnNode::Item(item) => {
+ s.s.space();
+ s.synth_comment(item.id.to_string())
+ }
+ pprust::AnnNode::SubItem(id) => {
+ s.s.space();
+ s.synth_comment(id.to_string())
+ }
+ pprust::AnnNode::Block(blk) => {
+ s.s.space();
+ s.synth_comment(format!("block {}", blk.id))
+ }
+ pprust::AnnNode::Expr(expr) => {
+ s.s.space();
+ s.synth_comment(expr.id.to_string());
+ s.pclose()
+ }
+ pprust::AnnNode::Pat(pat) => {
+ s.s.space();
+ s.synth_comment(format!("pat {}", pat.id));
+ }
+ }
+ }
+}
+
+impl<'hir> HirPrinterSupport<'hir> for IdentifiedAnnotation<'hir> {
+ fn sess(&self) -> &Session {
+ self.sess
+ }
+
+ fn hir_map(&self) -> Option<hir_map::Map<'hir>> {
+ self.tcx.map(|tcx| tcx.hir())
+ }
+
+ fn pp_ann(&self) -> &dyn pprust_hir::PpAnn {
+ self
+ }
+}
+
+impl<'hir> pprust_hir::PpAnn for IdentifiedAnnotation<'hir> {
+ fn nested(&self, state: &mut pprust_hir::State<'_>, nested: pprust_hir::Nested) {
+ if let Some(ref tcx) = self.tcx {
+ pprust_hir::PpAnn::nested(&(&tcx.hir() as &dyn hir::intravisit::Map<'_>), state, nested)
+ }
+ }
+ fn pre(&self, s: &mut pprust_hir::State<'_>, node: pprust_hir::AnnNode<'_>) {
+ if let pprust_hir::AnnNode::Expr(_) = node {
+ s.popen();
+ }
+ }
+ fn post(&self, s: &mut pprust_hir::State<'_>, node: pprust_hir::AnnNode<'_>) {
+ match node {
+ pprust_hir::AnnNode::Name(_) => {}
+ pprust_hir::AnnNode::Item(item) => {
+ s.s.space();
+ s.synth_comment(format!("hir_id: {}", item.hir_id()));
+ }
+ pprust_hir::AnnNode::SubItem(id) => {
+ s.s.space();
+ s.synth_comment(id.to_string());
+ }
+ pprust_hir::AnnNode::Block(blk) => {
+ s.s.space();
+ s.synth_comment(format!("block hir_id: {}", blk.hir_id));
+ }
+ pprust_hir::AnnNode::Expr(expr) => {
+ s.s.space();
+ s.synth_comment(format!("expr hir_id: {}", expr.hir_id));
+ s.pclose();
+ }
+ pprust_hir::AnnNode::Pat(pat) => {
+ s.s.space();
+ s.synth_comment(format!("pat hir_id: {}", pat.hir_id));
+ }
+ pprust_hir::AnnNode::Arm(arm) => {
+ s.s.space();
+ s.synth_comment(format!("arm hir_id: {}", arm.hir_id));
+ }
+ }
+ }
+}
+
+struct HygieneAnnotation<'a> {
+ sess: &'a Session,
+}
+
+impl<'a> PrinterSupport for HygieneAnnotation<'a> {
+ fn sess(&self) -> &Session {
+ self.sess
+ }
+
+ fn pp_ann(&self) -> &dyn pprust::PpAnn {
+ self
+ }
+}
+
+impl<'a> pprust::PpAnn for HygieneAnnotation<'a> {
+ fn post(&self, s: &mut pprust::State<'_>, node: pprust::AnnNode<'_>) {
+ match node {
+ pprust::AnnNode::Ident(&Ident { name, span }) => {
+ s.s.space();
+ s.synth_comment(format!("{}{:?}", name.as_u32(), span.ctxt()))
+ }
+ pprust::AnnNode::Name(&name) => {
+ s.s.space();
+ s.synth_comment(name.as_u32().to_string())
+ }
+ pprust::AnnNode::Crate(_) => {
+ s.s.hardbreak();
+ let verbose = self.sess.verbose();
+ s.synth_comment(rustc_span::hygiene::debug_hygiene_data(verbose));
+ s.s.hardbreak_if_not_bol();
+ }
+ _ => {}
+ }
+ }
+}
+
+struct TypedAnnotation<'tcx> {
+ tcx: TyCtxt<'tcx>,
+ maybe_typeck_results: Cell<Option<&'tcx ty::TypeckResults<'tcx>>>,
+}
+
+impl<'tcx> HirPrinterSupport<'tcx> for TypedAnnotation<'tcx> {
+ fn sess(&self) -> &Session {
+ self.tcx.sess
+ }
+
+ fn hir_map(&self) -> Option<hir_map::Map<'tcx>> {
+ Some(self.tcx.hir())
+ }
+
+ fn pp_ann(&self) -> &dyn pprust_hir::PpAnn {
+ self
+ }
+}
+
+impl<'tcx> pprust_hir::PpAnn for TypedAnnotation<'tcx> {
+ fn nested(&self, state: &mut pprust_hir::State<'_>, nested: pprust_hir::Nested) {
+ let old_maybe_typeck_results = self.maybe_typeck_results.get();
+ if let pprust_hir::Nested::Body(id) = nested {
+ self.maybe_typeck_results.set(Some(self.tcx.typeck_body(id)));
+ }
+ let pp_ann = &(&self.tcx.hir() as &dyn hir::intravisit::Map<'_>);
+ pprust_hir::PpAnn::nested(pp_ann, state, nested);
+ self.maybe_typeck_results.set(old_maybe_typeck_results);
+ }
+ fn pre(&self, s: &mut pprust_hir::State<'_>, node: pprust_hir::AnnNode<'_>) {
+ if let pprust_hir::AnnNode::Expr(_) = node {
+ s.popen();
+ }
+ }
+ fn post(&self, s: &mut pprust_hir::State<'_>, node: pprust_hir::AnnNode<'_>) {
+ if let pprust_hir::AnnNode::Expr(expr) = node {
+ let typeck_results = self.maybe_typeck_results.get().or_else(|| {
+ self.tcx
+ .hir()
+ .maybe_body_owned_by(expr.hir_id.owner.def_id)
+ .map(|body_id| self.tcx.typeck_body(body_id))
+ });
+
+ if let Some(typeck_results) = typeck_results {
+ s.s.space();
+ s.s.word("as");
+ s.s.space();
+ s.s.word(typeck_results.expr_ty(expr).to_string());
+ }
+
+ s.pclose();
+ }
+ }
+}
+
+fn get_source(sess: &Session) -> (String, FileName) {
+ let src_name = sess.io.input.source_name();
+ let src = String::clone(
+ sess.source_map()
+ .get_source_file(&src_name)
+ .expect("get_source_file")
+ .src
+ .as_ref()
+ .expect("src"),
+ );
+ (src, src_name)
+}
+
+fn write_or_print(out: &str, sess: &Session) {
+ match &sess.io.output_file {
+ None => print!("{out}"),
+ Some(p) => {
+ if let Err(e) = std::fs::write(p, out) {
+ sess.emit_fatal(UnprettyDumpFail {
+ path: p.display().to_string(),
+ err: e.to_string(),
+ });
+ }
+ }
+ }
+}
+
+pub fn print_after_parsing(sess: &Session, krate: &ast::Crate, ppm: PpMode) {
+ let (src, src_name) = get_source(sess);
+
+ let out = match ppm {
+ Source(s) => {
+ // Silently ignores an identified node.
+ call_with_pp_support(&s, sess, None, move |annotation| {
+ debug!("pretty printing source code {:?}", s);
+ let sess = annotation.sess();
+ let parse = &sess.parse_sess;
+ pprust::print_crate(
+ sess.source_map(),
+ krate,
+ src_name,
+ src,
+ annotation.pp_ann(),
+ false,
+ parse.edition,
+ &sess.parse_sess.attr_id_generator,
+ )
+ })
+ }
+ AstTree(PpAstTreeMode::Normal) => {
+ debug!("pretty printing AST tree");
+ format!("{krate:#?}")
+ }
+ _ => unreachable!(),
+ };
+
+ write_or_print(&out, sess);
+}
+
+pub fn print_after_hir_lowering<'tcx>(tcx: TyCtxt<'tcx>, ppm: PpMode) {
+ if ppm.needs_analysis() {
+ abort_on_err(print_with_analysis(tcx, ppm), tcx.sess);
+ return;
+ }
+
+ let (src, src_name) = get_source(tcx.sess);
+
+ let out = match ppm {
+ Source(s) => {
+ // Silently ignores an identified node.
+ call_with_pp_support(&s, tcx.sess, Some(tcx), move |annotation| {
+ debug!("pretty printing source code {:?}", s);
+ let sess = annotation.sess();
+ let parse = &sess.parse_sess;
+ pprust::print_crate(
+ sess.source_map(),
+ &tcx.resolver_for_lowering(()).borrow().1,
+ src_name,
+ src,
+ annotation.pp_ann(),
+ true,
+ parse.edition,
+ &sess.parse_sess.attr_id_generator,
+ )
+ })
+ }
+
+ AstTree(PpAstTreeMode::Expanded) => {
+ debug!("pretty-printing expanded AST");
+ format!("{:#?}", tcx.resolver_for_lowering(()).borrow().1)
+ }
+
+ Hir(s) => call_with_pp_support_hir(&s, tcx, move |annotation, hir_map| {
+ debug!("pretty printing HIR {:?}", s);
+ let sess = annotation.sess();
+ let sm = sess.source_map();
+ let attrs = |id| hir_map.attrs(id);
+ pprust_hir::print_crate(
+ sm,
+ hir_map.root_module(),
+ src_name,
+ src,
+ &attrs,
+ annotation.pp_ann(),
+ )
+ }),
+
+ HirTree => {
+ call_with_pp_support_hir(&PpHirMode::Normal, tcx, move |_annotation, hir_map| {
+ debug!("pretty printing HIR tree");
+ format!("{:#?}", hir_map.krate())
+ })
+ }
+
+ _ => unreachable!(),
+ };
+
+ write_or_print(&out, tcx.sess);
+}
+
+// In an ideal world, this would be a public function called by the driver after
+// analysis is performed. However, we want to call `phase_3_run_analysis_passes`
+// with a different callback than the standard driver, so that isn't easy.
+// Instead, we call that function ourselves.
+fn print_with_analysis(tcx: TyCtxt<'_>, ppm: PpMode) -> Result<(), ErrorGuaranteed> {
+ tcx.analysis(())?;
+ let out = match ppm {
+ Mir => {
+ let mut out = Vec::new();
+ write_mir_pretty(tcx, None, &mut out).unwrap();
+ String::from_utf8(out).unwrap()
+ }
+
+ MirCFG => {
+ let mut out = Vec::new();
+ write_mir_graphviz(tcx, None, &mut out).unwrap();
+ String::from_utf8(out).unwrap()
+ }
+
+ ThirTree => {
+ let mut out = String::new();
+ abort_on_err(rustc_hir_analysis::check_crate(tcx), tcx.sess);
+ debug!("pretty printing THIR tree");
+ for did in tcx.hir().body_owners() {
+ let _ = writeln!(
+ out,
+ "{:?}:\n{}\n",
+ did,
+ tcx.thir_tree(ty::WithOptConstParam::unknown(did))
+ );
+ }
+ out
+ }
+
+ ThirFlat => {
+ let mut out = String::new();
+ abort_on_err(rustc_hir_analysis::check_crate(tcx), tcx.sess);
+ debug!("pretty printing THIR flat");
+ for did in tcx.hir().body_owners() {
+ let _ = writeln!(
+ out,
+ "{:?}:\n{}\n",
+ did,
+ tcx.thir_flat(ty::WithOptConstParam::unknown(did))
+ );
+ }
+ out
+ }
+
+ _ => unreachable!(),
+ };
+
+ write_or_print(&out, tcx.sess);
+
+ Ok(())
+}
--- /dev/null
+use rustc_macros::Diagnostic;
+
+#[derive(Diagnostic)]
+#[diag(driver_impl_rlink_unable_to_read)]
+pub(crate) struct RlinkUnableToRead {
+ pub err: std::io::Error,
+}
+
+#[derive(Diagnostic)]
+#[diag(driver_impl_rlink_wrong_file_type)]
+pub(crate) struct RLinkWrongFileType;
+
+#[derive(Diagnostic)]
+#[diag(driver_impl_rlink_empty_version_number)]
+pub(crate) struct RLinkEmptyVersionNumber;
+
+#[derive(Diagnostic)]
+#[diag(driver_impl_rlink_encoding_version_mismatch)]
+pub(crate) struct RLinkEncodingVersionMismatch {
+ pub version_array: String,
+ pub rlink_version: u32,
+}
+
+#[derive(Diagnostic)]
+#[diag(driver_impl_rlink_rustc_version_mismatch)]
+pub(crate) struct RLinkRustcVersionMismatch<'a> {
+ pub rustc_version: String,
+ pub current_version: &'a str,
+}
+
+#[derive(Diagnostic)]
+#[diag(driver_impl_rlink_no_a_file)]
+pub(crate) struct RlinkNotAFile;
+
+#[derive(Diagnostic)]
+#[diag(driver_impl_unpretty_dump_fail)]
+pub(crate) struct UnprettyDumpFail {
+ pub path: String,
+ pub err: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(driver_impl_ice)]
+pub(crate) struct Ice;
+
+#[derive(Diagnostic)]
+#[diag(driver_impl_ice_bug_report)]
+pub(crate) struct IceBugReport<'a> {
+ pub bug_report_url: &'a str,
+}
+
+#[derive(Diagnostic)]
+#[diag(driver_impl_ice_version)]
+pub(crate) struct IceVersion<'a> {
+ pub version: &'a str,
+ pub triple: &'a str,
+}
+
+#[derive(Diagnostic)]
+#[diag(driver_impl_ice_flags)]
+pub(crate) struct IceFlags {
+ pub flags: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(driver_impl_ice_exclude_cargo_defaults)]
+pub(crate) struct IceExcludeCargoDefaults;
-driver_rlink_unable_to_read = failed to read rlink file: `{$err}`
+driver_impl_rlink_unable_to_read = failed to read rlink file: `{$err}`
-driver_rlink_wrong_file_type = The input does not look like a .rlink file
+driver_impl_rlink_wrong_file_type = The input does not look like a .rlink file
-driver_rlink_empty_version_number = The input does not contain version number
+driver_impl_rlink_empty_version_number = The input does not contain version number
-driver_rlink_encoding_version_mismatch = .rlink file was produced with encoding version `{$version_array}`, but the current version is `{$rlink_version}`
+driver_impl_rlink_encoding_version_mismatch = .rlink file was produced with encoding version `{$version_array}`, but the current version is `{$rlink_version}`
-driver_rlink_rustc_version_mismatch = .rlink file was produced by rustc version `{$rustc_version}`, but the current version is `{$current_version}`
+driver_impl_rlink_rustc_version_mismatch = .rlink file was produced by rustc version `{$rustc_version}`, but the current version is `{$current_version}`
-driver_rlink_no_a_file = rlink must be a file
+driver_impl_rlink_no_a_file = rlink must be a file
-driver_unpretty_dump_fail = pretty-print failed to write `{$path}` due to error `{$err}`
+driver_impl_unpretty_dump_fail = pretty-print failed to write `{$path}` due to error `{$err}`
-driver_ice = the compiler unexpectedly panicked. this is a bug.
-driver_ice_bug_report = we would appreciate a bug report: {$bug_report_url}
-driver_ice_version = rustc {$version} running on {$triple}
-driver_ice_flags = compiler flags: {$flags}
-driver_ice_exclude_cargo_defaults = some of the compiler flags provided by cargo are hidden
+driver_impl_ice = the compiler unexpectedly panicked. this is a bug.
+driver_impl_ice_bug_report = we would appreciate a bug report: {$bug_report_url}
+driver_impl_ice_version = rustc {$version} running on {$triple}
+driver_impl_ice_flags = compiler flags: {$flags}
+driver_impl_ice_exclude_cargo_defaults = some of the compiler flags provided by cargo are hidden
.use_in_not_of = try using `in` here instead
.add_in = try adding `in` here
+parse_missing_expression_in_for_loop = missing expression to iterate on in `for` loop
+ .suggestion = try adding an expression to the `for` loop
+
parse_missing_comma_after_match_arm = expected `,` following `match` arm
.suggestion = missing a comma here to end this `match` arm
parse_unexpected_self_in_generic_parameters = unexpected keyword `Self` in generic parameters
.note = you cannot use `Self` as a generic parameter because it is reserved for associated items
+parse_unexpected_default_value_for_lifetime_in_generic_parameters = unexpected default lifetime parameter
+ .label = lifetime parameters cannot have default values
+
parse_multiple_where_clauses = cannot define duplicate `where` clauses on an item
.label = previous `where` clause starts here
.suggestion = consider joining the two `where` clauses into one
#![deny(rustc::untranslatable_diagnostic)]
-use crate::errors::{
- ArgumentNotAttributes, AttrNoArguments, AttributeMetaItem, AttributeSingleWord,
- AttributesWrongForm, CannotBeNameOfMacro, ExpectedCommaInList, HelperAttributeNameInvalid,
- MacroBodyStability, MacroConstStability, NotAMetaItem, OnlyOneArgument, OnlyOneWord,
- ResolveRelativePath, TakesNoArguments, TraceMacro,
-};
+use crate::errors;
use crate::expand::{self, AstFragment, Invocation};
use crate::module::DirOwnership;
.unwrap_or_else(|| (None, helper_attrs));
let (stability, const_stability, body_stability) = attr::find_stability(&sess, attrs, span);
if let Some((_, sp)) = const_stability {
- sess.emit_err(MacroConstStability {
+ sess.emit_err(errors::MacroConstStability {
span: sp,
head_span: sess.source_map().guess_head_span(span),
});
}
if let Some((_, sp)) = body_stability {
- sess.emit_err(MacroBodyStability {
+ sess.emit_err(errors::MacroBodyStability {
span: sp,
head_span: sess.source_map().guess_head_span(span),
});
}
pub fn trace_macros_diag(&mut self) {
for (span, notes) in self.expansions.iter() {
- let mut db = self.sess.parse_sess.create_note(TraceMacro { span: *span });
+ let mut db = self.sess.parse_sess.create_note(errors::TraceMacro { span: *span });
for note in notes {
db.note(note);
}
.expect("attempting to resolve a file path in an external file"),
FileName::DocTest(path, _) => path,
other => {
- return Err(ResolveRelativePath {
+ return Err(errors::ResolveRelativePath {
span,
path: parse_sess.source_map().filename_for_diagnostics(&other).to_string(),
}
/// done as rarely as possible).
pub fn check_zero_tts(cx: &ExtCtxt<'_>, span: Span, tts: TokenStream, name: &str) {
if !tts.is_empty() {
- cx.emit_err(TakesNoArguments { span, name });
+ cx.emit_err(errors::TakesNoArguments { span, name });
}
}
) -> Option<Symbol> {
let mut p = cx.new_parser_from_tts(tts);
if p.token == token::Eof {
- cx.emit_err(OnlyOneArgument { span, name });
+ cx.emit_err(errors::OnlyOneArgument { span, name });
return None;
}
let ret = parse_expr(&mut p)?;
let _ = p.eat(&token::Comma);
if p.token != token::Eof {
- cx.emit_err(OnlyOneArgument { span, name });
+ cx.emit_err(errors::OnlyOneArgument { span, name });
}
expr_to_string(cx, ret, "argument must be a string literal").map(|(s, _)| s)
}
continue;
}
if p.token != token::Eof {
- cx.emit_err(ExpectedCommaInList { span: p.token.span });
+ cx.emit_err(errors::ExpectedCommaInList { span: p.token.span });
return None;
}
}
// `#[proc_macro_derive(Foo, attributes(A, ..))]`
let list = attr.meta_item_list()?;
if list.len() != 1 && list.len() != 2 {
- diag.emit_err(AttrNoArguments { span: attr.span });
+ diag.emit_err(errors::AttrNoArguments { span: attr.span });
return None;
}
let Some(trait_attr) = list[0].meta_item() else {
- diag.emit_err(NotAMetaItem {span: list[0].span()});
+ diag.emit_err(errors::NotAMetaItem {span: list[0].span()});
return None;
};
let trait_ident = match trait_attr.ident() {
Some(trait_ident) if trait_attr.is_word() => trait_ident,
_ => {
- diag.emit_err(OnlyOneWord { span: trait_attr.span });
+ diag.emit_err(errors::OnlyOneWord { span: trait_attr.span });
return None;
}
};
if !trait_ident.name.can_be_raw() {
- diag.emit_err(CannotBeNameOfMacro { span: trait_attr.span, trait_ident, macro_type });
+ diag.emit_err(errors::CannotBeNameOfMacro {
+ span: trait_attr.span,
+ trait_ident,
+ macro_type,
+ });
}
let attributes_attr = list.get(1);
let proc_attrs: Vec<_> = if let Some(attr) = attributes_attr {
if !attr.has_name(sym::attributes) {
- diag.emit_err(ArgumentNotAttributes { span: attr.span() });
+ diag.emit_err(errors::ArgumentNotAttributes { span: attr.span() });
}
attr.meta_item_list()
.unwrap_or_else(|| {
- diag.emit_err(AttributesWrongForm { span: attr.span() });
+ diag.emit_err(errors::AttributesWrongForm { span: attr.span() });
&[]
})
.iter()
.filter_map(|attr| {
let Some(attr) = attr.meta_item() else {
- diag.emit_err(AttributeMetaItem { span: attr.span() });
+ diag.emit_err(errors::AttributeMetaItem { span: attr.span() });
return None;
};
let ident = match attr.ident() {
Some(ident) if attr.is_word() => ident,
_ => {
- diag.emit_err(AttributeSingleWord { span: attr.span });
+ diag.emit_err(errors::AttributeSingleWord { span: attr.span });
return None;
}
};
if !ident.name.can_be_raw() {
- diag.emit_err(HelperAttributeNameInvalid { span: attr.span, name: ident });
+ diag.emit_err(errors::HelperAttributeNameInvalid {
+ span: attr.span,
+ name: ident,
+ });
}
Some(ident.name)
|| self.suggest_clone_for_ref(err, expr, expr_ty, expected)
|| self.suggest_into(err, expr, expr_ty, expected)
|| self.suggest_floating_point_literal(err, expr, expected)
+ || self.suggest_null_ptr_for_literal_zero_given_to_ptr_arg(err, expr, expected)
|| self.note_result_coercion(err, expr, expected, expr_ty);
if !suggested {
self.point_at_expr_source_of_inferred_type(err, expr, expr_ty, expected, expr.span);
use rustc_hir_analysis::astconv::AstConv;
use rustc_infer::traits::{self, StatementAsExpression};
use rustc_middle::lint::in_external_macro;
+use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_middle::ty::{
self, suggest_constraining_type_params, Binder, DefIdTree, IsSuggestable, ToPredicate, Ty,
TypeVisitable,
}
}
+ /// Suggest providing `std::ptr::null()` or `std::ptr::null_mut()` if they
+ /// pass in a literal 0 to an raw pointer.
+ #[instrument(skip(self, err))]
+ pub(crate) fn suggest_null_ptr_for_literal_zero_given_to_ptr_arg(
+ &self,
+ err: &mut Diagnostic,
+ expr: &hir::Expr<'_>,
+ expected_ty: Ty<'tcx>,
+ ) -> bool {
+ // Expected type needs to be a raw pointer.
+ let ty::RawPtr(ty::TypeAndMut { mutbl, .. }) = expected_ty.kind() else {
+ return false;
+ };
+
+ // Provided expression needs to be a literal `0`.
+ let ExprKind::Lit(Spanned {
+ node: rustc_ast::LitKind::Int(0, _),
+ span,
+ }) = expr.kind else {
+ return false;
+ };
+
+ // We need to find a null pointer symbol to suggest
+ let null_sym = match mutbl {
+ hir::Mutability::Not => sym::ptr_null,
+ hir::Mutability::Mut => sym::ptr_null_mut,
+ };
+ let Some(null_did) = self.tcx.get_diagnostic_item(null_sym) else {
+ return false;
+ };
+ let null_path_str = with_no_trimmed_paths!(self.tcx.def_path_str(null_did));
+
+ // We have satisfied all requirements to provide a suggestion. Emit it.
+ err.span_suggestion(
+ span,
+ format!("if you meant to create a null pointer, use `{null_path_str}()`"),
+ null_path_str + "()",
+ Applicability::MachineApplicable,
+ );
+
+ true
+ }
+
pub(crate) fn suggest_associated_const(
&self,
err: &mut Diagnostic,
}
}
+ #[inline]
fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
if !t.needs_infer() && !t.has_erasable_regions() {
- return t;
- }
-
- let tcx = self.infcx.tcx;
-
- match *t.kind() {
- ty::Infer(ty::TyVar(v)) => {
- let opt_ty = self.infcx.inner.borrow_mut().type_variables().probe(v).known();
- self.freshen_ty(opt_ty, ty::TyVar(v), ty::FreshTy)
- }
+ t
+ } else {
+ match *t.kind() {
+ ty::Infer(v) => self.fold_infer_ty(v).unwrap_or(t),
- ty::Infer(ty::IntVar(v)) => self.freshen_ty(
- self.infcx
- .inner
- .borrow_mut()
- .int_unification_table()
- .probe_value(v)
- .map(|v| v.to_type(tcx)),
- ty::IntVar(v),
- ty::FreshIntTy,
- ),
+ // This code is hot enough that a non-debug assertion here makes a noticeable
+ // difference on benchmarks like `wg-grammar`.
+ #[cfg(debug_assertions)]
+ ty::Placeholder(..) | ty::Bound(..) => bug!("unexpected type {:?}", t),
- ty::Infer(ty::FloatVar(v)) => self.freshen_ty(
- self.infcx
- .inner
- .borrow_mut()
- .float_unification_table()
- .probe_value(v)
- .map(|v| v.to_type(tcx)),
- ty::FloatVar(v),
- ty::FreshFloatTy,
- ),
-
- ty::Infer(ty::FreshTy(ct) | ty::FreshIntTy(ct) | ty::FreshFloatTy(ct)) => {
- if ct >= self.ty_freshen_count {
- bug!(
- "Encountered a freshend type with id {} \
- but our counter is only at {}",
- ct,
- self.ty_freshen_count
- );
- }
- t
+ _ => t.super_fold_with(self),
}
-
- ty::Generator(..)
- | ty::Bool
- | ty::Char
- | ty::Int(..)
- | ty::Uint(..)
- | ty::Float(..)
- | ty::Adt(..)
- | ty::Str
- | ty::Error(_)
- | ty::Array(..)
- | ty::Slice(..)
- | ty::RawPtr(..)
- | ty::Ref(..)
- | ty::FnDef(..)
- | ty::FnPtr(_)
- | ty::Dynamic(..)
- | ty::Never
- | ty::Tuple(..)
- | ty::Alias(..)
- | ty::Foreign(..)
- | ty::Param(..)
- | ty::Closure(..)
- | ty::GeneratorWitnessMIR(..)
- | ty::GeneratorWitness(..) => t.super_fold_with(self),
-
- ty::Placeholder(..) | ty::Bound(..) => bug!("unexpected type {:?}", t),
}
}
}
}
}
+
+impl<'a, 'tcx> TypeFreshener<'a, 'tcx> {
+ // This is separate from `fold_ty` to keep that method small and inlinable.
+ #[inline(never)]
+ fn fold_infer_ty(&mut self, v: ty::InferTy) -> Option<Ty<'tcx>> {
+ match v {
+ ty::TyVar(v) => {
+ let opt_ty = self.infcx.inner.borrow_mut().type_variables().probe(v).known();
+ Some(self.freshen_ty(opt_ty, ty::TyVar(v), ty::FreshTy))
+ }
+
+ ty::IntVar(v) => Some(
+ self.freshen_ty(
+ self.infcx
+ .inner
+ .borrow_mut()
+ .int_unification_table()
+ .probe_value(v)
+ .map(|v| v.to_type(self.infcx.tcx)),
+ ty::IntVar(v),
+ ty::FreshIntTy,
+ ),
+ ),
+
+ ty::FloatVar(v) => Some(
+ self.freshen_ty(
+ self.infcx
+ .inner
+ .borrow_mut()
+ .float_unification_table()
+ .probe_value(v)
+ .map(|v| v.to_type(self.infcx.tcx)),
+ ty::FloatVar(v),
+ ty::FreshFloatTy,
+ ),
+ ),
+
+ ty::FreshTy(ct) | ty::FreshIntTy(ct) | ty::FreshFloatTy(ct) => {
+ if ct >= self.ty_freshen_count {
+ bug!(
+ "Encountered a freshend type with id {} \
+ but our counter is only at {}",
+ ct,
+ self.ty_freshen_count
+ );
+ }
+ None
+ }
+ }
+ }
+}
use rustc_middle::ty::subst::{GenericArg, GenericArgKind, InternalSubsts, SubstsRef};
use rustc_middle::ty::visit::TypeVisitable;
pub use rustc_middle::ty::IntVarValue;
-use rustc_middle::ty::{self, GenericParamDefKind, InferConst, Ty, TyCtxt};
+use rustc_middle::ty::{self, GenericParamDefKind, InferConst, InferTy, Ty, TyCtxt};
use rustc_middle::ty::{ConstVid, FloatVid, IntVid, TyVid};
use rustc_span::symbol::Symbol;
use rustc_span::Span;
where
T: TypeFoldable<'tcx>,
{
- if !value.needs_infer() {
- return value; // Avoid duplicated subst-folding.
+ if !value.has_non_region_infer() {
+ return value;
}
let mut r = resolve::OpportunisticVarResolver::new(self);
value.fold_with(&mut r)
/// If `ty` is a type variable of some kind, resolve it one level
/// (but do not resolve types found in the result). If `typ` is
/// not a type variable, just return it unmodified.
+ #[inline]
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
- match *ty.kind() {
- ty::Infer(ty::TyVar(v)) => {
+ if let ty::Infer(v) = ty.kind() { self.fold_infer_ty(*v).unwrap_or(ty) } else { ty }
+ }
+
+ fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
+ if let ty::ConstKind::Infer(InferConst::Var(vid)) = ct.kind() {
+ self.infcx
+ .inner
+ .borrow_mut()
+ .const_unification_table()
+ .probe_value(vid)
+ .val
+ .known()
+ .unwrap_or(ct)
+ } else {
+ ct
+ }
+ }
+}
+
+impl<'a, 'tcx> ShallowResolver<'a, 'tcx> {
+ // This is separate from `fold_ty` to keep that method small and inlinable.
+ #[inline(never)]
+ fn fold_infer_ty(&mut self, v: InferTy) -> Option<Ty<'tcx>> {
+ match v {
+ ty::TyVar(v) => {
// Not entirely obvious: if `typ` is a type variable,
// it can be resolved to an int/float variable, which
// can then be recursively resolved, hence the
// Note: if these two lines are combined into one we get
// dynamic borrow errors on `self.inner`.
let known = self.infcx.inner.borrow_mut().type_variables().probe(v).known();
- known.map_or(ty, |t| self.fold_ty(t))
+ known.map(|t| self.fold_ty(t))
}
- ty::Infer(ty::IntVar(v)) => self
+ ty::IntVar(v) => self
.infcx
.inner
.borrow_mut()
.int_unification_table()
.probe_value(v)
- .map_or(ty, |v| v.to_type(self.infcx.tcx)),
+ .map(|v| v.to_type(self.infcx.tcx)),
- ty::Infer(ty::FloatVar(v)) => self
+ ty::FloatVar(v) => self
.infcx
.inner
.borrow_mut()
.float_unification_table()
.probe_value(v)
- .map_or(ty, |v| v.to_type(self.infcx.tcx)),
+ .map(|v| v.to_type(self.infcx.tcx)),
- _ => ty,
- }
- }
-
- fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
- if let ty::ConstKind::Infer(InferConst::Var(vid)) = ct.kind() {
- self.infcx
- .inner
- .borrow_mut()
- .const_unification_table()
- .probe_value(vid)
- .val
- .known()
- .unwrap_or(ct)
- } else {
- ct
+ ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_) => None,
}
}
}
where
D: TypeRelatingDelegate<'tcx>,
{
- fn const_equate_obligation(&mut self, _a: ty::Const<'tcx>, _b: ty::Const<'tcx>) {
- // We don't have to worry about the equality of consts during borrow checking
- // as consts always have a static lifetime.
- // FIXME(oli-obk): is this really true? We can at least have HKL and with
- // inline consts we may have further lifetimes that may be unsound to treat as
- // 'static.
+ fn const_equate_obligation(&mut self, a: ty::Const<'tcx>, b: ty::Const<'tcx>) {
+ self.delegate.register_obligations(vec![Obligation::new(
+ self.tcx(),
+ ObligationCause::dummy(),
+ self.param_env(),
+ ty::Binder::dummy(ty::PredicateKind::ConstEquate(a, b)),
+ )]);
}
}
/// useful for printing messages etc but also required at various
/// points for correctness.
pub struct OpportunisticVarResolver<'a, 'tcx> {
- infcx: &'a InferCtxt<'tcx>,
+ // The shallow resolver is used to resolve inference variables at every
+ // level of the type.
+ shallow_resolver: crate::infer::ShallowResolver<'a, 'tcx>,
}
impl<'a, 'tcx> OpportunisticVarResolver<'a, 'tcx> {
#[inline]
pub fn new(infcx: &'a InferCtxt<'tcx>) -> Self {
- OpportunisticVarResolver { infcx }
+ OpportunisticVarResolver { shallow_resolver: crate::infer::ShallowResolver { infcx } }
}
}
impl<'a, 'tcx> TypeFolder<'tcx> for OpportunisticVarResolver<'a, 'tcx> {
fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
- self.infcx.tcx
+ TypeFolder::tcx(&self.shallow_resolver)
}
+ #[inline]
fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
if !t.has_non_region_infer() {
t // micro-optimize -- if there is nothing in this type that this fold affects...
} else {
- let t = self.infcx.shallow_resolve(t);
+ let t = self.shallow_resolver.fold_ty(t);
t.super_fold_with(self)
}
}
if !ct.has_non_region_infer() {
ct // micro-optimize -- if there is nothing in this const that this fold affects...
} else {
- let ct = self.infcx.shallow_resolve(ct);
+ let ct = self.shallow_resolver.fold_const(ct);
ct.super_fold_with(self)
}
}
-use crate::errors::{
- CantEmitMIR, EmojiIdentifier, ErrorWritingDependencies, FerrisIdentifier,
- GeneratedFileConflictsWithDirectory, InputFileWouldBeOverWritten, MixedBinCrate,
- MixedProcMacroCrate, OutDirError, ProcMacroCratePanicAbort, ProcMacroDocWithoutArg,
- TempsDirError,
-};
+use crate::errors;
use crate::interface::{Compiler, Result};
use crate::proc_macro_decls;
use crate::util;
if crate_types.len() > 1 {
if is_executable_crate {
- sess.emit_err(MixedBinCrate);
+ sess.emit_err(errors::MixedBinCrate);
}
if is_proc_macro_crate {
- sess.emit_err(MixedProcMacroCrate);
+ sess.emit_err(errors::MixedProcMacroCrate);
}
}
if is_proc_macro_crate && sess.panic_strategy() == PanicStrategy::Abort {
- sess.emit_warning(ProcMacroCratePanicAbort);
+ sess.emit_warning(errors::ProcMacroCratePanicAbort);
}
// For backwards compatibility, we don't try to run proc macro injection
// However, we do emit a warning, to let such users know that they should
// start passing '--crate-type proc-macro'
if has_proc_macro_decls && sess.opts.actually_rustdoc && !is_proc_macro_crate {
- sess.emit_warning(ProcMacroDocWithoutArg);
+ sess.emit_warning(errors::ProcMacroDocWithoutArg);
} else {
krate = sess.time("maybe_create_a_macro_crate", || {
let is_test_crate = sess.opts.test;
spans.sort();
if ident == sym::ferris {
let first_span = spans[0];
- sess.emit_err(FerrisIdentifier { spans, first_span });
+ sess.emit_err(errors::FerrisIdentifier { spans, first_span });
} else {
- sess.emit_err(EmojiIdentifier { spans, ident });
+ sess.emit_err(errors::EmojiIdentifier { spans, ident });
}
}
});
}
}
Err(error) => {
- sess.emit_fatal(ErrorWritingDependencies { path: &deps_filename, error });
+ sess.emit_fatal(errors::ErrorWritingDependencies { path: &deps_filename, error });
}
}
}
if let Some(ref input_path) = sess.io.input.opt_path() {
if sess.opts.will_create_output_file() {
if output_contains_path(&output_paths, input_path) {
- sess.emit_fatal(InputFileWouldBeOverWritten { path: input_path });
+ sess.emit_fatal(errors::InputFileWouldBeOverWritten { path: input_path });
}
if let Some(ref dir_path) = output_conflicts_with_dir(&output_paths) {
- sess.emit_fatal(GeneratedFileConflictsWithDirectory { input_path, dir_path });
+ sess.emit_fatal(errors::GeneratedFileConflictsWithDirectory {
+ input_path,
+ dir_path,
+ });
}
}
}
if let Some(ref dir) = sess.io.temps_dir {
if fs::create_dir_all(dir).is_err() {
- sess.emit_fatal(TempsDirError);
+ sess.emit_fatal(errors::TempsDirError);
}
}
if !only_dep_info {
if let Some(ref dir) = sess.io.output_dir {
if fs::create_dir_all(dir).is_err() {
- sess.emit_fatal(OutDirError);
+ sess.emit_fatal(errors::OutDirError);
}
}
}
if tcx.sess.opts.output_types.contains_key(&OutputType::Mir) {
if let Err(error) = rustc_mir_transform::dump_mir::emit_mir(tcx) {
- tcx.sess.emit_err(CantEmitMIR { error });
+ tcx.sess.emit_err(errors::CantEmitMIR { error });
tcx.sess.abort_if_errors();
}
}
keep_space: (bool, bool),
) {
let primary_span = if let Some((lo, hi)) = spans {
+ if hi.is_empty() {
+ // do not point at delims that do not exist
+ return;
+ }
MultiSpan::from(vec![lo, hi])
} else {
MultiSpan::from(value_span)
//! Validates all used crates and extern libraries and loads their metadata
-use crate::errors::{
- ConflictingAllocErrorHandler, ConflictingGlobalAlloc, CrateNotPanicRuntime,
- GlobalAllocRequired, NoMultipleAllocErrorHandler, NoMultipleGlobalAlloc, NoPanicStrategy,
- NoTransitiveNeedsDep, NotProfilerRuntime, ProfilerBuiltinsNeedsCore,
-};
+use crate::errors;
use crate::locator::{CrateError, CrateLocator, CratePaths};
use crate::rmeta::{CrateDep, CrateMetadata, CrateNumMap, CrateRoot, MetadataBlob};
// Sanity check the loaded crate to ensure it is indeed a panic runtime
// and the panic strategy is indeed what we thought it was.
if !data.is_panic_runtime() {
- self.sess.emit_err(CrateNotPanicRuntime { crate_name: name });
+ self.sess.emit_err(errors::CrateNotPanicRuntime { crate_name: name });
}
if data.required_panic_strategy() != Some(desired_strategy) {
- self.sess.emit_err(NoPanicStrategy { crate_name: name, strategy: desired_strategy });
+ self.sess
+ .emit_err(errors::NoPanicStrategy { crate_name: name, strategy: desired_strategy });
}
self.cstore.injected_panic_runtime = Some(cnum);
let name = Symbol::intern(&self.sess.opts.unstable_opts.profiler_runtime);
if name == sym::profiler_builtins && self.sess.contains_name(&krate.attrs, sym::no_core) {
- self.sess.emit_err(ProfilerBuiltinsNeedsCore);
+ self.sess.emit_err(errors::ProfilerBuiltinsNeedsCore);
}
let Some(cnum) = self.resolve_crate(name, DUMMY_SP, CrateDepKind::Implicit) else { return; };
// Sanity check the loaded crate to ensure it is indeed a profiler runtime
if !data.is_profiler_runtime() {
- self.sess.emit_err(NotProfilerRuntime { crate_name: name });
+ self.sess.emit_err(errors::NotProfilerRuntime { crate_name: name });
}
}
fn inject_allocator_crate(&mut self, krate: &ast::Crate) {
self.cstore.has_global_allocator = match &*global_allocator_spans(&self.sess, krate) {
[span1, span2, ..] => {
- self.sess.emit_err(NoMultipleGlobalAlloc { span2: *span2, span1: *span1 });
+ self.sess.emit_err(errors::NoMultipleGlobalAlloc { span2: *span2, span1: *span1 });
true
}
spans => !spans.is_empty(),
};
self.cstore.has_alloc_error_handler = match &*alloc_error_handler_spans(&self.sess, krate) {
[span1, span2, ..] => {
- self.sess.emit_err(NoMultipleAllocErrorHandler { span2: *span2, span1: *span1 });
+ self.sess
+ .emit_err(errors::NoMultipleAllocErrorHandler { span2: *span2, span1: *span1 });
true
}
spans => !spans.is_empty(),
if data.has_global_allocator() {
match global_allocator {
Some(other_crate) => {
- self.sess.emit_err(ConflictingGlobalAlloc {
+ self.sess.emit_err(errors::ConflictingGlobalAlloc {
crate_name: data.name(),
other_crate_name: other_crate,
});
if data.has_alloc_error_handler() {
match alloc_error_handler {
Some(other_crate) => {
- self.sess.emit_err(ConflictingAllocErrorHandler {
+ self.sess.emit_err(errors::ConflictingAllocErrorHandler {
crate_name: data.name(),
other_crate_name: other_crate,
});
if !self.sess.contains_name(&krate.attrs, sym::default_lib_allocator)
&& !self.cstore.iter_crate_data().any(|(_, data)| data.has_default_lib_allocator())
{
- self.sess.emit_err(GlobalAllocRequired);
+ self.sess.emit_err(errors::GlobalAllocRequired);
}
self.cstore.allocator_kind = Some(AllocatorKind::Default);
}
for dep in self.cstore.crate_dependencies_in_reverse_postorder(krate) {
let data = self.cstore.get_crate_data(dep);
if needs_dep(&data) {
- self.sess.emit_err(NoTransitiveNeedsDep {
+ self.sess.emit_err(errors::NoTransitiveNeedsDep {
crate_name: self.cstore.get_crate_data(krate).name(),
needs_crate_name: what,
deps_crate_name: data.name(),
//! metadata::locator or metadata::creader for all the juicy details!
use crate::creader::Library;
-use crate::errors::{
- CannotFindCrate, CrateLocationUnknownType, DlError, ExternLocationNotExist,
- ExternLocationNotFile, FoundStaticlib, IncompatibleRustc, InvalidMetadataFiles,
- LibFilenameForm, MultipleCandidates, NewerCrateVersion, NoCrateWithTriple, NoDylibPlugin,
- NonAsciiName, StableCrateIdCollision, SymbolConflictsCurrent, SymbolConflictsOthers,
-};
+use crate::errors;
use crate::rmeta::{rustc_version, MetadataBlob, METADATA_HEADER};
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
pub(crate) fn report(self, sess: &Session, span: Span, missing_core: bool) {
match self {
CrateError::NonAsciiName(crate_name) => {
- sess.emit_err(NonAsciiName { span, crate_name });
+ sess.emit_err(errors::NonAsciiName { span, crate_name });
}
CrateError::ExternLocationNotExist(crate_name, loc) => {
- sess.emit_err(ExternLocationNotExist { span, crate_name, location: &loc });
+ sess.emit_err(errors::ExternLocationNotExist { span, crate_name, location: &loc });
}
CrateError::ExternLocationNotFile(crate_name, loc) => {
- sess.emit_err(ExternLocationNotFile { span, crate_name, location: &loc });
+ sess.emit_err(errors::ExternLocationNotFile { span, crate_name, location: &loc });
}
CrateError::MultipleCandidates(crate_name, flavor, candidates) => {
- sess.emit_err(MultipleCandidates { span, crate_name, flavor, candidates });
+ sess.emit_err(errors::MultipleCandidates { span, crate_name, flavor, candidates });
}
CrateError::SymbolConflictsCurrent(root_name) => {
- sess.emit_err(SymbolConflictsCurrent { span, crate_name: root_name });
+ sess.emit_err(errors::SymbolConflictsCurrent { span, crate_name: root_name });
}
CrateError::SymbolConflictsOthers(root_name) => {
- sess.emit_err(SymbolConflictsOthers { span, crate_name: root_name });
+ sess.emit_err(errors::SymbolConflictsOthers { span, crate_name: root_name });
}
CrateError::StableCrateIdCollision(crate_name0, crate_name1) => {
- sess.emit_err(StableCrateIdCollision { span, crate_name0, crate_name1 });
+ sess.emit_err(errors::StableCrateIdCollision { span, crate_name0, crate_name1 });
}
CrateError::DlOpen(s) | CrateError::DlSym(s) => {
- sess.emit_err(DlError { span, err: s });
+ sess.emit_err(errors::DlError { span, err: s });
}
CrateError::LocatorCombined(locator) => {
let crate_name = locator.crate_name;
if !locator.crate_rejections.via_filename.is_empty() {
let mismatches = locator.crate_rejections.via_filename.iter();
for CrateMismatch { path, .. } in mismatches {
- sess.emit_err(CrateLocationUnknownType { span, path: &path, crate_name });
- sess.emit_err(LibFilenameForm {
+ sess.emit_err(errors::CrateLocationUnknownType {
+ span,
+ path: &path,
+ crate_name,
+ });
+ sess.emit_err(errors::LibFilenameForm {
span,
dll_prefix: &locator.dll_prefix,
dll_suffix: &locator.dll_suffix,
));
}
}
- sess.emit_err(NewerCrateVersion {
+ sess.emit_err(errors::NewerCrateVersion {
span,
crate_name: crate_name,
add_info,
path.display(),
));
}
- sess.emit_err(NoCrateWithTriple {
+ sess.emit_err(errors::NoCrateWithTriple {
span,
crate_name,
locator_triple: locator.triple.triple(),
path.display()
));
}
- sess.emit_err(FoundStaticlib { span, crate_name, add_info, found_crates });
+ sess.emit_err(errors::FoundStaticlib {
+ span,
+ crate_name,
+ add_info,
+ found_crates,
+ });
} else if !locator.crate_rejections.via_version.is_empty() {
let mismatches = locator.crate_rejections.via_version.iter();
for CrateMismatch { path, got } in mismatches {
path.display(),
));
}
- sess.emit_err(IncompatibleRustc {
+ sess.emit_err(errors::IncompatibleRustc {
span,
crate_name,
add_info,
for CrateMismatch { path: _, got } in locator.crate_rejections.via_invalid {
crate_rejections.push(got);
}
- sess.emit_err(InvalidMetadataFiles {
+ sess.emit_err(errors::InvalidMetadataFiles {
span,
crate_name,
add_info,
crate_rejections,
});
} else {
- sess.emit_err(CannotFindCrate {
+ sess.emit_err(errors::CannotFindCrate {
span,
crate_name,
add_info,
}
}
CrateError::NonDylibPlugin(crate_name) => {
- sess.emit_err(NoDylibPlugin { span, crate_name });
+ sess.emit_err(errors::NoDylibPlugin { span, crate_name });
}
}
}
use rustc_span::symbol::{sym, Symbol};
use rustc_target::spec::abi::Abi;
-use crate::errors::{
- AsNeededCompatibility, BundleNeedsStatic, EmptyLinkName, EmptyRenamingTarget,
- FrameworkOnlyWindows, ImportNameTypeForm, ImportNameTypeRaw, ImportNameTypeX86,
- IncompatibleWasmLink, InvalidLinkModifier, LibFrameworkApple, LinkCfgForm,
- LinkCfgSinglePredicate, LinkFrameworkApple, LinkKindForm, LinkModifiersForm, LinkNameForm,
- LinkOrdinalRawDylib, LinkRequiresName, MissingNativeLibrary, MultipleCfgs,
- MultipleImportNameType, MultipleKindsInLink, MultipleLinkModifiers, MultipleModifiers,
- MultipleNamesInLink, MultipleRenamings, MultipleWasmImport, NoLinkModOverride, RawDylibNoNul,
- RenamingNoLink, UnexpectedLinkArg, UnknownImportNameType, UnknownLinkKind, UnknownLinkModifier,
- UnsupportedAbi, UnsupportedAbiI686, WasmImportForm, WholeArchiveNeedsStatic,
-};
+use crate::errors;
use std::path::PathBuf;
}
}
- sess.emit_fatal(MissingNativeLibrary::new(name, verbatim));
+ sess.emit_fatal(errors::MissingNativeLibrary::new(name, verbatim));
}
fn find_bundled_library(
match item.name_or_empty() {
sym::name => {
if name.is_some() {
- sess.emit_err(MultipleNamesInLink { span: item.span() });
+ sess.emit_err(errors::MultipleNamesInLink { span: item.span() });
continue;
}
let Some(link_name) = item.value_str() else {
- sess.emit_err(LinkNameForm { span: item.span() });
+ sess.emit_err(errors::LinkNameForm { span: item.span() });
continue;
};
let span = item.name_value_literal_span().unwrap();
if link_name.is_empty() {
- sess.emit_err(EmptyLinkName { span });
+ sess.emit_err(errors::EmptyLinkName { span });
}
name = Some((link_name, span));
}
sym::kind => {
if kind.is_some() {
- sess.emit_err(MultipleKindsInLink { span: item.span() });
+ sess.emit_err(errors::MultipleKindsInLink { span: item.span() });
continue;
}
let Some(link_kind) = item.value_str() else {
- sess.emit_err(LinkKindForm { span: item.span() });
+ sess.emit_err(errors::LinkKindForm { span: item.span() });
continue;
};
"dylib" => NativeLibKind::Dylib { as_needed: None },
"framework" => {
if !sess.target.is_like_osx {
- sess.emit_err(LinkFrameworkApple { span });
+ sess.emit_err(errors::LinkFrameworkApple { span });
}
NativeLibKind::Framework { as_needed: None }
}
"raw-dylib" => {
if !sess.target.is_like_windows {
- sess.emit_err(FrameworkOnlyWindows { span });
+ sess.emit_err(errors::FrameworkOnlyWindows { span });
} else if !features.raw_dylib && sess.target.arch == "x86" {
feature_err(
&sess.parse_sess,
NativeLibKind::RawDylib
}
kind => {
- sess.emit_err(UnknownLinkKind { span, kind });
+ sess.emit_err(errors::UnknownLinkKind { span, kind });
continue;
}
};
}
sym::modifiers => {
if modifiers.is_some() {
- sess.emit_err(MultipleLinkModifiers { span: item.span() });
+ sess.emit_err(errors::MultipleLinkModifiers { span: item.span() });
continue;
}
let Some(link_modifiers) = item.value_str() else {
- sess.emit_err(LinkModifiersForm { span: item.span() });
+ sess.emit_err(errors::LinkModifiersForm { span: item.span() });
continue;
};
modifiers = Some((link_modifiers, item.name_value_literal_span().unwrap()));
}
sym::cfg => {
if cfg.is_some() {
- sess.emit_err(MultipleCfgs { span: item.span() });
+ sess.emit_err(errors::MultipleCfgs { span: item.span() });
continue;
}
let Some(link_cfg) = item.meta_item_list() else {
- sess.emit_err(LinkCfgForm { span: item.span() });
+ sess.emit_err(errors::LinkCfgForm { span: item.span() });
continue;
};
let [NestedMetaItem::MetaItem(link_cfg)] = link_cfg else {
- sess.emit_err(LinkCfgSinglePredicate { span: item.span() });
+ sess.emit_err(errors::LinkCfgSinglePredicate { span: item.span() });
continue;
};
if !features.link_cfg {
}
sym::wasm_import_module => {
if wasm_import_module.is_some() {
- sess.emit_err(MultipleWasmImport { span: item.span() });
+ sess.emit_err(errors::MultipleWasmImport { span: item.span() });
continue;
}
let Some(link_wasm_import_module) = item.value_str() else {
- sess.emit_err(WasmImportForm { span: item.span() });
+ sess.emit_err(errors::WasmImportForm { span: item.span() });
continue;
};
wasm_import_module = Some((link_wasm_import_module, item.span()));
}
sym::import_name_type => {
if import_name_type.is_some() {
- sess.emit_err(MultipleImportNameType { span: item.span() });
+ sess.emit_err(errors::MultipleImportNameType { span: item.span() });
continue;
}
let Some(link_import_name_type) = item.value_str() else {
- sess.emit_err(ImportNameTypeForm { span: item.span() });
+ sess.emit_err(errors::ImportNameTypeForm { span: item.span() });
continue;
};
if self.tcx.sess.target.arch != "x86" {
- sess.emit_err(ImportNameTypeX86 { span: item.span() });
+ sess.emit_err(errors::ImportNameTypeX86 { span: item.span() });
continue;
}
"noprefix" => PeImportNameType::NoPrefix,
"undecorated" => PeImportNameType::Undecorated,
import_name_type => {
- sess.emit_err(UnknownImportNameType {
+ sess.emit_err(errors::UnknownImportNameType {
span: item.span(),
import_name_type,
});
import_name_type = Some((link_import_name_type, item.span()));
}
_ => {
- sess.emit_err(UnexpectedLinkArg { span: item.span() });
+ sess.emit_err(errors::UnexpectedLinkArg { span: item.span() });
}
}
}
let (modifier, value) = match modifier.strip_prefix(&['+', '-']) {
Some(m) => (m, modifier.starts_with('+')),
None => {
- sess.emit_err(InvalidLinkModifier { span });
+ sess.emit_err(errors::InvalidLinkModifier { span });
continue;
}
};
}
let assign_modifier = |dst: &mut Option<bool>| {
if dst.is_some() {
- sess.emit_err(MultipleModifiers { span, modifier });
+ sess.emit_err(errors::MultipleModifiers { span, modifier });
} else {
*dst = Some(value);
}
assign_modifier(bundle)
}
("bundle", _) => {
- sess.emit_err(BundleNeedsStatic { span });
+ sess.emit_err(errors::BundleNeedsStatic { span });
}
("verbatim", _) => assign_modifier(&mut verbatim),
assign_modifier(whole_archive)
}
("whole-archive", _) => {
- sess.emit_err(WholeArchiveNeedsStatic { span });
+ sess.emit_err(errors::WholeArchiveNeedsStatic { span });
}
("as-needed", Some(NativeLibKind::Dylib { as_needed }))
assign_modifier(as_needed)
}
("as-needed", _) => {
- sess.emit_err(AsNeededCompatibility { span });
+ sess.emit_err(errors::AsNeededCompatibility { span });
}
_ => {
- sess.emit_err(UnknownLinkModifier { span, modifier });
+ sess.emit_err(errors::UnknownLinkModifier { span, modifier });
}
}
}
if let Some((_, span)) = wasm_import_module {
if name.is_some() || kind.is_some() || modifiers.is_some() || cfg.is_some() {
- sess.emit_err(IncompatibleWasmLink { span });
+ sess.emit_err(errors::IncompatibleWasmLink { span });
}
} else if name.is_none() {
- sess.emit_err(LinkRequiresName { span: m.span });
+ sess.emit_err(errors::LinkRequiresName { span: m.span });
}
// Do this outside of the loop so that `import_name_type` can be specified before `kind`.
if let Some((_, span)) = import_name_type {
if kind != Some(NativeLibKind::RawDylib) {
- sess.emit_err(ImportNameTypeRaw { span });
+ sess.emit_err(errors::ImportNameTypeRaw { span });
}
}
let dll_imports = match kind {
Some(NativeLibKind::RawDylib) => {
if let Some((name, span)) = name && name.as_str().contains('\0') {
- sess.emit_err(RawDylibNoNul { span });
+ sess.emit_err(errors::RawDylibNoNul { span });
}
foreign_mod_items
.iter()
.iter()
.find(|a| a.has_name(sym::link_ordinal))
.unwrap();
- sess.emit_err(LinkOrdinalRawDylib { span: link_ordinal_attr.span });
+ sess.emit_err(errors::LinkOrdinalRawDylib {
+ span: link_ordinal_attr.span,
+ });
}
}
for lib in &self.tcx.sess.opts.libs {
if let NativeLibKind::Framework { .. } = lib.kind && !self.tcx.sess.target.is_like_osx {
// Cannot check this when parsing options because the target is not yet available.
- self.tcx.sess.emit_err(LibFrameworkApple);
+ self.tcx.sess.emit_err(errors::LibFrameworkApple);
}
if let Some(ref new_name) = lib.new_name {
let any_duplicate = self
.filter_map(|lib| lib.name.as_ref())
.any(|n| n.as_str() == lib.name);
if new_name.is_empty() {
- self.tcx.sess.emit_err(EmptyRenamingTarget { lib_name: &lib.name });
+ self.tcx.sess.emit_err(errors::EmptyRenamingTarget { lib_name: &lib.name });
} else if !any_duplicate {
- self.tcx.sess.emit_err(RenamingNoLink { lib_name: &lib.name });
+ self.tcx.sess.emit_err(errors::RenamingNoLink { lib_name: &lib.name });
} else if !renames.insert(&lib.name) {
- self.tcx.sess.emit_err(MultipleRenamings { lib_name: &lib.name });
+ self.tcx.sess.emit_err(errors::MultipleRenamings { lib_name: &lib.name });
}
}
}
// explicit `:rename` in particular.
if lib.has_modifiers() || passed_lib.has_modifiers() {
match lib.foreign_module {
- Some(def_id) => self.tcx.sess.emit_err(NoLinkModOverride {
- span: Some(self.tcx.def_span(def_id)),
- }),
- None => {
- self.tcx.sess.emit_err(NoLinkModOverride { span: None })
+ Some(def_id) => {
+ self.tcx.sess.emit_err(errors::NoLinkModOverride {
+ span: Some(self.tcx.def_span(def_id)),
+ })
}
+ None => self
+ .tcx
+ .sess
+ .emit_err(errors::NoLinkModOverride { span: None }),
};
}
if passed_lib.kind != NativeLibKind::Unspecified {
DllCallingConvention::Vectorcall(self.i686_arg_list_size(item))
}
_ => {
- self.tcx.sess.emit_fatal(UnsupportedAbiI686 { span: item.span });
+ self.tcx.sess.emit_fatal(errors::UnsupportedAbiI686 { span: item.span });
}
}
} else {
match abi {
Abi::C { .. } | Abi::Win64 { .. } | Abi::System { .. } => DllCallingConvention::C,
_ => {
- self.tcx.sess.emit_fatal(UnsupportedAbi { span: item.span });
+ self.tcx.sess.emit_fatal(errors::UnsupportedAbi { span: item.span });
}
}
};
AggregateKind::Closure(def_id, substs) => ty::tls::with(|tcx| {
let name = if tcx.sess.opts.unstable_opts.span_free_formats {
let substs = tcx.lift(substs).unwrap();
- format!(
- "[closure@{}]",
- tcx.def_path_str_with_substs(def_id.to_def_id(), substs),
- )
+ format!("[closure@{}]", tcx.def_path_str_with_substs(def_id, substs),)
} else {
let span = tcx.def_span(def_id);
format!(
let mut struct_fmt = fmt.debug_struct(&name);
// FIXME(project-rfc-2229#48): This should be a list of capture names/places
- if let Some(upvars) = tcx.upvars_mentioned(def_id) {
+ if let Some(def_id) = def_id.as_local()
+ && let Some(upvars) = tcx.upvars_mentioned(def_id)
+ {
for (&var_id, place) in iter::zip(upvars.keys(), places) {
let var_name = tcx.hir().name(var_id);
struct_fmt.field(var_name.as_str(), place);
}
+ } else {
+ for (index, place) in places.iter().enumerate() {
+ struct_fmt.field(&format!("{index}"), place);
+ }
}
struct_fmt.finish()
let mut struct_fmt = fmt.debug_struct(&name);
// FIXME(project-rfc-2229#48): This should be a list of capture names/places
- if let Some(upvars) = tcx.upvars_mentioned(def_id) {
+ if let Some(def_id) = def_id.as_local()
+ && let Some(upvars) = tcx.upvars_mentioned(def_id)
+ {
for (&var_id, place) in iter::zip(upvars.keys(), places) {
let var_name = tcx.hir().name(var_id);
struct_fmt.field(var_name.as_str(), place);
}
+ } else {
+ for (index, place) in places.iter().enumerate() {
+ struct_fmt.field(&format!("{index}"), place);
+ }
}
struct_fmt.finish()
/// active field index would identity the field `c`
Adt(DefId, VariantIdx, SubstsRef<'tcx>, Option<UserTypeAnnotationIndex>, Option<usize>),
- // Note: We can use LocalDefId since closures and generators a deaggregated
- // before codegen.
- Closure(LocalDefId, SubstsRef<'tcx>),
- Generator(LocalDefId, SubstsRef<'tcx>, hir::Movability),
+ Closure(DefId, SubstsRef<'tcx>),
+ Generator(DefId, SubstsRef<'tcx>, hir::Movability),
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)]
AggregateKind::Adt(did, _, substs, _, _) => {
tcx.bound_type_of(did).subst(tcx, substs)
}
- AggregateKind::Closure(did, substs) => tcx.mk_closure(did.to_def_id(), substs),
+ AggregateKind::Closure(did, substs) => tcx.mk_closure(did, substs),
AggregateKind::Generator(did, substs, movability) => {
- tcx.mk_generator(did.to_def_id(), substs, movability)
+ tcx.mk_generator(did, substs, movability)
}
},
Rvalue::ShallowInitBox(_, ty) => tcx.mk_box(ty),
}
}
-/// Helper for `TyCtxtEnsure` to avoid a closure.
-#[inline(always)]
-fn noop<T>(_: &T) {}
-
-/// Helper to ensure that queries only return `Copy` types.
-#[inline(always)]
-fn copy<T: Copy>(x: &T) -> T {
- *x
-}
-
macro_rules! query_helper_param_ty {
(DefId) => { impl IntoQueryParam<DefId> };
(LocalDefId) => { impl IntoQueryParam<LocalDefId> };
let key = key.into_query_param();
opt_remap_env_constness!([$($modifiers)*][key]);
- let cached = try_get_cached(self.tcx, &self.tcx.query_caches.$name, &key, noop);
-
- match cached {
- Ok(()) => return,
- Err(()) => (),
- }
-
- self.tcx.queries.$name(self.tcx, DUMMY_SP, key, QueryMode::Ensure);
+ match try_get_cached(self.tcx, &self.tcx.query_caches.$name, &key) {
+ Some(_) => return,
+ None => self.tcx.queries.$name(self.tcx, DUMMY_SP, key, QueryMode::Ensure),
+ };
})*
}
let key = key.into_query_param();
opt_remap_env_constness!([$($modifiers)*][key]);
- let cached = try_get_cached(self.tcx, &self.tcx.query_caches.$name, &key, copy);
-
- match cached {
- Ok(value) => return value,
- Err(()) => (),
+ match try_get_cached(self.tcx, &self.tcx.query_caches.$name, &key) {
+ Some(value) => value,
+ None => self.tcx.queries.$name(self.tcx, self.span, key, QueryMode::Get).unwrap(),
}
-
- self.tcx.queries.$name(self.tcx, self.span, key, QueryMode::Get).unwrap()
})*
}
let tcx = self.tcx;
let cache = &tcx.query_caches.$name;
- let cached = try_get_cached(tcx, cache, &key, copy);
-
- match cached {
- Ok(old) => {
+ match try_get_cached(tcx, cache, &key) {
+ Some(old) => {
bug!(
"Trying to feed an already recorded value for query {} key={key:?}:\nold value: {old:?}\nnew value: {value:?}",
stringify!($name),
+ )
+ }
+ None => {
+ let dep_node = dep_graph::DepNode::construct(tcx, dep_graph::DepKind::$name, &key);
+ let dep_node_index = tcx.dep_graph.with_feed_task(
+ dep_node,
+ tcx,
+ key,
+ &value,
+ hash_result!([$($modifiers)*]),
);
+ cache.complete(key, value, dep_node_index)
}
- Err(()) => (),
}
-
- let dep_node = dep_graph::DepNode::construct(tcx, dep_graph::DepKind::$name, &key);
- let dep_node_index = tcx.dep_graph.with_feed_task(
- dep_node,
- tcx,
- key,
- &value,
- hash_result!([$($modifiers)*]),
- );
- cache.complete(key, value, dep_node_index)
}
})*
}
b = tcx.expand_abstract_consts(b);
}
+ debug!("{}.super_relate_consts(normed_a = {:?}, normed_b = {:?})", relation.tag(), a, b);
+
// Currently, the values that can be unified are primitive types,
// and those that derive both `PartialEq` and `Eq`, corresponding
// to structural-match types.
// FIXME(generic_const_exprs): is it possible to relate two consts which are not identical
// exprs? Should we care about that?
+ // FIXME(generic_const_exprs): relating the `ty()`s is a little weird since it is supposed to
+ // ICE If they mismatch. Unfortunately `ConstKind::Expr` is a little special and can be thought
+ // of as being generic over the argument types, however this is implicit so these types don't get
+ // related when we relate the substs of the item this const arg is for.
let expr = match (ae, be) {
- (Expr::Binop(a_op, al, ar), Expr::Binop(b_op, bl, br))
- if a_op == b_op && al.ty() == bl.ty() && ar.ty() == br.ty() =>
- {
+ (Expr::Binop(a_op, al, ar), Expr::Binop(b_op, bl, br)) if a_op == b_op => {
+ r.relate(al.ty(), bl.ty())?;
+ r.relate(ar.ty(), br.ty())?;
Expr::Binop(a_op, r.consts(al, bl)?, r.consts(ar, br)?)
}
- (Expr::UnOp(a_op, av), Expr::UnOp(b_op, bv))
- if a_op == b_op && av.ty() == bv.ty() =>
- {
+ (Expr::UnOp(a_op, av), Expr::UnOp(b_op, bv)) if a_op == b_op => {
+ r.relate(av.ty(), bv.ty())?;
Expr::UnOp(a_op, r.consts(av, bv)?)
}
- (Expr::Cast(ak, av, at), Expr::Cast(bk, bv, bt))
- if ak == bk && av.ty() == bv.ty() =>
- {
+ (Expr::Cast(ak, av, at), Expr::Cast(bk, bv, bt)) if ak == bk => {
+ r.relate(av.ty(), bv.ty())?;
Expr::Cast(ak, r.consts(av, bv)?, r.tys(at, bt)?)
}
(Expr::FunctionCall(af, aa), Expr::FunctionCall(bf, ba))
- if aa.len() == ba.len()
- && af.ty() == bf.ty()
- && aa
- .iter()
- .zip(ba.iter())
- .all(|(a_arg, b_arg)| a_arg.ty() == b_arg.ty()) =>
+ if aa.len() == ba.len() =>
{
+ r.relate(af.ty(), bf.ty())?;
let func = r.consts(af, bf)?;
let mut related_args = Vec::with_capacity(aa.len());
for (a_arg, b_arg) in aa.iter().zip(ba.iter()) {
// We implicitly set the discriminant to 0. See
// librustc_mir/transform/deaggregator.rs for details.
let movability = movability.unwrap();
- Box::new(AggregateKind::Generator(closure_id, substs, movability))
+ Box::new(AggregateKind::Generator(
+ closure_id.to_def_id(),
+ substs,
+ movability,
+ ))
}
UpvarSubsts::Closure(substs) => {
- Box::new(AggregateKind::Closure(closure_id, substs))
+ Box::new(AggregateKind::Closure(closure_id.to_def_id(), substs))
}
};
block.and(Rvalue::Aggregate(result, operands))
}
}
&AggregateKind::Closure(def_id, _) | &AggregateKind::Generator(def_id, _, _) => {
+ let def_id = def_id.expect_local();
let UnsafetyCheckResult { violations, used_unsafe_blocks, .. } =
self.tcx.unsafety_check_result(def_id);
self.register_violations(violations, used_unsafe_blocks.iter().copied());
use rustc_const_eval::const_eval::CheckAlignment;
use rustc_const_eval::interpret::{ConstValue, ImmTy, Immediate, InterpCx, Scalar};
use rustc_data_structures::fx::FxHashMap;
+use rustc_hir::def::DefKind;
use rustc_middle::mir::visit::{MutVisitor, Visitor};
use rustc_middle::mir::*;
use rustc_middle::ty::{self, Ty, TyCtxt};
state: &mut State<Self::Value>,
) {
match rvalue {
+ Rvalue::Aggregate(kind, operands) => {
+ let target = self.map().find(target.as_ref());
+ if let Some(target) = target {
+ state.flood_idx_with(target, self.map(), FlatSet::Bottom);
+ let field_based = match **kind {
+ AggregateKind::Tuple | AggregateKind::Closure(..) => true,
+ AggregateKind::Adt(def_id, ..) => {
+ matches!(self.tcx.def_kind(def_id), DefKind::Struct)
+ }
+ _ => false,
+ };
+ if field_based {
+ for (field_index, operand) in operands.iter().enumerate() {
+ if let Some(field) = self
+ .map()
+ .apply(target, TrackElem::Field(Field::from_usize(field_index)))
+ {
+ let result = self.handle_operand(operand, state);
+ state.assign_idx(field, result, self.map());
+ }
+ }
+ }
+ }
+ }
Rvalue::CheckedBinaryOp(op, box (left, right)) => {
let target = self.map().find(target.as_ref());
if let Some(target) = target {
+++ /dev/null
-use crate::util::expand_aggregate;
-use crate::MirPass;
-use rustc_middle::mir::*;
-use rustc_middle::ty::TyCtxt;
-
-pub struct Deaggregator;
-
-impl<'tcx> MirPass<'tcx> for Deaggregator {
- fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
- let basic_blocks = body.basic_blocks.as_mut_preserves_cfg();
- for bb in basic_blocks {
- bb.expand_statements(|stmt| {
- // FIXME(eddyb) don't match twice on `stmt.kind` (post-NLL).
- match stmt.kind {
- // FIXME(#48193) Deaggregate arrays when it's cheaper to do so.
- StatementKind::Assign(box (
- _,
- Rvalue::Aggregate(box AggregateKind::Array(_), _),
- )) => {
- return None;
- }
- StatementKind::Assign(box (_, Rvalue::Aggregate(_, _))) => {}
- _ => return None,
- }
-
- let stmt = stmt.replace_nop();
- let source_info = stmt.source_info;
- let StatementKind::Assign(box (lhs, Rvalue::Aggregate(kind, operands))) = stmt.kind else {
- bug!();
- };
-
- Some(expand_aggregate(
- lhs,
- operands.into_iter().map(|op| {
- let ty = op.ty(&body.local_decls, tcx);
- (op, ty)
- }),
- *kind,
- source_info,
- tcx,
- ))
- });
- }
- }
-}
use crate::deref_separator::deref_finder;
use crate::simplify;
-use crate::util::expand_aggregate;
use crate::MirPass;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_errors::pluralize;
assert_eq!(self.state_adt_ref.variant(idx).fields.len(), 0);
// FIXME(swatinem): assert that `val` is indeed unit?
- statements.extend(expand_aggregate(
- Place::return_place(),
- std::iter::empty(),
- kind,
+ statements.push(Statement {
+ kind: StatementKind::Assign(Box::new((
+ Place::return_place(),
+ Rvalue::Aggregate(Box::new(kind), vec![]),
+ ))),
source_info,
- self.tcx,
- ));
+ });
return;
}
// else: `Poll::Ready(x)`, `GeneratorState::Yielded(x)` or `GeneratorState::Complete(x)`
assert_eq!(self.state_adt_ref.variant(idx).fields.len(), 1);
- let ty = self
- .tcx
- .bound_type_of(self.state_adt_ref.variant(idx).fields[0].did)
- .subst(self.tcx, self.state_substs);
-
- statements.extend(expand_aggregate(
- Place::return_place(),
- std::iter::once((val, ty)),
- kind,
+ statements.push(Statement {
+ kind: StatementKind::Assign(Box::new((
+ Place::return_place(),
+ Rvalue::Aggregate(Box::new(kind), vec![val]),
+ ))),
source_info,
- self.tcx,
- ));
+ });
}
// Create a Place referencing a generator struct field
mod ctfe_limit;
mod dataflow_const_prop;
mod dead_store_elimination;
-mod deaggregator;
mod deduce_param_attrs;
mod deduplicate_blocks;
mod deref_separator;
&elaborate_box_derefs::ElaborateBoxDerefs,
&generator::StateTransform,
&add_retag::AddRetag,
- // Deaggregator is necessary for const prop. We may want to consider implementing
- // CTFE support for aggregates.
- &deaggregator::Deaggregator,
&Lint(const_prop_lint::ConstProp),
];
pm::run_passes_no_validate(tcx, body, passes, Some(MirPhase::Runtime(RuntimePhase::Initial)));
use std::fmt;
use std::iter;
-use crate::util::expand_aggregate;
use crate::{
abort_unwinding_calls, add_call_guards, add_moves_for_packed_drops, deref_separator,
pass_manager as pm, remove_noop_landing_pads, simplify,
// return;
debug!("build_ctor: variant_index={:?}", variant_index);
- let statements = expand_aggregate(
- Place::return_place(),
- adt_def.variant(variant_index).fields.iter().enumerate().map(|(idx, field_def)| {
- (Operand::Move(Place::from(Local::new(idx + 1))), field_def.ty(tcx, substs))
- }),
- AggregateKind::Adt(adt_def.did(), variant_index, substs, None, None),
+ let kind = AggregateKind::Adt(adt_def.did(), variant_index, substs, None, None);
+ let variant = adt_def.variant(variant_index);
+ let statement = Statement {
+ kind: StatementKind::Assign(Box::new((
+ Place::return_place(),
+ Rvalue::Aggregate(
+ Box::new(kind),
+ (0..variant.fields.len())
+ .map(|idx| Operand::Move(Place::from(Local::new(idx + 1))))
+ .collect(),
+ ),
+ ))),
source_info,
- tcx,
- )
- .collect();
+ };
let start_block = BasicBlockData {
- statements,
+ statements: vec![statement],
terminator: Some(Terminator { source_info, kind: TerminatorKind::Return }),
is_cleanup: false,
};
AddIn(#[primary_span] Span),
}
+#[derive(Diagnostic)]
+#[diag(parse_missing_expression_in_for_loop)]
+pub(crate) struct MissingExpressionInForLoop {
+ #[primary_span]
+ #[suggestion(
+ code = "/* expression */ ",
+ applicability = "has-placeholders",
+ style = "verbose"
+ )]
+ pub span: Span,
+}
+
#[derive(Diagnostic)]
#[diag(parse_missing_comma_after_match_arm)]
pub(crate) struct MissingCommaAfterMatchArm {
pub span: Span,
}
+#[derive(Diagnostic)]
+#[diag(parse_unexpected_default_value_for_lifetime_in_generic_parameters)]
+pub(crate) struct UnexpectedDefaultValueForLifetimeInGenericParameters {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+}
+
#[derive(Diagnostic)]
#[diag(parse_multiple_where_clauses)]
pub(crate) struct MultipleWhereClauses {
AttrWrapper, BlockMode, ClosureSpans, ForceCollect, Parser, PathStyle, Restrictions,
SemiColonMode, SeqSep, TokenExpectType, TokenType, TrailingToken,
};
-use crate::errors::{
- ArrayBracketsInsteadOfSpaces, ArrayBracketsInsteadOfSpacesSugg, AsyncBlockIn2015,
- AsyncMoveOrderIncorrect, BracesForStructLiteral, CatchAfterTry, CommaAfterBaseStruct,
- ComparisonInterpretedAsGeneric, ComparisonOrShiftInterpretedAsGenericSugg,
- DoCatchSyntaxRemoved, DotDotDot, EqFieldInit, ExpectedElseBlock, ExpectedEqForLetExpr,
- ExpectedExpressionFoundLet, FieldExpressionWithGeneric, FloatLiteralRequiresIntegerPart,
- FoundExprWouldBeStmt, HelpUseLatestEdition, IfExpressionLetSomeSub,
- IfExpressionMissingCondition, IfExpressionMissingThenBlock, IfExpressionMissingThenBlockSub,
- InvalidBlockMacroSegment, InvalidComparisonOperator, InvalidComparisonOperatorSub,
- InvalidInterpolatedExpression, InvalidLiteralSuffixOnTupleIndex, InvalidLogicalOperator,
- InvalidLogicalOperatorSub, LabeledLoopInBreak, LeadingPlusNotSupported, LeftArrowOperator,
- LifetimeInBorrowExpression, MacroInvocationWithQualifiedPath, MalformedLoopLabel,
- MatchArmBodyWithoutBraces, MatchArmBodyWithoutBracesSugg, MissingCommaAfterMatchArm,
- MissingDotDot, MissingInInForLoop, MissingInInForLoopSub, MissingSemicolonBeforeArray,
- NoFieldsForFnCall, NotAsNegationOperator, NotAsNegationOperatorSub,
- OuterAttributeNotAllowedOnIfElse, ParenthesesWithStructFields,
- RequireColonAfterLabeledExpression, ShiftInterpretedAsGeneric, StructLiteralNotAllowedHere,
- StructLiteralNotAllowedHereSugg, TildeAsUnaryOperator, UnexpectedIfWithIf,
- UnexpectedTokenAfterLabel, UnexpectedTokenAfterLabelSugg, WrapExpressionInParentheses,
-};
+use crate::errors;
use crate::maybe_recover_from_interpolated_ty_qpath;
use core::mem;
use rustc_ast::ptr::P;
}
.into();
let invalid = format!("{}=", &sugg);
- self.sess.emit_err(InvalidComparisonOperator {
+ self.sess.emit_err(errors::InvalidComparisonOperator {
span: sp,
invalid: invalid.clone(),
- sub: InvalidComparisonOperatorSub::Correctable {
+ sub: errors::InvalidComparisonOperatorSub::Correctable {
span: sp,
invalid,
correct: sugg,
&& self.prev_token.span.hi() == self.token.span.lo()
{
let sp = op.span.to(self.token.span);
- self.sess.emit_err(InvalidComparisonOperator {
+ self.sess.emit_err(errors::InvalidComparisonOperator {
span: sp,
invalid: "<>".into(),
- sub: InvalidComparisonOperatorSub::Correctable {
+ sub: errors::InvalidComparisonOperatorSub::Correctable {
span: sp,
invalid: "<>".into(),
correct: "!=".into(),
&& self.prev_token.span.hi() == self.token.span.lo()
{
let sp = op.span.to(self.token.span);
- self.sess.emit_err(InvalidComparisonOperator {
+ self.sess.emit_err(errors::InvalidComparisonOperator {
span: sp,
invalid: "<=>".into(),
- sub: InvalidComparisonOperatorSub::Spaceship(sp),
+ sub: errors::InvalidComparisonOperatorSub::Spaceship(sp),
});
self.bump();
}
/// but the next token implies this should be parsed as an expression.
/// For example: `if let Some(x) = x { x } else { 0 } / 2`.
fn error_found_expr_would_be_stmt(&self, lhs: &Expr) {
- self.sess.emit_err(FoundExprWouldBeStmt {
+ self.sess.emit_err(errors::FoundExprWouldBeStmt {
span: self.token.span,
token: self.token.clone(),
suggestion: ExprParenthesesNeeded::surrounding(lhs.span),
}
(Some(op), _) => (op, self.token.span),
(None, Some((Ident { name: sym::and, span }, false))) if self.may_recover() => {
- self.sess.emit_err(InvalidLogicalOperator {
+ self.sess.emit_err(errors::InvalidLogicalOperator {
span: self.token.span,
incorrect: "and".into(),
- sub: InvalidLogicalOperatorSub::Conjunction(self.token.span),
+ sub: errors::InvalidLogicalOperatorSub::Conjunction(self.token.span),
});
(AssocOp::LAnd, span)
}
(None, Some((Ident { name: sym::or, span }, false))) if self.may_recover() => {
- self.sess.emit_err(InvalidLogicalOperator {
+ self.sess.emit_err(errors::InvalidLogicalOperator {
span: self.token.span,
incorrect: "or".into(),
- sub: InvalidLogicalOperatorSub::Disjunction(self.token.span),
+ sub: errors::InvalidLogicalOperatorSub::Disjunction(self.token.span),
});
(AssocOp::LOr, span)
}
}
// `+lit`
token::BinOp(token::Plus) if this.look_ahead(1, |tok| tok.is_numeric_lit()) => {
- let mut err =
- LeadingPlusNotSupported { span: lo, remove_plus: None, add_parentheses: None };
+ let mut err = errors::LeadingPlusNotSupported {
+ span: lo,
+ remove_plus: None,
+ add_parentheses: None,
+ };
// a block on the LHS might have been intended to be an expression instead
if let Some(sp) = this.sess.ambiguous_block_expr_parse.borrow().get(&lo) {
/// Recover on `~expr` in favor of `!expr`.
fn recover_tilde_expr(&mut self, lo: Span) -> PResult<'a, (Span, ExprKind)> {
- self.sess.emit_err(TildeAsUnaryOperator(lo));
+ self.sess.emit_err(errors::TildeAsUnaryOperator(lo));
self.parse_unary_expr(lo, UnOp::Not)
}
let negated_token = self.look_ahead(1, |t| t.clone());
let sub_diag = if negated_token.is_numeric_lit() {
- NotAsNegationOperatorSub::SuggestNotBitwise
+ errors::NotAsNegationOperatorSub::SuggestNotBitwise
} else if negated_token.is_bool_lit() {
- NotAsNegationOperatorSub::SuggestNotLogical
+ errors::NotAsNegationOperatorSub::SuggestNotLogical
} else {
- NotAsNegationOperatorSub::SuggestNotDefault
+ errors::NotAsNegationOperatorSub::SuggestNotDefault
};
- self.sess.emit_err(NotAsNegationOperator {
+ self.sess.emit_err(errors::NotAsNegationOperator {
negated: negated_token.span,
negated_desc: super::token_descr(&negated_token),
// Span the `not` plus trailing whitespace to avoid
match self.parse_labeled_expr(label, false) {
Ok(expr) => {
type_err.cancel();
- self.sess.emit_err(MalformedLoopLabel {
+ self.sess.emit_err(errors::MalformedLoopLabel {
span: label.ident.span,
correct_label: label.ident,
});
);
let args_span = self.look_ahead(1, |t| t.span).to(span_after_type);
- let suggestion = ComparisonOrShiftInterpretedAsGenericSugg {
+ let suggestion = errors::ComparisonOrShiftInterpretedAsGenericSugg {
left: expr.span.shrink_to_lo(),
right: expr.span.shrink_to_hi(),
};
match self.token.kind {
- token::Lt => self.sess.emit_err(ComparisonInterpretedAsGeneric {
- comparison: self.token.span,
- r#type: path,
- args: args_span,
- suggestion,
- }),
+ token::Lt => {
+ self.sess.emit_err(errors::ComparisonInterpretedAsGeneric {
+ comparison: self.token.span,
+ r#type: path,
+ args: args_span,
+ suggestion,
+ })
+ }
token::BinOp(token::Shl) => {
- self.sess.emit_err(ShiftInterpretedAsGeneric {
+ self.sess.emit_err(errors::ShiftInterpretedAsGeneric {
shift: self.token.span,
r#type: path,
args: args_span,
}
fn error_remove_borrow_lifetime(&self, span: Span, lt_span: Span) {
- self.sess.emit_err(LifetimeInBorrowExpression { span, lifetime_span: lt_span });
+ self.sess.emit_err(errors::LifetimeInBorrowExpression { span, lifetime_span: lt_span });
}
/// Parse `mut?` or `raw [ const | mut ]`.
let close_paren = self.prev_token.span;
let span = lo.to(self.prev_token.span);
if !fields.is_empty() {
- let mut replacement_err = ParenthesesWithStructFields {
+ let mut replacement_err = errors::ParenthesesWithStructFields {
span,
r#type: path,
- braces_for_struct: BracesForStructLiteral {
+ braces_for_struct: errors::BracesForStructLiteral {
first: open_paren,
second: close_paren,
},
- no_fields_for_fn: NoFieldsForFnCall {
+ no_fields_for_fn: errors::NoFieldsForFnCall {
fields: fields
.into_iter()
.map(|field| field.span.until(field.expr.span))
} else {
// Field access `expr.f`
if let Some(args) = seg.args {
- self.sess.emit_err(FieldExpressionWithGeneric(args.span()));
+ self.sess.emit_err(errors::FieldExpressionWithGeneric(args.span()));
}
let span = lo.to(self.prev_token.span);
let (span, kind) = if self.eat(&token::Not) {
// MACRO INVOCATION expression
if qself.is_some() {
- self.sess.emit_err(MacroInvocationWithQualifiedPath(path.span));
+ self.sess.emit_err(errors::MacroInvocationWithQualifiedPath(path.span));
}
let lo = path.span;
let mac = P(MacCall {
{
let (lit, _) =
self.recover_unclosed_char(label_.ident, Parser::mk_token_lit_char, |self_| {
- self_.sess.create_err(UnexpectedTokenAfterLabel {
+ self_.sess.create_err(errors::UnexpectedTokenAfterLabel {
span: self_.token.span,
remove_label: None,
enclose_in_block: None,
&& (self.check_noexpect(&TokenKind::Comma) || self.check_noexpect(&TokenKind::Gt))
{
// We're probably inside of a `Path<'a>` that needs a turbofish
- self.sess.emit_err(UnexpectedTokenAfterLabel {
+ self.sess.emit_err(errors::UnexpectedTokenAfterLabel {
span: self.token.span,
remove_label: None,
enclose_in_block: None,
consume_colon = false;
Ok(self.mk_expr_err(lo))
} else {
- let mut err = UnexpectedTokenAfterLabel {
+ let mut err = errors::UnexpectedTokenAfterLabel {
span: self.token.span,
remove_label: None,
enclose_in_block: None,
return expr;
}
- err.enclose_in_block = Some(UnexpectedTokenAfterLabelSugg {
+ err.enclose_in_block = Some(errors::UnexpectedTokenAfterLabelSugg {
left: span.shrink_to_lo(),
right: span.shrink_to_hi(),
});
}?;
if !ate_colon && consume_colon {
- self.sess.emit_err(RequireColonAfterLabeledExpression {
+ self.sess.emit_err(errors::RequireColonAfterLabeledExpression {
span: expr.span,
label: lo,
label_end: lo.shrink_to_hi(),
self.bump(); // `catch`
let span = lo.to(self.prev_token.span);
- self.sess.emit_err(DoCatchSyntaxRemoved { span });
+ self.sess.emit_err(errors::DoCatchSyntaxRemoved { span });
self.parse_try_block(lo)
}
// The value expression can be a labeled loop, see issue #86948, e.g.:
// `loop { break 'label: loop { break 'label 42; }; }`
let lexpr = self.parse_labeled_expr(label, true)?;
- self.sess.emit_err(LabeledLoopInBreak {
+ self.sess.emit_err(errors::LabeledLoopInBreak {
span: lexpr.span,
- sub: WrapExpressionInParentheses {
+ sub: errors::WrapExpressionInParentheses {
left: lexpr.span.shrink_to_lo(),
right: lexpr.span.shrink_to_hi(),
},
};
if let Some(expr) = expr {
if matches!(expr.kind, ExprKind::Err) {
- let mut err = InvalidInterpolatedExpression { span: self.token.span }
+ let mut err = errors::InvalidInterpolatedExpression { span: self.token.span }
.into_diagnostic(&self.sess.span_diagnostic);
err.downgrade_to_delayed_bug();
return Err(err);
});
if let Some(token) = &recovered {
self.bump();
- self.sess.emit_err(FloatLiteralRequiresIntegerPart {
+ self.sess.emit_err(errors::FloatLiteralRequiresIntegerPart {
span: token.span,
correct: pprust::token_to_string(token).into_owned(),
});
if [sym::i32, sym::u32, sym::isize, sym::usize].contains(&suffix) {
// #59553: warn instead of reject out of hand to allow the fix to percolate
// through the ecosystem when people fix their macros
- self.sess.emit_warning(InvalidLiteralSuffixOnTupleIndex {
+ self.sess.emit_warning(errors::InvalidLiteralSuffixOnTupleIndex {
span,
suffix,
exception: Some(()),
});
} else {
- self.sess.emit_err(InvalidLiteralSuffixOnTupleIndex { span, suffix, exception: None });
+ self.sess.emit_err(errors::InvalidLiteralSuffixOnTupleIndex {
+ span,
+ suffix,
+ exception: None,
+ });
}
}
let mut snapshot = self.create_snapshot_for_diagnostic();
match snapshot.parse_array_or_repeat_expr(Delimiter::Brace) {
Ok(arr) => {
- self.sess.emit_err(ArrayBracketsInsteadOfSpaces {
+ self.sess.emit_err(errors::ArrayBracketsInsteadOfSpaces {
span: arr.span,
- sub: ArrayBracketsInsteadOfSpacesSugg {
+ sub: errors::ArrayBracketsInsteadOfSpacesSugg {
left: lo,
right: snapshot.prev_token.span,
},
.span_to_snippet(snapshot.token.span)
.map_or(false, |snippet| snippet == "]") =>
{
- return Err(MissingSemicolonBeforeArray {
+ return Err(errors::MissingSemicolonBeforeArray {
open_delim: open_delim_span,
semicolon: prev_span.shrink_to_hi(),
}.into_diagnostic(&self.sess.span_diagnostic));
}
if self.token.is_whole_block() {
- self.sess.emit_err(InvalidBlockMacroSegment {
+ self.sess.emit_err(errors::InvalidBlockMacroSegment {
span: self.token.span,
context: lo.to(self.token.span),
});
// Check for `move async` and recover
if self.check_keyword(kw::Async) {
let move_async_span = self.token.span.with_lo(self.prev_token.span.data().lo);
- Err(AsyncMoveOrderIncorrect { span: move_async_span }
+ Err(errors::AsyncMoveOrderIncorrect { span: move_async_span }
.into_diagnostic(&self.sess.span_diagnostic))
} else {
Ok(CaptureBy::Value)
let block = match &mut cond.kind {
ExprKind::Binary(Spanned { span: binop_span, .. }, _, right)
if let ExprKind::Block(_, None) = right.kind => {
- self.sess.emit_err(IfExpressionMissingThenBlock {
+ self.sess.emit_err(errors::IfExpressionMissingThenBlock {
if_span: lo,
missing_then_block_sub:
- IfExpressionMissingThenBlockSub::UnfinishedCondition(cond_span.shrink_to_lo().to(*binop_span)),
+ errors::IfExpressionMissingThenBlockSub::UnfinishedCondition(cond_span.shrink_to_lo().to(*binop_span)),
let_else_sub: None,
});
std::mem::replace(right, this.mk_expr_err(binop_span.shrink_to_hi()))
},
ExprKind::Block(_, None) => {
- self.sess.emit_err(IfExpressionMissingCondition {
+ self.sess.emit_err(errors::IfExpressionMissingCondition {
if_span: lo.shrink_to_hi(),
block_span: self.sess.source_map().start_point(cond_span),
});
block
} else {
let let_else_sub = matches!(cond.kind, ExprKind::Let(..))
- .then(|| IfExpressionLetSomeSub { if_span: lo.until(cond_span) });
+ .then(|| errors::IfExpressionLetSomeSub { if_span: lo.until(cond_span) });
- self.sess.emit_err(IfExpressionMissingThenBlock {
+ self.sess.emit_err(errors::IfExpressionMissingThenBlock {
if_span: lo,
- missing_then_block_sub: IfExpressionMissingThenBlockSub::AddThenBlock(
+ missing_then_block_sub: errors::IfExpressionMissingThenBlockSub::AddThenBlock(
cond_span.shrink_to_hi(),
),
let_else_sub,
TokenKind::AndAnd | TokenKind::Ident(kw::If, _) | TokenKind::Ident(kw::While, _)
);
if !self.restrictions.contains(Restrictions::ALLOW_LET) || not_in_chain {
- self.sess.emit_err(ExpectedExpressionFoundLet { span: self.token.span });
+ self.sess.emit_err(errors::ExpectedExpressionFoundLet { span: self.token.span });
}
self.bump(); // Eat `let` token
CommaRecoveryMode::LikelyTuple,
)?;
if self.token == token::EqEq {
- self.sess.emit_err(ExpectedEqForLetExpr {
+ self.sess.emit_err(errors::ExpectedEqForLetExpr {
span: self.token.span,
sugg_span: self.token.span,
});
if self.check(&TokenKind::OpenDelim(Delimiter::Brace))
&& classify::expr_requires_semi_to_be_stmt(&cond) =>
{
- self.sess.emit_err(ExpectedElseBlock {
+ self.sess.emit_err(errors::ExpectedElseBlock {
first_tok_span,
first_tok,
else_span,
[x0 @ xn] | [x0, .., xn] => (x0.span.to(xn.span), xn.span),
};
let ctx = if is_ctx_else { "else" } else { "if" };
- self.sess.emit_err(OuterAttributeNotAllowedOnIfElse {
+ self.sess.emit_err(errors::OuterAttributeNotAllowedOnIfElse {
last,
branch_span,
ctx_span,
if let ExprKind::Binary(Spanned { span: binop_span, node: binop}, _, right) = &cond.kind &&
let BinOpKind::And = binop &&
let ExprKind::If(cond, ..) = &right.kind {
- Err(self.sess.create_err(UnexpectedIfWithIf(binop_span.shrink_to_hi().to(cond.span.shrink_to_lo()))))
+ Err(self.sess.create_err(errors::UnexpectedIfWithIf(binop_span.shrink_to_hi().to(cond.span.shrink_to_lo()))))
} else {
Ok(())
}
let pat = self.recover_parens_around_for_head(pat, begin_paren);
+ // Recover from missing expression in `for` loop
+ if matches!(expr.kind, ExprKind::Block(..))
+ && !matches!(self.token.kind, token::OpenDelim(token::Delimiter::Brace))
+ && self.may_recover()
+ {
+ self.sess
+ .emit_err(errors::MissingExpressionInForLoop { span: expr.span.shrink_to_lo() });
+ let err_expr = self.mk_expr(expr.span, ExprKind::Err);
+ let block = self.mk_block(vec![], BlockCheckMode::Default, self.prev_token.span);
+ return Ok(self.mk_expr(
+ lo.to(self.prev_token.span),
+ ExprKind::ForLoop(pat, err_expr, block, opt_label),
+ ));
+ }
+
let (attrs, loop_block) = self.parse_inner_attrs_and_block()?;
let kind = ExprKind::ForLoop(pat, expr, loop_block, opt_label);
// Possibly using JS syntax (#75311).
let span = self.token.span;
self.bump();
- (span, MissingInInForLoopSub::InNotOf)
+ (span, errors::MissingInInForLoopSub::InNotOf)
} else {
- (self.prev_token.span.between(self.token.span), MissingInInForLoopSub::AddIn)
+ (self.prev_token.span.between(self.token.span), errors::MissingInInForLoopSub::AddIn)
};
- self.sess.emit_err(MissingInInForLoop { span, sub: sub(span) });
+ self.sess.emit_err(errors::MissingInInForLoop { span, sub: sub(span) });
}
/// Parses a `while` or `while let` expression (`while` token already eaten).
let err = |this: &Parser<'_>, stmts: Vec<ast::Stmt>| {
let span = stmts[0].span.to(stmts[stmts.len() - 1].span);
- this.sess.emit_err(MatchArmBodyWithoutBraces {
+ this.sess.emit_err(errors::MatchArmBodyWithoutBraces {
statements: span,
arrow: arrow_span,
num_statements: stmts.len(),
sub: if stmts.len() > 1 {
- MatchArmBodyWithoutBracesSugg::AddBraces {
+ errors::MatchArmBodyWithoutBracesSugg::AddBraces {
left: span.shrink_to_lo(),
right: span.shrink_to_hi(),
}
} else {
- MatchArmBodyWithoutBracesSugg::UseComma { semicolon: semi_sp }
+ errors::MatchArmBodyWithoutBracesSugg::UseComma { semicolon: semi_sp }
},
});
this.mk_expr_err(span)
.is_ok();
if pattern_follows && snapshot.check(&TokenKind::FatArrow) {
err.cancel();
- this.sess.emit_err(MissingCommaAfterMatchArm {
+ this.sess.emit_err(errors::MissingCommaAfterMatchArm {
span: hi.shrink_to_hi(),
});
return Ok(true);
fn parse_try_block(&mut self, span_lo: Span) -> PResult<'a, P<Expr>> {
let (attrs, body) = self.parse_inner_attrs_and_block()?;
if self.eat_keyword(kw::Catch) {
- Err(CatchAfterTry { span: self.prev_token.span }
+ Err(errors::CatchAfterTry { span: self.prev_token.span }
.into_diagnostic(&self.sess.span_diagnostic))
} else {
let span = span_lo.to(body.span);
let expr = self.parse_struct_expr(qself.clone(), path.clone(), true);
if let (Ok(expr), false) = (&expr, struct_allowed) {
// This is a struct literal, but we don't can't accept them here.
- self.sess.emit_err(StructLiteralNotAllowedHere {
+ self.sess.emit_err(errors::StructLiteralNotAllowedHere {
span: expr.span,
- sub: StructLiteralNotAllowedHereSugg {
+ sub: errors::StructLiteralNotAllowedHereSugg {
left: path.span.shrink_to_lo(),
right: expr.span.shrink_to_hi(),
},
let mut async_block_err = |e: &mut Diagnostic, span: Span| {
recover_async = true;
- AsyncBlockIn2015 { span }.add_to_diagnostic(e);
- HelpUseLatestEdition::new().add_to_diagnostic(e);
+ errors::AsyncBlockIn2015 { span }.add_to_diagnostic(e);
+ errors::HelpUseLatestEdition::new().add_to_diagnostic(e);
};
while self.token != token::CloseDelim(close_delim) {
if self.token != token::Comma {
return;
}
- self.sess.emit_err(CommaAfterBaseStruct {
+ self.sess.emit_err(errors::CommaAfterBaseStruct {
span: span.to(self.prev_token.span),
comma: self.token.span,
});
{
// recover from typo of `...`, suggest `..`
let span = self.prev_token.span;
- self.sess.emit_err(MissingDotDot { token_span: span, sugg_span: span });
+ self.sess.emit_err(errors::MissingDotDot { token_span: span, sugg_span: span });
return true;
}
false
return;
}
- self.sess.emit_err(EqFieldInit {
+ self.sess.emit_err(errors::EqFieldInit {
span: self.token.span,
eq: field_name.span.shrink_to_hi().to(self.token.span),
});
}
fn err_dotdotdot_syntax(&self, span: Span) {
- self.sess.emit_err(DotDotDot { span });
+ self.sess.emit_err(errors::DotDotDot { span });
}
fn err_larrow_operator(&self, span: Span) {
- self.sess.emit_err(LeftArrowOperator { span });
+ self.sess.emit_err(errors::LeftArrowOperator { span });
}
fn mk_assign_op(&self, binop: BinOp, lhs: P<Expr>, rhs: P<Expr>) -> ExprKind {
use crate::errors::{
- MultipleWhereClauses, UnexpectedSelfInGenericParameters, WhereClauseBeforeTupleStructBody,
+ MultipleWhereClauses, UnexpectedDefaultValueForLifetimeInGenericParameters,
+ UnexpectedSelfInGenericParameters, WhereClauseBeforeTupleStructBody,
WhereClauseBeforeTupleStructBodySugg,
};
} else {
(None, Vec::new())
};
+
+ if this.check_noexpect(&token::Eq)
+ && this.look_ahead(1, |t| t.is_lifetime())
+ {
+ let lo = this.token.span;
+ // Parse `= 'lifetime`.
+ this.bump(); // `=`
+ this.bump(); // `'lifetime`
+ let span = lo.to(this.prev_token.span);
+ this.sess.emit_err(
+ UnexpectedDefaultValueForLifetimeInGenericParameters { span },
+ );
+ }
+
Some(ast::GenericParam {
ident: lifetime.ident,
id: lifetime.id,
use super::{
AttrWrapper, BlockMode, FnParseMode, ForceCollect, Parser, Restrictions, SemiColonMode,
};
-use crate::errors::{
- AssignmentElseNotAllowed, CompoundAssignmentExpressionInLet, ConstLetMutuallyExclusive,
- DocCommentDoesNotDocumentAnything, ExpectedStatementAfterOuterAttr, InvalidCurlyInLetElse,
- InvalidExpressionInLetElse, InvalidIdentiferStartsWithNumber, InvalidVariableDeclaration,
- InvalidVariableDeclarationSub, WrapExpressionInParentheses,
-};
+use crate::errors;
use crate::maybe_whole;
use rustc_ast as ast;
if self.token.is_keyword(kw::Mut) && self.is_keyword_ahead(1, &[kw::Let]) {
self.bump();
let mut_let_span = lo.to(self.token.span);
- self.sess.emit_err(InvalidVariableDeclaration {
+ self.sess.emit_err(errors::InvalidVariableDeclaration {
span: mut_let_span,
- sub: InvalidVariableDeclarationSub::SwitchMutLetOrder(mut_let_span),
+ sub: errors::InvalidVariableDeclarationSub::SwitchMutLetOrder(mut_let_span),
});
}
Ok(Some(if self.token.is_keyword(kw::Let) {
self.parse_local_mk(lo, attrs, capture_semi, force_collect)?
} else if self.is_kw_followed_by_ident(kw::Mut) && self.may_recover() {
- self.recover_stmt_local_after_let(lo, attrs, InvalidVariableDeclarationSub::MissingLet)?
+ self.recover_stmt_local_after_let(
+ lo,
+ attrs,
+ errors::InvalidVariableDeclarationSub::MissingLet,
+ )?
} else if self.is_kw_followed_by_ident(kw::Auto) && self.may_recover() {
self.bump(); // `auto`
self.recover_stmt_local_after_let(
lo,
attrs,
- InvalidVariableDeclarationSub::UseLetNotAuto,
+ errors::InvalidVariableDeclarationSub::UseLetNotAuto,
)?
} else if self.is_kw_followed_by_ident(sym::var) && self.may_recover() {
self.bump(); // `var`
self.recover_stmt_local_after_let(
lo,
attrs,
- InvalidVariableDeclarationSub::UseLetNotVar,
+ errors::InvalidVariableDeclarationSub::UseLetNotVar,
)?
} else if self.check_path() && !self.token.is_qpath_start() && !self.is_path_start_item() {
// We have avoided contextual keywords like `union`, items with `crate` visibility,
let bl = self.parse_block()?;
// Destructuring assignment ... else.
// This is not allowed, but point it out in a nice way.
- self.sess.emit_err(AssignmentElseNotAllowed { span: e.span.to(bl.span) });
+ self.sess.emit_err(errors::AssignmentElseNotAllowed { span: e.span.to(bl.span) });
}
self.mk_stmt(lo.to(e.span), StmtKind::Expr(e))
} else {
&& let attrs = attrs.take_for_recovery(self.sess)
&& let attrs @ [.., last] = &*attrs {
if last.is_doc_comment() {
- self.sess.emit_err(DocCommentDoesNotDocumentAnything {
+ self.sess.emit_err(errors::DocCommentDoesNotDocumentAnything {
span: last.span,
missing_comma: None,
});
} else if attrs.iter().any(|a| a.style == AttrStyle::Outer) {
- self.sess.emit_err(ExpectedStatementAfterOuterAttr { span: last.span });
+ self.sess.emit_err(errors::ExpectedStatementAfterOuterAttr { span: last.span });
}
}
}
&mut self,
lo: Span,
attrs: AttrWrapper,
- subdiagnostic: fn(Span) -> InvalidVariableDeclarationSub,
+ subdiagnostic: fn(Span) -> errors::InvalidVariableDeclarationSub,
) -> PResult<'a, Stmt> {
let stmt =
self.collect_tokens_trailing_token(attrs, ForceCollect::Yes, |this, attrs| {
TrailingToken::None,
))
})?;
- self.sess.emit_err(InvalidVariableDeclaration { span: lo, sub: subdiagnostic(lo) });
+ self.sess.emit_err(errors::InvalidVariableDeclaration { span: lo, sub: subdiagnostic(lo) });
Ok(stmt)
}
let lo = self.prev_token.span;
if self.token.is_keyword(kw::Const) && self.look_ahead(1, |t| t.is_ident()) {
- self.sess.emit_err(ConstLetMutuallyExclusive { span: lo.to(self.token.span) });
+ self.sess.emit_err(errors::ConstLetMutuallyExclusive { span: lo.to(self.token.span) });
self.bump();
}
rustc_ast::MetaItemLit::from_token(&self.token).is_none() &&
(lit.kind == token::LitKind::Integer || lit.kind == token::LitKind::Float) &&
self.look_ahead(1, |t| matches!(t.kind, token::Eq) || matches!(t.kind, token::Colon ) ) {
- return Err(self.sess.create_err(InvalidIdentiferStartsWithNumber { span: self.token.span }));
+ return Err(self.sess.create_err(errors::InvalidIdentiferStartsWithNumber { span: self.token.span }));
}
Ok(())
}
fn check_let_else_init_bool_expr(&self, init: &ast::Expr) {
if let ast::ExprKind::Binary(op, ..) = init.kind {
if op.node.lazy() {
- self.sess.emit_err(InvalidExpressionInLetElse {
+ self.sess.emit_err(errors::InvalidExpressionInLetElse {
span: init.span,
operator: op.node.to_string(),
- sugg: WrapExpressionInParentheses {
+ sugg: errors::WrapExpressionInParentheses {
left: init.span.shrink_to_lo(),
right: init.span.shrink_to_hi(),
},
fn check_let_else_init_trailing_brace(&self, init: &ast::Expr) {
if let Some(trailing) = classify::expr_trailing_brace(init) {
- self.sess.emit_err(InvalidCurlyInLetElse {
+ self.sess.emit_err(errors::InvalidCurlyInLetElse {
span: trailing.span.with_lo(trailing.span.hi() - BytePos(1)),
- sugg: WrapExpressionInParentheses {
+ sugg: errors::WrapExpressionInParentheses {
left: trailing.span.shrink_to_lo(),
right: trailing.span.shrink_to_hi(),
},
let eq_consumed = match self.token.kind {
token::BinOpEq(..) => {
// Recover `let x <op>= 1` as `let x = 1`
- self.sess.emit_err(CompoundAssignmentExpressionInLet { span: self.token.span });
+ self.sess
+ .emit_err(errors::CompoundAssignmentExpressionInLet { span: self.token.span });
self.bump();
true
}
//! conflicts between multiple such attributes attached to the same
//! item.
-use crate::errors::{
- self, AttrApplication, DebugVisualizerUnreadable, InvalidAttrAtCrateLevel, ObjectLifetimeErr,
- OnlyHasEffectOn, ProcMacroDiffArguments, ProcMacroInvalidAbi, ProcMacroMissingArguments,
- ProcMacroTypeError, ProcMacroUnsafe, TransparentIncompatible, UnrecognizedReprHint,
-};
+use crate::errors;
use rustc_ast::{ast, AttrStyle, Attribute, LitKind, MetaItemKind, MetaItemLit, NestedMetaItem};
use rustc_data_structures::fx::FxHashMap;
use rustc_errors::{fluent, Applicability, IntoDiagnosticArg, MultiSpan};
UNUSED_ATTRIBUTES,
hir_id,
attr.span,
- OnlyHasEffectOn {
+ errors::OnlyHasEffectOn {
attr_name: attr.name_or_empty(),
target_name: allowed_target.name().replace(' ', "_"),
},
ObjectLifetimeDefault::Param(def_id) => tcx.item_name(def_id).to_string(),
ObjectLifetimeDefault::Ambiguous => "Ambiguous".to_owned(),
};
- tcx.sess.emit_err(ObjectLifetimeErr { span: p.span, repr });
+ tcx.sess.emit_err(errors::ObjectLifetimeErr { span: p.span, repr });
}
}
}
match target {
Target::Struct | Target::Union | Target::Enum => continue,
_ => {
- self.tcx.sess.emit_err(AttrApplication::StructEnumUnion {
+ self.tcx.sess.emit_err(errors::AttrApplication::StructEnumUnion {
hint_span: hint.span(),
span,
});
match target {
Target::Struct | Target::Union | Target::Enum | Target::Fn => continue,
_ => {
- self.tcx.sess.emit_err(AttrApplication::StructEnumFunctionUnion {
- hint_span: hint.span(),
- span,
- });
+ self.tcx.sess.emit_err(
+ errors::AttrApplication::StructEnumFunctionUnion {
+ hint_span: hint.span(),
+ span,
+ },
+ );
}
}
}
sym::packed => {
if target != Target::Struct && target != Target::Union {
- self.tcx.sess.emit_err(AttrApplication::StructUnion {
+ self.tcx.sess.emit_err(errors::AttrApplication::StructUnion {
hint_span: hint.span(),
span,
});
sym::simd => {
is_simd = true;
if target != Target::Struct {
- self.tcx
- .sess
- .emit_err(AttrApplication::Struct { hint_span: hint.span(), span });
+ self.tcx.sess.emit_err(errors::AttrApplication::Struct {
+ hint_span: hint.span(),
+ span,
+ });
} else {
continue;
}
match target {
Target::Struct | Target::Union | Target::Enum => continue,
_ => {
- self.tcx.sess.emit_err(AttrApplication::StructEnumUnion {
+ self.tcx.sess.emit_err(errors::AttrApplication::StructEnumUnion {
hint_span: hint.span(),
span,
});
| sym::usize => {
int_reprs += 1;
if target != Target::Enum {
- self.tcx
- .sess
- .emit_err(AttrApplication::Enum { hint_span: hint.span(), span });
+ self.tcx.sess.emit_err(errors::AttrApplication::Enum {
+ hint_span: hint.span(),
+ span,
+ });
} else {
continue;
}
}
_ => {
- self.tcx.sess.emit_err(UnrecognizedReprHint { span: hint.span() });
+ self.tcx.sess.emit_err(errors::UnrecognizedReprHint { span: hint.span() });
continue;
}
};
// Error on repr(transparent, <anything else>).
if is_transparent && hints.len() > 1 {
let hint_spans: Vec<_> = hint_spans.clone().collect();
- self.tcx
- .sess
- .emit_err(TransparentIncompatible { hint_spans, target: target.to_string() });
+ self.tcx.sess.emit_err(errors::TransparentIncompatible {
+ hint_spans,
+ target: target.to_string(),
+ });
}
// Warn on repr(u8, u16), repr(C, simd), and c-like-enum-repr(C, u8)
if (int_reprs > 1)
match std::fs::File::open(&file) {
Ok(_) => true,
Err(error) => {
- self.tcx.sess.emit_err(DebugVisualizerUnreadable {
+ self.tcx.sess.emit_err(errors::DebugVisualizerUnreadable {
span: meta_item.span,
file: &file,
error,
let drcx = DeepRejectCtxt { treat_obligation_params: TreatParams::AsInfer };
if sig.abi != Abi::Rust {
- tcx.sess.emit_err(ProcMacroInvalidAbi { span: hir_sig.span, abi: sig.abi.name() });
+ tcx.sess.emit_err(errors::ProcMacroInvalidAbi {
+ span: hir_sig.span,
+ abi: sig.abi.name(),
+ });
self.abort.set(true);
}
if sig.unsafety == Unsafety::Unsafe {
- tcx.sess.emit_err(ProcMacroUnsafe { span: hir_sig.span });
+ tcx.sess.emit_err(errors::ProcMacroUnsafe { span: hir_sig.span });
self.abort.set(true);
}
// Typecheck the output
if !drcx.types_may_unify(output, tokenstream) {
- tcx.sess.emit_err(ProcMacroTypeError {
+ tcx.sess.emit_err(errors::ProcMacroTypeError {
span: hir_sig.decl.output.span(),
found: output,
kind,
}
if sig.inputs().len() < expected_input_count {
- tcx.sess.emit_err(ProcMacroMissingArguments {
+ tcx.sess.emit_err(errors::ProcMacroMissingArguments {
expected_input_count,
span: hir_sig.span,
kind,
sig.inputs().iter().zip(hir_sig.decl.inputs).take(expected_input_count)
{
if !drcx.types_may_unify(*arg, tokenstream) {
- tcx.sess.emit_err(ProcMacroTypeError {
+ tcx.sess.emit_err(errors::ProcMacroTypeError {
span: input.span,
found: *arg,
kind,
let body_id = tcx.hir().body_owned_by(id.def_id);
let excess = tcx.hir().body(body_id).params.get(expected_input_count..);
if let Some(excess @ [begin @ end] | excess @ [begin, .., end]) = excess {
- tcx.sess.emit_err(ProcMacroDiffArguments {
+ tcx.sess.emit_err(errors::ProcMacroDiffArguments {
span: begin.span.to(end.span),
count: excess.len(),
kind,
if attr.style == AttrStyle::Inner {
for attr_to_check in ATTRS_TO_CHECK {
if attr.has_name(*attr_to_check) {
- tcx.sess.emit_err(InvalidAttrAtCrateLevel {
+ tcx.sess.emit_err(errors::InvalidAttrAtCrateLevel {
span: attr.span,
snippet: tcx.sess.source_map().span_to_snippet(attr.span).ok(),
name: *attr_to_check,
//! A pass that annotates every item and method with its stability level,
//! propagating default levels lexically from parent to children ast nodes.
-use crate::errors::{
- self, CannotStabilizeDeprecated, DeprecatedAttribute, DuplicateFeatureErr,
- FeatureOnlyOnNightly, ImpliedFeatureNotExist, InvalidDeprecationVersion, InvalidStability,
- MissingConstErr, MissingConstStabAttr, MissingStabilityAttr, TraitImplConstStable,
- UnknownFeature, UselessStability,
-};
+use crate::errors;
use rustc_attr::{
self as attr, rust_version_symbol, ConstStability, Stability, StabilityLevel, Unstable,
UnstableReason, VERSION_PLACEHOLDER,
{
self.tcx
.sess
- .emit_err(MissingConstErr { fn_sig_span: fn_sig.span, const_span });
+ .emit_err(errors::MissingConstErr { fn_sig_span: fn_sig.span, const_span });
}
}
}
if let Some((rustc_attr::Deprecation { is_since_rustc_version: true, .. }, span)) = &depr {
if stab.is_none() {
- self.tcx.sess.emit_err(DeprecatedAttribute { span: *span });
+ self.tcx.sess.emit_err(errors::DeprecatedAttribute { span: *span });
}
}
if kind == AnnotationKind::Prohibited
|| (kind == AnnotationKind::Container && stab.level.is_stable() && is_deprecated)
{
- self.tcx.sess.emit_err(UselessStability { span, item_sp });
+ self.tcx.sess.emit_err(errors::UselessStability { span, item_sp });
}
debug!("annotate: found {:?}", stab);
{
match stab_v.parse::<u64>() {
Err(_) => {
- self.tcx.sess.emit_err(InvalidStability { span, item_sp });
+ self.tcx.sess.emit_err(errors::InvalidStability { span, item_sp });
break;
}
Ok(stab_vp) => match dep_v.parse::<u64>() {
Ok(dep_vp) => match dep_vp.cmp(&stab_vp) {
Ordering::Less => {
- self.tcx
- .sess
- .emit_err(CannotStabilizeDeprecated { span, item_sp });
+ self.tcx.sess.emit_err(errors::CannotStabilizeDeprecated {
+ span,
+ item_sp,
+ });
break;
}
Ordering::Equal => continue,
},
Err(_) => {
if dep_v != "TBD" {
- self.tcx
- .sess
- .emit_err(InvalidDeprecationVersion { span, item_sp });
+ self.tcx.sess.emit_err(errors::InvalidDeprecationVersion {
+ span,
+ item_sp,
+ });
}
break;
}
&& self.effective_visibilities.is_reachable(def_id)
{
let descr = self.tcx.def_kind(def_id).descr(def_id.to_def_id());
- self.tcx.sess.emit_err(MissingStabilityAttr { span, descr });
+ self.tcx.sess.emit_err(errors::MissingStabilityAttr { span, descr });
}
}
if is_const && is_stable && missing_const_stability_attribute && is_reachable {
let descr = self.tcx.def_kind(def_id).descr(def_id.to_def_id());
- self.tcx.sess.emit_err(MissingConstStabAttr { span, descr });
+ self.tcx.sess.emit_err(errors::MissingConstStabAttr { span, descr });
}
}
}
&& *constness == hir::Constness::Const
&& const_stab.map_or(false, |(stab, _)| stab.is_const_stable())
{
- self.tcx.sess.emit_err(TraitImplConstStable { span: item.span });
+ self.tcx.sess.emit_err(errors::TraitImplConstStable { span: item.span });
}
}
}
if !lang_features.insert(feature) {
// Warn if the user enables a lang feature multiple times.
- tcx.sess.emit_err(DuplicateFeatureErr { span, feature });
+ tcx.sess.emit_err(errors::DuplicateFeatureErr { span, feature });
}
}
let mut remaining_lib_features = FxIndexMap::default();
for (feature, span) in declared_lib_features {
if !tcx.sess.opts.unstable_features.is_nightly_build() {
- tcx.sess.emit_err(FeatureOnlyOnNightly {
+ tcx.sess.emit_err(errors::FeatureOnlyOnNightly {
span: *span,
release_channel: env!("CFG_RELEASE_CHANNEL"),
});
}
if remaining_lib_features.contains_key(&feature) {
// Warn if the user enables a lib feature multiple times.
- tcx.sess.emit_err(DuplicateFeatureErr { span: *span, feature: *feature });
+ tcx.sess.emit_err(errors::DuplicateFeatureErr { span: *span, feature: *feature });
}
remaining_lib_features.insert(feature, *span);
}
}
for (feature, span) in remaining_lib_features {
- tcx.sess.emit_err(UnknownFeature { span, feature: *feature });
+ tcx.sess.emit_err(errors::UnknownFeature { span, feature: *feature });
}
for (implied_by, feature) in remaining_implications {
.map(|(_, span)| span)
.or_else(|| local_defined_features.unstable.get(&feature))
.expect("feature that implied another does not exist");
- tcx.sess.emit_err(ImpliedFeatureNotExist { span, feature, implied_by });
+ tcx.sess.emit_err(errors::ImpliedFeatureNotExist { span, feature, implied_by });
}
// FIXME(#44232): the `used_features` table no longer exists, so we
pub trait CacheSelector<'tcx, V> {
type Cache
where
- V: Clone;
+ V: Copy;
type ArenaCache;
}
pub trait QueryStorage {
type Value: Debug;
- type Stored: Clone;
+ type Stored: Copy;
/// Store a value without putting it in the cache.
/// This is meant to be used with cycle errors.
/// It returns the shard index and a lock guard to the shard,
/// which will be used if the query is not in the cache and we need
/// to compute it.
- fn lookup<R, OnHit>(
- &self,
- key: &Self::Key,
- // `on_hit` can be called while holding a lock to the query state shard.
- on_hit: OnHit,
- ) -> Result<R, ()>
- where
- OnHit: FnOnce(&Self::Stored, DepNodeIndex) -> R;
+ fn lookup(&self, key: &Self::Key) -> Option<(Self::Stored, DepNodeIndex)>;
fn complete(&self, key: Self::Key, value: Self::Value, index: DepNodeIndex) -> Self::Stored;
impl<'tcx, K: Eq + Hash, V: 'tcx> CacheSelector<'tcx, V> for DefaultCacheSelector<K> {
type Cache = DefaultCache<K, V>
where
- V: Clone;
+ V: Copy;
type ArenaCache = ArenaCache<'tcx, K, V>;
}
}
}
-impl<K: Eq + Hash, V: Clone + Debug> QueryStorage for DefaultCache<K, V> {
+impl<K: Eq + Hash, V: Copy + Debug> QueryStorage for DefaultCache<K, V> {
type Value = V;
type Stored = V;
impl<K, V> QueryCache for DefaultCache<K, V>
where
K: Eq + Hash + Clone + Debug,
- V: Clone + Debug,
+ V: Copy + Debug,
{
type Key = K;
#[inline(always)]
- fn lookup<R, OnHit>(&self, key: &K, on_hit: OnHit) -> Result<R, ()>
- where
- OnHit: FnOnce(&V, DepNodeIndex) -> R,
- {
+ fn lookup(&self, key: &K) -> Option<(V, DepNodeIndex)> {
let key_hash = sharded::make_hash(key);
#[cfg(parallel_compiler)]
let lock = self.cache.get_shard_by_hash(key_hash).lock();
let lock = self.cache.lock();
let result = lock.raw_entry().from_key_hashed_nocheck(key_hash, key);
- if let Some((_, value)) = result {
- let hit_result = on_hit(&value.0, value.1);
- Ok(hit_result)
- } else {
- Err(())
- }
+ if let Some((_, value)) = result { Some(*value) } else { None }
}
#[inline]
type Key = K;
#[inline(always)]
- fn lookup<R, OnHit>(&self, key: &K, on_hit: OnHit) -> Result<R, ()>
- where
- OnHit: FnOnce(&&'tcx V, DepNodeIndex) -> R,
- {
+ fn lookup(&self, key: &K) -> Option<(&'tcx V, DepNodeIndex)> {
let key_hash = sharded::make_hash(key);
#[cfg(parallel_compiler)]
let lock = self.cache.get_shard_by_hash(key_hash).lock();
let lock = self.cache.lock();
let result = lock.raw_entry().from_key_hashed_nocheck(key_hash, key);
- if let Some((_, value)) = result {
- let hit_result = on_hit(&&value.0, value.1);
- Ok(hit_result)
- } else {
- Err(())
- }
+ if let Some((_, value)) = result { Some((&value.0, value.1)) } else { None }
}
#[inline]
impl<'tcx, K: Idx, V: 'tcx> CacheSelector<'tcx, V> for VecCacheSelector<K> {
type Cache = VecCache<K, V>
where
- V: Clone;
+ V: Copy;
type ArenaCache = VecArenaCache<'tcx, K, V>;
}
}
}
-impl<K: Eq + Idx, V: Clone + Debug> QueryStorage for VecCache<K, V> {
+impl<K: Eq + Idx, V: Copy + Debug> QueryStorage for VecCache<K, V> {
type Value = V;
type Stored = V;
impl<K, V> QueryCache for VecCache<K, V>
where
K: Eq + Idx + Clone + Debug,
- V: Clone + Debug,
+ V: Copy + Debug,
{
type Key = K;
#[inline(always)]
- fn lookup<R, OnHit>(&self, key: &K, on_hit: OnHit) -> Result<R, ()>
- where
- OnHit: FnOnce(&V, DepNodeIndex) -> R,
- {
+ fn lookup(&self, key: &K) -> Option<(V, DepNodeIndex)> {
#[cfg(parallel_compiler)]
let lock = self.cache.get_shard_by_hash(key.index() as u64).lock();
#[cfg(not(parallel_compiler))]
let lock = self.cache.lock();
- if let Some(Some(value)) = lock.get(*key) {
- let hit_result = on_hit(&value.0, value.1);
- Ok(hit_result)
- } else {
- Err(())
- }
+ if let Some(Some(value)) = lock.get(*key) { Some(*value) } else { None }
}
#[inline]
type Key = K;
#[inline(always)]
- fn lookup<R, OnHit>(&self, key: &K, on_hit: OnHit) -> Result<R, ()>
- where
- OnHit: FnOnce(&&'tcx V, DepNodeIndex) -> R,
- {
+ fn lookup(&self, key: &K) -> Option<(&'tcx V, DepNodeIndex)> {
#[cfg(parallel_compiler)]
let lock = self.cache.get_shard_by_hash(key.index() as u64).lock();
#[cfg(not(parallel_compiler))]
let lock = self.cache.lock();
- if let Some(Some(value)) = lock.get(*key) {
- let hit_result = on_hit(&&value.0, value.1);
- Ok(hit_result)
- } else {
- Err(())
- }
+ if let Some(Some(value)) = lock.get(*key) { Some((&value.0, value.1)) } else { None }
}
#[inline]
type Key: DepNodeParams<Qcx::DepContext> + Eq + Hash + Clone + Debug;
type Value: Debug;
- type Stored: Debug + Clone + std::borrow::Borrow<Self::Value>;
+ type Stored: Debug + Copy + std::borrow::Borrow<Self::Value>;
type Cache: QueryCache<Key = Self::Key, Stored = Self::Stored, Value = Self::Value>;
where
Qcx: QueryContext + crate::query::HasDepContext<DepKind = D>,
V: std::fmt::Debug + Value<Qcx::DepContext, Qcx::DepKind>,
- R: Clone,
+ R: Copy,
{
let error = report_cycle(qcx.dep_context().sess(), &cycle_error);
let value = handle_cycle_error(*qcx.dep_context(), &cycle_error, error, handler);
/// which will be used if the query is not in the cache and we need
/// to compute it.
#[inline]
-pub fn try_get_cached<Tcx, C, R, OnHit>(
- tcx: Tcx,
- cache: &C,
- key: &C::Key,
- // `on_hit` can be called while holding a lock to the query cache
- on_hit: OnHit,
-) -> Result<R, ()>
+pub fn try_get_cached<Tcx, C>(tcx: Tcx, cache: &C, key: &C::Key) -> Option<C::Stored>
where
C: QueryCache,
Tcx: DepContext,
- OnHit: FnOnce(&C::Stored) -> R,
{
- cache.lookup(&key, |value, index| {
- if std::intrinsics::unlikely(tcx.profiler().enabled()) {
- tcx.profiler().query_cache_hit(index.into());
+ match cache.lookup(&key) {
+ Some((value, index)) => {
+ if std::intrinsics::unlikely(tcx.profiler().enabled()) {
+ tcx.profiler().query_cache_hit(index.into());
+ }
+ tcx.dep_graph().read_index(index);
+ Some(value)
}
- tcx.dep_graph().read_index(index);
- on_hit(value)
- })
+ None => None,
+ }
}
fn try_execute_query<Q, Qcx>(
if Q::FEEDABLE {
// We may have put a value inside the cache from inside the execution.
// Verify that it has the same hash as what we have now, to ensure consistency.
- let _ = cache.lookup(&key, |cached_result, _| {
+ if let Some((cached_result, _)) = cache.lookup(&key) {
let hasher = Q::HASH_RESULT.expect("feedable forbids no_hash");
- let old_hash = qcx.dep_context().with_stable_hashing_context(|mut hcx| hasher(&mut hcx, cached_result.borrow()));
- let new_hash = qcx.dep_context().with_stable_hashing_context(|mut hcx| hasher(&mut hcx, &result));
+ let old_hash = qcx.dep_context().with_stable_hashing_context(|mut hcx| {
+ hasher(&mut hcx, cached_result.borrow())
+ });
+ let new_hash = qcx
+ .dep_context()
+ .with_stable_hashing_context(|mut hcx| hasher(&mut hcx, &result));
debug_assert_eq!(
- old_hash, new_hash,
+ old_hash,
+ new_hash,
"Computed query value for {:?}({:?}) is inconsistent with fed value,\ncomputed={:#?}\nfed={:#?}",
- Q::DEP_KIND, key, result, cached_result,
+ Q::DEP_KIND,
+ key,
+ result,
+ cached_result,
);
- });
+ }
}
let result = job.complete(cache, result, dep_node_index);
(result, Some(dep_node_index))
}
#[cfg(parallel_compiler)]
TryGetJob::JobCompleted(query_blocked_prof_timer) => {
- let (v, index) = cache
- .lookup(&key, |value, index| (value.clone(), index))
- .unwrap_or_else(|_| panic!("value must be in cache after waiting"));
+ let Some((v, index)) = cache.lookup(&key) else {
+ panic!("value must be in cache after waiting")
+ };
if std::intrinsics::unlikely(qcx.dep_context().profiler().enabled()) {
qcx.dep_context().profiler().query_cache_hit(index.into());
// We may be concurrently trying both execute and force a query.
// Ensure that only one of them runs the query.
let cache = Q::query_cache(qcx);
- let cached = cache.lookup(&key, |_, index| {
+ if let Some((_, index)) = cache.lookup(&key) {
if std::intrinsics::unlikely(qcx.dep_context().profiler().enabled()) {
qcx.dep_context().profiler().query_cache_hit(index.into());
}
- });
-
- match cached {
- Ok(()) => return,
- Err(()) => {}
+ return;
}
let state = Q::query_state(qcx);
pub use crate::code_stats::{DataTypeKind, FieldInfo, FieldKind, SizeKind, VariantInfo};
use crate::config::Input;
use crate::config::{self, CrateType, InstrumentCoverage, OptLevel, OutputType, SwitchWithOptPath};
-use crate::errors::{
- BranchProtectionRequiresAArch64, CannotEnableCrtStaticLinux, CannotMixAndMatchSanitizers,
- LinkerPluginToWindowsNotSupported, NotCircumventFeature, OptimisationFuelExhausted,
- ProfileSampleUseFileDoesNotExist, ProfileUseFileDoesNotExist, SanitizerCfiEnabled,
- SanitizerNotSupported, SanitizersNotSupported, SkippingConstChecks,
- SplitDebugInfoUnstablePlatform, StackProtectorNotSupportedForTarget,
- TargetRequiresUnwindTables, UnleashedFeatureHelp, UnstableVirtualFunctionElimination,
- UnsupportedDwarfVersion,
-};
+use crate::errors;
use crate::parse::{add_feature_diagnostics, ParseSess};
use crate::search_paths::{PathKind, SearchPath};
use crate::{filesearch, lint};
if !unleashed_features.is_empty() {
let mut must_err = false;
// Create a diagnostic pointing at where things got unleashed.
- self.emit_warning(SkippingConstChecks {
+ self.emit_warning(errors::SkippingConstChecks {
unleashed_features: unleashed_features
.iter()
.map(|(span, gate)| {
gate.map(|gate| {
must_err = true;
- UnleashedFeatureHelp::Named { span: *span, gate }
+ errors::UnleashedFeatureHelp::Named { span: *span, gate }
})
- .unwrap_or(UnleashedFeatureHelp::Unnamed { span: *span })
+ .unwrap_or(errors::UnleashedFeatureHelp::Unnamed { span: *span })
})
.collect(),
});
// If we should err, make sure we did.
if must_err && self.has_errors().is_none() {
// We have skipped a feature gate, and not run into other errors... reject.
- self.emit_err(NotCircumventFeature);
+ self.emit_err(errors::NotCircumventFeature);
}
}
}
// We only call `msg` in case we can actually emit warnings.
// Otherwise, this could cause a `delay_good_path_bug` to
// trigger (issue #79546).
- self.emit_warning(OptimisationFuelExhausted { msg: msg() });
+ self.emit_warning(errors::OptimisationFuelExhausted { msg: msg() });
}
fuel.out_of_fuel = true;
} else if fuel.remaining > 0 {
&& sess.opts.cg.prefer_dynamic
&& sess.target.is_like_windows
{
- sess.emit_err(LinkerPluginToWindowsNotSupported);
+ sess.emit_err(errors::LinkerPluginToWindowsNotSupported);
}
// Make sure that any given profiling data actually exists so LLVM can't
// decide to silently skip PGO.
if let Some(ref path) = sess.opts.cg.profile_use {
if !path.exists() {
- sess.emit_err(ProfileUseFileDoesNotExist { path });
+ sess.emit_err(errors::ProfileUseFileDoesNotExist { path });
}
}
// Do the same for sample profile data.
if let Some(ref path) = sess.opts.unstable_opts.profile_sample_use {
if !path.exists() {
- sess.emit_err(ProfileSampleUseFileDoesNotExist { path });
+ sess.emit_err(errors::ProfileSampleUseFileDoesNotExist { path });
}
}
// Unwind tables cannot be disabled if the target requires them.
if let Some(include_uwtables) = sess.opts.cg.force_unwind_tables {
if sess.target.requires_uwtable && !include_uwtables {
- sess.emit_err(TargetRequiresUnwindTables);
+ sess.emit_err(errors::TargetRequiresUnwindTables);
}
}
match unsupported_sanitizers.into_iter().count() {
0 => {}
1 => {
- sess.emit_err(SanitizerNotSupported { us: unsupported_sanitizers.to_string() });
+ sess.emit_err(errors::SanitizerNotSupported { us: unsupported_sanitizers.to_string() });
}
_ => {
- sess.emit_err(SanitizersNotSupported { us: unsupported_sanitizers.to_string() });
+ sess.emit_err(errors::SanitizersNotSupported {
+ us: unsupported_sanitizers.to_string(),
+ });
}
}
// Cannot mix and match sanitizers.
let mut sanitizer_iter = sess.opts.unstable_opts.sanitizer.into_iter();
if let (Some(first), Some(second)) = (sanitizer_iter.next(), sanitizer_iter.next()) {
- sess.emit_err(CannotMixAndMatchSanitizers {
+ sess.emit_err(errors::CannotMixAndMatchSanitizers {
first: first.to_string(),
second: second.to_string(),
});
// Cannot enable crt-static with sanitizers on Linux
if sess.crt_static(None) && !sess.opts.unstable_opts.sanitizer.is_empty() {
- sess.emit_err(CannotEnableCrtStaticLinux);
+ sess.emit_err(errors::CannotEnableCrtStaticLinux);
}
// LLVM CFI and VFE both require LTO.
if sess.lto() != config::Lto::Fat {
if sess.is_sanitizer_cfi_enabled() {
- sess.emit_err(SanitizerCfiEnabled);
+ sess.emit_err(errors::SanitizerCfiEnabled);
}
if sess.opts.unstable_opts.virtual_function_elimination {
- sess.emit_err(UnstableVirtualFunctionElimination);
+ sess.emit_err(errors::UnstableVirtualFunctionElimination);
}
}
// LLVM CFI and KCFI are mutually exclusive
if sess.is_sanitizer_cfi_enabled() && sess.is_sanitizer_kcfi_enabled() {
- sess.emit_err(CannotMixAndMatchSanitizers {
+ sess.emit_err(errors::CannotMixAndMatchSanitizers {
first: "cfi".to_string(),
second: "kcfi".to_string(),
});
if sess.opts.unstable_opts.stack_protector != StackProtector::None {
if !sess.target.options.supports_stack_protector {
- sess.emit_warning(StackProtectorNotSupportedForTarget {
+ sess.emit_warning(errors::StackProtectorNotSupportedForTarget {
stack_protector: sess.opts.unstable_opts.stack_protector,
target_triple: &sess.opts.target_triple,
});
}
if sess.opts.unstable_opts.branch_protection.is_some() && sess.target.arch != "aarch64" {
- sess.emit_err(BranchProtectionRequiresAArch64);
+ sess.emit_err(errors::BranchProtectionRequiresAArch64);
}
if let Some(dwarf_version) = sess.opts.unstable_opts.dwarf_version {
if dwarf_version > 5 {
- sess.emit_err(UnsupportedDwarfVersion { dwarf_version });
+ sess.emit_err(errors::UnsupportedDwarfVersion { dwarf_version });
}
}
if !sess.target.options.supported_split_debuginfo.contains(&sess.split_debuginfo())
&& !sess.opts.unstable_opts.unstable_options
{
- sess.emit_err(SplitDebugInfoUnstablePlatform { debuginfo: sess.split_debuginfo() });
+ sess.emit_err(errors::SplitDebugInfoUnstablePlatform { debuginfo: sess.split_debuginfo() });
}
}
///
/// The hash map will be able to hold at least `capacity` elements without
/// reallocating. This method is allowed to allocate for more elements than
- /// `capacity`. If `capacity` is 0, the hash set will not allocate.
+ /// `capacity`. If `capacity` is 0, the hash map will not allocate.
///
/// # Examples
///
is bootstrapped and in general, some of the technical details of the build
system.
-## Using rustbuild
+Note that this README only covers internal information, not how to use the tool.
+Please check [bootstrapping dev guide][bootstrapping-dev-guide] for further information.
-The rustbuild build system has a primary entry point, a top level `x.py` script:
+[bootstrapping-dev-guide]: https://rustc-dev-guide.rust-lang.org/building/bootstrapping.html
-```sh
-$ python ./x.py build
-```
-
-Note that if you're on Unix, you should be able to execute the script directly:
-
-```sh
-$ ./x.py build
-```
-
-The script accepts commands, flags, and arguments to determine what to do:
-
-* `build` - a general purpose command for compiling code. Alone, `build` will
- bootstrap the entire compiler, and otherwise, arguments passed indicate what to
- build. For example:
-
- ```
- # build the whole compiler
- ./x.py build --stage 2
-
- # build the stage1 compiler
- ./x.py build
-
- # build stage0 libstd
- ./x.py build --stage 0 library/std
-
- # build a particular crate in stage0
- ./x.py build --stage 0 library/test
- ```
-
- If files that would normally be rebuilt from stage 0 are dirty, the rebuild can be
- overridden using `--keep-stage 0`. Using `--keep-stage n` will skip all steps
- that belong to stage n or earlier:
-
- ```
- # build stage 1, keeping old build products for stage 0
- ./x.py build --keep-stage 0
- ```
-
-* `test` - a command for executing unit tests. Like the `build` command, this
- will execute the entire test suite by default, and otherwise, it can be used to
- select which test suite is run:
-
- ```
- # run all unit tests
- ./x.py test
-
- # execute tool tests
- ./x.py test tidy
-
- # execute the UI test suite
- ./x.py test tests/ui
-
- # execute only some tests in the UI test suite
- ./x.py test tests/ui --test-args substring-of-test-name
-
- # execute tests in the standard library in stage0
- ./x.py test --stage 0 library/std
-
- # execute tests in the core and standard library in stage0,
- # without running doc tests (thus avoid depending on building the compiler)
- ./x.py test --stage 0 --no-doc library/core library/std
+## Introduction
- # execute all doc tests
- ./x.py test src/doc
- ```
+The build system defers most of the complicated logic managing invocations
+of rustc and rustdoc to Cargo itself. However, moving through various stages
+and copying artifacts is still necessary for it to do. Each time rustbuild
+is invoked, it will iterate through the list of predefined steps and execute
+each serially in turn if it matches the paths passed or is a default rule.
+For each step rustbuild relies on the step internally being incremental and
+parallel. Note, though, that the `-j` parameter to rustbuild gets forwarded
+to appropriate test harnesses and such.
-* `doc` - a command for building documentation. Like above, can take arguments
- for what to document.
-
-## Configuring rustbuild
-
-rustbuild offers a TOML-based configuration system with a `config.toml`
-file. An example of this configuration can be found at `config.toml.example`,
-and the configuration file can also be passed as `--config path/to/config.toml`
-if the build system is being invoked manually (via the python script).
-
-You can generate a config.toml using `./configure` options if you want to automate creating the file without having to edit it.
-
-Finally, rustbuild makes use of the [cc-rs crate] which has [its own
-method][env-vars] of configuring C compilers and C flags via environment
-variables.
-
-[cc-rs crate]: https://github.com/alexcrichton/cc-rs
-[env-vars]: https://github.com/alexcrichton/cc-rs#external-configuration-via-environment-variables
-
-## Build stages
+## Build phases
The rustbuild build system goes through a few phases to actually build the
compiler. What actually happens when you invoke rustbuild is:
-1. The entry point script, `x.py` is run. This script is
- responsible for downloading the stage0 compiler/Cargo binaries, and it then
- compiles the build system itself (this folder). Finally, it then invokes the
- actual `bootstrap` binary build system.
+1. The entry point script(`x` for unix like systems, `x.ps1` for windows systems,
+ `x.py` cross-platform) is run. This script is responsible for downloading the stage0
+ compiler/Cargo binaries, and it then compiles the build system itself (this folder).
+ Finally, it then invokes the actual `bootstrap` binary build system.
2. In Rust, `bootstrap` will slurp up all configuration, perform a number of
sanity checks (whether compilers exist, for example), and then start building the
stage0 artifacts.
The goal of each stage is to (a) leverage Cargo as much as possible and failing
that (b) leverage Rust as much as possible!
-## Incremental builds
-
-You can configure rustbuild to use incremental compilation with the
-`--incremental` flag:
-
-```sh
-$ ./x.py build --incremental
-```
-
-The `--incremental` flag will store incremental compilation artifacts
-in `build/<host>/stage0-incremental`. Note that we only use incremental
-compilation for the stage0 -> stage1 compilation -- this is because
-the stage1 compiler is changing, and we don't try to cache and reuse
-incremental artifacts across different versions of the compiler.
-
-You can always drop the `--incremental` to build as normal (but you
-will still be using the local nightly as your bootstrap).
-
## Directory Layout
This build system houses all output under the `build` directory, which looks
# system will link (using hard links) output from stageN-{std,rustc} into
# each of these directories.
#
- # In theory, there is no extra build output in these directories.
+ # In theory these are working rustc sysroot directories, meaning there is
+ # no extra build output in these directories.
stage1/
stage2/
stage3/
```
-## Cargo projects
-
-The current build is unfortunately not quite as simple as `cargo build` in a
-directory, but rather the compiler is split into three different Cargo projects:
-
-* `library/std` - the standard library
-* `library/test` - testing support, depends on libstd
-* `compiler/rustc` - the actual compiler itself
-
-Each "project" has a corresponding Cargo.lock file with all dependencies, and
-this means that building the compiler involves running Cargo three times. The
-structure here serves two goals:
-
-1. Facilitating dependencies coming from crates.io. These dependencies don't
- depend on `std`, so libstd is a separate project compiled ahead of time
- before the actual compiler builds.
-2. Splitting "host artifacts" from "target artifacts". That is, when building
- code for an arbitrary target, you don't need the entire compiler, but you'll
- end up needing libraries like libtest that depend on std but also want to use
- crates.io dependencies. Hence, libtest is split out as its own project that
- is sequenced after `std` but before `rustc`. This project is built for all
- targets.
-
-There is some loss in build parallelism here because libtest can be compiled in
-parallel with a number of rustc artifacts, but in theory, the loss isn't too bad!
-
-## Build tools
-
-We've actually got quite a few tools that we use in the compiler's build system
-and for testing. To organize these, each tool is a project in `src/tools` with a
-corresponding `Cargo.toml`. All tools are compiled with Cargo (currently having
-independent `Cargo.lock` files) and do not currently explicitly depend on the
-compiler or standard library. Compiling each tool is sequenced after the
-appropriate libstd/libtest/librustc compile above.
-
## Extending rustbuild
-So, you'd like to add a feature to the rustbuild build system or just fix a bug.
-Great! One of the major motivational factors for moving away from `make` is that
-Rust is in theory much easier to read, modify, and write. If you find anything
-excessively confusing, please open an issue on this, and we'll try to get it
-documented or simplified, pronto.
+When you use the bootstrap system, you'll call it through the entry point script
+(`x`, `x.ps1`, or `x.py`). However, most of the code lives in `src/bootstrap`.
+`bootstrap` has a difficult problem: it is written in Rust, but yet it is run
+before the Rust compiler is built! To work around this, there are two components
+of bootstrap: the main one written in rust, and `bootstrap.py`. `bootstrap.py`
+is what gets run by entry point script. It takes care of downloading the `stage0`
+compiler, which will then build the bootstrap binary written in Rust.
-First up, you'll probably want to read over the documentation above, as that'll
-give you a high level overview of what rustbuild is doing. You also probably
-want to play around a bit yourself by just getting it up and running before you
-dive too much into the actual build system itself.
+Because there are two separate codebases behind `x.py`, they need to
+be kept in sync. In particular, both `bootstrap.py` and the bootstrap binary
+parse `config.toml` and read the same command line arguments. `bootstrap.py`
+keeps these in sync by setting various environment variables, and the
+programs sometimes have to add arguments that are explicitly ignored, to be
+read by the other.
-After that, each module in rustbuild should have enough documentation to keep
-you up and running. Some general areas that you may be interested in modifying
-are:
+Some general areas that you may be interested in modifying are:
* Adding a new build tool? Take a look at `bootstrap/tool.rs` for examples of
other tools.
Changes that do not affect contributors to the compiler or users
building rustc from source don't need an update to `VERSION`.
-If you have any questions, feel free to reach out on the `#t-infra` channel in
-the [Rust Zulip server][rust-zulip] or ask on internals.rust-lang.org. When
-you encounter bugs, please file issues on the rust-lang/rust issue tracker.
+If you have any questions, feel free to reach out on the `#t-infra/bootstrap` channel
+at [Rust Bootstrap Zulip server][rust-bootstrap-zulip]. When you encounter bugs,
+please file issues on the [Rust issue tracker][rust-issue-tracker].
-[rust-zulip]: https://rust-lang.zulipchat.com/#narrow/stream/242791-t-infra
+[rust-bootstrap-zulip]: https://rust-lang.zulipchat.com/#narrow/stream/t-infra.2Fbootstrap
+[rust-issue-tracker]: https://github.com/rust-lang/rust/issues
//! crates.io and Cargo.
//! * A standard interface to build across all platforms, including MSVC
//!
-//! ## Architecture
-//!
-//! The build system defers most of the complicated logic managing invocations
-//! of rustc and rustdoc to Cargo itself. However, moving through various stages
-//! and copying artifacts is still necessary for it to do. Each time rustbuild
-//! is invoked, it will iterate through the list of predefined steps and execute
-//! each serially in turn if it matches the paths passed or is a default rule.
-//! For each step rustbuild relies on the step internally being incremental and
-//! parallel. Note, though, that the `-j` parameter to rustbuild gets forwarded
-//! to appropriate test harnesses and such.
-//!
-//! Most of the "meaty" steps that matter are backed by Cargo, which does indeed
-//! have its own parallelism and incremental management. Later steps, like
-//! tests, aren't incremental and simply run the entire suite currently.
-//! However, compiletest itself tries to avoid running tests when the artifacts
-//! that are involved (mainly the compiler) haven't changed.
-//!
-//! When you execute `x.py build`, the steps executed are:
-//!
-//! * First, the python script is run. This will automatically download the
-//! stage0 rustc and cargo according to `src/stage0.json`, or use the cached
-//! versions if they're available. These are then used to compile rustbuild
-//! itself (using Cargo). Finally, control is then transferred to rustbuild.
-//!
-//! * Rustbuild takes over, performs sanity checks, probes the environment,
-//! reads configuration, and starts executing steps as it reads the command
-//! line arguments (paths) or going through the default rules.
-//!
-//! The build output will be something like the following:
-//!
-//! Building stage0 std artifacts
-//! Copying stage0 std
-//! Building stage0 test artifacts
-//! Copying stage0 test
-//! Building stage0 compiler artifacts
-//! Copying stage0 rustc
-//! Assembling stage1 compiler
-//! Building stage1 std artifacts
-//! Copying stage1 std
-//! Building stage1 test artifacts
-//! Copying stage1 test
-//! Building stage1 compiler artifacts
-//! Copying stage1 rustc
-//! Assembling stage2 compiler
-//! Uplifting stage1 std
-//! Uplifting stage1 test
-//! Uplifting stage1 rustc
-//!
-//! Let's disect that a little:
-//!
-//! ## Building stage0 {std,test,compiler} artifacts
-//!
-//! These steps use the provided (downloaded, usually) compiler to compile the
-//! local Rust source into libraries we can use.
-//!
-//! ## Copying stage0 {std,test,rustc}
-//!
-//! This copies the build output from Cargo into
-//! `build/$HOST/stage0-sysroot/lib/rustlib/$ARCH/lib`. FIXME: this step's
-//! documentation should be expanded -- the information already here may be
-//! incorrect.
-//!
-//! ## Assembling stage1 compiler
-//!
-//! This copies the libraries we built in "building stage0 ... artifacts" into
-//! the stage1 compiler's lib directory. These are the host libraries that the
-//! compiler itself uses to run. These aren't actually used by artifacts the new
-//! compiler generates. This step also copies the rustc and rustdoc binaries we
-//! generated into build/$HOST/stage/bin.
-//!
-//! The stage1/bin/rustc is a fully functional compiler, but it doesn't yet have
-//! any libraries to link built binaries or libraries to. The next 3 steps will
-//! provide those libraries for it; they are mostly equivalent to constructing
-//! the stage1/bin compiler so we don't go through them individually.
-//!
-//! ## Uplifting stage1 {std,test,rustc}
-//!
-//! This step copies the libraries from the stage1 compiler sysroot into the
-//! stage2 compiler. This is done to avoid rebuilding the compiler; libraries
-//! we'd build in this step should be identical (in function, if not necessarily
-//! identical on disk) so there's no need to recompile the compiler again. Note
-//! that if you want to, you can enable the full-bootstrap option to change this
-//! behavior.
-//!
-//! Each step is driven by a separate Cargo project and rustbuild orchestrates
-//! copying files between steps and otherwise preparing for Cargo to run.
-//!
//! ## Further information
//!
//! More documentation can be found in each respective module below, and you can
} else {
let mut br_with_padding = String::with_capacity(6 * indent + 28);
br_with_padding.push_str("<br>");
- for _ in 0..indent + 4 {
+
+ let padding_amout =
+ if ending == Ending::Newline { indent + 4 } else { indent + "fn where ".len() };
+
+ for _ in 0..padding_amout {
br_with_padding.push_str(" ");
}
let where_preds = where_preds.to_string().replace("<br>", &br_with_padding);
if indent == 0 {
format!("<br><span class=\"where\">where{where_preds}</span>")
} else {
+ // put the first one on the same line as the 'where' keyword
+ let where_preds = where_preds.replacen(&br_with_padding, " ", 1);
+
let mut clause = br_with_padding;
- clause.truncate(clause.len() - 4);
+ clause.truncate(clause.len() - "where ".len());
+
write!(clause, "<span class=\"where\">where{where_preds}</span>")?;
clause
}
if count_consts != 0 && count_methods != 0 {
w.write_str("\n");
}
+
+ if !required_methods.is_empty() {
+ write!(w, " // Required method{}\n", pluralize(required_methods.len()));
+ }
for (pos, m) in required_methods.iter().enumerate() {
render_assoc_item(
w,
if !required_methods.is_empty() && !provided_methods.is_empty() {
w.write_str("\n");
}
+
+ if !provided_methods.is_empty() {
+ write!(w, " // Provided method{}\n", pluralize(provided_methods.len()));
+ }
for (pos, m) in provided_methods.iter().enumerate() {
render_assoc_item(
w,
cx,
RenderMode::Normal,
);
- match *m.kind {
- clean::MethodItem(ref inner, _)
- if !inner.generics.where_predicates.is_empty() =>
- {
- w.write_str(",\n { ... }\n");
- }
- _ => {
- w.write_str(" { ... }\n");
- }
- }
+
+ w.write_str(" { ... }\n");
if pos < provided_methods.len() - 1 {
w.write_str("<span class=\"item-spacer\"></span>");
.item-spacer {
width: 100%;
height: 12px;
+ display: block;
}
.out-of-band > span.since {
}
function initSearch(rawSearchIndex) {
- const MAX_LEV_DISTANCE = 3;
const MAX_RESULTS = 200;
const NO_TYPE_FILTER = -1;
/**
* @param {QueryElement} elem - The element from the parsed query.
* @param {integer} defaultLev - This is the value to return in case there are no generics.
*
- * @return {integer} - Returns the best match (if any) or `MAX_LEV_DISTANCE + 1`.
+ * @return {integer} - Returns the best match (if any) or `maxLevDistance + 1`.
*/
- function checkGenerics(row, elem, defaultLev) {
+ function checkGenerics(row, elem, defaultLev, maxLevDistance) {
if (row.generics.length === 0) {
- return elem.generics.length === 0 ? defaultLev : MAX_LEV_DISTANCE + 1;
+ return elem.generics.length === 0 ? defaultLev : maxLevDistance + 1;
} else if (row.generics.length > 0 && row.generics[0].name === null) {
- return checkGenerics(row.generics[0], elem, defaultLev);
+ return checkGenerics(row.generics[0], elem, defaultLev, maxLevDistance);
}
// The names match, but we need to be sure that all generics kinda
// match as well.
elem_name = entry.name;
if (elem_name === "") {
// Pure generic, needs to check into it.
- if (checkGenerics(entry, elem, MAX_LEV_DISTANCE + 1) !== 0) {
- return MAX_LEV_DISTANCE + 1;
+ if (checkGenerics(entry, elem, maxLevDistance + 1, maxLevDistance) !== 0) {
+ return maxLevDistance + 1;
}
continue;
}
}
}
if (match === null) {
- return MAX_LEV_DISTANCE + 1;
+ return maxLevDistance + 1;
}
elems[match] -= 1;
if (elems[match] === 0) {
}
return 0;
}
- return MAX_LEV_DISTANCE + 1;
+ return maxLevDistance + 1;
}
/**
*
* @return {integer} - Returns a Levenshtein distance to the best match.
*/
- function checkIfInGenerics(row, elem) {
- let lev = MAX_LEV_DISTANCE + 1;
+ function checkIfInGenerics(row, elem, maxLevDistance) {
+ let lev = maxLevDistance + 1;
for (const entry of row.generics) {
- lev = Math.min(checkType(entry, elem, true), lev);
+ lev = Math.min(checkType(entry, elem, true, maxLevDistance), lev);
if (lev === 0) {
break;
}
* @param {boolean} literalSearch
*
* @return {integer} - Returns a Levenshtein distance to the best match. If there is
- * no match, returns `MAX_LEV_DISTANCE + 1`.
+ * no match, returns `maxLevDistance + 1`.
*/
- function checkType(row, elem, literalSearch) {
+ function checkType(row, elem, literalSearch, maxLevDistance) {
if (row.name === null) {
// This is a pure "generic" search, no need to run other checks.
if (row.generics.length > 0) {
- return checkIfInGenerics(row, elem);
+ return checkIfInGenerics(row, elem, maxLevDistance);
}
- return MAX_LEV_DISTANCE + 1;
+ return maxLevDistance + 1;
}
let lev = levenshtein(row.name, elem.name);
return 0;
}
}
- return MAX_LEV_DISTANCE + 1;
+ return maxLevDistance + 1;
} else if (elem.generics.length > 0) {
- return checkGenerics(row, elem, MAX_LEV_DISTANCE + 1);
+ return checkGenerics(row, elem, maxLevDistance + 1, maxLevDistance);
}
return 0;
} else if (row.generics.length > 0) {
}
// The name didn't match so we now check if the type we're looking for is inside
// the generics!
- lev = checkIfInGenerics(row, elem);
- // Now whatever happens, the returned distance is "less good" so we should mark
- // it as such, and so we add 0.5 to the distance to make it "less good".
- return lev + 0.5;
- } else if (lev > MAX_LEV_DISTANCE) {
+ lev = Math.min(lev, checkIfInGenerics(row, elem, maxLevDistance));
+ return lev;
+ } else if (lev > maxLevDistance) {
// So our item's name doesn't match at all and has generics.
//
// Maybe it's present in a sub generic? For example "f<A<B<C>>>()", if we're
// looking for "B<C>", we'll need to go down.
- return checkIfInGenerics(row, elem);
+ return checkIfInGenerics(row, elem, maxLevDistance);
} else {
// At this point, the name kinda match and we have generics to check, so
// let's go!
- const tmp_lev = checkGenerics(row, elem, lev);
- if (tmp_lev > MAX_LEV_DISTANCE) {
- return MAX_LEV_DISTANCE + 1;
+ const tmp_lev = checkGenerics(row, elem, lev, maxLevDistance);
+ if (tmp_lev > maxLevDistance) {
+ return maxLevDistance + 1;
}
// We compute the median value of both checks and return it.
return (tmp_lev + lev) / 2;
} else if (elem.generics.length > 0) {
// In this case, we were expecting generics but there isn't so we simply reject this
// one.
- return MAX_LEV_DISTANCE + 1;
+ return maxLevDistance + 1;
}
// No generics on our query or on the target type so we can return without doing
// anything else.
* @param {integer} typeFilter
*
* @return {integer} - Returns a Levenshtein distance to the best match. If there is no
- * match, returns `MAX_LEV_DISTANCE + 1`.
+ * match, returns `maxLevDistance + 1`.
*/
- function findArg(row, elem, typeFilter) {
- let lev = MAX_LEV_DISTANCE + 1;
+ function findArg(row, elem, typeFilter, maxLevDistance) {
+ let lev = maxLevDistance + 1;
if (row && row.type && row.type.inputs && row.type.inputs.length > 0) {
for (const input of row.type.inputs) {
if (!typePassesFilter(typeFilter, input.ty)) {
continue;
}
- lev = Math.min(lev, checkType(input, elem, parsedQuery.literalSearch));
+ lev = Math.min(
+ lev,
+ checkType(input, elem, parsedQuery.literalSearch, maxLevDistance)
+ );
if (lev === 0) {
return 0;
}
}
}
- return parsedQuery.literalSearch ? MAX_LEV_DISTANCE + 1 : lev;
+ return parsedQuery.literalSearch ? maxLevDistance + 1 : lev;
}
/**
* @param {integer} typeFilter
*
* @return {integer} - Returns a Levenshtein distance to the best match. If there is no
- * match, returns `MAX_LEV_DISTANCE + 1`.
+ * match, returns `maxLevDistance + 1`.
*/
- function checkReturned(row, elem, typeFilter) {
- let lev = MAX_LEV_DISTANCE + 1;
+ function checkReturned(row, elem, typeFilter, maxLevDistance) {
+ let lev = maxLevDistance + 1;
if (row && row.type && row.type.output.length > 0) {
const ret = row.type.output;
if (!typePassesFilter(typeFilter, ret_ty.ty)) {
continue;
}
- lev = Math.min(lev, checkType(ret_ty, elem, parsedQuery.literalSearch));
+ lev = Math.min(
+ lev,
+ checkType(ret_ty, elem, parsedQuery.literalSearch, maxLevDistance)
+ );
if (lev === 0) {
return 0;
}
}
}
- return parsedQuery.literalSearch ? MAX_LEV_DISTANCE + 1 : lev;
+ return parsedQuery.literalSearch ? maxLevDistance + 1 : lev;
}
- function checkPath(contains, ty) {
+ function checkPath(contains, ty, maxLevDistance) {
if (contains.length === 0) {
return 0;
}
- let ret_lev = MAX_LEV_DISTANCE + 1;
+ let ret_lev = maxLevDistance + 1;
const path = ty.path.split("::");
if (ty.parent && ty.parent.name) {
const length = path.length;
const clength = contains.length;
if (clength > length) {
- return MAX_LEV_DISTANCE + 1;
+ return maxLevDistance + 1;
}
for (let i = 0; i < length; ++i) {
if (i + clength > length) {
let aborted = false;
for (let x = 0; x < clength; ++x) {
const lev = levenshtein(path[i + x], contains[x]);
- if (lev > MAX_LEV_DISTANCE) {
+ if (lev > maxLevDistance) {
aborted = true;
break;
}
* following condition:
*
* * If it is a "literal search" (`parsedQuery.literalSearch`), then `lev` must be 0.
- * * If it is not a "literal search", `lev` must be <= `MAX_LEV_DISTANCE`.
+ * * If it is not a "literal search", `lev` must be <= `maxLevDistance`.
*
* The `results` map contains information which will be used to sort the search results:
*
* @param {integer} lev
* @param {integer} path_lev
*/
- function addIntoResults(results, fullId, id, index, lev, path_lev) {
- const inBounds = lev <= MAX_LEV_DISTANCE || index !== -1;
+ function addIntoResults(results, fullId, id, index, lev, path_lev, maxLevDistance) {
+ const inBounds = lev <= maxLevDistance || index !== -1;
if (lev === 0 || (!parsedQuery.literalSearch && inBounds)) {
if (results[fullId] !== undefined) {
const result = results[fullId];
elem,
results_others,
results_in_args,
- results_returned
+ results_returned,
+ maxLevDistance
) {
if (!row || (filterCrates !== null && row.crate !== filterCrates)) {
return;
const fullId = row.id;
const searchWord = searchWords[pos];
- const in_args = findArg(row, elem, parsedQuery.typeFilter);
- const returned = checkReturned(row, elem, parsedQuery.typeFilter);
+ const in_args = findArg(row, elem, parsedQuery.typeFilter, maxLevDistance);
+ const returned = checkReturned(row, elem, parsedQuery.typeFilter, maxLevDistance);
// path_lev is 0 because no parent path information is currently stored
// in the search index
- addIntoResults(results_in_args, fullId, pos, -1, in_args, 0);
- addIntoResults(results_returned, fullId, pos, -1, returned, 0);
+ addIntoResults(results_in_args, fullId, pos, -1, in_args, 0, maxLevDistance);
+ addIntoResults(results_returned, fullId, pos, -1, returned, 0, maxLevDistance);
if (!typePassesFilter(parsedQuery.typeFilter, row.ty)) {
return;
// No need to check anything else if it's a "pure" generics search.
if (elem.name.length === 0) {
if (row.type !== null) {
- lev = checkGenerics(row.type, elem, MAX_LEV_DISTANCE + 1);
+ lev = checkGenerics(row.type, elem, maxLevDistance + 1, maxLevDistance);
// path_lev is 0 because we know it's empty
- addIntoResults(results_others, fullId, pos, index, lev, 0);
+ addIntoResults(results_others, fullId, pos, index, lev, 0, maxLevDistance);
}
return;
}
if (elem.fullPath.length > 1) {
- path_lev = checkPath(elem.pathWithoutLast, row);
- if (path_lev > MAX_LEV_DISTANCE) {
+ path_lev = checkPath(elem.pathWithoutLast, row, maxLevDistance);
+ if (path_lev > maxLevDistance) {
return;
}
}
lev = levenshtein(searchWord, elem.pathLast);
- if (index === -1 && lev + path_lev > MAX_LEV_DISTANCE) {
+ if (index === -1 && lev + path_lev > maxLevDistance) {
return;
}
- addIntoResults(results_others, fullId, pos, index, lev, path_lev);
+ addIntoResults(results_others, fullId, pos, index, lev, path_lev, maxLevDistance);
}
/**
* @param {integer} pos - Position in the `searchIndex`.
* @param {Object} results
*/
- function handleArgs(row, pos, results) {
+ function handleArgs(row, pos, results, maxLevDistance) {
if (!row || (filterCrates !== null && row.crate !== filterCrates)) {
return;
}
function checkArgs(elems, callback) {
for (const elem of elems) {
// There is more than one parameter to the query so all checks should be "exact"
- const lev = callback(row, elem, NO_TYPE_FILTER);
+ const lev = callback(row, elem, NO_TYPE_FILTER, maxLevDistance);
if (lev <= 1) {
nbLev += 1;
totalLev += lev;
return;
}
const lev = Math.round(totalLev / nbLev);
- addIntoResults(results, row.id, pos, 0, lev, 0);
+ addIntoResults(results, row.id, pos, 0, lev, 0, maxLevDistance);
}
function innerRunQuery() {
let elem, i, nSearchWords, in_returned, row;
+ let queryLen = 0;
+ for (const elem of parsedQuery.elems) {
+ queryLen += elem.name.length;
+ }
+ for (const elem of parsedQuery.returned) {
+ queryLen += elem.name.length;
+ }
+ const maxLevDistance = Math.floor(queryLen / 3);
+
if (parsedQuery.foundElems === 1) {
if (parsedQuery.elems.length === 1) {
elem = parsedQuery.elems[0];
elem,
results_others,
results_in_args,
- results_returned
+ results_returned,
+ maxLevDistance
);
}
} else if (parsedQuery.returned.length === 1) {
elem = parsedQuery.returned[0];
for (i = 0, nSearchWords = searchWords.length; i < nSearchWords; ++i) {
row = searchIndex[i];
- in_returned = checkReturned(row, elem, parsedQuery.typeFilter);
- addIntoResults(results_others, row.id, i, -1, in_returned);
+ in_returned = checkReturned(
+ row,
+ elem,
+ parsedQuery.typeFilter,
+ maxLevDistance
+ );
+ addIntoResults(results_others, row.id, i, -1, in_returned, maxLevDistance);
}
}
} else if (parsedQuery.foundElems > 0) {
for (i = 0, nSearchWords = searchWords.length; i < nSearchWords; ++i) {
- handleArgs(searchIndex[i], i, results_others);
+ handleArgs(searchIndex[i], i, results_others, maxLevDistance);
}
}
}
*
* @return {boolean} - Whether the result is valid or not
*/
- function validateResult(name, path, keys, parent) {
+ function validateResult(name, path, keys, parent, maxLevDistance) {
if (!keys || !keys.length) {
return true;
}
(parent !== undefined && parent.name !== undefined &&
parent.name.toLowerCase().indexOf(key) > -1) ||
// lastly check to see if the name was a levenshtein match
- levenshtein(name, key) <= MAX_LEV_DISTANCE)) {
+ levenshtein(name, key) <= maxLevDistance)) {
return false;
}
}
bb1: {
_4 = move _2; // scope 0 at $DIR/async_await.rs:+0:14: +0:16
_3 = const (); // scope 0 at $DIR/async_await.rs:+0:14: +0:16
- Deinit(_0); // scope 0 at $DIR/async_await.rs:+0:16: +0:16
- ((_0 as Ready).0: ()) = move _3; // scope 0 at $DIR/async_await.rs:+0:16: +0:16
- discriminant(_0) = 0; // scope 0 at $DIR/async_await.rs:+0:16: +0:16
+ _0 = Poll::<()>::Ready(move _3); // scope 0 at $DIR/async_await.rs:+0:16: +0:16
discriminant((*(_1.0: &mut [async fn body@$DIR/async_await.rs:11:14: 11:16]))) = 1; // scope 0 at $DIR/async_await.rs:+0:16: +0:16
return; // scope 0 at $DIR/async_await.rs:+0:16: +0:16
}
StorageLive(_19); // scope 1 at $DIR/async_await.rs:+1:8: +1:14
StorageLive(_20); // scope 1 at $DIR/async_await.rs:+1:8: +1:14
_20 = (); // scope 1 at $DIR/async_await.rs:+1:8: +1:14
- Deinit(_0); // scope 1 at $DIR/async_await.rs:+1:8: +1:14
- discriminant(_0) = 1; // scope 1 at $DIR/async_await.rs:+1:8: +1:14
+ _0 = Poll::<()>::Pending; // scope 1 at $DIR/async_await.rs:+1:8: +1:14
discriminant((*(_1.0: &mut [async fn body@$DIR/async_await.rs:14:18: 17:2]))) = 3; // scope 1 at $DIR/async_await.rs:+1:8: +1:14
return; // scope 1 at $DIR/async_await.rs:+1:8: +1:14
}
StorageLive(_35); // scope 4 at $DIR/async_await.rs:+2:8: +2:14
StorageLive(_36); // scope 4 at $DIR/async_await.rs:+2:8: +2:14
_36 = (); // scope 4 at $DIR/async_await.rs:+2:8: +2:14
- Deinit(_0); // scope 4 at $DIR/async_await.rs:+2:8: +2:14
- discriminant(_0) = 1; // scope 4 at $DIR/async_await.rs:+2:8: +2:14
+ _0 = Poll::<()>::Pending; // scope 4 at $DIR/async_await.rs:+2:8: +2:14
discriminant((*(_1.0: &mut [async fn body@$DIR/async_await.rs:14:18: 17:2]))) = 4; // scope 4 at $DIR/async_await.rs:+2:8: +2:14
return; // scope 4 at $DIR/async_await.rs:+2:8: +2:14
}
}
bb26: {
- Deinit(_0); // scope 0 at $DIR/async_await.rs:+3:2: +3:2
- ((_0 as Ready).0: ()) = move _37; // scope 0 at $DIR/async_await.rs:+3:2: +3:2
- discriminant(_0) = 0; // scope 0 at $DIR/async_await.rs:+3:2: +3:2
+ _0 = Poll::<()>::Ready(move _37); // scope 0 at $DIR/async_await.rs:+3:2: +3:2
discriminant((*(_1.0: &mut [async fn body@$DIR/async_await.rs:14:18: 17:2]))) = 1; // scope 0 at $DIR/async_await.rs:+3:2: +3:2
return; // scope 0 at $DIR/async_await.rs:+3:2: +3:2
}
bb3: {
StorageDead(_9); // scope 0 at $DIR/combine_clone_of_primitives.rs:10:15: 10:16
- Deinit(_0); // scope 0 at $DIR/combine_clone_of_primitives.rs:+0:10: +0:15
- (_0.0: T) = move _2; // scope 0 at $DIR/combine_clone_of_primitives.rs:+0:10: +0:15
- (_0.1: u64) = move _5; // scope 0 at $DIR/combine_clone_of_primitives.rs:+0:10: +0:15
- (_0.2: [f32; 3]) = move _8; // scope 0 at $DIR/combine_clone_of_primitives.rs:+0:10: +0:15
+ _0 = MyThing::<T> { v: move _2, i: move _5, a: move _8 }; // scope 0 at $DIR/combine_clone_of_primitives.rs:+0:10: +0:15
StorageDead(_8); // scope 0 at $DIR/combine_clone_of_primitives.rs:+0:14: +0:15
StorageDead(_5); // scope 0 at $DIR/combine_clone_of_primitives.rs:+0:14: +0:15
StorageDead(_2); // scope 0 at $DIR/combine_clone_of_primitives.rs:+0:14: +0:15
alloc18 (size: 48, align: 4) {
0x00 │ 00 00 00 00 __ __ __ __ ╾─alloc5──╼ 00 00 00 00 │ ....░░░░╾──╼....
- 0x10 │ 00 00 00 00 __ __ __ __ ╾─alloc9──╼ 02 00 00 00 │ ....░░░░╾──╼....
- 0x20 │ 01 00 00 00 2a 00 00 00 ╾─alloc14─╼ 03 00 00 00 │ ....*...╾──╼....
+ 0x10 │ 00 00 00 00 __ __ __ __ ╾─alloc8──╼ 02 00 00 00 │ ....░░░░╾──╼....
+ 0x20 │ 01 00 00 00 2a 00 00 00 ╾─alloc13─╼ 03 00 00 00 │ ....*...╾──╼....
}
alloc5 (size: 0, align: 4) {}
-alloc9 (size: 16, align: 4) {
- ╾─alloc8──╼ 03 00 00 00 ╾─alloc10─╼ 03 00 00 00 │ ╾──╼....╾──╼....
+alloc8 (size: 16, align: 4) {
+ ╾─alloc9──╼ 03 00 00 00 ╾─alloc10─╼ 03 00 00 00 │ ╾──╼....╾──╼....
}
-alloc8 (size: 3, align: 1) {
+alloc9 (size: 3, align: 1) {
66 6f 6f │ foo
}
62 61 72 │ bar
}
-alloc14 (size: 24, align: 4) {
- 0x00 │ ╾─alloc13─╼ 03 00 00 00 ╾─alloc15─╼ 03 00 00 00 │ ╾──╼....╾──╼....
+alloc13 (size: 24, align: 4) {
+ 0x00 │ ╾─alloc14─╼ 03 00 00 00 ╾─alloc15─╼ 03 00 00 00 │ ╾──╼....╾──╼....
0x10 │ ╾─alloc16─╼ 04 00 00 00 │ ╾──╼....
}
-alloc13 (size: 3, align: 1) {
+alloc14 (size: 3, align: 1) {
6d 65 68 │ meh
}
alloc18 (size: 72, align: 8) {
0x00 │ 00 00 00 00 __ __ __ __ ╾───────alloc5────────╼ │ ....░░░░╾──────╼
0x10 │ 00 00 00 00 00 00 00 00 00 00 00 00 __ __ __ __ │ ............░░░░
- 0x20 │ ╾───────alloc9────────╼ 02 00 00 00 00 00 00 00 │ ╾──────╼........
- 0x30 │ 01 00 00 00 2a 00 00 00 ╾───────alloc14───────╼ │ ....*...╾──────╼
+ 0x20 │ ╾───────alloc8────────╼ 02 00 00 00 00 00 00 00 │ ╾──────╼........
+ 0x30 │ 01 00 00 00 2a 00 00 00 ╾───────alloc13───────╼ │ ....*...╾──────╼
0x40 │ 03 00 00 00 00 00 00 00 │ ........
}
alloc5 (size: 0, align: 8) {}
-alloc9 (size: 32, align: 8) {
- 0x00 │ ╾───────alloc8────────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........
+alloc8 (size: 32, align: 8) {
+ 0x00 │ ╾───────alloc9────────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........
0x10 │ ╾───────alloc10───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........
}
-alloc8 (size: 3, align: 1) {
+alloc9 (size: 3, align: 1) {
66 6f 6f │ foo
}
62 61 72 │ bar
}
-alloc14 (size: 48, align: 8) {
- 0x00 │ ╾───────alloc13───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........
+alloc13 (size: 48, align: 8) {
+ 0x00 │ ╾───────alloc14───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........
0x10 │ ╾───────alloc15───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........
0x20 │ ╾───────alloc16───────╼ 04 00 00 00 00 00 00 00 │ ╾──────╼........
}
-alloc13 (size: 3, align: 1) {
+alloc14 (size: 3, align: 1) {
6d 65 68 │ meh
}
let mut _6: u8; // in scope 0 at $DIR/const_debuginfo.rs:+4:15: +4:16
let mut _7: u8; // in scope 0 at $DIR/const_debuginfo.rs:+4:19: +4:20
let mut _8: u8; // in scope 0 at $DIR/const_debuginfo.rs:+4:23: +4:24
- let mut _12: u32; // in scope 0 at $DIR/const_debuginfo.rs:+13:13: +13:16
- let mut _13: u32; // in scope 0 at $DIR/const_debuginfo.rs:+13:19: +13:22
+ let mut _14: u32; // in scope 0 at $DIR/const_debuginfo.rs:+13:13: +13:16
+ let mut _15: u32; // in scope 0 at $DIR/const_debuginfo.rs:+13:19: +13:22
scope 1 {
- debug x => _1; // in scope 1 at $DIR/const_debuginfo.rs:+1:9: +1:10
+ debug x => const 1_u8; // in scope 1 at $DIR/const_debuginfo.rs:+1:9: +1:10
scope 5 {
- debug s => _9; // in scope 5 at $DIR/const_debuginfo.rs:+6:9: +6:10
+ debug s => const "hello, world!"; // in scope 5 at $DIR/const_debuginfo.rs:+6:9: +6:10
- let _14: bool; // in scope 5 at $DIR/const_debuginfo.rs:+8:9: +8:10
- let _15: bool; // in scope 5 at $DIR/const_debuginfo.rs:+8:9: +8:10
- let _16: u32; // in scope 5 at $DIR/const_debuginfo.rs:+8:9: +8:10
+ let _10: (bool, bool, u32); // in scope 5 at $DIR/const_debuginfo.rs:+8:9: +8:10
scope 6 {
- debug f => (bool, bool, u32){ .0 => _14, .1 => _15, .2 => _16, }; // in scope 6 at $DIR/const_debuginfo.rs:+8:9: +8:10
- let _10: std::option::Option<u16>; // in scope 6 at $DIR/const_debuginfo.rs:+10:9: +10:10
+ debug f => _10; // in scope 6 at $DIR/const_debuginfo.rs:+8:9: +8:10
+ let _11: std::option::Option<u16>; // in scope 6 at $DIR/const_debuginfo.rs:+10:9: +10:10
scope 7 {
- debug o => _10; // in scope 7 at $DIR/const_debuginfo.rs:+10:9: +10:10
- let _17: u32; // in scope 7 at $DIR/const_debuginfo.rs:+12:9: +12:10
- let _18: u32; // in scope 7 at $DIR/const_debuginfo.rs:+12:9: +12:10
+ debug o => _11; // in scope 7 at $DIR/const_debuginfo.rs:+10:9: +10:10
+ let _12: Point; // in scope 7 at $DIR/const_debuginfo.rs:+12:9: +12:10
scope 8 {
- debug p => Point{ .0 => _17, .1 => _18, }; // in scope 8 at $DIR/const_debuginfo.rs:+12:9: +12:10
- let _11: u32; // in scope 8 at $DIR/const_debuginfo.rs:+13:9: +13:10
+ debug p => _12; // in scope 8 at $DIR/const_debuginfo.rs:+12:9: +12:10
+ let _13: u32; // in scope 8 at $DIR/const_debuginfo.rs:+13:9: +13:10
scope 9 {
-- debug a => _11; // in scope 9 at $DIR/const_debuginfo.rs:+13:9: +13:10
+- debug a => _13; // in scope 9 at $DIR/const_debuginfo.rs:+13:9: +13:10
+ debug a => const 64_u32; // in scope 9 at $DIR/const_debuginfo.rs:+13:9: +13:10
}
}
// mir::Constant
// + span: $DIR/const_debuginfo.rs:14:13: 14:28
// + literal: Const { ty: &str, val: Value(Slice(..)) }
- StorageLive(_14); // scope 5 at $DIR/const_debuginfo.rs:+8:9: +8:10
- StorageLive(_15); // scope 5 at $DIR/const_debuginfo.rs:+8:9: +8:10
- StorageLive(_16); // scope 5 at $DIR/const_debuginfo.rs:+8:9: +8:10
- Deinit(_14); // scope 5 at $DIR/const_debuginfo.rs:+8:13: +8:34
- Deinit(_15); // scope 5 at $DIR/const_debuginfo.rs:+8:13: +8:34
- Deinit(_16); // scope 5 at $DIR/const_debuginfo.rs:+8:13: +8:34
- _14 = const true; // scope 5 at $DIR/const_debuginfo.rs:+8:13: +8:34
- _15 = const false; // scope 5 at $DIR/const_debuginfo.rs:+8:13: +8:34
- _16 = const 123_u32; // scope 5 at $DIR/const_debuginfo.rs:+8:13: +8:34
- StorageLive(_10); // scope 6 at $DIR/const_debuginfo.rs:+10:9: +10:10
- Deinit(_10); // scope 6 at $DIR/const_debuginfo.rs:+10:13: +10:24
- ((_10 as Some).0: u16) = const 99_u16; // scope 6 at $DIR/const_debuginfo.rs:+10:13: +10:24
- discriminant(_10) = 1; // scope 6 at $DIR/const_debuginfo.rs:+10:13: +10:24
- StorageLive(_17); // scope 7 at $DIR/const_debuginfo.rs:+12:9: +12:10
- StorageLive(_18); // scope 7 at $DIR/const_debuginfo.rs:+12:9: +12:10
- Deinit(_17); // scope 7 at $DIR/const_debuginfo.rs:+12:13: +12:35
- Deinit(_18); // scope 7 at $DIR/const_debuginfo.rs:+12:13: +12:35
- _17 = const 32_u32; // scope 7 at $DIR/const_debuginfo.rs:+12:13: +12:35
- _18 = const 32_u32; // scope 7 at $DIR/const_debuginfo.rs:+12:13: +12:35
- StorageLive(_11); // scope 8 at $DIR/const_debuginfo.rs:+13:9: +13:10
- StorageLive(_12); // scope 8 at $DIR/const_debuginfo.rs:+13:13: +13:16
- _12 = const 32_u32; // scope 8 at $DIR/const_debuginfo.rs:+13:13: +13:16
- StorageLive(_13); // scope 8 at $DIR/const_debuginfo.rs:+13:19: +13:22
- _13 = const 32_u32; // scope 8 at $DIR/const_debuginfo.rs:+13:19: +13:22
- _11 = const 64_u32; // scope 8 at $DIR/const_debuginfo.rs:+13:13: +13:22
- StorageDead(_13); // scope 8 at $DIR/const_debuginfo.rs:+13:21: +13:22
- StorageDead(_12); // scope 8 at $DIR/const_debuginfo.rs:+13:21: +13:22
- StorageDead(_11); // scope 8 at $DIR/const_debuginfo.rs:+14:1: +14:2
- StorageDead(_17); // scope 7 at $DIR/const_debuginfo.rs:+14:1: +14:2
- StorageDead(_18); // scope 7 at $DIR/const_debuginfo.rs:+14:1: +14:2
- StorageDead(_10); // scope 6 at $DIR/const_debuginfo.rs:+14:1: +14:2
- StorageDead(_14); // scope 5 at $DIR/const_debuginfo.rs:+14:1: +14:2
- StorageDead(_15); // scope 5 at $DIR/const_debuginfo.rs:+14:1: +14:2
- StorageDead(_16); // scope 5 at $DIR/const_debuginfo.rs:+14:1: +14:2
+ StorageLive(_10); // scope 5 at $DIR/const_debuginfo.rs:+8:9: +8:10
+ _10 = (const true, const false, const 123_u32); // scope 5 at $DIR/const_debuginfo.rs:+8:13: +8:34
+ StorageLive(_11); // scope 6 at $DIR/const_debuginfo.rs:+10:9: +10:10
+ _11 = Option::<u16>::Some(const 99_u16); // scope 6 at $DIR/const_debuginfo.rs:+10:13: +10:24
+ StorageLive(_12); // scope 7 at $DIR/const_debuginfo.rs:+12:9: +12:10
+ _12 = Point { x: const 32_u32, y: const 32_u32 }; // scope 7 at $DIR/const_debuginfo.rs:+12:13: +12:35
+ StorageLive(_13); // scope 8 at $DIR/const_debuginfo.rs:+13:9: +13:10
+ StorageLive(_14); // scope 8 at $DIR/const_debuginfo.rs:+13:13: +13:16
+ _14 = const 32_u32; // scope 8 at $DIR/const_debuginfo.rs:+13:13: +13:16
+ StorageLive(_15); // scope 8 at $DIR/const_debuginfo.rs:+13:19: +13:22
+ _15 = const 32_u32; // scope 8 at $DIR/const_debuginfo.rs:+13:19: +13:22
+ _13 = const 64_u32; // scope 8 at $DIR/const_debuginfo.rs:+13:13: +13:22
+ StorageDead(_15); // scope 8 at $DIR/const_debuginfo.rs:+13:21: +13:22
+ StorageDead(_14); // scope 8 at $DIR/const_debuginfo.rs:+13:21: +13:22
+ StorageDead(_13); // scope 8 at $DIR/const_debuginfo.rs:+14:1: +14:2
+ StorageDead(_12); // scope 7 at $DIR/const_debuginfo.rs:+14:1: +14:2
+ StorageDead(_11); // scope 6 at $DIR/const_debuginfo.rs:+14:1: +14:2
+ StorageDead(_10); // scope 5 at $DIR/const_debuginfo.rs:+14:1: +14:2
StorageDead(_9); // scope 4 at $DIR/const_debuginfo.rs:+14:1: +14:2
StorageDead(_4); // scope 3 at $DIR/const_debuginfo.rs:+14:1: +14:2
return; // scope 0 at $DIR/const_debuginfo.rs:+14:2: +14:2
bb0: {
StorageLive(_1); // scope 0 at $DIR/const_goto_storage.rs:+1:9: +1:12
- StorageLive(_2); // scope 0 at $DIR/const_goto_storage.rs:+1:21: +1:23
-- Deinit(_2); // scope 0 at $DIR/const_goto_storage.rs:+1:21: +1:23
+- _2 = (); // scope 0 at $DIR/const_goto_storage.rs:+1:21: +1:23
- StorageLive(_3); // scope 0 at $DIR/const_goto_storage.rs:+2:15: +6:10
- StorageLive(_4); // scope 0 at $DIR/const_goto_storage.rs:+2:18: +2:76
- StorageLive(_5); // scope 0 at $DIR/const_goto_storage.rs:+2:21: +2:52
--- /dev/null
+- // MIR for `foo` before ConstProp
++ // MIR for `foo` after ConstProp
+
+ fn foo(_1: u8) -> () {
+ debug x => _1; // in scope 0 at $DIR/aggregate.rs:+0:8: +0:9
+ let mut _0: (); // return place in scope 0 at $DIR/aggregate.rs:+0:15: +0:15
+ let _2: i32; // in scope 0 at $DIR/aggregate.rs:+2:9: +2:14
+ let mut _3: i32; // in scope 0 at $DIR/aggregate.rs:+2:17: +2:25
+ let mut _4: (i32, u8); // in scope 0 at $DIR/aggregate.rs:+2:17: +2:23
+ let mut _5: u8; // in scope 0 at $DIR/aggregate.rs:+2:21: +2:22
+ let mut _7: i32; // in scope 0 at $DIR/aggregate.rs:+3:18: +3:26
+ let mut _8: (u8, i32); // in scope 0 at $DIR/aggregate.rs:+3:18: +3:24
+ let mut _9: u8; // in scope 0 at $DIR/aggregate.rs:+3:19: +3:20
+ scope 1 {
+ debug first => _2; // in scope 1 at $DIR/aggregate.rs:+2:9: +2:14
+ let _6: i32; // in scope 1 at $DIR/aggregate.rs:+3:9: +3:15
+ scope 2 {
+ debug second => _6; // in scope 2 at $DIR/aggregate.rs:+3:9: +3:15
+ }
+ }
+
+ bb0: {
+ StorageLive(_2); // scope 0 at $DIR/aggregate.rs:+2:9: +2:14
+ StorageLive(_3); // scope 0 at $DIR/aggregate.rs:+2:17: +2:25
+ StorageLive(_4); // scope 0 at $DIR/aggregate.rs:+2:17: +2:23
+ StorageLive(_5); // scope 0 at $DIR/aggregate.rs:+2:21: +2:22
+ _5 = _1; // scope 0 at $DIR/aggregate.rs:+2:21: +2:22
+ _4 = (const 0_i32, move _5); // scope 0 at $DIR/aggregate.rs:+2:17: +2:23
+ StorageDead(_5); // scope 0 at $DIR/aggregate.rs:+2:22: +2:23
+- _3 = (_4.0: i32); // scope 0 at $DIR/aggregate.rs:+2:17: +2:25
+- _2 = Add(move _3, const 1_i32); // scope 0 at $DIR/aggregate.rs:+2:17: +2:29
++ _3 = const 0_i32; // scope 0 at $DIR/aggregate.rs:+2:17: +2:25
++ _2 = const 1_i32; // scope 0 at $DIR/aggregate.rs:+2:17: +2:29
+ StorageDead(_3); // scope 0 at $DIR/aggregate.rs:+2:28: +2:29
+ StorageDead(_4); // scope 0 at $DIR/aggregate.rs:+2:29: +2:30
+ StorageLive(_6); // scope 1 at $DIR/aggregate.rs:+3:9: +3:15
+ StorageLive(_7); // scope 1 at $DIR/aggregate.rs:+3:18: +3:26
+ StorageLive(_8); // scope 1 at $DIR/aggregate.rs:+3:18: +3:24
+ StorageLive(_9); // scope 1 at $DIR/aggregate.rs:+3:19: +3:20
+ _9 = _1; // scope 1 at $DIR/aggregate.rs:+3:19: +3:20
+ _8 = (move _9, const 1_i32); // scope 1 at $DIR/aggregate.rs:+3:18: +3:24
+ StorageDead(_9); // scope 1 at $DIR/aggregate.rs:+3:23: +3:24
+- _7 = (_8.1: i32); // scope 1 at $DIR/aggregate.rs:+3:18: +3:26
+- _6 = Add(move _7, const 2_i32); // scope 1 at $DIR/aggregate.rs:+3:18: +3:30
++ _7 = const 1_i32; // scope 1 at $DIR/aggregate.rs:+3:18: +3:26
++ _6 = const 3_i32; // scope 1 at $DIR/aggregate.rs:+3:18: +3:30
+ StorageDead(_7); // scope 1 at $DIR/aggregate.rs:+3:29: +3:30
+ StorageDead(_8); // scope 1 at $DIR/aggregate.rs:+3:30: +3:31
+ _0 = const (); // scope 0 at $DIR/aggregate.rs:+0:15: +4:2
+ StorageDead(_6); // scope 1 at $DIR/aggregate.rs:+4:1: +4:2
+ StorageDead(_2); // scope 0 at $DIR/aggregate.rs:+4:1: +4:2
+ return; // scope 0 at $DIR/aggregate.rs:+4:2: +4:2
+ }
+ }
+
--- /dev/null
+// MIR for `foo` after PreCodegen
+
+fn foo(_1: u8) -> () {
+ debug x => _1; // in scope 0 at $DIR/aggregate.rs:+0:8: +0:9
+ let mut _0: (); // return place in scope 0 at $DIR/aggregate.rs:+0:15: +0:15
+ let _2: i32; // in scope 0 at $DIR/aggregate.rs:+2:9: +2:14
+ let mut _3: i32; // in scope 0 at $DIR/aggregate.rs:+2:17: +2:25
+ let mut _4: (i32, u8); // in scope 0 at $DIR/aggregate.rs:+2:17: +2:23
+ let mut _5: u8; // in scope 0 at $DIR/aggregate.rs:+2:21: +2:22
+ let mut _7: i32; // in scope 0 at $DIR/aggregate.rs:+3:18: +3:26
+ let mut _8: (u8, i32); // in scope 0 at $DIR/aggregate.rs:+3:18: +3:24
+ let mut _9: u8; // in scope 0 at $DIR/aggregate.rs:+3:19: +3:20
+ scope 1 {
+ debug first => _2; // in scope 1 at $DIR/aggregate.rs:+2:9: +2:14
+ let _6: i32; // in scope 1 at $DIR/aggregate.rs:+3:9: +3:15
+ scope 2 {
+ debug second => _6; // in scope 2 at $DIR/aggregate.rs:+3:9: +3:15
+ }
+ }
+
+ bb0: {
+ StorageLive(_2); // scope 0 at $DIR/aggregate.rs:+2:9: +2:14
+ StorageLive(_3); // scope 0 at $DIR/aggregate.rs:+2:17: +2:25
+ StorageLive(_4); // scope 0 at $DIR/aggregate.rs:+2:17: +2:23
+ StorageLive(_5); // scope 0 at $DIR/aggregate.rs:+2:21: +2:22
+ _5 = _1; // scope 0 at $DIR/aggregate.rs:+2:21: +2:22
+ _4 = (const 0_i32, move _5); // scope 0 at $DIR/aggregate.rs:+2:17: +2:23
+ StorageDead(_5); // scope 0 at $DIR/aggregate.rs:+2:22: +2:23
+ _3 = const 0_i32; // scope 0 at $DIR/aggregate.rs:+2:17: +2:25
+ _2 = const 1_i32; // scope 0 at $DIR/aggregate.rs:+2:17: +2:29
+ StorageDead(_3); // scope 0 at $DIR/aggregate.rs:+2:28: +2:29
+ StorageDead(_4); // scope 0 at $DIR/aggregate.rs:+2:29: +2:30
+ StorageLive(_6); // scope 1 at $DIR/aggregate.rs:+3:9: +3:15
+ StorageLive(_7); // scope 1 at $DIR/aggregate.rs:+3:18: +3:26
+ StorageLive(_8); // scope 1 at $DIR/aggregate.rs:+3:18: +3:24
+ StorageLive(_9); // scope 1 at $DIR/aggregate.rs:+3:19: +3:20
+ _9 = _1; // scope 1 at $DIR/aggregate.rs:+3:19: +3:20
+ _8 = (move _9, const 1_i32); // scope 1 at $DIR/aggregate.rs:+3:18: +3:24
+ StorageDead(_9); // scope 1 at $DIR/aggregate.rs:+3:23: +3:24
+ _7 = const 1_i32; // scope 1 at $DIR/aggregate.rs:+3:18: +3:26
+ _6 = const 3_i32; // scope 1 at $DIR/aggregate.rs:+3:18: +3:30
+ StorageDead(_7); // scope 1 at $DIR/aggregate.rs:+3:29: +3:30
+ StorageDead(_8); // scope 1 at $DIR/aggregate.rs:+3:30: +3:31
+ _0 = const (); // scope 0 at $DIR/aggregate.rs:+0:15: +4:2
+ StorageDead(_6); // scope 1 at $DIR/aggregate.rs:+4:1: +4:2
+ StorageDead(_2); // scope 0 at $DIR/aggregate.rs:+4:1: +4:2
+ return; // scope 0 at $DIR/aggregate.rs:+4:2: +4:2
+ }
+}
fn main() -> () {
let mut _0: (); // return place in scope 0 at $DIR/aggregate.rs:+0:11: +0:11
- let _1: i32; // in scope 0 at $DIR/aggregate.rs:+1:9: +1:10
- let mut _2: i32; // in scope 0 at $DIR/aggregate.rs:+1:13: +1:24
- let mut _3: (i32, i32, i32); // in scope 0 at $DIR/aggregate.rs:+1:13: +1:22
+ let _1: u8; // in scope 0 at $DIR/aggregate.rs:+1:9: +1:10
+ let mut _2: u8; // in scope 0 at $DIR/aggregate.rs:+1:13: +1:24
+ let mut _3: (i32, u8, i32); // in scope 0 at $DIR/aggregate.rs:+1:13: +1:22
+ let _4: (); // in scope 0 at $DIR/aggregate.rs:+2:5: +2:11
+ let mut _5: u8; // in scope 0 at $DIR/aggregate.rs:+2:9: +2:10
scope 1 {
debug x => _1; // in scope 1 at $DIR/aggregate.rs:+1:9: +1:10
}
StorageLive(_1); // scope 0 at $DIR/aggregate.rs:+1:9: +1:10
StorageLive(_2); // scope 0 at $DIR/aggregate.rs:+1:13: +1:24
StorageLive(_3); // scope 0 at $DIR/aggregate.rs:+1:13: +1:22
- Deinit(_3); // scope 0 at $DIR/aggregate.rs:+1:13: +1:22
- (_3.0: i32) = const 0_i32; // scope 0 at $DIR/aggregate.rs:+1:13: +1:22
- (_3.1: i32) = const 1_i32; // scope 0 at $DIR/aggregate.rs:+1:13: +1:22
- (_3.2: i32) = const 2_i32; // scope 0 at $DIR/aggregate.rs:+1:13: +1:22
-- _2 = (_3.1: i32); // scope 0 at $DIR/aggregate.rs:+1:13: +1:24
-- _1 = Add(move _2, const 0_i32); // scope 0 at $DIR/aggregate.rs:+1:13: +1:28
-+ _2 = const 1_i32; // scope 0 at $DIR/aggregate.rs:+1:13: +1:24
-+ _1 = const 1_i32; // scope 0 at $DIR/aggregate.rs:+1:13: +1:28
+ _3 = (const 0_i32, const 1_u8, const 2_i32); // scope 0 at $DIR/aggregate.rs:+1:13: +1:22
+- _2 = (_3.1: u8); // scope 0 at $DIR/aggregate.rs:+1:13: +1:24
+- _1 = Add(move _2, const 0_u8); // scope 0 at $DIR/aggregate.rs:+1:13: +1:28
++ _2 = const 1_u8; // scope 0 at $DIR/aggregate.rs:+1:13: +1:24
++ _1 = const 1_u8; // scope 0 at $DIR/aggregate.rs:+1:13: +1:28
StorageDead(_2); // scope 0 at $DIR/aggregate.rs:+1:27: +1:28
StorageDead(_3); // scope 0 at $DIR/aggregate.rs:+1:28: +1:29
- _0 = const (); // scope 0 at $DIR/aggregate.rs:+0:11: +2:2
- StorageDead(_1); // scope 0 at $DIR/aggregate.rs:+2:1: +2:2
- return; // scope 0 at $DIR/aggregate.rs:+2:2: +2:2
+ StorageLive(_4); // scope 1 at $DIR/aggregate.rs:+2:5: +2:11
+ StorageLive(_5); // scope 1 at $DIR/aggregate.rs:+2:9: +2:10
+- _5 = _1; // scope 1 at $DIR/aggregate.rs:+2:9: +2:10
++ _5 = const 1_u8; // scope 1 at $DIR/aggregate.rs:+2:9: +2:10
+ _4 = foo(move _5) -> bb1; // scope 1 at $DIR/aggregate.rs:+2:5: +2:11
+ // mir::Constant
+ // + span: $DIR/aggregate.rs:8:5: 8:8
+ // + literal: Const { ty: fn(u8) {foo}, val: Value(<ZST>) }
+ }
+
+ bb1: {
+ StorageDead(_5); // scope 1 at $DIR/aggregate.rs:+2:10: +2:11
+ StorageDead(_4); // scope 1 at $DIR/aggregate.rs:+2:11: +2:12
+ _0 = const (); // scope 0 at $DIR/aggregate.rs:+0:11: +3:2
+ StorageDead(_1); // scope 0 at $DIR/aggregate.rs:+3:1: +3:2
+ return; // scope 0 at $DIR/aggregate.rs:+3:2: +3:2
}
}
fn main() -> () {
let mut _0: (); // return place in scope 0 at $DIR/aggregate.rs:+0:11: +0:11
- let _1: i32; // in scope 0 at $DIR/aggregate.rs:+1:9: +1:10
- let mut _2: i32; // in scope 0 at $DIR/aggregate.rs:+1:13: +1:24
- let mut _3: (i32, i32, i32); // in scope 0 at $DIR/aggregate.rs:+1:13: +1:22
+ let _1: u8; // in scope 0 at $DIR/aggregate.rs:+1:9: +1:10
+ let mut _2: u8; // in scope 0 at $DIR/aggregate.rs:+1:13: +1:24
+ let mut _3: (i32, u8, i32); // in scope 0 at $DIR/aggregate.rs:+1:13: +1:22
+ let _4: (); // in scope 0 at $DIR/aggregate.rs:+2:5: +2:11
+ let mut _5: u8; // in scope 0 at $DIR/aggregate.rs:+2:9: +2:10
scope 1 {
debug x => _1; // in scope 1 at $DIR/aggregate.rs:+1:9: +1:10
}
StorageLive(_1); // scope 0 at $DIR/aggregate.rs:+1:9: +1:10
StorageLive(_2); // scope 0 at $DIR/aggregate.rs:+1:13: +1:24
StorageLive(_3); // scope 0 at $DIR/aggregate.rs:+1:13: +1:22
- Deinit(_3); // scope 0 at $DIR/aggregate.rs:+1:13: +1:22
- (_3.0: i32) = const 0_i32; // scope 0 at $DIR/aggregate.rs:+1:13: +1:22
- (_3.1: i32) = const 1_i32; // scope 0 at $DIR/aggregate.rs:+1:13: +1:22
- (_3.2: i32) = const 2_i32; // scope 0 at $DIR/aggregate.rs:+1:13: +1:22
- _2 = const 1_i32; // scope 0 at $DIR/aggregate.rs:+1:13: +1:24
- _1 = const 1_i32; // scope 0 at $DIR/aggregate.rs:+1:13: +1:28
+ _3 = (const 0_i32, const 1_u8, const 2_i32); // scope 0 at $DIR/aggregate.rs:+1:13: +1:22
+ _2 = const 1_u8; // scope 0 at $DIR/aggregate.rs:+1:13: +1:24
+ _1 = const 1_u8; // scope 0 at $DIR/aggregate.rs:+1:13: +1:28
StorageDead(_2); // scope 0 at $DIR/aggregate.rs:+1:27: +1:28
StorageDead(_3); // scope 0 at $DIR/aggregate.rs:+1:28: +1:29
- _0 = const (); // scope 0 at $DIR/aggregate.rs:+0:11: +2:2
- StorageDead(_1); // scope 0 at $DIR/aggregate.rs:+2:1: +2:2
- return; // scope 0 at $DIR/aggregate.rs:+2:2: +2:2
+ StorageLive(_4); // scope 1 at $DIR/aggregate.rs:+2:5: +2:11
+ StorageLive(_5); // scope 1 at $DIR/aggregate.rs:+2:9: +2:10
+ _5 = const 1_u8; // scope 1 at $DIR/aggregate.rs:+2:9: +2:10
+ _4 = foo(move _5) -> bb1; // scope 1 at $DIR/aggregate.rs:+2:5: +2:11
+ // mir::Constant
+ // + span: $DIR/aggregate.rs:8:5: 8:8
+ // + literal: Const { ty: fn(u8) {foo}, val: Value(<ZST>) }
+ }
+
+ bb1: {
+ StorageDead(_5); // scope 1 at $DIR/aggregate.rs:+2:10: +2:11
+ StorageDead(_4); // scope 1 at $DIR/aggregate.rs:+2:11: +2:12
+ _0 = const (); // scope 0 at $DIR/aggregate.rs:+0:11: +3:2
+ StorageDead(_1); // scope 0 at $DIR/aggregate.rs:+3:1: +3:2
+ return; // scope 0 at $DIR/aggregate.rs:+3:2: +3:2
}
}
// EMIT_MIR aggregate.main.PreCodegen.after.mir
fn main() {
let x = (0, 1, 2).1 + 0;
+ foo(x);
+}
+
+// EMIT_MIR aggregate.foo.ConstProp.diff
+// EMIT_MIR aggregate.foo.PreCodegen.after.mir
+fn foo(x: u8) {
+ // Verify that we still propagate if part of the aggregate is not known.
+ let first = (0, x).0 + 1;
+ let second = (x, 1).1 + 2;
}
StorageLive(_1); // scope 0 at $DIR/discriminant.rs:+1:9: +1:10
StorageLive(_2); // scope 0 at $DIR/discriminant.rs:+1:13: +1:64
StorageLive(_3); // scope 2 at $DIR/discriminant.rs:+1:34: +1:44
- Deinit(_3); // scope 2 at $DIR/discriminant.rs:+1:34: +1:44
- ((_3 as Some).0: bool) = const true; // scope 2 at $DIR/discriminant.rs:+1:34: +1:44
- discriminant(_3) = 1; // scope 2 at $DIR/discriminant.rs:+1:34: +1:44
+- _3 = Option::<bool>::Some(const true); // scope 2 at $DIR/discriminant.rs:+1:34: +1:44
- _4 = discriminant(_3); // scope 2 at $DIR/discriminant.rs:+1:21: +1:31
- switchInt(move _4) -> [1: bb1, otherwise: bb3]; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31
++ _3 = const Option::<bool>::Some(true); // scope 2 at $DIR/discriminant.rs:+1:34: +1:44
++ // mir::Constant
++ // + span: $DIR/discriminant.rs:12:34: 12:44
++ // + literal: Const { ty: Option<bool>, val: Value(Scalar(0x01)) }
+ _4 = const 1_isize; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31
+ switchInt(const 1_isize) -> [1: bb1, otherwise: bb3]; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31
}
bb1: {
- switchInt(((_3 as Some).0: bool)) -> [0: bb3, otherwise: bb2]; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31
+- switchInt(((_3 as Some).0: bool)) -> [0: bb3, otherwise: bb2]; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31
++ switchInt(const true) -> [0: bb3, otherwise: bb2]; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31
}
bb2: {
StorageLive(_1); // scope 0 at $DIR/discriminant.rs:+1:9: +1:10
StorageLive(_2); // scope 0 at $DIR/discriminant.rs:+1:13: +1:64
StorageLive(_3); // scope 2 at $DIR/discriminant.rs:+1:34: +1:44
- Deinit(_3); // scope 2 at $DIR/discriminant.rs:+1:34: +1:44
- ((_3 as Some).0: bool) = const true; // scope 2 at $DIR/discriminant.rs:+1:34: +1:44
- discriminant(_3) = 1; // scope 2 at $DIR/discriminant.rs:+1:34: +1:44
+- _3 = Option::<bool>::Some(const true); // scope 2 at $DIR/discriminant.rs:+1:34: +1:44
- _4 = discriminant(_3); // scope 2 at $DIR/discriminant.rs:+1:21: +1:31
- switchInt(move _4) -> [1: bb1, otherwise: bb3]; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31
++ _3 = const Option::<bool>::Some(true); // scope 2 at $DIR/discriminant.rs:+1:34: +1:44
++ // mir::Constant
++ // + span: $DIR/discriminant.rs:12:34: 12:44
++ // + literal: Const { ty: Option<bool>, val: Value(Scalar(0x01)) }
+ _4 = const 1_isize; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31
+ switchInt(const 1_isize) -> [1: bb1, otherwise: bb3]; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31
}
bb1: {
- switchInt(((_3 as Some).0: bool)) -> [0: bb3, otherwise: bb2]; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31
+- switchInt(((_3 as Some).0: bool)) -> [0: bb3, otherwise: bb2]; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31
++ switchInt(const true) -> [0: bb3, otherwise: bb2]; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31
}
bb2: {
bb0: {
StorageLive(_1); // scope 0 at $DIR/invalid_constant.rs:+6:9: +6:22
StorageLive(_2); // scope 2 at $DIR/invalid_constant.rs:+6:34: +6:63
- Deinit(_2); // scope 2 at $DIR/invalid_constant.rs:+6:34: +6:63
- (_2.0: u32) = const 1114113_u32; // scope 2 at $DIR/invalid_constant.rs:+6:34: +6:63
+ _2 = InvalidChar { int: const 1114113_u32 }; // scope 2 at $DIR/invalid_constant.rs:+6:34: +6:63
- _1 = (_2.1: char); // scope 2 at $DIR/invalid_constant.rs:+6:34: +6:67
+ _1 = const {transmute(0x00110001): char}; // scope 2 at $DIR/invalid_constant.rs:+6:34: +6:67
StorageDead(_2); // scope 0 at $DIR/invalid_constant.rs:+6:69: +6:70
StorageLive(_3); // scope 1 at $DIR/invalid_constant.rs:+13:9: +13:21
StorageLive(_4); // scope 1 at $DIR/invalid_constant.rs:+13:25: +13:59
StorageLive(_5); // scope 4 at $DIR/invalid_constant.rs:+13:34: +13:55
- Deinit(_5); // scope 4 at $DIR/invalid_constant.rs:+13:34: +13:55
- (_5.0: u32) = const 4_u32; // scope 4 at $DIR/invalid_constant.rs:+13:34: +13:55
+ _5 = InvalidTag { int: const 4_u32 }; // scope 4 at $DIR/invalid_constant.rs:+13:34: +13:55
- _4 = (_5.1: E); // scope 4 at $DIR/invalid_constant.rs:+13:34: +13:57
- _3 = [move _4]; // scope 1 at $DIR/invalid_constant.rs:+13:24: +13:60
+ _4 = const Scalar(0x00000004): E; // scope 4 at $DIR/invalid_constant.rs:+13:34: +13:57
let mut _0: (); // return place in scope 0 at $DIR/issue_66971.rs:+0:11: +0:11
let _1: (); // in scope 0 at $DIR/issue_66971.rs:+1:5: +1:23
let mut _2: ((), u8, u8); // in scope 0 at $DIR/issue_66971.rs:+1:12: +1:22
+ let mut _3: (); // in scope 0 at $DIR/issue_66971.rs:+1:13: +1:15
bb0: {
StorageLive(_1); // scope 0 at $DIR/issue_66971.rs:+1:5: +1:23
StorageLive(_2); // scope 0 at $DIR/issue_66971.rs:+1:12: +1:22
- Deinit(_2); // scope 0 at $DIR/issue_66971.rs:+1:12: +1:22
- (_2.1: u8) = const 0_u8; // scope 0 at $DIR/issue_66971.rs:+1:12: +1:22
- (_2.2: u8) = const 0_u8; // scope 0 at $DIR/issue_66971.rs:+1:12: +1:22
+ StorageLive(_3); // scope 0 at $DIR/issue_66971.rs:+1:13: +1:15
+ _2 = (move _3, const 0_u8, const 0_u8); // scope 0 at $DIR/issue_66971.rs:+1:12: +1:22
+ StorageDead(_3); // scope 0 at $DIR/issue_66971.rs:+1:21: +1:22
_1 = encode(move _2) -> bb1; // scope 0 at $DIR/issue_66971.rs:+1:5: +1:23
// mir::Constant
// + span: $DIR/issue_66971.rs:17:5: 17:11
StorageLive(_1); // scope 0 at $DIR/issue_67019.rs:+1:5: +1:20
StorageLive(_2); // scope 0 at $DIR/issue_67019.rs:+1:10: +1:19
StorageLive(_3); // scope 0 at $DIR/issue_67019.rs:+1:11: +1:17
- Deinit(_3); // scope 0 at $DIR/issue_67019.rs:+1:11: +1:17
- (_3.0: u8) = const 1_u8; // scope 0 at $DIR/issue_67019.rs:+1:11: +1:17
- (_3.1: u8) = const 2_u8; // scope 0 at $DIR/issue_67019.rs:+1:11: +1:17
- Deinit(_2); // scope 0 at $DIR/issue_67019.rs:+1:10: +1:19
-- (_2.0: (u8, u8)) = move _3; // scope 0 at $DIR/issue_67019.rs:+1:10: +1:19
-+ (_2.0: (u8, u8)) = const (1_u8, 2_u8); // scope 0 at $DIR/issue_67019.rs:+1:10: +1:19
+- _3 = (const 1_u8, const 2_u8); // scope 0 at $DIR/issue_67019.rs:+1:11: +1:17
++ _3 = const (1_u8, 2_u8); // scope 0 at $DIR/issue_67019.rs:+1:11: +1:17
+ _2 = (move _3,); // scope 0 at $DIR/issue_67019.rs:+1:10: +1:19
StorageDead(_3); // scope 0 at $DIR/issue_67019.rs:+1:18: +1:19
_1 = test(move _2) -> bb1; // scope 0 at $DIR/issue_67019.rs:+1:5: +1:20
// mir::Constant
bb0: {
StorageLive(_1); // scope 0 at $DIR/mutable_variable_aggregate.rs:+1:9: +1:14
- Deinit(_1); // scope 0 at $DIR/mutable_variable_aggregate.rs:+1:17: +1:25
- (_1.0: i32) = const 42_i32; // scope 0 at $DIR/mutable_variable_aggregate.rs:+1:17: +1:25
- (_1.1: i32) = const 43_i32; // scope 0 at $DIR/mutable_variable_aggregate.rs:+1:17: +1:25
+- _1 = (const 42_i32, const 43_i32); // scope 0 at $DIR/mutable_variable_aggregate.rs:+1:17: +1:25
++ _1 = const (42_i32, 43_i32); // scope 0 at $DIR/mutable_variable_aggregate.rs:+1:17: +1:25
(_1.1: i32) = const 99_i32; // scope 1 at $DIR/mutable_variable_aggregate.rs:+2:5: +2:13
StorageLive(_2); // scope 1 at $DIR/mutable_variable_aggregate.rs:+3:9: +3:10
- _2 = _1; // scope 1 at $DIR/mutable_variable_aggregate.rs:+3:13: +3:14
bb0: {
StorageLive(_1); // scope 0 at $DIR/mutable_variable_aggregate_mut_ref.rs:+1:9: +1:14
- Deinit(_1); // scope 0 at $DIR/mutable_variable_aggregate_mut_ref.rs:+1:17: +1:25
- (_1.0: i32) = const 42_i32; // scope 0 at $DIR/mutable_variable_aggregate_mut_ref.rs:+1:17: +1:25
- (_1.1: i32) = const 43_i32; // scope 0 at $DIR/mutable_variable_aggregate_mut_ref.rs:+1:17: +1:25
+ _1 = (const 42_i32, const 43_i32); // scope 0 at $DIR/mutable_variable_aggregate_mut_ref.rs:+1:17: +1:25
StorageLive(_2); // scope 1 at $DIR/mutable_variable_aggregate_mut_ref.rs:+2:9: +2:10
_2 = &mut _1; // scope 1 at $DIR/mutable_variable_aggregate_mut_ref.rs:+2:13: +2:19
((*_2).1: i32) = const 99_i32; // scope 2 at $DIR/mutable_variable_aggregate_mut_ref.rs:+3:5: +3:13
fn main() -> () {
let mut _0: (); // return place in scope 0 at $DIR/mutable_variable_unprop_assign.rs:+0:11: +0:11
let _1: i32; // in scope 0 at $DIR/mutable_variable_unprop_assign.rs:+1:9: +1:10
- let mut _2: i32; // in scope 0 at $DIR/mutable_variable_unprop_assign.rs:+3:11: +3:12
+ let mut _3: i32; // in scope 0 at $DIR/mutable_variable_unprop_assign.rs:+3:11: +3:12
scope 1 {
debug a => _1; // in scope 1 at $DIR/mutable_variable_unprop_assign.rs:+1:9: +1:10
- let mut _5: i32; // in scope 1 at $DIR/mutable_variable_unprop_assign.rs:+2:9: +2:14
- let mut _6: i32; // in scope 1 at $DIR/mutable_variable_unprop_assign.rs:+2:9: +2:14
+ let mut _2: (i32, i32); // in scope 1 at $DIR/mutable_variable_unprop_assign.rs:+2:9: +2:14
scope 2 {
- debug x => (i32, i32){ .0 => _5, .1 => _6, }; // in scope 2 at $DIR/mutable_variable_unprop_assign.rs:+2:9: +2:14
- let _3: i32; // in scope 2 at $DIR/mutable_variable_unprop_assign.rs:+4:9: +4:10
+ debug x => _2; // in scope 2 at $DIR/mutable_variable_unprop_assign.rs:+2:9: +2:14
+ let _4: i32; // in scope 2 at $DIR/mutable_variable_unprop_assign.rs:+4:9: +4:10
scope 3 {
- debug y => _3; // in scope 3 at $DIR/mutable_variable_unprop_assign.rs:+4:9: +4:10
- let _4: i32; // in scope 3 at $DIR/mutable_variable_unprop_assign.rs:+5:9: +5:10
+ debug y => _4; // in scope 3 at $DIR/mutable_variable_unprop_assign.rs:+4:9: +4:10
+ let _5: i32; // in scope 3 at $DIR/mutable_variable_unprop_assign.rs:+5:9: +5:10
scope 4 {
- debug z => _4; // in scope 4 at $DIR/mutable_variable_unprop_assign.rs:+5:9: +5:10
+ debug z => _5; // in scope 4 at $DIR/mutable_variable_unprop_assign.rs:+5:9: +5:10
}
}
}
}
bb1: {
- StorageLive(_5); // scope 1 at $DIR/mutable_variable_unprop_assign.rs:+2:9: +2:14
- StorageLive(_6); // scope 1 at $DIR/mutable_variable_unprop_assign.rs:+2:9: +2:14
- Deinit(_5); // scope 1 at $DIR/mutable_variable_unprop_assign.rs:+2:29: +2:35
- Deinit(_6); // scope 1 at $DIR/mutable_variable_unprop_assign.rs:+2:29: +2:35
- _5 = const 1_i32; // scope 1 at $DIR/mutable_variable_unprop_assign.rs:+2:29: +2:35
- _6 = const 2_i32; // scope 1 at $DIR/mutable_variable_unprop_assign.rs:+2:29: +2:35
- StorageLive(_2); // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+3:11: +3:12
- _2 = _1; // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+3:11: +3:12
- _6 = move _2; // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+3:5: +3:12
- StorageDead(_2); // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+3:11: +3:12
- StorageLive(_3); // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+4:9: +4:10
- _3 = _6; // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+4:13: +4:16
- StorageLive(_4); // scope 3 at $DIR/mutable_variable_unprop_assign.rs:+5:9: +5:10
-- _4 = _5; // scope 3 at $DIR/mutable_variable_unprop_assign.rs:+5:13: +5:16
-+ _4 = const 1_i32; // scope 3 at $DIR/mutable_variable_unprop_assign.rs:+5:13: +5:16
- StorageDead(_4); // scope 3 at $DIR/mutable_variable_unprop_assign.rs:+6:1: +6:2
- StorageDead(_3); // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+6:1: +6:2
- StorageDead(_5); // scope 1 at $DIR/mutable_variable_unprop_assign.rs:+6:1: +6:2
- StorageDead(_6); // scope 1 at $DIR/mutable_variable_unprop_assign.rs:+6:1: +6:2
+ StorageLive(_2); // scope 1 at $DIR/mutable_variable_unprop_assign.rs:+2:9: +2:14
+- _2 = (const 1_i32, const 2_i32); // scope 1 at $DIR/mutable_variable_unprop_assign.rs:+2:29: +2:35
++ _2 = const (1_i32, 2_i32); // scope 1 at $DIR/mutable_variable_unprop_assign.rs:+2:29: +2:35
+ StorageLive(_3); // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+3:11: +3:12
+ _3 = _1; // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+3:11: +3:12
+ (_2.1: i32) = move _3; // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+3:5: +3:12
+ StorageDead(_3); // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+3:11: +3:12
+ StorageLive(_4); // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+4:9: +4:10
+ _4 = (_2.1: i32); // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+4:13: +4:16
+ StorageLive(_5); // scope 3 at $DIR/mutable_variable_unprop_assign.rs:+5:9: +5:10
+- _5 = (_2.0: i32); // scope 3 at $DIR/mutable_variable_unprop_assign.rs:+5:13: +5:16
++ _5 = const 1_i32; // scope 3 at $DIR/mutable_variable_unprop_assign.rs:+5:13: +5:16
+ StorageDead(_5); // scope 3 at $DIR/mutable_variable_unprop_assign.rs:+6:1: +6:2
+ StorageDead(_4); // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+6:1: +6:2
+ StorageDead(_2); // scope 1 at $DIR/mutable_variable_unprop_assign.rs:+6:1: +6:2
StorageDead(_1); // scope 0 at $DIR/mutable_variable_unprop_assign.rs:+6:1: +6:2
return; // scope 0 at $DIR/mutable_variable_unprop_assign.rs:+6:2: +6:2
}
let _5: usize; // in scope 0 at $DIR/optimizes_into_variable.rs:+2:32: +2:33
let mut _6: usize; // in scope 0 at $DIR/optimizes_into_variable.rs:+2:13: +2:34
let mut _7: bool; // in scope 0 at $DIR/optimizes_into_variable.rs:+2:13: +2:34
- let mut _9: u32; // in scope 0 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
+ let mut _9: Point; // in scope 0 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
scope 1 {
debug x => _1; // in scope 1 at $DIR/optimizes_into_variable.rs:+1:9: +1:10
let _3: i32; // in scope 1 at $DIR/optimizes_into_variable.rs:+2:9: +2:10
StorageDead(_4); // scope 1 at $DIR/optimizes_into_variable.rs:+2:34: +2:35
StorageLive(_8); // scope 2 at $DIR/optimizes_into_variable.rs:+3:9: +3:10
StorageLive(_9); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
- Deinit(_9); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
- _9 = const 42_u32; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
-- _8 = _9; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:38
+ _9 = Point { x: const 12_u32, y: const 42_u32 }; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
+- _8 = (_9.1: u32); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:38
+ _8 = const 42_u32; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:38
StorageDead(_9); // scope 2 at $DIR/optimizes_into_variable.rs:+3:38: +3:39
StorageDead(_8); // scope 2 at $DIR/optimizes_into_variable.rs:+4:1: +4:2
let _5: usize; // in scope 0 at $DIR/optimizes_into_variable.rs:+2:32: +2:33
let mut _6: usize; // in scope 0 at $DIR/optimizes_into_variable.rs:+2:13: +2:34
let mut _7: bool; // in scope 0 at $DIR/optimizes_into_variable.rs:+2:13: +2:34
- let mut _9: u32; // in scope 0 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
+ let mut _9: Point; // in scope 0 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
scope 1 {
debug x => _1; // in scope 1 at $DIR/optimizes_into_variable.rs:+1:9: +1:10
let _3: i32; // in scope 1 at $DIR/optimizes_into_variable.rs:+2:9: +2:10
StorageDead(_4); // scope 1 at $DIR/optimizes_into_variable.rs:+2:34: +2:35
StorageLive(_8); // scope 2 at $DIR/optimizes_into_variable.rs:+3:9: +3:10
StorageLive(_9); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
- Deinit(_9); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
- _9 = const 42_u32; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
-- _8 = _9; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:38
+ _9 = Point { x: const 12_u32, y: const 42_u32 }; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
+- _8 = (_9.1: u32); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:38
+ _8 = const 42_u32; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:38
StorageDead(_9); // scope 2 at $DIR/optimizes_into_variable.rs:+3:38: +3:39
StorageDead(_8); // scope 2 at $DIR/optimizes_into_variable.rs:+4:1: +4:2
let mut _6: usize; // in scope 0 at $DIR/optimizes_into_variable.rs:+2:13: +2:34
let mut _7: bool; // in scope 0 at $DIR/optimizes_into_variable.rs:+2:13: +2:34
let mut _9: Point; // in scope 0 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
-+ let mut _10: u32; // in scope 0 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
-+ let mut _11: u32; // in scope 0 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
scope 1 {
debug x => _1; // in scope 1 at $DIR/optimizes_into_variable.rs:+1:9: +1:10
let _3: i32; // in scope 1 at $DIR/optimizes_into_variable.rs:+2:9: +2:10
StorageDead(_5); // scope 1 at $DIR/optimizes_into_variable.rs:+2:34: +2:35
StorageDead(_4); // scope 1 at $DIR/optimizes_into_variable.rs:+2:34: +2:35
StorageLive(_8); // scope 2 at $DIR/optimizes_into_variable.rs:+3:9: +3:10
-- StorageLive(_9); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
-- Deinit(_9); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
-- (_9.0: u32) = const 12_u32; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
-- (_9.1: u32) = const 42_u32; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
-- _8 = (_9.1: u32); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:38
-- StorageDead(_9); // scope 2 at $DIR/optimizes_into_variable.rs:+3:38: +3:39
-+ StorageLive(_10); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
-+ StorageLive(_11); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
-+ Deinit(_10); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
-+ Deinit(_11); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
-+ _10 = const 12_u32; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
-+ _11 = const 42_u32; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
-+ _8 = _11; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:38
-+ StorageDead(_10); // scope 2 at $DIR/optimizes_into_variable.rs:+3:38: +3:39
-+ StorageDead(_11); // scope 2 at $DIR/optimizes_into_variable.rs:+3:38: +3:39
+ StorageLive(_9); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
+ _9 = Point { x: const 12_u32, y: const 42_u32 }; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
+ _8 = (_9.1: u32); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:38
+ StorageDead(_9); // scope 2 at $DIR/optimizes_into_variable.rs:+3:38: +3:39
nop; // scope 0 at $DIR/optimizes_into_variable.rs:+0:11: +4:2
StorageDead(_8); // scope 2 at $DIR/optimizes_into_variable.rs:+4:1: +4:2
StorageDead(_3); // scope 1 at $DIR/optimizes_into_variable.rs:+4:1: +4:2
let mut _6: usize; // in scope 0 at $DIR/optimizes_into_variable.rs:+2:13: +2:34
let mut _7: bool; // in scope 0 at $DIR/optimizes_into_variable.rs:+2:13: +2:34
let mut _9: Point; // in scope 0 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
-+ let mut _10: u32; // in scope 0 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
-+ let mut _11: u32; // in scope 0 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
scope 1 {
debug x => _1; // in scope 1 at $DIR/optimizes_into_variable.rs:+1:9: +1:10
let _3: i32; // in scope 1 at $DIR/optimizes_into_variable.rs:+2:9: +2:10
StorageDead(_5); // scope 1 at $DIR/optimizes_into_variable.rs:+2:34: +2:35
StorageDead(_4); // scope 1 at $DIR/optimizes_into_variable.rs:+2:34: +2:35
StorageLive(_8); // scope 2 at $DIR/optimizes_into_variable.rs:+3:9: +3:10
-- StorageLive(_9); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
-- Deinit(_9); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
-- (_9.0: u32) = const 12_u32; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
-- (_9.1: u32) = const 42_u32; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
-- _8 = (_9.1: u32); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:38
-- StorageDead(_9); // scope 2 at $DIR/optimizes_into_variable.rs:+3:38: +3:39
-+ StorageLive(_10); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
-+ StorageLive(_11); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
-+ Deinit(_10); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
-+ Deinit(_11); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
-+ _10 = const 12_u32; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
-+ _11 = const 42_u32; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
-+ _8 = _11; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:38
-+ StorageDead(_10); // scope 2 at $DIR/optimizes_into_variable.rs:+3:38: +3:39
-+ StorageDead(_11); // scope 2 at $DIR/optimizes_into_variable.rs:+3:38: +3:39
+ StorageLive(_9); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
+ _9 = Point { x: const 12_u32, y: const 42_u32 }; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36
+ _8 = (_9.1: u32); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:38
+ StorageDead(_9); // scope 2 at $DIR/optimizes_into_variable.rs:+3:38: +3:39
nop; // scope 0 at $DIR/optimizes_into_variable.rs:+0:11: +4:2
StorageDead(_8); // scope 2 at $DIR/optimizes_into_variable.rs:+4:1: +4:2
StorageDead(_3); // scope 1 at $DIR/optimizes_into_variable.rs:+4:1: +4:2
}
bb0: {
- StorageLive(_1); // scope 0 at $DIR/tuple_literal_propagation.rs:+1:9: +1:10
- Deinit(_1); // scope 0 at $DIR/tuple_literal_propagation.rs:+1:13: +1:19
- (_1.0: u32) = const 1_u32; // scope 0 at $DIR/tuple_literal_propagation.rs:+1:13: +1:19
- (_1.1: u32) = const 2_u32; // scope 0 at $DIR/tuple_literal_propagation.rs:+1:13: +1:19
+- _1 = (const 1_u32, const 2_u32); // scope 0 at $DIR/tuple_literal_propagation.rs:+1:13: +1:19
++ _1 = const (1_u32, 2_u32); // scope 0 at $DIR/tuple_literal_propagation.rs:+1:13: +1:19
StorageLive(_2); // scope 1 at $DIR/tuple_literal_propagation.rs:+3:5: +3:15
- StorageLive(_3); // scope 1 at $DIR/tuple_literal_propagation.rs:+3:13: +3:14
-- _3 = _1; // scope 1 at $DIR/tuple_literal_propagation.rs:+3:13: +3:14
-+ _3 = const (1_u32, 2_u32); // scope 1 at $DIR/tuple_literal_propagation.rs:+3:13: +3:14
- _2 = consume(move _3) -> bb1; // scope 1 at $DIR/tuple_literal_propagation.rs:+3:5: +3:15
+ _2 = consume(_1) -> bb1; // scope 1 at $DIR/tuple_literal_propagation.rs:+3:5: +3:15
// mir::Constant
// + span: $DIR/tuple_literal_propagation.rs:5:5: 5:12
// + literal: Const { ty: fn((u32, u32)) {consume}, val: Value(<ZST>) }
}
bb1: {
- StorageDead(_3); // scope 1 at $DIR/tuple_literal_propagation.rs:+3:14: +3:15
StorageDead(_2); // scope 1 at $DIR/tuple_literal_propagation.rs:+3:15: +3:16
- StorageDead(_1); // scope 0 at $DIR/tuple_literal_propagation.rs:+4:1: +4:2
return; // scope 0 at $DIR/tuple_literal_propagation.rs:+4:2: +4:2
}
}
bb0: {
StorageLive(_1); // scope 0 at $DIR/const_prop_miscompile.rs:+1:9: +1:14
- Deinit(_1); // scope 0 at $DIR/const_prop_miscompile.rs:+1:17: +1:21
- (_1.0: i32) = const 1_i32; // scope 0 at $DIR/const_prop_miscompile.rs:+1:17: +1:21
+- _1 = (const 1_i32,); // scope 0 at $DIR/const_prop_miscompile.rs:+1:17: +1:21
++ _1 = const (1_i32,); // scope 0 at $DIR/const_prop_miscompile.rs:+1:17: +1:21
StorageLive(_2); // scope 1 at $DIR/const_prop_miscompile.rs:+2:5: +4:6
StorageLive(_3); // scope 2 at $DIR/const_prop_miscompile.rs:+3:10: +3:22
_3 = &raw mut (_1.0: i32); // scope 2 at $DIR/const_prop_miscompile.rs:+3:10: +3:22
bb0: {
StorageLive(_1); // scope 0 at $DIR/const_prop_miscompile.rs:+1:9: +1:14
- Deinit(_1); // scope 0 at $DIR/const_prop_miscompile.rs:+1:17: +1:21
- (_1.0: i32) = const 1_i32; // scope 0 at $DIR/const_prop_miscompile.rs:+1:17: +1:21
+- _1 = (const 1_i32,); // scope 0 at $DIR/const_prop_miscompile.rs:+1:17: +1:21
++ _1 = const (1_i32,); // scope 0 at $DIR/const_prop_miscompile.rs:+1:17: +1:21
StorageLive(_2); // scope 1 at $DIR/const_prop_miscompile.rs:+2:6: +2:14
_2 = &mut (_1.0: i32); // scope 1 at $DIR/const_prop_miscompile.rs:+2:6: +2:14
(*_2) = const 5_i32; // scope 1 at $DIR/const_prop_miscompile.rs:+2:5: +2:18
bb1: {
StorageDead(_6); // scope 2 at $DIR/issue_107511.rs:+6:23: +6:24
- Deinit(_4); // scope 2 at $DIR/issue_107511.rs:+6:14: +6:24
- (_4.0: usize) = const 0_usize; // scope 2 at $DIR/issue_107511.rs:+6:14: +6:24
- (_4.1: usize) = move _5; // scope 2 at $DIR/issue_107511.rs:+6:14: +6:24
+ _4 = std::ops::Range::<usize> { start: const 0_usize, end: move _5 }; // scope 2 at $DIR/issue_107511.rs:+6:14: +6:24
StorageDead(_5); // scope 2 at $DIR/issue_107511.rs:+6:23: +6:24
_3 = <std::ops::Range<usize> as IntoIterator>::into_iter(move _4) -> bb2; // scope 2 at $DIR/issue_107511.rs:+6:14: +6:24
// mir::Constant
bb0: {
StorageLive(_1); // scope 0 at $DIR/enum.rs:+1:9: +1:10
- Deinit(_1); // scope 0 at $DIR/enum.rs:+1:13: +1:21
- ((_1 as V1).0: i32) = const 0_i32; // scope 0 at $DIR/enum.rs:+1:13: +1:21
- discriminant(_1) = 0; // scope 0 at $DIR/enum.rs:+1:13: +1:21
+ _1 = E::V1(const 0_i32); // scope 0 at $DIR/enum.rs:+1:13: +1:21
StorageLive(_2); // scope 1 at $DIR/enum.rs:+2:9: +2:10
_3 = discriminant(_1); // scope 1 at $DIR/enum.rs:+2:19: +2:20
switchInt(move _3) -> [0: bb3, 1: bb1, otherwise: bb2]; // scope 1 at $DIR/enum.rs:+2:13: +2:20
bb0: {
StorageLive(_1); // scope 0 at $DIR/repr_transparent.rs:+1:9: +1:10
- Deinit(_1); // scope 0 at $DIR/repr_transparent.rs:+1:13: +1:19
- (_1.0: i32) = const 0_i32; // scope 0 at $DIR/repr_transparent.rs:+1:13: +1:19
+ _1 = I32(const 0_i32); // scope 0 at $DIR/repr_transparent.rs:+1:13: +1:19
StorageLive(_2); // scope 1 at $DIR/repr_transparent.rs:+2:9: +2:10
StorageLive(_3); // scope 1 at $DIR/repr_transparent.rs:+2:17: +2:26
StorageLive(_4); // scope 1 at $DIR/repr_transparent.rs:+2:17: +2:20
+ _3 = const 0_i32; // scope 1 at $DIR/repr_transparent.rs:+2:17: +2:26
StorageDead(_5); // scope 1 at $DIR/repr_transparent.rs:+2:25: +2:26
StorageDead(_4); // scope 1 at $DIR/repr_transparent.rs:+2:25: +2:26
- Deinit(_2); // scope 1 at $DIR/repr_transparent.rs:+2:13: +2:27
-- (_2.0: i32) = move _3; // scope 1 at $DIR/repr_transparent.rs:+2:13: +2:27
-+ (_2.0: i32) = const 0_i32; // scope 1 at $DIR/repr_transparent.rs:+2:13: +2:27
+- _2 = I32(move _3); // scope 1 at $DIR/repr_transparent.rs:+2:13: +2:27
++ _2 = I32(const 0_i32); // scope 1 at $DIR/repr_transparent.rs:+2:13: +2:27
StorageDead(_3); // scope 1 at $DIR/repr_transparent.rs:+2:26: +2:27
_0 = const (); // scope 0 at $DIR/repr_transparent.rs:+0:11: +3:2
StorageDead(_2); // scope 1 at $DIR/repr_transparent.rs:+3:1: +3:2
bb0: {
StorageLive(_1); // scope 0 at $DIR/sibling_ptr.rs:+1:9: +1:14
- Deinit(_1); // scope 0 at $DIR/sibling_ptr.rs:+1:27: +1:33
- (_1.0: u8) = const 0_u8; // scope 0 at $DIR/sibling_ptr.rs:+1:27: +1:33
- (_1.1: u8) = const 0_u8; // scope 0 at $DIR/sibling_ptr.rs:+1:27: +1:33
+ _1 = (const 0_u8, const 0_u8); // scope 0 at $DIR/sibling_ptr.rs:+1:27: +1:33
StorageLive(_2); // scope 1 at $DIR/sibling_ptr.rs:+2:5: +5:6
StorageLive(_3); // scope 2 at $DIR/sibling_ptr.rs:+3:13: +3:14
_3 = &raw mut (_1.0: u8); // scope 2 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
bb0: {
StorageLive(_1); // scope 0 at $DIR/struct.rs:+1:9: +1:14
- Deinit(_1); // scope 0 at $DIR/struct.rs:+1:17: +1:21
- (_1.0: i32) = const 1_i32; // scope 0 at $DIR/struct.rs:+1:17: +1:21
+ _1 = S(const 1_i32); // scope 0 at $DIR/struct.rs:+1:17: +1:21
StorageLive(_2); // scope 1 at $DIR/struct.rs:+2:9: +2:10
StorageLive(_3); // scope 1 at $DIR/struct.rs:+2:13: +2:16
- _3 = (_1.0: i32); // scope 1 at $DIR/struct.rs:+2:13: +2:16
bb0: {
StorageLive(_1); // scope 0 at $DIR/tuple.rs:+1:9: +1:14
- Deinit(_1); // scope 0 at $DIR/tuple.rs:+1:17: +1:23
- (_1.0: i32) = const 1_i32; // scope 0 at $DIR/tuple.rs:+1:17: +1:23
- (_1.1: i32) = const 2_i32; // scope 0 at $DIR/tuple.rs:+1:17: +1:23
+ _1 = (const 1_i32, const 2_i32); // scope 0 at $DIR/tuple.rs:+1:17: +1:23
StorageLive(_2); // scope 1 at $DIR/tuple.rs:+2:9: +2:10
StorageLive(_3); // scope 1 at $DIR/tuple.rs:+2:13: +2:22
StorageLive(_4); // scope 1 at $DIR/tuple.rs:+2:13: +2:16
- _2 = Add(move _3, const 3_i32); // scope 1 at $DIR/tuple.rs:+2:13: +2:26
+ _2 = const 6_i32; // scope 1 at $DIR/tuple.rs:+2:13: +2:26
StorageDead(_3); // scope 1 at $DIR/tuple.rs:+2:25: +2:26
- Deinit(_1); // scope 2 at $DIR/tuple.rs:+3:5: +3:15
- (_1.0: i32) = const 2_i32; // scope 2 at $DIR/tuple.rs:+3:5: +3:15
- (_1.1: i32) = const 3_i32; // scope 2 at $DIR/tuple.rs:+3:5: +3:15
+ _1 = (const 2_i32, const 3_i32); // scope 2 at $DIR/tuple.rs:+3:5: +3:15
StorageLive(_6); // scope 2 at $DIR/tuple.rs:+4:9: +4:10
StorageLive(_7); // scope 2 at $DIR/tuple.rs:+4:13: +4:22
StorageLive(_8); // scope 2 at $DIR/tuple.rs:+4:13: +4:16
+++ /dev/null
-- // MIR for `bar` before Deaggregator
-+ // MIR for `bar` after Deaggregator
-
- fn bar(_1: usize) -> Baz {
- debug a => _1; // in scope 0 at $DIR/deaggregator_test.rs:+0:8: +0:9
- let mut _0: Baz; // return place in scope 0 at $DIR/deaggregator_test.rs:+0:21: +0:24
- let mut _2: usize; // in scope 0 at $DIR/deaggregator_test.rs:+1:14: +1:15
-
- bb0: {
- StorageLive(_2); // scope 0 at $DIR/deaggregator_test.rs:+1:14: +1:15
- _2 = _1; // scope 0 at $DIR/deaggregator_test.rs:+1:14: +1:15
-- _0 = Baz { x: move _2, y: const 0f32, z: const false }; // scope 0 at $DIR/deaggregator_test.rs:+1:5: +1:35
-+ Deinit(_0); // scope 0 at $DIR/deaggregator_test.rs:+1:5: +1:35
-+ (_0.0: usize) = move _2; // scope 0 at $DIR/deaggregator_test.rs:+1:5: +1:35
-+ (_0.1: f32) = const 0f32; // scope 0 at $DIR/deaggregator_test.rs:+1:5: +1:35
-+ (_0.2: bool) = const false; // scope 0 at $DIR/deaggregator_test.rs:+1:5: +1:35
- StorageDead(_2); // scope 0 at $DIR/deaggregator_test.rs:+1:34: +1:35
- return; // scope 0 at $DIR/deaggregator_test.rs:+2:2: +2:2
- }
- }
-
+++ /dev/null
-// unit-test: Deaggregator
-
-struct Baz {
- x: usize,
- y: f32,
- z: bool,
-}
-
-// EMIT_MIR deaggregator_test.bar.Deaggregator.diff
-fn bar(a: usize) -> Baz {
- Baz { x: a, y: 0.0, z: false }
-}
-
-fn main() {
- // Make sure the function actually gets instantiated.
- bar(0);
-}
+++ /dev/null
-- // MIR for `bar` before Deaggregator
-+ // MIR for `bar` after Deaggregator
-
- fn bar(_1: usize) -> Baz {
- debug a => _1; // in scope 0 at $DIR/deaggregator_test_enum.rs:+0:8: +0:9
- let mut _0: Baz; // return place in scope 0 at $DIR/deaggregator_test_enum.rs:+0:21: +0:24
- let mut _2: usize; // in scope 0 at $DIR/deaggregator_test_enum.rs:+1:19: +1:20
-
- bb0: {
- StorageLive(_2); // scope 0 at $DIR/deaggregator_test_enum.rs:+1:19: +1:20
- _2 = _1; // scope 0 at $DIR/deaggregator_test_enum.rs:+1:19: +1:20
-- _0 = Baz::Foo { x: move _2 }; // scope 0 at $DIR/deaggregator_test_enum.rs:+1:5: +1:22
-+ Deinit(_0); // scope 0 at $DIR/deaggregator_test_enum.rs:+1:5: +1:22
-+ ((_0 as Foo).0: usize) = move _2; // scope 0 at $DIR/deaggregator_test_enum.rs:+1:5: +1:22
-+ discriminant(_0) = 1; // scope 0 at $DIR/deaggregator_test_enum.rs:+1:5: +1:22
- StorageDead(_2); // scope 0 at $DIR/deaggregator_test_enum.rs:+1:21: +1:22
- return; // scope 0 at $DIR/deaggregator_test_enum.rs:+2:2: +2:2
- }
- }
-
+++ /dev/null
-// unit-test: Deaggregator
-
-enum Baz {
- Empty,
- Foo { x: usize },
-}
-
-// EMIT_MIR deaggregator_test_enum.bar.Deaggregator.diff
-fn bar(a: usize) -> Baz {
- Baz::Foo { x: a }
-}
-
-fn main() {
- let x = bar(10);
- match x {
- Baz::Empty => println!("empty"),
- Baz::Foo { x } => println!("{}", x),
- };
-}
+++ /dev/null
-// unit-test: Deaggregator
-// Test that deaggregate fires in more than one basic block
-
-enum Foo {
- A(i32),
- B(i32),
-}
-
-// EMIT_MIR deaggregator_test_enum_2.test1.Deaggregator.diff
-fn test1(x: bool, y: i32) -> Foo {
- if x {
- Foo::A(y)
- } else {
- Foo::B(y)
- }
-}
-
-fn main() {
- // Make sure the function actually gets instantiated.
- test1(false, 0);
-}
+++ /dev/null
-- // MIR for `test1` before Deaggregator
-+ // MIR for `test1` after Deaggregator
-
- fn test1(_1: bool, _2: i32) -> Foo {
- debug x => _1; // in scope 0 at $DIR/deaggregator_test_enum_2.rs:+0:10: +0:11
- debug y => _2; // in scope 0 at $DIR/deaggregator_test_enum_2.rs:+0:19: +0:20
- let mut _0: Foo; // return place in scope 0 at $DIR/deaggregator_test_enum_2.rs:+0:30: +0:33
- let mut _3: bool; // in scope 0 at $DIR/deaggregator_test_enum_2.rs:+1:8: +1:9
- let mut _4: i32; // in scope 0 at $DIR/deaggregator_test_enum_2.rs:+2:16: +2:17
- let mut _5: i32; // in scope 0 at $DIR/deaggregator_test_enum_2.rs:+4:16: +4:17
-
- bb0: {
- StorageLive(_3); // scope 0 at $DIR/deaggregator_test_enum_2.rs:+1:8: +1:9
- _3 = _1; // scope 0 at $DIR/deaggregator_test_enum_2.rs:+1:8: +1:9
- switchInt(move _3) -> [0: bb2, otherwise: bb1]; // scope 0 at $DIR/deaggregator_test_enum_2.rs:+1:8: +1:9
- }
-
- bb1: {
- StorageLive(_4); // scope 0 at $DIR/deaggregator_test_enum_2.rs:+2:16: +2:17
- _4 = _2; // scope 0 at $DIR/deaggregator_test_enum_2.rs:+2:16: +2:17
-- _0 = Foo::A(move _4); // scope 0 at $DIR/deaggregator_test_enum_2.rs:+2:9: +2:18
-+ Deinit(_0); // scope 0 at $DIR/deaggregator_test_enum_2.rs:+2:9: +2:18
-+ ((_0 as A).0: i32) = move _4; // scope 0 at $DIR/deaggregator_test_enum_2.rs:+2:9: +2:18
-+ discriminant(_0) = 0; // scope 0 at $DIR/deaggregator_test_enum_2.rs:+2:9: +2:18
- StorageDead(_4); // scope 0 at $DIR/deaggregator_test_enum_2.rs:+2:17: +2:18
- goto -> bb3; // scope 0 at $DIR/deaggregator_test_enum_2.rs:+1:5: +5:6
- }
-
- bb2: {
- StorageLive(_5); // scope 0 at $DIR/deaggregator_test_enum_2.rs:+4:16: +4:17
- _5 = _2; // scope 0 at $DIR/deaggregator_test_enum_2.rs:+4:16: +4:17
-- _0 = Foo::B(move _5); // scope 0 at $DIR/deaggregator_test_enum_2.rs:+4:9: +4:18
-+ Deinit(_0); // scope 0 at $DIR/deaggregator_test_enum_2.rs:+4:9: +4:18
-+ ((_0 as B).0: i32) = move _5; // scope 0 at $DIR/deaggregator_test_enum_2.rs:+4:9: +4:18
-+ discriminant(_0) = 1; // scope 0 at $DIR/deaggregator_test_enum_2.rs:+4:9: +4:18
- StorageDead(_5); // scope 0 at $DIR/deaggregator_test_enum_2.rs:+4:17: +4:18
- goto -> bb3; // scope 0 at $DIR/deaggregator_test_enum_2.rs:+1:5: +5:6
- }
-
- bb3: {
- StorageDead(_3); // scope 0 at $DIR/deaggregator_test_enum_2.rs:+5:5: +5:6
- return; // scope 0 at $DIR/deaggregator_test_enum_2.rs:+6:2: +6:2
- }
- }
-
+++ /dev/null
-// unit-test: Deaggregator
-// Test that deaggregate fires more than once per block
-
-enum Foo {
- A(i32),
- B,
-}
-
-// EMIT_MIR deaggregator_test_multiple.test.Deaggregator.diff
-fn test(x: i32) -> [Foo; 2] {
- [Foo::A(x), Foo::A(x)]
-}
-
-fn main() {
- // Make sure the function actually gets instantiated.
- test(0);
-}
+++ /dev/null
-- // MIR for `test` before Deaggregator
-+ // MIR for `test` after Deaggregator
-
- fn test(_1: i32) -> [Foo; 2] {
- debug x => _1; // in scope 0 at $DIR/deaggregator_test_multiple.rs:+0:9: +0:10
- let mut _0: [Foo; 2]; // return place in scope 0 at $DIR/deaggregator_test_multiple.rs:+0:20: +0:28
- let mut _2: Foo; // in scope 0 at $DIR/deaggregator_test_multiple.rs:+1:6: +1:15
- let mut _3: i32; // in scope 0 at $DIR/deaggregator_test_multiple.rs:+1:13: +1:14
- let mut _4: Foo; // in scope 0 at $DIR/deaggregator_test_multiple.rs:+1:17: +1:26
- let mut _5: i32; // in scope 0 at $DIR/deaggregator_test_multiple.rs:+1:24: +1:25
-
- bb0: {
- StorageLive(_2); // scope 0 at $DIR/deaggregator_test_multiple.rs:+1:6: +1:15
- StorageLive(_3); // scope 0 at $DIR/deaggregator_test_multiple.rs:+1:13: +1:14
- _3 = _1; // scope 0 at $DIR/deaggregator_test_multiple.rs:+1:13: +1:14
-- _2 = Foo::A(move _3); // scope 0 at $DIR/deaggregator_test_multiple.rs:+1:6: +1:15
-+ Deinit(_2); // scope 0 at $DIR/deaggregator_test_multiple.rs:+1:6: +1:15
-+ ((_2 as A).0: i32) = move _3; // scope 0 at $DIR/deaggregator_test_multiple.rs:+1:6: +1:15
-+ discriminant(_2) = 0; // scope 0 at $DIR/deaggregator_test_multiple.rs:+1:6: +1:15
- StorageDead(_3); // scope 0 at $DIR/deaggregator_test_multiple.rs:+1:14: +1:15
- StorageLive(_4); // scope 0 at $DIR/deaggregator_test_multiple.rs:+1:17: +1:26
- StorageLive(_5); // scope 0 at $DIR/deaggregator_test_multiple.rs:+1:24: +1:25
- _5 = _1; // scope 0 at $DIR/deaggregator_test_multiple.rs:+1:24: +1:25
-- _4 = Foo::A(move _5); // scope 0 at $DIR/deaggregator_test_multiple.rs:+1:17: +1:26
-+ Deinit(_4); // scope 0 at $DIR/deaggregator_test_multiple.rs:+1:17: +1:26
-+ ((_4 as A).0: i32) = move _5; // scope 0 at $DIR/deaggregator_test_multiple.rs:+1:17: +1:26
-+ discriminant(_4) = 0; // scope 0 at $DIR/deaggregator_test_multiple.rs:+1:17: +1:26
- StorageDead(_5); // scope 0 at $DIR/deaggregator_test_multiple.rs:+1:25: +1:26
- _0 = [move _2, move _4]; // scope 0 at $DIR/deaggregator_test_multiple.rs:+1:5: +1:27
- StorageDead(_4); // scope 0 at $DIR/deaggregator_test_multiple.rs:+1:26: +1:27
- StorageDead(_2); // scope 0 at $DIR/deaggregator_test_multiple.rs:+1:26: +1:27
- return; // scope 0 at $DIR/deaggregator_test_multiple.rs:+2:2: +2:2
- }
- }
-
_4 = _1; // scope 0 at $DIR/early_otherwise_branch.rs:+1:12: +1:13
StorageLive(_5); // scope 0 at $DIR/early_otherwise_branch.rs:+1:15: +1:16
_5 = _2; // scope 0 at $DIR/early_otherwise_branch.rs:+1:15: +1:16
- Deinit(_3); // scope 0 at $DIR/early_otherwise_branch.rs:+1:11: +1:17
- (_3.0: std::option::Option<u32>) = move _4; // scope 0 at $DIR/early_otherwise_branch.rs:+1:11: +1:17
- (_3.1: std::option::Option<u32>) = move _5; // scope 0 at $DIR/early_otherwise_branch.rs:+1:11: +1:17
+ _3 = (move _4, move _5); // scope 0 at $DIR/early_otherwise_branch.rs:+1:11: +1:17
StorageDead(_5); // scope 0 at $DIR/early_otherwise_branch.rs:+1:16: +1:17
StorageDead(_4); // scope 0 at $DIR/early_otherwise_branch.rs:+1:16: +1:17
_7 = discriminant((_3.0: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch.rs:+1:11: +1:17
_4 = _1; // scope 0 at $DIR/early_otherwise_branch.rs:+1:12: +1:13
StorageLive(_5); // scope 0 at $DIR/early_otherwise_branch.rs:+1:15: +1:16
_5 = _2; // scope 0 at $DIR/early_otherwise_branch.rs:+1:15: +1:16
- Deinit(_3); // scope 0 at $DIR/early_otherwise_branch.rs:+1:11: +1:17
- (_3.0: std::option::Option<u32>) = move _4; // scope 0 at $DIR/early_otherwise_branch.rs:+1:11: +1:17
- (_3.1: std::option::Option<u32>) = move _5; // scope 0 at $DIR/early_otherwise_branch.rs:+1:11: +1:17
+ _3 = (move _4, move _5); // scope 0 at $DIR/early_otherwise_branch.rs:+1:11: +1:17
StorageDead(_5); // scope 0 at $DIR/early_otherwise_branch.rs:+1:16: +1:17
StorageDead(_4); // scope 0 at $DIR/early_otherwise_branch.rs:+1:16: +1:17
_8 = discriminant((_3.0: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch.rs:+1:11: +1:17
_4 = _1; // scope 0 at $DIR/early_otherwise_branch.rs:+1:12: +1:13
StorageLive(_5); // scope 0 at $DIR/early_otherwise_branch.rs:+1:15: +1:16
_5 = _2; // scope 0 at $DIR/early_otherwise_branch.rs:+1:15: +1:16
- Deinit(_3); // scope 0 at $DIR/early_otherwise_branch.rs:+1:11: +1:17
- (_3.0: std::option::Option<u32>) = move _4; // scope 0 at $DIR/early_otherwise_branch.rs:+1:11: +1:17
- (_3.1: std::option::Option<bool>) = move _5; // scope 0 at $DIR/early_otherwise_branch.rs:+1:11: +1:17
+ _3 = (move _4, move _5); // scope 0 at $DIR/early_otherwise_branch.rs:+1:11: +1:17
StorageDead(_5); // scope 0 at $DIR/early_otherwise_branch.rs:+1:16: +1:17
StorageDead(_4); // scope 0 at $DIR/early_otherwise_branch.rs:+1:16: +1:17
_7 = discriminant((_3.0: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch.rs:+1:11: +1:17
_6 = _2; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:15: +1:16
StorageLive(_7); // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:18: +1:19
_7 = _3; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:18: +1:19
- Deinit(_4); // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:11: +1:20
- (_4.0: std::option::Option<u32>) = move _5; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:11: +1:20
- (_4.1: std::option::Option<u32>) = move _6; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:11: +1:20
- (_4.2: std::option::Option<u32>) = move _7; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:11: +1:20
+ _4 = (move _5, move _6, move _7); // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:11: +1:20
StorageDead(_7); // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:19: +1:20
StorageDead(_6); // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:19: +1:20
StorageDead(_5); // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:19: +1:20
_5 = _1; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:15: +5:16
StorageLive(_6); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:18: +5:23
_6 = _2; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:18: +5:23
- Deinit(_4); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24
- (_4.0: &ViewportPercentageLength) = move _5; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24
- (_4.1: &ViewportPercentageLength) = move _6; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24
+ _4 = (move _5, move _6); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24
StorageDead(_6); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:23: +5:24
StorageDead(_5); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:23: +5:24
_34 = deref_copy (_4.0: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24
bb2: {
StorageLive(_33); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+10:25: +10:27
- Deinit(_33); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+10:25: +10:27
- Deinit(_0); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+10:21: +10:28
- ((_0 as Err).0: ()) = move _33; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+10:21: +10:28
- discriminant(_0) = 1; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+10:21: +10:28
+ _33 = (); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+10:25: +10:27
+ _0 = Result::<ViewportPercentageLength, ()>::Err(move _33); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+10:21: +10:28
StorageDead(_33); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+10:27: +10:28
StorageDead(_3); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+11:6: +11:7
StorageDead(_4); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+12:1: +12:2
_14 = Add(move _15, move _16); // scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:38: +6:49
StorageDead(_16); // scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:48: +6:49
StorageDead(_15); // scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:48: +6:49
- Deinit(_3); // scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:35: +6:50
- ((_3 as Vw).0: f32) = move _14; // scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:35: +6:50
- discriminant(_3) = 0; // scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:35: +6:50
+ _3 = ViewportPercentageLength::Vw(move _14); // scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:35: +6:50
StorageDead(_14); // scope 1 at $DIR/early_otherwise_branch_68867.rs:+6:49: +6:50
StorageDead(_13); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+6:49: +6:50
StorageDead(_12); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+6:49: +6:50
_19 = Add(move _20, move _21); // scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:38: +7:49
StorageDead(_21); // scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:48: +7:49
StorageDead(_20); // scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:48: +7:49
- Deinit(_3); // scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:35: +7:50
- ((_3 as Vh).0: f32) = move _19; // scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:35: +7:50
- discriminant(_3) = 1; // scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:35: +7:50
+ _3 = ViewportPercentageLength::Vh(move _19); // scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:35: +7:50
StorageDead(_19); // scope 2 at $DIR/early_otherwise_branch_68867.rs:+7:49: +7:50
StorageDead(_18); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+7:49: +7:50
StorageDead(_17); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+7:49: +7:50
_24 = Add(move _25, move _26); // scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:44: +8:55
StorageDead(_26); // scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:54: +8:55
StorageDead(_25); // scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:54: +8:55
- Deinit(_3); // scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:39: +8:56
- ((_3 as Vmin).0: f32) = move _24; // scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:39: +8:56
- discriminant(_3) = 2; // scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:39: +8:56
+ _3 = ViewportPercentageLength::Vmin(move _24); // scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:39: +8:56
StorageDead(_24); // scope 3 at $DIR/early_otherwise_branch_68867.rs:+8:55: +8:56
StorageDead(_23); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+8:55: +8:56
StorageDead(_22); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+8:55: +8:56
_29 = Add(move _30, move _31); // scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:44: +9:55
StorageDead(_31); // scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:54: +9:55
StorageDead(_30); // scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:54: +9:55
- Deinit(_3); // scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:39: +9:56
- ((_3 as Vmax).0: f32) = move _29; // scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:39: +9:56
- discriminant(_3) = 3; // scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:39: +9:56
+ _3 = ViewportPercentageLength::Vmax(move _29); // scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:39: +9:56
StorageDead(_29); // scope 4 at $DIR/early_otherwise_branch_68867.rs:+9:55: +9:56
StorageDead(_28); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+9:55: +9:56
StorageDead(_27); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+9:55: +9:56
}
bb10: {
- Deinit(_0); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:5: +11:7
- ((_0 as Ok).0: ViewportPercentageLength) = move _3; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:5: +11:7
- discriminant(_0) = 0; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:5: +11:7
+ _0 = Result::<ViewportPercentageLength, ()>::Ok(move _3); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:5: +11:7
StorageDead(_3); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+11:6: +11:7
StorageDead(_4); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+12:1: +12:2
goto -> bb11; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+12:2: +12:2
_4 = _1; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:+1:12: +1:13
StorageLive(_5); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:+1:15: +1:16
_5 = _2; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:+1:15: +1:16
- Deinit(_3); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:+1:11: +1:17
- (_3.0: std::option::Option<u32>) = move _4; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:+1:11: +1:17
- (_3.1: std::option::Option<u32>) = move _5; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:+1:11: +1:17
+ _3 = (move _4, move _5); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:+1:11: +1:17
StorageDead(_5); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:+1:16: +1:17
StorageDead(_4); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:+1:16: +1:17
_8 = discriminant((_3.0: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:+1:11: +1:17
}
bb2: {
- Deinit(_6); // scope 1 at $DIR/funky_arms.rs:+10:17: +10:41
- discriminant(_6) = 1; // scope 1 at $DIR/funky_arms.rs:+10:17: +10:41
+- _6 = MinusPlus; // scope 1 at $DIR/funky_arms.rs:+10:17: +10:41
++ _6 = const MinusPlus; // scope 1 at $DIR/funky_arms.rs:+10:17: +10:41
++ // mir::Constant
++ // + span: $DIR/funky_arms.rs:21:17: 21:41
++ // + literal: Const { ty: Sign, val: Value(Scalar(0x01)) }
goto -> bb4; // scope 1 at $DIR/funky_arms.rs:+10:17: +10:41
}
bb3: {
- Deinit(_6); // scope 1 at $DIR/funky_arms.rs:+9:18: +9:38
- discriminant(_6) = 0; // scope 1 at $DIR/funky_arms.rs:+9:18: +9:38
+- _6 = Minus; // scope 1 at $DIR/funky_arms.rs:+9:18: +9:38
++ _6 = const Minus; // scope 1 at $DIR/funky_arms.rs:+9:18: +9:38
++ // mir::Constant
++ // + span: $DIR/funky_arms.rs:20:18: 20:38
++ // + literal: Const { ty: Sign, val: Value(Scalar(0x00)) }
goto -> bb4; // scope 1 at $DIR/funky_arms.rs:+9:18: +9:38
}
StorageLive(_6); // scope 1 at $DIR/generator_tiny.rs:+3:13: +3:18
StorageLive(_7); // scope 1 at $DIR/generator_tiny.rs:+3:13: +3:18
_7 = (); // scope 1 at $DIR/generator_tiny.rs:+3:13: +3:18
- Deinit(_0); // scope 1 at $DIR/generator_tiny.rs:+3:13: +3:18
- ((_0 as Yielded).0: ()) = move _7; // scope 1 at $DIR/generator_tiny.rs:+3:13: +3:18
- discriminant(_0) = 0; // scope 1 at $DIR/generator_tiny.rs:+3:13: +3:18
+ _0 = GeneratorState::<(), ()>::Yielded(move _7); // scope 1 at $DIR/generator_tiny.rs:+3:13: +3:18
discriminant((*(_1.0: &mut [generator@$DIR/generator_tiny.rs:19:16: 19:24]))) = 3; // scope 1 at $DIR/generator_tiny.rs:+3:13: +3:18
return; // scope 1 at $DIR/generator_tiny.rs:+3:13: +3:18
}
StorageLive(_3); // scope 0 at $DIR/cycle.rs:+1:5: +1:6
_3 = &_1; // scope 0 at $DIR/cycle.rs:+1:5: +1:6
StorageLive(_4); // scope 0 at $DIR/cycle.rs:+1:5: +1:8
- Deinit(_4); // scope 0 at $DIR/cycle.rs:+1:5: +1:8
+ _4 = (); // scope 0 at $DIR/cycle.rs:+1:5: +1:8
_2 = <impl Fn() as Fn<()>>::call(move _3, move _4) -> [return: bb1, unwind: bb3]; // scope 0 at $DIR/cycle.rs:+1:5: +1:8
// mir::Constant
// + span: $DIR/cycle.rs:6:5: 6:6
bb0: {
StorageLive(_3); // scope 0 at $DIR/inline_closure.rs:+1:9: +1:10
- Deinit(_3); // scope 0 at $DIR/inline_closure.rs:+1:13: +1:24
+ _3 = [closure@foo::<T>::{closure#0}]; // scope 0 at $DIR/inline_closure.rs:+1:13: +1:24
+ // closure
+ // + def_id: DefId(0:6 ~ inline_closure[92ba]::foo::{closure#0})
+ // + substs: [
+ // T,
+ // i8,
+ // extern "rust-call" fn((i32, i32)) -> i32,
+ // (),
+ // ]
StorageLive(_4); // scope 1 at $DIR/inline_closure.rs:+2:5: +2:6
_4 = &_3; // scope 1 at $DIR/inline_closure.rs:+2:5: +2:6
StorageLive(_5); // scope 1 at $DIR/inline_closure.rs:+2:5: +2:12
_6 = _2; // scope 1 at $DIR/inline_closure.rs:+2:7: +2:8
StorageLive(_7); // scope 1 at $DIR/inline_closure.rs:+2:10: +2:11
_7 = _2; // scope 1 at $DIR/inline_closure.rs:+2:10: +2:11
- Deinit(_5); // scope 1 at $DIR/inline_closure.rs:+2:5: +2:12
- (_5.0: i32) = move _6; // scope 1 at $DIR/inline_closure.rs:+2:5: +2:12
- (_5.1: i32) = move _7; // scope 1 at $DIR/inline_closure.rs:+2:5: +2:12
+ _5 = (move _6, move _7); // scope 1 at $DIR/inline_closure.rs:+2:5: +2:12
StorageLive(_8); // scope 1 at $DIR/inline_closure.rs:+2:5: +2:12
_8 = move (_5.0: i32); // scope 1 at $DIR/inline_closure.rs:+2:5: +2:12
StorageLive(_9); // scope 1 at $DIR/inline_closure.rs:+2:5: +2:12
bb0: {
StorageLive(_3); // scope 0 at $DIR/inline_closure_borrows_arg.rs:+1:9: +1:10
- Deinit(_3); // scope 0 at $DIR/inline_closure_borrows_arg.rs:+1:13: +4:6
+ _3 = [closure@foo::<T>::{closure#0}]; // scope 0 at $DIR/inline_closure_borrows_arg.rs:+1:13: +4:6
+ // closure
+ // + def_id: DefId(0:6 ~ inline_closure_borrows_arg[96e9]::foo::{closure#0})
+ // + substs: [
+ // T,
+ // i8,
+ // for<'a, 'b> extern "rust-call" fn((&'a i32, &'b i32)) -> i32,
+ // (),
+ // ]
StorageLive(_4); // scope 1 at $DIR/inline_closure_borrows_arg.rs:+5:5: +5:6
_4 = &_3; // scope 1 at $DIR/inline_closure_borrows_arg.rs:+5:5: +5:6
StorageLive(_5); // scope 1 at $DIR/inline_closure_borrows_arg.rs:+5:5: +5:12
_6 = &(*_2); // scope 1 at $DIR/inline_closure_borrows_arg.rs:+5:7: +5:8
StorageLive(_7); // scope 1 at $DIR/inline_closure_borrows_arg.rs:+5:10: +5:11
_7 = &(*_2); // scope 1 at $DIR/inline_closure_borrows_arg.rs:+5:10: +5:11
- Deinit(_5); // scope 1 at $DIR/inline_closure_borrows_arg.rs:+5:5: +5:12
- (_5.0: &i32) = move _6; // scope 1 at $DIR/inline_closure_borrows_arg.rs:+5:5: +5:12
- (_5.1: &i32) = move _7; // scope 1 at $DIR/inline_closure_borrows_arg.rs:+5:5: +5:12
+ _5 = (move _6, move _7); // scope 1 at $DIR/inline_closure_borrows_arg.rs:+5:5: +5:12
StorageLive(_8); // scope 1 at $DIR/inline_closure_borrows_arg.rs:+5:5: +5:12
_8 = move (_5.0: &i32); // scope 1 at $DIR/inline_closure_borrows_arg.rs:+5:5: +5:12
StorageLive(_9); // scope 1 at $DIR/inline_closure_borrows_arg.rs:+5:5: +5:12
_4 = &_2; // scope 0 at $DIR/inline_closure_captures.rs:+1:13: +1:24
StorageLive(_5); // scope 0 at $DIR/inline_closure_captures.rs:+1:13: +1:24
_5 = &_1; // scope 0 at $DIR/inline_closure_captures.rs:+1:13: +1:24
- Deinit(_3); // scope 0 at $DIR/inline_closure_captures.rs:+1:13: +1:24
- (_3.0: &i32) = move _4; // scope 0 at $DIR/inline_closure_captures.rs:+1:13: +1:24
- (_3.1: &T) = move _5; // scope 0 at $DIR/inline_closure_captures.rs:+1:13: +1:24
+ _3 = [closure@foo::<T>::{closure#0}] { q: move _4, t: move _5 }; // scope 0 at $DIR/inline_closure_captures.rs:+1:13: +1:24
+ // closure
+ // + def_id: DefId(0:6 ~ inline_closure_captures[8bc0]::foo::{closure#0})
+ // + substs: [
+ // T,
+ // i8,
+ // extern "rust-call" fn((i32,)) -> (i32, T),
+ // (&i32, &T),
+ // ]
StorageDead(_5); // scope 0 at $DIR/inline_closure_captures.rs:+1:16: +1:17
StorageDead(_4); // scope 0 at $DIR/inline_closure_captures.rs:+1:16: +1:17
StorageLive(_6); // scope 1 at $DIR/inline_closure_captures.rs:+2:5: +2:6
StorageLive(_7); // scope 1 at $DIR/inline_closure_captures.rs:+2:5: +2:9
StorageLive(_8); // scope 1 at $DIR/inline_closure_captures.rs:+2:7: +2:8
_8 = _2; // scope 1 at $DIR/inline_closure_captures.rs:+2:7: +2:8
- Deinit(_7); // scope 1 at $DIR/inline_closure_captures.rs:+2:5: +2:9
- (_7.0: i32) = move _8; // scope 1 at $DIR/inline_closure_captures.rs:+2:5: +2:9
+ _7 = (move _8,); // scope 1 at $DIR/inline_closure_captures.rs:+2:5: +2:9
StorageLive(_9); // scope 1 at $DIR/inline_closure_captures.rs:+2:5: +2:9
_9 = move (_7.0: i32); // scope 1 at $DIR/inline_closure_captures.rs:+2:5: +2:9
StorageLive(_10); // scope 2 at $DIR/inline_closure_captures.rs:+1:19: +1:20
StorageLive(_11); // scope 2 at $DIR/inline_closure_captures.rs:+1:22: +1:23
_13 = deref_copy ((*_6).1: &T); // scope 2 at $DIR/inline_closure_captures.rs:+1:22: +1:23
_11 = (*_13); // scope 2 at $DIR/inline_closure_captures.rs:+1:22: +1:23
- Deinit(_0); // scope 2 at $DIR/inline_closure_captures.rs:+1:18: +1:24
- (_0.0: i32) = move _10; // scope 2 at $DIR/inline_closure_captures.rs:+1:18: +1:24
- (_0.1: T) = move _11; // scope 2 at $DIR/inline_closure_captures.rs:+1:18: +1:24
+ _0 = (move _10, move _11); // scope 2 at $DIR/inline_closure_captures.rs:+1:18: +1:24
StorageDead(_11); // scope 2 at $DIR/inline_closure_captures.rs:+1:23: +1:24
StorageDead(_10); // scope 2 at $DIR/inline_closure_captures.rs:+1:23: +1:24
StorageDead(_9); // scope 1 at $DIR/inline_closure_captures.rs:+2:5: +2:9
+ StorageDead(_6); // scope 2 at $DIR/inline_diverging.rs:28:15: 28:16
+ StorageLive(_8); // scope 3 at $DIR/inline_diverging.rs:29:6: 29:7
+ _8 = move _3; // scope 3 at $DIR/inline_diverging.rs:29:6: 29:7
-+ Deinit(_1); // scope 3 at $DIR/inline_diverging.rs:29:5: 29:11
-+ (_1.0: !) = move _8; // scope 3 at $DIR/inline_diverging.rs:29:5: 29:11
-+ (_1.1: !) = move _9; // scope 3 at $DIR/inline_diverging.rs:29:5: 29:11
++ _1 = (move _8, move _9); // scope 3 at $DIR/inline_diverging.rs:29:5: 29:11
+ StorageDead(_8); // scope 3 at $DIR/inline_diverging.rs:29:10: 29:11
+ StorageDead(_3); // scope 1 at $DIR/inline_diverging.rs:30:1: 30:2
+ drop(_2) -> bb2; // scope 1 at $DIR/inline_diverging.rs:30:1: 30:2
- }
-
- bb1: {
-+ Deinit(_4); // scope 2 at $DIR/inline_generator.rs:15:5: 15:41
-+ discriminant(_4) = 0; // scope 2 at $DIR/inline_generator.rs:15:5: 15:41
++ _4 = [generator@$DIR/inline_generator.rs:15:5: 15:8 (#0)]; // scope 2 at $DIR/inline_generator.rs:15:5: 15:41
++ // generator
++ // + def_id: DefId(0:7 ~ inline_generator[ea31]::g::{closure#0})
++ // + substs: [
++ // bool,
++ // i32,
++ // bool,
++ // {bool, i32},
++ // (),
++ // ]
++ // + movability: Movable
_3 = &mut _4; // scope 0 at $DIR/inline_generator.rs:+1:23: +1:31
- _2 = Pin::<&mut [generator@$DIR/inline_generator.rs:15:5: 15:8]>::new(move _3) -> [return: bb2, unwind: bb4]; // scope 0 at $DIR/inline_generator.rs:+1:14: +1:32
- // mir::Constant
+ _5 = move _3; // scope 4 at $SRC_DIR/core/src/pin.rs:LL:COL
+ StorageLive(_6); // scope 5 at $SRC_DIR/core/src/pin.rs:LL:COL
+ _6 = move _5; // scope 5 at $SRC_DIR/core/src/pin.rs:LL:COL
-+ Deinit(_2); // scope 5 at $SRC_DIR/core/src/pin.rs:LL:COL
-+ (_2.0: &mut [generator@$DIR/inline_generator.rs:15:5: 15:8]) = move _6; // scope 5 at $SRC_DIR/core/src/pin.rs:LL:COL
++ _2 = Pin::<&mut [generator@$DIR/inline_generator.rs:15:5: 15:8]> { pointer: move _6 }; // scope 5 at $SRC_DIR/core/src/pin.rs:LL:COL
+ StorageDead(_6); // scope 5 at $SRC_DIR/core/src/pin.rs:LL:COL
+ StorageDead(_5); // scope 4 at $SRC_DIR/core/src/pin.rs:LL:COL
StorageDead(_3); // scope 0 at $DIR/inline_generator.rs:+1:31: +1:32
+ }
+
+ bb6: {
-+ Deinit(_1); // scope 6 at $DIR/inline_generator.rs:15:11: 15:39
-+ ((_1 as Yielded).0: i32) = move _8; // scope 6 at $DIR/inline_generator.rs:15:11: 15:39
-+ discriminant(_1) = 0; // scope 6 at $DIR/inline_generator.rs:15:11: 15:39
++ _1 = GeneratorState::<i32, bool>::Yielded(move _8); // scope 6 at $DIR/inline_generator.rs:15:11: 15:39
+ _11 = deref_copy (_2.0: &mut [generator@$DIR/inline_generator.rs:15:5: 15:8]); // scope 6 at $DIR/inline_generator.rs:15:11: 15:39
+ discriminant((*_11)) = 3; // scope 6 at $DIR/inline_generator.rs:15:11: 15:39
+ goto -> bb1; // scope 0 at $DIR/inline_generator.rs:15:11: 15:39
+ bb7: {
+ StorageLive(_8); // scope 6 at $DIR/inline_generator.rs:15:5: 15:41
+ StorageDead(_8); // scope 6 at $DIR/inline_generator.rs:15:38: 15:39
-+ Deinit(_1); // scope 6 at $DIR/inline_generator.rs:15:41: 15:41
-+ ((_1 as Complete).0: bool) = _7; // scope 6 at $DIR/inline_generator.rs:15:41: 15:41
-+ discriminant(_1) = 1; // scope 6 at $DIR/inline_generator.rs:15:41: 15:41
++ _1 = GeneratorState::<i32, bool>::Complete(_7); // scope 6 at $DIR/inline_generator.rs:15:41: 15:41
+ _12 = deref_copy (_2.0: &mut [generator@$DIR/inline_generator.rs:15:5: 15:8]); // scope 6 at $DIR/inline_generator.rs:15:41: 15:41
+ discriminant((*_12)) = 1; // scope 6 at $DIR/inline_generator.rs:15:41: 15:41
+ goto -> bb1; // scope 0 at $DIR/inline_generator.rs:15:41: 15:41
+ // + span: $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
+ // + user_ty: UserType(0)
+ // + literal: Const { ty: alloc::raw_vec::RawVec<u32>, val: Unevaluated(alloc::raw_vec::RawVec::<T>::NEW, [u32], None) }
-+ Deinit(_9); // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
-+ (_9.0: alloc::raw_vec::RawVec<u32>) = move _10; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
-+ (_9.1: usize) = const 0_usize; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
++ _9 = Vec::<u32> { buf: move _10, len: const 0_usize }; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
+ StorageDead(_10); // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
+ (*_8) = move _9; // scope 0 at $DIR/inline_into_box_place.rs:+1:33: +1:43
+ StorageDead(_9); // scope 0 at $DIR/inline_into_box_place.rs:+1:33: +1:43
bb0: {
StorageLive(_1); // scope 0 at $DIR/issue_76997_inline_scopes_parenting.rs:+1:9: +1:10
- Deinit(_1); // scope 0 at $DIR/issue_76997_inline_scopes_parenting.rs:+1:13: +1:33
+ _1 = [closure@$DIR/issue_76997_inline_scopes_parenting.rs:5:13: 5:16]; // scope 0 at $DIR/issue_76997_inline_scopes_parenting.rs:+1:13: +1:33
+ // closure
+ // + def_id: DefId(0:4 ~ issue_76997_inline_scopes_parenting[bc59]::main::{closure#0})
+ // + substs: [
+ // i8,
+ // extern "rust-call" fn(((),)),
+ // (),
+ // ]
StorageLive(_2); // scope 1 at $DIR/issue_76997_inline_scopes_parenting.rs:+2:5: +2:6
_2 = &_1; // scope 1 at $DIR/issue_76997_inline_scopes_parenting.rs:+2:5: +2:6
StorageLive(_3); // scope 1 at $DIR/issue_76997_inline_scopes_parenting.rs:+2:5: +2:10
StorageLive(_4); // scope 1 at $DIR/issue_76997_inline_scopes_parenting.rs:+2:7: +2:9
- Deinit(_4); // scope 1 at $DIR/issue_76997_inline_scopes_parenting.rs:+2:7: +2:9
- Deinit(_3); // scope 1 at $DIR/issue_76997_inline_scopes_parenting.rs:+2:5: +2:10
- (_3.0: ()) = move _4; // scope 1 at $DIR/issue_76997_inline_scopes_parenting.rs:+2:5: +2:10
+ _4 = (); // scope 1 at $DIR/issue_76997_inline_scopes_parenting.rs:+2:7: +2:9
+ _3 = (move _4,); // scope 1 at $DIR/issue_76997_inline_scopes_parenting.rs:+2:5: +2:10
StorageLive(_5); // scope 1 at $DIR/issue_76997_inline_scopes_parenting.rs:+2:5: +2:10
_5 = move (_3.0: ()); // scope 1 at $DIR/issue_76997_inline_scopes_parenting.rs:+2:5: +2:10
StorageLive(_6); // scope 2 at $DIR/issue_76997_inline_scopes_parenting.rs:+1:23: +1:24
bb1: {
_3 = &_4; // scope 0 at $DIR/issue_78442.rs:+4:5: +4:15
StorageLive(_5); // scope 0 at $DIR/issue_78442.rs:+4:5: +4:17
- Deinit(_5); // scope 0 at $DIR/issue_78442.rs:+4:5: +4:17
+ _5 = (); // scope 0 at $DIR/issue_78442.rs:+4:5: +4:17
- _2 = <fn() {foo} as Fn<()>>::call(move _3, move _5) -> [return: bb2, unwind: bb4]; // scope 0 at $DIR/issue_78442.rs:+4:5: +4:17
- // mir::Constant
- // + span: $DIR/issue_78442.rs:11:5: 11:15
bb1: {
_3 = &_4; // scope 0 at $DIR/issue_78442.rs:+4:5: +4:15
StorageLive(_5); // scope 0 at $DIR/issue_78442.rs:+4:5: +4:17
- Deinit(_5); // scope 0 at $DIR/issue_78442.rs:+4:5: +4:17
+ _5 = (); // scope 0 at $DIR/issue_78442.rs:+4:5: +4:17
- _2 = <impl Fn() as Fn<()>>::call(move _3, move _5) -> [return: bb2, unwind: bb4]; // scope 0 at $DIR/issue_78442.rs:+4:5: +4:17
+ _2 = <fn() {foo} as Fn<()>>::call(move _3, move _5) -> [return: bb2, unwind: bb4]; // scope 0 at $DIR/issue_78442.rs:+4:5: +4:17
// mir::Constant
bb7: {
StorageDead(_6); // scope 4 at $DIR/issue_75439.rs:+5:35: +5:36
- Deinit(_0); // scope 3 at $DIR/issue_75439.rs:+5:9: +5:39
- ((_0 as Some).0: [u8; 4]) = move _5; // scope 3 at $DIR/issue_75439.rs:+5:9: +5:39
- discriminant(_0) = 1; // scope 3 at $DIR/issue_75439.rs:+5:9: +5:39
+ _0 = Option::<[u8; 4]>::Some(move _5); // scope 3 at $DIR/issue_75439.rs:+5:9: +5:39
StorageDead(_5); // scope 3 at $DIR/issue_75439.rs:+5:38: +5:39
StorageDead(_4); // scope 1 at $DIR/issue_75439.rs:+6:5: +6:6
goto -> bb9; // scope 1 at $DIR/issue_75439.rs:+4:5: +8:6
}
bb8: {
- Deinit(_0); // scope 1 at $DIR/issue_75439.rs:+7:9: +7:13
- discriminant(_0) = 0; // scope 1 at $DIR/issue_75439.rs:+7:9: +7:13
+ _0 = Option::<[u8; 4]>::None; // scope 1 at $DIR/issue_75439.rs:+7:9: +7:13
goto -> bb9; // scope 1 at $DIR/issue_75439.rs:+4:5: +8:6
}
bb0: {
StorageLive(_1); // scope 0 at $DIR/lower_intrinsics.rs:+1:9: +1:12
- Deinit(_1); // scope 0 at $DIR/lower_intrinsics.rs:+1:15: +1:17
+ _1 = (); // scope 0 at $DIR/lower_intrinsics.rs:+1:15: +1:17
StorageLive(_2); // scope 1 at $DIR/lower_intrinsics.rs:+2:9: +2:16
- Deinit(_2); // scope 1 at $DIR/lower_intrinsics.rs:+2:19: +2:21
+ _2 = (); // scope 1 at $DIR/lower_intrinsics.rs:+2:19: +2:21
StorageLive(_3); // scope 3 at $DIR/lower_intrinsics.rs:+4:9: +4:95
StorageLive(_4); // scope 3 at $DIR/lower_intrinsics.rs:+4:29: +4:59
StorageLive(_5); // scope 3 at $DIR/lower_intrinsics.rs:+4:29: +4:45
- _3 = const false; // scope 4 at $DIR/matches_reduce_branches.rs:+16:13: +16:22
- _4 = const false; // scope 4 at $DIR/matches_reduce_branches.rs:+17:13: +17:22
- _5 = const true; // scope 4 at $DIR/matches_reduce_branches.rs:+18:13: +18:21
-- Deinit(_6); // scope 4 at $DIR/matches_reduce_branches.rs:+19:13: +19:15
+- _6 = (); // scope 4 at $DIR/matches_reduce_branches.rs:+19:13: +19:15
- goto -> bb3; // scope 4 at $DIR/matches_reduce_branches.rs:+19:13: +19:15
- }
-
+ _3 = Eq(_11, const 7_i32); // scope 4 at $DIR/matches_reduce_branches.rs:+9:13: +9:21
_4 = const false; // scope 4 at $DIR/matches_reduce_branches.rs:+10:13: +10:22
_5 = const true; // scope 4 at $DIR/matches_reduce_branches.rs:+11:13: +11:21
- Deinit(_6); // scope 4 at $DIR/matches_reduce_branches.rs:+12:13: +12:15
+ _6 = (); // scope 4 at $DIR/matches_reduce_branches.rs:+12:13: +12:15
- goto -> bb3; // scope 4 at $DIR/matches_reduce_branches.rs:+12:13: +12:15
- }
-
_9 = _4; // scope 4 at $DIR/matches_reduce_branches.rs:+23:12: +23:13
StorageLive(_10); // scope 4 at $DIR/matches_reduce_branches.rs:+23:15: +23:16
_10 = _5; // scope 4 at $DIR/matches_reduce_branches.rs:+23:15: +23:16
- Deinit(_0); // scope 4 at $DIR/matches_reduce_branches.rs:+23:5: +23:17
- (_0.0: bool) = move _7; // scope 4 at $DIR/matches_reduce_branches.rs:+23:5: +23:17
- (_0.1: bool) = move _8; // scope 4 at $DIR/matches_reduce_branches.rs:+23:5: +23:17
- (_0.2: bool) = move _9; // scope 4 at $DIR/matches_reduce_branches.rs:+23:5: +23:17
- (_0.3: bool) = move _10; // scope 4 at $DIR/matches_reduce_branches.rs:+23:5: +23:17
+ _0 = (move _7, move _8, move _9, move _10); // scope 4 at $DIR/matches_reduce_branches.rs:+23:5: +23:17
StorageDead(_10); // scope 4 at $DIR/matches_reduce_branches.rs:+23:16: +23:17
StorageDead(_9); // scope 4 at $DIR/matches_reduce_branches.rs:+23:16: +23:17
StorageDead(_8); // scope 4 at $DIR/matches_reduce_branches.rs:+23:16: +23:17
- }
-
- bb4: {
- Deinit(_0); // scope 0 at $DIR/matches_reduce_branches.rs:+2:9: +2:11
+ _0 = (); // scope 0 at $DIR/matches_reduce_branches.rs:+2:9: +2:11
- goto -> bb6; // scope 0 at $DIR/matches_reduce_branches.rs:+1:5: +3:6
+ goto -> bb3; // scope 0 at $DIR/matches_reduce_branches.rs:+1:5: +3:6
}
bb0: {
StorageLive(_1); // scope 0 at $DIR/matches_reduce_branches.rs:+1:9: +1:12
StorageLive(_2); // scope 0 at $DIR/matches_reduce_branches.rs:+1:21: +1:23
- Deinit(_2); // scope 0 at $DIR/matches_reduce_branches.rs:+1:21: +1:23
+ _2 = (); // scope 0 at $DIR/matches_reduce_branches.rs:+1:21: +1:23
StorageLive(_3); // scope 0 at $DIR/matches_reduce_branches.rs:+2:15: +6:10
StorageLive(_4); // scope 0 at $DIR/matches_reduce_branches.rs:+2:18: +2:76
StorageLive(_5); // scope 0 at $DIR/matches_reduce_branches.rs:+2:21: +2:52
StorageLive(_1); // scope 0 at $DIR/packed_struct_drop_aligned.rs:+1:9: +1:14
StorageLive(_2); // scope 0 at $DIR/packed_struct_drop_aligned.rs:+1:24: +1:42
StorageLive(_3); // scope 0 at $DIR/packed_struct_drop_aligned.rs:+1:32: +1:41
- Deinit(_3); // scope 0 at $DIR/packed_struct_drop_aligned.rs:+1:32: +1:41
- (_3.0: usize) = const 0_usize; // scope 0 at $DIR/packed_struct_drop_aligned.rs:+1:32: +1:41
- Deinit(_2); // scope 0 at $DIR/packed_struct_drop_aligned.rs:+1:24: +1:42
- (_2.0: Droppy) = move _3; // scope 0 at $DIR/packed_struct_drop_aligned.rs:+1:24: +1:42
+ _3 = Droppy(const 0_usize); // scope 0 at $DIR/packed_struct_drop_aligned.rs:+1:32: +1:41
+ _2 = Aligned(move _3); // scope 0 at $DIR/packed_struct_drop_aligned.rs:+1:24: +1:42
StorageDead(_3); // scope 0 at $DIR/packed_struct_drop_aligned.rs:+1:41: +1:42
- Deinit(_1); // scope 0 at $DIR/packed_struct_drop_aligned.rs:+1:17: +1:43
- (_1.0: Aligned) = move _2; // scope 0 at $DIR/packed_struct_drop_aligned.rs:+1:17: +1:43
+ _1 = Packed(move _2); // scope 0 at $DIR/packed_struct_drop_aligned.rs:+1:17: +1:43
StorageDead(_2); // scope 0 at $DIR/packed_struct_drop_aligned.rs:+1:42: +1:43
StorageLive(_4); // scope 1 at $DIR/packed_struct_drop_aligned.rs:+2:11: +2:29
StorageLive(_5); // scope 1 at $DIR/packed_struct_drop_aligned.rs:+2:19: +2:28
- Deinit(_5); // scope 1 at $DIR/packed_struct_drop_aligned.rs:+2:19: +2:28
- (_5.0: usize) = const 0_usize; // scope 1 at $DIR/packed_struct_drop_aligned.rs:+2:19: +2:28
- Deinit(_4); // scope 1 at $DIR/packed_struct_drop_aligned.rs:+2:11: +2:29
- (_4.0: Droppy) = move _5; // scope 1 at $DIR/packed_struct_drop_aligned.rs:+2:11: +2:29
+ _5 = Droppy(const 0_usize); // scope 1 at $DIR/packed_struct_drop_aligned.rs:+2:19: +2:28
+ _4 = Aligned(move _5); // scope 1 at $DIR/packed_struct_drop_aligned.rs:+2:11: +2:29
StorageDead(_5); // scope 1 at $DIR/packed_struct_drop_aligned.rs:+2:28: +2:29
StorageLive(_6); // scope 1 at $DIR/packed_struct_drop_aligned.rs:+2:5: +2:8
_6 = move (_1.0: Aligned); // scope 1 at $DIR/packed_struct_drop_aligned.rs:+2:5: +2:8
_1 = const 0_i32; // scope 0 at $DIR/remove_storage_markers.rs:+1:19: +1:20
- StorageLive(_2); // scope 1 at $DIR/remove_storage_markers.rs:+2:14: +2:19
- StorageLive(_3); // scope 1 at $DIR/remove_storage_markers.rs:+2:14: +2:19
- Deinit(_3); // scope 1 at $DIR/remove_storage_markers.rs:+2:14: +2:19
- (_3.0: i32) = const 0_i32; // scope 1 at $DIR/remove_storage_markers.rs:+2:14: +2:19
- (_3.1: i32) = const 10_i32; // scope 1 at $DIR/remove_storage_markers.rs:+2:14: +2:19
+ _3 = std::ops::Range::<i32> { start: const 0_i32, end: const 10_i32 }; // scope 1 at $DIR/remove_storage_markers.rs:+2:14: +2:19
_2 = <std::ops::Range<i32> as IntoIterator>::into_iter(move _3) -> bb1; // scope 1 at $DIR/remove_storage_markers.rs:+2:14: +2:19
// mir::Constant
// + span: $DIR/remove_storage_markers.rs:10:14: 10:19
fn get_union() -> Foo {
let mut _0: Foo; // return place in scope 0 at $DIR/remove_zsts.rs:+0:19: +0:22
+ let mut _1: (); // in scope 0 at $DIR/remove_zsts.rs:+1:14: +1:16
bb0: {
- Deinit(_0); // scope 0 at $DIR/remove_zsts.rs:+1:5: +1:18
+ StorageLive(_1); // scope 0 at $DIR/remove_zsts.rs:+1:14: +1:16
+ _0 = Foo { x: move _1 }; // scope 0 at $DIR/remove_zsts.rs:+1:5: +1:18
+ StorageDead(_1); // scope 0 at $DIR/remove_zsts.rs:+1:17: +1:18
return; // scope 0 at $DIR/remove_zsts.rs:+2:2: +2:2
}
}
bb0: {
StorageLive(_1); // scope 0 at $DIR/remove_zsts.rs:+1:14: +1:16
-- Deinit(_1); // scope 0 at $DIR/remove_zsts.rs:+1:14: +1:16
+- _1 = (); // scope 0 at $DIR/remove_zsts.rs:+1:14: +1:16
+ nop; // scope 0 at $DIR/remove_zsts.rs:+1:14: +1:16
- Deinit(_0); // scope 0 at $DIR/remove_zsts.rs:+1:5: +1:18
-- (_0.0: ()) = move _1; // scope 0 at $DIR/remove_zsts.rs:+1:5: +1:18
-+ nop; // scope 0 at $DIR/remove_zsts.rs:+1:5: +1:18
+ _0 = Foo { x: move _1 }; // scope 0 at $DIR/remove_zsts.rs:+1:5: +1:18
StorageDead(_1); // scope 0 at $DIR/remove_zsts.rs:+1:17: +1:18
return; // scope 0 at $DIR/remove_zsts.rs:+2:2: +2:2
}
// + literal: Const { ty: &usize, val: Unevaluated(array_casts, [], Some(promoted[0])) }
Retag(_35); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
_18 = &(*_35); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- Deinit(_13); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- (_13.0: &usize) = move _14; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- (_13.1: &usize) = move _18; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+ _13 = (move _14, move _18); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
Retag(_13); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
StorageDead(_18); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
StorageDead(_14); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
bb3: {
StorageLive(_27); // scope 7 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- Deinit(_27); // scope 7 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- discriminant(_27) = 0; // scope 7 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+ _27 = core::panicking::AssertKind::Eq; // scope 7 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
StorageLive(_28); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
StorageLive(_29); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
_29 = move _27; // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
_33 = &(*_21); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
_32 = &(*_33); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
StorageLive(_34); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- Deinit(_34); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- discriminant(_34) = 0; // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+ _34 = Option::<Arguments<'_>>::None; // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
Retag(_34); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
_28 = core::panicking::assert_failed::<usize, usize>(move _29, move _30, move _32, move _34); // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
// mir::Constant
StorageLive(_3); // scope 1 at $DIR/retag.rs:+3:13: +3:14
StorageLive(_4); // scope 1 at $DIR/retag.rs:+3:17: +3:36
StorageLive(_5); // scope 1 at $DIR/retag.rs:+3:17: +3:24
- Deinit(_5); // scope 1 at $DIR/retag.rs:+3:17: +3:24
- (_5.0: i32) = const 0_i32; // scope 1 at $DIR/retag.rs:+3:17: +3:24
+ _5 = Test(const 0_i32); // scope 1 at $DIR/retag.rs:+3:17: +3:24
_4 = &_5; // scope 1 at $DIR/retag.rs:+3:17: +3:36
StorageLive(_6); // scope 1 at $DIR/retag.rs:+3:29: +3:35
StorageLive(_7); // scope 1 at $DIR/retag.rs:+3:29: +3:35
StorageDead(_2); // scope 1 at $DIR/retag.rs:+8:5: +8:6
StorageLive(_13); // scope 1 at $DIR/retag.rs:+11:9: +11:10
StorageLive(_14); // scope 1 at $DIR/retag.rs:+11:31: +14:6
- Deinit(_14); // scope 1 at $DIR/retag.rs:+11:31: +14:6
+ _14 = [closure@main::{closure#0}]; // scope 1 at $DIR/retag.rs:+11:31: +14:6
+ // closure
+ // + def_id: DefId(0:14 ~ retag[4622]::main::{closure#0})
+ // + substs: [
+ // i8,
+ // for<'a> extern "rust-call" fn((&'a i32,)) -> &'a i32,
+ // (),
+ // ]
Retag(_14); // scope 1 at $DIR/retag.rs:+11:31: +14:6
_13 = move _14 as for<'a> fn(&'a i32) -> &'a i32 (Pointer(ClosureFnPointer(Normal))); // scope 1 at $DIR/retag.rs:+11:31: +14:6
StorageDead(_14); // scope 1 at $DIR/retag.rs:+11:47: +11:48
StorageLive(_19); // scope 7 at $DIR/retag.rs:+18:5: +18:24
StorageLive(_20); // scope 7 at $DIR/retag.rs:+18:5: +18:24
StorageLive(_21); // scope 7 at $DIR/retag.rs:+18:5: +18:12
- Deinit(_21); // scope 7 at $DIR/retag.rs:+18:5: +18:12
- (_21.0: i32) = const 0_i32; // scope 7 at $DIR/retag.rs:+18:5: +18:12
+ _21 = Test(const 0_i32); // scope 7 at $DIR/retag.rs:+18:5: +18:12
_20 = &_21; // scope 7 at $DIR/retag.rs:+18:5: +18:24
StorageLive(_22); // scope 7 at $DIR/retag.rs:+18:21: +18:23
StorageLive(_23); // scope 7 at $DIR/retag.rs:+18:21: +18:23
StorageLive(_4); // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:9
_4 = _1; // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:9
_10 = discriminant(_4); // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
-- switchInt(move _10) -> [0: bb7, 1: bb5, otherwise: bb6]; // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
-+ switchInt(move _10) -> [0: bb6, 1: bb4, otherwise: bb5]; // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
+ switchInt(move _10) -> [0: bb7, 1: bb5, otherwise: bb6]; // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
}
bb1: {
-- StorageDead(_4); // scope 0 at $DIR/separate_const_switch.rs:+1:9: +1:10
-- _5 = discriminant(_3); // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
-- switchInt(move _5) -> [0: bb2, 1: bb4, otherwise: bb3]; // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
-- }
--
-- bb2: {
+ StorageDead(_4); // scope 0 at $DIR/separate_const_switch.rs:+1:9: +1:10
+ _5 = discriminant(_3); // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
+ switchInt(move _5) -> [0: bb2, 1: bb4, otherwise: bb3]; // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
+ }
+
+ bb2: {
StorageLive(_9); // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
_9 = ((_3 as Continue).0: i32); // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
_2 = _9; // scope 4 at $DIR/separate_const_switch.rs:+1:8: +1:10
StorageDead(_9); // scope 0 at $DIR/separate_const_switch.rs:+1:9: +1:10
- Deinit(_0); // scope 0 at $DIR/separate_const_switch.rs:+1:5: +1:11
- ((_0 as Ok).0: i32) = move _2; // scope 0 at $DIR/separate_const_switch.rs:+1:5: +1:11
- discriminant(_0) = 0; // scope 0 at $DIR/separate_const_switch.rs:+1:5: +1:11
+ _0 = Result::<i32, i32>::Ok(move _2); // scope 0 at $DIR/separate_const_switch.rs:+1:5: +1:11
StorageDead(_2); // scope 0 at $DIR/separate_const_switch.rs:+1:10: +1:11
StorageDead(_3); // scope 0 at $DIR/separate_const_switch.rs:+2:1: +2:2
return; // scope 0 at $DIR/separate_const_switch.rs:+2:2: +2:2
}
-- bb3: {
-+ bb2: {
+ bb3: {
unreachable; // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
}
-- bb4: {
-+ bb3: {
+ bb4: {
StorageLive(_6); // scope 0 at $DIR/separate_const_switch.rs:+1:9: +1:10
_6 = ((_3 as Break).0: std::result::Result<std::convert::Infallible, i32>); // scope 0 at $DIR/separate_const_switch.rs:+1:9: +1:10
StorageLive(_8); // scope 2 at $DIR/separate_const_switch.rs:+1:9: +1:10
_18 = move _16; // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL
_17 = move _18; // scope 10 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
StorageDead(_18); // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL
- Deinit(_0); // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL
- ((_0 as Err).0: i32) = move _17; // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL
- discriminant(_0) = 1; // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL
+ _0 = Result::<i32, i32>::Err(move _17); // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL
StorageDead(_17); // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL
StorageDead(_16); // scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
StorageDead(_8); // scope 2 at $DIR/separate_const_switch.rs:+1:9: +1:10
return; // scope 0 at $DIR/separate_const_switch.rs:+2:2: +2:2
}
-- bb5: {
-+ bb4: {
+ bb5: {
StorageLive(_13); // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
_13 = move ((_4 as Err).0: i32); // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
StorageLive(_14); // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
StorageLive(_15); // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
_15 = move _13; // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
- Deinit(_14); // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
- ((_14 as Err).0: i32) = move _15; // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
- discriminant(_14) = 1; // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+ _14 = Result::<Infallible, i32>::Err(move _15); // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
StorageDead(_15); // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
- Deinit(_3); // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
- ((_3 as Break).0: std::result::Result<std::convert::Infallible, i32>) = move _14; // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
- discriminant(_3) = 1; // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+ _3 = ControlFlow::<Result<Infallible, i32>, i32>::Break(move _14); // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
StorageDead(_14); // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
StorageDead(_13); // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
-- goto -> bb1; // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
-+ StorageDead(_4); // scope 0 at $DIR/separate_const_switch.rs:+1:9: +1:10
-+ _5 = discriminant(_3); // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
-+ switchInt(move _5) -> [0: bb1, 1: bb3, otherwise: bb2]; // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
+ goto -> bb1; // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
}
-- bb6: {
-+ bb5: {
+ bb6: {
unreachable; // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
}
-- bb7: {
-+ bb6: {
+ bb7: {
StorageLive(_11); // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
_11 = move ((_4 as Ok).0: i32); // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
StorageLive(_12); // scope 6 at $SRC_DIR/core/src/result.rs:LL:COL
_12 = move _11; // scope 6 at $SRC_DIR/core/src/result.rs:LL:COL
- Deinit(_3); // scope 6 at $SRC_DIR/core/src/result.rs:LL:COL
- ((_3 as Continue).0: i32) = move _12; // scope 6 at $SRC_DIR/core/src/result.rs:LL:COL
- discriminant(_3) = 0; // scope 6 at $SRC_DIR/core/src/result.rs:LL:COL
+ _3 = ControlFlow::<Result<Infallible, i32>, i32>::Continue(move _12); // scope 6 at $SRC_DIR/core/src/result.rs:LL:COL
StorageDead(_12); // scope 6 at $SRC_DIR/core/src/result.rs:LL:COL
StorageDead(_11); // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
-- goto -> bb1; // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
-+ StorageDead(_4); // scope 0 at $DIR/separate_const_switch.rs:+1:9: +1:10
-+ _5 = discriminant(_3); // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
-+ switchInt(move _5) -> [0: bb1, 1: bb3, otherwise: bb2]; // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
+ goto -> bb1; // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
}
}
_6 = ((_1 as Err).0: usize); // scope 0 at $DIR/separate_const_switch.rs:+8:17: +8:18
StorageLive(_7); // scope 2 at $DIR/separate_const_switch.rs:+8:42: +8:43
_7 = _6; // scope 2 at $DIR/separate_const_switch.rs:+8:42: +8:43
- Deinit(_2); // scope 2 at $DIR/separate_const_switch.rs:+8:23: +8:44
- ((_2 as Break).0: usize) = move _7; // scope 2 at $DIR/separate_const_switch.rs:+8:23: +8:44
- discriminant(_2) = 1; // scope 2 at $DIR/separate_const_switch.rs:+8:23: +8:44
+ _2 = ControlFlow::<usize, i32>::Break(move _7); // scope 2 at $DIR/separate_const_switch.rs:+8:23: +8:44
StorageDead(_7); // scope 2 at $DIR/separate_const_switch.rs:+8:43: +8:44
StorageDead(_6); // scope 0 at $DIR/separate_const_switch.rs:+8:43: +8:44
-- goto -> bb4; // scope 0 at $DIR/separate_const_switch.rs:+8:43: +8:44
-+ _8 = discriminant(_2); // scope 0 at $DIR/separate_const_switch.rs:+5:11: +10:6
-+ switchInt(move _8) -> [0: bb6, 1: bb4, otherwise: bb5]; // scope 0 at $DIR/separate_const_switch.rs:+5:5: +10:6
+ goto -> bb4; // scope 0 at $DIR/separate_const_switch.rs:+8:43: +8:44
}
bb2: {
_4 = ((_1 as Ok).0: i32); // scope 0 at $DIR/separate_const_switch.rs:+7:16: +7:17
StorageLive(_5); // scope 1 at $DIR/separate_const_switch.rs:+7:44: +7:45
_5 = _4; // scope 1 at $DIR/separate_const_switch.rs:+7:44: +7:45
- Deinit(_2); // scope 1 at $DIR/separate_const_switch.rs:+7:22: +7:46
- ((_2 as Continue).0: i32) = move _5; // scope 1 at $DIR/separate_const_switch.rs:+7:22: +7:46
- discriminant(_2) = 0; // scope 1 at $DIR/separate_const_switch.rs:+7:22: +7:46
+ _2 = ControlFlow::<usize, i32>::Continue(move _5); // scope 1 at $DIR/separate_const_switch.rs:+7:22: +7:46
StorageDead(_5); // scope 1 at $DIR/separate_const_switch.rs:+7:45: +7:46
StorageDead(_4); // scope 0 at $DIR/separate_const_switch.rs:+7:45: +7:46
-- goto -> bb4; // scope 0 at $DIR/separate_const_switch.rs:+7:45: +7:46
-- }
--
-- bb4: {
+ goto -> bb4; // scope 0 at $DIR/separate_const_switch.rs:+7:45: +7:46
+ }
+
+ bb4: {
_8 = discriminant(_2); // scope 0 at $DIR/separate_const_switch.rs:+5:11: +10:6
-- switchInt(move _8) -> [0: bb7, 1: bb5, otherwise: bb6]; // scope 0 at $DIR/separate_const_switch.rs:+5:5: +10:6
-+ switchInt(move _8) -> [0: bb6, 1: bb4, otherwise: bb5]; // scope 0 at $DIR/separate_const_switch.rs:+5:5: +10:6
+ switchInt(move _8) -> [0: bb7, 1: bb5, otherwise: bb6]; // scope 0 at $DIR/separate_const_switch.rs:+5:5: +10:6
}
-- bb5: {
-+ bb4: {
+ bb5: {
StorageLive(_11); // scope 0 at $DIR/separate_const_switch.rs:+12:28: +12:29
_11 = ((_2 as Break).0: usize); // scope 0 at $DIR/separate_const_switch.rs:+12:28: +12:29
- Deinit(_0); // scope 4 at $DIR/separate_const_switch.rs:+12:34: +12:38
- discriminant(_0) = 0; // scope 4 at $DIR/separate_const_switch.rs:+12:34: +12:38
+ _0 = Option::<i32>::None; // scope 4 at $DIR/separate_const_switch.rs:+12:34: +12:38
StorageDead(_11); // scope 0 at $DIR/separate_const_switch.rs:+12:37: +12:38
-- goto -> bb8; // scope 0 at $DIR/separate_const_switch.rs:+12:37: +12:38
-+ goto -> bb7; // scope 0 at $DIR/separate_const_switch.rs:+12:37: +12:38
+ goto -> bb8; // scope 0 at $DIR/separate_const_switch.rs:+12:37: +12:38
}
-- bb6: {
-+ bb5: {
+ bb6: {
unreachable; // scope 0 at $DIR/separate_const_switch.rs:+5:11: +10:6
}
-- bb7: {
-+ bb6: {
+ bb7: {
StorageLive(_9); // scope 0 at $DIR/separate_const_switch.rs:+11:31: +11:32
_9 = ((_2 as Continue).0: i32); // scope 0 at $DIR/separate_const_switch.rs:+11:31: +11:32
StorageLive(_10); // scope 3 at $DIR/separate_const_switch.rs:+11:42: +11:43
_10 = _9; // scope 3 at $DIR/separate_const_switch.rs:+11:42: +11:43
- Deinit(_0); // scope 3 at $DIR/separate_const_switch.rs:+11:37: +11:44
- ((_0 as Some).0: i32) = move _10; // scope 3 at $DIR/separate_const_switch.rs:+11:37: +11:44
- discriminant(_0) = 1; // scope 3 at $DIR/separate_const_switch.rs:+11:37: +11:44
+ _0 = Option::<i32>::Some(move _10); // scope 3 at $DIR/separate_const_switch.rs:+11:37: +11:44
StorageDead(_10); // scope 3 at $DIR/separate_const_switch.rs:+11:43: +11:44
StorageDead(_9); // scope 0 at $DIR/separate_const_switch.rs:+11:43: +11:44
-- goto -> bb8; // scope 0 at $DIR/separate_const_switch.rs:+11:43: +11:44
-+ goto -> bb7; // scope 0 at $DIR/separate_const_switch.rs:+11:43: +11:44
+ goto -> bb8; // scope 0 at $DIR/separate_const_switch.rs:+11:43: +11:44
}
-- bb8: {
-+ bb7: {
+ bb8: {
StorageDead(_2); // scope 0 at $DIR/separate_const_switch.rs:+14:1: +14:2
return; // scope 0 at $DIR/separate_const_switch.rs:+14:2: +14:2
}
debug x => _1; // in scope 0 at $DIR/simple_option_map_e2e.rs:+0:14: +0:15
let mut _0: std::option::Option<i32>; // return place in scope 0 at $DIR/simple_option_map_e2e.rs:+0:33: +0:44
let mut _2: [closure@$DIR/simple_option_map_e2e.rs:14:12: 14:15]; // in scope 0 at $DIR/simple_option_map_e2e.rs:+1:12: +1:21
+ let mut _7: i32; // in scope 0 at $DIR/simple_option_map_e2e.rs:7:25: 7:29
scope 1 (inlined map::<i32, i32, [closure@$DIR/simple_option_map_e2e.rs:14:12: 14:15]>) { // at $DIR/simple_option_map_e2e.rs:14:5: 14:22
debug slf => _1; // in scope 1 at $DIR/simple_option_map_e2e.rs:2:17: 2:20
debug f => _2; // in scope 1 at $DIR/simple_option_map_e2e.rs:2:33: 2:34
let mut _3: isize; // in scope 1 at $DIR/simple_option_map_e2e.rs:7:9: 7:16
- let mut _4: i32; // in scope 1 at $DIR/simple_option_map_e2e.rs:7:25: 7:29
+ let _4: i32; // in scope 1 at $DIR/simple_option_map_e2e.rs:7:14: 7:15
let mut _5: i32; // in scope 1 at $DIR/simple_option_map_e2e.rs:7:25: 7:29
+ let mut _6: (i32,); // in scope 1 at $DIR/simple_option_map_e2e.rs:7:25: 7:29
scope 2 {
- debug x => _5; // in scope 2 at $DIR/simple_option_map_e2e.rs:7:14: 7:15
+ debug x => _4; // in scope 2 at $DIR/simple_option_map_e2e.rs:7:14: 7:15
scope 3 (inlined ezmap::{closure#0}) { // at $DIR/simple_option_map_e2e.rs:7:25: 7:29
- debug n => _5; // in scope 3 at $DIR/simple_option_map_e2e.rs:+1:13: +1:14
+ debug n => _7; // in scope 3 at $DIR/simple_option_map_e2e.rs:+1:13: +1:14
}
}
}
bb0: {
StorageLive(_2); // scope 0 at $DIR/simple_option_map_e2e.rs:+1:12: +1:21
+ StorageLive(_4); // scope 0 at $DIR/simple_option_map_e2e.rs:+1:5: +1:22
_3 = discriminant(_1); // scope 1 at $DIR/simple_option_map_e2e.rs:6:11: 6:14
switchInt(move _3) -> [0: bb1, 1: bb3, otherwise: bb2]; // scope 1 at $DIR/simple_option_map_e2e.rs:6:5: 6:14
}
bb1: {
- Deinit(_0); // scope 1 at $DIR/simple_option_map_e2e.rs:8:17: 8:21
- discriminant(_0) = 0; // scope 1 at $DIR/simple_option_map_e2e.rs:8:17: 8:21
+ _0 = Option::<i32>::None; // scope 1 at $DIR/simple_option_map_e2e.rs:8:17: 8:21
goto -> bb4; // scope 1 at $DIR/simple_option_map_e2e.rs:8:17: 8:21
}
}
bb3: {
- _5 = move ((_1 as Some).0: i32); // scope 1 at $DIR/simple_option_map_e2e.rs:7:14: 7:15
- StorageLive(_4); // scope 2 at $DIR/simple_option_map_e2e.rs:7:25: 7:29
- _4 = Add(_5, const 1_i32); // scope 3 at $DIR/simple_option_map_e2e.rs:+1:16: +1:21
- Deinit(_0); // scope 2 at $DIR/simple_option_map_e2e.rs:7:20: 7:30
- ((_0 as Some).0: i32) = move _4; // scope 2 at $DIR/simple_option_map_e2e.rs:7:20: 7:30
- discriminant(_0) = 1; // scope 2 at $DIR/simple_option_map_e2e.rs:7:20: 7:30
- StorageDead(_4); // scope 2 at $DIR/simple_option_map_e2e.rs:7:29: 7:30
+ _4 = move ((_1 as Some).0: i32); // scope 1 at $DIR/simple_option_map_e2e.rs:7:14: 7:15
+ StorageLive(_5); // scope 2 at $DIR/simple_option_map_e2e.rs:7:25: 7:29
+ StorageLive(_6); // scope 2 at $DIR/simple_option_map_e2e.rs:7:25: 7:29
+ _6 = (move _4,); // scope 2 at $DIR/simple_option_map_e2e.rs:7:25: 7:29
+ StorageLive(_7); // scope 2 at $DIR/simple_option_map_e2e.rs:7:25: 7:29
+ _7 = move (_6.0: i32); // scope 2 at $DIR/simple_option_map_e2e.rs:7:25: 7:29
+ _5 = Add(_7, const 1_i32); // scope 3 at $DIR/simple_option_map_e2e.rs:+1:16: +1:21
+ StorageDead(_7); // scope 2 at $DIR/simple_option_map_e2e.rs:7:25: 7:29
+ StorageDead(_6); // scope 2 at $DIR/simple_option_map_e2e.rs:7:28: 7:29
+ _0 = Option::<i32>::Some(move _5); // scope 2 at $DIR/simple_option_map_e2e.rs:7:20: 7:30
+ StorageDead(_5); // scope 2 at $DIR/simple_option_map_e2e.rs:7:29: 7:30
goto -> bb4; // scope 1 at $DIR/simple_option_map_e2e.rs:10:1: 10:2
}
bb4: {
+ StorageDead(_4); // scope 0 at $DIR/simple_option_map_e2e.rs:+1:5: +1:22
StorageDead(_2); // scope 0 at $DIR/simple_option_map_e2e.rs:+1:21: +1:22
return; // scope 0 at $DIR/simple_option_map_e2e.rs:+2:2: +2:2
}
bb0: {
- StorageLive(_1); // scope 0 at $DIR/simplify_locals.rs:+2:13: +2:17
-- Deinit(_1); // scope 0 at $DIR/simplify_locals.rs:+2:13: +2:17
-- discriminant(_1) = 0; // scope 0 at $DIR/simplify_locals.rs:+2:13: +2:17
+- _1 = E::A; // scope 0 at $DIR/simplify_locals.rs:+2:13: +2:17
- StorageDead(_1); // scope 0 at $DIR/simplify_locals.rs:+2:17: +2:18
_0 = const (); // scope 0 at $DIR/simplify_locals.rs:+0:9: +3:2
return; // scope 0 at $DIR/simplify_locals.rs:+3:2: +3:2
bb0: {
- StorageLive(_1); // scope 0 at $DIR/simplify_locals.rs:+2:22: +2:26
-- Deinit(_1); // scope 0 at $DIR/simplify_locals.rs:+2:22: +2:26
-- discriminant(_1) = 1; // scope 0 at $DIR/simplify_locals.rs:+2:22: +2:26
+- _1 = E::B; // scope 0 at $DIR/simplify_locals.rs:+2:22: +2:26
- StorageLive(_2); // scope 0 at $DIR/simplify_locals.rs:+2:5: +2:17
- StorageLive(_3); // scope 0 at $DIR/simplify_locals.rs:+2:11: +2:15
-- Deinit(_3); // scope 0 at $DIR/simplify_locals.rs:+2:11: +2:15
-- discriminant(_3) = 0; // scope 0 at $DIR/simplify_locals.rs:+2:11: +2:15
-- Deinit(_2); // scope 0 at $DIR/simplify_locals.rs:+2:6: +2:16
-- (_2.0: i32) = const 10_i32; // scope 0 at $DIR/simplify_locals.rs:+2:6: +2:16
-- (_2.1: E) = move _3; // scope 0 at $DIR/simplify_locals.rs:+2:6: +2:16
+- _3 = E::A; // scope 0 at $DIR/simplify_locals.rs:+2:11: +2:15
+- _2 = (const 10_i32, move _3); // scope 0 at $DIR/simplify_locals.rs:+2:6: +2:16
- StorageDead(_3); // scope 0 at $DIR/simplify_locals.rs:+2:15: +2:16
- (_2.1: E) = move _1; // scope 0 at $DIR/simplify_locals.rs:+2:5: +2:26
- StorageDead(_1); // scope 0 at $DIR/simplify_locals.rs:+2:25: +2:26
bb0: {
StorageLive(_1); // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:30: +1:69
StorageLive(_2); // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:31: +1:49
- Deinit(_2); // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:31: +1:49
- discriminant(_2) = 0; // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:31: +1:49
+ _2 = Option::<u8>::None; // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:31: +1:49
StorageLive(_3); // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:51: +1:68
- Deinit(_3); // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:51: +1:68
- discriminant(_3) = 0; // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:51: +1:68
- Deinit(_1); // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:30: +1:69
- (_1.0: std::option::Option<u8>) = move _2; // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:30: +1:69
- (_1.1: std::option::Option<T>) = move _3; // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:30: +1:69
+ _3 = Option::<T>::None; // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:51: +1:68
+ _1 = (move _2, move _3); // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:30: +1:69
StorageDead(_3); // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:68: +1:69
StorageDead(_2); // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:68: +1:69
_5 = discriminant((_1.0: std::option::Option<u8>)); // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:12: +1:27
bb0: {
- StorageLive(_1); // scope 0 at $DIR/simplify_locals_removes_unused_consts.rs:+1:20: +1:28
- StorageLive(_2); // scope 0 at $DIR/simplify_locals_removes_unused_consts.rs:+1:21: +1:23
-- Deinit(_2); // scope 0 at $DIR/simplify_locals_removes_unused_consts.rs:+1:21: +1:23
+- _2 = (); // scope 0 at $DIR/simplify_locals_removes_unused_consts.rs:+1:21: +1:23
- StorageLive(_3); // scope 0 at $DIR/simplify_locals_removes_unused_consts.rs:+1:25: +1:27
-- Deinit(_3); // scope 0 at $DIR/simplify_locals_removes_unused_consts.rs:+1:25: +1:27
-- Deinit(_1); // scope 0 at $DIR/simplify_locals_removes_unused_consts.rs:+1:20: +1:28
-- (_1.0: ()) = move _2; // scope 0 at $DIR/simplify_locals_removes_unused_consts.rs:+1:20: +1:28
-- (_1.1: ()) = move _3; // scope 0 at $DIR/simplify_locals_removes_unused_consts.rs:+1:20: +1:28
+- _3 = (); // scope 0 at $DIR/simplify_locals_removes_unused_consts.rs:+1:25: +1:27
+- _1 = (move _2, move _3); // scope 0 at $DIR/simplify_locals_removes_unused_consts.rs:+1:20: +1:28
- StorageDead(_3); // scope 0 at $DIR/simplify_locals_removes_unused_consts.rs:+1:27: +1:28
- StorageDead(_2); // scope 0 at $DIR/simplify_locals_removes_unused_consts.rs:+1:27: +1:28
- StorageDead(_1); // scope 0 at $DIR/simplify_locals_removes_unused_consts.rs:+1:28: +1:29
- StorageLive(_4); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:5: +2:22
- StorageLive(_5); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:13: +2:21
- StorageLive(_6); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:14: +2:16
-- Deinit(_6); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:14: +2:16
+- _6 = (); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:14: +2:16
- StorageLive(_7); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:18: +2:20
-- Deinit(_7); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:18: +2:20
-- Deinit(_5); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:13: +2:21
-- (_5.0: ()) = move _6; // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:13: +2:21
-- (_5.1: ()) = move _7; // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:13: +2:21
+- _7 = (); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:18: +2:20
+- _5 = (move _6, move _7); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:13: +2:21
- StorageDead(_7); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:20: +2:21
- StorageDead(_6); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:20: +2:21
- _4 = use_zst(move _5) -> bb1; // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:5: +2:22
+ StorageLive(_1); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:5: +2:22
+ StorageLive(_2); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:13: +2:21
+ StorageLive(_3); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:14: +2:16
-+ Deinit(_3); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:14: +2:16
++ _3 = (); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:14: +2:16
+ StorageLive(_4); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:18: +2:20
-+ Deinit(_4); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:18: +2:20
-+ Deinit(_2); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:13: +2:21
-+ (_2.0: ()) = move _3; // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:13: +2:21
-+ (_2.1: ()) = move _4; // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:13: +2:21
++ _4 = (); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:18: +2:20
++ _2 = (move _3, move _4); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:13: +2:21
+ StorageDead(_4); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:20: +2:21
+ StorageDead(_3); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:20: +2:21
+ _1 = use_zst(move _2) -> bb1; // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:5: +2:22
- StorageLive(_9); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+4:12: +4:34
- StorageLive(_10); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+4:12: +4:30
- StorageLive(_11); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+4:12: +4:28
-- Deinit(_11); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+4:12: +4:28
-- (_11.0: u8) = const 40_u8; // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+4:12: +4:28
+- _11 = Temp { x: const 40_u8 }; // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+4:12: +4:28
- _10 = (_11.0: u8); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+4:12: +4:30
- _9 = Add(move _10, const 2_u8); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+4:12: +4:34
- StorageDead(_10); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+4:33: +4:34
+ StorageLive(_6); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+4:12: +4:34
+ StorageLive(_7); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+4:12: +4:30
+ StorageLive(_8); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+4:12: +4:28
-+ Deinit(_8); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+4:12: +4:28
-+ (_8.0: u8) = const 40_u8; // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+4:12: +4:28
++ _8 = Temp { x: const 40_u8 }; // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+4:12: +4:28
+ _7 = (_8.0: u8); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+4:12: +4:30
+ _6 = Add(move _7, const 2_u8); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+4:12: +4:34
+ StorageDead(_7); // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+4:33: +4:34
_3 = move ((_1 as Some).0: std::boxed::Box<()>); // scope 0 at $DIR/simplify_locals_removes_unused_discriminant_reads.rs:+3:14: +3:15
StorageLive(_4); // scope 1 at $DIR/simplify_locals_removes_unused_discriminant_reads.rs:+3:25: +3:26
_4 = move _3; // scope 1 at $DIR/simplify_locals_removes_unused_discriminant_reads.rs:+3:25: +3:26
- Deinit(_0); // scope 1 at $DIR/simplify_locals_removes_unused_discriminant_reads.rs:+3:20: +3:27
- ((_0 as Some).0: std::boxed::Box<()>) = move _4; // scope 1 at $DIR/simplify_locals_removes_unused_discriminant_reads.rs:+3:20: +3:27
- discriminant(_0) = 1; // scope 1 at $DIR/simplify_locals_removes_unused_discriminant_reads.rs:+3:20: +3:27
+ _0 = Option::<Box<()>>::Some(move _4); // scope 1 at $DIR/simplify_locals_removes_unused_discriminant_reads.rs:+3:20: +3:27
StorageDead(_4); // scope 1 at $DIR/simplify_locals_removes_unused_discriminant_reads.rs:+3:26: +3:27
StorageDead(_3); // scope 0 at $DIR/simplify_locals_removes_unused_discriminant_reads.rs:+3:26: +3:27
goto -> bb4; // scope 0 at $DIR/simplify_locals_removes_unused_discriminant_reads.rs:+3:26: +3:27
}
bb3: {
- Deinit(_0); // scope 0 at $DIR/simplify_locals_removes_unused_discriminant_reads.rs:+2:17: +2:21
- discriminant(_0) = 0; // scope 0 at $DIR/simplify_locals_removes_unused_discriminant_reads.rs:+2:17: +2:21
+ _0 = Option::<Box<()>>::None; // scope 0 at $DIR/simplify_locals_removes_unused_discriminant_reads.rs:+2:17: +2:21
goto -> bb4; // scope 0 at $DIR/simplify_locals_removes_unused_discriminant_reads.rs:+2:17: +2:21
}
StorageLive(_1); // scope 0 at $DIR/sroa.rs:+1:5: +1:32
StorageLive(_2); // scope 0 at $DIR/sroa.rs:+1:5: +1:30
StorageLive(_3); // scope 0 at $DIR/sroa.rs:+1:7: +1:13
- Deinit(_3); // scope 0 at $DIR/sroa.rs:+1:7: +1:13
- (_3.0: usize) = const 0_usize; // scope 0 at $DIR/sroa.rs:+1:7: +1:13
+ _3 = Tag(const 0_usize); // scope 0 at $DIR/sroa.rs:+1:7: +1:13
StorageLive(_4); // scope 0 at $DIR/sroa.rs:+1:15: +1:21
- Deinit(_4); // scope 0 at $DIR/sroa.rs:+1:15: +1:21
- (_4.0: usize) = const 1_usize; // scope 0 at $DIR/sroa.rs:+1:15: +1:21
+ _4 = Tag(const 1_usize); // scope 0 at $DIR/sroa.rs:+1:15: +1:21
StorageLive(_5); // scope 0 at $DIR/sroa.rs:+1:23: +1:29
- Deinit(_5); // scope 0 at $DIR/sroa.rs:+1:23: +1:29
- (_5.0: usize) = const 2_usize; // scope 0 at $DIR/sroa.rs:+1:23: +1:29
- Deinit(_2); // scope 0 at $DIR/sroa.rs:+1:5: +1:30
- (_2.0: Tag) = move _3; // scope 0 at $DIR/sroa.rs:+1:5: +1:30
- (_2.1: Tag) = move _4; // scope 0 at $DIR/sroa.rs:+1:5: +1:30
- (_2.2: Tag) = move _5; // scope 0 at $DIR/sroa.rs:+1:5: +1:30
+ _5 = Tag(const 2_usize); // scope 0 at $DIR/sroa.rs:+1:23: +1:29
+ _2 = S(move _3, move _4, move _5); // scope 0 at $DIR/sroa.rs:+1:5: +1:30
StorageDead(_5); // scope 0 at $DIR/sroa.rs:+1:29: +1:30
StorageDead(_4); // scope 0 at $DIR/sroa.rs:+1:29: +1:30
StorageDead(_3); // scope 0 at $DIR/sroa.rs:+1:29: +1:30
StorageLive(_2); // scope 1 at $DIR/sroa.rs:+1:22: +1:29
StorageLive(_3); // scope 1 at $DIR/sroa.rs:+1:27: +1:28
_3 = _1; // scope 1 at $DIR/sroa.rs:+1:27: +1:28
- Deinit(_2); // scope 1 at $DIR/sroa.rs:+1:22: +1:29
- ((_2 as Some).0: usize) = move _3; // scope 1 at $DIR/sroa.rs:+1:22: +1:29
- discriminant(_2) = 1; // scope 1 at $DIR/sroa.rs:+1:22: +1:29
+ _2 = Option::<usize>::Some(move _3); // scope 1 at $DIR/sroa.rs:+1:22: +1:29
StorageDead(_3); // scope 1 at $DIR/sroa.rs:+1:28: +1:29
_4 = discriminant(_2); // scope 1 at $DIR/sroa.rs:+1:12: +1:19
switchInt(move _4) -> [1: bb1, otherwise: bb2]; // scope 1 at $DIR/sroa.rs:+1:12: +1:19
}
bb1: {
- Deinit(_4); // scope 0 at $DIR/sroa.rs:+2:8: +2:39
- (_4.0: u32) = const 1_u32; // scope 0 at $DIR/sroa.rs:+2:8: +2:39
- (_4.1: u32) = const 2_u32; // scope 0 at $DIR/sroa.rs:+2:8: +2:39
- (_4.2: u32) = move _5; // scope 0 at $DIR/sroa.rs:+2:8: +2:39
+ _4 = Escaping { a: const 1_u32, b: const 2_u32, c: move _5 }; // scope 0 at $DIR/sroa.rs:+2:8: +2:39
StorageDead(_5); // scope 0 at $DIR/sroa.rs:+2:38: +2:39
_3 = &(_4.0: u32); // scope 0 at $DIR/sroa.rs:+2:7: +2:41
_2 = &raw const (*_3); // scope 0 at $DIR/sroa.rs:+2:7: +2:41
let mut _5: Foo; // in scope 0 at $DIR/sroa.rs:+1:30: +1:70
let mut _6: (); // in scope 0 at $DIR/sroa.rs:+1:45: +1:47
let mut _7: std::option::Option<isize>; // in scope 0 at $DIR/sroa.rs:+1:60: +1:68
-+ let mut _8: u8; // in scope 0 at $DIR/sroa.rs:+1:30: +1:70
-+ let mut _9: (); // in scope 0 at $DIR/sroa.rs:+1:30: +1:70
-+ let mut _10: &str; // in scope 0 at $DIR/sroa.rs:+1:30: +1:70
-+ let mut _11: std::option::Option<isize>; // in scope 0 at $DIR/sroa.rs:+1:30: +1:70
scope 1 {
debug a => _1; // in scope 1 at $DIR/sroa.rs:+1:15: +1:16
debug b => _2; // in scope 1 at $DIR/sroa.rs:+1:18: +1:19
}
bb0: {
-- StorageLive(_5); // scope 0 at $DIR/sroa.rs:+1:30: +1:70
-+ StorageLive(_8); // scope 0 at $DIR/sroa.rs:+1:30: +1:70
-+ StorageLive(_9); // scope 0 at $DIR/sroa.rs:+1:30: +1:70
-+ StorageLive(_10); // scope 0 at $DIR/sroa.rs:+1:30: +1:70
-+ StorageLive(_11); // scope 0 at $DIR/sroa.rs:+1:30: +1:70
+ StorageLive(_5); // scope 0 at $DIR/sroa.rs:+1:30: +1:70
StorageLive(_6); // scope 0 at $DIR/sroa.rs:+1:45: +1:47
- Deinit(_6); // scope 0 at $DIR/sroa.rs:+1:45: +1:47
+ _6 = (); // scope 0 at $DIR/sroa.rs:+1:45: +1:47
StorageLive(_7); // scope 0 at $DIR/sroa.rs:+1:60: +1:68
- Deinit(_7); // scope 0 at $DIR/sroa.rs:+1:60: +1:68
- ((_7 as Some).0: isize) = const -4_isize; // scope 0 at $DIR/sroa.rs:+1:60: +1:68
- discriminant(_7) = 1; // scope 0 at $DIR/sroa.rs:+1:60: +1:68
-- Deinit(_5); // scope 0 at $DIR/sroa.rs:+1:30: +1:70
-- (_5.0: u8) = const 5_u8; // scope 0 at $DIR/sroa.rs:+1:30: +1:70
-- (_5.1: ()) = move _6; // scope 0 at $DIR/sroa.rs:+1:30: +1:70
-- (_5.2: &str) = const "a"; // scope 0 at $DIR/sroa.rs:+1:30: +1:70
-+ Deinit(_8); // scope 0 at $DIR/sroa.rs:+1:30: +1:70
-+ Deinit(_9); // scope 0 at $DIR/sroa.rs:+1:30: +1:70
-+ Deinit(_10); // scope 0 at $DIR/sroa.rs:+1:30: +1:70
-+ Deinit(_11); // scope 0 at $DIR/sroa.rs:+1:30: +1:70
-+ _8 = const 5_u8; // scope 0 at $DIR/sroa.rs:+1:30: +1:70
-+ _9 = move _6; // scope 0 at $DIR/sroa.rs:+1:30: +1:70
-+ _10 = const "a"; // scope 0 at $DIR/sroa.rs:+1:30: +1:70
+ _7 = Option::<isize>::Some(const -4_isize); // scope 0 at $DIR/sroa.rs:+1:60: +1:68
+ _5 = Foo { a: const 5_u8, b: move _6, c: const "a", d: move _7 }; // scope 0 at $DIR/sroa.rs:+1:30: +1:70
// mir::Constant
// + span: $DIR/sroa.rs:57:52: 57:55
// + literal: Const { ty: &str, val: Value(Slice(..)) }
-- (_5.3: std::option::Option<isize>) = move _7; // scope 0 at $DIR/sroa.rs:+1:30: +1:70
-+ _11 = move _7; // scope 0 at $DIR/sroa.rs:+1:30: +1:70
StorageDead(_7); // scope 0 at $DIR/sroa.rs:+1:69: +1:70
StorageDead(_6); // scope 0 at $DIR/sroa.rs:+1:69: +1:70
StorageLive(_1); // scope 0 at $DIR/sroa.rs:+1:15: +1:16
-- _1 = (_5.0: u8); // scope 0 at $DIR/sroa.rs:+1:15: +1:16
-+ _1 = _8; // scope 0 at $DIR/sroa.rs:+1:15: +1:16
+ _1 = (_5.0: u8); // scope 0 at $DIR/sroa.rs:+1:15: +1:16
StorageLive(_2); // scope 0 at $DIR/sroa.rs:+1:18: +1:19
-- _2 = (_5.1: ()); // scope 0 at $DIR/sroa.rs:+1:18: +1:19
-+ _2 = _9; // scope 0 at $DIR/sroa.rs:+1:18: +1:19
+ _2 = (_5.1: ()); // scope 0 at $DIR/sroa.rs:+1:18: +1:19
StorageLive(_3); // scope 0 at $DIR/sroa.rs:+1:21: +1:22
-- _3 = (_5.2: &str); // scope 0 at $DIR/sroa.rs:+1:21: +1:22
-+ _3 = _10; // scope 0 at $DIR/sroa.rs:+1:21: +1:22
+ _3 = (_5.2: &str); // scope 0 at $DIR/sroa.rs:+1:21: +1:22
StorageLive(_4); // scope 0 at $DIR/sroa.rs:+1:24: +1:25
-- _4 = (_5.3: std::option::Option<isize>); // scope 0 at $DIR/sroa.rs:+1:24: +1:25
-- StorageDead(_5); // scope 0 at $DIR/sroa.rs:+1:70: +1:71
-+ _4 = _11; // scope 0 at $DIR/sroa.rs:+1:24: +1:25
-+ StorageDead(_8); // scope 0 at $DIR/sroa.rs:+1:70: +1:71
-+ StorageDead(_9); // scope 0 at $DIR/sroa.rs:+1:70: +1:71
-+ StorageDead(_10); // scope 0 at $DIR/sroa.rs:+1:70: +1:71
-+ StorageDead(_11); // scope 0 at $DIR/sroa.rs:+1:70: +1:71
+ _4 = (_5.3: std::option::Option<isize>); // scope 0 at $DIR/sroa.rs:+1:24: +1:25
+ StorageDead(_5); // scope 0 at $DIR/sroa.rs:+1:70: +1:71
_0 = const (); // scope 0 at $DIR/sroa.rs:+0:15: +6:2
StorageDead(_4); // scope 0 at $DIR/sroa.rs:+6:1: +6:2
StorageDead(_3); // scope 0 at $DIR/sroa.rs:+6:1: +6:2
let mut _0: f32; // return place in scope 0 at $DIR/sroa.rs:+0:27: +0:30
let mut _2: structs::U; // in scope 0 at $DIR/sroa.rs:+6:5: +6:21
let mut _3: f32; // in scope 0 at $DIR/sroa.rs:+6:18: +6:19
-+ let mut _4: usize; // in scope 0 at $DIR/sroa.rs:+6:5: +6:21
-+ let mut _5: f32; // in scope 0 at $DIR/sroa.rs:+6:5: +6:21
bb0: {
-- StorageLive(_2); // scope 0 at $DIR/sroa.rs:+6:5: +6:21
-+ StorageLive(_4); // scope 0 at $DIR/sroa.rs:+6:5: +6:21
-+ StorageLive(_5); // scope 0 at $DIR/sroa.rs:+6:5: +6:21
+ StorageLive(_2); // scope 0 at $DIR/sroa.rs:+6:5: +6:21
StorageLive(_3); // scope 0 at $DIR/sroa.rs:+6:18: +6:19
_3 = _1; // scope 0 at $DIR/sroa.rs:+6:18: +6:19
-- Deinit(_2); // scope 0 at $DIR/sroa.rs:+6:5: +6:21
-- (_2.0: usize) = const 0_usize; // scope 0 at $DIR/sroa.rs:+6:5: +6:21
-- (_2.1: f32) = move _3; // scope 0 at $DIR/sroa.rs:+6:5: +6:21
-+ Deinit(_4); // scope 0 at $DIR/sroa.rs:+6:5: +6:21
-+ Deinit(_5); // scope 0 at $DIR/sroa.rs:+6:5: +6:21
-+ _4 = const 0_usize; // scope 0 at $DIR/sroa.rs:+6:5: +6:21
-+ _5 = move _3; // scope 0 at $DIR/sroa.rs:+6:5: +6:21
+ _2 = U { _foo: const 0_usize, a: move _3 }; // scope 0 at $DIR/sroa.rs:+6:5: +6:21
StorageDead(_3); // scope 0 at $DIR/sroa.rs:+6:20: +6:21
-- _0 = (_2.1: f32); // scope 0 at $DIR/sroa.rs:+6:5: +6:23
-- StorageDead(_2); // scope 0 at $DIR/sroa.rs:+7:1: +7:2
-+ _0 = _5; // scope 0 at $DIR/sroa.rs:+6:5: +6:23
-+ StorageDead(_4); // scope 0 at $DIR/sroa.rs:+7:1: +7:2
-+ StorageDead(_5); // scope 0 at $DIR/sroa.rs:+7:1: +7:2
+ _0 = (_2.1: f32); // scope 0 at $DIR/sroa.rs:+6:5: +6:23
+ StorageDead(_2); // scope 0 at $DIR/sroa.rs:+7:1: +7:2
return; // scope 0 at $DIR/sroa.rs:+7:2: +7:2
}
}
StorageLive(_2); // scope 1 at $DIR/sroa.rs:+5:14: +5:27
StorageLive(_3); // scope 1 at $DIR/sroa.rs:+5:24: +5:25
_3 = _1; // scope 1 at $DIR/sroa.rs:+5:24: +5:25
- Deinit(_2); // scope 1 at $DIR/sroa.rs:+5:14: +5:27
- (_2.0: f32) = move _3; // scope 1 at $DIR/sroa.rs:+5:14: +5:27
+ _2 = Repr { f: move _3 }; // scope 1 at $DIR/sroa.rs:+5:14: +5:27
StorageDead(_3); // scope 1 at $DIR/sroa.rs:+5:26: +5:27
_0 = (_2.1: u32); // scope 1 at $DIR/sroa.rs:+5:14: +5:29
StorageDead(_2); // scope 0 at $DIR/sroa.rs:+6:1: +6:2
bb0: {
StorageLive(_2); // scope 0 at $DIR/try_identity_e2e.rs:+2:15: +7:10
_3 = discriminant(_1); // scope 0 at $DIR/try_identity_e2e.rs:+3:19: +3:20
- switchInt(move _3) -> [0: bb2, 1: bb1, otherwise: bb4]; // scope 0 at $DIR/try_identity_e2e.rs:+3:13: +3:20
+ switchInt(move _3) -> [0: bb2, 1: bb1, otherwise: bb5]; // scope 0 at $DIR/try_identity_e2e.rs:+3:13: +3:20
}
bb1: {
_5 = move ((_1 as Err).0: E); // scope 0 at $DIR/try_identity_e2e.rs:+5:21: +5:22
- Deinit(_2); // scope 2 at $DIR/try_identity_e2e.rs:+5:27: +5:48
- ((_2 as Break).0: E) = move _5; // scope 2 at $DIR/try_identity_e2e.rs:+5:27: +5:48
- discriminant(_2) = 1; // scope 2 at $DIR/try_identity_e2e.rs:+5:27: +5:48
- _6 = discriminant(_2); // scope 0 at $DIR/try_identity_e2e.rs:+2:15: +7:10
- switchInt(move _6) -> [0: bb5, 1: bb3, otherwise: bb4]; // scope 0 at $DIR/try_identity_e2e.rs:+2:9: +7:10
+ _2 = ControlFlow::<E, T>::Break(move _5); // scope 2 at $DIR/try_identity_e2e.rs:+5:27: +5:48
+ goto -> bb3; // scope 0 at $DIR/try_identity_e2e.rs:+5:47: +5:48
}
bb2: {
_4 = move ((_1 as Ok).0: T); // scope 0 at $DIR/try_identity_e2e.rs:+4:20: +4:21
- Deinit(_2); // scope 1 at $DIR/try_identity_e2e.rs:+4:26: +4:50
- ((_2 as Continue).0: T) = move _4; // scope 1 at $DIR/try_identity_e2e.rs:+4:26: +4:50
- discriminant(_2) = 0; // scope 1 at $DIR/try_identity_e2e.rs:+4:26: +4:50
- _6 = discriminant(_2); // scope 0 at $DIR/try_identity_e2e.rs:+2:15: +7:10
- switchInt(move _6) -> [0: bb5, 1: bb3, otherwise: bb4]; // scope 0 at $DIR/try_identity_e2e.rs:+2:9: +7:10
+ _2 = ControlFlow::<E, T>::Continue(move _4); // scope 1 at $DIR/try_identity_e2e.rs:+4:26: +4:50
+ goto -> bb3; // scope 0 at $DIR/try_identity_e2e.rs:+4:49: +4:50
}
bb3: {
+ _6 = discriminant(_2); // scope 0 at $DIR/try_identity_e2e.rs:+2:15: +7:10
+ switchInt(move _6) -> [0: bb6, 1: bb4, otherwise: bb5]; // scope 0 at $DIR/try_identity_e2e.rs:+2:9: +7:10
+ }
+
+ bb4: {
_8 = move ((_2 as Break).0: E); // scope 0 at $DIR/try_identity_e2e.rs:+9:32: +9:33
- Deinit(_0); // scope 4 at $DIR/try_identity_e2e.rs:+9:45: +9:51
- ((_0 as Err).0: E) = move _8; // scope 4 at $DIR/try_identity_e2e.rs:+9:45: +9:51
- discriminant(_0) = 1; // scope 4 at $DIR/try_identity_e2e.rs:+9:45: +9:51
+ _0 = Result::<T, E>::Err(move _8); // scope 4 at $DIR/try_identity_e2e.rs:+9:45: +9:51
StorageDead(_2); // scope 0 at $DIR/try_identity_e2e.rs:+12:1: +12:2
return; // scope 0 at $DIR/try_identity_e2e.rs:+12:1: +12:2
}
- bb4: {
+ bb5: {
unreachable; // scope 0 at $DIR/try_identity_e2e.rs:+2:15: +7:10
}
- bb5: {
+ bb6: {
_7 = move ((_2 as Continue).0: T); // scope 0 at $DIR/try_identity_e2e.rs:+8:35: +8:36
- Deinit(_0); // scope 0 at $DIR/try_identity_e2e.rs:+1:5: +11:6
- ((_0 as Ok).0: T) = move _7; // scope 0 at $DIR/try_identity_e2e.rs:+1:5: +11:6
- discriminant(_0) = 0; // scope 0 at $DIR/try_identity_e2e.rs:+1:5: +11:6
+ _0 = Result::<T, E>::Ok(move _7); // scope 0 at $DIR/try_identity_e2e.rs:+1:5: +11:6
StorageDead(_2); // scope 0 at $DIR/try_identity_e2e.rs:+12:1: +12:2
return; // scope 0 at $DIR/try_identity_e2e.rs:+12:1: +12:2
}
bb1: {
_4 = move ((_1 as Err).0: E); // scope 0 at $DIR/try_identity_e2e.rs:+4:17: +4:18
- Deinit(_0); // scope 2 at $DIR/try_identity_e2e.rs:+4:30: +4:36
- ((_0 as Err).0: E) = move _4; // scope 2 at $DIR/try_identity_e2e.rs:+4:30: +4:36
- discriminant(_0) = 1; // scope 2 at $DIR/try_identity_e2e.rs:+4:30: +4:36
+ _0 = Result::<T, E>::Err(move _4); // scope 2 at $DIR/try_identity_e2e.rs:+4:30: +4:36
return; // scope 0 at $DIR/try_identity_e2e.rs:+7:1: +7:2
}
bb3: {
_3 = move ((_1 as Ok).0: T); // scope 0 at $DIR/try_identity_e2e.rs:+3:16: +3:17
- Deinit(_0); // scope 0 at $DIR/try_identity_e2e.rs:+1:5: +6:6
- ((_0 as Ok).0: T) = move _3; // scope 0 at $DIR/try_identity_e2e.rs:+1:5: +6:6
- discriminant(_0) = 0; // scope 0 at $DIR/try_identity_e2e.rs:+1:5: +6:6
+ _0 = Result::<T, E>::Ok(move _3); // scope 0 at $DIR/try_identity_e2e.rs:+1:5: +6:6
return; // scope 0 at $DIR/try_identity_e2e.rs:+7:1: +7:2
}
}
bb0: {
StorageLive(_1); // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:5: +5:6
StorageLive(_2); // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:11: +1:19
- Deinit(_2); // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:11: +1:19
- discriminant(_2) = 2; // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:11: +1:19
+ _2 = Test1::C; // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:11: +1:19
_3 = discriminant(_2); // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:11: +1:19
switchInt(move _3) -> [2: bb1, otherwise: bb2]; // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:5: +1:19
}
StorageDead(_1); // scope 0 at $DIR/uninhabited_enum_branching.rs:+5:6: +5:7
StorageLive(_6); // scope 0 at $DIR/uninhabited_enum_branching.rs:+7:5: +10:6
StorageLive(_7); // scope 0 at $DIR/uninhabited_enum_branching.rs:+7:11: +7:19
- Deinit(_7); // scope 0 at $DIR/uninhabited_enum_branching.rs:+7:11: +7:19
- discriminant(_7) = 0; // scope 0 at $DIR/uninhabited_enum_branching.rs:+7:11: +7:19
+ _7 = Test2::D; // scope 0 at $DIR/uninhabited_enum_branching.rs:+7:11: +7:19
_8 = discriminant(_7); // scope 0 at $DIR/uninhabited_enum_branching.rs:+7:11: +7:19
switchInt(move _8) -> [4: bb5, 5: bb3, otherwise: bb4]; // scope 0 at $DIR/uninhabited_enum_branching.rs:+7:5: +7:19
}
bb0: {
StorageLive(_1); // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:5: +5:6
StorageLive(_2); // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:11: +1:19
- Deinit(_2); // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:11: +1:19
- discriminant(_2) = 2; // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:11: +1:19
+ _2 = Test1::C; // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:11: +1:19
_3 = discriminant(_2); // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:11: +1:19
- switchInt(move _3) -> [0: bb3, 1: bb4, 2: bb1, otherwise: bb2]; // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:5: +1:19
+ switchInt(move _3) -> [2: bb1, otherwise: bb2]; // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:5: +1:19
StorageDead(_1); // scope 0 at $DIR/uninhabited_enum_branching.rs:+5:6: +5:7
StorageLive(_6); // scope 0 at $DIR/uninhabited_enum_branching.rs:+7:5: +10:6
StorageLive(_7); // scope 0 at $DIR/uninhabited_enum_branching.rs:+7:11: +7:19
- Deinit(_7); // scope 0 at $DIR/uninhabited_enum_branching.rs:+7:11: +7:19
- discriminant(_7) = 0; // scope 0 at $DIR/uninhabited_enum_branching.rs:+7:11: +7:19
+ _7 = Test2::D; // scope 0 at $DIR/uninhabited_enum_branching.rs:+7:11: +7:19
_8 = discriminant(_7); // scope 0 at $DIR/uninhabited_enum_branching.rs:+7:11: +7:19
switchInt(move _8) -> [4: bb8, 5: bb6, otherwise: bb7]; // scope 0 at $DIR/uninhabited_enum_branching.rs:+7:5: +7:19
}
bb0: {
StorageLive(_1); // scope 0 at $DIR/uninhabited_enum_branching2.rs:+1:9: +1:13
StorageLive(_2); // scope 0 at $DIR/uninhabited_enum_branching2.rs:+1:38: +1:46
- Deinit(_2); // scope 0 at $DIR/uninhabited_enum_branching2.rs:+1:38: +1:46
- discriminant(_2) = 2; // scope 0 at $DIR/uninhabited_enum_branching2.rs:+1:38: +1:46
- Deinit(_1); // scope 0 at $DIR/uninhabited_enum_branching2.rs:+1:16: +1:48
- (_1.0: u32) = const 51_u32; // scope 0 at $DIR/uninhabited_enum_branching2.rs:+1:16: +1:48
- (_1.1: Test1) = move _2; // scope 0 at $DIR/uninhabited_enum_branching2.rs:+1:16: +1:48
+ _2 = Test1::C; // scope 0 at $DIR/uninhabited_enum_branching2.rs:+1:38: +1:46
+ _1 = Plop { xx: const 51_u32, test1: move _2 }; // scope 0 at $DIR/uninhabited_enum_branching2.rs:+1:16: +1:48
StorageDead(_2); // scope 0 at $DIR/uninhabited_enum_branching2.rs:+1:47: +1:48
StorageLive(_3); // scope 1 at $DIR/uninhabited_enum_branching2.rs:+3:5: +8:6
StorageLive(_4); // scope 1 at $DIR/uninhabited_enum_branching2.rs:+3:11: +3:22
bb0: {
StorageLive(_1); // scope 0 at $DIR/uninhabited_enum_branching2.rs:+1:9: +1:13
StorageLive(_2); // scope 0 at $DIR/uninhabited_enum_branching2.rs:+1:38: +1:46
- Deinit(_2); // scope 0 at $DIR/uninhabited_enum_branching2.rs:+1:38: +1:46
- discriminant(_2) = 2; // scope 0 at $DIR/uninhabited_enum_branching2.rs:+1:38: +1:46
- Deinit(_1); // scope 0 at $DIR/uninhabited_enum_branching2.rs:+1:16: +1:48
- (_1.0: u32) = const 51_u32; // scope 0 at $DIR/uninhabited_enum_branching2.rs:+1:16: +1:48
- (_1.1: Test1) = move _2; // scope 0 at $DIR/uninhabited_enum_branching2.rs:+1:16: +1:48
+ _2 = Test1::C; // scope 0 at $DIR/uninhabited_enum_branching2.rs:+1:38: +1:46
+ _1 = Plop { xx: const 51_u32, test1: move _2 }; // scope 0 at $DIR/uninhabited_enum_branching2.rs:+1:16: +1:48
StorageDead(_2); // scope 0 at $DIR/uninhabited_enum_branching2.rs:+1:47: +1:48
StorageLive(_3); // scope 1 at $DIR/uninhabited_enum_branching2.rs:+3:5: +8:6
StorageLive(_4); // scope 1 at $DIR/uninhabited_enum_branching2.rs:+3:11: +3:22
let mut _0: Test; // return place in scope 0 at $DIR/unusual_item_types.rs:+0:5: +0:6
bb0: {
- Deinit(_0); // scope 0 at $DIR/unusual_item_types.rs:+0:5: +0:6
- ((_0 as X).0: usize) = move _1; // scope 0 at $DIR/unusual_item_types.rs:+0:5: +0:6
- discriminant(_0) = 0; // scope 0 at $DIR/unusual_item_types.rs:+0:5: +0:6
+ _0 = Test::X(move _1); // scope 0 at $DIR/unusual_item_types.rs:+0:5: +0:6
return; // scope 0 at $DIR/unusual_item_types.rs:+0:5: +0:6
}
}
StorageLive(_1); // scope 0 at $DIR/while_let_loops.rs:+1:9: +1:15
_1 = const 0_i32; // scope 0 at $DIR/while_let_loops.rs:+1:18: +1:19
StorageLive(_2); // scope 2 at $DIR/while_let_loops.rs:+2:28: +2:32
- Deinit(_2); // scope 2 at $DIR/while_let_loops.rs:+2:28: +2:32
- discriminant(_2) = 0; // scope 2 at $DIR/while_let_loops.rs:+2:28: +2:32
+ _2 = Option::<u32>::None; // scope 2 at $DIR/while_let_loops.rs:+2:28: +2:32
- _3 = discriminant(_2); // scope 2 at $DIR/while_let_loops.rs:+2:15: +2:25
- switchInt(move _3) -> [1: bb1, otherwise: bb3]; // scope 2 at $DIR/while_let_loops.rs:+2:15: +2:25
+ _3 = const 0_isize; // scope 2 at $DIR/while_let_loops.rs:+2:15: +2:25
pub mod doc_block_table {
pub trait DocBlockTableTrait {
- fn func();
+ fn foo();
}
/// Struct doc.
/// | header1 | header2 |
/// |--------------------------|--------------------------|
/// | Lorem Ipsum, Lorem Ipsum | Lorem Ipsum, Lorem Ipsum |
- fn func() {
+ fn foo() {
println!();
}
}
///
/// </sub>
pub mod codeblock_sub {}
+pub mod search_results {
+
+ pub struct SearchResults {
+ pub foo: i32,
+ }
+
+ #[macro_export]
+ macro_rules! foo {
+ () => {};
+ }
+
+}
--- /dev/null
+// exact-check
+
+// https://github.com/rust-lang/rust/issues/103357
+const QUERY = 'regex';
+
+const EXPECTED = {
+ 'others': [],
+ 'in_args': [],
+ 'returned': [],
+};
{ 'path': 'std', 'name': 'println' },
{ 'path': 'std', 'name': 'eprint' },
{ 'path': 'std', 'name': 'eprintln' },
- { 'path': 'std::pin', 'name': 'pin' },
- { 'path': 'std::future', 'name': 'join' },
- { 'path': 'std', 'name': 'line' },
- { 'path': 'std', 'name': 'write' },
],
};
-// exact-check
-
const QUERY = [
'StructItem',
'StructFieldItem',
'others': [
{ 'path': 'module_substring::Sig', 'name': 'pc' },
{ 'path': 'module_substring::Si', 'name': 'pc' },
- { 'path': 'module_substring::Si', 'name': 'pa' },
],
};
fn bar(&self);
fn foo(&mut self) {}
}
+
+pub trait Bar {
+ fn bar(&self);
+ fn foo1(&mut self) {}
+ fn foo2(&mut self) {}
+}
+
+pub trait Baz {
+ fn bar1(&self);
+ fn bar2(&self);
+ fn foo(&mut self) {}
+}
<code>pub trait Write {
+ // Required methods
fn <a href="#tymethod.poll_write" class="fn">poll_write</a>(<br />        self: <a class="enum" href="{{channel}}/core/option/enum.Option.html" title="enum core::option::Option">Option</a><<a class="struct" href="{{channel}}/alloc/string/struct.String.html" title="struct alloc::string::String">String</a>>,<br />        cx: &mut <a class="enum" href="{{channel}}/core/option/enum.Option.html" title="enum core::option::Option">Option</a><<a class="struct" href="{{channel}}/alloc/string/struct.String.html" title="struct alloc::string::String">String</a>>,<br />        buf: &mut [<a class="primitive" href="{{channel}}/std/primitive.usize.html">usize</a>]<br />    ) -> <a class="enum" href="{{channel}}/core/option/enum.Option.html" title="enum core::option::Option">Option</a><<a class="enum" href="{{channel}}/core/result/enum.Result.html" title="enum core::result::Result">Result</a><<a class="primitive" href="{{channel}}/std/primitive.usize.html">usize</a>, <a class="struct" href="struct.Error.html" title="struct foo::Error">Error</a>>>;
<span class="item-spacer" /> fn <a href="#tymethod.poll_flush" class="fn">poll_flush</a>(<br />        self: <a class="enum" href="{{channel}}/core/option/enum.Option.html" title="enum core::option::Option">Option</a><<a class="struct" href="{{channel}}/alloc/string/struct.String.html" title="struct alloc::string::String">String</a>>,<br />        cx: &mut <a class="enum" href="{{channel}}/core/option/enum.Option.html" title="enum core::option::Option">Option</a><<a class="struct" href="{{channel}}/alloc/string/struct.String.html" title="struct alloc::string::String">String</a>><br />    ) -> <a class="enum" href="{{channel}}/core/option/enum.Option.html" title="enum core::option::Option">Option</a><<a class="enum" href="{{channel}}/core/result/enum.Result.html" title="enum core::result::Result">Result</a><<a class="primitive" href="{{channel}}/std/primitive.unit.html">()</a>, <a class="struct" href="struct.Error.html" title="struct foo::Error">Error</a>>>;
<span class="item-spacer" /> fn <a href="#tymethod.poll_close" class="fn">poll_close</a>(<br />        self: <a class="enum" href="{{channel}}/core/option/enum.Option.html" title="enum core::option::Option">Option</a><<a class="struct" href="{{channel}}/alloc/string/struct.String.html" title="struct alloc::string::String">String</a>>,<br />        cx: &mut <a class="enum" href="{{channel}}/core/option/enum.Option.html" title="enum core::option::Option">Option</a><<a class="struct" href="{{channel}}/alloc/string/struct.String.html" title="struct alloc::string::String">String</a>><br />    ) -> <a class="enum" href="{{channel}}/core/option/enum.Option.html" title="enum core::option::Option">Option</a><<a class="enum" href="{{channel}}/core/result/enum.Result.html" title="enum core::result::Result">Result</a><<a class="primitive" href="{{channel}}/std/primitive.unit.html">()</a>, <a class="struct" href="struct.Error.html" title="struct foo::Error">Error</a>>>;
+ // Provided method
fn <a href="#method.poll_write_vectored" class="fn">poll_write_vectored</a>(<br />        self: <a class="enum" href="{{channel}}/core/option/enum.Option.html" title="enum core::option::Option">Option</a><<a class="struct" href="{{channel}}/alloc/string/struct.String.html" title="struct alloc::string::String">String</a>>,<br />        cx: &mut <a class="enum" href="{{channel}}/core/option/enum.Option.html" title="enum core::option::Option">Option</a><<a class="struct" href="{{channel}}/alloc/string/struct.String.html" title="struct alloc::string::String">String</a>>,<br />        bufs: &[<a class="primitive" href="{{channel}}/std/primitive.usize.html">usize</a>]<br />    ) -> <a class="enum" href="{{channel}}/core/option/enum.Option.html" title="enum core::option::Option">Option</a><<a class="enum" href="{{channel}}/core/result/enum.Result.html" title="enum core::result::Result">Result</a><<a class="primitive" href="{{channel}}/std/primitive.usize.html">usize</a>, <a class="struct" href="struct.Error.html" title="struct foo::Error">Error</a>>> { ... }
-}</code>
\ No newline at end of file
+}</code>
extern crate inline_default_methods;
// @has inline_default_methods/trait.Foo.html
-// @has - '//pre[@class="rust item-decl"]' 'fn bar(&self);'
-// @has - '//pre[@class="rust item-decl"]' 'fn foo(&mut self) { ... }'
+// @has - '//pre[@class="rust item-decl"]' '// Required method fn bar(&self);'
+// @has - '//pre[@class="rust item-decl"]' '// Provided method fn foo(&mut self)'
pub use inline_default_methods::Foo;
+
+// @has inline_default_methods/trait.Bar.html
+// @has - '//pre[@class="rust item-decl"]' '// Required method fn bar(&self);'
+// @has - '//pre[@class="rust item-decl"]' '// Provided methods fn foo1(&mut self)'
+// @has - '//pre[@class="rust item-decl"]' 'fn foo2(&mut self)'
+pub use inline_default_methods::Bar;
+
+// @has inline_default_methods/trait.Baz.html
+// @has - '//pre[@class="rust item-decl"]' '// Required methods fn bar1(&self);'
+// @has - '//pre[@class="rust item-decl"]' 'fn bar2(&self);'
+// @has - '//pre[@class="rust item-decl"]' '// Provided method fn foo(&mut self)'
+pub use inline_default_methods::Baz;
extern crate issue_85454;
// @has foo/trait.FromResidual.html
-// @has - '//pre[@class="rust item-decl"]' 'pub trait FromResidual<R = <Self as Try>::Residual> { fn from_residual(residual: R) -> Self; }'
+// @has - '//pre[@class="rust item-decl"]' 'pub trait FromResidual<R = <Self as Try>::Residual> { // Required method fn from_residual(residual: R) -> Self; }'
pub trait FromResidual<R = <Self as Try>::Residual> {
fn from_residual(residual: R) -> Self;
}
pub mod reexport {
// @has foo/reexport/trait.FromResidual.html
- // @has - '//pre[@class="rust item-decl"]' 'pub trait FromResidual<R = <Self as Try>::Residual> { fn from_residual(residual: R) -> Self; }'
+ // @has - '//pre[@class="rust item-decl"]' 'pub trait FromResidual<R = <Self as Try>::Residual> { // Required method fn from_residual(residual: R) -> Self; }'
pub use issue_85454::*;
}
<pre class="rust item-decl"><code>pub trait TraitWhere {
- type <a href="#associatedtype.Item" class="associatedtype">Item</a><'a><br />    <span class="where">where<br />        Self: 'a</span>;
+ type <a href="#associatedtype.Item" class="associatedtype">Item</a><'a><br />       <span class="where">where Self: 'a</span>;
- fn <a href="#method.func" class="fn">func</a>(self)<br />    <span class="where">where<br />        Self: <a class="trait" href="{{channel}}/core/marker/trait.Sized.html" title="trait core::marker::Sized">Sized</a></span>,
- { ... }
-<span class="item-spacer" /> fn <a href="#method.lines" class="fn">lines</a>(self) -> <a class="struct" href="{{channel}}/std/io/struct.Lines.html" title="struct std::io::Lines">Lines</a><Self><br />    <span class="where">where<br />        Self: <a class="trait" href="{{channel}}/core/marker/trait.Sized.html" title="trait core::marker::Sized">Sized</a></span>,
- { ... }
+ // Provided methods
+ fn <a href="#method.func" class="fn">func</a>(self)<br />       <span class="where">where Self: <a class="trait" href="{{channel}}/core/marker/trait.Sized.html" title="trait core::marker::Sized">Sized</a></span> { ... }
+<span class="item-spacer" /> fn <a href="#method.lines" class="fn">lines</a>(self) -> <a class="struct" href="{{channel}}/std/io/struct.Lines.html" title="struct std::io::Lines">Lines</a><Self><br />       <span class="where">where Self: <a class="trait" href="{{channel}}/core/marker/trait.Sized.html" title="trait core::marker::Sized">Sized</a></span> { ... }
+<span class="item-spacer" /> fn <a href="#method.merge" class="fn">merge</a><T>(self, a: T)<br />       <span class="where">where Self: <a class="trait" href="{{channel}}/core/marker/trait.Sized.html" title="trait core::marker::Sized">Sized</a>,<br />             T: <a class="trait" href="{{channel}}/core/marker/trait.Sized.html" title="trait core::marker::Sized">Sized</a></span> { ... }
}</code></pre>
\ No newline at end of file
where
Self: Sized,
{ todo!() }
+
+ fn merge<T>(self, a: T)
+ where
+ Self: Sized,
+ T: Sized,
+ { todo!() }
}
// @has foo/struct.Echo.html '//*[@class="impl"]//h3[@class="code-header"]' \
<pre class="rust item-decl"><code>pub trait ToOwned<T><span class="where fmt-newline">where<br />    T: <a class="trait" href="{{channel}}/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a>,</span>{
type <a href="#associatedtype.Owned" class="associatedtype">Owned</a>;
+ // Required methods
fn <a href="#tymethod.to_owned" class="fn">to_owned</a>(&self) -> Self::<a class="associatedtype" href="trait.ToOwned.html#associatedtype.Owned" title="type foo::ToOwned::Owned">Owned</a>;
<span class="item-spacer" /> fn <a href="#tymethod.whatever" class="fn">whatever</a>(&self) -> T;
}</code></pre>
\ No newline at end of file
<pre class="rust item-decl"><code>pub trait ToOwned2<T: <a class="trait" href="{{channel}}/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a>> {
type <a href="#associatedtype.Owned" class="associatedtype">Owned</a>;
+ // Required methods
fn <a href="#tymethod.to_owned" class="fn">to_owned</a>(&self) -> Self::<a class="associatedtype" href="trait.ToOwned2.html#associatedtype.Owned" title="type foo::ToOwned2::Owned">Owned</a>;
<span class="item-spacer" /> fn <a href="#tymethod.whatever" class="fn">whatever</a>(&self) -> T;
}</code></pre>
\ No newline at end of file
error[E0594]: cannot assign to `**t1`, which is behind a `&` reference
--> $DIR/borrowck-borrow-mut-base-ptr-in-aliasable-loc.rs:9:5
|
-LL | let t1 = t0;
- | -- consider changing this binding's type to be: `&mut &mut isize`
-LL | let p: &isize = &**t0;
LL | **t1 = 22;
| ^^^^^^^^^ `t1` is a `&` reference, so the data it refers to cannot be written
+ |
+help: consider specifying this binding's type
+ |
+LL | let t1: &mut &mut isize = t0;
+ | +++++++++++++++++
error[E0502]: cannot borrow `**t0` as immutable because it is also borrowed as mutable
--> $DIR/borrowck-borrow-mut-base-ptr-in-aliasable-loc.rs:14:21
fn main() {
let mut test = Vec::new();
let rofl: &Vec<Vec<i32>> = &mut test;
- //~^ NOTE consider changing this binding's type to be
+ //~^ HELP consider changing this binding's type
rofl.push(Vec::new());
//~^ ERROR cannot borrow `*rofl` as mutable, as it is behind a `&` reference
//~| NOTE `rofl` is a `&` reference, so the data it refers to cannot be borrowed as mutable
#[rustfmt::skip]
let x: &usize = &mut{0};
- //~^ NOTE consider changing this binding's type to be
+ //~^ HELP consider changing this binding's type
*x = 1;
//~^ ERROR cannot assign to `*x`, which is behind a `&` reference
//~| NOTE `x` is a `&` reference, so the data it refers to cannot be written
#[rustfmt::skip]
let y: &usize = &mut(0);
- //~^ NOTE consider changing this binding's type to be
+ //~^ HELP consider changing this binding's type
*y = 1;
//~^ ERROR cannot assign to `*y`, which is behind a `&` reference
//~| NOTE `y` is a `&` reference, so the data it refers to cannot be written
error[E0596]: cannot borrow `*rofl` as mutable, as it is behind a `&` reference
--> $DIR/issue-85765.rs:5:5
|
-LL | let rofl: &Vec<Vec<i32>> = &mut test;
- | ---- consider changing this binding's type to be: `&mut Vec<Vec<i32>>`
-LL |
LL | rofl.push(Vec::new());
| ^^^^^^^^^^^^^^^^^^^^^ `rofl` is a `&` reference, so the data it refers to cannot be borrowed as mutable
+ |
+help: consider changing this binding's type
+ |
+LL | let rofl: &mut Vec<Vec<i32>> = &mut test;
+ | ~~~~~~~~~~~~~~~~~~
error[E0594]: cannot assign to `*r`, which is behind a `&` reference
--> $DIR/issue-85765.rs:12:5
error[E0594]: cannot assign to `*x`, which is behind a `&` reference
--> $DIR/issue-85765.rs:19:5
|
-LL | let x: &usize = &mut{0};
- | - consider changing this binding's type to be: `&mut usize`
-LL |
LL | *x = 1;
| ^^^^^^ `x` is a `&` reference, so the data it refers to cannot be written
+ |
+help: consider changing this binding's type
+ |
+LL | let x: &mut usize = &mut{0};
+ | ~~~~~~~~~~
error[E0594]: cannot assign to `*y`, which is behind a `&` reference
--> $DIR/issue-85765.rs:26:5
|
-LL | let y: &usize = &mut(0);
- | - consider changing this binding's type to be: `&mut usize`
-LL |
LL | *y = 1;
| ^^^^^^ `y` is a `&` reference, so the data it refers to cannot be written
+ |
+help: consider changing this binding's type
+ |
+LL | let y: &mut usize = &mut(0);
+ | ~~~~~~~~~~
error: aborting due to 4 previous errors
fn main() {
let client = TestClient;
let inner = client.get_inner_ref();
- //~^ NOTE consider changing this binding's type to be
+ //~^ HELP consider specifying this binding's type
inner.clear();
//~^ ERROR cannot borrow `*inner` as mutable, as it is behind a `&` reference [E0596]
//~| NOTE `inner` is a `&` reference, so the data it refers to cannot be borrowed as mutable
error[E0596]: cannot borrow `*inner` as mutable, as it is behind a `&` reference
--> $DIR/issue-91206.rs:13:5
|
-LL | let inner = client.get_inner_ref();
- | ----- consider changing this binding's type to be: `&mut Vec<usize>`
-LL |
LL | inner.clear();
| ^^^^^^^^^^^^^ `inner` is a `&` reference, so the data it refers to cannot be borrowed as mutable
+ |
+help: consider specifying this binding's type
+ |
+LL | let inner: &mut Vec<usize> = client.get_inner_ref();
+ | +++++++++++++++++
error: aborting due to previous error
error[E0594]: cannot assign to `*foo`, which is behind a `&` reference
--> $DIR/issue-92015.rs:6:5
|
-LL | let foo = Some(&0).unwrap();
- | --- consider changing this binding's type to be: `&mut i32`
LL | *foo = 1;
| ^^^^^^^^ `foo` is a `&` reference, so the data it refers to cannot be written
+ |
+help: consider specifying this binding's type
+ |
+LL | let foo: &mut i32 = Some(&0).unwrap();
+ | ++++++++++
error: aborting due to previous error
--- /dev/null
+// checks that when we relate a `Expr::Binop` we also relate the types of the
+// const arguments.
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+
+struct Bar<const B: bool>;
+
+const fn make_generic(_: usize, a: bool) -> bool {
+ a
+}
+
+fn foo<const N: usize>() -> Bar<{ make_generic(N, true == false) }> {
+ Bar::<{ make_generic(N, 1_u8 == 0_u8) }>
+ //~^ error: mismatched types
+ //~| error: unconstrained generic constant
+}
+
+fn main() {}
--- /dev/null
+error[E0308]: mismatched types
+ --> $DIR/relate_binop_arg_tys.rs:13:5
+ |
+LL | Bar::<{ make_generic(N, 1_u8 == 0_u8) }>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `{ make_generic(N, true == false) }`, found `{ make_generic(N, 1_u8 == 0_u8) }`
+ |
+ = note: expected constant `{ make_generic(N, true == false) }`
+ found constant `{ make_generic(N, 1_u8 == 0_u8) }`
+
+error: unconstrained generic constant
+ --> $DIR/relate_binop_arg_tys.rs:13:11
+ |
+LL | Bar::<{ make_generic(N, 1_u8 == 0_u8) }>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: try adding a `where` bound using this expression: `where [(); { make_generic(N, 1_u8 == 0_u8) }]:`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
--- /dev/null
+// checks that when we relate a `Expr::Cast` we also relate the type of the
+// const argument.
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+
+fn foo<const N: usize>() -> [(); (true as usize) + N] {
+ [(); (1_u8 as usize) + N]
+ //~^ error: mismatched types
+ //~| error: unconstrained generic constant
+}
+
+fn main() {}
--- /dev/null
+error[E0308]: mismatched types
+ --> $DIR/relate_cast_arg_ty.rs:7:5
+ |
+LL | [(); (1_u8 as usize) + N]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `(true as usize) + N`, found `(1_u8 as usize) + N`
+ |
+ = note: expected constant `(true as usize) + N`
+ found constant `(1_u8 as usize) + N`
+
+error: unconstrained generic constant
+ --> $DIR/relate_cast_arg_ty.rs:7:10
+ |
+LL | [(); (1_u8 as usize) + N]
+ | ^^^^^^^^^^^^^^^^^^^
+ |
+ = help: try adding a `where` bound using this expression: `where [(); (1_u8 as usize) + N]:`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
LL | black_box((S::<i32>::FOO, S::<u32>::FOO));
| ^^^^^^^^^^^^^
-note: erroneous constant used
- --> $DIR/const-err-late.rs:19:31
- |
-LL | black_box((S::<i32>::FOO, S::<u32>::FOO));
- | ^^^^^^^^^^^^^
-
note: erroneous constant used
--> $DIR/const-err-late.rs:19:16
|
LL | black_box((S::<i32>::FOO, S::<u32>::FOO));
| ^^^^^^^^^^^^^
-note: erroneous constant used
- --> $DIR/const-err-late.rs:19:31
- |
-LL | black_box((S::<i32>::FOO, S::<u32>::FOO));
- | ^^^^^^^^^^^^^
-
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0080`.
*foo = 32;
//~^ ERROR cannot assign to `*foo`, which is behind a `&` reference
let bar = foo;
+ //~^ HELP consider specifying this binding's type
*bar = 64;
//~^ ERROR cannot assign to `*bar`, which is behind a `&` reference
}
| ~~~~~~~
error[E0594]: cannot assign to `*bar`, which is behind a `&` reference
- --> $DIR/issue-51515.rs:8:5
+ --> $DIR/issue-51515.rs:9:5
|
-LL | let bar = foo;
- | --- consider changing this binding's type to be: `&mut i32`
LL | *bar = 64;
| ^^^^^^^^^ `bar` is a `&` reference, so the data it refers to cannot be written
+ |
+help: consider specifying this binding's type
+ |
+LL | let bar: &mut i32 = foo;
+ | ++++++++++
error: aborting due to 2 previous errors
--- /dev/null
+pub struct DefaultLifetime<'a, 'b = 'static> {
+ //~^ ERROR unexpected default lifetime parameter
+ _marker: std::marker::PhantomData<&'a &'b ()>,
+}
+
+fn main(){}
--- /dev/null
+error: unexpected default lifetime parameter
+ --> $DIR/issue-107492-default-value-for-lifetime.rs:1:35
+ |
+LL | pub struct DefaultLifetime<'a, 'b = 'static> {
+ | ^^^^^^^^^ lifetime parameters cannot have default values
+
+error: aborting due to previous error
+
--- /dev/null
+// check that we don't generate a span that points beyond EOF
+
+// error-pattern: unclosed delimiter
+// error-pattern: unclosed delimiter
+// error-pattern: unclosed delimiter
+
+fn a(){{{
--- /dev/null
+error: this file contains an unclosed delimiter
+ --> $DIR/issue-107423-unused-delim-only-one-no-pair.rs:7:11
+ |
+LL | fn a(){{{
+ | --- ^
+ | |||
+ | ||unclosed delimiter
+ | |unclosed delimiter
+ | unclosed delimiter
+
+error: this file contains an unclosed delimiter
+ --> $DIR/issue-107423-unused-delim-only-one-no-pair.rs:7:11
+ |
+LL | fn a(){{{
+ | --- ^
+ | |||
+ | ||unclosed delimiter
+ | |unclosed delimiter
+ | unclosed delimiter
+
+error: this file contains an unclosed delimiter
+ --> $DIR/issue-107423-unused-delim-only-one-no-pair.rs:7:11
+ |
+LL | fn a(){{{
+ | --- ^
+ | |||
+ | ||unclosed delimiter
+ | |unclosed delimiter
+ | unclosed delimiter
+
+error: aborting due to 3 previous errors
+
--- /dev/null
+fn main() {
+ for i in {
+ //~^ ERROR missing expression to iterate on in `for` loop
+ }
+}
--- /dev/null
+error: missing expression to iterate on in `for` loop
+ --> $DIR/missing-expression-in-for-loop.rs:2:14
+ |
+LL | for i in {
+ | ^
+ |
+help: try adding an expression to the `for` loop
+ |
+LL | for i in /* expression */ {
+ | ++++++++++++++++
+
+error: aborting due to previous error
+
--- /dev/null
+// run-rustfix
+
+// Suggest providing a std::ptr::null{,_mut}() to a function that takes in a raw
+// pointer if a literal 0 was provided by the user.
+
+extern "C" {
+ fn foo(ptr: *const u8);
+
+ fn foo_mut(ptr: *mut u8);
+
+ fn usize(ptr: *const usize);
+
+ fn usize_mut(ptr: *mut usize);
+}
+
+fn main() {
+ unsafe {
+ foo(std::ptr::null());
+ //~^ mismatched types [E0308]
+ //~| if you meant to create a null pointer, use `std::ptr::null()`
+ foo_mut(std::ptr::null_mut());
+ //~^ mismatched types [E0308]
+ //~| if you meant to create a null pointer, use `std::ptr::null_mut()`
+ usize(std::ptr::null());
+ //~^ mismatched types [E0308]
+ //~| if you meant to create a null pointer, use `std::ptr::null()`
+ usize_mut(std::ptr::null_mut());
+ //~^ mismatched types [E0308]
+ //~| if you meant to create a null pointer, use `std::ptr::null_mut()`
+ }
+}
--- /dev/null
+// run-rustfix
+
+// Suggest providing a std::ptr::null{,_mut}() to a function that takes in a raw
+// pointer if a literal 0 was provided by the user.
+
+extern "C" {
+ fn foo(ptr: *const u8);
+
+ fn foo_mut(ptr: *mut u8);
+
+ fn usize(ptr: *const usize);
+
+ fn usize_mut(ptr: *mut usize);
+}
+
+fn main() {
+ unsafe {
+ foo(0);
+ //~^ mismatched types [E0308]
+ //~| if you meant to create a null pointer, use `std::ptr::null()`
+ foo_mut(0);
+ //~^ mismatched types [E0308]
+ //~| if you meant to create a null pointer, use `std::ptr::null_mut()`
+ usize(0);
+ //~^ mismatched types [E0308]
+ //~| if you meant to create a null pointer, use `std::ptr::null()`
+ usize_mut(0);
+ //~^ mismatched types [E0308]
+ //~| if you meant to create a null pointer, use `std::ptr::null_mut()`
+ }
+}
--- /dev/null
+error[E0308]: mismatched types
+ --> $DIR/suggest-null-ptr.rs:18:13
+ |
+LL | foo(0);
+ | --- ^ expected `*const u8`, found `usize`
+ | |
+ | arguments to this function are incorrect
+ |
+ = note: expected raw pointer `*const u8`
+ found type `usize`
+note: function defined here
+ --> $DIR/suggest-null-ptr.rs:7:8
+ |
+LL | fn foo(ptr: *const u8);
+ | ^^^
+help: if you meant to create a null pointer, use `std::ptr::null()`
+ |
+LL | foo(std::ptr::null());
+ | ~~~~~~~~~~~~~~~~
+
+error[E0308]: mismatched types
+ --> $DIR/suggest-null-ptr.rs:21:17
+ |
+LL | foo_mut(0);
+ | ------- ^ expected `*mut u8`, found `usize`
+ | |
+ | arguments to this function are incorrect
+ |
+ = note: expected raw pointer `*mut u8`
+ found type `usize`
+note: function defined here
+ --> $DIR/suggest-null-ptr.rs:9:8
+ |
+LL | fn foo_mut(ptr: *mut u8);
+ | ^^^^^^^
+help: if you meant to create a null pointer, use `std::ptr::null_mut()`
+ |
+LL | foo_mut(std::ptr::null_mut());
+ | ~~~~~~~~~~~~~~~~~~~~
+
+error[E0308]: mismatched types
+ --> $DIR/suggest-null-ptr.rs:24:15
+ |
+LL | usize(0);
+ | ----- ^ expected `*const usize`, found `usize`
+ | |
+ | arguments to this function are incorrect
+ |
+ = note: expected raw pointer `*const usize`
+ found type `usize`
+note: function defined here
+ --> $DIR/suggest-null-ptr.rs:11:8
+ |
+LL | fn usize(ptr: *const usize);
+ | ^^^^^
+help: if you meant to create a null pointer, use `std::ptr::null()`
+ |
+LL | usize(std::ptr::null());
+ | ~~~~~~~~~~~~~~~~
+
+error[E0308]: mismatched types
+ --> $DIR/suggest-null-ptr.rs:27:19
+ |
+LL | usize_mut(0);
+ | --------- ^ expected `*mut usize`, found `usize`
+ | |
+ | arguments to this function are incorrect
+ |
+ = note: expected raw pointer `*mut usize`
+ found type `usize`
+note: function defined here
+ --> $DIR/suggest-null-ptr.rs:13:8
+ |
+LL | fn usize_mut(ptr: *mut usize);
+ | ^^^^^^^^^
+help: if you meant to create a null pointer, use `std::ptr::null_mut()`
+ |
+LL | usize_mut(std::ptr::null_mut());
+ | ~~~~~~~~~~~~~~~~~~~~
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
[mentions."compiler/rustc_error_messages"]
message = "`rustc_error_messages` was changed"
-cc = ["@davidtwco", "@compiler-errors", "@JohnTitor", "@estebank", "@TaKO8Ki"]
+cc = ["@davidtwco", "@compiler-errors", "@JohnTitor", "@TaKO8Ki"]
[mentions."compiler/rustc_errors/src/translation.rs"]
message = "`rustc_errors::translation` was changed"
-cc = ["@davidtwco", "@compiler-errors", "@JohnTitor", "@estebank", "@TaKO8Ki"]
+cc = ["@davidtwco", "@compiler-errors", "@JohnTitor", "@TaKO8Ki"]
[mentions."compiler/rustc_macros/src/diagnostics"]
message = "`rustc_macros::diagnostics` was changed"
-cc = ["@davidtwco", "@compiler-errors", "@JohnTitor", "@estebank", "@TaKO8Ki"]
+cc = ["@davidtwco", "@compiler-errors", "@JohnTitor", "@TaKO8Ki"]
[mentions."compiler/rustc_target/src/spec"]
message = """
[assign.adhoc_groups]
compiler-team = [
"@cjgillot",
- "@estebank",
"@petrochenkov",
"@davidtwco",
"@oli-obk",
diagnostics = [
"@compiler-errors",
"@davidtwco",
- "@estebank",
"@oli-obk",
"@TaKO8Ki",
]
parser = [
"@davidtwco",
- "@estebank",
"@nnethercote",
"@petrochenkov",
]