-------------------------------------------------------------------------------- I1 cache: 65536 B, 64 B, 4-way associative D1 cache: 32768 B, 64 B, 8-way associative LL cache: 67108864 B, 64 B, 64-way associative Command: /usr/home/liquid/.rustup/toolchains/w-profiling/bin/rustc --crate-name actix_threadpool --edition=2018 src/lib.rs --error-format=json --json=diagnostic-rendered-ansi,artifacts,future-incompat --crate-type lib --emit=dep-info,metadata,link -C embed-bitcode=no -C debuginfo=2 -C metadata=836a1a1922fab88b -C extra-filename=-836a1a1922fab88b --out-dir /usr/home/liquid/tmp/.tmpqa3lrl/target/debug/deps -L dependency=/usr/home/liquid/tmp/.tmpqa3lrl/target/debug/deps --extern derive_more=/usr/home/liquid/tmp/.tmpqa3lrl/target/debug/deps/libderive_more-4abb392275f10380.so --extern futures_channel=/usr/home/liquid/tmp/.tmpqa3lrl/target/debug/deps/libfutures_channel-895fd9fe5df219af.rmeta --extern lazy_static=/usr/home/liquid/tmp/.tmpqa3lrl/target/debug/deps/liblazy_static-34247ca5ec35351b.rmeta --extern log=/usr/home/liquid/tmp/.tmpqa3lrl/target/debug/deps/liblog-4f7417fc1215ce43.rmeta --extern num_cpus=/usr/home/liquid/tmp/.tmpqa3lrl/target/debug/deps/libnum_cpus-6c418dc8cdad9aca.rmeta --extern parking_lot=/usr/home/liquid/tmp/.tmpqa3lrl/target/debug/deps/libparking_lot-13fc41516e4e349c.rmeta --extern threadpool=/usr/home/liquid/tmp/.tmpqa3lrl/target/debug/deps/libthreadpool-4e1b329c1f7ca33e.rmeta -Adeprecated -Aunknown-lints -Zincremental-verify-ich Data file: results/cgout-w-profiling-actix-threadpool-0.3.3-Debug-Full Events recorded: Ir Events shown: Ir Event sort order: Ir Thresholds: 0.1 Include dirs: User annotated: Auto-annotation: on -------------------------------------------------------------------------------- Ir -------------------------------------------------------------------------------- 538,329,803 (100.0%) PROGRAM TOTALS -------------------------------------------------------------------------------- Ir file:function -------------------------------------------------------------------------------- 18,126,426 ( 3.37%) ./malloc/malloc.c:_int_malloc 17,480,672 ( 3.25%) ./elf/dl-lookup.c:_dl_lookup_symbol_x 15,926,438 ( 2.96%) ./malloc/malloc.c:_int_free 15,145,515 ( 2.81%) ???:llvm::FPPassManager::runOnFunction(llvm::Function&) 11,561,325 ( 2.15%) ./elf/dl-lookup.c:do_lookup_x 9,820,785 ( 1.82%) ./malloc/malloc.c:malloc 8,480,585 ( 1.58%) ???:(anonymous namespace)::Verifier::visitMDNode(llvm::MDNode const&, (anonymous namespace)::Verifier::AreDebugLocsAllowed) 5,796,690 ( 1.08%) ./string/../sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S:__memcpy_avx_unaligned_erms 5,399,825 ( 1.00%) ./string/../sysdeps/x86_64/multiarch/memset-vec-unaligned-erms.S:__memset_avx2_erms 4,860,494 ( 0.90%) ./elf/../sysdeps/x86_64/dl-machine.h:_dl_relocate_object 4,677,622 ( 0.87%) ???:llvm::MCObjectStreamer::emitBytes(llvm::StringRef) 4,561,224 ( 0.85%) ???:llvm::SelectionDAG::Combine(llvm::CombineLevel, llvm::AAResults*, llvm::CodeGenOpt::Level) 4,547,458 ( 0.84%) ./malloc/malloc.c:free 4,494,485 ( 0.83%) ???:llvm::raw_svector_ostream::write_impl(char const*, unsigned long) 4,251,008 ( 0.79%) ???:llvm::PassRegistry::enumerateWith(llvm::PassRegistrationListener*) 4,202,419 ( 0.78%) ???:llvm::StringMapImpl::LookupBucketFor(llvm::StringRef) 4,111,678 ( 0.76%) ???:llvm::FoldingSetNodeID::AddInteger(unsigned int) 3,935,758 ( 0.73%) ???:llvm::AttributeList::addAttributes(llvm::LLVMContext&, unsigned int, llvm::AttrBuilder const&) const 3,568,496 ( 0.66%) ???:llvm::X86TargetLowering::X86TargetLowering(llvm::X86TargetMachine const&, llvm::X86Subtarget const&) 3,058,746 ( 0.57%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_serialize/src/opaque.rs:>::decode 3,052,960 ( 0.57%) ???:llvm::TargetLoweringBase::computeRegisterProperties(llvm::TargetRegisterInfo const*) 3,036,873 ( 0.56%) ???:llvm::PMDataManager::verifyPreservedAnalysis(llvm::Pass*) 2,910,809 ( 0.54%) ???:SetImpliedBits(llvm::FeatureBitset&, llvm::FeatureBitset const&, llvm::ArrayRef) 2,867,698 ( 0.53%) ???:llvm::MDString::get(llvm::LLVMContext&, llvm::StringRef) 2,826,447 ( 0.53%) ./malloc/malloc.c:malloc_consolidate 2,780,188 ( 0.52%) ./string/../sysdeps/x86_64/multiarch/memcmp-avx2-movbe.S:__memcmp_avx2_movbe 2,741,079 ( 0.51%) /usr/home/liquid/rust/worktree-benchmarking/library/alloc/src/vec/mod.rs:>::decode 2,632,812 ( 0.49%) ???:llvm::MDNode::MDNode(llvm::LLVMContext&, unsigned int, llvm::Metadata::StorageType, llvm::ArrayRef, llvm::ArrayRef) 2,564,097 ( 0.48%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_span/src/lib.rs:>::decode 2,420,787 ( 0.45%) ???:(anonymous namespace)::ELFObjectWriter::recordRelocation(llvm::MCAssembler&, llvm::MCAsmLayout const&, llvm::MCFragment const*, llvm::MCFixup const&, llvm::MCValue, unsigned long&) [clone .llvm.14145361893594770252] 2,357,984 ( 0.44%) ./elf/do-rel.h:_dl_relocate_object 2,255,765 ( 0.42%) ???:llvm::MCExpr::evaluateAsRelocatableImpl(llvm::MCValue&, llvm::MCAssembler const*, llvm::MCAsmLayout const*, llvm::MCFixup const*, llvm::DenseMap, llvm::detail::DenseMapPair > const*, bool) const 2,243,903 ( 0.42%) ???:llvm::MCAsmLayout::getSymbolOffset(llvm::MCSymbol const&) const 2,149,584 ( 0.40%) ???:char* llvm::hashing::detail::hash_combine_recursive_helper::combine_data(unsigned long&, char*, char*, llvm::Metadata*) 2,148,261 ( 0.40%) ???:llvm::hashing::detail::hash_combine_recursive_helper::combine(unsigned long, char*, char*) 2,087,595 ( 0.39%) ???:(anonymous namespace)::Verifier::visitInstruction(llvm::Instruction&) 2,085,522 ( 0.39%) ./malloc/malloc.c:unlink_chunk.constprop.0 2,016,515 ( 0.37%) ./string/../sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S:__memcpy_sse2_unaligned_erms 1,999,940 ( 0.37%) ???:llvm::FoldingSetBase::FindNodeOrInsertPos(llvm::FoldingSetNodeID const&, void*&, llvm::FoldingSetBase::FoldingSetInfo const&) 1,840,998 ( 0.34%) ???:llvm::MDNodeKeyImpl::MDNodeKeyImpl(llvm::DICompositeType const*) 1,827,071 ( 0.34%) ???:llvm::MachineInstr::addOperand(llvm::MachineFunction&, llvm::MachineOperand const&) 1,744,092 ( 0.32%) ???:llvm::MCStreamer::emitULEB128IntValue(unsigned long, unsigned int) 1,713,412 ( 0.32%) ???:llvm::SelectionDAGISel::SelectCodeCommon(llvm::SDNode*, unsigned char const*, unsigned int) 1,624,745 ( 0.30%) ???:llvm::BumpPtrAllocatorImpl::Allocate(unsigned long, llvm::Align) 1,514,292 ( 0.28%) ???:(anonymous namespace)::RegAllocFast::allocateBasicBlock(llvm::MachineBasicBlock&) 1,485,369 ( 0.28%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_serialize/src/leb128.rs:::read_u32 1,397,763 ( 0.26%) ???:(anonymous namespace)::GetCFGOnlyPasses::passEnumerate(llvm::PassInfo const*) [clone .llvm.764396836974782617] 1,365,494 ( 0.25%) ???:llvm::MDString* llvm::DINode::getOperandAs(unsigned int) const 1,326,455 ( 0.25%) ???:(anonymous namespace)::ELFWriter::writeObject(llvm::MCAssembler&, llvm::MCAsmLayout const&) 1,306,410 ( 0.24%) ???:llvm::MCAssembler::layout(llvm::MCAsmLayout&) 1,292,808 ( 0.24%) ???:llvm::LLVMContextImpl::~LLVMContextImpl() 1,292,335 ( 0.24%) ./elf/dl-lookup.c:check_match 1,287,009 ( 0.24%) ???:llvm::raw_ostream::write(char const*, unsigned long) 1,273,351 ( 0.24%) ???:llvm::coro::declaresIntrinsics(llvm::Module const&, std::initializer_list) 1,272,972 ( 0.24%) ???:llvm::TargetRegisterInfo::checkAllSuperRegsMarked(llvm::BitVector const&, llvm::ArrayRef) const 1,264,413 ( 0.23%) ???:llvm::MCAsmLayout::getFragmentOffset(llvm::MCFragment const*) const 1,257,523 ( 0.23%) ???:(anonymous namespace)::Verifier::verifyFunctionAttrs(llvm::FunctionType*, llvm::AttributeList, llvm::Value const*, bool) 1,248,904 ( 0.23%) ???:llvm::DIEAbbrev::Profile(llvm::FoldingSetNodeID&) const 1,238,805 ( 0.23%) ./malloc/malloc.c:realloc 1,236,736 ( 0.23%) ???:bool llvm::DenseMapBase, llvm::detail::DenseSetPair >, llvm::DICompositeType*, llvm::detail::DenseSetEmpty, llvm::MDNodeInfo, llvm::detail::DenseSetPair >::LookupBucketFor(llvm::DICompositeType* const&, llvm::detail::DenseSetPair const*&) const 1,221,766 ( 0.23%) ???:llvm::X86_MC::initLLVMToSEHAndCVRegMapping(llvm::MCRegisterInfo*) 1,209,090 ( 0.22%) ???:llvm::MDTuple::getImpl(llvm::LLVMContext&, llvm::ArrayRef, llvm::Metadata::StorageType, bool) 1,193,508 ( 0.22%) ???:llvm::PMDataManager::removeNotPreservedAnalysis(llvm::Pass*) 1,193,007 ( 0.22%) /usr/home/liquid/rust/worktree-benchmarking/library/core/src/slice/iter/macros.rs:, >::decode::{closure#0}>, ::imported_source_files::{closure#3}::{closure#0}> as core::iter::traits::iterator::Iterator>::fold::<(), core::iter::traits::iterator::Iterator::for_each::call as alloc::vec::spec_extend::SpecExtend, >::decode::{closure#0}>, ::imported_source_files::{closure#3}::{closure#0}>>>::spec_extend::{closure#0}>::{closure#0}> 1,188,340 ( 0.22%) /usr/home/liquid/rust/worktree-benchmarking/library/core/src/slice/iter/macros.rs:::new_imported_source_file 1,184,740 ( 0.22%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_span/src/lib.rs:::new_imported_source_file 1,171,560 ( 0.22%) ./string/../sysdeps/x86_64/multiarch/strcmp-avx2.S:__strncmp_avx2 1,115,807 ( 0.21%) ???:(anonymous namespace)::X86AsmBackend::applyFixup(llvm::MCAssembler const&, llvm::MCFixup const&, llvm::MCValue const&, llvm::MutableArrayRef, unsigned long, bool, llvm::MCSubtargetInfo const*) const 1,114,469 ( 0.21%) ???:llvm::MDNode::dropAllReferences() 1,101,322 ( 0.20%) ???:llvm::MCObjectStreamer::emitValueImpl(llvm::MCExpr const*, unsigned int, llvm::SMLoc) 1,087,007 ( 0.20%) ???:llvm::DIEValueList::addValue(llvm::BumpPtrAllocatorImpl&, llvm::DIEValue const&) 1,071,812 ( 0.20%) ???:multikeySort(llvm::MutableArrayRef*>, int) 1,038,682 ( 0.19%) /usr/home/liquid/.cargo/registry/src/github.com-1ecc6299db9ec823/hashbrown-0.12.0/src/raw/mod.rs:, (), core::hash::BuildHasherDefault>>::from_hash::>::{closure#0}> 1,011,634 ( 0.19%) /usr/home/liquid/.cargo/registry/src/github.com-1ecc6299db9ec823/rustc-hash-1.1.0/src/lib.rs:<&str as core::hash::Hash>::hash:: 1,008,704 ( 0.19%) ???:llvm::PMTopLevelManager::AUFoldingSetNode::Profile(llvm::FoldingSetNodeID&, llvm::AnalysisUsage const&) 1,004,196 ( 0.19%) ./string/../sysdeps/x86_64/multiarch/strlen-avx2.S:__strlen_avx2 965,426 ( 0.18%) /tmp/gcc-build/x86_64-unknown-linux-gnu/libstdc++-v3/libsupc++/../../../../gcc-5.5.0/libstdc++-v3/libsupc++/new_op.cc:operator new(unsigned long) 940,193 ( 0.17%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_metadata/src/rmeta/decoder.rs:>::decode 920,072 ( 0.17%) ???:(anonymous namespace)::VarLocBasedLDV::process(llvm::MachineInstr&, (anonymous namespace)::VarLocBasedLDV::OpenRangesSet&, (anonymous namespace)::VarLocBasedLDV::VarLocMap&, llvm::SmallVector<(anonymous namespace)::VarLocBasedLDV::TransferDebugPair, 4u>&) 912,405 ( 0.17%) ???:llvm::ScheduleDAGSDNodes::BuildSchedUnits() 894,854 ( 0.17%) ???:llvm::DIE::generateAbbrev() const 875,528 ( 0.16%) ./malloc/malloc.c:_int_realloc 871,801 ( 0.16%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_metadata/src/rmeta/decoder.rs:, >::decode::{closure#0}>, ::imported_source_files::{closure#3}::{closure#0}> as core::iter::traits::iterator::Iterator>::fold::<(), core::iter::traits::iterator::Iterator::for_each::call as alloc::vec::spec_extend::SpecExtend, >::decode::{closure#0}>, ::imported_source_files::{closure#3}::{closure#0}>>>::spec_extend::{closure#0}>::{closure#0}> 866,149 ( 0.16%) ???:llvm::hash_code llvm::hashing::detail::hash_combine_recursive_helper::combine(unsigned long, char*, char*, llvm::Metadata* const&, unsigned int const&, llvm::Metadata* const&, llvm::Metadata* const&, llvm::Metadata* const&, llvm::Metadata* const&) 862,315 ( 0.16%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_serialize/src/leb128.rs:::read_usize 862,019 ( 0.16%) ???:llvm::StringMapImpl::RehashTable(unsigned int) 855,138 ( 0.16%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_serialize/src/leb128.rs:::read_u32 825,863 ( 0.15%) ???:llvm::hash_code llvm::hashing::detail::hash_combine_recursive_helper::combine(unsigned long, char*, char*, llvm::Metadata* const&, llvm::Metadata* const&, llvm::Metadata* const&, llvm::Metadata* const&) 821,888 ( 0.15%) ???:llvm::LegacyLegalizerInfo::computeTables() 802,644 ( 0.15%) ???:llvm::TargetLoweringBase::getTypeConversion(llvm::LLVMContext&, llvm::EVT) const 792,387 ( 0.15%) /usr/home/liquid/.cargo/registry/src/github.com-1ecc6299db9ec823/hashbrown-0.12.0/src/raw/mod.rs:)>>::remove_entry::>::{closure#0}> 790,877 ( 0.15%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_span/src/lib.rs:, >::decode::{closure#0}>, ::imported_source_files::{closure#3}::{closure#0}> as core::iter::traits::iterator::Iterator>::fold::<(), core::iter::traits::iterator::Iterator::for_each::call as alloc::vec::spec_extend::SpecExtend, >::decode::{closure#0}>, ::imported_source_files::{closure#3}::{closure#0}>>>::spec_extend::{closure#0}>::{closure#0}> 787,531 ( 0.15%) ???:llvm::DwarfUnit::addDIEEntry(llvm::DIE&, llvm::dwarf::Attribute, llvm::DIEEntry) 787,193 ( 0.15%) ???:llvm::DIEInteger::SizeOf(llvm::AsmPrinter const*, llvm::dwarf::Form) const 784,232 ( 0.15%) ???:(anonymous namespace)::Verifier::visitCallBase(llvm::CallBase&) 783,674 ( 0.15%) ???:llvm::SmallSet >::insert(llvm::Register const&) 774,330 ( 0.14%) ???:llvm::DIE::computeOffsetsAndAbbrevs(llvm::AsmPrinter const*, llvm::DIEAbbrevSet&, unsigned int) 767,442 ( 0.14%) ???:llvm::TargetRegisterInfo::shouldRealignStack(llvm::MachineFunction const&) const 766,206 ( 0.14%) ???:bool llvm::DenseMapBase, llvm::detail::DenseSetPair >, llvm::DICompositeType*, llvm::detail::DenseSetEmpty, llvm::MDNodeInfo, llvm::detail::DenseSetPair >::LookupBucketFor >(llvm::MDNodeKeyImpl const&, llvm::detail::DenseSetPair const*&) const 764,187 ( 0.14%) ???:llvm::MCContext::getOrCreateSymbol(llvm::Twine const&) 764,050 ( 0.14%) ???:??? 755,286 ( 0.14%) ???:llvm::DenseMapBase, llvm::detail::DenseMapPair >, llvm::MCRegister, int, llvm::DenseMapInfo, llvm::detail::DenseMapPair >::moveFromOldBuckets(llvm::detail::DenseMapPair*, llvm::detail::DenseMapPair*) 752,790 ( 0.14%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_serialize/src/leb128.rs:::read_usize 746,514 ( 0.14%) ???:llvm::AsmPrinter::emitDwarfDIE(llvm::DIE const&) const 746,414 ( 0.14%) ./string/../sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S:memcpy@GLIBC_2.2.5 738,468 ( 0.14%) ???:llvm::MCELFStreamer::emitLabel(llvm::MCSymbol*, llvm::SMLoc) 726,876 ( 0.14%) ???:(anonymous namespace)::Verifier::verify(llvm::Function const&) [clone .llvm.4153962086227604281] 716,122 ( 0.13%) ???:llvm::DwarfUnit::getDIE(llvm::DINode const*) const 700,397 ( 0.13%) ???:llvm::FoldingSet::NodeEquals(llvm::FoldingSetBase const*, llvm::FoldingSetBase::Node*, llvm::FoldingSetNodeID const&, unsigned int, llvm::FoldingSetNodeID&) 695,866 ( 0.13%) ???:llvm::DwarfUnit::addString(llvm::DIE&, llvm::dwarf::Attribute, llvm::StringRef) 684,402 ( 0.13%) ???:llvm::MCStreamer::emitIntValue(unsigned long, unsigned int) 679,052 ( 0.13%) ???:(anonymous namespace)::X86AsmBackend::getFixupKindInfo(llvm::MCFixupKind) const 667,623 ( 0.12%) ???:llvm::hash_code llvm::hashing::detail::hash_combine_recursive_helper::combine(unsigned long, char*, char*, llvm::Metadata* const&, llvm::Metadata* const&) 663,274 ( 0.12%) /usr/home/liquid/.cargo/registry/src/github.com-1ecc6299db9ec823/snap-1.0.1/src/decompress.rs:::decompress 648,383 ( 0.12%) /usr/home/liquid/rust/worktree-benchmarking/library/std/src/sys/unix/alloc.rs:__rdl_alloc 647,614 ( 0.12%) ???:(anonymous namespace)::TwoAddressInstructionPass::runOnMachineFunction(llvm::MachineFunction&) 639,243 ( 0.12%) ???:(anonymous namespace)::VarLocBasedLDV::ExtendRanges(llvm::MachineFunction&, llvm::TargetPassConfig*) [clone .llvm.4451506318407214204] 634,820 ( 0.12%) ???:llvm::PMTopLevelManager::setLastUser(llvm::ArrayRef, llvm::Pass*) 634,431 ( 0.12%) ???:llvm::MetadataTracking::track(void*, llvm::Metadata&, llvm::PointerUnion) 633,689 ( 0.12%) ???:llvm::DomTreeBuilder::SemiNCAInfo >::CalculateFromScratch(llvm::DominatorTreeBase&, llvm::DomTreeBuilder::SemiNCAInfo >::BatchUpdateInfo*) 629,053 ( 0.12%) ./string/../sysdeps/x86_64/strcmp.S:strcmp 612,612 ( 0.11%) ???:llvm::hashing::detail::hash_combine_recursive_helper::hash_combine_recursive_helper() 610,181 ( 0.11%) /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs:rustc_codegen_ssa::debuginfo::type_names::push_item_name 600,622 ( 0.11%) ???:llvm::Twine::printOneChild(llvm::raw_ostream&, llvm::Twine::Child, llvm::Twine::NodeKind) const 596,548 ( 0.11%) ???:(anonymous namespace)::X86MCCodeEmitter::emitPrefixImpl(unsigned int&, llvm::MCInst const&, llvm::MCSubtargetInfo const&, llvm::raw_ostream&) const 578,335 ( 0.11%) /usr/home/liquid/.cargo/registry/src/github.com-1ecc6299db9ec823/hashbrown-0.12.0/src/rustc_entry.rs:>>::rustc_entry 575,780 ( 0.11%) ???:llvm::DAGTypeLegalizer::run() 571,856 ( 0.11%) ???:llvm::AnalysisUsage::pushUnique(llvm::SmallVectorImpl&, void const*) 561,918 ( 0.10%) /usr/home/liquid/rust/worktree-benchmarking/library/core/src/fmt/num.rs:core::fmt::num::::fmt 559,946 ( 0.10%) ???:llvm::InstrEmitter::EmitMachineNode(llvm::SDNode*, bool, bool, llvm::DenseMap, llvm::detail::DenseMapPair >&) 559,032 ( 0.10%) ???:(anonymous namespace)::SelectionDAGLegalize::LegalizeOp(llvm::SDNode*) [clone .llvm.8386621111310650999] 555,751 ( 0.10%) ???:llvm::SelectionDAG::MorphNodeTo(llvm::SDNode*, unsigned int, llvm::SDVTList, llvm::ArrayRef) 541,858 ( 0.10%) ./string/../sysdeps/x86_64/multiarch/memset-vec-unaligned-erms.S:__memset_avx2_unaligned_erms -------------------------------------------------------------------------------- -- Auto-annotated source: /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_metadata/src/rmeta/decoder.rs -------------------------------------------------------------------------------- Ir -- line 176 ---------------------------------------- . } . fn sess(self) -> Option<&'tcx Session> { . None . } . fn tcx(self) -> Option> { . None . } . 7,539 ( 0.00%) fn decoder(self, pos: usize) -> DecodeContext<'a, 'tcx> { 2,513 ( 0.00%) let tcx = self.tcx(); 267,396 ( 0.05%) DecodeContext { 28,966 ( 0.01%) opaque: opaque::Decoder::new(self.blob(), pos), 2,513 ( 0.00%) cdata: self.cdata(), . blob: self.blob(), 12,002 ( 0.00%) sess: self.sess().or(tcx.map(|tcx| tcx.sess)), . tcx, . last_source_file_index: 0, . lazy_state: LazyState::NoNode, . alloc_decoding_session: self . .cdata() 24,983 ( 0.00%) .map(|cdata| cdata.cdata.alloc_decoding_state.new_decoding_session()), . } 7,539 ( 0.00%) } . } . . impl<'a, 'tcx> Metadata<'a, 'tcx> for &'a MetadataBlob { . #[inline] . fn blob(self) -> &'a MetadataBlob { . self . } . } -- line 206 ---------------------------------------- -- line 255 ---------------------------------------- . } . #[inline] . fn tcx(self) -> Option> { . Some(self.1) . } . } . . impl<'a, 'tcx, T: Decodable>> Lazy { 40,935 ( 0.01%) fn decode>(self, metadata: M) -> T { 27,874 ( 0.01%) let mut dcx = metadata.decoder(self.position.get()); 76,666 ( 0.01%) dcx.lazy_state = LazyState::NodeStart(self.position); 23,614 ( 0.00%) T::decode(&mut dcx) 52,267 ( 0.01%) } . } . . impl<'a: 'x, 'tcx: 'x, 'x, T: Decodable>> Lazy<[T]> { . fn decode>( . self, . metadata: M, . ) -> impl ExactSizeIterator + Captures<'a> + Captures<'tcx> + 'x { 280 ( 0.00%) let mut dcx = metadata.decoder(self.position.get()); 80 ( 0.00%) dcx.lazy_state = LazyState::NodeStart(self.position); 36,427 ( 0.01%) (0..self.meta).map(move |_| T::decode(&mut dcx)) . } . } . . impl<'a, 'tcx> DecodeContext<'a, 'tcx> { . #[inline] . fn tcx(&self) -> TyCtxt<'tcx> { . debug_assert!(self.tcx.is_some(), "missing TyCtxt in DecodeContext"); . self.tcx.unwrap() -- line 285 ---------------------------------------- -- line 292 ---------------------------------------- . . #[inline] . pub fn cdata(&self) -> CrateMetadataRef<'a> { . debug_assert!(self.cdata.is_some(), "missing CrateMetadata in DecodeContext"); . self.cdata.unwrap() . } . . fn map_encoded_cnum_to_current(&self, cnum: CrateNum) -> CrateNum { 111,192 ( 0.02%) if cnum == LOCAL_CRATE { self.cdata().cnum } else { self.cdata().cnum_map[cnum] } . } . 41,665 ( 0.01%) fn read_lazy_with_meta(&mut self, meta: T::Meta) -> Lazy { . let distance = self.read_usize(); 40,257 ( 0.01%) let position = match self.lazy_state { . LazyState::NoNode => bug!("read_lazy_with_meta: outside of a metadata node"), 5,504 ( 0.00%) LazyState::NodeStart(start) => { . let start = start.get(); 11,008 ( 0.00%) assert!(distance <= start); . start - distance . } 14,247 ( 0.00%) LazyState::Previous(last_pos) => last_pos.get() + distance, . }; 20,506 ( 0.00%) self.lazy_state = LazyState::Previous(NonZeroUsize::new(position).unwrap()); . Lazy::from_position_and_meta(NonZeroUsize::new(position).unwrap(), meta) 41,665 ( 0.01%) } . . #[inline] . pub fn read_raw_bytes(&mut self, len: usize) -> &'a [u8] { . self.opaque.read_raw_bytes(len) . } . } . . impl<'a, 'tcx> TyDecoder<'tcx> for DecodeContext<'a, 'tcx> { -- line 324 ---------------------------------------- -- line 326 ---------------------------------------- . . #[inline] . fn tcx(&self) -> TyCtxt<'tcx> { . self.tcx.expect("missing TyCtxt in DecodeContext") . } . . #[inline] . fn peek_byte(&self) -> u8 { 92,345 ( 0.02%) self.opaque.data[self.opaque.position()] . } . . #[inline] . fn position(&self) -> usize { 1 ( 0.00%) self.opaque.position() . } . 86,135 ( 0.02%) fn cached_ty_for_shorthand(&mut self, shorthand: usize, or_insert_with: F) -> Ty<'tcx> . where . F: FnOnce(&mut Self) -> Ty<'tcx>, . { 12,305 ( 0.00%) let tcx = self.tcx(); . 12,305 ( 0.00%) let key = ty::CReaderCacheKey { cnum: Some(self.cdata().cnum), pos: shorthand }; . 36,132 ( 0.01%) if let Some(&ty) = tcx.ty_rcache.borrow().get(&key) { . return ty; . } . 3,272 ( 0.00%) let ty = or_insert_with(self); . tcx.ty_rcache.borrow_mut().insert(key, ty); . ty 110,745 ( 0.02%) } . 4 ( 0.00%) fn with_position(&mut self, pos: usize, f: F) -> R . where . F: FnOnce(&mut Self) -> R, . { . let new_opaque = opaque::Decoder::new(self.opaque.data, pos); . let old_opaque = mem::replace(&mut self.opaque, new_opaque); . let old_state = mem::replace(&mut self.lazy_state, LazyState::NoNode); 2 ( 0.00%) let r = f(self); 17,120 ( 0.00%) self.opaque = old_opaque; 3,424 ( 0.00%) self.lazy_state = old_state; . r 5 ( 0.00%) } . . fn decode_alloc_id(&mut self) -> rustc_middle::mir::interpret::AllocId { 7 ( 0.00%) if let Some(alloc_decoding_session) = self.alloc_decoding_session { 2 ( 0.00%) alloc_decoding_session.decode_alloc_id(self) . } else { . bug!("Attempting to decode interpret::AllocId without CrateMetadata") . } . } . } . . impl<'a, 'tcx> Decodable> for CrateNum { . fn decode(d: &mut DecodeContext<'a, 'tcx>) -> CrateNum { 63,676 ( 0.01%) let cnum = CrateNum::from_u32(d.read_u32()); . d.map_encoded_cnum_to_current(cnum) . } . } . . impl<'a, 'tcx> Decodable> for DefIndex { 232 ( 0.00%) fn decode(d: &mut DecodeContext<'a, 'tcx>) -> DefIndex { 111,467 ( 0.02%) DefIndex::from_u32(d.read_u32()) 464 ( 0.00%) } . } . . impl<'a, 'tcx> Decodable> for ExpnIndex { . fn decode(d: &mut DecodeContext<'a, 'tcx>) -> ExpnIndex { . ExpnIndex::from_u32(d.read_u32()) . } . } . . impl<'a, 'tcx> Decodable> for SyntaxContext { 68,896 ( 0.01%) fn decode(decoder: &mut DecodeContext<'a, 'tcx>) -> SyntaxContext { 17,224 ( 0.00%) let cdata = decoder.cdata(); 17,224 ( 0.00%) let sess = decoder.sess.unwrap(); 34,448 ( 0.01%) let cname = cdata.root.name; . rustc_span::hygiene::decode_syntax_context(decoder, &cdata.hygiene_context, |_, id| { . debug!("SpecializedDecoder: decoding {}", id); 276 ( 0.00%) cdata . .root . .syntax_contexts . .get(cdata, id) . .unwrap_or_else(|| panic!("Missing SyntaxContext {:?} for crate {:?}", id, cname)) . .decode((cdata, sess)) . }) 86,120 ( 0.02%) } . } . . impl<'a, 'tcx> Decodable> for ExpnId { 3,724 ( 0.00%) fn decode(decoder: &mut DecodeContext<'a, 'tcx>) -> ExpnId { 532 ( 0.00%) let local_cdata = decoder.cdata(); 532 ( 0.00%) let sess = decoder.sess.unwrap(); . . let cnum = CrateNum::decode(decoder); . let index = u32::decode(decoder); . . let expn_id = rustc_span::hygiene::decode_expn_id(cnum, index, |expn_id| { . let ExpnId { krate: cnum, local_id: index } = expn_id; . // Lookup local `ExpnData`s in our own crate data. Foreign `ExpnData`s . // are stored in the owning crate, to avoid duplication. . debug_assert_ne!(cnum, LOCAL_CRATE); 92 ( 0.00%) let crate_data = if cnum == local_cdata.cnum { . local_cdata . } else { . local_cdata.cstore.get_crate_data(cnum) . }; 460 ( 0.00%) let expn_data = crate_data . .root . .expn_data . .get(crate_data, index) . .unwrap() . .decode((crate_data, sess)); 460 ( 0.00%) let expn_hash = crate_data . .root . .expn_hashes . .get(crate_data, index) . .unwrap() . .decode((crate_data, sess)); 920 ( 0.00%) (expn_data, expn_hash) . }); . expn_id 4,256 ( 0.00%) } . } . . impl<'a, 'tcx> Decodable> for Span { 136,136 ( 0.03%) fn decode(decoder: &mut DecodeContext<'a, 'tcx>) -> Span { 17,017 ( 0.00%) let ctxt = SyntaxContext::decode(decoder); . let tag = u8::decode(decoder); . 34,034 ( 0.01%) if tag == TAG_PARTIAL_SPAN { . return DUMMY_SP.with_ctxt(ctxt); . } . . debug_assert!(tag == TAG_VALID_SPAN_LOCAL || tag == TAG_VALID_SPAN_FOREIGN); . . let lo = BytePos::decode(decoder); . let len = BytePos::decode(decoder); . let hi = lo + len; . 50,976 ( 0.01%) let Some(sess) = decoder.sess else { . bug!("Cannot decode Span without Session.") . }; . . // There are two possibilities here: . // 1. This is a 'local span', which is located inside a `SourceFile` . // that came from this crate. In this case, we use the source map data . // encoded in this crate. This branch should be taken nearly all of the time. . // 2. This is a 'foreign span', which is located inside a `SourceFile` -- line 476 ---------------------------------------- -- line 492 ---------------------------------------- . // a transitive dependency. . // . // When we encode a foreign span, we adjust its 'lo' and 'high' values . // to be based on the *foreign* crate (e.g. crate C), not the crate . // we are writing metadata for (e.g. crate B). This allows us to . // treat the 'local' and 'foreign' cases almost identically during deserialization: . // we can call `imported_source_files` for the proper crate, and binary search . // through the returned slice using our span. 37,171 ( 0.01%) let imported_source_files = if tag == TAG_VALID_SPAN_LOCAL { . decoder.cdata().imported_source_files(sess) . } else { . // When we encode a proc-macro crate, all `Span`s should be encoded . // with `TAG_VALID_SPAN_LOCAL` 109 ( 0.00%) if decoder.cdata().root.is_proc_macro_crate() { . // Decode `CrateNum` as u32 - using `CrateNum::decode` will ICE . // since we don't have `cnum_map` populated. . let cnum = u32::decode(decoder); . panic!( . "Decoding of crate {:?} tried to access proc-macro dep {:?}", . decoder.cdata().root.name, . cnum . ); -- line 513 ---------------------------------------- -- line 518 ---------------------------------------- . "SpecializedDecoder::specialized_decode: loading source files from cnum {:?}", . cnum . ); . . // Decoding 'foreign' spans should be rare enough that it's . // not worth it to maintain a per-CrateNum cache for `last_source_file_index`. . // We just set it to 0, to ensure that we don't try to access something out . // of bounds for our initial 'guess' 218 ( 0.00%) decoder.last_source_file_index = 0; . 109 ( 0.00%) let foreign_data = decoder.cdata().cstore.get_crate_data(cnum); . foreign_data.imported_source_files(sess) . }; . . let source_file = { . // Optimize for the case that most spans within a translated item . // originate from the same source_file. 50,976 ( 0.01%) let last_source_file = &imported_source_files[decoder.last_source_file_index]; . 67,841 ( 0.01%) if lo >= last_source_file.original_start_pos && lo <= last_source_file.original_end_pos . { . last_source_file . } else { . let index = imported_source_files . .binary_search_by_key(&lo, |source_file| source_file.original_start_pos) 6,372 ( 0.00%) .unwrap_or_else(|index| index - 1); . . // Don't try to cache the index for foreign spans, . // as this would require a map from CrateNums to indices 3,187 ( 0.00%) if tag == TAG_VALID_SPAN_LOCAL { 3,084 ( 0.00%) decoder.last_source_file_index = index; . } 6,374 ( 0.00%) &imported_source_files[index] . } . }; . . // Make sure our binary search above is correct. . debug_assert!( . lo >= source_file.original_start_pos && lo <= source_file.original_end_pos, . "Bad binary search: lo={:?} source_file.original_start_pos={:?} source_file.original_end_pos={:?}", . lo, -- line 558 ---------------------------------------- -- line 565 ---------------------------------------- . hi >= source_file.original_start_pos && hi <= source_file.original_end_pos, . "Bad binary search: hi={:?} source_file.original_start_pos={:?} source_file.original_end_pos={:?}", . hi, . source_file.original_start_pos, . source_file.original_end_pos . ); . . let lo = 67,968 ( 0.01%) (lo + source_file.translated_source_file.start_pos) - source_file.original_start_pos; . let hi = . (hi + source_file.translated_source_file.start_pos) - source_file.original_start_pos; . . // Do not try to decode parent for foreign spans. . Span::new(lo, hi, ctxt, None) 153,153 ( 0.03%) } . } . . impl<'a, 'tcx> Decodable> for &'tcx [thir::abstract_const::Node<'tcx>] { . fn decode(d: &mut DecodeContext<'a, 'tcx>) -> Self { . ty::codec::RefDecodable::decode(d) . } . } . -- line 587 ---------------------------------------- -- line 590 ---------------------------------------- . ty::codec::RefDecodable::decode(d) . } . } . . impl<'a, 'tcx, T: Decodable>> Decodable> . for Lazy . { . fn decode(decoder: &mut DecodeContext<'a, 'tcx>) -> Self { 9,975 ( 0.00%) decoder.read_lazy_with_meta(()) . } . } . . impl<'a, 'tcx, T: Decodable>> Decodable> . for Lazy<[T]> . { . fn decode(decoder: &mut DecodeContext<'a, 'tcx>) -> Self { . let len = decoder.read_usize(); 15,512 ( 0.00%) if len == 0 { Lazy::empty() } else { decoder.read_lazy_with_meta(len) } . } . } . . impl<'a, 'tcx, I: Idx, T: Decodable>> Decodable> . for Lazy> . where . Option: FixedSizeEncoding, . { . fn decode(decoder: &mut DecodeContext<'a, 'tcx>) -> Self { . let len = decoder.read_usize(); 17,576 ( 0.00%) decoder.read_lazy_with_meta(len) . } . } . . implement_ty_decoder!(DecodeContext<'a, 'tcx>); . . impl<'tcx> MetadataBlob { . crate fn new(metadata_ref: MetadataRef) -> MetadataBlob { . MetadataBlob(Lrc::new(metadata_ref)) -- line 626 ---------------------------------------- -- line 630 ---------------------------------------- . self.blob().starts_with(METADATA_HEADER) . } . . crate fn get_rustc_version(&self) -> String { . Lazy::::from_position(NonZeroUsize::new(METADATA_HEADER.len() + 4).unwrap()) . .decode(self) . } . 312 ( 0.00%) crate fn get_root(&self) -> CrateRoot<'tcx> { 104 ( 0.00%) let slice = &self.blob()[..]; . let offset = METADATA_HEADER.len(); 520 ( 0.00%) let pos = (((slice[offset + 0] as u32) << 24) 208 ( 0.00%) | ((slice[offset + 1] as u32) << 16) 416 ( 0.00%) | ((slice[offset + 2] as u32) << 8) 312 ( 0.00%) | ((slice[offset + 3] as u32) << 0)) as usize; . Lazy::>::from_position(NonZeroUsize::new(pos).unwrap()).decode(self) 520 ( 0.00%) } . . crate fn list_crate_metadata(&self, out: &mut dyn io::Write) -> io::Result<()> { . let root = self.get_root(); . writeln!(out, "Crate info:")?; . writeln!(out, "name {}{}", root.name, root.extra_filename)?; . writeln!(out, "hash {} stable_crate_id {:?}", root.hash, root.stable_crate_id)?; . writeln!(out, "proc_macro {:?}", root.proc_macro_data.is_some())?; . writeln!(out, "=External Dependencies=")?; -- line 654 ---------------------------------------- -- line 666 ---------------------------------------- . } . write!(out, "\n")?; . Ok(()) . } . } . . impl CrateRoot<'_> { . crate fn is_proc_macro_crate(&self) -> bool { 67 ( 0.00%) self.proc_macro_data.is_some() . } . . crate fn name(&self) -> Symbol { 14 ( 0.00%) self.name . } . . crate fn hash(&self) -> Svh { 34 ( 0.00%) self.hash . } . . crate fn stable_crate_id(&self) -> StableCrateId { 71 ( 0.00%) self.stable_crate_id . } . . crate fn triple(&self) -> &TargetTriple { . &self.triple . } . . crate fn decode_crate_deps<'a>( . &self, . metadata: &'a MetadataBlob, . ) -> impl ExactSizeIterator + Captures<'a> { 66 ( 0.00%) self.crate_deps.decode(metadata) . } . } . . impl<'a, 'tcx> CrateMetadataRef<'a> { 343 ( 0.00%) fn raw_proc_macro(self, id: DefIndex) -> &'a ProcMacro { . // DefIndex's in root.proc_macro_data have a one-to-one correspondence . // with items in 'raw_proc_macros'. 98 ( 0.00%) let pos = self . .root . .proc_macro_data . .as_ref() . .unwrap() . .macros . .decode(self) . .position(|i| i == id) . .unwrap(); 196 ( 0.00%) &self.raw_proc_macros.unwrap()[pos] 441 ( 0.00%) } . 24,794 ( 0.00%) fn opt_item_ident(self, item_index: DefIndex, sess: &Session) -> Option { 18,492 ( 0.00%) let name = self.def_key(item_index).disambiguated_data.data.get_opt_name()?; 10,941 ( 0.00%) let span = match self.root.tables.ident_span.get(self, item_index) { . Some(lazy_span) => lazy_span.decode((self, sess)), . None => { . // FIXME: this weird case of a name with no span is specific to `extern crate` . // items, which are supposed to be treated like `use` items and only be encoded . // to metadata as `Export`s, return `None` because that's what all the callers . // expect in this case. 189 ( 0.00%) assert_eq!(self.def_kind(item_index), DefKind::ExternCrate); . return None; . } . }; . Some(Ident::new(name, span)) 31,740 ( 0.01%) } . 213 ( 0.00%) fn item_ident(self, item_index: DefIndex, sess: &Session) -> Ident { 3,937 ( 0.00%) self.opt_item_ident(item_index, sess).expect("no encoded ident for item") 426 ( 0.00%) } . . fn maybe_kind(self, item_id: DefIndex) -> Option { 10,170 ( 0.00%) self.root.tables.kind.get(self, item_id).map(|k| k.decode(self)) . } . 40,680 ( 0.01%) fn kind(self, item_id: DefIndex) -> EntryKind { . self.maybe_kind(item_id).unwrap_or_else(|| { . bug!( . "CrateMetadata::kind({:?}): id not found, in crate {:?} with number {}", . item_id, . self.root.name, . self.cnum, . ) . }) 30,510 ( 0.01%) } . 6,993 ( 0.00%) fn def_kind(self, item_id: DefIndex) -> DefKind { 6,221 ( 0.00%) self.root.tables.def_kind.get(self, item_id).map(|k| k.decode(self)).unwrap_or_else(|| { . bug!( . "CrateMetadata::def_kind({:?}): id not found, in crate {:?} with number {}", . item_id, . self.root.name, . self.cnum, . ) . }) 3,996 ( 0.00%) } . 1,917 ( 0.00%) fn get_span(self, index: DefIndex, sess: &Session) -> Span { 4,649 ( 0.00%) self.root . .tables . .span . .get(self, index) . .unwrap_or_else(|| panic!("Missing span for {:?}", index)) . .decode((self, sess)) 1,065 ( 0.00%) } . . fn load_proc_macro(self, id: DefIndex, sess: &Session) -> SyntaxExtension { 16 ( 0.00%) let (name, kind, helper_attrs) = match *self.raw_proc_macro(id) { 10 ( 0.00%) ProcMacro::CustomDerive { trait_name, attributes, client } => { . let helper_attrs = . attributes.iter().cloned().map(Symbol::intern).collect::>(); . ( . trait_name, . SyntaxExtensionKind::Derive(Box::new(ProcMacroDerive { client })), 6 ( 0.00%) helper_attrs, . ) . } . ProcMacro::Attr { name, client } => { . (name, SyntaxExtensionKind::Attr(Box::new(AttrProcMacro { client })), Vec::new()) . } . ProcMacro::Bang { name, client } => { . (name, SyntaxExtensionKind::Bang(Box::new(BangProcMacro { client })), Vec::new()) . } . }; . 5 ( 0.00%) let attrs: Vec<_> = self.get_item_attrs(id, sess).collect(); 12 ( 0.00%) SyntaxExtension::new( . sess, 5 ( 0.00%) kind, . self.get_span(id, sess), 4 ( 0.00%) helper_attrs, 3 ( 0.00%) self.root.edition, 1 ( 0.00%) Symbol::intern(name), . &attrs, . ) . } . 429 ( 0.00%) fn get_trait_def(self, item_id: DefIndex, sess: &Session) -> ty::TraitDef { 132 ( 0.00%) match self.kind(item_id) { 33 ( 0.00%) EntryKind::Trait(data) => { 198 ( 0.00%) let data = data.decode((self, sess)); 528 ( 0.00%) ty::TraitDef::new( . self.local_def_id(item_id), 66 ( 0.00%) data.unsafety, 66 ( 0.00%) data.paren_sugar, 66 ( 0.00%) data.has_auto_impl, 66 ( 0.00%) data.is_marker, 33 ( 0.00%) data.skip_array_during_method_dispatch, 33 ( 0.00%) data.specialization_kind, 132 ( 0.00%) self.def_path_hash(item_id), 33 ( 0.00%) data.must_implement_one_of, . ) . } . EntryKind::TraitAlias => ty::TraitDef::new( . self.local_def_id(item_id), . hir::Unsafety::Normal, . false, . false, . false, . false, . ty::trait_def::TraitSpecializationKind::None, . self.def_path_hash(item_id), . None, . ), . _ => bug!("def-index does not refer to trait or trait alias"), . } 297 ( 0.00%) } . 1,233 ( 0.00%) fn get_variant( . self, . kind: &EntryKind, . index: DefIndex, . parent_did: DefId, . sess: &Session, . ) -> ty::VariantDef { 548 ( 0.00%) let data = match kind { . EntryKind::Variant(data) | EntryKind::Struct(data, _) | EntryKind::Union(data, _) => { 685 ( 0.00%) data.decode(self) . } . _ => bug!(), . }; . 470 ( 0.00%) let adt_kind = match kind { . EntryKind::Variant(_) => ty::AdtKind::Enum, . EntryKind::Struct(..) => ty::AdtKind::Struct, . EntryKind::Union(..) => ty::AdtKind::Union, . _ => bug!(), . }; . . let variant_did = . if adt_kind == ty::AdtKind::Enum { Some(self.local_def_id(index)) } else { None }; 274 ( 0.00%) let ctor_did = data.ctor.map(|index| self.local_def_id(index)); . 3,014 ( 0.00%) ty::VariantDef::new( . self.item_ident(index, sess).name, . variant_did, . ctor_did, 548 ( 0.00%) data.discr, 822 ( 0.00%) self.root . .tables . .children . .get(self, index) . .unwrap_or_else(Lazy::empty) . .decode(self) . .map(|index| ty::FieldDef { 202 ( 0.00%) did: self.local_def_id(index), 404 ( 0.00%) name: self.item_ident(index, sess).name, 404 ( 0.00%) vis: self.get_visibility(index), . }) . .collect(), . data.ctor_kind, . adt_kind, . parent_did, . false, 137 ( 0.00%) data.is_non_exhaustive, . ) 1,233 ( 0.00%) } . 1,650 ( 0.00%) fn get_adt_def(self, item_id: DefIndex, tcx: TyCtxt<'tcx>) -> &'tcx ty::AdtDef { 440 ( 0.00%) let kind = self.kind(item_id); 220 ( 0.00%) let did = self.local_def_id(item_id); . 526 ( 0.00%) let (adt_kind, repr) = match kind { . EntryKind::Enum(repr) => (ty::AdtKind::Enum, repr), . EntryKind::Struct(_, repr) => (ty::AdtKind::Struct, repr), . EntryKind::Union(_, repr) => (ty::AdtKind::Union, repr), . _ => bug!("get_adt_def called on a non-ADT {:?}", did), . }; . . let variants = if let ty::AdtKind::Enum = adt_kind { 65 ( 0.00%) self.root . .tables . .children . .get(self, item_id) . .unwrap_or_else(Lazy::empty) . .decode(self) 680 ( 0.00%) .map(|index| self.get_variant(&self.kind(index), index, did, tcx.sess)) . .collect() . } else { 776 ( 0.00%) std::iter::once(self.get_variant(&kind, item_id, did, tcx.sess)).collect() . }; . 1,605 ( 0.00%) tcx.alloc_adt_def(did, adt_kind, variants, repr) 770 ( 0.00%) } . . fn get_explicit_predicates( . self, . item_id: DefIndex, . tcx: TyCtxt<'tcx>, . ) -> ty::GenericPredicates<'tcx> { 1,880 ( 0.00%) self.root.tables.explicit_predicates.get(self, item_id).unwrap().decode((self, tcx)) . } . . fn get_inferred_outlives( . self, . item_id: DefIndex, . tcx: TyCtxt<'tcx>, . ) -> &'tcx [(ty::Predicate<'tcx>, Span)] { 1,880 ( 0.00%) self.root . .tables . .inferred_outlives . .get(self, item_id) 16 ( 0.00%) .map(|predicates| tcx.arena.alloc_from_iter(predicates.decode((self, tcx)))) . .unwrap_or_default() . } . . fn get_super_predicates( . self, . item_id: DefIndex, . tcx: TyCtxt<'tcx>, . ) -> ty::GenericPredicates<'tcx> { 100 ( 0.00%) self.root.tables.super_predicates.get(self, item_id).unwrap().decode((self, tcx)) . } . . fn get_explicit_item_bounds( . self, . item_id: DefIndex, . tcx: TyCtxt<'tcx>, . ) -> &'tcx [(ty::Predicate<'tcx>, Span)] { 15 ( 0.00%) self.root . .tables . .explicit_item_bounds . .get(self, item_id) 8 ( 0.00%) .map(|bounds| tcx.arena.alloc_from_iter(bounds.decode((self, tcx)))) . .unwrap_or_default() . } . . fn get_generics(self, item_id: DefIndex, sess: &Session) -> ty::Generics { 1,933 ( 0.00%) self.root.tables.generics.get(self, item_id).unwrap().decode((self, sess)) . } . . fn get_type(self, id: DefIndex, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { 9,260 ( 0.00%) self.root . .tables . .ty . .get(self, id) . .unwrap_or_else(|| panic!("Not a type: {:?}", id)) . .decode((self, tcx)) . } . . fn get_stability(self, id: DefIndex) -> Option { 305 ( 0.00%) self.root.tables.stability.get(self, id).map(|stab| stab.decode(self)) . } . . fn get_const_stability(self, id: DefIndex) -> Option { 10 ( 0.00%) self.root.tables.const_stability.get(self, id).map(|stab| stab.decode(self)) . } . . fn get_deprecation(self, id: DefIndex) -> Option { 370 ( 0.00%) self.root.tables.deprecation.get(self, id).map(|depr| depr.decode(self)) . } . 114 ( 0.00%) fn get_visibility(self, id: DefIndex) -> ty::Visibility { 4,531 ( 0.00%) self.root.tables.visibility.get(self, id).unwrap().decode(self) 76 ( 0.00%) } . . fn get_impl_data(self, id: DefIndex) -> ImplData { 21,240 ( 0.00%) match self.kind(id) { 17,700 ( 0.00%) EntryKind::Impl(data) => data.decode(self), . _ => bug!(), . } . } . . fn get_parent_impl(self, id: DefIndex) -> Option { 10,302 ( 0.00%) self.get_impl_data(id).parent_impl . } . . fn get_impl_polarity(self, id: DefIndex) -> ty::ImplPolarity { 73 ( 0.00%) self.get_impl_data(id).polarity . } . . fn get_impl_defaultness(self, id: DefIndex) -> hir::Defaultness { 14 ( 0.00%) self.get_impl_data(id).defaultness . } . . fn get_impl_constness(self, id: DefIndex) -> hir::Constness { 19 ( 0.00%) self.get_impl_data(id).constness . } . . fn get_trait_item_def_id(self, id: DefIndex) -> Option { 2,225 ( 0.00%) self.root.tables.trait_item_def_id.get(self, id).map(|d| d.decode(self)) . } . . fn get_coerce_unsized_info(self, id: DefIndex) -> Option { . self.get_impl_data(id).coerce_unsized_info . } . . fn get_impl_trait(self, id: DefIndex, tcx: TyCtxt<'tcx>) -> Option> { 42,001 ( 0.01%) self.root.tables.impl_trait_ref.get(self, id).map(|tr| tr.decode((self, tcx))) . } . . fn get_expn_that_defined(self, id: DefIndex, sess: &Session) -> ExpnId { 1,855 ( 0.00%) self.root.tables.expn_that_defined.get(self, id).unwrap().decode((self, sess)) . } . . fn get_const_param_default( . self, . tcx: TyCtxt<'tcx>, . id: DefIndex, . ) -> rustc_middle::ty::Const<'tcx> { . self.root.tables.const_defaults.get(self, id).unwrap().decode((self, tcx)) -- line 1026 ---------------------------------------- -- line 1028 ---------------------------------------- . . /// Iterates over all the stability attributes in the given crate. . fn get_lib_features(self, tcx: TyCtxt<'tcx>) -> &'tcx [(Symbol, Option)] { . tcx.arena.alloc_from_iter(self.root.lib_features.decode(self)) . } . . /// Iterates over the language items in the given crate. . fn get_lang_items(self, tcx: TyCtxt<'tcx>) -> &'tcx [(DefId, usize)] { 102 ( 0.00%) tcx.arena.alloc_from_iter( 68 ( 0.00%) self.root . .lang_items . .decode(self) 564 ( 0.00%) .map(|(def_index, index)| (self.local_def_id(def_index), index)), . ) . } . . /// Iterates over the diagnostic items in the given crate. . fn get_diagnostic_items(self) -> DiagnosticItems { . let mut id_to_name = FxHashMap::default(); 68 ( 0.00%) let name_to_id = self . .root . .diagnostic_items . .decode(self) . .map(|(name, def_index)| { 130 ( 0.00%) let id = self.local_def_id(def_index); 130 ( 0.00%) id_to_name.insert(id, name); . (name, id) . }) . .collect(); 306 ( 0.00%) DiagnosticItems { id_to_name, name_to_id } . } . . /// Iterates over all named children of the given module, . /// including both proper items and reexports. . /// Module here is understood in name resolution sense - it can be a `mod` item, . /// or a crate root, or an enum, or a trait. . fn for_each_module_child( . self, . id: DefIndex, . mut callback: impl FnMut(ModChild), . sess: &Session, . ) { 224 ( 0.00%) if let Some(data) = &self.root.proc_macro_data { . // If we are loading as a proc macro, we want to return . // the view of this crate as a proc macro crate. 1 ( 0.00%) if id == CRATE_DEF_INDEX { 15 ( 0.00%) for def_index in data.macros.decode(self) { 144 ( 0.00%) let raw_macro = self.raw_proc_macro(def_index); . let res = Res::Def( . DefKind::Macro(macro_kind(raw_macro)), . self.local_def_id(def_index), . ); . let ident = self.item_ident(def_index, sess); . callback(ModChild { . ident, . res, -- line 1083 ---------------------------------------- -- line 1085 ---------------------------------------- . span: ident.span, . }); . } . } . return; . } . . // Iterate over all children. 440 ( 0.00%) if let Some(children) = self.root.tables.children.get(self, id) { 880 ( 0.00%) for child_index in children.decode((self, sess)) { 7,500 ( 0.00%) if let Some(ident) = self.opt_item_ident(child_index, sess) { 1,476 ( 0.00%) let kind = self.def_kind(child_index); 984 ( 0.00%) if matches!(kind, DefKind::Macro(..)) { . // FIXME: Macros are currently encoded twice, once as items and once as . // reexports. We ignore the items here and only use the reexports. . continue; . } . let def_id = self.local_def_id(child_index); . let res = Res::Def(kind, def_id); . let vis = self.get_visibility(child_index); . let span = self.get_span(child_index, sess); . . callback(ModChild { ident, res, vis, span }); . . // For non-re-export structs and variants add their constructors to children. . // Re-export lists automatically contain constructors when necessary. 1,922 ( 0.00%) match kind { . DefKind::Struct => { 45 ( 0.00%) if let Some((ctor_def_id, ctor_kind)) = . self.get_ctor_def_id_and_kind(child_index) . { . let ctor_res = . Res::Def(DefKind::Ctor(CtorOf::Struct, ctor_kind), ctor_def_id); . let vis = self.get_visibility(ctor_def_id.index); . callback(ModChild { ident, res: ctor_res, vis, span }); . } . } . DefKind::Variant => { . // Braced variants, unlike structs, generate unusable names in . // value namespace, they are reserved for possible future use. . // It's ok to use the variant's id as a ctor id since an . // error will be reported on any use of such resolution anyway. 21 ( 0.00%) let (ctor_def_id, ctor_kind) = self . .get_ctor_def_id_and_kind(child_index) . .unwrap_or((def_id, CtorKind::Fictive)); . let ctor_res = . Res::Def(DefKind::Ctor(CtorOf::Variant, ctor_kind), ctor_def_id); . let mut vis = self.get_visibility(ctor_def_id.index); 7 ( 0.00%) if ctor_def_id == def_id && vis.is_public() { . // For non-exhaustive variants lower the constructor visibility to . // within the crate. We only need this for fictive constructors, . // for other constructors correct visibilities . // were already encoded in metadata. . let mut attrs = self.get_item_attrs(def_id.index, sess); . if attrs.any(|item| item.has_name(sym::non_exhaustive)) { . let crate_def_id = self.local_def_id(CRATE_DEF_INDEX); . vis = ty::Visibility::Restricted(crate_def_id); -- line 1141 ---------------------------------------- -- line 1144 ---------------------------------------- . callback(ModChild { ident, res: ctor_res, vis, span }); . } . _ => {} . } . } . } . } . 553 ( 0.00%) match self.kind(id) { 44 ( 0.00%) EntryKind::Mod(exports) => { 1,388 ( 0.00%) for exp in exports.decode((self, sess)) { . callback(exp); . } . } . EntryKind::Enum(..) | EntryKind::Trait(..) => {} . _ => bug!("`for_each_module_child` is called on a non-module: {:?}", self.def_kind(id)), . } . } . . fn is_ctfe_mir_available(self, id: DefIndex) -> bool { 152 ( 0.00%) self.root.tables.mir_for_ctfe.get(self, id).is_some() . } . . fn is_item_mir_available(self, id: DefIndex) -> bool { 244 ( 0.00%) self.root.tables.mir.get(self, id).is_some() . } . . fn module_expansion(self, id: DefIndex, sess: &Session) -> ExpnId { 2,422 ( 0.00%) match self.kind(id) { . EntryKind::Mod(_) | EntryKind::Enum(_) | EntryKind::Trait(_) => { . self.get_expn_that_defined(id, sess) . } . _ => panic!("Expected module, found {:?}", self.local_def_id(id)), . } . } . . fn get_optimized_mir(self, tcx: TyCtxt<'tcx>, id: DefIndex) -> Body<'tcx> { 300 ( 0.00%) self.root . .tables . .mir . .get(self, id) . .unwrap_or_else(|| { . bug!("get_optimized_mir: missing MIR for `{:?}`", self.local_def_id(id)) . }) . .decode((self, tcx)) . } . . fn get_mir_for_ctfe(self, tcx: TyCtxt<'tcx>, id: DefIndex) -> Body<'tcx> { 190 ( 0.00%) self.root . .tables . .mir_for_ctfe . .get(self, id) . .unwrap_or_else(|| { . bug!("get_mir_for_ctfe: missing MIR for `{:?}`", self.local_def_id(id)) . }) . .decode((self, tcx)) . } -- line 1200 ---------------------------------------- -- line 1216 ---------------------------------------- . .tables . .unused_generic_params . .get(self, id) . .map(|params| params.decode(self)) . .unwrap_or_default() . } . . fn get_promoted_mir(self, tcx: TyCtxt<'tcx>, id: DefIndex) -> IndexVec> { 5 ( 0.00%) self.root . .tables . .promoted_mir . .get(self, id) . .unwrap_or_else(|| { . bug!("get_promoted_mir: missing MIR for `{:?}`", self.local_def_id(id)) . }) . .decode((self, tcx)) . } . . fn mir_const_qualif(self, id: DefIndex) -> mir::ConstQualifs { 23 ( 0.00%) match self.kind(id) { . EntryKind::AnonConst(qualif, _) . | EntryKind::Const(qualif, _) . | EntryKind::AssocConst( . AssocContainer::ImplDefault . | AssocContainer::ImplFinal . | AssocContainer::TraitWithDefault, 2 ( 0.00%) qualif, . _, . ) => qualif, . _ => bug!("mir_const_qualif: unexpected kind"), . } . } . . fn get_fn_has_self_parameter(self, id: DefIndex) -> bool { 575 ( 0.00%) match self.kind(id) { 460 ( 0.00%) EntryKind::AssocFn(data) => data.decode(self).has_self, . _ => false, . } . } . . fn get_associated_item_def_ids(self, tcx: TyCtxt<'tcx>, id: DefIndex) -> &'tcx [DefId] { 637 ( 0.00%) if let Some(children) = self.root.tables.children.get(self, id) { 273 ( 0.00%) tcx.arena.alloc_from_iter( 91 ( 0.00%) children.decode((self, tcx.sess)).map(|child_index| self.local_def_id(child_index)), . ) . } else { . &[] . } . } . 4,620 ( 0.00%) fn get_associated_item(self, id: DefIndex, sess: &Session) -> ty::AssocItem { 2,695 ( 0.00%) let def_key = self.def_key(id); . let parent = self.local_def_id(def_key.parent.unwrap()); . let ident = self.item_ident(id, sess); . 2,747 ( 0.00%) let (kind, container, has_self) = match self.kind(id) { 8 ( 0.00%) EntryKind::AssocConst(container, _, _) => (ty::AssocKind::Const, container, false), 361 ( 0.00%) EntryKind::AssocFn(data) => { . let data = data.decode(self); 2,527 ( 0.00%) (ty::AssocKind::Fn, data.container, data.has_self) . } 44 ( 0.00%) EntryKind::AssocType(container) => (ty::AssocKind::Type, container, false), . _ => bug!("cannot get associated-item of `{:?}`", def_key), . }; . 6,930 ( 0.00%) ty::AssocItem { . name: ident.name, . kind, . vis: self.get_visibility(id), . defaultness: container.defaultness(), . def_id: self.local_def_id(id), . trait_item_def_id: self.get_trait_item_def_id(id), . container: container.with_def_id(parent), . fn_has_self_parameter: has_self, . } 3,465 ( 0.00%) } . . fn get_item_variances(self, id: DefIndex) -> impl Iterator + 'a { 160 ( 0.00%) self.root.tables.variances.get(self, id).unwrap_or_else(Lazy::empty).decode(self) . } . . fn get_ctor_def_id_and_kind(self, node_id: DefIndex) -> Option<(DefId, CtorKind)> { 1,378 ( 0.00%) match self.kind(node_id) { . EntryKind::Struct(data, _) | EntryKind::Variant(data) => { 595 ( 0.00%) let vdata = data.decode(self); 345 ( 0.00%) vdata.ctor.map(|index| (self.local_def_id(index), vdata.ctor_kind)) . } . _ => None, . } 687 ( 0.00%) } . 360 ( 0.00%) fn get_item_attrs( . self, . id: DefIndex, . sess: &'a Session, . ) -> impl Iterator + 'a { 1,542 ( 0.00%) self.root . .tables . .attributes . .get(self, id) . .unwrap_or_else(|| { . // Structure and variant constructors don't have any attributes encoded for them, . // but we assume that someone passing a constructor ID actually wants to look at . // the attributes on the corresponding struct or variant. . let def_key = self.def_key(id); -- line 1320 ---------------------------------------- -- line 1322 ---------------------------------------- . let parent_id = def_key.parent.expect("no parent for a constructor"); . self.root . .tables . .attributes . .get(self, parent_id) . .expect("no encoded attributes for a structure or variant") . }) . .decode((self, sess)) 270 ( 0.00%) } . . fn get_struct_field_names( . self, . id: DefIndex, . sess: &'a Session, . ) -> impl Iterator> + 'a { 645 ( 0.00%) self.root . .tables . .children . .get(self, id) . .unwrap_or_else(Lazy::empty) . .decode(self) 2,130 ( 0.00%) .map(move |index| respan(self.get_span(index, sess), self.item_ident(index, sess).name)) . } . . fn get_struct_field_visibilities(self, id: DefIndex) -> impl Iterator + 'a { 125 ( 0.00%) self.root . .tables . .children . .get(self, id) . .unwrap_or_else(Lazy::empty) . .decode(self) 38 ( 0.00%) .map(move |field_index| self.get_visibility(field_index)) . } . . fn get_inherent_implementations_for_type( . self, . tcx: TyCtxt<'tcx>, . id: DefIndex, . ) -> &'tcx [DefId] { 64 ( 0.00%) tcx.arena.alloc_from_iter( 80 ( 0.00%) self.root . .tables . .inherent_impls . .get(self, id) . .unwrap_or_else(Lazy::empty) . .decode(self) 384 ( 0.00%) .map(|index| self.local_def_id(index)), . ) . } . . fn get_traits(self) -> impl Iterator + 'a { . self.root.traits.decode(self).map(move |index| self.local_def_id(index)) . } . . fn get_trait_impls(self) -> impl Iterator)> + 'a { -- line 1376 ---------------------------------------- -- line 1380 ---------------------------------------- . index: *trait_index, . }; . impls.decode(self).map(move |(impl_index, simplified_self_ty)| { . (trait_def_id, self.local_def_id(impl_index), simplified_self_ty) . }) . }) . } . 9,792 ( 0.00%) fn get_implementations_of_trait( . self, . tcx: TyCtxt<'tcx>, . trait_def_id: DefId, . ) -> &'tcx [(DefId, Option)] { 1,088 ( 0.00%) if self.trait_impls.is_empty() { . return &[]; . } . . // Do a reverse lookup beforehand to avoid touching the crate_num . // hash map in the loop below. 1,522 ( 0.00%) let key = match self.reverse_translate_def_id(trait_def_id) { . Some(def_id) => (def_id.krate.as_u32(), def_id.index), . None => return &[], . }; . . if let Some(impls) = self.trait_impls.get(&key) { 840 ( 0.00%) tcx.arena.alloc_from_iter( 420 ( 0.00%) impls . .decode(self) 6,335 ( 0.00%) .map(|(idx, simplified_self_ty)| (self.local_def_id(idx), simplified_self_ty)), . ) . } else { . &[] . } 8,704 ( 0.00%) } . . fn get_trait_of_item(self, id: DefIndex) -> Option { 508 ( 0.00%) let def_key = self.def_key(id); 635 ( 0.00%) match def_key.disambiguated_data.data { . DefPathData::TypeNs(..) | DefPathData::ValueNs(..) => (), . // Not an associated item . _ => return None, . } 1,098 ( 0.00%) def_key.parent.and_then(|parent_index| match self.kind(parent_index) { . EntryKind::Trait(_) | EntryKind::TraitAlias => Some(self.local_def_id(parent_index)), . _ => None, . }) . } . . fn get_native_libraries(self, sess: &'a Session) -> impl Iterator + 'a { 68 ( 0.00%) self.root.native_libraries.decode((self, sess)) . } . . fn get_proc_macro_quoted_span(self, index: usize, sess: &Session) -> Span { . self.root . .tables . .proc_macro_quoted_spans . .get(self, index) . .unwrap_or_else(|| panic!("Missing proc macro quoted span: {:?}", index)) -- line 1437 ---------------------------------------- -- line 1450 ---------------------------------------- . self.root.dylib_dependency_formats.decode(self).enumerate().flat_map(|(i, link)| { . let cnum = CrateNum::new(i + 1); . link.map(|link| (self.cnum_map[cnum], link)) . }), . ) . } . . fn get_missing_lang_items(self, tcx: TyCtxt<'tcx>) -> &'tcx [lang_items::LangItem] { 170 ( 0.00%) tcx.arena.alloc_from_iter(self.root.lang_items_missing.decode(self)) . } . . fn get_fn_param_names(self, tcx: TyCtxt<'tcx>, id: DefIndex) -> &'tcx [Ident] { . let param_names = match self.kind(id) { . EntryKind::Fn(data) | EntryKind::ForeignFn(data) => data.decode(self).param_names, . EntryKind::AssocFn(data) => data.decode(self).fn_data.param_names, . _ => Lazy::empty(), . }; . tcx.arena.alloc_from_iter(param_names.decode((self, tcx))) . } . . fn exported_symbols( . self, . tcx: TyCtxt<'tcx>, . ) -> &'tcx [(ExportedSymbol<'tcx>, SymbolExportLevel)] { 204 ( 0.00%) tcx.arena.alloc_from_iter(self.root.exported_symbols.decode((self, tcx))) . } . . fn get_rendered_const(self, id: DefIndex) -> String { . match self.kind(id) { . EntryKind::AnonConst(_, data) . | EntryKind::Const(_, data) . | EntryKind::AssocConst(_, _, data) => data.decode(self).0, . _ => bug!(), . } . } . . fn get_macro(self, id: DefIndex, sess: &Session) -> MacroDef { 114 ( 0.00%) match self.kind(id) { 19 ( 0.00%) EntryKind::MacroDef(macro_def) => macro_def.decode((self, sess)), . _ => bug!(), . } . } . . // This replicates some of the logic of the crate-local `is_const_fn_raw` query, because we . // don't serialize constness for tuple variant and tuple struct constructors. . fn is_const_fn_raw(self, id: DefIndex) -> bool { 117 ( 0.00%) let constness = match self.kind(id) { 24 ( 0.00%) EntryKind::AssocFn(data) => data.decode(self).fn_data.constness, 6 ( 0.00%) EntryKind::Fn(data) => data.decode(self).constness, . EntryKind::ForeignFn(data) => data.decode(self).constness, . EntryKind::Variant(..) | EntryKind::Struct(..) => hir::Constness::Const, . _ => hir::Constness::NotConst, . }; . constness == hir::Constness::Const . } . . fn asyncness(self, id: DefIndex) -> hir::IsAsync { -- line 1506 ---------------------------------------- -- line 1508 ---------------------------------------- . EntryKind::Fn(data) => data.decode(self).asyncness, . EntryKind::AssocFn(data) => data.decode(self).fn_data.asyncness, . EntryKind::ForeignFn(data) => data.decode(self).asyncness, . _ => bug!("asyncness: expected function kind"), . } . } . . fn is_foreign_item(self, id: DefIndex) -> bool { 990 ( 0.00%) match self.kind(id) { . EntryKind::ForeignImmStatic | EntryKind::ForeignMutStatic | EntryKind::ForeignFn(_) => { . true . } . _ => false, . } . } . . fn static_mutability(self, id: DefIndex) -> Option { 352 ( 0.00%) match self.kind(id) { . EntryKind::ImmStatic | EntryKind::ForeignImmStatic => Some(hir::Mutability::Not), . EntryKind::MutStatic | EntryKind::ForeignMutStatic => Some(hir::Mutability::Mut), . _ => None, . } . } . . fn generator_kind(self, id: DefIndex) -> Option { 20 ( 0.00%) match self.kind(id) { . EntryKind::Generator(data) => Some(data), . _ => None, . } . } . . fn fn_sig(self, id: DefIndex, tcx: TyCtxt<'tcx>) -> ty::PolyFnSig<'tcx> { 630 ( 0.00%) self.root.tables.fn_sig.get(self, id).unwrap().decode((self, tcx)) . } . . #[inline] 176,015 ( 0.03%) fn def_key(self, index: DefIndex) -> DefKey { 50,404 ( 0.01%) *self . .def_key_cache . .lock() . .entry(index) 11,549 ( 0.00%) .or_insert_with(|| self.root.tables.def_keys.get(self, index).unwrap().decode(self)) 201,160 ( 0.04%) } . . // Returns the path leading to the thing with this `id`. . fn def_path(self, id: DefIndex) -> DefPath { . debug!("def_path(cnum={:?}, id={:?})", self.cnum, id); 96 ( 0.00%) DefPath::make(self.cnum, id, |parent| self.def_key(parent)) . } . . fn def_path_hash_unlocked( . self, . index: DefIndex, . def_path_hashes: &mut FxHashMap, . ) -> DefPathHash { 3,528 ( 0.00%) *def_path_hashes.entry(index).or_insert_with(|| { 3,210 ( 0.00%) self.root.tables.def_path_hashes.get(self, index).unwrap().decode(self) . }) . } . . #[inline] 12,348 ( 0.00%) fn def_path_hash(self, index: DefIndex) -> DefPathHash { . let mut def_path_hashes = self.def_path_hash_cache.lock(); . self.def_path_hash_unlocked(index, &mut def_path_hashes) 14,112 ( 0.00%) } . . #[inline] . fn def_path_hash_to_def_index(self, hash: DefPathHash) -> DefIndex { . self.def_path_hash_map.def_path_hash_to_def_index(&hash) . } . . fn expn_hash_to_expn_id(self, sess: &Session, index_guess: u32, hash: ExpnHash) -> ExpnId { . debug_assert_eq!(ExpnId::from_hash(hash), None); -- line 1580 ---------------------------------------- -- line 1635 ---------------------------------------- . /// Proc macro crates don't currently export spans, so this function does not have . /// to work for them. . fn imported_source_files(self, sess: &Session) -> &'a [ImportedSourceFile] { . // Translate the virtual `/rustc/$hash` prefix back to a real directory . // that should hold actual sources, where possible. . // . // NOTE: if you update this, you might need to also update bootstrap's code for generating . // the `rust-src` component in `Src::run` in `src/bootstrap/dist.rs`. 33,984 ( 0.01%) let virtual_rust_source_base_dir = option_env!("CFG_VIRTUAL_RUST_SOURCE_BASE_DIR") . .map(Path::new) . .filter(|_| { . // Only spend time on further checks if we have what to translate *to*. . sess.opts.real_rust_source_base_dir.is_some() . }) . .filter(|virtual_dir| { . // Don't translate away `/rustc/$hash` if we're still remapping to it, . // since that means we're still building `std`/`rustc` that need it, . // and we don't want the real path to leak into codegen/debuginfo. . !sess.opts.remap_path_prefix.iter().any(|(_from, to)| to == virtual_dir) . }); 33,984 ( 0.01%) let try_to_translate_virtual_to_real = |name: &mut rustc_span::FileName| { . debug!( . "try_to_translate_virtual_to_real(name={:?}): \ . virtual_rust_source_base_dir={:?}, real_rust_source_base_dir={:?}", . name, virtual_rust_source_base_dir, sess.opts.real_rust_source_base_dir, . ); . 3,125 ( 0.00%) if let Some(virtual_dir) = virtual_rust_source_base_dir { . if let Some(real_dir) = &sess.opts.real_rust_source_base_dir { . if let rustc_span::FileName::Real(old_name) = name { . if let rustc_span::RealFileName::Remapped { local_path: _, virtual_name } = . old_name . { . if let Ok(rest) = virtual_name.strip_prefix(virtual_dir) { . let virtual_name = virtual_name.clone(); . -- line 1670 ---------------------------------------- -- line 1709 ---------------------------------------- . *old_name = new_name; . } . } . } . } . } . }; . 33,875 ( 0.01%) self.cdata.source_map_import_info.get_or_init(|| { 63 ( 0.00%) let external_source_map = self.root.source_map.decode(self); . . external_source_map . .map(|source_file_to_import| { . // We can't reuse an existing SourceFile, so allocate a new one . // containing the information we need. . let rustc_span::SourceFile { 13,125 ( 0.00%) mut name, 3,750 ( 0.00%) src_hash, 625 ( 0.00%) start_pos, 1,250 ( 0.00%) end_pos, 3,125 ( 0.00%) mut lines, 3,125 ( 0.00%) mut multibyte_chars, 3,750 ( 0.00%) mut non_narrow_chars, 3,125 ( 0.00%) mut normalized_pos, 3,750 ( 0.00%) name_hash, . .. . } = source_file_to_import; . . // If this file is under $sysroot/lib/rustlib/src/ but has not been remapped . // during rust bootstrapping by `remap-debuginfo = true`, and the user . // wish to simulate that behaviour by -Z simulate-remapped-rust-src-base, . // then we change `name` to a similar state as if the rust was bootstrapped . // with `remap-debuginfo = true`. . // This is useful for testing so that tests about the effects of . // `try_to_translate_virtual_to_real` don't have to worry about how the . // compiler is bootstrapped. 1,250 ( 0.00%) if let Some(virtual_dir) = . &sess.opts.debugging_opts.simulate_remapped_rust_src_base . { . if let Some(real_dir) = &sess.opts.real_rust_source_base_dir { . if let rustc_span::FileName::Real(ref mut old_name) = name { . if let rustc_span::RealFileName::LocalPath(local) = old_name { . if let Ok(rest) = local.strip_prefix(real_dir) { . *old_name = rustc_span::RealFileName::Remapped { . local_path: None, -- line 1753 ---------------------------------------- -- line 1767 ---------------------------------------- . let source_length = (end_pos - start_pos).to_usize(); . . // Translate line-start positions and multibyte character . // position into frame of reference local to file. . // `SourceMap::new_imported_source_file()` will then translate those . // coordinates to their new global frame of reference when the . // offset of the SourceFile is known. . for pos in &mut lines { 782,094 ( 0.15%) *pos = *pos - start_pos; . } . for mbc in &mut multibyte_chars { 1,608 ( 0.00%) mbc.pos = mbc.pos - start_pos; . } . for swc in &mut non_narrow_chars { 924 ( 0.00%) *swc = *swc - start_pos; . } . for np in &mut normalized_pos { 4,050 ( 0.00%) np.pos = np.pos - start_pos; . } . 11,250 ( 0.00%) let local_version = sess.source_map().new_imported_source_file( 8,125 ( 0.00%) name, 4,375 ( 0.00%) src_hash, . name_hash, . source_length, 1,250 ( 0.00%) self.cnum, 3,125 ( 0.00%) lines, 3,750 ( 0.00%) multibyte_chars, 3,125 ( 0.00%) non_narrow_chars, 2,500 ( 0.00%) normalized_pos, . start_pos, . end_pos, . ); . debug!( . "CrateMetaData::imported_source_files alloc \ . source_file {:?} original (start_pos {:?} end_pos {:?}) \ . translated (start_pos {:?} end_pos {:?})", . local_version.name, -- line 1804 ---------------------------------------- -- line 1808 ---------------------------------------- . local_version.end_pos . ); . . ImportedSourceFile { . original_start_pos: start_pos, . original_end_pos: end_pos, . translated_source_file: local_version, . } 1,875 ( 0.00%) }) . .collect() . }) . } . } . . impl CrateMetadata { 408 ( 0.00%) crate fn new( . sess: &Session, . blob: MetadataBlob, . root: CrateRoot<'static>, . raw_proc_macros: Option<&'static [ProcMacro]>, . cnum: CrateNum, . cnum_map: CrateNumMap, . dep_kind: CrateDepKind, . source: CrateSource, . private_dep: bool, . host_hash: Option, . ) -> CrateMetadata { 102 ( 0.00%) let trait_impls = root . .impls . .decode((&blob, sess)) . .map(|trait_impls| (trait_impls.trait_id, trait_impls.impls)) . .collect(); . let alloc_decoding_state = 102 ( 0.00%) AllocDecodingState::new(root.interpret_alloc_index.decode(&blob).collect()); . let dependencies = Lock::new(cnum_map.iter().cloned().collect()); . . // Pre-decode the DefPathHash->DefIndex table. This is a cheap operation . // that does not copy any data. It just does some data verification. 34 ( 0.00%) let def_path_hash_map = root.def_path_hash_map.decode(&blob); . 782 ( 0.00%) CrateMetadata { 34 ( 0.00%) blob, 102 ( 0.00%) root, 136 ( 0.00%) trait_impls, . raw_proc_macros, . source_map_import_info: OnceCell::new(), 136 ( 0.00%) def_path_hash_map, . expn_hash_map: Default::default(), 238 ( 0.00%) alloc_decoding_state, . cnum, 136 ( 0.00%) cnum_map, 170 ( 0.00%) dependencies, . dep_kind: Lock::new(dep_kind), 408 ( 0.00%) source, . private_dep, . host_hash, . extern_crate: Lock::new(None), . hygiene_context: Default::default(), . def_key_cache: Default::default(), . def_path_hash_cache: Default::default(), . } 306 ( 0.00%) } . . crate fn dependencies(&self) -> LockGuard<'_, Vec> { . self.dependencies.borrow() . } . . crate fn add_dependency(&self, cnum: CrateNum) { . self.dependencies.borrow_mut().push(cnum); . } . . crate fn update_extern_crate(&self, new_extern_crate: ExternCrate) -> bool { . let mut extern_crate = self.extern_crate.borrow_mut(); . let update = Some(new_extern_crate.rank()) > extern_crate.as_ref().map(ExternCrate::rank); . if update { 180 ( 0.00%) *extern_crate = Some(new_extern_crate); . } . update . } . . crate fn source(&self) -> &CrateSource { 168 ( 0.00%) &self.source . } . . crate fn dep_kind(&self) -> CrateDepKind { . *self.dep_kind.lock() . } . . crate fn update_dep_kind(&self, f: impl FnOnce(CrateDepKind) -> CrateDepKind) { 290 ( 0.00%) self.dep_kind.with_lock(|dep_kind| *dep_kind = f(*dep_kind)) . } . . crate fn panic_strategy(&self) -> PanicStrategy { . self.root.panic_strategy . } . . crate fn needs_panic_runtime(&self) -> bool { . self.root.needs_panic_runtime -- line 1905 ---------------------------------------- -- line 1909 ---------------------------------------- . self.root.panic_runtime . } . . crate fn is_profiler_runtime(&self) -> bool { . self.root.profiler_runtime . } . . crate fn needs_allocator(&self) -> bool { 5 ( 0.00%) self.root.needs_allocator . } . . crate fn has_global_allocator(&self) -> bool { . self.root.has_global_allocator . } . . crate fn has_default_lib_allocator(&self) -> bool { . self.root.has_default_lib_allocator . } . . crate fn is_proc_macro_crate(&self) -> bool { . self.root.is_proc_macro_crate() . } . . crate fn name(&self) -> Symbol { 602 ( 0.00%) self.root.name . } . . crate fn stable_crate_id(&self) -> StableCrateId { . self.root.stable_crate_id . } . . crate fn hash(&self) -> Svh { . self.root.hash . } . . fn num_def_ids(&self) -> usize { . self.root.tables.def_keys.size() . } . . fn local_def_id(&self, index: DefIndex) -> DefId { 11,362 ( 0.00%) DefId { krate: self.cnum, index } . } . . // Translate a DefId from the current compilation environment to a DefId . // for an external crate. . fn reverse_translate_def_id(&self, did: DefId) -> Option { . for (local, &global) in self.cnum_map.iter_enumerated() { 4,075 ( 0.00%) if global == did.krate { . return Some(DefId { krate: local, index: did.index }); . } . } . . None . } . } . . // Cannot be implemented on 'ProcMacro', as libproc_macro . // does not depend on librustc_ast . fn macro_kind(raw: &ProcMacro) -> MacroKind { 144 ( 0.00%) match raw { . ProcMacro::CustomDerive { .. } => MacroKind::Derive, . ProcMacro::Attr { .. } => MacroKind::Attr, . ProcMacro::Bang { .. } => MacroKind::Bang, . } . } 416,094 ( 0.08%) -------------------------------------------------------------------------------- -- Auto-annotated source: /usr/home/liquid/.cargo/registry/src/github.com-1ecc6299db9ec823/hashbrown-0.12.0/src/raw/mod.rs -------------------------------------------------------------------------------- Ir -- line 110 ---------------------------------------- . /// Control byte value for an empty bucket. . const EMPTY: u8 = 0b1111_1111; . . /// Control byte value for a deleted bucket. . const DELETED: u8 = 0b1000_0000; . . /// Checks whether a control byte represents a full bucket (top bit is clear). . #[inline] 111 ( 0.00%) fn is_full(ctrl: u8) -> bool { 356,814 ( 0.07%) ctrl & 0x80 == 0 148 ( 0.00%) } . . /// Checks whether a control byte represents a special value (top bit is set). . #[inline] . fn is_special(ctrl: u8) -> bool { . ctrl & 0x80 != 0 . } . . /// Checks whether a special control value is EMPTY (just check 1 bit). . #[inline] 63 ( 0.00%) fn special_is_empty(ctrl: u8) -> bool { . debug_assert!(is_special(ctrl)); 29,307 ( 0.01%) ctrl & 0x01 != 0 84 ( 0.00%) } . . /// Primary hash function, used to select the initial bucket to probe from. . #[inline] . #[allow(clippy::cast_possible_truncation)] 126 ( 0.00%) fn h1(hash: u64) -> usize { . // On 32-bit platforms we simply ignore the higher hash bits. . hash as usize 84 ( 0.00%) } . . /// Secondary hash function, saved in the low 7 bits of the control byte. . #[inline] . #[allow(clippy::cast_possible_truncation)] 105 ( 0.00%) fn h2(hash: u64) -> u8 { . // Grab the top 7 bits of the hash. While the hash is normally a full 64-bit . // value, some hash functions (such as FxHash) produce a usize result . // instead, which means that the top 32 bits are 0 on 32-bit platforms. 210 ( 0.00%) let hash_len = usize::min(mem::size_of::(), mem::size_of::()); 3,076,641 ( 0.57%) let top7 = hash >> (hash_len * 8 - 7); 35 ( 0.00%) (top7 & 0x7f) as u8 // truncation 70 ( 0.00%) } . . /// Probe sequence based on triangular numbers, which is guaranteed (since our . /// table size is a power of two) to visit every group of elements exactly once. . /// . /// A triangular probe has us jump by 1 more group every time. So first we . /// jump by 1 group (meaning we just continue our linear scan), then 2 groups . /// (skipping over 1 group), then 3 groups (skipping over 2 groups), and so on. . /// -- line 161 ---------------------------------------- -- line 170 ---------------------------------------- . #[inline] . fn move_next(&mut self, bucket_mask: usize) { . // We should have found an empty bucket by now and ended the probe. . debug_assert!( . self.stride <= bucket_mask, . "Went past end of probe sequence" . ); . 42,946 ( 0.01%) self.stride += Group::WIDTH; 42,946 ( 0.01%) self.pos += self.stride; 35,005 ( 0.01%) self.pos &= bucket_mask; . } . } . . /// Returns the number of buckets needed to hold the given number of items, . /// taking the maximum load factor into account. . /// . /// Returns `None` if an overflow occurs. . // Workaround for emscripten bug emscripten-core/emscripten-fastcomp#258 . #[cfg_attr(target_os = "emscripten", inline(never))] . #[cfg_attr(not(target_os = "emscripten"), inline)] 30 ( 0.00%) fn capacity_to_buckets(cap: usize) -> Option { . debug_assert_ne!(cap, 0); . . // For small tables we require at least 1 empty bucket so that lookups are . // guaranteed to terminate if an element doesn't exist in the table. 14,580 ( 0.00%) if cap < 8 { . // We don't bother with a table size of 2 buckets since that can only . // hold a single element. Instead we skip directly to a 4 bucket table . // which can hold 3 elements. 27,556 ( 0.01%) return Some(if cap < 4 { 4 } else { 8 }); . } . . // Otherwise require 1/8 buckets to be empty (87.5% load) . // . // Be careful when modifying this, calculate_layout relies on the . // overflow check here. 10,686 ( 0.00%) let adjusted_cap = cap.checked_mul(8)? / 7; . . // Any overflows will have been caught by the checked_mul. Also, any . // rounding errors from the division above will be cleaned up by . // next_power_of_two (which can't overflow because of the previous division). . Some(adjusted_cap.next_power_of_two()) 40 ( 0.00%) } . . /// Returns the maximum effective capacity for the given bucket mask, taking . /// the maximum load factor into account. . #[inline] 72 ( 0.00%) fn bucket_mask_to_capacity(bucket_mask: usize) -> usize { 42,419 ( 0.01%) if bucket_mask < 8 { . // For tables with 1/2/4/8 buckets, we always reserve one empty slot. . // Keep in mind that the bucket mask is one less than the bucket count. 24 ( 0.00%) bucket_mask . } else { . // For larger tables we reserve 12.5% of the slots as empty. 12,012 ( 0.00%) ((bucket_mask + 1) / 8) * 7 . } 72 ( 0.00%) } . . /// Helper which allows the max calculation for ctrl_align to be statically computed for each T . /// while keeping the rest of `calculate_layout_for` independent of `T` . #[derive(Copy, Clone)] . struct TableLayout { . size: usize, . ctrl_align: usize, . } . . impl TableLayout { . #[inline] 19 ( 0.00%) fn new() -> Self { 57 ( 0.00%) let layout = Layout::new::(); 38 ( 0.00%) Self { 57 ( 0.00%) size: layout.size(), 114 ( 0.00%) ctrl_align: usize::max(layout.align(), Group::WIDTH), . } 76 ( 0.00%) } . . #[inline] 260 ( 0.00%) fn calculate_layout_for(self, buckets: usize) -> Option<(Layout, usize)> { . debug_assert!(buckets.is_power_of_two()); . 40 ( 0.00%) let TableLayout { size, ctrl_align } = self; . // Manual layout calculation since Layout methods are not yet stable. . let ctrl_offset = 25,749 ( 0.00%) size.checked_mul(buckets)?.checked_add(ctrl_align - 1)? & !(ctrl_align - 1); 37,757 ( 0.01%) let len = ctrl_offset.checked_add(buckets + Group::WIDTH)?; . 180 ( 0.00%) Some(( 80 ( 0.00%) unsafe { Layout::from_size_align_unchecked(len, ctrl_align) }, . ctrl_offset, . )) 60 ( 0.00%) } . } . . /// Returns a Layout which describes the allocation required for a hash table, . /// and the offset of the control bytes in the allocation. . /// (the offset is also one past last element of buckets) . /// . /// Returns `None` if an overflow occurs. . #[cfg_attr(feature = "inline-more", inline)] 20 ( 0.00%) fn calculate_layout(buckets: usize) -> Option<(Layout, usize)> { 16 ( 0.00%) TableLayout::new::().calculate_layout_for(buckets) 8 ( 0.00%) } . . /// A reference to a hash table bucket containing a `T`. . /// . /// This is usually just a pointer to the element itself. However if the element . /// is a ZST, then we instead track the index of the element in the table so . /// that `erase` works properly. . pub struct Bucket { . // Actually it is pointer to next element than element itself -- line 280 ---------------------------------------- -- line 292 ---------------------------------------- . #[inline] . fn clone(&self) -> Self { . Self { ptr: self.ptr } . } . } . . impl Bucket { . #[inline] 165 ( 0.00%) unsafe fn from_base_index(base: NonNull, index: usize) -> Self { 132 ( 0.00%) let ptr = if mem::size_of::() == 0 { . // won't overflow because index must be less than length . (index + 1) as *mut T . } else { 132 ( 0.00%) base.as_ptr().sub(index) . }; 33 ( 0.00%) Self { 132 ( 0.00%) ptr: NonNull::new_unchecked(ptr), . } 99 ( 0.00%) } . #[inline] . unsafe fn to_base_index(&self, base: NonNull) -> usize { . if mem::size_of::() == 0 { . self.ptr.as_ptr() as usize - 1 . } else { . offset_from(base.as_ptr(), self.ptr.as_ptr()) . } . } . #[inline] 102 ( 0.00%) pub fn as_ptr(&self) -> *mut T { 136 ( 0.00%) if mem::size_of::() == 0 { . // Just return an arbitrary ZST pointer which is properly aligned . mem::align_of::() as *mut T . } else { 204 ( 0.00%) unsafe { self.ptr.as_ptr().sub(1) } . } 102 ( 0.00%) } . #[inline] 35 ( 0.00%) unsafe fn next_n(&self, offset: usize) -> Self { 28 ( 0.00%) let ptr = if mem::size_of::() == 0 { . (self.ptr.as_ptr() as usize + offset) as *mut T . } else { 35 ( 0.00%) self.ptr.as_ptr().sub(offset) . }; 7 ( 0.00%) Self { 28 ( 0.00%) ptr: NonNull::new_unchecked(ptr), . } 21 ( 0.00%) } . #[cfg_attr(feature = "inline-more", inline)] 6 ( 0.00%) pub unsafe fn drop(&self) { 6 ( 0.00%) self.as_ptr().drop_in_place(); 6 ( 0.00%) } . #[inline] 28 ( 0.00%) pub unsafe fn read(&self) -> T { 14 ( 0.00%) self.as_ptr().read() 8 ( 0.00%) } . #[inline] 63 ( 0.00%) pub unsafe fn write(&self, val: T) { 186 ( 0.00%) self.as_ptr().write(val); 28 ( 0.00%) } . #[inline] 22 ( 0.00%) pub unsafe fn as_ref<'a>(&self) -> &'a T { 22 ( 0.00%) &*self.as_ptr() 22 ( 0.00%) } . #[inline] 4 ( 0.00%) pub unsafe fn as_mut<'a>(&self) -> &'a mut T { 4 ( 0.00%) &mut *self.as_ptr() 4 ( 0.00%) } . #[cfg(feature = "raw")] . #[inline] . pub unsafe fn copy_from_nonoverlapping(&self, other: &Self) { . self.as_ptr().copy_from_nonoverlapping(other.as_ptr(), 1); . } . } . . /// A raw hash table with an unsafe API. -- line 366 ---------------------------------------- -- line 392 ---------------------------------------- . . impl RawTable { . /// Creates a new empty hash table without allocating any memory. . /// . /// In effect this returns a table with exactly 1 bucket. However we can . /// leave the data pointer dangling since that bucket is never written to . /// due to our load factor forcing us to always have at least 1 free bucket. . #[inline] 21 ( 0.00%) pub const fn new() -> Self { 56 ( 0.00%) Self { 14 ( 0.00%) table: RawTableInner::new_in(Global), . marker: PhantomData, . } 14 ( 0.00%) } . . /// Attempts to allocate a new hash table with at least enough capacity . /// for inserting the given number of elements without reallocating. . #[cfg(feature = "raw")] . pub fn try_with_capacity(capacity: usize) -> Result { . Self::try_with_capacity_in(capacity, Global) . } . -- line 413 ---------------------------------------- -- line 421 ---------------------------------------- . impl RawTable { . /// Creates a new empty hash table without allocating any memory, using the . /// given allocator. . /// . /// In effect this returns a table with exactly 1 bucket. However we can . /// leave the data pointer dangling since that bucket is never written to . /// due to our load factor forcing us to always have at least 1 free bucket. . #[inline] 12 ( 0.00%) pub fn new_in(alloc: A) -> Self { 206 ( 0.00%) Self { 8 ( 0.00%) table: RawTableInner::new_in(alloc), . marker: PhantomData, . } 8 ( 0.00%) } . . /// Allocates a new hash table with the given number of buckets. . /// . /// The control bytes are left uninitialized. . #[cfg_attr(feature = "inline-more", inline)] . unsafe fn new_uninitialized( . alloc: A, . buckets: usize, . fallibility: Fallibility, . ) -> Result { . debug_assert!(buckets.is_power_of_two()); . . Ok(Self { 25 ( 0.00%) table: RawTableInner::new_uninitialized( . alloc, . TableLayout::new::(), . buckets, . fallibility, . )?, . marker: PhantomData, . }) . } -- line 456 ---------------------------------------- -- line 458 ---------------------------------------- . /// Attempts to allocate a new hash table with at least enough capacity . /// for inserting the given number of elements without reallocating. . fn fallible_with_capacity( . alloc: A, . capacity: usize, . fallibility: Fallibility, . ) -> Result { . Ok(Self { 1,641 ( 0.00%) table: RawTableInner::fallible_with_capacity( . alloc, . TableLayout::new::(), . capacity, . fallibility, . )?, . marker: PhantomData, . }) . } -- line 474 ---------------------------------------- -- line 493 ---------------------------------------- . /// Returns a reference to the underlying allocator. . #[inline] . pub fn allocator(&self) -> &A { . &self.table.alloc . } . . /// Deallocates the table without dropping any entries. . #[cfg_attr(feature = "inline-more", inline)] 15 ( 0.00%) unsafe fn free_buckets(&mut self) { 20 ( 0.00%) self.table.free_buckets(TableLayout::new::()); 10 ( 0.00%) } . . /// Returns pointer to one past last element of data table. . #[inline] 56 ( 0.00%) pub unsafe fn data_end(&self) -> NonNull { 140 ( 0.00%) NonNull::new_unchecked(self.table.ctrl.as_ptr().cast()) 56 ( 0.00%) } . . /// Returns pointer to start of data table. . #[inline] . #[cfg(feature = "nightly")] . pub unsafe fn data_start(&self) -> *mut T { . self.data_end().as_ptr().wrapping_sub(self.buckets()) . } . -- line 517 ---------------------------------------- -- line 518 ---------------------------------------- . /// Returns the index of a bucket from a `Bucket`. . #[inline] . pub unsafe fn bucket_index(&self, bucket: &Bucket) -> usize { . bucket.to_base_index(self.data_end()) . } . . /// Returns a pointer to an element in the table. . #[inline] 80 ( 0.00%) pub unsafe fn bucket(&self, index: usize) -> Bucket { . debug_assert_ne!(self.table.bucket_mask, 0); . debug_assert!(index < self.buckets()); 80 ( 0.00%) Bucket::from_base_index(self.data_end(), index) 40 ( 0.00%) } . . /// Erases an element from the table without dropping it. . #[cfg_attr(feature = "inline-more", inline)] . #[deprecated(since = "0.8.1", note = "use erase or remove instead")] 1,209 ( 0.00%) pub unsafe fn erase_no_drop(&mut self, item: &Bucket) { 1,209 ( 0.00%) let index = self.bucket_index(item); . self.table.erase(index); 2,418 ( 0.00%) } . . /// Erases an element from the table, dropping it in place. . #[cfg_attr(feature = "inline-more", inline)] . #[allow(clippy::needless_pass_by_value)] . #[allow(deprecated)] . pub unsafe fn erase(&mut self, item: Bucket) { . // Erase the element from the table first since drop might panic. 390 ( 0.00%) self.erase_no_drop(&item); . item.drop(); . } . . /// Finds and erases an element from the table, dropping it in place. . /// Returns true if an element was found. . #[cfg(feature = "raw")] . #[cfg_attr(feature = "inline-more", inline)] . pub fn erase_entry(&mut self, hash: u64, eq: impl FnMut(&T) -> bool) -> bool { -- line 554 ---------------------------------------- -- line 563 ---------------------------------------- . } . } . . /// Removes an element from the table, returning it. . #[cfg_attr(feature = "inline-more", inline)] . #[allow(clippy::needless_pass_by_value)] . #[allow(deprecated)] . pub unsafe fn remove(&mut self, item: Bucket) -> T { 2,028 ( 0.00%) self.erase_no_drop(&item); 15 ( 0.00%) item.read() . } . . /// Finds and removes an element from the table, returning it. . #[cfg_attr(feature = "inline-more", inline)] 85,757 ( 0.02%) pub fn remove_entry(&mut self, hash: u64, eq: impl FnMut(&T) -> bool) -> Option { . // Avoid `Option::map` because it bloats LLVM IR. 282 ( 0.00%) match self.find(hash, eq) { 247 ( 0.00%) Some(bucket) => Some(unsafe { self.remove(bucket) }), 3,898 ( 0.00%) None => None, . } 127,903 ( 0.02%) } . . /// Marks all table buckets as empty without dropping their contents. . #[cfg_attr(feature = "inline-more", inline)] 8 ( 0.00%) pub fn clear_no_drop(&mut self) { 4 ( 0.00%) self.table.clear_no_drop(); 8 ( 0.00%) } . . /// Removes all elements from the table without freeing the backing memory. . #[cfg_attr(feature = "inline-more", inline)] 8 ( 0.00%) pub fn clear(&mut self) { . // Ensure that the table is reset even if one of the drops panic 36 ( 0.00%) let mut self_ = guard(self, |self_| self_.clear_no_drop()); . unsafe { 25 ( 0.00%) self_.drop_elements(); . } 20 ( 0.00%) } . 34 ( 0.00%) unsafe fn drop_elements(&mut self) { 1,228 ( 0.00%) if mem::needs_drop::() && !self.is_empty() { 90 ( 0.00%) for item in self.iter() { 6 ( 0.00%) item.drop(); . } . } 26 ( 0.00%) } . . /// Shrinks the table to fit `max(self.len(), min_size)` elements. . #[cfg_attr(feature = "inline-more", inline)] . pub fn shrink_to(&mut self, min_size: usize, hasher: impl Fn(&T) -> u64) { . // Calculate the minimal number of elements that we need to reserve . // space for. . let min_size = usize::max(self.table.items, min_size); . if min_size == 0 { -- line 615 ---------------------------------------- -- line 641 ---------------------------------------- . } . } . } . } . . /// Ensures that at least `additional` items can be inserted into the table . /// without reallocation. . #[cfg_attr(feature = "inline-more", inline)] 98 ( 0.00%) pub fn reserve(&mut self, additional: usize, hasher: impl Fn(&T) -> u64) { 63,540 ( 0.01%) if additional > self.table.growth_left { . // Avoid `Result::unwrap_or_else` because it bloats LLVM IR. 25,676 ( 0.00%) if self 20 ( 0.00%) .reserve_rehash(additional, hasher, Fallibility::Infallible) . .is_err() . { . unsafe { hint::unreachable_unchecked() } . } . } 70 ( 0.00%) } . . /// Tries to ensure that at least `additional` items can be inserted into . /// the table without reallocation. . #[cfg_attr(feature = "inline-more", inline)] . pub fn try_reserve( . &mut self, . additional: usize, . hasher: impl Fn(&T) -> u64, -- line 667 ---------------------------------------- -- line 671 ---------------------------------------- . } else { . Ok(()) . } . } . . /// Out-of-line slow path for `reserve` and `try_reserve`. . #[cold] . #[inline(never)] 57,592 ( 0.01%) fn reserve_rehash( . &mut self, . additional: usize, . hasher: impl Fn(&T) -> u64, . fallibility: Fallibility, . ) -> Result<(), TryReserveError> { . unsafe { 120 ( 0.00%) self.table.reserve_rehash_inner( . additional, 99 ( 0.00%) &|table, index| hasher(table.bucket::(index).as_ref()), . fallibility, 40 ( 0.00%) TableLayout::new::(), 56 ( 0.00%) if mem::needs_drop::() { 35 ( 0.00%) Some(mem::transmute(ptr::drop_in_place:: as unsafe fn(*mut T))) . } else { 3 ( 0.00%) None . }, . ) . } 34,718 ( 0.01%) } . . /// Allocates a new table of a different size and moves the contents of the . /// current table into it. . fn resize( . &mut self, . capacity: usize, . hasher: impl Fn(&T) -> u64, . fallibility: Fallibility, -- line 706 ---------------------------------------- -- line 714 ---------------------------------------- . ) . } . } . . /// Inserts a new element into the table, and returns its raw bucket. . /// . /// This does not check if the given element already exists in the table. . #[cfg_attr(feature = "inline-more", inline)] 470,607 ( 0.09%) pub fn insert(&mut self, hash: u64, value: T, hasher: impl Fn(&T) -> u64) -> Bucket { . unsafe { 91 ( 0.00%) let mut index = self.table.find_insert_slot(hash); . . // We can avoid growing the table once we have reached our load . // factor if we are replacing a tombstone. This works since the . // number of EMPTY slots does not change in this case. 705 ( 0.00%) let old_ctrl = *self.table.ctrl(index); 337,913 ( 0.06%) if unlikely(self.table.growth_left == 0 && special_is_empty(old_ctrl)) { 28 ( 0.00%) self.reserve(1, hasher); 28 ( 0.00%) index = self.table.find_insert_slot(hash); . } . 48 ( 0.00%) self.table.record_item_insert_at(index, old_ctrl, hash); . 60 ( 0.00%) let bucket = self.bucket(index); 102 ( 0.00%) bucket.write(value); 24 ( 0.00%) bucket . } 347,074 ( 0.06%) } . . /// Attempts to insert a new element without growing the table and return its raw bucket. . /// . /// Returns an `Err` containing the given element if inserting it would require growing the . /// table. . /// . /// This does not check if the given element already exists in the table. . #[cfg(feature = "raw")] -- line 749 ---------------------------------------- -- line 760 ---------------------------------------- . } . } . } . . /// Inserts a new element into the table, and returns a mutable reference to it. . /// . /// This does not check if the given element already exists in the table. . #[cfg_attr(feature = "inline-more", inline)] 124,352 ( 0.02%) pub fn insert_entry(&mut self, hash: u64, value: T, hasher: impl Fn(&T) -> u64) -> &mut T { 289 ( 0.00%) unsafe { self.insert(hash, value, hasher).as_mut() } 93,264 ( 0.02%) } . . /// Inserts a new element into the table, without growing the table. . /// . /// There must be enough space in the table to insert the new element. . /// . /// This does not check if the given element already exists in the table. . #[cfg_attr(feature = "inline-more", inline)] . #[cfg(any(feature = "raw", feature = "rustc-internal-api"))] 113 ( 0.00%) pub unsafe fn insert_no_grow(&mut self, hash: u64, value: T) -> Bucket { 88,794 ( 0.02%) let (index, old_ctrl) = self.table.prepare_insert_slot(hash); 705 ( 0.00%) let bucket = self.table.bucket(index); . . // If we are replacing a DELETED entry then we don't need to update . // the load counter. 175,310 ( 0.03%) self.table.growth_left -= special_is_empty(old_ctrl) as usize; . 20 ( 0.00%) bucket.write(value); 140,800 ( 0.03%) self.table.items += 1; . bucket 207 ( 0.00%) } . . /// Temporary removes a bucket, applying the given function to the removed . /// element and optionally put back the returned value in the same bucket. . /// . /// Returns `true` if the bucket still contains an element . /// . /// This does not check if the given bucket is actually occupied. . #[cfg_attr(feature = "inline-more", inline)] -- line 798 ---------------------------------------- -- line 813 ---------------------------------------- . true . } else { . false . } . } . . /// Searches for an element in the table. . #[inline] 3,821 ( 0.00%) pub fn find(&self, hash: u64, mut eq: impl FnMut(&T) -> bool) -> Option> { 645 ( 0.00%) let result = self.table.find_inner(hash, &mut |index| unsafe { 3,029 ( 0.00%) eq(self.bucket(index).as_ref()) 89 ( 0.00%) }); . . // Avoid `Option::map` because it bloats LLVM IR. 62 ( 0.00%) match result { 69 ( 0.00%) Some(index) => Some(unsafe { self.bucket(index) }), 28 ( 0.00%) None => None, . } 4,296 ( 0.00%) } . . /// Gets a reference to an element in the table. . #[inline] 16 ( 0.00%) pub fn get(&self, hash: u64, eq: impl FnMut(&T) -> bool) -> Option<&T> { . // Avoid `Option::map` because it bloats LLVM IR. 1,793 ( 0.00%) match self.find(hash, eq) { 24 ( 0.00%) Some(bucket) => Some(unsafe { bucket.as_ref() }), . None => None, . } 12 ( 0.00%) } . . /// Gets a mutable reference to an element in the table. . #[inline] 1,112 ( 0.00%) pub fn get_mut(&mut self, hash: u64, eq: impl FnMut(&T) -> bool) -> Option<&mut T> { . // Avoid `Option::map` because it bloats LLVM IR. 1,957 ( 0.00%) match self.find(hash, eq) { . Some(bucket) => Some(unsafe { bucket.as_mut() }), 24 ( 0.00%) None => None, . } 1,252 ( 0.00%) } . . /// Attempts to get mutable references to `N` entries in the table at once. . /// . /// Returns an array of length `N` with the results of each query. . /// . /// At most one mutable reference will be returned to any entry. `None` will be returned if any . /// of the hashes are duplicates. `None` will be returned if the hash is not found. . /// -- line 859 ---------------------------------------- -- line 913 ---------------------------------------- . /// more, but is guaranteed to be able to hold at least this many. . #[inline] . pub fn capacity(&self) -> usize { . self.table.items + self.table.growth_left . } . . /// Returns the number of elements in the table. . #[inline] 36 ( 0.00%) pub fn len(&self) -> usize { 18 ( 0.00%) self.table.items 36 ( 0.00%) } . . /// Returns `true` if the table contains no elements. . #[inline] 14 ( 0.00%) pub fn is_empty(&self) -> bool { 94,371 ( 0.02%) self.len() == 0 28 ( 0.00%) } . . /// Returns the number of buckets in the table. . #[inline] . pub fn buckets(&self) -> usize { . self.table.bucket_mask + 1 . } . . /// Returns an iterator over every element in the table. It is up to . /// the caller to ensure that the `RawTable` outlives the `RawIter`. . /// Because we cannot make the `next` method unsafe on the `RawIter` . /// struct, we have to make the `iter` method unsafe. . #[inline] 56 ( 0.00%) pub unsafe fn iter(&self) -> RawIter { 56 ( 0.00%) let data = Bucket::from_base_index(self.data_end(), 0); 72 ( 0.00%) RawIter { 56 ( 0.00%) iter: RawIterRange::new(self.table.ctrl.as_ptr(), data, self.table.buckets()), 5,901 ( 0.00%) items: self.table.items, . } 16 ( 0.00%) } . . /// Returns an iterator over occupied buckets that could match a given hash. . /// . /// `RawTable` only stores 7 bits of the hash value, so this iterator may . /// return items that have a hash value different than the one provided. You . /// should always validate the returned values before using them. . /// . /// It is up to the caller to ensure that the `RawTable` outlives the -- line 956 ---------------------------------------- -- line 991 ---------------------------------------- . } . . /// Returns an iterator which consumes all elements from the table. . /// . /// Iteration starts at the provided iterator's current location. . /// . /// It is up to the caller to ensure that the iterator is valid for this . /// `RawTable` and covers all items that remain in the table. 35 ( 0.00%) pub unsafe fn into_iter_from(self, iter: RawIter) -> RawIntoIter { 10 ( 0.00%) debug_assert_eq!(iter.len(), self.len()); . 10 ( 0.00%) let alloc = self.table.alloc.clone(); 1,013 ( 0.00%) let allocation = self.into_allocation(); 781 ( 0.00%) RawIntoIter { 1,230 ( 0.00%) iter, 30 ( 0.00%) allocation, . marker: PhantomData, . alloc, . } 10 ( 0.00%) } . . /// Converts the table into a raw allocation. The contents of the table . /// should be dropped using a `RawIter` before freeing the allocation. . #[cfg_attr(feature = "inline-more", inline)] 30 ( 0.00%) pub(crate) fn into_allocation(self) -> Option<(NonNull, Layout)> { 346 ( 0.00%) let alloc = if self.table.is_empty_singleton() { 1 ( 0.00%) None . } else { . // Avoid `Option::unwrap_or_else` because it bloats LLVM IR. 84 ( 0.00%) let (layout, ctrl_offset) = match calculate_layout::(self.table.buckets()) { 32 ( 0.00%) Some(lco) => lco, . None => unsafe { hint::unreachable_unchecked() }, . }; 36 ( 0.00%) Some(( 183 ( 0.00%) unsafe { NonNull::new_unchecked(self.table.ctrl.as_ptr().sub(ctrl_offset)) }, . layout, . )) . }; 40 ( 0.00%) mem::forget(self); . alloc 10 ( 0.00%) } . } . . unsafe impl Send for RawTable . where . T: Send, . A: Send, . { . } -- line 1039 ---------------------------------------- -- line 1041 ---------------------------------------- . where . T: Sync, . A: Sync, . { . } . . impl RawTableInner { . #[inline] 33 ( 0.00%) const fn new_in(alloc: A) -> Self { 55,601 ( 0.01%) Self { . // Be careful to cast the entire slice to a raw pointer. 77 ( 0.00%) ctrl: unsafe { NonNull::new_unchecked(Group::static_empty() as *const _ as *mut u8) }, . bucket_mask: 0, . items: 0, . growth_left: 0, . alloc, . } 22 ( 0.00%) } . } . . impl RawTableInner { . #[cfg_attr(feature = "inline-more", inline)] 33,799 ( 0.01%) unsafe fn new_uninitialized( . alloc: A, . table_layout: TableLayout, . buckets: usize, . fallibility: Fallibility, . ) -> Result { . debug_assert!(buckets.is_power_of_two()); . . // Avoid `Option::ok_or_else` because it bloats LLVM IR. 160 ( 0.00%) let (layout, ctrl_offset) = match table_layout.calculate_layout_for(buckets) { 120 ( 0.00%) Some(lco) => lco, . None => return Err(fallibility.capacity_overflow()), . }; . . // We need an additional check to ensure that the allocation doesn't . // exceed `isize::MAX`. We can skip this check on 64-bit systems since . // such allocations will never succeed anyways. . // . // This mirrors what Vec does in the standard library. 40 ( 0.00%) if mem::size_of::() < 8 && layout.size() > isize::MAX as usize { . return Err(fallibility.capacity_overflow()); . } . 12,858 ( 0.00%) let ptr: NonNull = match do_alloc(&alloc, layout) { 60 ( 0.00%) Ok(block) => block.cast(), . Err(_) => return Err(fallibility.alloc_err(layout)), . }; . 90 ( 0.00%) let ctrl = NonNull::new_unchecked(ptr.as_ptr().add(ctrl_offset)); 20,572 ( 0.00%) Ok(Self { . ctrl, 10,742 ( 0.00%) bucket_mask: buckets - 1, . items: 0, 90 ( 0.00%) growth_left: bucket_mask_to_capacity(buckets - 1), . alloc, . }) 24,744 ( 0.00%) } . . #[inline] 7,043 ( 0.00%) fn fallible_with_capacity( . alloc: A, . table_layout: TableLayout, . capacity: usize, . fallibility: Fallibility, . ) -> Result { 1,782 ( 0.00%) if capacity == 0 { 921 ( 0.00%) Ok(Self::new_in(alloc)) . } else { . unsafe { . let buckets = 170 ( 0.00%) capacity_to_buckets(capacity).ok_or_else(|| fallibility.capacity_overflow())?; . 15,615 ( 0.00%) let result = Self::new_uninitialized(alloc, table_layout, buckets, fallibility)?; 60 ( 0.00%) result.ctrl(0).write_bytes(EMPTY, result.num_ctrl_bytes()); . 4,273 ( 0.00%) Ok(result) . } . } 6,953 ( 0.00%) } . . /// Searches for an empty or deleted bucket which is suitable for inserting . /// a new element and sets the hash for that slot. . /// . /// There must be at least 1 empty bucket in the table. . #[inline] 29,171 ( 0.01%) unsafe fn prepare_insert_slot(&self, hash: u64) -> (usize, u8) { 15 ( 0.00%) let index = self.find_insert_slot(hash); 29,171 ( 0.01%) let old_ctrl = *self.ctrl(index); 5 ( 0.00%) self.set_ctrl_h2(index, hash); 10 ( 0.00%) (index, old_ctrl) 58,312 ( 0.01%) } . . /// Searches for an empty or deleted bucket which is suitable for inserting . /// a new element. . /// . /// There must be at least 1 empty bucket in the table. . #[inline] 96 ( 0.00%) fn find_insert_slot(&self, hash: u64) -> usize { 72 ( 0.00%) let mut probe_seq = self.probe_seq(hash); 24 ( 0.00%) loop { . unsafe { 192 ( 0.00%) let group = Group::load(self.ctrl(probe_seq.pos)); 234,664 ( 0.04%) if let Some(bit) = group.match_empty_or_deleted().lowest_set_bit() { 682,191 ( 0.13%) let result = (probe_seq.pos + bit) & self.bucket_mask; . . // In tables smaller than the group width, trailing control . // bytes outside the range of the table are filled with . // EMPTY entries. These will unfortunately trigger a . // match, but once masked may point to a full bucket that . // is already occupied. We detect this situation here and . // perform a second scan starting at the beginning of the . // table. This second scan is guaranteed to find an empty . // slot (due to the load factor) before hitting the trailing . // control bytes (containing EMPTY). 312,044 ( 0.06%) if unlikely(is_full(*self.ctrl(result))) { . debug_assert!(self.bucket_mask < Group::WIDTH); . debug_assert_ne!(probe_seq.pos, 0); 15 ( 0.00%) return Group::load_aligned(self.ctrl(0)) . .match_empty_or_deleted() . .lowest_set_bit_nonzero(); . } . 46 ( 0.00%) return result; . } . } . probe_seq.move_next(self.bucket_mask); . } 72 ( 0.00%) } . . /// Searches for an element in the table. This uses dynamic dispatch to reduce the amount of . /// code generated, but it is eliminated by LLVM optimizations. . #[inline] 216 ( 0.00%) fn find_inner(&self, hash: u64, eq: &mut dyn FnMut(usize) -> bool) -> Option { 54 ( 0.00%) let h2_hash = h2(hash); 54 ( 0.00%) let mut probe_seq = self.probe_seq(hash); . 8,294 ( 0.00%) loop { 144 ( 0.00%) let group = unsafe { Group::load(self.ctrl(probe_seq.pos)) }; . 437,626 ( 0.08%) for bit in group.match_byte(h2_hash) { 725,156 ( 0.13%) let index = (probe_seq.pos + bit) & self.bucket_mask; . 535,880 ( 0.10%) if likely(eq(index)) { 8 ( 0.00%) return Some(index); . } . } . 183,450 ( 0.03%) if likely(group.match_empty().any_bit_set()) { 14 ( 0.00%) return None; . } . . probe_seq.move_next(self.bucket_mask); . } 72 ( 0.00%) } . . #[allow(clippy::mut_mut)] . #[inline] . unsafe fn prepare_rehash_in_place(&mut self) { . // Bulk convert all full control bytes to DELETED, and all DELETED . // control bytes to EMPTY. This effectively frees up all buckets . // containing a DELETED entry. 3 ( 0.00%) for i in (0..self.buckets()).step_by(Group::WIDTH) { . let group = Group::load_aligned(self.ctrl(i)); . let group = group.convert_special_to_empty_and_full_to_deleted(); . group.store_aligned(self.ctrl(i)); . } . . // Fix up the trailing control bytes. See the comments in set_ctrl . // for the handling of tables smaller than the group width. 3 ( 0.00%) if self.buckets() < Group::WIDTH { . self.ctrl(0) . .copy_to(self.ctrl(Group::WIDTH), self.buckets()); . } else { . self.ctrl(0) . .copy_to(self.ctrl(self.buckets()), Group::WIDTH); . } . } . . #[inline] 20 ( 0.00%) unsafe fn bucket(&self, index: usize) -> Bucket { . debug_assert_ne!(self.bucket_mask, 0); . debug_assert!(index < self.buckets()); 20 ( 0.00%) Bucket::from_base_index(self.data_end(), index) 10 ( 0.00%) } . . #[inline] 36 ( 0.00%) unsafe fn bucket_ptr(&self, index: usize, size_of: usize) -> *mut u8 { . debug_assert_ne!(self.bucket_mask, 0); . debug_assert!(index < self.buckets()); 30 ( 0.00%) let base: *mut u8 = self.data_end().as_ptr(); 871,612 ( 0.16%) base.sub((index + 1) * size_of) 12 ( 0.00%) } . . #[inline] 22 ( 0.00%) unsafe fn data_end(&self) -> NonNull { 55 ( 0.00%) NonNull::new_unchecked(self.ctrl.as_ptr().cast()) 22 ( 0.00%) } . . /// Returns an iterator-like object for a probe sequence on the table. . /// . /// This iterator never terminates, but is guaranteed to visit each bucket . /// group exactly once. The loop using `probe_seq` must terminate upon . /// reaching a group containing an empty bucket. . #[inline] 294 ( 0.00%) fn probe_seq(&self, hash: u64) -> ProbeSeq { 84 ( 0.00%) ProbeSeq { 3,189,594 ( 0.59%) pos: h1(hash) & self.bucket_mask, . stride: 0, . } 168 ( 0.00%) } . . /// Returns the index of a bucket for which a value must be inserted if there is enough rooom . /// in the table, otherwise returns error . #[cfg(feature = "raw")] . #[inline] . unsafe fn prepare_insert_no_grow(&mut self, hash: u64) -> Result { . let index = self.find_insert_slot(hash); . let old_ctrl = *self.ctrl(index); -- line 1260 ---------------------------------------- -- line 1262 ---------------------------------------- . Err(()) . } else { . self.record_item_insert_at(index, old_ctrl, hash); . Ok(index) . } . } . . #[inline] 108 ( 0.00%) unsafe fn record_item_insert_at(&mut self, index: usize, old_ctrl: u8, hash: u64) { 424,646 ( 0.08%) self.growth_left -= special_is_empty(old_ctrl) as usize; 24 ( 0.00%) self.set_ctrl_h2(index, hash); 337,804 ( 0.06%) self.items += 1; 24 ( 0.00%) } . . #[inline] . fn is_in_same_group(&self, i: usize, new_i: usize, hash: u64) -> bool { . let probe_seq_pos = self.probe_seq(hash).pos; . let probe_index = . |pos: usize| (pos.wrapping_sub(probe_seq_pos) & self.bucket_mask) / Group::WIDTH; 6 ( 0.00%) probe_index(i) == probe_index(new_i) . } . . /// Sets a control byte to the hash, and possibly also the replicated control byte at . /// the end of the array. . #[inline] 153 ( 0.00%) unsafe fn set_ctrl_h2(&self, index: usize, hash: u64) { 68 ( 0.00%) self.set_ctrl(index, h2(hash)); 34 ( 0.00%) } . . #[inline] . unsafe fn replace_ctrl_h2(&self, index: usize, hash: u64) -> u8 { . let prev_ctrl = *self.ctrl(index); . self.set_ctrl_h2(index, hash); . prev_ctrl . } . . /// Sets a control byte, and possibly also the replicated control byte at . /// the end of the array. . #[inline] 170 ( 0.00%) unsafe fn set_ctrl(&self, index: usize, ctrl: u8) { . // Replicate the first Group::WIDTH control bytes at the end of . // the array without using a branch: . // - If index >= Group::WIDTH then index == index2. . // - Otherwise index2 == self.bucket_mask + 1 + index. . // . // The very last replicated control byte is never actually read because . // we mask the initial index for unaligned loads, but we write it . // anyways because it makes the set_ctrl implementation simpler. -- line 1309 ---------------------------------------- -- line 1312 ---------------------------------------- . // replicate the buckets at the end of the trailing group. For example . // with 2 buckets and a group size of 4, the control bytes will look . // like this: . // . // Real | Replicated . // --------------------------------------------- . // | [A] | [B] | [EMPTY] | [EMPTY] | [A] | [B] | . // --------------------------------------------- 668,262 ( 0.12%) let index2 = ((index.wrapping_sub(Group::WIDTH)) & self.bucket_mask) + Group::WIDTH; . 222,683 ( 0.04%) *self.ctrl(index) = ctrl; 222,705 ( 0.04%) *self.ctrl(index2) = ctrl; 34 ( 0.00%) } . . /// Returns a pointer to a control byte. . #[inline] 572 ( 0.00%) unsafe fn ctrl(&self, index: usize) -> *mut u8 { . debug_assert!(index < self.num_ctrl_bytes()); 429 ( 0.00%) self.ctrl.as_ptr().add(index) 286 ( 0.00%) } . . #[inline] 56 ( 0.00%) fn buckets(&self) -> usize { 25,900 ( 0.00%) self.bucket_mask + 1 56 ( 0.00%) } . . #[inline] 24 ( 0.00%) fn num_ctrl_bytes(&self) -> usize { 19,737 ( 0.00%) self.bucket_mask + 1 + Group::WIDTH 24 ( 0.00%) } . . #[inline] 50 ( 0.00%) fn is_empty_singleton(&self) -> bool { 111,572 ( 0.02%) self.bucket_mask == 0 100 ( 0.00%) } . . #[allow(clippy::mut_mut)] . #[inline] 170 ( 0.00%) unsafe fn prepare_resize( . &self, . table_layout: TableLayout, . capacity: usize, . fallibility: Fallibility, . ) -> Result, TryReserveError> { 10 ( 0.00%) debug_assert!(self.items <= capacity); . . // Allocate and initialize the new table. 1,641 ( 0.00%) let mut new_table = RawTableInner::fallible_with_capacity( 10 ( 0.00%) self.alloc.clone(), . table_layout, . capacity, . fallibility, . )?; 15,352 ( 0.00%) new_table.growth_left -= self.items; 20 ( 0.00%) new_table.items = self.items; . . // The hash function may panic, in which case we simply free the new . // table without dropping any elements that may have been copied into . // it. . // . // This guard is also used to free the old table on success, see . // the comment at the bottom of this function. 270 ( 0.00%) Ok(guard(new_table, move |self_| { 7,104 ( 0.00%) if !self_.is_empty_singleton() { 3 ( 0.00%) self_.free_buckets(table_layout); . } 20 ( 0.00%) })) 40 ( 0.00%) } . . /// Reserves or rehashes to make room for `additional` more elements. . /// . /// This uses dynamic dispatch to reduce the amount of . /// code generated, but it is eliminated by LLVM optimizations when inlined. . #[allow(clippy::inline_always)] . #[inline(always)] . unsafe fn reserve_rehash_inner( -- line 1387 ---------------------------------------- -- line 1388 ---------------------------------------- . &mut self, . additional: usize, . hasher: &dyn Fn(&mut Self, usize) -> u64, . fallibility: Fallibility, . layout: TableLayout, . drop: Option, . ) -> Result<(), TryReserveError> { . // Avoid `Option::ok_or_else` because it bloats LLVM IR. 14,228 ( 0.00%) let new_items = match self.items.checked_add(additional) { 40 ( 0.00%) Some(new_items) => new_items, . None => return Err(fallibility.capacity_overflow()), . }; 14,158 ( 0.00%) let full_capacity = bucket_mask_to_capacity(self.bucket_mask); 29,510 ( 0.01%) if new_items <= full_capacity / 2 { . // Rehash in-place without re-allocating if we have plenty of spare . // capacity that is locked up due to DELETED entries. . self.rehash_in_place(hasher, layout.size, drop); 2 ( 0.00%) Ok(()) . } else { . // Otherwise, conservatively resize to at least the next size up . // to avoid churning deletes into frequent rehashes. . self.resize_inner( 7,153 ( 0.00%) usize::max(new_items, full_capacity + 1), . hasher, . fallibility, . layout, . ) . } 20 ( 0.00%) } . . /// Allocates a new table of a different size and moves the contents of the . /// current table into it. . /// . /// This uses dynamic dispatch to reduce the amount of . /// code generated, but it is eliminated by LLVM optimizations when inlined. . #[allow(clippy::inline_always)] . #[inline(always)] . unsafe fn resize_inner( . &mut self, . capacity: usize, . hasher: &dyn Fn(&mut Self, usize) -> u64, . fallibility: Fallibility, . layout: TableLayout, . ) -> Result<(), TryReserveError> { 3,573 ( 0.00%) let mut new_table = self.prepare_resize(layout, capacity, fallibility)?; . . // Copy all elements to the new table. 461 ( 0.00%) for i in 0..self.buckets() { 129,530 ( 0.02%) if !is_full(*self.ctrl(i)) { . continue; . } . . // This may panic. 27 ( 0.00%) let hash = hasher(self, i); . . // We can use a simpler version of insert() here since: . // - there are no DELETED entries. . // - we know there is enough space in the table. . // - all elements are unique. 27 ( 0.00%) let (index, _) = new_table.prepare_insert_slot(hash); . 9 ( 0.00%) ptr::copy_nonoverlapping( 9 ( 0.00%) self.bucket_ptr(i, layout.size), 18 ( 0.00%) new_table.bucket_ptr(index, layout.size), . layout.size, . ); . } . . // We successfully copied all elements without panicking. Now replace . // self with the new table. The old table will have its memory freed but . // the items will not be dropped (since they have been moved into the . // new table). 50 ( 0.00%) mem::swap(self, &mut new_table); . 7,073 ( 0.00%) Ok(()) 40 ( 0.00%) } . . /// Rehashes the contents of the table in place (i.e. without changing the . /// allocation). . /// . /// If `hasher` panics then some the table's contents may be lost. . /// . /// This uses dynamic dispatch to reduce the amount of . /// code generated, but it is eliminated by LLVM optimizations when inlined. -- line 1471 ---------------------------------------- -- line 1496 ---------------------------------------- . } . self_.growth_left = bucket_mask_to_capacity(self_.bucket_mask) - self_.items; . }); . . // At this point, DELETED elements are elements that we haven't . // rehashed yet. Find them and re-insert them at their ideal . // position. . 'outer: for i in 0..guard.buckets() { 64 ( 0.00%) if *guard.ctrl(i) != DELETED { . continue; . } . . let i_p = guard.bucket_ptr(i, size_of); . . 'inner: loop { . // Hash the current item . let hash = hasher(*guard, i); -- line 1512 ---------------------------------------- -- line 1515 ---------------------------------------- . let new_i = guard.find_insert_slot(hash); . let new_i_p = guard.bucket_ptr(new_i, size_of); . . // Probing works by scanning through all of the control . // bytes in groups, which may not be aligned to the group . // size. If both the new and old position fall within the . // same unaligned group, then there is no benefit in moving . // it and we can just continue to the next item. 2 ( 0.00%) if likely(guard.is_in_same_group(i, new_i, hash)) { . guard.set_ctrl_h2(i, hash); . continue 'outer; . } . . // We are moving the current item to a new position. Write . // our H2 to the control byte of the new position. . let prev_ctrl = guard.replace_ctrl_h2(new_i, hash); . if prev_ctrl == EMPTY { -- line 1531 ---------------------------------------- -- line 1541 ---------------------------------------- . // swapped into the old slot. . debug_assert_eq!(prev_ctrl, DELETED); . ptr::swap_nonoverlapping(i_p, new_i_p, size_of); . continue 'inner; . } . } . } . 3 ( 0.00%) guard.growth_left = bucket_mask_to_capacity(guard.bucket_mask) - guard.items; . . mem::forget(guard); . } . . #[inline] 42 ( 0.00%) unsafe fn free_buckets(&mut self, table_layout: TableLayout) { . // Avoid `Option::unwrap_or_else` because it bloats LLVM IR. 120 ( 0.00%) let (layout, ctrl_offset) = match table_layout.calculate_layout_for(self.buckets()) { 72 ( 0.00%) Some(lco) => lco, . None => hint::unreachable_unchecked(), . }; 18 ( 0.00%) self.alloc.deallocate( 4,297 ( 0.00%) NonNull::new_unchecked(self.ctrl.as_ptr().sub(ctrl_offset)), . layout, . ); 12 ( 0.00%) } . . /// Marks all table buckets as empty without dropping their contents. . #[inline] 12 ( 0.00%) fn clear_no_drop(&mut self) { 583 ( 0.00%) if !self.is_empty_singleton() { . unsafe { 12 ( 0.00%) self.ctrl(0).write_bytes(EMPTY, self.num_ctrl_bytes()); . } . } 723 ( 0.00%) self.items = 0; 592 ( 0.00%) self.growth_left = bucket_mask_to_capacity(self.bucket_mask); 8 ( 0.00%) } . . #[inline] . unsafe fn erase(&mut self, index: usize) { . debug_assert!(is_full(*self.ctrl(index))); 22,764 ( 0.00%) let index_before = index.wrapping_sub(Group::WIDTH) & self.bucket_mask; . let empty_before = Group::load(self.ctrl(index_before)).match_empty(); . let empty_after = Group::load(self.ctrl(index)).match_empty(); . . // If we are inside a continuous block of Group::WIDTH full or deleted . // cells then a probe window may have seen a full block when trying to . // insert. We therefore need to keep that block non-empty so that . // lookups will continue searching to the next probe window. . // . // Note that in this context `leading_zeros` refers to the bytes at the . // end of a group, while `trailing_zeros` refers to the bytes at the . // beginning of a group. 91,056 ( 0.02%) let ctrl = if empty_before.leading_zeros() + empty_after.trailing_zeros() >= Group::WIDTH { . DELETED . } else { 113,245 ( 0.02%) self.growth_left += 1; . EMPTY . }; . self.set_ctrl(index, ctrl); 91,056 ( 0.02%) self.items -= 1; . } . } . . impl Clone for RawTable { 480 ( 0.00%) fn clone(&self) -> Self { 63 ( 0.00%) if self.table.is_empty_singleton() { . Self::new_in(self.table.alloc.clone()) . } else { . unsafe { . let mut new_table = ManuallyDrop::new( . // Avoid `Result::ok_or_else` because it bloats LLVM IR. . match Self::new_uninitialized( . self.table.alloc.clone(), . self.table.buckets(), -- line 1615 ---------------------------------------- -- line 1624 ---------------------------------------- . // We need to free the memory allocated for the new table. . new_table.free_buckets(); . }); . . // Return the newly created table. . ManuallyDrop::into_inner(new_table) . } . } 540 ( 0.00%) } . . fn clone_from(&mut self, source: &Self) { . if source.table.is_empty_singleton() { . *self = Self::new_in(self.table.alloc.clone()); . } else { . unsafe { . // First, drop all our elements without clearing the control bytes. . self.drop_elements(); -- line 1640 ---------------------------------------- -- line 1687 ---------------------------------------- . .table . .ctrl(0) . .copy_to_nonoverlapping(self.table.ctrl(0), self.table.num_ctrl_bytes()); . source . .data_start() . .copy_to_nonoverlapping(self.data_start(), self.table.buckets()); . . self.table.items = source.table.items; 10 ( 0.00%) self.table.growth_left = source.table.growth_left; . } . } . . impl RawTable { . /// Common code for clone and clone_from. Assumes `self.buckets() == source.buckets()`. . #[cfg_attr(feature = "inline-more", inline)] . unsafe fn clone_from_impl(&mut self, source: &Self, mut on_panic: impl FnMut(&mut Self)) { . // Copy the control bytes unchanged. We do this in a single pass -- line 1703 ---------------------------------------- -- line 1790 ---------------------------------------- . fn default() -> Self { . Self::new_in(Default::default()) . } . } . . #[cfg(feature = "nightly")] . unsafe impl<#[may_dangle] T, A: Allocator + Clone> Drop for RawTable { . #[cfg_attr(feature = "inline-more", inline)] 62,631 ( 0.01%) fn drop(&mut self) { 47,441 ( 0.01%) if !self.table.is_empty_singleton() { . unsafe { 5 ( 0.00%) self.drop_elements(); 5 ( 0.00%) self.free_buckets(); . } . } 67,268 ( 0.01%) } . } . #[cfg(not(feature = "nightly"))] . impl Drop for RawTable { . #[cfg_attr(feature = "inline-more", inline)] . fn drop(&mut self) { . if !self.table.is_empty_singleton() { . unsafe { . self.drop_elements(); -- line 1813 ---------------------------------------- -- line 1817 ---------------------------------------- . } . } . . impl IntoIterator for RawTable { . type Item = T; . type IntoIter = RawIntoIter; . . #[cfg_attr(feature = "inline-more", inline)] 988 ( 0.00%) fn into_iter(self) -> RawIntoIter { . unsafe { 25 ( 0.00%) let iter = self.iter(); 75 ( 0.00%) self.into_iter_from(iter) . } 1,220 ( 0.00%) } . } . . /// Iterator over a sub-range of a table. Unlike `RawIter` this iterator does . /// not track an item count. . pub(crate) struct RawIterRange { . // Mask of full buckets in the current group. Bits are cleared from this . // mask as each element is processed. . current_group: BitMask, -- line 1838 ---------------------------------------- -- line 1848 ---------------------------------------- . end: *const u8, . } . . impl RawIterRange { . /// Returns a `RawIterRange` covering a subset of a table. . /// . /// The control byte address must be aligned to the group size. . #[cfg_attr(feature = "inline-more", inline)] 96 ( 0.00%) unsafe fn new(ctrl: *const u8, data: Bucket, len: usize) -> Self { . debug_assert_ne!(len, 0); . debug_assert_eq!(ctrl as usize % Group::WIDTH, 0); 8 ( 0.00%) let end = ctrl.add(len); . . // Load the first group and advance ctrl to point to the next group 48 ( 0.00%) let current_group = Group::load_aligned(ctrl).match_full(); 8 ( 0.00%) let next_ctrl = ctrl.add(Group::WIDTH); . 32 ( 0.00%) Self { . current_group, . data, . next_ctrl, . end, . } 16 ( 0.00%) } . . /// Splits a `RawIterRange` into two halves. . /// . /// Returns `None` if the remaining range is smaller than or equal to the . /// group width. . #[cfg_attr(feature = "inline-more", inline)] . #[cfg(feature = "rayon")] . pub(crate) fn split(mut self) -> (Self, Option>) { -- line 1879 ---------------------------------------- -- line 1931 ---------------------------------------- . } . } . } . . impl Iterator for RawIterRange { . type Item = Bucket; . . #[cfg_attr(feature = "inline-more", inline)] 60 ( 0.00%) fn next(&mut self) -> Option> { . unsafe { . loop { 19,213 ( 0.00%) if let Some(index) = self.current_group.lowest_set_bit() { 2,289 ( 0.00%) self.current_group = self.current_group.remove_lowest_bit(); 3,303 ( 0.00%) return Some(self.data.next_n(index)); . } . 13,933 ( 0.00%) if self.next_ctrl >= self.end { 8 ( 0.00%) return None; . } . . // We might read past self.end up to the next group boundary, . // but this is fine because it only occurs on tables smaller . // than the group size where the trailing control bytes are all . // EMPTY. On larger tables self.end is guaranteed to be aligned . // to the group size (since tables are power-of-two sized). 714 ( 0.00%) self.current_group = Group::load_aligned(self.next_ctrl).match_full(); 172 ( 0.00%) self.data = self.data.next_n(Group::WIDTH); 1,791 ( 0.00%) self.next_ctrl = self.next_ctrl.add(Group::WIDTH); . } . } 45 ( 0.00%) } . . #[inline] . fn size_hint(&self) -> (usize, Option) { . // We don't have an item count, so just guess based on the range size. . ( . 0, . Some(unsafe { offset_from(self.end, self.next_ctrl) + Group::WIDTH }), . ) -- line 1969 ---------------------------------------- -- line 2101 ---------------------------------------- . } . } . } else { . // We must have already iterated past the removed item. . } . } . } . 10 ( 0.00%) unsafe fn drop_elements(&mut self) { 517 ( 0.00%) if mem::needs_drop::() && self.len() != 0 { . for item in self { . item.drop(); . } . } 10 ( 0.00%) } . } . . impl Clone for RawIter { . #[cfg_attr(feature = "inline-more", inline)] . fn clone(&self) -> Self { . Self { . iter: self.iter.clone(), . items: self.items, -- line 2123 ---------------------------------------- -- line 2124 ---------------------------------------- . } . } . } . . impl Iterator for RawIter { . type Item = Bucket; . . #[cfg_attr(feature = "inline-more", inline)] 2,417 ( 0.00%) fn next(&mut self) -> Option> { 5,428 ( 0.00%) if let Some(b) = self.iter.next() { 23,925 ( 0.00%) self.items -= 1; 7 ( 0.00%) Some(b) . } else { . // We don't check against items == 0 here to allow the . // compiler to optimize away the item count entirely if the . // iterator length is never queried. . debug_assert_eq!(self.items, 0); 8 ( 0.00%) None . } 4,789 ( 0.00%) } . . #[inline] 24 ( 0.00%) fn size_hint(&self) -> (usize, Option) { 72 ( 0.00%) (self.items, Some(self.items)) 16 ( 0.00%) } . } . . impl ExactSizeIterator for RawIter {} . impl FusedIterator for RawIter {} . . /// Iterator which consumes a table and returns elements. . pub struct RawIntoIter { . iter: RawIter, -- line 2156 ---------------------------------------- -- line 2177 ---------------------------------------- . T: Sync, . A: Sync, . { . } . . #[cfg(feature = "nightly")] . unsafe impl<#[may_dangle] T, A: Allocator + Clone> Drop for RawIntoIter { . #[cfg_attr(feature = "inline-more", inline)] 781 ( 0.00%) fn drop(&mut self) { . unsafe { . // Drop all remaining elements 5 ( 0.00%) self.iter.drop_elements(); . . // Free the table 1,452 ( 0.00%) if let Some((ptr, layout)) = self.allocation { 8 ( 0.00%) self.alloc.deallocate(ptr, layout); . } . } 224 ( 0.00%) } . } . #[cfg(not(feature = "nightly"))] . impl Drop for RawIntoIter { . #[cfg_attr(feature = "inline-more", inline)] . fn drop(&mut self) { . unsafe { . // Drop all remaining elements . self.iter.drop_elements(); -- line 2203 ---------------------------------------- -- line 2209 ---------------------------------------- . } . } . } . . impl Iterator for RawIntoIter { . type Item = T; . . #[cfg_attr(feature = "inline-more", inline)] 275 ( 0.00%) fn next(&mut self) -> Option { 217 ( 0.00%) unsafe { Some(self.iter.next()?.read()) } 579 ( 0.00%) } . . #[inline] 12 ( 0.00%) fn size_hint(&self) -> (usize, Option) { 7 ( 0.00%) self.iter.size_hint() 6 ( 0.00%) } . } . . impl ExactSizeIterator for RawIntoIter {} . impl FusedIterator for RawIntoIter {} . . /// Iterator which consumes elements without freeing the table storage. . pub struct RawDrain<'a, T, A: Allocator + Clone = Global> { . iter: RawIter, -- line 2232 ---------------------------------------- -- line 2259 ---------------------------------------- . where . T: Sync, . A: Sync, . { . } . . impl Drop for RawDrain<'_, T, A> { . #[cfg_attr(feature = "inline-more", inline)] 168 ( 0.00%) fn drop(&mut self) { . unsafe { . // Drop all remaining elements. Note that this may panic. . self.iter.drop_elements(); . . // Reset the contents of the table now that all elements have been . // dropped. . self.table.clear_no_drop(); . . // Move the now empty table back to its original location. 21 ( 0.00%) self.orig_table . .as_ptr() . .copy_from_nonoverlapping(&*self.table, 1); . } 168 ( 0.00%) } . } . . impl Iterator for RawDrain<'_, T, A> { . type Item = T; . . #[cfg_attr(feature = "inline-more", inline)] . fn next(&mut self) -> Option { . unsafe { -- line 2289 ---------------------------------------- 1,645,953 ( 0.31%) -------------------------------------------------------------------------------- -- Auto-annotated source: /usr/home/liquid/rust/worktree-benchmarking/library/core/src/fmt/num.rs -------------------------------------------------------------------------------- Ir -- line 34 ---------------------------------------- . })* . ) . } . macro_rules! impl_uint { . ($($t:ident)*) => ( . $(impl DisplayInt for $t { . fn zero() -> Self { 0 } . fn from_u8(u: u8) -> Self { u as Self } 130,582 ( 0.02%) fn to_u8(&self) -> u8 { *self as u8 } . fn to_u16(&self) -> u16 { *self as u16 } . fn to_u32(&self) -> u32 { *self as u32 } 1,477 ( 0.00%) fn to_u64(&self) -> u64 { *self as u64 } . fn to_u128(&self) -> u128 { *self as u128 } . })* . ) . } . . impl_int! { i8 i16 i32 i64 i128 isize } . impl_uint! { u8 u16 u32 u64 u128 usize } . -- line 53 ---------------------------------------- -- line 75 ---------------------------------------- . if is_nonnegative { . // Accumulate each digit of the number from the least significant . // to the most significant figure. . for byte in buf.iter_mut().rev() { . let n = x % base; // Get the current place value. . x = x / base; // Deaccumulate the number. . byte.write(Self::digit(n.to_u8())); // Store the digit in the buffer. . curr -= 1; 133,052 ( 0.02%) if x == zero { . // No more digits left to accumulate. . break; . }; . } . } else { . // Do the same as above, but accounting for two's complement. . for byte in buf.iter_mut().rev() { . let n = zero - (x % base); // Get the current place value. -- line 91 ---------------------------------------- -- line 102 ---------------------------------------- . // SAFETY: The only chars in `buf` are created by `Self::digit` which are assumed to be . // valid UTF-8 . let buf = unsafe { . str::from_utf8_unchecked(slice::from_raw_parts( . MaybeUninit::slice_as_ptr(buf), . buf.len(), . )) . }; 23,735 ( 0.00%) f.pad_integral(is_nonnegative, Self::PREFIX, buf) . } . } . . /// A binary (base 2) radix . #[derive(Clone, PartialEq)] . struct Binary; . . /// An octal (base 8) radix -- line 118 ---------------------------------------- -- line 139 ---------------------------------------- . } . } . } . } . } . . radix! { Binary, 2, "0b", x @ 0 ..= 1 => b'0' + x } . radix! { Octal, 8, "0o", x @ 0 ..= 7 => b'0' + x } 199,578 ( 0.04%) radix! { LowerHex, 16, "0x", x @ 0 ..= 9 => b'0' + x, x @ 10 ..= 15 => b'a' + (x - 10) } . radix! { UpperHex, 16, "0x", x @ 0 ..= 9 => b'0' + x, x @ 10 ..= 15 => b'A' + (x - 10) } . . macro_rules! int_base { . (fmt::$Trait:ident for $T:ident as $U:ident -> $Radix:ident) => { . #[stable(feature = "rust1", since = "1.0.0")] . impl fmt::$Trait for $T { 4,747 ( 0.00%) fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 4,747 ( 0.00%) $Radix.fmt_int(*self as $U, f) 9,494 ( 0.00%) } . } . }; . } . . macro_rules! integer { . ($Int:ident, $Uint:ident) => { . int_base! { fmt::Binary for $Int as $Uint -> Binary } . int_base! { fmt::Octal for $Int as $Uint -> Octal } -- line 164 ---------------------------------------- -- line 203 ---------------------------------------- . static DEC_DIGITS_LUT: &[u8; 200] = b"0001020304050607080910111213141516171819\ . 2021222324252627282930313233343536373839\ . 4041424344454647484950515253545556575859\ . 6061626364656667686970717273747576777879\ . 8081828384858687888990919293949596979899"; . . macro_rules! impl_Display { . ($($t:ident),* as $u:ident via $conv_fn:ident named $name:ident) => { 5,908 ( 0.00%) fn $name(mut n: $u, is_nonnegative: bool, f: &mut fmt::Formatter<'_>) -> fmt::Result { . // 2^128 is about 3*10^38, so 39 gives an extra byte of space . let mut buf = [MaybeUninit::::uninit(); 39]; . let mut curr = buf.len() as isize; . let buf_ptr = MaybeUninit::slice_as_mut_ptr(&mut buf); . let lut_ptr = DEC_DIGITS_LUT.as_ptr(); . . // SAFETY: Since `d1` and `d2` are always less than or equal to `198`, we . // can copy from `lut_ptr[d1..d1 + 1]` and `lut_ptr[d2..d2 + 1]`. To show -- line 219 ---------------------------------------- -- line 222 ---------------------------------------- . // each step this is kept the same as `n` is divided. Since `n` is always . // non-negative, this means that `curr > 0` so `buf_ptr[curr..curr + 1]` . // is safe to access. . unsafe { . // need at least 16 bits for the 4-characters-at-a-time to work. . assert!(crate::mem::size_of::<$u>() >= 2); . . // eagerly decode 4 characters at a time 2,954 ( 0.00%) while n >= 10000 { . let rem = (n % 10000) as isize; . n /= 10000; . . let d1 = (rem / 100) << 1; . let d2 = (rem % 100) << 1; . curr -= 4; . . // We are allowed to copy to `buf_ptr[curr..curr + 3]` here since -- line 238 ---------------------------------------- -- line 241 ---------------------------------------- . ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2); . ptr::copy_nonoverlapping(lut_ptr.offset(d2), buf_ptr.offset(curr + 2), 2); . } . . // if we reach here numbers are <= 9999, so at most 4 chars long . let mut n = n as isize; // possibly reduce 64bit math . . // decode 2 more chars, if > 2 chars 2,954 ( 0.00%) if n >= 100 { 216 ( 0.00%) let d1 = (n % 100) << 1; 540 ( 0.00%) n /= 100; 216 ( 0.00%) curr -= 2; . ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2); . } . . // decode last 1 or 2 chars 2,954 ( 0.00%) if n < 10 { 2,266 ( 0.00%) curr -= 1; 3,399 ( 0.00%) *buf_ptr.offset(curr) = (n as u8) + b'0'; . } else { . let d1 = n << 1; 688 ( 0.00%) curr -= 2; . ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2); . } . } . . // SAFETY: `curr` > 0 (since we made `buf` large enough), and all the chars are valid . // UTF-8 since `DEC_DIGITS_LUT` is . let buf_slice = unsafe { . str::from_utf8_unchecked( 2,954 ( 0.00%) slice::from_raw_parts(buf_ptr.offset(curr), buf.len() - curr as usize)) . }; 7,385 ( 0.00%) f.pad_integral(is_nonnegative, "", buf_slice) 4,431 ( 0.00%) } . . $(#[stable(feature = "rust1", since = "1.0.0")] . impl fmt::Display for $t { . #[allow(unused_comparisons)] 1,477 ( 0.00%) fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { . let is_nonnegative = *self >= 0; . let n = if is_nonnegative { . self.$conv_fn() . } else { . // convert the negative num to positive by summing 1 to it's 2 complement . (!self.$conv_fn()).wrapping_add(1) . }; 2,954 ( 0.00%) $name(n, is_nonnegative, f) . } . })* . }; . } . . macro_rules! impl_Exp { . ($($t:ident),* as $u:ident via $conv_fn:ident named $name:ident) => { . fn $name( -- line 295 ---------------------------------------- -- line 474 ---------------------------------------- . impl_Display!(i8, u8, i16, u16, i32, u32, isize, usize as u32 via to_u32 named fmt_u32); . impl_Display!(i64, u64 as u64 via to_u64 named fmt_u64); . impl_Exp!(i8, u8, i16, u16, i32, u32, isize, usize as u32 via to_u32 named exp_u32); . impl_Exp!(i64, u64 as u64 via to_u64 named exp_u64); . } . impl_Exp!(i128, u128 as u128 via to_u128 named exp_u128); . . /// Helper function for writing a u64 into `buf` going from last to first, with `curr`. 7 ( 0.00%) fn parse_u64_into(mut n: u64, buf: &mut [MaybeUninit; N], curr: &mut isize) { . let buf_ptr = MaybeUninit::slice_as_mut_ptr(buf); . let lut_ptr = DEC_DIGITS_LUT.as_ptr(); 3 ( 0.00%) assert!(*curr > 19); . . // SAFETY: . // Writes at most 19 characters into the buffer. Guaranteed that any ptr into LUT is at most . // 198, so will never OOB. There is a check above that there are at least 19 characters . // remaining. . unsafe { 2 ( 0.00%) if n >= 1e16 as u64 { . let to_parse = n % 1e16 as u64; . n /= 1e16 as u64; . . // Some of these are nops but it looks more elegant this way. . let d1 = ((to_parse / 1e14 as u64) % 100) << 1; . let d2 = ((to_parse / 1e12 as u64) % 100) << 1; . let d3 = ((to_parse / 1e10 as u64) % 100) << 1; . let d4 = ((to_parse / 1e8 as u64) % 100) << 1; -- line 500 ---------------------------------------- -- line 509 ---------------------------------------- . ptr::copy_nonoverlapping(lut_ptr.offset(d2 as isize), buf_ptr.offset(*curr + 2), 2); . ptr::copy_nonoverlapping(lut_ptr.offset(d3 as isize), buf_ptr.offset(*curr + 4), 2); . ptr::copy_nonoverlapping(lut_ptr.offset(d4 as isize), buf_ptr.offset(*curr + 6), 2); . ptr::copy_nonoverlapping(lut_ptr.offset(d5 as isize), buf_ptr.offset(*curr + 8), 2); . ptr::copy_nonoverlapping(lut_ptr.offset(d6 as isize), buf_ptr.offset(*curr + 10), 2); . ptr::copy_nonoverlapping(lut_ptr.offset(d7 as isize), buf_ptr.offset(*curr + 12), 2); . ptr::copy_nonoverlapping(lut_ptr.offset(d8 as isize), buf_ptr.offset(*curr + 14), 2); . } 2 ( 0.00%) if n >= 1e8 as u64 { . let to_parse = n % 1e8 as u64; . n /= 1e8 as u64; . . // Some of these are nops but it looks more elegant this way. . let d1 = ((to_parse / 1e6 as u64) % 100) << 1; . let d2 = ((to_parse / 1e4 as u64) % 100) << 1; . let d3 = ((to_parse / 1e2 as u64) % 100) << 1; . let d4 = ((to_parse / 1e0 as u64) % 100) << 1; -- line 525 ---------------------------------------- -- line 527 ---------------------------------------- . . ptr::copy_nonoverlapping(lut_ptr.offset(d1 as isize), buf_ptr.offset(*curr + 0), 2); . ptr::copy_nonoverlapping(lut_ptr.offset(d2 as isize), buf_ptr.offset(*curr + 2), 2); . ptr::copy_nonoverlapping(lut_ptr.offset(d3 as isize), buf_ptr.offset(*curr + 4), 2); . ptr::copy_nonoverlapping(lut_ptr.offset(d4 as isize), buf_ptr.offset(*curr + 6), 2); . } . // `n` < 1e8 < (1 << 32) . let mut n = n as u32; 2 ( 0.00%) if n >= 1e4 as u32 { . let to_parse = n % 1e4 as u32; . n /= 1e4 as u32; . . let d1 = (to_parse / 100) << 1; . let d2 = (to_parse % 100) << 1; . *curr -= 4; . . ptr::copy_nonoverlapping(lut_ptr.offset(d1 as isize), buf_ptr.offset(*curr + 0), 2); . ptr::copy_nonoverlapping(lut_ptr.offset(d2 as isize), buf_ptr.offset(*curr + 2), 2); . } . . // `n` < 1e4 < (1 << 16) . let mut n = n as u16; 2 ( 0.00%) if n >= 100 { . let d1 = (n % 100) << 1; . n /= 100; . *curr -= 2; . ptr::copy_nonoverlapping(lut_ptr.offset(d1 as isize), buf_ptr.offset(*curr), 2); . } . . // decode last 1 or 2 chars 2 ( 0.00%) if n < 10 { . *curr -= 1; . *buf_ptr.offset(*curr) = (n as u8) + b'0'; . } else { . let d1 = n << 1; 2 ( 0.00%) *curr -= 2; 1 ( 0.00%) ptr::copy_nonoverlapping(lut_ptr.offset(d1 as isize), buf_ptr.offset(*curr), 2); . } . } 8 ( 0.00%) } . . #[stable(feature = "rust1", since = "1.0.0")] . impl fmt::Display for u128 { 1 ( 0.00%) fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 5 ( 0.00%) fmt_u128(*self, true, f) . } . } . . #[stable(feature = "rust1", since = "1.0.0")] . impl fmt::Display for i128 { . fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { . let is_nonnegative = *self >= 0; . let n = if is_nonnegative { -- line 579 ---------------------------------------- -- line 585 ---------------------------------------- . fmt_u128(n, is_nonnegative, f) . } . } . . /// Specialized optimization for u128. Instead of taking two items at a time, it splits . /// into at most 2 u64s, and then chunks by 10e16, 10e8, 10e4, 10e2, and then 10e1. . /// It also has to handle 1 last item, as 10^40 > 2^128 > 10^39, whereas . /// 10^20 > 2^64 > 10^19. 9 ( 0.00%) fn fmt_u128(n: u128, is_nonnegative: bool, f: &mut fmt::Formatter<'_>) -> fmt::Result { . // 2^128 is about 3*10^38, so 39 gives an extra byte of space . let mut buf = [MaybeUninit::::uninit(); 39]; 2 ( 0.00%) let mut curr = buf.len() as isize; . . let (n, rem) = udiv_1e19(n); 1 ( 0.00%) parse_u64_into(rem, &mut buf, &mut curr); . 3 ( 0.00%) if n != 0 { . // 0 pad up to point . let target = (buf.len() - 19) as isize; . // SAFETY: Guaranteed that we wrote at most 19 bytes, and there must be space . // remaining since it has length 39 . unsafe { . ptr::write_bytes( . MaybeUninit::slice_as_mut_ptr(&mut buf).offset(target), . b'0', -- line 609 ---------------------------------------- -- line 629 ---------------------------------------- . } . } . } . . // SAFETY: `curr` > 0 (since we made `buf` large enough), and all the chars are valid . // UTF-8 since `DEC_DIGITS_LUT` is . let buf_slice = unsafe { . str::from_utf8_unchecked(slice::from_raw_parts( 2 ( 0.00%) MaybeUninit::slice_as_mut_ptr(&mut buf).offset(curr), 2 ( 0.00%) buf.len() - curr as usize, . )) . }; 5 ( 0.00%) f.pad_integral(is_nonnegative, "", buf_slice) 8 ( 0.00%) } . . /// Partition of `n` into n > 1e19 and rem <= 1e19 . /// . /// Integer division algorithm is based on the following paper: . /// . /// T. Granlund and P. Montgomery, “Division by Invariant Integers Using Multiplication” . /// in Proc. of the SIGPLAN94 Conference on Programming Language Design and . /// Implementation, 1994, pp. 61–72 . /// . fn udiv_1e19(n: u128) -> (u128, u64) { . const DIV: u64 = 1e19 as u64; . const FACTOR: u128 = 156927543384667019095894735580191660403; . 2 ( 0.00%) let quot = if n < 1 << 83 { 7 ( 0.00%) ((n >> 19) as u64 / (DIV >> 19)) as u128 . } else { . u128_mulhi(n, FACTOR) >> 62 . }; . 8 ( 0.00%) let rem = (n - quot * DIV as u128) as u64; . (quot, rem) . } . . /// Multiply unsigned 128 bit integers, return upper 128 bits of the result . #[inline] . fn u128_mulhi(x: u128, y: u128) -> u128 { . let x_lo = x as u64; . let x_hi = (x >> 64) as u64; -- line 670 ---------------------------------------- 72,755 ( 0.01%) -------------------------------------------------------------------------------- -- Auto-annotated source: /usr/home/liquid/rust/worktree-benchmarking/library/std/src/sys/unix/alloc.rs -------------------------------------------------------------------------------- Ir -- line 5 ---------------------------------------- . #[stable(feature = "alloc_system_type", since = "1.28.0")] . unsafe impl GlobalAlloc for System { . #[inline] . unsafe fn alloc(&self, layout: Layout) -> *mut u8 { . // jemalloc provides alignment less than MIN_ALIGN for small allocations. . // So only rely on MIN_ALIGN if size >= align. . // Also see and . // . 370,502 ( 0.07%) if layout.align() <= MIN_ALIGN && layout.align() <= layout.size() { 277,875 ( 0.05%) libc::malloc(layout.size()) as *mut u8 . } else { . #[cfg(target_os = "macos")] . { . if layout.align() > (1 << 31) { . return ptr::null_mut(); . } . } . aligned_malloc(&layout) . } . } . . #[inline] . unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 { . // See the comment above in `alloc` for why this check looks the way it does. 13,264 ( 0.00%) if layout.align() <= MIN_ALIGN && layout.align() <= layout.size() { 19,896 ( 0.00%) libc::calloc(layout.size(), 1) as *mut u8 . } else { . let ptr = self.alloc(layout); . if !ptr.is_null() { . ptr::write_bytes(ptr, 0, layout.size()); . } . ptr . } . } . . #[inline] . unsafe fn dealloc(&self, ptr: *mut u8, _layout: Layout) { 95,930 ( 0.02%) libc::free(ptr as *mut libc::c_void) . } . . #[inline] . unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 { 41,688 ( 0.01%) if layout.align() <= MIN_ALIGN && layout.align() <= new_size { 83,376 ( 0.02%) libc::realloc(ptr as *mut libc::c_void, new_size) as *mut u8 . } else { . realloc_fallback(self, ptr, layout, new_size) . } . } . } . . cfg_if::cfg_if! { . if #[cfg(any( -- line 56 ---------------------------------------- -- line 84 ---------------------------------------- . } else if #[cfg(target_os = "wasi")] { . #[inline] . unsafe fn aligned_malloc(layout: &Layout) -> *mut u8 { . libc::aligned_alloc(layout.align(), layout.size()) as *mut u8 . } . } else { . #[inline] . unsafe fn aligned_malloc(layout: &Layout) -> *mut u8 { 1 ( 0.00%) let mut out = ptr::null_mut(); . // posix_memalign requires that the alignment be a multiple of `sizeof(void*)`. . // Since these are all powers of 2, we can just use max. . let align = layout.align().max(crate::mem::size_of::()); 2 ( 0.00%) let ret = libc::posix_memalign(&mut out, align, layout.size()); 2 ( 0.00%) if ret != 0 { ptr::null_mut() } else { out as *mut u8 } . } . } . } 1 ( 0.00%) -------------------------------------------------------------------------------- -- Auto-annotated source: /usr/home/liquid/rust/worktree-benchmarking/library/alloc/src/vec/mod.rs -------------------------------------------------------------------------------- Ir -- line 416 ---------------------------------------- . /// ``` . /// # #![allow(unused_mut)] . /// let mut vec: Vec = Vec::new(); . /// ``` . #[inline] . #[rustc_const_stable(feature = "const_vec_new", since = "1.39.0")] . #[stable(feature = "rust1", since = "1.0.0")] . #[must_use] 195 ( 0.00%) pub const fn new() -> Self { 233,317 ( 0.04%) Vec { buf: RawVec::NEW, len: 0 } 237 ( 0.00%) } . . /// Constructs a new, empty `Vec` with the specified capacity. . /// . /// The vector will be able to hold exactly `capacity` elements without . /// reallocating. If `capacity` is 0, the vector will not allocate. . /// . /// It is important to note that although the returned vector has the . /// *capacity* specified, the vector will have a zero *length*. For an -- line 434 ---------------------------------------- -- line 461 ---------------------------------------- . /// vec.push(11); . /// assert_eq!(vec.len(), 11); . /// assert!(vec.capacity() >= 11); . /// ``` . #[cfg(not(no_global_oom_handling))] . #[inline] . #[stable(feature = "rust1", since = "1.0.0")] . #[must_use] 16 ( 0.00%) pub fn with_capacity(capacity: usize) -> Self { 4 ( 0.00%) Self::with_capacity_in(capacity, Global) 8 ( 0.00%) } . . /// Creates a `Vec` directly from the raw components of another vector. . /// . /// # Safety . /// . /// This is highly unsafe, due to the number of invariants that aren't . /// checked: . /// -- line 479 ---------------------------------------- -- line 529 ---------------------------------------- . /// . /// // Put everything back together into a Vec . /// let rebuilt = Vec::from_raw_parts(p, len, cap); . /// assert_eq!(rebuilt, [4, 5, 6]); . /// } . /// ``` . #[inline] . #[stable(feature = "rust1", since = "1.0.0")] 18 ( 0.00%) pub unsafe fn from_raw_parts(ptr: *mut T, length: usize, capacity: usize) -> Self { 3 ( 0.00%) unsafe { Self::from_raw_parts_in(ptr, length, capacity, Global) } 6 ( 0.00%) } . } . . impl Vec { . /// Constructs a new, empty `Vec`. . /// . /// The vector will not allocate until elements are pushed onto it. . /// . /// # Examples -- line 547 ---------------------------------------- -- line 600 ---------------------------------------- . /// // ...but this may make the vector reallocate . /// vec.push(11); . /// assert_eq!(vec.len(), 11); . /// assert!(vec.capacity() >= 11); . /// ``` . #[cfg(not(no_global_oom_handling))] . #[inline] . #[unstable(feature = "allocator_api", issue = "32838")] 315 ( 0.00%) pub fn with_capacity_in(capacity: usize, alloc: A) -> Self { 131,172 ( 0.02%) Vec { buf: RawVec::with_capacity_in(capacity, alloc), len: 0 } 90 ( 0.00%) } . . /// Creates a `Vec` directly from the raw components of another vector. . /// . /// # Safety . /// . /// This is highly unsafe, due to the number of invariants that aren't . /// checked: . /// -- line 618 ---------------------------------------- -- line 676 ---------------------------------------- . /// . /// // Put everything back together into a Vec . /// let rebuilt = Vec::from_raw_parts_in(p, len, cap, alloc.clone()); . /// assert_eq!(rebuilt, [4, 5, 6]); . /// } . /// ``` . #[inline] . #[unstable(feature = "allocator_api", issue = "32838")] 143 ( 0.00%) pub unsafe fn from_raw_parts_in(ptr: *mut T, length: usize, capacity: usize, alloc: A) -> Self { 5,501 ( 0.00%) unsafe { Vec { buf: RawVec::from_raw_parts_in(ptr, capacity, alloc), len: length } } 22 ( 0.00%) } . . /// Decomposes a `Vec` into its raw components. . /// . /// Returns the raw pointer to the underlying data, the length of . /// the vector (in elements), and the allocated capacity of the . /// data (in elements). These are the same arguments in the same . /// order as the arguments to [`from_raw_parts`]. . /// -- line 694 ---------------------------------------- -- line 777 ---------------------------------------- . /// # Examples . /// . /// ``` . /// let vec: Vec = Vec::with_capacity(10); . /// assert_eq!(vec.capacity(), 10); . /// ``` . #[inline] . #[stable(feature = "rust1", since = "1.0.0")] 124 ( 0.00%) pub fn capacity(&self) -> usize { 27,190 ( 0.01%) self.buf.capacity() 62 ( 0.00%) } . . /// Reserves capacity for at least `additional` more elements to be inserted . /// in the given `Vec`. The collection may reserve more space to avoid . /// frequent reallocations. After calling `reserve`, capacity will be . /// greater than or equal to `self.len() + additional`. Does nothing if . /// capacity is already sufficient. . /// . /// # Panics -- line 795 ---------------------------------------- -- line 800 ---------------------------------------- . /// . /// ``` . /// let mut vec = vec![1]; . /// vec.reserve(10); . /// assert!(vec.capacity() >= 11); . /// ``` . #[cfg(not(no_global_oom_handling))] . #[stable(feature = "rust1", since = "1.0.0")] 210 ( 0.00%) pub fn reserve(&mut self, additional: usize) { 66,619 ( 0.01%) self.buf.reserve(self.len, additional); 84 ( 0.00%) } . . /// Reserves the minimum capacity for exactly `additional` more elements to . /// be inserted in the given `Vec`. After calling `reserve_exact`, . /// capacity will be greater than or equal to `self.len() + additional`. . /// Does nothing if the capacity is already sufficient. . /// . /// Note that the allocator may give the collection more space than it . /// requests. Therefore, capacity can not be relied upon to be precisely -- line 818 ---------------------------------------- -- line 829 ---------------------------------------- . /// ``` . /// let mut vec = vec![1]; . /// vec.reserve_exact(10); . /// assert!(vec.capacity() >= 11); . /// ``` . #[cfg(not(no_global_oom_handling))] . #[stable(feature = "rust1", since = "1.0.0")] . pub fn reserve_exact(&mut self, additional: usize) { 1,210 ( 0.00%) self.buf.reserve_exact(self.len, additional); . } . . /// Tries to reserve capacity for at least `additional` more elements to be inserted . /// in the given `Vec`. The collection may reserve more space to avoid . /// frequent reallocations. After calling `try_reserve`, capacity will be . /// greater than or equal to `self.len() + additional`. Does nothing if . /// capacity is already sufficient. . /// -- line 845 ---------------------------------------- -- line 926 ---------------------------------------- . /// let mut vec = Vec::with_capacity(10); . /// vec.extend([1, 2, 3]); . /// assert_eq!(vec.capacity(), 10); . /// vec.shrink_to_fit(); . /// assert!(vec.capacity() >= 3); . /// ``` . #[cfg(not(no_global_oom_handling))] . #[stable(feature = "rust1", since = "1.0.0")] 75 ( 0.00%) pub fn shrink_to_fit(&mut self) { . // The capacity is never less than the length, and there's nothing to do when . // they are equal, so we can avoid the panic case in `RawVec::shrink_to_fit` . // by only calling it with a greater capacity. 2,649 ( 0.00%) if self.capacity() > self.len { 1,028 ( 0.00%) self.buf.shrink_to_fit(self.len); . } 50 ( 0.00%) } . . /// Shrinks the capacity of the vector with a lower bound. . /// . /// The capacity will remain at least as large as both the length . /// and the supplied value. . /// . /// If the current capacity is less than the lower limit, this is a no-op. . /// -- line 949 ---------------------------------------- -- line 987 ---------------------------------------- . /// vec.extend([1, 2, 3]); . /// . /// assert_eq!(vec.capacity(), 10); . /// let slice = vec.into_boxed_slice(); . /// assert_eq!(slice.into_vec().capacity(), 3); . /// ``` . #[cfg(not(no_global_oom_handling))] . #[stable(feature = "rust1", since = "1.0.0")] 50 ( 0.00%) pub fn into_boxed_slice(mut self) -> Box<[T], A> { . unsafe { 150 ( 0.00%) self.shrink_to_fit(); 646 ( 0.00%) let me = ManuallyDrop::new(self); 250 ( 0.00%) let buf = ptr::read(&me.buf); 125 ( 0.00%) let len = me.len(); 325 ( 0.00%) buf.into_box(len).assume_init() 25 ( 0.00%) } 50 ( 0.00%) } . . /// Shortens the vector, keeping the first `len` elements and dropping . /// the rest. . /// . /// If `len` is greater than the vector's current length, this has no . /// effect. . /// . /// The [`drain`] method can emulate `truncate`, but causes the excess -- line 1011 ---------------------------------------- -- line 1040 ---------------------------------------- . /// let mut vec = vec![1, 2, 3]; . /// vec.truncate(0); . /// assert_eq!(vec, []); . /// ``` . /// . /// [`clear`]: Vec::clear . /// [`drain`]: Vec::drain . #[stable(feature = "rust1", since = "1.0.0")] 21,188 ( 0.00%) pub fn truncate(&mut self, len: usize) { . // This is safe because: . // . // * the slice passed to `drop_in_place` is valid; the `len > self.len` . // case avoids creating an invalid slice, and . // * the `len` of the vector is shrunk before calling `drop_in_place`, . // such that no value will be dropped twice in case `drop_in_place` . // were to panic once (if it panics twice, the program aborts). . unsafe { . // Note: It's intentional that this is `>` and not `>=`. . // Changing it to `>=` has negative performance . // implications in some cases. See #78884 for more. 15,633 ( 0.00%) if len > self.len { . return; . } . let remaining_len = self.len - len; . let s = ptr::slice_from_raw_parts_mut(self.as_mut_ptr().add(len), remaining_len); 14,274 ( 0.00%) self.len = len; 335 ( 0.00%) ptr::drop_in_place(s); . } 25,406 ( 0.00%) } . . /// Extracts a slice containing the entire vector. . /// . /// Equivalent to `&s[..]`. . /// . /// # Examples . /// . /// ``` -- line 1076 ---------------------------------------- -- line 1123 ---------------------------------------- . /// assert_eq!(*x_ptr.add(i), 1 << i); . /// } . /// } . /// ``` . /// . /// [`as_mut_ptr`]: Vec::as_mut_ptr . #[stable(feature = "vec_as_ptr", since = "1.37.0")] . #[inline] 612 ( 0.00%) pub fn as_ptr(&self) -> *const T { . // We shadow the slice method of the same name to avoid going through . // `deref`, which creates an intermediate reference. 278,810 ( 0.05%) let ptr = self.buf.ptr(); . unsafe { 306 ( 0.00%) assume(!ptr.is_null()); . } . ptr 612 ( 0.00%) } . . /// Returns an unsafe mutable pointer to the vector's buffer. . /// . /// The caller must ensure that the vector outlives the pointer this . /// function returns, or else it will end up pointing to garbage. . /// Modifying the vector may cause its buffer to be reallocated, . /// which would also make any pointers to it invalid. . /// -- line 1147 ---------------------------------------- -- line 1159 ---------------------------------------- . /// *x_ptr.add(i) = i as i32; . /// } . /// x.set_len(size); . /// } . /// assert_eq!(&*x, &[0, 1, 2, 3]); . /// ``` . #[stable(feature = "vec_as_ptr", since = "1.37.0")] . #[inline] 1,862 ( 0.00%) pub fn as_mut_ptr(&mut self) -> *mut T { . // We shadow the slice method of the same name to avoid going through . // `deref_mut`, which creates an intermediate reference. 603,356 ( 0.11%) let ptr = self.buf.ptr(); . unsafe { 931 ( 0.00%) assume(!ptr.is_null()); . } . ptr 1,862 ( 0.00%) } . . /// Returns a reference to the underlying allocator. . #[unstable(feature = "allocator_api", issue = "32838")] . #[inline] 124 ( 0.00%) pub fn allocator(&self) -> &A { 124 ( 0.00%) self.buf.allocator() 124 ( 0.00%) } . . /// Forces the length of the vector to `new_len`. . /// . /// This is a low-level operation that maintains none of the normal . /// invariants of the type. Normally changing the length of a vector . /// is done using one of the safe operations instead, such as . /// [`truncate`], [`resize`], [`extend`], or [`clear`]. . /// -- line 1190 ---------------------------------------- -- line 1256 ---------------------------------------- . /// vec.set_len(0); . /// } . /// ``` . /// . /// Normally, here, one would use [`clear`] instead to correctly drop . /// the contents and thus not leak memory. . #[inline] . #[stable(feature = "rust1", since = "1.0.0")] 288 ( 0.00%) pub unsafe fn set_len(&mut self, new_len: usize) { . debug_assert!(new_len <= self.capacity()); . 58,150 ( 0.01%) self.len = new_len; 1,114 ( 0.00%) } . . /// Removes an element from the vector and returns it. . /// . /// The removed element is replaced by the last element of the vector. . /// . /// This does not preserve ordering, but is *O*(1). . /// If you need to preserve the element order, use [`remove`] instead. . /// -- line 1276 ---------------------------------------- -- line 1329 ---------------------------------------- . /// let mut vec = vec![1, 2, 3]; . /// vec.insert(1, 4); . /// assert_eq!(vec, [1, 4, 2, 3]); . /// vec.insert(4, 5); . /// assert_eq!(vec, [1, 4, 2, 3, 5]); . /// ``` . #[cfg(not(no_global_oom_handling))] . #[stable(feature = "rust1", since = "1.0.0")] 511 ( 0.00%) pub fn insert(&mut self, index: usize, element: T) { . #[cold] . #[inline(never)] . fn assert_failed(index: usize, len: usize) -> ! { . panic!("insertion index (is {}) should be <= len (is {})", index, len); . } . 76 ( 0.00%) let len = self.len(); 176 ( 0.00%) if index > len { . assert_failed(index, len); . } . . // space for the new element 280 ( 0.00%) if len == self.buf.capacity() { . self.reserve(1); . } . . unsafe { . // infallible . // The spot to put the new value . { . let p = self.as_mut_ptr().add(index); . // Shift everything over to make space. (Duplicating the . // `index`th element into two consecutive places.) 375 ( 0.00%) ptr::copy(p, p.offset(1), len - index); . // Write it in, overwriting the first copy of the `index`th . // element. . ptr::write(p, element); . } 256 ( 0.00%) self.set_len(len + 1); . } 438 ( 0.00%) } . . /// Removes and returns the element at position `index` within the vector, . /// shifting all elements after it to the left. . /// . /// Note: Because this shifts over the remaining elements, it has a . /// worst-case performance of *O*(*n*). If you don't need the order of elements . /// to be preserved, use [`swap_remove`] instead. If you'd like to remove . /// elements from the beginning of the `Vec`, consider using -- line 1376 ---------------------------------------- -- line 1387 ---------------------------------------- . /// . /// ``` . /// let mut v = vec![1, 2, 3]; . /// assert_eq!(v.remove(1), 2); . /// assert_eq!(v, [1, 3]); . /// ``` . #[stable(feature = "rust1", since = "1.0.0")] . #[track_caller] 75 ( 0.00%) pub fn remove(&mut self, index: usize) -> T { . #[cold] . #[inline(never)] . #[track_caller] . fn assert_failed(index: usize, len: usize) -> ! { . panic!("removal index (is {}) should be < len (is {})", index, len); . } . 68 ( 0.00%) let len = self.len(); 240 ( 0.00%) if index >= len { . assert_failed(index, len); . } . unsafe { . // infallible . let ret; . { . // the place we are taking from. . let ptr = self.as_mut_ptr().add(index); . // copy it out, unsafely having a copy of the value on . // the stack and in the vector at the same time. 262 ( 0.00%) ret = ptr::read(ptr); . . // Shift everything down to fill in that spot. 162 ( 0.00%) ptr::copy(ptr.offset(1), ptr, len - index - 1); . } 68 ( 0.00%) self.set_len(len - 1); . ret . } 125 ( 0.00%) } . . /// Retains only the elements specified by the predicate. . /// . /// In other words, remove all elements `e` such that `f(&e)` returns `false`. . /// This method operates in place, visiting each element exactly once in the . /// original order, and preserves the order of the retained elements. . /// . /// # Examples -- line 1431 ---------------------------------------- -- line 1442 ---------------------------------------- . /// ``` . /// let mut vec = vec![1, 2, 3, 4, 5]; . /// let keep = [false, true, true, false, true]; . /// let mut iter = keep.iter(); . /// vec.retain(|_| *iter.next().unwrap()); . /// assert_eq!(vec, [2, 3, 5]); . /// ``` . #[stable(feature = "rust1", since = "1.0.0")] 18,027 ( 0.00%) pub fn retain(&mut self, mut f: F) . where . F: FnMut(&T) -> bool, . { 693 ( 0.00%) self.retain_mut(|elem| f(elem)); 17,704 ( 0.00%) } . . /// Retains only the elements specified by the predicate, passing a mutable reference to it. . /// . /// In other words, remove all elements `e` such that `f(&mut e)` returns `false`. . /// This method operates in place, visiting each element exactly once in the . /// original order, and preserves the order of the retained elements. . /// . /// # Examples -- line 1463 ---------------------------------------- -- line 1474 ---------------------------------------- . /// }); . /// assert_eq!(vec, [2, 3, 4]); . /// ``` . #[unstable(feature = "vec_retain_mut", issue = "90829")] . pub fn retain_mut(&mut self, mut f: F) . where . F: FnMut(&mut T) -> bool, . { 2,262 ( 0.00%) let original_len = self.len(); . // Avoid double drop if the drop guard is not executed, . // since we may make some holes during the process. . unsafe { self.set_len(0) }; . . // Vec: [Kept, Kept, Hole, Hole, Hole, Hole, Unchecked, Unchecked] . // |<- processed len ->| ^- next to check . // |<- deleted cnt ->| . // |<- original_len ->| -- line 1490 ---------------------------------------- -- line 1499 ---------------------------------------- . v: &'a mut Vec, . processed_len: usize, . deleted_cnt: usize, . original_len: usize, . } . . impl Drop for BackshiftOnDrop<'_, T, A> { . fn drop(&mut self) { 2,456 ( 0.00%) if self.deleted_cnt > 0 { . // SAFETY: Trailing unchecked items must be valid since we never touch them. . unsafe { . ptr::copy( . self.v.as_ptr().add(self.processed_len), 1,894 ( 0.00%) self.v.as_mut_ptr().add(self.processed_len - self.deleted_cnt), . self.original_len - self.processed_len, . ); . } . } . // SAFETY: After filling holes, all items are in contiguous memory. . unsafe { 2 ( 0.00%) self.v.set_len(self.original_len - self.deleted_cnt); . } . } . } . . let mut g = BackshiftOnDrop { v: self, processed_len: 0, deleted_cnt: 0, original_len }; . . fn process_loop( . original_len: usize, . f: &mut F, . g: &mut BackshiftOnDrop<'_, T, A>, . ) where . F: FnMut(&mut T) -> bool, . { 21,659 ( 0.00%) while g.processed_len != original_len { . // SAFETY: Unchecked element must be valid. . let cur = unsafe { &mut *g.v.as_mut_ptr().add(g.processed_len) }; 5,833 ( 0.00%) if !f(cur) { . // Advance early to avoid double drop if `drop_in_place` panicked. 947 ( 0.00%) g.processed_len += 1; 462 ( 0.00%) g.deleted_cnt += 1; . // SAFETY: We never touch this element again after dropped. 49 ( 0.00%) unsafe { ptr::drop_in_place(cur) }; . // We already advanced the counter. . if DELETED { . continue; . } else { . break; . } . } . if DELETED { . // SAFETY: `deleted_cnt` > 0, so the hole slot must not overlap with current element. . // We use copy for move, and never touch this element again. . unsafe { 750 ( 0.00%) let hole_slot = g.v.as_mut_ptr().add(g.processed_len - g.deleted_cnt); . ptr::copy_nonoverlapping(cur, hole_slot, 1); . } . } 655 ( 0.00%) g.processed_len += 1; . } . } . . // Stage 1: Nothing was deleted. . process_loop::(original_len, &mut f, &mut g); . . // Stage 2: Some elements were deleted. . process_loop::(original_len, &mut f, &mut g); -- line 1565 ---------------------------------------- -- line 1606 ---------------------------------------- . /// ``` . /// let mut vec = vec!["foo", "bar", "Bar", "baz", "bar"]; . /// . /// vec.dedup_by(|a, b| a.eq_ignore_ascii_case(b)); . /// . /// assert_eq!(vec, ["foo", "bar", "baz", "bar"]); . /// ``` . #[stable(feature = "dedup_by", since = "1.16.0")] 245 ( 0.00%) pub fn dedup_by(&mut self, mut same_bucket: F) . where . F: FnMut(&mut T, &mut T) -> bool, . { 85 ( 0.00%) let len = self.len(); 252 ( 0.00%) if len <= 1 { . return; . } . . /* INVARIANT: vec.len() > read >= write > write-1 >= 0 */ . struct FillGapOnDrop<'a, T, A: core::alloc::Allocator> { . /* Offset of the element we want to check if it is duplicate */ . read: usize, . -- line 1627 ---------------------------------------- -- line 1670 ---------------------------------------- . let ptr = gap.vec.as_mut_ptr(); . . /* Drop items while going through Vec, it should be more efficient than . * doing slice partition_dedup + truncate */ . . /* SAFETY: Because of the invariant, read_ptr, prev_ptr and write_ptr . * are always in-bounds and read_ptr never aliases prev_ptr */ . unsafe { 531 ( 0.00%) while gap.read < len { . let read_ptr = ptr.add(gap.read); . let prev_ptr = ptr.add(gap.write.wrapping_sub(1)); . 68 ( 0.00%) if same_bucket(&mut *read_ptr, &mut *prev_ptr) { . // Increase `gap.read` now since the drop may panic. . gap.read += 1; . /* We have found duplicate, drop it in-place */ . ptr::drop_in_place(read_ptr); . } else { . let write_ptr = ptr.add(gap.write); . . /* Because `read_ptr` can be equal to `write_ptr`, we either . * have to use `copy` or conditional `copy_nonoverlapping`. . * Looks like the first option is faster. */ . ptr::copy(read_ptr, write_ptr, 1); . . /* We have filled that place, so go further */ 305 ( 0.00%) gap.write += 1; . gap.read += 1; . } . } . . /* Technically we could let `gap` clean up with its Drop, but . * when `same_bucket` is guaranteed to not panic, this bloats a little . * the codegen, so we just do it manually */ . gap.vec.set_len(gap.write); . mem::forget(gap); . } 280 ( 0.00%) } . . /// Appends an element to the back of a collection. . /// . /// # Panics . /// . /// Panics if the new capacity exceeds `isize::MAX` bytes. . /// . /// # Examples -- line 1715 ---------------------------------------- -- line 1717 ---------------------------------------- . /// ``` . /// let mut vec = vec![1, 2]; . /// vec.push(3); . /// assert_eq!(vec, [1, 2, 3]); . /// ``` . #[cfg(not(no_global_oom_handling))] . #[inline] . #[stable(feature = "rust1", since = "1.0.0")] 2,621 ( 0.00%) pub fn push(&mut self, value: T) { . // This will panic or abort if we would allocate > isize::MAX bytes . // or if the length increment would overflow for zero-sized types. 1,485,358 ( 0.28%) if self.len == self.buf.capacity() { 49,000 ( 0.01%) self.buf.reserve_for_push(self.len); . } . unsafe { 24,846 ( 0.00%) let end = self.as_mut_ptr().add(self.len); 3,554 ( 0.00%) ptr::write(end, value); 1,581,313 ( 0.29%) self.len += 1; . } 1,010 ( 0.00%) } . . /// Removes the last element from a vector and returns it, or [`None`] if it . /// is empty. . /// . /// If you'd like to pop the first element, consider using . /// [`VecDeque::pop_front`] instead. . /// . /// [`VecDeque::pop_front`]: crate::collections::VecDeque::pop_front -- line 1744 ---------------------------------------- -- line 1748 ---------------------------------------- . /// ``` . /// let mut vec = vec![1, 2, 3]; . /// assert_eq!(vec.pop(), Some(3)); . /// assert_eq!(vec, [1, 2]); . /// ``` . #[inline] . #[stable(feature = "rust1", since = "1.0.0")] . pub fn pop(&mut self) -> Option { 59,544 ( 0.01%) if self.len == 0 { 9 ( 0.00%) None . } else { . unsafe { 39,637 ( 0.01%) self.len -= 1; 8,295 ( 0.00%) Some(ptr::read(self.as_ptr().add(self.len()))) . } . } . } . . /// Moves all the elements of `other` into `Self`, leaving `other` empty. . /// . /// # Panics . /// -- line 1769 ---------------------------------------- -- line 1776 ---------------------------------------- . /// let mut vec2 = vec![4, 5, 6]; . /// vec.append(&mut vec2); . /// assert_eq!(vec, [1, 2, 3, 4, 5, 6]); . /// assert_eq!(vec2, []); . /// ``` . #[cfg(not(no_global_oom_handling))] . #[inline] . #[stable(feature = "append", since = "1.4.0")] 35 ( 0.00%) pub fn append(&mut self, other: &mut Self) { . unsafe { . self.append_elements(other.as_slice() as _); . other.set_len(0); . } 30 ( 0.00%) } . . /// Appends elements to `Self` from other buffer. . #[cfg(not(no_global_oom_handling))] . #[inline] 420 ( 0.00%) unsafe fn append_elements(&mut self, other: *const [T]) { 42 ( 0.00%) let count = unsafe { (*other).len() }; 42 ( 0.00%) self.reserve(count); 26,125 ( 0.00%) let len = self.len(); 130 ( 0.00%) unsafe { ptr::copy_nonoverlapping(other as *const T, self.as_mut_ptr().add(len), count) }; 180,962 ( 0.03%) self.len += count; 84 ( 0.00%) } . . /// Creates a draining iterator that removes the specified range in the vector . /// and yields the removed items. . /// . /// When the iterator **is** dropped, all elements in the range are removed . /// from the vector, even if the iterator was not fully consumed. If the . /// iterator **is not** dropped (with [`mem::forget`] for example), it is . /// unspecified how many elements are removed. -- line 1808 ---------------------------------------- -- line 1820 ---------------------------------------- . /// assert_eq!(v, &[1]); . /// assert_eq!(u, &[2, 3]); . /// . /// // A full range clears the vector . /// v.drain(..); . /// assert_eq!(v, &[]); . /// ``` . #[stable(feature = "drain", since = "1.6.0")] 357 ( 0.00%) pub fn drain(&mut self, range: R) -> Drain<'_, T, A> . where . R: RangeBounds, . { . // Memory safety . // . // When the Drain is first created, it shortens the length of . // the source vector to make sure no uninitialized or moved-from elements . // are accessible at all if the Drain's destructor never gets to run. . // . // Drain will ptr::read out the values to remove. . // When finished, remaining tail of the vec is copied back to cover . // the hole, and the vector length is restored to the new length. . // 1,679 ( 0.00%) let len = self.len(); 765 ( 0.00%) let Range { start, end } = slice::range(range, ..len); . . unsafe { . // set self.vec length's to start, to be safe in case Drain is leaked 153 ( 0.00%) self.set_len(start); . // Use the borrow in the IterMut to indicate borrowing behavior of the . // whole Drain iterator (like &mut T). 935 ( 0.00%) let range_slice = slice::from_raw_parts_mut(self.as_mut_ptr().add(start), end - start); 1,211 ( 0.00%) Drain { . tail_start: end, 369 ( 0.00%) tail_len: len - end, 255 ( 0.00%) iter: range_slice.iter(), 204 ( 0.00%) vec: NonNull::from(self), . } . } 102 ( 0.00%) } . . /// Clears the vector, removing all values. . /// . /// Note that this method has no effect on the allocated capacity . /// of the vector. . /// . /// # Examples . /// -- line 1866 ---------------------------------------- -- line 1869 ---------------------------------------- . /// . /// v.clear(); . /// . /// assert!(v.is_empty()); . /// ``` . #[inline] . #[stable(feature = "rust1", since = "1.0.0")] . pub fn clear(&mut self) { 35,167 ( 0.01%) self.truncate(0) . } . . /// Returns the number of elements in the vector, also referred to . /// as its 'length'. . /// . /// # Examples . /// . /// ``` . /// let a = vec![1, 2, 3]; . /// assert_eq!(a.len(), 3); . /// ``` . #[inline] . #[stable(feature = "rust1", since = "1.0.0")] 594 ( 0.00%) pub fn len(&self) -> usize { 297 ( 0.00%) self.len 594 ( 0.00%) } . . /// Returns `true` if the vector contains no elements. . /// . /// # Examples . /// . /// ``` . /// let mut v = Vec::new(); . /// assert!(v.is_empty()); . /// . /// v.push(1); . /// assert!(!v.is_empty()); . /// ``` . #[stable(feature = "rust1", since = "1.0.0")] 206 ( 0.00%) pub fn is_empty(&self) -> bool { 24,430 ( 0.00%) self.len() == 0 412 ( 0.00%) } . . /// Splits the collection into two at the given index. . /// . /// Returns a newly allocated vector containing the elements in the range . /// `[at, len)`. After the call, the original vector will be left containing . /// the elements `[0, at)` with its previous capacity unchanged. . /// . /// # Panics -- line 1917 ---------------------------------------- -- line 1935 ---------------------------------------- . A: Clone, . { . #[cold] . #[inline(never)] . fn assert_failed(at: usize, len: usize) -> ! { . panic!("`at` split index (is {}) should be <= len (is {})", at, len); . } . 54 ( 0.00%) if at > self.len() { . assert_failed(at, self.len()); . } . 42 ( 0.00%) if at == 0 { . // the new vector can take over the original buffer and avoid the copy . return mem::replace( . self, . Vec::with_capacity_in(self.capacity(), self.allocator().clone()), . ); . } . . let other_len = self.len - at; -- line 1955 ---------------------------------------- -- line 1988 ---------------------------------------- . /// . /// let mut vec = vec![]; . /// let mut p = 1; . /// vec.resize_with(4, || { p *= 2; p }); . /// assert_eq!(vec, [2, 4, 8, 16]); . /// ``` . #[cfg(not(no_global_oom_handling))] . #[stable(feature = "vec_resize_with", since = "1.33.0")] 1,378 ( 0.00%) pub fn resize_with(&mut self, new_len: usize, f: F) . where . F: FnMut() -> T, . { 182 ( 0.00%) let len = self.len(); 364 ( 0.00%) if new_len > len { 961 ( 0.00%) self.extend_with(new_len - len, ExtendFunc(f)); . } else { . self.truncate(new_len); . } 1,196 ( 0.00%) } . . /// Consumes and leaks the `Vec`, returning a mutable reference to the contents, . /// `&'a mut [T]`. Note that the type `T` must outlive the chosen lifetime . /// `'a`. If the type has only static references, or none at all, then this . /// may be chosen to be `'static`. . /// . /// As of Rust 1.57, this method does not reallocate or shrink the `Vec`, . /// so the leaked allocation may include unused capacity that is not part -- line 2014 ---------------------------------------- -- line 2064 ---------------------------------------- . /// unsafe { . /// v.set_len(3); . /// } . /// . /// assert_eq!(&v, &[0, 1, 2]); . /// ``` . #[stable(feature = "vec_spare_capacity", since = "1.60.0")] . #[inline] 108 ( 0.00%) pub fn spare_capacity_mut(&mut self) -> &mut [MaybeUninit] { . // Note: . // This method is not implemented in terms of `split_at_spare_mut`, . // to prevent invalidation of pointers to the buffer. . unsafe { 144 ( 0.00%) slice::from_raw_parts_mut( 256 ( 0.00%) self.as_mut_ptr().add(self.len) as *mut MaybeUninit, 248 ( 0.00%) self.buf.capacity() - self.len, . ) . } 72 ( 0.00%) } . . /// Returns vector content as a slice of `T`, along with the remaining spare . /// capacity of the vector as a slice of `MaybeUninit`. . /// . /// The returned spare capacity slice can be used to fill the vector with data . /// (e.g. by reading from a file) before marking the data as initialized using . /// the [`set_len`] method. . /// -- line 2090 ---------------------------------------- -- line 2189 ---------------------------------------- . /// assert_eq!(vec, ["hello", "world", "world"]); . /// . /// let mut vec = vec![1, 2, 3, 4]; . /// vec.resize(2, 0); . /// assert_eq!(vec, [1, 2]); . /// ``` . #[cfg(not(no_global_oom_handling))] . #[stable(feature = "vec_resize", since = "1.5.0")] 1,380 ( 0.00%) pub fn resize(&mut self, new_len: usize, value: T) { 138 ( 0.00%) let len = self.len(); . 414 ( 0.00%) if new_len > len { 315 ( 0.00%) self.extend_with(new_len - len, ExtendElement(value)) . } else { . self.truncate(new_len); . } 178 ( 0.00%) } . . /// Clones and appends all elements in a slice to the `Vec`. . /// . /// Iterates over the slice `other`, clones each element, and then appends . /// it to this `Vec`. The `other` slice is traversed in-order. . /// . /// Note that this function is same as [`extend`] except that it is . /// specialized to work with slices instead. If and when Rust gets -- line 2213 ---------------------------------------- -- line 2220 ---------------------------------------- . /// let mut vec = vec![1]; . /// vec.extend_from_slice(&[2, 3, 4]); . /// assert_eq!(vec, [1, 2, 3, 4]); . /// ``` . /// . /// [`extend`]: Vec::extend . #[cfg(not(no_global_oom_handling))] . #[stable(feature = "vec_extend_from_slice", since = "1.6.0")] 462 ( 0.00%) pub fn extend_from_slice(&mut self, other: &[T]) { 168 ( 0.00%) self.spec_extend(other.iter()) 84 ( 0.00%) } . . /// Copies elements from `src` range to the end of the vector. . /// . /// # Panics . /// . /// Panics if the starting point is greater than the end point or if . /// the end point is greater than the length of the vector. . /// -- line 2238 ---------------------------------------- -- line 2271 ---------------------------------------- . trait ExtendWith { . fn next(&mut self) -> T; . fn last(self) -> T; . } . . struct ExtendElement(T); . impl ExtendWith for ExtendElement { . fn next(&mut self) -> T { 68 ( 0.00%) self.0.clone() . } . fn last(self) -> T { . self.0 . } . } . . struct ExtendFunc(F); . impl T> ExtendWith for ExtendFunc { -- line 2287 ---------------------------------------- -- line 2291 ---------------------------------------- . fn last(mut self) -> T { . (self.0)() . } . } . . impl Vec { . #[cfg(not(no_global_oom_handling))] . /// Extend the vector by `n` values, using the given generator. 14,934 ( 0.00%) fn extend_with>(&mut self, n: usize, mut value: E) { . self.reserve(n); . . unsafe { 417 ( 0.00%) let mut ptr = self.as_mut_ptr().add(self.len()); . // Use SetLenOnDrop to work around bug where compiler . // might not realize the store through `ptr` through self.set_len() . // don't alias. . let mut local_len = SetLenOnDrop::new(&mut self.len); . . // Write all elements except the last one . for _ in 1..n { . ptr::write(ptr, value.next()); . ptr = ptr.offset(1); . // Increment the length in every step in case next() panics . local_len.increment_len(1); . } . 17,021 ( 0.00%) if n > 0 { . // We can write the last element directly without cloning needlessly . ptr::write(ptr, value.last()); . local_len.increment_len(1); . } . . // len set by scope guard . } 11,751 ( 0.00%) } . } . . impl Vec { . /// Removes consecutive repeated elements in the vector according to the . /// [`PartialEq`] trait implementation. . /// . /// If the vector is sorted, this removes all duplicates. . /// -- line 2333 ---------------------------------------- -- line 2338 ---------------------------------------- . /// . /// vec.dedup(); . /// . /// assert_eq!(vec, [1, 2, 3, 2]); . /// ``` . #[stable(feature = "rust1", since = "1.0.0")] . #[inline] . pub fn dedup(&mut self) { 36 ( 0.00%) self.dedup_by(|a, b| a == b) . } . } . . //////////////////////////////////////////////////////////////////////////////// . // Internal methods and functions . //////////////////////////////////////////////////////////////////////////////// . . #[doc(hidden)] . #[cfg(not(no_global_oom_handling))] . #[stable(feature = "rust1", since = "1.0.0")] 5,151 ( 0.00%) pub fn from_elem(elem: T, n: usize) -> Vec { 22,354 ( 0.00%) ::from_elem(elem, n, Global) 5,867 ( 0.00%) } . . #[doc(hidden)] . #[cfg(not(no_global_oom_handling))] . #[unstable(feature = "allocator_api", issue = "32838")] . pub fn from_elem_in(elem: T, n: usize, alloc: A) -> Vec { . ::from_elem(elem, n, alloc) . } . -- line 2367 ---------------------------------------- -- line 2423 ---------------------------------------- . //////////////////////////////////////////////////////////////////////////////// . // Common trait implementations for Vec . //////////////////////////////////////////////////////////////////////////////// . . #[stable(feature = "rust1", since = "1.0.0")] . impl ops::Deref for Vec { . type Target = [T]; . 918 ( 0.00%) fn deref(&self) -> &[T] { 437,258 ( 0.08%) unsafe { slice::from_raw_parts(self.as_ptr(), self.len) } 635 ( 0.00%) } . } . . #[stable(feature = "rust1", since = "1.0.0")] . impl ops::DerefMut for Vec { . fn deref_mut(&mut self) -> &mut [T] { 72,561 ( 0.01%) unsafe { slice::from_raw_parts_mut(self.as_mut_ptr(), self.len) } . } . } . . #[cfg(not(no_global_oom_handling))] . trait SpecCloneFrom { . fn clone_from(this: &mut Self, other: &Self); . } . -- line 2447 ---------------------------------------- -- line 2468 ---------------------------------------- . this.extend_from_slice(other); . } . } . . #[cfg(not(no_global_oom_handling))] . #[stable(feature = "rust1", since = "1.0.0")] . impl Clone for Vec { . #[cfg(not(test))] 13,555 ( 0.00%) fn clone(&self) -> Self { 180 ( 0.00%) let alloc = self.allocator().clone(); 326 ( 0.00%) <[T]>::to_vec_in(&**self, alloc) 16,643 ( 0.00%) } . . // HACK(japaric): with cfg(test) the inherent `[T]::to_vec` method, which is . // required for this method definition, is not available. Instead use the . // `slice::to_vec` function which is only available with cfg(test) . // NB see the slice::hack module in slice.rs for more information . #[cfg(test)] . fn clone(&self) -> Self { . let alloc = self.allocator().clone(); -- line 2487 ---------------------------------------- -- line 2503 ---------------------------------------- . /// let b = std::collections::hash_map::RandomState::new(); . /// let v: Vec = vec![0xa8, 0x3c, 0x09]; . /// let s: &[u8] = &[0xa8, 0x3c, 0x09]; . /// assert_eq!(b.hash_one(v), b.hash_one(s)); . /// ``` . #[stable(feature = "rust1", since = "1.0.0")] . impl Hash for Vec { . #[inline] 28 ( 0.00%) fn hash(&self, state: &mut H) { 28 ( 0.00%) Hash::hash(&**self, state) 14 ( 0.00%) } . } . . #[stable(feature = "rust1", since = "1.0.0")] . #[rustc_on_unimplemented( . message = "vector indices are of type `usize` or ranges of `usize`", . label = "vector indices are of type `usize` or ranges of `usize`" . )] . impl, A: Allocator> Index for Vec { . type Output = I::Output; . . #[inline] 22 ( 0.00%) fn index(&self, index: I) -> &Self::Output { 5,282 ( 0.00%) Index::index(&**self, index) 12 ( 0.00%) } . } . . #[stable(feature = "rust1", since = "1.0.0")] . #[rustc_on_unimplemented( . message = "vector indices are of type `usize` or ranges of `usize`", . label = "vector indices are of type `usize` or ranges of `usize`" . )] . impl, A: Allocator> IndexMut for Vec { . #[inline] . fn index_mut(&mut self, index: I) -> &mut Self::Output { 4 ( 0.00%) IndexMut::index_mut(&mut **self, index) . } . } . . #[cfg(not(no_global_oom_handling))] . #[stable(feature = "rust1", since = "1.0.0")] . impl FromIterator for Vec { . #[inline] 12 ( 0.00%) fn from_iter>(iter: I) -> Vec { 189,735 ( 0.04%) >::from_iter(iter.into_iter()) 8 ( 0.00%) } . } . . #[stable(feature = "rust1", since = "1.0.0")] . impl IntoIterator for Vec { . type Item = T; . type IntoIter = IntoIter; . . /// Creates a consuming iterator, that is, one that moves each value out of -- line 2556 ---------------------------------------- -- line 2562 ---------------------------------------- . /// ``` . /// let v = vec!["a".to_string(), "b".to_string()]; . /// for s in v.into_iter() { . /// // s has type String, not &String . /// println!("{}", s); . /// } . /// ``` . #[inline] 78 ( 0.00%) fn into_iter(self) -> IntoIter { . unsafe { 39,620 ( 0.01%) let mut me = ManuallyDrop::new(self); 52 ( 0.00%) let alloc = ptr::read(me.allocator()); 124 ( 0.00%) let begin = me.as_mut_ptr(); 78 ( 0.00%) let end = if mem::size_of::() == 0 { . arith_offset(begin as *const i8, me.len() as isize) as *const T . } else { 124 ( 0.00%) begin.add(me.len()) as *const T . }; 26 ( 0.00%) let cap = me.buf.capacity(); 17,027 ( 0.00%) IntoIter { 98 ( 0.00%) buf: NonNull::new_unchecked(begin), . phantom: PhantomData, . cap, . alloc, . ptr: begin, 26 ( 0.00%) end, . } . } 52 ( 0.00%) } . } . . #[stable(feature = "rust1", since = "1.0.0")] . impl<'a, T, A: Allocator> IntoIterator for &'a Vec { . type Item = &'a T; . type IntoIter = slice::Iter<'a, T>; . 18 ( 0.00%) fn into_iter(self) -> slice::Iter<'a, T> { 66 ( 0.00%) self.iter() 18 ( 0.00%) } . } . . #[stable(feature = "rust1", since = "1.0.0")] . impl<'a, T, A: Allocator> IntoIterator for &'a mut Vec { . type Item = &'a mut T; . type IntoIter = slice::IterMut<'a, T>; . . fn into_iter(self) -> slice::IterMut<'a, T> { 1,250 ( 0.00%) self.iter_mut() . } . } . . #[cfg(not(no_global_oom_handling))] . #[stable(feature = "rust1", since = "1.0.0")] . impl Extend for Vec { . #[inline] 256 ( 0.00%) fn extend>(&mut self, iter: I) { 38,296 ( 0.01%) >::spec_extend(self, iter.into_iter()) 256 ( 0.00%) } . . #[inline] . fn extend_one(&mut self, item: T) { . self.push(item); . } . . #[inline] . fn extend_reserve(&mut self, additional: usize) { -- line 2627 ---------------------------------------- -- line 2628 ---------------------------------------- . self.reserve(additional); . } . } . . impl Vec { . // leaf method to which various SpecFrom/SpecExtend implementations delegate when . // they have no further optimizations to apply . #[cfg(not(no_global_oom_handling))] 16 ( 0.00%) fn extend_desugared>(&mut self, mut iterator: I) { . // This is the case for a general iterator. . // . // This function should be the moral equivalent of: . // . // for item in iterator { . // self.push(item); . // } 18,024 ( 0.00%) while let Some(element) = iterator.next() { 1,058 ( 0.00%) let len = self.len(); 23,003 ( 0.00%) if len == self.capacity() { 271 ( 0.00%) let (lower, _) = iterator.size_hint(); . self.reserve(lower.saturating_add(1)); . } . unsafe { . ptr::write(self.as_mut_ptr().add(len), element); . // Since next() executes user code which can panic we have to bump the length . // after each step. . // NB can't overflow since we would have had to alloc the address space 20,196 ( 0.00%) self.set_len(len + 1); . } . } 133 ( 0.00%) } . . /// Creates a splicing iterator that replaces the specified range in the vector . /// with the given `replace_with` iterator and yields the removed items. . /// `replace_with` does not need to be the same length as `range`. . /// . /// `range` is removed even if the iterator is not consumed until the end. . /// . /// It is unspecified how many elements are removed from the vector -- line 2666 ---------------------------------------- -- line 2693 ---------------------------------------- . #[cfg(not(no_global_oom_handling))] . #[inline] . #[stable(feature = "vec_splice", since = "1.21.0")] . pub fn splice(&mut self, range: R, replace_with: I) -> Splice<'_, I::IntoIter, A> . where . R: RangeBounds, . I: IntoIterator, . { 66 ( 0.00%) Splice { drain: self.drain(range), replace_with: replace_with.into_iter() } . } . . /// Creates an iterator which uses a closure to determine if an element should be removed. . /// . /// If the closure returns true, then the element is removed and yielded. . /// If the closure returns false, the element will remain in the vector and will not be yielded . /// by the iterator. . /// -- line 2709 ---------------------------------------- -- line 2745 ---------------------------------------- . /// assert_eq!(evens, vec![2, 4, 6, 8, 14]); . /// assert_eq!(odds, vec![1, 3, 5, 9, 11, 13, 15]); . /// ``` . #[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")] . pub fn drain_filter(&mut self, filter: F) -> DrainFilter<'_, T, F, A> . where . F: FnMut(&mut T) -> bool, . { 350 ( 0.00%) let old_len = self.len(); . . // Guard against us getting leaked (leak amplification) . unsafe { . self.set_len(0); . } . 576 ( 0.00%) DrainFilter { vec: self, idx: 0, del: 0, old_len, pred: filter, panic_flag: false } . } . } . . /// Extend implementation that copies elements out of references before pushing them onto the Vec. . /// . /// This implementation is specialized for slice iterators, where it uses [`copy_from_slice`] to . /// append the entire slice at once. . /// . /// [`copy_from_slice`]: slice::copy_from_slice . #[cfg(not(no_global_oom_handling))] . #[stable(feature = "extend_ref", since = "1.2.0")] . impl<'a, T: Copy + 'a, A: Allocator + 'a> Extend<&'a T> for Vec { 6,904 ( 0.00%) fn extend>(&mut self, iter: I) { . self.spec_extend(iter.into_iter()) 5,178 ( 0.00%) } . . #[inline] . fn extend_one(&mut self, &item: &'a T) { . self.push(item); . } . . #[inline] . fn extend_reserve(&mut self, additional: usize) { -- line 2783 ---------------------------------------- -- line 2803 ---------------------------------------- . #[inline] . fn cmp(&self, other: &Self) -> Ordering { . Ord::cmp(&**self, &**other) . } . } . . #[stable(feature = "rust1", since = "1.0.0")] . unsafe impl<#[may_dangle] T, A: Allocator> Drop for Vec { 58,727 ( 0.01%) fn drop(&mut self) { . unsafe { . // use drop for [T] . // use a raw slice to refer to the elements of the vector as weakest necessary type; . // could avoid questions of validity in certain cases 31,290 ( 0.01%) ptr::drop_in_place(ptr::slice_from_raw_parts_mut(self.as_mut_ptr(), self.len)) . } . // RawVec handles deallocation 68,400 ( 0.01%) } . } . . #[stable(feature = "rust1", since = "1.0.0")] . #[rustc_const_unstable(feature = "const_default_impls", issue = "87864")] . impl const Default for Vec { . /// Creates an empty `Vec`. . fn default() -> Vec { . Vec::new() -- line 2827 ---------------------------------------- -- line 2976 ---------------------------------------- . /// newly-allocated buffer with exactly the right capacity. . /// . /// # Examples . /// . /// ``` . /// assert_eq!(Box::from(vec![1, 2, 3]), vec![1, 2, 3].into_boxed_slice()); . /// ``` . fn from(v: Vec) -> Self { 4 ( 0.00%) v.into_boxed_slice() . } . } . . #[cfg(not(no_global_oom_handling))] . #[stable(feature = "rust1", since = "1.0.0")] . impl From<&str> for Vec { . /// Allocate a `Vec` and fill it with a UTF-8 string. . /// -- line 2992 ---------------------------------------- 139,450 ( 0.03%) -------------------------------------------------------------------------------- -- Auto-annotated source: /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_serialize/src/opaque.rs -------------------------------------------------------------------------------- Ir -- line 14 ---------------------------------------- . . pub type EncodeResult = Result<(), !>; . . pub struct Encoder { . pub data: Vec, . } . . impl Encoder { 1 ( 0.00%) pub fn new(data: Vec) -> Encoder { 4 ( 0.00%) Encoder { data } 1 ( 0.00%) } . 1 ( 0.00%) pub fn into_inner(self) -> Vec { 4 ( 0.00%) self.data 1 ( 0.00%) } . . #[inline] . pub fn position(&self) -> usize { 1,556 ( 0.00%) self.data.len() . } . } . . macro_rules! write_leb128 { . ($enc:expr, $value:expr, $int_ty:ty, $fun:ident) => {{ . const MAX_ENCODED_LEN: usize = max_leb128_len!($int_ty); . let old_len = $enc.data.len(); . -- line 40 ---------------------------------------- -- line 67 ---------------------------------------- . . #[inline] . fn emit_unit(&mut self) -> EncodeResult { . Ok(()) . } . . #[inline] . fn emit_usize(&mut self, v: usize) -> EncodeResult { 58,579 ( 0.01%) write_leb128!(self, v, usize, write_usize_leb128) . } . . #[inline] . fn emit_u128(&mut self, v: u128) -> EncodeResult { 721 ( 0.00%) write_leb128!(self, v, u128, write_u128_leb128) . } . . #[inline] . fn emit_u64(&mut self, v: u64) -> EncodeResult { 847 ( 0.00%) write_leb128!(self, v, u64, write_u64_leb128) . } . . #[inline] . fn emit_u32(&mut self, v: u32) -> EncodeResult { 49,612 ( 0.01%) write_leb128!(self, v, u32, write_u32_leb128) . } . . #[inline] . fn emit_u16(&mut self, v: u16) -> EncodeResult { . self.data.extend_from_slice(&v.to_le_bytes()); . Ok(()) . } . -- line 98 ---------------------------------------- -- line 131 ---------------------------------------- . #[inline] . fn emit_i8(&mut self, v: i8) -> EncodeResult { . let as_u8: u8 = unsafe { std::mem::transmute(v) }; . self.emit_u8(as_u8) . } . . #[inline] . fn emit_bool(&mut self, v: bool) -> EncodeResult { 799 ( 0.00%) self.emit_u8(if v { 1 } else { 0 }) . } . . #[inline] . fn emit_f64(&mut self, v: f64) -> EncodeResult { . let as_u64: u64 = v.to_bits(); . self.emit_u64(as_u64) . } . -- line 147 ---------------------------------------- -- line 549 ---------------------------------------- . #[inline] . pub fn advance(&mut self, bytes: usize) { . self.position += bytes; . } . . #[inline] . pub fn read_raw_bytes(&mut self, bytes: usize) -> &'a [u8] { . let start = self.position; 34 ( 0.00%) self.position += bytes; 34 ( 0.00%) &self.data[start..self.position] . } . } . . macro_rules! read_leb128 { . ($dec:expr, $fun:ident) => {{ leb128::$fun($dec.data, &mut $dec.position) }}; . } . . impl<'a> serialize::Decoder for Decoder<'a> { . #[inline] . fn read_unit(&mut self) -> () { . () . } . . #[inline] . fn read_u128(&mut self) -> u128 { 835 ( 0.00%) read_leb128!(self, read_u128_leb128) . } . . #[inline] . fn read_u64(&mut self) -> u64 { 3,932 ( 0.00%) read_leb128!(self, read_u64_leb128) . } . . #[inline] 38,162 ( 0.01%) fn read_u32(&mut self) -> u32 { 178,519 ( 0.03%) read_leb128!(self, read_u32_leb128) 76,324 ( 0.01%) } . . #[inline] . fn read_u16(&mut self) -> u16 { 561,386 ( 0.10%) let bytes = [self.data[self.position], self.data[self.position + 1]]; 80,198 ( 0.01%) let value = u16::from_le_bytes(bytes); 160,396 ( 0.03%) self.position += 2; . value . } . . #[inline] . fn read_u8(&mut self) -> u8 { 2,094,332 ( 0.39%) let value = self.data[self.position]; 406,137 ( 0.08%) self.position += 1; . value . } . . #[inline] 235,098 ( 0.04%) fn read_usize(&mut self) -> usize { 235,106 ( 0.04%) read_leb128!(self, read_usize_leb128) 470,196 ( 0.09%) } . . #[inline] . fn read_i128(&mut self) -> i128 { . read_leb128!(self, read_i128_leb128) . } . . #[inline] . fn read_i64(&mut self) -> i64 { -- line 613 ---------------------------------------- -- line 637 ---------------------------------------- . #[inline] . fn read_isize(&mut self) -> isize { . read_leb128!(self, read_isize_leb128) . } . . #[inline] . fn read_bool(&mut self) -> bool { . let value = self.read_u8(); 13,562 ( 0.00%) value != 0 . } . . #[inline] . fn read_f64(&mut self) -> f64 { . let bits = self.read_u64(); . f64::from_bits(bits) . } . -- line 653 ---------------------------------------- -- line 660 ---------------------------------------- . #[inline] . fn read_char(&mut self) -> char { . let bits = self.read_u32(); . std::char::from_u32(bits).unwrap() . } . . #[inline] . fn read_str(&mut self) -> Cow<'_, str> { 40,708 ( 0.01%) let len = self.read_usize(); 208,920 ( 0.04%) let sentinel = self.data[self.position + len]; 52,236 ( 0.01%) assert!(sentinel == STR_SENTINEL); . let s = unsafe { . std::str::from_utf8_unchecked(&self.data[self.position..self.position + len]) . }; 130,590 ( 0.02%) self.position += len + 1; 43,485 ( 0.01%) Cow::Borrowed(s) . } . . #[inline] . fn read_raw_bytes_into(&mut self, s: &mut [u8]) { 642 ( 0.00%) let start = self.position; 2,844 ( 0.00%) self.position += s.len(); 642 ( 0.00%) s.copy_from_slice(&self.data[start..self.position]); . } . } . . // Specializations for contiguous byte sequences follow. The default implementations for slices . // encode and decode each element individually. This isn't necessary for `u8` slices when using . // opaque encoders and decoders, because each `u8` is unchanged by encoding and decoding. . // Therefore, we can use more efficient implementations that process the entire sequence at once. . -- line 690 ---------------------------------------- 538,607 ( 0.10%) -------------------------------------------------------------------------------- -- Auto-annotated source: /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs -------------------------------------------------------------------------------- Ir -- line 24 ---------------------------------------- . use smallvec::SmallVec; . . use std::fmt::Write; . . // Compute the name of the type as it should be stored in debuginfo. Does not do . // any caching, i.e., calling the function twice with the same type will also do . // the work twice. The `qualified` parameter only affects the first level of the . // type name, further levels (i.e., type parameters) are always fully qualified. 25,578 ( 0.00%) pub fn compute_debuginfo_type_name<'tcx>( . tcx: TyCtxt<'tcx>, . t: Ty<'tcx>, . qualified: bool, . ) -> String { . let _prof = tcx.prof.generic_activity("compute_debuginfo_type_name"); . . let mut result = String::with_capacity(64); . let mut visited = FxHashSet::default(); 10,962 ( 0.00%) push_debuginfo_type_name(tcx, t, qualified, &mut result, &mut visited); . result 16,443 ( 0.00%) } . . // Pushes the name of the type as it should be stored in debuginfo on the . // `output` String. See also compute_debuginfo_type_name(). 116,432 ( 0.02%) fn push_debuginfo_type_name<'tcx>( . tcx: TyCtxt<'tcx>, . t: Ty<'tcx>, . qualified: bool, . output: &mut String, . visited: &mut FxHashSet>, . ) { . // When targeting MSVC, emit C++ style type names for compatibility with . // .natvis visualizers (and perhaps other existing native debuggers?) . let cpp_like_debuginfo = cpp_like_debuginfo(tcx); . 24,064 ( 0.00%) match *t.kind() { . ty::Bool => output.push_str("bool"), . ty::Char => output.push_str("char"), . ty::Str => output.push_str("str"), . ty::Never => { . if cpp_like_debuginfo { . output.push_str("never$"); . } else { . output.push('!'); . } . } 154 ( 0.00%) ty::Int(int_ty) => output.push_str(int_ty.name_str()), 1,127 ( 0.00%) ty::Uint(uint_ty) => output.push_str(uint_ty.name_str()), . ty::Float(float_ty) => output.push_str(float_ty.name_str()), 39 ( 0.00%) ty::Foreign(def_id) => push_item_name(tcx, def_id, qualified, output), 9,258 ( 0.00%) ty::Adt(def, substs) => { 13,887 ( 0.00%) if def.is_enum() && cpp_like_debuginfo { . msvc_enum_fallback(tcx, t, def, substs, output, visited); . } else { 32,403 ( 0.01%) push_item_name(tcx, def.did, qualified, output); 55,548 ( 0.01%) push_generic_params_internal(tcx, substs, output, visited); . } . } 44 ( 0.00%) ty::Tuple(component_types) => { 44 ( 0.00%) if cpp_like_debuginfo { . output.push_str("tuple$<"); . } else { . output.push('('); . } . . for component_type in component_types { 108 ( 0.00%) push_debuginfo_type_name(tcx, component_type.expect_ty(), true, output, visited); . push_arg_separator(cpp_like_debuginfo, output); . } 8 ( 0.00%) if !component_types.is_empty() { . pop_arg_separator(output); . } . 8 ( 0.00%) if cpp_like_debuginfo { . push_close_angle_bracket(cpp_like_debuginfo, output); . } else { . output.push(')'); . } . } 432 ( 0.00%) ty::RawPtr(ty::TypeAndMut { ty: inner_type, mutbl }) => { 216 ( 0.00%) if cpp_like_debuginfo { . match mutbl { . hir::Mutability::Not => output.push_str("ptr_const$<"), . hir::Mutability::Mut => output.push_str("ptr_mut$<"), . } . } else { . output.push('*'); 432 ( 0.00%) match mutbl { . hir::Mutability::Not => output.push_str("const "), . hir::Mutability::Mut => output.push_str("mut "), . } . } . 648 ( 0.00%) push_debuginfo_type_name(tcx, inner_type, qualified, output, visited); . . if cpp_like_debuginfo { . push_close_angle_bracket(cpp_like_debuginfo, output); . } . } 411 ( 0.00%) ty::Ref(_, inner_type, mutbl) => { . // Slices and `&str` are treated like C++ pointers when computing debug . // info for MSVC debugger. However, wrapping these types' names in a synthetic type . // causes the .natvis engine for WinDbg to fail to display their data, so we opt these . // types out to aid debugging in MSVC. . let is_slice_or_str = matches!(*inner_type.kind(), ty::Slice(_) | ty::Str); . 137 ( 0.00%) if !cpp_like_debuginfo { . output.push('&'); 137 ( 0.00%) output.push_str(mutbl.prefix_str()); . } else if !is_slice_or_str { . match mutbl { . hir::Mutability::Not => output.push_str("ref$<"), . hir::Mutability::Mut => output.push_str("ref_mut$<"), . } . } . 1,096 ( 0.00%) push_debuginfo_type_name(tcx, inner_type, qualified, output, visited); . . if cpp_like_debuginfo && !is_slice_or_str { . push_close_angle_bracket(cpp_like_debuginfo, output); . } . } 36 ( 0.00%) ty::Array(inner_type, len) => { 12 ( 0.00%) if cpp_like_debuginfo { . output.push_str("array$<"); . push_debuginfo_type_name(tcx, inner_type, true, output, visited); . match len.val { . ty::ConstKind::Param(param) => write!(output, ",{}>", param.name).unwrap(), . _ => write!(output, ",{}>", len.eval_usize(tcx, ty::ParamEnv::reveal_all())) . .unwrap(), . } . } else { . output.push('['); 72 ( 0.00%) push_debuginfo_type_name(tcx, inner_type, true, output, visited); 24 ( 0.00%) match len.val { . ty::ConstKind::Param(param) => write!(output, "; {}]", param.name).unwrap(), 108 ( 0.00%) _ => write!(output, "; {}]", len.eval_usize(tcx, ty::ParamEnv::reveal_all())) . .unwrap(), . } . } . } 17 ( 0.00%) ty::Slice(inner_type) => { 17 ( 0.00%) if cpp_like_debuginfo { . output.push_str("slice$<"); . } else { . output.push('['); . } . 85 ( 0.00%) push_debuginfo_type_name(tcx, inner_type, true, output, visited); . . if cpp_like_debuginfo { . push_close_angle_bracket(cpp_like_debuginfo, output); . } else { . output.push(']'); . } . } . ty::Dynamic(ref trait_data, ..) => { 672 ( 0.00%) let auto_traits: SmallVec<[DefId; 4]> = trait_data.auto_traits().collect(); . 672 ( 0.00%) let has_enclosing_parens = if cpp_like_debuginfo { . output.push_str("dyn$<"); . false . } else { 4,030 ( 0.00%) if trait_data.len() > 1 && auto_traits.len() != 0 { . // We need enclosing parens because there is more than one trait . output.push_str("(dyn "); . true . } else { . output.push_str("dyn "); . false . } . }; . 3,360 ( 0.00%) if let Some(principal) = trait_data.principal() { . let principal = 7,392 ( 0.00%) tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), principal); 4,032 ( 0.00%) push_item_name(tcx, principal.def_id, qualified, output); . let principal_has_generic_params = 3,360 ( 0.00%) push_generic_params_internal(tcx, principal.substs, output, visited); . 672 ( 0.00%) let projection_bounds: SmallVec<[_; 4]> = trait_data . .projection_bounds() . .map(|bound| { . let ExistentialProjection { item_def_id, term, .. } = bound.skip_binder(); . // FIXME(associated_const_equality): allow for consts here . (item_def_id, term.ty().unwrap()) . }) . .collect(); . 2,016 ( 0.00%) if projection_bounds.len() != 0 { . if principal_has_generic_params { . // push_generic_params_internal() above added a `>` but we actually . // want to add more items to that list, so remove that again. . pop_close_angle_bracket(output); . } . . for (item_def_id, ty) in projection_bounds { . push_arg_separator(cpp_like_debuginfo, output); -- line 220 ---------------------------------------- -- line 230 ---------------------------------------- . output.push('='); . push_debuginfo_type_name(tcx, ty, true, output, visited); . } . } . . push_close_angle_bracket(cpp_like_debuginfo, output); . } . 1,344 ( 0.00%) if auto_traits.len() != 0 { 671 ( 0.00%) push_auto_trait_separator(cpp_like_debuginfo, output); . } 672 ( 0.00%) } . 2,016 ( 0.00%) if auto_traits.len() != 0 { 3,355 ( 0.00%) let mut auto_traits: SmallVec<[String; 4]> = auto_traits . .into_iter() . .map(|def_id| { . let mut name = String::with_capacity(20); 3,355 ( 0.00%) push_item_name(tcx, def_id, true, &mut name); . name . }) . .collect(); . auto_traits.sort_unstable(); . 14,762 ( 0.00%) for auto_trait in auto_traits { . output.push_str(&auto_trait); . push_auto_trait_separator(cpp_like_debuginfo, output); . } . . pop_auto_trait_separator(output); . } . 672 ( 0.00%) if cpp_like_debuginfo { . push_close_angle_bracket(cpp_like_debuginfo, output); 1,344 ( 0.00%) } else if has_enclosing_parens { 1,342 ( 0.00%) output.push(')'); . } 672 ( 0.00%) } . ty::FnDef(..) | ty::FnPtr(_) => { . // We've encountered a weird 'recursive type' . // Currently, the only way to generate such a type . // is by using 'impl trait': . // . // fn foo() -> impl Copy { foo } . // . // There's not really a sensible name we can generate, . // since we don't include 'impl trait' types (e.g. ty::Opaque) . // in the output . // . // Since we need to generate *something*, we just . // use a dummy string that should make it clear . // that something unusual is going on 36 ( 0.00%) if !visited.insert(t) { . output.push_str(if cpp_like_debuginfo { . "recursive_type$" . } else { . "" . }); . return; . } . . let sig = 198 ( 0.00%) tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), t.fn_sig(tcx)); . 18 ( 0.00%) if cpp_like_debuginfo { . // Format as a C++ function pointer: return_type (*)(params...) . if sig.output().is_unit() { . output.push_str("void"); . } else { . push_debuginfo_type_name(tcx, sig.output(), true, output, visited); . } . output.push_str(" (*)("); . } else { 54 ( 0.00%) output.push_str(sig.unsafety.prefix_str()); . 18 ( 0.00%) if sig.abi != rustc_target::spec::abi::Abi::Rust { . output.push_str("extern \""); . output.push_str(sig.abi.name()); . output.push_str("\" "); . } . . output.push_str("fn("); . } . 36 ( 0.00%) if !sig.inputs().is_empty() { 4 ( 0.00%) for ¶meter_type in sig.inputs() { 12 ( 0.00%) push_debuginfo_type_name(tcx, parameter_type, true, output, visited); . push_arg_separator(cpp_like_debuginfo, output); . } . pop_arg_separator(output); . } . 36 ( 0.00%) if sig.c_variadic { . if !sig.inputs().is_empty() { . output.push_str(", ..."); . } else { . output.push_str("..."); . } . } . . output.push(')'); . 36 ( 0.00%) if !cpp_like_debuginfo && !sig.output().is_unit() { . output.push_str(" -> "); 162 ( 0.00%) push_debuginfo_type_name(tcx, sig.output(), true, output, visited); . } . . // We only keep the type in 'visited' . // for the duration of the body of this method. . // It's fine for a particular function type . // to show up multiple times in one overall type . // (e.g. MyType u8, fn() -> u8> . // . // We only care about avoiding recursing . // directly back to the type we're currently . // processing 36 ( 0.00%) visited.remove(t); . } . ty::Closure(def_id, ..) | ty::Generator(def_id, ..) => { 306 ( 0.00%) let key = tcx.def_key(def_id); 102 ( 0.00%) if qualified { . let parent_def_id = DefId { index: key.parent.unwrap(), ..def_id }; 231 ( 0.00%) push_item_name(tcx, parent_def_id, true, output); . output.push_str("::"); . } 663 ( 0.00%) push_unqualified_item_name(tcx, def_id, key.disambiguated_data, output); . } . // Type parameters from polymorphized functions. . ty::Param(_) => { . output.push_str(&format!("{:?}", t)); . } . ty::Error(_) . | ty::Infer(_) . | ty::Placeholder(..) -- line 363 ---------------------------------------- -- line 422 ---------------------------------------- . output.push_str(&format!(", {}", variant)); . } . } . push_close_angle_bracket(true, output); . } . . const NON_CPP_AUTO_TRAIT_SEPARATOR: &str = " + "; . 1,342 ( 0.00%) fn push_auto_trait_separator(cpp_like_debuginfo: bool, output: &mut String) { 2,013 ( 0.00%) if cpp_like_debuginfo { . push_arg_separator(cpp_like_debuginfo, output); . } else { . output.push_str(NON_CPP_AUTO_TRAIT_SEPARATOR); . } 1,342 ( 0.00%) } . . fn pop_auto_trait_separator(output: &mut String) { 671 ( 0.00%) if output.ends_with(NON_CPP_AUTO_TRAIT_SEPARATOR) { 2,684 ( 0.00%) output.truncate(output.len() - NON_CPP_AUTO_TRAIT_SEPARATOR.len()); . } else { . pop_arg_separator(output); . } . } 8,936 ( 0.00%) } . . /// Computes a name for the global variable storing a vtable. . /// . /// The name is of the form: . /// . /// `::{vtable}` . /// . /// or, when generating C++-like names: . /// . /// `impl$::vtable$` 11 ( 0.00%) pub fn compute_debuginfo_vtable_name<'tcx>( . tcx: TyCtxt<'tcx>, . t: Ty<'tcx>, . trait_ref: Option>, . ) -> String { . let cpp_like_debuginfo = cpp_like_debuginfo(tcx); . . let mut vtable_name = String::with_capacity(64); . 1 ( 0.00%) if cpp_like_debuginfo { . vtable_name.push_str("impl$<"); . } else { . vtable_name.push('<'); . } . . let mut visited = FxHashSet::default(); 5 ( 0.00%) push_debuginfo_type_name(tcx, t, true, &mut vtable_name, &mut visited); . 1 ( 0.00%) if cpp_like_debuginfo { . vtable_name.push_str(", "); . } else { . vtable_name.push_str(" as "); . } . 2 ( 0.00%) if let Some(trait_ref) = trait_ref { . let trait_ref = 10 ( 0.00%) tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), trait_ref); 6 ( 0.00%) push_item_name(tcx, trait_ref.def_id, true, &mut vtable_name); . visited.clear(); 4 ( 0.00%) push_generic_params_internal(tcx, trait_ref.substs, &mut vtable_name, &mut visited); . } else { . vtable_name.push_str("_"); . } . 4 ( 0.00%) push_close_angle_bracket(cpp_like_debuginfo, &mut vtable_name); . 1 ( 0.00%) let suffix = if cpp_like_debuginfo { "::vtable$" } else { "::{vtable}" }; . . vtable_name.reserve_exact(suffix.len()); . vtable_name.push_str(suffix); . . vtable_name 9 ( 0.00%) } . 190,668 ( 0.04%) pub fn push_item_name(tcx: TyCtxt<'_>, def_id: DefId, qualified: bool, output: &mut String) { 79,445 ( 0.01%) let def_key = tcx.def_key(def_id); 63,556 ( 0.01%) if qualified { . if let Some(parent) = def_key.parent { 54,066 ( 0.01%) push_item_name(tcx, DefId { krate: def_id.krate, index: parent }, true, output); . output.push_str("::"); . } . } . 222,446 ( 0.04%) push_unqualified_item_name(tcx, def_id, def_key.disambiguated_data, output); . } . 191,280 ( 0.04%) fn push_unqualified_item_name( . tcx: TyCtxt<'_>, . def_id: DefId, . disambiguated_data: DisambiguatedDefPathData, . output: &mut String, . ) { 54,950 ( 0.01%) match disambiguated_data.data { . DefPathData::CrateRoot => { 22,025 ( 0.00%) output.push_str(tcx.crate_name(def_id.krate).as_str()); . } 60 ( 0.00%) DefPathData::ClosureExpr if tcx.generator_kind(def_id).is_some() => { . let key = match tcx.generator_kind(def_id).unwrap() { . hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Block) => "async_block", . hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Closure) => "async_closure", . hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Fn) => "async_fn", . hir::GeneratorKind::Gen => "generator", . }; . // Generators look like closures, but we want to treat them differently . // in the debug info. . if cpp_like_debuginfo(tcx) { . write!(output, "{}${}", key, disambiguated_data.disambiguator).unwrap(); . } else { . write!(output, "{{{}#{}}}", key, disambiguated_data.disambiguator).unwrap(); . } . } 34,605 ( 0.01%) _ => match disambiguated_data.data.name() { 22,840 ( 0.00%) DefPathDataName::Named(name) => { 34,260 ( 0.01%) output.push_str(name.as_str()); . } 115 ( 0.00%) DefPathDataName::Anon { namespace } => { 115 ( 0.00%) if cpp_like_debuginfo(tcx) { . write!(output, "{}${}", namespace, disambiguated_data.disambiguator).unwrap(); . } else { 1,035 ( 0.00%) write!(output, "{{{}#{}}}", namespace, disambiguated_data.disambiguator) . .unwrap(); . } . } . }, . }; 127,520 ( 0.02%) } . . // Pushes the generic parameters in the given `InternalSubsts` to the output string. . // This ignores region parameters, since they can't reliably be . // reconstructed for items from non-local crates. For local crates, this . // would be possible but with inlining and LTO we have to use the least . // common denominator - otherwise we would run into conflicts. 59,521 ( 0.01%) fn push_generic_params_internal<'tcx>( . tcx: TyCtxt<'tcx>, . substs: SubstsRef<'tcx>, . output: &mut String, . visited: &mut FxHashSet>, . ) -> bool { . if substs.non_erasable_generics().next().is_none() { . return false; . } -- line 566 ---------------------------------------- -- line 569 ---------------------------------------- . . let cpp_like_debuginfo = cpp_like_debuginfo(tcx); . . output.push('<'); . . for type_parameter in substs.non_erasable_generics() { . match type_parameter { . GenericArgKind::Type(type_parameter) => { 22,644 ( 0.00%) push_debuginfo_type_name(tcx, type_parameter, true, output, visited); . } . GenericArgKind::Const(ct) => { . push_const_param(tcx, ct, output); . } . other => bug!("Unexpected non-erasable generic: {:?}", other), . } . . push_arg_separator(cpp_like_debuginfo, output); . } . pop_arg_separator(output); 11,300 ( 0.00%) push_close_angle_bracket(cpp_like_debuginfo, output); . . true 43,288 ( 0.01%) } . . fn push_const_param<'tcx>(tcx: TyCtxt<'tcx>, ct: &'tcx ty::Const<'tcx>, output: &mut String) { . match ct.val { . ty::ConstKind::Param(param) => { . write!(output, "{}", param.name) . } . _ => match ct.ty.kind() { . ty::Int(ity) => { -- line 599 ---------------------------------------- -- line 630 ---------------------------------------- . write!(output, "{{CONST#{:x}}}", hash) . } . } . }, . } . .unwrap(); . } . 1,308 ( 0.00%) pub fn push_generic_params<'tcx>(tcx: TyCtxt<'tcx>, substs: SubstsRef<'tcx>, output: &mut String) { . let _prof = tcx.prof.generic_activity("compute_debuginfo_type_name"); . let mut visited = FxHashSet::default(); 436 ( 0.00%) push_generic_params_internal(tcx, substs, output, &mut visited); 763 ( 0.00%) } . 5,652 ( 0.00%) fn push_close_angle_bracket(cpp_like_debuginfo: bool, output: &mut String) { . // MSVC debugger always treats `>>` as a shift, even when parsing templates, . // so add a space to avoid confusion. 5,652 ( 0.00%) if cpp_like_debuginfo && output.ends_with('>') { . output.push(' ') . }; . . output.push('>'); 5,652 ( 0.00%) } . . fn pop_close_angle_bracket(output: &mut String) { . assert!(output.ends_with('>'), "'output' does not end with '>': {}", output); . output.pop(); . if output.ends_with(' ') { . output.pop(); . } . } . . fn push_arg_separator(cpp_like_debuginfo: bool, output: &mut String) { . // Natvis does not always like having spaces between parts of the type name . // and this causes issues when we need to write a typename in natvis, for example . // as part of a cast like the `HashMap` visualizer does. 3,775 ( 0.00%) if cpp_like_debuginfo { . output.push(','); . } else { . output.push_str(", "); . }; . } . . fn pop_arg_separator(output: &mut String) { 2,834 ( 0.00%) if output.ends_with(' ') { . output.pop(); . } . 2,834 ( 0.00%) assert!(output.ends_with(',')); . . output.pop(); . } . . /// Check if we should generate C++ like names and debug information. 593 ( 0.00%) pub fn cpp_like_debuginfo(tcx: TyCtxt<'_>) -> bool { 37,738 ( 0.01%) tcx.sess.target.is_like_msvc 1,186 ( 0.00%) } 38,309 ( 0.01%) -------------------------------------------------------------------------------- -- Auto-annotated source: /usr/home/liquid/.cargo/registry/src/github.com-1ecc6299db9ec823/hashbrown-0.12.0/src/rustc_entry.rs -------------------------------------------------------------------------------- Ir -- line 26 ---------------------------------------- . /// } . /// . /// assert_eq!(letters[&'s'], 2); . /// assert_eq!(letters[&'t'], 3); . /// assert_eq!(letters[&'u'], 1); . /// assert_eq!(letters.get(&'y'), None); . /// ``` . #[cfg_attr(feature = "inline-more", inline)] 668,951 ( 0.12%) pub fn rustc_entry(&mut self, key: K) -> RustcEntry<'_, K, V, A> { 8 ( 0.00%) let hash = make_insert_hash(&self.hash_builder, &key); 1,200 ( 0.00%) if let Some(elem) = self.table.find(hash, |q| q.0.eq(&key)) { 102,363 ( 0.02%) RustcEntry::Occupied(RustcOccupiedEntry { 56,615 ( 0.01%) key: Some(key), . elem, . table: &mut self.table, . }) . } else { . // Ideally we would put this in VacantEntry::insert, but Entry is not . // generic over the BuildHasher and adding a generic parameter would be . // a breaking change. 4 ( 0.00%) self.reserve(1); . 113,036 ( 0.02%) RustcEntry::Vacant(RustcVacantEntry { . hash, 20,280 ( 0.00%) key, . table: &mut self.table, . }) . } 549,067 ( 0.10%) } . } . . /// A view into a single entry in a map, which may either be vacant or occupied. . /// . /// This `enum` is constructed from the [`entry`] method on [`HashMap`]. . /// . /// [`HashMap`]: struct.HashMap.html . /// [`entry`]: struct.HashMap.html#method.rustc_entry -- line 62 ---------------------------------------- -- line 405 ---------------------------------------- . /// if let RustcEntry::Occupied(o) = map.rustc_entry("poneyland") { . /// *o.into_mut() += 10; . /// } . /// . /// assert_eq!(map["poneyland"], 22); . /// ``` . #[cfg_attr(feature = "inline-more", inline)] . pub fn into_mut(self) -> &'a mut V { 26,655 ( 0.00%) unsafe { &mut self.elem.as_mut().1 } . } . . /// Sets the value of the entry, and returns the entry's old value. . /// . /// # Examples . /// . /// ``` . /// use hashbrown::HashMap; -- line 421 ---------------------------------------- -- line 568 ---------------------------------------- . /// let mut map: HashMap<&str, u32> = HashMap::new(); . /// . /// if let RustcEntry::Vacant(o) = map.rustc_entry("poneyland") { . /// o.insert(37); . /// } . /// assert_eq!(map["poneyland"], 37); . /// ``` . #[cfg_attr(feature = "inline-more", inline)] 948 ( 0.00%) pub fn insert(self, value: V) -> &'a mut V { . unsafe { 10,478 ( 0.00%) let bucket = self.table.insert_no_grow(self.hash, (self.key, value)); 749 ( 0.00%) &mut bucket.as_mut().1 . } 1,124 ( 0.00%) } . . /// Sets the value of the entry with the RustcVacantEntry's key, . /// and returns a RustcOccupiedEntry. . /// . /// # Examples . /// . /// ``` . /// use hashbrown::HashMap; -- line 589 ---------------------------------------- 183,562 ( 0.03%) -------------------------------------------------------------------------------- -- Auto-annotated source: /usr/home/liquid/.cargo/registry/src/github.com-1ecc6299db9ec823/rustc-hash-1.1.0/src/lib.rs -------------------------------------------------------------------------------- Ir -- line 71 ---------------------------------------- . fn default() -> FxHasher { . FxHasher { hash: 0 } . } . } . . impl FxHasher { . #[inline] . fn add_to_hash(&mut self, i: usize) { 174,934 ( 0.03%) self.hash = self.hash.rotate_left(5).bitxor(i).wrapping_mul(K); . } . } . . impl Hasher for FxHasher { . #[inline] 1,590 ( 0.00%) fn write(&mut self, mut bytes: &[u8]) { . #[cfg(target_pointer_width = "32")] . let read_usize = |bytes: &[u8]| u32::from_ne_bytes(bytes[..4].try_into().unwrap()); . #[cfg(target_pointer_width = "64")] . let read_usize = |bytes: &[u8]| u64::from_ne_bytes(bytes[..8].try_into().unwrap()); . 52,583 ( 0.01%) let mut hash = FxHasher { hash: self.hash }; . assert!(size_of::() <= 8); 805,127 ( 0.15%) while bytes.len() >= size_of::() { . hash.add_to_hash(read_usize(bytes) as usize); . bytes = &bytes[size_of::()..]; . } 121,326 ( 0.02%) if (size_of::() > 4) && (bytes.len() >= 4) { . hash.add_to_hash(u32::from_ne_bytes(bytes[..4].try_into().unwrap()) as usize); . bytes = &bytes[4..]; . } 121,326 ( 0.02%) if (size_of::() > 2) && bytes.len() >= 2 { . hash.add_to_hash(u16::from_ne_bytes(bytes[..2].try_into().unwrap()) as usize); . bytes = &bytes[2..]; . } 134,271 ( 0.02%) if (size_of::() > 1) && bytes.len() >= 1 { 26,902 ( 0.00%) hash.add_to_hash(bytes[0] as usize); . } 2,899 ( 0.00%) self.hash = hash.hash; 1,590 ( 0.00%) } . . #[inline] . fn write_u8(&mut self, i: u8) { 2,018 ( 0.00%) self.add_to_hash(i as usize); . } . . #[inline] . fn write_u16(&mut self, i: u16) { 55 ( 0.00%) self.add_to_hash(i as usize); . } . . #[inline] . fn write_u32(&mut self, i: u32) { 161,452 ( 0.03%) self.add_to_hash(i as usize); . } . . #[cfg(target_pointer_width = "32")] . #[inline] . fn write_u64(&mut self, i: u64) { . self.add_to_hash(i as usize); . self.add_to_hash((i >> 32) as usize); . } -- line 131 ---------------------------------------- 5,126 ( 0.00%) -------------------------------------------------------------------------------- -- Auto-annotated source: /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_span/src/lib.rs -------------------------------------------------------------------------------- Ir -- line 84 ---------------------------------------- . pub struct SessionGlobals { . symbol_interner: symbol::Interner, . span_interner: Lock, . hygiene_data: Lock, . source_map: Lock>>, . } . . impl SessionGlobals { 12 ( 0.00%) pub fn new(edition: Edition) -> SessionGlobals { 50 ( 0.00%) SessionGlobals { 2 ( 0.00%) symbol_interner: symbol::Interner::fresh(), . span_interner: Lock::new(span_encoding::SpanInterner::default()), 6 ( 0.00%) hygiene_data: Lock::new(hygiene::HygieneData::new(edition)), . source_map: Lock::new(None), . } 10 ( 0.00%) } . } . . #[inline] . pub fn create_session_globals_then(edition: Edition, f: impl FnOnce() -> R) -> R { 1 ( 0.00%) assert!( . !SESSION_GLOBALS.is_set(), . "SESSION_GLOBALS should never be overwritten! \ . Use another thread if you need another SessionGlobals" . ); 3 ( 0.00%) let session_globals = SessionGlobals::new(edition); 7 ( 0.00%) SESSION_GLOBALS.set(&session_globals, f) 1 ( 0.00%) } . . #[inline] . pub fn set_session_globals_then(session_globals: &SessionGlobals, f: impl FnOnce() -> R) -> R { . assert!( . !SESSION_GLOBALS.is_set(), . "SESSION_GLOBALS should never be overwritten! \ . Use another thread if you need another SessionGlobals" . ); -- line 119 ---------------------------------------- -- line 120 ---------------------------------------- . SESSION_GLOBALS.set(session_globals, f) . } . . #[inline] . pub fn create_default_session_if_not_set_then(f: F) -> R . where . F: FnOnce(&SessionGlobals) -> R, . { 4 ( 0.00%) create_session_if_not_set_then(edition::DEFAULT_EDITION, f) . } . . #[inline] . pub fn create_session_if_not_set_then(edition: Edition, f: F) -> R . where . F: FnOnce(&SessionGlobals) -> R, . { 1 ( 0.00%) if !SESSION_GLOBALS.is_set() { 3 ( 0.00%) let session_globals = SessionGlobals::new(edition); 11 ( 0.00%) SESSION_GLOBALS.set(&session_globals, || SESSION_GLOBALS.with(f)) 1 ( 0.00%) } else { . SESSION_GLOBALS.with(f) . } . } . . #[inline] . pub fn with_session_globals(f: F) -> R . where . F: FnOnce(&SessionGlobals) -> R, . { 38,457 ( 0.01%) SESSION_GLOBALS.with(f) . } . . #[inline] . pub fn create_default_session_globals_then(f: impl FnOnce() -> R) -> R { . create_session_globals_then(edition::DEFAULT_EDITION, f) . } . . // If this ever becomes non thread-local, `decode_syntax_context` . // and `decode_expn_id` will need to be updated to handle concurrent . // deserialization. . scoped_tls::scoped_thread_local!(static SESSION_GLOBALS: SessionGlobals); . . // FIXME: We should use this enum or something like it to get rid of the . // use of magic `/rust/1.x/...` paths across the board. 43 ( 0.00%) #[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd)] 1,232 ( 0.00%) #[derive(Decodable)] . pub enum RealFileName { 6 ( 0.00%) LocalPath(PathBuf), . /// For remapped paths (namely paths into libstd that have been mapped . /// to the appropriate spot on the local host's file system, and local file . /// system paths that have been remapped with `FilePathMapping`), . Remapped { . /// `local_path` is the (host-dependent) local path to the file. This is . /// None if the file was imported from another crate . local_path: Option, . /// `virtual_name` is the stable path rustc will store internally within -- line 175 ---------------------------------------- -- line 179 ---------------------------------------- . } . . impl Hash for RealFileName { . fn hash(&self, state: &mut H) { . // To prevent #70924 from happening again we should only hash the . // remapped (virtualized) path if that exists. This is because . // virtualized paths to sysroot crates (/rust/$hash or /rust/$version) . // remain stable even if the corresponding local_path changes 3,105 ( 0.00%) self.remapped_path_if_available().hash(state) . } . } . . // This is functionally identical to #[derive(Encodable)], with the exception of . // an added assert statement . impl Encodable for RealFileName { . fn encode(&self, encoder: &mut S) -> Result<(), S::Error> { 2 ( 0.00%) encoder.emit_enum(|encoder| match *self { . RealFileName::LocalPath(ref local_path) => { 8 ( 0.00%) encoder.emit_enum_variant("LocalPath", 0, 1, |encoder| { . encoder.emit_enum_variant_arg(true, |encoder| local_path.encode(encoder))?; . Ok(()) . }) . } . . RealFileName::Remapped { ref local_path, ref virtual_name } => encoder . .emit_enum_variant("Remapped", 1, 2, |encoder| { . // For privacy and build reproducibility, we must not embed host-dependant path in artifacts -- line 205 ---------------------------------------- -- line 213 ---------------------------------------- . } . } . . impl RealFileName { . /// Returns the path suitable for reading from the file system on the local host, . /// if this information exists. . /// Avoid embedding this in build artifacts; see `remapped_path_if_available()` for that. . pub fn local_path(&self) -> Option<&Path> { 4 ( 0.00%) match self { . RealFileName::LocalPath(p) => Some(p), . RealFileName::Remapped { local_path: p, virtual_name: _ } => { . p.as_ref().map(PathBuf::as_path) . } . } . } . . /// Returns the path suitable for reading from the file system on the local host, . /// if this information exists. . /// Avoid embedding this in build artifacts; see `remapped_path_if_available()` for that. 2 ( 0.00%) pub fn into_local_path(self) -> Option { 2 ( 0.00%) match self { . RealFileName::LocalPath(p) => Some(p), . RealFileName::Remapped { local_path: p, virtual_name: _ } => p, . } 3 ( 0.00%) } . . /// Returns the path suitable for embedding into build artifacts. This would still . /// be a local path if it has not been remapped. A remapped path will not correspond . /// to a valid file system path: see `local_path_if_available()` for something that . /// is more likely to return paths into the local host file system. . pub fn remapped_path_if_available(&self) -> &Path { 3,392 ( 0.00%) match self { . RealFileName::LocalPath(p) . | RealFileName::Remapped { local_path: _, virtual_name: p } => &p, . } 2 ( 0.00%) } . . /// Returns the path suitable for reading from the file system on the local host, . /// if this information exists. Otherwise returns the remapped name. . /// Avoid embedding this in build artifacts; see `remapped_path_if_available()` for that. . pub fn local_path_if_available(&self) -> &Path { 1 ( 0.00%) match self { . RealFileName::LocalPath(path) . | RealFileName::Remapped { local_path: None, virtual_name: path } . | RealFileName::Remapped { local_path: Some(path), virtual_name: _ } => path, . } . } . 164 ( 0.00%) pub fn to_string_lossy(&self, display_pref: FileNameDisplayPreference) -> Cow<'_, str> { 539 ( 0.00%) match display_pref { . FileNameDisplayPreference::Local => self.local_path_if_available().to_string_lossy(), . FileNameDisplayPreference::Remapped => { . self.remapped_path_if_available().to_string_lossy() . } . } 246 ( 0.00%) } . } . . /// Differentiates between real files and common virtual files. 6,377 ( 0.00%) #[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Hash)] 7,450 ( 0.00%) #[derive(Decodable, Encodable)] . pub enum FileName { . Real(RealFileName), . /// Call to `quote!`. . QuoteExpansion(u64), . /// Command line. . Anon(u64), . /// Hack in `src/librustc_ast/parse.rs`. . // FIXME(jseyfried) -- line 281 ---------------------------------------- -- line 288 ---------------------------------------- . /// Custom sources for explicit parser calls from plugins and drivers. . Custom(String), . DocTest(PathBuf, isize), . /// Post-substitution inline assembly from LLVM. . InlineAsm(u64), . } . . impl From for FileName { 7 ( 0.00%) fn from(p: PathBuf) -> Self { 2 ( 0.00%) assert!(!p.to_string_lossy().ends_with('>')); 6 ( 0.00%) FileName::Real(RealFileName::LocalPath(p)) 7 ( 0.00%) } . } . 34 ( 0.00%) #[derive(Clone, Copy, Eq, PartialEq, Hash, Debug)] . pub enum FileNameDisplayPreference { . Remapped, . Local, . } . . pub struct FileNameDisplay<'a> { . inner: &'a FileName, . display_pref: FileNameDisplayPreference, . } . . impl fmt::Display for FileNameDisplay<'_> { 1,460 ( 0.00%) fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { . use FileName::*; 2,190 ( 0.00%) match *self.inner { . Real(ref name) => { 2,190 ( 0.00%) write!(fmt, "{}", name.to_string_lossy(self.display_pref)) . } . QuoteExpansion(_) => write!(fmt, ""), . MacroExpansion(_) => write!(fmt, ""), . Anon(_) => write!(fmt, ""), . ProcMacroSourceCode(_) => write!(fmt, ""), . CfgSpec(_) => write!(fmt, ""), . CliCrateAttr(_) => write!(fmt, ""), . Custom(ref s) => write!(fmt, "<{}>", s), . DocTest(ref path, _) => write!(fmt, "{}", path.display()), . InlineAsm(_) => write!(fmt, ""), . } 1,825 ( 0.00%) } . } . . impl FileNameDisplay<'_> { 40 ( 0.00%) pub fn to_string_lossy(&self) -> Cow<'_, str> { 30 ( 0.00%) match self.inner { 10 ( 0.00%) FileName::Real(ref inner) => inner.to_string_lossy(self.display_pref), . _ => Cow::from(format!("{}", self)), . } 40 ( 0.00%) } . } . . impl FileName { . pub fn is_real(&self) -> bool { . use FileName::*; 1,934 ( 0.00%) match *self { . Real(_) => true, . Anon(_) . | MacroExpansion(_) . | ProcMacroSourceCode(_) . | CfgSpec(_) . | CliCrateAttr(_) . | Custom(_) . | QuoteExpansion(_) . | DocTest(_, _) . | InlineAsm(_) => false, . } . } . 363 ( 0.00%) pub fn prefer_remapped(&self) -> FileNameDisplay<'_> { . FileNameDisplay { inner: self, display_pref: FileNameDisplayPreference::Remapped } 726 ( 0.00%) } . . // This may include transient local filesystem information. . // Must not be embedded in build outputs. 1 ( 0.00%) pub fn prefer_local(&self) -> FileNameDisplay<'_> { . FileNameDisplay { inner: self, display_pref: FileNameDisplayPreference::Local } 2 ( 0.00%) } . . pub fn display(&self, display_pref: FileNameDisplayPreference) -> FileNameDisplay<'_> { . FileNameDisplay { inner: self, display_pref } . } . . pub fn macro_expansion_source_code(src: &str) -> FileName { . let mut hasher = StableHasher::new(); . src.hash(&mut hasher); -- line 375 ---------------------------------------- -- line 423 ---------------------------------------- . /// that the length of the span is equal to `span.hi - span.lo`; there may be space in the . /// [`BytePos`] range between files. . /// . /// `SpanData` is public because `Span` uses a thread-local interner and can't be . /// sent to other threads, but some pieces of performance infra run in a separate thread. . /// Using `Span` is generally preferred. . #[derive(Clone, Copy, Hash, PartialEq, Eq)] . pub struct SpanData { 3 ( 0.00%) pub lo: BytePos, 3 ( 0.00%) pub hi: BytePos, . /// Information about where the macro came from, if this piece of . /// code was created by a macro expansion. 9 ( 0.00%) pub ctxt: SyntaxContext, 3 ( 0.00%) pub parent: Option, . } . . // Order spans by position in the file. . impl Ord for SpanData { . fn cmp(&self, other: &Self) -> Ordering { . let SpanData { . lo: s_lo, . hi: s_hi, -- line 444 ---------------------------------------- -- line 485 ---------------------------------------- . } . #[inline] . pub fn with_parent(&self, parent: Option) -> Span { . Span::new(self.lo, self.hi, self.ctxt, parent) . } . /// Returns `true` if this is a dummy span with any hygienic context. . #[inline] . pub fn is_dummy(self) -> bool { 11,668 ( 0.00%) self.lo.0 == 0 && self.hi.0 == 0 . } . /// Returns `true` if `self` fully encloses `other`. . pub fn contains(self, other: Self) -> bool { 36 ( 0.00%) self.lo <= other.lo && other.hi <= self.hi . } . } . . // The interner is pointed to by a thread local value which is only set on the main thread . // with parallelization is disabled. So we don't allow `Span` to transfer between threads . // to avoid panics and other errors, even though it would be memory safe to do so. . #[cfg(not(parallel_compiler))] . impl !Send for Span {} . #[cfg(not(parallel_compiler))] . impl !Sync for Span {} . . impl PartialOrd for Span { 5,712 ( 0.00%) fn partial_cmp(&self, rhs: &Self) -> Option { 4,284 ( 0.00%) PartialOrd::partial_cmp(&self.data(), &rhs.data()) 5,712 ( 0.00%) } . } . impl Ord for Span { . fn cmp(&self, rhs: &Self) -> Ordering { . Ord::cmp(&self.data(), &rhs.data()) . } . } . . /// A collection of `Span`s. -- line 520 ---------------------------------------- -- line 532 ---------------------------------------- . } . . impl Span { . #[inline] . pub fn lo(self) -> BytePos { . self.data().lo . } . #[inline] 4,374 ( 0.00%) pub fn with_lo(self, lo: BytePos) -> Span { . self.data().with_lo(lo) 2,916 ( 0.00%) } . #[inline] 288 ( 0.00%) pub fn hi(self) -> BytePos { . self.data().hi 288 ( 0.00%) } . #[inline] 855 ( 0.00%) pub fn with_hi(self, hi: BytePos) -> Span { . self.data().with_hi(hi) 570 ( 0.00%) } . #[inline] . pub fn ctxt(self) -> SyntaxContext { . self.data_untracked().ctxt . } . #[inline] 445 ( 0.00%) pub fn with_ctxt(self, ctxt: SyntaxContext) -> Span { . self.data_untracked().with_ctxt(ctxt) 267 ( 0.00%) } . #[inline] . pub fn parent(self) -> Option { . self.data().parent . } . #[inline] . pub fn with_parent(self, ctxt: Option) -> Span { . self.data().with_parent(ctxt) . } -- line 566 ---------------------------------------- -- line 600 ---------------------------------------- . /// Returns a new span representing an empty span at the beginning of this span. . #[inline] . pub fn shrink_to_lo(self) -> Span { . let span = self.data_untracked(); . span.with_hi(span.lo) . } . /// Returns a new span representing an empty span at the end of this span. . #[inline] 6 ( 0.00%) pub fn shrink_to_hi(self) -> Span { . let span = self.data_untracked(); . span.with_lo(span.hi) 4 ( 0.00%) } . . #[inline] . /// Returns `true` if `hi == lo`. . pub fn is_empty(self) -> bool { . let span = self.data_untracked(); . span.hi == span.lo . } . . /// Returns `self` if `self` is not the dummy span, and `other` otherwise. . pub fn substitute_dummy(self, other: Span) -> Span { . if self.is_dummy() { other } else { self } . } . . /// Returns `true` if `self` fully encloses `other`. 108 ( 0.00%) pub fn contains(self, other: Span) -> bool { . let span = self.data(); . let other = other.data(); . span.contains(other) 72 ( 0.00%) } . . /// Returns `true` if `self` touches `other`. . pub fn overlaps(self, other: Span) -> bool { . let span = self.data(); . let other = other.data(); . span.lo < other.hi && other.lo < span.hi . } . -- line 638 ---------------------------------------- -- line 663 ---------------------------------------- . /// The `Span` for the tokens in the previous macro expansion from which `self` was generated, . /// if any. . pub fn parent_callsite(self) -> Option { . let expn_data = self.ctxt().outer_expn_data(); . if !expn_data.is_root() { Some(expn_data.call_site) } else { None } . } . . /// Walk down the expansion ancestors to find a span that's contained within `outer`. 110 ( 0.00%) pub fn find_ancestor_inside(mut self, outer: Span) -> Option { 55 ( 0.00%) while !outer.contains(self) { . self = self.parent_callsite()?; . } . Some(self) 121 ( 0.00%) } . . /// Edition of the crate from which this span came. 726 ( 0.00%) pub fn edition(self) -> edition::Edition { . self.ctxt().edition() 484 ( 0.00%) } . . #[inline] . pub fn rust_2015(self) -> bool { 166 ( 0.00%) self.edition() == edition::Edition::Edition2015 . } . . #[inline] . pub fn rust_2018(self) -> bool { 69 ( 0.00%) self.edition() >= edition::Edition::Edition2018 . } . . #[inline] . pub fn rust_2021(self) -> bool { 107 ( 0.00%) self.edition() >= edition::Edition::Edition2021 . } . . /// Returns the source callee. . /// . /// Returns `None` if the supplied span has no expansion trace, . /// else returns the `ExpnData` for the macro definition . /// corresponding to the source callsite. . pub fn source_callee(self) -> Option { -- line 703 ---------------------------------------- -- line 707 ---------------------------------------- . } . let expn_data = self.ctxt().outer_expn_data(); . if !expn_data.is_root() { Some(source_callee(expn_data)) } else { None } . } . . /// Checks if a span is "internal" to a macro in which `#[unstable]` . /// items can be used (that is, a macro marked with . /// `#[allow_internal_unstable]`). 140 ( 0.00%) pub fn allows_unstable(self, feature: Symbol) -> bool { 28 ( 0.00%) self.ctxt() . .outer_expn_data() . .allow_internal_unstable . .map_or(false, |features| features.iter().any(|&f| f == feature)) 112 ( 0.00%) } . . /// Checks if this span arises from a compiler desugaring of kind `kind`. 322 ( 0.00%) pub fn is_desugaring(self, kind: DesugaringKind) -> bool { 276 ( 0.00%) match self.ctxt().outer_expn_data().kind { . ExpnKind::Desugaring(k) => k == kind, . _ => false, . } 230 ( 0.00%) } . . /// Returns the compiler desugaring that created this span, or `None` . /// if this span is not from a desugaring. . pub fn desugaring_kind(self) -> Option { . match self.ctxt().outer_expn_data().kind { . ExpnKind::Desugaring(k) => Some(k), . _ => None, . } . } . . /// Checks if a span is "internal" to a macro in which `unsafe` . /// can be used without triggering the `unsafe_code` lint. . // (that is, a macro marked with `#[allow_internal_unsafe]`). 12 ( 0.00%) pub fn allows_unsafe(self) -> bool { 3 ( 0.00%) self.ctxt().outer_expn_data().allow_internal_unsafe 12 ( 0.00%) } . . pub fn macro_backtrace(mut self) -> impl Iterator { . let mut prev_span = DUMMY_SP; . std::iter::from_fn(move || { . loop { . let expn_data = self.ctxt().outer_expn_data(); . if expn_data.is_root() { . return None; -- line 752 ---------------------------------------- -- line 767 ---------------------------------------- . . /// Returns a `Span` that would enclose both `self` and `end`. . /// . /// ```text . /// ____ ___ . /// self lorem ipsum end . /// ^^^^^^^^^^^^^^^^^^^^ . /// ``` 12,045 ( 0.00%) pub fn to(self, end: Span) -> Span { . let span_data = self.data(); . let end_data = end.data(); . // FIXME(jseyfried): `self.ctxt` should always equal `end.ctxt` here (cf. issue #23480). . // Return the macro span on its own to avoid weird diagnostic output. It is preferable to . // have an incomplete span than a completely nonsensical one. 2,158 ( 0.00%) if span_data.ctxt != end_data.ctxt { 32 ( 0.00%) if span_data.ctxt == SyntaxContext::root() { . return end; 28 ( 0.00%) } else if end_data.ctxt == SyntaxContext::root() { . return self; . } . // Both spans fall within a macro. . // FIXME(estebank): check if it is the *same* macro. . } . Span::new( . cmp::min(span_data.lo, end_data.lo), . cmp::max(span_data.hi, end_data.hi), . if span_data.ctxt == SyntaxContext::root() { end_data.ctxt } else { span_data.ctxt }, 7,483 ( 0.00%) if span_data.parent == end_data.parent { span_data.parent } else { None }, . ) 9,855 ( 0.00%) } . . /// Returns a `Span` between the end of `self` to the beginning of `end`. . /// . /// ```text . /// ____ ___ . /// self lorem ipsum end . /// ^^^^^^^^^^^^^ . /// ``` 55 ( 0.00%) pub fn between(self, end: Span) -> Span { . let span = self.data(); . let end = end.data(); . Span::new( . span.hi, . end.lo, . if end.ctxt == SyntaxContext::root() { end.ctxt } else { span.ctxt }, 35 ( 0.00%) if span.parent == end.parent { span.parent } else { None }, . ) 40 ( 0.00%) } . . /// Returns a `Span` from the beginning of `self` until the beginning of `end`. . /// . /// ```text . /// ____ ___ . /// self lorem ipsum end . /// ^^^^^^^^^^^^^^^^^ . /// ``` 44 ( 0.00%) pub fn until(self, end: Span) -> Span { . // Most of this function's body is copied from `to`. . // We can't just do `self.to(end.shrink_to_lo())`, . // because to also does some magic where it uses min/max so . // it can handle overlapping spans. Some advanced mis-use of . // `until` with different ctxts makes this visible. . let span_data = self.data(); . let end_data = end.data(); . // FIXME(jseyfried): `self.ctxt` should always equal `end.ctxt` here (cf. issue #23480). . // Return the macro span on its own to avoid weird diagnostic output. It is preferable to . // have an incomplete span than a completely nonsensical one. 8 ( 0.00%) if span_data.ctxt != end_data.ctxt { . if span_data.ctxt == SyntaxContext::root() { . return end; . } else if end_data.ctxt == SyntaxContext::root() { . return self; . } . // Both spans fall within a macro. . // FIXME(estebank): check if it is the *same* macro. . } . Span::new( . span_data.lo, . end_data.lo, . if end_data.ctxt == SyntaxContext::root() { end_data.ctxt } else { span_data.ctxt }, 28 ( 0.00%) if span_data.parent == end_data.parent { span_data.parent } else { None }, . ) 36 ( 0.00%) } . 22 ( 0.00%) pub fn from_inner(self, inner: InnerSpan) -> Span { . let span = self.data(); . Span::new( . span.lo + BytePos::from_usize(inner.start), . span.lo + BytePos::from_usize(inner.end), . span.ctxt, . span.parent, . ) 14 ( 0.00%) } . . /// Equivalent of `Span::def_site` from the proc macro API, . /// except that the location is taken from the `self` span. . pub fn with_def_site_ctxt(self, expn_id: ExpnId) -> Span { 82 ( 0.00%) self.with_ctxt_from_mark(expn_id, Transparency::Opaque) . } . . /// Equivalent of `Span::call_site` from the proc macro API, . /// except that the location is taken from the `self` span. . pub fn with_call_site_ctxt(self, expn_id: ExpnId) -> Span { 4 ( 0.00%) self.with_ctxt_from_mark(expn_id, Transparency::Transparent) . } . . /// Equivalent of `Span::mixed_site` from the proc macro API, . /// except that the location is taken from the `self` span. . pub fn with_mixed_site_ctxt(self, expn_id: ExpnId) -> Span { 2 ( 0.00%) self.with_ctxt_from_mark(expn_id, Transparency::SemiTransparent) . } . . /// Produces a span with the same location as `self` and context produced by a macro with the . /// given ID and transparency, assuming that macro was defined directly and not produced by . /// some other macro (which is the case for built-in and procedural macros). 528 ( 0.00%) pub fn with_ctxt_from_mark(self, expn_id: ExpnId, transparency: Transparency) -> Span { . self.with_ctxt(SyntaxContext::root().apply_mark(expn_id, transparency)) 308 ( 0.00%) } . . #[inline] . pub fn apply_mark(self, expn_id: ExpnId, transparency: Transparency) -> Span { . let span = self.data(); 5,454 ( 0.00%) span.with_ctxt(span.ctxt.apply_mark(expn_id, transparency)) . } . . #[inline] . pub fn remove_mark(&mut self) -> ExpnId { . let mut span = self.data(); . let mark = span.ctxt.remove_mark(); . *self = Span::new(span.lo, span.hi, span.ctxt, span.parent); . mark -- line 897 ---------------------------------------- -- line 901 ---------------------------------------- . pub fn adjust(&mut self, expn_id: ExpnId) -> Option { . let mut span = self.data(); . let mark = span.ctxt.adjust(expn_id); . *self = Span::new(span.lo, span.hi, span.ctxt, span.parent); . mark . } . . #[inline] 2,331 ( 0.00%) pub fn normalize_to_macros_2_0_and_adjust(&mut self, expn_id: ExpnId) -> Option { 1,554 ( 0.00%) let mut span = self.data(); 1,281 ( 0.00%) let mark = span.ctxt.normalize_to_macros_2_0_and_adjust(expn_id); 2,331 ( 0.00%) *self = Span::new(span.lo, span.hi, span.ctxt, span.parent); . mark 2,576 ( 0.00%) } . . #[inline] . pub fn glob_adjust(&mut self, expn_id: ExpnId, glob_span: Span) -> Option> { . let mut span = self.data(); . let mark = span.ctxt.glob_adjust(expn_id, glob_span); . *self = Span::new(span.lo, span.hi, span.ctxt, span.parent); . mark . } -- line 922 ---------------------------------------- -- line 929 ---------------------------------------- . ) -> Option> { . let mut span = self.data(); . let mark = span.ctxt.reverse_glob_adjust(expn_id, glob_span); . *self = Span::new(span.lo, span.hi, span.ctxt, span.parent); . mark . } . . #[inline] 1,648 ( 0.00%) pub fn normalize_to_macros_2_0(self) -> Span { . let span = self.data(); . span.with_ctxt(span.ctxt.normalize_to_macros_2_0()) 1,442 ( 0.00%) } . . #[inline] . pub fn normalize_to_macro_rules(self) -> Span { . let span = self.data(); . span.with_ctxt(span.ctxt.normalize_to_macro_rules()) . } . } . -- line 948 ---------------------------------------- -- line 958 ---------------------------------------- . . /// What label should we attach to this span (if any)? . pub label: Option, . } . . impl Default for Span { . fn default() -> Self { . DUMMY_SP 2 ( 0.00%) } . } . . impl Encodable for Span { . default fn encode(&self, s: &mut E) -> Result<(), E::Error> { . let span = self.data(); . s.emit_struct(false, |s| { . s.emit_struct_field("lo", true, |s| span.lo.encode(s))?; . s.emit_struct_field("hi", false, |s| span.hi.encode(s)) -- line 974 ---------------------------------------- -- line 990 ---------------------------------------- . /// any spans that are debug-printed during the closure's execution. . /// . /// Normally, the global `TyCtxt` is used to retrieve the `SourceMap` . /// (see `rustc_interface::callbacks::span_debug1`). However, some parts . /// of the compiler (e.g. `rustc_parse`) may debug-print `Span`s before . /// a `TyCtxt` is available. In this case, we fall back to . /// the `SourceMap` provided to this function. If that is not available, . /// we fall back to printing the raw `Span` field values. 9 ( 0.00%) pub fn with_source_map T>(source_map: Lrc, f: F) -> T { . with_session_globals(|session_globals| { 2 ( 0.00%) *session_globals.source_map.borrow_mut() = Some(source_map); . }); . struct ClearSourceMap; . impl Drop for ClearSourceMap { . fn drop(&mut self) { . with_session_globals(|session_globals| { 1 ( 0.00%) session_globals.source_map.borrow_mut().take(); . }); . } . } . . let _guard = ClearSourceMap; 4 ( 0.00%) f() 8 ( 0.00%) } . . pub fn debug_with_source_map( . span: Span, . f: &mut fmt::Formatter<'_>, . source_map: &SourceMap, . ) -> fmt::Result { . write!(f, "{} ({:?})", source_map.span_to_diagnostic_string(span), span.ctxt()) . } -- line 1021 ---------------------------------------- -- line 1048 ---------------------------------------- . . impl MultiSpan { . #[inline] . pub fn new() -> MultiSpan { . MultiSpan { primary_spans: vec![], span_labels: vec![] } . } . . pub fn from_span(primary_span: Span) -> MultiSpan { 230 ( 0.00%) MultiSpan { primary_spans: vec![primary_span], span_labels: vec![] } . } . . pub fn from_spans(mut vec: Vec) -> MultiSpan { . vec.sort(); 10 ( 0.00%) MultiSpan { primary_spans: vec, span_labels: vec![] } . } . . pub fn push_span_label(&mut self, span: Span, label: String) { . self.span_labels.push((span, label)); . } . . /// Selects the first primary span (if any). . pub fn primary_span(&self) -> Option { . self.primary_spans.first().cloned() 40 ( 0.00%) } . . /// Returns all primary spans. . pub fn primary_spans(&self) -> &[Span] { . &self.primary_spans 1 ( 0.00%) } . . /// Returns `true` if any of the primary spans are displayable. . pub fn has_primary_spans(&self) -> bool { . self.primary_spans.iter().any(|sp| !sp.is_dummy()) . } . . /// Returns `true` if this contains only a dummy primary span with any hygienic context. . pub fn is_dummy(&self) -> bool { -- line 1084 ---------------------------------------- -- line 1139 ---------------------------------------- . . /// Returns `true` if any of the span labels is displayable. . pub fn has_span_labels(&self) -> bool { . self.span_labels.iter().any(|(sp, _)| !sp.is_dummy()) . } . } . . impl From for MultiSpan { 230 ( 0.00%) fn from(span: Span) -> MultiSpan { . MultiSpan::from_span(span) 230 ( 0.00%) } . } . . impl From> for MultiSpan { 10 ( 0.00%) fn from(spans: Vec) -> MultiSpan { 8 ( 0.00%) MultiSpan::from_spans(spans) 10 ( 0.00%) } . } . . /// Identifies an offset of a multi-byte character in a `SourceFile`. . #[derive(Copy, Clone, Encodable, Decodable, Eq, PartialEq, Debug)] . pub struct MultiByteChar { . /// The absolute offset of the character in the `SourceMap`. . pub pos: BytePos, . /// The number of bytes, `>= 2`. . pub bytes: u8, . } . . /// Identifies an offset of a non-narrow character in a `SourceFile`. 308 ( 0.00%) #[derive(Copy, Clone, Encodable, Decodable, Eq, PartialEq, Debug)] . pub enum NonNarrowChar { . /// Represents a zero-width character. . ZeroWidth(BytePos), . /// Represents a wide (full-width) character. . Wide(BytePos), . /// Represents a tab character, represented visually with a width of 4 characters. . Tab(BytePos), . } -- line 1176 ---------------------------------------- -- line 1201 ---------------------------------------- . } . } . } . . impl Add for NonNarrowChar { . type Output = Self; . . fn add(self, rhs: BytePos) -> Self { 532 ( 0.00%) match self { . NonNarrowChar::ZeroWidth(pos) => NonNarrowChar::ZeroWidth(pos + rhs), . NonNarrowChar::Wide(pos) => NonNarrowChar::Wide(pos + rhs), . NonNarrowChar::Tab(pos) => NonNarrowChar::Tab(pos + rhs), . } . } . } . . impl Sub for NonNarrowChar { . type Output = Self; . 154 ( 0.00%) fn sub(self, rhs: BytePos) -> Self { 532 ( 0.00%) match self { . NonNarrowChar::ZeroWidth(pos) => NonNarrowChar::ZeroWidth(pos - rhs), . NonNarrowChar::Wide(pos) => NonNarrowChar::Wide(pos - rhs), . NonNarrowChar::Tab(pos) => NonNarrowChar::Tab(pos - rhs), . } 462 ( 0.00%) } . } . . /// Identifies an offset of a character that was normalized away from `SourceFile`. . #[derive(Copy, Clone, Encodable, Decodable, Eq, PartialEq, Debug)] . pub struct NormalizedPos { . /// The absolute offset of the character in the `SourceMap`. . pub pos: BytePos, . /// The difference between original and normalized string at position. . pub diff: u32, . } . 3 ( 0.00%) #[derive(PartialEq, Eq, Clone, Debug)] . pub enum ExternalSource { . /// No external source has to be loaded, since the `SourceFile` represents a local crate. . Unneeded, . Foreign { . kind: ExternalSourceKind, . /// This SourceFile's byte-offset within the source_map of its original crate. . original_start_pos: BytePos, . /// The end of this SourceFile within the source_map of its original crate. -- line 1246 ---------------------------------------- -- line 1257 ---------------------------------------- . AbsentOk, . /// A failed attempt has been made to load the external source. . AbsentErr, . Unneeded, . } . . impl ExternalSource { . pub fn get_source(&self) -> Option<&Lrc> { 79 ( 0.00%) match self { . ExternalSource::Foreign { kind: ExternalSourceKind::Present(ref src), .. } => Some(src), . _ => None, . } . } . } . . #[derive(Debug)] . pub struct OffsetOverflowError; . 1,250 ( 0.00%) #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable)] . pub enum SourceFileHashAlgorithm { . Md5, . Sha1, . Sha256, . } . . impl FromStr for SourceFileHashAlgorithm { . type Err = (); -- line 1283 ---------------------------------------- -- line 1290 ---------------------------------------- . _ => Err(()), . } . } . } . . rustc_data_structures::impl_stable_hash_via_hash!(SourceFileHashAlgorithm); . . /// The hash of the on-disk source file used for debug info. 6 ( 0.00%) #[derive(Copy, Clone, PartialEq, Eq, Debug)] 2,500 ( 0.00%) #[derive(HashStable_Generic, Encodable, Decodable)] . pub struct SourceFileHash { . pub kind: SourceFileHashAlgorithm, . value: [u8; 32], . } . . impl SourceFileHash { . pub fn new(kind: SourceFileHashAlgorithm, src: &str) -> SourceFileHash { 2 ( 0.00%) let mut hash = SourceFileHash { kind, value: Default::default() }; . let len = hash.hash_len(); . let value = &mut hash.value[..len]; . let data = src.as_bytes(); . match kind { . SourceFileHashAlgorithm::Md5 => { 9 ( 0.00%) value.copy_from_slice(&Md5::digest(data)); . } . SourceFileHashAlgorithm::Sha1 => { . value.copy_from_slice(&Sha1::digest(data)); . } . SourceFileHashAlgorithm::Sha256 => { . value.copy_from_slice(&Sha256::digest(data)); . } . } . hash . } . . /// Check if the stored hash matches the hash of the string. . pub fn matches(&self, src: &str) -> bool { 2 ( 0.00%) Self::new(self.kind, src) == *self . } . . /// The bytes of the hash. . pub fn hash_bytes(&self) -> &[u8] { 40 ( 0.00%) let len = self.hash_len(); 40 ( 0.00%) &self.value[..len] 40 ( 0.00%) } . . fn hash_len(&self) -> usize { 87 ( 0.00%) match self.kind { . SourceFileHashAlgorithm::Md5 => 16, . SourceFileHashAlgorithm::Sha1 => 20, . SourceFileHashAlgorithm::Sha256 => 32, . } . } . } . . /// A single source in the [`SourceMap`]. 58 ( 0.00%) #[derive(Clone)] . pub struct SourceFile { . /// The name of the file that the source came from. Source that doesn't . /// originate from files has names between angle brackets by convention . /// (e.g., ``). . pub name: FileName, . /// The complete source code. 1 ( 0.00%) pub src: Option>, . /// The source code's hash. . pub src_hash: SourceFileHash, . /// The external source code (used for external crates, which will have a `None` . /// value as `self.src`. . pub external_src: Lock, . /// The start position of this source in the `SourceMap`. . pub start_pos: BytePos, . /// The end position of this source in the `SourceMap`. -- line 1361 ---------------------------------------- -- line 1364 ---------------------------------------- . pub lines: Vec, . /// Locations of multi-byte characters in the source code. . pub multibyte_chars: Vec, . /// Width of characters that are not narrow in the source code. . pub non_narrow_chars: Vec, . /// Locations of characters removed during normalization. . pub normalized_pos: Vec, . /// A hash of the filename, used for speeding up hashing in incremental compilation. 1 ( 0.00%) pub name_hash: u128, . /// Indicates which crate this `SourceFile` was imported from. 1 ( 0.00%) pub cnum: CrateNum, . } . . impl Encodable for SourceFile { . fn encode(&self, s: &mut S) -> Result<(), S::Error> { . s.emit_struct(false, |s| { . s.emit_struct_field("name", true, |s| self.name.encode(s))?; . s.emit_struct_field("src_hash", false, |s| self.src_hash.encode(s))?; . s.emit_struct_field("start_pos", false, |s| self.start_pos.encode(s))?; . s.emit_struct_field("end_pos", false, |s| self.end_pos.encode(s))?; . s.emit_struct_field("lines", false, |s| { . let lines = &self.lines[..]; . // Store the length. . s.emit_u32(lines.len() as u32)?; . 4 ( 0.00%) if !lines.is_empty() { . // In order to preserve some space, we exploit the fact that . // the lines list is sorted and individual lines are . // probably not that long. Because of that we can store lines . // as a difference list, using as little space as possible . // for the differences. . let max_line_length = if lines.len() == 1 { . 0 . } else { -- line 1397 ---------------------------------------- -- line 1399 ---------------------------------------- . .array_windows() . .map(|&[fst, snd]| snd - fst) . .map(|bp| bp.to_usize()) . .max() . .unwrap() . }; . . let bytes_per_diff: u8 = match max_line_length { 2 ( 0.00%) 0..=0xFF => 1, . 0x100..=0xFFFF => 2, . _ => 4, . }; . . // Encode the number of bytes used per diff. . bytes_per_diff.encode(s)?; . . // Encode the first element. . lines[0].encode(s)?; . . let diff_iter = lines.array_windows().map(|&[fst, snd]| snd - fst); . 2 ( 0.00%) match bytes_per_diff { . 1 => { . for diff in diff_iter { . (diff.0 as u8).encode(s)? . } . } . 2 => { . for diff in diff_iter { . (diff.0 as u16).encode(s)? -- line 1428 ---------------------------------------- -- line 1436 ---------------------------------------- . _ => unreachable!(), . } . } . . Ok(()) . })?; . s.emit_struct_field("multibyte_chars", false, |s| self.multibyte_chars.encode(s))?; . s.emit_struct_field("non_narrow_chars", false, |s| self.non_narrow_chars.encode(s))?; 3 ( 0.00%) s.emit_struct_field("name_hash", false, |s| self.name_hash.encode(s))?; . s.emit_struct_field("normalized_pos", false, |s| self.normalized_pos.encode(s))?; 11 ( 0.00%) s.emit_struct_field("cnum", false, |s| self.cnum.encode(s)) . }) . } . } . . impl Decodable for SourceFile { 5,625 ( 0.00%) fn decode(d: &mut D) -> SourceFile { . d.read_struct(|d| { . let name: FileName = d.read_struct_field("name", |d| Decodable::decode(d)); . let src_hash: SourceFileHash = . d.read_struct_field("src_hash", |d| Decodable::decode(d)); . let start_pos: BytePos = d.read_struct_field("start_pos", |d| Decodable::decode(d)); . let end_pos: BytePos = d.read_struct_field("end_pos", |d| Decodable::decode(d)); . let lines: Vec = d.read_struct_field("lines", |d| { . let num_lines: u32 = Decodable::decode(d); 625 ( 0.00%) let mut lines = Vec::with_capacity(num_lines as usize); . . if num_lines > 0 { . // Read the number of bytes used per diff. . let bytes_per_diff: u8 = Decodable::decode(d); . . // Read the first element. . let mut line_start: BytePos = Decodable::decode(d); . lines.push(line_start); . . for _ in 1..num_lines { 941,240 ( 0.17%) let diff = match bytes_per_diff { . 1 => d.read_u8() as u32, . 2 => d.read_u16() as u32, . 4 => d.read_u32(), . _ => unreachable!(), . }; . . line_start = line_start + BytePos(diff); . -- line 1480 ---------------------------------------- -- line 1483 ---------------------------------------- . } . . lines . }); . let multibyte_chars: Vec = . d.read_struct_field("multibyte_chars", |d| Decodable::decode(d)); . let non_narrow_chars: Vec = . d.read_struct_field("non_narrow_chars", |d| Decodable::decode(d)); 1,250 ( 0.00%) let name_hash: u128 = d.read_struct_field("name_hash", |d| Decodable::decode(d)); . let normalized_pos: Vec = . d.read_struct_field("normalized_pos", |d| Decodable::decode(d)); . let cnum: CrateNum = d.read_struct_field("cnum", |d| Decodable::decode(d)); 6,875 ( 0.00%) SourceFile { 5,000 ( 0.00%) name, . start_pos, . end_pos, . src: None, 2,500 ( 0.00%) src_hash, . // Unused - the metadata decoder will construct . // a new SourceFile, filling in `external_src` properly . external_src: Lock::new(ExternalSource::Unneeded), 2,500 ( 0.00%) lines, 2,500 ( 0.00%) multibyte_chars, 2,500 ( 0.00%) non_narrow_chars, 2,500 ( 0.00%) normalized_pos, . name_hash, . cnum, . } . }) 5,625 ( 0.00%) } . } . . impl fmt::Debug for SourceFile { . fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { . write!(fmt, "SourceFile({:?})", self.name) . } . } . . impl SourceFile { 11 ( 0.00%) pub fn new( . name: FileName, . mut src: String, . start_pos: BytePos, . hash_kind: SourceFileHashAlgorithm, . ) -> Self { . // Compute the file hash before any normalization. . let src_hash = SourceFileHash::new(hash_kind, &src); 3 ( 0.00%) let normalized_pos = normalize_src(&mut src, start_pos); . . let name_hash = { . let mut hasher: StableHasher = StableHasher::new(); 2 ( 0.00%) name.hash(&mut hasher); . hasher.finish::() . }; 2 ( 0.00%) let end_pos = start_pos.to_usize() + src.len(); 3 ( 0.00%) assert!(end_pos <= u32::MAX as usize); . 12 ( 0.00%) let (lines, multibyte_chars, non_narrow_chars) = 2 ( 0.00%) analyze_source_file::analyze_source_file(&src, start_pos); . 17 ( 0.00%) SourceFile { . name, . src: Some(Lrc::new(src)), 11 ( 0.00%) src_hash, . external_src: Lock::new(ExternalSource::Unneeded), . start_pos, . end_pos: Pos::from_usize(end_pos), 4 ( 0.00%) lines, 4 ( 0.00%) multibyte_chars, 4 ( 0.00%) non_narrow_chars, 4 ( 0.00%) normalized_pos, . name_hash, . cnum: LOCAL_CRATE, . } 9 ( 0.00%) } . . /// Returns the `BytePos` of the beginning of the current line. 3,680 ( 0.00%) pub fn line_begin_pos(&self, pos: BytePos) -> BytePos { . let line_index = self.lookup_line(pos).unwrap(); 1,840 ( 0.00%) self.lines[line_index] 3,680 ( 0.00%) } . . /// Add externally loaded source. . /// If the hash of the input doesn't match or no input is supplied via None, . /// it is interpreted as an error and the corresponding enum variant is set. . /// The return value signifies whether some kind of source is present. 119 ( 0.00%) pub fn add_external_src(&self, get_src: F) -> bool . where . F: FnOnce() -> Option, . { 27 ( 0.00%) if matches!( 34 ( 0.00%) *self.external_src.borrow(), . ExternalSource::Foreign { kind: ExternalSourceKind::AbsentOk, .. } . ) { 2 ( 0.00%) let src = get_src(); . let mut external_src = self.external_src.borrow_mut(); . // Check that no-one else have provided the source while we were getting it 6 ( 0.00%) if let ExternalSource::Foreign { . kind: src_kind @ ExternalSourceKind::AbsentOk, .. . } = &mut *external_src . { 10 ( 0.00%) if let Some(mut src) = src { . // The src_hash needs to be computed on the pre-normalized src. 2 ( 0.00%) if self.src_hash.matches(&src) { 6 ( 0.00%) normalize_src(&mut src, BytePos::from_usize(0)); 16 ( 0.00%) *src_kind = ExternalSourceKind::Present(Lrc::new(src)); . return true; . } . } else { . *src_kind = ExternalSourceKind::AbsentErr; . } . . false . } else { . self.src.is_some() || external_src.get_source().is_some() . } . } else { 15 ( 0.00%) self.src.is_some() || self.external_src.borrow().get_source().is_some() . } 153 ( 0.00%) } . . /// Gets a line from the list of pre-computed line-beginnings. . /// The line number here is 0-based. . pub fn get_line(&self, line_number: usize) -> Option> { . fn get_until_newline(src: &str, begin: usize) -> &str { . // We can't use `lines.get(line_number+1)` because we might . // be parsing when we call this function and thus the current . // line is the last one we have line info for. -- line 1610 ---------------------------------------- -- line 1627 ---------------------------------------- . Some(Cow::Owned(String::from(get_until_newline(src, begin)))) . } else { . None . } . } . . pub fn is_real_file(&self) -> bool { . self.name.is_real() 967 ( 0.00%) } . . pub fn is_imported(&self) -> bool { . self.src.is_none() 2,129 ( 0.00%) } . . pub fn count_lines(&self) -> usize { . self.lines.len() . } . . /// Finds the line containing the given position. The return value is the . /// index into the `lines` array of this `SourceFile`, not the 1-based line . /// number. If the source_file is empty or the position is located before the . /// first line, `None` is returned. . pub fn lookup_line(&self, pos: BytePos) -> Option { 3,897 ( 0.00%) match self.lines.binary_search(&pos) { . Ok(idx) => Some(idx), . Err(0) => None, . Err(idx) => Some(idx - 1), . } . } . . pub fn line_bounds(&self, line_index: usize) -> Range { 1,101 ( 0.00%) if self.is_empty() { . return self.start_pos..self.end_pos; . } . 726 ( 0.00%) assert!(line_index < self.lines.len()); 1,035 ( 0.00%) if line_index == (self.lines.len() - 1) { 13 ( 0.00%) self.lines[line_index]..self.end_pos . } else { 680 ( 0.00%) self.lines[line_index]..self.lines[line_index + 1] . } . } . . /// Returns whether or not the file contains the given `SourceMap` byte . /// position. The position one past the end of the file is considered to be . /// contained by the file. This implies that files for which `is_empty` . /// returns true still contain one byte position according to this function. . #[inline] -- line 1674 ---------------------------------------- -- line 1692 ---------------------------------------- . Err(i) if i == 0 => 0, . Err(i) => self.normalized_pos[i - 1].diff, . }; . . BytePos::from_u32(pos.0 - self.start_pos.0 + diff) . } . . /// Converts an absolute `BytePos` to a `CharPos` relative to the `SourceFile`. 194 ( 0.00%) pub fn bytepos_to_file_charpos(&self, bpos: BytePos) -> CharPos { . // The number of extra bytes due to multibyte chars in the `SourceFile`. . let mut total_extra_bytes = 0; . 582 ( 0.00%) for mbc in self.multibyte_chars.iter() { . debug!("{}-byte char at {:?}", mbc.bytes, mbc.pos); 32 ( 0.00%) if mbc.pos < bpos { . // Every character is at least one byte, so we only . // count the actual extra bytes. 36 ( 0.00%) total_extra_bytes += mbc.bytes as u32 - 1; . // We should never see a byte position in the middle of a . // character. 30 ( 0.00%) assert!(bpos.to_u32() >= mbc.pos.to_u32() + mbc.bytes as u32); . } else { . break; . } . } . 1,164 ( 0.00%) assert!(self.start_pos.to_u32() + total_extra_bytes <= bpos.to_u32()); 970 ( 0.00%) CharPos(bpos.to_usize() - self.start_pos.to_usize() - total_extra_bytes as usize) 388 ( 0.00%) } . . /// Looks up the file's (1-based) line number and (0-based `CharPos`) column offset, for a . /// given `BytePos`. 679 ( 0.00%) pub fn lookup_file_pos(&self, pos: BytePos) -> (usize, CharPos) { 194 ( 0.00%) let chpos = self.bytepos_to_file_charpos(pos); 93 ( 0.00%) match self.lookup_line(pos) { . Some(a) => { . let line = a + 1; // Line numbers start at 1 97 ( 0.00%) let linebpos = self.lines[a]; 194 ( 0.00%) let linechpos = self.bytepos_to_file_charpos(linebpos); . let col = chpos - linechpos; . debug!("byte pos {:?} is on the line at byte pos {:?}", pos, linebpos); . debug!("char pos {:?} is on the line at char pos {:?}", chpos, linechpos); . debug!("byte is on line: {}", line); 97 ( 0.00%) assert!(chpos >= linechpos); . (line, col) . } . None => (0, chpos), . } 776 ( 0.00%) } . . /// Looks up the file's (1-based) line number, (0-based `CharPos`) column offset, and (0-based) . /// column offset when displayed, for a given `BytePos`. 776 ( 0.00%) pub fn lookup_file_pos_with_col_display(&self, pos: BytePos) -> (usize, CharPos, usize) { 291 ( 0.00%) let (line, col_or_chpos) = self.lookup_file_pos(pos); 194 ( 0.00%) if line > 0 { . let col = col_or_chpos; 97 ( 0.00%) let linebpos = self.lines[line - 1]; . let col_display = { . let start_width_idx = self . .non_narrow_chars . .binary_search_by_key(&linebpos, |x| x.pos()) . .unwrap_or_else(|x| x); . let end_width_idx = self . .non_narrow_chars . .binary_search_by_key(&pos, |x| x.pos()) . .unwrap_or_else(|x| x); . let special_chars = end_width_idx - start_width_idx; . let non_narrow: usize = self.non_narrow_chars[start_width_idx..end_width_idx] . .iter() . .map(|x| x.width()) . .sum(); 485 ( 0.00%) col.0 - special_chars + non_narrow . }; . (line, col, col_display) . } else { . let chpos = col_or_chpos; . let col_display = { . let end_width_idx = self . .non_narrow_chars . .binary_search_by_key(&pos, |x| x.pos()) . .unwrap_or_else(|x| x); . let non_narrow: usize = . self.non_narrow_chars[0..end_width_idx].iter().map(|x| x.width()).sum(); . chpos.0 - end_width_idx + non_narrow . }; . (0, chpos, col_display) . } 679 ( 0.00%) } . } . . /// Normalizes the source code and records the normalizations. 30 ( 0.00%) fn normalize_src(src: &mut String, start_pos: BytePos) -> Vec { . let mut normalized_pos = vec![]; . remove_bom(src, &mut normalized_pos); . normalize_newlines(src, &mut normalized_pos); . . // Offset all the positions by start_pos to match the final file positions. . for np in &mut normalized_pos { . np.pos.0 += start_pos.0; . } . . normalized_pos 27 ( 0.00%) } . . /// Removes UTF-8 BOM, if any. . fn remove_bom(src: &mut String, normalized_pos: &mut Vec) { 3 ( 0.00%) if src.starts_with('\u{feff}') { . src.drain(..3); . normalized_pos.push(NormalizedPos { pos: BytePos(0), diff: 3 }); . } . } . . /// Replaces `\r\n` with `\n` in-place in `src`. . /// . /// Returns error if there's a lone `\r` in the string. . fn normalize_newlines(src: &mut String, normalized_pos: &mut Vec) { 3 ( 0.00%) if !src.as_bytes().contains(&b'\r') { . return; . } . . // We replace `\r\n` with `\n` in-place, which doesn't break utf-8 encoding. . // While we *can* call `as_mut_vec` and do surgery on the live string . // directly, let's rather steal the contents of `src`. This makes the code . // safe even if a panic occurs. . -- line 1816 ---------------------------------------- -- line 1877 ---------------------------------------- . ( . $( . $(#[$attr:meta])* . $vis:vis struct $ident:ident($inner_vis:vis $inner_ty:ty); . )* . ) => { . $( . $(#[$attr])* 1,617 ( 0.00%) $vis struct $ident($inner_vis $inner_ty); . . impl Pos for $ident { . #[inline(always)] . fn from_usize(n: usize) -> $ident { 75 ( 0.00%) $ident(n as $inner_ty) . } . . #[inline(always)] . fn to_usize(&self) -> usize { 1,933 ( 0.00%) self.0 as usize . } . . #[inline(always)] . fn from_u32(n: u32) -> $ident { . $ident(n as $inner_ty) . } . . #[inline(always)] -- line 1903 ---------------------------------------- -- line 1906 ---------------------------------------- . } . } . . impl Add for $ident { . type Output = $ident; . . #[inline(always)] . fn add(self, rhs: $ident) -> $ident { 1,676,581 ( 0.31%) $ident(self.0 + rhs.0) . } . } . . impl Sub for $ident { . type Output = $ident; . . #[inline(always)] . fn sub(self, rhs: $ident) -> $ident { 884,872 ( 0.16%) $ident(self.0 - rhs.0) . } . } . )* . }; . } . . impl_pos! { . /// A byte offset. -- line 1931 ---------------------------------------- -- line 1946 ---------------------------------------- . impl Encodable for BytePos { . fn encode(&self, s: &mut S) -> Result<(), S::Error> { . s.emit_u32(self.0) . } . } . . impl Decodable for BytePos { . fn decode(d: &mut D) -> BytePos { 111,360 ( 0.02%) BytePos(d.read_u32()) . } . } . . // _____________________________________________________________________________ . // Loc, SourceFileAndLine, SourceFileAndBytePos . // . . /// A source code location used for error reporting. -- line 1962 ---------------------------------------- -- line 2042 ---------------------------------------- . /// Range inside of a `Span` used for diagnostics when we only have access to relative positions. . #[derive(Copy, Clone, PartialEq, Eq, Debug)] . pub struct InnerSpan { . pub start: usize, . pub end: usize, . } . . impl InnerSpan { 14 ( 0.00%) pub fn new(start: usize, end: usize) -> InnerSpan { . InnerSpan { start, end } 7 ( 0.00%) } . } . . /// Requirements for a `StableHashingContext` to be used in this crate. . /// . /// This is a hack to allow using the [`HashStable_Generic`] derive macro . /// instead of implementing everything in rustc_middle. . pub trait HashStableContext { . fn def_path_hash(&self, def_id: DefId) -> DefPathHash; -- line 2060 ---------------------------------------- -- line 2079 ---------------------------------------- . /// offsets into the `SourceMap`). Instead, we hash the (file name, line, column) . /// triple, which stays the same even if the containing `SourceFile` has moved . /// within the `SourceMap`. . /// . /// Also note that we are hashing byte offsets for the column, not unicode . /// codepoint offsets. For the purpose of the hash that's sufficient. . /// Also, hashing filenames is expensive so we avoid doing it twice when the . /// span starts and ends in the same file, which is almost always the case. 13,699 ( 0.00%) fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { . const TAG_VALID_SPAN: u8 = 0; . const TAG_INVALID_SPAN: u8 = 1; . const TAG_RELATIVE_SPAN: u8 = 2; . 2,589 ( 0.00%) if !ctx.hash_spans() { . return; . } . 11,110 ( 0.00%) let span = self.data_untracked(); 3,975 ( 0.00%) span.ctxt.hash_stable(ctx, hasher); 5,871 ( 0.00%) span.parent.hash_stable(ctx, hasher); . 3,948 ( 0.00%) if span.is_dummy() { . Hash::hash(&TAG_INVALID_SPAN, hasher); . return; . } . 3,846 ( 0.00%) if let Some(parent) = span.parent { . let def_span = ctx.def_span(parent).data_untracked(); . if def_span.contains(span) { . // This span is enclosed in a definition: only hash the relative position. . Hash::hash(&TAG_RELATIVE_SPAN, hasher); . (span.lo - def_span.lo).to_u32().hash_stable(ctx, hasher); . (span.hi - def_span.lo).to_u32().hash_stable(ctx, hasher); . return; . } . } . . // If this is not an empty or invalid span, we want to hash the last . // position that belongs to it, as opposed to hashing the first . // position past it. 7,692 ( 0.00%) let (file, line_lo, col_lo, line_hi, col_hi) = match ctx.span_data_to_lines_and_cols(&span) . { 3,846 ( 0.00%) Some(pos) => pos, . None => { . Hash::hash(&TAG_INVALID_SPAN, hasher); . return; . } . }; . . Hash::hash(&TAG_VALID_SPAN, hasher); . // We truncate the stable ID hash and line and column numbers. The chances -- line 2129 ---------------------------------------- -- line 2134 ---------------------------------------- . // hash only the length, for example, then two otherwise equal spans with . // different end locations will have the same hash. This can cause a problem . // during incremental compilation wherein a previous result for a query that . // depends on the end location of a span will be incorrectly reused when the . // end location of the span it depends on has changed (see issue #74890). A . // similar analysis applies if some query depends specifically on the length . // of the span, but we only hash the end location. So hash both. . 1,923 ( 0.00%) let col_lo_trunc = (col_lo.0 as u64) & 0xFF; . let line_lo_trunc = ((line_lo as u64) & 0xFF_FF_FF) << 8; . let col_hi_trunc = (col_hi.0 as u64) & 0xFF << 32; . let line_hi_trunc = ((line_hi as u64) & 0xFF_FF_FF) << 40; . let col_line = col_lo_trunc | line_lo_trunc | col_hi_trunc | line_hi_trunc; 1,923 ( 0.00%) let len = (span.hi - span.lo).0; . Hash::hash(&col_line, hasher); . Hash::hash(&len, hasher); 15,656 ( 0.00%) } . } 1,286,072 ( 0.24%) -------------------------------------------------------------------------------- -- Auto-annotated source: /usr/home/liquid/rust/worktree-benchmarking/compiler/rustc_serialize/src/leb128.rs -------------------------------------------------------------------------------- Ir -- line 17 ---------------------------------------- . #[inline] . pub fn $fn_name( . out: &mut [::std::mem::MaybeUninit; max_leb128_len!($int_ty)], . mut value: $int_ty, . ) -> &[u8] { . let mut i = 0; . . loop { 35,041 ( 0.01%) if value < 0x80 { . unsafe { 16,882 ( 0.00%) *out.get_unchecked_mut(i).as_mut_ptr() = value as u8; . } . 23,630 ( 0.00%) i += 1; . break; . } else { . unsafe { 14,916 ( 0.00%) *out.get_unchecked_mut(i).as_mut_ptr() = ((value & 0x7f) | 0x80) as u8; . } . 6,112 ( 0.00%) value >>= 7; . i += 1; . } . } . . unsafe { ::std::mem::MaybeUninit::slice_assume_init_ref(&out.get_unchecked(..i)) } . } . }; . } -- line 45 ---------------------------------------- -- line 53 ---------------------------------------- . macro_rules! impl_read_unsigned_leb128 { . ($fn_name:ident, $int_ty:ty) => { . #[inline] . pub fn $fn_name(slice: &[u8], position: &mut usize) -> $int_ty { . // The first iteration of this loop is unpeeled. This is a . // performance win because this code is hot and integer values less . // than 128 are very common, typically occurring 50-80% or more of . // the time, even for u64 and u128. 1,673,568 ( 0.31%) let byte = slice[*position]; 836,784 ( 0.16%) *position += 1; 836,784 ( 0.16%) if (byte & 0x80) == 0 { 420 ( 0.00%) return byte as $int_ty; . } 1,250 ( 0.00%) let mut result = (byte & 0x7F) as $int_ty; . let mut shift = 7; . loop { 565,626 ( 0.11%) let byte = slice[*position]; 368,988 ( 0.07%) *position += 1; 377,084 ( 0.07%) if (byte & 0x80) == 0 { 304,624 ( 0.06%) result |= (byte as $int_ty) << shift; . return result; . } else { . result |= ((byte & 0x7F) as $int_ty) << shift; . } . shift += 7; . } . } . }; -- line 80 ---------------------------------------- 599,205 ( 0.11%) -------------------------------------------------------------------------------- -- Auto-annotated source: /usr/home/liquid/.cargo/registry/src/github.com-1ecc6299db9ec823/snap-1.0.1/src/decompress.rs -------------------------------------------------------------------------------- Ir -- line 22 ---------------------------------------- . /// compressor. . /// . /// # Errors . /// . /// This function returns an error in the following circumstances: . /// . /// * An invalid Snappy header was seen. . /// * The total space required for decompression exceeds `2^32 - 1`. 8 ( 0.00%) pub fn decompress_len(input: &[u8]) -> Result { 4 ( 0.00%) if input.is_empty() { . return Ok(0); . } 8 ( 0.00%) Ok(Header::read(input)?.decompress_len) 12 ( 0.00%) } . . /// Decoder is a raw decoder for decompressing bytes in the Snappy format. . /// . /// This decoder does not use the Snappy frame format and simply decompresses . /// the given bytes as if it were returned from `Encoder`. . /// . /// Unless you explicitly need the low-level control, you should use . /// [`read::FrameDecoder`](../read/struct.FrameDecoder.html) -- line 43 ---------------------------------------- -- line 47 ---------------------------------------- . // Place holder for potential future fields. . _dummy: (), . } . . impl Decoder { . /// Return a new decoder that can be used for decompressing bytes. . pub fn new() -> Decoder { . Decoder { _dummy: () } 2 ( 0.00%) } . . /// Decompresses all bytes in `input` into `output`. . /// . /// `input` must be a sequence of bytes returned by a conforming Snappy . /// compressor. . /// . /// The size of `output` must be large enough to hold all decompressed . /// bytes from the `input`. The size required can be queried with the -- line 63 ---------------------------------------- -- line 67 ---------------------------------------- . /// . /// # Errors . /// . /// This method returns an error in the following circumstances: . /// . /// * Invalid compressed Snappy data was seen. . /// * The total space required for decompression exceeds `2^32 - 1`. . /// * `output` has length less than `decompress_len(input)`. 32 ( 0.00%) pub fn decompress( . &mut self, . input: &[u8], . output: &mut [u8], . ) -> Result { 4 ( 0.00%) if input.is_empty() { . return Err(Error::Empty); . } . let hdr = Header::read(input)?; 8 ( 0.00%) if hdr.decompress_len > output.len() { . return Err(Error::BufferTooSmall { . given: output.len() as u64, . min: hdr.decompress_len as u64, . }); . } . let dst = &mut output[..hdr.decompress_len]; . let mut dec = . Decompress { src: &input[hdr.len..], s: 0, dst: dst, d: 0 }; . dec.decompress()?; 12 ( 0.00%) Ok(dec.dst.len()) 36 ( 0.00%) } . . /// Decompresses all bytes in `input` into a freshly allocated `Vec`. . /// . /// This is just like the `decompress` method, except it allocates a `Vec` . /// with the right size for you. (This is intended to be a convenience . /// method.) . /// . /// This method returns an error under the same circumstances that -- line 103 ---------------------------------------- -- line 123 ---------------------------------------- . } . . impl<'s, 'd> Decompress<'s, 'd> { . /// Decompresses snappy compressed bytes in `src` to `dst`. . /// . /// This assumes that the header has already been read and that `dst` is . /// big enough to store all decompressed bytes. . fn decompress(&mut self) -> Result<()> { 29,428 ( 0.01%) while self.s < self.src.len() { 14,710 ( 0.00%) let byte = self.src[self.s]; 14,710 ( 0.00%) self.s += 1; 29,420 ( 0.01%) if byte & 0b000000_11 == 0 { 16,272 ( 0.00%) let len = (byte >> 2) as usize + 1; . self.read_literal(len)?; . } else { . self.read_copy(byte)?; . } . } 8 ( 0.00%) if self.d != self.dst.len() { . return Err(Error::HeaderMismatch { . expected_len: self.dst.len() as u64, . got_len: self.d as u64, . }); . } . Ok(()) . } . -- line 149 ---------------------------------------- -- line 162 ---------------------------------------- . debug_assert!(len <= 64); . let mut len = len as u64; . // As an optimization for the common case, if the literal length is . // <=16 and we have enough room in both `src` and `dst`, copy the . // literal using unaligned loads and stores. . // . // We pick 16 bytes with the hope that it optimizes down to a 128 bit . // load/store. 21,568 ( 0.00%) if len <= 16 16,080 ( 0.00%) && self.s + 16 <= self.src.len() 21,440 ( 0.00%) && self.d + 16 <= self.dst.len() . { . unsafe { . // SAFETY: We know both src and dst have at least 16 bytes of . // wiggle room after s/d, even if `len` is <16, so the copy is . // safe. . let srcp = self.src.as_ptr().add(self.s); . let dstp = self.dst.as_mut_ptr().add(self.d); . // Hopefully uses SIMD registers for 128 bit load/store. . ptr::copy_nonoverlapping(srcp, dstp, 16); . } 5,360 ( 0.00%) self.d += len as usize; 16,080 ( 0.00%) self.s += len as usize; . return Ok(()); . } . // When the length is bigger than 60, it indicates that we need to read . // an additional 1-4 bytes to get the real length of the literal. 128 ( 0.00%) if len >= 61 { . // If there aren't at least 4 bytes left to read then we know this . // is corrupt because the literal must have length >=61. 90 ( 0.00%) if self.s as u64 + 4 > self.src.len() as u64 { . return Err(Error::Literal { . len: 4, . src_len: (self.src.len() - self.s) as u64, . dst_len: (self.dst.len() - self.d) as u64, . }); . } . // Since we know there are 4 bytes left to read, read a 32 bit LE . // integer and mask away the bits we don't need. . let byte_count = len as usize - 60; . len = bytes::read_u32_le(&self.src[self.s..]) as u64; 108 ( 0.00%) len = (len & (WORD_MASK[byte_count] as u64)) + 1; 18 ( 0.00%) self.s += byte_count; . } . // If there's not enough buffer left to load or store this literal, . // then the input is corrupt. . // if self.s + len > self.src.len() || self.d + len > self.dst.len() { 384 ( 0.00%) if ((self.src.len() - self.s) as u64) < len 192 ( 0.00%) || ((self.dst.len() - self.d) as u64) < len . { . return Err(Error::Literal { . len: len, . src_len: (self.src.len() - self.s) as u64, . dst_len: (self.dst.len() - self.d) as u64, . }); . } . unsafe { . // SAFETY: We've already checked the bounds, so we know this copy . // is correct. . let srcp = self.src.as_ptr().add(self.s); . let dstp = self.dst.as_mut_ptr().add(self.d); . ptr::copy_nonoverlapping(srcp, dstp, len as usize); . } 128 ( 0.00%) self.s += len as usize; 128 ( 0.00%) self.d += len as usize; . Ok(()) . } . . /// Reads a copy from `src` and writes the decompressed bytes to `dst`. `s` . /// should point to the byte immediately proceding the copy tag byte. . #[inline(always)] . fn read_copy(&mut self, tag_byte: u8) -> Result<()> { . // Find the copy offset and len, then advance the input past the copy. . // The rest of this function deals with reading/writing to output only. . let entry = TAG_LOOKUP_TABLE.entry(tag_byte); . let offset = entry.offset(self.src, self.s)?; . let len = entry.len(); 18,572 ( 0.00%) self.s += entry.num_tag_bytes(); . . // What we really care about here is whether `d == 0` or `d < offset`. . // To save an extra branch, use `d < offset - 1` instead. If `d` is . // `0`, then `offset.wrapping_sub(1)` will be usize::MAX which is also . // the max value of `d`. 18,572 ( 0.00%) if self.d <= offset.wrapping_sub(1) { . return Err(Error::Offset { . offset: offset as u64, . dst_pos: self.d as u64, . }); . } . // When all is said and done, dst is advanced to end. 27,858 ( 0.01%) let end = self.d + len; . // When the copy is small and the offset is at least 8 bytes away from . // `d`, then we can decompress the copy with two 64 bit unaligned . // loads/stores. 67,034 ( 0.01%) if offset >= 8 && len <= 16 && self.d + 16 <= self.dst.len() { . unsafe { . // SAFETY: We know dstp points to at least 16 bytes of memory . // from the condition above, and we also know that dstp is . // preceded by at least `offset` bytes from the `d <= offset` . // check above. . // . // We also know that dstp and dstp-8 do not overlap from the . // check above, justifying the use of copy_nonoverlapping. -- line 264 ---------------------------------------- -- line 273 ---------------------------------------- . // If we have some wiggle room, try to decompress the copy 16 bytes . // at a time with 128 bit unaligned loads/stores. Remember, we can't . // just do a memcpy because decompressing copies may require copying . // overlapping memory. . // . // We need the extra wiggle room to make effective use of 128 bit . // loads/stores. Even if the store ends up copying more data than we . // need, we're careful to advance `d` by the correct amount at the end. 16,540 ( 0.00%) } else if end + 24 <= self.dst.len() { . unsafe { . // SAFETY: We know that dstp is preceded by at least `offset` . // bytes from the `d <= offset` check above. . // . // We don't know whether dstp overlaps with srcp, so we start . // by copying from srcp to dstp until they no longer overlap. . // The worst case is when dstp-src = 3 and copy length = 1. The . // first loop will issue these copy operations before stopping: -- line 289 ---------------------------------------- -- line 295 ---------------------------------------- . // But the copy had length 1, so it was only supposed to write . // to [0, 0]. But the last copy wrote to [9, 24], which is 24 . // extra bytes in dst *beyond* the end of the copy, which is . // guaranteed by the conditional above. . let mut dstp = self.dst.as_mut_ptr().add(self.d); . let mut srcp = dstp.sub(offset); . loop { . debug_assert!(dstp >= srcp); 23,334 ( 0.00%) let diff = (dstp as usize) - (srcp as usize); 15,556 ( 0.00%) if diff >= 16 { . break; . } . // srcp and dstp can overlap, so use ptr::copy. . debug_assert!(self.d + 16 <= self.dst.len()); . ptr::copy(srcp, dstp, 16); 8,944 ( 0.00%) self.d += diff as usize; . dstp = dstp.add(diff); . } 42,202 ( 0.01%) while self.d < end { . ptr::copy_nonoverlapping(srcp, dstp, 16); . srcp = srcp.add(16); . dstp = dstp.add(16); 34,460 ( 0.01%) self.d += 16; . } . // At this point, `d` is likely wrong. We correct it before . // returning. It's correct value is `end`. . } . } else { 4 ( 0.00%) if end > self.dst.len() { . return Err(Error::CopyWrite { . len: len as u64, . dst_len: (self.dst.len() - self.d) as u64, . }); . } . // Finally, the slow byte-by-byte case, which should only be used . // for the last few bytes of decompression. 242 ( 0.00%) while self.d != end { 1,070 ( 0.00%) self.dst[self.d] = self.dst[self.d - offset]; 118 ( 0.00%) self.d += 1; . } . } . self.d = end; . Ok(()) . } . } . . /// Header represents the single varint that starts every Snappy compressed -- line 341 ---------------------------------------- -- line 350 ---------------------------------------- . . impl Header { . /// Reads the varint header from the given input. . /// . /// If there was a problem reading the header then an error is returned. . /// If a header is returned then it is guaranteed to be valid. . #[inline(always)] . fn read(input: &[u8]) -> Result
{ 32 ( 0.00%) let (decompress_len, header_len) = bytes::read_varu64(input); 16 ( 0.00%) if header_len == 0 { . return Err(Error::Header); . } 24 ( 0.00%) if decompress_len > MAX_INPUT_SIZE { . return Err(Error::TooBig { . given: decompress_len as u64, . max: MAX_INPUT_SIZE, . }); . } . Ok(Header { len: header_len, decompress_len: decompress_len as usize }) . } . } -- line 370 ---------------------------------------- -- line 426 ---------------------------------------- . /// This requires reading from the compressed input since the offset is . /// encoded in bytes proceding the tag byte. . fn offset(&self, src: &[u8], s: usize) -> Result { . let num_tag_bytes = self.num_tag_bytes(); . let trailer = . // It is critical for this case to come first, since it is the . // fast path. We really hope that this case gets branch . // predicted. 46,430 ( 0.01%) if s + 4 <= src.len() { . unsafe { . // SAFETY: The conditional above guarantees that . // src[s..s+4] is valid to read from. . let p = src.as_ptr().add(s); . // We use WORD_MASK here to mask out the bits we don't . // need. While we're guaranteed to read 4 valid bytes, . // not all of those bytes are necessarily part of the . // offset. This is the key optimization: we don't need to . // branch on num_tag_bytes. 46,420 ( 0.01%) bytes::loadu_u32_le(p) as usize & WORD_MASK[num_tag_bytes] . } 8 ( 0.00%) } else if num_tag_bytes == 1 { . if s >= src.len() { . return Err(Error::CopyRead { . len: 1, . src_len: (src.len() - s) as u64, . }); . } . src[s] as usize . } else if num_tag_bytes == 2 { 6 ( 0.00%) if s + 1 >= src.len() { . return Err(Error::CopyRead { . len: 2, . src_len: (src.len() - s) as u64, . }); . } . bytes::read_u16_le(&src[s..]) as usize . } else { . return Err(Error::CopyRead { -- line 463 ---------------------------------------- 109,520 ( 0.02%) -------------------------------------------------------------------------------- -- Auto-annotated source: /usr/home/liquid/rust/worktree-benchmarking/library/core/src/slice/iter/macros.rs -------------------------------------------------------------------------------- Ir -- line 70 ---------------------------------------- . . impl<'a, T> $name<'a, T> { . // Helper function for creating a slice from the iterator. . #[inline(always)] . fn make_slice(&self) -> &'a [T] { . // SAFETY: the iterator was created from a slice with pointer . // `self.ptr` and length `len!(self)`. This guarantees that all . // the prerequisites for `from_raw_parts` are fulfilled. 2,355 ( 0.00%) unsafe { from_raw_parts(self.ptr.as_ptr(), len!(self)) } . } . . // Helper function for moving the start of the iterator forwards by `offset` elements, . // returning the old start. . // Unsafe because the offset must not exceed `self.len()`. . #[inline(always)] . unsafe fn post_inc_start(&mut self, offset: isize) -> * $raw_mut T { . if mem::size_of::() == 0 { . zst_shrink!(self, offset); . self.ptr.as_ptr() . } else { 3,300 ( 0.00%) let old = self.ptr.as_ptr(); . // SAFETY: the caller guarantees that `offset` doesn't exceed `self.len()`, . // so this new pointer is inside `self` and thus guaranteed to be non-null. 26,121 ( 0.00%) self.ptr = unsafe { NonNull::new_unchecked(self.ptr.as_ptr().offset(offset)) }; 550 ( 0.00%) old . } 1,100 ( 0.00%) } . . // Helper function for moving the end of the iterator backwards by `offset` elements, . // returning the new end. . // Unsafe because the offset must not exceed `self.len()`. . #[inline(always)] . unsafe fn pre_dec_end(&mut self, offset: isize) -> * $raw_mut T { . if mem::size_of::() == 0 { . zst_shrink!(self, offset); . self.ptr.as_ptr() . } else { . // SAFETY: the caller guarantees that `offset` doesn't exceed `self.len()`, . // which is guaranteed to not overflow an `isize`. Also, the resulting pointer . // is in bounds of `slice`, which fulfills the other requirements for `offset`. 919 ( 0.00%) self.end = unsafe { self.end.offset(-offset) }; 180 ( 0.00%) self.end . } 180 ( 0.00%) } . } . . #[stable(feature = "rust1", since = "1.0.0")] . impl ExactSizeIterator for $name<'_, T> { . #[inline(always)] . fn len(&self) -> usize { 4,478 ( 0.00%) len!(self) 110 ( 0.00%) } . . #[inline(always)] . fn is_empty(&self) -> bool { . is_empty!(self) . } . } . . #[stable(feature = "rust1", since = "1.0.0")] . impl<'a, T> Iterator for $name<'a, T> { . type Item = $elem; . . #[inline] 2,412 ( 0.00%) fn next(&mut self) -> Option<$elem> { . // could be implemented with slices, but this avoids bounds checks . . // SAFETY: `assume` calls are safe since a slice's start pointer . // must be non-null, and slices over non-ZSTs must also have a . // non-null end pointer. The call to `next_unchecked!` is safe . // since we check if the iterator is empty first. . unsafe { 18,049 ( 0.00%) assume(!self.ptr.as_ptr().is_null()); 4,020 ( 0.00%) if mem::size_of::() != 0 { 3,929 ( 0.00%) assume(!self.end.is_null()); . } 4,410,478 ( 0.82%) if is_empty!(self) { 254 ( 0.00%) None . } else { 1,101 ( 0.00%) Some(next_unchecked!(self)) . } . } 2,412 ( 0.00%) } . . #[inline] 20 ( 0.00%) fn size_hint(&self) -> (usize, Option) { 63,549 ( 0.01%) let exact = len!(self); 36 ( 0.00%) (exact, Some(exact)) 8 ( 0.00%) } . . #[inline] . fn count(self) -> usize { . len!(self) . } . . #[inline] . fn nth(&mut self, n: usize) -> Option<$elem> { 960 ( 0.00%) if n >= len!(self) { . // This iterator is now empty. . if mem::size_of::() == 0 { . // We have to do it this way as `ptr` may never be 0, but `end` . // could be (due to wrapping). . self.end = self.ptr.as_ptr(); . } else { . // SAFETY: end can't be 0 if T isn't ZST because ptr isn't 0 and end >= ptr . unsafe { -- line 175 ---------------------------------------- -- line 203 ---------------------------------------- . // faster to compile. . #[inline] . fn for_each(mut self, mut f: F) . where . Self: Sized, . F: FnMut(Self::Item), . { . while let Some(x) = self.next() { 168 ( 0.00%) f(x); . } . } . . // We override the default implementation, which uses `try_fold`, . // because this simple implementation generates less LLVM IR and is . // faster to compile. . #[inline] . fn all(&mut self, mut f: F) -> bool . where . Self: Sized, . F: FnMut(Self::Item) -> bool, . { 206 ( 0.00%) while let Some(x) = self.next() { 5,535 ( 0.00%) if !f(x) { . return false; . } . } . true . } . . // We override the default implementation, which uses `try_fold`, . // because this simple implementation generates less LLVM IR and is . // faster to compile. . #[inline] 8 ( 0.00%) fn any(&mut self, mut f: F) -> bool . where . Self: Sized, . F: FnMut(Self::Item) -> bool, . { 16,155 ( 0.00%) while let Some(x) = self.next() { 22,593 ( 0.00%) if f(x) { . return true; . } . } . false 8 ( 0.00%) } . . // We override the default implementation, which uses `try_fold`, . // because this simple implementation generates less LLVM IR and is . // faster to compile. . #[inline] 50 ( 0.00%) fn find

(&mut self, mut predicate: P) -> Option . where . Self: Sized, . P: FnMut(&Self::Item) -> bool, . { 4,664 ( 0.00%) while let Some(x) = self.next() { 14,242 ( 0.00%) if predicate(&x) { 6 ( 0.00%) return Some(x); . } . } 7 ( 0.00%) None 4,804 ( 0.00%) } . . // We override the default implementation, which uses `try_fold`, . // because this simple implementation generates less LLVM IR and is . // faster to compile. . #[inline] 56 ( 0.00%) fn find_map(&mut self, mut f: F) -> Option . where . Self: Sized, . F: FnMut(Self::Item) -> Option, . { 5,202 ( 0.00%) while let Some(x) = self.next() { 5,891 ( 0.00%) if let Some(y) = f(x) { 927 ( 0.00%) return Some(y); . } . } 4 ( 0.00%) None 220 ( 0.00%) } . . // We override the default implementation, which uses `try_fold`, . // because this simple implementation generates less LLVM IR and is . // faster to compile. Also, the `assume` avoids a bounds check. . #[inline] . #[rustc_inherit_overflow_checks] . fn position

(&mut self, mut predicate: P) -> Option where . Self: Sized, . P: FnMut(Self::Item) -> bool, . { . let n = len!(self); . let mut i = 0; . while let Some(x) = self.next() { 4,317 ( 0.00%) if predicate(x) { . // SAFETY: we are guaranteed to be in bounds by the loop invariant: . // when `i >= n`, `self.next()` returns `None` and the loop breaks. . unsafe { assume(i < n) }; . return Some(i); . } . i += 1; . } . None -- line 303 ---------------------------------------- -- line 308 ---------------------------------------- . // faster to compile. Also, the `assume` avoids a bounds check. . #[inline] . fn rposition

(&mut self, mut predicate: P) -> Option where . P: FnMut(Self::Item) -> bool, . Self: Sized + ExactSizeIterator + DoubleEndedIterator . { . let n = len!(self); . let mut i = n; 3,575 ( 0.00%) while let Some(x) = self.next_back() { 70,332 ( 0.01%) i -= 1; 60,722 ( 0.01%) if predicate(x) { . // SAFETY: `i` must be lower than `n` since it starts at `n` . // and is only decreasing. . unsafe { assume(i < n) }; . return Some(i); . } . } . None . } -- line 326 ---------------------------------------- -- line 332 ---------------------------------------- . // the returned references is guaranteed to refer to an element . // of the slice and thus guaranteed to be valid. . // . // Also note that the caller also guarantees that we're never . // called with the same index again, and that no other methods . // that will access this subslice are called, so it is valid . // for the returned reference to be mutable in the case of . // `IterMut` 3,882 ( 0.00%) unsafe { & $( $mut_ )? * self.ptr.as_ptr().add(idx) } . } . . $($extra)* . } . . #[stable(feature = "rust1", since = "1.0.0")] . impl<'a, T> DoubleEndedIterator for $name<'a, T> { . #[inline] 270 ( 0.00%) fn next_back(&mut self) -> Option<$elem> { . // could be implemented with slices, but this avoids bounds checks . . // SAFETY: `assume` calls are safe since a slice's start pointer must be non-null, . // and slices over non-ZSTs must also have a non-null end pointer. . // The call to `next_back_unchecked!` is safe since we check if the iterator is . // empty first. . unsafe { 846 ( 0.00%) assume(!self.ptr.as_ptr().is_null()); 450 ( 0.00%) if mem::size_of::() != 0 { 700 ( 0.00%) assume(!self.end.is_null()); . } 73,417 ( 0.01%) if is_empty!(self) { . None . } else { 180 ( 0.00%) Some(next_back_unchecked!(self)) . } . } 270 ( 0.00%) } . . #[inline] . fn nth_back(&mut self, n: usize) -> Option<$elem> { . if n >= len!(self) { . // This iterator is now empty. . self.end = self.ptr.as_ptr(); . return None; . } -- line 375 ---------------------------------------- 426,242 ( 0.08%) -------------------------------------------------------------------------------- The following files chosen for auto-annotation could not be found: -------------------------------------------------------------------------------- ./elf/../sysdeps/x86_64/dl-machine.h ./elf/dl-lookup.c ./elf/do-rel.h ./malloc/malloc.c ./string/../sysdeps/x86_64/multiarch/memcmp-avx2-movbe.S ./string/../sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S ./string/../sysdeps/x86_64/multiarch/memset-vec-unaligned-erms.S ./string/../sysdeps/x86_64/multiarch/strcmp-avx2.S ./string/../sysdeps/x86_64/multiarch/strlen-avx2.S ./string/../sysdeps/x86_64/strcmp.S /tmp/gcc-build/x86_64-unknown-linux-gnu/libstdc++-v3/libsupc++/../../../../gcc-5.5.0/libstdc++-v3/libsupc++/new_op.cc -------------------------------------------------------------------------------- Ir -------------------------------------------------------------------------------- 52,766,743 ( 9.80%) events annotated