diff options
| author | Ralf Jung <post@ralfj.de> | 2024-05-04 18:37:35 +0200 |
|---|---|---|
| committer | Ralf Jung <post@ralfj.de> | 2024-05-04 18:37:35 +0200 |
| commit | 0c989293cefeaa23390aea4f4a4dec07447b8236 (patch) | |
| tree | 60910c960bb6108f3d39af6ee68f58b9889c3c9a /compiler | |
| parent | adb74ae486938f14ef5a337b0550804abaa6aa0d (diff) | |
| parent | d7ea27808deb5e10a0f7384e339e4e6165e33398 (diff) | |
| download | rust-0c989293cefeaa23390aea4f4a4dec07447b8236.tar.gz rust-0c989293cefeaa23390aea4f4a4dec07447b8236.zip | |
Merge from rustc
Diffstat (limited to 'compiler')
75 files changed, 673 insertions, 374 deletions
diff --git a/compiler/rustc/src/main.rs b/compiler/rustc/src/main.rs index 434b978ae31..7ba58406ef1 100644 --- a/compiler/rustc/src/main.rs +++ b/compiler/rustc/src/main.rs @@ -1,5 +1,3 @@ -#![feature(unix_sigpipe)] - // A note about jemalloc: rustc uses jemalloc when built for CI and // distribution. The obvious way to do this is with the `#[global_allocator]` // mechanism. However, for complicated reasons (see @@ -34,7 +32,6 @@ // https://github.com/rust-lang/rust/commit/b90cfc887c31c3e7a9e6d462e2464db1fe506175#diff-43914724af6e464c1da2171e4a9b6c7e607d5bc1203fa95c0ab85be4122605ef // for an example of how to do so. -#[unix_sigpipe = "sig_dfl"] fn main() { // See the comment at the top of this file for an explanation of this. #[cfg(feature = "jemalloc-sys")] diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index 6a2943da4a3..5e3f64540e4 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -21,6 +21,8 @@ use rustc_macros::{Decodable_Generic, Encodable_Generic}; use std::iter::Step; mod layout; +#[cfg(test)] +mod tests; pub use layout::LayoutCalculator; diff --git a/compiler/rustc_abi/src/tests.rs b/compiler/rustc_abi/src/tests.rs new file mode 100644 index 00000000000..d993012378c --- /dev/null +++ b/compiler/rustc_abi/src/tests.rs @@ -0,0 +1,7 @@ +use super::*; + +#[test] +fn align_constants() { + assert_eq!(Align::ONE, Align::from_bytes(1).unwrap()); + assert_eq!(Align::EIGHT, Align::from_bytes(8).unwrap()); +} diff --git a/compiler/rustc_ast_lowering/src/index.rs b/compiler/rustc_ast_lowering/src/index.rs index be6c7da4108..7254be2b2f4 100644 --- a/compiler/rustc_ast_lowering/src/index.rs +++ b/compiler/rustc_ast_lowering/src/index.rs @@ -62,7 +62,7 @@ pub(super) fn index_hir<'hir>( if let Node::Err(span) = node.node { let hir_id = HirId { owner: item.def_id(), local_id }; let msg = format!("ID {hir_id} not encountered when visiting item HIR"); - tcx.dcx().span_delayed_bug(*span, msg); + tcx.dcx().span_delayed_bug(span, msg); } } @@ -376,7 +376,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { } } - fn visit_array_length(&mut self, len: &'hir ArrayLen) { + fn visit_array_length(&mut self, len: &'hir ArrayLen<'hir>) { match len { ArrayLen::Infer(inf) => self.insert(inf.span, inf.hir_id, Node::ArrayLenInfer(inf)), ArrayLen::Body(..) => intravisit::walk_array_len(self, len), diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index dcd8f5d5f15..156e369c458 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -1589,11 +1589,12 @@ impl<'hir> LoweringContext<'_, 'hir> { }), )), )), - default: Some(hir::AnonConst { + default: Some(self.arena.alloc(hir::AnonConst { def_id: anon_const, hir_id: const_id, body: const_body, - }), + span, + })), is_host_effect: true, }, colon_span: None, diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index dd8c09ce485..6c54363e306 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1178,14 +1178,17 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { tokens: None, }; - let ct = self.with_new_scopes(span, |this| hir::AnonConst { - def_id, - hir_id: this.lower_node_id(node_id), - body: this.lower_const_body(path_expr.span, Some(&path_expr)), + let ct = self.with_new_scopes(span, |this| { + self.arena.alloc(hir::AnonConst { + def_id, + hir_id: this.lower_node_id(node_id), + body: this + .lower_const_body(path_expr.span, Some(&path_expr)), + span, + }) }); return GenericArg::Const(ConstArg { value: ct, - span, is_desugared_from_effects: false, }); } @@ -1197,7 +1200,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } ast::GenericArg::Const(ct) => GenericArg::Const(ConstArg { value: self.lower_anon_const(ct), - span: self.lower_span(ct.value.span), is_desugared_from_effects: false, }), } @@ -2315,7 +2317,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable - fn lower_array_length(&mut self, c: &AnonConst) -> hir::ArrayLen { + fn lower_array_length(&mut self, c: &AnonConst) -> hir::ArrayLen<'hir> { match c.value.kind { ExprKind::Underscore => { if self.tcx.features().generic_arg_infer { @@ -2338,12 +2340,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } } - fn lower_anon_const(&mut self, c: &AnonConst) -> hir::AnonConst { - self.with_new_scopes(c.value.span, |this| hir::AnonConst { + fn lower_anon_const(&mut self, c: &AnonConst) -> &'hir hir::AnonConst { + self.arena.alloc(self.with_new_scopes(c.value.span, |this| hir::AnonConst { def_id: this.local_def_id(c.id), hir_id: this.lower_node_id(c.id), body: this.lower_const_body(c.value.span, Some(&c.value)), - }) + span: this.lower_span(c.value.span), + })) } fn lower_unsafe_source(&mut self, u: UnsafeSource) -> hir::UnsafeSource { @@ -2650,8 +2653,7 @@ impl<'hir> GenericArgsCtor<'hir> { lcx.children.push((def_id, hir::MaybeOwner::NonOwner(hir_id))); self.args.push(hir::GenericArg::Const(hir::ConstArg { - value: hir::AnonConst { def_id, hir_id, body }, - span, + value: lcx.arena.alloc(hir::AnonConst { def_id, hir_id, body, span }), is_desugared_from_effects: true, })) } diff --git a/compiler/rustc_builtin_macros/src/format.rs b/compiler/rustc_builtin_macros/src/format.rs index 2c717661a1c..2450ac8f4b3 100644 --- a/compiler/rustc_builtin_macros/src/format.rs +++ b/compiler/rustc_builtin_macros/src/format.rs @@ -307,7 +307,7 @@ fn make_format_args( return ExpandResult::Ready(Err(guar)); } - let to_span = |inner_span: rustc_parse_format::InnerSpan| { + let to_span = |inner_span: parse::InnerSpan| { is_source_literal.then(|| { fmt_span.from_inner(InnerSpan { start: inner_span.start, end: inner_span.end }) }) @@ -577,7 +577,7 @@ fn make_format_args( fn invalid_placeholder_type_error( ecx: &ExtCtxt<'_>, ty: &str, - ty_span: Option<rustc_parse_format::InnerSpan>, + ty_span: Option<parse::InnerSpan>, fmt_span: Span, ) { let sp = ty_span.map(|sp| fmt_span.from_inner(InnerSpan::new(sp.start, sp.end))); diff --git a/compiler/rustc_codegen_gcc/src/context.rs b/compiler/rustc_codegen_gcc/src/context.rs index 16a85b4e8fa..4a1f5188a80 100644 --- a/compiler/rustc_codegen_gcc/src/context.rs +++ b/compiler/rustc_codegen_gcc/src/context.rs @@ -6,7 +6,8 @@ use gccjit::{ use rustc_codegen_ssa::base::wants_msvc_seh; use rustc_codegen_ssa::errors as ssa_errors; use rustc_codegen_ssa::traits::{BackendTypes, BaseTypeMethods, MiscMethods}; -use rustc_data_structures::base_n; +use rustc_data_structures::base_n::ToBaseN; +use rustc_data_structures::base_n::ALPHANUMERIC_ONLY; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_middle::mir::mono::CodegenUnit; use rustc_middle::span_bug; @@ -621,7 +622,7 @@ impl<'b, 'tcx> CodegenCx<'b, 'tcx> { let mut name = String::with_capacity(prefix.len() + 6); name.push_str(prefix); name.push_str("."); - base_n::push_str(idx as u128, base_n::ALPHANUMERIC_ONLY, &mut name); + name.push_str(&(idx as u64).to_base(ALPHANUMERIC_ONLY)); name } } diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index 5c8f358d03a..1a1b4ae3831 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -17,7 +17,7 @@ use rustc_data_structures::small_c_str::SmallCStr; use rustc_hir::def_id::DefId; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs; use rustc_middle::ty::layout::{ - FnAbiError, FnAbiOfHelpers, FnAbiRequest, HasTyCtxt, LayoutError, LayoutOfHelpers, TyAndLayout, + FnAbiError, FnAbiOfHelpers, FnAbiRequest, LayoutError, LayoutOfHelpers, TyAndLayout, }; use rustc_middle::ty::{self, Instance, Ty, TyCtxt}; use rustc_sanitizers::{cfi, kcfi}; @@ -27,7 +27,6 @@ use rustc_target::abi::{self, call::FnAbi, Align, Size, WrappingRange}; use rustc_target::spec::{HasTargetSpec, SanitizerSet, Target}; use smallvec::SmallVec; use std::borrow::Cow; -use std::ffi::CString; use std::iter; use std::ops::Deref; use std::ptr; @@ -1705,13 +1704,21 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> { kcfi_bundle } + /// Emits a call to `llvm.instrprof.mcdc.parameters`. + /// + /// This doesn't produce any code directly, but is used as input by + /// the LLVM pass that handles coverage instrumentation. + /// + /// (See clang's [`CodeGenPGO::emitMCDCParameters`] for comparison.) + /// + /// [`CodeGenPGO::emitMCDCParameters`]: + /// https://github.com/rust-lang/llvm-project/blob/5399a24/clang/lib/CodeGen/CodeGenPGO.cpp#L1124 pub(crate) fn mcdc_parameters( &mut self, fn_name: &'ll Value, hash: &'ll Value, bitmap_bytes: &'ll Value, - max_decision_depth: u32, - ) -> Vec<&'ll Value> { + ) { debug!("mcdc_parameters() with args ({:?}, {:?}, {:?})", fn_name, hash, bitmap_bytes); assert!(llvm_util::get_version() >= (18, 0, 0), "MCDC intrinsics require LLVM 18 or later"); @@ -1724,8 +1731,6 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> { let args = &[fn_name, hash, bitmap_bytes]; let args = self.check_call("call", llty, llfn, args); - let mut cond_bitmaps = vec![]; - unsafe { let _ = llvm::LLVMRustBuildCall( self.llbuilder, @@ -1736,23 +1741,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> { [].as_ptr(), 0 as c_uint, ); - // Create condition bitmap named `mcdc.addr`. - for i in 0..=max_decision_depth { - let mut bx = Builder::with_cx(self.cx); - bx.position_at_start(llvm::LLVMGetFirstBasicBlock(self.llfn())); - - let name = CString::new(format!("mcdc.addr.{i}")).unwrap(); - let cond_bitmap = { - let alloca = - llvm::LLVMBuildAlloca(bx.llbuilder, bx.cx.type_i32(), name.as_ptr()); - llvm::LLVMSetAlignment(alloca, 4); - alloca - }; - bx.store(self.const_i32(0), cond_bitmap, self.tcx().data_layout.i32_align.abi); - cond_bitmaps.push(cond_bitmap); - } } - cond_bitmaps } pub(crate) fn mcdc_tvbitmap_update( @@ -1794,8 +1783,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> { 0 as c_uint, ); } - let i32_align = self.tcx().data_layout.i32_align.abi; - self.store(self.const_i32(0), mcdc_temp, i32_align); + self.store(self.const_i32(0), mcdc_temp, self.tcx.data_layout.i32_align.abi); } pub(crate) fn mcdc_condbitmap_update( diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index d32baa6dc02..653abb4e41b 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -11,7 +11,8 @@ use crate::value::Value; use rustc_codegen_ssa::base::{wants_msvc_seh, wants_wasm_eh}; use rustc_codegen_ssa::errors as ssa_errors; use rustc_codegen_ssa::traits::*; -use rustc_data_structures::base_n; +use rustc_data_structures::base_n::ToBaseN; +use rustc_data_structures::base_n::ALPHANUMERIC_ONLY; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::small_c_str::SmallCStr; use rustc_hir::def_id::DefId; @@ -1015,7 +1016,7 @@ impl CodegenCx<'_, '_> { let mut name = String::with_capacity(prefix.len() + 6); name.push_str(prefix); name.push('.'); - base_n::push_str(idx as u128, base_n::ALPHANUMERIC_ONLY, &mut name); + name.push_str(&(idx as u64).to_base(ALPHANUMERIC_ONLY)); name } } diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs index 679c6e1a2ff..c51a7744a30 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs @@ -13,10 +13,10 @@ use rustc_codegen_ssa::traits::{ use rustc_data_structures::fx::{FxHashMap, FxIndexMap}; use rustc_llvm::RustString; use rustc_middle::bug; -use rustc_middle::mir::coverage::{CoverageKind, FunctionCoverageInfo}; +use rustc_middle::mir::coverage::CoverageKind; use rustc_middle::ty::layout::HasTyCtxt; use rustc_middle::ty::Instance; -use rustc_target::abi::Align; +use rustc_target::abi::{Align, Size}; use std::cell::RefCell; @@ -91,6 +91,42 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { } impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> { + fn init_coverage(&mut self, instance: Instance<'tcx>) { + let Some(function_coverage_info) = + self.tcx.instance_mir(instance.def).function_coverage_info.as_deref() + else { + return; + }; + + // If there are no MC/DC bitmaps to set up, return immediately. + if function_coverage_info.mcdc_bitmap_bytes == 0 { + return; + } + + let fn_name = self.get_pgo_func_name_var(instance); + let hash = self.const_u64(function_coverage_info.function_source_hash); + let bitmap_bytes = self.const_u32(function_coverage_info.mcdc_bitmap_bytes); + self.mcdc_parameters(fn_name, hash, bitmap_bytes); + + // Create pointers named `mcdc.addr.{i}` to stack-allocated condition bitmaps. + let mut cond_bitmaps = vec![]; + for i in 0..function_coverage_info.mcdc_num_condition_bitmaps { + // MC/DC intrinsics will perform loads/stores that use the ABI default + // alignment for i32, so our variable declaration should match. + let align = self.tcx.data_layout.i32_align.abi; + let cond_bitmap = self.alloca(Size::from_bytes(4), align); + llvm::set_value_name(cond_bitmap, format!("mcdc.addr.{i}").as_bytes()); + self.store(self.const_i32(0), cond_bitmap, align); + cond_bitmaps.push(cond_bitmap); + } + + self.coverage_context() + .expect("always present when coverage is enabled") + .mcdc_condition_bitmap_map + .borrow_mut() + .insert(instance, cond_bitmaps); + } + #[instrument(level = "debug", skip(self))] fn add_coverage(&mut self, instance: Instance<'tcx>, kind: &CoverageKind) { // Our caller should have already taken care of inlining subtleties, @@ -109,10 +145,6 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> { return; }; - if function_coverage_info.mcdc_bitmap_bytes > 0 { - ensure_mcdc_parameters(bx, instance, function_coverage_info); - } - let Some(coverage_context) = bx.coverage_context() else { return }; let mut coverage_map = coverage_context.function_coverage_map.borrow_mut(); let func_coverage = coverage_map @@ -193,28 +225,6 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> { } } -fn ensure_mcdc_parameters<'ll, 'tcx>( - bx: &mut Builder<'_, 'll, 'tcx>, - instance: Instance<'tcx>, - function_coverage_info: &FunctionCoverageInfo, -) { - let Some(cx) = bx.coverage_context() else { return }; - if cx.mcdc_condition_bitmap_map.borrow().contains_key(&instance) { - return; - } - - let fn_name = bx.get_pgo_func_name_var(instance); - let hash = bx.const_u64(function_coverage_info.function_source_hash); - let bitmap_bytes = bx.const_u32(function_coverage_info.mcdc_bitmap_bytes); - let max_decision_depth = function_coverage_info.mcdc_max_decision_depth; - let cond_bitmap = bx.mcdc_parameters(fn_name, hash, bitmap_bytes, max_decision_depth as u32); - bx.coverage_context() - .expect("already checked above") - .mcdc_condition_bitmap_map - .borrow_mut() - .insert(instance, cond_bitmap); -} - /// Calls llvm::createPGOFuncNameVar() with the given function instance's /// mangled function name. The LLVM API returns an llvm::GlobalVariable /// containing the function name, with the specific variable name and linkage diff --git a/compiler/rustc_codegen_ssa/src/mir/mod.rs b/compiler/rustc_codegen_ssa/src/mir/mod.rs index 0064c16f5d9..cf6e2e8d14c 100644 --- a/compiler/rustc_codegen_ssa/src/mir/mod.rs +++ b/compiler/rustc_codegen_ssa/src/mir/mod.rs @@ -259,6 +259,10 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( // Apply debuginfo to the newly allocated locals. fx.debug_introduce_locals(&mut start_bx); + // If the backend supports coverage, and coverage is enabled for this function, + // do any necessary start-of-function codegen (e.g. locals for MC/DC bitmaps). + start_bx.init_coverage(instance); + // The builders will be created separately for each basic block at `codegen_block`. // So drop the builder of `start_llbb` to avoid having two at the same time. drop(start_bx); diff --git a/compiler/rustc_codegen_ssa/src/traits/coverageinfo.rs b/compiler/rustc_codegen_ssa/src/traits/coverageinfo.rs index d1d813bd389..906d8b87d3b 100644 --- a/compiler/rustc_codegen_ssa/src/traits/coverageinfo.rs +++ b/compiler/rustc_codegen_ssa/src/traits/coverageinfo.rs @@ -3,6 +3,11 @@ use rustc_middle::mir::coverage::CoverageKind; use rustc_middle::ty::Instance; pub trait CoverageInfoBuilderMethods<'tcx>: BackendTypes { + /// Performs any start-of-function codegen needed for coverage instrumentation. + /// + /// Can be a no-op in backends that don't support coverage instrumentation. + fn init_coverage(&mut self, _instance: Instance<'tcx>) {} + /// Handle the MIR coverage info in a backend-specific way. /// /// This can potentially be a no-op in backends that don't support diff --git a/compiler/rustc_const_eval/src/const_eval/dummy_machine.rs b/compiler/rustc_const_eval/src/const_eval/dummy_machine.rs index 7b6828c6e18..afc60d33647 100644 --- a/compiler/rustc_const_eval/src/const_eval/dummy_machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/dummy_machine.rs @@ -105,7 +105,7 @@ impl<'mir, 'tcx: 'mir> interpret::Machine<'mir, 'tcx> for DummyMachine { _destination: &interpret::MPlaceTy<'tcx, Self::Provenance>, _target: Option<BasicBlock>, _unwind: UnwindAction, - ) -> interpret::InterpResult<'tcx> { + ) -> interpret::InterpResult<'tcx, Option<ty::Instance<'tcx>>> { unimplemented!() } diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index dd835279df3..e9cf5a3d769 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -459,16 +459,26 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, dest: &MPlaceTy<'tcx, Self::Provenance>, target: Option<mir::BasicBlock>, _unwind: mir::UnwindAction, - ) -> InterpResult<'tcx> { + ) -> InterpResult<'tcx, Option<ty::Instance<'tcx>>> { // Shared intrinsics. if ecx.emulate_intrinsic(instance, args, dest, target)? { - return Ok(()); + return Ok(None); } let intrinsic_name = ecx.tcx.item_name(instance.def_id()); // CTFE-specific intrinsics. let Some(ret) = target else { - throw_unsup_format!("intrinsic `{intrinsic_name}` is not supported at compile-time"); + // Handle diverging intrinsics. We can't handle any of them (that are not already + // handled above), but check if there is a fallback body. + if ecx.tcx.intrinsic(instance.def_id()).unwrap().must_be_overridden { + throw_unsup_format!( + "intrinsic `{intrinsic_name}` is not supported at compile-time" + ); + } + return Ok(Some(ty::Instance { + def: ty::InstanceDef::Item(instance.def_id()), + args: instance.args, + })); }; match intrinsic_name { sym::ptr_guaranteed_cmp => { @@ -536,14 +546,21 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, // not the optimization stage.) sym::is_val_statically_known => ecx.write_scalar(Scalar::from_bool(false), dest)?, _ => { - throw_unsup_format!( - "intrinsic `{intrinsic_name}` is not supported at compile-time" - ); + // We haven't handled the intrinsic, let's see if we can use a fallback body. + if ecx.tcx.intrinsic(instance.def_id()).unwrap().must_be_overridden { + throw_unsup_format!( + "intrinsic `{intrinsic_name}` is not supported at compile-time" + ); + } + return Ok(Some(ty::Instance { + def: ty::InstanceDef::Item(instance.def_id()), + args: instance.args, + })); } } ecx.go_to_block(ret); - Ok(()) + Ok(None) } fn assert_panic( diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index 4d37c3c22cd..f73293856c7 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -414,7 +414,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } self.copy_op(&self.project_index(&input, index)?, dest)?; } - sym::likely | sym::unlikely | sym::black_box => { + sym::black_box => { // These just return their argument self.copy_op(&args[0], dest)?; } diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs index 8bc569bed54..8405d0746df 100644 --- a/compiler/rustc_const_eval/src/interpret/machine.rs +++ b/compiler/rustc_const_eval/src/interpret/machine.rs @@ -216,6 +216,9 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized { /// Directly process an intrinsic without pushing a stack frame. It is the hook's /// responsibility to advance the instruction pointer as appropriate. + /// + /// Returns `None` if the intrinsic was fully handled. + /// Otherwise, returns an `Instance` of the function that implements the intrinsic. fn call_intrinsic( ecx: &mut InterpCx<'mir, 'tcx, Self>, instance: ty::Instance<'tcx>, @@ -223,7 +226,7 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized { destination: &MPlaceTy<'tcx, Self::Provenance>, target: Option<mir::BasicBlock>, unwind: mir::UnwindAction, - ) -> InterpResult<'tcx>; + ) -> InterpResult<'tcx, Option<ty::Instance<'tcx>>>; /// Called to evaluate `Assert` MIR terminators that trigger a panic. fn assert_panic( diff --git a/compiler/rustc_const_eval/src/interpret/terminator.rs b/compiler/rustc_const_eval/src/interpret/terminator.rs index 9c31532a9ce..07425f9a686 100644 --- a/compiler/rustc_const_eval/src/interpret/terminator.rs +++ b/compiler/rustc_const_eval/src/interpret/terminator.rs @@ -539,14 +539,28 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ty::InstanceDef::Intrinsic(def_id) => { assert!(self.tcx.intrinsic(def_id).is_some()); // FIXME: Should `InPlace` arguments be reset to uninit? - M::call_intrinsic( + if let Some(fallback) = M::call_intrinsic( self, instance, &self.copy_fn_args(args), destination, target, unwind, - ) + )? { + assert!(!self.tcx.intrinsic(fallback.def_id()).unwrap().must_be_overridden); + assert!(matches!(fallback.def, ty::InstanceDef::Item(_))); + return self.eval_fn_call( + FnVal::Instance(fallback), + (caller_abi, caller_fn_abi), + args, + with_caller_location, + destination, + target, + unwind, + ); + } else { + Ok(()) + } } ty::InstanceDef::VTableShim(..) | ty::InstanceDef::ReifyShim(..) diff --git a/compiler/rustc_data_structures/src/base_n.rs b/compiler/rustc_data_structures/src/base_n.rs index a3eb2b9c416..aed89fadc4c 100644 --- a/compiler/rustc_data_structures/src/base_n.rs +++ b/compiler/rustc_data_structures/src/base_n.rs @@ -1,6 +1,7 @@ /// Converts unsigned integers into a string representation with some base. /// Bases up to and including 36 can be used for case-insensitive things. -use std::str; +use std::ascii; +use std::fmt; #[cfg(test)] mod tests; @@ -9,36 +10,101 @@ pub const MAX_BASE: usize = 64; pub const ALPHANUMERIC_ONLY: usize = 62; pub const CASE_INSENSITIVE: usize = 36; -const BASE_64: &[u8; MAX_BASE] = - b"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ@$"; +const BASE_64: [ascii::Char; MAX_BASE] = { + let bytes = b"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ@$"; + let Some(ascii) = bytes.as_ascii() else { panic!() }; + *ascii +}; -#[inline] -pub fn push_str(mut n: u128, base: usize, output: &mut String) { - debug_assert!(base >= 2 && base <= MAX_BASE); - let mut s = [0u8; 128]; - let mut index = s.len(); +pub struct BaseNString { + start: usize, + buf: [ascii::Char; 128], +} + +impl std::ops::Deref for BaseNString { + type Target = str; - let base = base as u128; + fn deref(&self) -> &str { + self.buf[self.start..].as_str() + } +} + +impl AsRef<str> for BaseNString { + fn as_ref(&self) -> &str { + self.buf[self.start..].as_str() + } +} + +impl fmt::Display for BaseNString { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(self) + } +} + +// This trait just lets us reserve the exact right amount of space when doing fixed-length +// case-insensitve encoding. Add any impls you need. +pub trait ToBaseN: Into<u128> { + fn encoded_len(base: usize) -> usize; + + fn to_base_fixed_len(self, base: usize) -> BaseNString { + let mut encoded = self.to_base(base); + encoded.start = encoded.buf.len() - Self::encoded_len(base); + encoded + } - loop { - index -= 1; - s[index] = BASE_64[(n % base) as usize]; - n /= base; + fn to_base(self, base: usize) -> BaseNString { + let mut output = [ascii::Char::Digit0; 128]; - if n == 0 { - break; + let mut n: u128 = self.into(); + + let mut index = output.len(); + loop { + index -= 1; + output[index] = BASE_64[(n % base as u128) as usize]; + n /= base as u128; + + if n == 0 { + break; + } + } + assert_eq!(n, 0); + + BaseNString { start: index, buf: output } + } +} + +impl ToBaseN for u128 { + fn encoded_len(base: usize) -> usize { + let mut max = u128::MAX; + let mut len = 0; + while max > 0 { + len += 1; + max /= base as u128; } + len } +} - output.push_str(unsafe { - // SAFETY: `s` is populated using only valid utf8 characters from `BASE_64` - str::from_utf8_unchecked(&s[index..]) - }); +impl ToBaseN for u64 { + fn encoded_len(base: usize) -> usize { + let mut max = u64::MAX; + let mut len = 0; + while max > 0 { + len += 1; + max /= base as u64; + } + len + } } -#[inline] -pub fn encode(n: u128, base: usize) -> String { - let mut s = String::new(); - push_str(n, base, &mut s); - s +impl ToBaseN for u32 { + fn encoded_len(base: usize) -> usize { + let mut max = u32::MAX; + let mut len = 0; + while max > 0 { + len += 1; + max /= base as u32; + } + len + } } diff --git a/compiler/rustc_data_structures/src/base_n/tests.rs b/compiler/rustc_data_structures/src/base_n/tests.rs index 2be2f0532c9..148d8dde02a 100644 --- a/compiler/rustc_data_structures/src/base_n/tests.rs +++ b/compiler/rustc_data_structures/src/base_n/tests.rs @@ -1,9 +1,17 @@ use super::*; #[test] -fn test_encode() { +fn limits() { + assert_eq!(Ok(u128::MAX), u128::from_str_radix(&u128::MAX.to_base(36), 36)); + assert_eq!(Ok(u64::MAX), u64::from_str_radix(&u64::MAX.to_base(36), 36)); + assert_eq!(Ok(u32::MAX), u32::from_str_radix(&u32::MAX.to_base(36), 36)); +} + +#[test] +fn test_to_base() { fn test(n: u128, base: usize) { - assert_eq!(Ok(n), u128::from_str_radix(&encode(n, base), base as u32)); + assert_eq!(Ok(n), u128::from_str_radix(&n.to_base(base), base as u32)); + assert_eq!(Ok(n), u128::from_str_radix(&n.to_base_fixed_len(base), base as u32)); } for base in 2..37 { diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs index cf54e700e2b..8dd85b25e0e 100644 --- a/compiler/rustc_data_structures/src/lib.rs +++ b/compiler/rustc_data_structures/src/lib.rs @@ -16,6 +16,8 @@ #![doc(rust_logo)] #![feature(allocator_api)] #![feature(array_windows)] +#![feature(ascii_char)] +#![feature(ascii_char_variants)] #![feature(auto_traits)] #![feature(cfg_match)] #![feature(core_intrinsics)] diff --git a/compiler/rustc_driver_impl/Cargo.toml b/compiler/rustc_driver_impl/Cargo.toml index a8bba3afb7e..cb37644d570 100644 --- a/compiler/rustc_driver_impl/Cargo.toml +++ b/compiler/rustc_driver_impl/Cargo.toml @@ -42,9 +42,8 @@ rustc_privacy = { path = "../rustc_privacy" } rustc_query_system = { path = "../rustc_query_system" } rustc_resolve = { path = "../rustc_resolve" } rustc_session = { path = "../rustc_session" } -rustc_smir ={ path = "../rustc_smir" } +rustc_smir = { path = "../rustc_smir" } rustc_span = { path = "../rustc_span" } -rustc_symbol_mangling = { path = "../rustc_symbol_mangling" } rustc_target = { path = "../rustc_target" } rustc_trait_selection = { path = "../rustc_trait_selection" } rustc_ty_utils = { path = "../rustc_ty_utils" } diff --git a/compiler/rustc_errors/src/diagnostic_impls.rs b/compiler/rustc_errors/src/diagnostic_impls.rs index b3a1e29f8e2..4696917554f 100644 --- a/compiler/rustc_errors/src/diagnostic_impls.rs +++ b/compiler/rustc_errors/src/diagnostic_impls.rs @@ -13,7 +13,7 @@ use rustc_span::symbol::{Ident, MacroRulesNormalizedIdent, Symbol}; use rustc_span::Span; use rustc_target::abi::TargetDataLayoutErrors; use rustc_target::spec::{PanicStrategy, SplitDebuginfo, StackProtector, TargetTriple}; -use rustc_type_ir as type_ir; +use rustc_type_ir::{ClosureKind, FloatTy}; use std::backtrace::Backtrace; use std::borrow::Cow; use std::fmt; @@ -196,7 +196,7 @@ impl IntoDiagArg for ast::token::TokenKind { } } -impl IntoDiagArg for type_ir::FloatTy { +impl IntoDiagArg for FloatTy { fn into_diag_arg(self) -> DiagArgValue { DiagArgValue::Str(Cow::Borrowed(self.name_str())) } @@ -252,7 +252,7 @@ impl IntoDiagArg for Level { } } -impl IntoDiagArg for type_ir::ClosureKind { +impl IntoDiagArg for ClosureKind { fn into_diag_arg(self) -> DiagArgValue { DiagArgValue::Str(self.as_str().into()) } diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index 9d3aac66c41..9c33cc8ed0b 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -396,10 +396,6 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ ), // Entry point: - gated!( - unix_sigpipe, Normal, template!(NameValueStr: "inherit|sig_ign|sig_dfl"), ErrorFollowing, - EncodeCrossCrate::Yes, experimental!(unix_sigpipe) - ), ungated!(start, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::No), ungated!(no_start, CrateLevel, template!(Word), WarnFollowing, EncodeCrossCrate::No), ungated!(no_main, CrateLevel, template!(Word), WarnFollowing, EncodeCrossCrate::No), diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index e7d7a9f380b..fe50499db76 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -619,8 +619,6 @@ declare_features! ( /// Allows creation of instances of a struct by moving fields that have /// not changed from prior instances of the same struct (RFC #2528) (unstable, type_changing_struct_update, "1.58.0", Some(86555)), - /// Enables rustc to generate code that instructs libstd to NOT ignore SIGPIPE. - (unstable, unix_sigpipe, "1.65.0", Some(97889)), /// Allows unnamed fields of struct and union type (incomplete, unnamed_fields, "1.74.0", Some(49804)), /// Allows unsized fn parameters. diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index fc8f7466694..244c479120d 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -229,9 +229,8 @@ impl<'hir> PathSegment<'hir> { } #[derive(Clone, Copy, Debug, HashStable_Generic)] -pub struct ConstArg { - pub value: AnonConst, - pub span: Span, +pub struct ConstArg<'hir> { + pub value: &'hir AnonConst, /// Indicates whether this comes from a `~const` desugaring. pub is_desugared_from_effects: bool, } @@ -252,7 +251,7 @@ impl InferArg { pub enum GenericArg<'hir> { Lifetime(&'hir Lifetime), Type(&'hir Ty<'hir>), - Const(ConstArg), + Const(ConstArg<'hir>), Infer(InferArg), } @@ -261,7 +260,7 @@ impl GenericArg<'_> { match self { GenericArg::Lifetime(l) => l.ident.span, GenericArg::Type(t) => t.span, - GenericArg::Const(c) => c.span, + GenericArg::Const(c) => c.value.span, GenericArg::Infer(i) => i.span, } } @@ -490,7 +489,7 @@ pub enum GenericParamKind<'hir> { Const { ty: &'hir Ty<'hir>, /// Optional default value for the const generic param - default: Option<AnonConst>, + default: Option<&'hir AnonConst>, is_host_effect: bool, }, } @@ -1562,12 +1561,12 @@ impl fmt::Display for ConstContext { pub type Lit = Spanned<LitKind>; #[derive(Copy, Clone, Debug, HashStable_Generic)] -pub enum ArrayLen { +pub enum ArrayLen<'hir> { Infer(InferArg), - Body(AnonConst), + Body(&'hir AnonConst), } -impl ArrayLen { +impl ArrayLen<'_> { pub fn hir_id(&self) -> HirId { match self { ArrayLen::Infer(InferArg { hir_id, .. }) | ArrayLen::Body(AnonConst { hir_id, .. }) => { @@ -1590,6 +1589,7 @@ pub struct AnonConst { pub hir_id: HirId, pub def_id: LocalDefId, pub body: BodyId, + pub span: Span, } /// An inline constant expression `const { something }`. @@ -2002,7 +2002,7 @@ pub enum ExprKind<'hir> { /// /// E.g., `[1; 5]`. The first expression is the element /// to be repeated; the second is the number of times to repeat it. - Repeat(&'hir Expr<'hir>, ArrayLen), + Repeat(&'hir Expr<'hir>, ArrayLen<'hir>), /// A suspension point for coroutines (i.e., `yield <expr>`). Yield(&'hir Expr<'hir>, YieldSource), @@ -2382,7 +2382,7 @@ pub struct TypeBinding<'hir> { #[derive(Debug, Clone, Copy, HashStable_Generic)] pub enum Term<'hir> { Ty(&'hir Ty<'hir>), - Const(AnonConst), + Const(&'hir AnonConst), } impl<'hir> From<&'hir Ty<'hir>> for Term<'hir> { @@ -2391,8 +2391,8 @@ impl<'hir> From<&'hir Ty<'hir>> for Term<'hir> { } } -impl<'hir> From<AnonConst> for Term<'hir> { - fn from(c: AnonConst) -> Self { +impl<'hir> From<&'hir AnonConst> for Term<'hir> { + fn from(c: &'hir AnonConst) -> Self { Term::Const(c) } } @@ -2683,7 +2683,7 @@ pub enum TyKind<'hir> { /// A variable length slice (i.e., `[T]`). Slice(&'hir Ty<'hir>), /// A fixed length array (i.e., `[T; n]`). - Array(&'hir Ty<'hir>, ArrayLen), + Array(&'hir Ty<'hir>, ArrayLen<'hir>), /// A raw pointer (i.e., `*const T` or `*mut T`). Ptr(MutTy<'hir>), /// A reference (i.e., `&'a T` or `&'a mut T`). @@ -2712,7 +2712,7 @@ pub enum TyKind<'hir> { /// where `Bound` is a trait or a lifetime. TraitObject(&'hir [PolyTraitRef<'hir>], &'hir Lifetime, TraitObjectSyntax), /// Unused for now. - Typeof(AnonConst), + Typeof(&'hir AnonConst), /// `TyKind::Infer` means the type should be inferred instead of it having been /// specified. This can appear anywhere in a type. Infer, @@ -2745,10 +2745,10 @@ pub enum InlineAsmOperand<'hir> { out_expr: Option<&'hir Expr<'hir>>, }, Const { - anon_const: AnonConst, + anon_const: &'hir AnonConst, }, SymFn { - anon_const: AnonConst, + anon_const: &'hir AnonConst, }, SymStatic { path: QPath<'hir>, @@ -2950,7 +2950,7 @@ pub struct Variant<'hir> { /// Fields and constructor id of the variant. pub data: VariantData<'hir>, /// Explicit discriminant (e.g., `Foo = 1`). - pub disr_expr: Option<AnonConst>, + pub disr_expr: Option<&'hir AnonConst>, /// Span pub span: Span, } @@ -3479,15 +3479,13 @@ impl<'hir> OwnerNode<'hir> { } } - // Span by reference to pass to `Node::Err`. - #[allow(rustc::pass_by_value)] - pub fn span(&self) -> &'hir Span { + pub fn span(&self) -> Span { match self { OwnerNode::Item(Item { span, .. }) | OwnerNode::ForeignItem(ForeignItem { span, .. }) | OwnerNode::ImplItem(ImplItem { span, .. }) - | OwnerNode::TraitItem(TraitItem { span, .. }) => span, - OwnerNode::Crate(Mod { spans: ModSpans { inner_span, .. }, .. }) => inner_span, + | OwnerNode::TraitItem(TraitItem { span, .. }) => *span, + OwnerNode::Crate(Mod { spans: ModSpans { inner_span, .. }, .. }) => *inner_span, OwnerNode::Synthetic => unreachable!(), } } @@ -3632,9 +3630,7 @@ pub enum Node<'hir> { PreciseCapturingNonLifetimeArg(&'hir PreciseCapturingNonLifetimeArg), // Created by query feeding Synthetic, - // Span by reference to minimize `Node`'s size - #[allow(rustc::pass_by_value)] - Err(&'hir Span), + Err(Span), } impl<'hir> Node<'hir> { @@ -3871,7 +3867,7 @@ mod size_asserts { static_assert_size!(FnDecl<'_>, 40); static_assert_size!(ForeignItem<'_>, 72); static_assert_size!(ForeignItemKind<'_>, 40); - static_assert_size!(GenericArg<'_>, 32); + static_assert_size!(GenericArg<'_>, 24); static_assert_size!(GenericBound<'_>, 48); static_assert_size!(Generics<'_>, 56); static_assert_size!(Impl<'_>, 80); diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index cd9f9ff9109..fa89a4a44ef 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -338,7 +338,7 @@ pub trait Visitor<'v>: Sized { fn visit_pat_field(&mut self, f: &'v PatField<'v>) -> Self::Result { walk_pat_field(self, f) } - fn visit_array_length(&mut self, len: &'v ArrayLen) -> Self::Result { + fn visit_array_length(&mut self, len: &'v ArrayLen<'v>) -> Self::Result { walk_array_len(self, len) } fn visit_anon_const(&mut self, c: &'v AnonConst) -> Self::Result { @@ -703,7 +703,7 @@ pub fn walk_pat_field<'v, V: Visitor<'v>>(visitor: &mut V, field: &'v PatField<' visitor.visit_pat(field.pat) } -pub fn walk_array_len<'v, V: Visitor<'v>>(visitor: &mut V, len: &'v ArrayLen) -> V::Result { +pub fn walk_array_len<'v, V: Visitor<'v>>(visitor: &mut V, len: &'v ArrayLen<'v>) -> V::Result { match len { // FIXME: Use `visit_infer` here. ArrayLen::Infer(InferArg { hir_id, span: _ }) => visitor.visit_id(*hir_id), diff --git a/compiler/rustc_hir_analysis/src/bounds.rs b/compiler/rustc_hir_analysis/src/bounds.rs index aafb5c1c0b4..5562b81871f 100644 --- a/compiler/rustc_hir_analysis/src/bounds.rs +++ b/compiler/rustc_hir_analysis/src/bounds.rs @@ -23,7 +23,7 @@ use rustc_span::Span; /// include the self type (e.g., `trait_bounds`) but in others we do not #[derive(Default, PartialEq, Eq, Clone, Debug)] pub struct Bounds<'tcx> { - pub clauses: Vec<(ty::Clause<'tcx>, Span)>, + clauses: Vec<(ty::Clause<'tcx>, Span)>, } impl<'tcx> Bounds<'tcx> { diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 0f0736f8756..9198ceb8f59 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -143,7 +143,7 @@ impl<'v> Visitor<'v> for HirPlaceholderCollector { _ => {} } } - fn visit_array_length(&mut self, length: &'v hir::ArrayLen) { + fn visit_array_length(&mut self, length: &'v hir::ArrayLen<'v>) { if let hir::ArrayLen::Infer(inf) = length { self.0.push(inf.span); } diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index 9d7deebac48..5ccfd06f258 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -24,7 +24,7 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> { let hir_id = tcx.local_def_id_to_hir_id(def_id); let node = tcx.hir_node(hir_id); - let Node::AnonConst(_) = node else { + let Node::AnonConst(&AnonConst { span, .. }) = node else { span_bug!( tcx.def_span(def_id), "expected anon const in `anon_const_type_of`, got {node:?}" @@ -134,7 +134,7 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> { // I dont think it's possible to reach this but I'm not 100% sure - BoxyUwU return Ty::new_error_with_message( tcx, - tcx.def_span(def_id), + span, "unexpected non-GAT usage of an anon const", ); } @@ -152,7 +152,7 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> { let Some(type_dependent_def) = tables.type_dependent_def_id(parent_node_id) else { return Ty::new_error_with_message( tcx, - tcx.def_span(def_id), + span, format!("unable to find type-dependent def for {parent_node_id:?}"), ); }; @@ -194,7 +194,7 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> { } else { return Ty::new_error_with_message( tcx, - tcx.def_span(def_id), + span, format!("unable to find const parent for {hir_id} in pat {pat:?}"), ); } @@ -202,7 +202,7 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> { _ => { return Ty::new_error_with_message( tcx, - tcx.def_span(def_id), + span, format!("unexpected const parent path {parent_node:?}"), ); } @@ -226,11 +226,7 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> { .map(|idx| (idx, seg)) }) }) else { - return Ty::new_error_with_message( - tcx, - tcx.def_span(def_id), - "no arg matching AnonConst in path", - ); + return Ty::new_error_with_message(tcx, span, "no arg matching AnonConst in path"); }; let generics = match tcx.res_generics_def_id(segment.res) { @@ -238,7 +234,7 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> { None => { return Ty::new_error_with_message( tcx, - tcx.def_span(def_id), + span, format!("unexpected anon const res {:?} in path: {:?}", segment.res, path), ); } @@ -250,7 +246,7 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> { _ => { return Ty::new_error_with_message( tcx, - tcx.def_span(def_id), + span, format!("unexpected const parent in type_of(): {parent_node:?}"), ); } @@ -278,7 +274,7 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> { } else { return Ty::new_error_with_message( tcx, - tcx.def_span(def_id), + span, format!("const generic parameter not found in {generics:?} at position {arg_idx:?}"), ); } diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 285b99c2c69..4f5fbd024a9 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -968,7 +968,7 @@ impl<'a> State<'a> { self.print_else(elseopt) } - fn print_array_length(&mut self, len: &hir::ArrayLen) { + fn print_array_length(&mut self, len: &hir::ArrayLen<'_>) { match len { hir::ArrayLen::Infer(..) => self.word("_"), hir::ArrayLen::Body(ct) => self.print_anon_const(ct), @@ -1052,7 +1052,7 @@ impl<'a> State<'a> { self.end() } - fn print_expr_repeat(&mut self, element: &hir::Expr<'_>, count: &hir::ArrayLen) { + fn print_expr_repeat(&mut self, element: &hir::Expr<'_>, count: &hir::ArrayLen<'_>) { self.ibox(INDENT_UNIT); self.word("["); self.print_expr(element); diff --git a/compiler/rustc_hir_typeck/Cargo.toml b/compiler/rustc_hir_typeck/Cargo.toml index 9e7f0776b60..73a775690d6 100644 --- a/compiler/rustc_hir_typeck/Cargo.toml +++ b/compiler/rustc_hir_typeck/Cargo.toml @@ -12,7 +12,6 @@ rustc_attr = { path = "../rustc_attr" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } rustc_fluent_macro = { path = "../rustc_fluent_macro" } -rustc_graphviz = { path = "../rustc_graphviz" } rustc_hir = { path = "../rustc_hir" } rustc_hir_analysis = { path = "../rustc_hir_analysis" } rustc_hir_pretty = { path = "../rustc_hir_pretty" } diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 8b1ea7c952c..7b552bb7077 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -1444,7 +1444,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return; }; if let hir::TyKind::Array(_, length) = ty.peel_refs().kind - && let hir::ArrayLen::Body(hir::AnonConst { hir_id, .. }) = length + && let hir::ArrayLen::Body(&hir::AnonConst { hir_id, .. }) = length { let span = self.tcx.hir().span(hir_id); self.dcx().try_steal_modify_and_emit_err( @@ -1483,7 +1483,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn check_expr_repeat( &self, element: &'tcx hir::Expr<'tcx>, - count: &'tcx hir::ArrayLen, + count: &'tcx hir::ArrayLen<'tcx>, expected: Expectation<'tcx>, expr: &'tcx hir::Expr<'tcx>, ) -> Ty<'tcx> { diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index 2060e08aacf..552747bdc52 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -438,7 +438,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - pub fn lower_array_length(&self, length: &hir::ArrayLen) -> ty::Const<'tcx> { + pub fn lower_array_length(&self, length: &hir::ArrayLen<'tcx>) -> ty::Const<'tcx> { match length { hir::ArrayLen::Infer(inf) => self.ct_infer(self.tcx.types.usize, None, inf.span), hir::ArrayLen::Body(anon_const) => { diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index 382dba5f95f..8c7ae7f8e98 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -10,7 +10,6 @@ use rustc_hir::pat_util::EnumerateAndAdjustIterator; use rustc_hir::{self as hir, BindingMode, ByRef, HirId, Mutability, Pat, PatKind}; use rustc_infer::infer; use rustc_infer::infer::type_variable::TypeVariableOrigin; -use rustc_lint as lint; use rustc_middle::mir::interpret::ErrorHandled; use rustc_middle::ty::{self, Ty, TypeVisitableExt}; use rustc_session::lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS; @@ -684,7 +683,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { { // `mut x` resets the binding mode in edition <= 2021. self.tcx.emit_node_span_lint( - lint::builtin::DEREFERENCING_MUT_BINDING, + rustc_lint::builtin::DEREFERENCING_MUT_BINDING, pat.hir_id, pat.span, errors::DereferencingMutBinding { span: pat.span }, diff --git a/compiler/rustc_incremental/src/persist/fs.rs b/compiler/rustc_incremental/src/persist/fs.rs index 3d7c0cfc30a..193042b8cdf 100644 --- a/compiler/rustc_incremental/src/persist/fs.rs +++ b/compiler/rustc_incremental/src/persist/fs.rs @@ -104,10 +104,14 @@ //! implemented. use crate::errors; +use rustc_data_structures::base_n; +use rustc_data_structures::base_n::BaseNString; +use rustc_data_structures::base_n::ToBaseN; +use rustc_data_structures::base_n::CASE_INSENSITIVE; +use rustc_data_structures::flock; use rustc_data_structures::fx::{FxHashSet, FxIndexSet}; use rustc_data_structures::svh::Svh; use rustc_data_structures::unord::{UnordMap, UnordSet}; -use rustc_data_structures::{base_n, flock}; use rustc_errors::ErrorGuaranteed; use rustc_fs_util::{link_or_copy, try_canonicalize, LinkOrCopy}; use rustc_middle::bug; @@ -333,31 +337,24 @@ pub fn finalize_session_directory(sess: &Session, svh: Option<Svh>) { debug!("finalize_session_directory() - session directory: {}", incr_comp_session_dir.display()); - let old_sub_dir_name = incr_comp_session_dir + let mut sub_dir_name = incr_comp_session_dir .file_name() .unwrap() .to_str() - .expect("malformed session dir name: contains non-Unicode characters"); + .expect("malformed session dir name: contains non-Unicode characters") + .to_string(); - // Keep the 's-{timestamp}-{random-number}' prefix, but replace the - // '-working' part with the SVH of the crate - let dash_indices: Vec<_> = old_sub_dir_name.match_indices('-').map(|(idx, _)| idx).collect(); - if dash_indices.len() != 3 { - bug!( - "Encountered incremental compilation session directory with \ - malformed name: {}", - incr_comp_session_dir.display() - ) - } - - // State: "s-{timestamp}-{random-number}-" - let mut new_sub_dir_name = String::from(&old_sub_dir_name[..=dash_indices[2]]); + // Keep the 's-{timestamp}-{random-number}' prefix, but replace "working" with the SVH of the crate + sub_dir_name.truncate(sub_dir_name.len() - "working".len()); + // Double-check that we kept this: "s-{timestamp}-{random-number}-" + assert!(sub_dir_name.ends_with('-'), "{:?}", sub_dir_name); + assert!(sub_dir_name.as_bytes().iter().filter(|b| **b == b'-').count() == 3); - // Append the svh - base_n::push_str(svh.as_u128(), INT_ENCODE_BASE, &mut new_sub_dir_name); + // Append the SVH + sub_dir_name.push_str(&svh.as_u128().to_base_fixed_len(CASE_INSENSITIVE)); // Create the full path - let new_path = incr_comp_session_dir.parent().unwrap().join(new_sub_dir_name); + let new_path = incr_comp_session_dir.parent().unwrap().join(&*sub_dir_name); debug!("finalize_session_directory() - new path: {}", new_path.display()); match rename_path_with_retry(&*incr_comp_session_dir, &new_path, 3) { @@ -453,11 +450,11 @@ fn generate_session_dir_path(crate_dir: &Path) -> PathBuf { let random_number = thread_rng().next_u32(); debug!("generate_session_dir_path: random_number = {}", random_number); - let directory_name = format!( - "s-{}-{}-working", - timestamp, - base_n::encode(random_number as u128, INT_ENCODE_BASE) - ); + // Chop the first 3 characters off the timestamp. Those 3 bytes will be zero for a while. + let (zeroes, timestamp) = timestamp.split_at(3); + assert_eq!(zeroes, "000"); + let directory_name = + format!("s-{}-{}-working", timestamp, random_number.to_base_fixed_len(CASE_INSENSITIVE)); debug!("generate_session_dir_path: directory_name = {}", directory_name); let directory_path = crate_dir.join(directory_name); debug!("generate_session_dir_path: directory_path = {}", directory_path.display()); @@ -588,10 +585,10 @@ fn extract_timestamp_from_session_dir(directory_name: &str) -> Result<SystemTime string_to_timestamp(&directory_name[dash_indices[0] + 1..dash_indices[1]]) } -fn timestamp_to_string(timestamp: SystemTime) -> String { +fn timestamp_to_string(timestamp: SystemTime) -> BaseNString { let duration = timestamp.duration_since(UNIX_EPOCH).unwrap(); let micros = duration.as_secs() * 1_000_000 + (duration.subsec_nanos() as u64) / 1000; - base_n::encode(micros as u128, INT_ENCODE_BASE) + micros.to_base_fixed_len(CASE_INSENSITIVE) } fn string_to_timestamp(s: &str) -> Result<SystemTime, &'static str> { @@ -622,9 +619,8 @@ fn crate_path(sess: &Session) -> PathBuf { sess.cfg_version, ); - let stable_crate_id = base_n::encode(stable_crate_id.as_u64() as u128, INT_ENCODE_BASE); - - let crate_name = format!("{crate_name}-{stable_crate_id}"); + let crate_name = + format!("{crate_name}-{}", stable_crate_id.as_u64().to_base_fixed_len(CASE_INSENSITIVE)); incr_dir.join(crate_name) } diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index b593c41a8ea..76d5d7a3ac2 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -4,7 +4,6 @@ use crate::proc_macro_decls; use crate::util; use rustc_ast::{self as ast, visit}; -use rustc_borrowck as mir_borrowck; use rustc_codegen_ssa::traits::CodegenBackend; use rustc_data_structures::parallel; use rustc_data_structures::steal::Steal; @@ -20,7 +19,6 @@ use rustc_middle::arena::Arena; use rustc_middle::dep_graph::DepGraph; use rustc_middle::ty::{self, GlobalCtxt, RegisteredTools, TyCtxt}; use rustc_middle::util::Providers; -use rustc_mir_build as mir_build; use rustc_parse::{parse_crate_from_file, parse_crate_from_source_str, validate_attr}; use rustc_passes::{abi_test, hir_stats, layout_test}; use rustc_resolve::Resolver; @@ -616,8 +614,8 @@ pub static DEFAULT_QUERY_PROVIDERS: LazyLock<Providers> = LazyLock::new(|| { proc_macro_decls::provide(providers); rustc_const_eval::provide(providers); rustc_middle::hir::provide(providers); - mir_borrowck::provide(providers); - mir_build::provide(providers); + rustc_borrowck::provide(providers); + rustc_mir_build::provide(providers); rustc_mir_transform::provide(providers); rustc_monomorphize::provide(providers); rustc_privacy::provide(providers); diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index db150cc1f87..36f9dda7250 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -20,7 +20,7 @@ use rustc_span::source_map::{RealFileLoader, SourceMapInputs}; use rustc_span::symbol::sym; use rustc_span::{FileName, SourceFileHashAlgorithm}; use rustc_target::spec::{ - CodeModel, LinkerFlavorCli, MergeFunctions, PanicStrategy, RelocModel, WasmCAbi, + CodeModel, LinkerFlavorCli, MergeFunctions, OnBrokenPipe, PanicStrategy, RelocModel, WasmCAbi, }; use rustc_target::spec::{RelroLevel, SanitizerSet, SplitDebuginfo, StackProtector, TlsModel}; use std::collections::{BTreeMap, BTreeSet}; @@ -809,6 +809,7 @@ fn test_unstable_options_tracking_hash() { tracked!(no_profiler_runtime, true); tracked!(no_trait_vptr, true); tracked!(no_unique_section_names, true); + tracked!(on_broken_pipe, OnBrokenPipe::Kill); tracked!(oom, OomStrategy::Panic); tracked!(osx_rpath_install_name, true); tracked!(packed_bundled_libs, true); diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index 02dcfe9c8df..ce4d3825015 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -7,18 +7,16 @@ use rustc_data_structures::sync; use rustc_metadata::{load_symbol_from_dylib, DylibError}; use rustc_middle::ty::CurrentGcx; use rustc_parse::validate_attr; -use rustc_session as session; -use rustc_session::config::{Cfg, OutFileName, OutputFilenames, OutputTypes}; +use rustc_session::config::{host_triple, Cfg, OutFileName, OutputFilenames, OutputTypes}; use rustc_session::filesearch::sysroot_candidates; use rustc_session::lint::{self, BuiltinLintDiag, LintBuffer}; -use rustc_session::{filesearch, Session}; +use rustc_session::output::{categorize_crate_type, CRATE_TYPES}; +use rustc_session::{filesearch, EarlyDiagCtxt, Session}; use rustc_span::edit_distance::find_best_match_for_name; use rustc_span::edition::Edition; use rustc_span::source_map::SourceMapInputs; use rustc_span::symbol::sym; use rustc_target::spec::Target; -use session::output::{categorize_crate_type, CRATE_TYPES}; -use session::EarlyDiagCtxt; use std::env::consts::{DLL_PREFIX, DLL_SUFFIX}; use std::path::{Path, PathBuf}; use std::sync::atomic::{AtomicBool, Ordering}; @@ -286,7 +284,7 @@ fn get_codegen_sysroot( "cannot load the default codegen backend twice" ); - let target = session::config::host_triple(); + let target = host_triple(); let sysroot_candidates = sysroot_candidates(); let sysroot = iter::once(sysroot) diff --git a/compiler/rustc_lint/src/pass_by_value.rs b/compiler/rustc_lint/src/pass_by_value.rs index 1f0a8a0b567..c1f5cd45dc8 100644 --- a/compiler/rustc_lint/src/pass_by_value.rs +++ b/compiler/rustc_lint/src/pass_by_value.rs @@ -74,9 +74,12 @@ fn gen_args(cx: &LateContext<'_>, segment: &PathSegment<'_>) -> String { GenericArg::Type(ty) => { cx.tcx.sess.source_map().span_to_snippet(ty.span).unwrap_or_else(|_| "_".into()) } - GenericArg::Const(c) => { - cx.tcx.sess.source_map().span_to_snippet(c.span).unwrap_or_else(|_| "_".into()) - } + GenericArg::Const(c) => cx + .tcx + .sess + .source_map() + .span_to_snippet(c.value.span) + .unwrap_or_else(|_| "_".into()), GenericArg::Infer(_) => String::from("_"), }) .collect::<Vec<_>>(); diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index c0c773c6285..c7aea137b68 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -885,7 +885,7 @@ impl<'hir> Map<'hir> { Node::ImplItem(impl_item) => impl_item.span, Node::Variant(variant) => variant.span, Node::Field(field) => field.span, - Node::AnonConst(constant) => self.body(constant.body).value.span, + Node::AnonConst(constant) => constant.span, Node::ConstBlock(constant) => self.body(constant.body).value.span, Node::Expr(expr) => expr.span, Node::ExprField(field) => field.span, @@ -912,7 +912,7 @@ impl<'hir> Map<'hir> { Node::ArrayLenInfer(inf) => inf.span, Node::PreciseCapturingNonLifetimeArg(param) => param.ident.span, Node::Synthetic => unreachable!(), - Node::Err(span) => *span, + Node::Err(span) => span, } } diff --git a/compiler/rustc_middle/src/mir/coverage.rs b/compiler/rustc_middle/src/mir/coverage.rs index 9d9ca22247a..477303e2434 100644 --- a/compiler/rustc_middle/src/mir/coverage.rs +++ b/compiler/rustc_middle/src/mir/coverage.rs @@ -277,7 +277,7 @@ pub struct FunctionCoverageInfo { pub mappings: Vec<Mapping>, /// The depth of the deepest decision is used to know how many /// temp condbitmaps should be allocated for the function. - pub mcdc_max_decision_depth: u16, + pub mcdc_num_condition_bitmaps: usize, } /// Branch information recorded during THIR-to-MIR lowering, and stored in MIR. diff --git a/compiler/rustc_middle/src/mir/mono.rs b/compiler/rustc_middle/src/mir/mono.rs index 6d4585cfbc6..daab6c85581 100644 --- a/compiler/rustc_middle/src/mir/mono.rs +++ b/compiler/rustc_middle/src/mir/mono.rs @@ -1,7 +1,9 @@ use crate::dep_graph::{DepNode, WorkProduct, WorkProductId}; use crate::ty::{GenericArgs, Instance, InstanceDef, SymbolName, TyCtxt}; use rustc_attr::InlineAttr; -use rustc_data_structures::base_n; +use rustc_data_structures::base_n::BaseNString; +use rustc_data_structures::base_n::ToBaseN; +use rustc_data_structures::base_n::CASE_INSENSITIVE; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::fx::FxIndexMap; @@ -337,14 +339,11 @@ impl<'tcx> CodegenUnit<'tcx> { self.is_code_coverage_dead_code_cgu = true; } - pub fn mangle_name(human_readable_name: &str) -> String { - // We generate a 80 bit hash from the name. This should be enough to - // avoid collisions and is still reasonably short for filenames. + pub fn mangle_name(human_readable_name: &str) -> BaseNString { let mut hasher = StableHasher::new(); human_readable_name.hash(&mut hasher); let hash: Hash128 = hasher.finish(); - let hash = hash.as_u128() & ((1u128 << 80) - 1); - base_n::encode(hash, base_n::CASE_INSENSITIVE) + hash.as_u128().to_base_fixed_len(CASE_INSENSITIVE) } pub fn compute_size_estimate(&mut self) { diff --git a/compiler/rustc_middle/src/traits/solve.rs b/compiler/rustc_middle/src/traits/solve.rs index 4c34bf88c7f..3ad6b68d129 100644 --- a/compiler/rustc_middle/src/traits/solve.rs +++ b/compiler/rustc_middle/src/traits/solve.rs @@ -273,6 +273,8 @@ pub enum GoalSource { /// they are from an impl where-clause. This is necessary due to /// backwards compatability, cc trait-system-refactor-initiatitive#70. ImplWhereBound, + /// Instantiating a higher-ranked goal and re-proving it. + InstantiateHigherRanked, } /// Possible ways the given goal can be proven. diff --git a/compiler/rustc_middle/src/traits/solve/inspect/format.rs b/compiler/rustc_middle/src/traits/solve/inspect/format.rs index 2d73be387fd..11aa0e10931 100644 --- a/compiler/rustc_middle/src/traits/solve/inspect/format.rs +++ b/compiler/rustc_middle/src/traits/solve/inspect/format.rs @@ -127,6 +127,7 @@ impl<'a, 'b> ProofTreeFormatter<'a, 'b> { let source = match source { GoalSource::Misc => "misc", GoalSource::ImplWhereBound => "impl where-bound", + GoalSource::InstantiateHigherRanked => "higher-ranked goal", }; writeln!(this.f, "ADDED GOAL ({source}): {goal:?}")? } diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs index d6e6cc957b4..794e7ebb7b4 100644 --- a/compiler/rustc_mir_build/src/build/mod.rs +++ b/compiler/rustc_mir_build/src/build/mod.rs @@ -566,7 +566,8 @@ fn construct_const<'a, 'tcx>( span, .. }) => (*span, ty.span), - Node::AnonConst(_) | Node::ConstBlock(_) => { + Node::AnonConst(ct) => (ct.span, ct.span), + Node::ConstBlock(_) => { let span = tcx.def_span(def); (span, span) } diff --git a/compiler/rustc_mir_transform/src/copy_prop.rs b/compiler/rustc_mir_transform/src/copy_prop.rs index 0119b95cced..c1f9313a377 100644 --- a/compiler/rustc_mir_transform/src/copy_prop.rs +++ b/compiler/rustc_mir_transform/src/copy_prop.rs @@ -3,7 +3,6 @@ use rustc_index::IndexSlice; use rustc_middle::mir::visit::*; use rustc_middle::mir::*; use rustc_middle::ty::TyCtxt; -use rustc_mir_dataflow::impls::borrowed_locals; use crate::ssa::SsaLocals; @@ -32,8 +31,8 @@ impl<'tcx> MirPass<'tcx> for CopyProp { } fn propagate_ssa<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - let borrowed_locals = borrowed_locals(body); - let ssa = SsaLocals::new(body); + let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id()); + let ssa = SsaLocals::new(tcx, body, param_env); let fully_moved = fully_moved_locals(&ssa, body); debug!(?fully_moved); @@ -51,7 +50,7 @@ fn propagate_ssa<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { tcx, copy_classes: ssa.copy_classes(), fully_moved, - borrowed_locals, + borrowed_locals: ssa.borrowed_locals(), storage_to_remove, } .visit_body_preserves_cfg(body); @@ -101,7 +100,7 @@ struct Replacer<'a, 'tcx> { tcx: TyCtxt<'tcx>, fully_moved: BitSet<Local>, storage_to_remove: BitSet<Local>, - borrowed_locals: BitSet<Local>, + borrowed_locals: &'a BitSet<Local>, copy_classes: &'a IndexSlice<Local, Local>, } @@ -112,6 +111,12 @@ impl<'tcx> MutVisitor<'tcx> for Replacer<'_, 'tcx> { fn visit_local(&mut self, local: &mut Local, ctxt: PlaceContext, _: Location) { let new_local = self.copy_classes[*local]; + // We must not unify two locals that are borrowed. But this is fine if one is borrowed and + // the other is not. We chose to check the original local, and not the target. That way, if + // the original local is borrowed and the target is not, we do not pessimize the whole class. + if self.borrowed_locals.contains(*local) { + return; + } match ctxt { // Do not modify the local in storage statements. PlaceContext::NonUse(NonUseContext::StorageLive | NonUseContext::StorageDead) => {} @@ -122,32 +127,14 @@ impl<'tcx> MutVisitor<'tcx> for Replacer<'_, 'tcx> { } } - fn visit_place(&mut self, place: &mut Place<'tcx>, ctxt: PlaceContext, loc: Location) { + fn visit_place(&mut self, place: &mut Place<'tcx>, _: PlaceContext, loc: Location) { if let Some(new_projection) = self.process_projection(place.projection, loc) { place.projection = self.tcx().mk_place_elems(&new_projection); } - let observes_address = match ctxt { - PlaceContext::NonMutatingUse( - NonMutatingUseContext::SharedBorrow - | NonMutatingUseContext::FakeBorrow - | NonMutatingUseContext::AddressOf, - ) => true, - // For debuginfo, merging locals is ok. - PlaceContext::NonUse(NonUseContext::VarDebugInfo) => { - self.borrowed_locals.contains(place.local) - } - _ => false, - }; - if observes_address && !place.is_indirect() { - // We observe the address of `place.local`. Do not replace it. - } else { - self.visit_local( - &mut place.local, - PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy), - loc, - ) - } + // Any non-mutating use context is ok. + let ctxt = PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy); + self.visit_local(&mut place.local, ctxt, loc) } fn visit_operand(&mut self, operand: &mut Operand<'tcx>, loc: Location) { diff --git a/compiler/rustc_mir_transform/src/coverage/mod.rs b/compiler/rustc_mir_transform/src/coverage/mod.rs index 9edde666246..ffe61e761c5 100644 --- a/compiler/rustc_mir_transform/src/coverage/mod.rs +++ b/compiler/rustc_mir_transform/src/coverage/mod.rs @@ -102,7 +102,7 @@ fn instrument_function_for_coverage<'tcx>(tcx: TyCtxt<'tcx>, mir_body: &mut mir: inject_mcdc_statements(mir_body, &basic_coverage_blocks, &coverage_spans); - let mcdc_max_decision_depth = coverage_spans + let mcdc_num_condition_bitmaps = coverage_spans .mappings .iter() .filter_map(|bcb_mapping| match bcb_mapping.kind { @@ -110,7 +110,7 @@ fn instrument_function_for_coverage<'tcx>(tcx: TyCtxt<'tcx>, mir_body: &mut mir: _ => None, }) .max() - .unwrap_or(0); + .map_or(0, |max| usize::from(max) + 1); mir_body.function_coverage_info = Some(Box::new(FunctionCoverageInfo { function_source_hash: hir_info.function_source_hash, @@ -118,7 +118,7 @@ fn instrument_function_for_coverage<'tcx>(tcx: TyCtxt<'tcx>, mir_body: &mut mir: mcdc_bitmap_bytes: coverage_spans.test_vector_bitmap_bytes(), expressions: coverage_counters.into_expressions(), mappings, - mcdc_max_decision_depth, + mcdc_num_condition_bitmaps, })); } diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index 24832086b16..4dd595ce1e1 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -121,7 +121,7 @@ impl<'tcx> MirPass<'tcx> for GVN { fn propagate_ssa<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id()); - let ssa = SsaLocals::new(body); + let ssa = SsaLocals::new(tcx, body, param_env); // Clone dominators as we need them while mutating the body. let dominators = body.basic_blocks.dominators().clone(); @@ -724,6 +724,14 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { // Invariant: `value` holds the value up-to the `index`th projection excluded. let mut value = self.locals[place.local]?; for (index, proj) in place.projection.iter().enumerate() { + if let Value::Projection(pointer, ProjectionElem::Deref) = *self.get(value) + && let Value::Address { place: mut pointee, kind, .. } = *self.get(pointer) + && let AddressKind::Ref(BorrowKind::Shared) = kind + && let Some(v) = self.simplify_place_value(&mut pointee, location) + { + value = v; + place_ref = pointee.project_deeper(&place.projection[index..], self.tcx).as_ref(); + } if let Some(local) = self.try_as_local(value, location) { // Both `local` and `Place { local: place.local, projection: projection[..index] }` // hold the same value. Therefore, following place holds the value in the original @@ -735,6 +743,14 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { value = self.project(base, value, proj)?; } + if let Value::Projection(pointer, ProjectionElem::Deref) = *self.get(value) + && let Value::Address { place: mut pointee, kind, .. } = *self.get(pointer) + && let AddressKind::Ref(BorrowKind::Shared) = kind + && let Some(v) = self.simplify_place_value(&mut pointee, location) + { + value = v; + place_ref = pointee.project_deeper(&[], self.tcx).as_ref(); + } if let Some(new_local) = self.try_as_local(value, location) { place_ref = PlaceRef { local: new_local, projection: &[] }; } diff --git a/compiler/rustc_mir_transform/src/normalize_array_len.rs b/compiler/rustc_mir_transform/src/normalize_array_len.rs index 128634bd7f2..c26a5461633 100644 --- a/compiler/rustc_mir_transform/src/normalize_array_len.rs +++ b/compiler/rustc_mir_transform/src/normalize_array_len.rs @@ -22,7 +22,8 @@ impl<'tcx> MirPass<'tcx> for NormalizeArrayLen { } fn normalize_array_len_calls<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - let ssa = SsaLocals::new(body); + let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id()); + let ssa = SsaLocals::new(tcx, body, param_env); let slice_lengths = compute_slice_length(tcx, &ssa, body); debug!(?slice_lengths); diff --git a/compiler/rustc_mir_transform/src/ref_prop.rs b/compiler/rustc_mir_transform/src/ref_prop.rs index d5642be5513..044ae32c1d4 100644 --- a/compiler/rustc_mir_transform/src/ref_prop.rs +++ b/compiler/rustc_mir_transform/src/ref_prop.rs @@ -82,7 +82,8 @@ impl<'tcx> MirPass<'tcx> for ReferencePropagation { } fn propagate_ssa<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) -> bool { - let ssa = SsaLocals::new(body); + let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id()); + let ssa = SsaLocals::new(tcx, body, param_env); let mut replacer = compute_replacement(tcx, body, &ssa); debug!(?replacer.targets); diff --git a/compiler/rustc_mir_transform/src/ssa.rs b/compiler/rustc_mir_transform/src/ssa.rs index fddc62e6652..55fed7d9da2 100644 --- a/compiler/rustc_mir_transform/src/ssa.rs +++ b/compiler/rustc_mir_transform/src/ssa.rs @@ -2,8 +2,9 @@ //! 1/ They are only assigned-to once, either as a function parameter, or in an assign statement; //! 2/ This single assignment dominates all uses; //! -//! As a consequence of rule 2, we consider that borrowed locals are not SSA, even if they are -//! `Freeze`, as we do not track that the assignment dominates all uses of the borrow. +//! As we do not track indirect assignments, a local that has its address taken (either by +//! AddressOf or by borrowing) is considered non-SSA. However, it is UB to modify through an +//! immutable borrow of a `Freeze` local. Those can still be considered to be SSA. use rustc_data_structures::graph::dominators::Dominators; use rustc_index::bit_set::BitSet; @@ -11,6 +12,7 @@ use rustc_index::{IndexSlice, IndexVec}; use rustc_middle::middle::resolve_bound_vars::Set1; use rustc_middle::mir::visit::*; use rustc_middle::mir::*; +use rustc_middle::ty::{ParamEnv, TyCtxt}; pub struct SsaLocals { /// Assignments to each local. This defines whether the local is SSA. @@ -24,6 +26,8 @@ pub struct SsaLocals { /// Number of "direct" uses of each local, ie. uses that are not dereferences. /// We ignore non-uses (Storage statements, debuginfo). direct_uses: IndexVec<Local, u32>, + /// Set of SSA locals that are immutably borrowed. + borrowed_locals: BitSet<Local>, } pub enum AssignedValue<'a, 'tcx> { @@ -33,15 +37,22 @@ pub enum AssignedValue<'a, 'tcx> { } impl SsaLocals { - pub fn new<'tcx>(body: &Body<'tcx>) -> SsaLocals { + pub fn new<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, param_env: ParamEnv<'tcx>) -> SsaLocals { let assignment_order = Vec::with_capacity(body.local_decls.len()); let assignments = IndexVec::from_elem(Set1::Empty, &body.local_decls); let dominators = body.basic_blocks.dominators(); let direct_uses = IndexVec::from_elem(0, &body.local_decls); - let mut visitor = - SsaVisitor { body, assignments, assignment_order, dominators, direct_uses }; + let borrowed_locals = BitSet::new_empty(body.local_decls.len()); + let mut visitor = SsaVisitor { + body, + assignments, + assignment_order, + dominators, + direct_uses, + borrowed_locals, + }; for local in body.args_iter() { visitor.assignments[local] = Set1::One(DefLocation::Argument); @@ -58,6 +69,16 @@ impl SsaLocals { visitor.visit_var_debug_info(var_debug_info); } + // The immutability of shared borrows only works on `Freeze` locals. If the visitor found + // borrows, we need to check the types. For raw pointers and mutable borrows, the locals + // have already been marked as non-SSA. + debug!(?visitor.borrowed_locals); + for local in visitor.borrowed_locals.iter() { + if !body.local_decls[local].ty.is_freeze(tcx, param_env) { + visitor.assignments[local] = Set1::Many; + } + } + debug!(?visitor.assignments); debug!(?visitor.direct_uses); @@ -70,6 +91,7 @@ impl SsaLocals { assignments: visitor.assignments, assignment_order: visitor.assignment_order, direct_uses: visitor.direct_uses, + borrowed_locals: visitor.borrowed_locals, // This is filled by `compute_copy_classes`. copy_classes: IndexVec::default(), }; @@ -174,6 +196,11 @@ impl SsaLocals { &self.copy_classes } + /// Set of SSA locals that are immutably borrowed. + pub fn borrowed_locals(&self) -> &BitSet<Local> { + &self.borrowed_locals + } + /// Make a property uniform on a copy equivalence class by removing elements. pub fn meet_copy_equivalence(&self, property: &mut BitSet<Local>) { // Consolidate to have a local iff all its copies are. @@ -208,6 +235,8 @@ struct SsaVisitor<'tcx, 'a> { assignments: IndexVec<Local, Set1<DefLocation>>, assignment_order: Vec<Local>, direct_uses: IndexVec<Local, u32>, + // Track locals that are immutably borrowed, so we can check their type is `Freeze` later. + borrowed_locals: BitSet<Local>, } impl SsaVisitor<'_, '_> { @@ -232,16 +261,18 @@ impl<'tcx> Visitor<'tcx> for SsaVisitor<'tcx, '_> { PlaceContext::MutatingUse(MutatingUseContext::Projection) | PlaceContext::NonMutatingUse(NonMutatingUseContext::Projection) => bug!(), // Anything can happen with raw pointers, so remove them. - // We do not verify that all uses of the borrow dominate the assignment to `local`, - // so we have to remove them too. - PlaceContext::NonMutatingUse( - NonMutatingUseContext::SharedBorrow - | NonMutatingUseContext::FakeBorrow - | NonMutatingUseContext::AddressOf, - ) + PlaceContext::NonMutatingUse(NonMutatingUseContext::AddressOf) | PlaceContext::MutatingUse(_) => { self.assignments[local] = Set1::Many; } + // Immutable borrows are ok, but we need to delay a check that the type is `Freeze`. + PlaceContext::NonMutatingUse( + NonMutatingUseContext::SharedBorrow | NonMutatingUseContext::FakeBorrow, + ) => { + self.borrowed_locals.insert(local); + self.check_dominates(local, loc); + self.direct_uses[local] += 1; + } PlaceContext::NonMutatingUse(_) => { self.check_dominates(local, loc); self.direct_uses[local] += 1; diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index a545c170297..8878310d6e9 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -695,9 +695,6 @@ passes_transparent_incompatible = passes_undefined_naked_function_abi = Rust ABI is unsupported in naked functions -passes_unix_sigpipe_values = - valid values for `#[unix_sigpipe = "..."]` are `inherit`, `sig_ign`, or `sig_dfl` - passes_unknown_external_lang_item = unknown external lang item: `{$lang_item}` diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index c403e9196fa..e60aa27dba2 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -2523,7 +2523,6 @@ fn check_invalid_crate_level_attr(tcx: TyCtxt<'_>, attrs: &[Attribute]) { sym::automatically_derived, sym::start, sym::rustc_main, - sym::unix_sigpipe, sym::derive, sym::test, sym::test_case, diff --git a/compiler/rustc_passes/src/entry.rs b/compiler/rustc_passes/src/entry.rs index 438c583db49..d52092f2aa9 100644 --- a/compiler/rustc_passes/src/entry.rs +++ b/compiler/rustc_passes/src/entry.rs @@ -12,8 +12,7 @@ use rustc_span::symbol::sym; use rustc_span::{Span, Symbol}; use crate::errors::{ - AttrOnlyInFunctions, AttrOnlyOnMain, AttrOnlyOnRootMain, ExternMain, MultipleRustcMain, - MultipleStartFunctions, NoMainErr, UnixSigpipeValues, + AttrOnlyInFunctions, ExternMain, MultipleRustcMain, MultipleStartFunctions, NoMainErr, }; struct EntryContext<'tcx> { @@ -67,11 +66,7 @@ fn find_item(id: ItemId, ctxt: &mut EntryContext<'_>) { ctxt.tcx.opt_item_name(id.owner_id.to_def_id()), ); match entry_point_type { - EntryPointType::None => { - if let Some(span) = attr_span_by_symbol(ctxt, id, sym::unix_sigpipe) { - ctxt.tcx.dcx().emit_err(AttrOnlyOnMain { span, attr: sym::unix_sigpipe }); - } - } + EntryPointType::None => (), _ if !matches!(ctxt.tcx.def_kind(id.owner_id), DefKind::Fn) => { for attr in [sym::start, sym::rustc_main] { if let Some(span) = attr_span_by_symbol(ctxt, id, attr) { @@ -81,9 +76,6 @@ fn find_item(id: ItemId, ctxt: &mut EntryContext<'_>) { } EntryPointType::MainNamed => (), EntryPointType::OtherMain => { - if let Some(span) = attr_span_by_symbol(ctxt, id, sym::unix_sigpipe) { - ctxt.tcx.dcx().emit_err(AttrOnlyOnRootMain { span, attr: sym::unix_sigpipe }); - } ctxt.non_main_fns.push(ctxt.tcx.def_span(id.owner_id)); } EntryPointType::RustcMainAttr => { @@ -98,9 +90,6 @@ fn find_item(id: ItemId, ctxt: &mut EntryContext<'_>) { } } EntryPointType::Start => { - if let Some(span) = attr_span_by_symbol(ctxt, id, sym::unix_sigpipe) { - ctxt.tcx.dcx().emit_err(AttrOnlyOnMain { span, attr: sym::unix_sigpipe }); - } if ctxt.start_fn.is_none() { ctxt.start_fn = Some((id.owner_id.def_id, ctxt.tcx.def_span(id.owner_id))); } else { @@ -120,7 +109,7 @@ fn configure_main(tcx: TyCtxt<'_>, visitor: &EntryContext<'_>) -> Option<(DefId, Some((def_id.to_def_id(), EntryFnType::Start)) } else if let Some((local_def_id, _)) = visitor.attr_main_fn { let def_id = local_def_id.to_def_id(); - Some((def_id, EntryFnType::Main { sigpipe: sigpipe(tcx, def_id) })) + Some((def_id, EntryFnType::Main { sigpipe: sigpipe(tcx) })) } else { if let Some(main_def) = tcx.resolutions(()).main_def && let Some(def_id) = main_def.opt_fn_def_id() @@ -133,31 +122,19 @@ fn configure_main(tcx: TyCtxt<'_>, visitor: &EntryContext<'_>) -> Option<(DefId, return None; } - return Some((def_id, EntryFnType::Main { sigpipe: sigpipe(tcx, def_id) })); + return Some((def_id, EntryFnType::Main { sigpipe: sigpipe(tcx) })); } no_main_err(tcx, visitor); None } } -fn sigpipe(tcx: TyCtxt<'_>, def_id: DefId) -> u8 { - if let Some(attr) = tcx.get_attr(def_id, sym::unix_sigpipe) { - match (attr.value_str(), attr.meta_item_list()) { - (Some(sym::inherit), None) => sigpipe::INHERIT, - (Some(sym::sig_ign), None) => sigpipe::SIG_IGN, - (Some(sym::sig_dfl), None) => sigpipe::SIG_DFL, - (Some(_), None) => { - tcx.dcx().emit_err(UnixSigpipeValues { span: attr.span }); - sigpipe::DEFAULT - } - _ => { - // Keep going so that `fn emit_malformed_attribute()` can print - // an excellent error message - sigpipe::DEFAULT - } - } - } else { - sigpipe::DEFAULT +fn sigpipe(tcx: TyCtxt<'_>) -> u8 { + match tcx.sess.opts.unstable_opts.on_broken_pipe { + rustc_target::spec::OnBrokenPipe::Default => sigpipe::DEFAULT, + rustc_target::spec::OnBrokenPipe::Kill => sigpipe::SIG_DFL, + rustc_target::spec::OnBrokenPipe::Error => sigpipe::SIG_IGN, + rustc_target::spec::OnBrokenPipe::Inherit => sigpipe::INHERIT, } } diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index 03a607348e8..743faf54560 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -1259,13 +1259,6 @@ pub struct ExternMain { pub span: Span, } -#[derive(Diagnostic)] -#[diag(passes_unix_sigpipe_values)] -pub struct UnixSigpipeValues { - #[primary_span] - pub span: Span, -} - pub struct NoMainErr { pub sp: Span, pub crate_name: Symbol, diff --git a/compiler/rustc_privacy/Cargo.toml b/compiler/rustc_privacy/Cargo.toml index e7a32771f35..f998e0ff154 100644 --- a/compiler/rustc_privacy/Cargo.toml +++ b/compiler/rustc_privacy/Cargo.toml @@ -11,7 +11,6 @@ rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } rustc_fluent_macro = { path = "../rustc_fluent_macro" } rustc_hir = { path = "../rustc_hir" } -rustc_hir_analysis = { path = "../rustc_hir_analysis" } rustc_macros = { path = "../rustc_macros" } rustc_middle = { path = "../rustc_middle" } rustc_session = { path = "../rustc_session" } diff --git a/compiler/rustc_query_system/Cargo.toml b/compiler/rustc_query_system/Cargo.toml index 6ea87a4a633..4d845ab0d07 100644 --- a/compiler/rustc_query_system/Cargo.toml +++ b/compiler/rustc_query_system/Cargo.toml @@ -19,7 +19,6 @@ rustc_serialize = { path = "../rustc_serialize" } rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } rustc_target = { path = "../rustc_target" } -rustc_type_ir = { path = "../rustc_type_ir" } smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } thin-vec = "0.2.12" tracing = "0.1" diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 12484462f82..01e279b6d04 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -1617,7 +1617,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let post = format!(", consider renaming `{}` into `{snippet}`", suggestion.candidate); (span, snippet, post) } else { - (span, suggestion.candidate.to_string(), String::new()) + (span, suggestion.candidate.to_ident_string(), String::new()) }; let msg = match suggestion.target { SuggestionTarget::SimilarlyNamed => format!( diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index 82e41b6c314..35bf3f761df 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -141,7 +141,7 @@ pub(crate) fn registered_tools(tcx: TyCtxt<'_>, (): ()) -> RegisteredTools { } // We implicitly add `rustfmt`, `clippy`, `diagnostic` to known tools, // but it's not an error to register them explicitly. - let predefined_tools = [sym::clippy, sym::rustfmt, sym::diagnostic]; + let predefined_tools = [sym::clippy, sym::rustfmt, sym::diagnostic, sym::miri]; registered_tools.extend(predefined_tools.iter().cloned().map(Ident::with_dummy_span)); registered_tools } diff --git a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs index 40cd0c14b05..d67132d2dd4 100644 --- a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs +++ b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs @@ -4,7 +4,9 @@ //! //! For more information about LLVM CFI and cross-language LLVM CFI support for the Rust compiler, //! see design document in the tracking issue #89653. -use rustc_data_structures::base_n; +use rustc_data_structures::base_n::ToBaseN; +use rustc_data_structures::base_n::ALPHANUMERIC_ONLY; +use rustc_data_structures::base_n::CASE_INSENSITIVE; use rustc_data_structures::fx::FxHashMap; use rustc_hir as hir; use rustc_middle::bug; @@ -736,7 +738,7 @@ fn encode_ty_name(tcx: TyCtxt<'_>, def_id: DefId) -> String { /// <https://rust-lang.github.io/rfcs/2603-rust-symbol-name-mangling-v0.html>). fn to_disambiguator(num: u64) -> String { if let Some(num) = num.checked_sub(1) { - format!("s{}_", base_n::encode(num as u128, base_n::ALPHANUMERIC_ONLY)) + format!("s{}_", num.to_base(ALPHANUMERIC_ONLY)) } else { "s_".to_string() } @@ -746,7 +748,7 @@ fn to_disambiguator(num: u64) -> String { /// <https://itanium-cxx-abi.github.io/cxx-abi/abi.html#mangle.seq-id>). fn to_seq_id(num: usize) -> String { if let Some(num) = num.checked_sub(1) { - base_n::encode(num as u128, base_n::CASE_INSENSITIVE).to_uppercase() + (num as u64).to_base(CASE_INSENSITIVE).to_uppercase() } else { "".to_string() } diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index ad66e5e1c2b..f2bdabbf394 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -2909,7 +2909,9 @@ pub(crate) mod dep_tracking { use rustc_feature::UnstableFeatures; use rustc_span::edition::Edition; use rustc_span::RealFileName; - use rustc_target::spec::{CodeModel, MergeFunctions, PanicStrategy, RelocModel, WasmCAbi}; + use rustc_target::spec::{ + CodeModel, MergeFunctions, OnBrokenPipe, PanicStrategy, RelocModel, WasmCAbi, + }; use rustc_target::spec::{ RelroLevel, SanitizerSet, SplitDebuginfo, StackProtector, TargetTriple, TlsModel, }; @@ -2973,6 +2975,7 @@ pub(crate) mod dep_tracking { InstrumentXRay, CrateType, MergeFunctions, + OnBrokenPipe, PanicStrategy, RelroLevel, OptLevel, diff --git a/compiler/rustc_session/src/config/sigpipe.rs b/compiler/rustc_session/src/config/sigpipe.rs index 1fadc75cfd0..1830ee03485 100644 --- a/compiler/rustc_session/src/config/sigpipe.rs +++ b/compiler/rustc_session/src/config/sigpipe.rs @@ -1,6 +1,6 @@ //! NOTE: Keep these constants in sync with `library/std/src/sys/pal/unix/mod.rs`! -/// The default value if `#[unix_sigpipe]` is not specified. This resolves +/// The default value if `-Zon-broken-pipe=...` is not specified. This resolves /// to `SIG_IGN` in `library/std/src/sys/pal/unix/mod.rs`. /// /// Note that `SIG_IGN` has been the Rust default since 2014. See diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 7355e5b6953..65660286dd7 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -12,7 +12,7 @@ use rustc_span::edition::Edition; use rustc_span::RealFileName; use rustc_span::SourceFileHashAlgorithm; use rustc_target::spec::{ - CodeModel, LinkerFlavorCli, MergeFunctions, PanicStrategy, SanitizerSet, WasmCAbi, + CodeModel, LinkerFlavorCli, MergeFunctions, OnBrokenPipe, PanicStrategy, SanitizerSet, WasmCAbi, }; use rustc_target::spec::{ RelocModel, RelroLevel, SplitDebuginfo, StackProtector, TargetTriple, TlsModel, @@ -378,6 +378,7 @@ mod desc { pub const parse_time_passes_format: &str = "`text` (default) or `json`"; pub const parse_passes: &str = "a space-separated list of passes, or `all`"; pub const parse_panic_strategy: &str = "either `unwind` or `abort`"; + pub const parse_on_broken_pipe: &str = "either `kill`, `error`, or `inherit`"; pub const parse_opt_panic_strategy: &str = parse_panic_strategy; pub const parse_oom_strategy: &str = "either `panic` or `abort`"; pub const parse_relro_level: &str = "one of: `full`, `partial`, or `off`"; @@ -708,6 +709,17 @@ mod parse { true } + pub(crate) fn parse_on_broken_pipe(slot: &mut OnBrokenPipe, v: Option<&str>) -> bool { + match v { + // OnBrokenPipe::Default can't be explicitly specified + Some("kill") => *slot = OnBrokenPipe::Kill, + Some("error") => *slot = OnBrokenPipe::Error, + Some("inherit") => *slot = OnBrokenPipe::Inherit, + _ => return false, + } + true + } + pub(crate) fn parse_oom_strategy(slot: &mut OomStrategy, v: Option<&str>) -> bool { match v { Some("panic") => *slot = OomStrategy::Panic, @@ -1833,6 +1845,8 @@ options! { "do not use unique names for text and data sections when -Z function-sections is used"), normalize_docs: bool = (false, parse_bool, [TRACKED], "normalize associated items in rustdoc when generating documentation"), + on_broken_pipe: OnBrokenPipe = (OnBrokenPipe::Default, parse_on_broken_pipe, [TRACKED], + "behavior of std::io::ErrorKind::BrokenPipe (SIGPIPE)"), oom: OomStrategy = (OomStrategy::Abort, parse_oom_strategy, [TRACKED], "panic strategy for out-of-memory handling"), osx_rpath_install_name: bool = (false, parse_bool, [TRACKED], diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 7fe94c2e82b..9c556f1152a 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1936,7 +1936,6 @@ symbols! { unit, universal_impl_trait, unix, - unix_sigpipe, unlikely, unmarked_api, unnamed_fields, diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index fc2c3dcb2d9..5cdfb773b5c 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -1,4 +1,4 @@ -use rustc_data_structures::base_n; +use rustc_data_structures::base_n::ToBaseN; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::intern::Interned; use rustc_hir as hir; @@ -832,7 +832,7 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> { /// e.g. `1` becomes `"0_"`, `62` becomes `"Z_"`, etc. pub(crate) fn push_integer_62(x: u64, output: &mut String) { if let Some(x) = x.checked_sub(1) { - base_n::push_str(x as u128, base_n::ALPHANUMERIC_ONLY, output); + output.push_str(&x.to_base(62)); } output.push('_'); } diff --git a/compiler/rustc_target/src/spec/base/fuchsia.rs b/compiler/rustc_target/src/spec/base/fuchsia.rs index 4c2775850d1..d1ac22f3a09 100644 --- a/compiler/rustc_target/src/spec/base/fuchsia.rs +++ b/compiler/rustc_target/src/spec/base/fuchsia.rs @@ -1,4 +1,6 @@ -use crate::spec::{crt_objects, cvs, Cc, LinkOutputKind, LinkerFlavor, Lld, TargetOptions}; +use crate::spec::{ + crt_objects, cvs, Cc, FramePointer, LinkOutputKind, LinkerFlavor, Lld, TargetOptions, +}; pub fn opts() -> TargetOptions { // This mirrors the linker options provided by clang. We presume lld for @@ -38,6 +40,7 @@ pub fn opts() -> TargetOptions { ]), position_independent_executables: true, has_thread_local: true, + frame_pointer: FramePointer::NonLeaf, ..Default::default() } } diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index bd347c1b4b3..cbb248a0fc2 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -778,6 +778,14 @@ pub enum PanicStrategy { Abort, } +#[derive(Clone, Copy, Debug, PartialEq, Hash, Encodable, Decodable, HashStable_Generic)] +pub enum OnBrokenPipe { + Default, + Kill, + Error, + Inherit, +} + impl PanicStrategy { pub fn desc(&self) -> &str { match *self { diff --git a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs index 280975f63bd..f2ca42a0be9 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs @@ -58,15 +58,15 @@ pub(super) trait GoalKind<'tcx>: /// goal by equating it with the assumption. fn probe_and_consider_implied_clause( ecx: &mut EvalCtxt<'_, 'tcx>, - source: CandidateSource, + parent_source: CandidateSource, goal: Goal<'tcx, Self>, assumption: ty::Clause<'tcx>, - requirements: impl IntoIterator<Item = Goal<'tcx, ty::Predicate<'tcx>>>, + requirements: impl IntoIterator<Item = (GoalSource, Goal<'tcx, ty::Predicate<'tcx>>)>, ) -> Result<Candidate<'tcx>, NoSolution> { - Self::probe_and_match_goal_against_assumption(ecx, source, goal, assumption, |ecx| { - // FIXME(-Znext-solver=coinductive): check whether this should be - // `GoalSource::ImplWhereBound` for any caller. - ecx.add_goals(GoalSource::Misc, requirements); + Self::probe_and_match_goal_against_assumption(ecx, parent_source, goal, assumption, |ecx| { + for (nested_source, goal) in requirements { + ecx.add_goal(nested_source, goal); + } ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) }) } @@ -85,9 +85,8 @@ pub(super) trait GoalKind<'tcx>: let ty::Dynamic(bounds, _, _) = *goal.predicate.self_ty().kind() else { bug!("expected object type in `probe_and_consider_object_bound_candidate`"); }; - // FIXME(-Znext-solver=coinductive): Should this be `GoalSource::ImplWhereBound`? ecx.add_goals( - GoalSource::Misc, + GoalSource::ImplWhereBound, structural_traits::predicates_for_object_candidate( ecx, goal.param_env, diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs index 6722abd709c..d6bf2b596ef 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs @@ -90,6 +90,8 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { &mut self, certainty: Certainty, ) -> QueryResult<'tcx> { + self.inspect.make_canonical_response(certainty); + let goals_certainty = self.try_evaluate_added_goals()?; assert_eq!( self.tainted, @@ -98,8 +100,6 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { previous call to `try_evaluate_added_goals!`" ); - self.inspect.make_canonical_response(certainty); - // When normalizing, we've replaced the expected term with an unconstrained // inference variable. This means that we dropped information which could // have been important. We handle this by instead returning the nested goals diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs index 1710746ae50..bae1c6b6011 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs @@ -454,7 +454,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> { } else { self.infcx.enter_forall(kind, |kind| { let goal = goal.with(self.tcx(), ty::Binder::dummy(kind)); - self.add_goal(GoalSource::Misc, goal); + self.add_goal(GoalSource::InstantiateHigherRanked, goal); self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) }) } diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs index 3fa409eefff..796222129f1 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs @@ -1,15 +1,19 @@ use std::mem; +use std::ops::ControlFlow; use rustc_infer::infer::InferCtxt; -use rustc_infer::traits::solve::MaybeCause; +use rustc_infer::traits::query::NoSolution; +use rustc_infer::traits::solve::inspect::ProbeKind; +use rustc_infer::traits::solve::{CandidateSource, GoalSource, MaybeCause}; use rustc_infer::traits::{ - query::NoSolution, FulfillmentError, FulfillmentErrorCode, MismatchedProjectionTypes, - PredicateObligation, SelectionError, TraitEngine, + self, FulfillmentError, FulfillmentErrorCode, MismatchedProjectionTypes, Obligation, + ObligationCause, PredicateObligation, SelectionError, TraitEngine, }; -use rustc_middle::ty; use rustc_middle::ty::error::{ExpectedFound, TypeError}; +use rustc_middle::ty::{self, TyCtxt}; use super::eval_ctxt::GenerateProofTree; +use super::inspect::{ProofTreeInferCtxtExt, ProofTreeVisitor}; use super::{Certainty, InferCtxtEvalExt}; /// A trait engine using the new trait solver. @@ -133,9 +137,9 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> { .collect(); errors.extend(self.obligations.overflowed.drain(..).map(|obligation| FulfillmentError { - root_obligation: obligation.clone(), + obligation: find_best_leaf_obligation(infcx, &obligation), code: FulfillmentErrorCode::Ambiguity { overflow: Some(true) }, - obligation, + root_obligation: obligation, })); errors @@ -192,8 +196,10 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> { fn fulfillment_error_for_no_solution<'tcx>( infcx: &InferCtxt<'tcx>, - obligation: PredicateObligation<'tcx>, + root_obligation: PredicateObligation<'tcx>, ) -> FulfillmentError<'tcx> { + let obligation = find_best_leaf_obligation(infcx, &root_obligation); + let code = match obligation.predicate.kind().skip_binder() { ty::PredicateKind::Clause(ty::ClauseKind::Projection(_)) => { FulfillmentErrorCode::ProjectionError( @@ -234,7 +240,8 @@ fn fulfillment_error_for_no_solution<'tcx>( bug!("unexpected goal: {obligation:?}") } }; - FulfillmentError { root_obligation: obligation.clone(), code, obligation } + + FulfillmentError { obligation, code, root_obligation } } fn fulfillment_error_for_stalled<'tcx>( @@ -258,5 +265,136 @@ fn fulfillment_error_for_stalled<'tcx>( } }); - FulfillmentError { obligation: obligation.clone(), code, root_obligation: obligation } + FulfillmentError { + obligation: find_best_leaf_obligation(infcx, &obligation), + code, + root_obligation: obligation, + } +} + +fn find_best_leaf_obligation<'tcx>( + infcx: &InferCtxt<'tcx>, + obligation: &PredicateObligation<'tcx>, +) -> PredicateObligation<'tcx> { + let obligation = infcx.resolve_vars_if_possible(obligation.clone()); + infcx + .visit_proof_tree( + obligation.clone().into(), + &mut BestObligation { obligation: obligation.clone() }, + ) + .break_value() + .unwrap_or(obligation) +} + +struct BestObligation<'tcx> { + obligation: PredicateObligation<'tcx>, +} + +impl<'tcx> BestObligation<'tcx> { + fn with_derived_obligation( + &mut self, + derived_obligation: PredicateObligation<'tcx>, + and_then: impl FnOnce(&mut Self) -> <Self as ProofTreeVisitor<'tcx>>::Result, + ) -> <Self as ProofTreeVisitor<'tcx>>::Result { + let old_obligation = std::mem::replace(&mut self.obligation, derived_obligation); + let res = and_then(self); + self.obligation = old_obligation; + res + } +} + +impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> { + type Result = ControlFlow<PredicateObligation<'tcx>>; + + fn span(&self) -> rustc_span::Span { + self.obligation.cause.span + } + + fn visit_goal(&mut self, goal: &super::inspect::InspectGoal<'_, 'tcx>) -> Self::Result { + // FIXME: Throw out candidates that have no failing WC and >0 failing misc goal. + // This most likely means that the goal just didn't unify at all, e.g. a param + // candidate with an alias in it. + let candidates = goal.candidates(); + + let [candidate] = candidates.as_slice() else { + return ControlFlow::Break(self.obligation.clone()); + }; + + // FIXME: Could we extract a trait ref from a projection here too? + // FIXME: Also, what about considering >1 layer up the stack? May be necessary + // for normalizes-to. + let Some(parent_trait_pred) = goal.goal().predicate.to_opt_poly_trait_pred() else { + return ControlFlow::Break(self.obligation.clone()); + }; + + let tcx = goal.infcx().tcx; + let mut impl_where_bound_count = 0; + for nested_goal in candidate.instantiate_nested_goals(self.span()) { + let obligation; + match nested_goal.source() { + GoalSource::Misc => { + continue; + } + GoalSource::ImplWhereBound => { + obligation = Obligation { + cause: derive_cause( + tcx, + candidate.kind(), + self.obligation.cause.clone(), + impl_where_bound_count, + parent_trait_pred, + ), + param_env: nested_goal.goal().param_env, + predicate: nested_goal.goal().predicate, + recursion_depth: self.obligation.recursion_depth + 1, + }; + impl_where_bound_count += 1; + } + GoalSource::InstantiateHigherRanked => { + obligation = self.obligation.clone(); + } + } + + // Skip nested goals that hold. + //FIXME: We should change the max allowed certainty based on if we're + // visiting an ambiguity or error obligation. + if matches!(nested_goal.result(), Ok(Certainty::Yes)) { + continue; + } + + self.with_derived_obligation(obligation, |this| nested_goal.visit_with(this))?; + } + + ControlFlow::Break(self.obligation.clone()) + } +} + +fn derive_cause<'tcx>( + tcx: TyCtxt<'tcx>, + candidate_kind: ProbeKind<'tcx>, + mut cause: ObligationCause<'tcx>, + idx: usize, + parent_trait_pred: ty::PolyTraitPredicate<'tcx>, +) -> ObligationCause<'tcx> { + match candidate_kind { + ProbeKind::TraitCandidate { source: CandidateSource::Impl(impl_def_id), result: _ } => { + if let Some((_, span)) = + tcx.predicates_of(impl_def_id).instantiate_identity(tcx).iter().nth(idx) + { + cause = cause.derived_cause(parent_trait_pred, |derived| { + traits::ImplDerivedObligation(Box::new(traits::ImplDerivedObligationCause { + derived, + impl_or_alias_def_id: impl_def_id, + impl_def_predicate_index: Some(idx), + span, + })) + }) + } + } + ProbeKind::TraitCandidate { source: CandidateSource::BuiltinImpl(..), result: _ } => { + cause = cause.derived_cause(parent_trait_pred, traits::BuiltinDerivedObligation); + } + _ => {} + }; + cause } diff --git a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs index 97de25295b8..4f79f1b2aaf 100644 --- a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs +++ b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs @@ -41,6 +41,7 @@ pub struct InspectGoal<'a, 'tcx> { result: Result<Certainty, NoSolution>, evaluation_kind: inspect::CanonicalGoalEvaluationKind<'tcx>, normalizes_to_term_hack: Option<NormalizesToTermHack<'tcx>>, + source: GoalSource, } /// The expected term of a `NormalizesTo` goal gets replaced @@ -90,7 +91,7 @@ impl<'tcx> NormalizesToTermHack<'tcx> { pub struct InspectCandidate<'a, 'tcx> { goal: &'a InspectGoal<'a, 'tcx>, kind: inspect::ProbeKind<'tcx>, - nested_goals: Vec<inspect::CanonicalState<'tcx, Goal<'tcx, ty::Predicate<'tcx>>>>, + nested_goals: Vec<(GoalSource, inspect::CanonicalState<'tcx, Goal<'tcx, ty::Predicate<'tcx>>>)>, final_state: inspect::CanonicalState<'tcx, ()>, result: QueryResult<'tcx>, shallow_certainty: Certainty, @@ -125,10 +126,8 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> { /// back their inference constraints. This function modifies /// the state of the `infcx`. pub fn visit_nested_no_probe<V: ProofTreeVisitor<'tcx>>(&self, visitor: &mut V) -> V::Result { - if self.goal.depth < visitor.config().max_depth { - for goal in self.instantiate_nested_goals(visitor.span()) { - try_visit!(visitor.visit_goal(&goal)); - } + for goal in self.instantiate_nested_goals(visitor.span()) { + try_visit!(goal.visit_with(visitor)); } V::Result::output() @@ -143,13 +142,16 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> { let instantiated_goals: Vec<_> = self .nested_goals .iter() - .map(|goal| { - canonical::instantiate_canonical_state( - infcx, - span, - param_env, - &mut orig_values, - *goal, + .map(|(source, goal)| { + ( + *source, + canonical::instantiate_canonical_state( + infcx, + span, + param_env, + &mut orig_values, + *goal, + ), ) }) .collect(); @@ -171,7 +173,7 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> { instantiated_goals .into_iter() - .map(|goal| match goal.predicate.kind().no_bound_vars() { + .map(|(source, goal)| match goal.predicate.kind().no_bound_vars() { Some(ty::PredicateKind::NormalizesTo(ty::NormalizesTo { alias, term })) => { let unconstrained_term = match term.unpack() { ty::TermKind::Ty(_) => infcx @@ -195,6 +197,7 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> { self.goal.depth + 1, proof_tree.unwrap(), Some(NormalizesToTermHack { term, unconstrained_term }), + source, ) } _ => InspectGoal::new( @@ -202,6 +205,7 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> { self.goal.depth + 1, infcx.evaluate_root_goal(goal, GenerateProofTree::Yes).1.unwrap(), None, + source, ), }) .collect() @@ -227,16 +231,23 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> { self.result } + pub fn source(&self) -> GoalSource { + self.source + } + fn candidates_recur( &'a self, candidates: &mut Vec<InspectCandidate<'a, 'tcx>>, - nested_goals: &mut Vec<inspect::CanonicalState<'tcx, Goal<'tcx, ty::Predicate<'tcx>>>>, + nested_goals: &mut Vec<( + GoalSource, + inspect::CanonicalState<'tcx, Goal<'tcx, ty::Predicate<'tcx>>>, + )>, probe: &inspect::Probe<'tcx>, ) { let mut shallow_certainty = None; for step in &probe.steps { match step { - &inspect::ProbeStep::AddGoal(_source, goal) => nested_goals.push(goal), + &inspect::ProbeStep::AddGoal(source, goal) => nested_goals.push((source, goal)), inspect::ProbeStep::NestedProbe(ref probe) => { // Nested probes have to prove goals added in their parent // but do not leak them, so we truncate the added goals @@ -319,6 +330,7 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> { depth: usize, root: inspect::GoalEvaluation<'tcx>, normalizes_to_term_hack: Option<NormalizesToTermHack<'tcx>>, + source: GoalSource, ) -> Self { let inspect::GoalEvaluation { uncanonicalized_goal, kind, evaluation } = root; let inspect::GoalEvaluationKind::Root { orig_values } = kind else { unreachable!() }; @@ -341,8 +353,17 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> { result, evaluation_kind: evaluation.kind, normalizes_to_term_hack, + source, } } + + pub(crate) fn visit_with<V: ProofTreeVisitor<'tcx>>(&self, visitor: &mut V) -> V::Result { + if self.depth < visitor.config().max_depth { + try_visit!(visitor.visit_goal(self)); + } + + V::Result::output() + } } /// The public API to interact with proof trees. @@ -367,6 +388,6 @@ impl<'tcx> InferCtxt<'tcx> { ) -> V::Result { let (_, proof_tree) = self.evaluate_root_goal(goal, GenerateProofTree::Yes); let proof_tree = proof_tree.unwrap(); - visitor.visit_goal(&InspectGoal::new(self, 0, proof_tree, None)) + visitor.visit_goal(&InspectGoal::new(self, 0, proof_tree, None, GoalSource::Misc)) } } diff --git a/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs b/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs index dab87fffe46..f886c588650 100644 --- a/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs @@ -389,7 +389,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { CandidateSource::BuiltinImpl(BuiltinImplSource::Misc), goal, pred, - [goal.with(tcx, output_is_sized_pred)], + [(GoalSource::ImplWhereBound, goal.with(tcx, output_is_sized_pred))], ) } @@ -473,7 +473,8 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { pred, [goal.with(tcx, output_is_sized_pred)] .into_iter() - .chain(nested_preds.into_iter().map(|pred| goal.with(tcx, pred))), + .chain(nested_preds.into_iter().map(|pred| goal.with(tcx, pred))) + .map(|goal| (GoalSource::ImplWhereBound, goal)), ) } diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals.rs b/compiler/rustc_trait_selection/src/solve/trait_goals.rs index c8cb14abb55..d2b893d6383 100644 --- a/compiler/rustc_trait_selection/src/solve/trait_goals.rs +++ b/compiler/rustc_trait_selection/src/solve/trait_goals.rs @@ -321,7 +321,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { CandidateSource::BuiltinImpl(BuiltinImplSource::Misc), goal, pred, - [goal.with(tcx, output_is_sized_pred)], + [(GoalSource::ImplWhereBound, goal.with(tcx, output_is_sized_pred))], ) } @@ -367,7 +367,8 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { pred, [goal.with(tcx, output_is_sized_pred)] .into_iter() - .chain(nested_preds.into_iter().map(|pred| goal.with(tcx, pred))), + .chain(nested_preds.into_iter().map(|pred| goal.with(tcx, pred))) + .map(|goal| (GoalSource::ImplWhereBound, goal)), ) } |
